14#ifndef OR_TOOLS_SAT_INTEGER_EXPR_H_
15#define OR_TOOLS_SAT_INTEGER_EXPR_H_
25#include "absl/types/span.h"
63 IntegerSumLE(
const std::vector<Literal>& enforcement_literals,
64 const std::vector<IntegerVariable>& vars,
65 const std::vector<IntegerValue>& coeffs,
92 void FillIntegerReason();
94 const std::vector<Literal> enforcement_literals_;
95 const IntegerValue upper_bound_;
103 bool is_registered_ =
false;
104 IntegerValue rev_lb_fixed_vars_;
107 int rev_num_fixed_vars_;
112 std::vector<IntegerVariable> vars_;
113 std::vector<IntegerValue> coeffs_;
114 std::vector<IntegerValue> max_variations_;
116 std::vector<Literal> literal_reason_;
119 std::vector<IntegerLiteral> integer_reason_;
120 std::vector<IntegerValue> reason_coeffs_;
136 const std::vector<IntegerVariable>& vars,
137 const std::vector<IntegerValue>& coeffs,
Model*
model);
142 const IntegerVariable target_;
143 const std::vector<IntegerVariable> vars_;
144 const std::vector<IntegerValue> coeffs_;
146 IntegerValue gcd_ = IntegerValue(1);
185 const std::vector<IntegerVariable> vars_;
186 const IntegerVariable min_var_;
189 std::vector<IntegerLiteral> integer_reason_;
211 bool PropagateLinearUpperBound(const
std::vector<IntegerVariable>& vars,
212 const
std::vector<IntegerValue>& coeffs,
216 const IntegerVariable min_var_;
217 std::vector<IntegerValue> expr_lbs_;
221 int rev_unique_candidate_ = 0;
238 bool CanonicalizeCases();
242 bool PropagateWhenAllNonNegative();
246 IntegerValue min_p, IntegerValue max_p);
274 bool PropagateSigns();
309 const IntegerValue b_;
328 bool PropagateSignsAndTargetRange();
331 bool PropagateOuterBounds();
334 const IntegerValue mod_;
366template <
typename VectorInt>
368 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
372 if (vars.size() == 1) {
412 const int num_vars = vars.size();
413 if (num_vars > 100) {
414 std::vector<IntegerVariable> bucket_sum_vars;
416 std::vector<IntegerVariable> local_vars;
417 std::vector<IntegerValue> local_coeffs;
420 const int num_buckets =
static_cast<int>(std::round(std::sqrt(num_vars)));
421 for (
int b = 0;
b < num_buckets; ++
b) {
423 local_coeffs.clear();
424 int64_t bucket_lb = 0;
425 int64_t bucket_ub = 0;
426 const int limit = num_vars * (
b + 1);
427 for (; i * num_buckets < limit; ++i) {
428 local_vars.push_back(vars[i]);
430 const int64_t term1 =
432 const int64_t term2 =
434 bucket_lb +=
std::min(term1, term2);
435 bucket_ub +=
std::max(term1, term2);
438 const IntegerVariable bucket_sum =
440 bucket_sum_vars.push_back(bucket_sum);
441 local_vars.push_back(bucket_sum);
442 local_coeffs.push_back(IntegerValue(-1));
444 {}, local_vars, local_coeffs, IntegerValue(0),
model);
446 model->TakeOwnership(constraint);
451 local_coeffs.clear();
452 for (
const IntegerVariable
var : bucket_sum_vars) {
453 local_vars.push_back(
var);
454 local_coeffs.push_back(IntegerValue(1));
459 model->TakeOwnership(constraint);
468 model->TakeOwnership(constraint);
473template <
typename VectorInt>
475 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
479 for (int64_t& ref : negated_coeffs) ref = -ref;
484template <
typename VectorInt>
486 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
495template <
typename VectorInt>
497 const std::vector<Literal>& enforcement_literals,
498 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
502 if (vars.size() == 1) {
506 enforcement_literals,
512 enforcement_literals,
524 enforcement_literals);
533 enforcement_literals);
538 IntegerValue expression_min(0);
540 for (
int i = 0; i < vars.size(); ++i) {
543 ? integer_trail->LowerBound(vars[i])
544 : integer_trail->UpperBound(vars[i]));
550 IntegerValue non_cached_min;
551 for (
int i = 0; i < vars.size(); ++i) {
553 const IntegerValue lb = integer_trail->LowerBound(vars[i]);
558 const IntegerValue ub = integer_trail->UpperBound(vars[i]);
564 if (non_cached_min > expression_min) {
565 std::vector<Literal> clause;
566 for (
const Literal l : enforcement_literals) {
567 clause.push_back(l.Negated());
573 enforcement_literals, vars,
577 model->TakeOwnership(constraint);
583template <
typename VectorInt>
585 const std::vector<Literal>& enforcement_literals,
586 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
590 for (int64_t& ref : negated_coeffs) ref = -ref;
596template <
typename VectorInt>
598 Literal is_le,
const std::vector<IntegerVariable>& vars,
609template <
typename VectorInt>
611 Literal is_ge,
const std::vector<IntegerVariable>& vars,
623 if (cst.
vars.empty()) {
624 if (cst.
lb <= 0 && cst.
ub >= 0)
return;
630 std::vector<int64_t> converted_coeffs;
632 for (
const IntegerValue v : cst.
coeffs) converted_coeffs.push_back(v.value());
644 const absl::Span<const Literal> enforcement_literals,
646 if (enforcement_literals.empty()) {
649 if (cst.
vars.empty()) {
650 if (cst.
lb <= 0 && cst.
ub >= 0)
return;
655 std::vector<Literal> converted_literals(enforcement_literals.begin(),
656 enforcement_literals.end());
657 std::vector<int64_t> converted_coeffs;
658 for (
const IntegerValue v : cst.
coeffs) converted_coeffs.push_back(v.value());
662 converted_literals, cst.
vars, converted_coeffs, cst.
ub.value()));
666 converted_literals, cst.
vars, converted_coeffs, cst.
lb.value()));
672template <
typename VectorInt>
674 Literal is_eq,
const std::vector<IntegerVariable>& vars,
689template <
typename VectorInt>
691 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
711template <
typename VectorInt>
713 const VectorInt&
coefficients,
const std::vector<IntegerVariable>& vars) {
715 std::vector<IntegerVariable> new_vars = vars;
722 for (
int i = 0; i < new_vars.size(); ++i) {
733 new_vars.push_back(sum);
735 new_coeffs.push_back(-1);
744 IntegerVariable min_var,
const std::vector<IntegerVariable>& vars) {
746 for (
const IntegerVariable&
var : vars) {
753 model->TakeOwnership(constraint);
762 const std::vector<LinearExpression>& exprs) {
766 IntegerVariable min_var;
767 if (min_expr.
vars.size() == 1 &&
768 std::abs(min_expr.
coeffs[0].value()) == 1 && min_expr.
offset == 0) {
769 if (min_expr.
coeffs[0].value() == 1) {
770 min_var = min_expr.
vars[0];
781 std::vector<IntegerVariable> min_sum_vars = min_expr.
vars;
782 std::vector<int64_t> min_sum_coeffs;
784 min_sum_coeffs.push_back(
coeff.value());
786 min_sum_vars.push_back(min_var);
787 min_sum_coeffs.push_back(-1);
790 -min_expr.
offset.value()));
794 std::vector<IntegerVariable> vars = expr.vars;
795 std::vector<int64_t> coeffs;
796 for (IntegerValue
coeff : expr.coeffs) {
797 coeffs.push_back(
coeff.value());
799 vars.push_back(min_var);
800 coeffs.push_back(-1);
806 model->TakeOwnership(constraint);
813 IntegerVariable max_var,
const std::vector<IntegerVariable>& vars) {
815 std::vector<IntegerVariable> negated_vars;
816 for (
const IntegerVariable&
var : vars) {
824 model->TakeOwnership(constraint);
830std::function<void(Model*)>
IsOneOf(IntegerVariable
var,
831 const std::vector<Literal>& selectors,
832 const std::vector<IntegerValue>& values);
877 model->TakeOwnership(constraint);
891 model->TakeOwnership(constraint);
904 model->TakeOwnership(constraint);
#define CHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
void RegisterWith(GenericLiteralWatcher *watcher)
bool PropagateAtLevelZero()
std::pair< IntegerValue, IntegerValue > ConditionalLb(IntegerLiteral integer_literal, IntegerVariable target_var) const
IntegerSumLE(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const std::vector< IntegerValue > &coeffs, IntegerValue upper_bound, Model *model)
IntegerValue UpperBound(IntegerVariable i) const
IntegerVariable AddIntegerVariable(IntegerValue lower_bound, IntegerValue upper_bound)
IntegerValue LowerBound(IntegerVariable i) const
LevelZeroEquality(IntegerVariable target, const std::vector< IntegerVariable > &vars, const std::vector< IntegerValue > &coeffs, Model *model)
LinMinPropagator & operator=(const LinMinPropagator &)=delete
LinMinPropagator(const std::vector< LinearExpression > &exprs, IntegerVariable min_var, Model *model)
LinMinPropagator(const LinMinPropagator &)=delete
void RegisterWith(GenericLiteralWatcher *watcher)
void RegisterWith(GenericLiteralWatcher *watcher)
MinPropagator(const std::vector< IntegerVariable > &vars, IntegerVariable min_var, IntegerTrail *integer_trail)
Class that owns everything related to a particular optimization model.
absl::Span< const double > coefficients
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
std::function< void(Model *)> WeightedSumGreaterOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
IntegerValue LinExprLowerBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
std::function< void(Model *)> WeightedSumLowerOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
std::function< void(Model *)> ProductConstraint(AffineExpression a, AffineExpression b, AffineExpression p)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
std::function< BooleanVariable(Model *)> NewBooleanVariable()
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::function< void(Model *)> FixedDivisionConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
void LoadConditionalLinearConstraint(const absl::Span< const Literal > enforcement_literals, const LinearConstraint &cst, Model *model)
std::function< void(Model *)> ConditionalWeightedSumGreaterOrEqual(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
std::function< void(Model *)> WeightedSumGreaterOrEqualReif(Literal is_ge, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
std::function< void(Model *)> Sum2LowerOrEqual(IntegerVariable a, IntegerVariable b, int64_t ub)
std::function< void(Model *)> ConditionalWeightedSumLowerOrEqual(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
std::function< void(Model *)> WeightedSumNotEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
std::function< void(Model *)> IsEqualToMaxOf(IntegerVariable max_var, const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> DivisionConstraint(AffineExpression num, AffineExpression denom, AffineExpression div)
std::function< void(Model *)> Implication(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
std::function< void(Model *)> WeightedSumLowerOrEqualReif(Literal is_le, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
void RegisterAndTransferOwnership(Model *model, T *ct)
void LoadLinearConstraint(const ConstraintProto &ct, Model *m)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::function< void(Model *)> ReifiedBoolAnd(const std::vector< Literal > &literals, Literal r)
std::function< void(Model *)> FixedWeightedSumReif(Literal is_eq, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> IsEqualToMinOf(IntegerVariable min_var, const std::vector< IntegerVariable > &vars)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
std::function< void(Model *)> ConditionalSum2LowerOrEqual(IntegerVariable a, IntegerVariable b, int64_t ub, const std::vector< Literal > &enforcement_literals)
std::function< void(Model *)> Sum3LowerOrEqual(IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub)
IntegerValue LinExprUpperBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
std::function< IntegerVariable(Model *)> NewWeightedSum(const VectorInt &coefficients, const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> FixedModuloConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
std::function< void(Model *)> ConditionalSum3LowerOrEqual(IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub, const std::vector< Literal > &enforcement_literals)
std::function< void(Model *)> FixedWeightedSum(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
Collection of objects used to extend the Constraint Solver library.
AffineExpression Negated() const
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
std::vector< IntegerValue > coeffs
std::vector< IntegerVariable > vars
std::vector< IntegerValue > coeffs
std::vector< IntegerVariable > vars