18 #include "absl/strings/str_format.h"
38 const std::vector<IntervalVar*>& intervals,
39 const std::vector<IntVar*>& nexts,
40 const std::string&
name)
42 intervals_(intervals),
44 previous_(nexts.size() + 1, -1) {
51 return intervals_[
index];
57 int64 hmin, hmax, dmin, dmax;
64 return absl::StrFormat(
65 "%s(horizon = %d..%d, duration = %d..%d, not ranked = %d, ranked = %d, "
67 name(), hmin, hmax, dmin, dmax, not_ranked, ranked,
78 for (
int i = 0; i < intervals_.size(); ++i) {
94 for (
int i = 0; i < intervals_.size(); ++i) {
107 int64*
const hmax)
const {
108 absl::flat_hash_set<int> decided;
109 for (
int i = 0; i < intervals_.size(); ++i) {
110 if (intervals_[i]->CannotBePerformed()) {
115 while (nexts_[first]->Bound()) {
116 first = nexts_[first]->Min();
117 if (first < nexts_.size()) {
118 decided.insert(ValueToIndex(first));
123 if (first != nexts_.size()) {
125 int last = nexts_.size();
126 while (previous_[last] != -1) {
127 last = previous_[last];
128 decided.insert(ValueToIndex(last));
133 for (
int i = 0; i < intervals_.size(); ++i) {
145 int*
const unperformed)
const {
147 for (
int i = 0; i < intervals_.size(); ++i) {
148 if (intervals_[i]->CannotBePerformed()) {
154 while (first < nexts_.size() && nexts_[first]->Bound()) {
155 first = nexts_[first]->Min();
158 if (first != nexts_.size()) {
160 int last = nexts_.size();
161 while (previous_[last] != -1) {
162 last = previous_[last];
168 *not_ranked = intervals_.size() - *ranked - *unperformed;
171 int SequenceVar::ComputeForwardFrontier() {
173 while (first != nexts_.size() && nexts_[first]->Bound()) {
174 first = nexts_[first]->Min();
179 int SequenceVar::ComputeBackwardFrontier() {
181 int last = nexts_.size();
182 while (previous_[last] != -1) {
183 last = previous_[last];
189 std::vector<int>*
const possible_firsts,
190 std::vector<int>*
const possible_lasts) {
191 possible_firsts->clear();
192 possible_lasts->clear();
193 absl::flat_hash_set<int> to_check;
194 for (
int i = 0; i < intervals_.size(); ++i) {
195 if (intervals_[i]->MayBePerformed()) {
200 while (nexts_[first]->Bound()) {
201 first = nexts_[first]->Min();
202 if (first == nexts_.size()) {
205 to_check.erase(ValueToIndex(first));
208 IntVar*
const forward_var = nexts_[first];
209 std::vector<int> candidates;
211 int ssm_support = -1;
212 for (
int64 i = forward_var->
Min(); i <= forward_var->Max(); ++i) {
214 if (i != 0 && i < IndexToValue(intervals_.size()) &&
215 intervals_[ValueToIndex(i)]->MayBePerformed() &&
217 const int candidate = ValueToIndex(i);
218 candidates.push_back(candidate);
219 if (intervals_[candidate]->MustBePerformed()) {
220 if (smallest_start_max > intervals_[candidate]->StartMax()) {
221 smallest_start_max = intervals_[candidate]->StartMax();
222 ssm_support = candidate;
227 for (
int i = 0; i < candidates.size(); ++i) {
228 const int candidate = candidates[i];
229 if (candidate == ssm_support ||
230 intervals_[candidate]->EndMin() <= smallest_start_max) {
231 possible_firsts->push_back(candidate);
236 int last = nexts_.size();
237 while (previous_[last] != -1) {
238 last = previous_[last];
239 to_check.erase(ValueToIndex(last));
244 int bem_support = -1;
245 for (
const int candidate : to_check) {
246 if (nexts_[IndexToValue(candidate)]->Contains(last)) {
247 candidates.push_back(candidate);
248 if (intervals_[candidate]->MustBePerformed()) {
249 if (biggest_end_min < intervals_[candidate]->EndMin()) {
250 biggest_end_min = intervals_[candidate]->EndMin();
251 bem_support = candidate;
257 for (
int i = 0; i < candidates.size(); ++i) {
258 const int candidate = candidates[i];
259 if (candidate == bem_support ||
260 intervals_[candidate]->StartMax() >= biggest_end_min) {
261 possible_lasts->push_back(candidate);
267 const std::vector<int>& rank_last,
268 const std::vector<int>& unperformed) {
272 for (
const int value : unperformed) {
273 intervals_[
value]->SetPerformed(
false);
277 for (
int i = 0; i < rank_first.size(); ++i) {
278 const int next = 1 + rank_first[i];
279 nexts_[forward]->SetValue(
next);
283 int backward = IndexToValue(intervals_.size());
284 for (
int i = 0; i < rank_last.size(); ++i) {
285 const int next = 1 + rank_last[i];
286 nexts_[
next]->SetValue(backward);
293 intervals_[
index]->SetPerformed(
true);
294 int forward_frontier = 0;
295 while (forward_frontier != nexts_.size() &&
296 nexts_[forward_frontier]->Bound()) {
297 forward_frontier = nexts_[forward_frontier]->Min();
298 if (forward_frontier == IndexToValue(
index)) {
302 DCHECK_LT(forward_frontier, nexts_.size());
303 nexts_[forward_frontier]->SetValue(IndexToValue(
index));
308 const int forward_frontier = ComputeForwardFrontier();
309 if (forward_frontier < nexts_.size()) {
310 nexts_[forward_frontier]->RemoveValue(IndexToValue(
index));
316 intervals_[
index]->SetPerformed(
true);
318 int backward_frontier = nexts_.size();
319 while (previous_[backward_frontier] != -1) {
320 backward_frontier = previous_[backward_frontier];
321 if (backward_frontier == IndexToValue(
index)) {
326 nexts_[IndexToValue(
index)]->SetValue(backward_frontier);
331 const int backward_frontier = ComputeBackwardFrontier();
332 nexts_[IndexToValue(
index)]->RemoveValue(backward_frontier);
335 void SequenceVar::UpdatePrevious()
const {
336 for (
int i = 0; i < intervals_.size() + 2; ++i) {
339 for (
int i = 0; i < nexts_.size(); ++i) {
340 if (nexts_[i]->Bound()) {
341 previous_[nexts_[i]->Min()] = i;
347 std::vector<int>*
const rank_last,
348 std::vector<int>*
const unperformed)
const {
349 CHECK(rank_first !=
nullptr);
350 CHECK(rank_last !=
nullptr);
351 CHECK(unperformed !=
nullptr);
354 unperformed->clear();
355 for (
int i = 0; i < intervals_.size(); ++i) {
356 if (intervals_[i]->CannotBePerformed()) {
357 unperformed->push_back(i);
361 while (nexts_[first]->Bound()) {
362 first = nexts_[first]->Min();
363 if (first < nexts_.size()) {
364 rank_first->push_back(ValueToIndex(first));
369 if (first != nexts_.size()) {
371 int last = nexts_.size();
372 while (previous_[last] != -1) {
373 last = previous_[last];
374 rank_last->push_back(ValueToIndex(last));
387 class ScheduleOrPostpone :
public Decision {
390 : var_(
var), est_(est), marker_(marker) {}
391 ~ScheduleOrPostpone()
override {}
393 void Apply(Solver*
const s)
override {
394 var_->SetPerformed(
true);
395 if (est_.Value() < var_->StartMin()) {
396 est_.SetValue(s, var_->StartMin());
398 var_->SetStartRange(est_.Value(), est_.Value());
401 void Refute(Solver*
const s)
override {
402 s->SaveAndSetValue(marker_, est_.Value());
405 void Accept(DecisionVisitor*
const visitor)
const override {
406 CHECK(visitor !=
nullptr);
407 visitor->VisitScheduleOrPostpone(var_, est_.Value());
410 std::string DebugString()
const override {
411 return absl::StrFormat(
"ScheduleOrPostpone(%s at %d)", var_->DebugString(),
416 IntervalVar*
const var_;
417 NumericalRev<int64> est_;
418 int64*
const marker_;
421 class SetTimesForward :
public DecisionBuilder {
423 explicit SetTimesForward(
const std::vector<IntervalVar*>& vars)
426 ~SetTimesForward()
override {}
428 Decision* Next(Solver*
const s)
override {
435 for (
int i = 0; i <
vars_.size(); ++i) {
436 IntervalVar*
const v =
vars_[i];
437 if (v->MayBePerformed() && v->StartMax() != v->StartMin() &&
439 (v->StartMin() < best_est ||
440 (v->StartMin() == best_est && v->EndMax() < best_lct))) {
441 best_est = v->StartMin();
442 best_lct = v->EndMax();
452 UnperformPostponedTaskBefore(best_est);
454 new ScheduleOrPostpone(vars_[support], best_est, &markers_[support]));
457 std::string DebugString()
const override {
return "SetTimesForward()"; }
459 void Accept(ModelVisitor*
const visitor)
const override {
467 bool IsPostponed(
int index) {
472 void UnperformPostponedTaskBefore(
int64 date) {
473 for (
int i = 0; i <
vars_.size(); ++i) {
474 IntervalVar*
const v =
vars_[i];
475 if (v->MayBePerformed() && v->StartMin() != v->StartMax() &&
484 (v->EndMin() <= date || v->StartMax() <= date)) {
485 v->SetPerformed(
false);
490 const std::vector<IntervalVar*>
vars_;
491 std::vector<int64> markers_;
497 class ScheduleOrExpedite :
public Decision {
499 ScheduleOrExpedite(IntervalVar*
const var,
int64 est,
int64*
const marker)
500 : var_(
var), est_(est), marker_(marker) {}
501 ~ScheduleOrExpedite()
override {}
503 void Apply(Solver*
const s)
override {
504 var_->SetPerformed(
true);
505 if (est_.Value() > var_->EndMax()) {
506 est_.SetValue(s, var_->EndMax());
508 var_->SetEndRange(est_.Value(), est_.Value());
511 void Refute(Solver*
const s)
override {
512 s->SaveAndSetValue(marker_, est_.Value() - 1);
515 void Accept(DecisionVisitor*
const visitor)
const override {
516 CHECK(visitor !=
nullptr);
517 visitor->VisitScheduleOrExpedite(var_, est_.Value());
520 std::string DebugString()
const override {
521 return absl::StrFormat(
"ScheduleOrExpedite(%s at %d)", var_->DebugString(),
526 IntervalVar*
const var_;
527 NumericalRev<int64> est_;
528 int64*
const marker_;
531 class SetTimesBackward :
public DecisionBuilder {
533 explicit SetTimesBackward(
const std::vector<IntervalVar*>& vars)
536 ~SetTimesBackward()
override {}
538 Decision* Next(Solver*
const s)
override {
543 for (
int i = 0; i <
vars_.size(); ++i) {
544 IntervalVar*
const v =
vars_[i];
545 if (v->MayBePerformed() && v->EndMax() > v->EndMin()) {
546 if (v->EndMax() <= markers_[i] &&
547 (v->EndMax() > best_end ||
548 (v->EndMax() == best_end && v->StartMin() > best_start))) {
549 best_end = v->EndMax();
550 best_start = v->StartMin();
566 return s->RevAlloc(
new ScheduleOrExpedite(
567 vars_[support], vars_[support]->EndMax(), &markers_[support]));
570 std::string DebugString()
const override {
return "SetTimesBackward()"; }
572 void Accept(ModelVisitor*
const visitor)
const override {
580 const std::vector<IntervalVar*>
vars_;
581 std::vector<int64> markers_;
586 class RankFirst :
public Decision {
588 RankFirst(SequenceVar*
const seq,
int index)
589 : sequence_(seq), index_(
index) {}
590 ~RankFirst()
override {}
592 void Apply(Solver*
const s)
override { sequence_->RankFirst(index_); }
594 void Refute(Solver*
const s)
override { sequence_->RankNotFirst(index_); }
596 void Accept(DecisionVisitor*
const visitor)
const override {
597 CHECK(visitor !=
nullptr);
598 visitor->VisitRankFirstInterval(sequence_, index_);
601 std::string DebugString()
const override {
602 return absl::StrFormat(
"RankFirst(%s, %d)", sequence_->DebugString(),
607 SequenceVar*
const sequence_;
611 class RankLast :
public Decision {
613 RankLast(SequenceVar*
const seq,
int index) : sequence_(seq), index_(
index) {}
614 ~RankLast()
override {}
616 void Apply(Solver*
const s)
override { sequence_->RankLast(index_); }
618 void Refute(Solver*
const s)
override { sequence_->RankNotLast(index_); }
620 void Accept(DecisionVisitor*
const visitor)
const override {
621 CHECK(visitor !=
nullptr);
622 visitor->VisitRankLastInterval(sequence_, index_);
625 std::string DebugString()
const override {
626 return absl::StrFormat(
"RankLast(%s, %d)", sequence_->DebugString(),
631 SequenceVar*
const sequence_;
635 class RankFirstIntervalVars :
public DecisionBuilder {
637 RankFirstIntervalVars(
const std::vector<SequenceVar*>& sequences,
639 : sequences_(sequences), strategy_(str) {}
641 ~RankFirstIntervalVars()
override {}
643 Decision* Next(Solver*
const s)
override {
644 SequenceVar* best_sequence =
nullptr;
645 best_possible_firsts_.clear();
647 if (FindSequenceVar(s, &best_sequence)) {
649 DCHECK(best_sequence !=
nullptr);
650 if (best_possible_firsts_.size() == 1 &&
651 best_sequence->Interval(best_possible_firsts_.back())
652 ->MustBePerformed()) {
653 best_sequence->RankFirst(best_possible_firsts_.back());
656 int best_interval = -1;
657 if (!FindIntervalVar(s, best_sequence, &best_interval)) {
661 return s->RevAlloc(
new RankFirst(best_sequence, best_interval));
668 void Accept(ModelVisitor*
const visitor)
const override {
677 bool FindIntervalVarOnStartMin(Solver*
const s,
678 SequenceVar*
const best_sequence,
679 int*
const best_interval_index) {
680 int best_interval = -1;
683 const int candidate = best_possible_firsts_[
index];
684 IntervalVar*
const interval = best_sequence->Interval(candidate);
685 if (
interval->StartMin() < best_start_min) {
686 best_interval = candidate;
687 best_start_min =
interval->StartMin();
690 if (best_interval == -1) {
693 *best_interval_index = best_interval;
698 bool FindIntervalVarRandomly(Solver*
const s,
699 SequenceVar*
const best_sequence,
700 int*
const best_interval_index) {
701 DCHECK(!best_possible_firsts_.empty());
702 const int index = s->Rand32(best_possible_firsts_.size());
703 *best_interval_index = best_possible_firsts_[
index];
707 bool FindIntervalVar(Solver*
const s, SequenceVar*
const best_sequence,
708 int*
const best_interval_index) {
713 return FindIntervalVarOnStartMin(s, best_sequence, best_interval_index);
715 return FindIntervalVarRandomly(s, best_sequence, best_interval_index);
717 LOG(
FATAL) <<
"Unknown strategy " << strategy_;
723 bool FindSequenceVarOnSlack(Solver*
const s,
724 SequenceVar**
const best_sequence) {
727 *best_sequence =
nullptr;
728 best_possible_firsts_.clear();
729 for (
int i = 0; i < sequences_.size(); ++i) {
730 SequenceVar*
const candidate_sequence = sequences_[i];
734 candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
735 if (not_ranked > 0) {
736 candidate_possible_firsts_.clear();
737 candidate_possible_lasts_.clear();
738 candidate_sequence->ComputePossibleFirstsAndLasts(
739 &candidate_possible_firsts_, &candidate_possible_lasts_);
741 if (candidate_possible_firsts_.empty()) {
745 if (candidate_possible_firsts_.size() == 1 &&
746 candidate_sequence->Interval(candidate_possible_firsts_.back())
747 ->MustBePerformed()) {
748 *best_sequence = candidate_sequence;
749 best_possible_firsts_ = candidate_possible_firsts_;
754 int64 hmin, hmax, dmin, dmax;
755 candidate_sequence->HorizonRange(&hmin, &hmax);
756 candidate_sequence->DurationRange(&dmin, &dmax);
758 candidate_sequence->ActiveHorizonRange(&ahmin, &ahmax);
759 const int64 current_slack = (hmax - hmin - dmax);
760 if (current_slack < best_slack ||
761 (current_slack == best_slack && ahmin < best_ahmin)) {
762 best_slack = current_slack;
763 *best_sequence = candidate_sequence;
764 best_possible_firsts_ = candidate_possible_firsts_;
769 return *best_sequence !=
nullptr;
772 bool FindSequenceVarRandomly(Solver*
const s,
773 SequenceVar**
const best_sequence) {
774 std::vector<SequenceVar*> all_candidates;
775 std::vector<std::vector<int>> all_possible_firsts;
776 for (
int i = 0; i < sequences_.size(); ++i) {
777 SequenceVar*
const candidate_sequence = sequences_[i];
781 candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
782 if (not_ranked > 0) {
783 candidate_possible_firsts_.clear();
784 candidate_possible_lasts_.clear();
785 candidate_sequence->ComputePossibleFirstsAndLasts(
786 &candidate_possible_firsts_, &candidate_possible_lasts_);
788 if (candidate_possible_firsts_.empty()) {
792 if (candidate_possible_firsts_.size() == 1 &&
793 candidate_sequence->Interval(candidate_possible_firsts_.back())
794 ->MustBePerformed()) {
795 *best_sequence = candidate_sequence;
796 best_possible_firsts_ = candidate_possible_firsts_;
800 all_candidates.push_back(candidate_sequence);
801 all_possible_firsts.push_back(candidate_possible_firsts_);
804 if (all_candidates.empty()) {
807 const int chosen = s->Rand32(all_candidates.size());
808 *best_sequence = all_candidates[chosen];
809 best_possible_firsts_ = all_possible_firsts[chosen];
813 bool FindSequenceVar(Solver*
const s, SequenceVar**
const best_sequence) {
818 return FindSequenceVarOnSlack(s, best_sequence);
820 return FindSequenceVarRandomly(s, best_sequence);
822 LOG(
FATAL) <<
"Unknown strategy " << strategy_;
826 const std::vector<SequenceVar*> sequences_;
828 std::vector<int> best_possible_firsts_;
829 std::vector<int> candidate_possible_firsts_;
830 std::vector<int> candidate_possible_lasts_;
835 int64*
const marker) {
837 CHECK(marker !=
nullptr);
838 return RevAlloc(
new ScheduleOrPostpone(
var, est, marker));
842 int64*
const marker) {
844 CHECK(marker !=
nullptr);
845 return RevAlloc(
new ScheduleOrExpedite(
var, est, marker));
854 return RevAlloc(
new SetTimesForward(intervals));
856 return RevAlloc(
new SetTimesBackward(intervals));
858 LOG(
FATAL) <<
"Unknown strategy " << str;
864 CHECK(sequence !=
nullptr);
869 CHECK(sequence !=
nullptr);
875 return RevAlloc(
new RankFirstIntervalVars(sequences, str));