26 #include "absl/strings/str_format.h"
27 #include "absl/strings/str_join.h"
38 "Initial size of the array of the hash "
39 "table of caches for objects of type Var(x == 3)");
47 class EqualityExprCst :
public Constraint {
49 EqualityExprCst(Solver*
const s, IntExpr*
const e, int64_t v);
50 ~EqualityExprCst()
override {}
52 void InitialPropagate()
override;
53 IntVar* Var()
override {
54 return solver()->MakeIsEqualCstVar(
expr_->Var(), value_);
56 std::string DebugString()
const override;
58 void Accept(ModelVisitor*
const visitor)
const override {
71 EqualityExprCst::EqualityExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
72 : Constraint(s),
expr_(e), value_(v) {}
74 void EqualityExprCst::Post() {
75 if (!
expr_->IsVar()) {
76 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
81 void EqualityExprCst::InitialPropagate() {
expr_->SetValue(value_); }
83 std::string EqualityExprCst::DebugString()
const {
84 return absl::StrFormat(
"(%s == %d)",
expr_->DebugString(), value_);
89 CHECK_EQ(
this, e->
solver());
92 if (IsADifference(e, &left, &right)) {
93 return MakeEquality(left, MakeSum(right, v));
95 return MakeFalseConstraint();
96 }
else if (e->
Min() == e->
Max() && e->
Min() == v) {
97 return MakeTrueConstraint();
99 return RevAlloc(
new EqualityExprCst(
this, e, v));
104 CHECK_EQ(
this, e->
solver());
107 if (IsADifference(e, &left, &right)) {
108 return MakeEquality(left, MakeSum(right, v));
110 return MakeFalseConstraint();
111 }
else if (e->
Min() == e->
Max() && e->
Min() == v) {
112 return MakeTrueConstraint();
114 return RevAlloc(
new EqualityExprCst(
this, e, v));
124 GreaterEqExprCst(
Solver*
const s,
IntExpr*
const e, int64_t v);
125 ~GreaterEqExprCst()
override {}
126 void Post()
override;
129 IntVar*
Var()
override {
133 void Accept(ModelVisitor*
const visitor)
const override {
134 visitor->BeginVisitConstraint(ModelVisitor::kGreaterOrEqual,
this);
135 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
137 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
138 visitor->EndVisitConstraint(ModelVisitor::kGreaterOrEqual,
this);
142 IntExpr*
const expr_;
147 GreaterEqExprCst::GreaterEqExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
148 : Constraint(s),
expr_(e), value_(v), demon_(nullptr) {}
150 void GreaterEqExprCst::Post() {
152 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
160 void GreaterEqExprCst::InitialPropagate() {
162 if (demon_ !=
nullptr &&
expr_->
Min() >= value_) {
167 std::string GreaterEqExprCst::DebugString()
const {
173 CHECK_EQ(
this, e->
solver());
176 }
else if (e->
Max() < v) {
179 return RevAlloc(
new GreaterEqExprCst(
this, e, v));
184 CHECK_EQ(
this, e->
solver());
187 }
else if (e->
Max() < v) {
190 return RevAlloc(
new GreaterEqExprCst(
this, e, v));
195 CHECK_EQ(
this, e->
solver());
198 }
else if (e->
Max() <= v) {
201 return RevAlloc(
new GreaterEqExprCst(
this, e, v + 1));
206 CHECK_EQ(
this, e->
solver());
209 }
else if (e->
Max() <= v) {
212 return RevAlloc(
new GreaterEqExprCst(
this, e, v + 1));
223 ~LessEqExprCst()
override {}
224 void Post()
override;
225 void InitialPropagate()
override;
226 std::string DebugString()
const override;
227 IntVar* Var()
override {
228 return solver()->MakeIsLessOrEqualCstVar(
expr_->Var(), value_);
230 void Accept(ModelVisitor*
const visitor)
const override {
239 IntExpr*
const expr_;
244 LessEqExprCst::LessEqExprCst(Solver*
const s, IntExpr*
const e, int64_t v)
245 : Constraint(s),
expr_(e), value_(v), demon_(nullptr) {}
247 void LessEqExprCst::Post() {
249 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
257 void LessEqExprCst::InitialPropagate() {
259 if (demon_ !=
nullptr &&
expr_->
Max() <= value_) {
264 std::string LessEqExprCst::DebugString()
const {
270 CHECK_EQ(
this, e->
solver());
273 }
else if (e->
Min() > v) {
276 return RevAlloc(
new LessEqExprCst(
this, e, v));
281 CHECK_EQ(
this, e->
solver());
284 }
else if (e->
Min() > v) {
287 return RevAlloc(
new LessEqExprCst(
this, e, v));
292 CHECK_EQ(
this, e->
solver());
295 }
else if (e->
Min() >= v) {
298 return RevAlloc(
new LessEqExprCst(
this, e, v - 1));
303 CHECK_EQ(
this, e->
solver());
306 }
else if (e->
Min() >= v) {
309 return RevAlloc(
new LessEqExprCst(
this, e, v - 1));
320 ~DiffCst()
override {}
321 void Post()
override {}
322 void InitialPropagate()
override;
323 void BoundPropagate();
324 std::string DebugString()
const override;
325 IntVar* Var()
override {
326 return solver()->MakeIsDifferentCstVar(var_, value_);
328 void Accept(ModelVisitor*
const visitor)
const override {
337 bool HasLargeDomain(IntVar*
var);
344 DiffCst::DiffCst(Solver*
const s, IntVar*
const var, int64_t
value)
345 : Constraint(s), var_(
var), value_(
value), demon_(nullptr) {}
347 void DiffCst::InitialPropagate() {
348 if (HasLargeDomain(var_)) {
357 void DiffCst::BoundPropagate() {
358 const int64_t var_min = var_->
Min();
359 const int64_t var_max = var_->
Max();
360 if (var_min > value_ || var_max < value_) {
362 }
else if (var_min == value_) {
364 }
else if (var_max == value_) {
366 }
else if (!HasLargeDomain(var_)) {
372 std::string DiffCst::DebugString()
const {
373 return absl::StrFormat(
"(%s != %d)", var_->
DebugString(), value_);
376 bool DiffCst::HasLargeDomain(IntVar*
var) {
382 CHECK_EQ(
this, e->
solver());
385 if (IsADifference(e, &left, &right)) {
389 }
else if (e->
Bound() && e->
Min() == v) {
397 CHECK_EQ(
this, e->
solver());
400 if (IsADifference(e, &left, &right)) {
404 }
else if (e->
Bound() && e->
Min() == v) {
417 void Post()
override {
418 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
419 var_->WhenDomain(demon_);
422 void InitialPropagate()
override {
423 bool inhibit = var_->Bound();
424 int64_t u = var_->Contains(
cst_);
425 int64_t l = inhibit ? u : 0;
429 if (var_->Size() <= 0xFFFFFF) {
430 var_->RemoveValue(
cst_);
434 var_->SetValue(
cst_);
439 demon_->inhibit(solver());
442 std::string DebugString()
const override {
443 return absl::StrFormat(
"IsEqualCstCt(%s, %d, %s)", var_->DebugString(),
447 void Accept(ModelVisitor*
const visitor)
const override {
467 if (IsADifference(
var, &left, &right)) {
491 CHECK_EQ(
this,
var->solver());
492 CHECK_EQ(
this, boolvar->
solver());
505 if (boolvar->
Bound()) {
506 if (boolvar->
Min() == 0) {
514 model_cache_->InsertExprConstantExpression(
518 if (IsADifference(
var, &left, &right)) {
533 void Post()
override {
534 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
535 var_->WhenDomain(demon_);
539 void InitialPropagate()
override {
540 bool inhibit = var_->Bound();
541 int64_t l = 1 - var_->Contains(
cst_);
542 int64_t u = inhibit ? l : 1;
546 if (var_->Size() <= 0xFFFFFF) {
547 var_->RemoveValue(
cst_);
551 var_->SetValue(
cst_);
556 demon_->inhibit(solver());
560 std::string DebugString()
const override {
561 return absl::StrFormat(
"IsDiffCstCt(%s, %d, %s)", var_->DebugString(),
cst_,
565 void Accept(ModelVisitor*
const visitor)
const override {
585 if (IsADifference(
var, &left, &right)) {
588 return var->Var()->IsDifferent(
value);
593 CHECK_EQ(
this,
var->solver());
594 CHECK_EQ(
this, boolvar->
solver());
601 if (
var->IsVar() && !
var->Var()->Contains(
value)) {
607 if (boolvar->
Bound()) {
608 if (boolvar->
Min() == 0) {
614 model_cache_->InsertExprConstantExpression(
618 if (IsADifference(
var, &left, &right)) {
630 IsGreaterEqualCstCt(
Solver*
const s,
IntExpr*
const v, int64_t c,
633 void Post()
override {
634 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
635 expr_->WhenRange(demon_);
638 void InitialPropagate()
override {
639 bool inhibit =
false;
655 demon_->inhibit(solver());
658 std::string DebugString()
const override {
659 return absl::StrFormat(
"IsGreaterEqualCstCt(%s, %d, %s)",
664 void Accept(ModelVisitor*
const visitor)
const override {
675 IntExpr*
const expr_;
689 return var->Var()->IsGreaterOrEqual(
value);
704 if (boolvar->
Bound()) {
705 if (boolvar->
Min() == 0) {
711 CHECK_EQ(
this,
var->solver());
712 CHECK_EQ(
this, boolvar->
solver());
713 model_cache_->InsertExprConstantExpression(
728 IsLessEqualCstCt(
Solver*
const s,
IntExpr*
const v, int64_t c,
732 void Post()
override {
733 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
734 expr_->WhenRange(demon_);
738 void InitialPropagate()
override {
739 bool inhibit =
false;
755 demon_->inhibit(solver());
759 std::string DebugString()
const override {
760 return absl::StrFormat(
"IsLessEqualCstCt(%s, %d, %s)",
expr_->DebugString(),
764 void Accept(ModelVisitor*
const visitor)
const override {
775 IntExpr*
const expr_;
789 return var->Var()->IsLessOrEqual(
value);
804 if (boolvar->
Bound()) {
805 if (boolvar->
Min() == 0) {
811 CHECK_EQ(
this,
var->solver());
812 CHECK_EQ(
this, boolvar->
solver());
813 model_cache_->InsertExprConstantExpression(
828 BetweenCt(
Solver*
const s,
IntExpr*
const v, int64_t l, int64_t u)
831 void Post()
override {
832 if (!
expr_->IsVar()) {
833 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
834 expr_->WhenRange(demon_);
838 void InitialPropagate()
override {
839 expr_->SetRange(min_, max_);
842 expr_->Range(&emin, &emax);
843 if (demon_ !=
nullptr && emin >= min_ && emax <= max_) {
844 demon_->inhibit(solver());
848 std::string DebugString()
const override {
849 return absl::StrFormat(
"BetweenCt(%s, %d, %d)",
expr_->DebugString(), min_,
853 void Accept(ModelVisitor*
const visitor)
const override {
863 IntExpr*
const expr_;
871 class NotBetweenCt :
public Constraint {
873 NotBetweenCt(Solver*
const s, IntExpr*
const v, int64_t l, int64_t u)
874 : Constraint(s),
expr_(v), min_(l), max_(u), demon_(nullptr) {}
876 void Post()
override {
877 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
878 expr_->WhenRange(demon_);
881 void InitialPropagate()
override {
884 expr_->Range(&emin, &emax);
886 expr_->SetMin(max_ + 1);
887 }
else if (emax <= max_) {
888 expr_->SetMax(min_ - 1);
891 if (!
expr_->IsVar() && (emax < min_ || emin > max_)) {
892 demon_->inhibit(solver());
896 std::string DebugString()
const override {
897 return absl::StrFormat(
"NotBetweenCt(%s, %d, %d)",
expr_->DebugString(),
901 void Accept(ModelVisitor*
const visitor)
const override {
911 IntExpr*
const expr_;
917 int64_t ExtractExprProductCoeff(IntExpr** expr) {
920 while ((*expr)->solver()->IsProduct(*expr, expr, &coeff)) prod *= coeff;
926 DCHECK_EQ(
this, expr->
solver());
934 expr->
Range(&emin, &emax);
942 int64_t coeff = ExtractExprProductCoeff(&expr);
954 return RevAlloc(
new BetweenCt(
this, expr, l, u));
959 DCHECK_EQ(
this, expr->
solver());
967 expr->
Range(&emin, &emax);
973 if (emax <= u)
return MakeLess(expr, l);
976 return RevAlloc(
new NotBetweenCt(
this, expr, l, u));
984 IsBetweenCt(
Solver*
const s,
IntExpr*
const e, int64_t l, int64_t u,
993 void Post()
override {
994 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
995 expr_->WhenRange(demon_);
996 boolvar_->WhenBound(demon_);
999 void InitialPropagate()
override {
1000 bool inhibit =
false;
1003 expr_->Range(&emin, &emax);
1004 int64_t u = 1 - (emin > max_ || emax < min_);
1005 int64_t l = emax <= max_ && emin >= min_;
1006 boolvar_->SetRange(l, u);
1007 if (boolvar_->Bound()) {
1009 if (boolvar_->Min() == 0) {
1010 if (
expr_->IsVar()) {
1011 expr_->Var()->RemoveInterval(min_, max_);
1013 }
else if (emin > min_) {
1014 expr_->SetMin(max_ + 1);
1015 }
else if (emax < max_) {
1016 expr_->SetMax(min_ - 1);
1019 expr_->SetRange(min_, max_);
1022 if (inhibit &&
expr_->IsVar()) {
1023 demon_->inhibit(solver());
1028 std::string DebugString()
const override {
1029 return absl::StrFormat(
"IsBetweenCt(%s, %d, %d, %s)",
expr_->DebugString(),
1030 min_, max_, boolvar_->DebugString());
1033 void Accept(ModelVisitor*
const visitor)
const override {
1045 IntExpr*
const expr_;
1048 IntVar*
const boolvar_;
1055 CHECK_EQ(
this, expr->
solver());
1056 CHECK_EQ(
this,
b->solver());
1064 expr->
Range(&emin, &emax);
1072 int64_t coeff = ExtractExprProductCoeff(&expr);
1085 return RevAlloc(
new IsBetweenCt(
this, expr, l, u,
b));
1090 CHECK_EQ(
this, v->
solver());
1105 const std::vector<int64_t>& sorted_values)
1106 :
Constraint(s), var_(v), values_(sorted_values) {
1107 DCHECK(v !=
nullptr);
1108 DCHECK(s !=
nullptr);
1111 void Post()
override {}
1113 void InitialPropagate()
override { var_->SetValues(values_); }
1115 std::string DebugString()
const override {
1116 return absl::StrFormat(
"Member(%s, %s)", var_->DebugString(),
1117 absl::StrJoin(values_,
", "));
1120 void Accept(ModelVisitor*
const visitor)
const override {
1130 const std::vector<int64_t> values_;
1133 class NotMemberCt :
public Constraint {
1135 NotMemberCt(Solver*
const s, IntVar*
const v,
1136 const std::vector<int64_t>& sorted_values)
1137 : Constraint(s), var_(v), values_(sorted_values) {
1138 DCHECK(v !=
nullptr);
1139 DCHECK(s !=
nullptr);
1142 void Post()
override {}
1144 void InitialPropagate()
override { var_->RemoveValues(values_); }
1146 std::string DebugString()
const override {
1147 return absl::StrFormat(
"NotMember(%s, %s)", var_->DebugString(),
1148 absl::StrJoin(values_,
", "));
1151 void Accept(ModelVisitor*
const visitor)
const override {
1161 const std::vector<int64_t> values_;
1166 const std::vector<int64_t>& values) {
1167 const int64_t coeff = ExtractExprProductCoeff(&expr);
1169 return std::find(values.begin(), values.end(), 0) == values.end()
1173 std::vector<int64_t> copied_values = values;
1178 for (
const int64_t v : copied_values) {
1179 if (v % coeff == 0) copied_values[num_kept++] = v / coeff;
1181 copied_values.resize(num_kept);
1187 expr->
Range(&emin, &emax);
1188 for (
const int64_t v : copied_values) {
1189 if (v >= emin && v <= emax) copied_values[num_kept++] = v;
1191 copied_values.resize(num_kept);
1197 if (copied_values.size() == 1)
return MakeEquality(expr, copied_values[0]);
1199 if (copied_values.size() ==
1200 copied_values.back() - copied_values.front() + 1) {
1202 return MakeBetweenCt(expr, copied_values.front(), copied_values.back());
1207 if (emax - emin < 2 * copied_values.size()) {
1209 std::vector<bool> is_among_input_values(emax - emin + 1,
false);
1210 for (
const int64_t v : copied_values)
1211 is_among_input_values[v - emin] =
true;
1214 copied_values.clear();
1215 for (int64_t v_off = 0; v_off < is_among_input_values.size(); ++v_off) {
1216 if (!is_among_input_values[v_off]) copied_values.push_back(v_off + emin);
1220 DCHECK_GE(copied_values.size(), 1);
1221 if (copied_values.size() == 1) {
1224 return RevAlloc(
new NotMemberCt(
this, expr->
Var(), copied_values));
1227 return RevAlloc(
new MemberCt(
this, expr->
Var(), copied_values));
1231 const std::vector<int>& values) {
1236 const std::vector<int64_t>& values) {
1237 const int64_t coeff = ExtractExprProductCoeff(&expr);
1239 return std::find(values.begin(), values.end(), 0) == values.end()
1243 std::vector<int64_t> copied_values = values;
1248 for (
const int64_t v : copied_values) {
1249 if (v % coeff == 0) copied_values[num_kept++] = v / coeff;
1251 copied_values.resize(num_kept);
1257 expr->
Range(&emin, &emax);
1258 for (
const int64_t v : copied_values) {
1259 if (v >= emin && v <= emax) copied_values[num_kept++] = v;
1261 copied_values.resize(num_kept);
1267 if (copied_values.size() == 1)
return MakeNonEquality(expr, copied_values[0]);
1269 if (copied_values.size() ==
1270 copied_values.back() - copied_values.front() + 1) {
1271 return MakeNotBetweenCt(expr, copied_values.front(), copied_values.back());
1276 if (emax - emin < 2 * copied_values.size()) {
1278 std::vector<bool> is_among_input_values(emax - emin + 1,
false);
1279 for (
const int64_t v : copied_values)
1280 is_among_input_values[v - emin] =
true;
1283 copied_values.clear();
1284 for (int64_t v_off = 0; v_off < is_among_input_values.size(); ++v_off) {
1285 if (!is_among_input_values[v_off]) copied_values.push_back(v_off + emin);
1289 DCHECK_GE(copied_values.size(), 1);
1290 if (copied_values.size() == 1) {
1293 return RevAlloc(
new MemberCt(
this, expr->
Var(), copied_values));
1296 return RevAlloc(
new NotMemberCt(
this, expr->
Var(), copied_values));
1300 const std::vector<int>& values) {
1310 const std::vector<int64_t>& sorted_values,
IntVar*
const b)
1313 values_as_set_(sorted_values.begin(), sorted_values.
end()),
1314 values_(sorted_values),
1318 domain_(var_->MakeDomainIterator(true)),
1319 neg_support_(std::numeric_limits<int64_t>::
min()) {
1320 DCHECK(v !=
nullptr);
1321 DCHECK(s !=
nullptr);
1322 DCHECK(
b !=
nullptr);
1323 while (values_as_set_.contains(neg_support_)) {
1328 void Post()
override {
1331 if (!var_->Bound()) {
1332 var_->WhenDomain(demon_);
1334 if (!boolvar_->Bound()) {
1336 solver(),
this, &IsMemberCt::TargetBound,
"TargetBound");
1337 boolvar_->WhenBound(bdemon);
1341 void InitialPropagate()
override {
1342 boolvar_->SetRange(0, 1);
1343 if (boolvar_->Bound()) {
1350 std::string DebugString()
const override {
1351 return absl::StrFormat(
"IsMemberCt(%s, %s, %s)", var_->DebugString(),
1352 absl::StrJoin(values_,
", "),
1353 boolvar_->DebugString());
1356 void Accept(ModelVisitor*
const visitor)
const override {
1368 if (boolvar_->Bound()) {
1371 for (
int offset = 0; offset < values_.size(); ++offset) {
1372 const int candidate = (support_ + offset) % values_.size();
1373 if (var_->Contains(values_[candidate])) {
1374 support_ = candidate;
1375 if (var_->Bound()) {
1376 demon_->inhibit(solver());
1377 boolvar_->SetValue(1);
1382 if (var_->Contains(neg_support_)) {
1386 for (
const int64_t
value : InitAndGetValues(domain_)) {
1387 if (!values_as_set_.contains(
value)) {
1388 neg_support_ =
value;
1394 demon_->inhibit(solver());
1395 boolvar_->SetValue(1);
1400 demon_->inhibit(solver());
1401 boolvar_->SetValue(0);
1405 void TargetBound() {
1406 DCHECK(boolvar_->Bound());
1407 if (boolvar_->Min() == 1LL) {
1408 demon_->inhibit(solver());
1409 var_->SetValues(values_);
1411 demon_->inhibit(solver());
1412 var_->RemoveValues(values_);
1417 absl::flat_hash_set<int64_t> values_as_set_;
1418 std::vector<int64_t> values_;
1419 IntVar*
const boolvar_;
1422 IntVarIterator*
const domain_;
1423 int64_t neg_support_;
1427 Constraint* BuildIsMemberCt(Solver*
const solver, IntExpr*
const expr,
1428 const std::vector<T>& values,
1429 IntVar*
const boolvar) {
1432 IntExpr* sub =
nullptr;
1434 if (solver->IsProduct(expr, &sub, &
coef) &&
coef != 0 &&
coef != 1) {
1435 std::vector<int64_t> new_values;
1436 new_values.reserve(values.size());
1437 for (
const int64_t
value : values) {
1442 return BuildIsMemberCt(solver, sub, new_values, boolvar);
1445 std::set<T> set_of_values(values.begin(), values.end());
1446 std::vector<int64_t> filtered_values;
1447 bool all_values =
false;
1448 if (expr->IsVar()) {
1449 IntVar*
const var = expr->
Var();
1450 for (
const T
value : set_of_values) {
1452 filtered_values.push_back(
value);
1455 all_values = (filtered_values.size() ==
var->
Size());
1459 expr->
Range(&emin, &emax);
1460 for (
const T
value : set_of_values) {
1462 filtered_values.push_back(
value);
1465 all_values = (filtered_values.size() == emax - emin + 1);
1467 if (filtered_values.empty()) {
1468 return solver->MakeEquality(boolvar,
Zero());
1469 }
else if (all_values) {
1470 return solver->MakeEquality(boolvar, 1);
1471 }
else if (filtered_values.size() == 1) {
1472 return solver->MakeIsEqualCstCt(expr, filtered_values.back(), boolvar);
1473 }
else if (filtered_values.back() ==
1474 filtered_values.front() + filtered_values.size() - 1) {
1476 return solver->MakeIsBetweenCt(expr, filtered_values.front(),
1477 filtered_values.back(), boolvar);
1479 return solver->RevAlloc(
1480 new IsMemberCt(solver, expr->Var(), filtered_values, boolvar));
1486 const std::vector<int64_t>& values,
1488 return BuildIsMemberCt(
this, expr, values, boolvar);
1492 const std::vector<int>& values,
1494 return BuildIsMemberCt(
this, expr, values, boolvar);
1498 const std::vector<int64_t>& values) {
1505 const std::vector<int>& values) {
1512 class SortedDisjointForbiddenIntervalsConstraint :
public Constraint {
1514 SortedDisjointForbiddenIntervalsConstraint(
1517 :
Constraint(solver), var_(
var), intervals_(std::move(intervals)) {}
1519 ~SortedDisjointForbiddenIntervalsConstraint()
override {}
1521 void Post()
override {
1522 Demon*
const demon = solver()->MakeConstraintInitialPropagateCallback(
this);
1523 var_->WhenRange(demon);
1526 void InitialPropagate()
override {
1527 const int64_t vmin = var_->Min();
1528 const int64_t vmax = var_->Max();
1529 const auto first_interval_it = intervals_.FirstIntervalGreaterOrEqual(vmin);
1530 if (first_interval_it == intervals_.end()) {
1534 const auto last_interval_it = intervals_.LastIntervalLessOrEqual(vmax);
1535 if (last_interval_it == intervals_.end()) {
1541 if (vmin >= first_interval_it->start) {
1544 var_->SetMin(
CapAdd(first_interval_it->end, 1));
1546 if (vmax <= last_interval_it->
end) {
1548 var_->SetMax(
CapSub(last_interval_it->start, 1));
1552 std::string DebugString()
const override {
1553 return absl::StrFormat(
"ForbiddenIntervalCt(%s, %s)", var_->DebugString(),
1554 intervals_.DebugString());
1557 void Accept(ModelVisitor*
const visitor)
const override {
1561 std::vector<int64_t> starts;
1562 std::vector<int64_t> ends;
1563 for (
auto&
interval : intervals_) {
1574 const SortedDisjointIntervalList intervals_;
1579 std::vector<int64_t> starts,
1580 std::vector<int64_t> ends) {
1581 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1582 this, expr->
Var(), {starts, ends}));
1586 std::vector<int> starts,
1587 std::vector<int> ends) {
1588 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1589 this, expr->
Var(), {starts, ends}));
1594 return RevAlloc(
new SortedDisjointForbiddenIntervalsConstraint(
1595 this, expr->
Var(), std::move(intervals)));
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 IntVar * Var()=0
Creates a variable from the expression.
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 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.
IntVar * Var() override
Creates a variable from the expression.
virtual void RemoveValue(int64_t v)=0
This method removes the value 'v' from the domain of the variable.
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)
T * RevAlloc(T *object)
Registers the given object as being reversible.
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)
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)
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
int64_t CapSub(int64_t x, int64_t y)
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