00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <stddef.h>
00017 #include <string>
00018 #include <vector>
00019
00020 #include "base/commandlineflags.h"
00021 #include "base/integral_types.h"
00022 #include "base/logging.h"
00023 #include "base/scoped_ptr.h"
00024 #include "base/stringprintf.h"
00025 #include "constraint_solver/constraint_solver.h"
00026 #include "constraint_solver/constraint_solveri.h"
00027 #include "util/const_int_array.h"
00028
00029 DEFINE_int32(cache_initial_size, 1024, "Initial size of the array of the hash "
00030 "table of caches for objects of type Var(x == 3)");
00031
00032 namespace operations_research {
00033
00034
00035
00036
00037 namespace {
00038 class EqualityExprCst : public Constraint {
00039 public:
00040 EqualityExprCst(Solver* const s, IntExpr* const e, int64 v);
00041 virtual ~EqualityExprCst() {}
00042 virtual void Post();
00043 virtual void InitialPropagate();
00044 virtual IntVar* Var() {
00045 return solver()->MakeIsEqualCstVar(expr_->Var(), value_);
00046 }
00047 virtual string DebugString() const;
00048
00049 virtual void Accept(ModelVisitor* const visitor) const {
00050 visitor->BeginVisitConstraint(ModelVisitor::kEquality, this);
00051 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00052 expr_);
00053 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00054 visitor->EndVisitConstraint(ModelVisitor::kEquality, this);
00055 }
00056
00057 private:
00058 IntExpr* const expr_;
00059 int64 value_;
00060 };
00061
00062 EqualityExprCst::EqualityExprCst(Solver* const s, IntExpr* const e, int64 v)
00063 : Constraint(s), expr_(e), value_(v) {}
00064
00065 void EqualityExprCst::Post() {
00066 if (!expr_->IsVar()) {
00067 Demon* d = solver()->MakeConstraintInitialPropagateCallback(this);
00068 expr_->WhenRange(d);
00069 }
00070 }
00071
00072 void EqualityExprCst::InitialPropagate() {
00073 expr_->SetValue(value_);
00074 }
00075
00076 string EqualityExprCst::DebugString() const {
00077 return StringPrintf("(%s == %" GG_LL_FORMAT "d)",
00078 expr_->DebugString().c_str(), value_);
00079 }
00080 }
00081
00082 Constraint* Solver::MakeEquality(IntExpr* const e, int64 v) {
00083 CHECK_EQ(this, e->solver());
00084 return RevAlloc(new EqualityExprCst(this, e, v));
00085 }
00086
00087 Constraint* Solver::MakeEquality(IntExpr* const e, int v) {
00088 CHECK_EQ(this, e->solver());
00089 return RevAlloc(new EqualityExprCst(this, e, v));
00090 }
00091
00092
00093
00094
00095 namespace {
00096 class GreaterEqExprCst : public Constraint {
00097 public:
00098 GreaterEqExprCst(Solver* const s, IntExpr* const e, int64 v);
00099 virtual ~GreaterEqExprCst() {}
00100 virtual void Post();
00101 virtual void InitialPropagate();
00102 virtual string DebugString() const;
00103 virtual IntVar* Var() {
00104 return solver()->MakeIsGreaterOrEqualCstVar(expr_->Var(), value_);
00105 }
00106
00107 virtual void Accept(ModelVisitor* const visitor) const {
00108 visitor->BeginVisitConstraint(ModelVisitor::kGreaterOrEqual, this);
00109 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00110 expr_);
00111 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00112 visitor->EndVisitConstraint(ModelVisitor::kGreaterOrEqual, this);
00113 }
00114
00115 private:
00116 IntExpr* const expr_;
00117 int64 value_;
00118 };
00119
00120 GreaterEqExprCst::GreaterEqExprCst(Solver* const s, IntExpr* const e, int64 v)
00121 : Constraint(s), expr_(e), value_(v) {}
00122
00123 void GreaterEqExprCst::Post() {
00124 if (!expr_->IsVar()) {
00125 Demon* d = solver()->MakeConstraintInitialPropagateCallback(this);
00126 expr_->WhenRange(d);
00127 }
00128 }
00129
00130 void GreaterEqExprCst::InitialPropagate() {
00131 expr_->SetMin(value_);
00132 }
00133
00134 string GreaterEqExprCst::DebugString() const {
00135 return StringPrintf("(%s >= %" GG_LL_FORMAT "d)",
00136 expr_->DebugString().c_str(), value_);
00137 }
00138 }
00139
00140 Constraint* Solver::MakeGreaterOrEqual(IntExpr* const e, int64 v) {
00141 CHECK_EQ(this, e->solver());
00142 return RevAlloc(new GreaterEqExprCst(this, e, v));
00143 }
00144
00145 Constraint* Solver::MakeGreaterOrEqual(IntExpr* const e, int v) {
00146 CHECK_EQ(this, e->solver());
00147 return RevAlloc(new GreaterEqExprCst(this, e, v));
00148 }
00149
00150 Constraint* Solver::MakeGreater(IntExpr* const e, int64 v) {
00151 CHECK_EQ(this, e->solver());
00152 return RevAlloc(new GreaterEqExprCst(this, e, v + 1));
00153 }
00154
00155 Constraint* Solver::MakeGreater(IntExpr* const e, int v) {
00156 CHECK_EQ(this, e->solver());
00157 return RevAlloc(new GreaterEqExprCst(this, e, v + 1));
00158 }
00159
00160
00161
00162
00163 namespace {
00164 class LessEqExprCst : public Constraint {
00165 public:
00166 LessEqExprCst(Solver* const s, IntExpr* const e, int64 v);
00167 virtual ~LessEqExprCst() {}
00168 virtual void Post();
00169 virtual void InitialPropagate();
00170 virtual string DebugString() const;
00171 virtual IntVar* Var() {
00172 return solver()->MakeIsLessOrEqualCstVar(expr_->Var(), value_);
00173 }
00174 virtual void Accept(ModelVisitor* const visitor) const {
00175 visitor->BeginVisitConstraint(ModelVisitor::kLessOrEqual, this);
00176 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00177 expr_);
00178 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00179 visitor->EndVisitConstraint(ModelVisitor::kLessOrEqual, this);
00180 }
00181 private:
00182 IntExpr* const expr_;
00183 int64 value_;
00184 };
00185
00186 LessEqExprCst::LessEqExprCst(Solver* const s, IntExpr* const e, int64 v)
00187 : Constraint(s), expr_(e), value_(v) {}
00188
00189 void LessEqExprCst::Post() {
00190 if (!expr_->IsVar()) {
00191 Demon* d = solver()->MakeConstraintInitialPropagateCallback(this);
00192 expr_->WhenRange(d);
00193 }
00194 }
00195
00196 void LessEqExprCst::InitialPropagate() {
00197 expr_->SetMax(value_);
00198 }
00199
00200 string LessEqExprCst::DebugString() const {
00201 return StringPrintf("(%s <= %" GG_LL_FORMAT "d)",
00202 expr_->DebugString().c_str(), value_);
00203 }
00204 }
00205
00206 Constraint* Solver::MakeLessOrEqual(IntExpr* const e, int64 v) {
00207 CHECK_EQ(this, e->solver());
00208 return RevAlloc(new LessEqExprCst(this, e, v));
00209 }
00210
00211 Constraint* Solver::MakeLessOrEqual(IntExpr* const e, int v) {
00212 CHECK_EQ(this, e->solver());
00213 return RevAlloc(new LessEqExprCst(this, e, v));
00214 }
00215
00216 Constraint* Solver::MakeLess(IntExpr* const e, int64 v) {
00217 CHECK_EQ(this, e->solver());
00218 return RevAlloc(new LessEqExprCst(this, e, v - 1));
00219 }
00220
00221 Constraint* Solver::MakeLess(IntExpr* const e, int v) {
00222 CHECK_EQ(this, e->solver());
00223 return RevAlloc(new LessEqExprCst(this, e, v - 1));
00224 }
00225
00226
00227
00228
00229 namespace {
00230 class DiffCst : public Constraint {
00231 public:
00232 DiffCst(Solver* const s, IntVar* const var, int64 value);
00233 virtual ~DiffCst() {}
00234 virtual void Post() {}
00235 virtual void InitialPropagate();
00236 void BoundPropagate();
00237 virtual string DebugString() const;
00238 virtual IntVar* Var() {
00239 return solver()->MakeIsDifferentCstVar(var_, value_);
00240 }
00241 virtual void Accept(ModelVisitor* const visitor) const {
00242 visitor->BeginVisitConstraint(ModelVisitor::kNonEqual, this);
00243 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00244 var_);
00245 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00246 visitor->EndVisitConstraint(ModelVisitor::kNonEqual, this);
00247 }
00248 private:
00249 IntVar* const var_;
00250 int64 value_;
00251 Demon* demon_;
00252 };
00253
00254 DiffCst::DiffCst(Solver* const s, IntVar* const var, int64 value)
00255 : Constraint(s), var_(var), value_(value), demon_(NULL) {}
00256
00257 void DiffCst::InitialPropagate() {
00258 if (var_->Size() >= 0xFFFFFFFF) {
00259 demon_ = MakeConstraintDemon0(solver(),
00260 this,
00261 &DiffCst::BoundPropagate,
00262 "BoundPropagate");
00263 var_->WhenRange(demon_);
00264 } else {
00265 var_->RemoveValue(value_);
00266 }
00267 }
00268
00269 void DiffCst::BoundPropagate() {
00270 const int64 var_min = var_->Min();
00271 const int64 var_max = var_->Max();
00272 if (var_min > value_ || var_max < value_) {
00273 demon_->inhibit(solver());
00274 } else if (var_min == value_) {
00275 var_->SetMin(value_ + 1);
00276 } else if (var_max == value_) {
00277 var_->SetMax(value_ - 1);
00278 } else if (var_->Size() <= 0xFFFFFF) {
00279 demon_->inhibit(solver());
00280 var_->RemoveValue(value_);
00281 }
00282 }
00283
00284 string DiffCst::DebugString() const {
00285 return StringPrintf("(%s != %" GG_LL_FORMAT "d)",
00286 var_->DebugString().c_str(), value_);
00287 }
00288 }
00289
00290 Constraint* Solver::MakeNonEquality(IntVar* const e, int64 v) {
00291 CHECK_EQ(this, e->solver());
00292 return RevAlloc(new DiffCst(this, e, v));
00293 }
00294
00295 Constraint* Solver::MakeNonEquality(IntVar* const e, int v) {
00296 CHECK_EQ(this, e->solver());
00297 return RevAlloc(new DiffCst(this, e, v));
00298 }
00299
00300
00301 namespace {
00302 class IsEqualCstCt : public CastConstraint {
00303 public:
00304 IsEqualCstCt(Solver* const s, IntVar* const v, int64 c, IntVar* const b)
00305 : CastConstraint(s, b), var_(v), cst_(c), demon_(NULL) {}
00306 virtual void Post() {
00307 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00308 var_->WhenDomain(demon_);
00309 target_var_->WhenBound(demon_);
00310 }
00311 virtual void InitialPropagate() {
00312 bool inhibit = var_->Bound();
00313 int64 u = var_->Contains(cst_);
00314 int64 l = inhibit ? u : 0;
00315 target_var_->SetRange(l, u);
00316 if (target_var_->Bound()) {
00317 inhibit = true;
00318 if (target_var_->Min() == 0) {
00319 var_->RemoveValue(cst_);
00320 } else {
00321 var_->SetValue(cst_);
00322 }
00323 }
00324 if (inhibit) {
00325 demon_->inhibit(solver());
00326 }
00327 }
00328 string DebugString() const {
00329 return StringPrintf("IsEqualCstCt(%s, %" GG_LL_FORMAT "d, %s)",
00330 var_->DebugString().c_str(),
00331 cst_,
00332 target_var_->DebugString().c_str());
00333 }
00334
00335 void Accept(ModelVisitor* const visitor) const {
00336 visitor->BeginVisitConstraint(ModelVisitor::kIsEqual, this);
00337 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00338 var_);
00339 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, cst_);
00340 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00341 target_var_);
00342 visitor->EndVisitConstraint(ModelVisitor::kIsEqual, this);
00343 }
00344
00345 private:
00346 IntVar* const var_;
00347 int64 cst_;
00348 Demon* demon_;
00349 };
00350 }
00351
00352 IntVar* Solver::MakeIsEqualCstVar(IntVar* const var, int64 value) {
00353 if (value == var->Min()) {
00354 return MakeIsLessOrEqualCstVar(var, value);
00355 }
00356 if (value == var->Max()) {
00357 return MakeIsGreaterOrEqualCstVar(var, value);
00358 }
00359 if (!var->Contains(value)) {
00360 return MakeIntConst(0LL);
00361 }
00362 if (var->Bound() && var->Value() == value) {
00363 return MakeIntConst(1LL);
00364 }
00365 IntExpr* const cache = model_cache_->FindVarConstantExpression(
00366 var,
00367 value,
00368 ModelCache::VAR_CONSTANT_IS_EQUAL);
00369 if (cache != NULL) {
00370 return cache->Var();
00371 } else {
00372 string name = var->name();
00373 if (name.empty()) {
00374 name = var->DebugString();
00375 }
00376 IntVar* const boolvar = MakeBoolVar(
00377 StringPrintf("Var<%s == %" GG_LL_FORMAT "d>",
00378 name.c_str(), value));
00379 CastConstraint* const maintain =
00380 RevAlloc(new IsEqualCstCt(this, var, value, boolvar));
00381 AddConstraint(maintain);
00382 model_cache_->InsertVarConstantExpression(
00383 boolvar,
00384 var,
00385 value,
00386 ModelCache::VAR_CONSTANT_IS_EQUAL);
00387 return boolvar;
00388 }
00389 }
00390
00391 Constraint* Solver::MakeIsEqualCstCt(IntVar* const var,
00392 int64 value,
00393 IntVar* const boolvar) {
00394 CHECK_EQ(this, var->solver());
00395 CHECK_EQ(this, boolvar->solver());
00396 if (value == var->Min()) {
00397 return MakeIsLessOrEqualCstCt(var, value, boolvar);
00398 }
00399 if (value == var->Max()) {
00400 return MakeIsGreaterOrEqualCstCt(var, value, boolvar);
00401 }
00402
00403
00404 model_cache_->InsertVarConstantExpression(
00405 boolvar,
00406 var,
00407 value,
00408 ModelCache::VAR_CONSTANT_IS_EQUAL);
00409 return RevAlloc(new IsEqualCstCt(this, var, value, boolvar));
00410 }
00411
00412
00413
00414 namespace {
00415 class IsDiffCstCt : public CastConstraint {
00416 public:
00417 IsDiffCstCt(Solver* const s, IntVar* const v, int64 c, IntVar* const b)
00418 : CastConstraint(s, b), var_(v), cst_(c), demon_(NULL) {}
00419
00420 virtual void Post() {
00421 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00422 var_->WhenDomain(demon_);
00423 target_var_->WhenBound(demon_);
00424 }
00425
00426 virtual void InitialPropagate() {
00427 bool inhibit = var_->Bound();
00428 int64 l = 1 - var_->Contains(cst_);
00429 int64 u = inhibit ? l : 1;
00430 target_var_->SetRange(l, u);
00431 if (target_var_->Bound()) {
00432 inhibit = true;
00433 if (target_var_->Min() == 1) {
00434 var_->RemoveValue(cst_);
00435 } else {
00436 var_->SetValue(cst_);
00437 }
00438 }
00439 if (inhibit) {
00440 demon_->inhibit(solver());
00441 }
00442 }
00443
00444 virtual string DebugString() const {
00445 return StringPrintf("IsDiffCstCt(%s, %" GG_LL_FORMAT "d, %s)",
00446 var_->DebugString().c_str(),
00447 cst_,
00448 target_var_->DebugString().c_str());
00449 }
00450
00451 void Accept(ModelVisitor* const visitor) const {
00452 visitor->BeginVisitConstraint(ModelVisitor::kIsDifferent, this);
00453 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00454 var_);
00455 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, cst_);
00456 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00457 target_var_);
00458 visitor->EndVisitConstraint(ModelVisitor::kIsDifferent, this);
00459 }
00460
00461 private:
00462 IntVar* const var_;
00463 int64 cst_;
00464 Demon* demon_;
00465 };
00466 }
00467
00468 IntVar* Solver::MakeIsDifferentCstVar(IntVar* const var, int64 value) {
00469 if (value == var->Min()) {
00470 return MakeIsGreaterOrEqualCstVar(var, value + 1);
00471 }
00472 if (value == var->Max()) {
00473 return MakeIsLessOrEqualCstVar(var, value - 1);
00474 }
00475 if (!var->Contains(value)) {
00476 return MakeIntConst(1LL);
00477 }
00478 if (var->Bound() && var->Value() == value) {
00479 return MakeIntConst(0LL);
00480 }
00481 IntExpr* const cache = model_cache_->FindVarConstantExpression(
00482 var,
00483 value,
00484 ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
00485 if (cache != NULL) {
00486 return cache->Var();
00487 } else {
00488 string name = var->name();
00489 if (name.empty()) {
00490 name = var->DebugString();
00491 }
00492 IntVar* const boolvar = MakeBoolVar(
00493 StringPrintf("Var<%s != %" GG_LL_FORMAT "d>",
00494 name.c_str(), value));
00495 CastConstraint* const maintain =
00496 RevAlloc(new IsDiffCstCt(this, var, value, boolvar));
00497 AddConstraint(maintain);
00498 model_cache_->InsertVarConstantExpression(
00499 boolvar,
00500 var,
00501 value,
00502 ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
00503 return boolvar;
00504 }
00505 }
00506
00507 Constraint* Solver::MakeIsDifferentCstCt(IntVar* const var,
00508 int64 value,
00509 IntVar* const boolvar) {
00510 CHECK_EQ(this, var->solver());
00511 CHECK_EQ(this, boolvar->solver());
00512 if (value == var->Min()) {
00513 return MakeIsGreaterOrEqualCstCt(var, value + 1, boolvar);
00514 }
00515 if (value == var->Max()) {
00516 return MakeIsLessOrEqualCstCt(var, value - 1, boolvar);
00517 }
00518 model_cache_->InsertVarConstantExpression(
00519 boolvar,
00520 var,
00521 value,
00522 ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
00523 return RevAlloc(new IsDiffCstCt(this, var, value, boolvar));
00524 }
00525
00526
00527
00528 namespace {
00529 class IsGreaterEqualCstCt : public CastConstraint {
00530 public:
00531 IsGreaterEqualCstCt(Solver* const s, IntVar* const v, int64 c,
00532 IntVar* const b)
00533 : CastConstraint(s, b), var_(v), cst_(c), demon_(NULL) {}
00534 virtual void Post() {
00535 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00536 var_->WhenRange(demon_);
00537 target_var_->WhenBound(demon_);
00538 }
00539 virtual void InitialPropagate() {
00540 bool inhibit = false;
00541 int64 u = var_->Max() >= cst_;
00542 int64 l = var_->Min() >= cst_;
00543 target_var_->SetRange(l, u);
00544 if (target_var_->Bound()) {
00545 inhibit = true;
00546 if (target_var_->Min() == 0) {
00547 var_->SetMax(cst_ - 1);
00548 } else {
00549 var_->SetMin(cst_);
00550 }
00551 }
00552 if (inhibit) {
00553 demon_->inhibit(solver());
00554 }
00555 }
00556 virtual string DebugString() const {
00557 return StringPrintf("IsGreaterEqualCstCt(%s, %" GG_LL_FORMAT "d, %s)",
00558 var_->DebugString().c_str(),
00559 cst_,
00560 target_var_->DebugString().c_str());
00561 }
00562
00563 virtual void Accept(ModelVisitor* const visitor) const {
00564 visitor->BeginVisitConstraint(ModelVisitor::kIsGreaterOrEqual, this);
00565 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00566 var_);
00567 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, cst_);
00568 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00569 target_var_);
00570 visitor->EndVisitConstraint(ModelVisitor::kIsGreaterOrEqual, this);
00571 }
00572
00573 private:
00574 IntVar* const var_;
00575 int64 cst_;
00576 Demon* demon_;
00577 };
00578 }
00579
00580 IntVar* Solver::MakeIsGreaterOrEqualCstVar(IntVar* const var, int64 value) {
00581 if (var->Min() >= value) {
00582 return MakeIntConst(1LL);
00583 }
00584 if (var->Max() < value) {
00585 return MakeIntConst(0LL);
00586 }
00587 IntExpr* const cache = model_cache_->FindVarConstantExpression(
00588 var,
00589 value,
00590 ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
00591 if (cache != NULL) {
00592 return cache->Var();
00593 } else {
00594 string name = var->name();
00595 if (name.empty()) {
00596 name = var->DebugString();
00597 }
00598 IntVar* const boolvar = MakeBoolVar(
00599 StringPrintf("Var<%s >= %" GG_LL_FORMAT "d>",
00600 name.c_str(), value));
00601 CastConstraint* const maintain =
00602 RevAlloc(new IsGreaterEqualCstCt(this, var, value, boolvar));
00603 AddConstraint(maintain);
00604 model_cache_->InsertVarConstantExpression(
00605 boolvar,
00606 var,
00607 value,
00608 ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
00609 return boolvar;
00610 }
00611 }
00612
00613 IntVar* Solver::MakeIsGreaterCstVar(IntVar* const var, int64 value) {
00614 return MakeIsGreaterOrEqualCstVar(var, value + 1);
00615 }
00616
00617 Constraint* Solver::MakeIsGreaterOrEqualCstCt(IntVar* const var,
00618 int64 value,
00619 IntVar* const boolvar) {
00620 CHECK_EQ(this, var->solver());
00621 CHECK_EQ(this, boolvar->solver());
00622 model_cache_->InsertVarConstantExpression(
00623 boolvar,
00624 var,
00625 value,
00626 ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
00627 return RevAlloc(new IsGreaterEqualCstCt(this, var, value, boolvar));
00628 }
00629
00630 Constraint* Solver::MakeIsGreaterCstCt(IntVar* const v, int64 c,
00631 IntVar* const b) {
00632 return MakeIsGreaterOrEqualCstCt(v, c + 1, b);
00633 }
00634
00635
00636
00637 namespace {
00638 class IsLessEqualCstCt : public CastConstraint {
00639 public:
00640 IsLessEqualCstCt(Solver* const s, IntVar* const v, int64 c, IntVar* const b)
00641 : CastConstraint(s, b), var_(v), cst_(c), demon_(NULL) {}
00642
00643 virtual void Post() {
00644 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00645 var_->WhenRange(demon_);
00646 target_var_->WhenBound(demon_);
00647 }
00648
00649 virtual void InitialPropagate() {
00650 bool inhibit = false;
00651 int64 u = var_->Min() <= cst_;
00652 int64 l = var_->Max() <= cst_;
00653 target_var_->SetRange(l, u);
00654 if (target_var_->Bound()) {
00655 inhibit = true;
00656 if (target_var_->Min() == 0) {
00657 var_->SetMin(cst_ + 1);
00658 } else {
00659 var_->SetMax(cst_);
00660 }
00661 }
00662 if (inhibit) {
00663 demon_->inhibit(solver());
00664 }
00665 }
00666
00667 virtual string DebugString() const {
00668 return StringPrintf("IsLessEqualCstCt(%s, %" GG_LL_FORMAT "d, %s)",
00669 var_->DebugString().c_str(),
00670 cst_,
00671 target_var_->DebugString().c_str());
00672 }
00673
00674 virtual void Accept(ModelVisitor* const visitor) const {
00675 visitor->BeginVisitConstraint(ModelVisitor::kIsLessOrEqual, this);
00676 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00677 var_);
00678 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, cst_);
00679 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00680 target_var_);
00681 visitor->EndVisitConstraint(ModelVisitor::kIsLessOrEqual, this);
00682 }
00683
00684 private:
00685 IntVar* const var_;
00686 int64 cst_;
00687 Demon* demon_;
00688 };
00689 }
00690
00691
00692 IntVar* Solver::MakeIsLessOrEqualCstVar(IntVar* const var, int64 value) {
00693 if (var->Max() <= value) {
00694 return MakeIntConst(1LL);
00695 }
00696 if (var->Min() > value) {
00697 return MakeIntConst(0LL);
00698 }
00699 IntExpr* const cache = model_cache_->FindVarConstantExpression(
00700 var,
00701 value,
00702 ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
00703 if (cache != NULL) {
00704 return cache->Var();
00705 } else {
00706 string name = var->name();
00707 if (name.empty()) {
00708 name = var->DebugString();
00709 }
00710 IntVar* const boolvar = MakeBoolVar(
00711 StringPrintf("Var<%s <= %" GG_LL_FORMAT "d>",
00712 name.c_str(), value));
00713 CastConstraint* const maintain =
00714 RevAlloc(new IsLessEqualCstCt(this, var, value, boolvar));
00715 AddConstraint(maintain);
00716 model_cache_->InsertVarConstantExpression(
00717 boolvar,
00718 var,
00719 value,
00720 ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
00721 return boolvar;
00722 }
00723 }
00724
00725 IntVar* Solver::MakeIsLessCstVar(IntVar* const var, int64 value) {
00726 return MakeIsLessOrEqualCstVar(var, value - 1);
00727 }
00728
00729 Constraint* Solver::MakeIsLessOrEqualCstCt(IntVar* const var,
00730 int64 value,
00731 IntVar* const boolvar) {
00732 CHECK_EQ(this, var->solver());
00733 CHECK_EQ(this, boolvar->solver());
00734 model_cache_->InsertVarConstantExpression(
00735 boolvar,
00736 var,
00737 value,
00738 ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
00739 return RevAlloc(new IsLessEqualCstCt(this, var, value, boolvar));
00740 }
00741
00742 Constraint* Solver::MakeIsLessCstCt(IntVar* const v, int64 c,
00743 IntVar* const b) {
00744 return MakeIsLessOrEqualCstCt(v, c - 1, b);
00745 }
00746
00747
00748
00749 namespace {
00750 class BetweenCt : public Constraint {
00751 public:
00752 BetweenCt(Solver* const s, IntVar* const v, int64 l, int64 u)
00753 : Constraint(s), var_(v), min_(l), max_(u) {}
00754
00755 virtual void Post() {}
00756
00757 virtual void InitialPropagate() {
00758 var_->SetRange(min_, max_);
00759 }
00760
00761 virtual string DebugString() const {
00762 return StringPrintf("BetweenCt(%s, %" GG_LL_FORMAT "d, %" GG_LL_FORMAT "d)",
00763 var_->DebugString().c_str(), min_, max_);
00764 }
00765
00766 virtual void Accept(ModelVisitor* const visitor) const {
00767 visitor->BeginVisitConstraint(ModelVisitor::kBetween, this);
00768 visitor->VisitIntegerArgument(ModelVisitor::kMinArgument, min_);
00769 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00770 var_);
00771 visitor->VisitIntegerArgument(ModelVisitor::kMaxArgument, max_);
00772 visitor->EndVisitConstraint(ModelVisitor::kBetween, this);
00773 }
00774
00775 private:
00776 IntVar* const var_;
00777 int64 min_;
00778 int64 max_;
00779 };
00780 }
00781
00782 Constraint* Solver::MakeBetweenCt(IntVar* const v, int64 l, int64 u) {
00783 CHECK_EQ(this, v->solver());
00784 return RevAlloc(new BetweenCt(this, v, l, u));
00785 }
00786
00787
00788
00789 namespace {
00790 class IsBetweenCt : public Constraint {
00791 public:
00792 IsBetweenCt(Solver* const s, IntVar* const v, int64 l, int64 u,
00793 IntVar* const b)
00794 : Constraint(s), var_(v), min_(l), max_(u), boolvar_(b), demon_(NULL) {}
00795
00796 virtual void Post() {
00797 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00798 var_->WhenRange(demon_);
00799 boolvar_->WhenBound(demon_);
00800 }
00801
00802 virtual void InitialPropagate() {
00803 bool inhibit = false;
00804 int64 u = 1 - (var_->Min() > max_ || var_->Max() < min_);
00805 int64 l = var_->Max() <= max_ && var_->Min() >= min_;
00806 boolvar_->SetRange(l, u);
00807 if (boolvar_->Bound()) {
00808 inhibit = true;
00809 if (boolvar_->Min() == 0) {
00810 var_->RemoveInterval(min_, max_);
00811 } else {
00812 var_->SetRange(min_, max_);
00813 }
00814 }
00815 if (inhibit) {
00816 demon_->inhibit(solver());
00817 }
00818 }
00819
00820 virtual string DebugString() const {
00821 return StringPrintf(
00822 "IsBetweenCt(%s, %" GG_LL_FORMAT "d, %" GG_LL_FORMAT "d, %s)",
00823 var_->DebugString().c_str(), min_, max_,
00824 boolvar_->DebugString().c_str());
00825 }
00826
00827 virtual void Accept(ModelVisitor* const visitor) const {
00828 visitor->BeginVisitConstraint(ModelVisitor::kIsBetween, this);
00829 visitor->VisitIntegerArgument(ModelVisitor::kMinArgument, min_);
00830 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00831 var_);
00832 visitor->VisitIntegerArgument(ModelVisitor::kMaxArgument, max_);
00833 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00834 boolvar_);
00835 visitor->EndVisitConstraint(ModelVisitor::kIsBetween, this);
00836 }
00837
00838 private:
00839 IntVar* const var_;
00840 int64 min_;
00841 int64 max_;
00842 IntVar* const boolvar_;
00843 Demon* demon_;
00844 };
00845 }
00846
00847 Constraint* Solver::MakeIsBetweenCt(IntVar* const v,
00848 int64 l,
00849 int64 u,
00850 IntVar* const b) {
00851 CHECK_EQ(this, v->solver());
00852 CHECK_EQ(this, b->solver());
00853 return RevAlloc(new IsBetweenCt(this, v, l, u, b));
00854 }
00855
00856
00857
00858
00859
00860 namespace {
00861 class MemberCt : public Constraint {
00862 public:
00863 MemberCt(Solver* const s,
00864 IntVar* const v,
00865 std::vector<int64>* const sorted_values)
00866 : Constraint(s), var_(v), values_(sorted_values) {
00867 DCHECK(v != NULL);
00868 DCHECK(s != NULL);
00869 DCHECK(sorted_values != NULL);
00870 }
00871
00872 virtual void Post() {}
00873
00874 virtual void InitialPropagate() {
00875 var_->SetValues(values_.RawData(), values_.size());
00876 }
00877
00878 virtual string DebugString() const {
00879 return StringPrintf("Member(%s, %s)",
00880 var_->DebugString().c_str(),
00881 values_.DebugString().c_str());
00882 }
00883
00884 virtual void Accept(ModelVisitor* const visitor) const {
00885 visitor->BeginVisitConstraint(ModelVisitor::kMember, this);
00886 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00887 var_);
00888 visitor->VisitConstIntArrayArgument(ModelVisitor::kValuesArgument,
00889 values_);
00890 visitor->EndVisitConstraint(ModelVisitor::kMember, this);
00891 }
00892
00893 private:
00894 IntVar* const var_;
00895 ConstIntArray values_;
00896 };
00897 }
00898
00899 Constraint* Solver::MakeMemberCt(IntVar* const var,
00900 const int64* const values,
00901 int size) {
00902 ConstIntArray local_values(values, size);
00903 return RevAlloc(
00904 new MemberCt(this, var, local_values.SortedCopyWithoutDuplicates(true)));
00905 }
00906
00907 Constraint* Solver::MakeMemberCt(IntVar* const var,
00908 const std::vector<int64>& values) {
00909 return MakeMemberCt(var, values.data(), values.size());
00910 }
00911
00912 Constraint* Solver::MakeMemberCt(IntVar* const var,
00913 const int* const values,
00914 int size) {
00915 ConstIntArray local_values(values, size);
00916 return RevAlloc(
00917 new MemberCt(this, var, local_values.SortedCopyWithoutDuplicates(true)));
00918 }
00919
00920 Constraint* Solver::MakeMemberCt(IntVar* const var,
00921 const std::vector<int>& values) {
00922 return MakeMemberCt(var, values.data(), values.size());
00923 }
00924
00925
00926
00927 namespace {
00928 class IsMemberCt : public Constraint {
00929 public:
00930 IsMemberCt(Solver* const s,
00931 IntVar* const v,
00932 std::vector<int64>* const sorted_values,
00933 IntVar* const b)
00934 : Constraint(s),
00935 var_(v),
00936 values_(sorted_values),
00937 boolvar_(b),
00938 support_pos_(0),
00939 demon_(NULL) {
00940 DCHECK(v != NULL);
00941 DCHECK(s != NULL);
00942 DCHECK(b != NULL);
00943 DCHECK(sorted_values != NULL);
00944 }
00945
00946 virtual void Post() {
00947 demon_ = solver()->MakeConstraintInitialPropagateCallback(this);
00948 if (!var_->Bound()) {
00949 var_->WhenDomain(demon_);
00950 }
00951 if (!boolvar_->Bound()) {
00952 boolvar_->WhenBound(demon_);
00953 }
00954 }
00955
00956 virtual void InitialPropagate() {
00957 if (boolvar_->Min() == 1LL) {
00958 demon_->inhibit(solver());
00959 var_->SetValues(values_.RawData(), values_.size());
00960 } else if (boolvar_->Max() == 1LL) {
00961 int support = support_pos_.Value();
00962 const int64 vmin = var_->Min();
00963 const int64 vmax = var_->Max();
00964 while (support < values_.size() &&
00965 (values_[support] < vmin ||
00966 !var_->Contains(values_[support]))) {
00967 if (values_[support] <= vmax) {
00968 support++;
00969 } else {
00970 support = values_.size();
00971 }
00972 }
00973 support_pos_.SetValue(solver(), support);
00974 if (support >= values_.size()) {
00975 demon_->inhibit(solver());
00976 boolvar_->SetValue(0LL);
00977 } else if (var_->Bound()) {
00978 demon_->inhibit(solver());
00979 boolvar_->SetValue(1LL);
00980 }
00981 } else {
00982 demon_->inhibit(solver());
00983 var_->RemoveValues(values_.RawData(), values_.size());
00984 }
00985 }
00986
00987 virtual string DebugString() const {
00988 return StringPrintf("IsMemberCt(%s, %s, %s)",
00989 var_->DebugString().c_str(),
00990 values_.DebugString().c_str(),
00991 boolvar_->DebugString().c_str());
00992 }
00993
00994 virtual void Accept(ModelVisitor* const visitor) const {
00995 visitor->BeginVisitConstraint(ModelVisitor::kIsMember, this);
00996 visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
00997 var_);
00998 visitor->VisitConstIntArrayArgument(ModelVisitor::kValuesArgument,
00999 values_);
01000 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
01001 boolvar_);
01002 visitor->EndVisitConstraint(ModelVisitor::kIsMember, this);
01003 }
01004
01005 private:
01006 IntVar* const var_;
01007 ConstIntArray values_;
01008 IntVar* const boolvar_;
01009 Rev<int> support_pos_;
01010 Demon* demon_;
01011 };
01012 }
01013
01014 Constraint* Solver::MakeIsMemberCt(IntVar* const var,
01015 const int64* const values,
01016 int size,
01017 IntVar* const boolvar) {
01018 ConstIntArray local_values(values, size);
01019 return RevAlloc(
01020 new IsMemberCt(this,
01021 var,
01022 local_values.SortedCopyWithoutDuplicates(true),
01023 boolvar));
01024 }
01025
01026 Constraint* Solver::MakeIsMemberCt(IntVar* const var,
01027 const std::vector<int64>& values,
01028 IntVar* const boolvar) {
01029 return MakeIsMemberCt(var, values.data(), values.size(), boolvar);
01030 }
01031
01032 Constraint* Solver::MakeIsMemberCt(IntVar* const var,
01033 const int* const values,
01034 int size,
01035 IntVar* const boolvar) {
01036 ConstIntArray local_values(values, size);
01037 return RevAlloc(
01038 new IsMemberCt(this,
01039 var,
01040 local_values.SortedCopyWithoutDuplicates(true),
01041 boolvar));
01042 }
01043
01044 Constraint* Solver::MakeIsMemberCt(IntVar* const var,
01045 const std::vector<int>& values,
01046 IntVar* const boolvar) {
01047 return MakeIsMemberCt(var, values.data(), values.size(), boolvar);
01048 }
01049
01050 IntVar* Solver::MakeIsMemberVar(IntVar* const var,
01051 const int64* const values,
01052 int size) {
01053 IntVar* const b = MakeBoolVar();
01054 AddConstraint(MakeIsMemberCt(var, values, size, b));
01055 return b;
01056 }
01057
01058 IntVar* Solver::MakeIsMemberVar(IntVar* const var,
01059 const std::vector<int64>& values) {
01060 return MakeIsMemberVar(var, values.data(), values.size());
01061 }
01062
01063 IntVar* Solver::MakeIsMemberVar(IntVar* const var,
01064 const int* const values,
01065 int size) {
01066 IntVar* const b = MakeBoolVar();
01067 AddConstraint(MakeIsMemberCt(var, values, size, b));
01068 return b;
01069 }
01070
01071 IntVar* Solver::MakeIsMemberVar(IntVar* const var, const std::vector<int>& values) {
01072 return MakeIsMemberVar(var, values.data(), values.size());
01073 }
01074 }