OR-Tools  9.6
variable_and_expressions.h
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 // IWYU pragma: private, include "ortools/math_opt/cpp/math_opt.h"
15 // IWYU pragma: friend "ortools/math_opt/cpp/.*"
16 
17 // An object oriented wrapper for variables in ModelStorage (used internally by
18 // Model) with support for arithmetic operations to build linear expressions and
19 // express linear constraints.
20 //
21 // Types are:
22 // - Variable: a reference to a variable of an ModelStorage.
23 //
24 // - LinearExpression: a weighted sum of variables with an optional offset;
25 // something like `3*x + 2*y + 5`.
26 //
27 // - LinearTerm: a term of a linear expression, something like `2*x`. It is
28 // used as an intermediate in the arithmetic operations that builds linear
29 // expressions.
30 //
31 // - (Lower|Upper)BoundedLinearExpression: two classes representing the result
32 // of the comparison of a LinearExpression with a constant. For example `3*x
33 // + 2*y + 5 >= 3`.
34 //
35 // - BoundedLinearExpression: the result of the comparison of a linear
36 // expression with two bounds, an upper bound and a lower bound. For example
37 // `2 <= 3*x + 2*y + 5 <= 3`; or `4 >= 3*x + 2*y + 5 >= 1`.
38 //
39 // - QuadraticTermKey: a key used internally to represent a pair of Variables.
40 //
41 // - QuadraticTerm: a term representing the product of a scalar coefficient
42 // and two Variables (possibly the same); something like `2*x*y` or `3*x*x`.
43 // It is used as an intermediate in the arithmetic operations that build
44 // quadratic expressions.
45 //
46 // - QuadraticExpression: a sum of a quadratic terms, linear terms, and a
47 // scalar offset; something like `3*x*y + 2*x*x + 4x + 5`.
48 //
49 // - VariablesEquality: the result of comparing two Variable instances with
50 // the == operator. For example `a == b`. This intermediate class support
51 // implicit conversion to both bool and BoundedLinearExpression types. This
52 // enables using variables as key of maps (using the conversion to bool)
53 // without preventing adding constraints of variable equality.
54 //
55 // The basic arithmetic operators are overloaded for those types so that we can
56 // write math expressions with variables to build linear expressions. The >=, <=
57 // and == comparison operators are overloaded to produce BoundedLinearExpression
58 // that can be used to build constraints.
59 //
60 // For example we can have:
61 // const Variable x = ...;
62 // const Variable y = ...;
63 // const LinearExpression expr = 2 * x + 3 * y - 2;
64 // const BoundedLinearExpression bounded_expr = 1 <= 2 * x + 3 * y - 2 <= 10;
65 //
66 // To making working with containers of doubles/Variables/LinearExpressions
67 // easier, the template methods Sum() and InnerProduct() are provided, e.g.
68 // const std::vector<int> ints = ...;
69 // const std::vector<double> doubles = ...;
70 // const std::vector<Variable> vars = ...;
71 // const std::vector<LinearTerm> terms = ...;
72 // const std::vector<LinearExpression> exprs = ...;
73 // const LinearExpression s1 = Sum(ints);
74 // const LinearExpression s2 = Sum(doubles);
75 // const LinearExpression s3 = Sum(vars);
76 // const LinearExpression s4 = Sum(terms);
77 // const LinearExpression s5 = Sum(exprs);
78 // const LinearExpression p1 = InnerProduct(ints, vars);
79 // const LinearExpression p2 = InnerProduct(terms, doubles);
80 // const LinearExpression p3 = InnerProduct(doubles, exprs);
81 // These methods work on any iterable type (defining begin() and end()). For
82 // InnerProduct, the inputs must be of equal size, and a compile time error will
83 // be generated unless at least one input is a container of a type implicitly
84 // convertible to double.
85 //
86 // Pre C++20, avoid the use of std::accumulate and std::inner_product with
87 // LinearExpression, they cause a quadratic blowup in running time.
88 //
89 // While there is some complexity in the source, users typically should not need
90 // to look at types other than Variable and LinearExpression too closely. Their
91 // code usually will only refer to those types.
92 #ifndef OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
93 #define OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
94 
95 #include <stdint.h>
96 
97 #include <initializer_list>
98 #include <iterator>
99 #include <limits>
100 #include <ostream>
101 #include <string>
102 #include <utility>
103 
104 #include "absl/container/flat_hash_map.h"
105 #include "absl/strings/string_view.h"
106 #include "absl/log/check.h"
107 #include "ortools/base/logging.h"
108 #include "ortools/base/strong_int.h"
109 #include "ortools/math_opt/cpp/id_map.h" // IWYU pragma: export
110 #include "ortools/math_opt/cpp/key_types.h" // IWYU pragma: export
113 
114 namespace operations_research {
115 namespace math_opt {
116 
117 // Forward declaration needed by Variable.
118 class LinearExpression;
119 
120 // A value type that references a variable from ModelStorage. Usually this type
121 // is passed by copy.
122 class Variable {
123  public:
124  // The typed integer used for ids.
125  using IdType = VariableId;
126 
127  // Usually users will obtain variables using Model::AddVariable(). There
128  // should be little for users to build this object from an ModelStorage.
129  inline Variable(const ModelStorage* storage, VariableId id);
130 
131  // Each call to AddVariable will produce Variables id() increasing by one,
132  // starting at zero. Deleted ids are NOT reused. Thus, if no variables are
133  // deleted, the ids in the model will be consecutive.
134  inline int64_t id() const;
135 
136  inline VariableId typed_id() const;
137  inline const ModelStorage* storage() const;
138 
139  inline double lower_bound() const;
140  inline double upper_bound() const;
141  inline bool is_integer() const;
142  inline absl::string_view name() const;
143 
144  template <typename H>
145  friend H AbslHashValue(H h, const Variable& variable);
146  friend std::ostream& operator<<(std::ostream& ostr, const Variable& variable);
147 
148  inline LinearExpression operator-() const;
149 
150  private:
151  const ModelStorage* storage_;
152  VariableId id_;
153 };
154 
155 // Implements the API of std::unordered_map<Variable, V>, but forbids Variables
156 // from different models in the same map.
157 template <typename V>
159 
160 inline std::ostream& operator<<(std::ostream& ostr, const Variable& variable);
161 
162 // A term in an sum of variables multiplied by coefficients.
163 struct LinearTerm {
164  // Usually this constructor is never called explicitly by users. Instead it
165  // will be implicitly used when writing linear expression. For example `x +
166  // 2*y` will automatically use this constructor to build a LinearTerm from `x`
167  // and the overload of the operator* will also automatically create the one
168  // from `2*y`.
169  inline LinearTerm(Variable variable, double coefficient);
170  inline LinearTerm operator-() const;
171  inline LinearTerm& operator*=(double d);
172  inline LinearTerm& operator/=(double d);
174  double coefficient;
175 };
176 
177 inline LinearTerm operator*(double coefficient, LinearTerm term);
178 inline LinearTerm operator*(LinearTerm term, double coefficient);
179 inline LinearTerm operator*(double coefficient, Variable variable);
180 inline LinearTerm operator*(Variable variable, double coefficient);
181 inline LinearTerm operator/(LinearTerm term, double coefficient);
182 inline LinearTerm operator/(Variable variable, double coefficient);
183 
184 // Forward declaration so that we may add it as a friend to LinearExpression
185 class QuadraticExpression;
186 
187 // This class represents a sum of variables multiplied by coefficient and an
188 // optional offset constant. For example: "3*x + 2*y + 5".
189 //
190 // All operations, including constructor, will raise an assertion if the
191 // operands involve variables from different Model objects.
192 //
193 // Contrary to Variable type, expressions owns the linear expression their
194 // represent. Hence they are usually passed by reference to prevent unnecessary
195 // copies.
196 //
197 // TODO(b/169415098): add a function to remove zero terms.
198 // TODO(b/169415834): study if exact zeros should be automatically removed.
199 // TODO(b/169415103): add tests that some expressions don't compile.
201  public:
202  // For unit testing purpose, we define optional counters. We have to
203  // explicitly define default constructors in that case.
204 #ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
205  LinearExpression() = default;
206 #else // MATH_OPT_USE_EXPRESSION_COUNTERS
208  LinearExpression(const LinearExpression& other);
210  LinearExpression& operator=(const LinearExpression& other);
211 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
212  // Usually users should use the overloads of operators to build linear
213  // expressions. For example, assuming `x` and `y` are Variable, then `x + 2*y
214  // + 5` will build a LinearExpression automatically.
215  inline LinearExpression(std::initializer_list<LinearTerm> terms,
216  double offset);
217  inline LinearExpression(double offset); // NOLINT
218  inline LinearExpression(Variable variable); // NOLINT
219  inline LinearExpression(const LinearTerm& term); // NOLINT
220 
221  inline LinearExpression& operator+=(const LinearExpression& other);
222  inline LinearExpression& operator+=(const LinearTerm& term);
223  inline LinearExpression& operator+=(Variable variable);
224  inline LinearExpression& operator+=(double value);
225  inline LinearExpression& operator-=(const LinearExpression& other);
226  inline LinearExpression& operator-=(const LinearTerm& term);
227  inline LinearExpression& operator-=(Variable variable);
228  inline LinearExpression& operator-=(double value);
229  inline LinearExpression& operator*=(double value);
230  inline LinearExpression& operator/=(double value);
231 
232  // Adds each element of items to this.
233  //
234  // Specifically, letting
235  // (i_1, i_2, ..., i_n) = items
236  // adds
237  // i_1 + i_2 + ... + i_n
238  // to this.
239  //
240  // Example:
241  // const Variable a = ...;
242  // const Variable b = ...;
243  // const std::vector<Variable> vars = {a, b};
244  // LinearExpression expr(8.0);
245  // expr.AddSum(vars);
246  // Results in expr having the value a + b + 8.0.
247  //
248  // Compile time requirements:
249  // * Iterable is a sequence (an array or object with begin() and end()).
250  // * The type of an element of items is one of double, Variable, LinearTerm
251  // or LinearExpression (or is implicitly convertible to one of these types,
252  // e.g. int).
253  //
254  // Note: The implementation is equivalent to:
255  // for(const auto item : items) {
256  // *this += item;
257  // }
258  template <typename Iterable>
259  inline void AddSum(const Iterable& items);
260 
261  // Creates a new LinearExpression object equal to the sum. The implementation
262  // is equivalent to:
263  // LinearExpression expr;
264  // expr.AddSum(items);
265  template <typename Iterable>
266  static inline LinearExpression Sum(const Iterable& items);
267 
268  // Adds the inner product of left and right to this.
269  //
270  // Specifically, letting
271  // (l_1, l_2 ..., l_n) = left,
272  // (r_1, r_2, ..., r_n) = right,
273  // adds
274  // l_1 * r_1 + l_2 * r_2 + ... + l_n * r_n
275  // to this.
276  //
277  // Example:
278  // const Variable a = ...;
279  // const Variable b = ...;
280  // const std::vector<Variable> left = {a, b};
281  // const std::vector<double> right = {10.0, 2.0};
282  // LinearExpression expr(3.0);
283  // expr.AddInnerProduct(left, right)
284  // Results in expr having the value 10.0 * a + 2.0 * b + 3.0.
285  //
286  // Compile time requirements:
287  // * LeftIterable and RightIterable are both sequences (arrays or objects
288  // with begin() and end())
289  // * For both left and right, their elements a type of either double,
290  // Variable, LinearTerm or LinearExpression (or type implicitly convertible
291  // to one of these types, e.g. int).
292  // * At least one of left or right has elements with type double (or a type
293  // implicitly convertible, e.g. int).
294  // Runtime requirements (or CHECK fails):
295  // * left and right have an equal number of elements.
296  //
297  // Note: The implementation is equivalent to the following pseudocode:
298  // for(const auto& [l, r] : zip(left, right)) {
299  // *this += l * r;
300  // }
301  // In particular, the multiplication will be performed on the types of the
302  // elements in left and right (take care with low precision types), but the
303  // addition will always use double precision.
304  template <typename LeftIterable, typename RightIterable>
305  inline void AddInnerProduct(const LeftIterable& left,
306  const RightIterable& right);
307 
308  // Creates a new LinearExpression object equal to the inner product. The
309  // implementation is equivalent to:
310  // LinearExpression expr;
311  // expr.AddInnerProduct(left, right);
312  template <typename LeftIterable, typename RightIterable>
313  static inline LinearExpression InnerProduct(const LeftIterable& left,
314  const RightIterable& right);
315 
316  // Returns the terms in this expression.
317  inline const VariableMap<double>& terms() const;
318  inline double offset() const;
319 
320  // Compute the numeric value of this expression when variables are substituted
321  // by their values in variable_values.
322  //
323  // Will CHECK fail the underlying model storage is different or if a variable
324  // in terms() is missing from variables_values.
325  double Evaluate(const VariableMap<double>& variable_values) const;
326 
327  // Compute the numeric value of this expression when variables are substituted
328  // by their values in variable_values, or zero if missing from the map.
329  //
330  // Will CHECK fail the underlying model storage is different.
332  const VariableMap<double>& variable_values) const;
333 
334  inline const ModelStorage* storage() const;
335  inline const absl::flat_hash_map<VariableId, double>& raw_terms() const;
336 
337 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
338  static thread_local int num_calls_default_constructor_;
339  static thread_local int num_calls_copy_constructor_;
340  static thread_local int num_calls_move_constructor_;
341  static thread_local int num_calls_initializer_list_constructor_;
342  // Reset all counters in the current thread to 0.
343  static void ResetCounters();
344 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
345 
346  private:
348  friend std::ostream& operator<<(std::ostream& ostr,
349  const LinearExpression& expression);
350  friend QuadraticExpression;
351 
352  VariableMap<double> terms_;
353  double offset_ = 0.0;
354 };
355 
356 // Returns the sum of the elements of items as a LinearExpression.
357 //
358 // Specifically, letting
359 // (i_1, i_2, ..., i_n) = items
360 // returns
361 // i_1 + i_2 + ... + i_n.
362 //
363 // Example:
364 // const Variable a = ...;
365 // const Variable b = ...;
366 // const std::vector<Variable> vars = {a, b, a};
367 // Sum(vars)
368 // => 2.0 * a + b
369 // Note, instead of:
370 // LinearExpression expr(3.0);
371 // expr += Sum(items);
372 // Prefer:
373 // expr.AddSum(items);
374 //
375 // See LinearExpression::AddSum() for a precise contract on the type Iterable.
376 //
377 // If the inner product cannot be represented as a LinearExpression, consider
378 // instead QuadraticExpression::Sum().
379 template <typename Iterable>
380 inline LinearExpression Sum(const Iterable& items);
381 
382 // Returns the inner product of left and right as a LinearExpression.
383 //
384 // Specifically, letting
385 // (l_1, l_2 ..., l_n) = left,
386 // (r_1, r_2, ..., r_n) = right,
387 // returns
388 // l_1 * r_1 + l_2 * r_2 + ... + l_n * r_n.
389 //
390 // Example:
391 // const Variable a = ...;
392 // const Variable b = ...;
393 // const std::vector<Variable> left = {a, b};
394 // const std::vector<double> right = {10.0, 2.0};
395 // InnerProduct(left, right);
396 // -=> 10.0 * a + 2.0 * b
397 // Note, instead of:
398 // LinearExpression expr(3.0);
399 // expr += InnerProduct(left, right);
400 // Prefer:
401 // expr.AddInnerProduct(left, right);
402 //
403 // Requires that left and right have equal size, see
404 // LinearExpression::AddInnerProduct for a precise contract on template types.
405 //
406 // If the inner product cannot be represented as a LinearExpression, consider
407 // instead QuadraticExpression::InnerProduct().
408 template <typename LeftIterable, typename RightIterable>
409 inline LinearExpression InnerProduct(const LeftIterable& left,
410  const RightIterable& right);
411 
412 std::ostream& operator<<(std::ostream& ostr,
413  const LinearExpression& expression);
414 
415 // We intentionally pass one of the LinearExpression argument by value so
416 // that we don't make unnecessary copies of temporary objects by using the move
417 // constructor and the returned values optimization (RVO).
419 inline LinearExpression operator+(Variable lhs, double rhs);
420 inline LinearExpression operator+(double lhs, Variable rhs);
422 inline LinearExpression operator+(const LinearTerm& lhs, double rhs);
423 inline LinearExpression operator+(double lhs, const LinearTerm& rhs);
424 inline LinearExpression operator+(const LinearTerm& lhs, Variable rhs);
425 inline LinearExpression operator+(Variable lhs, const LinearTerm& rhs);
426 inline LinearExpression operator+(const LinearTerm& lhs, const LinearTerm& rhs);
427 inline LinearExpression operator+(LinearExpression lhs, double rhs);
428 inline LinearExpression operator+(double lhs, LinearExpression rhs);
431 inline LinearExpression operator+(LinearExpression lhs, const LinearTerm& rhs);
434  const LinearExpression& rhs);
435 inline LinearExpression operator-(Variable lhs, double rhs);
436 inline LinearExpression operator-(double lhs, Variable rhs);
438 inline LinearExpression operator-(const LinearTerm& lhs, double rhs);
439 inline LinearExpression operator-(double lhs, const LinearTerm& rhs);
440 inline LinearExpression operator-(const LinearTerm& lhs, Variable rhs);
441 inline LinearExpression operator-(Variable lhs, const LinearTerm& rhs);
442 inline LinearExpression operator-(const LinearTerm& lhs, const LinearTerm& rhs);
443 inline LinearExpression operator-(LinearExpression lhs, double rhs);
444 inline LinearExpression operator-(double lhs, LinearExpression rhs);
447 inline LinearExpression operator-(LinearExpression lhs, const LinearTerm& rhs);
450  const LinearExpression& rhs);
451 inline LinearExpression operator*(LinearExpression lhs, double rhs);
452 inline LinearExpression operator*(double lhs, LinearExpression rhs);
453 inline LinearExpression operator/(LinearExpression lhs, double rhs);
454 
455 namespace internal {
456 
457 // The result of the equality comparison between two Variable.
458 //
459 // We use an object here to delay the evaluation of equality so that we can use
460 // the operator== in two use-cases:
461 //
462 // 1. when the user want to test that two Variable values references the same
463 // variable. This is supported by having this object support implicit
464 // conversion to bool.
465 //
466 // 2. when the user want to use the equality to create a constraint of equality
467 // between two variables.
469  // Users are not expected to call this constructor. Instead they should only
470  // use the overload of `operator==` that returns this when comparing two
471  // Variable. For example `x == y`.
473  inline operator bool() const; // NOLINT
476 };
477 
478 } // namespace internal
479 
481  const Variable& rhs);
482 inline bool operator!=(const Variable& lhs, const Variable& rhs);
483 
484 // A LinearExpression with a lower bound.
486  // Users are not expected to use this constructor. Instead, they should build
487  // this object using overloads of the >= and <= operators. For example, `x + y
488  // >= 3`.
490  double lower_bound);
492  double lower_bound;
493 };
494 
495 // A LinearExpression with an upper bound.
497  // Users are not expected to use this constructor. Instead they should build
498  // this object using overloads of the >= and <= operators. For example, `x + y
499  // <= 3`.
501  double upper_bound);
503  double upper_bound;
504 };
505 
506 // A LinearExpression with upper and lower bounds.
508  // Users are not expected to use this constructor. Instead they should build
509  // this object using overloads of the >=, <=, and == operators. For example,
510  // `3 <= x + y <= 3`.
512  double lower_bound, double upper_bound);
513  // Users are not expected to use this constructor. This implicit conversion
514  // will be used where a BoundedLinearExpression is expected and the user uses
515  // == comparison of two variables. For example `AddLinearConstraint(x == y);`.
516  inline BoundedLinearExpression( // NOLINT
517  const internal::VariablesEquality& eq);
518  inline BoundedLinearExpression( // NOLINT
519  LowerBoundedLinearExpression lb_expression);
520  inline BoundedLinearExpression( // NOLINT
521  UpperBoundedLinearExpression ub_expression);
522 
523  // Returns the actual lower_bound after taking into account the linear
524  // expression offset.
525  inline double lower_bound_minus_offset() const;
526  // Returns the actual upper_bound after taking into account the linear
527  // expression offset.
528  inline double upper_bound_minus_offset() const;
529 
531  double lower_bound;
532  double upper_bound;
533 };
534 
535 std::ostream& operator<<(std::ostream& ostr,
536  const BoundedLinearExpression& bounded_expression);
537 
538 // We intentionally pass the LinearExpression argument by value so that we don't
539 // make unnecessary copies of temporary objects by using the move constructor
540 // and the returned values optimization (RVO).
542  double constant);
543 inline LowerBoundedLinearExpression operator<=(double constant,
544  LinearExpression expression);
546  double constant);
547 inline LowerBoundedLinearExpression operator<=(double constant,
548  const LinearTerm& term);
550  double constant);
551 inline LowerBoundedLinearExpression operator<=(double constant,
552  Variable variable);
554  double constant);
555 inline UpperBoundedLinearExpression operator>=(double constant,
556  LinearExpression expression);
558  double constant);
559 inline UpperBoundedLinearExpression operator>=(double constant,
560  const LinearTerm& term);
562  double constant);
563 inline UpperBoundedLinearExpression operator>=(double constant,
564  Variable variable);
565 
566 // We intentionally pass the UpperBoundedLinearExpression and
567 // LowerBoundedLinearExpression arguments by value so that we don't
568 // make unnecessary copies of temporary objects by using the move constructor
569 // and the returned values optimization (RVO).
571  double rhs);
572 inline BoundedLinearExpression operator>=(double lhs,
575  double rhs);
576 inline BoundedLinearExpression operator<=(double lhs,
578 // We intentionally pass one LinearExpression argument by value so that we don't
579 // make unnecessary copies of temporary objects by using the move constructor
580 // and the returned values optimization (RVO).
582  const LinearExpression& rhs);
584  const LinearExpression& rhs);
586  const LinearTerm& rhs);
588  const LinearTerm& rhs);
590  LinearExpression rhs);
592  LinearExpression rhs);
598  const LinearTerm& rhs);
600  const LinearTerm& rhs);
601 inline BoundedLinearExpression operator<=(const LinearTerm& lhs, Variable rhs);
602 inline BoundedLinearExpression operator>=(const LinearTerm& lhs, Variable rhs);
603 inline BoundedLinearExpression operator<=(Variable lhs, const LinearTerm& rhs);
604 inline BoundedLinearExpression operator>=(Variable lhs, const LinearTerm& rhs);
608  const LinearExpression& rhs);
610  const LinearTerm& rhs);
612  LinearExpression rhs);
615 inline BoundedLinearExpression operator==(LinearExpression lhs, double rhs);
616 inline BoundedLinearExpression operator==(double lhs, LinearExpression rhs);
618  const LinearTerm& rhs);
619 inline BoundedLinearExpression operator==(const LinearTerm& lhs, Variable rhs);
620 inline BoundedLinearExpression operator==(Variable lhs, const LinearTerm& rhs);
621 inline BoundedLinearExpression operator==(const LinearTerm& lhs, double rhs);
622 inline BoundedLinearExpression operator==(double lhs, const LinearTerm& rhs);
623 inline BoundedLinearExpression operator==(Variable lhs, double rhs);
624 inline BoundedLinearExpression operator==(double lhs, Variable rhs);
625 
626 // Id type used for quadratic terms, i.e. products of two variables.
627 using QuadraticProductId = std::pair<VariableId, VariableId>;
628 
629 // Couples a QuadraticProductId with a ModelStorage, for use with IdMaps.
630 // Namely, this key type satisfies the requirements stated in key_types.h.
631 // Invariant:
632 // * variable_ids_.first <= variable_ids_.second. The constructor will
633 // silently correct this if not satisfied by the inputs.
635  public:
636  // NOTE: this definition is for use by IdMap; clients should not rely upon it.
638 
639  // NOTE: This constructor will silently re-order the passed id so that, upon
640  // exiting the constructor, variable_ids_.first <= variable_ids_.second.
642  // NOTE: This constructor will CHECK fail if the variable models do not agree,
643  // i.e. first_variable.storage() != second_variable.storage(). It will also
644  // silently re-order the passed id so that, upon exiting the constructor,
645  // variable_ids_.first <= variable_ids_.second.
646  inline QuadraticTermKey(Variable first_variable, Variable second_variable);
647 
648  inline QuadraticProductId typed_id() const;
649  inline const ModelStorage* storage() const;
650 
651  // Returns the Variable with the smallest id.
652  Variable first() const { return Variable(storage_, variable_ids_.first); }
653 
654  // Returns the Variable the largest id.
655  Variable second() const { return Variable(storage_, variable_ids_.second); }
656 
657  template <typename H>
658  friend H AbslHashValue(H h, const QuadraticTermKey& key);
659 
660  private:
661  const ModelStorage* storage_;
662  QuadraticProductId variable_ids_;
663 };
664 
665 inline std::ostream& operator<<(std::ostream& ostr,
666  const QuadraticTermKey& key);
667 
668 inline bool operator==(const QuadraticTermKey lhs, const QuadraticTermKey rhs);
669 inline bool operator!=(const QuadraticTermKey lhs, const QuadraticTermKey rhs);
670 
671 // Represents a quadratic term in a sum: coefficient * variable_1 * variable_2.
672 // Invariant:
673 // * first_variable.storage() == second_variable.storage(). The constructor
674 // will CHECK fail if not satisfied.
676  public:
677  QuadraticTerm() = delete;
678  // NOTE: This will CHECK fail if
679  // first_variable.storage() != second_variable.storage().
681  double coefficient);
682 
683  inline double coefficient() const;
684  inline Variable first_variable() const;
685  inline Variable second_variable() const;
686 
687  // This is useful for working with IdMaps
688  inline QuadraticTermKey GetKey() const;
689 
690  inline QuadraticTerm& operator*=(double value);
691  inline QuadraticTerm& operator/=(double value);
692 
693  private:
695  friend QuadraticTerm operator*(double lhs, QuadraticTerm rhs);
696  friend QuadraticTerm operator*(QuadraticTerm lhs, double rhs);
697  friend QuadraticTerm operator/(QuadraticTerm lhs, double rhs);
698 
699  Variable first_variable_;
700  Variable second_variable_;
701  double coefficient_;
702 };
703 // We declare those operator overloads that result in a QuadraticTerm, stated in
704 // lexicographic ordering based on lhs type, rhs type):
706 inline QuadraticTerm operator*(double lhs, QuadraticTerm rhs);
707 inline QuadraticTerm operator*(Variable lhs, Variable rhs);
708 inline QuadraticTerm operator*(Variable lhs, LinearTerm rhs);
709 inline QuadraticTerm operator*(LinearTerm lhs, Variable rhs);
711 inline QuadraticTerm operator*(QuadraticTerm lhs, double rhs);
712 inline QuadraticTerm operator/(QuadraticTerm lhs, double rhs);
713 
714 // Implements the API of std::unordered_map<QuadraticTermKey, V>, but forbids
715 // QuadraticTermKeys from different models in the same map.
716 template <typename V>
718 
719 // This class represents a sum of quadratic terms, linear terms, and constant
720 // offset. For example: "3*x*y + 2*x + 1".
721 //
722 // Mixing terms involving variables from different ModelStorage objects will
723 // lead to CHECK fails, including from the constructors.
724 //
725 // The type owns the associated data representing the terms, and so should
726 // usually be passed by (const) reference to avoid unnecessary copies.
727 //
728 // Note for implementers: Care must be taken to ensure that
729 // linear_terms_.storage() and quadratic_terms_.storage() do not disagree. That
730 // is, it is forbidden that both are non-null and not equal. Use
731 // CheckModelsAgree() and the initializer_list constructor to enforce this
732 // invariant in any class or friend method.
734  public:
735 #ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
736  QuadraticExpression() = default;
737 #else // MATH_OPT_USE_EXPRESSION_COUNTERS
741  QuadraticExpression& operator=(const QuadraticExpression& other);
742 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
743  // Users should prefer the default constructor and operator overloads to build
744  // expressions.
745  inline QuadraticExpression(
746  std::initializer_list<QuadraticTerm> quadratic_terms,
747  std::initializer_list<LinearTerm> linear_terms, double offset);
748  inline QuadraticExpression(double offset); // NOLINT
749  inline QuadraticExpression(Variable variable); // NOLINT
750  inline QuadraticExpression(const LinearTerm& term); // NOLINT
751  inline QuadraticExpression(LinearExpression expr); // NOLINT
752  inline QuadraticExpression(const QuadraticTerm& term); // NOLINT
753 
754  inline double offset() const;
755  inline const VariableMap<double>& linear_terms() const;
756  inline const QuadraticTermMap<double>& quadratic_terms() const;
757 
758  inline const absl::flat_hash_map<VariableId, double>& raw_linear_terms()
759  const;
760  inline const absl::flat_hash_map<QuadraticProductId, double>&
761  raw_quadratic_terms() const;
762 
763  inline QuadraticExpression& operator+=(double value);
764  inline QuadraticExpression& operator+=(Variable variable);
765  inline QuadraticExpression& operator+=(const LinearTerm& term);
766  inline QuadraticExpression& operator+=(const LinearExpression& expr);
767  inline QuadraticExpression& operator+=(const QuadraticTerm& term);
769  inline QuadraticExpression& operator-=(double value);
770  inline QuadraticExpression& operator-=(Variable variable);
771  inline QuadraticExpression& operator-=(const LinearTerm& term);
772  inline QuadraticExpression& operator-=(const LinearExpression& expr);
773  inline QuadraticExpression& operator-=(const QuadraticTerm& term);
775  inline QuadraticExpression& operator*=(double value);
776  inline QuadraticExpression& operator/=(double value);
777 
778  // Adds each element of items to this.
779  //
780  // Specifically, letting
781  // (i_1, i_2, ..., i_n) = items
782  // adds
783  // i_1 + i_2 + ... + i_n
784  // to this.
785  //
786  // Example:
787  // const Variable a = ...;
788  // const Variable b = ...;
789  // const std::vector<Variable> vars = {a, b};
790  // const std::vector<QuadraticTerm> terms = {2 * a * b};
791  // QuadraticExpression expr = 8;
792  // expr.AddSum(vars);
793  // expr.AddSum(terms);
794  // Results in expr having the value 2 * a * b + a + b + 8.0.
795  //
796  // Compile time requirements:
797  // * Iterable is a sequence (an array or object with begin() and end()).
798  // * The type of an element of items is one of double, Variable, LinearTerm,
799  // LinearExpression, QuadraticTerm, or QuadraticExpression (or is
800  // implicitly convertible to one of these types, e.g. int).
801  //
802  // Note: The implementation is equivalent to:
803  // for(const auto item : items) {
804  // *this += item;
805  // }
806  template <typename Iterable>
807  inline void AddSum(const Iterable& items);
808 
809  // Returns the sum of the elements of items.
810  //
811  // Specifically, letting
812  // (i_1, i_2, ..., i_n) = items
813  // returns
814  // i_1 + i_2 + ... + i_n.
815  //
816  // Example:
817  // const Variable a = ...;
818  // const Variable b = ...;
819  // const std::vector<QuadraticTerm> terms = {a * a, 2 * a * b, 3 * b * a};
820  // QuadraticExpression::Sum(vars)
821  // => a^2 + 5 a * b
822  // Note, instead of:
823  // QuadraticExpression expr(3.0);
824  // expr += QuadraticExpression::Sum(items);
825  // Prefer:
826  // expr.AddSum(items);
827  //
828  // See QuadraticExpression::AddSum() for a precise contract on the type
829  // Iterable.
830  template <typename Iterable>
831  static inline QuadraticExpression Sum(const Iterable& items);
832 
833  // Adds the inner product of left and right to this.
834  //
835  // Specifically, letting
836  // (l_1, l_2 ..., l_n) = left,
837  // (r_1, r_2, ..., r_n) = right,
838  // adds
839  // l_1 * r_1 + l_2 * r_2 + ... + l_n * r_n
840  // to this.
841  //
842  // Example:
843  // const Variable a = ...;
844  // const Variable b = ...;
845  // const std::vector<Variable> vars = {a, b};
846  // const std::vector<double> coeffs = {10.0, 2.0};
847  // QuadraticExpression expr = 3.0;
848  // expr.AddInnerProduct(coeffs, vars);
849  // expr.AddInnerProduct(vars, vars);
850  // Results in expr having the value a^2 + b^2 + 10.0 * a + 2.0 * b + 3.0.
851  //
852  // Compile time requirements:
853  // * LeftIterable and RightIterable are both sequences (arrays or objects
854  // with begin() and end())
855  // * For both left and right, their elements are of type double, Variable,
856  // LinearTerm, LinearExpression, QuadraticTerm, or QuadraticExpression (or
857  // is implicitly convertible to one of these types, e.g. int).
858  // Runtime requirements (or CHECK fails):
859  // * The inner product value, and its constitutive intermediate terms, can be
860  // represented as a QuadraticExpression (potentially through an implicit
861  // conversion).
862  // * left and right have an equal number of elements.
863  //
864  // Note: The implementation is equivalent to the following pseudocode:
865  // for(const auto& [l, r] : zip(left, right)) {
866  // *this += l * r;
867  // }
868  // In particular, the multiplication will be performed on the types of the
869  // elements in left and right (take care with low precision types), but the
870  // addition will always use double precision.
871  template <typename LeftIterable, typename RightIterable>
872  inline void AddInnerProduct(const LeftIterable& left,
873  const RightIterable& right);
874 
875  // Returns the inner product of left and right.
876  //
877  // Specifically, letting
878  // (l_1, l_2 ..., l_n) = left,
879  // (r_1, r_2, ..., r_n) = right,
880  // returns
881  // l_1 * r_1 + l_2 * r_2 + ... + l_n * r_n.
882  //
883  // Example:
884  // const Variable a = ...;
885  // const Variable b = ...;
886  // const std::vector<Variable> left = {a, a};
887  // const std::vector<Variable> left = {a, b};
888  // QuadraticExpression::InnerProduct(left, right);
889  // -=> a^2 + a * b
890  // Note, instead of:
891  // QuadraticExpression expr(3.0);
892  // expr += QuadraticExpression::InnerProduct(left, right);
893  // Prefer:
894  // expr.AddInnerProduct(left, right);
895  //
896  // Requires that left and right have equal size, see
897  // QuadraticExpression::AddInnerProduct() for a precise contract on template
898  // types.
899  template <typename LeftIterable, typename RightIterable>
900  static inline QuadraticExpression InnerProduct(const LeftIterable& left,
901  const RightIterable& right);
902 
903  // Compute the numeric value of this expression when variables are substituted
904  // by their values in variable_values.
905  //
906  // Will CHECK fail if the underlying model storage is different, or if a
907  // variable in linear_terms() or quadratic_terms() is missing from
908  // variables_values.
909  double Evaluate(const VariableMap<double>& variable_values) const;
910 
911  // Compute the numeric value of this expression when variables are substituted
912  // by their values in variable_values, or zero if missing from the map.
913  //
914  // Will CHECK fail the underlying model storage is different.
916  const VariableMap<double>& variable_values) const;
917 
918  inline const ModelStorage* storage() const;
919 
920 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
921  static thread_local int num_calls_default_constructor_;
922  static thread_local int num_calls_copy_constructor_;
923  static thread_local int num_calls_move_constructor_;
924  static thread_local int num_calls_initializer_list_constructor_;
925  static thread_local int num_calls_linear_expression_constructor_;
926  // Reset all counters in the current thread to 0.
927  static void ResetCounters();
928 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
929 
930  private:
932  friend std::ostream& operator<<(std::ostream& ostr,
933  const QuadraticExpression& expr);
934  inline void CheckModelsAgree();
935 
936  QuadraticTermMap<double> quadratic_terms_;
937  VariableMap<double> linear_terms_;
938  double offset_ = 0.0;
939 };
940 
941 // We have 6 types that we must consider arithmetic among:
942 // 1. double (scalar value)
943 // 2. Variable (affine value)
944 // 3. LinearTerm (affine value)
945 // 4. LinearExpression (affine value)
946 // 5. QuadraticTerm (quadratic value)
947 // 6. QuadraticExpression (quadratic value)
948 // We care only about those methods that result in a QuadraticExpression. For
949 // example, multiplying a linear value with a linear value, or adding a scalar
950 // to a quadratic value. The single unary method is:
952 
953 // The binary methods, listed in lexicographic order based on
954 // (operator, lhs type #, rhs type #), with the type #s are listed above, are:
955 inline QuadraticExpression operator+(double lhs, const QuadraticTerm& rhs);
956 inline QuadraticExpression operator+(double lhs, QuadraticExpression rhs);
957 inline QuadraticExpression operator+(Variable lhs, const QuadraticTerm& rhs);
959 inline QuadraticExpression operator+(const LinearTerm& lhs,
960  const QuadraticTerm& rhs);
961 inline QuadraticExpression operator+(const LinearTerm& lhs,
962  QuadraticExpression rhs);
964  const QuadraticTerm& rhs);
966  QuadraticExpression rhs);
967 inline QuadraticExpression operator+(const QuadraticTerm& lhs, double rhs);
968 inline QuadraticExpression operator+(const QuadraticTerm& lhs, Variable rhs);
970  const LinearTerm& rhs);
972  LinearExpression rhs);
974  const QuadraticTerm& rhs);
976  QuadraticExpression rhs);
977 inline QuadraticExpression operator+(QuadraticExpression lhs, double rhs);
980  const LinearTerm& rhs);
982  const LinearExpression& rhs);
984  const QuadraticTerm& rhs);
986  const QuadraticExpression& rhs);
987 
988 inline QuadraticExpression operator-(double lhs, const QuadraticTerm& rhs);
989 inline QuadraticExpression operator-(double lhs, QuadraticExpression rhs);
990 inline QuadraticExpression operator-(Variable lhs, const QuadraticTerm& rhs);
992 inline QuadraticExpression operator-(const LinearTerm& lhs,
993  const QuadraticTerm& rhs);
994 inline QuadraticExpression operator-(const LinearTerm& lhs,
995  QuadraticExpression rhs);
997  const QuadraticTerm& rhs);
999  QuadraticExpression rhs);
1000 inline QuadraticExpression operator-(const QuadraticTerm& lhs, double rhs);
1001 inline QuadraticExpression operator-(const QuadraticTerm& lhs, Variable rhs);
1002 inline QuadraticExpression operator-(const QuadraticTerm& lhs,
1003  const LinearTerm& rhs);
1004 inline QuadraticExpression operator-(const QuadraticTerm& lhs,
1005  LinearExpression rhs);
1006 inline QuadraticExpression operator-(const QuadraticTerm& lhs,
1007  const QuadraticTerm& rhs);
1008 inline QuadraticExpression operator-(const QuadraticTerm& lhs,
1009  QuadraticExpression rhs);
1010 inline QuadraticExpression operator-(QuadraticExpression lhs, double rhs);
1013  const LinearTerm& rhs);
1015  const LinearExpression& rhs);
1017  const QuadraticTerm& rhs);
1019  const QuadraticExpression& rhs);
1020 
1021 inline QuadraticExpression operator*(double lhs, QuadraticExpression rhs);
1022 inline QuadraticExpression operator*(Variable lhs, const LinearExpression& rhs);
1024  const LinearExpression& rhs);
1025 inline QuadraticExpression operator*(const LinearExpression& lhs, Variable rhs);
1027  LinearTerm rhs);
1029  const LinearExpression& rhs);
1030 inline QuadraticExpression operator*(QuadraticExpression lhs, double rhs);
1031 
1032 inline QuadraticExpression operator/(QuadraticExpression lhs, double rhs);
1033 
1034 // A QuadraticExpression with a lower bound.
1036  // Users are not expected to use this constructor. Instead, they should build
1037  // this object using overloads of the >= and <= operators. For example, `x * y
1038  // >= 3`.
1040  double lower_bound);
1041  // Users are not expected to explicitly use the following constructor.
1042  inline LowerBoundedQuadraticExpression( // NOLINT
1043  LowerBoundedLinearExpression lb_expression);
1044 
1046  double lower_bound;
1047 };
1048 
1049 // A QuadraticExpression with an upper bound.
1051  // Users are not expected to use this constructor. Instead, they should build
1052  // this object using overloads of the >= and <= operators. For example, `x * y
1053  // <= 3`.
1055  double upper_bound);
1056  // Users are not expected to explicitly use the following constructor.
1057  inline UpperBoundedQuadraticExpression( // NOLINT
1058  UpperBoundedLinearExpression ub_expression);
1059 
1061  double upper_bound;
1062 };
1063 
1064 // A QuadraticExpression with upper and lower bounds.
1066  // Users are not expected to use this constructor. Instead, they should build
1067  // this object using overloads of the >=, <=, and == operators. For example,
1068  // `3 <= x * y <= 3`.
1070  double lower_bound, double upper_bound);
1071 
1072  // Users are not expected to explicitly use the following constructors.
1073  inline BoundedQuadraticExpression( // NOLINT
1074  internal::VariablesEquality var_equality);
1075  inline BoundedQuadraticExpression( // NOLINT
1076  LowerBoundedLinearExpression lb_expression);
1077  inline BoundedQuadraticExpression( // NOLINT
1078  UpperBoundedLinearExpression ub_expression);
1079  inline BoundedQuadraticExpression( // NOLINT
1080  BoundedLinearExpression bounded_expression);
1081  inline BoundedQuadraticExpression( // NOLINT
1082  LowerBoundedQuadraticExpression lb_expression);
1083  inline BoundedQuadraticExpression( // NOLINT
1084  UpperBoundedQuadraticExpression ub_expression);
1085 
1086  // Returns the actual lower_bound after taking into account the quadratic
1087  // expression offset.
1088  inline double lower_bound_minus_offset() const;
1089  // Returns the actual upper_bound after taking into account the quadratic
1090  // expression offset.
1091  inline double upper_bound_minus_offset() const;
1092 
1094  double lower_bound;
1095  double upper_bound;
1096 };
1097 
1098 std::ostream& operator<<(std::ostream& ostr,
1099  const BoundedQuadraticExpression& bounded_expression);
1100 
1101 // We intentionally pass the QuadraticExpression argument by value so that we
1102 // don't make unnecessary copies of temporary objects by using the move
1103 // constructor and the returned values optimization (RVO).
1105  double rhs);
1107  double rhs);
1109  QuadraticExpression rhs);
1111  QuadraticTerm rhs);
1112 
1114  QuadraticExpression rhs);
1116  QuadraticTerm rhs);
1118  double rhs);
1120  double rhs);
1121 
1122 // We intentionally pass the UpperBoundedQuadraticExpression and
1123 // LowerBoundedQuadraticExpression arguments by value so that we don't
1124 // make unnecessary copies of temporary objects by using the move constructor
1125 // and the returned values optimization (RVO).
1127  UpperBoundedQuadraticExpression lhs, double rhs);
1129  double lhs, LowerBoundedQuadraticExpression rhs);
1131  LowerBoundedQuadraticExpression lhs, double rhs);
1133  double lhs, UpperBoundedQuadraticExpression rhs);
1134 // We intentionally pass one QuadraticExpression argument by value so that we
1135 // don't make unnecessary copies of temporary objects by using the move
1136 // constructor and the returned values optimization (RVO).
1137 
1138 // Comparisons with lhs = QuadraticExpression
1140  const QuadraticExpression& rhs);
1142  QuadraticTerm rhs);
1144  const LinearExpression& rhs);
1146  LinearTerm rhs);
1148  Variable rhs);
1150  const QuadraticExpression& rhs);
1152  QuadraticTerm rhs);
1154  const LinearExpression& rhs);
1156  LinearTerm rhs);
1158  Variable rhs);
1160  const QuadraticExpression& rhs);
1162  QuadraticTerm rhs);
1164  const LinearExpression& rhs);
1166  LinearTerm rhs);
1168  Variable rhs);
1170  double rhs);
1171 // Comparisons with lhs = QuadraticTerm
1173  QuadraticExpression rhs);
1175  QuadraticTerm rhs);
1177  LinearExpression rhs);
1181  QuadraticExpression rhs);
1183  QuadraticTerm rhs);
1185  LinearExpression rhs);
1189  QuadraticExpression rhs);
1191  QuadraticTerm rhs);
1193  LinearExpression rhs);
1196 inline BoundedQuadraticExpression operator==(QuadraticTerm lhs, double rhs);
1197 // Comparisons with lhs = LinearExpression
1199  QuadraticExpression rhs);
1201  QuadraticTerm rhs);
1203  QuadraticExpression rhs);
1205  QuadraticTerm rhs);
1207  QuadraticExpression rhs);
1209  QuadraticTerm rhs);
1210 // Comparisons with lhs = LinearTerm
1212  QuadraticExpression rhs);
1215  QuadraticExpression rhs);
1218  QuadraticExpression rhs);
1220 // Comparisons with lhs = Variable
1222  QuadraticExpression rhs);
1225  QuadraticExpression rhs);
1228  QuadraticExpression rhs);
1230 // Comparisons with lhs = Double
1231 inline BoundedQuadraticExpression operator==(double lhs, QuadraticTerm rhs);
1232 inline BoundedQuadraticExpression operator==(double lhs,
1233  QuadraticExpression rhs);
1234 
1237 // Inline function implementations /////////////////////////////////////////////
1240 
1242 // Variable
1244 
1245 Variable::Variable(const ModelStorage* const storage, const VariableId id)
1246  : storage_(storage), id_(id) {
1247  DCHECK(storage != nullptr);
1248 }
1249 
1250 int64_t Variable::id() const { return id_.value(); }
1251 
1252 VariableId Variable::typed_id() const { return id_; }
1253 
1254 const ModelStorage* Variable::storage() const { return storage_; }
1255 
1256 double Variable::lower_bound() const {
1257  return storage_->variable_lower_bound(id_);
1258 }
1259 
1260 double Variable::upper_bound() const {
1261  return storage_->variable_upper_bound(id_);
1262 }
1263 
1264 bool Variable::is_integer() const { return storage_->is_variable_integer(id_); }
1265 
1266 absl::string_view Variable::name() const {
1267  if (storage()->has_variable(id_)) {
1268  return storage_->variable_name(id_);
1269  }
1270  return "[variable deleted from model]";
1271 }
1272 
1273 template <typename H>
1274 H AbslHashValue(H h, const Variable& variable) {
1275  return H::combine(std::move(h), variable.id_.value(), variable.storage_);
1276 }
1277 
1278 std::ostream& operator<<(std::ostream& ostr, const Variable& variable) {
1279  // TODO(b/170992529): handle quoting of invalid characters in the name.
1280  const absl::string_view name = variable.name();
1281  if (name.empty()) {
1282  ostr << "__var#" << variable.id() << "__";
1283  } else {
1284  ostr << name;
1285  }
1286  return ostr;
1287 }
1288 
1290  return LinearExpression({LinearTerm(*this, -1.0)}, 0.0);
1291 }
1292 
1294 // LinearTerm
1296 
1298  : variable(std::move(variable)), coefficient(coefficient) {}
1299 
1301  return LinearTerm(variable, -coefficient);
1302 }
1303 
1305  coefficient *= d;
1306  return *this;
1307 }
1308 
1310  coefficient /= d;
1311  return *this;
1312 }
1313 
1315  term *= coefficient;
1316  return term;
1317 }
1318 
1320  term *= coefficient;
1321  return term;
1322 }
1323 
1324 LinearTerm operator*(const double coefficient, Variable variable) {
1325  return LinearTerm(std::move(variable), coefficient);
1326 }
1327 
1328 LinearTerm operator*(Variable variable, const double coefficient) {
1329  return LinearTerm(std::move(variable), coefficient);
1330 }
1331 
1333  term /= coefficient;
1334  return term;
1335 }
1336 
1337 LinearTerm operator/(Variable variable, const double coefficient) {
1338  return LinearTerm(std::move(variable), 1 / coefficient);
1339 }
1340 
1342 // LinearExpression
1344 
1345 LinearExpression::LinearExpression(std::initializer_list<LinearTerm> terms,
1346  const double offset)
1347  : offset_(offset) {
1348 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1349  ++num_calls_initializer_list_constructor_;
1350 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
1351  for (const auto& term : terms) {
1352  // The same variable may appear multiple times in the input list; we must
1353  // accumulate the coefficients.
1354  terms_[term.variable] += term.coefficient;
1355  }
1356 }
1357 
1359  : LinearExpression({}, offset) {}
1360 
1362  : LinearExpression({LinearTerm(variable, 1.0)}, 0.0) {}
1363 
1365  : LinearExpression({term}, 0.0) {}
1366 
1368  expr.offset_ = -expr.offset_;
1369  for (auto term : expr.terms_) {
1370  term.second = -term.second;
1371  }
1372  return expr;
1373 }
1374 
1375 LinearExpression operator+(const Variable lhs, const double rhs) {
1376  return LinearTerm(lhs, 1.0) + rhs;
1377 }
1378 
1379 LinearExpression operator+(const double lhs, const Variable rhs) {
1380  return lhs + LinearTerm(rhs, 1.0);
1381 }
1382 
1384  return LinearTerm(lhs, 1.0) + LinearTerm(rhs, 1.0);
1385 }
1386 
1387 LinearExpression operator+(const LinearTerm& lhs, const double rhs) {
1388  return LinearExpression({lhs}, rhs);
1389 }
1390 
1391 LinearExpression operator+(const double lhs, const LinearTerm& rhs) {
1392  return LinearExpression({rhs}, lhs);
1393 }
1394 
1396  return lhs + LinearTerm(rhs, 1.0);
1397 }
1398 
1400  return LinearTerm(lhs, 1.0) + rhs;
1401 }
1402 
1404  return LinearExpression({lhs, rhs}, 0);
1405 }
1406 
1408  lhs += rhs;
1409  return lhs;
1410 }
1411 
1413  rhs += lhs;
1414  return rhs;
1415 }
1416 
1418  return std::move(lhs) + LinearTerm(rhs, 1.0);
1419 }
1420 
1422  return LinearTerm(lhs, 1.0) + std::move(rhs);
1423 }
1424 
1426  lhs += rhs;
1427  return lhs;
1428 }
1429 
1431  rhs += lhs;
1432  return rhs;
1433 }
1434 
1436  lhs += rhs;
1437  return lhs;
1438 }
1439 
1440 LinearExpression operator-(const Variable lhs, const double rhs) {
1441  return LinearTerm(lhs, 1.0) - rhs;
1442 }
1443 
1444 LinearExpression operator-(const double lhs, const Variable rhs) {
1445  return lhs - LinearTerm(rhs, 1.0);
1446 }
1447 
1449  return LinearTerm(lhs, 1.0) - LinearTerm(rhs, 1.0);
1450 }
1451 
1452 LinearExpression operator-(const LinearTerm& lhs, const double rhs) {
1453  return LinearExpression({lhs}, -rhs);
1454 }
1455 
1456 LinearExpression operator-(const double lhs, const LinearTerm& rhs) {
1457  return LinearExpression({-rhs}, lhs);
1458 }
1459 
1461  return lhs - LinearTerm(rhs, 1.0);
1462 }
1463 
1465  return LinearTerm(lhs, 1.0) - rhs;
1466 }
1467 
1469  return LinearExpression({lhs, -rhs}, 0);
1470 }
1471 
1473  lhs -= rhs;
1474  return lhs;
1475 }
1476 
1478  auto ret = -std::move(rhs);
1479  ret += lhs;
1480  return ret;
1481 }
1482 
1484  return std::move(lhs) - LinearTerm(rhs, 1.0);
1485 }
1486 
1488  return LinearTerm(lhs, 1.0) - std::move(rhs);
1489 }
1490 
1492  lhs -= rhs;
1493  return lhs;
1494 }
1495 
1497  auto ret = -std::move(rhs);
1498  ret += lhs;
1499  return ret;
1500 }
1501 
1503  lhs -= rhs;
1504  return lhs;
1505 }
1506 
1508  lhs *= rhs;
1509  return lhs;
1510 }
1511 
1513  rhs *= lhs;
1514  return rhs;
1515 }
1516 
1518  lhs /= rhs;
1519  return lhs;
1520 }
1521 
1523  terms_.Add(other.terms_);
1524  offset_ += other.offset_;
1525  return *this;
1526 }
1527 
1529  terms_[term.variable] += term.coefficient;
1530  return *this;
1531 }
1532 
1534  return *this += LinearTerm(variable, 1.0);
1535 }
1536 
1538  offset_ += value;
1539  return *this;
1540 }
1541 
1543  terms_.Subtract(other.terms_);
1544  offset_ -= other.offset_;
1545  return *this;
1546 }
1547 
1549  terms_[term.variable] -= term.coefficient;
1550  return *this;
1551 }
1552 
1554  return *this -= LinearTerm(variable, 1.0);
1555 }
1556 
1558  offset_ -= value;
1559  return *this;
1560 }
1561 
1563  offset_ *= value;
1564  for (auto term : terms_) {
1565  term.second *= value;
1566  }
1567  return *this;
1568 }
1569 
1571  offset_ /= value;
1572  for (auto term : terms_) {
1573  term.second /= value;
1574  }
1575  return *this;
1576 }
1577 
1578 template <typename Iterable>
1579 void LinearExpression::AddSum(const Iterable& items) {
1580  for (const auto& item : items) {
1581  *this += item;
1582  }
1583 }
1584 
1585 template <typename Iterable>
1586 LinearExpression LinearExpression::Sum(const Iterable& items) {
1587  LinearExpression result;
1588  result.AddSum(items);
1589  return result;
1590 }
1591 
1592 template <typename Iterable>
1593 LinearExpression Sum(const Iterable& items) {
1594  return LinearExpression::Sum(items);
1595 }
1596 
1597 namespace internal {
1598 
1599 template <typename LeftIterable, typename RightIterable, typename Expression>
1600 void AddInnerProduct(const LeftIterable& left, const RightIterable& right,
1601  Expression& expr) {
1602  using std::begin;
1603  using std::end;
1604  auto l = begin(left);
1605  auto r = begin(right);
1606  const auto l_end = end(left);
1607  const auto r_end = end(right);
1608  for (; l != l_end && r != r_end; ++l, ++r) {
1609  expr += (*l) * (*r);
1610  }
1611  CHECK(l == l_end)
1612  << "left had more elements than right, sizes should be equal";
1613  CHECK(r == r_end)
1614  << "right had more elements than left, sizes should be equal";
1615 }
1616 
1617 } // namespace internal
1618 
1619 template <typename LeftIterable, typename RightIterable>
1620 void LinearExpression::AddInnerProduct(const LeftIterable& left,
1621  const RightIterable& right) {
1622  internal::AddInnerProduct(left, right, *this);
1623 }
1624 
1625 template <typename LeftIterable, typename RightIterable>
1627  const RightIterable& right) {
1628  LinearExpression result;
1629  result.AddInnerProduct(left, right);
1630  return result;
1631 }
1632 
1633 template <typename LeftIterable, typename RightIterable>
1634 LinearExpression InnerProduct(const LeftIterable& left,
1635  const RightIterable& right) {
1636  return LinearExpression::InnerProduct(left, right);
1637 }
1638 
1639 const VariableMap<double>& LinearExpression::terms() const { return terms_; }
1640 
1641 double LinearExpression::offset() const { return offset_; }
1642 
1644  return terms_.storage();
1645 }
1646 
1647 const absl::flat_hash_map<VariableId, double>& LinearExpression::raw_terms()
1648  const {
1649  return terms_.raw_map();
1650 }
1651 
1653 // VariablesEquality
1655 
1656 namespace internal {
1657 
1659  : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
1660 
1661 inline VariablesEquality::operator bool() const {
1662  return lhs.typed_id() == rhs.typed_id() && lhs.storage() == rhs.storage();
1663 }
1664 
1665 } // namespace internal
1666 
1668  const Variable& rhs) {
1669  return internal::VariablesEquality(lhs, rhs);
1670 }
1671 
1672 bool operator!=(const Variable& lhs, const Variable& rhs) {
1673  return !(lhs == rhs);
1674 }
1675 
1677 // LowerBoundedLinearExpression
1678 // UpperBoundedLinearExpression
1679 // BoundedLinearExpression
1681 
1683  LinearExpression expression, const double lower_bound)
1684  : expression(std::move(expression)), lower_bound(lower_bound) {}
1685 
1687  LinearExpression expression, const double upper_bound)
1688  : expression(std::move(expression)), upper_bound(upper_bound) {}
1689 
1691  const double lower_bound,
1692  const double upper_bound)
1693  : expression(std::move(expression)),
1696 
1698  const internal::VariablesEquality& eq)
1699  : expression({{eq.lhs, 1.0}, {eq.rhs, -1.0}}, 0.0),
1700  lower_bound(0.0),
1701  upper_bound(0.0) {}
1702 
1704  LowerBoundedLinearExpression lb_expression)
1705  : expression(std::move(lb_expression.expression)),
1706  lower_bound(lb_expression.lower_bound),
1707  upper_bound(std::numeric_limits<double>::infinity()) {}
1708 
1710  UpperBoundedLinearExpression ub_expression)
1711  : expression(std::move(ub_expression.expression)),
1712  lower_bound(-std::numeric_limits<double>::infinity()),
1713  upper_bound(ub_expression.upper_bound) {}
1714 
1716  return lower_bound - expression.offset();
1717 }
1718 
1720  return upper_bound - expression.offset();
1721 }
1722 
1724  const double constant) {
1725  return LowerBoundedLinearExpression(std::move(expression), constant);
1726 }
1727 
1729  LinearExpression expression) {
1730  return LowerBoundedLinearExpression(std::move(expression), constant);
1731 }
1732 
1734  const double constant) {
1735  return LowerBoundedLinearExpression(LinearExpression({term}, 0.0), constant);
1736 }
1737 
1739  const LinearTerm& term) {
1740  return LowerBoundedLinearExpression(LinearExpression({term}, 0.0), constant);
1741 }
1742 
1744  const double constant) {
1745  return LinearTerm(variable, 1.0) >= constant;
1746 }
1747 
1749  const Variable variable) {
1750  return constant <= LinearTerm(variable, 1.0);
1751 }
1752 
1754  const double constant) {
1755  return UpperBoundedLinearExpression(std::move(expression), constant);
1756 }
1757 
1759  LinearExpression expression) {
1760  return UpperBoundedLinearExpression(std::move(expression), constant);
1761 }
1762 
1764  const double constant) {
1765  return UpperBoundedLinearExpression(LinearExpression({term}, 0.0), constant);
1766 }
1767 
1769  const LinearTerm& term) {
1770  return UpperBoundedLinearExpression(LinearExpression({term}, 0.0), constant);
1771 }
1772 
1774  const double constant) {
1775  return LinearTerm(variable, 1.0) <= constant;
1776 }
1777 
1779  const Variable variable) {
1780  return constant >= LinearTerm(variable, 1.0);
1781 }
1782 
1784  const double rhs) {
1785  return BoundedLinearExpression(std::move(lhs.expression),
1786  /*lower_bound=*/lhs.lower_bound,
1787  /*upper_bound=*/rhs);
1788 }
1789 
1792  return BoundedLinearExpression(std::move(rhs.expression),
1793  /*lower_bound=*/rhs.lower_bound,
1794  /*upper_bound=*/lhs);
1795 }
1796 
1798  const double rhs) {
1799  return BoundedLinearExpression(std::move(lhs.expression),
1800  /*lower_bound=*/rhs,
1801  /*upper_bound=*/lhs.upper_bound);
1802 }
1803 
1806  return BoundedLinearExpression(std::move(rhs.expression),
1807  /*lower_bound=*/lhs,
1808  /*upper_bound=*/rhs.upper_bound);
1809 }
1810 
1812  const LinearExpression& rhs) {
1813  lhs -= rhs;
1814  return BoundedLinearExpression(
1815  std::move(lhs), /*lower_bound=*/-std::numeric_limits<double>::infinity(),
1816  /*upper_bound=*/0.0);
1817 }
1818 
1820  const LinearExpression& rhs) {
1821  lhs -= rhs;
1822  return BoundedLinearExpression(
1823  std::move(lhs), /*lower_bound=*/0.0,
1824  /*upper_bound=*/std::numeric_limits<double>::infinity());
1825 }
1826 
1828  const LinearTerm& rhs) {
1829  lhs -= rhs;
1830  return BoundedLinearExpression(
1831  std::move(lhs), /*lower_bound=*/-std::numeric_limits<double>::infinity(),
1832  /*upper_bound=*/0.0);
1833 }
1834 
1836  const LinearTerm& rhs) {
1837  lhs -= rhs;
1838  return BoundedLinearExpression(
1839  std::move(lhs), /*lower_bound=*/0.0,
1840  /*upper_bound=*/std::numeric_limits<double>::infinity());
1841 }
1842 
1844  LinearExpression rhs) {
1845  rhs -= lhs;
1846  return BoundedLinearExpression(
1847  std::move(rhs), /*lower_bound=*/0.0,
1848  /*upper_bound=*/std::numeric_limits<double>::infinity());
1849 }
1850 
1852  LinearExpression rhs) {
1853  rhs -= lhs;
1854  return BoundedLinearExpression(
1855  std::move(rhs), /*lower_bound=*/-std::numeric_limits<double>::infinity(),
1856  /*upper_bound=*/0.0);
1857 }
1858 
1860  return std::move(lhs) <= LinearTerm(rhs, 1.0);
1861 }
1862 
1864  return std::move(lhs) >= LinearTerm(rhs, 1.0);
1865 }
1866 
1868  return LinearTerm(lhs, 1.0) <= std::move(rhs);
1869 }
1870 
1872  return LinearTerm(lhs, 1.0) >= std::move(rhs);
1873 }
1874 
1876  const LinearTerm& rhs) {
1877  return BoundedLinearExpression(
1878  LinearExpression({lhs, -rhs}, 0.0),
1879  /*lower_bound=*/-std::numeric_limits<double>::infinity(),
1880  /*upper_bound=*/0.0);
1881 }
1882 
1884  const LinearTerm& rhs) {
1885  return BoundedLinearExpression(
1886  LinearExpression({lhs, -rhs}, 0.0), /*lower_bound=*/0.0,
1887  /*upper_bound=*/std::numeric_limits<double>::infinity());
1888 }
1889 
1891  return lhs <= LinearTerm(rhs, 1.0);
1892 }
1893 
1895  return lhs >= LinearTerm(rhs, 1.0);
1896 }
1897 
1899  return LinearTerm(lhs, 1.0) <= rhs;
1900 }
1901 
1903  return LinearTerm(lhs, 1.0) >= rhs;
1904 }
1905 
1907  return LinearTerm(lhs, 1.0) <= LinearTerm(rhs, 1.0);
1908 }
1909 
1911  return LinearTerm(lhs, 1.0) >= LinearTerm(rhs, 1.0);
1912 }
1913 
1915  const LinearExpression& rhs) {
1916  lhs -= rhs;
1917  return BoundedLinearExpression(std::move(lhs), /*lower_bound=*/0.0,
1918  /*upper_bound=*/0.0);
1919 }
1920 
1922  const LinearTerm& rhs) {
1923  lhs -= rhs;
1924  return BoundedLinearExpression(std::move(lhs), /*lower_bound=*/0.0,
1925  /*upper_bound=*/0.0);
1926 }
1927 
1929  LinearExpression rhs) {
1930  rhs -= lhs;
1931  return BoundedLinearExpression(std::move(rhs), /*lower_bound=*/0.0,
1932  /*upper_bound=*/0.0);
1933 }
1934 
1936  return std::move(lhs) == LinearTerm(rhs, 1.0);
1937 }
1938 
1940  return LinearTerm(lhs, 1.0) == std::move(rhs);
1941 }
1942 
1944  lhs -= rhs;
1945  return BoundedLinearExpression(std::move(lhs), /*lower_bound=*/0.0,
1946  /*upper_bound=*/0.0);
1947 }
1948 
1950  rhs -= lhs;
1951  return BoundedLinearExpression(std::move(rhs), /*lower_bound=*/0.0,
1952  /*upper_bound=*/0.0);
1953 }
1954 
1956  const LinearTerm& rhs) {
1957  return BoundedLinearExpression(LinearExpression({lhs, -rhs}, 0.0),
1958  /*lower_bound=*/0.0,
1959  /*upper_bound=*/0.0);
1960 }
1961 
1963  return lhs == LinearTerm(rhs, 1.0);
1964 }
1965 
1967  return LinearTerm(lhs, 1.0) == rhs;
1968 }
1969 
1970 BoundedLinearExpression operator==(const LinearTerm& lhs, const double rhs) {
1971  return BoundedLinearExpression(LinearExpression({lhs}, -rhs),
1972  /*lower_bound=*/0.0, /*upper_bound=*/0.0);
1973 }
1974 
1975 BoundedLinearExpression operator==(const double lhs, const LinearTerm& rhs) {
1976  return BoundedLinearExpression(LinearExpression({rhs}, -lhs),
1977  /*lower_bound=*/0.0, /*upper_bound=*/0.0);
1978 }
1979 
1980 BoundedLinearExpression operator==(const Variable lhs, const double rhs) {
1981  return LinearTerm(lhs, 1.0) == rhs;
1982 }
1983 
1984 BoundedLinearExpression operator==(const double lhs, const Variable rhs) {
1985  return lhs == LinearTerm(rhs, 1.0);
1986 }
1987 
1989 // QuadraticTermKey
1991 
1993  const QuadraticProductId id)
1994  : storage_(storage), variable_ids_(id) {
1995  if (variable_ids_.first > variable_ids_.second) {
1996  using std::swap; // go/using-std-swap
1997  swap(variable_ids_.first, variable_ids_.second);
1998  }
1999 }
2000 
2002  const Variable second_variable)
2003  : QuadraticTermKey(first_variable.storage(), {first_variable.typed_id(),
2004  second_variable.typed_id()}) {
2005  CHECK_EQ(first_variable.storage(), second_variable.storage())
2007 }
2008 
2009 QuadraticProductId QuadraticTermKey::typed_id() const { return variable_ids_; }
2010 
2011 const ModelStorage* QuadraticTermKey::storage() const { return storage_; }
2012 
2013 template <typename H>
2014 H AbslHashValue(H h, const QuadraticTermKey& key) {
2015  return H::combine(std::move(h), key.typed_id().first.value(),
2016  key.typed_id().second.value(), key.storage());
2017 }
2018 
2019 std::ostream& operator<<(std::ostream& ostr, const QuadraticTermKey& key) {
2020  ostr << "(" << Variable(key.storage(), key.typed_id().first) << ", "
2021  << Variable(key.storage(), key.typed_id().second) << ")";
2022  return ostr;
2023 }
2024 
2025 bool operator==(const QuadraticTermKey lhs, const QuadraticTermKey rhs) {
2026  return lhs.storage() == rhs.storage() && lhs.typed_id() == rhs.typed_id();
2027 }
2028 
2029 bool operator!=(const QuadraticTermKey lhs, const QuadraticTermKey rhs) {
2030  return !(lhs == rhs);
2031 }
2032 
2034 // QuadraticTerm (no arithmetic)
2036 
2037 QuadraticTerm::QuadraticTerm(Variable first_variable, Variable second_variable,
2038  const double coefficient)
2039  : first_variable_(std::move(first_variable)),
2040  second_variable_(std::move(second_variable)),
2041  coefficient_(coefficient) {
2042  CHECK_EQ(first_variable_.storage(), second_variable_.storage())
2044 }
2045 
2046 double QuadraticTerm::coefficient() const { return coefficient_; }
2047 Variable QuadraticTerm::first_variable() const { return first_variable_; }
2048 Variable QuadraticTerm::second_variable() const { return second_variable_; }
2049 
2051  return QuadraticTermKey(
2052  first_variable_.storage(),
2053  std::make_pair(first_variable_.typed_id(), second_variable_.typed_id()));
2054 }
2055 
2057 // QuadraticExpression (no arithmetic)
2059 
2061  const std::initializer_list<QuadraticTerm> quadratic_terms,
2062  const std::initializer_list<LinearTerm> linear_terms, const double offset)
2063  : offset_(offset) {
2064 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2065  ++num_calls_initializer_list_constructor_;
2066 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
2067  for (const LinearTerm& term : linear_terms) {
2068  linear_terms_[term.variable] += term.coefficient;
2069  }
2070  for (const QuadraticTerm& term : quadratic_terms) {
2071  quadratic_terms_[term.GetKey()] += term.coefficient();
2072  }
2073  CheckModelsAgree();
2074 }
2075 
2077  : QuadraticExpression({}, {}, offset) {}
2078 
2080  : QuadraticExpression({}, {LinearTerm(variable, 1.0)}, 0.0) {}
2081 
2083  : QuadraticExpression({}, {term}, 0.0) {}
2084 
2086  : linear_terms_(std::move(expr.terms_)),
2087  offset_(std::exchange(expr.offset_, 0.0)) {
2088 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2089  ++num_calls_linear_expression_constructor_;
2090 #endif // MATH_OPT_USE_EXPRESSION_COUNTERS
2091 }
2092 
2094  : QuadraticExpression({term}, {}, 0.0) {}
2095 
2096 void QuadraticExpression::CheckModelsAgree() {
2097  const ModelStorage* const quadratic_model = quadratic_terms_.storage();
2098  const ModelStorage* const linear_model = linear_terms_.storage();
2099  if ((linear_model != nullptr) && (quadratic_model != nullptr) &&
2100  (quadratic_model != linear_model)) {
2102  }
2103 }
2104 
2106  if (quadratic_terms().storage()) {
2107  return quadratic_terms().storage();
2108  } else {
2109  return linear_terms().storage();
2110  }
2111 }
2112 
2113 double QuadraticExpression::offset() const { return offset_; }
2114 
2116  return linear_terms_;
2117 }
2118 
2120  return quadratic_terms_;
2121 }
2122 
2123 const absl::flat_hash_map<VariableId, double>&
2125  return linear_terms_.raw_map();
2126 }
2127 
2128 const absl::flat_hash_map<QuadraticProductId, double>&
2130  return quadratic_terms_.raw_map();
2131 }
2132 
2134 // Arithmetic operators (non-member).
2135 //
2136 // These are NOT required to explicitly CHECK that the underlying model storages
2137 // agree between linear_terms_ and quadratic_terms_ unless they are a friend of
2138 // QuadraticExpression. As much as possible, defer to the assignment operators
2139 // and the initializer list constructor for QuadraticExpression.
2141 
2142 // ----------------------------- Addition (+) ----------------------------------
2143 
2144 QuadraticExpression operator+(const double lhs, const QuadraticTerm& rhs) {
2145  return QuadraticExpression({rhs}, {}, lhs);
2146 }
2147 
2149  rhs += lhs;
2150  return rhs;
2151 }
2152 
2154  return QuadraticExpression({rhs}, {LinearTerm(lhs, 1.0)}, 0.0);
2155 }
2156 
2158  rhs += LinearTerm(lhs, 1.0);
2159  return rhs;
2160 }
2161 
2163  return QuadraticExpression({rhs}, {lhs}, 0.0);
2164 }
2165 
2167  rhs += lhs;
2168  return rhs;
2169 }
2170 
2172  QuadraticExpression expr(std::move(lhs));
2173  expr += rhs;
2174  return expr;
2175 }
2176 
2178  QuadraticExpression rhs) {
2179  rhs += lhs;
2180  return rhs;
2181 }
2182 
2183 QuadraticExpression operator+(const QuadraticTerm& lhs, const double rhs) {
2184  return QuadraticExpression({lhs}, {}, rhs);
2185 }
2186 
2188  return QuadraticExpression({lhs}, {LinearTerm(rhs, 1.0)}, 0.0);
2189 }
2190 
2192  return QuadraticExpression({lhs}, {rhs}, 0.0);
2193 }
2194 
2196  QuadraticExpression expr(std::move(rhs));
2197  expr += lhs;
2198  return expr;
2199 }
2200 
2202  const QuadraticTerm& rhs) {
2203  return QuadraticExpression({lhs, rhs}, {}, 0.0);
2204 }
2205 
2207  QuadraticExpression rhs) {
2208  rhs += lhs;
2209  return rhs;
2210 }
2211 
2213  lhs += rhs;
2214  return lhs;
2215 }
2216 
2218  lhs += LinearTerm(rhs, 1.0);
2219  return lhs;
2220 }
2221 
2223  lhs += rhs;
2224  return lhs;
2225 }
2226 
2228  const LinearExpression& rhs) {
2229  lhs += rhs;
2230  return lhs;
2231 }
2232 
2234  const QuadraticTerm& rhs) {
2235  lhs += rhs;
2236  return lhs;
2237 }
2238 
2240  const QuadraticExpression& rhs) {
2241  lhs += rhs;
2242  return lhs;
2243 }
2244 
2245 // --------------------------- Subtraction (-) ---------------------------------
2246 
2247 // NOTE: A friend of QuadraticTerm, but does not touch variables
2249  term.coefficient_ *= -1.0;
2250  return term;
2251 }
2252 
2253 // NOTE: A friend of QuadraticExpression, but does not touch variables
2255  expr.offset_ = -expr.offset_;
2256  for (auto term : expr.linear_terms_) {
2257  term.second = -term.second;
2258  }
2259  for (auto term : expr.quadratic_terms_) {
2260  term.second = -term.second;
2261  }
2262  return expr;
2263 }
2264 
2265 QuadraticExpression operator-(const double lhs, const QuadraticTerm& rhs) {
2266  return QuadraticExpression({-rhs}, {}, lhs);
2267 }
2268 
2270  auto expr = -std::move(rhs);
2271  expr += lhs;
2272  return expr;
2273 }
2274 
2276  return QuadraticExpression({-rhs}, {LinearTerm(lhs, 1.0)}, 0.0);
2277 }
2278 
2280  return LinearTerm(lhs, 1.0) - std::move(rhs);
2281 }
2282 
2284  return QuadraticExpression({-rhs}, {lhs}, 0.0);
2285 }
2286 
2288  auto expr = -std::move(rhs);
2289  expr += lhs;
2290  return expr;
2291 }
2292 
2294  QuadraticExpression expr(std::move(lhs));
2295  expr -= rhs;
2296  return expr;
2297 }
2298 
2300  QuadraticExpression rhs) {
2301  auto expr = -std::move(rhs);
2302  expr += lhs;
2303  return expr;
2304 }
2305 
2306 QuadraticExpression operator-(const QuadraticTerm& lhs, const double rhs) {
2307  return QuadraticExpression({lhs}, {}, -rhs);
2308 }
2309 
2311  return QuadraticExpression({lhs}, {LinearTerm(rhs, -1.0)}, 0.0);
2312 }
2313 
2315  return QuadraticExpression({lhs}, {-rhs}, 0.0);
2316 }
2317 
2319  QuadraticExpression expr(-std::move(rhs));
2320  expr += lhs;
2321  return expr;
2322 }
2323 
2325  const QuadraticTerm& rhs) {
2326  return QuadraticExpression({lhs, -rhs}, {}, 0.0);
2327 }
2328 
2330  QuadraticExpression rhs) {
2331  rhs *= -1.0;
2332  rhs += lhs;
2333  return rhs;
2334 }
2335 
2337  lhs -= rhs;
2338  return lhs;
2339 }
2340 
2341 // NOTE: Out-of-order for compilation purposes
2343  lhs -= rhs;
2344  return lhs;
2345 }
2346 
2348  lhs -= LinearTerm(rhs, 1.0);
2349  return lhs;
2350 }
2351 
2352 // NOTE: operator-(QuadraticExpression, const LinearTerm) appears above
2353 
2355  const LinearExpression& rhs) {
2356  lhs -= rhs;
2357  return lhs;
2358 }
2359 
2361  const QuadraticTerm& rhs) {
2362  lhs -= rhs;
2363  return lhs;
2364 }
2365 
2367  const QuadraticExpression& rhs) {
2368  lhs -= rhs;
2369  return lhs;
2370 }
2371 
2372 // ---------------------------- Multiplication (*) -----------------------------
2373 
2374 // NOTE: A friend of QuadraticTerm, but does not touch variables
2375 QuadraticTerm operator*(const double lhs, QuadraticTerm rhs) {
2376  rhs.coefficient_ *= lhs;
2377  return rhs;
2378 }
2379 
2381  rhs *= lhs;
2382  return rhs;
2383 }
2384 
2386  return QuadraticTerm(std::move(lhs), std::move(rhs), 1.0);
2387 }
2388 
2390  return QuadraticTerm(std::move(lhs), std::move(rhs.variable),
2391  rhs.coefficient);
2392 }
2393 
2395  QuadraticExpression expr;
2396  for (const auto& [var, coeff] : rhs.terms()) {
2397  expr += QuadraticTerm(lhs, var, coeff);
2398  }
2399  if (rhs.offset() != 0) {
2400  expr += LinearTerm(std::move(lhs), rhs.offset());
2401  }
2402  return expr;
2403 }
2404 
2406  return QuadraticTerm(std::move(lhs.variable), std::move(rhs),
2407  lhs.coefficient);
2408 }
2409 
2411  return QuadraticTerm(std::move(lhs.variable), std::move(rhs.variable),
2412  lhs.coefficient * rhs.coefficient);
2413 }
2414 
2416  QuadraticExpression expr;
2417  for (const auto& [var, coeff] : rhs.terms()) {
2418  expr += QuadraticTerm(lhs.variable, var, lhs.coefficient * coeff);
2419  }
2420  if (rhs.offset() != 0) {
2421  expr += LinearTerm(std::move(lhs.variable), lhs.coefficient * rhs.offset());
2422  }
2423  return expr;
2424 }
2425 
2427  QuadraticExpression expr;
2428  for (const auto& [var, coeff] : lhs.terms()) {
2429  expr += QuadraticTerm(var, rhs, coeff);
2430  }
2431  if (lhs.offset() != 0) {
2432  expr += LinearTerm(std::move(rhs), lhs.offset());
2433  }
2434  return expr;
2435 }
2436 
2438  QuadraticExpression expr;
2439  for (const auto& [var, coeff] : lhs.terms()) {
2440  expr += QuadraticTerm(var, rhs.variable, coeff * rhs.coefficient);
2441  }
2442  if (lhs.offset() != 0) {
2443  expr += LinearTerm(std::move(rhs.variable), lhs.offset() * rhs.coefficient);
2444  }
2445  return expr;
2446 }
2447 
2449  const LinearExpression& rhs) {
2450  QuadraticExpression expr = lhs.offset() * rhs.offset();
2451  if (rhs.offset() != 0) {
2452  for (const auto& [var, coeff] : lhs.terms()) {
2453  expr += LinearTerm(var, coeff * rhs.offset());
2454  }
2455  }
2456  if (lhs.offset() != 0) {
2457  for (const auto& [var, coeff] : rhs.terms()) {
2458  expr += LinearTerm(var, lhs.offset() * coeff);
2459  }
2460  }
2461  for (const auto& [lhs_var, lhs_coeff] : lhs.terms()) {
2462  for (const auto& [rhs_var, rhs_coeff] : rhs.terms()) {
2463  expr += QuadraticTerm(lhs_var, rhs_var, lhs_coeff * rhs_coeff);
2464  }
2465  }
2466  return expr;
2467 }
2468 
2469 // NOTE: A friend of QuadraticTerm, but does not touch variables
2470 QuadraticTerm operator*(QuadraticTerm lhs, const double rhs) {
2471  lhs.coefficient_ *= rhs;
2472  return lhs;
2473 }
2474 
2476  lhs *= rhs;
2477  return lhs;
2478 }
2479 
2480 // ------------------------------- Division (/) --------------------------------
2481 
2482 // NOTE: A friend of QuadraticTerm, but does not touch variables
2483 QuadraticTerm operator/(QuadraticTerm lhs, const double rhs) {
2484  lhs.coefficient_ /= rhs;
2485  return lhs;
2486 }
2487 
2489  lhs /= rhs;
2490  return lhs;
2491 }
2492 
2494 // In-place arithmetic operators.
2495 //
2496 // These must guarantee that the underlying model storages for linear_terms_ and
2497 // quadratic_terms_ agree upon exit of the function, using CheckModelsAgree(),
2498 // the list initializer constructor for QuadraticExpression, or similar logic.
2500 
2502  offset_ += value;
2503  // NOTE: Not touching terms, no need to check models
2504  return *this;
2505 }
2506 
2508  linear_terms_[variable] += 1;
2509  CheckModelsAgree();
2510  return *this;
2511 }
2512 
2514  linear_terms_[term.variable] += term.coefficient;
2515  CheckModelsAgree();
2516  return *this;
2517 }
2518 
2520  const LinearExpression& expr) {
2521  offset_ += expr.offset();
2522  linear_terms_.Add(expr.terms());
2523  CheckModelsAgree();
2524  return *this;
2525 }
2526 
2528  const QuadraticTerm& term) {
2529  quadratic_terms_[term.GetKey()] += term.coefficient();
2530  CheckModelsAgree();
2531  return *this;
2532 }
2533 
2535  const QuadraticExpression& expr) {
2536  offset_ += expr.offset();
2537  linear_terms_.Add(expr.linear_terms());
2538  quadratic_terms_.Add(expr.quadratic_terms());
2539  CheckModelsAgree();
2540  return *this;
2541 }
2542 
2544  offset_ -= value;
2545  // NOTE: Not touching terms, no need to check models
2546  return *this;
2547 }
2548 
2550  linear_terms_[variable] -= 1;
2551  CheckModelsAgree();
2552  return *this;
2553 }
2554 
2556  linear_terms_[term.variable] -= term.coefficient;
2557  CheckModelsAgree();
2558  return *this;
2559 }
2560 
2562  const LinearExpression& expr) {
2563  offset_ -= expr.offset();
2564  linear_terms_.Subtract(expr.terms());
2565  CheckModelsAgree();
2566  return *this;
2567 }
2568 
2570  const QuadraticTerm& term) {
2571  quadratic_terms_[term.GetKey()] -= term.coefficient();
2572  CheckModelsAgree();
2573  return *this;
2574 }
2575 
2577  const QuadraticExpression& expr) {
2578  offset_ -= expr.offset();
2579  linear_terms_.Subtract(expr.linear_terms());
2580  quadratic_terms_.Subtract(expr.quadratic_terms());
2581  CheckModelsAgree();
2582  return *this;
2583 }
2584 
2586  coefficient_ *= value;
2587  // NOTE: Not touching variables in term, just modifying coefficient, so no
2588  // need to check that models agree.
2589  return *this;
2590 }
2591 
2593  offset_ *= value;
2594  for (auto term : linear_terms_) {
2595  term.second *= value;
2596  }
2597  for (auto term : quadratic_terms_) {
2598  term.second *= value;
2599  }
2600  // NOTE: Not adding/removing/altering variables in expression, just modifying
2601  // coefficients, so no need to check that models agree.
2602  return *this;
2603 }
2604 
2606  coefficient_ /= value;
2607  // NOTE: Not touching variables in term, just modifying coefficient, so no
2608  // need to check that models agree.
2609  return *this;
2610 }
2611 
2613  offset_ /= value;
2614  for (auto term : linear_terms_) {
2615  term.second /= value;
2616  }
2617  for (auto term : quadratic_terms_) {
2618  term.second /= value;
2619  }
2620  // NOTE: Not adding/removing/altering variables in expression, just modifying
2621  // coefficients, so no need to check that models agree.
2622  return *this;
2623 }
2624 
2625 template <typename Iterable>
2626 void QuadraticExpression::AddSum(const Iterable& items) {
2627  for (const auto& item : items) {
2628  *this += item;
2629  }
2630 }
2631 
2632 template <typename Iterable>
2634  QuadraticExpression result;
2635  result.AddSum(items);
2636  return result;
2637 }
2638 
2639 template <typename LeftIterable, typename RightIterable>
2640 void QuadraticExpression::AddInnerProduct(const LeftIterable& left,
2641  const RightIterable& right) {
2642  internal::AddInnerProduct(left, right, *this);
2643 }
2644 
2645 template <typename LeftIterable, typename RightIterable>
2647  const LeftIterable& left, const RightIterable& right) {
2648  QuadraticExpression result;
2649  result.AddInnerProduct(left, right);
2650  return result;
2651 }
2652 
2654 // LowerBoundedQuadraticExpression
2655 // UpperBoundedQuadraticExpression
2656 // BoundedQuadraticExpression
2658 
2660  QuadraticExpression expression, const double lower_bound)
2661  : expression(std::move(expression)), lower_bound(lower_bound) {}
2663  LowerBoundedLinearExpression lb_expression)
2664  : expression(std::move(lb_expression.expression)),
2665  lower_bound(lb_expression.lower_bound) {}
2666 
2668  QuadraticExpression expression, const double upper_bound)
2669  : expression(std::move(expression)), upper_bound(upper_bound) {}
2671  UpperBoundedLinearExpression ub_expression)
2672  : expression(std::move(ub_expression.expression)),
2673  upper_bound(ub_expression.upper_bound) {}
2674 
2676  QuadraticExpression expression, const double lower_bound,
2677  const double upper_bound)
2678  : expression(std::move(expression)),
2682  internal::VariablesEquality var_equality)
2683  : lower_bound(0), upper_bound(0) {
2684  expression += var_equality.lhs;
2685  expression -= var_equality.rhs;
2686 }
2688  LowerBoundedLinearExpression lb_expression)
2689  : expression(std::move(lb_expression.expression)),
2690  lower_bound(lb_expression.lower_bound),
2691  upper_bound(std::numeric_limits<double>::infinity()) {}
2693  UpperBoundedLinearExpression ub_expression)
2694  : expression(std::move(ub_expression.expression)),
2695  lower_bound(-std::numeric_limits<double>::infinity()),
2696  upper_bound(ub_expression.upper_bound) {}
2698  BoundedLinearExpression bounded_expression)
2699  : expression(std::move(bounded_expression.expression)),
2700  lower_bound(bounded_expression.lower_bound),
2701  upper_bound(bounded_expression.upper_bound) {}
2703  LowerBoundedQuadraticExpression lb_expression)
2704  : expression(std::move(lb_expression.expression)),
2705  lower_bound(lb_expression.lower_bound),
2706  upper_bound(std::numeric_limits<double>::infinity()) {}
2708  UpperBoundedQuadraticExpression ub_expression)
2709  : expression(std::move(ub_expression.expression)),
2710  lower_bound(-std::numeric_limits<double>::infinity()),
2711  upper_bound(ub_expression.upper_bound) {}
2712 
2714  return lower_bound - expression.offset();
2715 }
2716 
2718  return upper_bound - expression.offset();
2719 }
2720 
2722  const double rhs) {
2723  return LowerBoundedQuadraticExpression(std::move(lhs), rhs);
2724 }
2726  const double rhs) {
2727  return LowerBoundedQuadraticExpression(lhs, rhs);
2728 }
2730  QuadraticExpression rhs) {
2731  return LowerBoundedQuadraticExpression(std::move(rhs), lhs);
2732 }
2734  const QuadraticTerm rhs) {
2735  return LowerBoundedQuadraticExpression(rhs, lhs);
2736 }
2737 
2739  QuadraticExpression rhs) {
2740  return UpperBoundedQuadraticExpression(std::move(rhs), lhs);
2741 }
2743  const QuadraticTerm rhs) {
2744  return UpperBoundedQuadraticExpression(rhs, lhs);
2745 }
2747  const double rhs) {
2748  return UpperBoundedQuadraticExpression(std::move(lhs), rhs);
2749 }
2751  const double rhs) {
2752  return UpperBoundedQuadraticExpression(lhs, rhs);
2753 }
2754 
2756  const double rhs) {
2757  return BoundedQuadraticExpression(std::move(lhs.expression), rhs,
2758  lhs.upper_bound);
2759 }
2762  return BoundedQuadraticExpression(std::move(rhs.expression), rhs.lower_bound,
2763  lhs);
2764 }
2766  const double rhs) {
2767  return BoundedQuadraticExpression(std::move(lhs.expression), lhs.lower_bound,
2768  rhs);
2769 }
2772  return BoundedQuadraticExpression(std::move(rhs.expression), lhs,
2773  rhs.upper_bound);
2774 }
2775 
2777  const QuadraticExpression& rhs) {
2778  lhs -= rhs;
2779  return BoundedQuadraticExpression(std::move(lhs), 0,
2780  std::numeric_limits<double>::infinity());
2781 }
2783  const QuadraticTerm rhs) {
2784  lhs -= rhs;
2785  return BoundedQuadraticExpression(std::move(lhs), 0,
2786  std::numeric_limits<double>::infinity());
2787 }
2789  const LinearExpression& rhs) {
2790  lhs -= rhs;
2791  return BoundedQuadraticExpression(std::move(lhs), 0,
2792  std::numeric_limits<double>::infinity());
2793 }
2795  const LinearTerm rhs) {
2796  lhs -= rhs;
2797  return BoundedQuadraticExpression(std::move(lhs), 0,
2798  std::numeric_limits<double>::infinity());
2799 }
2801  const Variable rhs) {
2802  lhs -= rhs;
2803  return BoundedQuadraticExpression(std::move(lhs), 0,
2804  std::numeric_limits<double>::infinity());
2805 }
2807  const QuadraticExpression& rhs) {
2808  lhs -= rhs;
2810  std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2811 }
2813  const QuadraticTerm rhs) {
2814  lhs -= rhs;
2816  std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2817 }
2819  const LinearExpression& rhs) {
2820  lhs -= rhs;
2822  std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2823 }
2825  const LinearTerm rhs) {
2826  lhs -= rhs;
2828  std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2829 }
2831  const Variable rhs) {
2832  lhs -= rhs;
2834  std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2835 }
2837  const QuadraticExpression& rhs) {
2838  lhs -= rhs;
2839  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2840 }
2842  const QuadraticTerm rhs) {
2843  lhs -= rhs;
2844  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2845 }
2847  const LinearExpression& rhs) {
2848  lhs -= rhs;
2849  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2850 }
2852  const LinearTerm rhs) {
2853  lhs -= rhs;
2854  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2855 }
2857  const Variable rhs) {
2858  lhs -= rhs;
2859  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2860 }
2862  const double rhs) {
2863  lhs -= rhs;
2864  return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2865 }
2866 
2868  QuadraticExpression rhs) {
2869  rhs -= lhs;
2871  std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2872 }
2874  const QuadraticTerm rhs) {
2876  rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2877 }
2879  LinearExpression rhs) {
2881  std::move(rhs) - lhs, -std::numeric_limits<double>::infinity(), 0);
2882 }
2884  const LinearTerm rhs) {
2886  rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2887 }
2889  const Variable rhs) {
2891  rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2892 }
2894  QuadraticExpression rhs) {
2895  rhs -= lhs;
2896  return BoundedQuadraticExpression(std::move(rhs), 0,
2897  std::numeric_limits<double>::infinity());
2898 }
2900  const QuadraticTerm rhs) {
2901  return BoundedQuadraticExpression(rhs - lhs, 0,
2902  std::numeric_limits<double>::infinity());
2903 }
2905  LinearExpression rhs) {
2906  return BoundedQuadraticExpression(std::move(rhs) - lhs, 0,
2907  std::numeric_limits<double>::infinity());
2908 }
2910  const LinearTerm rhs) {
2911  return BoundedQuadraticExpression(rhs - lhs, 0,
2912  std::numeric_limits<double>::infinity());
2913 }
2915  const Variable rhs) {
2916  return BoundedQuadraticExpression(rhs - lhs, 0,
2917  std::numeric_limits<double>::infinity());
2918 }
2920  QuadraticExpression rhs) {
2921  rhs -= lhs;
2922  return BoundedQuadraticExpression(std::move(rhs), 0, 0);
2923 }
2925  const QuadraticTerm rhs) {
2926  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
2927 }
2929  LinearExpression rhs) {
2930  return BoundedQuadraticExpression(std::move(rhs) - lhs, 0, 0);
2931 }
2933  const LinearTerm rhs) {
2934  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
2935 }
2937  const Variable rhs) {
2938  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
2939 }
2941  const double rhs) {
2942  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
2943 }
2944 
2946  QuadraticExpression rhs) {
2947  rhs -= lhs;
2949  std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2950 }
2952  const QuadraticTerm rhs) {
2954  rhs - std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2955 }
2957  QuadraticExpression rhs) {
2958  rhs -= lhs;
2959  return BoundedQuadraticExpression(std::move(rhs), 0,
2960  std::numeric_limits<double>::infinity());
2961 }
2963  const QuadraticTerm rhs) {
2964  return BoundedQuadraticExpression(rhs - std::move(lhs), 0,
2965  std::numeric_limits<double>::infinity());
2966 }
2968  QuadraticExpression rhs) {
2969  rhs -= lhs;
2970  return BoundedQuadraticExpression(std::move(rhs), 0, 0);
2971 }
2973  const QuadraticTerm rhs) {
2974  return BoundedQuadraticExpression(rhs - std::move(lhs), 0, 0);
2975 }
2976 // LinearTerm --
2978  QuadraticExpression rhs) {
2979  rhs -= lhs;
2981  std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2982 }
2984  const QuadraticTerm rhs) {
2986  rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2987 }
2989  QuadraticExpression rhs) {
2990  rhs -= lhs;
2991  return BoundedQuadraticExpression(std::move(rhs), 0,
2992  std::numeric_limits<double>::infinity());
2993 }
2995  const QuadraticTerm rhs) {
2996  return BoundedQuadraticExpression(rhs - lhs, 0,
2997  std::numeric_limits<double>::infinity());
2998 }
3000  QuadraticExpression rhs) {
3001  rhs -= lhs;
3002  return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3003 }
3005  const QuadraticTerm rhs) {
3006  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3007 }
3008 // Variable --
3010  QuadraticExpression rhs) {
3011  rhs -= lhs;
3013  std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
3014 }
3016  const QuadraticTerm rhs) {
3018  rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
3019 }
3021  QuadraticExpression rhs) {
3022  rhs -= lhs;
3023  return BoundedQuadraticExpression(std::move(rhs), 0,
3024  std::numeric_limits<double>::infinity());
3025 }
3027  const QuadraticTerm rhs) {
3028  return BoundedQuadraticExpression(rhs - lhs, 0,
3029  std::numeric_limits<double>::infinity());
3030 }
3032  QuadraticExpression rhs) {
3033  rhs -= lhs;
3034  return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3035 }
3037  const QuadraticTerm rhs) {
3038  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3039 }
3040 
3041 // Double --
3043  QuadraticExpression rhs) {
3044  rhs -= lhs;
3045  return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3046 }
3048  const QuadraticTerm rhs) {
3049  return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3050 }
3051 
3052 } // namespace math_opt
3053 } // namespace operations_research
3054 
3055 #endif // OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
LinearExpression & operator+=(const LinearExpression &other)
double Evaluate(const VariableMap< double > &variable_values) const
static LinearExpression Sum(const Iterable &items)
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
friend LinearExpression operator-(LinearExpression expr)
friend std::ostream & operator<<(std::ostream &ostr, const LinearExpression &expression)
LinearExpression & operator-=(const LinearExpression &other)
static LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const absl::flat_hash_map< VariableId, double > & raw_terms() const
const std::string & variable_name(VariableId id) const
double variable_lower_bound(VariableId id) const
bool is_variable_integer(VariableId id) const
double variable_upper_bound(VariableId id) const
double Evaluate(const VariableMap< double > &variable_values) const
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
const QuadraticTermMap< double > & quadratic_terms() const
static QuadraticExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
friend std::ostream & operator<<(std::ostream &ostr, const QuadraticExpression &expr)
static QuadraticExpression Sum(const Iterable &items)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const absl::flat_hash_map< QuadraticProductId, double > & raw_quadratic_terms() const
const absl::flat_hash_map< VariableId, double > & raw_linear_terms() const
friend QuadraticExpression operator-(QuadraticExpression expr)
friend QuadraticTerm operator*(double lhs, QuadraticTerm rhs)
friend QuadraticTerm operator-(QuadraticTerm term)
friend QuadraticTerm operator/(QuadraticTerm lhs, double rhs)
QuadraticTermKey(const ModelStorage *storage, QuadraticProductId id)
friend H AbslHashValue(H h, const QuadraticTermKey &key)
friend std::ostream & operator<<(std::ostream &ostr, const Variable &variable)
friend H AbslHashValue(H h, const Variable &variable)
Variable(const ModelStorage *storage, VariableId id)
const std::string name
int64_t value
IntVar * var
Definition: expr_array.cc:1874
const int64_t offset_
Definition: interval.cc:2109
constexpr absl::string_view kObjectsFromOtherModelStorage
Definition: key_types.h:57
void AddInnerProduct(const LeftIterable &left, const RightIterable &right, Expression &expr)
LowerBoundedLinearExpression operator>=(LinearExpression expression, double constant)
std::pair< VariableId, VariableId > QuadraticProductId
LinearExpression Sum(const Iterable &items)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:269
LinearExpression operator-(LinearExpression expr)
bool operator==(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
bool operator!=(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
LowerBoundedLinearExpression operator<=(double constant, LinearExpression expression)
LinearExpression operator+(Variable lhs, double rhs)
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
LinearTerm operator*(double coefficient, LinearTerm term)
LinearTerm operator/(LinearTerm term, double coefficient)
H AbslHashValue(H h, const IndicatorConstraint &constraint)
Collection of objects used to extend the Constraint Solver library.
IntVar * upper_bound
Definition: routing.cc:1087
IntVar * lower_bound
Definition: routing.cc:1086
int64_t coefficient
std::optional< int64_t > end
BoundedLinearExpression(LinearExpression expression, double lower_bound, double upper_bound)
BoundedQuadraticExpression(QuadraticExpression expression, double lower_bound, double upper_bound)
LinearTerm(Variable variable, double coefficient)
LowerBoundedLinearExpression(LinearExpression expression, double lower_bound)
LowerBoundedQuadraticExpression(QuadraticExpression expression, double lower_bound)
UpperBoundedLinearExpression(LinearExpression expression, double upper_bound)
UpperBoundedQuadraticExpression(QuadraticExpression expression, double upper_bound)