14#ifndef OR_TOOLS_SAT_INTEGER_EXPR_H_
15#define OR_TOOLS_SAT_INTEGER_EXPR_H_
26#include "absl/log/check.h"
27#include "absl/types/span.h"
34#include "ortools/sat/sat_parameters.pb.h"
66template <
bool use_
int128 = false>
75 absl::Span<const IntegerVariable> vars,
76 absl::Span<const IntegerValue> coeffs,
101 IntegerLiteral integer_literal, IntegerVariable target_var)
const;
104 void Explain(
int id, IntegerValue propagation_slack,
105 IntegerVariable var_to_explain,
int trail_index,
106 std::vector<Literal>* literals_reason,
107 std::vector<int>* trail_indices_reason)
final;
114 void FillIntegerReason();
116 const IntegerValue upper_bound_;
128 rev_integer_value_repository(
138 std::vector<IntegerLiteral> integer_reason;
139 std::vector<IntegerValue> reason_coeffs;
144 bool is_registered_ =
false;
145 IntegerValue rev_lb_fixed_vars_;
148 int rev_num_fixed_vars_;
154 const std::unique_ptr<IntegerVariable[]> vars_;
155 const std::unique_ptr<IntegerValue[]> coeffs_;
156 const std::unique_ptr<IntegerValue[]> max_variations_;
159 std::vector<Literal> literal_reason_;
180 const std::vector<IntegerVariable>& vars,
181 const std::vector<IntegerValue>& coeffs,
Model*
model);
183 bool Propagate()
final;
186 const IntegerVariable target_;
187 const std::vector<IntegerVariable>
vars_;
188 const std::vector<IntegerValue> coeffs_;
190 IntegerValue gcd_ = IntegerValue(1);
229 bool Propagate() final;
233 const
std::vector<IntegerVariable>
vars_;
234 const IntegerVariable min_var_;
250 bool Propagate() final;
254 void Explain(
int id, IntegerValue propagation_slack,
255 IntegerVariable var_to_explain,
int trail_index,
257 std::vector<
int>* trail_indices_reason) final;
263 bool PropagateLinearUpperBound(
int id,
absl::Span<const IntegerVariable> vars,
264 absl::Span<const IntegerValue> coeffs,
268 const IntegerVariable min_var_;
269 std::vector<IntegerValue> expr_lbs_;
272 std::vector<IntegerValue> max_variations_;
273 std::vector<IntegerValue> reason_coeffs_;
276 int rev_unique_candidate_ = 0;
292 bool Propagate() final;
297 bool CanonicalizeCases();
301 bool PropagateWhenAllNonNegative();
305 IntegerValue min_p, IntegerValue max_p);
329 bool Propagate() final;
369 bool Propagate() final;
374 const IntegerValue b_;
391 bool Propagate() final;
395 bool PropagateSignsAndTargetRange();
398 bool PropagateOuterBounds();
401 const IntegerValue mod_;
419 bool Propagate() final;
433template <typename VectorInt>
435 const
std::vector<IntegerVariable>& vars, const VectorInt&
coefficients,
444template <
typename VectorInt>
446 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
450 for (int64_t& ref : negated_coeffs) ref = -ref;
455template <
typename VectorInt>
457 const std::vector<IntegerVariable>& vars,
const VectorInt&
coefficients,
467 absl::Span<const Literal> enforcement_literals,
468 absl::Span<const IntegerVariable> vars,
471 DCHECK_GE(vars.size(), 1);
472 if (vars.size() == 1) {
474 IntegerVariable
var = vars[0];
481 if (enforcement_literals.empty()) {
491 const SatParameters& params = *
model->GetOrCreate<SatParameters>();
492 if (!params.new_linear_propagation()) {
496 enforcement_literals,
506 enforcement_literals,
519 if (!enforcement_literals.empty()) {
520 IntegerValue expression_min(0);
522 for (
int i = 0;
i < vars.size(); ++
i) {
532 IntegerValue non_cached_min;
533 for (
int i = 0;
i < vars.size(); ++
i) {
546 if (non_cached_min > expression_min) {
547 std::vector<Literal> clause;
548 for (
const Literal l : enforcement_literals) {
549 clause.push_back(l.Negated());
557 if (params.new_linear_propagation()) {
559 enforcement_literals, vars,
564 if (sat_solver->CurrentDecisionLevel() == 0) {
565 sat_solver->NotifyThatModelIsUnsat();
567 LOG(FATAL) <<
"We currently do not support adding conflicting "
568 "constraint at positive level.";
573 enforcement_literals, vars,
577 model->TakeOwnership(constraint);
583 absl::Span<const Literal> enforcement_literals,
584 absl::Span<const IntegerVariable> vars,
588 for (int64_t& ref : negated_coeffs) ref = -ref;
595 const std::vector<Literal>& enforcement_literals,
596 const std::vector<IntegerVariable>& vars,
604 const std::vector<Literal>& enforcement_literals,
605 const std::vector<IntegerVariable>& vars,
615 const absl::Span<const Literal> enforcement_literals,
618 if (cst.
lb <= 0 && cst.
ub >= 0)
return;
621 std::vector<Literal> clause;
622 for (
const Literal lit : enforcement_literals) {
623 clause.push_back(
lit.Negated());
629 std::vector<IntegerVariable> vars(cst.
num_terms);
630 std::vector<int64_t> coeffs(cst.
num_terms);
651 const absl::Span<const Literal> enforcement_literals, AffineExpression left,
666template <
typename VectorInt>
668 const VectorInt&
coefficients,
const std::vector<IntegerVariable>& vars) {
670 std::vector<IntegerVariable> new_vars = vars;
677 for (
int i = 0;
i < new_vars.size(); ++
i) {
688 new_vars.push_back(sum);
690 new_coeffs.push_back(-1);
699 IntegerVariable min_var,
const std::vector<IntegerVariable>& vars) {
701 for (
const IntegerVariable&
var : vars) {
708 model->TakeOwnership(constraint);
716 const LinearExpression& min_expr,
717 const std::vector<LinearExpression>& exprs) {
721 IntegerVariable min_var;
722 if (min_expr.vars.size() == 1 &&
723 std::abs(min_expr.coeffs[0].value()) == 1 && min_expr.offset == 0) {
724 if (min_expr.coeffs[0].value() == 1) {
725 min_var = min_expr.vars[0];
731 IntegerValue min_lb = min_expr.Min(*integer_trail);
732 IntegerValue min_ub = min_expr.Max(*integer_trail);
750 model->TakeOwnership(constraint);
757 IntegerVariable max_var,
const std::vector<IntegerVariable>& vars) {
759 std::vector<IntegerVariable> negated_vars;
760 for (
const IntegerVariable&
var : vars) {
768 model->TakeOwnership(constraint);
774std::function<void(Model*)>
IsOneOf(IntegerVariable
var,
775 const std::vector<Literal>& selectors,
776 const std::vector<IntegerValue>& values);
780 ct->RegisterWith(
model->GetOrCreate<GenericLiteralWatcher>());
808 AffineExpression denom,
821 model->TakeOwnership(constraint);
835 model->TakeOwnership(constraint);
848 model->TakeOwnership(constraint);
const std::vector< IntVar * > vars_
void RegisterWith(GenericLiteralWatcher *watcher)
DivisionPropagator(const DivisionPropagator &)=delete
This type is neither copyable nor movable.
DivisionPropagator & operator=(const DivisionPropagator &)=delete
FixedDivisionPropagator(const FixedDivisionPropagator &)=delete
This type is neither copyable nor movable.
FixedDivisionPropagator & operator=(const FixedDivisionPropagator &)=delete
FixedModuloPropagator & operator=(const FixedModuloPropagator &)=delete
FixedModuloPropagator(const FixedModuloPropagator &)=delete
This type is neither copyable nor movable.
IntegerValue LowerBound(IntegerVariable i) const
Returns the current lower/upper bound of the given integer variable.
IntegerValue UpperBound(IntegerVariable i) const
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
Returns globally valid lower/upper bound on the given integer variable.
IntegerVariable AddIntegerVariable(IntegerValue lower_bound, IntegerValue upper_bound)
LinMinPropagator & operator=(const LinMinPropagator &)=delete
void RegisterWith(GenericLiteralWatcher *watcher)
LinMinPropagator(const LinMinPropagator &)=delete
void AddTerm(IntegerVariable var, IntegerValue coeff)
void AddLinearExpression(const LinearExpression &expr)
std::pair< IntegerValue, IntegerValue > ConditionalLb(IntegerLiteral integer_literal, IntegerVariable target_var) const
NOTE(user): This is only used with int128, so we code only a single version.
void RegisterWith(GenericLiteralWatcher *watcher)
LinearConstraintPropagator(absl::Span< const Literal > enforcement_literals, absl::Span< const IntegerVariable > vars, absl::Span< const IntegerValue > coeffs, IntegerValue upper_bound, Model *model)
void Explain(int id, IntegerValue propagation_slack, IntegerVariable var_to_explain, int trail_index, std::vector< Literal > *literals_reason, std::vector< int > *trail_indices_reason) final
For LazyReasonInterface.
bool PropagateAtLevelZero()
MinPropagator(const MinPropagator &)=delete
This type is neither copyable nor movable.
void RegisterWith(GenericLiteralWatcher *watcher)
MinPropagator & operator=(const MinPropagator &)=delete
ProductPropagator(const ProductPropagator &)=delete
This type is neither copyable nor movable.
ProductPropagator & operator=(const ProductPropagator &)=delete
Base class for CP like propagators.
SquarePropagator(const SquarePropagator &)=delete
This type is neither copyable nor movable.
SquarePropagator & operator=(const SquarePropagator &)=delete
const VariablesAssignment & Assignment() const
absl::Span< const double > coefficients
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
std::function< void(Model *)> WeightedSumGreaterOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t lower_bound)
Weighted sum >= constant.
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< void(Model *)> WeightedSumLowerOrEqual(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t upper_bound)
Weighted sum <= constant.
std::function< void(Model *)> ProductConstraint(AffineExpression a, AffineExpression b, AffineExpression p)
Adds the constraint: a * b = p.
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Returns the vector of the negated variables.
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::function< void(Model *)> FixedDivisionConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
Adds the constraint: a / b = c where b is a constant.
void LoadConditionalLinearConstraint(const absl::Span< const Literal > enforcement_literals, const LinearConstraint &cst, Model *model)
LinearConstraint version.
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
std::function< void(Model *)> IsEqualToMaxOf(IntegerVariable max_var, const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> DivisionConstraint(AffineExpression num, AffineExpression denom, AffineExpression div)
Adds the constraint: num / denom = div. (denom > 0).
void AddConditionalAffinePrecedence(const absl::Span< const Literal > enforcement_literals, AffineExpression left, AffineExpression right, Model *model)
void RegisterAndTransferOwnership(Model *model, T *ct)
void AddWeightedSumLowerOrEqual(absl::Span< const Literal > enforcement_literals, absl::Span< const IntegerVariable > vars, absl::Span< const int64_t > coefficients, int64_t upper_bound, Model *model)
enforcement_literals => sum <= upper_bound
std::function< void(Model *)> ConditionalWeightedSumGreaterOrEqual(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const std::vector< int64_t > &coefficients, int64_t upper_bound)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::function< void(Model *)> ConditionalWeightedSumLowerOrEqual(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const std::vector< int64_t > &coefficients, int64_t upper_bound)
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)
void AddConditionalSum3LowerOrEqual(absl::Span< const Literal > enforcement_literals, IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub, Model *model)
std::function< IntegerVariable(Model *)> NewWeightedSum(const VectorInt &coefficients, const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> FixedModuloConstraint(AffineExpression a, IntegerValue b, AffineExpression c)
Adds the constraint: a % b = c where b is a constant.
void LoadLinearConstraint(const ConstraintProto &ct, Model *m)
void AddWeightedSumGreaterOrEqual(absl::Span< const Literal > enforcement_literals, absl::Span< const IntegerVariable > vars, absl::Span< const int64_t > coefficients, int64_t lower_bound, Model *model)
enforcement_literals => sum >= lower_bound
LinearConstraintPropagator< false > IntegerSumLE
void AddConditionalSum2LowerOrEqual(absl::Span< const Literal > enforcement_literals, IntegerVariable a, IntegerVariable b, int64_t ub, Model *model)
l => (a + b <= ub).
std::function< void(Model *)> FixedWeightedSum(const std::vector< IntegerVariable > &vars, const VectorInt &coefficients, int64_t value)
Weighted sum == constant.
In SWIG mode, we don't want anything besides these top-level includes.
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
std::unique_ptr< IntegerValue[]> coeffs
std::unique_ptr< IntegerVariable[]> vars