21#include "absl/strings/str_format.h"
32class RangeEquality :
public Constraint {
34 RangeEquality(Solver*
const s, IntExpr*
const l, IntExpr*
const r)
35 : Constraint(s), left_(l), right_(r) {}
37 ~RangeEquality()
override {}
39 void Post()
override {
40 Demon*
const d = solver()->MakeConstraintInitialPropagateCallback(
this);
45 void InitialPropagate()
override {
46 left_->SetRange(right_->Min(), right_->Max());
47 right_->SetRange(left_->Min(), left_->Max());
50 std::string DebugString()
const override {
51 return left_->DebugString() +
" == " + right_->DebugString();
54 IntVar* Var()
override {
return solver()->MakeIsEqualVar(left_, right_); }
56 void Accept(ModelVisitor*
const visitor)
const override {
66 IntExpr*
const right_;
72class RangeLessOrEqual :
public Constraint {
74 RangeLessOrEqual(Solver* s, IntExpr* l, IntExpr* r);
75 ~RangeLessOrEqual()
override {}
77 void InitialPropagate()
override;
78 std::string DebugString()
const override;
79 IntVar* Var()
override {
80 return solver()->MakeIsLessOrEqualVar(left_, right_);
82 void Accept(ModelVisitor*
const visitor)
const override {
92 IntExpr*
const right_;
96RangeLessOrEqual::RangeLessOrEqual(Solver*
const s, IntExpr*
const l,
98 : Constraint(s), left_(l), right_(r), demon_(nullptr) {}
100void RangeLessOrEqual::Post() {
101 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
102 left_->WhenRange(demon_);
103 right_->WhenRange(demon_);
106void RangeLessOrEqual::InitialPropagate() {
107 left_->SetMax(right_->Max());
108 right_->SetMin(left_->Min());
109 if (left_->Max() <= right_->Min()) {
110 demon_->inhibit(solver());
114std::string RangeLessOrEqual::DebugString()
const {
115 return left_->DebugString() +
" <= " + right_->DebugString();
121class RangeLess :
public Constraint {
123 RangeLess(Solver* s, IntExpr* l, IntExpr* r);
124 ~RangeLess()
override {}
125 void Post()
override;
126 void InitialPropagate()
override;
127 std::string DebugString()
const override;
128 IntVar* Var()
override {
return solver()->MakeIsLessVar(left_, right_); }
129 void Accept(ModelVisitor*
const visitor)
const override {
130 visitor->BeginVisitConstraint(ModelVisitor::kLess,
this);
131 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
132 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
134 visitor->EndVisitConstraint(ModelVisitor::kLess,
this);
138 IntExpr*
const left_;
139 IntExpr*
const right_;
143RangeLess::RangeLess(Solver*
const s, IntExpr*
const l, IntExpr*
const r)
144 : Constraint(s), left_(l), right_(r), demon_(nullptr) {}
146void RangeLess::Post() {
147 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
148 left_->WhenRange(demon_);
149 right_->WhenRange(demon_);
152void RangeLess::InitialPropagate() {
153 if (right_->Max() ==
kint64min) solver()->Fail();
154 left_->SetMax(right_->Max() - 1);
155 if (left_->Min() ==
kint64max) solver()->Fail();
156 right_->SetMin(left_->Min() + 1);
157 if (left_->Max() < right_->Min()) {
158 demon_->inhibit(solver());
162std::string RangeLess::DebugString()
const {
163 return left_->DebugString() +
" < " + right_->DebugString();
169class DiffVar :
public Constraint {
171 DiffVar(Solver* s, IntVar* l, IntVar* r);
172 ~DiffVar()
override {}
173 void Post()
override;
174 void InitialPropagate()
override;
175 std::string DebugString()
const override;
176 IntVar* Var()
override {
return solver()->MakeIsDifferentVar(left_, right_); }
180 void Accept(ModelVisitor*
const visitor)
const override {
181 visitor->BeginVisitConstraint(ModelVisitor::kNonEqual,
this);
182 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
183 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
185 visitor->EndVisitConstraint(ModelVisitor::kNonEqual,
this);
190 IntVar*
const right_;
193DiffVar::DiffVar(Solver*
const s, IntVar*
const l, IntVar*
const r)
194 : Constraint(s), left_(l), right_(r) {}
196void DiffVar::Post() {
197 Demon*
const left_demon =
199 Demon*
const right_demon =
201 left_->WhenBound(left_demon);
202 right_->WhenBound(right_demon);
206void DiffVar::LeftBound() {
207 if (right_->Size() < 0xFFFFFF) {
208 right_->RemoveValue(left_->Min());
210 solver()->AddConstraint(solver()->MakeNonEquality(right_, left_->Min()));
214void DiffVar::RightBound() {
215 if (left_->Size() < 0xFFFFFF) {
216 left_->RemoveValue(right_->Min());
218 solver()->AddConstraint(solver()->MakeNonEquality(left_, right_->Min()));
222void DiffVar::InitialPropagate() {
223 if (left_->Bound()) {
226 if (right_->Bound()) {
231std::string DiffVar::DebugString()
const {
232 return left_->DebugString() +
" != " + right_->DebugString();
242class IsEqualCt :
public CastConstraint {
244 IsEqualCt(Solver*
const s, IntExpr*
const l, IntExpr*
const r,
246 : CastConstraint(s,
b), left_(l), right_(r), range_demon_(nullptr) {}
248 ~IsEqualCt()
override {}
250 void Post()
override {
251 range_demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
252 left_->WhenRange(range_demon_);
253 right_->WhenRange(range_demon_);
255 solver(),
this, &IsEqualCt::PropagateTarget,
"PropagateTarget");
256 target_var_->WhenBound(target_demon);
259 void InitialPropagate()
override {
260 if (target_var_->Bound()) {
264 if (left_->Min() > right_->Max() || left_->Max() < right_->Min()) {
265 target_var_->SetValue(0);
266 range_demon_->inhibit(solver());
267 }
else if (left_->Bound()) {
268 if (right_->Bound()) {
269 target_var_->SetValue(left_->Min() == right_->Min());
270 }
else if (right_->IsVar() && !right_->Var()->Contains(left_->Min())) {
271 range_demon_->inhibit(solver());
272 target_var_->SetValue(0);
274 }
else if (right_->Bound() && left_->IsVar() &&
275 !left_->Var()->Contains(right_->Min())) {
276 range_demon_->inhibit(solver());
277 target_var_->SetValue(0);
281 void PropagateTarget() {
282 if (target_var_->Min() == 0) {
283 if (left_->Bound()) {
284 range_demon_->inhibit(solver());
285 if (right_->IsVar()) {
286 right_->Var()->RemoveValue(left_->Min());
288 solver()->AddConstraint(
289 solver()->MakeNonEquality(right_, left_->Min()));
291 }
else if (right_->Bound()) {
292 range_demon_->inhibit(solver());
293 if (left_->IsVar()) {
294 left_->Var()->RemoveValue(right_->Min());
296 solver()->AddConstraint(
297 solver()->MakeNonEquality(left_, right_->Min()));
301 left_->SetRange(right_->Min(), right_->Max());
302 right_->SetRange(left_->Min(), left_->Max());
306 std::string DebugString()
const override {
307 return absl::StrFormat(
"IsEqualCt(%s, %s, %s)", left_->DebugString(),
308 right_->DebugString(), target_var_->DebugString());
311 void Accept(ModelVisitor*
const visitor)
const override {
312 visitor->BeginVisitConstraint(ModelVisitor::kIsEqual,
this);
313 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
314 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
316 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
318 visitor->EndVisitConstraint(ModelVisitor::kIsEqual,
this);
322 IntExpr*
const left_;
323 IntExpr*
const right_;
329class IsDifferentCt :
public CastConstraint {
331 IsDifferentCt(Solver*
const s, IntExpr*
const l, IntExpr*
const r,
333 : CastConstraint(s,
b), left_(l), right_(r), range_demon_(nullptr) {}
335 ~IsDifferentCt()
override {}
337 void Post()
override {
338 range_demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
339 left_->WhenRange(range_demon_);
340 right_->WhenRange(range_demon_);
342 solver(),
this, &IsDifferentCt::PropagateTarget,
"PropagateTarget");
343 target_var_->WhenBound(target_demon);
346 void InitialPropagate()
override {
347 if (target_var_->Bound()) {
351 if (left_->Min() > right_->Max() || left_->Max() < right_->Min()) {
352 target_var_->SetValue(1);
353 range_demon_->inhibit(solver());
354 }
else if (left_->Bound()) {
355 if (right_->Bound()) {
356 target_var_->SetValue(left_->Min() != right_->Min());
357 }
else if (right_->IsVar() && !right_->Var()->Contains(left_->Min())) {
358 range_demon_->inhibit(solver());
359 target_var_->SetValue(1);
361 }
else if (right_->Bound() && left_->IsVar() &&
362 !left_->Var()->Contains(right_->Min())) {
363 range_demon_->inhibit(solver());
364 target_var_->SetValue(1);
368 void PropagateTarget() {
369 if (target_var_->Min() == 0) {
370 left_->SetRange(right_->Min(), right_->Max());
371 right_->SetRange(left_->Min(), left_->Max());
373 if (left_->Bound()) {
374 range_demon_->inhibit(solver());
375 solver()->AddConstraint(
376 solver()->MakeNonEquality(right_, left_->Min()));
377 }
else if (right_->Bound()) {
378 range_demon_->inhibit(solver());
379 solver()->AddConstraint(
380 solver()->MakeNonEquality(left_, right_->Min()));
385 std::string DebugString()
const override {
386 return absl::StrFormat(
"IsDifferentCt(%s, %s, %s)", left_->DebugString(),
387 right_->DebugString(), target_var_->DebugString());
390 void Accept(ModelVisitor*
const visitor)
const override {
391 visitor->BeginVisitConstraint(ModelVisitor::kIsDifferent,
this);
392 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
393 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
395 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
397 visitor->EndVisitConstraint(ModelVisitor::kIsDifferent,
this);
401 IntExpr*
const left_;
402 IntExpr*
const right_;
406class IsLessOrEqualCt :
public CastConstraint {
408 IsLessOrEqualCt(Solver*
const s, IntExpr*
const l, IntExpr*
const r,
410 : CastConstraint(s,
b), left_(l), right_(r), demon_(nullptr) {}
412 ~IsLessOrEqualCt()
override {}
414 void Post()
override {
415 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
416 left_->WhenRange(demon_);
417 right_->WhenRange(demon_);
418 target_var_->WhenBound(demon_);
421 void InitialPropagate()
override {
422 if (target_var_->Bound()) {
423 if (target_var_->Min() == 0) {
424 right_->SetMax(left_->Max() - 1);
425 left_->SetMin(right_->Min() + 1);
427 right_->SetMin(left_->Min());
428 left_->SetMax(right_->Max());
430 }
else if (right_->Min() >= left_->Max()) {
431 demon_->inhibit(solver());
432 target_var_->SetValue(1);
433 }
else if (right_->Max() < left_->Min()) {
434 demon_->inhibit(solver());
435 target_var_->SetValue(0);
439 std::string DebugString()
const override {
440 return absl::StrFormat(
"IsLessOrEqualCt(%s, %s, %s)", left_->DebugString(),
441 right_->DebugString(), target_var_->DebugString());
444 void Accept(ModelVisitor*
const visitor)
const override {
445 visitor->BeginVisitConstraint(ModelVisitor::kIsLessOrEqual,
this);
446 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
447 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
449 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
451 visitor->EndVisitConstraint(ModelVisitor::kIsLessOrEqual,
this);
455 IntExpr*
const left_;
456 IntExpr*
const right_;
460class IsLessCt :
public CastConstraint {
462 IsLessCt(Solver*
const s, IntExpr*
const l, IntExpr*
const r, IntVar*
const b)
463 : CastConstraint(s,
b), left_(l), right_(r), demon_(nullptr) {}
465 ~IsLessCt()
override {}
467 void Post()
override {
468 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
469 left_->WhenRange(demon_);
470 right_->WhenRange(demon_);
471 target_var_->WhenBound(demon_);
474 void InitialPropagate()
override {
475 if (target_var_->Bound()) {
476 if (target_var_->Min() == 0) {
477 right_->SetMax(left_->Max());
478 left_->SetMin(right_->Min());
480 right_->SetMin(left_->Min() + 1);
481 left_->SetMax(right_->Max() - 1);
483 }
else if (right_->Min() > left_->Max()) {
484 demon_->inhibit(solver());
485 target_var_->SetValue(1);
486 }
else if (right_->Max() <= left_->Min()) {
487 demon_->inhibit(solver());
488 target_var_->SetValue(0);
492 std::string DebugString()
const override {
493 return absl::StrFormat(
"IsLessCt(%s, %s, %s)", left_->DebugString(),
494 right_->DebugString(), target_var_->DebugString());
497 void Accept(ModelVisitor*
const visitor)
const override {
498 visitor->BeginVisitConstraint(ModelVisitor::kIsLess,
this);
499 visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
500 visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
502 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
504 visitor->EndVisitConstraint(ModelVisitor::kIsLess,
this);
508 IntExpr*
const left_;
509 IntExpr*
const right_;
514Constraint* Solver::MakeEquality(IntExpr*
const l, IntExpr*
const r) {
515 CHECK(l !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
516 CHECK(r !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
517 CHECK_EQ(
this, l->solver());
518 CHECK_EQ(
this, r->solver());
520 return MakeEquality(r, l->Min());
521 }
else if (r->Bound()) {
522 return MakeEquality(l, r->Min());
524 return RevAlloc(
new RangeEquality(
this, l, r));
528Constraint* Solver::MakeLessOrEqual(IntExpr*
const l, IntExpr*
const r) {
529 CHECK(l !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
530 CHECK(r !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
531 CHECK_EQ(
this, l->solver());
532 CHECK_EQ(
this, r->solver());
534 return MakeTrueConstraint();
535 }
else if (l->Bound()) {
536 return MakeGreaterOrEqual(r, l->Min());
537 }
else if (r->Bound()) {
538 return MakeLessOrEqual(l, r->Min());
540 return RevAlloc(
new RangeLessOrEqual(
this, l, r));
544Constraint* Solver::MakeGreaterOrEqual(IntExpr*
const l, IntExpr*
const r) {
545 return MakeLessOrEqual(r, l);
549 CHECK(l !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
550 CHECK(r !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
551 CHECK_EQ(
this, l->
solver());
554 return MakeGreater(r, l->
Min());
555 }
else if (r->
Bound()) {
556 return MakeLess(l, r->
Min());
558 return RevAlloc(
new RangeLess(
this, l, r));
562Constraint* Solver::MakeGreater(IntExpr*
const l, IntExpr*
const r) {
563 return MakeLess(r, l);
567 CHECK(l !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
568 CHECK(r !=
nullptr) <<
"left expression nullptr, maybe a bad cast";
569 CHECK_EQ(
this, l->
solver());
572 return MakeNonEquality(r, l->
Min());
573 }
else if (r->
Bound()) {
574 return MakeNonEquality(l, r->
Min());
576 return RevAlloc(
new DiffVar(
this, l->
Var(), r->
Var()));
579IntVar* Solver::MakeIsEqualVar(IntExpr*
const v1, IntExpr*
const v2) {
580 CHECK_EQ(
this, v1->solver());
581 CHECK_EQ(
this, v2->solver());
583 return MakeIsEqualCstVar(v2, v1->Min());
584 }
else if (v2->Bound()) {
585 return MakeIsEqualCstVar(v1, v2->Min());
587 IntExpr* cache = model_cache_->FindExprExprExpression(
588 v1, v2, ModelCache::EXPR_EXPR_IS_EQUAL);
589 if (cache ==
nullptr) {
590 cache = model_cache_->FindExprExprExpression(
591 v2, v1, ModelCache::EXPR_EXPR_IS_EQUAL);
593 if (cache !=
nullptr) {
596 IntVar* boolvar =
nullptr;
597 IntExpr* reverse_cache = model_cache_->FindExprExprExpression(
598 v1, v2, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
599 if (reverse_cache ==
nullptr) {
600 reverse_cache = model_cache_->FindExprExprExpression(
601 v2, v1, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
603 if (reverse_cache !=
nullptr) {
604 boolvar = MakeDifference(1, reverse_cache)->Var();
606 std::string name1 = v1->name();
608 name1 = v1->DebugString();
610 std::string name2 = v2->name();
612 name2 = v2->DebugString();
615 MakeBoolVar(absl::StrFormat(
"IsEqualVar(%s, %s)", name1, name2));
616 AddConstraint(MakeIsEqualCt(v1, v2, boolvar));
617 model_cache_->InsertExprExprExpression(boolvar, v1, v2,
618 ModelCache::EXPR_EXPR_IS_EQUAL);
624Constraint* Solver::MakeIsEqualCt(IntExpr*
const v1, IntExpr*
const v2,
626 CHECK_EQ(
this, v1->solver());
627 CHECK_EQ(
this, v2->solver());
629 return MakeIsEqualCstCt(v2, v1->Min(),
b);
630 }
else if (v2->Bound()) {
631 return MakeIsEqualCstCt(v1, v2->Min(),
b);
635 return MakeNonEquality(v1, v2);
637 return MakeEquality(v1, v2);
640 return RevAlloc(
new IsEqualCt(
this, v1, v2,
b));
643IntVar* Solver::MakeIsDifferentVar(IntExpr*
const v1, IntExpr*
const v2) {
644 CHECK_EQ(
this, v1->solver());
645 CHECK_EQ(
this, v2->solver());
647 return MakeIsDifferentCstVar(v2, v1->Min());
648 }
else if (v2->Bound()) {
649 return MakeIsDifferentCstVar(v1, v2->Min());
651 IntExpr* cache = model_cache_->FindExprExprExpression(
652 v1, v2, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
653 if (cache ==
nullptr) {
654 cache = model_cache_->FindExprExprExpression(
655 v2, v1, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
657 if (cache !=
nullptr) {
660 IntVar* boolvar =
nullptr;
661 IntExpr* reverse_cache = model_cache_->FindExprExprExpression(
662 v1, v2, ModelCache::EXPR_EXPR_IS_EQUAL);
663 if (reverse_cache ==
nullptr) {
664 reverse_cache = model_cache_->FindExprExprExpression(
665 v2, v1, ModelCache::EXPR_EXPR_IS_EQUAL);
667 if (reverse_cache !=
nullptr) {
668 boolvar = MakeDifference(1, reverse_cache)->Var();
670 std::string name1 = v1->name();
672 name1 = v1->DebugString();
674 std::string name2 = v2->name();
676 name2 = v2->DebugString();
679 MakeBoolVar(absl::StrFormat(
"IsDifferentVar(%s, %s)", name1, name2));
680 AddConstraint(MakeIsDifferentCt(v1, v2, boolvar));
682 model_cache_->InsertExprExprExpression(boolvar, v1, v2,
683 ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
688Constraint* Solver::MakeIsDifferentCt(IntExpr*
const v1, IntExpr*
const v2,
690 CHECK_EQ(
this, v1->solver());
691 CHECK_EQ(
this, v2->solver());
693 return MakeIsDifferentCstCt(v2, v1->Min(),
b);
694 }
else if (v2->Bound()) {
695 return MakeIsDifferentCstCt(v1, v2->Min(),
b);
697 return RevAlloc(
new IsDifferentCt(
this, v1, v2,
b));
700IntVar* Solver::MakeIsLessOrEqualVar(IntExpr*
const left,
701 IntExpr*
const right) {
702 CHECK_EQ(
this, left->solver());
703 CHECK_EQ(
this, right->solver());
705 return MakeIsGreaterOrEqualCstVar(right, left->Min());
706 }
else if (right->Bound()) {
707 return MakeIsLessOrEqualCstVar(left, right->Min());
709 IntExpr*
const cache = model_cache_->FindExprExprExpression(
710 left, right, ModelCache::EXPR_EXPR_IS_LESS_OR_EQUAL);
711 if (cache !=
nullptr) {
714 std::string name1 = left->name();
716 name1 = left->DebugString();
718 std::string name2 = right->name();
720 name2 = right->DebugString();
722 IntVar*
const boolvar =
723 MakeBoolVar(absl::StrFormat(
"IsLessOrEqual(%s, %s)", name1, name2));
725 AddConstraint(RevAlloc(
new IsLessOrEqualCt(
this, left, right, boolvar)));
726 model_cache_->InsertExprExprExpression(
727 boolvar, left, right, ModelCache::EXPR_EXPR_IS_LESS_OR_EQUAL);
732Constraint* Solver::MakeIsLessOrEqualCt(IntExpr*
const left,
733 IntExpr*
const right, IntVar*
const b) {
734 CHECK_EQ(
this, left->solver());
735 CHECK_EQ(
this, right->solver());
737 return MakeIsGreaterOrEqualCstCt(right, left->Min(),
b);
738 }
else if (right->Bound()) {
739 return MakeIsLessOrEqualCstCt(left, right->Min(),
b);
741 return RevAlloc(
new IsLessOrEqualCt(
this, left, right,
b));
744IntVar* Solver::MakeIsLessVar(IntExpr*
const left, IntExpr*
const right) {
745 CHECK_EQ(
this, left->solver());
746 CHECK_EQ(
this, right->solver());
748 return MakeIsGreaterCstVar(right, left->Min());
749 }
else if (right->Bound()) {
750 return MakeIsLessCstVar(left, right->Min());
752 IntExpr*
const cache = model_cache_->FindExprExprExpression(
753 left, right, ModelCache::EXPR_EXPR_IS_LESS);
754 if (cache !=
nullptr) {
757 std::string name1 = left->name();
759 name1 = left->DebugString();
761 std::string name2 = right->name();
763 name2 = right->DebugString();
765 IntVar*
const boolvar =
766 MakeBoolVar(absl::StrFormat(
"IsLessOrEqual(%s, %s)", name1, name2));
768 AddConstraint(RevAlloc(
new IsLessCt(
this, left, right, boolvar)));
769 model_cache_->InsertExprExprExpression(boolvar, left, right,
770 ModelCache::EXPR_EXPR_IS_LESS);
775Constraint* Solver::MakeIsLessCt(IntExpr*
const left, IntExpr*
const right,
777 CHECK_EQ(
this, left->solver());
778 CHECK_EQ(
this, right->solver());
780 return MakeIsGreaterCstCt(right, left->Min(),
b);
781 }
else if (right->Bound()) {
782 return MakeIsLessCstCt(left, right->Min(),
b);
784 return RevAlloc(
new IsLessCt(
this, left, right,
b));
787IntVar* Solver::MakeIsGreaterOrEqualVar(IntExpr*
const left,
788 IntExpr*
const right) {
789 return MakeIsLessOrEqualVar(right, left);
795 return MakeIsLessOrEqualCt(right, left,
b);
799 return MakeIsLessVar(right, left);
804 return MakeIsLessCt(right, left,
b);
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual int64_t Min() const =0
virtual IntVar * Var()=0
Creates a variable from the expression.
static const char kLessOrEqual[]
static const char kRightArgument[]
static const char kEquality[]
static const char kLeftArgument[]
In SWIG mode, we don't want anything besides these top-level includes.
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
static const int64_t kint64max
static const int64_t kint64min