15"""Linear constraint in a model."""
17from typing
import Any, Iterator, Optional
26 """An indicator constraint for an optimization model.
28 An IndicatorConstraint adds the following restriction on feasible solutions to
29 an optimization model:
30 if z == 1 then lb <= sum_{i in I} a_i * x_i <= ub
31 where z is a binary decision variable (or its negation) and x_i are the
32 decision variables of the problem. Equality constraints lb == ub is allowed,
33 which models the constraint:
34 if z == 1 then sum_{i in I} a_i * x_i == b
35 Setting lb > ub will result in an InvalidArgument error at solve time.
37 Indicator constraints have limited mutability. You can delete a variable
38 that the constraint uses, or you can delete the entire constraint. You
39 currently cannot update bounds or coefficients. This may change in future
42 If the indicator variable is deleted or was None at creation time, the
43 constraint will lead to an invalid model at solve time, unless the constraint
44 is deleted before solving.
46 The name is optional, read only, and used only for debugging. Non-empty names
49 Do not create an IndicatorConstraint directly, use
50 Model.add_indicator_constraint() instead. Two IndicatorConstraint objects can
51 represent the same constraint (for the same model). They will have the same
52 underlying IndicatorConstraint.elemental for storing the data. The
53 IndicatorConstraint class is simply a reference to an Elemental.
56 __slots__ =
"_elemental",
"_id"
58 def __init__(self, elem: elemental.Elemental, cid: int) ->
None:
59 """Internal only, prefer Model functions (add_indicator_constraint() and get_indicator_constraint())."""
60 if not isinstance(cid, int):
61 raise TypeError(f
"cid type should be int, was:{type(cid).__name__!r}")
68 enums.DoubleAttr1.INDICATOR_CONSTRAINT_LOWER_BOUND, (self.
_id,)
74 enums.DoubleAttr1.INDICATOR_CONSTRAINT_UPPER_BOUND, (self.
_id,)
80 enums.BoolAttr1.INDICATOR_CONSTRAINT_ACTIVATE_ON_ZERO, (self.
_id,)
86 enums.VariableAttr1.INDICATOR_CONSTRAINT_INDICATOR, (self.
_id,)
95 enums.ElementType.INDICATOR_CONSTRAINT, self.
_id
103 def elemental(self) -> elemental.Elemental:
104 """Internal use only."""
108 from_model.model_is_same(var, self)
110 enums.DoubleAttr2.INDICATOR_CONSTRAINT_LINEAR_COEFFICIENT,
114 def terms(self) -> Iterator[variables.LinearTerm]:
115 """Yields the variable/coefficient pairs with nonzero coefficient for this linear constraint."""
117 enums.DoubleAttr2.INDICATOR_CONSTRAINT_LINEAR_COEFFICIENT, 0, self.
_id
120 enums.DoubleAttr2.INDICATOR_CONSTRAINT_LINEAR_COEFFICIENT, keys
122 for i
in range(len(keys)):
125 coefficient=float(coefs[i]),
129 """Returns the bounded expression from lower_bound, upper_bound and terms."""
130 return variables.BoundedLinearExpression(
135 """Returns the name, or a string containing the id if the name is empty."""
136 return self.
name if self.
name else f
"linear_constraint_{self.id}"
139 return f
"<LinearConstraint id: {self.id}, name: {self.name!r}>"
142 if isinstance(other, IndicatorConstraint):
143 return self.
_id == other._id
and self.
_elemental is other._elemental
147 return hash(self.
_id)