14#ifndef ORTOOLS_SAT_INTEGER_BASE_H_
15#define ORTOOLS_SAT_INTEGER_BASE_H_
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"
70 std::numeric_limits<IntegerValue::ValueType>::max() - 1);
74 const double kInfinity = std::numeric_limits<double>::infinity();
77 return static_cast<double>(value.value());
80template <
class IntType>
82 return IntType(std::abs(t.value()));
86 IntegerValue positive_divisor) {
87 DCHECK_GT(positive_divisor, 0);
88 const IntegerValue result = dividend / positive_divisor;
89 const IntegerValue adjust =
90 static_cast<IntegerValue
>(result * positive_divisor < dividend);
91 return result + adjust;
95 IntegerValue positive_divisor) {
96 DCHECK_GT(positive_divisor, 0);
97 const IntegerValue result = dividend / positive_divisor;
98 const IntegerValue adjust =
99 static_cast<IntegerValue
>(result * positive_divisor > dividend);
100 return result - adjust;
105 IntegerValue positive_divisor) {
106 if (positive_divisor == 1)
return dividend;
107 return FloorRatio(dividend, positive_divisor);
112inline IntegerValue
CapProdI(IntegerValue a, IntegerValue
b) {
113 return IntegerValue(
CapProd(a.value(),
b.value()));
116inline IntegerValue
CapSubI(IntegerValue a, IntegerValue
b) {
117 return IntegerValue(
CapSub(a.value(),
b.value()));
120inline IntegerValue
CapAddI(IntegerValue a, IntegerValue
b) {
121 return IntegerValue(
CapAdd(a.value(),
b.value()));
139 IntegerValue positive_divisor) {
140 DCHECK_GT(positive_divisor, 0);
141 const IntegerValue m = dividend % positive_divisor;
142 return m < 0 ? m + positive_divisor : m;
145inline bool AddTo(IntegerValue a, IntegerValue* result) {
147 const IntegerValue add =
CapAddI(a, *result);
154inline bool AddProductTo(IntegerValue a, IntegerValue
b, IntegerValue* result) {
155 const IntegerValue prod =
CapProdI(a,
b);
157 const IntegerValue add =
CapAddI(prod, *result);
176 return IntegerVariable(
i.value() ^ 1);
180 return (
i.value() & 1) == 0;
184 return IntegerVariable(
i.value() & (~1));
190 return PositiveOnlyIndex(var.value() / 2);
194 IntegerValue coeff) {
200std::vector<IntegerVariable>
NegationOf(absl::Span<const IntegerVariable> vars);
245 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
246 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
251 IntegerValue
bound = IntegerValue(0);
260 absl::Span<const IntegerLiteral> literals) {
269 os << literal.DebugString();
315 IntegerValue
ValueAt(IntegerValue var_value)
const {
328 template <
typename Sink>
333 absl::Format(&sink,
"(%v + %d)",
344 IntegerValue
coeff = IntegerValue(0);
351 h = H::combine(std::move(h), e.
var);
352 h = H::combine(std::move(h), e.
coeff);
354 h = H::combine(std::move(h), e.
constant);
406 IntegerValue other_var_lb)
const;
423 const int first =
coeffs[0] == 0 ? 1 : 0;
424 const int last =
coeffs[1] == 0 ? 0 : 1;
425 return absl::MakeSpan(&
vars[first], last - first + 1);
429 const int first =
coeffs[0] == 0 ? 1 : 0;
430 const int last =
coeffs[1] == 0 ? 0 : 1;
431 return absl::MakeSpan(&
coeffs[first], last - first + 1);
447 template <
typename Sink>
449 if (expr.
coeffs[0] == 0) {
450 if (expr.
coeffs[1] == 0) {
451 absl::Format(&sink,
"0");
453 absl::Format(&sink,
"%v",
457 absl::Format(&sink,
"%v + %v",
471 expr.
vars[1] =
b.var;
473 IntegerValue rhs = ub +
b.constant - a.
constant;
479 return {std::move(expr), rhs};
484 h = H::combine(std::move(h), e.
vars[0]);
485 h = H::combine(std::move(h), e.
vars[1]);
486 h = H::combine(std::move(h), e.
coeffs[0]);
487 h = H::combine(std::move(h), e.
coeffs[1]);
515 IntegerValue ub)
const;
523 std::vector<std::pair<LinearExpression2, IntegerValue>>
526 std::vector<std::tuple<LinearExpression2, IntegerValue, IntegerValue>>
531 absl::flat_hash_map<LinearExpression2, std::pair<IntegerValue, IntegerValue>>
579 return (a.
value <
b.value) ||
590 IntegerValue
value = IntegerValue(0);
609 const auto it = best_bounds_.find(expr);
610 if (it != best_bounds_.end()) {
611 const auto [known_lb, known_ub] = it->second;
626 IntegerValue bound) {
632 IntegerValue bound) {
655 IntegerValue bound)
const {
std::pair< AddResult, AddResult > Add(LinearExpression2 expr, IntegerValue lb, IntegerValue ub)
int64_t num_bounds() const
IntegerValue UpperBoundWhenCanonicalized(LinearExpression2 expr) const
std::vector< std::tuple< LinearExpression2, IntegerValue, IntegerValue > > GetSortedNonTrivialBounds() const
std::vector< std::pair< LinearExpression2, IntegerValue > > GetSortedNonTrivialUpperBounds() const
RelationStatus GetStatus(LinearExpression2 expr, IntegerValue lb, IntegerValue ub) const
bool AddSquareTo(IntegerValue a, IntegerValue *result)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
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)
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)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
IntegerValue CapAddI(IntegerValue a, IntegerValue b)
H AbslHashValue(H h, const IntVar &i)
std::pair< LinearExpression2, IntegerValue > EncodeDifferenceLowerThan(AffineExpression a, AffineExpression b, IntegerValue ub)
IntegerValue FloorRatioWithTest(IntegerValue dividend, IntegerValue positive_divisor)
constexpr Fractional kInfinity
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
bool VariableIsPositive(IntegerVariable i)
IntegerValue CapSubI(IntegerValue a, IntegerValue b)
bool AtMinOrMaxInt64I(IntegerValue t)
IntegerValue CapProdI(IntegerValue a, IntegerValue b)
double ToDouble(IntegerValue value)
bool AtMinOrMaxInt64(int64_t x)
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
bool operator==(AffineExpression o) const
AffineExpression MultipliedBy(IntegerValue multiplier) const
AffineExpression Negated() const
AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
AffineExpression()=default
IntegerValue ValueAt(IntegerValue var_value) const
AffineExpression(IntegerVariable v, IntegerValue c)
double LpValue(const util_intops::StrongVector< IntegerVariable, double > &lp_values) const
AffineExpression(IntegerValue cst)
friend void AbslStringify(Sink &sink, const AffineExpression &expr)
AffineExpression(IntegerVariable v)
IntegerLiteral LowerOrEqual(IntegerValue bound) const
IntegerValue inner_objective_value
std::vector< int64_t > proto_values
util_intops::StrongVector< IntegerVariable, bool > ivar_has_value
util_intops::StrongVector< IntegerVariable, IntegerValue > ivar_values
bool operator==(IntegerLiteral o) const
bool IsAlwaysFalse() const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral TrueLiteral()
IntegerLiteral Negated() const
std::string DebugString() const
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
bool IsAlwaysTrue() const
static IntegerLiteral FalseLiteral()
IntegerLiteral(IntegerVariable v, IntegerValue b)
bool operator!=(IntegerLiteral o) const
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
bool NegateForCanonicalization()
absl::Span< const IntegerVariable > non_zero_vars() const
friend void AbslStringify(Sink &sink, const LinearExpression2 &expr)
void MakeVariablesPositive()
LinearExpression2()=default
static LinearExpression2 Difference(IntegerVariable v1, IntegerVariable v2)
IntegerValue DivideByGcd()
AffineExpression GetAffineLowerBound(int var_index, IntegerValue expr_lb, IntegerValue other_var_lb) const
bool IsCanonicalized() const
bool CanonicalizeAndUpdateBounds(IntegerValue &lb, IntegerValue &ub)
void SimpleCanonicalization()
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
std::string DebugString() const
bool operator==(const ValueLiteralPair &o) const