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);
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);
318template <
bool time_direction>
321 task_to_disjunctives_.resize(helper_->
NumTasks());
324 const int id = watcher->
Register(
this);
327 watcher->NotifyThatPropagatorMayNotReachFixedPointInOnePass(
id);
330template <
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);
341template <
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)) {
523bool 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()) {
690bool 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()) {
896bool 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()) {
1057bool 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)) {
1211bool 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);
#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
IntegerType GetEnvelopeOf(int event) const
void GetEventsWithOptionalEnvelopeGreaterThan(IntegerType target_envelope, int *critical_event, int *optional_event, IntegerType *available_energy) const
IntegerType GetOptionalEnvelope() const
void RemoveEvent(int event)
int GetMaxEventWithEnvelopeGreaterThan(IntegerType target_envelope) const
void Reset(int num_events)
void AddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)
IntegerType EnergyMin(int event) const
void AddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
IntegerType GetEnvelope() 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)
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< void(Model *)> AllDifferentOnBounds(const std::vector< AffineExpression > &expressions)
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)