21#include "absl/container/flat_hash_map.h"
22#include "absl/memory/memory.h"
32 const std::vector<IntegerVariable>& vars,
33 const std::vector<IntegerValue>& coeffs,
35 : enforcement_literals_(enforcement_literals),
40 rev_integer_value_repository_(
45 CHECK(!vars_.empty());
46 max_variations_.resize(vars_.size());
49 for (
int i = 0; i < vars.size(); ++i) {
52 coeffs_[i] = -coeffs_[i];
58 literal_reason_.push_back(
literal.Negated());
62 rev_num_fixed_vars_ = 0;
63 rev_lb_fixed_vars_ = IntegerValue(0);
66void IntegerSumLE::FillIntegerReason() {
67 integer_reason_.clear();
68 reason_coeffs_.clear();
69 const int num_vars = vars_.size();
70 for (
int i = 0; i < num_vars; ++i) {
71 const IntegerVariable
var = vars_[i];
74 reason_coeffs_.push_back(coeffs_[i]);
82 int num_unassigned_enforcement_literal = 0;
87 ++num_unassigned_enforcement_literal;
88 unique_unnasigned_literal =
literal.Index();
94 if (num_unassigned_enforcement_literal > 1)
return true;
98 rev_integer_value_repository_->
SaveState(&rev_lb_fixed_vars_);
100 rev_num_fixed_vars_ = 0;
101 rev_lb_fixed_vars_ = 0;
105 IntegerValue lb_unfixed_vars = IntegerValue(0);
106 const int num_vars = vars_.size();
107 for (
int i = rev_num_fixed_vars_; i < num_vars; ++i) {
108 const IntegerVariable
var = vars_[i];
109 const IntegerValue coeff = coeffs_[i];
113 max_variations_[i] = (ub - lb) * coeff;
114 lb_unfixed_vars += lb * coeff;
117 std::swap(vars_[i], vars_[rev_num_fixed_vars_]);
118 std::swap(coeffs_[i], coeffs_[rev_num_fixed_vars_]);
119 std::swap(max_variations_[i], max_variations_[rev_num_fixed_vars_]);
120 rev_num_fixed_vars_++;
121 rev_lb_fixed_vars_ += lb * coeff;
125 static_cast<double>(num_vars - rev_num_fixed_vars_) * 1e-9);
128 const IntegerValue slack =
129 upper_bound_ - (rev_lb_fixed_vars_ + lb_unfixed_vars);
135 if (num_unassigned_enforcement_literal == 1) {
138 std::vector<Literal> tmp = literal_reason_;
139 tmp.erase(std::find(tmp.begin(), tmp.end(), to_propagate));
140 integer_trail_->
EnqueueLiteral(to_propagate, tmp, integer_reason_);
143 return integer_trail_->
ReportConflict(literal_reason_, integer_reason_);
147 if (num_unassigned_enforcement_literal > 0)
return true;
151 for (
int i = rev_num_fixed_vars_; i < num_vars; ++i) {
152 if (max_variations_[i] <= slack)
continue;
154 const IntegerVariable
var = vars_[i];
155 const IntegerValue coeff = coeffs_[i];
156 const IntegerValue div = slack / coeff;
157 const IntegerValue new_ub = integer_trail_->
LowerBound(
var) + div;
158 const IntegerValue propagation_slack = (div + 1) * coeff - slack - 1;
161 [
this, propagation_slack](
163 std::vector<Literal>* literal_reason,
164 std::vector<int>* trail_indices_reason) {
165 *literal_reason = literal_reason_;
166 trail_indices_reason->clear();
167 reason_coeffs_.clear();
168 const int size = vars_.size();
169 for (int i = 0; i < size; ++i) {
170 const IntegerVariable var = vars_[i];
171 if (PositiveVariable(var) == PositiveVariable(i_lit.var)) {
175 integer_trail_->FindTrailIndexOfVarBefore(var, trail_index);
177 trail_indices_reason->push_back(index);
178 if (propagation_slack > 0) {
179 reason_coeffs_.push_back(coeffs_[i]);
183 if (propagation_slack > 0) {
185 propagation_slack, reason_coeffs_, trail_indices_reason);
195bool IntegerSumLE::PropagateAtLevelZero() {
198 if (!enforcement_literals_.empty())
return true;
201 IntegerValue min_activity = IntegerValue(0);
202 const int num_vars =
vars_.size();
203 for (
int i = 0; i < num_vars; ++i) {
204 const IntegerVariable
var =
vars_[i];
205 const IntegerValue coeff = coeffs_[i];
206 const IntegerValue lb = integer_trail_->LevelZeroLowerBound(
var);
207 const IntegerValue ub = integer_trail_->LevelZeroUpperBound(
var);
208 max_variations_[i] = (ub - lb) * coeff;
209 min_activity += lb * coeff;
211 time_limit_->AdvanceDeterministicTime(
static_cast<double>(num_vars * 1e-9));
214 const IntegerValue slack = upper_bound_ - min_activity;
216 return integer_trail_->ReportConflict({}, {});
221 for (
int i = 0; i < num_vars; ++i) {
222 if (max_variations_[i] <= slack)
continue;
224 const IntegerVariable
var =
vars_[i];
225 const IntegerValue coeff = coeffs_[i];
226 const IntegerValue div = slack / coeff;
227 const IntegerValue new_ub = integer_trail_->LevelZeroLowerBound(
var) + div;
238 is_registered_ =
true;
239 const int id = watcher->
Register(
this);
240 for (
const IntegerVariable&
var :
vars_) {
253LevelZeroEquality::LevelZeroEquality(IntegerVariable target,
254 const std::vector<IntegerVariable>& vars,
255 const std::vector<IntegerValue>& coeffs,
263 const int id = watcher->
Register(
this);
264 watcher->SetPropagatorPriority(
id, 2);
265 watcher->WatchIntegerVariable(target,
id);
266 for (
const IntegerVariable&
var : vars_) {
267 watcher->WatchIntegerVariable(
var,
id);
285 for (
int i = 0; i < vars_.size(); ++i) {
286 if (integer_trail_->
IsFixed(vars_[i])) {
287 sum += coeffs_[i] * integer_trail_->
LowerBound(vars_[i]);
293 if (gcd == 0)
return true;
296 VLOG(1) <<
"Objective gcd: " << gcd;
299 gcd_ = IntegerValue(gcd);
301 const IntegerValue lb = integer_trail_->
LowerBound(target_);
303 if (lb_remainder != 0) {
310 const IntegerValue ub = integer_trail_->
UpperBound(target_);
311 const IntegerValue ub_remainder =
313 if (ub_remainder != 0) {
323 IntegerVariable min_var,
325 :
vars_(vars), min_var_(min_var), integer_trail_(integer_trail) {}
328 if (vars_.empty())
return true;
334 const IntegerValue current_min_ub = integer_trail_->
UpperBound(min_var_);
335 int num_intervals_that_can_be_min = 0;
336 int last_possible_min_interval = 0;
339 for (
int i = 0; i < vars_.size(); ++i) {
340 const IntegerValue lb = integer_trail_->
LowerBound(vars_[i]);
342 if (lb <= current_min_ub) {
343 ++num_intervals_that_can_be_min;
344 last_possible_min_interval = i;
350 integer_reason_.clear();
351 for (
const IntegerVariable
var : vars_) {
355 {}, integer_reason_)) {
361 if (num_intervals_that_can_be_min == 1) {
362 const IntegerValue ub_of_only_candidate =
363 integer_trail_->
UpperBound(vars_[last_possible_min_interval]);
364 if (current_min_ub < ub_of_only_candidate) {
365 integer_reason_.clear();
369 integer_reason_.push_back(min_ub_literal);
370 for (
const IntegerVariable
var : vars_) {
371 if (
var ==
vars_[last_possible_min_interval])
continue;
372 integer_reason_.push_back(
378 {}, integer_reason_)) {
390 if (num_intervals_that_can_be_min == 0) {
391 integer_reason_.clear();
394 integer_reason_.push_back(min_ub_literal);
395 for (
const IntegerVariable
var : vars_) {
396 integer_reason_.push_back(
406 const int id = watcher->
Register(
this);
407 for (
const IntegerVariable&
var : vars_) {
420bool LinMinPropagator::PropagateLinearUpperBound(
421 const std::vector<IntegerVariable>& vars,
422 const std::vector<IntegerValue>& coeffs,
const IntegerValue
upper_bound) {
423 IntegerValue sum_lb = IntegerValue(0);
424 const int num_vars = vars.size();
425 std::vector<IntegerValue> max_variations;
426 for (
int i = 0; i < num_vars; ++i) {
427 const IntegerVariable
var = vars[i];
428 const IntegerValue coeff = coeffs[i];
433 max_variations.push_back((ub - lb) * coeff);
434 sum_lb += lb * coeff;
438 static_cast<double>(num_vars) * 1e-9);
442 std::vector<IntegerLiteral> linear_sum_reason;
443 std::vector<IntegerValue> reason_coeffs;
444 for (
int i = 0; i < num_vars; ++i) {
445 const IntegerVariable
var = vars[i];
448 reason_coeffs.push_back(coeffs[i]);
455 std::vector<IntegerLiteral> local_reason =
456 integer_reason_for_unique_candidate_;
457 local_reason.insert(local_reason.end(), linear_sum_reason.begin(),
458 linear_sum_reason.end());
464 for (
int i = 0; i < num_vars; ++i) {
465 if (max_variations[i] <= slack)
continue;
467 const IntegerVariable
var = vars[i];
468 const IntegerValue coeff = coeffs[i];
469 const IntegerValue div = slack / coeff;
470 const IntegerValue new_ub = integer_trail_->
LowerBound(
var) + div;
472 const IntegerValue propagation_slack = (div + 1) * coeff - slack - 1;
475 [
this, &vars, &coeffs, propagation_slack](
476 IntegerLiteral i_lit,
int trail_index,
477 std::vector<Literal>* literal_reason,
478 std::vector<int>* trail_indices_reason) {
479 literal_reason->clear();
480 trail_indices_reason->clear();
481 std::vector<IntegerValue> reason_coeffs;
482 const int size = vars.size();
483 for (
int i = 0; i < size; ++i) {
484 const IntegerVariable
var = vars[i];
491 trail_indices_reason->push_back(
index);
492 if (propagation_slack > 0) {
493 reason_coeffs.push_back(coeffs[i]);
497 if (propagation_slack > 0) {
499 propagation_slack, reason_coeffs, trail_indices_reason);
502 for (IntegerLiteral reason_lit :
503 integer_reason_for_unique_candidate_) {
505 reason_lit.var, trail_index);
507 trail_indices_reason->push_back(
index);
518 if (exprs_.empty())
return true;
522 const IntegerValue current_min_ub = integer_trail_->
UpperBound(min_var_);
523 int num_intervals_that_can_be_min = 0;
524 int last_possible_min_interval = 0;
528 for (
int i = 0; i < exprs_.size(); ++i) {
530 expr_lbs_.push_back(lb);
531 min_of_linear_expression_lb =
std::min(min_of_linear_expression_lb, lb);
532 if (lb <= current_min_ub) {
533 ++num_intervals_that_can_be_min;
534 last_possible_min_interval = i;
542 if (min_of_linear_expression_lb > current_min_ub) {
543 min_of_linear_expression_lb = current_min_ub + 1;
545 if (min_of_linear_expression_lb > integer_trail_->
LowerBound(min_var_)) {
546 std::vector<IntegerLiteral> local_reason;
547 for (
int i = 0; i < exprs_.size(); ++i) {
548 const IntegerValue slack = expr_lbs_[i] - min_of_linear_expression_lb;
550 exprs_[i].vars, &local_reason);
553 min_var_, min_of_linear_expression_lb),
563 if (num_intervals_that_can_be_min == 1) {
564 const IntegerValue ub_of_only_candidate =
566 if (current_min_ub < ub_of_only_candidate) {
569 if (rev_unique_candidate_ == 0) {
570 integer_reason_for_unique_candidate_.clear();
574 integer_reason_for_unique_candidate_.push_back(
576 for (
int i = 0; i < exprs_.size(); ++i) {
577 if (i == last_possible_min_interval)
continue;
578 const IntegerValue slack = expr_lbs_[i] - (current_min_ub + 1);
580 slack, exprs_[i].coeffs, exprs_[i].vars,
581 &integer_reason_for_unique_candidate_);
583 rev_unique_candidate_ = 1;
586 return PropagateLinearUpperBound(
587 exprs_[last_possible_min_interval].vars,
588 exprs_[last_possible_min_interval].coeffs,
589 current_min_ub - exprs_[last_possible_min_interval].offset);
597 const int id = watcher->
Register(
this);
599 for (
int i = 0; i < expr.vars.size(); ++i) {
600 const IntegerVariable&
var = expr.vars[i];
601 const IntegerValue coeff = expr.coeffs[i];
614 IntegerVariable
a, IntegerVariable
b, IntegerVariable p,
616 : a_(
a), b_(
b), p_(p), integer_trail_(integer_trail) {
627 const IntegerValue max_a = integer_trail_->
UpperBound(a_);
628 const IntegerValue max_b = integer_trail_->
UpperBound(b_);
629 const IntegerValue new_max(
CapProd(max_a.value(), max_b.value()));
630 if (new_max < integer_trail_->
UpperBound(p_)) {
632 {integer_trail_->UpperBoundAsLiteral(a_),
633 integer_trail_->UpperBoundAsLiteral(b_)})) {
638 const IntegerValue min_a = integer_trail_->
LowerBound(a_);
639 const IntegerValue min_b = integer_trail_->
LowerBound(b_);
640 const IntegerValue new_min(
CapProd(min_a.value(), min_b.value()));
641 if (new_min > integer_trail_->
LowerBound(p_)) {
644 {integer_trail_->LowerBoundAsLiteral(a_),
645 integer_trail_->LowerBoundAsLiteral(b_)})) {
650 for (
int i = 0; i < 2; ++i) {
651 const IntegerVariable
a = i == 0 ? a_ : b_;
652 const IntegerVariable
b = i == 0 ? b_ : a_;
653 const IntegerValue max_a = integer_trail_->
UpperBound(
a);
654 const IntegerValue min_b = integer_trail_->
LowerBound(
b);
655 const IntegerValue min_p = integer_trail_->
LowerBound(p_);
656 const IntegerValue max_p = integer_trail_->
UpperBound(p_);
657 const IntegerValue prod(
CapProd(max_a.value(), min_b.value()));
665 }
else if (prod < min_p) {
679 const int id = watcher->
Register(
this);
691IntegerValue FloorSquareRoot(IntegerValue
a) {
692 IntegerValue result(
static_cast<int64_t
>(
693 std::floor(std::sqrt(
static_cast<double>(
a.value())))));
694 while (
CapProd(result.value(), result.value()) >
a) --result;
695 while (
CapProd(result.value() + 1, result.value() + 1) <=
a) ++result;
700IntegerValue CeilSquareRoot(IntegerValue
a) {
701 IntegerValue result(
static_cast<int64_t
>(
702 std::ceil(std::sqrt(
static_cast<double>(
a.value())))));
703 while (
CapProd(result.value(), result.value()) <
a) ++result;
704 while ((result.value() - 1) * (result.value() - 1) >=
a) --result;
712 : x_(x), s_(s), integer_trail_(integer_trail) {
719 const IntegerValue min_x = integer_trail_->
LowerBound(x_);
720 const IntegerValue min_s = integer_trail_->
LowerBound(s_);
721 const IntegerValue min_x_square(
CapProd(min_x.value(), min_x.value()));
722 if (min_x_square > min_s) {
725 {IntegerLiteral::GreaterOrEqual(x_, min_x)})) {
728 }
else if (min_x_square < min_s) {
729 const IntegerValue new_min = CeilSquareRoot(min_s);
732 {IntegerLiteral::GreaterOrEqual(
733 s_, (new_min - 1) * (new_min - 1) + 1)})) {
738 const IntegerValue max_x = integer_trail_->
UpperBound(x_);
739 const IntegerValue max_s = integer_trail_->
UpperBound(s_);
740 const IntegerValue max_x_square(
CapProd(max_x.value(), max_x.value()));
741 if (max_x_square < max_s) {
744 {IntegerLiteral::LowerOrEqual(x_, max_x)})) {
747 }
else if (max_x_square > max_s) {
748 const IntegerValue new_max = FloorSquareRoot(max_s);
751 {IntegerLiteral::LowerOrEqual(
753 CapProd(new_max.value() + 1, new_max.value() + 1)) -
763 const int id = watcher->
Register(
this);
770 IntegerVariable num, IntegerVariable denom, IntegerVariable div,
772 : num_(num), denom_(denom), div_(div), integer_trail_(integer_trail) {
780 const IntegerValue min_num = integer_trail_->
LowerBound(num_);
781 const IntegerValue max_num = integer_trail_->
UpperBound(num_);
782 const IntegerValue min_denom = integer_trail_->
LowerBound(denom_);
783 const IntegerValue max_denom = integer_trail_->
UpperBound(denom_);
784 const IntegerValue min_div = integer_trail_->
LowerBound(div_);
785 const IntegerValue max_div = integer_trail_->
UpperBound(div_);
787 const IntegerValue new_max_div = max_num / min_denom;
788 if (max_div > new_max_div) {
791 {integer_trail_->UpperBoundAsLiteral(num_),
792 integer_trail_->LowerBoundAsLiteral(denom_)})) {
797 const IntegerValue new_min_div = min_num / max_denom;
798 if (min_div < new_min_div) {
801 {integer_trail_->LowerBoundAsLiteral(num_),
802 integer_trail_->UpperBoundAsLiteral(denom_)})) {
810 const IntegerValue new_max_num = (max_div + 1) * max_denom - 1;
811 if (max_num > new_max_num) {
814 {integer_trail_->UpperBoundAsLiteral(denom_),
815 integer_trail_->UpperBoundAsLiteral(div_)})) {
823 const IntegerValue new_min_num = min_denom * min_div;
824 if (min_num < new_min_num) {
827 {integer_trail_->LowerBoundAsLiteral(denom_),
828 integer_trail_->LowerBoundAsLiteral(div_)})) {
839 const IntegerValue new_max_denom = max_num / min_div;
840 if (max_denom > new_max_denom) {
843 {integer_trail_->UpperBoundAsLiteral(num_),
844 integer_trail_->LowerBoundAsLiteral(div_)})) {
855 const IntegerValue new_min_denom =
CeilRatio(min_num + 1, max_div + 1);
856 if (min_denom < new_min_denom) {
859 {integer_trail_->LowerBoundAsLiteral(num_),
860 integer_trail_->UpperBoundAsLiteral(div_)})) {
869 const int id = watcher->
Register(
this);
880 : a_(
a), b_(
b), c_(c), integer_trail_(integer_trail) {}
883 const IntegerValue min_a = integer_trail_->
LowerBound(a_);
884 const IntegerValue max_a = integer_trail_->
UpperBound(a_);
885 IntegerValue min_c = integer_trail_->
LowerBound(c_);
886 IntegerValue max_c = integer_trail_->
UpperBound(c_);
890 if (max_a / b_ < max_c) {
893 {integer_trail_->UpperBoundAsLiteral(a_)})) {
896 }
else if (max_a / b_ > max_c) {
897 const IntegerValue new_max_a =
898 max_c >= 0 ? max_c * b_ + b_ - 1
899 : IntegerValue(
CapProd(max_c.value(), b_.value()));
903 {integer_trail_->UpperBoundAsLiteral(c_)})) {
908 if (min_a / b_ > min_c) {
911 {integer_trail_->LowerBoundAsLiteral(a_)})) {
914 }
else if (min_a / b_ < min_c) {
915 const IntegerValue new_min_a =
916 min_c > 0 ? IntegerValue(
CapProd(min_c.value(), b_.value()))
917 : min_c * b_ - b_ + 1;
921 {integer_trail_->LowerBoundAsLiteral(c_)})) {
930 const int id = watcher->
Register(
this);
936 const std::vector<Literal>& selectors,
937 const std::vector<IntegerValue>& values) {
942 CHECK(!values.empty());
943 CHECK_EQ(values.size(), selectors.size());
944 std::vector<int64_t> unique_values;
945 absl::flat_hash_map<int64_t, std::vector<Literal>> value_to_selector;
946 for (
int i = 0; i < values.size(); ++i) {
947 unique_values.push_back(values[i].
value());
948 value_to_selector[values[i].value()].push_back(selectors[i]);
953 if (unique_values.size() == 1) {
960 for (
const int64_t v : unique_values) {
961 const std::vector<Literal>& selectors = value_to_selector[v];
962 if (selectors.size() == 1) {
963 encoder->AssociateToIntegerEqualValue(selectors[0],
var,
968 encoder->AssociateToIntegerEqualValue(l,
var, IntegerValue(v));
const std::vector< IntVar * > vars_
#define CHECK_LT(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_GT(val1, val2)
#define DCHECK_GE(val1, val2)
#define VLOG(verboselevel)
static Domain FromValues(std::vector< int64_t > values)
Creates a domain from the union of an unsorted list of integer values.
static int64_t GCD64(int64_t x, int64_t y)
void SaveState(T *object)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
void AdvanceDeterministicTime(double deterministic_duration)
Advances the deterministic time.
FixedDivisionPropagator(IntegerVariable a, IntegerValue b, IntegerVariable c, IntegerTrail *integer_trail)
void RegisterWith(GenericLiteralWatcher *watcher)
void RegisterReversibleInt(int id, int *rev)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
int Register(PropagatorInterface *propagator)
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
IntegerSumLE(const std::vector< Literal > &enforcement_literals, const std::vector< IntegerVariable > &vars, const std::vector< IntegerValue > &coeffs, IntegerValue upper_bound, Model *model)
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
int FindTrailIndexOfVarBefore(IntegerVariable var, int threshold) const
bool IsFixed(IntegerVariable i) const
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
IntegerValue UpperBound(IntegerVariable i) const
bool VariableLowerBoundIsFromLevelZero(IntegerVariable var) const
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
void RelaxLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, std::vector< IntegerLiteral > *reason) const
IntegerValue LowerBound(IntegerVariable i) const
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
bool UpdateInitialDomain(IntegerVariable var, Domain domain)
LinMinPropagator(const std::vector< LinearExpression > &exprs, IntegerVariable min_var, Model *model)
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.
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
void RegisterWith(GenericLiteralWatcher *watcher)
PositiveDivisionPropagator(IntegerVariable num, IntegerVariable denom, IntegerVariable div, IntegerTrail *integer_trail)
void RegisterWith(GenericLiteralWatcher *watcher)
PositiveProductPropagator(IntegerVariable a, IntegerVariable b, IntegerVariable p, IntegerTrail *integer_trail)
void RegisterWith(GenericLiteralWatcher *watcher)
SquarePropagator(IntegerVariable x, IntegerVariable s, IntegerTrail *integer_trail)
const VariablesAssignment & Assignment() const
int CurrentDecisionLevel() const
bool LiteralIsTrue(Literal literal) const
bool LiteralIsFalse(Literal literal) const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
IntegerValue LinExprLowerBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
std::function< void(Model *)> ReifiedBoolOr(const std::vector< Literal > &literals, Literal r)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
const LiteralIndex kNoLiteralIndex(-1)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
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)
IntegerVariable PositiveVariable(IntegerVariable i)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
IntegerValue LinExprUpperBound(const LinearExpression &expr, const IntegerTrail &integer_trail)
Collection of objects used to extend the Constraint Solver library.
int64_t CapProd(int64_t x, int64_t y)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)