14 #ifndef OR_TOOLS_SAT_INTEGER_EXPR_H_ 15 #define OR_TOOLS_SAT_INTEGER_EXPR_H_ 57 IntegerSumLE(
const std::vector<Literal>& enforcement_literals,
58 const std::vector<IntegerVariable>& vars,
59 const std::vector<IntegerValue>& coeffs,
86 void FillIntegerReason();
88 const std::vector<Literal> enforcement_literals_;
89 const IntegerValue upper_bound_;
97 bool is_registered_ =
false;
98 IntegerValue rev_lb_fixed_vars_;
101 int rev_num_fixed_vars_;
106 std::vector<IntegerVariable> vars_;
107 std::vector<IntegerValue> coeffs_;
108 std::vector<IntegerValue> max_variations_;
110 std::vector<Literal> literal_reason_;
113 std::vector<IntegerLiteral> integer_reason_;
114 std::vector<IntegerValue> reason_coeffs_;
130 const std::vector<IntegerVariable>& vars,
131 const std::vector<IntegerValue>& coeffs,
Model*
model);
136 const IntegerVariable target_;
137 const std::vector<IntegerVariable> vars_;
138 const std::vector<IntegerValue> coeffs_;
140 IntegerValue gcd_ = IntegerValue(1);
179 const std::vector<IntegerVariable> vars_;
180 const IntegerVariable min_var_;
183 std::vector<IntegerLiteral> integer_reason_;
205 bool PropagateLinearUpperBound(
const std::vector<IntegerVariable>& vars,
206 const std::vector<IntegerValue>& coeffs,
209 const std::vector<LinearExpression> exprs_;
210 const IntegerVariable min_var_;
211 std::vector<IntegerValue> expr_lbs_;
214 std::vector<IntegerLiteral> integer_reason_for_unique_candidate_;
215 int rev_unique_candidate_ = 0;
232 bool CanonicalizeCases();
236 bool PropagateWhenAllNonNegative();
240 IntegerValue min_p, IntegerValue max_p);
268 bool PropagateSigns();
303 const IntegerValue b_;
322 bool PropagateSignsAndTargetRange();
325 bool PropagateOuterBounds();
328 const IntegerValue mod_;
360 template <
typename VectorInt>
362 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
366 if (vars.size() == 1) {
406 const int num_vars = vars.size();
407 if (num_vars > 100) {
408 std::vector<IntegerVariable> bucket_sum_vars;
410 std::vector<IntegerVariable> local_vars;
411 std::vector<IntegerValue> local_coeffs;
414 const int num_buckets = static_cast<int>(std::round(std::sqrt(num_vars)));
415 for (
int b = 0;
b < num_buckets; ++
b) {
417 local_coeffs.clear();
418 int64_t bucket_lb = 0;
419 int64_t bucket_ub = 0;
420 const int limit = num_vars * (
b + 1);
421 for (; i * num_buckets < limit; ++i) {
422 local_vars.push_back(vars[i]);
424 const int64_t term1 =
426 const int64_t term2 =
428 bucket_lb +=
std::min(term1, term2);
429 bucket_ub +=
std::max(term1, term2);
432 const IntegerVariable bucket_sum =
434 bucket_sum_vars.push_back(bucket_sum);
435 local_vars.push_back(bucket_sum);
436 local_coeffs.push_back(IntegerValue(-1));
438 {}, local_vars, local_coeffs, IntegerValue(0),
model);
440 model->TakeOwnership(constraint);
445 local_coeffs.clear();
446 for (
const IntegerVariable
var : bucket_sum_vars) {
447 local_vars.push_back(
var);
448 local_coeffs.push_back(IntegerValue(1));
453 model->TakeOwnership(constraint);
462 model->TakeOwnership(constraint);
467 template <
typename VectorInt>
469 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
473 for (int64_t& ref : negated_coeffs) ref = -ref;
478 template <
typename VectorInt>
480 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
489 template <
typename VectorInt>
491 const std::vector<Literal>& enforcement_literals,
492 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
496 if (vars.size() == 1) {
500 enforcement_literals,
506 enforcement_literals,
518 enforcement_literals);
527 enforcement_literals);
532 IntegerValue expression_min(0);
534 for (
int i = 0; i < vars.size(); ++i) {
537 ? integer_trail->LowerBound(vars[i])
538 : integer_trail->UpperBound(vars[i]));
544 IntegerValue non_cached_min;
545 for (
int i = 0; i < vars.size(); ++i) {
547 const IntegerValue lb = integer_trail->LowerBound(vars[i]);
552 const IntegerValue ub = integer_trail->UpperBound(vars[i]);
558 if (non_cached_min > expression_min) {
559 std::vector<Literal> clause;
560 for (
const Literal l : enforcement_literals) {
561 clause.push_back(l.Negated());
567 enforcement_literals, vars,
571 model->TakeOwnership(constraint);
577 template <
typename VectorInt>
579 const std::vector<Literal>& enforcement_literals,
580 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
584 for (int64_t& ref : negated_coeffs) ref = -ref;
590 template <
typename VectorInt>
592 Literal is_le,
const std::vector<IntegerVariable>& vars,
603 template <
typename VectorInt>
605 Literal is_ge,
const std::vector<IntegerVariable>& vars,
617 if (cst.
vars.empty()) {
618 if (cst.
lb <= 0 && cst.
ub >= 0)
return;
624 std::vector<int64_t> converted_coeffs;
626 for (
const IntegerValue v : cst.
coeffs) converted_coeffs.push_back(v.value());
638 const absl::Span<const Literal> enforcement_literals,
640 if (enforcement_literals.empty()) {
643 if (cst.
vars.empty()) {
644 if (cst.
lb <= 0 && cst.
ub >= 0)
return;
649 std::vector<Literal> converted_literals(enforcement_literals.begin(),
650 enforcement_literals.end());
651 std::vector<int64_t> converted_coeffs;
652 for (
const IntegerValue v : cst.
coeffs) converted_coeffs.push_back(v.value());
656 converted_literals, cst.
vars, converted_coeffs, cst.
ub.value()));
660 converted_literals, cst.
vars, converted_coeffs, cst.
lb.value()));
666 template <
typename VectorInt>
668 Literal is_eq,
const std::vector<IntegerVariable>& vars,
683 template <
typename VectorInt>
685 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
705 template <
typename VectorInt>
707 const VectorInt&
coefficients,
const std::vector<IntegerVariable>& vars) {
709 std::vector<IntegerVariable> new_vars = vars;
716 for (
int i = 0; i < new_vars.size(); ++i) {
727 new_vars.push_back(sum);
729 new_coeffs.push_back(-1);
738 IntegerVariable min_var,
const std::vector<IntegerVariable>& vars) {
740 for (
const IntegerVariable&
var : vars) {
747 model->TakeOwnership(constraint);
756 const std::vector<LinearExpression>& exprs) {
760 IntegerVariable min_var;
761 if (min_expr.
vars.size() == 1 &&
762 std::abs(min_expr.
coeffs[0].value()) == 1 && min_expr.
offset == 0) {
763 if (min_expr.
coeffs[0].value() == 1) {
764 min_var = min_expr.
vars[0];
775 std::vector<IntegerVariable> min_sum_vars = min_expr.
vars;
776 std::vector<int64_t> min_sum_coeffs;
777 for (IntegerValue coeff : min_expr.
coeffs) {
778 min_sum_coeffs.push_back(coeff.value());
780 min_sum_vars.push_back(min_var);
781 min_sum_coeffs.push_back(-1);
784 -min_expr.
offset.value()));
788 std::vector<IntegerVariable> vars = expr.vars;
789 std::vector<int64_t> coeffs;
790 for (IntegerValue coeff : expr.coeffs) {
791 coeffs.push_back(coeff.value());
793 vars.push_back(min_var);
794 coeffs.push_back(-1);
800 model->TakeOwnership(constraint);
807 IntegerVariable max_var,
const std::vector<IntegerVariable>& vars) {
809 std::vector<IntegerVariable> negated_vars;
810 for (
const IntegerVariable&
var : vars) {
818 model->TakeOwnership(constraint);
825 const std::vector<Literal>& selectors,
826 const std::vector<IntegerValue>& values);
871 model->TakeOwnership(constraint);
885 model->TakeOwnership(constraint);
898 model->TakeOwnership(constraint);
905 #endif // OR_TOOLS_SAT_INTEGER_EXPR_H_ std::function< IntegerVariable(Model *)> NewWeightedSum(const VectorInt &coefficients, const std::vector< IntegerVariable > &vars)
DivisionPropagator(AffineExpression num, AffineExpression denom, AffineExpression div, IntegerTrail *integer_trail)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
std::function< BooleanVariable(Model *)> NewBooleanVariable()
AffineExpression Negated() const
IntegerVariable AddIntegerVariable(IntegerValue lower_bound, IntegerValue upper_bound)
std::function< void(Model *)> Sum3LowerOrEqual(IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub)
void RegisterWith(GenericLiteralWatcher *watcher)
std::function< void(Model *)> WeightedSumLowerOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
FixedDivisionPropagator(AffineExpression a, IntegerValue b, AffineExpression c, IntegerTrail *integer_trail)
#define CHECK_GE(val1, val2)
IntegerValue LinExprLowerBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
Class that owns everything related to a particular optimization model.
LinMinPropagator(const std::vector< LinearExpression > &exprs, IntegerVariable min_var, Model *model)
std::function< void(Model *)> WeightedSumLowerOrEqualReif(Literal is_le, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
std::vector< IntegerValue > coeffs
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
void RegisterWith(GenericLiteralWatcher *watcher)
ProductPropagator(AffineExpression a, AffineExpression b, AffineExpression p, IntegerTrail *integer_trail)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
std::function< void(Model *)> ReifiedBoolAnd(const std::vector< Literal > &literals, Literal r)
std::pair< IntegerValue, IntegerValue > ConditionalLb(IntegerLiteral integer_literal, IntegerVariable target_var) const
IntegerValue LowerBound(IntegerVariable i) const
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 *)> ProductConstraint(AffineExpression a, AffineExpression b, AffineExpression p)
std::function< void(Model *)> DivisionConstraint(AffineExpression num, AffineExpression denom, AffineExpression div)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::vector< IntegerValue > coeffs
std::vector< IntegerVariable > vars
std::vector< IntegerVariable > vars
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
LevelZeroEquality(IntegerVariable target, const std::vector< IntegerVariable > &vars, const std::vector< IntegerValue > &coeffs, Model *model)
void RegisterWith(GenericLiteralWatcher *watcher)
std::function< void(Model *)> IsEqualToMaxOf(IntegerVariable max_var, const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
std::function< void(Model *)> IsEqualToMinOf(IntegerVariable min_var, const std::vector< IntegerVariable > &vars)
SquarePropagator(AffineExpression x, AffineExpression s, IntegerTrail *integer_trail)
bool PropagateAtLevelZero()
void RegisterWith(GenericLiteralWatcher *watcher)
std::function< void(Model *)> ConditionalSum2LowerOrEqual(IntegerVariable a, IntegerVariable b, int64_t ub, const std::vector< Literal > &enforcement_literals)
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
std::function< void(Model *)> ConditionalSum3LowerOrEqual(IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub, const std::vector< Literal > &enforcement_literals)
std::function< void(Model *)> WeightedSumNotEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
FixedModuloPropagator(AffineExpression expr, IntegerValue mod, AffineExpression target, IntegerTrail *integer_trail)
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 *)> FixedModuloConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
IntegerValue LinExprUpperBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> WeightedSumGreaterOrEqualReif(Literal is_ge, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
std::function< void(Model *)> Implication(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
void RegisterWith(GenericLiteralWatcher *watcher)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
IntegerValue UpperBound(IntegerVariable i) const
MinPropagator(const std::vector< IntegerVariable > &vars, IntegerVariable min_var, IntegerTrail *integer_trail)
void RegisterWith(GenericLiteralWatcher *watcher)
IntegerSumLE(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const std::vector< IntegerValue > &coeffs, IntegerValue upper_bound, Model *model)
Collection of objects used to extend the Constraint Solver library.
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
void RegisterWith(GenericLiteralWatcher *watcher)
absl::Span< const double > coefficients
std::function< void(Model *)> FixedDivisionConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
std::function< void(Model *)> WeightedSumGreaterOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
std::function< void(Model *)> FixedWeightedSumReif(Literal is_eq, const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
void RegisterWith(GenericLiteralWatcher *watcher)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
void RegisterAndTransferOwnership(Model *model, T *ct)
std::function< void(Model *)> FixedWeightedSum(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
void LoadLinearConstraint(const ConstraintProto &ct, Model *m)
void LoadConditionalLinearConstraint(const absl::Span< const Literal > enforcement_literals, const LinearConstraint &cst, Model *model)
#define CHECK_NE(val1, val2)
LinMinPropagator & operator=(const LinMinPropagator &)=delete