14"""Linear constraint in a model."""
16from typing
import Any, Iterator, NamedTuple
25 """A linear constraint for an optimization model.
27 A LinearConstraint adds the following restriction on feasible solutions to an
29 lb <= sum_{i in I} a_i * x_i <= ub
30 where x_i are the decision variables of the problem. lb == ub is allowed, this
31 models the equality constraint:
32 sum_{i in I} a_i * x_i == b
33 Setting lb > ub will result in an InvalidArgument error at solve time (the
34 values are allowed to cross temporarily between solves).
36 A LinearConstraint can be configured as follows:
37 * lower_bound: a float property, lb above. Should not be NaN nor +inf.
38 * upper_bound: a float property, ub above. Should not be NaN nor -inf.
39 * set_coefficient() and get_coefficient(): get and set the a_i * x_i
40 terms. The variable must be from the same model as this constraint, and
41 the a_i must be finite and not NaN. The coefficient for any variable not
42 set is 0.0, and setting a coefficient to 0.0 removes it from I above.
44 The name is optional, read only, and used only for debugging. Non-empty names
47 Do not create a LinearConstraint directly, use Model.add_linear_constraint()
48 instead. Two LinearConstraint objects can represent the same constraint (for
49 the same model). They will have the same underlying LinearConstraint.elemental
50 for storing the data. The LinearConstraint class is simply a reference to an
54 __slots__ =
"_elemental",
"_id"
56 def __init__(self, elem: elemental.Elemental, cid: int) ->
None:
57 """Internal only, prefer Model functions (add_linear_constraint() and get_linear_constraint())."""
58 if not isinstance(cid, int):
59 raise TypeError(f
"cid type should be int, was:{type(cid).__name__!r}")
66 enums.DoubleAttr1.LINEAR_CONSTRAINT_LOWER_BOUND, (self.
_id,)
72 enums.DoubleAttr1.LINEAR_CONSTRAINT_LOWER_BOUND, (self.
_id,), value
78 enums.DoubleAttr1.LINEAR_CONSTRAINT_UPPER_BOUND, (self.
_id,)
84 enums.DoubleAttr1.LINEAR_CONSTRAINT_UPPER_BOUND, (self.
_id,), value
90 enums.ElementType.LINEAR_CONSTRAINT, self.
_id
98 def elemental(self) -> elemental.Elemental:
99 """Internal use only."""
103 from_model.model_is_same(var, self)
105 enums.DoubleAttr2.LINEAR_CONSTRAINT_COEFFICIENT,
111 from_model.model_is_same(var, self)
113 enums.DoubleAttr2.LINEAR_CONSTRAINT_COEFFICIENT, (self.
_id, var.id)
116 def terms(self) -> Iterator[variables.LinearTerm]:
117 """Yields the variable/coefficient pairs with nonzero coefficient for this linear constraint."""
119 enums.DoubleAttr2.LINEAR_CONSTRAINT_COEFFICIENT, 0, self.
_id
122 enums.DoubleAttr2.LINEAR_CONSTRAINT_COEFFICIENT, keys
124 for i
in range(len(keys)):
127 coefficient=float(coefs[i]),
131 """Returns the bounded expression from lower_bound, upper_bound and terms."""
132 return variables.BoundedLinearExpression(
137 """Returns the name, or a string containing the id if the name is empty."""
138 return self.
name if self.
name else f
"linear_constraint_{self.id}"
141 return f
"<LinearConstraint id: {self.id}, name: {self.name!r}>"
144 if isinstance(other, LinearConstraint):
145 return self.
_id == other._id
and self.
_elemental is other._elemental
149 return hash(self.
_id)
153 linear_constraint: LinearConstraint