Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
integer_base.h
Go to the documentation of this file.
1// Copyright 2010-2025 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#ifndef OR_TOOLS_SAT_INTEGER_BASE_H_
15#define OR_TOOLS_SAT_INTEGER_BASE_H_
16
17#include <stdlib.h>
18
19#include <algorithm>
20#include <cstdint>
21#include <limits>
22#include <numeric>
23#include <ostream>
24#include <string>
25#include <utility>
26#include <vector>
27
28#include "absl/container/flat_hash_map.h"
29#include "absl/log/check.h"
30#include "absl/strings/str_cat.h"
31#include "absl/types/span.h"
38
39namespace operations_research {
40namespace sat {
41
42// Callbacks that will be called when the search goes back to level 0.
43// Callbacks should return false if the propagation fails.
45 std::vector<std::function<bool()>> callbacks;
46};
47
48// Value type of an integer variable. An integer variable is always bounded
49// on both sides, and this type is also used to store the bounds [lb, ub] of the
50// range of each integer variable.
51//
52// Note that both bounds are inclusive, which allows to write many propagation
53// algorithms for just one of the bound and apply it to the negated variables to
54// get the symmetric algorithm for the other bound.
56
57// The max range of an integer variable is [kMinIntegerValue, kMaxIntegerValue].
58//
59// It is symmetric so the set of possible ranges stays the same when we take the
60// negation of a variable. Moreover, we need some IntegerValue that fall outside
61// this range on both side so that we can usually take care of integer overflow
62// by simply doing "saturated arithmetic" and if one of the bound overflow, the
63// two bounds will "cross" each others and we will get an empty range.
64constexpr IntegerValue kMaxIntegerValue(
65 std::numeric_limits<IntegerValue::ValueType>::max() - 1);
66constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value());
67
68inline double ToDouble(IntegerValue value) {
69 const double kInfinity = std::numeric_limits<double>::infinity();
70 if (value >= kMaxIntegerValue) return kInfinity;
71 if (value <= kMinIntegerValue) return -kInfinity;
72 return static_cast<double>(value.value());
73}
74
75template <class IntType>
76inline IntType IntTypeAbs(IntType t) {
77 return IntType(std::abs(t.value()));
78}
79
80inline IntegerValue CeilRatio(IntegerValue dividend,
81 IntegerValue positive_divisor) {
82 DCHECK_GT(positive_divisor, 0);
83 const IntegerValue result = dividend / positive_divisor;
84 const IntegerValue adjust =
85 static_cast<IntegerValue>(result * positive_divisor < dividend);
86 return result + adjust;
87}
88
89inline IntegerValue FloorRatio(IntegerValue dividend,
90 IntegerValue positive_divisor) {
91 DCHECK_GT(positive_divisor, 0);
92 const IntegerValue result = dividend / positive_divisor;
93 const IntegerValue adjust =
94 static_cast<IntegerValue>(result * positive_divisor > dividend);
95 return result - adjust;
96}
97
98// Overflows and saturated arithmetic.
99
100inline IntegerValue CapProdI(IntegerValue a, IntegerValue b) {
101 return IntegerValue(CapProd(a.value(), b.value()));
102}
103
104inline IntegerValue CapSubI(IntegerValue a, IntegerValue b) {
105 return IntegerValue(CapSub(a.value(), b.value()));
106}
107
108inline IntegerValue CapAddI(IntegerValue a, IntegerValue b) {
109 return IntegerValue(CapAdd(a.value(), b.value()));
110}
111
112inline bool ProdOverflow(IntegerValue t, IntegerValue value) {
113 return AtMinOrMaxInt64(CapProd(t.value(), value.value()));
114}
115
116inline bool AtMinOrMaxInt64I(IntegerValue t) {
117 return AtMinOrMaxInt64(t.value());
118}
119
120// Returns dividend - FloorRatio(dividend, divisor) * divisor;
121//
122// This function is around the same speed than the computation above, but it
123// never causes integer overflow. Note also that when calling FloorRatio() then
124// PositiveRemainder(), the compiler should optimize the modulo away and just
125// reuse the one from the first integer division.
126inline IntegerValue PositiveRemainder(IntegerValue dividend,
127 IntegerValue positive_divisor) {
128 DCHECK_GT(positive_divisor, 0);
129 const IntegerValue m = dividend % positive_divisor;
130 return m < 0 ? m + positive_divisor : m;
131}
132
133inline bool AddTo(IntegerValue a, IntegerValue* result) {
134 if (AtMinOrMaxInt64I(a)) return false;
135 const IntegerValue add = CapAddI(a, *result);
136 if (AtMinOrMaxInt64I(add)) return false;
137 *result = add;
138 return true;
139}
140
141// Computes result += a * b, and return false iff there is an overflow.
142inline bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue* result) {
143 const IntegerValue prod = CapProdI(a, b);
144 if (AtMinOrMaxInt64I(prod)) return false;
145 const IntegerValue add = CapAddI(prod, *result);
146 if (AtMinOrMaxInt64I(add)) return false;
147 *result = add;
148 return true;
149}
150
151// Computes result += a * a, and return false iff there is an overflow.
152inline bool AddSquareTo(IntegerValue a, IntegerValue* result) {
153 return AddProductTo(a, a, result);
154}
155
156// Index of an IntegerVariable.
157//
158// Each time we create an IntegerVariable we also create its negation. This is
159// done like that so internally we only stores and deal with lower bound. The
160// upper bound being the lower bound of the negated variable.
162const IntegerVariable kNoIntegerVariable(-1);
163inline IntegerVariable NegationOf(IntegerVariable i) {
164 return IntegerVariable(i.value() ^ 1);
165}
166
167inline bool VariableIsPositive(IntegerVariable i) {
168 return (i.value() & 1) == 0;
169}
170
171inline IntegerVariable PositiveVariable(IntegerVariable i) {
172 return IntegerVariable(i.value() & (~1));
173}
174
175// Special type for storing only one thing for var and NegationOf(var).
176DEFINE_STRONG_INDEX_TYPE(PositiveOnlyIndex);
177inline PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var) {
178 return PositiveOnlyIndex(var.value() / 2);
179}
180
181inline std::string IntegerTermDebugString(IntegerVariable var,
182 IntegerValue coeff) {
183 coeff = VariableIsPositive(var) ? coeff : -coeff;
184 return absl::StrCat(coeff.value(), "*X", var.value() / 2);
185}
186
187// Returns the vector of the negated variables.
188std::vector<IntegerVariable> NegationOf(absl::Span<const IntegerVariable> vars);
189
190// The integer equivalent of a literal.
191// It represents an IntegerVariable and an upper/lower bound on it.
192//
193// Overflow: all the bounds below kMinIntegerValue and kMaxIntegerValue are
194// treated as kMinIntegerValue - 1 and kMaxIntegerValue + 1.
196 // Because IntegerLiteral should never be created at a bound less constrained
197 // than an existing IntegerVariable bound, we don't allow GreaterOrEqual() to
198 // have a bound lower than kMinIntegerValue, and LowerOrEqual() to have a
199 // bound greater than kMaxIntegerValue. The other side is not constrained
200 // to allow for a computed bound to overflow. Note that both the full initial
201 // domain and the empty domain can always be represented.
202 static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound);
203 static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound);
204
205 // These two static integer literals represent an always true and an always
206 // false condition.
209
210 // Clients should prefer the static construction methods above.
212 IntegerLiteral(IntegerVariable v, IntegerValue b) : var(v), bound(b) {
213 DCHECK_GE(bound, kMinIntegerValue);
214 DCHECK_LE(bound, kMaxIntegerValue + 1);
215 }
216
217 bool IsValid() const { return var != kNoIntegerVariable; }
218 bool IsAlwaysTrue() const { return var == kNoIntegerVariable && bound <= 0; }
219 bool IsAlwaysFalse() const { return var == kNoIntegerVariable && bound > 0; }
220
221 // The negation of x >= bound is x <= bound - 1.
222 IntegerLiteral Negated() const;
223
225 return var == o.var && bound == o.bound;
226 }
228 return var != o.var || bound != o.bound;
229 }
230
231 std::string DebugString() const {
232 return VariableIsPositive(var)
233 ? absl::StrCat("I", var.value() / 2, ">=", bound.value())
234 : absl::StrCat("I", var.value() / 2, "<=", -bound.value());
235 }
236
237 // Note that bound should be in [kMinIntegerValue, kMaxIntegerValue + 1].
238 IntegerVariable var = kNoIntegerVariable;
239 IntegerValue bound = IntegerValue(0);
240};
241
242inline std::ostream& operator<<(std::ostream& os, IntegerLiteral i_lit) {
243 os << i_lit.DebugString();
244 return os;
245}
246
247inline std::ostream& operator<<(std::ostream& os,
248 absl::Span<const IntegerLiteral> literals) {
249 os << "[";
250 bool first = true;
251 for (const IntegerLiteral literal : literals) {
252 if (first) {
253 first = false;
254 } else {
255 os << ",";
256 }
257 os << literal.DebugString();
258 }
259 os << "]";
260 return os;
261}
262
263// Represents [coeff * variable + constant] or just a [constant].
264//
265// In some places it is useful to manipulate such expression instead of having
266// to create an extra integer variable. This is mainly used for scheduling
267// related constraints.
269 // Helper to construct an AffineExpression.
270 AffineExpression() = default;
271 AffineExpression(IntegerValue cst) // NOLINT(runtime/explicit)
272 : constant(cst) {}
273 AffineExpression(IntegerVariable v) // NOLINT(runtime/explicit)
274 : var(v), coeff(1) {}
275 AffineExpression(IntegerVariable v, IntegerValue c)
276 : var(c >= 0 ? v : NegationOf(v)), coeff(IntTypeAbs(c)) {}
277 AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
278 : var(c >= 0 ? v : NegationOf(v)), coeff(IntTypeAbs(c)), constant(cst) {}
279
280 // Returns the integer literal corresponding to expression >= value or
281 // expression <= value.
282 //
283 // On constant expressions, they will return IntegerLiteral::TrueLiteral()
284 // or IntegerLiteral::FalseLiteral().
285 IntegerLiteral GreaterOrEqual(IntegerValue bound) const;
286 IntegerLiteral LowerOrEqual(IntegerValue bound) const;
287
292
293 AffineExpression MultipliedBy(IntegerValue multiplier) const {
294 // Note that this also works if multiplier is negative.
295 return AffineExpression(var, coeff * multiplier, constant * multiplier);
296 }
297
299 return var == o.var && coeff == o.coeff && constant == o.constant;
300 }
301
302 // Returns the value of this affine expression given its variable value.
303 IntegerValue ValueAt(IntegerValue var_value) const {
304 return coeff * var_value + constant;
305 }
306
307 // Returns the affine expression value under a given LP solution.
309 lp_values) const {
310 if (var == kNoIntegerVariable) return ToDouble(constant);
311 return ToDouble(coeff) * lp_values[var] + ToDouble(constant);
312 }
313
314 bool IsConstant() const { return var == kNoIntegerVariable; }
315
316 std::string DebugString() const {
317 if (var == kNoIntegerVariable) return absl::StrCat(constant.value());
318 if (constant == 0) {
319 return absl::StrCat("(", coeff.value(), " * X", var.value(), ")");
320 } else {
321 return absl::StrCat("(", coeff.value(), " * X", var.value(), " + ",
322 constant.value(), ")");
323 }
324 }
325
326 // The coefficient MUST be positive. Use NegationOf(var) if needed.
327 //
328 // TODO(user): Make this private to enforce the invariant that coeff cannot be
329 // negative.
330 IntegerVariable var = kNoIntegerVariable; // kNoIntegerVariable for constant.
331 IntegerValue coeff = IntegerValue(0); // Zero for constant.
332 IntegerValue constant = IntegerValue(0);
333};
334
335template <typename H>
337 if (e.var != kNoIntegerVariable) {
338 h = H::combine(std::move(h), e.var);
339 h = H::combine(std::move(h), e.coeff);
340 }
341 h = H::combine(std::move(h), e.constant);
342
343 return h;
344}
345
346// A linear expression with at most two variables (coeffs can be zero).
347// And some utility to canonicalize them.
349 LinearExpression2() = default;
350 LinearExpression2(IntegerVariable v1, IntegerVariable v2, IntegerValue c1,
351 IntegerValue c2) {
352 vars[0] = v1;
353 vars[1] = v2;
354 coeffs[0] = c1;
355 coeffs[1] = c2;
356 }
357
358 // Build (v1 - v2)
359 static LinearExpression2 Difference(IntegerVariable v1, IntegerVariable v2) {
360 return LinearExpression2(v1, v2, 1, -1);
361 }
362
363 // Take the negation of this expression.
364 void Negate() {
365 vars[0] = NegationOf(vars[0]);
366 vars[1] = NegationOf(vars[1]);
367 }
368
369 // This will not change any bounds on the LinearExpression2.
370 // That is we will not potentially Negate() the expression like
371 // CanonicalizeAndUpdateBounds() might do.
372 // Note that since kNoIntegerVariable=-1 and we sort the variables, if we any
373 // one zero and one non-zero we will always have the zero first.
375
376 // Fully canonicalizes the expression and updates the given bounds
377 // accordingly. This is the same as SimpleCanonicalization(), DivideByGcd()
378 // and the NegateForCanonicalization() with a proper updates of the bounds.
379 void CanonicalizeAndUpdateBounds(IntegerValue& lb, IntegerValue& ub,
380 bool allow_negation = false);
381
382 // Divides the expression by the gcd of both coefficients, and returns it.
383 // Note that we always return something >= 1 even if both coefficients are
384 // zero.
385 IntegerValue DivideByGcd();
386
387 // Makes sure expr and -expr have the same canonical representation by
388 // negating the expression of it is in the non-canonical form. Returns true if
389 // the expression was negated.
391
392 absl::Span<const IntegerVariable> non_zero_vars() const {
393 const int first = coeffs[0] == 0 ? 1 : 0;
394 const int last = coeffs[1] == 0 ? 0 : 1;
395 return absl::MakeSpan(&vars[first], last - first + 1);
396 }
397
398 absl::Span<const IntegerValue> non_zero_coeffs() const {
399 const int first = coeffs[0] == 0 ? 1 : 0;
400 const int last = coeffs[1] == 0 ? 0 : 1;
401 return absl::MakeSpan(&coeffs[first], last - first + 1);
402 }
403
404 bool operator==(const LinearExpression2& o) const {
405 return vars[0] == o.vars[0] && vars[1] == o.vars[1] &&
406 coeffs[0] == o.coeffs[0] && coeffs[1] == o.coeffs[1];
407 }
408
409 bool operator<(const LinearExpression2& o) const {
410 return std::tie(vars[0], vars[1], coeffs[0], coeffs[1]) <
411 std::tie(o.vars[0], o.vars[1], o.coeffs[0], o.coeffs[1]);
412 }
413
414 IntegerValue coeffs[2];
415 IntegerVariable vars[2];
416};
417
418inline std::ostream& operator<<(std::ostream& os,
419 const LinearExpression2& expr) {
420 os << absl::StrCat(expr.coeffs[0], " X", expr.vars[0], " + ", expr.coeffs[1],
421 " X", expr.vars[1]);
422 return os;
423}
424
425template <typename H>
427 h = H::combine(std::move(h), e.vars[0]);
428 h = H::combine(std::move(h), e.vars[1]);
429 h = H::combine(std::move(h), e.coeffs[0]);
430 h = H::combine(std::move(h), e.coeffs[1]);
431 return h;
432}
433
434// Note that we only care about binary relation, not just simple variable bound.
437 public:
438 // Register the fact that expr \in [lb, ub] is true.
439 //
440 // Returns true if this fact is new, that is if the bounds are tighter than
441 // the current ones.
442 bool Add(LinearExpression2 expr, IntegerValue lb, IntegerValue ub);
443
444 // Returns the known status of expr <= bound.
445 RelationStatus GetStatus(LinearExpression2 expr, IntegerValue lb,
446 IntegerValue ub) const;
447
448 // Return a valid upper-bound on the given LinearExpression2. Note that we
449 // assume kMaxIntegerValue is always valid and returns it if we don't have an
450 // entry in the hash-map.
451 IntegerValue GetUpperBound(LinearExpression2 expr) const;
452
453 private:
454 // The best bound on the given "canonicalized" expression.
455 absl::flat_hash_map<LinearExpression2, std::pair<IntegerValue, IntegerValue>>
456 best_bounds_;
457};
458
459// A model singleton that holds the root level integer variable domains.
460// we just store a single domain for both var and its negation.
462 : public util_intops::StrongVector<PositiveOnlyIndex, Domain> {};
463
464// A model singleton used for debugging. If this is set in the model, then we
465// can check that various derived constraint do not exclude this solution (if it
466// is a known optimal solution for instance).
468 // This is the value of all proto variables.
469 // It should be of the same size of the PRESOLVED model and should correspond
470 // to a solution to the presolved model.
471 std::vector<int64_t> proto_values;
472
473 // This is filled from proto_values at load-time, and using the
474 // cp_model_mapping, we cache the solution of the integer variables that are
475 // mapped. Note that it is possible that not all integer variable are mapped.
476 //
477 // TODO(user): When this happen we should be able to infer the value of these
478 // derived variable in the solution. For now, we only do that for the
479 // objective variable.
482};
483
484// A value and a literal.
488 const ValueLiteralPair& b) const {
489 return a.literal < b.literal;
490 }
491 };
494 const ValueLiteralPair& b) const {
495 return (a.value < b.value) ||
496 (a.value == b.value && a.literal < b.literal);
497 }
498 };
499
500 bool operator==(const ValueLiteralPair& o) const {
501 return value == o.value && literal == o.literal;
502 }
503
504 std::string DebugString() const;
505
506 IntegerValue value = IntegerValue(0);
508};
509
510std::ostream& operator<<(std::ostream& os, const ValueLiteralPair& p);
511
512DEFINE_STRONG_INDEX_TYPE(IntervalVariable);
513const IntervalVariable kNoIntervalVariable(-1);
514
515// ============================================================================
516// Implementation.
517// ============================================================================
518
519inline IntegerLiteral IntegerLiteral::GreaterOrEqual(IntegerVariable i,
520 IntegerValue bound) {
523}
524
525inline IntegerLiteral IntegerLiteral::LowerOrEqual(IntegerVariable i,
526 IntegerValue bound) {
532 return IntegerLiteral(kNoIntegerVariable, IntegerValue(-1));
536 return IntegerLiteral(kNoIntegerVariable, IntegerValue(1));
538
540 // Note that bound >= kMinIntegerValue, so -bound + 1 will have the correct
541 // capped value.
542 return IntegerLiteral(
543 NegationOf(IntegerVariable(var)),
545}
546
547// var * coeff + constant >= bound.
549 IntegerValue bound) const {
551 return constant >= bound ? IntegerLiteral::TrueLiteral()
553 }
554 DCHECK_GT(coeff, 0);
556 CeilRatio(bound - constant, coeff));
557}
558
559// var * coeff + constant <= bound.
560inline IntegerLiteral AffineExpression::LowerOrEqual(IntegerValue bound) const {
561 if (var == kNoIntegerVariable) {
563 : IntegerLiteral::FalseLiteral();
564 }
565 DCHECK_GT(coeff, 0);
567}
568
569} // namespace sat
570} // namespace operations_research
571
572#endif // OR_TOOLS_SAT_INTEGER_BASE_H_
IntegerValue GetUpperBound(LinearExpression2 expr) const
bool Add(LinearExpression2 expr, IntegerValue lb, IntegerValue ub)
RelationStatus GetStatus(LinearExpression2 expr, IntegerValue lb, IntegerValue ub) const
Returns the known status of expr <= bound.
bool AddSquareTo(IntegerValue a, IntegerValue *result)
Computes result += a * a, and return false iff there is an overflow.
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
Computes result += a * b, and return false iff there is an overflow.
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
bool AddTo(IntegerValue a, IntegerValue *result)
IntType IntTypeAbs(IntType t)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool ProdOverflow(IntegerValue t, IntegerValue value)
const LiteralIndex kNoLiteralIndex(-1)
std::string IntegerTermDebugString(IntegerVariable var, IntegerValue coeff)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
Returns the vector of the negated variables.
Definition integer.cc:52
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
const IntervalVariable kNoIntervalVariable(-1)
IntegerVariable PositiveVariable(IntegerVariable i)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition cp_model.cc:89
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
IntegerValue CapAddI(IntegerValue a, IntegerValue b)
H AbslHashValue(H h, const IntVar &i)
– ABSL HASHING SUPPORT --------------------------------------------------—
Definition cp_model.h:515
constexpr Fractional kInfinity
Infinity for type Fractional.
Definition lp_types.h:87
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
bool VariableIsPositive(IntegerVariable i)
IntegerValue CapSubI(IntegerValue a, IntegerValue b)
bool AtMinOrMaxInt64I(IntegerValue t)
IntegerValue CapProdI(IntegerValue a, IntegerValue b)
Overflows and saturated arithmetic.
double ToDouble(IntegerValue value)
In SWIG mode, we don't want anything besides these top-level includes.
bool AtMinOrMaxInt64(int64_t x)
Checks if x is equal to the min or the max value of an int64_t.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapSub(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
#define DEFINE_STRONG_INT64_TYPE(integer_type_name)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
IntegerLiteral GreaterOrEqual(IntegerValue bound) const
var * coeff + constant >= bound.
bool operator==(AffineExpression o) const
AffineExpression MultipliedBy(IntegerValue multiplier) const
AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
AffineExpression()=default
Helper to construct an AffineExpression.
IntegerValue ValueAt(IntegerValue var_value) const
Returns the value of this affine expression given its variable value.
AffineExpression(IntegerVariable v, IntegerValue c)
double LpValue(const util_intops::StrongVector< IntegerVariable, double > &lp_values) const
Returns the affine expression value under a given LP solution.
IntegerLiteral LowerOrEqual(IntegerValue bound) const
var * coeff + constant <= bound.
util_intops::StrongVector< IntegerVariable, bool > ivar_has_value
util_intops::StrongVector< IntegerVariable, IntegerValue > ivar_values
bool operator==(IntegerLiteral o) const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
IntegerLiteral Negated() const
The negation of x >= bound is x <= bound - 1.
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
IntegerLiteral(IntegerVariable v, IntegerValue b)
bool operator!=(IntegerLiteral o) const
IntegerLiteral()
Clients should prefer the static construction methods above.
std::vector< std::function< bool()> > callbacks
bool operator==(const LinearExpression2 &o) const
bool operator<(const LinearExpression2 &o) const
LinearExpression2(IntegerVariable v1, IntegerVariable v2, IntegerValue c1, IntegerValue c2)
absl::Span< const IntegerValue > non_zero_coeffs() const
absl::Span< const IntegerVariable > non_zero_vars() const
void CanonicalizeAndUpdateBounds(IntegerValue &lb, IntegerValue &ub, bool allow_negation=false)
static LinearExpression2 Difference(IntegerVariable v1, IntegerVariable v2)
Build (v1 - v2)
void Negate()
Take the negation of this expression.
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
bool operator==(const ValueLiteralPair &o) const