00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <string.h>
00024 #include <algorithm>
00025 #include "base/hash.h"
00026 #include <string>
00027 #include <vector>
00028
00029 #include "base/commandlineflags.h"
00030 #include "base/integral_types.h"
00031 #include "base/logging.h"
00032 #include "base/macros.h"
00033 #include "base/scoped_ptr.h"
00034 #include "base/stringprintf.h"
00035 #include "base/join.h"
00036 #include "base/stl_util.h"
00037 #include "base/mathutil.h"
00038 #include "constraint_solver/constraint_solver.h"
00039 #include "constraint_solver/constraint_solveri.h"
00040 #include "util/bitset.h"
00041 #include "util/monoid_operation_tree.h"
00042
00043
00044
00045 DEFINE_bool(cp_use_cumulative_edge_finder, true,
00046 "Use the O(n log n) cumulative edge finding algorithm described "
00047 "in 'Edge Finding Filtering Algorithm for Discrete Cumulative "
00048 "Resources in O(kn log n)' by Petr Vilim, CP 2009.");
00049 DEFINE_bool(cp_use_cumulative_time_table, true,
00050 "Use a O(n^2) cumulative time table propagation algorithm.");
00051 DEFINE_bool(cp_use_sequence_high_demand_tasks, true,
00052 "Use a sequence constraints for cumulative tasks that have a "
00053 "demand greater than half of the capacity of the resource.");
00054 DEFINE_bool(cp_use_all_possible_disjunctions, true,
00055 "Post temporal disjunctions for all pairs of tasks sharing a "
00056 "cumulative resource and that cannot overlap because the sum of "
00057 "their demand exceeds the capacity.");
00058
00059 namespace operations_research {
00060 namespace {
00061
00062
00063
00064
00065
00066
00067
00068
00069 class DisjunctiveTask : public BaseObject {
00070 public:
00071 explicit DisjunctiveTask(IntervalVar* const interval) : interval_(interval) {}
00072
00073
00074 DisjunctiveTask(const DisjunctiveTask& task) : interval_(task.interval_) {}
00075 const IntervalVar* const interval() const { return interval_; }
00076 IntervalVar* const mutable_interval() { return interval_; }
00077 virtual string DebugString() const {
00078 return interval()->DebugString();
00079 }
00080 private:
00081 IntervalVar* const interval_;
00082 };
00083
00084
00085
00086
00087
00088
00089
00090
00091 class CumulativeTask : public BaseObject {
00092 public:
00093 CumulativeTask(IntervalVar* const interval, int64 demand)
00094 : interval_(interval),
00095 demand_(demand) {}
00096
00097
00098 CumulativeTask(const CumulativeTask& task)
00099 : interval_(task.interval_), demand_(task.demand_) {}
00100
00101 const IntervalVar* const interval() const { return interval_; }
00102 IntervalVar* const mutable_interval() { return interval_; }
00103 int64 demand() const { return demand_; }
00104 int64 EnergyMin() const { return interval_->DurationMin() * demand_; }
00105 virtual string DebugString() const {
00106 return StringPrintf("Task{ %s, demand: %" GG_LL_FORMAT "d }",
00107 interval_->DebugString().c_str(), demand_);
00108 }
00109 private:
00110 IntervalVar* const interval_;
00111 const int64 demand_;
00112 };
00113
00114
00115
00116 template <class Task>
00117 class IndexedTask {
00118 public:
00119 static const int kUnknown;
00120 explicit IndexedTask(Task task) : task_(task), start_min_index_(kUnknown) {}
00121
00122 IntervalVar* const mutable_interval() { return task_.mutable_interval(); }
00123 const IntervalVar* const interval() const { return task_.interval(); }
00124 const Task& task() const { return task_; }
00125 int start_min_index() const { return start_min_index_; }
00126 void set_start_min_index(int pos) { start_min_index_ = pos; }
00127
00128
00129 int64 StartMin() const { return interval()->StartMin(); }
00130 int64 StartMax() const { return interval()->StartMax(); }
00131 int64 EndMin() const { return interval()->EndMin(); }
00132 int64 EndMax() const { return interval()->EndMax(); }
00133
00134 string DebugString() const {
00135 return StringPrintf("Wrapper(%s, start_min_index = %d)",
00136 task_->DebugString().c_str(), start_min_index_);
00137 }
00138
00139 private:
00140 Task task_;
00141 int start_min_index_;
00142 DISALLOW_COPY_AND_ASSIGN(IndexedTask<Task>);
00143 };
00144
00145 template <class Task> const int IndexedTask<Task>::kUnknown = -1;
00146
00147 typedef IndexedTask<DisjunctiveTask> DisjunctiveIndexedTask;
00148 typedef IndexedTask<CumulativeTask> CumulativeIndexedTask;
00149
00150
00151 template<class Task>
00152 bool StartMinLessThan(const IndexedTask<Task>* const w1,
00153 const IndexedTask<Task>* const w2) {
00154 return (w1->StartMin() < w2->StartMin());
00155 }
00156
00157 template<class Task>
00158 bool EndMaxLessThan(const IndexedTask<Task>* const w1,
00159 const IndexedTask<Task>* const w2) {
00160 return (w1->EndMax() < w2->EndMax());
00161 }
00162
00163 template<class Task>
00164 bool StartMaxLessThan(const IndexedTask<Task>* const w1,
00165 const IndexedTask<Task>* const w2) {
00166 return (w1->StartMax() < w2->StartMax());
00167 }
00168
00169 template<class Task>
00170 bool EndMinLessThan(const IndexedTask<Task>* const w1,
00171 const IndexedTask<Task>* const w2) {
00172 return (w1->EndMin() < w2->EndMin());
00173 }
00174
00175 template<typename T, typename Compare>
00176 void Sort(std::vector<T>* vector, Compare compare) {
00177 std::sort(vector->begin(), vector->end(), compare);
00178 }
00179
00180 bool TaskStartMinLessThan(const CumulativeTask* const task1,
00181 const CumulativeTask* const task2) {
00182 return (task1->interval()->StartMin() < task2->interval()->StartMin());
00183 }
00184
00185
00186
00187
00188
00189 class ThetaNode {
00190 public:
00191
00192 ThetaNode() : total_processing_(0), total_ect_(kint64min) {}
00193
00194 explicit ThetaNode(const IntervalVar* const interval)
00195 : total_processing_(interval->DurationMin()),
00196 total_ect_(interval->EndMin()) {}
00197 void Set(const ThetaNode& node) {
00198 total_ect_ = node.total_ect_;
00199 total_processing_ = node.total_processing_;
00200 }
00201 void Compute(const ThetaNode& left, const ThetaNode& right) {
00202 total_processing_ = left.total_processing_ + right.total_processing_;
00203 total_ect_ = std::max(left.total_ect_ + right.total_processing_,
00204 right.total_ect_);
00205 }
00206 int64 total_ect() const { return total_ect_; }
00207 bool IsIdentity() const {
00208 return total_processing_ == 0LL && total_ect_ == kint64min;
00209 }
00210 string DebugString() const {
00211 return StringPrintf(
00212 "ThetaNode{ p = %" GG_LL_FORMAT "d, e = %" GG_LL_FORMAT "d }",
00213 total_processing_, total_ect_ < 0LL ? -1LL : total_ect_);
00214 }
00215
00216 private:
00217 int64 total_processing_;
00218 int64 total_ect_;
00219 DISALLOW_COPY_AND_ASSIGN(ThetaNode);
00220 };
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 class ThetaTree : public MonoidOperationTree<ThetaNode> {
00232 public:
00233 explicit ThetaTree(int size)
00234 : MonoidOperationTree<ThetaNode>(size) {}
00235 virtual ~ThetaTree() {}
00236 int64 ECT() const { return result().total_ect(); }
00237 void Insert(const DisjunctiveIndexedTask* const indexed_task) {
00238 ThetaNode thetaNode(indexed_task->interval());
00239 Set(indexed_task->start_min_index(), thetaNode);
00240 }
00241 void Remove(const DisjunctiveIndexedTask* indexed_task) {
00242 Reset(indexed_task->start_min_index());
00243 }
00244 bool IsInserted(const DisjunctiveIndexedTask* const indexed_task) const {
00245 return !GetOperand(indexed_task->start_min_index()).IsIdentity();
00246 }
00247 private:
00248 DISALLOW_COPY_AND_ASSIGN(ThetaTree);
00249 };
00250
00251
00252
00253
00254
00255
00256
00257 class LambdaThetaNode {
00258 public:
00259
00260 static const int kNone;
00261
00262
00263 LambdaThetaNode()
00264 : energy_(0LL),
00265 energetic_end_min_(kint64min),
00266 energy_opt_(0LL),
00267 argmax_energy_opt_(kNone),
00268 energetic_end_min_opt_(kint64min),
00269 argmax_energetic_end_min_opt_(kNone) {}
00270
00271
00272 LambdaThetaNode(int64 capacity, const CumulativeTask& task)
00273 : energy_(task.EnergyMin()),
00274 energetic_end_min_(capacity * task.interval()->StartMin() + energy_),
00275 energy_opt_(energy_),
00276 argmax_energy_opt_(kNone),
00277 energetic_end_min_opt_(energetic_end_min_),
00278 argmax_energetic_end_min_opt_(kNone) {}
00279
00280
00281 LambdaThetaNode(int64 capacity, const CumulativeTask& task, int index)
00282 : energy_(0LL),
00283 energetic_end_min_(kint64min),
00284 energy_opt_(task.EnergyMin()),
00285 argmax_energy_opt_(index),
00286 energetic_end_min_opt_(capacity * task.interval()->StartMin() +
00287 energy_opt_),
00288 argmax_energetic_end_min_opt_(index) {
00289 DCHECK_GE(index, 0);
00290 }
00291
00292
00293 explicit LambdaThetaNode(const IntervalVar* const interval)
00294 : energy_(interval->DurationMin()),
00295 energetic_end_min_(interval->EndMin()),
00296 energy_opt_(interval->DurationMin()),
00297 argmax_energy_opt_(kNone),
00298 energetic_end_min_opt_(interval->EndMin()),
00299 argmax_energetic_end_min_opt_(kNone) {}
00300
00301
00302
00303 LambdaThetaNode(const IntervalVar* const interval, int index)
00304 : energy_(0LL),
00305 energetic_end_min_(kint64min),
00306 energy_opt_(interval->DurationMin()),
00307 argmax_energy_opt_(index),
00308 energetic_end_min_opt_(interval->EndMin()),
00309 argmax_energetic_end_min_opt_(index) {
00310 DCHECK_GE(index, 0);
00311 }
00312
00313
00314 int64 energetic_end_min() const { return energetic_end_min_; }
00315 int64 energetic_end_min_opt() const { return energetic_end_min_opt_; }
00316 int argmax_energetic_end_min_opt() const {
00317 return argmax_energetic_end_min_opt_;
00318 }
00319
00320
00321 void Set(const LambdaThetaNode& node) {
00322 energy_ = node.energy_;
00323 energetic_end_min_ = node.energetic_end_min_;
00324 energy_opt_ = node.energy_opt_;
00325 argmax_energy_opt_ = node.argmax_energy_opt_;
00326 energetic_end_min_opt_ = node.energetic_end_min_opt_;
00327 argmax_energetic_end_min_opt_ =
00328 node.argmax_energetic_end_min_opt_;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338 void Compute(const LambdaThetaNode& left, const LambdaThetaNode& right) {
00339 energy_ = left.energy_ + right.energy_;
00340 energetic_end_min_ = std::max(right.energetic_end_min_,
00341 left.energetic_end_min_ + right.energy_);
00342 const int64 energy_left_opt = left.energy_opt_ + right.energy_;
00343 const int64 energy_right_opt = left.energy_ + right.energy_opt_;
00344 if (energy_left_opt > energy_right_opt) {
00345 energy_opt_ = energy_left_opt;
00346 argmax_energy_opt_ = left.argmax_energy_opt_;
00347 } else {
00348 energy_opt_ = energy_right_opt;
00349 argmax_energy_opt_ = right.argmax_energy_opt_;
00350 }
00351 const int64 ect1 = right.energetic_end_min_opt_;
00352 const int64 ect2 = left.energetic_end_min_ + right.energy_opt_;
00353 const int64 ect3 = left.energetic_end_min_opt_ + right.energy_;
00354 if (ect1 >= ect2 && ect1 >= ect3) {
00355 energetic_end_min_opt_ = ect1;
00356 argmax_energetic_end_min_opt_ = right.argmax_energetic_end_min_opt_;
00357 } else if (ect2 >= ect1 && ect2 >= ect3) {
00358 energetic_end_min_opt_ = ect2;
00359 argmax_energetic_end_min_opt_ = right.argmax_energy_opt_;
00360 } else {
00361 energetic_end_min_opt_ = ect3;
00362 argmax_energetic_end_min_opt_ = left.argmax_energetic_end_min_opt_;
00363 }
00364
00365
00366 DCHECK(energy_opt_ >= energy_);
00367
00368
00369
00370 DCHECK((argmax_energy_opt_ != kNone) || (energy_opt_ == energy_));
00371 }
00372
00373 private:
00374
00375
00376 int64 energy_;
00377
00378
00379 int64 energetic_end_min_;
00380
00381
00382 int64 energy_opt_;
00383
00384
00385
00386 int argmax_energy_opt_;
00387
00388
00389
00390 int64 energetic_end_min_opt_;
00391
00392
00393
00394 int argmax_energetic_end_min_opt_;
00395 };
00396
00397 const int LambdaThetaNode::kNone = -1;
00398
00399
00400 class DisjunctiveLambdaThetaTree : public MonoidOperationTree<LambdaThetaNode> {
00401 public:
00402 explicit DisjunctiveLambdaThetaTree(int size)
00403 : MonoidOperationTree<LambdaThetaNode>(size) {}
00404 virtual ~DisjunctiveLambdaThetaTree() {}
00405 void Insert(const DisjunctiveIndexedTask* indexed_task) {
00406 LambdaThetaNode lambdaThetaNode(indexed_task->interval());
00407 Set(indexed_task->start_min_index(), lambdaThetaNode);
00408 }
00409 void Grey(const DisjunctiveIndexedTask* const indexed_task) {
00410 const IntervalVar* const interval = indexed_task->interval();
00411 const int start_min_index = indexed_task->start_min_index();
00412 LambdaThetaNode greyNode(interval, start_min_index);
00413 Set(indexed_task->start_min_index(), greyNode);
00414 }
00415 int64 ECT() const { return result().energetic_end_min(); }
00416 int64 ECT_opt() const { return result().energetic_end_min_opt(); }
00417 int Responsible_opt() const {
00418 return result().argmax_energetic_end_min_opt();
00419 }
00420
00421 private:
00422 DISALLOW_COPY_AND_ASSIGN(DisjunctiveLambdaThetaTree);
00423 };
00424
00425
00426 class CumulativeLambdaThetaTree : public MonoidOperationTree<LambdaThetaNode> {
00427 public:
00428 CumulativeLambdaThetaTree(int size, int64 capacity)
00429 : MonoidOperationTree<LambdaThetaNode>(size),
00430 capacity_(capacity) {}
00431 virtual ~CumulativeLambdaThetaTree() {}
00432 void Insert(const CumulativeIndexedTask* indexed_task) {
00433 LambdaThetaNode lambdaThetaNode(capacity_, indexed_task->task());
00434 Set(indexed_task->start_min_index(), lambdaThetaNode);
00435 }
00436 void Grey(const CumulativeIndexedTask* indexed_task) {
00437 const CumulativeTask& task = indexed_task->task();
00438 const int start_min_index = indexed_task->start_min_index();
00439 LambdaThetaNode greyNode(capacity_, task, start_min_index);
00440 Set(indexed_task->start_min_index(), greyNode);
00441 }
00442 int64 energetic_end_min() const { return result().energetic_end_min(); }
00443 int64 energetic_end_min_opt() const {
00444 return result().energetic_end_min_opt();
00445 }
00446 int64 ECT() const {
00447 return MathUtil::CeilOfRatio(energetic_end_min(), capacity_);
00448 }
00449 int64 ECT_opt() const {
00450 return MathUtil::CeilOfRatio(result().energetic_end_min_opt(), capacity_);
00451 }
00452 int argmax_energetic_end_min_opt() const {
00453 return result().argmax_energetic_end_min_opt();
00454 }
00455
00456 private:
00457 const int64 capacity_;
00458 DISALLOW_COPY_AND_ASSIGN(CumulativeLambdaThetaTree);
00459 };
00460
00461
00462
00463
00464
00465
00466 class NotLast {
00467 public:
00468 NotLast(Solver* const solver,
00469 IntervalVar* const * intervals,
00470 int size,
00471 bool mirror);
00472 ~NotLast() {
00473 STLDeleteElements(&by_start_min_);
00474 }
00475 bool Propagate();
00476
00477 private:
00478 const int size_;
00479 ThetaTree theta_tree_;
00480 std::vector<DisjunctiveIndexedTask*> by_start_min_;
00481 std::vector<DisjunctiveIndexedTask*> by_end_max_;
00482 std::vector<DisjunctiveIndexedTask*> by_start_max_;
00483 std::vector<int64> new_lct_;
00484 DISALLOW_COPY_AND_ASSIGN(NotLast);
00485 };
00486
00487 NotLast::NotLast(Solver* const solver,
00488 IntervalVar* const * intervals,
00489 int size,
00490 bool mirror)
00491 : size_(size),
00492 theta_tree_(size),
00493 by_start_min_(size),
00494 by_end_max_(size),
00495 by_start_max_(size),
00496 new_lct_(size, -1LL) {
00497 CHECK_GE(size_, 0);
00498
00499 for (int i = 0; i < size; ++i) {
00500 IntervalVar* const underlying = mirror ?
00501 solver->MakeMirrorInterval(intervals[i]) :
00502 intervals[i];
00503 IntervalVar* const relaxed = solver->MakeIntervalRelaxedMin(underlying);
00504 by_start_min_[i] = new DisjunctiveIndexedTask(DisjunctiveTask(relaxed));
00505 by_end_max_[i] = by_start_min_[i];
00506 by_start_max_[i] = by_start_min_[i];
00507 }
00508 }
00509
00510 bool NotLast::Propagate() {
00511
00512 Sort(&by_start_max_, StartMaxLessThan<DisjunctiveTask>);
00513 Sort(&by_end_max_, EndMaxLessThan<DisjunctiveTask>);
00514
00515 Sort(&by_start_min_, StartMinLessThan<DisjunctiveTask>);
00516 for (int i = 0; i < size_; ++i) {
00517 by_start_min_[i]->set_start_min_index(i);
00518 }
00519 theta_tree_.Clear();
00520 for (int i = 0; i < size_; ++i) {
00521 new_lct_[i] = by_start_min_[i]->EndMax();
00522 }
00523
00524
00525 int j = 0;
00526 for (int i = 0; i < size_; ++i) {
00527 DisjunctiveIndexedTask* const twi = by_end_max_[i];
00528 while (j < size_ &&
00529 twi->EndMax() > by_start_max_[j]->StartMax()) {
00530 if (j > 0 && theta_tree_.ECT() > by_start_max_[j]->StartMax()) {
00531 const int64 new_end_max = by_start_max_[j - 1]->StartMax();
00532 new_lct_[by_start_max_[j]->start_min_index()] = new_end_max;
00533 }
00534 theta_tree_.Insert(by_start_max_[j]);
00535 j++;
00536 }
00537 const bool inserted = theta_tree_.IsInserted(twi);
00538 if (inserted) {
00539 theta_tree_.Remove(twi);
00540 }
00541 const int64 ect_theta_less_i = theta_tree_.ECT();
00542 if (inserted) {
00543 theta_tree_.Insert(twi);
00544 }
00545 if (ect_theta_less_i > twi->EndMax() && j > 0) {
00546 const int64 new_end_max = by_start_max_[j - 1]->EndMax();
00547 if (new_end_max > new_lct_[twi->start_min_index()]) {
00548 new_lct_[twi->start_min_index()] = new_end_max;
00549 }
00550 }
00551 }
00552
00553
00554 bool modified = false;
00555 for (int i = 0; i < size_; ++i) {
00556 if (by_start_min_[i]->EndMax() > new_lct_[i]) {
00557 modified = true;
00558 by_start_min_[i]->mutable_interval()->SetEndMax(new_lct_[i]);
00559 }
00560 }
00561 return modified;
00562 }
00563
00564
00565
00566
00567
00568
00569 class EdgeFinderAndDetectablePrecedences {
00570 public:
00571 EdgeFinderAndDetectablePrecedences(Solver* const solver,
00572 IntervalVar* const * intervals,
00573 int size,
00574 bool mirror);
00575 ~EdgeFinderAndDetectablePrecedences() {
00576 STLDeleteElements(&by_start_min_);
00577 }
00578 int size() const { return size_; }
00579 IntervalVar* mutable_interval(int start_min_index) {
00580 return by_start_min_[start_min_index]->mutable_interval();
00581 }
00582 void UpdateEst();
00583 void OverloadChecking();
00584 bool DetectablePrecedences();
00585 bool EdgeFinder();
00586
00587 private:
00588 Solver* const solver_;
00589 const int size_;
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 ThetaTree theta_tree_;
00601 std::vector<DisjunctiveIndexedTask*> by_end_min_;
00602 std::vector<DisjunctiveIndexedTask*> by_start_min_;
00603 std::vector<DisjunctiveIndexedTask*> by_end_max_;
00604 std::vector<DisjunctiveIndexedTask*> by_start_max_;
00605
00606 std::vector<int64> new_est_;
00607
00608 std::vector<int64> new_lct_;
00609 DisjunctiveLambdaThetaTree lt_tree_;
00610 };
00611
00612 EdgeFinderAndDetectablePrecedences::EdgeFinderAndDetectablePrecedences(
00613 Solver* const solver,
00614 IntervalVar* const * intervals,
00615 int size,
00616 bool mirror)
00617 : solver_(solver), size_(size), theta_tree_(size), lt_tree_(size) {
00618
00619 for (int i = 0; i < size; ++i) {
00620 IntervalVar* const underlying = mirror ?
00621 solver->MakeMirrorInterval(intervals[i]) :
00622 intervals[i];
00623 IntervalVar* const relaxed = solver->MakeIntervalRelaxedMax(underlying);
00624 DisjunctiveIndexedTask* const w =
00625 new DisjunctiveIndexedTask(DisjunctiveTask(relaxed));
00626 by_end_min_.push_back(w);
00627 by_start_min_.push_back(w);
00628 by_end_max_.push_back(w);
00629 by_start_max_.push_back(w);
00630 new_est_.push_back(kint64min);
00631 }
00632 }
00633
00634 void EdgeFinderAndDetectablePrecedences::UpdateEst() {
00635 Sort(&by_start_min_, StartMinLessThan<DisjunctiveTask>);
00636 for (int i = 0; i < size_; ++i) {
00637 by_start_min_[i]->set_start_min_index(i);
00638 }
00639 }
00640
00641 void EdgeFinderAndDetectablePrecedences::OverloadChecking() {
00642
00643 UpdateEst();
00644 Sort(&by_end_max_, EndMaxLessThan<DisjunctiveTask>);
00645 theta_tree_.Clear();
00646
00647 for (int i = 0; i < size_; ++i) {
00648 DisjunctiveIndexedTask* const indexed_task = by_end_max_[i];
00649 theta_tree_.Insert(indexed_task);
00650 if (theta_tree_.ECT() > indexed_task->EndMax()) {
00651 solver_->Fail();
00652 }
00653 }
00654 }
00655
00656 bool EdgeFinderAndDetectablePrecedences::DetectablePrecedences() {
00657
00658 UpdateEst();
00659 for (int i = 0; i < size_; ++i) {
00660 new_est_[i] = kint64min;
00661 }
00662
00663
00664 Sort(&by_end_min_, EndMinLessThan<DisjunctiveTask>);
00665 Sort(&by_start_max_, StartMaxLessThan<DisjunctiveTask>);
00666 theta_tree_.Clear();
00667 int j = 0;
00668 for (int i = 0; i < size_; ++i) {
00669 DisjunctiveIndexedTask* const task_i = by_end_min_[i];
00670 if (j < size_) {
00671 DisjunctiveIndexedTask* task_j = by_start_max_[j];
00672 while (task_i->EndMin() > task_j->StartMax()) {
00673 theta_tree_.Insert(task_j);
00674 j++;
00675 if (j == size_)
00676 break;
00677 task_j = by_start_max_[j];
00678 }
00679 }
00680 const int64 esti = task_i->StartMin();
00681 bool inserted = theta_tree_.IsInserted(task_i);
00682 if (inserted) {
00683 theta_tree_.Remove(task_i);
00684 }
00685 const int64 oesti = theta_tree_.ECT();
00686 if (inserted) {
00687 theta_tree_.Insert(task_i);
00688 }
00689 if (oesti > esti) {
00690 new_est_[task_i->start_min_index()] = oesti;
00691 } else {
00692 new_est_[task_i->start_min_index()] = kint64min;
00693 }
00694 }
00695
00696
00697 bool modified = false;
00698 for (int i = 0; i < size_; ++i) {
00699 if (new_est_[i] != kint64min) {
00700 modified = true;
00701 by_start_min_[i]->mutable_interval()->SetStartMin(new_est_[i]);
00702 }
00703 }
00704 return modified;
00705 }
00706
00707 bool EdgeFinderAndDetectablePrecedences::EdgeFinder() {
00708
00709 UpdateEst();
00710 for (int i = 0; i < size_; ++i) {
00711 new_est_[i] = by_start_min_[i]->StartMin();
00712 }
00713
00714
00715 Sort(&by_end_max_, EndMaxLessThan<DisjunctiveTask>);
00716 lt_tree_.Clear();
00717 for (int i = 0; i < size_; ++i) {
00718 lt_tree_.Insert(by_start_min_[i]);
00719 DCHECK_EQ(i, by_start_min_[i]->start_min_index());
00720 }
00721 for (int j = size_ - 2; j >= 0; --j) {
00722 lt_tree_.Grey(by_end_max_[j+1]);
00723 DisjunctiveIndexedTask* const twj = by_end_max_[j];
00724
00725 DCHECK_LE(lt_tree_.ECT(), twj->EndMax());
00726 while (lt_tree_.ECT_opt() > twj->EndMax()) {
00727 const int i = lt_tree_.Responsible_opt();
00728 DCHECK_GE(i, 0);
00729 if (lt_tree_.ECT() > new_est_[i]) {
00730 new_est_[i] = lt_tree_.ECT();
00731 }
00732 lt_tree_.Reset(i);
00733 }
00734 }
00735
00736
00737 bool modified = false;
00738 for (int i = 0; i < size_; ++i) {
00739 if (by_start_min_[i]->StartMin() < new_est_[i]) {
00740 modified = true;
00741 by_start_min_[i]->mutable_interval()->SetStartMin(new_est_[i]);
00742 }
00743 }
00744 return modified;
00745 }
00746
00747
00748
00749
00750
00751 class DisjunctiveConstraint : public Constraint {
00752 public:
00753 DisjunctiveConstraint(Solver* const s,
00754 IntervalVar* const * intervals,
00755 int size);
00756 virtual ~DisjunctiveConstraint() { }
00757
00758 virtual void Post() {
00759 Demon* d = MakeDelayedConstraintDemon0(
00760 solver(),
00761 this,
00762 &DisjunctiveConstraint::InitialPropagate,
00763 "InitialPropagate");
00764 for (int32 i = 0; i < straight_.size(); ++i) {
00765 straight_.mutable_interval(i)->WhenAnything(d);
00766 }
00767 }
00768
00769 virtual void InitialPropagate() {
00770 do {
00771 do {
00772 do {
00773
00774
00775 straight_.OverloadChecking();
00776 } while (straight_.DetectablePrecedences() ||
00777 mirror_.DetectablePrecedences());
00778 } while (straight_not_last_.Propagate() || mirror_not_last_.Propagate());
00779 } while (straight_.EdgeFinder() || mirror_.EdgeFinder());
00780 }
00781
00782 void Accept(ModelVisitor* const visitor) const {
00783 visitor->BeginVisitConstraint(ModelVisitor::kDisjunctive, this);
00784 visitor->VisitIntervalArrayArgument(ModelVisitor::kIntervalsArgument,
00785 intervals_.get(),
00786 size_);
00787 visitor->EndVisitConstraint(ModelVisitor::kDisjunctive, this);
00788 }
00789
00790 private:
00791 scoped_array<IntervalVar*> intervals_;
00792 const int size_;
00793 EdgeFinderAndDetectablePrecedences straight_;
00794 EdgeFinderAndDetectablePrecedences mirror_;
00795 NotLast straight_not_last_;
00796 NotLast mirror_not_last_;
00797 DISALLOW_COPY_AND_ASSIGN(DisjunctiveConstraint);
00798 };
00799
00800 DisjunctiveConstraint::DisjunctiveConstraint(Solver* const s,
00801 IntervalVar* const * intervals,
00802 int size)
00803 : Constraint(s),
00804 intervals_(new IntervalVar*[size]),
00805 size_(size),
00806 straight_(s, intervals, size, false),
00807 mirror_(s, intervals, size, true),
00808 straight_not_last_(s, intervals, size, false),
00809 mirror_not_last_(s, intervals, size, true) {
00810 memcpy(intervals_.get(), intervals, size_ * sizeof(*intervals));
00811 }
00812
00813
00814
00815
00816
00817 CumulativeTask* MakeTask(Solver* solver, IntervalVar* interval, int64 demand) {
00818 return solver->RevAlloc(new CumulativeTask(interval, demand));
00819 }
00820
00821
00822
00823 class DualCapacityThetaNode {
00824 public:
00825
00826 static const int kNone;
00827
00828
00829 DualCapacityThetaNode()
00830 : energy_(0LL),
00831 energetic_end_min_(kint64min),
00832 residual_energetic_end_min_(kint64min) {}
00833
00834
00835 DualCapacityThetaNode(int64 capacity, int64 residual_capacity,
00836 const CumulativeTask& task)
00837 : energy_(task.EnergyMin()),
00838 energetic_end_min_(
00839 capacity * task.interval()->StartMin() + energy_),
00840 residual_energetic_end_min_(
00841 residual_capacity * task.interval()->StartMin() + energy_) {}
00842
00843
00844 int64 energy() const { return energy_; }
00845 int64 energetic_end_min() const { return energetic_end_min_; }
00846 int64 residual_energetic_end_min() const {
00847 return residual_energetic_end_min_;
00848 }
00849
00850
00851 void Set(const DualCapacityThetaNode& node) {
00852 energy_ = node.energy_;
00853 energetic_end_min_ = node.energetic_end_min_;
00854 residual_energetic_end_min_ = node.residual_energetic_end_min_;
00855 }
00856
00857
00858
00859
00860
00861
00862
00863 void Compute(const DualCapacityThetaNode& left,
00864 const DualCapacityThetaNode& right) {
00865 energy_ = left.energy_ + right.energy_;
00866 energetic_end_min_ =
00867 std::max(left.energetic_end_min_ + right.energy_,
00868 right.energetic_end_min_);
00869 residual_energetic_end_min_ =
00870 std::max(left.residual_energetic_end_min_ + right.energy_,
00871 right.residual_energetic_end_min_);
00872 }
00873
00874 private:
00875
00876
00877 int64 energy_;
00878
00879
00880 int64 energetic_end_min_;
00881
00882
00883 int64 residual_energetic_end_min_;
00884 DISALLOW_COPY_AND_ASSIGN(DualCapacityThetaNode);
00885 };
00886
00887 const int DualCapacityThetaNode::kNone = -1;
00888
00889
00890 class DualCapacityThetaTree
00891 : public MonoidOperationTree<DualCapacityThetaNode> {
00892 public:
00893 static const int64 kNotInitialized;
00894 DualCapacityThetaTree(int size, int64 capacity)
00895 : MonoidOperationTree<DualCapacityThetaNode>(size),
00896 capacity_(capacity),
00897 residual_capacity_(-1) {}
00898 virtual ~DualCapacityThetaTree() {}
00899 void Insert(const CumulativeIndexedTask* indexed_task) {
00900 DualCapacityThetaNode thetaNode(
00901 capacity_, residual_capacity_, indexed_task->task());
00902 Set(indexed_task->start_min_index(), thetaNode);
00903 }
00904 void SetResidualCapacity(int residual_capacity) {
00905 Clear();
00906 DCHECK_LE(0, residual_capacity);
00907 DCHECK_LE(residual_capacity, capacity_);
00908 residual_capacity_ = residual_capacity;
00909 }
00910
00911 private:
00912 const int64 capacity_;
00913 int64 residual_capacity_;
00914 DISALLOW_COPY_AND_ASSIGN(DualCapacityThetaTree);
00915 };
00916
00917 const int64 DualCapacityThetaTree::kNotInitialized = -1LL;
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 class EnvJCComputeDiver {
00930 public:
00931 static const int64 kNotAvailable;
00932 explicit EnvJCComputeDiver(int energy_threshold)
00933 : energy_threshold_(energy_threshold),
00934 energy_alpha_(kNotAvailable),
00935 energetic_end_min_alpha_(kNotAvailable) {}
00936 void OnArgumentReached(int index, const DualCapacityThetaNode& argument) {
00937 energy_alpha_ = argument.energy();
00938 energetic_end_min_alpha_ = argument.energetic_end_min();
00939
00940 DCHECK_GT(energetic_end_min_alpha_, kint64min);
00941 }
00942 bool ChooseGoLeft(const DualCapacityThetaNode& current,
00943 const DualCapacityThetaNode& left_child,
00944 const DualCapacityThetaNode& right_child) {
00945 if (right_child.residual_energetic_end_min() > energy_threshold_) {
00946 return false;
00947 } else {
00948 energy_threshold_ -= right_child.energy();
00949 return true;
00950 }
00951 }
00952 void OnComeBackFromLeft(const DualCapacityThetaNode& current,
00953 const DualCapacityThetaNode& left_child,
00954 const DualCapacityThetaNode& right_child) {
00955
00956
00957
00958
00959 }
00960 void OnComeBackFromRight(const DualCapacityThetaNode& current,
00961 const DualCapacityThetaNode& left_child,
00962 const DualCapacityThetaNode& right_child) {
00963
00964
00965 energetic_end_min_alpha_ =
00966 std::max(energetic_end_min_alpha_,
00967 left_child.energetic_end_min() + energy_alpha_);
00968 energy_alpha_ += left_child.energy();
00969 }
00970 int64 GetEnvJC(const DualCapacityThetaNode& root) const {
00971 const int64 energy = root.energy();
00972 const int64 energy_beta = energy - energy_alpha_;
00973 return energetic_end_min_alpha_ + energy_beta;
00974 }
00975
00976 private:
00977
00978
00979
00980
00981
00982 int64 energy_threshold_;
00983
00984
00985
00986
00987
00988 int64 energy_alpha_;
00989
00990
00991
00992
00993 int64 energetic_end_min_alpha_;
00994 };
00995
00996 const int64 EnvJCComputeDiver::kNotAvailable = -1LL;
00997
00998
00999 class StartMinUpdater {
01000 public:
01001 StartMinUpdater(IntervalVar* interval, int64 new_start_min)
01002 : interval_(interval), new_start_min_(new_start_min) {}
01003 void Run() {
01004 interval_->SetStartMin(new_start_min_);
01005 }
01006 private:
01007 IntervalVar* interval_;
01008 int64 new_start_min_;
01009 };
01010
01011
01012
01013
01014
01015
01016
01017
01018 class UpdatesForADemand {
01019 public:
01020 explicit UpdatesForADemand(int size)
01021 : updates_(size, 0), up_to_date_(false) {
01022 }
01023 const std::vector<int64>& updates() { return updates_; }
01024 bool up_to_date() const { return up_to_date_; }
01025 void Reset() { up_to_date_ = false; }
01026 void SetUpdate(int index, int64 update) {
01027 DCHECK(!up_to_date_);
01028 updates_[index] = update;
01029 }
01030 void SetUpToDate() { up_to_date_ = true; }
01031 private:
01032 std::vector<int64> updates_;
01033 bool up_to_date_;
01034 DISALLOW_COPY_AND_ASSIGN(UpdatesForADemand);
01035 };
01036
01037
01038 int64 SafeProduct(int64 a, int64 b) {
01039 DCHECK_GE(a, 0);
01040
01041 const bool is_positive = b >= 0;
01042 b = std::max(b, -b);
01043
01044
01045 DCHECK_GE(b, 0);
01046 const int kint64SurelyOverflow = 63;
01047 const bool surely_overflow = MostSignificantBitPosition64(a)
01048 + MostSignificantBitPosition64(b)
01049 > kint64SurelyOverflow;
01050
01051
01052
01053
01054
01055
01056
01057
01058 const int64 product = a * b;
01059 return (!surely_overflow && product >= 0)
01060 ? ((is_positive) ? product : -product)
01061 : ((is_positive) ? kint64max : -kint64max);
01062 }
01063
01064
01065 class EdgeFinder : public Constraint {
01066 public:
01067 EdgeFinder(Solver* const solver,
01068 const std::vector<CumulativeTask*>& tasks,
01069 int64 capacity)
01070 : Constraint(solver),
01071 capacity_(capacity),
01072 size_(tasks.size()),
01073 by_start_min_(size_),
01074 by_end_max_(size_),
01075 by_end_min_(size_),
01076 lt_tree_(size_, capacity_) {
01077
01078 for (int i = 0; i < size_; ++i) {
01079 CumulativeIndexedTask* const indexed_task =
01080 new CumulativeIndexedTask(*tasks[i]);
01081 by_start_min_[i] = indexed_task;
01082 by_end_max_[i] = indexed_task;
01083 by_end_min_[i] = indexed_task;
01084 const int64 demand = indexed_task->task().demand();
01085
01086
01087 if (update_map_[demand] == NULL) {
01088 update_map_[demand] = new UpdatesForADemand(size_);
01089 }
01090 }
01091 }
01092 virtual ~EdgeFinder() {
01093 STLDeleteElements(&by_start_min_);
01094 STLDeleteValues(&update_map_);
01095 }
01096
01097 virtual void Post() {
01098
01099 for (int i = 0; i < size_; ++i) {
01100 IntervalVar* const interval =
01101 by_start_min_[i]->mutable_interval();
01102
01103
01104 Demon* const demon = MakeDelayedConstraintDemon0(
01105 solver(), this, &EdgeFinder::InitialPropagate, "RangeChanged");
01106 interval->WhenAnything(demon);
01107 }
01108 }
01109
01110
01111
01112 virtual void InitialPropagate() {
01113 InitPropagation();
01114 PropagateBasedOnEndMinGreaterThanEndMax();
01115 FillInTree();
01116 PropagateBasedOnEnergy();
01117 ApplyNewBounds();
01118 }
01119
01120 void Accept(ModelVisitor* const visitor) const {
01121 LOG(FATAL) << "Should Not Be Visited";
01122 }
01123
01124 private:
01125
01126 void InitPropagation() {
01127
01128 new_start_min_.clear();
01129
01130 Sort(&by_start_min_, StartMinLessThan<CumulativeTask>);
01131 for (int i = 0; i < size_; ++i) {
01132 by_start_min_[i]->set_start_min_index(i);
01133 }
01134
01135 Sort(&by_end_max_, EndMaxLessThan<CumulativeTask>);
01136
01137 Sort(&by_end_min_, EndMinLessThan<CumulativeTask>);
01138
01139 lt_tree_.Clear();
01140
01141 typedef UpdateMap::iterator iterator;
01142 for (iterator it = update_map_.begin(); it != update_map_.end(); ++it) {
01143 it->second->Reset();
01144 }
01145 }
01146
01147
01148
01149
01150
01151 void ComputeConditionalStartMins(int64 demand) {
01152 DCHECK_GT(demand, 0);
01153 UpdatesForADemand* const updates = update_map_[demand];
01154 DCHECK(!updates->up_to_date());
01155 DualCapacityThetaTree dual_capa_tree(size_, capacity_);
01156 const int64 residual_capacity = capacity_ - demand;
01157 dual_capa_tree.SetResidualCapacity(residual_capacity);
01158
01159
01160
01161
01162 int64 update = IntervalVar::kMinValidValue;
01163 for (int i = 0; i < size_; ++i) {
01164 const int64 current_end_max = by_end_max_[i]->EndMax();
01165 dual_capa_tree.Insert(by_end_max_[i]);
01166 const int64 energy_threshold = residual_capacity * current_end_max;
01167 const DualCapacityThetaNode& root = dual_capa_tree.result();
01168 const int64 res_energetic_end_min = root.residual_energetic_end_min();
01169 if (res_energetic_end_min > energy_threshold) {
01170 EnvJCComputeDiver diver(energy_threshold);
01171 dual_capa_tree.DiveInTree(&diver);
01172 const int64 enjv = diver.GetEnvJC(dual_capa_tree.result());
01173 const int64 numerator = enjv - energy_threshold;
01174 const int64 diff = MathUtil::CeilOfRatio(numerator, demand);
01175 update = std::max(update, diff);
01176 }
01177 updates->SetUpdate(i, update);
01178 }
01179 updates->SetUpToDate();
01180 }
01181
01182
01183
01184 int64 ConditionalStartMin(const CumulativeIndexedTask& task_to_push,
01185 int end_max_index) {
01186 const int64 demand = task_to_push.task().demand();
01187 if (!update_map_[demand]->up_to_date()) {
01188 ComputeConditionalStartMins(demand);
01189 }
01190 DCHECK(update_map_[demand]->up_to_date());
01191 return update_map_[demand]->updates().at(end_max_index);
01192 }
01193
01194
01195
01196
01197
01198
01199 void PropagateBasedOnEndMinGreaterThanEndMax() {
01200 int end_max_index = 0;
01201 int64 max_start_min = kint64min;
01202 for (int i = 0; i < size_; ++i) {
01203 CumulativeIndexedTask* const task = by_end_min_[i];
01204 const int64 end_min = task->EndMin();
01205 while (end_max_index < size_ &&
01206 by_end_max_[end_max_index]->EndMax() <= end_min) {
01207 max_start_min = std::max(max_start_min,
01208 by_end_max_[end_max_index]->StartMin());
01209 ++end_max_index;
01210 }
01211 if (end_max_index > 0 &&
01212 task->StartMin() <= max_start_min &&
01213 task->EndMax() > task->EndMin()) {
01214 DCHECK_LE(by_end_max_[end_max_index - 1]->EndMax(), end_min);
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 const int64 update = ConditionalStartMin(*task, end_max_index - 1);
01228 StartMinUpdater startMinUpdater(task->mutable_interval(), update);
01229 new_start_min_.push_back(startMinUpdater);
01230 }
01231 }
01232 }
01233
01234
01235 void FillInTree() {
01236 for (int i = 0; i < size_; ++i) {
01237 CumulativeIndexedTask* const indexed_task = by_end_max_[i];
01238 lt_tree_.Insert(indexed_task);
01239
01240 const int64 max_feasible = SafeProduct(capacity_, indexed_task->EndMax());
01241 if (lt_tree_.energetic_end_min() > max_feasible) {
01242 solver()->Fail();
01243 }
01244 }
01245 }
01246
01247
01248
01249 void PropagateBasedOnEnergy() {
01250 for (int j = size_ - 2; j >= 0; --j) {
01251 lt_tree_.Grey(by_end_max_[j+1]);
01252 CumulativeIndexedTask* const twj = by_end_max_[j];
01253
01254 const int64 max_feasible = SafeProduct(capacity_, twj->EndMax());
01255 DCHECK_LE(lt_tree_.energetic_end_min(), max_feasible);
01256 while (lt_tree_.energetic_end_min_opt() > max_feasible) {
01257 const int i = lt_tree_.argmax_energetic_end_min_opt();
01258 DCHECK_GE(i, 0);
01259 PropagateTaskCannotEndBefore(i, j);
01260 lt_tree_.Reset(i);
01261 }
01262 }
01263 }
01264
01265
01266
01267 void PropagateTaskCannotEndBefore(int start_min_index, int end_max_index) {
01268 CumulativeIndexedTask* const task_to_push = by_start_min_[start_min_index];
01269 const int64 update = ConditionalStartMin(*task_to_push, end_max_index);
01270 StartMinUpdater startMinUpdater(task_to_push->mutable_interval(), update);
01271 new_start_min_.push_back(startMinUpdater);
01272 }
01273
01274
01275 void ApplyNewBounds() {
01276 for (int i = 0; i < new_start_min_.size(); ++i) {
01277 new_start_min_[i].Run();
01278 }
01279 }
01280
01281
01282 const int64 capacity_;
01283
01284
01285 const int size_;
01286
01287
01288 std::vector<CumulativeIndexedTask*> by_start_min_;
01289
01290
01291 std::vector<CumulativeIndexedTask*> by_end_max_;
01292
01293
01294 std::vector<CumulativeIndexedTask*> by_end_min_;
01295
01296
01297 CumulativeLambdaThetaTree lt_tree_;
01298
01299
01300 std::vector<StartMinUpdater> new_start_min_;
01301
01302 typedef hash_map<int64, UpdatesForADemand*> UpdateMap;
01303
01304
01305
01306
01307 UpdateMap update_map_;
01308
01309 DISALLOW_COPY_AND_ASSIGN(EdgeFinder);
01310 };
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 struct ProfileDelta {
01334 ProfileDelta(int64 _time, int64 _delta) : time(_time), delta(_delta) {}
01335 int64 time;
01336 int64 delta;
01337 };
01338
01339 bool TimeLessThan(const ProfileDelta& delta1, const ProfileDelta& delta2) {
01340 return delta1.time < delta2.time;
01341 }
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 class CumulativeTimeTable : public Constraint {
01356 public:
01357 CumulativeTimeTable(Solver* const solver,
01358 const std::vector<CumulativeTask*>& tasks,
01359 int64 capacity)
01360 : Constraint(solver),
01361 by_start_min_(tasks),
01362 capacity_(capacity) {
01363
01364
01365 const int profile_max_size = 2 * NumTasks() + 2;
01366 profile_non_unique_time_.reserve(profile_max_size);
01367 profile_unique_time_.reserve(profile_max_size);
01368 }
01369 virtual void InitialPropagate() {
01370 BuildProfile();
01371 PushTasks();
01372 }
01373 virtual void Post() {
01374 Demon* d = MakeDelayedConstraintDemon0(
01375 solver(),
01376 this,
01377 &CumulativeTimeTable::InitialPropagate,
01378 "InitialPropagate");
01379 for (int i = 0; i < NumTasks(); ++i) {
01380 by_start_min_[i]->mutable_interval()->WhenAnything(d);
01381 }
01382 }
01383 int NumTasks() const { return by_start_min_.size(); }
01384
01385 void Accept(ModelVisitor* const visitor) const {
01386 LOG(FATAL) << "Should not be visited";
01387 }
01388
01389 private:
01390
01391 void BuildProfile() {
01392
01393 profile_non_unique_time_.clear();
01394 for (int i = 0; i < NumTasks(); ++i) {
01395 const CumulativeTask* task = by_start_min_[i];
01396 const IntervalVar* const interval = task->interval();
01397 const int64 start_max = interval->StartMax();
01398 const int64 end_min = interval->EndMin();
01399 if (interval->MustBePerformed() && start_max < end_min) {
01400 const int64 demand = task->demand();
01401 profile_non_unique_time_.push_back(ProfileDelta(start_max, +demand));
01402 profile_non_unique_time_.push_back(ProfileDelta(end_min, -demand));
01403 }
01404 }
01405
01406 std::sort(profile_non_unique_time_.begin(),
01407 profile_non_unique_time_.end(),
01408 TimeLessThan);
01409
01410 int64 usage = 0;
01411 profile_unique_time_.clear();
01412 profile_unique_time_.push_back(ProfileDelta(kint64min, 0));
01413 for (int i = 0; i < profile_non_unique_time_.size(); ++i) {
01414 const ProfileDelta& profile_delta = profile_non_unique_time_[i];
01415 if (profile_delta.time == profile_unique_time_.back().time) {
01416 profile_unique_time_.back().delta += profile_delta.delta;
01417 } else {
01418 if (usage > capacity_) {
01419 solver()->Fail();
01420 }
01421 profile_unique_time_.push_back(profile_delta);
01422 }
01423 usage += profile_delta.delta;
01424 }
01425 DCHECK_EQ(0, usage);
01426 profile_unique_time_.push_back(ProfileDelta(kint64max, 0));
01427 }
01428
01429
01430 void PushTasks() {
01431 Sort(&by_start_min_, TaskStartMinLessThan);
01432 int64 usage = 0;
01433 int profile_index = 0;
01434 for (int task_index = 0 ; task_index < NumTasks(); ++task_index) {
01435 CumulativeTask* const task = by_start_min_[task_index];
01436 while (task->interval()->StartMin() >
01437 profile_unique_time_[profile_index].time) {
01438 DCHECK(profile_index < profile_unique_time_.size());
01439 ++profile_index;
01440 usage += profile_unique_time_[profile_index].delta;
01441 }
01442 PushTask(task, profile_index, usage);
01443 }
01444 }
01445
01446
01447
01448
01449
01450 void PushTask(CumulativeTask* const task,
01451 int profile_index,
01452 int64 usage) {
01453
01454 const IntervalVar* const interval = task->interval();
01455 const int64 demand = task->demand();
01456 const int64 residual_capacity = capacity_ - demand;
01457 const int64 duration = task->interval()->DurationMin();
01458 const ProfileDelta& first_prof_delta = profile_unique_time_[profile_index];
01459
01460 int64 new_start_min = interval->StartMin();
01461
01462 DCHECK_GE(first_prof_delta.time, interval->StartMin());
01463
01464 if (first_prof_delta.time > interval->StartMin()) {
01465
01466
01467
01468
01469 DCHECK(
01470 (interval->StartMax() >= first_prof_delta.time) ||
01471 (interval->StartMax() >= interval->EndMin()));
01472
01473
01474 const int64 usage_at_start_min = usage - first_prof_delta.delta;
01475 if (usage_at_start_min > residual_capacity) {
01476 new_start_min = profile_unique_time_[profile_index].time;
01477 }
01478 }
01479
01480
01481 const int64 start_max = interval->StartMax();
01482 const int64 end_min = interval->EndMin();
01483 ProfileDelta delta_start(start_max, 0);
01484 ProfileDelta delta_end(end_min, 0);
01485 if (interval->MustBePerformed() && start_max < end_min) {
01486 delta_start.delta = +demand;
01487 delta_end.delta = -demand;
01488 }
01489 while (profile_unique_time_[profile_index].time <
01490 duration + new_start_min) {
01491 const ProfileDelta& profile_delta = profile_unique_time_[profile_index];
01492 DCHECK(profile_index < profile_unique_time_.size());
01493
01494 if (profile_delta.time == delta_start.time) {
01495 usage -= delta_start.delta;
01496 }
01497 if (profile_delta.time == delta_end.time) {
01498 usage -= delta_end.delta;
01499 }
01500
01501 ++profile_index;
01502 DCHECK(profile_index < profile_unique_time_.size());
01503
01504 if (usage > residual_capacity) {
01505 new_start_min = profile_unique_time_[profile_index].time;
01506 }
01507 usage += profile_unique_time_[profile_index].delta;
01508 }
01509 task->mutable_interval()->SetStartMin(new_start_min);
01510 }
01511
01512 typedef std::vector<ProfileDelta> Profile;
01513
01514 Profile profile_unique_time_;
01515 Profile profile_non_unique_time_;
01516 std::vector<CumulativeTask*> by_start_min_;
01517 const int64 capacity_;
01518
01519 DISALLOW_COPY_AND_ASSIGN(CumulativeTimeTable);
01520 };
01521
01522 class CumulativeConstraint : public Constraint {
01523 public:
01524 CumulativeConstraint(Solver* const s,
01525 IntervalVar* const * intervals,
01526 int64 const * demands,
01527 int size,
01528 int64 capacity,
01529 const string& name)
01530 : Constraint(s),
01531 capacity_(capacity),
01532 tasks_(new CumulativeTask*[size]),
01533 size_(size),
01534 intervals_(new IntervalVar*[size]),
01535 demands_(new int64[size]) {
01536 for (int i = 0; i < size; ++i) {
01537 tasks_[i] = MakeTask(solver(), intervals[i], demands[i]);
01538 intervals_[i] = intervals[i];
01539 demands_[i] = demands[i];
01540 }
01541 }
01542
01543 CumulativeConstraint(Solver* const s,
01544 IntervalVar* const * intervals,
01545 int const * demands,
01546 int size,
01547 int64 capacity,
01548 const string& name)
01549 : Constraint(s),
01550 capacity_(capacity),
01551 tasks_(new CumulativeTask*[size]),
01552 size_(size),
01553 intervals_(new IntervalVar*[size]),
01554 demands_(new int64[size]) {
01555 for (int i = 0; i < size; ++i) {
01556 tasks_[i] = MakeTask(solver(), intervals[i], demands[i]);
01557 intervals_[i] = intervals[i];
01558 demands_[i] = demands[i];
01559 }
01560 }
01561
01562 virtual void Post() {
01563
01564
01565
01566 if (FLAGS_cp_use_cumulative_time_table) {
01567 PostOneSidedConstraint(false, false);
01568 PostOneSidedConstraint(true, false);
01569 }
01570 if (FLAGS_cp_use_cumulative_edge_finder) {
01571 PostOneSidedConstraint(false, true);
01572 PostOneSidedConstraint(true, true);
01573 }
01574 if (FLAGS_cp_use_sequence_high_demand_tasks) {
01575 PostHighDemandSequenceConstraint();
01576 }
01577 if (FLAGS_cp_use_all_possible_disjunctions) {
01578 PostAllDisjunctions();
01579 }
01580 }
01581
01582 virtual void InitialPropagate() {
01583
01584 }
01585
01586 void Accept(ModelVisitor* const visitor) const {
01587
01588 visitor->BeginVisitConstraint(ModelVisitor::kCumulative, this);
01589 visitor->VisitIntervalArrayArgument(ModelVisitor::kIntervalsArgument,
01590 intervals_.get(),
01591 size_);
01592 visitor->VisitIntegerArrayArgument(ModelVisitor::kDemandsArgument,
01593 demands_.get(),
01594 size_);
01595 visitor->VisitIntegerArgument(ModelVisitor::kCapacityArgument, capacity_);
01596 visitor->EndVisitConstraint(ModelVisitor::kCumulative, this);
01597 }
01598
01599 private:
01600
01601 void PostAllDisjunctions() {
01602 for (int i = 0; i < size_; ++i) {
01603 IntervalVar* const interval_i = intervals_[i];
01604 if (interval_i->MayBePerformed()) {
01605 for (int j = i + 1; j < size_; ++j) {
01606 IntervalVar* const interval_j = intervals_[j];
01607 if (interval_j->MayBePerformed()) {
01608 if (tasks_[i]->demand() + tasks_[j]->demand() > capacity_) {
01609 Constraint* const constraint =
01610 solver()->MakeTemporalDisjunction(interval_i, interval_j);
01611 solver()->AddConstraint(constraint);
01612 }
01613 }
01614 }
01615 }
01616 }
01617 }
01618
01619
01620
01621 void PostHighDemandSequenceConstraint() {
01622 Constraint* constraint = NULL;
01623 {
01624 std::vector<IntervalVar*> high_demand_intervals;
01625 high_demand_intervals.reserve(size_);
01626 for (int i = 0; i < size_; ++i) {
01627 const int64 demand = tasks_[i]->demand();
01628
01629
01630
01631
01632
01633
01634 if (demand * 2 > capacity_ && tasks_[i]->interval()->MayBePerformed()) {
01635 high_demand_intervals.push_back(tasks_[i]->mutable_interval());
01636 }
01637 }
01638 if (high_demand_intervals.size() >= 2) {
01639
01640
01641
01642 constraint = solver()->MakeDisjunctiveConstraint(high_demand_intervals);
01643 }
01644 }
01645 if (constraint != NULL) {
01646 solver()->AddConstraint(constraint);
01647 }
01648 }
01649
01650
01651 CumulativeTask* MakeRelaxedTask(CumulativeTask* original_task, bool mirror) {
01652 IntervalVar* const original_interval = original_task->mutable_interval();
01653 IntervalVar* const interval = mirror ?
01654 solver()->MakeMirrorInterval(original_interval) : original_interval;
01655 IntervalVar* const relaxed_max = solver()->MakeIntervalRelaxedMax(interval);
01656 CumulativeTask* const task = new CumulativeTask(relaxed_max,
01657 original_task->demand());
01658 return solver()->RevAlloc(task);
01659 }
01660
01661
01662
01663 void PopulateVectorUsefulTasks(bool mirror,
01664 std::vector<CumulativeTask*>* const useful_tasks) {
01665 DCHECK(useful_tasks->empty());
01666 for (int i = 0; i < size_; ++i) {
01667 CumulativeTask* const original_task = tasks_[i];
01668 IntervalVar* const interval = original_task->mutable_interval();
01669
01670 if (original_task->demand() > capacity_) {
01671 interval->SetPerformed(false);
01672 }
01673
01674
01675 if (interval->MayBePerformed() && original_task->demand() > 0) {
01676 useful_tasks->push_back(MakeRelaxedTask(original_task, mirror));
01677 }
01678 }
01679 }
01680
01681
01682
01683 Constraint* MakeOneSidedConstraint(bool mirror, bool edge_finder) {
01684 std::vector<CumulativeTask*> useful_tasks;
01685 PopulateVectorUsefulTasks(mirror, &useful_tasks);
01686 if (useful_tasks.empty()) {
01687 return NULL;
01688 } else {
01689 Constraint* constraint;
01690 if (edge_finder) {
01691 constraint = new EdgeFinder(solver(), useful_tasks, capacity_);
01692 } else {
01693 constraint = new CumulativeTimeTable(solver(), useful_tasks, capacity_);
01694 }
01695 return solver()->RevAlloc(constraint);
01696 }
01697 }
01698
01699
01700 void PostOneSidedConstraint(bool mirror, bool edge_finder) {
01701 Constraint* const constraint = MakeOneSidedConstraint(mirror, edge_finder);
01702 if (constraint != NULL) {
01703 solver()->AddConstraint(constraint);
01704 }
01705 }
01706
01707
01708 const int64 capacity_;
01709
01710
01711 const scoped_array<CumulativeTask*> tasks_;
01712
01713
01714 const int size_;
01715
01716
01717 scoped_array<IntervalVar*> intervals_;
01718
01719 scoped_array<int64> demands_;
01720
01721 DISALLOW_COPY_AND_ASSIGN(CumulativeConstraint);
01722 };
01723 }
01724
01725
01726
01727 Constraint* Solver::MakeDisjunctiveConstraint(
01728 const std::vector<IntervalVar*>& intervals) {
01729
01730 std::vector<IntervalVar*> may_be_performed;
01731 for (int i = 0; i < intervals.size(); ++i) {
01732 if (intervals[i]->MayBePerformed()) {
01733 may_be_performed.push_back(intervals[i]);
01734 }
01735 }
01736 return RevAlloc(new DisjunctiveConstraint(this,
01737 may_be_performed.data(),
01738 may_be_performed.size()));
01739 }
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750 SequenceVar::SequenceVar(Solver* const s,
01751 const IntervalVar* const * intervals,
01752 int size,
01753 const string& name)
01754 : PropagationBaseObject(s),
01755 intervals_(new IntervalVar*[size]),
01756 size_(size),
01757 ranked_before_(size, 0),
01758 count_ranked_first_(0),
01759 ranked_after_(size, 0),
01760 count_ranked_last_(0),
01761 precedence_matrix_(new RevBitMatrix(size_, size_)) {
01762 memcpy(intervals_.get(), intervals, size_ * sizeof(*intervals));
01763 set_name(name);
01764 }
01765
01766 SequenceVar::~SequenceVar() {}
01767
01768 IntervalVar* SequenceVar::Interval(int index) const {
01769 return intervals_[index];
01770 }
01771
01772 string SequenceVar::DebugString() const {
01773 int64 hmin, hmax, dmin, dmax;
01774 HorizonRange(&hmin, &hmax);
01775 DurationRange(&dmin, &dmax);
01776 return StringPrintf("%s(horizon = %" GG_LL_FORMAT
01777 "d..%" GG_LL_FORMAT
01778 "d, duration = %" GG_LL_FORMAT
01779 "d..%" GG_LL_FORMAT
01780 "d, not ranked = %d, ranked = %d)",
01781 name().c_str(),
01782 hmin,
01783 hmax,
01784 dmin,
01785 dmax,
01786 NotRanked(),
01787 Ranked());
01788 }
01789
01790 void SequenceVar::Accept(ModelVisitor* const visitor) const {
01791 visitor->VisitSequenceVariable(this);
01792 }
01793
01794 void SequenceVar::DurationRange(int64* const dmin, int64* const dmax) const {
01795 int64 dur_min = 0;
01796 int64 dur_max = 0;
01797 for (int i = 0; i < size_; ++i) {
01798 IntervalVar* const t = intervals_[i];
01799 if (t->MayBePerformed()) {
01800 if (t->MustBePerformed()) {
01801 dur_min += t->DurationMin();
01802 }
01803 dur_max += t->DurationMax();
01804 }
01805 }
01806 *dmin = dur_min;
01807 *dmax = dur_max;
01808 }
01809
01810 void SequenceVar::HorizonRange(int64* const hmin, int64* const hmax) const {
01811 int64 hor_min = kint64max;
01812 int64 hor_max = kint64min;
01813 for (int i = 0; i < size_; ++i) {
01814 IntervalVar* const t = intervals_[i];
01815 if (t->MayBePerformed()) {
01816 const int64 tmin = t->StartMin();
01817 const int64 tmax = t->EndMax();
01818 if (tmin < hor_min) {
01819 hor_min = tmin;
01820 }
01821 if (tmax > hor_max) {
01822 hor_max = tmax;
01823 }
01824 }
01825 }
01826 *hmin = hor_min;
01827 *hmax = hor_max;
01828 }
01829
01830 bool SequenceVar::IsActive(int index) const {
01831 return (intervals_[index]->MayBePerformed() &&
01832 ranked_before_[index] >= count_ranked_first_.Value() &&
01833 ranked_after_[index] >= count_ranked_last_.Value());
01834 }
01835
01836 void SequenceVar::ActiveHorizonRange(int64* const hmin,
01837 int64* const hmax) const {
01838 int64 hor_min = kint64max;
01839 int64 hor_max = kint64min;
01840 for (int interval_index = 0; interval_index < size_; ++interval_index) {
01841 IntervalVar* const t = intervals_[interval_index];
01842 if (IsActive(interval_index)) {
01843 const int64 tmin = t->StartMin();
01844 const int64 tmax = t->EndMax();
01845 if (tmin < hor_min) {
01846 hor_min = tmin;
01847 }
01848 if (tmax > hor_max) {
01849 hor_max = tmax;
01850 }
01851 }
01852 }
01853 *hmin = hor_min;
01854 *hmax = hor_max;
01855 }
01856
01857 int SequenceVar::Ranked() const {
01858 return count_ranked_last_.Value() + count_ranked_first_.Value();
01859 }
01860
01861 int SequenceVar::NotRanked() const {
01862 int count = 0;
01863 for (int interval_index = 0; interval_index < size_; ++interval_index) {
01864 if (IsActive(interval_index)) {
01865 count++;
01866 }
01867 }
01868 return count;
01869 }
01870
01871 void SequenceVar::ComputePossibleFirstsAndLasts(
01872 std::vector<int>* const possible_firsts,
01873 std::vector<int>* const possible_lasts) {
01874 for (int candidate = 0; candidate < size_; ++candidate) {
01875
01876 if (!intervals_[candidate]->MayBePerformed()) {
01877 continue;
01878 }
01879 if (ranked_before_[candidate] == count_ranked_first_.Value()) {
01880 int ranked_before = 0;
01881 int ranked_after = 0;
01882 for (int other = 0; other < size_; ++other) {
01883 if (other != candidate && intervals_[other]->MustBePerformed()) {
01884 if (IsBefore(other, candidate)) {
01885 ranked_before++;
01886 } else if (IsBefore(candidate, other)) {
01887 ranked_after++;
01888 }
01889 }
01890 }
01891 if (ranked_before > count_ranked_first_.Value()) {
01892 ranked_before_.SetValue(solver(), candidate, ranked_before);
01893 } else {
01894 possible_firsts->push_back(candidate);
01895 }
01896 if (ranked_after > count_ranked_last_.Value()) {
01897 ranked_after_.SetValue(solver(), candidate, ranked_after);
01898 } else {
01899 possible_lasts->push_back(candidate);
01900 }
01901 }
01902 }
01903 }
01904
01905 bool SequenceVar::IsBefore(int before, int after) const {
01906 return precedence_matrix_->IsSet(before, after) ||
01907 intervals_[before]->StartMax() < intervals_[after]->EndMin();
01908 }
01909
01910 void SequenceVar::AddPrecedence(int before, int after) {
01911 if (IsBefore(after, before)) {
01912 solver()->Fail();
01913 }
01914 if (IsBefore(before, after)) {
01915 return;
01916 }
01917 IntervalVar* const before_interval = intervals_[before];
01918 IntervalVar* const after_interval = intervals_[after];
01919 solver()->AddConstraint(
01920 solver()->MakeIntervalVarRelation(after_interval,
01921 Solver::STARTS_AFTER_END,
01922 before_interval));
01923 precedence_matrix_->SetToOne(solver(), before, after);
01924 }
01925
01926 void SequenceVar::MarkUnperformed(const std::vector<int>& unperformed) {
01927 for (ConstIter<std::vector<int> > it(unperformed); !it.at_end(); ++it) {
01928 intervals_[*it]->SetPerformed(false);
01929 }
01930 }
01931
01932 void SequenceVar::ComputeRanks(const std::vector<int>& rank_first,
01933 const std::vector<int>& rank_last) {
01934
01935 for (int i = 0; i < rank_first.size(); ++i) {
01936 const int index = rank_first[i];
01937 intervals_[index]->SetPerformed(true);
01938 ranked_before_.SetValue(solver(), index, i);
01939 }
01940
01941 for (int i = 0; i < rank_last.size(); ++i) {
01942 const int index = rank_last[i];
01943 intervals_[index]->SetPerformed(true);
01944 ranked_after_.SetValue(solver(), index, i);
01945 }
01946
01947 for (int i = 0; i < size_; ++i) {
01948 if (intervals_[i]->MayBePerformed()) {
01949 if (!ContainsKey(first_set_, i)) {
01950 ranked_before_.SetValue(solver(), i, rank_first.size());
01951 }
01952 if (!ContainsKey(last_set_, i)) {
01953 ranked_after_.SetValue(solver(), i, rank_last.size());
01954 }
01955 }
01956 }
01957 }
01958
01959 void SequenceVar::AddPrecedences(const std::vector<int>& rank_first,
01960 const std::vector<int>& rank_last) {
01961
01962 for (int i = 1; i < rank_first.size(); ++i) {
01963
01964 AddPrecedence(rank_first[i - 1], rank_first[i]);
01965 }
01966
01967 for (int i = 1; i < rank_last.size(); ++i) {
01968
01969 AddPrecedence(rank_last[i], rank_last[i - 1]);
01970 }
01971
01972 for (int i = 0; i < size_; ++i) {
01973 if (!ContainsKey(first_set_, i) && !rank_first.empty()) {
01974 AddPrecedence(rank_first.back(), i);
01975 }
01976 if (!ContainsKey(last_set_, i) && !rank_last.empty()) {
01977 AddPrecedence(i, rank_last.back());
01978 }
01979 }
01980 }
01981
01982 void SequenceVar::ComputeTransitiveClosure(const std::vector<int>& rank_first,
01983 const std::vector<int>& rank_last) {
01984
01985
01986
01987 hash_set<int> ranked;
01988
01989 for (ConstIter<std::vector<int> > it(rank_first); !it.at_end(); ++it) {
01990 ranked.insert(*it);
01991 for (int j = 0; j < size_; ++j) {
01992 if (!ContainsKey(ranked, j)) {
01993 precedence_matrix_->SetToOne(solver(), *it, j);
01994 }
01995 }
01996 }
01997 ranked.clear();
01998
01999 for (ConstIter<std::vector<int> > it(rank_last); !it.at_end(); ++it) {
02000 ranked.insert(*it);
02001 for (int j = 0; j < size_; ++j) {
02002 if (!ContainsKey(ranked, j)) {
02003 precedence_matrix_->SetToOne(solver(), j, *it);
02004 }
02005 }
02006 }
02007 }
02008
02009 void SequenceVar::RankSequence(const std::vector<int>& rank_first,
02010 const std::vector<int>& rank_last,
02011 const std::vector<int>& unperformed) {
02012 solver()->GetPropagationMonitor()->RankSequence(this,
02013 rank_first,
02014 rank_last,
02015 unperformed);
02016 MarkUnperformed(unperformed);
02017
02018
02019 first_set_.clear();
02020 first_set_.insert(rank_first.begin(), rank_first.end());
02021 last_set_.clear();
02022 last_set_.insert(rank_last.begin(), rank_last.end());
02023
02024 ComputeRanks(rank_first, rank_last);
02025 AddPrecedences(rank_first, rank_last);
02026 ComputeTransitiveClosure(rank_first, rank_last);
02027
02028 count_ranked_first_.SetValue(solver(), rank_first.size());
02029 count_ranked_last_.SetValue(solver(), rank_last.size());
02030 }
02031
02032 void SequenceVar::RankFirst(int index) {
02033 solver()->GetPropagationMonitor()->RankFirst(this, index);
02034 IntervalVar* const t = intervals_[index];
02035 t->SetPerformed(true);
02036 Solver* const s = solver();
02037 for (int i = 0; i < size_; ++i) {
02038 if (i != index &&
02039 ranked_before_[i] >= count_ranked_first_.Value() &&
02040 intervals_[i]->MayBePerformed()) {
02041 if (ranked_before_[i] == count_ranked_first_.Value()) {
02042 ranked_before_.SetValue(s, i, count_ranked_first_.Value() + 1);
02043 }
02044 AddPrecedence(index, i);
02045 }
02046 }
02047 ranked_before_.SetValue(s, index, count_ranked_first_.Value());
02048 count_ranked_first_.SetValue(s, count_ranked_first_.Value() + 1);
02049 }
02050
02051 void SequenceVar::RankNotFirst(int index) {
02052 solver()->GetPropagationMonitor()->RankNotFirst(this, index);
02053 ranked_before_.SetValue(solver(), index, count_ranked_first_.Value() + 1);
02054 int possible_first = -1;
02055 for (int i = 0; i < size_; ++i) {
02056 if (ranked_before_[i] == count_ranked_first_.Value() &&
02057 intervals_[i]->MayBePerformed()) {
02058 if (possible_first != -1) {
02059 return;
02060 }
02061 possible_first = i;
02062 }
02063 }
02064 if (possible_first == -1) {
02065 solver()->Fail();
02066 }
02067 if (intervals_[possible_first]->MustBePerformed()) {
02068 RankFirst(possible_first);
02069 }
02070 }
02071
02072 void SequenceVar::RankLast(int index) {
02073 solver()->GetPropagationMonitor()->RankLast(this, index);
02074 IntervalVar* const t = intervals_[index];
02075 t->SetPerformed(true);
02076 Solver* const s = solver();
02077 for (int i = 0; i < size_; ++i) {
02078 if (i != index &&
02079 ranked_after_[i] >= count_ranked_last_.Value() &&
02080 intervals_[i]->MayBePerformed()) {
02081 if (ranked_after_[i] == count_ranked_last_.Value()) {
02082 ranked_after_.SetValue(s, i, count_ranked_last_.Value() + 1);
02083 }
02084 AddPrecedence(i, index);
02085 }
02086 }
02087 ranked_after_.SetValue(s, index, count_ranked_last_.Value());
02088 count_ranked_last_.SetValue(s, count_ranked_last_.Value() + 1);
02089 }
02090
02091 void SequenceVar::RankNotLast(int index) {
02092 solver()->GetPropagationMonitor()->RankNotLast(this, index);
02093 ranked_after_.SetValue(solver(), index, count_ranked_last_.Value() + 1);
02094 int possible_last = -1;
02095 for (int i = 0; i < size_; ++i) {
02096 if (ranked_after_[i] == count_ranked_last_.Value() &&
02097 intervals_[i]->MayBePerformed()) {
02098 if (possible_last != -1) {
02099 return;
02100 }
02101 possible_last = i;
02102 }
02103 }
02104 if (possible_last == -1) {
02105 solver()->Fail();
02106 }
02107 if (intervals_[possible_last]->MustBePerformed()) {
02108 RankLast(possible_last);
02109 }
02110 }
02111
02112 void SequenceVar::FillSequence(std::vector<int>* const rank_first,
02113 std::vector<int>* const rank_last,
02114 std::vector<int>* const unperformed) const {
02115 CHECK_NOTNULL(rank_first);
02116 CHECK_NOTNULL(rank_last);
02117 CHECK_NOTNULL(unperformed);
02118 rank_first->clear();
02119 rank_first->resize(count_ranked_first_.Value(), -1);
02120 rank_last->clear();
02121 rank_last->resize(count_ranked_last_.Value(), -1);
02122 int min_filled = 0;
02123 int max_filled = 0;
02124 for (int var_index = 0; var_index < size_; ++var_index) {
02125 if (intervals_[var_index]->MustBePerformed()) {
02126 const int ranked_before = ranked_before_[var_index];
02127 const int ranked_after = ranked_after_[var_index];
02128 if (ranked_before < count_ranked_first_.Value()) {
02129 DCHECK_EQ(-1, (*rank_first)[ranked_before]);
02130 (*rank_first)[ranked_before] = var_index;
02131 min_filled++;
02132 } else if (ranked_after < count_ranked_last_.Value()) {
02133 (*rank_last)[ranked_after] = var_index;
02134 max_filled++;
02135 }
02136 } else if (!intervals_[var_index]->MayBePerformed()) {
02137 unperformed->push_back(var_index);
02138 }
02139 }
02140 DCHECK_EQ(count_ranked_first_.Value(), min_filled);
02141 DCHECK_EQ(count_ranked_last_.Value(), max_filled);
02142 if (unperformed->size() + rank_first->size() + rank_last->size() == size_) {
02143
02144 while (!rank_last->empty()) {
02145 rank_first->push_back(rank_last->back());
02146 rank_last->pop_back();
02147 }
02148 }
02149 }
02150
02151
02152
02153 SequenceVar* Solver::MakeSequenceVar(const std::vector<IntervalVar*>& intervals,
02154 const string& name) {
02155 return RevAlloc(new SequenceVar(this,
02156 intervals.data(),
02157 intervals.size(),
02158 name));
02159 }
02160
02161 Constraint* Solver::MakeCumulative(const std::vector<IntervalVar*>& intervals,
02162 const std::vector<int64>& demands,
02163 int64 capacity,
02164 const string& name) {
02165 CHECK_EQ(intervals.size(), demands.size());
02166 for (int i = 0; i < intervals.size(); ++i) {
02167 CHECK_GE(demands[i], 0);
02168 }
02169 return RevAlloc(new CumulativeConstraint(this,
02170 intervals.data(),
02171 demands.data(),
02172 intervals.size(),
02173 capacity,
02174 name));
02175 }
02176
02177 Constraint* Solver::MakeCumulative(const std::vector<IntervalVar*>& intervals,
02178 const std::vector<int>& demands,
02179 int64 capacity,
02180 const string& name) {
02181 CHECK_EQ(intervals.size(), demands.size());
02182 for (int i = 0; i < intervals.size(); ++i) {
02183 CHECK_GE(demands[i], 0);
02184 }
02185 return RevAlloc(new CumulativeConstraint(this,
02186 intervals.data(),
02187 demands.data(),
02188 intervals.size(),
02189 capacity,
02190 name));
02191 }
02192 }