00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <string.h>
00015 #include <algorithm>
00016 #include <string>
00017 #include <vector>
00018
00019 #include "base/callback.h"
00020 #include "base/integral_types.h"
00021 #include "base/logging.h"
00022 #include "base/scoped_ptr.h"
00023 #include "constraint_solver/constraint_solver.h"
00024 #include "constraint_solver/constraint_solveri.h"
00025
00026 namespace operations_research {
00027
00028 Demon* Solver::MakeConstraintInitialPropagateCallback(Constraint* const ct) {
00029 return MakeConstraintDemon0(this,
00030 ct,
00031 &Constraint::InitialPropagate,
00032 "InitialPropagate");
00033 }
00034
00035 Demon* Solver::MakeDelayedConstraintInitialPropagateCallback(
00036 Constraint* const ct) {
00037 return MakeDelayedConstraintDemon0(this,
00038 ct,
00039 &Constraint::InitialPropagate,
00040 "InitialPropagate");
00041 }
00042
00043 namespace {
00044 class Callback1Demon : public Demon {
00045 public:
00046
00047 explicit Callback1Demon(Callback1<Solver*>* const callback)
00048 : callback_(callback) {
00049 CHECK_NOTNULL(callback);
00050 callback_->CheckIsRepeatable();
00051 }
00052 virtual ~Callback1Demon() {}
00053
00054 virtual void Run(Solver* const solver) {
00055 callback_->Run(solver);
00056 }
00057 private:
00058 scoped_ptr<Callback1<Solver*> > callback_;
00059 };
00060
00061 class ClosureDemon : public Demon {
00062 public:
00063
00064 explicit ClosureDemon(Closure* const callback) : callback_(callback) {
00065 CHECK_NOTNULL(callback);
00066 callback_->CheckIsRepeatable();
00067 }
00068 virtual ~ClosureDemon() {}
00069
00070 virtual void Run(Solver* const solver) {
00071 callback_->Run();
00072 }
00073 private:
00074 scoped_ptr<Closure> callback_;
00075 };
00076 }
00077
00078 Demon* Solver::MakeCallbackDemon(Callback1<Solver*>* const callback) {
00079 return RevAlloc(new Callback1Demon(callback));
00080 }
00081
00082 Demon* Solver::MakeCallbackDemon(Closure* const callback) {
00083 return RevAlloc(new ClosureDemon(callback));
00084 }
00085
00086
00087
00088 namespace {
00089 class TrueConstraint : public Constraint {
00090 public:
00091 explicit TrueConstraint(Solver* const s) : Constraint(s) {}
00092 virtual ~TrueConstraint() {}
00093
00094 virtual void Post() {}
00095 virtual void InitialPropagate() {}
00096 virtual string DebugString() const { return "TrueConstraint()"; }
00097
00098 void Accept(ModelVisitor* const visitor) const {
00099 visitor->BeginVisitConstraint(ModelVisitor::kTrueConstraint, this);
00100 visitor->EndVisitConstraint(ModelVisitor::kTrueConstraint, this);
00101 }
00102 };
00103 }
00104
00105 Constraint* Solver::MakeTrueConstraint() {
00106 DCHECK(true_constraint_ != NULL);
00107 return true_constraint_;
00108 }
00109
00110 namespace {
00111 class FalseConstraint : public Constraint {
00112 public:
00113 explicit FalseConstraint(Solver* const s) : Constraint(s) {}
00114 FalseConstraint(Solver* const s, const string& explanation)
00115 : Constraint(s), explanation_(explanation) {}
00116 virtual ~FalseConstraint() {}
00117
00118 virtual void Post() {}
00119 virtual void InitialPropagate() { solver()->Fail(); }
00120 virtual string DebugString() const {
00121 return StrCat("FalseConstraint(", explanation_, ")");
00122 }
00123
00124 void Accept(ModelVisitor* const visitor) const {
00125 visitor->BeginVisitConstraint(ModelVisitor::kFalseConstraint, this);
00126 visitor->EndVisitConstraint(ModelVisitor::kFalseConstraint, this);
00127 }
00128
00129 private:
00130 const string explanation_;
00131 };
00132 }
00133
00134 Constraint* Solver::MakeFalseConstraint() {
00135 DCHECK(false_constraint_ != NULL);
00136 return false_constraint_;
00137 }
00138 Constraint* Solver::MakeFalseConstraint(const string& explanation) {
00139 return RevAlloc(new FalseConstraint(this, explanation));
00140 }
00141
00142 void Solver::InitCachedConstraint() {
00143 DCHECK(true_constraint_ == NULL);
00144 true_constraint_ = RevAlloc(new TrueConstraint(this));
00145 DCHECK(false_constraint_ == NULL);
00146 false_constraint_ = RevAlloc(new FalseConstraint(this));
00147 }
00148
00149
00150
00151
00152
00153
00154 namespace {
00155 class MapDomain : public Constraint {
00156 public:
00157 MapDomain(Solver* const s,
00158 IntVar* const var,
00159 IntVar* const * actives,
00160 int size)
00161 : Constraint(s), var_(var), actives_(new IntVar*[size]), size_(size) {
00162 memcpy(actives_.get(), actives, size_ * sizeof(*actives));
00163 holes_ = var->MakeHoleIterator(true);
00164 }
00165
00166 virtual ~MapDomain() {}
00167
00168 virtual void Post() {
00169 Demon* vd = MakeConstraintDemon0(solver(),
00170 this,
00171 &MapDomain::VarDomain,
00172 "VarDomain");
00173 var_->WhenDomain(vd);
00174 Demon* vb = MakeConstraintDemon0(solver(),
00175 this,
00176 &MapDomain::VarBound,
00177 "VarBound");
00178 var_->WhenBound(vb);
00179 scoped_ptr<IntVarIterator> it(var_->MakeDomainIterator(false));
00180 for (it->Init(); it->Ok(); it->Next()) {
00181 const int64 index = it->Value();
00182 if (index >= 0 && index < size_ && !actives_[index]->Bound()) {
00183 Demon* d = MakeConstraintDemon1(solver(),
00184 this,
00185 &MapDomain::UpdateActive,
00186 "UpdateActive",
00187 index);
00188 actives_[index]->WhenDomain(d);
00189 }
00190 }
00191 }
00192
00193 virtual void InitialPropagate() {
00194 for (int i = 0; i < size_; ++i) {
00195 actives_[i]->SetRange(0LL, 1LL);
00196 if (!var_->Contains(i)) {
00197 actives_[i]->SetValue(0);
00198 } else if (actives_[i]->Max() == 0LL) {
00199 var_->RemoveValue(i);
00200 }
00201 if (actives_[i]->Min() == 1LL) {
00202 var_->SetValue(i);
00203 }
00204 }
00205 if (var_->Bound()) {
00206 VarBound();
00207 }
00208 }
00209
00210 void UpdateActive(int64 index) {
00211 IntVar* const act = actives_[index];
00212 if (act->Max() == 0) {
00213 var_->RemoveValue(index);
00214 } else if (act->Min() == 1) {
00215 var_->SetValue(index);
00216 }
00217 }
00218
00219 void VarDomain() {
00220 const int64 oldmin = var_->OldMin();
00221 const int64 oldmax = var_->OldMax();
00222 const int64 vmin = var_->Min();
00223 const int64 vmax = var_->Max();
00224 const int64 size = size_;
00225 for (int64 j = std::max(oldmin, 0LL); j < std::min(vmin, size); ++j) {
00226 actives_[j]->SetValue(0);
00227 }
00228 for (holes_->Init(); holes_->Ok(); holes_->Next()) {
00229 const int64 j = holes_->Value();
00230 if (j >= 0 && j < size_) {
00231 actives_[j]->SetValue(0);
00232 }
00233 }
00234 for (int64 j = std::max(vmax + 1LL, 0LL);
00235 j <= std::min(oldmax, size_ - 1LL); ++j) {
00236 actives_[j]->SetValue(0LL);
00237 }
00238 }
00239
00240 void VarBound() {
00241 const int64 val = var_->Min();
00242 if (val >= 0 && val < size_) {
00243 actives_[val]->SetValue(1);
00244 }
00245 }
00246 virtual string DebugString() const {
00247 string out = "MapDomain(" + var_->DebugString() + ", [";
00248 for (int i = 0; i < size_; ++i) {
00249 out += actives_[i]->DebugString() + " ";
00250 }
00251 out += "])";
00252 return out;
00253 }
00254
00255 void Accept(ModelVisitor* const visitor) const {
00256 visitor->BeginVisitConstraint(ModelVisitor::kMapDomain, this);
00257 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00258 var_);
00259 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00260 actives_.get(),
00261 size_);
00262 visitor->EndVisitConstraint(ModelVisitor::kMapDomain, this);
00263 }
00264
00265 private:
00266 IntVar* const var_;
00267 scoped_array<IntVar*> actives_;
00268 int size_;
00269 IntVarIterator* holes_;
00270 };
00271 }
00272
00273 Constraint* Solver::MakeMapDomain(IntVar* const var, IntVar* const * actives,
00274 int size) {
00275 return RevAlloc(new MapDomain(this, var, actives, size));
00276 }
00277
00278 Constraint* Solver::MakeMapDomain(IntVar* const var,
00279 const std::vector<IntVar*>& actives) {
00280 return RevAlloc(new MapDomain(this, var, actives.data(), actives.size()));
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 namespace {
00298 class NoCycle : public Constraint {
00299 public:
00300 NoCycle(Solver* const s, const IntVar* const* nexts, int size,
00301 const IntVar* const* active,
00302 ResultCallback1<bool, int64>* sink_handler,
00303 bool owner,
00304 bool assume_paths);
00305 virtual ~NoCycle() {
00306 if (owner_) {
00307 delete sink_handler_;
00308 }
00309 }
00310 virtual void Post();
00311 virtual void InitialPropagate();
00312 void CheckSupport(int index);
00313 void ActiveBound(int index);
00314 void NextBound(int index);
00315 void ComputeSupports();
00316 virtual string DebugString() const;
00317
00318 void Accept(ModelVisitor* const visitor) const {
00319 visitor->BeginVisitConstraint(ModelVisitor::kNoCycle, this);
00320 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kNextsArgument,
00321 nexts_.get(),
00322 size_);
00323 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kActiveArgument,
00324 active_.get(),
00325 size_);
00326 visitor->VisitIntegerArgument("assume_paths", assume_paths_);
00327 visitor->VisitInt64ToBoolExtension(sink_handler_, -size_, size_);
00328 visitor->EndVisitConstraint(ModelVisitor::kNoCycle, this);
00329 }
00330
00331 private:
00332 const scoped_array<IntVar*> nexts_;
00333 const int size_;
00334 const scoped_array<IntVar*> active_;
00335 scoped_array<int64> starts_;
00336 scoped_array<int64> ends_;
00337 scoped_array<int64> outbound_supports_;
00338 ResultCallback1<bool, int64>* sink_handler_;
00339 std::vector<int64> sinks_;
00340 bool owner_;
00341 bool assume_paths_;
00342 };
00343
00344 NoCycle::NoCycle(Solver* const s, const IntVar* const* nexts, int size,
00345 const IntVar* const* active,
00346 ResultCallback1<bool, int64>* sink_handler, bool owner,
00347 bool assume_paths)
00348 : Constraint(s),
00349 nexts_(new IntVar*[size]),
00350 size_(size),
00351 active_(new IntVar*[size]),
00352 starts_(new int64[size]),
00353 ends_(new int64[size]),
00354 outbound_supports_(new int64[size]),
00355 sink_handler_(sink_handler),
00356 owner_(owner),
00357 assume_paths_(assume_paths) {
00358 CHECK_GE(size_, 0);
00359 if (size_ > 0) {
00360 memcpy(nexts_.get(), nexts, size_ * sizeof(*nexts));
00361 memcpy(active_.get(), active, size_ * sizeof(*active));
00362 }
00363 for (int i = 0; i < size; ++i) {
00364 starts_[i] = i;
00365 ends_[i] = i;
00366 outbound_supports_[i] = -1;
00367 }
00368 sink_handler_->CheckIsRepeatable();
00369 }
00370
00371 void NoCycle::InitialPropagate() {
00372
00373 for (int i = 0; i < size_; ++i) {
00374 IntVar* next = nexts_[i];
00375 for (int j = next->Min(); j < 0; ++j) {
00376 if (!sink_handler_->Run(j)) {
00377 next->RemoveValue(j);
00378 }
00379 }
00380 for (int j = next->Max(); j >= size_; --j) {
00381 if (!sink_handler_->Run(j)) {
00382 next->RemoveValue(j);
00383 }
00384 }
00385 }
00386 for (int i = 0; i < size_; ++i) {
00387 if (nexts_[i]->Bound()) {
00388 NextBound(i);
00389 }
00390 }
00391 ComputeSupports();
00392 }
00393
00394 void NoCycle::Post() {
00395 if (size_ == 0) return;
00396 for (int i = 0; i < size_; ++i) {
00397 IntVar* next = nexts_[i];
00398 Demon* d = MakeConstraintDemon1(solver(),
00399 this,
00400 &NoCycle::NextBound,
00401 "NextBound",
00402 i);
00403 next->WhenBound(d);
00404 Demon* support_demon = MakeConstraintDemon1(solver(),
00405 this,
00406 &NoCycle::CheckSupport,
00407 "CheckSupport",
00408 i);
00409 next->WhenDomain(support_demon);
00410 Demon* active_demon = MakeConstraintDemon1(solver(),
00411 this,
00412 &NoCycle::ActiveBound,
00413 "ActiveBound",
00414 i);
00415 active_[i]->WhenBound(active_demon);
00416 }
00417
00418 int64 min_min = nexts_[0]->Min();
00419 int64 max_max = nexts_[0]->Max();
00420 for (int i = 1; i < size_; ++i) {
00421 const IntVar* next = nexts_[i];
00422 min_min = std::min(min_min, next->Min());
00423 max_max = std::max(max_max, next->Max());
00424 }
00425 sinks_.clear();
00426 for (int i = min_min; i <= max_max; ++i) {
00427 if (sink_handler_->Run(i)) {
00428 sinks_.push_back(i);
00429 }
00430 }
00431 }
00432
00433 void NoCycle::CheckSupport(int index) {
00434
00435 if (!nexts_[index]->Contains(outbound_supports_[index])) {
00436 ComputeSupports();
00437 }
00438 }
00439
00440 void NoCycle::ActiveBound(int index) {
00441 if (nexts_[index]->Bound()) {
00442 NextBound(index);
00443 }
00444 }
00445
00446 void NoCycle::NextBound(int index) {
00447 if (active_[index]->Min() == 0) return;
00448 const int64 next = nexts_[index]->Value();
00449 const int64 chain_start = starts_[index];
00450 const int64 chain_end = !sink_handler_->Run(next) ? ends_[next] : next;
00451 Solver* const s = solver();
00452 s->SaveAndSetValue(&ends_[chain_start], chain_end);
00453 if (!sink_handler_->Run(chain_end)) {
00454 s->SaveAndSetValue(&starts_[chain_end], chain_start);
00455 nexts_[chain_end]->RemoveValue(chain_start);
00456 if (!assume_paths_) {
00457 for (int i = 0; i < size_; ++i) {
00458 int64 current = i;
00459 bool found = (current == chain_end);
00460
00461 int count = 0;
00462 while (!found
00463 && count < size_
00464 && !sink_handler_->Run(current)
00465 && nexts_[current]->Bound()) {
00466 current = nexts_[current]->Value();
00467 found = (current == chain_end);
00468 ++count;
00469 }
00470 if (found) {
00471 nexts_[chain_end]->RemoveValue(i);
00472 }
00473 }
00474 }
00475 }
00476 }
00477
00478
00479
00480
00481 void NoCycle::ComputeSupports() {
00482 scoped_array<int64> supported(new int64[size_]);
00483 int64 support_count = 0;
00484 for (int i = 0; i < size_; ++i) {
00485 if (nexts_[i]->Bound()) {
00486 supported[support_count] = i;
00487 outbound_supports_[i] = nexts_[i]->Value();
00488 ++support_count;
00489 } else {
00490 outbound_supports_[i] = -1;
00491 }
00492 }
00493 if (size_ == support_count) {
00494 return;
00495 }
00496 const int size = sinks_.size();
00497 for (int i = 0; i < size_; ++i) {
00498 const IntVar* next = nexts_[i];
00499 if (!nexts_[i]->Bound()) {
00500 for (int j = 0; j < size; ++j) {
00501 if (next->Contains(sinks_[j])) {
00502 supported[support_count] = i;
00503 outbound_supports_[i] = sinks_[j];
00504 ++support_count;
00505 break;
00506 }
00507 }
00508 }
00509 }
00510 for (int i = 0; i < support_count && support_count < size_; ++i) {
00511 const int64 supported_i = supported[i];
00512 for (int j = 0; j < size_; ++j) {
00513 if (outbound_supports_[j] < 0 && nexts_[j]->Contains(supported_i)) {
00514 supported[support_count] = j;
00515 outbound_supports_[j] = supported_i;
00516 ++support_count;
00517 }
00518 }
00519 }
00520 if (size_ != support_count) {
00521 supported.reset(NULL);
00522 for (int i = 0; i < size_; ++i) {
00523 if (outbound_supports_[i] < 0) {
00524 active_[i]->SetMax(0);
00525 }
00526 }
00527 }
00528 }
00529
00530 string NoCycle::DebugString() const {
00531 string out = "NoCycle(";
00532 for (int i = 0; i < size_; ++i) {
00533 out += nexts_[i]->DebugString() + " ";
00534 }
00535 out += ")";
00536 return out;
00537 }
00538
00539 bool GreaterThan(int64 x, int64 y) {
00540 return y >= x;
00541 }
00542 }
00543
00544 Constraint* Solver::MakeNoCycle(const std::vector<IntVar*>& nexts,
00545 const std::vector<IntVar*>& active,
00546 ResultCallback1<bool, int64>* sink_handler,
00547 bool assume_paths) {
00548 CHECK_EQ(nexts.size(), active.size());
00549 return MakeNoCycle(nexts.data(),
00550 active.data(),
00551 nexts.size(),
00552 sink_handler,
00553 assume_paths);
00554 }
00555
00556 Constraint* Solver::MakeNoCycle(const IntVar* const* nexts,
00557 const IntVar* const* active,
00558 int size,
00559 ResultCallback1<bool, int64>* sink_handler,
00560 bool assume_paths) {
00561 if (sink_handler == NULL) {
00562 sink_handler = NewPermanentCallback(&GreaterThan,
00563 static_cast<int64>(size));
00564 }
00565 return RevAlloc(new NoCycle(this,
00566 nexts,
00567 size,
00568 active,
00569 sink_handler,
00570 true,
00571 assume_paths));
00572 }
00573
00574 Constraint* Solver::MakeNoCycle(const std::vector<IntVar*>& nexts,
00575 const std::vector<IntVar*>& active,
00576 ResultCallback1<bool, int64>* sink_handler) {
00577 return MakeNoCycle(nexts, active, sink_handler, true);
00578 }
00579
00580 Constraint* Solver::MakeNoCycle(const IntVar* const* nexts,
00581 const IntVar* const* active,
00582 int size,
00583 ResultCallback1<bool, int64>* sink_handler) {
00584 return MakeNoCycle(nexts, active, size, sink_handler, true);
00585 }
00586
00587
00588
00589
00590
00591 namespace {
00592 class PathCumul : public Constraint {
00593 public:
00594 PathCumul(Solver* const s,
00595 const IntVar* const* nexts, int size,
00596 const IntVar* const* active,
00597 const IntVar* const* cumuls, int cumul_size,
00598 const IntVar* const* transits);
00599 virtual ~PathCumul() {}
00600 virtual void Post();
00601 virtual void InitialPropagate();
00602 void ActiveBound(int index);
00603 void NextBound(int index);
00604 bool AcceptLink(int i, int j) const;
00605 void UpdateSupport(int index);
00606 void CumulRange(int index);
00607 void TransitRange(int index);
00608 virtual string DebugString() const;
00609
00610 void Accept(ModelVisitor* const visitor) const {
00611 visitor->BeginVisitConstraint(ModelVisitor::kPathCumul, this);
00612 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kNextsArgument,
00613 nexts_.get(),
00614 size_);
00615 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kActiveArgument,
00616 active_.get(),
00617 size_);
00618 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCumulsArgument,
00619 cumuls_.get(),
00620 cumul_size_);
00621 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kTransitsArgument,
00622 transits_.get(),
00623 size_);
00624 visitor->EndVisitConstraint(ModelVisitor::kPathCumul, this);
00625 }
00626
00627 private:
00628 scoped_array<IntVar*> nexts_;
00629 int size_;
00630 scoped_array<IntVar*> active_;
00631 scoped_array<IntVar*> cumuls_;
00632 int cumul_size_;
00633 scoped_array<IntVar*> transits_;
00634 RevArray<int> prevs_;
00635 scoped_array<int> supports_;
00636 };
00637
00638 PathCumul::PathCumul(Solver* const s,
00639 const IntVar* const* nexts, int size,
00640 const IntVar* const* active,
00641 const IntVar* const* cumuls, int cumul_size,
00642 const IntVar* const* transits)
00643 : Constraint(s),
00644 nexts_(NULL),
00645 size_(size),
00646 active_(NULL),
00647 cumuls_(NULL),
00648 cumul_size_(cumul_size),
00649 prevs_(cumul_size, -1),
00650 supports_(new int[size]) {
00651 CHECK_GE(size_, 0);
00652 if (size_ > 0) {
00653 nexts_.reset(new IntVar*[size_]);
00654 memcpy(nexts_.get(), nexts, size_ * sizeof(*nexts));
00655 active_.reset(new IntVar*[size_]);
00656 memcpy(active_.get(), active, size_ * sizeof(*active));
00657 transits_.reset(new IntVar*[size_]);
00658 memcpy(transits_.get(), transits, size_ * sizeof(*transits));
00659 }
00660 CHECK_GE(cumul_size_, 0);
00661 CHECK_GE(cumul_size_, size_);
00662 if (cumul_size_ > 0) {
00663 cumuls_.reset(new IntVar*[cumul_size_]);
00664 memcpy(cumuls_.get(), cumuls, cumul_size_ * sizeof(*cumuls));
00665 }
00666 for (int i = 0; i < size_; ++i) {
00667 supports_[i] = -1;
00668 }
00669 }
00670
00671 void PathCumul::InitialPropagate() {
00672 for (int i = 0; i < size_; ++i) {
00673 if (nexts_[i]->Bound()) {
00674 NextBound(i);
00675 } else {
00676 UpdateSupport(i);
00677 }
00678 }
00679 }
00680
00681 void PathCumul::Post() {
00682 for (int i = 0; i < size_; ++i) {
00683 IntVar* var = nexts_[i];
00684 Demon* d = MakeConstraintDemon1(solver(),
00685 this,
00686 &PathCumul::NextBound,
00687 "NextBound",
00688 i);
00689 var->WhenBound(d);
00690 Demon* ds = MakeConstraintDemon1(solver(),
00691 this,
00692 &PathCumul::UpdateSupport,
00693 "UpdateSupport",
00694 i);
00695 var->WhenDomain(ds);
00696 Demon* active_demon = MakeConstraintDemon1(solver(),
00697 this,
00698 &PathCumul::ActiveBound,
00699 "ActiveBound",
00700 i);
00701 active_[i]->WhenBound(active_demon);
00702 Demon* transit_demon = MakeConstraintDemon1(solver(),
00703 this,
00704 &PathCumul::TransitRange,
00705 "TransitRange",
00706 i);
00707 transits_[i]->WhenRange(transit_demon);
00708 }
00709 for (int i = 0; i < cumul_size_; ++i) {
00710 IntVar* cumul = cumuls_[i];
00711 Demon* d = MakeConstraintDemon1(solver(),
00712 this,
00713 &PathCumul::CumulRange,
00714 "CumulRange",
00715 i);
00716 cumul->WhenRange(d);
00717 }
00718 }
00719
00720 void PathCumul::ActiveBound(int index) {
00721 if (nexts_[index]->Bound()) {
00722 NextBound(index);
00723 }
00724 }
00725
00726 void PathCumul::NextBound(int index) {
00727 if (active_[index]->Min() == 0) return;
00728 const int64 next = nexts_[index]->Value();
00729 IntVar* cumul = cumuls_[index];
00730 IntVar* cumul_next = cumuls_[next];
00731 IntVar* transit = transits_[index];
00732 cumul_next->SetMin(cumul->Min() + transit->Min());
00733 const int64 cumul_next_max = cumul->Max() + transit->Max();
00734 if (cumul_next_max >= 0) {
00735 cumul_next->SetMax(cumul_next_max);
00736 }
00737 cumul->SetMin(cumul_next->Min() - transit->Max());
00738 cumul->SetMax(cumul_next->Max() - transit->Min());
00739 transit->SetMin(cumul_next->Min() - cumul->Max());
00740 transit->SetMax(cumul_next->Max() - cumul->Min());
00741 if (prevs_[next] < 0) {
00742 prevs_.SetValue(solver(), next, index);
00743 }
00744 }
00745
00746 void PathCumul::CumulRange(int index) {
00747 if (index < size_) {
00748 if (nexts_[index]->Bound()) {
00749 NextBound(index);
00750 } else {
00751 UpdateSupport(index);
00752 }
00753 }
00754 if (prevs_[index] >= 0) {
00755 NextBound(prevs_[index]);
00756 } else {
00757 for (int i = 0; i < size_; ++i) {
00758 if (index == supports_[i]) {
00759 UpdateSupport(i);
00760 }
00761 }
00762 }
00763 }
00764
00765 void PathCumul::TransitRange(int index) {
00766 if (nexts_[index]->Bound()) {
00767 NextBound(index);
00768 } else {
00769 UpdateSupport(index);
00770 }
00771 if (prevs_[index] >= 0) {
00772 NextBound(prevs_[index]);
00773 } else {
00774 for (int i = 0; i < size_; ++i) {
00775 if (index == supports_[i]) {
00776 UpdateSupport(i);
00777 }
00778 }
00779 }
00780 }
00781
00782 bool PathCumul::AcceptLink(int i, int j) const {
00783 const IntVar* const cumul_i = cumuls_[i];
00784 const IntVar* const cumul_j = cumuls_[j];
00785 const IntVar* const transit_i = transits_[i];
00786 return transit_i->Min() <= cumul_j->Max() - cumul_i->Min()
00787 && cumul_j->Min() - cumul_i->Max() <= transit_i->Max();
00788 }
00789
00790 void PathCumul::UpdateSupport(int index) {
00791 int support = supports_[index];
00792 if (support < 0 || !AcceptLink(index, support)) {
00793 IntVar* var = nexts_[index];
00794 for (int i = var->Min(); i <= var->Max(); ++i) {
00795 if (i != support && AcceptLink(index, i)) {
00796 supports_[index] = i;
00797 return;
00798 }
00799 }
00800 active_[index]->SetMax(0);
00801 }
00802 }
00803
00804 string PathCumul::DebugString() const {
00805 string out = "PathCumul(";
00806 for (int i = 0; i < size_; ++i) {
00807 out += nexts_[i]->DebugString() + " " + cumuls_[i]->DebugString();
00808 }
00809 out += ")";
00810 return out;
00811 }
00812 }
00813
00814 Constraint* Solver::MakePathCumul(const std::vector<IntVar*>& nexts,
00815 const std::vector<IntVar*>& active,
00816 const std::vector<IntVar*>& cumuls,
00817 const std::vector<IntVar*>& transits) {
00818 CHECK_EQ(nexts.size(), active.size());
00819 CHECK_EQ(transits.size(), nexts.size());
00820 return RevAlloc(new PathCumul(this,
00821 nexts.data(), nexts.size(),
00822 active.data(),
00823 cumuls.data(), cumuls.size(),
00824 transits.data()));
00825 }
00826
00827 Constraint* Solver::MakePathCumul(const IntVar* const* nexts,
00828 const IntVar* const* active,
00829 const IntVar* const* cumuls,
00830 const IntVar* const* transits,
00831 int next_size,
00832 int cumul_size) {
00833 return RevAlloc(new PathCumul(this,
00834 nexts, next_size,
00835 active,
00836 cumuls, cumul_size,
00837 transits));
00838 }
00839
00840 }