15"""Quadratic constraint in a model."""
17from typing
import Any, Iterator
26 """A quadratic constraint for an optimization model.
28 A QuadraticConstraint adds the following restriction on feasible solutions to
29 an optimization model:
30 lb <= sum_i a_i x_i + sum_i sum_{j : i <= j} b_ij x_i x_j <= ub
31 where x_i are the decision variables of the problem. lb == ub is allowed, and
32 this models an equality constraint. lb > ub is also allowed, but the
33 optimization problem will be infeasible.
35 Quadratic constraints have limited mutability. You can delete a variable
36 that the constraint uses, or you can delete the entire constraint. You
37 currently cannot update bounds or coefficients. This may change in future
40 A QuadraticConstraint can be queried as follows:
41 * lower_bound: a float property, lb above. Should not be NaN nor +inf.
42 * upper_bound: a float property, ub above. Should not be NaN nor -inf.
43 * get_linear_coefficient(): get the a_i * x_i terms. The variable must be
44 from the same model as this constraint, and the a_i must be finite and not
45 NaN. The coefficient for any variable not set is 0.0.
46 * get_quadratic_coefficient(): like get_linear_coefficient() but for the
47 b_ij terms. Note that get_quadratic_coefficient(x, y, 8) and
48 get_quadratic_coefficient(y, x, 8) have the same result.
50 The name is optional, read only, and used only for debugging. Non-empty names
53 Do not create a QuadraticConstraint directly, use
54 Model.add_quadratic_constraint() instead. Two QuadraticConstraint objects
55 can represent the same constraint (for the same model). They will have the
56 same underlying QuadraticConstraint.elemental for storing the data. The
57 QuadraticConstraint class is simply a reference to an Elemental.
60 __slots__ =
"_elemental",
"_id"
62 def __init__(self, elem: elemental.Elemental, cid: int) ->
None:
63 """Internal only, prefer Model functions (add_quadratic_constraint() and get_quadratic_constraint())."""
64 if not isinstance(cid, int):
65 raise TypeError(f
"cid type should be int, was:{type(cid).__name__!r}")
71 """The quadratic expression of the constraint must be at least this."""
73 enums.DoubleAttr1.QUADRATIC_CONSTRAINT_LOWER_BOUND, (self.
_id,)
78 """The quadratic expression of the constraint must be at most this."""
80 enums.DoubleAttr1.QUADRATIC_CONSTRAINT_UPPER_BOUND, (self.
_id,)
85 """The name of this constraint."""
87 enums.ElementType.QUADRATIC_CONSTRAINT, self.
_id
92 """A unique (for the model) identifier for this constraint."""
96 def elemental(self) -> elemental.Elemental:
97 """Internal use only."""
101 """Returns the linear coefficient for var in the constraint's quadratic expression."""
102 from_model.model_is_same(var, self)
104 enums.DoubleAttr2.QUADRATIC_CONSTRAINT_LINEAR_COEFFICIENT,
109 """Yields variable/coefficient pairs from the linear part of the constraint.
111 Only the pairs with nonzero coefficient are returned.
114 The variable, coefficient pairs.
117 enums.DoubleAttr2.QUADRATIC_CONSTRAINT_LINEAR_COEFFICIENT, 0, self.
_id
120 enums.DoubleAttr2.QUADRATIC_CONSTRAINT_LINEAR_COEFFICIENT, keys
122 for i
in range(len(keys)):
125 coefficient=float(coefs[i]),
131 """Returns the quadratic coefficient for the pair (var1, var2) in the constraint's quadratic expression."""
132 from_model.model_is_same(var1, self)
133 from_model.model_is_same(var2, self)
135 enums.SymmetricDoubleAttr3.QUADRATIC_CONSTRAINT_QUADRATIC_COEFFICIENT,
136 (self.
_id, var1.id, var2.id),
140 """Yields variable/coefficient pairs from the quadratic part of the constraint.
142 Only the pairs with nonzero coefficient are returned.
145 The variable, coefficient pairs.
148 enums.SymmetricDoubleAttr3.QUADRATIC_CONSTRAINT_QUADRATIC_COEFFICIENT,
153 enums.SymmetricDoubleAttr3.QUADRATIC_CONSTRAINT_QUADRATIC_COEFFICIENT,
156 for i
in range(len(keys)):
162 coefficient=float(coefs[i]),
166 """Returns the name, or a string containing the id if the name is empty."""
167 return self.
name if self.
name else f
"quadratic_constraint_{self.id}"
170 return f
"<QuadraticConstraint id: {self.id}, name: {self.name!r}>"
173 if isinstance(other, QuadraticConstraint):
174 return self.
_id == other._id
and self.
_elemental is other._elemental