24#include "absl/strings/str_format.h"
25#include "absl/strings/str_join.h"
34 "If true, caching for IntElement is disabled.");
46 explicit VectorLess(
const std::vector<T>* values) : values_(values) {}
47 bool operator()(
const T&
x,
const T&
y)
const {
48 return (*values_)[
x] < (*values_)[
y];
52 const std::vector<T>* values_;
58 explicit VectorGreater(
const std::vector<T>* values) : values_(values) {}
59 bool operator()(
const T&
x,
const T&
y)
const {
60 return (*values_)[
x] > (*values_)[
y];
64 const std::vector<T>* values_;
69class BaseIntExprElement :
public BaseIntExpr {
71 BaseIntExprElement(Solver* s, IntVar* e);
72 ~BaseIntExprElement()
override {}
73 int64_t Min()
const override;
74 int64_t Max()
const override;
75 void Range(int64_t* mi, int64_t* ma)
override;
76 void SetMin(int64_t m)
override;
77 void SetMax(int64_t m)
override;
78 void SetRange(int64_t mi, int64_t ma)
override;
79 bool Bound()
const override {
return (
expr_->Bound()); }
81 void WhenRange(Demon* d)
override {
expr_->WhenRange(d); }
84 virtual int64_t ElementValue(
int index)
const = 0;
85 virtual int64_t ExprMin()
const = 0;
86 virtual int64_t ExprMax()
const = 0;
91 void UpdateSupports()
const;
93 void UpdateElementIndexBounds(T check_value) {
94 const int64_t emin = ExprMin();
95 const int64_t emax = ExprMax();
97 int64_t
value = ElementValue(nmin);
98 while (nmin < emax && check_value(
value)) {
100 value = ElementValue(nmin);
102 if (nmin == emax && check_value(
value)) {
106 value = ElementValue(nmax);
107 while (nmax >= nmin && check_value(
value)) {
109 value = ElementValue(nmax);
111 expr_->SetRange(nmin, nmax);
114 mutable int64_t min_;
115 mutable int min_support_;
116 mutable int64_t max_;
117 mutable int max_support_;
118 mutable bool initial_update_;
119 IntVarIterator*
const expr_iterator_;
122BaseIntExprElement::BaseIntExprElement(Solver*
const s, IntVar*
const e)
129 initial_update_(
true),
130 expr_iterator_(
expr_->MakeDomainIterator(
true)) {
135int64_t BaseIntExprElement::Min()
const {
140int64_t BaseIntExprElement::Max()
const {
145void BaseIntExprElement::Range(int64_t* mi, int64_t* ma) {
151void BaseIntExprElement::SetMin(int64_t m) {
152 UpdateElementIndexBounds([m](int64_t
value) {
return value < m; });
155void BaseIntExprElement::SetMax(int64_t m) {
156 UpdateElementIndexBounds([m](int64_t
value) {
return value > m; });
159void BaseIntExprElement::SetRange(int64_t mi, int64_t ma) {
163 UpdateElementIndexBounds(
167void BaseIntExprElement::UpdateSupports()
const {
168 if (initial_update_ || !
expr_->Contains(min_support_) ||
169 !
expr_->Contains(max_support_)) {
170 const int64_t emin = ExprMin();
171 const int64_t emax = ExprMax();
172 int64_t min_value = ElementValue(emax);
173 int64_t max_value = min_value;
174 int min_support = emax;
175 int max_support = emax;
176 const uint64_t expr_size =
expr_->Size();
178 if (expr_size == emax - emin + 1) {
182 if (
value > max_value) {
185 }
else if (
value < min_value) {
191 for (
const int64_t
index : InitAndGetValues(expr_iterator_)) {
194 if (
value > max_value) {
197 }
else if (
value < min_value) {
205 Solver* s = solver();
206 s->SaveAndSetValue(&min_, min_value);
207 s->SaveAndSetValue(&min_support_, min_support);
208 s->SaveAndSetValue(&max_, max_value);
209 s->SaveAndSetValue(&max_support_, max_support);
210 s->SaveAndSetValue(&initial_update_,
false);
219class IntElementConstraint :
public CastConstraint {
221 IntElementConstraint(Solver*
const s,
const std::vector<int64_t>& values,
222 IntVar*
const index, IntVar*
const elem)
223 : CastConstraint(s, elem),
226 index_iterator_(index_->MakeDomainIterator(
true)) {
227 CHECK(
index !=
nullptr);
230 void Post()
override {
232 solver()->MakeDelayedConstraintInitialPropagateCallback(
this);
233 index_->WhenDomain(d);
234 target_var_->WhenRange(d);
237 void InitialPropagate()
override {
238 index_->SetRange(0, values_.size() - 1);
239 const int64_t target_var_min = target_var_->Min();
240 const int64_t target_var_max = target_var_->Max();
241 int64_t new_min = target_var_max;
242 int64_t new_max = target_var_min;
244 for (
const int64_t
index : InitAndGetValues(index_iterator_)) {
247 to_remove_.push_back(
index);
249 if (
value < new_min) {
252 if (
value > new_max) {
257 target_var_->SetRange(new_min, new_max);
258 if (!to_remove_.empty()) {
259 index_->RemoveValues(to_remove_);
263 std::string DebugString()
const override {
264 return absl::StrFormat(
"IntElementConstraint(%s, %s, %s)",
265 absl::StrJoin(values_,
", "), index_->DebugString(),
266 target_var_->DebugString());
269 void Accept(ModelVisitor*
const visitor)
const override {
270 visitor->BeginVisitConstraint(ModelVisitor::kElementEqual,
this);
271 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument, values_);
272 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
274 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
276 visitor->EndVisitConstraint(ModelVisitor::kElementEqual,
this);
280 const std::vector<int64_t> values_;
281 IntVar*
const index_;
282 IntVarIterator*
const index_iterator_;
283 std::vector<int64_t> to_remove_;
288IntVar* BuildDomainIntVar(Solver* solver, std::vector<int64_t>* values);
290class IntExprElement :
public BaseIntExprElement {
292 IntExprElement(Solver*
const s,
const std::vector<int64_t>& vals,
294 : BaseIntExprElement(s, expr), values_(vals) {}
296 ~IntExprElement()
override {}
298 std::string
name()
const override {
299 const int size = values_.size();
301 return absl::StrFormat(
"IntElement(array of size %d, %s)",
size,
304 return absl::StrFormat(
"IntElement(%s, %s)", absl::StrJoin(values_,
", "),
309 std::string DebugString()
const override {
310 const int size = values_.size();
312 return absl::StrFormat(
"IntElement(array of size %d, %s)",
size,
313 expr_->DebugString());
315 return absl::StrFormat(
"IntElement(%s, %s)", absl::StrJoin(values_,
", "),
316 expr_->DebugString());
320 IntVar* CastToVar()
override {
321 Solver*
const s = solver();
322 IntVar*
const var = s->MakeIntVar(values_);
323 s->AddCastConstraint(
324 s->RevAlloc(
new IntElementConstraint(s, values_,
expr_,
var)),
var,
329 void Accept(ModelVisitor*
const visitor)
const override {
330 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
331 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument, values_);
332 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
334 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
338 int64_t ElementValue(
int index)
const override {
339 DCHECK_LT(
index, values_.size());
340 return values_[
index];
342 int64_t ExprMin()
const override {
343 return std::max<int64_t>(0,
expr_->Min());
345 int64_t ExprMax()
const override {
346 return values_.empty()
348 : std::min<int64_t>(values_.size() - 1,
expr_->Max());
352 const std::vector<int64_t> values_;
357class RangeMinimumQueryExprElement :
public BaseIntExpr {
359 RangeMinimumQueryExprElement(Solver* solver,
360 const std::vector<int64_t>& values,
362 ~RangeMinimumQueryExprElement()
override {}
363 int64_t Min()
const override;
364 int64_t Max()
const override;
365 void Range(int64_t* mi, int64_t* ma)
override;
366 void SetMin(int64_t m)
override;
367 void SetMax(int64_t m)
override;
368 void SetRange(int64_t mi, int64_t ma)
override;
369 bool Bound()
const override {
return (index_->Bound()); }
371 void WhenRange(Demon* d)
override { index_->WhenRange(d); }
372 IntVar* CastToVar()
override {
376 IntVar*
const var = solver()->MakeIntVar(min_rmq_.array());
377 solver()->AddCastConstraint(solver()->RevAlloc(
new IntElementConstraint(
378 solver(), min_rmq_.array(), index_,
var)),
382 void Accept(ModelVisitor*
const visitor)
const override {
383 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
384 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
386 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
388 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
392 int64_t IndexMin()
const {
return std::max<int64_t>(0, index_->Min()); }
393 int64_t IndexMax()
const {
394 return std::min<int64_t>(min_rmq_.array().size() - 1, index_->Max());
397 IntVar*
const index_;
398 const RangeMinimumQuery<int64_t, std::less<int64_t>> min_rmq_;
399 const RangeMinimumQuery<int64_t, std::greater<int64_t>> max_rmq_;
402RangeMinimumQueryExprElement::RangeMinimumQueryExprElement(
403 Solver* solver,
const std::vector<int64_t>& values, IntVar*
index)
404 : BaseIntExpr(solver), index_(
index), min_rmq_(values), max_rmq_(values) {
405 CHECK(solver !=
nullptr);
406 CHECK(
index !=
nullptr);
409int64_t RangeMinimumQueryExprElement::Min()
const {
410 return min_rmq_.GetMinimumFromRange(IndexMin(), IndexMax() + 1);
413int64_t RangeMinimumQueryExprElement::Max()
const {
414 return max_rmq_.GetMinimumFromRange(IndexMin(), IndexMax() + 1);
417void RangeMinimumQueryExprElement::Range(int64_t* mi, int64_t* ma) {
418 const int64_t range_min = IndexMin();
419 const int64_t range_max = IndexMax() + 1;
420 *mi = min_rmq_.GetMinimumFromRange(range_min, range_max);
421 *ma = max_rmq_.GetMinimumFromRange(range_min, range_max);
424#define UPDATE_RMQ_BASE_ELEMENT_INDEX_BOUNDS(test) \
425 const std::vector<int64_t>& values = min_rmq_.array(); \
426 int64_t index_min = IndexMin(); \
427 int64_t index_max = IndexMax(); \
428 int64_t value = values[index_min]; \
429 while (index_min < index_max && (test)) { \
431 value = values[index_min]; \
433 if (index_min == index_max && (test)) { \
436 value = values[index_max]; \
437 while (index_max >= index_min && (test)) { \
439 value = values[index_max]; \
441 index_->SetRange(index_min, index_max);
443void RangeMinimumQueryExprElement::SetMin(int64_t m) {
447void RangeMinimumQueryExprElement::SetMax(int64_t m) {
451void RangeMinimumQueryExprElement::SetRange(int64_t mi, int64_t ma) {
458#undef UPDATE_RMQ_BASE_ELEMENT_INDEX_BOUNDS
462class IncreasingIntExprElement :
public BaseIntExpr {
464 IncreasingIntExprElement(Solver* s,
const std::vector<int64_t>& values,
466 ~IncreasingIntExprElement()
override {}
468 int64_t Min()
const override;
469 void SetMin(int64_t m)
override;
470 int64_t Max()
const override;
471 void SetMax(int64_t m)
override;
472 void SetRange(int64_t mi, int64_t ma)
override;
473 bool Bound()
const override {
return (index_->Bound()); }
475 std::string
name()
const override {
476 return absl::StrFormat(
"IntElement(%s, %s)", absl::StrJoin(values_,
", "),
479 std::string DebugString()
const override {
480 return absl::StrFormat(
"IntElement(%s, %s)", absl::StrJoin(values_,
", "),
481 index_->DebugString());
484 void Accept(ModelVisitor*
const visitor)
const override {
485 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
486 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument, values_);
487 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
489 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
492 void WhenRange(Demon* d)
override { index_->WhenRange(d); }
494 IntVar* CastToVar()
override {
495 Solver*
const s = solver();
496 IntVar*
const var = s->MakeIntVar(values_);
502 const std::vector<int64_t> values_;
503 IntVar*
const index_;
506IncreasingIntExprElement::IncreasingIntExprElement(
507 Solver*
const s,
const std::vector<int64_t>& values, IntVar*
const index)
508 : BaseIntExpr(s), values_(values), index_(
index) {
513int64_t IncreasingIntExprElement::Min()
const {
514 const int64_t expression_min = std::max<int64_t>(0, index_->Min());
515 return (expression_min < values_.size()
516 ? values_[expression_min]
517 : std::numeric_limits<int64_t>::max());
520void IncreasingIntExprElement::SetMin(int64_t m) {
521 const int64_t index_min = std::max<int64_t>(0, index_->Min());
522 const int64_t index_max =
523 std::min<int64_t>(values_.size() - 1, index_->Max());
525 if (index_min > index_max || m > values_[index_max]) {
529 const std::vector<int64_t>::const_iterator first =
530 std::lower_bound(values_.begin(), values_.end(), m);
531 const int64_t new_index_min = first - values_.begin();
532 index_->SetMin(new_index_min);
535int64_t IncreasingIntExprElement::Max()
const {
536 const int64_t expression_max =
537 std::min<int64_t>(values_.size() - 1, index_->Max());
538 return (expression_max >= 0 ? values_[expression_max]
539 : std::numeric_limits<int64_t>::max());
542void IncreasingIntExprElement::SetMax(int64_t m) {
543 int64_t index_min = std::max<int64_t>(0, index_->Min());
544 if (m < values_[index_min]) {
548 const std::vector<int64_t>::const_iterator last_after =
549 std::upper_bound(values_.begin(), values_.end(), m);
550 const int64_t new_index_max = (last_after - values_.begin()) - 1;
551 index_->SetRange(0, new_index_max);
554void IncreasingIntExprElement::SetRange(int64_t mi, int64_t ma) {
558 const int64_t index_min = std::max<int64_t>(0, index_->Min());
559 const int64_t index_max =
560 std::min<int64_t>(values_.size() - 1, index_->Max());
562 if (mi > ma || ma < values_[index_min] || mi > values_[index_max]) {
566 const std::vector<int64_t>::const_iterator first =
567 std::lower_bound(values_.begin(), values_.end(), mi);
568 const int64_t new_index_min = first - values_.begin();
570 const std::vector<int64_t>::const_iterator last_after =
571 std::upper_bound(first, values_.end(), ma);
572 const int64_t new_index_max = (last_after - values_.begin()) - 1;
575 index_->SetRange(new_index_min, new_index_max);
579IntExpr* BuildElement(Solver*
const solver,
const std::vector<int64_t>& values,
580 IntVar*
const index) {
584 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, values.size() - 1));
585 return solver->MakeIntConst(values[0]);
590 std::vector<int64_t> ones;
592 for (
int i = 0;
i < values.size(); ++
i) {
593 if (values[i] == 1) {
599 if (ones.size() == 1) {
600 DCHECK_EQ(int64_t{1}, values[ones.back()]);
601 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, values.size() - 1));
602 return solver->MakeIsEqualCstVar(
index, ones.back());
603 }
else if (ones.size() == values.size() - 1) {
604 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, values.size() - 1));
605 return solver->MakeIsDifferentCstVar(
index, first_zero);
606 }
else if (ones.size() == ones.back() - ones.front() + 1) {
607 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, values.size() - 1));
608 IntVar*
const b = solver->MakeBoolVar(
"ContiguousBooleanElementVar");
609 solver->AddConstraint(
610 solver->MakeIsBetweenCt(
index, ones.front(), ones.back(),
b));
613 IntVar*
const b = solver->MakeBoolVar(
"NonContiguousBooleanElementVar");
614 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, values.size() - 1));
615 solver->AddConstraint(solver->MakeIsMemberCt(
index, ones,
b));
619 IntExpr* cache =
nullptr;
620 if (!absl::GetFlag(FLAGS_cp_disable_element_cache)) {
621 cache = solver->Cache()->FindVarConstantArrayExpression(
622 index, values, ModelCache::VAR_CONSTANT_ARRAY_ELEMENT);
624 if (cache !=
nullptr) {
627 IntExpr* result =
nullptr;
628 if (values.size() >= 2 &&
index->Min() == 0 &&
index->Max() == 1) {
629 result = solver->MakeSum(solver->MakeProd(
index, values[1] - values[0]),
631 }
else if (values.size() == 2 &&
index->Contains(0) &&
index->Contains(1)) {
632 solver->AddConstraint(solver->MakeBetweenCt(
index, 0, 1));
633 result = solver->MakeSum(solver->MakeProd(
index, values[1] - values[0]),
636 result = solver->MakeSum(
index, values[0]);
638 result = solver->RegisterIntExpr(solver->RevAlloc(
639 new IncreasingIntExprElement(solver, values,
index)));
641 if (solver->parameters().use_element_rmq()) {
642 result = solver->RegisterIntExpr(solver->RevAlloc(
643 new RangeMinimumQueryExprElement(solver, values,
index)));
645 result = solver->RegisterIntExpr(
646 solver->RevAlloc(
new IntExprElement(solver, values,
index)));
649 if (!absl::GetFlag(FLAGS_cp_disable_element_cache)) {
650 solver->Cache()->InsertVarConstantArrayExpression(
651 result,
index, values, ModelCache::VAR_CONSTANT_ARRAY_ELEMENT);
658IntExpr* Solver::MakeElement(
const std::vector<int64_t>& values,
661 DCHECK_EQ(
this,
index->solver());
662 if (
index->Bound()) {
663 return MakeIntConst(values[
index->Min()]);
665 return BuildElement(
this, values,
index);
668IntExpr* Solver::MakeElement(
const std::vector<int>& values,
671 DCHECK_EQ(
this,
index->solver());
672 if (
index->Bound()) {
673 return MakeIntConst(values[
index->Min()]);
681class IntExprFunctionElement :
public BaseIntExprElement {
684 ~IntExprFunctionElement()
override;
686 std::string
name()
const override {
687 return absl::StrFormat(
"IntFunctionElement(%s)",
expr_->name());
690 std::string DebugString()
const override {
691 return absl::StrFormat(
"IntFunctionElement(%s)",
expr_->DebugString());
694 void Accept(ModelVisitor*
const visitor)
const override {
696 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
697 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
699 visitor->VisitInt64ToInt64Extension(values_,
expr_->Min(),
expr_->Max());
700 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
704 int64_t ElementValue(
int index)
const override {
return values_(
index); }
705 int64_t ExprMin()
const override {
return expr_->Min(); }
706 int64_t ExprMax()
const override {
return expr_->Max(); }
709 Solver::IndexEvaluator1 values_;
712IntExprFunctionElement::IntExprFunctionElement(Solver*
const s,
713 Solver::IndexEvaluator1 values,
715 : BaseIntExprElement(s, e), values_(
std::move(values)) {
716 CHECK(values_ !=
nullptr);
719IntExprFunctionElement::~IntExprFunctionElement() {}
723class IncreasingIntExprFunctionElement :
public BaseIntExpr {
725 IncreasingIntExprFunctionElement(Solver*
const s,
726 Solver::IndexEvaluator1 values,
728 : BaseIntExpr(s), values_(
std::move(values)), index_(
index) {
729 DCHECK(values_ !=
nullptr);
734 ~IncreasingIntExprFunctionElement()
override {}
736 int64_t Min()
const override {
return values_(index_->
Min()); }
738 void SetMin(int64_t m)
override {
739 const int64_t index_min = index_->
Min();
740 const int64_t index_max = index_->
Max();
741 if (m > values_(index_max)) {
744 const int64_t new_index_min = FindNewIndexMin(index_min, index_max, m);
745 index_->
SetMin(new_index_min);
748 int64_t Max()
const override {
return values_(index_->
Max()); }
750 void SetMax(int64_t m)
override {
751 int64_t index_min = index_->
Min();
752 int64_t index_max = index_->
Max();
753 if (m < values_(index_min)) {
756 const int64_t new_index_max = FindNewIndexMax(index_min, index_max, m);
757 index_->
SetMax(new_index_max);
760 void SetRange(int64_t mi, int64_t ma)
override {
761 const int64_t index_min = index_->
Min();
762 const int64_t index_max = index_->
Max();
763 const int64_t value_min = values_(index_min);
764 const int64_t value_max = values_(index_max);
765 if (mi > ma || ma < value_min || mi > value_max) {
768 if (mi <= value_min && ma >= value_max) {
773 const int64_t new_index_min = FindNewIndexMin(index_min, index_max, mi);
774 const int64_t new_index_max = FindNewIndexMax(new_index_min, index_max, ma);
776 index_->
SetRange(new_index_min, new_index_max);
779 std::string
name()
const override {
780 return absl::StrFormat(
"IncreasingIntExprFunctionElement(values, %s)",
784 std::string DebugString()
const override {
785 return absl::StrFormat(
"IncreasingIntExprFunctionElement(values, %s)",
789 void WhenRange(Demon* d)
override { index_->
WhenRange(d); }
791 void Accept(ModelVisitor*
const visitor)
const override {
793 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
794 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
796 if (index_->
Min() == 0) {
797 visitor->VisitInt64ToInt64AsArray(values_, ModelVisitor::kValuesArgument,
800 visitor->VisitInt64ToInt64Extension(values_, index_->
Min(),
803 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
807 int64_t FindNewIndexMin(int64_t index_min, int64_t index_max, int64_t m) {
808 if (m <= values_(index_min)) {
812 DCHECK_LT(values_(index_min), m);
813 DCHECK_GE(values_(index_max), m);
815 int64_t index_lower_bound = index_min;
816 int64_t index_upper_bound = index_max;
817 while (index_upper_bound - index_lower_bound > 1) {
818 DCHECK_LT(values_(index_lower_bound), m);
819 DCHECK_GE(values_(index_upper_bound), m);
820 const int64_t pivot = (index_lower_bound + index_upper_bound) / 2;
821 const int64_t pivot_value = values_(pivot);
822 if (pivot_value < m) {
823 index_lower_bound = pivot;
825 index_upper_bound = pivot;
828 DCHECK(values_(index_upper_bound) >= m);
829 return index_upper_bound;
832 int64_t FindNewIndexMax(int64_t index_min, int64_t index_max, int64_t m) {
833 if (m >= values_(index_max)) {
837 DCHECK_LE(values_(index_min), m);
838 DCHECK_GT(values_(index_max), m);
840 int64_t index_lower_bound = index_min;
841 int64_t index_upper_bound = index_max;
842 while (index_upper_bound - index_lower_bound > 1) {
843 DCHECK_LE(values_(index_lower_bound), m);
844 DCHECK_GT(values_(index_upper_bound), m);
845 const int64_t pivot = (index_lower_bound + index_upper_bound) / 2;
846 const int64_t pivot_value = values_(pivot);
847 if (pivot_value > m) {
848 index_upper_bound = pivot;
850 index_lower_bound = pivot;
853 DCHECK(values_(index_lower_bound) <= m);
854 return index_lower_bound;
857 Solver::IndexEvaluator1 values_;
858 IntVar*
const index_;
864 CHECK_EQ(
this,
index->solver());
865 return RegisterIntExpr(
866 RevAlloc(
new IntExprFunctionElement(
this, std::move(values),
index)));
871 CHECK_EQ(
this,
index->solver());
873 return RegisterIntExpr(
874 RevAlloc(
new IncreasingIntExprFunctionElement(
this, values,
index)));
881 return RegisterIntExpr(MakeOpposite(RevAlloc(
882 new IncreasingIntExprFunctionElement(
this, opposite_values,
index))));
889class IntIntExprFunctionElement :
public BaseIntExpr {
893 ~IntIntExprFunctionElement()
override;
894 std::string DebugString()
const override {
895 return absl::StrFormat(
"IntIntFunctionElement(%s,%s)",
898 int64_t Min()
const override;
899 int64_t Max()
const override;
904 bool Bound()
const override {
return expr1_->
Bound() && expr2_->
Bound(); }
906 void WhenRange(Demon* d)
override {
911 void Accept(ModelVisitor*
const visitor)
const override {
912 visitor->BeginVisitIntegerExpression(ModelVisitor::kElement,
this);
913 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
915 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndex2Argument,
918 const int64_t expr1_min = expr1_->
Min();
919 const int64_t expr1_max = expr1_->
Max();
920 visitor->VisitIntegerArgument(ModelVisitor::kMinArgument, expr1_min);
921 visitor->VisitIntegerArgument(ModelVisitor::kMaxArgument, expr1_max);
922 for (
int i = expr1_min;
i <= expr1_max; ++
i) {
923 visitor->VisitInt64ToInt64Extension(
924 [
this, i](int64_t j) {
return values_(i, j); }, expr2_->
Min(),
927 visitor->EndVisitIntegerExpression(ModelVisitor::kElement,
this);
931 int64_t ElementValue(
int index1,
int index2)
const {
932 return values_(index1, index2);
934 void UpdateSupports()
const;
936 IntVar*
const expr1_;
937 IntVar*
const expr2_;
938 mutable int64_t min_;
939 mutable int min_support1_;
940 mutable int min_support2_;
941 mutable int64_t max_;
942 mutable int max_support1_;
943 mutable int max_support2_;
944 mutable bool initial_update_;
945 Solver::IndexEvaluator2 values_;
946 IntVarIterator*
const expr1_iterator_;
947 IntVarIterator*
const expr2_iterator_;
950IntIntExprFunctionElement::IntIntExprFunctionElement(
962 initial_update_(
true),
963 values_(
std::move(values)),
964 expr1_iterator_(expr1_->MakeDomainIterator(
true)),
965 expr2_iterator_(expr2_->MakeDomainIterator(
true)) {
966 CHECK(values_ !=
nullptr);
969IntIntExprFunctionElement::~IntIntExprFunctionElement() {}
971int64_t IntIntExprFunctionElement::Min()
const {
976int64_t IntIntExprFunctionElement::Max()
const {
981void IntIntExprFunctionElement::Range(int64_t*
lower_bound,
988#define UPDATE_ELEMENT_INDEX_BOUNDS(test) \
989 const int64_t emin1 = expr1_->Min(); \
990 const int64_t emax1 = expr1_->Max(); \
991 const int64_t emin2 = expr2_->Min(); \
992 const int64_t emax2 = expr2_->Max(); \
993 int64_t nmin1 = emin1; \
994 bool found = false; \
995 while (nmin1 <= emax1 && !found) { \
996 for (int i = emin2; i <= emax2; ++i) { \
997 int64_t value = ElementValue(nmin1, i); \
1007 if (nmin1 > emax1) { \
1010 int64_t nmin2 = emin2; \
1012 while (nmin2 <= emax2 && !found) { \
1013 for (int i = emin1; i <= emax1; ++i) { \
1014 int64_t value = ElementValue(i, nmin2); \
1024 if (nmin2 > emax2) { \
1027 int64_t nmax1 = emax1; \
1029 while (nmax1 >= nmin1 && !found) { \
1030 for (int i = emin2; i <= emax2; ++i) { \
1031 int64_t value = ElementValue(nmax1, i); \
1041 int64_t nmax2 = emax2; \
1043 while (nmax2 >= nmin2 && !found) { \
1044 for (int i = emin1; i <= emax1; ++i) { \
1045 int64_t value = ElementValue(i, nmax2); \
1055 expr1_->SetRange(nmin1, nmax1); \
1056 expr2_->SetRange(nmin2, nmax2);
1058void IntIntExprFunctionElement::SetMin(int64_t
lower_bound) {
1062void IntIntExprFunctionElement::SetMax(int64_t
upper_bound) {
1066void IntIntExprFunctionElement::SetRange(int64_t
lower_bound,
1074#undef UPDATE_ELEMENT_INDEX_BOUNDS
1076void IntIntExprFunctionElement::UpdateSupports()
const {
1077 if (initial_update_ || !expr1_->
Contains(min_support1_) ||
1079 !expr2_->
Contains(max_support2_)) {
1080 const int64_t emax1 = expr1_->
Max();
1081 const int64_t emax2 = expr2_->
Max();
1082 int64_t min_value = ElementValue(emax1, emax2);
1083 int64_t max_value = min_value;
1084 int min_support1 = emax1;
1085 int max_support1 = emax1;
1086 int min_support2 = emax2;
1087 int max_support2 = emax2;
1088 for (
const int64_t index1 : InitAndGetValues(expr1_iterator_)) {
1089 for (
const int64_t index2 : InitAndGetValues(expr2_iterator_)) {
1090 const int64_t
value = ElementValue(index1, index2);
1091 if (
value > max_value) {
1093 max_support1 = index1;
1094 max_support2 = index2;
1095 }
else if (
value < min_value) {
1097 min_support1 = index1;
1098 min_support2 = index2;
1102 Solver* s = solver();
1103 s->SaveAndSetValue(&min_, min_value);
1104 s->SaveAndSetValue(&min_support1_, min_support1);
1105 s->SaveAndSetValue(&min_support2_, min_support2);
1106 s->SaveAndSetValue(&max_, max_value);
1107 s->SaveAndSetValue(&max_support1_, max_support1);
1108 s->SaveAndSetValue(&max_support2_, max_support2);
1109 s->SaveAndSetValue(&initial_update_,
false);
1116 CHECK_EQ(
this, index1->
solver());
1117 CHECK_EQ(
this, index2->
solver());
1118 return RegisterIntExpr(RevAlloc(
1119 new IntIntExprFunctionElement(
this, std::move(values), index1, index2)));
1131 condition_(condition),
1138 Demon*
const demon = solver()->MakeConstraintInitialPropagateCallback(
this);
1139 condition_->WhenBound(demon);
1140 one_->WhenRange(demon);
1141 zero_->WhenRange(demon);
1142 target_var_->WhenRange(demon);
1146 condition_->SetRange(0, 1);
1147 const int64_t target_var_min = target_var_->Min();
1148 const int64_t target_var_max = target_var_->Max();
1149 int64_t new_min = std::numeric_limits<int64_t>::min();
1150 int64_t new_max = std::numeric_limits<int64_t>::max();
1151 if (condition_->Max() == 0) {
1152 zero_->SetRange(target_var_min, target_var_max);
1153 zero_->Range(&new_min, &new_max);
1154 }
else if (condition_->Min() == 1) {
1155 one_->SetRange(target_var_min, target_var_max);
1156 one_->Range(&new_min, &new_max);
1158 if (target_var_max < zero_->Min() || target_var_min > zero_->Max()) {
1159 condition_->SetValue(1);
1160 one_->SetRange(target_var_min, target_var_max);
1161 one_->Range(&new_min, &new_max);
1162 }
else if (target_var_max < one_->Min() || target_var_min > one_->Max()) {
1163 condition_->SetValue(0);
1164 zero_->SetRange(target_var_min, target_var_max);
1165 zero_->Range(&new_min, &new_max);
1171 zero_->Range(&zl, &zu);
1172 one_->Range(&ol, &ou);
1173 new_min = std::min(zl, ol);
1174 new_max = std::max(zu, ou);
1177 target_var_->SetRange(new_min, new_max);
1181 return absl::StrFormat(
"(%s ? %s : %s) == %s", condition_->DebugString(),
1182 one_->DebugString(), zero_->DebugString(),
1183 target_var_->DebugString());
1189 IntVar*
const condition_;
1201class IntExprEvaluatorElementCt :
public CastConstraint {
1203 IntExprEvaluatorElementCt(Solver* s, Solver::Int64ToIntVar evaluator,
1204 int64_t range_start, int64_t range_end,
1205 IntVar*
index, IntVar* target_var);
1206 ~IntExprEvaluatorElementCt()
override {}
1208 void Post()
override;
1209 void InitialPropagate()
override;
1212 void Update(
int index);
1215 std::string DebugString()
const override;
1216 void Accept(ModelVisitor* visitor)
const override;
1219 IntVar*
const index_;
1222 const Solver::Int64ToIntVar evaluator_;
1223 const int64_t range_start_;
1224 const int64_t range_end_;
1229IntExprEvaluatorElementCt::IntExprEvaluatorElementCt(
1231 int64_t range_end, IntVar*
const index, IntVar*
const target_var)
1232 : CastConstraint(s, target_var),
1234 evaluator_(
std::move(evaluator)),
1235 range_start_(range_start),
1236 range_end_(range_end),
1240void IntExprEvaluatorElementCt::Post() {
1242 solver(),
this, &IntExprEvaluatorElementCt::Propagate,
"Propagate");
1243 for (
int i = range_start_;
i < range_end_; ++
i) {
1244 IntVar*
const current_var = evaluator_(i);
1245 current_var->WhenRange(delayed_propagate_demon);
1247 solver(),
this, &IntExprEvaluatorElementCt::Update,
"Update", i);
1248 current_var->WhenRange(update_demon);
1250 index_->
WhenRange(delayed_propagate_demon);
1252 solver(),
this, &IntExprEvaluatorElementCt::UpdateExpr,
"UpdateExpr");
1255 solver(),
this, &IntExprEvaluatorElementCt::Propagate,
"UpdateVar");
1257 target_var_->WhenRange(update_var_demon);
1260void IntExprEvaluatorElementCt::InitialPropagate() { Propagate(); }
1262void IntExprEvaluatorElementCt::Propagate() {
1263 const int64_t emin = std::max(range_start_, index_->
Min());
1264 const int64_t emax = std::min<int64_t>(range_end_ - 1, index_->
Max());
1265 const int64_t vmin = target_var_->Min();
1266 const int64_t vmax = target_var_->Max();
1269 evaluator_(emin)->SetRange(vmin, vmax);
1271 int64_t nmin = emin;
1272 for (; nmin <= emax; nmin++) {
1276 IntVar*
const nmin_var = evaluator_(nmin);
1277 if (nmin_var->Min() <= vmax && nmin_var->Max() >= vmin)
break;
1279 int64_t nmax = emax;
1280 for (; nmin <= nmax; nmax--) {
1284 IntExpr*
const nmax_var = evaluator_(nmax);
1285 if (nmax_var->Min() <= vmax && nmax_var->Max() >= vmin)
break;
1289 evaluator_(nmin)->SetRange(vmin, vmax);
1292 if (min_support_ == -1 || max_support_ == -1) {
1293 int min_support = -1;
1294 int max_support = -1;
1295 int64_t gmin = std::numeric_limits<int64_t>::max();
1296 int64_t gmax = std::numeric_limits<int64_t>::min();
1297 for (
int i = index_->
Min(); i <= index_->Max(); ++
i) {
1298 IntExpr*
const var_i = evaluator_(i);
1299 const int64_t vmin = var_i->Min();
1303 const int64_t vmax = var_i->Max();
1308 solver()->SaveAndSetValue(&min_support_, min_support);
1309 solver()->SaveAndSetValue(&max_support_, max_support);
1310 target_var_->SetRange(gmin, gmax);
1314void IntExprEvaluatorElementCt::Update(
int index) {
1315 if (
index == min_support_ ||
index == max_support_) {
1316 solver()->SaveAndSetValue(&min_support_, -1);
1317 solver()->SaveAndSetValue(&max_support_, -1);
1321void IntExprEvaluatorElementCt::UpdateExpr() {
1323 solver()->SaveAndSetValue(&min_support_, -1);
1324 solver()->SaveAndSetValue(&max_support_, -1);
1330 int64_t range_start, int64_t range_end) {
1332 for (int64_t i = range_start;
i < range_end; ++
i) {
1333 if (i != range_start) {
1336 out += absl::StrFormat(
"%d -> %s", i, evaluator(i)->DebugString());
1342 int64_t range_begin, int64_t range_end) {
1344 if (range_end - range_begin > 10) {
1345 out = absl::StrFormat(
1346 "IntToIntVar(%s, ...%s)",
1347 StringifyEvaluatorBare(evaluator, range_begin, range_begin + 5),
1348 StringifyEvaluatorBare(evaluator, range_end - 5, range_end));
1350 out = absl::StrFormat(
1352 StringifyEvaluatorBare(evaluator, range_begin, range_end));
1358std::string IntExprEvaluatorElementCt::DebugString()
const {
1359 return StringifyInt64ToIntVar(evaluator_, range_start_, range_end_);
1362void IntExprEvaluatorElementCt::Accept(ModelVisitor*
const visitor)
const {
1363 visitor->BeginVisitConstraint(ModelVisitor::kElementEqual,
this);
1364 visitor->VisitIntegerVariableEvaluatorArgument(
1365 ModelVisitor::kEvaluatorArgument, evaluator_);
1366 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument, index_);
1367 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
1369 visitor->EndVisitConstraint(ModelVisitor::kElementEqual,
this);
1377class IntExprArrayElementCt :
public IntExprEvaluatorElementCt {
1379 IntExprArrayElementCt(Solver* s, std::vector<IntVar*> vars, IntVar*
index,
1380 IntVar* target_var);
1382 std::string DebugString()
const override;
1383 void Accept(ModelVisitor* visitor)
const override;
1386 const std::vector<IntVar*>
vars_;
1389IntExprArrayElementCt::IntExprArrayElementCt(Solver*
const s,
1390 std::vector<IntVar*> vars,
1391 IntVar*
const index,
1392 IntVar*
const target_var)
1393 : IntExprEvaluatorElementCt(
1394 s, [this](int64_t idx) {
return vars_[idx]; }, 0, vars.size(),
index,
1396 vars_(std::move(vars)) {}
1398std::string IntExprArrayElementCt::DebugString()
const {
1401 return absl::StrFormat(
1402 "IntExprArrayElement(var array of size %d, %s) == %s",
size,
1403 index_->DebugString(), target_var_->DebugString());
1405 return absl::StrFormat(
"IntExprArrayElement([%s], %s) == %s",
1407 index_->DebugString(), target_var_->DebugString());
1411void IntExprArrayElementCt::Accept(ModelVisitor*
const visitor)
const {
1412 visitor->BeginVisitConstraint(ModelVisitor::kElementEqual,
this);
1413 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1415 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument, index_);
1416 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
1418 visitor->EndVisitConstraint(ModelVisitor::kElementEqual,
this);
1425class IntExprArrayElementCstCt :
public Constraint {
1427 IntExprArrayElementCstCt(Solver*
const s,
const std::vector<IntVar*>& vars,
1428 IntVar*
const index, int64_t target)
1433 demons_(vars.
size()) {}
1435 ~IntExprArrayElementCstCt()
override {}
1437 void Post()
override {
1438 for (
int i = 0;
i <
vars_.size(); ++
i) {
1440 solver(),
this, &IntExprArrayElementCstCt::Propagate,
"Propagate", i);
1441 vars_[
i]->WhenDomain(demons_[i]);
1444 solver(),
this, &IntExprArrayElementCstCt::PropagateIndex,
1449 void InitialPropagate()
override {
1450 for (
int i = 0;
i <
vars_.size(); ++
i) {
1456 void Propagate(
int index) {
1459 demons_[
index]->inhibit(solver());
1463 void PropagateIndex() {
1464 if (index_->
Bound()) {
1465 vars_[index_->
Min()]->SetValue(target_);
1469 std::string DebugString()
const override {
1470 return absl::StrFormat(
"IntExprArrayElement([%s], %s) == %d",
1475 void Accept(ModelVisitor*
const visitor)
const override {
1476 visitor->BeginVisitConstraint(ModelVisitor::kElementEqual,
this);
1477 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1479 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
1481 visitor->VisitIntegerArgument(ModelVisitor::kTargetArgument, target_);
1482 visitor->EndVisitConstraint(ModelVisitor::kElementEqual,
this);
1486 const std::vector<IntVar*>
vars_;
1487 IntVar*
const index_;
1488 const int64_t target_;
1489 std::vector<Demon*> demons_;
1494class IntExprIndexOfCt :
public Constraint {
1496 IntExprIndexOfCt(Solver*
const s,
const std::vector<IntVar*>& vars,
1497 IntVar*
const index, int64_t target)
1503 index_iterator_(
index->MakeHoleIterator(
true)) {}
1505 ~IntExprIndexOfCt()
override {}
1507 void Post()
override {
1508 for (
int i = 0;
i <
vars_.size(); ++
i) {
1510 solver(),
this, &IntExprIndexOfCt::Propagate,
"Propagate", i);
1511 vars_[
i]->WhenDomain(demons_[i]);
1514 solver(),
this, &IntExprIndexOfCt::PropagateIndex,
"PropagateIndex");
1518 void InitialPropagate()
override {
1519 for (
int i = 0;
i <
vars_.size(); ++
i) {
1521 vars_[
i]->RemoveValue(target_);
1522 }
else if (!
vars_[i]->Contains(target_)) {
1524 demons_[
i]->inhibit(solver());
1525 }
else if (
vars_[i]->Bound()) {
1527 demons_[
i]->inhibit(solver());
1532 void Propagate(
int index) {
1535 demons_[
index]->inhibit(solver());
1541 void PropagateIndex() {
1542 const int64_t oldmax = index_->
OldMax();
1543 const int64_t vmin = index_->
Min();
1544 const int64_t vmax = index_->
Max();
1547 demons_[
value]->inhibit(solver());
1549 for (
const int64_t
value : InitAndGetValues(index_iterator_)) {
1551 demons_[
value]->inhibit(solver());
1555 demons_[
value]->inhibit(solver());
1557 if (index_->
Bound()) {
1558 vars_[index_->
Min()]->SetValue(target_);
1562 std::string DebugString()
const override {
1563 return absl::StrFormat(
"IntExprIndexOf([%s], %s) == %d",
1568 void Accept(ModelVisitor*
const visitor)
const override {
1569 visitor->BeginVisitConstraint(ModelVisitor::kIndexOf,
this);
1570 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1572 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
1574 visitor->VisitIntegerArgument(ModelVisitor::kTargetArgument, target_);
1575 visitor->EndVisitConstraint(ModelVisitor::kIndexOf,
this);
1579 const std::vector<IntVar*>
vars_;
1580 IntVar*
const index_;
1581 const int64_t target_;
1582 std::vector<Demon*> demons_;
1583 IntVarIterator*
const index_iterator_;
1588Constraint* MakeElementEqualityFunc(Solver*
const solver,
1589 const std::vector<int64_t>& vals,
1590 IntVar*
const index, IntVar*
const target) {
1591 if (
index->Bound()) {
1592 const int64_t val =
index->Min();
1593 if (val < 0 || val >= vals.size()) {
1594 return solver->MakeFalseConstraint();
1596 return solver->MakeEquality(target, vals[val]);
1600 return solver->MakeEquality(target, solver->MakeSum(
index, vals[0]));
1602 return solver->RevAlloc(
1603 new IntElementConstraint(solver, vals,
index, target));
1612 IntVar*
const target_var) {
1614 new IfThenElseCt(
this, condition, then_expr, else_expr, target_var));
1619 if (
index->Bound()) {
1620 return vars[
index->Min()];
1622 const int size = vars.size();
1624 std::vector<int64_t> values(
size);
1625 for (
int i = 0; i <
size; ++i) {
1626 values[i] = vars[i]->Value();
1628 return MakeElement(values,
index);
1631 index->Min() >= 0 &&
index->Max() < vars.size()) {
1636 const std::string
name = absl::StrFormat(
1638 IntVar*
const target = MakeIntVar(std::min(zero->
Min(), one->
Min()),
1641 RevAlloc(
new IfThenElseCt(
this, scaled_index, one, zero, target)));
1644 int64_t emin = std::numeric_limits<int64_t>::max();
1645 int64_t emax = std::numeric_limits<int64_t>::min();
1646 std::unique_ptr<IntVarIterator> iterator(
index->MakeDomainIterator(
false));
1648 if (index_value >= 0 && index_value <
size) {
1649 emin = std::min(emin, vars[index_value]->Min());
1650 emax = std::max(emax, vars[index_value]->Max());
1653 const std::string vname =
1654 size > 10 ? absl::StrFormat(
"ElementVar(var array of size %d, %s)",
size,
1655 index->DebugString())
1656 : absl::StrFormat(
"ElementVar([%s], %s)",
1658 IntVar*
const element_var = MakeIntVar(emin, emax, vname);
1660 RevAlloc(
new IntExprArrayElementCt(
this, vars,
index, element_var)));
1665 int64_t range_end,
IntVar* argument) {
1666 const std::string index_name =
1668 const std::string vname = absl::StrFormat(
1669 "ElementVar(%s, %s)",
1670 StringifyInt64ToIntVar(vars, range_start, range_end), index_name);
1671 IntVar*
const element_var =
1672 MakeIntVar(std::numeric_limits<int64_t>::min(),
1673 std::numeric_limits<int64_t>::max(), vname);
1674 IntExprEvaluatorElementCt* evaluation_ct =
new IntExprEvaluatorElementCt(
1675 this, std::move(vars), range_start, range_end, argument, element_var);
1676 AddConstraint(RevAlloc(evaluation_ct));
1677 evaluation_ct->Propagate();
1684 return MakeElementEqualityFunc(
this, vals,
index, target);
1697 std::vector<int64_t> values(vars.size());
1698 for (
int i = 0; i < vars.size(); ++i) {
1699 values[i] = vars[i]->Value();
1701 return MakeElementEquality(values,
index, target);
1703 if (
index->Bound()) {
1704 const int64_t val =
index->Min();
1705 if (val < 0 || val >= vars.size()) {
1706 return MakeFalseConstraint();
1708 return MakeEquality(target, vars[val]);
1711 if (target->
Bound()) {
1713 new IntExprArrayElementCstCt(
this, vars,
index, target->
Min()));
1715 return RevAlloc(
new IntExprArrayElementCt(
this, vars,
index, target));
1723 std::vector<int> valid_indices;
1724 for (
int i = 0; i < vars.size(); ++i) {
1725 if (vars[i]->Value() == target) {
1726 valid_indices.push_back(i);
1729 return MakeMemberCt(
index, valid_indices);
1731 if (
index->Bound()) {
1732 const int64_t pos =
index->Min();
1733 if (pos >= 0 && pos < vars.size()) {
1735 return MakeEquality(
var, target);
1737 return MakeFalseConstraint();
1740 return RevAlloc(
new IntExprArrayElementCstCt(
this, vars,
index, target));
1746 if (
index->Bound()) {
1747 const int64_t pos =
index->Min();
1748 if (pos >= 0 && pos < vars.size()) {
1750 return MakeEquality(
var, target);
1752 return MakeFalseConstraint();
1755 return RevAlloc(
new IntExprIndexOfCt(
this, vars,
index, target));
1761 IntExpr*
const cache = model_cache_->FindVarArrayConstantExpression(
1763 if (cache !=
nullptr) {
1764 return cache->
Var();
1766 const std::string
name =
1769 AddConstraint(MakeIndexOfConstraint(vars,
index,
value));
1770 model_cache_->InsertVarArrayConstantExpression(
const std::vector< IntVar * > vars_
-------— Generalized element -------—
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
IfThenElseCt(Solver *const solver, IntVar *const condition, IntExpr *const one, IntExpr *const zero, IntVar *const target)
std::string DebugString() const override
--------------— Constraint class ----------------—
void InitialPropagate() override
virtual void SetValue(int64_t v)
This method sets the value of the expression.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual void SetMax(int64_t m)=0
virtual void SetRange(int64_t l, int64_t u)
This method sets both the min and the max of the expression.
virtual int64_t Min() const =0
virtual void SetMin(int64_t m)=0
virtual void WhenRange(Demon *d)=0
Attach a demon that will watch the min or the max of the expression.
virtual IntVar * Var()=0
Creates a variable from the expression.
virtual int64_t Max() const =0
virtual void WhenBound(Demon *d)=0
virtual void WhenDomain(Demon *d)=0
virtual int64_t OldMax() const =0
Returns the previous max.
IntVar * Var() override
Creates a variable from the expression.
virtual bool Contains(int64_t v) const =0
virtual void RemoveValue(int64_t v)=0
This method removes the value 'v' from the domain of the variable.
virtual int64_t OldMin() const =0
Returns the previous min.
@ VAR_ARRAY_CONSTANT_INDEX
virtual std::string name() const
Object naming.
std::string DebugString() const override
For the time being, Solver is neither MT_SAFE nor MT_HOT.
IntExpr * MakeElement(const std::vector< int64_t > &values, IntVar *index)
values[index]
Constraint * MakeIfThenElseCt(IntVar *condition, IntExpr *then_expr, IntExpr *else_expr, IntVar *target_var)
Special cases with arrays of size two.
IntExpr * MakeMonotonicElement(IndexEvaluator1 values, bool increasing, IntVar *index)
Constraint * MakeElementEquality(const std::vector< int64_t > &vals, IntVar *index, IntVar *target)
Constraint * MakeIndexOfConstraint(const std::vector< IntVar * > &vars, IntVar *index, int64_t target)
IntExpr * MakeIndexExpression(const std::vector< IntVar * > &vars, int64_t value)
std::function< IntVar *(int64_t)> Int64ToIntVar
std::function< int64_t(int64_t)> IndexEvaluator1
Callback typedefs.
std::function< int64_t(int64_t, int64_t)> IndexEvaluator2
const std::string name
A name for logging purposes.
#define UPDATE_ELEMENT_INDEX_BOUNDS(test)
ABSL_FLAG(bool, cp_disable_element_cache, true, "If true, caching for IntElement is disabled.")
#define UPDATE_RMQ_BASE_ELEMENT_INDEX_BOUNDS(test)
std::pair< double, double > Range
A range of values, first is the minimum, second is the maximum.
In SWIG mode, we don't want anything besides these top-level includes.
bool IsArrayConstant(const std::vector< T > &values, const T &value)
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
Join v[i]->DebugString().
bool IsIncreasing(const std::vector< T > &values)
bool IsArrayBoolean(const std::vector< T > &values)
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
void LinkVarExpr(Solver *s, IntExpr *expr, IntVar *var)
--— IntExprElement --—
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
--— Vector manipulations --—
bool IsIncreasingContiguous(const std::vector< T > &values)
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
bool AreAllBound(const std::vector< IntVar * > &vars)
std::string JoinNamePtr(const std::vector< T > &v, absl::string_view separator)
Join v[i]->name().