14"""Patch to the python wrapper of ../linear_solver.h providing an algebraic API.
16This is directly imported, and use exclusively in ./linear_solver.i. See that
18For examples leveraging the code defined here, see ./pywraplp_test.py and
19../../../python/linear_programming.py.
34 """A dummy class for a singleton instance used to represent the constant.
36 To represent linear expressions, we store a dictionary
37 MPVariable->coefficient. To represent the constant offset of the expression,
38 we use this class as a substitute: its coefficient will be the offset. To
39 properly be evaluated, its solution_value() needs to be 1.
53 if isinstance(v, numbers.Number):
60 """Holds linear expressions.
62 A linear expression is essentially an offset (floating-point value), and a
63 dictionary mapping MPVariable objects to their coefficient (which is also a
64 floating-point value).
67 OVERRIDDEN_OPERATOR_METHODS = [
89 """Value of this linear expr, using the solution_value of its vars."""
91 return sum(var.solution_value() * coeff
for var, coeff
in coeffs.items())
94 """Private function used by GetCoeffs() to delegate processing.
96 Implementation must either update coeffs or push to the stack a
97 sub-expression and the accumulated multiplier that applies to it.
100 coeffs: A dictionary of variables' coefficients. It is a defaultdict that
101 initializes the new values to 0 by default.
102 multiplier: The current accumulated multiplier to apply to this
104 stack: A list to append to if the current expression is composed of
105 sub-expressions. The elements of the stack are pair tuples
106 (multiplier, linear_expression).
108 raise NotImplementedError
111 coeffs = collections.defaultdict(float)
112 stack = [(1.0, self)]
114 current_multiplier, current_expression = stack.pop()
115 current_expression.AddSelfToCoeffMapOrStack(
116 coeffs, current_multiplier, stack
121 return Sum(self, expr)
124 return Sum(self, cst)
127 return Sum(self, -expr)
130 return Sum(-self, cst)
148 if isinstance(arg, numbers.Number):
154 if isinstance(arg, numbers.Number):
160 if isinstance(arg, numbers.Number):
166 raise ValueError(
'Operators "<" and ">" not supported with the linear solver')
169 raise ValueError(
'Operators "<" and ">" not supported with the linear solver')
172 raise ValueError(
'Operator "!=" not supported with the linear solver')
176 """Represents a LinearExpr containing only a single variable."""
182 return str(self.
__var)
185 coeffs[self.
__var] += multiplier
189 """Represents the product of a LinearExpr by a constant."""
193 if isinstance(coef, numbers.Number):
200 return "-" + str(self.
__expr)
202 return "(" + str(self.
__coef) +
" * " + str(self.
__expr) +
")"
205 current_multiplier = multiplier * self.
__coef
206 if current_multiplier:
207 stack.append((current_multiplier, self.
__expr))
216 return str(self.
__val)
219 coeffs[OFFSET_KEY] += self.
__val * multiplier
223 """Represents the sum of a list of LinearExpr."""
230 for term
in map(str, self.
__array):
235 parts.append(
" - " + term[1:])
237 parts.append(
" + " + term)
238 return f
'({"".join(parts)})'
245 for arg
in reversed(self.
__array):
246 stack.append((multiplier, arg))
257 """Represents a linear constraint: LowerBound <= LinearExpr <= UpperBound."""
265 if self.
__lb > -inf
and self.
__ub < inf:
267 return str(self.
__expr) +
" == " + str(self.
__lb)
270 str(self.
__lb) +
" <= " + str(self.
__expr) +
" <= " + str(self.
__ub)
272 elif self.
__lb > -inf:
273 return str(self.
__expr) +
" >= " + str(self.
__lb)
274 elif self.
__ub < inf:
275 return str(self.
__expr) +
" <= " + str(self.
__ub)
277 return "Trivial inequality (always true)"
280 """Performs the actual creation of the constraint object."""
281 coeffs = self.
__expr.GetCoeffs()
282 constant = coeffs.pop(OFFSET_KEY, 0.0)
283 lb = -solver.infinity()
284 ub = solver.infinity()
286 lb = self.
__lb - constant
288 ub = self.
__ub - constant
290 constraint = solver.RowConstraint(lb, ub, name)
295 constraint.SetCoefficient(v, float(c))