29 #include "ortools/sat/sat_parameters.pb.h"
40 const std::vector<IntervalVariable>& intervals) {
42 bool is_all_different =
true;
44 for (
const IntervalVariable
var : intervals) {
47 is_all_different =
false;
51 if (is_all_different) {
52 std::vector<AffineExpression> starts;
53 starts.reserve(intervals.size());
54 for (
const IntervalVariable
interval : intervals) {
62 const auto& sat_parameters = *
model->GetOrCreate<SatParameters>();
63 if (intervals.size() > 2 && sat_parameters.use_combined_no_overlap()) {
71 model->TakeOwnership(helper);
76 std::vector<AffineExpression> demands(intervals.size(), one);
83 model->TakeOwnership(timetable);
87 if (intervals.size() == 2) {
90 model->TakeOwnership(propagator);
99 watcher->SetPropagatorPriority(
id, 1);
100 model->TakeOwnership(overload_checker);
102 for (
const bool time_direction : {
true,
false}) {
105 const int id = detectable_precedences->
RegisterWith(watcher);
106 watcher->SetPropagatorPriority(
id, 2);
107 model->TakeOwnership(detectable_precedences);
109 for (
const bool time_direction : {
true,
false}) {
113 watcher->SetPropagatorPriority(
id, 3);
114 model->TakeOwnership(not_last);
116 for (
const bool time_direction : {
true,
false}) {
120 watcher->SetPropagatorPriority(
id, 4);
121 model->TakeOwnership(edge_finding);
128 if (sat_parameters.use_precedences_in_disjunctive_constraint() &&
129 !sat_parameters.use_combined_no_overlap()) {
130 for (
const bool time_direction : {
true,
false}) {
135 watcher->SetPropagatorPriority(
id, 5);
136 model->TakeOwnership(precedences);
143 const std::vector<IntervalVariable>& intervals,
Model*
model) {
147 std::vector<Literal> enforcement_literals;
148 for (
int i = 1; i < intervals.size(); ++i) {
149 enforcement_literals.clear();
152 if (repository->IsOptional(intervals[i])) {
153 enforcement_literals.push_back(repository->PresenceLiteral(intervals[i]));
155 const int enforcement_literals_size = enforcement_literals.size();
157 for (
int j = 0; j < i; ++j) {
158 enforcement_literals.resize(enforcement_literals_size);
161 if (repository->IsOptional(intervals[j])) {
162 enforcement_literals.push_back(
163 repository->PresenceLiteral(intervals[j]));
166 DCHECK_LE(enforcement_literals.size(), 2);
168 if (integer_trail->UpperBound(start_i) <
169 integer_trail->LowerBound(end_j)) {
173 }
else if (integer_trail->UpperBound(start_j) <
174 integer_trail->LowerBound(end_i)) {
182 enforcement_literals.push_back(i_before_j);
185 DCHECK_LE(enforcement_literals.size(), 3);
186 enforcement_literals.pop_back();
187 enforcement_literals.push_back(i_before_j.
Negated());
190 DCHECK_LE(enforcement_literals.size(), 3);
191 enforcement_literals.pop_back();
196 if (repository->IsOptional(intervals[i])) {
198 repository->PresenceLiteral(intervals[i]).Negated(), i_before_j));
200 if (repository->IsOptional(intervals[j])) {
202 repository->PresenceLiteral(intervals[j]).Negated(), i_before_j));
210 const std::vector<IntervalVariable>& intervals,
Model*
model) {
216 int j = sorted_tasks_.size();
217 sorted_tasks_.push_back(e);
219 sorted_tasks_[j] = sorted_tasks_[j - 1];
222 sorted_tasks_[j] = e;
223 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
227 if (j <= optimized_restart_) optimized_restart_ = 0;
232 const IntegerValue dmin = helper.
SizeMin(t);
237 const int size = sorted_tasks_.size();
238 for (
int i = 0;; ++i) {
239 if (i == size)
return;
240 if (sorted_tasks_[i].task == e.
task) {
241 sorted_tasks_.erase(sorted_tasks_.begin() + i);
246 optimized_restart_ = sorted_tasks_.size();
247 sorted_tasks_.push_back(e);
248 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
252 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
253 const int size = sorted_tasks_.size();
255 for (
int i = optimized_restart_; i < size; ++i) {
256 const Entry& e = sorted_tasks_[i];
258 optimized_restart_ = i;
268 int* critical_index)
const {
270 DCHECK(std::is_sorted(sorted_tasks_.begin(), sorted_tasks_.end()));
271 bool ignored =
false;
272 const int size = sorted_tasks_.size();
277 if (optimized_restart_ + 1 == size &&
278 sorted_tasks_[optimized_restart_].task == task_to_ignore) {
279 optimized_restart_ = 0;
282 for (
int i = optimized_restart_; i < size; ++i) {
283 const Entry& e = sorted_tasks_[i];
284 if (e.
task == task_to_ignore) {
290 if (!ignored) optimized_restart_ = i;
326 const IntegerValue end_min_before = helper_->
EndMin(task_before);
327 if (helper_->
StartMin(task_after) < end_min_before) {
342 const IntegerValue start_max_after = helper_->
StartMax(task_after);
343 if (helper_->
EndMax(task_before) > start_max_after) {
361 const int id = watcher->
Register(
this);
367 template <
bool time_direction>
370 task_to_disjunctives_.resize(helper_->
NumTasks());
373 const int id = watcher->
Register(
this);
376 watcher->NotifyThatPropagatorMayNotReachFixedPointInOnePass(
id);
379 template <
bool time_direction>
381 const std::vector<IntervalVariable>& vars) {
382 const int index = task_sets_.size();
383 task_sets_.emplace_back(vars.size());
385 for (
const IntervalVariable
var : vars) {
386 task_to_disjunctives_[
var.value()].push_back(
index);
390 template <
bool time_direction>
392 if (!helper_->SynchronizeAndSetTimeDirection(time_direction))
return false;
393 const auto& task_by_increasing_end_min = helper_->TaskByIncreasingEndMin();
394 const auto& task_by_decreasing_start_max =
395 helper_->TaskByDecreasingStartMax();
397 for (
auto& task_set : task_sets_) task_set.Clear();
401 const int num_tasks = helper_->NumTasks();
402 task_is_added_.assign(num_tasks,
false);
403 int queue_index = num_tasks - 1;
404 for (
const auto task_time : task_by_increasing_end_min) {
405 const int t = task_time.task_index;
406 const IntegerValue
end_min = task_time.time;
407 if (helper_->IsAbsent(t))
continue;
410 while (queue_index >= 0) {
411 const auto to_insert = task_by_decreasing_start_max[queue_index];
412 const int task_index = to_insert.task_index;
413 const IntegerValue
start_max = to_insert.time;
415 if (helper_->IsPresent(task_index)) {
416 task_is_added_[task_index] =
true;
417 const IntegerValue shifted_smin = helper_->ShiftedStartMin(task_index);
418 const IntegerValue size_min = helper_->SizeMin(task_index);
419 for (
const int d_index : task_to_disjunctives_[task_index]) {
421 task_sets_[d_index].AddEntry({task_index, shifted_smin, size_min});
422 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
423 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
431 IntegerValue new_start_min = helper_->StartMin(t);
432 if (new_start_min >= max_of_end_min)
continue;
433 int best_critical_index = 0;
434 int best_d_index = -1;
435 if (task_is_added_[t]) {
436 for (
const int d_index : task_to_disjunctives_[t]) {
437 if (new_start_min >= end_mins_[d_index])
continue;
438 int critical_index = 0;
439 const IntegerValue end_min_of_critical_tasks =
440 task_sets_[d_index].ComputeEndMin(t,
442 DCHECK_LE(end_min_of_critical_tasks, max_of_end_min);
443 if (end_min_of_critical_tasks > new_start_min) {
444 new_start_min = end_min_of_critical_tasks;
445 best_d_index = d_index;
446 best_critical_index = critical_index;
452 for (
const int d_index : task_to_disjunctives_[t]) {
453 if (end_mins_[d_index] > new_start_min) {
454 new_start_min = end_mins_[d_index];
455 best_d_index = d_index;
458 if (best_d_index != -1) {
459 const IntegerValue end_min_of_critical_tasks =
460 task_sets_[best_d_index].ComputeEndMin(t,
461 &best_critical_index);
462 CHECK_EQ(end_min_of_critical_tasks, new_start_min);
467 if (best_d_index == -1)
continue;
472 helper_->ClearReason();
473 const std::vector<TaskSet::Entry>& sorted_tasks =
474 task_sets_[best_d_index].SortedTasks();
475 const IntegerValue window_start =
476 sorted_tasks[best_critical_index].start_min;
477 for (
int i = best_critical_index; i < sorted_tasks.size(); ++i) {
478 const int ct = sorted_tasks[i].task;
479 if (
ct == t)
continue;
480 helper_->AddPresenceReason(
ct);
481 helper_->AddEnergyAfterReason(
ct, sorted_tasks[i].size_min, window_start);
482 helper_->AddStartMaxReason(
ct,
end_min - 1);
484 helper_->AddEndMinReason(t,
end_min);
485 if (!helper_->IncreaseStartMin(t, new_start_min)) {
493 if (task_is_added_[t]) {
494 const IntegerValue shifted_smin = helper_->ShiftedStartMin(t);
495 const IntegerValue size_min = helper_->SizeMin(t);
496 for (
const int d_index : task_to_disjunctives_[t]) {
500 task_sets_[d_index].NotifyEntryIsNowLastIfPresent(
501 {t, shifted_smin, size_min});
502 end_mins_[d_index] = task_sets_[d_index].ComputeEndMin();
503 max_of_end_min =
std::max(max_of_end_min, end_mins_[d_index]);
527 IntegerValue relevant_end;
528 int relevant_size = 0;
530 const int task = task_time.task_index;
531 if (helper_->
IsAbsent(task))
continue;
533 const IntegerValue
start_min = task_time.time;
535 window_.push_back(task_time);
536 window_end += helper_->
SizeMin(task);
537 if (window_end > helper_->
EndMax(task)) {
538 relevant_size = window_.size();
539 relevant_end = window_end;
547 window_.resize(relevant_size);
548 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
554 window_.push_back(task_time);
560 window_.resize(relevant_size);
561 if (relevant_size > 0 && !PropagateSubwindow(relevant_end)) {
575 bool DisjunctiveOverloadChecker::PropagateSubwindow(
576 IntegerValue global_window_end) {
578 const int window_size = window_.size();
579 theta_tree_.
Reset(window_size);
580 task_by_increasing_end_max_.clear();
581 for (
int i = 0; i < window_size; ++i) {
583 const int task = window_[i].task_index;
585 if (
end_max < global_window_end) {
586 task_to_event_[task] = i;
587 task_by_increasing_end_max_.push_back({task,
end_max});
592 std::sort(task_by_increasing_end_max_.begin(),
593 task_by_increasing_end_max_.end());
594 for (
const auto task_time : task_by_increasing_end_max_) {
595 const int current_task = task_time.task_index;
600 if (helper_->
IsAbsent(current_task))
continue;
602 DCHECK_NE(task_to_event_[current_task], -1);
604 const int current_event = task_to_event_[current_task];
605 const IntegerValue energy_min = helper_->
SizeMin(current_task);
611 energy_min, energy_min);
614 current_event, window_[current_event].
time, energy_min);
618 const IntegerValue current_end = task_time.time;
622 const int critical_event =
624 const IntegerValue window_start = window_[critical_event].time;
625 const IntegerValue window_end =
627 for (
int event = critical_event;
event < window_size;
event++) {
628 const IntegerValue energy_min = theta_tree_.
EnergyMin(event);
629 if (energy_min > 0) {
630 const int task = window_[event].task_index;
647 IntegerValue available_energy;
649 current_end, &critical_event, &optional_event, &available_energy);
651 const int optional_task = window_[optional_event].task_index;
655 if (!helper_->
IsAbsent(optional_task)) {
656 const IntegerValue optional_size_min = helper_->
SizeMin(optional_task);
657 const IntegerValue window_start = window_[critical_event].time;
658 const IntegerValue window_end =
659 current_end + optional_size_min - available_energy - 1;
660 for (
int event = critical_event;
event < window_size;
event++) {
661 const IntegerValue energy_min = theta_tree_.
EnergyMin(event);
662 if (energy_min > 0) {
663 const int task = window_[event].task_index;
686 const int id = watcher->
Register(
this);
696 to_propagate_.clear();
697 processed_.assign(helper_->
NumTasks(),
false);
706 task_by_increasing_end_min_.clear();
709 const int task = task_time.task_index;
710 if (helper_->
IsAbsent(task))
continue;
714 const IntegerValue size_min = helper_->
SizeMin(task);
719 task_by_increasing_end_min_.push_back({task,
end_min});
725 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
730 task_by_increasing_end_min_.clear();
731 task_by_increasing_end_min_.push_back({task,
end_min});
735 if (task_by_increasing_end_min_.size() > 1 && !PropagateSubwindow()) {
742 bool DisjunctiveDetectablePrecedences::PropagateSubwindow() {
743 DCHECK(!task_by_increasing_end_min_.empty());
748 task_by_increasing_end_min_.end());
749 const IntegerValue max_end_min = task_by_increasing_end_min_.back().time;
755 task_by_increasing_start_max_.clear();
756 for (
const TaskTime entry : task_by_increasing_end_min_) {
757 const int task = entry.task_index;
759 if (start_max < max_end_min && helper_->IsPresent(task)) {
760 task_by_increasing_start_max_.push_back({task,
start_max});
763 if (task_by_increasing_start_max_.empty())
return true;
764 std::sort(task_by_increasing_start_max_.begin(),
765 task_by_increasing_start_max_.end());
773 to_propagate_.clear();
774 bool need_update =
false;
778 int blocking_task = -1;
779 const int queue_size = task_by_increasing_start_max_.size();
780 for (
const auto task_time : task_by_increasing_end_min_) {
784 const int current_task = task_time.task_index;
785 const IntegerValue current_end_min = task_time.time;
786 if (helper_->
IsAbsent(current_task))
continue;
788 for (; queue_index < queue_size; ++queue_index) {
789 const auto to_insert = task_by_increasing_start_max_[queue_index];
790 const IntegerValue
start_max = to_insert.time;
793 const int t = to_insert.task_index;
807 if (!processed_[t]) {
808 if (blocking_task != -1) {
818 <<
" task should have mandatory part: "
820 DCHECK(to_propagate_.empty());
822 to_propagate_.push_back(t);
831 if (blocking_task != current_task) {
832 to_propagate_.push_back(current_task);
833 if (blocking_task != -1)
continue;
835 for (
const int t : to_propagate_) {
836 DCHECK(!processed_[t]);
837 processed_[t] =
true;
856 if (task_set_end_min > helper_->
StartMin(t)) {
858 const std::vector<TaskSet::Entry>& sorted_tasks =
865 const IntegerValue end_min_if_present =
867 const IntegerValue window_start =
868 sorted_tasks[critical_index].start_min;
869 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
870 const int ct = sorted_tasks[i].task;
892 if (t == blocking_task) {
903 to_propagate_.clear();
910 const int id = watcher->
Register(
this);
923 const int task = task_time.task_index;
926 const IntegerValue
start_min = task_time.time;
928 window_.push_back(task_time);
929 window_end += helper_->
SizeMin(task);
933 if (window_.size() > 1 && !PropagateSubwindow()) {
939 window_.push_back(task_time);
942 if (window_.size() > 1 && !PropagateSubwindow()) {
948 bool DisjunctivePrecedences::PropagateSubwindow() {
954 index_to_end_vars_.clear();
956 for (
const auto task_time : window_) {
957 const int task = task_time.task_index;
963 window_[new_size++] = task_time;
964 index_to_end_vars_.push_back(end_exp.
var);
966 window_.resize(new_size);
969 const int size = before_.size();
970 for (
int i = 0; i < size;) {
971 const IntegerVariable
var = before_[i].var;
975 const int initial_i = i;
977 for (; i < size && before_[i].var ==
var; ++i) {
979 const TaskTime task_time = window_[before_[i].index];
984 const AffineExpression& end_exp = helper_->
Ends()[task_time.task_index];
985 min_offset =
std::min(min_offset, before_[i].offset - end_exp.constant);
990 helper_->
SizeMin(task_time.task_index)});
997 const IntegerValue new_lb = task_set_.
ComputeEndMin() + min_offset;
999 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
1004 for (
int j = initial_i; j < i; ++j) {
1005 const int task = window_[before_[j].index].task_index;
1006 task_to_arc_index_[task] = before_[j].arc_index;
1010 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
1011 for (
int i = critical_index; i < sorted_tasks.size(); ++i) {
1012 const int ct = sorted_tasks[i].task;
1017 const AffineExpression& end_exp = helper_->
Ends()[
ct];
1019 task_to_arc_index_[
ct], min_offset + end_exp.constant,
1036 const int id = watcher->
Register(
this);
1046 const auto& task_by_decreasing_start_max =
1048 const auto& task_by_increasing_shifted_start_min =
1062 int queue_index = task_by_decreasing_start_max.size() - 1;
1063 const int num_tasks = task_by_increasing_shifted_start_min.size();
1064 for (
int i = 0; i < num_tasks;) {
1065 start_min_window_.clear();
1067 for (; i < num_tasks; ++i) {
1068 const TaskTime task_time = task_by_increasing_shifted_start_min[i];
1070 if (!helper_->
IsPresent(task))
continue;
1073 if (start_min_window_.empty()) {
1074 start_min_window_.push_back(task_time);
1077 start_min_window_.push_back(task_time);
1078 window_end += helper_->
SizeMin(task);
1086 start_max_window_.clear();
1087 for (; queue_index >= 0; queue_index--) {
1088 const auto task_time = task_by_decreasing_start_max[queue_index];
1091 if (task_time.time >= window_end)
break;
1092 if (helper_->
IsAbsent(task_time.task_index))
continue;
1093 start_max_window_.push_back(task_time);
1099 if (start_min_window_.size() <= 1)
continue;
1102 if (!start_max_window_.empty() && !PropagateSubwindow()) {
1109 bool DisjunctiveNotLast::PropagateSubwindow() {
1110 auto& task_by_increasing_end_max = start_max_window_;
1111 for (
TaskTime& entry : task_by_increasing_end_max) {
1112 entry.time = helper_->
EndMax(entry.task_index);
1115 task_by_increasing_end_max.end());
1117 const IntegerValue threshold = task_by_increasing_end_max.back().time;
1118 auto& task_by_increasing_start_max = start_min_window_;
1120 for (
const TaskTime entry : task_by_increasing_start_max) {
1121 const int task = entry.task_index;
1125 task_by_increasing_start_max[queue_size++] = {task,
start_max};
1131 if (queue_size <= 1)
return true;
1133 task_by_increasing_start_max.resize(queue_size);
1134 std::sort(task_by_increasing_start_max.begin(),
1135 task_by_increasing_start_max.end());
1138 int queue_index = 0;
1139 for (
const auto task_time : task_by_increasing_end_max) {
1140 const int t = task_time.task_index;
1141 const IntegerValue
end_max = task_time.time;
1145 if (helper_->
IsAbsent(t))
continue;
1150 while (queue_index < queue_size) {
1151 const auto to_insert = task_by_increasing_start_max[queue_index];
1152 const IntegerValue
start_max = to_insert.time;
1155 const int task_index = to_insert.task_index;
1158 helper_->
SizeMin(task_index)});
1172 int critical_index = 0;
1173 const IntegerValue end_min_of_critical_tasks =
1175 if (end_min_of_critical_tasks <= helper_->StartMax(t))
continue;
1180 const std::vector<TaskSet::Entry>& sorted_tasks = task_set_.
SortedTasks();
1181 const int sorted_tasks_size = sorted_tasks.size();
1182 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1183 const int ct = sorted_tasks[i].task;
1184 if (t ==
ct)
continue;
1194 end_max > largest_ct_start_max);
1195 if (
end_max > largest_ct_start_max) {
1198 const IntegerValue window_start = sorted_tasks[critical_index].start_min;
1199 for (
int i = critical_index; i < sorted_tasks_size; ++i) {
1200 const int ct = sorted_tasks[i].task;
1201 if (
ct == t)
continue;
1213 if (!helper_->
DecreaseEndMax(t, largest_ct_start_max))
return false;
1220 const int id = watcher->
Register(
this);
1227 const int num_tasks = helper_->
NumTasks();
1229 is_gray_.resize(num_tasks,
false);
1230 non_gray_task_to_event_.resize(num_tasks);
1235 const int task = task_time.task_index;
1236 if (helper_->
IsAbsent(task))
continue;
1240 if (helper_->
StartMin(task) < window_end) {
1241 window_.push_back(task_time);
1242 window_end += helper_->
SizeMin(task);
1248 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1254 window_.push_back(task_time);
1255 window_end = task_time.time + helper_->
SizeMin(task);
1257 if (window_.size() > 2 && !PropagateSubwindow(window_end)) {
1263 bool DisjunctiveEdgeFinding::PropagateSubwindow(IntegerValue window_end_min) {
1265 task_by_increasing_end_max_.clear();
1266 for (
const auto task_time : window_) {
1267 const int task = task_time.task_index;
1280 is_gray_[task] =
false;
1281 task_by_increasing_end_max_.push_back({task,
end_max});
1283 is_gray_[task] =
true;
1289 if (task_by_increasing_end_max_.size() < 2)
return true;
1290 std::sort(task_by_increasing_end_max_.begin(),
1291 task_by_increasing_end_max_.end());
1302 const int window_size = window_.size();
1303 event_size_.clear();
1304 theta_tree_.
Reset(window_size);
1305 for (
int event = 0;
event < window_size; ++event) {
1306 const TaskTime task_time = window_[event];
1307 const int task = task_time.task_index;
1308 const IntegerValue energy_min = helper_->
SizeMin(task);
1309 event_size_.push_back(energy_min);
1310 if (is_gray_[task]) {
1313 non_gray_task_to_event_[task] = event;
1322 DCHECK(!is_gray_[task_by_increasing_end_max_.back().task_index]);
1323 const IntegerValue non_gray_end_max =
1324 task_by_increasing_end_max_.back().time;
1327 const IntegerValue non_gray_end_min = theta_tree_.
GetEnvelope();
1328 if (non_gray_end_min > non_gray_end_max) {
1332 const int critical_event =
1334 const IntegerValue window_start = window_[critical_event].time;
1335 const IntegerValue window_end =
1337 for (
int event = critical_event;
event < window_size;
event++) {
1338 const int task = window_[event].task_index;
1339 if (is_gray_[task])
continue;
1357 int critical_event_with_gray;
1359 IntegerValue available_energy;
1361 non_gray_end_max, &critical_event_with_gray, &gray_event,
1363 const int gray_task = window_[gray_event].task_index;
1364 DCHECK(is_gray_[gray_task]);
1368 if (helper_->
IsAbsent(gray_task)) {
1374 if (helper_->
StartMin(gray_task) < non_gray_end_min) {
1377 const int critical_event =
1380 const int first_event =
1381 std::min(critical_event, critical_event_with_gray);
1382 const int second_event =
1383 std::max(critical_event, critical_event_with_gray);
1384 const IntegerValue first_start = window_[first_event].time;
1385 const IntegerValue second_start = window_[second_event].time;
1389 const IntegerValue window_end =
1390 non_gray_end_max + event_size_[gray_event] - available_energy - 1;
1391 CHECK_GE(window_end, non_gray_end_max);
1395 for (
int event = first_event;
event < window_size;
event++) {
1396 const int task = window_[event].task_index;
1397 if (is_gray_[task])
continue;
1400 task, event_size_[event],
1401 event >= second_event ? second_start : first_start);
1408 window_[critical_event_with_gray].
time);
1425 if (task_by_increasing_end_max_.size() <= 2)
break;
1428 if (task_by_increasing_end_max_[0].
time >=
1434 const int new_gray_task = task_by_increasing_end_max_.back().task_index;
1435 task_by_increasing_end_max_.pop_back();
1436 const int new_gray_event = non_gray_task_to_event_[new_gray_task];
1437 DCHECK(!is_gray_[new_gray_task]);
1438 is_gray_[new_gray_task] =
true;
1440 window_[new_gray_event].
time,
1441 event_size_[new_gray_event]);
1448 const int id = watcher->
Register(
this);
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()
IntegerValue ShiftedStartMin(int t) const
IntegerValue EndMin(int t) const
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
std::vector< Literal > * MutableLiteralReason()
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue value)
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue value)
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)
std::vector< IntegerLiteral > * MutableIntegerReason()
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)
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)
IntegerValue SizeMin(int t) const
const std::vector< AffineExpression > & Ends() const
void AddUnsortedEntry(const Entry &e)
void NotifyEntryIsNowLastIfPresent(const Entry &e)
int GetCriticalIndex() 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
const std::vector< Entry > & SortedTasks() 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)
void AddDisjunctiveWithBooleanPrecedencesOnly(const std::vector< IntervalVariable > &intervals, Model *model)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
void AddDisjunctiveWithBooleanPrecedences(const std::vector< IntervalVariable > &intervals, Model *model)
std::function< void(Model *)> Disjunctive(const std::vector< IntervalVariable > &intervals)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
void AddConditionalAffinePrecedence(const std::vector< Literal > &enforcement_literals, AffineExpression left, AffineExpression right, Model *model)
const IntegerVariable kNoIntegerVariable(-1)
std::function< void(Model *)> Implication(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
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)