24#include "absl/strings/str_format.h"
25#include "absl/strings/str_join.h"
36 "Initial size of the array of the hash "
37 "table of caches for objects of type Var(x == 3)");
45class EqualityExprCst :
public Constraint {
47 EqualityExprCst(Solver*
const s, IntExpr*
const e, int64_t v);
48 ~EqualityExprCst()
override {}
50 void InitialPropagate()
override;
51 IntVar* Var()
override {
52 return solver()->MakeIsEqualCstVar(
expr_->Var(), value_);
54 std::string DebugString()
const override;
56 void Accept(ModelVisitor*
const visitor)
const override {
69EqualityExprCst::EqualityExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
70 : Constraint(s),
expr_(e), value_(v) {}
72void EqualityExprCst::Post() {
73 if (!
expr_->IsVar()) {
74 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
79void EqualityExprCst::InitialPropagate() {
expr_->SetValue(value_); }
81std::string EqualityExprCst::DebugString()
const {
82 return absl::StrFormat(
"(%s == %d)",
expr_->DebugString(), value_);
90 if (IsADifference(e, &left, &right)) {
91 return MakeEquality(left, MakeSum(right, v));
93 return MakeFalseConstraint();
94 }
else if (e->
Min() == e->
Max() && e->
Min() == v) {
95 return MakeTrueConstraint();
97 return RevAlloc(
new EqualityExprCst(
this, e, v));
105 if (IsADifference(e, &left, &right)) {
106 return MakeEquality(left, MakeSum(right, v));
108 return MakeFalseConstraint();
109 }
else if (e->
Min() == e->
Max() && e->
Min() == v) {
110 return MakeTrueConstraint();
112 return RevAlloc(
new EqualityExprCst(
this, e, v));
122 GreaterEqExprCst(
Solver*
const s,
IntExpr*
const e, int64_t v);
123 ~GreaterEqExprCst()
override {}
124 void Post()
override;
127 IntVar*
Var()
override {
131 void Accept(ModelVisitor*
const visitor)
const override {
132 visitor->BeginVisitConstraint(ModelVisitor::kGreaterOrEqual,
this);
133 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
135 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
136 visitor->EndVisitConstraint(ModelVisitor::kGreaterOrEqual,
this);
140 IntExpr*
const expr_;
145GreaterEqExprCst::GreaterEqExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
146 : Constraint(s),
expr_(e), value_(v), demon_(nullptr) {}
148void GreaterEqExprCst::Post() {
150 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
158void GreaterEqExprCst::InitialPropagate() {
160 if (demon_ !=
nullptr &&
expr_->
Min() >= value_) {
165std::string GreaterEqExprCst::DebugString()
const {
174 }
else if (e->
Max() < v) {
177 return RevAlloc(
new GreaterEqExprCst(
this, e, v));
185 }
else if (e->
Max() < v) {
188 return RevAlloc(
new GreaterEqExprCst(
this, e, v));
196 }
else if (e->
Max() <= v) {
199 return RevAlloc(
new GreaterEqExprCst(
this, e, v + 1));
207 }
else if (e->
Max() <= v) {
210 return RevAlloc(
new GreaterEqExprCst(
this, e, v + 1));
221 ~LessEqExprCst()
override {}
222 void Post()
override;
223 void InitialPropagate()
override;
224 std::string DebugString()
const override;
225 IntVar* Var()
override {
226 return solver()->MakeIsLessOrEqualCstVar(
expr_->Var(), value_);
228 void Accept(ModelVisitor*
const visitor)
const override {
237 IntExpr*
const expr_;
242LessEqExprCst::LessEqExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
243 : Constraint(s),
expr_(e), value_(v), demon_(nullptr) {}
245void LessEqExprCst::Post() {
247 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
255void LessEqExprCst::InitialPropagate() {
257 if (demon_ !=
nullptr &&
expr_->
Max() <= value_) {
262std::string LessEqExprCst::DebugString()
const {
271 }
else if (e->
Min() > v) {
274 return RevAlloc(
new LessEqExprCst(
this, e, v));
282 }
else if (e->
Min() > v) {
285 return RevAlloc(
new LessEqExprCst(
this, e, v));
293 }
else if (e->
Min() >= v) {
296 return RevAlloc(
new LessEqExprCst(
this, e, v - 1));
304 }
else if (e->
Min() >= v) {
307 return RevAlloc(
new LessEqExprCst(
this, e, v - 1));
318 ~DiffCst()
override {}
319 void Post()
override {}
320 void InitialPropagate()
override;
321 void BoundPropagate();
322 std::string DebugString()
const override;
323 IntVar* Var()
override {
324 return solver()->MakeIsDifferentCstVar(var_, value_);
326 void Accept(ModelVisitor*
const visitor)
const override {
335 bool HasLargeDomain(IntVar*
var);
342DiffCst::DiffCst(Solver*
const s, IntVar*
const var, int64_t
value)
343 : Constraint(s), var_(
var), value_(
value), demon_(nullptr) {}
345void DiffCst::InitialPropagate() {
346 if (HasLargeDomain(var_)) {
355void DiffCst::BoundPropagate() {
356 const int64_t var_min = var_->
Min();
357 const int64_t var_max = var_->
Max();
358 if (var_min > value_ || var_max < value_) {
360 }
else if (var_min == value_) {
362 }
else if (var_max == value_) {
364 }
else if (!HasLargeDomain(var_)) {
370std::string DiffCst::DebugString()
const {
371 return absl::StrFormat(
"(%s != %d)", var_->
DebugString(), value_);
374bool DiffCst::HasLargeDomain(IntVar*
var) {
383 if (IsADifference(e, &left, &right)) {
387 }
else if (e->
Bound() && e->
Min() == v) {
398 if (IsADifference(e, &left, &right)) {
402 }
else if (e->
Bound() && e->
Min() == v) {
415 void Post()
override {
416 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
417 var_->WhenDomain(demon_);
420 void InitialPropagate()
override {
421 bool inhibit = var_->Bound();
422 int64_t u = var_->Contains(
cst_);
423 int64_t l = inhibit ? u : 0;
427 if (var_->Size() <= 0xFFFFFF) {
428 var_->RemoveValue(
cst_);
432 var_->SetValue(
cst_);
437 demon_->inhibit(solver());
440 std::string DebugString()
const override {
441 return absl::StrFormat(
"IsEqualCstCt(%s, %d, %s)", var_->DebugString(),
445 void Accept(ModelVisitor*
const visitor)
const override {
465 if (IsADifference(
var, &left, &right)) {
503 if (boolvar->
Bound()) {
504 if (boolvar->
Min() == 0) {
512 model_cache_->InsertExprConstantExpression(
516 if (IsADifference(
var, &left, &right)) {
531 void Post()
override {
532 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
533 var_->WhenDomain(demon_);
537 void InitialPropagate()
override {
538 bool inhibit = var_->Bound();
539 int64_t l = 1 - var_->Contains(
cst_);
540 int64_t u = inhibit ? l : 1;
544 if (var_->Size() <= 0xFFFFFF) {
545 var_->RemoveValue(
cst_);
549 var_->SetValue(
cst_);
554 demon_->inhibit(solver());
558 std::string DebugString()
const override {
559 return absl::StrFormat(
"IsDiffCstCt(%s, %d, %s)", var_->DebugString(),
cst_,
563 void Accept(ModelVisitor*
const visitor)
const override {
583 if (IsADifference(
var, &left, &right)) {
586 return var->Var()->IsDifferent(
value);
599 if (
var->IsVar() && !
var->Var()->Contains(
value)) {
605 if (boolvar->
Bound()) {
606 if (boolvar->
Min() == 0) {
612 model_cache_->InsertExprConstantExpression(
616 if (IsADifference(
var, &left, &right)) {
628 IsGreaterEqualCstCt(
Solver*
const s,
IntExpr*
const v, int64_t c,
631 void Post()
override {
632 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
633 expr_->WhenRange(demon_);
636 void InitialPropagate()
override {
637 bool inhibit =
false;
653 demon_->inhibit(solver());
656 std::string DebugString()
const override {
657 return absl::StrFormat(
"IsGreaterEqualCstCt(%s, %d, %s)",
662 void Accept(ModelVisitor*
const visitor)
const override {
673 IntExpr*
const expr_;
687 return var->Var()->IsGreaterOrEqual(
value);
702 if (boolvar->
Bound()) {
703 if (boolvar->
Min() == 0) {
711 model_cache_->InsertExprConstantExpression(
726 IsLessEqualCstCt(
Solver*
const s,
IntExpr*
const v, int64_t c,
730 void Post()
override {
731 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
732 expr_->WhenRange(demon_);
736 void InitialPropagate()
override {
737 bool inhibit =
false;
753 demon_->inhibit(solver());
757 std::string DebugString()
const override {
758 return absl::StrFormat(
"IsLessEqualCstCt(%s, %d, %s)",
expr_->DebugString(),
762 void Accept(ModelVisitor*
const visitor)
const override {
773 IntExpr*
const expr_;
787 return var->Var()->IsLessOrEqual(
value);
802 if (boolvar->
Bound()) {
803 if (boolvar->
Min() == 0) {
811 model_cache_->InsertExprConstantExpression(
826 BetweenCt(
Solver*
const s,
IntExpr*
const v, int64_t l, int64_t u)
829 void Post()
override {
830 if (!
expr_->IsVar()) {
831 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
832 expr_->WhenRange(demon_);
836 void InitialPropagate()
override {
837 expr_->SetRange(min_, max_);
840 expr_->Range(&emin, &emax);
841 if (demon_ !=
nullptr && emin >= min_ && emax <= max_) {
842 demon_->inhibit(solver());
846 std::string DebugString()
const override {
847 return absl::StrFormat(
"BetweenCt(%s, %d, %d)",
expr_->DebugString(), min_,
851 void Accept(ModelVisitor*
const visitor)
const override {
861 IntExpr*
const expr_;
869class NotBetweenCt :
public Constraint {
871 NotBetweenCt(Solver*
const s, IntExpr*
const v, int64_t l, int64_t u)
872 : Constraint(s),
expr_(v), min_(l), max_(u), demon_(nullptr) {}
874 void Post()
override {
875 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
876 expr_->WhenRange(demon_);
879 void InitialPropagate()
override {
882 expr_->Range(&emin, &emax);
884 expr_->SetMin(max_ + 1);
885 }
else if (emax <= max_) {
886 expr_->SetMax(min_ - 1);
889 if (!
expr_->IsVar() && (emax < min_ || emin > max_)) {
890 demon_->inhibit(solver());
894 std::string DebugString()
const override {
895 return absl::StrFormat(
"NotBetweenCt(%s, %d, %d)",
expr_->DebugString(),
899 void Accept(ModelVisitor*
const visitor)
const override {
909 IntExpr*
const expr_;
915int64_t ExtractExprProductCoeff(IntExpr** expr) {
918 while ((*expr)->solver()->IsProduct(*expr, expr, &
coeff)) prod *=
coeff;
932 expr->
Range(&emin, &emax);
940 int64_t
coeff = ExtractExprProductCoeff(&expr);
952 return RevAlloc(
new BetweenCt(
this, expr, l, u));
965 expr->
Range(&emin, &emax);
971 if (emax <= u)
return MakeLess(expr, l);
974 return RevAlloc(
new NotBetweenCt(
this, expr, l, u));
982 IsBetweenCt(
Solver*
const s,
IntExpr*
const e, int64_t l, int64_t u,
991 void Post()
override {
992 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
993 expr_->WhenRange(demon_);
994 boolvar_->WhenBound(demon_);
997 void InitialPropagate()
override {
998 bool inhibit =
false;
1001 expr_->Range(&emin, &emax);
1002 int64_t u = 1 - (emin > max_ || emax < min_);
1003 int64_t l = emax <= max_ && emin >= min_;
1004 boolvar_->SetRange(l, u);
1005 if (boolvar_->Bound()) {
1007 if (boolvar_->Min() == 0) {
1008 if (
expr_->IsVar()) {
1009 expr_->Var()->RemoveInterval(min_, max_);
1011 }
else if (emin > min_) {
1012 expr_->SetMin(max_ + 1);
1013 }
else if (emax < max_) {
1014 expr_->SetMax(min_ - 1);
1017 expr_->SetRange(min_, max_);
1020 if (inhibit &&
expr_->IsVar()) {
1021 demon_->inhibit(solver());
1026 std::string DebugString()
const override {
1027 return absl::StrFormat(
"IsBetweenCt(%s, %d, %d, %s)",
expr_->DebugString(),
1028 min_, max_, boolvar_->DebugString());
1031 void Accept(ModelVisitor*
const visitor)
const override {
1043 IntExpr*
const expr_;
1046 IntVar*
const boolvar_;
1062 expr->
Range(&emin, &emax);
1070 int64_t
coeff = ExtractExprProductCoeff(&expr);
1083 return RevAlloc(
new IsBetweenCt(
this, expr, l, u,
b));
1103 const std::vector<int64_t>& sorted_values)
1104 :
Constraint(s), var_(v), values_(sorted_values) {
1109 void Post()
override {}
1111 void InitialPropagate()
override { var_->SetValues(values_); }
1113 std::string DebugString()
const override {
1114 return absl::StrFormat(
"Member(%s, %s)", var_->DebugString(),
1115 absl::StrJoin(values_,
", "));
1118 void Accept(ModelVisitor*
const visitor)
const override {
1128 const std::vector<int64_t> values_;
1131class NotMemberCt :
public Constraint {
1133 NotMemberCt(Solver*
const s, IntVar*
const v,
1134 const std::vector<int64_t>& sorted_values)
1135 : Constraint(s), var_(v), values_(sorted_values) {
1140 void Post()
override {}
1142 void InitialPropagate()
override { var_->RemoveValues(values_); }
1144 std::string DebugString()
const override {
1145 return absl::StrFormat(
"NotMember(%s, %s)", var_->DebugString(),
1146 absl::StrJoin(values_,
", "));
1149 void Accept(ModelVisitor*
const visitor)
const override {
1159 const std::vector<int64_t> values_;
1164 const std::vector<int64_t>& values) {
1165 const int64_t
coeff = ExtractExprProductCoeff(&expr);
1167 return std::find(values.begin(), values.end(), 0) == values.end()
1171 std::vector<int64_t> copied_values = values;
1176 for (
const int64_t v : copied_values) {
1177 if (v %
coeff == 0) copied_values[num_kept++] = v /
coeff;
1179 copied_values.resize(num_kept);
1185 expr->
Range(&emin, &emax);
1186 for (
const int64_t v : copied_values) {
1187 if (v >= emin && v <= emax) copied_values[num_kept++] = v;
1189 copied_values.resize(num_kept);
1195 if (copied_values.size() == 1)
return MakeEquality(expr, copied_values[0]);
1197 if (copied_values.size() ==
1198 copied_values.back() - copied_values.front() + 1) {
1200 return MakeBetweenCt(expr, copied_values.front(), copied_values.back());
1205 if (emax - emin < 2 * copied_values.size()) {
1207 std::vector<bool> is_among_input_values(emax - emin + 1,
false);
1208 for (
const int64_t v : copied_values)
1209 is_among_input_values[v - emin] =
true;
1212 copied_values.clear();
1213 for (int64_t v_off = 0; v_off < is_among_input_values.size(); ++v_off) {
1214 if (!is_among_input_values[v_off]) copied_values.push_back(v_off + emin);
1219 if (copied_values.size() == 1) {
1222 return RevAlloc(
new NotMemberCt(
this, expr->
Var(), copied_values));
1225 return RevAlloc(
new MemberCt(
this, expr->
Var(), copied_values));
1229 const std::vector<int>& values) {
1234 const std::vector<int64_t>& values) {
1235 const int64_t
coeff = ExtractExprProductCoeff(&expr);
1237 return std::find(values.begin(), values.end(), 0) == values.end()
1241 std::vector<int64_t> copied_values = values;
1246 for (
const int64_t v : copied_values) {
1247 if (v %
coeff == 0) copied_values[num_kept++] = v /
coeff;
1249 copied_values.resize(num_kept);
1255 expr->
Range(&emin, &emax);
1256 for (
const int64_t v : copied_values) {
1257 if (v >= emin && v <= emax) copied_values[num_kept++] = v;
1259 copied_values.resize(num_kept);
1265 if (copied_values.size() == 1)
return MakeNonEquality(expr, copied_values[0]);
1267 if (copied_values.size() ==
1268 copied_values.back() - copied_values.front() + 1) {
1269 return MakeNotBetweenCt(expr, copied_values.front(), copied_values.back());
1274 if (emax - emin < 2 * copied_values.size()) {
1276 std::vector<bool> is_among_input_values(emax - emin + 1,
false);
1277 for (
const int64_t v : copied_values)
1278 is_among_input_values[v - emin] =
true;
1281 copied_values.clear();
1282 for (int64_t v_off = 0; v_off < is_among_input_values.size(); ++v_off) {
1283 if (!is_among_input_values[v_off]) copied_values.push_back(v_off + emin);
1288 if (copied_values.size() == 1) {
1291 return RevAlloc(
new MemberCt(
this, expr->
Var(), copied_values));
1294 return RevAlloc(
new NotMemberCt(
this, expr->
Var(), copied_values));
1298 const std::vector<int>& values) {
1308 const std::vector<int64_t>& sorted_values,
IntVar*
const b)
1311 values_as_set_(sorted_values.begin(), sorted_values.
end()),
1312 values_(sorted_values),
1316 domain_(var_->MakeDomainIterator(true)),
1317 neg_support_(
std::numeric_limits<int64_t>::
min()) {
1321 while (values_as_set_.contains(neg_support_)) {
1326 void Post()
override {
1329 if (!var_->Bound()) {
1330 var_->WhenDomain(demon_);
1332 if (!boolvar_->Bound()) {
1334 solver(),
this, &IsMemberCt::TargetBound,
"TargetBound");
1335 boolvar_->WhenBound(bdemon);
1339 void InitialPropagate()
override {
1340 boolvar_->SetRange(0, 1);
1341 if (boolvar_->Bound()) {
1348 std::string DebugString()
const override {
1349 return absl::StrFormat(
"IsMemberCt(%s, %s, %s)", var_->DebugString(),
1350 absl::StrJoin(values_,
", "),
1351 boolvar_->DebugString());
1354 void Accept(ModelVisitor*
const visitor)
const override {
1366 if (boolvar_->Bound()) {
1369 for (
int offset = 0; offset < values_.size(); ++offset) {
1370 const int candidate = (support_ + offset) % values_.size();
1371 if (var_->Contains(values_[candidate])) {
1372 support_ = candidate;
1373 if (var_->Bound()) {
1374 demon_->inhibit(solver());
1375 boolvar_->SetValue(1);
1380 if (var_->Contains(neg_support_)) {
1384 for (
const int64_t
value : InitAndGetValues(domain_)) {
1385 if (!values_as_set_.contains(
value)) {
1386 neg_support_ =
value;
1392 demon_->inhibit(solver());
1393 boolvar_->SetValue(1);
1398 demon_->inhibit(solver());
1399 boolvar_->SetValue(0);
1403 void TargetBound() {
1404 DCHECK(boolvar_->Bound());
1405 if (boolvar_->Min() == 1LL) {
1406 demon_->inhibit(solver());
1407 var_->SetValues(values_);
1409 demon_->inhibit(solver());
1410 var_->RemoveValues(values_);
1415 absl::flat_hash_set<int64_t> values_as_set_;
1416 std::vector<int64_t> values_;
1417 IntVar*
const boolvar_;
1420 IntVarIterator*
const domain_;
1421 int64_t neg_support_;
1425Constraint* BuildIsMemberCt(Solver*
const solver, IntExpr*
const expr,
1426 const std::vector<T>& values,
1427 IntVar*
const boolvar) {
1430 IntExpr* sub =
nullptr;
1432 if (solver->IsProduct(expr, &sub, &
coef) &&
coef != 0 &&
coef != 1) {
1433 std::vector<int64_t> new_values;
1434 new_values.reserve(values.size());
1435 for (
const int64_t
value : values) {
1440 return BuildIsMemberCt(solver, sub, new_values, boolvar);
1443 std::set<T> set_of_values(values.begin(), values.end());
1444 std::vector<int64_t> filtered_values;
1445 bool all_values =
false;
1446 if (expr->IsVar()) {
1447 IntVar*
const var = expr->
Var();
1448 for (
const T
value : set_of_values) {
1450 filtered_values.push_back(
value);
1453 all_values = (filtered_values.size() ==
var->
Size());
1457 expr->
Range(&emin, &emax);
1458 for (
const T
value : set_of_values) {
1460 filtered_values.push_back(
value);
1463 all_values = (filtered_values.size() == emax - emin + 1);
1465 if (filtered_values.empty()) {
1466 return solver->MakeEquality(boolvar,
Zero());
1467 }
else if (all_values) {
1468 return solver->MakeEquality(boolvar, 1);
1469 }
else if (filtered_values.size() == 1) {
1470 return solver->MakeIsEqualCstCt(expr, filtered_values.back(), boolvar);
1471 }
else if (filtered_values.back() ==
1472 filtered_values.front() + filtered_values.size() - 1) {
1474 return solver->MakeIsBetweenCt(expr, filtered_values.front(),
1475 filtered_values.back(), boolvar);
1477 return solver->RevAlloc(
1478 new IsMemberCt(solver, expr->Var(), filtered_values, boolvar));
1484 const std::vector<int64_t>& values,
1486 return BuildIsMemberCt(
this, expr, values, boolvar);
1490 const std::vector<int>& values,
1492 return BuildIsMemberCt(
this, expr, values, boolvar);
1496 const std::vector<int64_t>& values) {
1503 const std::vector<int>& values) {
1510class SortedDisjointForbiddenIntervalsConstraint :
public Constraint {
1512 SortedDisjointForbiddenIntervalsConstraint(
1517 ~SortedDisjointForbiddenIntervalsConstraint()
override {}
1519 void Post()
override {
1520 Demon*
const demon = solver()->MakeConstraintInitialPropagateCallback(
this);
1521 var_->WhenRange(demon);
1524 void InitialPropagate()
override {
1525 const int64_t vmin = var_->Min();
1526 const int64_t vmax = var_->Max();
1527 const auto first_interval_it = intervals_.FirstIntervalGreaterOrEqual(vmin);
1528 if (first_interval_it == intervals_.end()) {
1532 const auto last_interval_it = intervals_.LastIntervalLessOrEqual(vmax);
1533 if (last_interval_it == intervals_.end()) {
1539 if (vmin >= first_interval_it->start) {
1542 var_->SetMin(
CapAdd(first_interval_it->end, 1));
1544 if (vmax <= last_interval_it->
end) {
1546 var_->SetMax(
CapSub(last_interval_it->start, 1));
1550 std::string DebugString()
const override {
1551 return absl::StrFormat(
"ForbiddenIntervalCt(%s, %s)", var_->DebugString(),
1552 intervals_.DebugString());
1555 void Accept(ModelVisitor*
const visitor)
const override {
1559 std::vector<int64_t> starts;
1560 std::vector<int64_t> ends;
1561 for (
auto&
interval : intervals_) {
1572 const SortedDisjointIntervalList intervals_;
1577 std::vector<int64_t> starts,
1578 std::vector<int64_t> ends) {
1579 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1580 this, expr->
Var(), {starts, ends}));
1584 std::vector<int> starts,
1585 std::vector<int> ends) {
1586 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1587 this, expr->
Var(), {starts, ends}));
1592 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1593 this, expr->
Var(), std::move(intervals)));
#define CHECK_EQ(val1, val2)
#define DCHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
Cast constraints are special channeling constraints designed to keep a variable in sync with an expre...
A constraint is the main modeling object.
virtual void InitialPropagate()=0
This method performs the initial propagation of the constraint.
virtual void Accept(ModelVisitor *const visitor) const
Accepts the given visitor.
virtual IntVar * Var()
Creates a Boolean variable representing the status of the constraint (false = constraint is violated,...
std::string DebugString() const override
virtual void Post()=0
This method is called when the constraint is processed by the solver.
void inhibit(Solver *const s)
This method inhibits the demon in the search tree below the current position.
The class IntExpr is the base of all integer expressions in constraint programming.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual bool IsVar() const
Returns true if the expression is indeed a variable.
virtual int64_t Min() const =0
virtual void SetMax(int64_t m)=0
virtual IntVar * Var()=0
Creates a variable from the expression.
virtual void SetMin(int64_t m)=0
virtual int64_t Max() const =0
virtual void Range(int64_t *l, int64_t *u)
By default calls Min() and Max(), but can be redefined when Min and Max code can be factorized.
virtual void WhenRange(Demon *d)=0
Attach a demon that will watch the min or the max of the expression.
The class IntVar is a subset of IntExpr.
virtual bool Contains(int64_t v) const =0
This method returns whether the value 'v' is in the domain of the variable.
virtual void RemoveValue(int64_t v)=0
This method removes the value 'v' from the domain of the variable.
IntVar * Var() override
Creates a variable from the expression.
bool IsVar() const override
Returns true if the expression is indeed a variable.
virtual uint64_t Size() const =0
This method returns the number of values in the domain of the variable.
@ EXPR_CONSTANT_IS_GREATER_OR_EQUAL
@ EXPR_CONSTANT_IS_NOT_EQUAL
@ EXPR_CONSTANT_IS_LESS_OR_EQUAL
static const char kIsMember[]
static const char kMinArgument[]
static const char kEndsArgument[]
static const char kMember[]
static const char kIsBetween[]
static const char kTargetArgument[]
static const char kMaxArgument[]
static const char kBetween[]
static const char kLessOrEqual[]
static const char kValueArgument[]
static const char kIsDifferent[]
static const char kIsGreaterOrEqual[]
static const char kIsLessOrEqual[]
static const char kNotMember[]
static const char kStartsArgument[]
static const char kExpressionArgument[]
static const char kNotBetween[]
static const char kValuesArgument[]
static const char kEquality[]
static const char kNonEqual[]
static const char kIsEqual[]
std::string DebugString() const override
Constraint * MakeBetweenCt(IntExpr *const expr, int64_t l, int64_t u)
(l <= expr <= u)
Constraint * MakeIsLessCstCt(IntExpr *const v, int64_t c, IntVar *const b)
b == (v < c)
IntVar * MakeIsGreaterCstVar(IntExpr *const var, int64_t value)
status var of (var > value)
Constraint * MakeLess(IntExpr *const left, IntExpr *const right)
left < right
Constraint * MakeFalseConstraint()
This constraint always fails.
Constraint * MakeEquality(IntExpr *const left, IntExpr *const right)
left == right
Constraint * MakeIsDifferentCt(IntExpr *const v1, IntExpr *const v2, IntVar *const b)
b == (v1 != v2)
Constraint * MakeLessOrEqual(IntExpr *const left, IntExpr *const right)
left <= right
IntVar * MakeIsGreaterOrEqualCstVar(IntExpr *const var, int64_t value)
status var of (var >= value)
Constraint * MakeIsLessOrEqualCstCt(IntExpr *const var, int64_t value, IntVar *const boolvar)
boolvar == (var <= value)
Constraint * MakeNotMemberCt(IntExpr *const expr, const std::vector< int64_t > &values)
expr not in set.
IntVar * MakeIsDifferentVar(IntExpr *const v1, IntExpr *const v2)
status var of (v1 != v2)
IntVar * MakeIsEqualVar(IntExpr *const v1, IntExpr *v2)
status var of (v1 == v2)
Constraint * MakeGreater(IntExpr *const left, IntExpr *const right)
left > right
IntVar * MakeIsLessCstVar(IntExpr *const var, int64_t value)
status var of (var < value)
Constraint * MakeMemberCt(IntExpr *const expr, const std::vector< int64_t > &values)
expr in set.
Constraint * MakeNotBetweenCt(IntExpr *const expr, int64_t l, int64_t u)
(expr < l || expr > u) This constraint is lazy as it will not make holes in the domain of variables.
void AddConstraint(Constraint *const c)
Adds the constraint 'c' to the model.
Constraint * MakeIsEqualCstCt(IntExpr *const var, int64_t value, IntVar *const boolvar)
boolvar == (var == value)
Constraint * MakeIsEqualCt(IntExpr *const v1, IntExpr *v2, IntVar *const b)
b == (v1 == v2)
Constraint * MakeTrueConstraint()
This constraint always succeeds.
IntVar * MakeIsBetweenVar(IntExpr *const v, int64_t l, int64_t u)
IntVar * MakeIsMemberVar(IntExpr *const expr, const std::vector< int64_t > &values)
IntVar * MakeIsLessOrEqualCstVar(IntExpr *const var, int64_t value)
status var of (var <= value)
IntExpr * MakeDifference(IntExpr *const left, IntExpr *const right)
left - right
Constraint * MakeIsDifferentCstCt(IntExpr *const var, int64_t value, IntVar *const boolvar)
boolvar == (var != value)
IntVar * MakeBoolVar()
MakeBoolVar will create a variable with a {0, 1} domain.
IntVar * MakeIsDifferentCstVar(IntExpr *const var, int64_t value)
status var of (var != value)
Constraint * MakeNonEquality(IntExpr *const left, IntExpr *const right)
left != right
Constraint * MakeIsGreaterOrEqualCstCt(IntExpr *const var, int64_t value, IntVar *const boolvar)
boolvar == (var >= value)
Constraint * MakeIsBetweenCt(IntExpr *const expr, int64_t l, int64_t u, IntVar *const b)
b == (l <= expr <= u)
IntExpr * MakeSum(IntExpr *const left, IntExpr *const right)
left + right.
Constraint * MakeIsGreaterCstCt(IntExpr *const v, int64_t c, IntVar *const b)
b == (v > c)
IntVar * MakeIntConst(int64_t val, const std::string &name)
IntConst will create a constant expression.
Constraint * MakeGreaterOrEqual(IntExpr *const left, IntExpr *const right)
left >= right
IntVar * MakeIsEqualCstVar(IntExpr *const var, int64_t value)
status var of (var == value)
Constraint * MakeIsMemberCt(IntExpr *const expr, const std::vector< int64_t > &values, IntVar *const boolvar)
boolvar == (expr in set)
T * RevAlloc(T *object)
Registers the given object as being reversible.
This class represents a sorted list of disjoint, closed intervals.
ABSL_FLAG(int, cache_initial_size, 1024, "Initial size of the array of the hash " "table of caches for objects of type Var(x == 3)")
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Collection of objects used to extend the Constraint Solver library.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapSub(int64_t x, int64_t y)
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)
int64_t PosIntDivDown(int64_t e, int64_t v)
int64_t PosIntDivUp(int64_t e, int64_t v)
IntervalVar *const target_var_
std::optional< int64_t > end