35 std::move(energies),
capacity, integer_trail, helper);
36 constraint->RegisterWith(watcher);
37 model->TakeOwnership(constraint);
47 std::vector<AffineExpression> energies;
48 const int num_tasks = helper->
NumTasks();
49 CHECK_EQ(demands.size(), num_tasks);
50 for (
int t = 0; t < num_tasks; ++t) {
61 CHECK_GE(
demand.constant, 0);
65 CHECK_GE(
demand.constant, 0);
66 energies.push_back(duration);
67 energies.back().coeff *=
demand.constant;
68 energies.back().constant *=
demand.constant;
71 energies.push_back(
demand);
72 energies.back().coeff *= duration.
constant;
73 energies.back().constant *= duration.
constant;
81 <<
"Overload checker with variable demand and varialbe duration "
82 "is currently not implemented. Skipping.";
90 model->TakeOwnership(constraint);
96 : energies_(std::move(energies)),
98 integer_trail_(integer_trail),
101 const int num_tasks = helper_->
NumTasks();
102 CHECK_EQ(energies_.size(), num_tasks);
103 task_to_start_event_.resize(num_tasks);
107 const int id = watcher->
Register(
this);
117 const IntegerValue capacity_max = integer_trail_->
UpperBound(capacity_);
119 if (capacity_max <= 0)
return true;
122 start_event_task_time_.clear();
125 const int task = task_time.task_index;
127 integer_trail_->
UpperBound(energies_[task]) == 0) {
128 task_to_start_event_[task] = -1;
131 start_event_task_time_.emplace_back(task_time);
132 task_to_start_event_[task] = num_events;
135 start_event_is_present_.assign(num_events,
false);
136 theta_tree_.
Reset(num_events);
138 bool tree_has_mandatory_intervals =
false;
141 for (
const auto task_time :
143 const int current_task = task_time.task_index;
144 const IntegerValue current_end = task_time.time;
145 if (task_to_start_event_[current_task] == -1)
continue;
149 const int current_event = task_to_start_event_[current_task];
150 const IntegerValue
start_min = start_event_task_time_[current_event].time;
151 const bool is_present = helper_->
IsPresent(current_task);
152 start_event_is_present_[current_event] = is_present;
154 tree_has_mandatory_intervals =
true;
157 integer_trail_->
LowerBound(energies_[current_task]),
158 integer_trail_->
UpperBound(energies_[current_task]));
162 integer_trail_->
UpperBound(energies_[current_task]));
166 if (tree_has_mandatory_intervals) {
168 const IntegerValue envelope = theta_tree_.
GetEnvelope();
169 const int critical_event =
171 const IntegerValue window_start =
172 start_event_task_time_[critical_event].time;
173 const IntegerValue window_end = current_end;
174 const IntegerValue window_size = window_end - window_start;
175 if (window_size == 0)
continue;
176 const IntegerValue new_capacity_min =
177 CeilRatio(envelope - window_start * capacity_max, window_size);
185 if (new_capacity_min > integer_trail_->
LowerBound(capacity_)) {
187 for (
int event = critical_event;
event < num_events;
event++) {
188 if (start_event_is_present_[event]) {
189 const int task = start_event_task_time_[event].task_index;
224 int event_with_new_energy_max;
225 IntegerValue new_energy_max;
227 current_end * capacity_max, &critical_event,
228 &event_with_new_energy_max, &new_energy_max);
230 const IntegerValue window_start =
231 start_event_task_time_[critical_event].time;
234 const IntegerValue window_end = current_end;
235 for (
int event = critical_event;
event < num_events;
event++) {
236 if (start_event_is_present_[event]) {
237 if (event == event_with_new_energy_max)
continue;
238 const int task = start_event_task_time_[event].task_index;
253 const int task_with_new_energy_max =
254 start_event_task_time_[event_with_new_energy_max].task_index;
259 integer_trail_->
LowerBound(energies_[task_with_new_energy_max])) {
260 if (helper_->
IsOptional(task_with_new_energy_max)) {
267 energies_[task_with_new_energy_max].LowerOrEqual(new_energy_max);
274 if (helper_->
IsPresent(task_with_new_energy_max)) {
276 task_to_start_event_[task_with_new_energy_max],
277 start_event_task_time_[event_with_new_energy_max].
time *
279 integer_trail_->
LowerBound(energies_[task_with_new_energy_max]),
282 theta_tree_.
RemoveEvent(event_with_new_energy_max);