31 const std::vector<IntervalVariable>& vars) {
33 bool is_all_different =
true;
35 for (
const IntervalVariable
var : vars) {
40 is_all_different =
false;
44 if (is_all_different) {
45 std::vector<IntegerVariable> starts;
46 starts.reserve(vars.size());
47 for (
const IntervalVariable
var : vars) {
56 if (vars.size() > 2 && sat_parameters.use_combined_no_overlap()) {
64 model->TakeOwnership(helper);
69 std::vector<AffineExpression> demands(vars.size(), one);
73 model->TakeOwnership(timetable);
77 if (vars.size() == 2) {
80 model->TakeOwnership(propagator);
89 watcher->SetPropagatorPriority(
id, 1);
90 model->TakeOwnership(overload_checker);
92 for (
const bool time_direction : {
true,
false}) {
95 const int id = detectable_precedences->
RegisterWith(watcher);
96 watcher->SetPropagatorPriority(
id, 2);
97 model->TakeOwnership(detectable_precedences);
99 for (
const bool time_direction : {
true,
false}) {
103 watcher->SetPropagatorPriority(
id, 3);
104 model->TakeOwnership(not_last);
106 for (
const bool time_direction : {
true,
false}) {
110 watcher->SetPropagatorPriority(
id, 4);
111 model->TakeOwnership(edge_finding);
118 if (sat_parameters.use_precedences_in_disjunctive_constraint() &&
119 !sat_parameters.use_combined_no_overlap()) {
120 for (
const bool time_direction : {
true,
false}) {
125 watcher->SetPropagatorPriority(
id, 5);
126 model->TakeOwnership(precedences);
133 const std::vector<IntervalVariable>& vars) {
139 for (
int i = 0; i < vars.size(); ++i) {
140 for (
int j = 0; j < i; ++j) {
144 precedences->AddConditionalPrecedence(repository->EndVar(vars[i]),
145 repository->StartVar(vars[j]),
147 precedences->AddConditionalPrecedence(repository->EndVar(vars[j]),
148 repository->StartVar(vars[i]),
156 const std::vector<IntervalVariable>& vars) {
164 int j = sorted_tasks_.size();
165 sorted_tasks_.push_back(e);
167 sorted_tasks_[j] = sorted_tasks_[j - 1];
170 sorted_tasks_[j] = e;
171 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
175 if (j <= optimized_restart_) optimized_restart_ = 0;
180 const IntegerValue dmin = helper.
SizeMin(t);
185 const int size = sorted_tasks_.size();
186 for (
int i = 0;; ++i) {
187 if (i == size)
return;
188 if (sorted_tasks_[i].task == e.
task) {
189 sorted_tasks_.erase(sorted_tasks_.begin() + i);
194 optimized_restart_ = sorted_tasks_.size();
195 sorted_tasks_.push_back(e);
196 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
200 sorted_tasks_.erase(sorted_tasks_.begin() +
index);
201 optimized_restart_ = 0;
205 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
206 const int size = sorted_tasks_.size();
208 for (
int i = optimized_restart_; i < size; ++i) {
209 const Entry& e = sorted_tasks_[i];
211 optimized_restart_ = i;
221 int* critical_index)
const {
223 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
224 bool ignored =
false;
225 const int size = sorted_tasks_.size();
230 if (optimized_restart_ + 1 == size &&
231 sorted_tasks_[optimized_restart_].task == task_to_ignore) {
232 optimized_restart_ = 0;
235 for (
int i = optimized_restart_; i < size; ++i) {
236 const Entry& e = sorted_tasks_[i];
237 if (e.
task == task_to_ignore) {
243 if (!ignored) optimized_restart_ = i;
279 const IntegerValue end_min_before = helper_->
EndMin(task_before);
280 if (helper_->
StartMin(task_after) < end_min_before) {
295 const IntegerValue start_max_after = helper_->
StartMax(task_after);
296 if (helper_->
EndMax(task_before) > start_max_after) {
315 const int id = watcher->
Register(
this);
320template <
bool time_direction>
323 task_to_disjunctives_.resize(helper_->
NumTasks());
326 const int id = watcher->
Register(
this);
329 watcher->NotifyThatPropagatorMayNotReachFixedPointInOnePass(
id);
332template <
bool time_direction>
334 const std::vector<IntervalVariable>& vars) {
335 const int index = task_sets_.size();
336 task_sets_.emplace_back(vars.size());
338 for (
const IntervalVariable
var : vars) {
339 task_to_disjunctives_[
var.value()].push_back(
index);
343template <
bool time_direction>
345 if (!helper_->SynchronizeAndSetTimeDirection(time_direction))
return false;
346 const auto& task_by_increasing_end_min = helper_->TaskByIncreasingEndMin();
347 const auto& task_by_decreasing_start_max =
348 helper_->TaskByDecreasingStartMax();
350 for (
auto& task_set : task_sets_) task_set.Clear();
354 const int num_tasks = helper_->NumTasks();
355 task_is_added_.assign(num_tasks,
false);
356 int queue_index = num_tasks - 1;
357 for (
const auto task_time : task_by_increasing_end_min) {
358 const int t = task_time.task_index;
359 const IntegerValue
end_min = task_time.time;
360 if (helper_->IsAbsent(t))
continue;
363 while (queue_index >= 0) {
364 const auto to_insert = task_by_decreasing_start_max[queue_index];
365 const int task_index = to_insert.task_index;
366 const IntegerValue
start_max = to_insert.time;
368 if (helper_->IsPresent(task_index)) {
369 task_is_added_[task_index] =
true;
370 const IntegerValue shifted_smin = helper_->ShiftedStartMin(task_index);
371 const IntegerValue size_min = helper_->SizeMin(task_index);
372 for (
const int d_index : task_to_disjunctives_[task_index]) {
374 task_sets_[d_index].AddEntry({task_index, shifted_smin, size_min});
375 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
376 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
384 IntegerValue new_start_min = helper_->StartMin(t);
385 if (new_start_min >= max_of_end_min)
continue;
386 int best_critical_index = 0;
387 int best_d_index = -1;
388 if (task_is_added_[t]) {
389 for (
const int d_index : task_to_disjunctives_[t]) {
390 if (new_start_min >= end_mins_[d_index])
continue;
391 int critical_index = 0;
392 const IntegerValue end_min_of_critical_tasks =
393 task_sets_[d_index].ComputeEndMin(t,
395 DCHECK_LE(end_min_of_critical_tasks, max_of_end_min);
396 if (end_min_of_critical_tasks > new_start_min) {
397 new_start_min = end_min_of_critical_tasks;
398 best_d_index = d_index;
399 best_critical_index = critical_index;
405 for (
const int d_index : task_to_disjunctives_[t]) {
406 if (end_mins_[d_index] > new_start_min) {
407 new_start_min = end_mins_[d_index];
408 best_d_index = d_index;
411 if (best_d_index != -1) {
412 const IntegerValue end_min_of_critical_tasks =
413 task_sets_[best_d_index].ComputeEndMin(t,
414 &best_critical_index);
415 CHECK_EQ(end_min_of_critical_tasks, new_start_min);
420 if (best_d_index == -1)
continue;
425 helper_->ClearReason();
426 const std::vector<TaskSet::Entry>& sorted_tasks =
427 task_sets_[best_d_index].SortedTasks();
428 const IntegerValue window_start =
429 sorted_tasks[best_critical_index].start_min;
430 for (
int i = best_critical_index; i < sorted_tasks.size(); ++i) {
431 const int ct = sorted_tasks[i].task;
432 if (
ct == t)
continue;
433 helper_->AddPresenceReason(
ct);
434 helper_->AddEnergyAfterReason(
ct, sorted_tasks[i].size_min, window_start);
435 helper_->AddStartMaxReason(
ct,
end_min - 1);
437 helper_->AddEndMinReason(t,
end_min);
438 if (!helper_->IncreaseStartMin(t, new_start_min)) {
446 if (task_is_added_[t]) {
447 const IntegerValue shifted_smin = helper_->ShiftedStartMin(t);
448 const IntegerValue size_min = helper_->SizeMin(t);
449 for (
const int d_index : task_to_disjunctives_[t]) {
450 task_sets_[d_index].NotifyEntryIsNowLastIfPresent(
451 {t, shifted_smin, size_min});
452 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
453 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
477 IntegerValue relevant_end;
478 int relevant_size = 0;
480 const int task = task_time.task_index;
481 if (helper_->
IsAbsent(task))
continue;
483 const IntegerValue
start_min = task_time.time;
485 window_.push_back(task_time);
486 window_end += helper_->
SizeMin(task);
487 if (window_end > helper_->
EndMax(task)) {
488 relevant_size = window_.size();
489 relevant_end = window_end;
497 window_.resize(relevant_size);
498 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
504 window_.push_back(task_time);
510 window_.resize(relevant_size);
511 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
525bool DisjunctiveOverloadChecker::PropagateSubwindow(
526 IntegerValue global_window_end) {
528 const int window_size = window_.size();
529 theta_tree_.Reset(window_size);
530 task_by_increasing_end_max_.clear();
531 for (
int i = 0; i < window_size; ++i) {
533 const int task = window_[i].task_index;
535 if (
end_max < global_window_end) {
536 task_to_event_[task] = i;
537 task_by_increasing_end_max_.push_back({task,
end_max});
542 std::sort(task_by_increasing_end_max_.begin(),
543 task_by_increasing_end_max_.end());
544 for (
const auto task_time : task_by_increasing_end_max_) {
545 const int current_task = task_time.task_index;
550 if (helper_->
IsAbsent(current_task))
continue;
552 DCHECK_NE(task_to_event_[current_task], -1);
554 const int current_event = task_to_event_[current_task];
555 const IntegerValue energy_min = helper_->
SizeMin(current_task);
560 theta_tree_.AddOrUpdateEvent(current_event, window_[current_event].
time,
561 energy_min, energy_min);
563 theta_tree_.AddOrUpdateOptionalEvent(
564 current_event, window_[current_event].
time, energy_min);
568 const IntegerValue current_end = task_time.time;
569 if (theta_tree_.GetEnvelope() > current_end) {
572 const int critical_event =
573 theta_tree_.GetMaxEventWithEnvelopeGreaterThan(current_end);
574 const IntegerValue window_start = window_[critical_event].time;
575 const IntegerValue window_end =
576 theta_tree_.GetEnvelopeOf(critical_event) - 1;
577 for (
int event = critical_event;
event < window_size;
event++) {
578 const IntegerValue energy_min = theta_tree_.EnergyMin(event);
579 if (energy_min > 0) {
580 const int task = window_[event].task_index;
590 while (theta_tree_.GetOptionalEnvelope() > current_end) {
597 IntegerValue available_energy;
598 theta_tree_.GetEventsWithOptionalEnvelopeGreaterThan(
599 current_end, &critical_event, &optional_event, &available_energy);
601 const int optional_task = window_[optional_event].task_index;
605 if (!helper_->
IsAbsent(optional_task)) {
606 const IntegerValue optional_size_min = helper_->
SizeMin(optional_task);
607 const IntegerValue window_start = window_[critical_event].time;
608 const IntegerValue window_end =
609 current_end + optional_size_min - available_energy - 1;
610 for (
int event = critical_event;
event < window_size;
event++) {
611 const IntegerValue energy_min = theta_tree_.EnergyMin(event);
612 if (energy_min > 0) {
613 const int task = window_[event].task_index;
627 theta_tree_.RemoveEvent(optional_event);
636 const int id = watcher->
Register(
this);
646 to_propagate_.clear();
647 processed_.assign(helper_->
NumTasks(),
false);
656 task_by_increasing_end_min_.clear();
659 const int task = task_time.task_index;
660 if (helper_->
IsAbsent(task))
continue;
664 const IntegerValue size_min = helper_->
SizeMin(task);
669 task_by_increasing_end_min_.push_back({task,
end_min});
675 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
680 task_by_increasing_end_min_.clear();
681 task_by_increasing_end_min_.push_back({task,
end_min});
685 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
692bool DisjunctiveDetectablePrecedences::PropagateSubwindow() {
693 DCHECK(!task_by_increasing_end_min_.empty());
698 task_by_increasing_end_min_.end());
699 const IntegerValue max_end_min = task_by_increasing_end_min_.back().time;
705 task_by_increasing_start_max_.clear();
706 for (
const TaskTime entry : task_by_increasing_end_min_) {
707 const int task = entry.task_index;
709 if (start_max < max_end_min && helper_->IsPresent(task)) {
710 task_by_increasing_start_max_.push_back({task,
start_max});
713 if (task_by_increasing_start_max_.empty())
return true;
714 std::sort(task_by_increasing_start_max_.begin(),
715 task_by_increasing_start_max_.end());
723 to_propagate_.clear();
724 bool need_update =
false;
728 int blocking_task = -1;
729 const int queue_size = task_by_increasing_start_max_.size();
730 for (
const auto task_time : task_by_increasing_end_min_) {
734 const int current_task = task_time.task_index;
735 const IntegerValue current_end_min = task_time.time;
736 if (helper_->
IsAbsent(current_task))
continue;
738 for (; queue_index < queue_size; ++queue_index) {
739 const auto to_insert = task_by_increasing_start_max_[queue_index];
740 const IntegerValue
start_max = to_insert.time;
743 const int t = to_insert.task_index;
757 if (!processed_[t]) {
758 if (blocking_task != -1) {
768 <<
" task should have mandatory part: "
770 DCHECK(to_propagate_.empty());
772 to_propagate_.push_back(t);
781 if (blocking_task != current_task) {
782 to_propagate_.push_back(current_task);
783 if (blocking_task != -1)
continue;
785 for (
const int t : to_propagate_) {
787 processed_[t] =
true;
806 if (task_set_end_min > helper_->
StartMin(t)) {
808 const std::vector<TaskSet::Entry>& sorted_tasks =
815 const IntegerValue end_min_if_present =
817 const IntegerValue window_start =
818 sorted_tasks[critical_index].start_min;
819 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
820 const int ct = sorted_tasks[i].task;
842 if (t == blocking_task) {
853 to_propagate_.clear();
860 const int id = watcher->
Register(
this);
873 const int task = task_time.task_index;
876 const IntegerValue
start_min = task_time.time;
878 window_.push_back(task_time);
879 window_end += helper_->
SizeMin(task);
883 if (window_.size() > 1 && !PropagateSubwindow()) {
889 window_.push_back(task_time);
892 if (window_.size() > 1 && !PropagateSubwindow()) {
898bool DisjunctivePrecedences::PropagateSubwindow() {
904 index_to_end_vars_.clear();
906 for (
const auto task_time : window_) {
907 const int task = task_time.task_index;
913 window_[new_size++] = task_time;
914 index_to_end_vars_.push_back(end_exp.
var);
916 window_.resize(new_size);
919 const int size = before_.size();
920 for (
int i = 0; i < size;) {
921 const IntegerVariable
var = before_[i].var;
925 const int initial_i = i;
927 for (; i < size && before_[i].var ==
var; ++i) {
929 const TaskTime task_time = window_[before_[i].index];
934 const AffineExpression& end_exp = helper_->
Ends()[task_time.task_index];
935 min_offset =
std::min(min_offset, before_[i].offset - end_exp.constant);
940 helper_->
SizeMin(task_time.task_index)});
947 const IntegerValue new_lb = task_set_.
ComputeEndMin() + min_offset;
949 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
954 for (
int j = initial_i; j < i; ++j) {
955 const int task = window_[before_[j].index].task_index;
956 task_to_arc_index_[task] = before_[j].arc_index;
960 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
961 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
962 const int ct = sorted_tasks[i].task;
967 const AffineExpression& end_exp = helper_->
Ends()[
ct];
969 task_to_arc_index_[
ct], min_offset + end_exp.constant,
986 const int id = watcher->
Register(
this);
996 const auto& task_by_decreasing_start_max =
998 const auto& task_by_increasing_shifted_start_min =
1012 int queue_index = task_by_decreasing_start_max.size() - 1;
1013 const int num_tasks = task_by_increasing_shifted_start_min.size();
1014 for (
int i = 0; i < num_tasks;) {
1015 start_min_window_.clear();
1017 for (; i < num_tasks; ++i) {
1018 const TaskTime task_time = task_by_increasing_shifted_start_min[i];
1020 if (!helper_->
IsPresent(task))
continue;
1023 if (start_min_window_.empty()) {
1024 start_min_window_.push_back(task_time);
1027 start_min_window_.push_back(task_time);
1028 window_end += helper_->
SizeMin(task);
1036 start_max_window_.clear();
1037 for (; queue_index >= 0; queue_index--) {
1038 const auto task_time = task_by_decreasing_start_max[queue_index];
1041 if (task_time.time >= window_end)
break;
1042 if (helper_->
IsAbsent(task_time.task_index))
continue;
1043 start_max_window_.push_back(task_time);
1049 if (start_min_window_.size() <= 1)
continue;
1052 if (!start_max_window_.empty() && !PropagateSubwindow()) {
1059bool DisjunctiveNotLast::PropagateSubwindow() {
1060 auto& task_by_increasing_end_max = start_max_window_;
1061 for (
TaskTime& entry : task_by_increasing_end_max) {
1062 entry.time = helper_->
EndMax(entry.task_index);
1065 task_by_increasing_end_max.end());
1067 const IntegerValue threshold = task_by_increasing_end_max.back().time;
1068 auto& task_by_increasing_start_max = start_min_window_;
1070 for (
const TaskTime entry : task_by_increasing_start_max) {
1071 const int task = entry.task_index;
1075 task_by_increasing_start_max[queue_size++] = {task,
start_max};
1081 if (queue_size <= 1)
return true;
1083 task_by_increasing_start_max.resize(queue_size);
1084 std::sort(task_by_increasing_start_max.begin(),
1085 task_by_increasing_start_max.end());
1088 int queue_index = 0;
1089 for (
const auto task_time : task_by_increasing_end_max) {
1090 const int t = task_time.task_index;
1091 const IntegerValue
end_max = task_time.time;
1095 if (helper_->
IsAbsent(t))
continue;
1100 while (queue_index < queue_size) {
1101 const auto to_insert = task_by_increasing_start_max[queue_index];
1102 const IntegerValue
start_max = to_insert.time;
1105 const int task_index = to_insert.task_index;
1108 helper_->
SizeMin(task_index)});
1122 int critical_index = 0;
1123 const IntegerValue end_min_of_critical_tasks =
1125 if (end_min_of_critical_tasks <= helper_->StartMax(t))
continue;
1130 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
1131 const int sorted_tasks_size = sorted_tasks.size();
1132 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1133 const int ct = sorted_tasks[i].task;
1134 if (t ==
ct)
continue;
1144 end_max > largest_ct_start_max);
1145 if (
end_max > largest_ct_start_max) {
1148 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
1149 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1150 const int ct = sorted_tasks[i].task;
1151 if (
ct == t)
continue;
1163 if (!helper_->
DecreaseEndMax(t, largest_ct_start_max))
return false;
1170 const int id = watcher->
Register(
this);
1177 const int num_tasks = helper_->
NumTasks();
1179 is_gray_.resize(num_tasks,
false);
1180 non_gray_task_to_event_.resize(num_tasks);
1185 const int task = task_time.task_index;
1186 if (helper_->
IsAbsent(task))
continue;
1190 if (helper_->
StartMin(task) < window_end) {
1191 window_.push_back(task_time);
1192 window_end += helper_->
SizeMin(task);
1198 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1204 window_.push_back(task_time);
1205 window_end = task_time.time + helper_->
SizeMin(task);
1207 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1213bool DisjunctiveEdgeFinding::PropagateSubwindow(IntegerValue window_end_min) {
1215 task_by_increasing_end_max_.clear();
1216 for (
const auto task_time : window_) {
1217 const int task = task_time.task_index;
1230 is_gray_[task] =
false;
1231 task_by_increasing_end_max_.push_back({task,
end_max});
1233 is_gray_[task] =
true;
1239 if (task_by_increasing_end_max_.size() < 2)
return true;
1240 std::sort(task_by_increasing_end_max_.begin(),
1241 task_by_increasing_end_max_.end());
1252 const int window_size = window_.size();
1253 event_size_.clear();
1254 theta_tree_.Reset(window_size);
1255 for (
int event = 0;
event < window_size; ++event) {
1256 const TaskTime task_time = window_[event];
1257 const int task = task_time.task_index;
1258 const IntegerValue energy_min = helper_->
SizeMin(task);
1259 event_size_.push_back(energy_min);
1260 if (is_gray_[task]) {
1261 theta_tree_.AddOrUpdateOptionalEvent(event, task_time.time, energy_min);
1263 non_gray_task_to_event_[task] = event;
1264 theta_tree_.AddOrUpdateEvent(event, task_time.time, energy_min,
1272 DCHECK(!is_gray_[task_by_increasing_end_max_.back().task_index]);
1273 const IntegerValue non_gray_end_max =
1274 task_by_increasing_end_max_.back().time;
1277 const IntegerValue non_gray_end_min = theta_tree_.GetEnvelope();
1278 if (non_gray_end_min > non_gray_end_max) {
1282 const int critical_event =
1283 theta_tree_.GetMaxEventWithEnvelopeGreaterThan(non_gray_end_max);
1284 const IntegerValue window_start = window_[critical_event].time;
1285 const IntegerValue window_end =
1286 theta_tree_.GetEnvelopeOf(critical_event) - 1;
1287 for (
int event = critical_event;
event < window_size;
event++) {
1288 const int task = window_[event].task_index;
1289 if (is_gray_[task])
continue;
1306 while (theta_tree_.GetOptionalEnvelope() > non_gray_end_max) {
1307 int critical_event_with_gray;
1309 IntegerValue available_energy;
1310 theta_tree_.GetEventsWithOptionalEnvelopeGreaterThan(
1311 non_gray_end_max, &critical_event_with_gray, &gray_event,
1313 const int gray_task = window_[gray_event].task_index;
1314 DCHECK(is_gray_[gray_task]);
1318 if (helper_->
IsAbsent(gray_task)) {
1319 theta_tree_.RemoveEvent(gray_event);
1324 if (helper_->
StartMin(gray_task) < non_gray_end_min) {
1327 const int critical_event =
1328 theta_tree_.GetMaxEventWithEnvelopeGreaterThan(non_gray_end_min -
1330 const int first_event =
1331 std::min(critical_event, critical_event_with_gray);
1332 const int second_event =
1333 std::max(critical_event, critical_event_with_gray);
1334 const IntegerValue first_start = window_[first_event].time;
1335 const IntegerValue second_start = window_[second_event].time;
1339 const IntegerValue window_end =
1340 non_gray_end_max + event_size_[gray_event] - available_energy - 1;
1341 CHECK_GE(window_end, non_gray_end_max);
1345 for (
int event = first_event;
event < window_size;
event++) {
1346 const int task = window_[event].task_index;
1347 if (is_gray_[task])
continue;
1350 task, event_size_[event],
1351 event >= second_event ? second_start : first_start);
1358 window_[critical_event_with_gray].
time);
1371 theta_tree_.RemoveEvent(gray_event);
1375 if (task_by_increasing_end_max_.size() <= 2)
break;
1378 if (task_by_increasing_end_max_[0].
time >=
1379 theta_tree_.GetOptionalEnvelope()) {
1384 const int new_gray_task = task_by_increasing_end_max_.back().task_index;
1385 task_by_increasing_end_max_.pop_back();
1386 const int new_gray_event = non_gray_task_to_event_[new_gray_task];
1387 DCHECK(!is_gray_[new_gray_task]);
1388 is_gray_[new_gray_task] =
true;
1389 theta_tree_.AddOrUpdateOptionalEvent(new_gray_event,
1390 window_[new_gray_event].
time,
1391 event_size_[new_gray_event]);
1398 const int id = watcher->
Register(
this);
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
void AddNoOverlap(const std::vector< IntervalVariable > &var)
CombinedDisjunctive(Model *model)
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
int Register(PropagatorInterface *propagator)
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
bool IsCurrentlyIgnored(IntegerVariable i) const
IntegerValue LowerBound(IntegerVariable i) const
IntegerValue MaxSize(IntervalVariable i) const
AffineExpression Start(IntervalVariable i) const
IntegerValue MinSize(IntervalVariable i) const
bool IsOptional(IntervalVariable i) const
Class that owns everything related to a particular optimization model.
void AddPrecedenceReason(int arc_index, IntegerValue min_offset, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason) const
void ComputePrecedences(const std::vector< IntegerVariable > &vars, std::vector< IntegerPrecedences > *output)
BooleanVariable NewBooleanVariable()
std::vector< Literal > * MutableLiteralReason()
IntegerValue ShiftedStartMin(int t) const
IntegerValue EndMin(int t) const
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
std::vector< IntegerLiteral > * MutableIntegerReason()
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
const std::vector< TaskTime > & TaskByIncreasingStartMin()
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
void AddPresenceReason(int t)
bool IsPresent(int t) const
void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time)
bool InPropagationLoop() const
std::string TaskDebugString(int t) const
void AddEndMinReason(int t, IntegerValue lower_bound)
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
bool IsAbsent(int t) const
IntegerValue EndMax(int t) const
ABSL_MUST_USE_RESULT bool ReportConflict()
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
IntegerValue StartMin(int t) const
const std::vector< TaskTime > & TaskByDecreasingStartMax()
void AddEndMaxReason(int t, IntegerValue upper_bound)
IntegerValue StartMax(int t) const
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
void AddReasonForBeingBefore(int before, int after)
void AddStartMaxReason(int t, IntegerValue upper_bound)
void SetTimeDirection(bool is_forward)
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_end_max)
const std::vector< AffineExpression > & Ends() const
IntegerValue SizeMin(int t) const
void AddUnsortedEntry(const Entry &e)
void NotifyEntryIsNowLastIfPresent(const Entry &e)
void RemoveEntryWithIndex(int index)
int GetCriticalIndex() const
const std::vector< Entry > & SortedTasks() const
void AddShiftedStartMinEntry(const SchedulingConstraintHelper &helper, int t)
IntegerValue ComputeEndMin() const
void AddEntry(const Entry &e)
IntegerValue ComputeEndMin(int task_to_ignore, int *critical_index) const
void RegisterWith(GenericLiteralWatcher *watcher)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
std::function< void(Model *)> AllDifferentOnBounds(const std::vector< IntegerVariable > &vars)
const IntegerVariable kNoIntegerVariable(-1)
std::function< void(Model *)> DisjunctiveWithBooleanPrecedencesOnly(const std::vector< IntervalVariable > &vars)
std::function< void(Model *)> DisjunctiveWithBooleanPrecedences(const std::vector< IntervalVariable > &vars)
std::function< void(Model *)> Disjunctive(const std::vector< IntervalVariable > &vars)
std::function< IntegerVariable(const Model &)> StartVar(IntervalVariable v)
Collection of objects used to extend the Constraint Solver library.
void IncrementalSort(int max_comparisons, Iterator begin, Iterator end, Compare comp=Compare{}, bool is_stable=false)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)