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);
72 timetable->RegisterWith(watcher);
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);
320 template <
bool time_direction>
323 task_to_disjunctives_.resize(helper_->
NumTasks());
326 const int id = watcher->
Register(
this);
329 watcher->NotifyThatPropagatorMayNotReachFixedPointInOnePass(
id);
332 template <
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);
343 template <
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)) {
525 bool 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);
561 energy_min, energy_min);
564 current_event, window_[current_event].
time, energy_min);
568 const IntegerValue current_end = task_time.time;
572 const int critical_event =
574 const IntegerValue window_start = window_[critical_event].time;
575 const IntegerValue window_end =
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;
597 IntegerValue available_energy;
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;
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()) {
692 bool 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()) {
898 bool 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()) {
1059 bool 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)) {
1213 bool 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]) {
1263 non_gray_task_to_event_[task] = event;
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 =
1284 const IntegerValue window_start = window_[critical_event].time;
1285 const IntegerValue window_end =
1287 for (
int event = critical_event;
event < window_size;
event++) {
1288 const int task = window_[event].task_index;
1289 if (is_gray_[task])
continue;
1307 int critical_event_with_gray;
1309 IntegerValue available_energy;
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)) {
1324 if (helper_->
StartMin(gray_task) < non_gray_end_min) {
1327 const int critical_event =
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);
1375 if (task_by_increasing_end_max_.size() <= 2)
break;
1378 if (task_by_increasing_end_max_[0].
time >=
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;
1390 window_[new_gray_event].
time,
1391 event_size_[new_gray_event]);
1398 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
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
std::function< void(Model *)> AllDifferentOnBounds(const std::vector< IntegerVariable > &vars)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
std::function< IntegerVariable(const Model &)> StartVar(IntervalVariable v)
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)