31 const std::vector<IntervalVariable>& vars) {
33 bool is_all_different =
true;
35 for (
const IntervalVariable
var : vars) {
38 is_all_different =
false;
42 if (is_all_different) {
43 std::vector<AffineExpression> starts;
44 starts.reserve(vars.size());
45 for (
const IntervalVariable
interval : vars) {
54 if (vars.size() > 2 && sat_parameters.use_combined_no_overlap()) {
62 model->TakeOwnership(helper);
67 std::vector<AffineExpression> demands(vars.size(), one);
70 timetable->RegisterWith(watcher);
71 model->TakeOwnership(timetable);
75 if (vars.size() == 2) {
78 model->TakeOwnership(propagator);
87 watcher->SetPropagatorPriority(
id, 1);
88 model->TakeOwnership(overload_checker);
90 for (
const bool time_direction : {
true,
false}) {
93 const int id = detectable_precedences->
RegisterWith(watcher);
94 watcher->SetPropagatorPriority(
id, 2);
95 model->TakeOwnership(detectable_precedences);
97 for (
const bool time_direction : {
true,
false}) {
101 watcher->SetPropagatorPriority(
id, 3);
102 model->TakeOwnership(not_last);
104 for (
const bool time_direction : {
true,
false}) {
108 watcher->SetPropagatorPriority(
id, 4);
109 model->TakeOwnership(edge_finding);
116 if (sat_parameters.use_precedences_in_disjunctive_constraint() &&
117 !sat_parameters.use_combined_no_overlap()) {
118 for (
const bool time_direction : {
true,
false}) {
123 watcher->SetPropagatorPriority(
id, 5);
124 model->TakeOwnership(precedences);
131 const std::vector<IntervalVariable>& vars) {
137 for (
int i = 0; i < vars.size(); ++i) {
138 for (
int j = 0; j < i; ++j) {
142 precedences->AddConditionalPrecedence(repository->EndVar(vars[i]),
143 repository->StartVar(vars[j]),
145 precedences->AddConditionalPrecedence(repository->EndVar(vars[j]),
146 repository->StartVar(vars[i]),
154 const std::vector<IntervalVariable>& vars) {
162 int j = sorted_tasks_.size();
163 sorted_tasks_.push_back(e);
165 sorted_tasks_[j] = sorted_tasks_[j - 1];
168 sorted_tasks_[j] = e;
169 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
173 if (j <= optimized_restart_) optimized_restart_ = 0;
178 const IntegerValue dmin = helper.
SizeMin(t);
183 const int size = sorted_tasks_.size();
184 for (
int i = 0;; ++i) {
185 if (i == size)
return;
186 if (sorted_tasks_[i].task == e.
task) {
187 sorted_tasks_.erase(sorted_tasks_.begin() + i);
192 optimized_restart_ = sorted_tasks_.size();
193 sorted_tasks_.push_back(e);
194 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
198 sorted_tasks_.erase(sorted_tasks_.begin() +
index);
199 optimized_restart_ = 0;
203 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
204 const int size = sorted_tasks_.size();
206 for (
int i = optimized_restart_; i < size; ++i) {
207 const Entry& e = sorted_tasks_[i];
209 optimized_restart_ = i;
219 int* critical_index)
const {
221 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
222 bool ignored =
false;
223 const int size = sorted_tasks_.size();
228 if (optimized_restart_ + 1 == size &&
229 sorted_tasks_[optimized_restart_].task == task_to_ignore) {
230 optimized_restart_ = 0;
233 for (
int i = optimized_restart_; i < size; ++i) {
234 const Entry& e = sorted_tasks_[i];
235 if (e.
task == task_to_ignore) {
241 if (!ignored) optimized_restart_ = i;
277 const IntegerValue end_min_before = helper_->
EndMin(task_before);
278 if (helper_->
StartMin(task_after) < end_min_before) {
293 const IntegerValue start_max_after = helper_->
StartMax(task_after);
294 if (helper_->
EndMax(task_before) > start_max_after) {
312 const int id = watcher->
Register(
this);
318 template <
bool time_direction>
321 task_to_disjunctives_.resize(helper_->
NumTasks());
324 const int id = watcher->
Register(
this);
327 watcher->NotifyThatPropagatorMayNotReachFixedPointInOnePass(
id);
330 template <
bool time_direction>
332 const std::vector<IntervalVariable>& vars) {
333 const int index = task_sets_.size();
334 task_sets_.emplace_back(vars.size());
336 for (
const IntervalVariable
var : vars) {
337 task_to_disjunctives_[
var.value()].push_back(
index);
341 template <
bool time_direction>
343 if (!helper_->SynchronizeAndSetTimeDirection(time_direction))
return false;
344 const auto& task_by_increasing_end_min = helper_->TaskByIncreasingEndMin();
345 const auto& task_by_decreasing_start_max =
346 helper_->TaskByDecreasingStartMax();
348 for (
auto& task_set : task_sets_) task_set.Clear();
352 const int num_tasks = helper_->NumTasks();
353 task_is_added_.assign(num_tasks,
false);
354 int queue_index = num_tasks - 1;
355 for (
const auto task_time : task_by_increasing_end_min) {
356 const int t = task_time.task_index;
357 const IntegerValue
end_min = task_time.time;
358 if (helper_->IsAbsent(t))
continue;
361 while (queue_index >= 0) {
362 const auto to_insert = task_by_decreasing_start_max[queue_index];
363 const int task_index = to_insert.task_index;
364 const IntegerValue
start_max = to_insert.time;
366 if (helper_->IsPresent(task_index)) {
367 task_is_added_[task_index] =
true;
368 const IntegerValue shifted_smin = helper_->ShiftedStartMin(task_index);
369 const IntegerValue size_min = helper_->SizeMin(task_index);
370 for (
const int d_index : task_to_disjunctives_[task_index]) {
372 task_sets_[d_index].AddEntry({task_index, shifted_smin, size_min});
373 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
374 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
382 IntegerValue new_start_min = helper_->StartMin(t);
383 if (new_start_min >= max_of_end_min)
continue;
384 int best_critical_index = 0;
385 int best_d_index = -1;
386 if (task_is_added_[t]) {
387 for (
const int d_index : task_to_disjunctives_[t]) {
388 if (new_start_min >= end_mins_[d_index])
continue;
389 int critical_index = 0;
390 const IntegerValue end_min_of_critical_tasks =
391 task_sets_[d_index].ComputeEndMin(t,
393 DCHECK_LE(end_min_of_critical_tasks, max_of_end_min);
394 if (end_min_of_critical_tasks > new_start_min) {
395 new_start_min = end_min_of_critical_tasks;
396 best_d_index = d_index;
397 best_critical_index = critical_index;
403 for (
const int d_index : task_to_disjunctives_[t]) {
404 if (end_mins_[d_index] > new_start_min) {
405 new_start_min = end_mins_[d_index];
406 best_d_index = d_index;
409 if (best_d_index != -1) {
410 const IntegerValue end_min_of_critical_tasks =
411 task_sets_[best_d_index].ComputeEndMin(t,
412 &best_critical_index);
413 CHECK_EQ(end_min_of_critical_tasks, new_start_min);
418 if (best_d_index == -1)
continue;
423 helper_->ClearReason();
424 const std::vector<TaskSet::Entry>& sorted_tasks =
425 task_sets_[best_d_index].SortedTasks();
426 const IntegerValue window_start =
427 sorted_tasks[best_critical_index].start_min;
428 for (
int i = best_critical_index; i < sorted_tasks.size(); ++i) {
429 const int ct = sorted_tasks[i].task;
430 if (
ct == t)
continue;
431 helper_->AddPresenceReason(
ct);
432 helper_->AddEnergyAfterReason(
ct, sorted_tasks[i].size_min, window_start);
433 helper_->AddStartMaxReason(
ct,
end_min - 1);
435 helper_->AddEndMinReason(t,
end_min);
436 if (!helper_->IncreaseStartMin(t, new_start_min)) {
444 if (task_is_added_[t]) {
445 const IntegerValue shifted_smin = helper_->ShiftedStartMin(t);
446 const IntegerValue size_min = helper_->SizeMin(t);
447 for (
const int d_index : task_to_disjunctives_[t]) {
448 task_sets_[d_index].NotifyEntryIsNowLastIfPresent(
449 {t, shifted_smin, size_min});
450 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
451 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
475 IntegerValue relevant_end;
476 int relevant_size = 0;
478 const int task = task_time.task_index;
479 if (helper_->
IsAbsent(task))
continue;
481 const IntegerValue
start_min = task_time.time;
483 window_.push_back(task_time);
484 window_end += helper_->
SizeMin(task);
485 if (window_end > helper_->
EndMax(task)) {
486 relevant_size = window_.size();
487 relevant_end = window_end;
495 window_.resize(relevant_size);
496 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
502 window_.push_back(task_time);
508 window_.resize(relevant_size);
509 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
523 bool DisjunctiveOverloadChecker::PropagateSubwindow(
524 IntegerValue global_window_end) {
526 const int window_size = window_.size();
527 theta_tree_.
Reset(window_size);
528 task_by_increasing_end_max_.clear();
529 for (
int i = 0; i < window_size; ++i) {
531 const int task = window_[i].task_index;
533 if (
end_max < global_window_end) {
534 task_to_event_[task] = i;
535 task_by_increasing_end_max_.push_back({task,
end_max});
540 std::sort(task_by_increasing_end_max_.begin(),
541 task_by_increasing_end_max_.end());
542 for (
const auto task_time : task_by_increasing_end_max_) {
543 const int current_task = task_time.task_index;
548 if (helper_->
IsAbsent(current_task))
continue;
550 DCHECK_NE(task_to_event_[current_task], -1);
552 const int current_event = task_to_event_[current_task];
553 const IntegerValue energy_min = helper_->
SizeMin(current_task);
559 energy_min, energy_min);
562 current_event, window_[current_event].
time, energy_min);
566 const IntegerValue current_end = task_time.time;
570 const int critical_event =
572 const IntegerValue window_start = window_[critical_event].time;
573 const IntegerValue window_end =
575 for (
int event = critical_event;
event < window_size;
event++) {
576 const IntegerValue energy_min = theta_tree_.
EnergyMin(event);
577 if (energy_min > 0) {
578 const int task = window_[event].task_index;
595 IntegerValue available_energy;
597 current_end, &critical_event, &optional_event, &available_energy);
599 const int optional_task = window_[optional_event].task_index;
603 if (!helper_->
IsAbsent(optional_task)) {
604 const IntegerValue optional_size_min = helper_->
SizeMin(optional_task);
605 const IntegerValue window_start = window_[critical_event].time;
606 const IntegerValue window_end =
607 current_end + optional_size_min - available_energy - 1;
608 for (
int event = critical_event;
event < window_size;
event++) {
609 const IntegerValue energy_min = theta_tree_.
EnergyMin(event);
610 if (energy_min > 0) {
611 const int task = window_[event].task_index;
634 const int id = watcher->
Register(
this);
644 to_propagate_.clear();
645 processed_.assign(helper_->
NumTasks(),
false);
654 task_by_increasing_end_min_.clear();
657 const int task = task_time.task_index;
658 if (helper_->
IsAbsent(task))
continue;
662 const IntegerValue size_min = helper_->
SizeMin(task);
667 task_by_increasing_end_min_.push_back({task,
end_min});
673 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
678 task_by_increasing_end_min_.clear();
679 task_by_increasing_end_min_.push_back({task,
end_min});
683 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
690 bool DisjunctiveDetectablePrecedences::PropagateSubwindow() {
691 DCHECK(!task_by_increasing_end_min_.empty());
696 task_by_increasing_end_min_.end());
697 const IntegerValue max_end_min = task_by_increasing_end_min_.back().time;
703 task_by_increasing_start_max_.clear();
704 for (
const TaskTime entry : task_by_increasing_end_min_) {
705 const int task = entry.task_index;
707 if (start_max < max_end_min && helper_->IsPresent(task)) {
708 task_by_increasing_start_max_.push_back({task,
start_max});
711 if (task_by_increasing_start_max_.empty())
return true;
712 std::sort(task_by_increasing_start_max_.begin(),
713 task_by_increasing_start_max_.end());
721 to_propagate_.clear();
722 bool need_update =
false;
726 int blocking_task = -1;
727 const int queue_size = task_by_increasing_start_max_.size();
728 for (
const auto task_time : task_by_increasing_end_min_) {
732 const int current_task = task_time.task_index;
733 const IntegerValue current_end_min = task_time.time;
734 if (helper_->
IsAbsent(current_task))
continue;
736 for (; queue_index < queue_size; ++queue_index) {
737 const auto to_insert = task_by_increasing_start_max_[queue_index];
738 const IntegerValue
start_max = to_insert.time;
741 const int t = to_insert.task_index;
755 if (!processed_[t]) {
756 if (blocking_task != -1) {
766 <<
" task should have mandatory part: " 768 DCHECK(to_propagate_.empty());
770 to_propagate_.push_back(t);
779 if (blocking_task != current_task) {
780 to_propagate_.push_back(current_task);
781 if (blocking_task != -1)
continue;
783 for (
const int t : to_propagate_) {
785 processed_[t] =
true;
804 if (task_set_end_min > helper_->
StartMin(t)) {
806 const std::vector<TaskSet::Entry>& sorted_tasks =
813 const IntegerValue end_min_if_present =
815 const IntegerValue window_start =
816 sorted_tasks[critical_index].start_min;
817 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
818 const int ct = sorted_tasks[i].task;
840 if (t == blocking_task) {
851 to_propagate_.clear();
858 const int id = watcher->
Register(
this);
871 const int task = task_time.task_index;
874 const IntegerValue
start_min = task_time.time;
876 window_.push_back(task_time);
877 window_end += helper_->
SizeMin(task);
881 if (window_.size() > 1 && !PropagateSubwindow()) {
887 window_.push_back(task_time);
890 if (window_.size() > 1 && !PropagateSubwindow()) {
896 bool DisjunctivePrecedences::PropagateSubwindow() {
902 index_to_end_vars_.clear();
904 for (
const auto task_time : window_) {
905 const int task = task_time.task_index;
911 window_[new_size++] = task_time;
912 index_to_end_vars_.push_back(end_exp.
var);
914 window_.resize(new_size);
917 const int size = before_.size();
918 for (
int i = 0; i < size;) {
919 const IntegerVariable
var = before_[i].var;
923 const int initial_i = i;
925 for (; i < size && before_[i].var ==
var; ++i) {
927 const TaskTime task_time = window_[before_[i].index];
932 const AffineExpression& end_exp = helper_->
Ends()[task_time.task_index];
933 min_offset =
std::min(min_offset, before_[i].offset - end_exp.constant);
938 helper_->
SizeMin(task_time.task_index)});
945 const IntegerValue new_lb = task_set_.
ComputeEndMin() + min_offset;
947 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
952 for (
int j = initial_i; j < i; ++j) {
953 const int task = window_[before_[j].index].task_index;
954 task_to_arc_index_[task] = before_[j].arc_index;
958 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
959 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
960 const int ct = sorted_tasks[i].task;
965 const AffineExpression& end_exp = helper_->
Ends()[
ct];
967 task_to_arc_index_[
ct], min_offset + end_exp.constant,
984 const int id = watcher->
Register(
this);
994 const auto& task_by_decreasing_start_max =
996 const auto& task_by_increasing_shifted_start_min =
1010 int queue_index = task_by_decreasing_start_max.size() - 1;
1011 const int num_tasks = task_by_increasing_shifted_start_min.size();
1012 for (
int i = 0; i < num_tasks;) {
1013 start_min_window_.clear();
1015 for (; i < num_tasks; ++i) {
1016 const TaskTime task_time = task_by_increasing_shifted_start_min[i];
1018 if (!helper_->
IsPresent(task))
continue;
1021 if (start_min_window_.empty()) {
1022 start_min_window_.push_back(task_time);
1025 start_min_window_.push_back(task_time);
1026 window_end += helper_->
SizeMin(task);
1034 start_max_window_.clear();
1035 for (; queue_index >= 0; queue_index--) {
1036 const auto task_time = task_by_decreasing_start_max[queue_index];
1039 if (task_time.time >= window_end)
break;
1040 if (helper_->
IsAbsent(task_time.task_index))
continue;
1041 start_max_window_.push_back(task_time);
1047 if (start_min_window_.size() <= 1)
continue;
1050 if (!start_max_window_.empty() && !PropagateSubwindow()) {
1057 bool DisjunctiveNotLast::PropagateSubwindow() {
1058 auto& task_by_increasing_end_max = start_max_window_;
1059 for (
TaskTime& entry : task_by_increasing_end_max) {
1060 entry.time = helper_->
EndMax(entry.task_index);
1063 task_by_increasing_end_max.end());
1065 const IntegerValue threshold = task_by_increasing_end_max.back().time;
1066 auto& task_by_increasing_start_max = start_min_window_;
1068 for (
const TaskTime entry : task_by_increasing_start_max) {
1069 const int task = entry.task_index;
1073 task_by_increasing_start_max[queue_size++] = {task,
start_max};
1079 if (queue_size <= 1)
return true;
1081 task_by_increasing_start_max.resize(queue_size);
1082 std::sort(task_by_increasing_start_max.begin(),
1083 task_by_increasing_start_max.end());
1086 int queue_index = 0;
1087 for (
const auto task_time : task_by_increasing_end_max) {
1088 const int t = task_time.task_index;
1089 const IntegerValue
end_max = task_time.time;
1093 if (helper_->
IsAbsent(t))
continue;
1098 while (queue_index < queue_size) {
1099 const auto to_insert = task_by_increasing_start_max[queue_index];
1100 const IntegerValue
start_max = to_insert.time;
1103 const int task_index = to_insert.task_index;
1106 helper_->
SizeMin(task_index)});
1120 int critical_index = 0;
1121 const IntegerValue end_min_of_critical_tasks =
1123 if (end_min_of_critical_tasks <= helper_->StartMax(t))
continue;
1128 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
1129 const int sorted_tasks_size = sorted_tasks.size();
1130 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1131 const int ct = sorted_tasks[i].task;
1132 if (t ==
ct)
continue;
1142 end_max > largest_ct_start_max);
1143 if (
end_max > largest_ct_start_max) {
1146 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
1147 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1148 const int ct = sorted_tasks[i].task;
1149 if (
ct == t)
continue;
1161 if (!helper_->
DecreaseEndMax(t, largest_ct_start_max))
return false;
1168 const int id = watcher->
Register(
this);
1175 const int num_tasks = helper_->
NumTasks();
1177 is_gray_.resize(num_tasks,
false);
1178 non_gray_task_to_event_.resize(num_tasks);
1183 const int task = task_time.task_index;
1184 if (helper_->
IsAbsent(task))
continue;
1188 if (helper_->
StartMin(task) < window_end) {
1189 window_.push_back(task_time);
1190 window_end += helper_->
SizeMin(task);
1196 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1202 window_.push_back(task_time);
1203 window_end = task_time.time + helper_->
SizeMin(task);
1205 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1211 bool DisjunctiveEdgeFinding::PropagateSubwindow(IntegerValue window_end_min) {
1213 task_by_increasing_end_max_.clear();
1214 for (
const auto task_time : window_) {
1215 const int task = task_time.task_index;
1228 is_gray_[task] =
false;
1229 task_by_increasing_end_max_.push_back({task,
end_max});
1231 is_gray_[task] =
true;
1237 if (task_by_increasing_end_max_.size() < 2)
return true;
1238 std::sort(task_by_increasing_end_max_.begin(),
1239 task_by_increasing_end_max_.end());
1250 const int window_size = window_.size();
1251 event_size_.clear();
1252 theta_tree_.
Reset(window_size);
1253 for (
int event = 0;
event < window_size; ++event) {
1254 const TaskTime task_time = window_[event];
1255 const int task = task_time.task_index;
1256 const IntegerValue energy_min = helper_->
SizeMin(task);
1257 event_size_.push_back(energy_min);
1258 if (is_gray_[task]) {
1261 non_gray_task_to_event_[task] = event;
1270 DCHECK(!is_gray_[task_by_increasing_end_max_.back().task_index]);
1271 const IntegerValue non_gray_end_max =
1272 task_by_increasing_end_max_.back().time;
1275 const IntegerValue non_gray_end_min = theta_tree_.
GetEnvelope();
1276 if (non_gray_end_min > non_gray_end_max) {
1280 const int critical_event =
1282 const IntegerValue window_start = window_[critical_event].time;
1283 const IntegerValue window_end =
1285 for (
int event = critical_event;
event < window_size;
event++) {
1286 const int task = window_[event].task_index;
1287 if (is_gray_[task])
continue;
1305 int critical_event_with_gray;
1307 IntegerValue available_energy;
1309 non_gray_end_max, &critical_event_with_gray, &gray_event,
1311 const int gray_task = window_[gray_event].task_index;
1312 DCHECK(is_gray_[gray_task]);
1316 if (helper_->
IsAbsent(gray_task)) {
1322 if (helper_->
StartMin(gray_task) < non_gray_end_min) {
1325 const int critical_event =
1328 const int first_event =
1329 std::min(critical_event, critical_event_with_gray);
1330 const int second_event =
1331 std::max(critical_event, critical_event_with_gray);
1332 const IntegerValue first_start = window_[first_event].time;
1333 const IntegerValue second_start = window_[second_event].time;
1337 const IntegerValue window_end =
1338 non_gray_end_max + event_size_[gray_event] - available_energy - 1;
1339 CHECK_GE(window_end, non_gray_end_max);
1343 for (
int event = first_event;
event < window_size;
event++) {
1344 const int task = window_[event].task_index;
1345 if (is_gray_[task])
continue;
1348 task, event_size_[event],
1349 event >= second_event ? second_start : first_start);
1356 window_[critical_event_with_gray].
time);
1373 if (task_by_increasing_end_max_.size() <= 2)
break;
1376 if (task_by_increasing_end_max_[0].
time >=
1382 const int new_gray_task = task_by_increasing_end_max_.back().task_index;
1383 task_by_increasing_end_max_.pop_back();
1384 const int new_gray_event = non_gray_task_to_event_[new_gray_task];
1385 DCHECK(!is_gray_[new_gray_task]);
1386 is_gray_[new_gray_task] =
true;
1388 window_[new_gray_event].
time,
1389 event_size_[new_gray_event]);
1396 const int id = watcher->
Register(
this);
void RemoveEntryWithIndex(int index)
IntegerValue SizeMin(int t) const
int RegisterWith(GenericLiteralWatcher *watcher)
void AddEndMaxReason(int t, IntegerValue upper_bound)
void IncrementalSort(int max_comparisons, Iterator begin, Iterator end, Compare comp=Compare{}, bool is_stable=false)
IntegerValue StartMax(int t) const
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
#define CHECK_GE(val1, val2)
bool IsAbsent(int t) const
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
Class that owns everything related to a particular optimization model.
void AddEntry(const Entry &e)
CombinedDisjunctive(Model *model)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
std::function< void(Model *)> DisjunctiveWithBooleanPrecedencesOnly(const std::vector< IntervalVariable > &vars)
int RegisterWith(GenericLiteralWatcher *watcher)
std::string TaskDebugString(int t) const
void AddShiftedStartMinEntry(const SchedulingConstraintHelper &helper, int t)
IntegerType EnergyMin(int event) const
void AddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
IntegerValue LowerBound(IntegerVariable i) const
int RegisterWith(GenericLiteralWatcher *watcher)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
void ComputePrecedences(const std::vector< IntegerVariable > &vars, std::vector< IntegerPrecedences > *output)
int GetCriticalIndex() const
void AddReasonForBeingBefore(int before, int after)
void AddUnsortedEntry(const Entry &e)
bool IsPresent(int t) const
void AddNoOverlap(const std::vector< IntervalVariable > &var)
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
void AddStartMaxReason(int t, IntegerValue upper_bound)
std::function< void(Model *)> DisjunctiveWithBooleanPrecedences(const std::vector< IntervalVariable > &vars)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
void AddEndMinReason(int t, IntegerValue lower_bound)
const std::vector< Entry > & SortedTasks() const
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_end_max)
#define DCHECK_NE(val1, val2)
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
void RemoveEvent(int event)
std::function< void(Model *)> Disjunctive(const std::vector< IntervalVariable > &vars)
void NotifyEntryIsNowLastIfPresent(const Entry &e)
IntegerValue StartMin(int t) const
#define DCHECK_GE(val1, val2)
#define CHECK_EQ(val1, val2)
void AddPrecedenceReason(int arc_index, IntegerValue min_offset, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason) const
BooleanVariable NewBooleanVariable()
IntegerValue EndMin(int t) const
std::function< void(Model *)> AllDifferentOnBounds(const std::vector< IntegerVariable > &vars)
ABSL_MUST_USE_RESULT bool ReportConflict()
IntegerValue EndMax(int t) const
IntegerType GetOptionalEnvelope() const
#define DCHECK(condition)
const std::vector< AffineExpression > & Ends() const
IntegerValue ComputeEndMin() const
IntegerType GetEnvelopeOf(int event) const
std::vector< Literal > * MutableLiteralReason()
#define DCHECK_EQ(val1, val2)
bool IsCurrentlyIgnored(IntegerVariable i) const
int GetMaxEventWithEnvelopeGreaterThan(IntegerType target_envelope) const
void AddPresenceReason(int t)
const std::vector< TaskTime > & TaskByIncreasingStartMin()
void Reset(int num_events)
#define DCHECK_LE(val1, val2)
int Register(PropagatorInterface *propagator)
std::vector< IntegerLiteral > * MutableIntegerReason()
Collection of objects used to extend the Constraint Solver library.
int RegisterWith(GenericLiteralWatcher *watcher)
const IntegerVariable kNoIntegerVariable(-1)
IntegerValue MaxSize(IntervalVariable i) const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
IntegerValue ShiftedStartMin(int t) const
IntegerValue MinSize(IntervalVariable i) const
void SetTimeDirection(bool is_forward)
AffineExpression Start(IntervalVariable i) const
int RegisterWith(GenericLiteralWatcher *watcher)
int RegisterWith(GenericLiteralWatcher *watcher)
bool IsOptional(IntervalVariable i) const
IntegerType GetEnvelope() const
const std::vector< TaskTime > & TaskByDecreasingStartMax()
bool InPropagationLoop() const
void GetEventsWithOptionalEnvelopeGreaterThan(IntegerType target_envelope, int *critical_event, int *optional_event, IntegerType *available_energy) const
void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time)
#define DCHECK_LT(val1, val2)
IntegerValue ComputeEndMin(int task_to_ignore, int *critical_index) const
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
void AddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)