00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <string>
00015
00016 #include "base/integral_types.h"
00017 #include "base/logging.h"
00018 #include "base/macros.h"
00019 #include "base/stringprintf.h"
00020 #include "constraint_solver/constraint_solver.h"
00021 #include "constraint_solver/constraint_solveri.h"
00022
00023 namespace operations_research {
00024
00025
00026
00027 namespace {
00028 const char* kUnaryNames[] = {
00029 "ENDS_AFTER",
00030 "ENDS_AT",
00031 "ENDS_BEFORE",
00032 "STARTS_AFTER",
00033 "STARTS_AT",
00034 "STARTS_BEFORE",
00035 "CROSS_DATE",
00036 "AVOID_DATE",
00037 };
00038
00039 const char* kBinaryNames[] = {
00040 "ENDS_AFTER_END",
00041 "ENDS_AFTER_START",
00042 "ENDS_AT_END",
00043 "ENDS_AT_START",
00044 "STARTS_AFTER_END",
00045 "STARTS_AFTER_START",
00046 "STARTS_AT_END",
00047 "STARTS_AT_START",
00048 "STAYS_IN_SYNC"
00049 };
00050
00051 class IntervalUnaryRelation : public Constraint {
00052 public:
00053 IntervalUnaryRelation(Solver* const s,
00054 IntervalVar* const t,
00055 int64 d,
00056 Solver::UnaryIntervalRelation rel)
00057 : Constraint(s), t_(t), d_(d), rel_(rel) {}
00058 virtual ~IntervalUnaryRelation() {}
00059
00060 virtual void Post();
00061
00062 virtual void InitialPropagate();
00063
00064 virtual string DebugString() const {
00065 return StringPrintf("(%s %s %" GG_LL_FORMAT "d)",
00066 t_->DebugString().c_str(), kUnaryNames[rel_], d_);
00067 }
00068
00069 virtual void Accept(ModelVisitor* const visitor) const {
00070 visitor->BeginVisitConstraint(ModelVisitor::kIntervalUnaryRelation, this);
00071 visitor->VisitIntervalArgument(ModelVisitor::kIntervalArgument, t_);
00072 visitor->VisitIntegerArgument(ModelVisitor::kRelationArgument, rel_);
00073 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, d_);
00074 visitor->EndVisitConstraint(ModelVisitor::kIntervalUnaryRelation, this);
00075 }
00076
00077 private:
00078 IntervalVar* const t_;
00079 const int64 d_;
00080 const Solver::UnaryIntervalRelation rel_;
00081 };
00082
00083 void IntervalUnaryRelation::Post() {
00084 if (t_->MayBePerformed()) {
00085 Demon* d = solver()->MakeConstraintInitialPropagateCallback(this);
00086 t_->WhenAnything(d);
00087 }
00088 }
00089
00090 void IntervalUnaryRelation::InitialPropagate() {
00091 if (t_->MayBePerformed()) {
00092 switch (rel_) {
00093 case Solver::ENDS_AFTER:
00094 t_->SetEndMin(d_);
00095 break;
00096 case Solver::ENDS_AT:
00097 t_->SetEndRange(d_, d_);
00098 break;
00099 case Solver::ENDS_BEFORE:
00100 t_->SetEndMax(d_);
00101 break;
00102 case Solver::STARTS_AFTER:
00103 t_->SetStartMin(d_);
00104 break;
00105 case Solver::STARTS_AT:
00106 t_->SetStartRange(d_, d_);
00107 break;
00108
00109 case Solver::STARTS_BEFORE:
00110 t_->SetStartMax(d_);
00111 break;
00112 case Solver::CROSS_DATE:
00113 t_->SetStartMax(d_);
00114 t_->SetEndMin(d_);
00115 break;
00116 case Solver::AVOID_DATE:
00117 if (t_->EndMin() > d_) {
00118 t_->SetStartMin(d_);
00119 } else if (t_->StartMax() < d_) {
00120 t_->SetEndMax(d_);
00121 }
00122 break;
00123 }
00124 }
00125 }
00126 }
00127
00128 Constraint* Solver::MakeIntervalVarRelation(IntervalVar* const t,
00129 Solver::UnaryIntervalRelation r,
00130 int64 d) {
00131 return RevAlloc(new IntervalUnaryRelation(this, t, d, r));
00132 }
00133
00134
00135
00136 namespace {
00137 class IntervalBinaryRelation : public Constraint {
00138 public:
00139 IntervalBinaryRelation(Solver* const s,
00140 IntervalVar* const t1,
00141 IntervalVar* const t2,
00142 Solver::BinaryIntervalRelation rel)
00143 : Constraint(s), t1_(t1), t2_(t2), rel_(rel) {}
00144 virtual ~IntervalBinaryRelation() {}
00145
00146 virtual void Post();
00147
00148 virtual void InitialPropagate();
00149
00150 virtual string DebugString() const {
00151 return StringPrintf("(%s %s %s)",
00152 t1_->DebugString().c_str(),
00153 kBinaryNames[rel_],
00154 t2_->DebugString().c_str());
00155 }
00156
00157 virtual void Accept(ModelVisitor* const visitor) const {
00158 visitor->BeginVisitConstraint(ModelVisitor::kIntervalBinaryRelation, this);
00159 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
00160 visitor->VisitIntegerArgument(ModelVisitor::kRelationArgument, rel_);
00161 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
00162 visitor->EndVisitConstraint(ModelVisitor::kIntervalBinaryRelation, this);
00163 }
00164
00165 private:
00166 IntervalVar* const t1_;
00167 IntervalVar* const t2_;
00168 const Solver::BinaryIntervalRelation rel_;
00169 };
00170
00171 void IntervalBinaryRelation::Post() {
00172 if (t1_->MayBePerformed() && t2_->MayBePerformed()) {
00173 Demon* d = solver()->MakeConstraintInitialPropagateCallback(this);
00174 t1_->WhenAnything(d);
00175 t2_->WhenAnything(d);
00176 }
00177 }
00178
00179
00180 void IntervalBinaryRelation::InitialPropagate() {
00181 switch (rel_) {
00182 case Solver::ENDS_AFTER_END:
00183 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00184 t1_->SetEndMin(t2_->EndMin());
00185 }
00186 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00187 t2_->SetEndMax(t1_->EndMax());
00188 }
00189 break;
00190 case Solver::ENDS_AFTER_START:
00191 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00192 t1_->SetEndMin(t2_->StartMin());
00193 }
00194 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00195 t2_->SetStartMax(t1_->EndMax());
00196 }
00197 break;
00198 case Solver::ENDS_AT_END:
00199 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00200 t1_->SetEndRange(t2_->EndMin(), t2_->EndMax());
00201 }
00202 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00203 t2_->SetEndRange(t1_->EndMin(), t1_->EndMax());
00204 }
00205 break;
00206 case Solver::ENDS_AT_START:
00207 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00208 t1_->SetEndRange(t2_->StartMin(), t2_->StartMax());
00209 }
00210 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00211 t2_->SetStartRange(t1_->EndMin(), t1_->EndMax());
00212 }
00213 break;
00214 case Solver::STARTS_AFTER_END:
00215 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00216 t1_->SetStartMin(t2_->EndMin());
00217 }
00218 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00219 t2_->SetEndMax(t1_->StartMax());
00220 }
00221 break;
00222 case Solver::STARTS_AFTER_START:
00223 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00224 t1_->SetStartMin(t2_->StartMin());
00225 }
00226 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00227 t2_->SetEndMax(t1_->StartMax());
00228 }
00229 break;
00230 case Solver::STARTS_AT_END:
00231 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00232 t1_->SetStartRange(t2_->EndMin(), t2_->EndMax());
00233 }
00234 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00235 t2_->SetEndRange(t1_->StartMin(), t1_->StartMax());
00236 }
00237 break;
00238 case Solver::STARTS_AT_START:
00239 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00240 t1_->SetStartRange(t2_->StartMin(), t2_->StartMax());
00241 }
00242 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00243 t2_->SetStartRange(t1_->StartMin(), t1_->StartMax());
00244 }
00245 break;
00246 case Solver::STAYS_IN_SYNC:
00247 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00248 t1_->SetStartRange(t2_->StartMin(), t2_->StartMax());
00249 t1_->SetEndRange(t2_->EndMin(), t2_->EndMax());
00250 }
00251 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00252 t2_->SetStartRange(t1_->StartMin(), t1_->StartMax());
00253 t2_->SetEndRange(t1_->EndMin(), t1_->EndMax());
00254 }
00255 break;
00256 }
00257 }
00258 }
00259
00260 Constraint* Solver::MakeIntervalVarRelation(IntervalVar* const t1,
00261 Solver::BinaryIntervalRelation r,
00262 IntervalVar* const t2) {
00263 return RevAlloc(new IntervalBinaryRelation(this, t1, t2, r));
00264 }
00265
00266
00267
00268 namespace {
00269 class TemporalDisjunction : public Constraint {
00270 public:
00271 enum State { ONE_BEFORE_TWO, TWO_BEFORE_ONE, UNDECIDED };
00272
00273 TemporalDisjunction(Solver* const s,
00274 IntervalVar* const t1,
00275 IntervalVar* const t2,
00276 IntVar* const alt)
00277 : Constraint(s), t1_(t1), t2_(t2), alt_(alt), state_(UNDECIDED) {}
00278 virtual ~TemporalDisjunction() {}
00279
00280 virtual void Post();
00281 virtual void InitialPropagate();
00282 virtual string DebugString() const;
00283
00284 void RangeDemon1();
00285 void RangeDemon2();
00286 void RangeAlt();
00287 void Decide(State s);
00288 void TryToDecide();
00289
00290 virtual void Accept(ModelVisitor* const visitor) const {
00291 visitor->BeginVisitConstraint(ModelVisitor::kIntervalDisjunction, this);
00292 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
00293 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
00294 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00295 alt_);
00296 visitor->EndVisitConstraint(ModelVisitor::kIntervalDisjunction, this);
00297 }
00298
00299 private:
00300 IntervalVar* const t1_;
00301 IntervalVar* const t2_;
00302 IntVar* const alt_;
00303 State state_;
00304 };
00305
00306 void TemporalDisjunction::Post() {
00307 Solver* const s = solver();
00308 Demon* d = MakeConstraintDemon0(s,
00309 this,
00310 &TemporalDisjunction::RangeDemon1,
00311 "RangeDemon1");
00312 t1_->WhenAnything(d);
00313 d = MakeConstraintDemon0(s,
00314 this,
00315 &TemporalDisjunction::RangeDemon2,
00316 "RangeDemon2");
00317 t2_->WhenAnything(d);
00318 if (alt_ != NULL) {
00319 d = MakeConstraintDemon0(s,
00320 this,
00321 &TemporalDisjunction::RangeAlt,
00322 "RangeAlt");
00323 alt_->WhenRange(d);
00324 }
00325 }
00326
00327 void TemporalDisjunction::InitialPropagate() {
00328 if (alt_ != NULL) {
00329 alt_->SetRange(0, 1);
00330 }
00331 if (alt_ != NULL && alt_->Bound()) {
00332 RangeAlt();
00333 } else {
00334 RangeDemon1();
00335 RangeDemon2();
00336 }
00337 }
00338
00339 string TemporalDisjunction::DebugString() const {
00340 string out;
00341 SStringPrintf(&out, "TemporalDisjunction(%s, %s",
00342 t1_->DebugString().c_str(), t2_->DebugString().c_str());
00343 if (alt_ != NULL) {
00344 StringAppendF(&out, " => %s", alt_->DebugString().c_str());
00345 }
00346 out += ") ";
00347 return out;
00348 }
00349
00350 void TemporalDisjunction::TryToDecide() {
00351 DCHECK_EQ(UNDECIDED, state_);
00352 if (t1_->MayBePerformed() && t2_->MayBePerformed() &&
00353 (t1_->MustBePerformed() || t2_->MustBePerformed())) {
00354 if (t1_->EndMin() > t2_->StartMax()) {
00355 Decide(TWO_BEFORE_ONE);
00356 } else if (t2_->EndMin() > t1_->StartMax()) {
00357 Decide(ONE_BEFORE_TWO);
00358 }
00359 }
00360 }
00361
00362 void TemporalDisjunction::RangeDemon1() {
00363 switch (state_) {
00364 case ONE_BEFORE_TWO: {
00365 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00366 t2_->SetStartMin(t1_->EndMin());
00367 }
00368 break;
00369 }
00370 case TWO_BEFORE_ONE: {
00371 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
00372 t2_->SetEndMax(t1_->StartMax());
00373 }
00374 break;
00375 }
00376 case UNDECIDED: {
00377 TryToDecide();
00378 }
00379 }
00380 }
00381
00382 void TemporalDisjunction::RangeDemon2() {
00383 if (t1_->MayBePerformed() || t2_->MayBePerformed()) {
00384 switch (state_) {
00385 case ONE_BEFORE_TWO: {
00386 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00387 t1_->SetEndMax(t2_->StartMax());
00388 }
00389 break;
00390 }
00391 case TWO_BEFORE_ONE: {
00392 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
00393 t1_->SetStartMin(t2_->EndMin());
00394 }
00395 break;
00396 }
00397 case UNDECIDED: {
00398 TryToDecide();
00399 }
00400 }
00401 }
00402 }
00403
00404 void TemporalDisjunction::RangeAlt() {
00405 DCHECK(alt_ != NULL);
00406 if (alt_->Value() == 0) {
00407 Decide(ONE_BEFORE_TWO);
00408 } else {
00409 Decide(TWO_BEFORE_ONE);
00410 }
00411 }
00412
00413 void TemporalDisjunction::Decide(State s) {
00414
00415 DCHECK_NE(s, UNDECIDED);
00416 if (state_ != UNDECIDED && state_ != s) {
00417 solver()->Fail();
00418 }
00419 solver()->SaveValue(reinterpret_cast<int*>(&state_));
00420 state_ = s;
00421 if (alt_ != NULL) {
00422 if (s == ONE_BEFORE_TWO) {
00423 alt_->SetValue(0);
00424 } else {
00425 alt_->SetValue(1);
00426 }
00427 }
00428 RangeDemon1();
00429 RangeDemon2();
00430 }
00431 }
00432
00433 Constraint* Solver::MakeTemporalDisjunction(IntervalVar* const t1,
00434 IntervalVar* const t2,
00435 IntVar* const alt) {
00436 return RevAlloc(new TemporalDisjunction(this, t1, t2, alt));
00437 }
00438
00439 Constraint* Solver::MakeTemporalDisjunction(IntervalVar* const t1,
00440 IntervalVar* const t2) {
00441 return RevAlloc(new TemporalDisjunction(this, t1, t2, NULL));
00442 }
00443
00444 }