15"""Patch to the python wrapper of ../linear_solver.h providing an algebraic API.
17This is directly imported, and use exclusively in ./linear_solver.swig. See that
19For examples leveraging the code defined here, see ./pywraplp_test.py and
20../../../python/linear_programming.py.
35 """A dummy class for a singleton instance used to represent the constant.
37 To represent linear expressions, we store a dictionary
38 MPVariable->coefficient. To represent the constant offset of the expression,
39 we use this class as a substitute: its coefficient will be the offset. To
40 properly be evaluated, its solution_value() needs to be 1.
54 if isinstance(v, numbers.Number):
61 """Holds linear expressions.
63 A linear expression is essentially an offset (floating-point value), and a
64 dictionary mapping MPVariable objects to their coefficient (which is also a
65 floating-point value).
68 OVERRIDDEN_OPERATOR_METHODS = [
90 """Value of this linear expr, using the solution_value of its vars."""
92 return sum(var.solution_value() * coeff
for var, coeff
in coeffs.items())
95 """Private function used by GetCoeffs() to delegate processing.
97 Implementation must either update coeffs or push to the stack a
98 sub-expression and the accumulated multiplier that applies to it.
101 coeffs: A dictionary of variables' coefficients. It is a defaultdict that
102 initializes the new values to 0 by default.
103 multiplier: The current accumulated multiplier to apply to this
105 stack: A list to append to if the current expression is composed of
106 sub-expressions. The elements of the stack are pair tuples
107 (multiplier, linear_expression).
109 raise NotImplementedError
112 coeffs = collections.defaultdict(float)
113 stack = [(1.0, self)]
115 current_multiplier, current_expression = stack.pop()
116 current_expression.AddSelfToCoeffMapOrStack(
117 coeffs, current_multiplier, stack
122 return Sum(self, expr)
125 return Sum(self, cst)
128 return Sum(self, -expr)
131 return Sum(-self, cst)
149 if isinstance(arg, numbers.Number):
155 if isinstance(arg, numbers.Number):
161 if isinstance(arg, numbers.Number):
167 raise ValueError(
'Operators "<" and ">" not supported with the linear solver')
170 raise ValueError(
'Operators "<" and ">" not supported with the linear solver')
173 raise ValueError(
'Operator "!=" not supported with the linear solver')
177 """Represents a LinearExpr containing only a single variable."""
183 return str(self.
__var)
186 coeffs[self.
__var] += multiplier
190 """Represents the product of a LinearExpr by a constant."""
194 if isinstance(coef, numbers.Number):
201 return "-" + str(self.
__expr)
203 return "(" + str(self.
__coef) +
" * " + str(self.
__expr) +
")"
206 current_multiplier = multiplier * self.
__coef
207 if current_multiplier:
208 stack.append((current_multiplier, self.
__expr))
217 return str(self.
__val)
220 coeffs[OFFSET_KEY] += self.
__val * multiplier
224 """Represents the sum of a list of LinearExpr."""
231 for term
in map(str, self.
__array):
236 parts.append(
" - " + term[1:])
238 parts.append(
" + " + term)
239 return f
'({"".join(parts)})'
246 for arg
in reversed(self.
__array):
247 stack.append((multiplier, arg))
258 """Represents a linear constraint: LowerBound <= LinearExpr <= UpperBound."""
266 if self.
__lb > -inf
and self.
__ub < inf:
268 return str(self.
__expr) +
" == " + str(self.
__lb)
271 str(self.
__lb) +
" <= " + str(self.
__expr) +
" <= " + str(self.
__ub)
273 elif self.
__lb > -inf:
274 return str(self.
__expr) +
" >= " + str(self.
__lb)
275 elif self.
__ub < inf:
276 return str(self.
__expr) +
" <= " + str(self.
__ub)
278 return "Trivial inequality (always true)"
281 """Performs the actual creation of the constraint object."""
282 coeffs = self.
__expr.GetCoeffs()
283 constant = coeffs.pop(OFFSET_KEY, 0.0)
284 lb = -solver.infinity()
285 ub = solver.infinity()
287 lb = self.
__lb - constant
289 ub = self.
__ub - constant
291 constraint = solver.RowConstraint(lb, ub, name)
296 constraint.SetCoefficient(v, float(c))