39 constraint->RegisterWith(watcher);
40 model->TakeOwnership(constraint);
50 const int num_tasks = helper_->
NumTasks();
51 task_to_start_event_.resize(num_tasks);
55 const int id = watcher->
Register(
this);
67 const IntegerValue capacity_max = integer_trail_->
UpperBound(capacity_);
69 if (capacity_max <= 0)
return true;
72 start_event_task_time_.clear();
75 const int task = task_time.task_index;
77 task_to_start_event_[task] = -1;
80 start_event_task_time_.emplace_back(task_time);
81 task_to_start_event_[task] = num_events;
84 start_event_is_present_.assign(num_events,
false);
85 theta_tree_.
Reset(num_events);
87 bool tree_has_mandatory_intervals =
false;
90 for (
const auto task_time :
92 const int current_task = task_time.task_index;
93 const IntegerValue current_end = task_time.time;
94 if (task_to_start_event_[current_task] == -1)
continue;
98 const int current_event = task_to_start_event_[current_task];
99 const IntegerValue
start_min = start_event_task_time_[current_event].time;
100 const bool is_present = helper_->
IsPresent(current_task);
101 start_event_is_present_[current_event] = is_present;
103 tree_has_mandatory_intervals =
true;
114 if (tree_has_mandatory_intervals) {
116 const IntegerValue envelope = theta_tree_.
GetEnvelope();
117 const int critical_event =
119 const IntegerValue window_start =
120 start_event_task_time_[critical_event].time;
121 const IntegerValue window_end = current_end;
122 const IntegerValue window_size = window_end - window_start;
123 if (window_size == 0)
continue;
124 const IntegerValue new_capacity_min =
125 CeilRatio(envelope - window_start * capacity_max, window_size);
133 if (new_capacity_min > integer_trail_->
LowerBound(capacity_)) {
135 for (
int event = critical_event;
event < num_events;
event++) {
136 if (start_event_is_present_[event]) {
137 const int task = start_event_task_time_[event].task_index;
169 int event_with_new_energy_max;
170 IntegerValue new_energy_max;
172 current_end * capacity_max, &critical_event,
173 &event_with_new_energy_max, &new_energy_max);
175 const IntegerValue window_start =
176 start_event_task_time_[critical_event].time;
179 const IntegerValue window_end = current_end;
180 for (
int event = critical_event;
event < num_events;
event++) {
181 if (start_event_is_present_[event]) {
182 if (event == event_with_new_energy_max)
continue;
183 const int task = start_event_task_time_[event].task_index;
195 const int task_with_new_energy_max =
196 start_event_task_time_[event_with_new_energy_max].task_index;
204 if (helper_->
IsPresent(task_with_new_energy_max)) {
206 task_to_start_event_[task_with_new_energy_max],
207 start_event_task_time_[event_with_new_energy_max].
time *
209 demands_->
EnergyMin(task_with_new_energy_max), new_energy_max);
211 theta_tree_.
RemoveEvent(event_with_new_energy_max);
220 const std::vector<int>& subtasks,
const std::vector<IntegerValue>& offsets,
229 is_in_subtasks_.assign(helper->
NumTasks(),
false);
230 task_offsets_.assign(helper->
NumTasks(), 0);
231 for (
int i = 0; i < subtasks.size(); ++i) {
232 is_in_subtasks_[subtasks[i]] =
true;
233 task_offsets_[subtasks[i]] = offsets[i];
244 IntegerValue energy_after_time(0);
245 IntegerValue profile_height(0);
250 const IntegerValue capacity_max = integer_trail_->
UpperBound(capacity_);
251 dp_.
Reset(capacity_max.value());
257 for (
int i = profile.size() - 1; i >= 0;) {
260 const int t = profile[i].task;
261 if (!helper_->
IsPresent(t) || !is_in_subtasks_[t]) {
267 const IntegerValue
time = profile[i].time;
268 if (profile_height > 0) {
269 energy_after_time += profile_height * (previous_time -
time);
271 previous_time =
time;
275 const IntegerValue saved_capa_max = dp_.
CurrentMax();
276 const IntegerValue saved_min_offset = min_offset;
278 for (; i >= 0 && profile[i].time ==
time; --i) {
280 const int t = profile[i].task;
281 if (!helper_->
IsPresent(t) || !is_in_subtasks_[t])
continue;
283 min_offset =
std::min(min_offset, task_offsets_[t]);
284 const IntegerValue demand_min = demands_->
DemandMin(t);
285 if (profile[i].is_first) {
286 profile_height -= demand_min;
288 profile_height += demand_min;
289 if (demands_->
Demands()[t].IsConstant()) {
290 dp_.
Add(demand_min.value());
292 dp_.
Add(capacity_max.value());
304 if (energy_after_time == 0)
continue;
305 DCHECK_GT(saved_capa_max, 0);
307 const IntegerValue end_min_with_offset =
308 time +
CeilRatio(energy_after_time, saved_capa_max) + saved_min_offset;
309 if (end_min_with_offset > best_bound) {
311 best_bound = end_min_with_offset;
314 DCHECK_EQ(profile_height, 0);
317 if (best_bound > integer_trail_->
LowerBound(var_to_push_)) {
321 for (
int t = 0; t < helper_->
NumTasks(); ++t) {
322 if (!is_in_subtasks_[t])
continue;
325 const IntegerValue size_min = helper_->
SizeMin(t);
326 if (size_min == 0)
continue;
328 const IntegerValue demand_min = demands_->
DemandMin(t);
329 if (demand_min == 0)
continue;
332 if (
end_min <= best_time)
continue;
357 const int id = watcher->
Register(
this);
360 for (
const int t : subtasks_) {
CumulativeEnergyConstraint(AffineExpression capacity, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands, Model *model)
void RegisterWith(GenericLiteralWatcher *watcher)
CumulativeIsAfterSubsetConstraint(IntegerVariable var, AffineExpression capacity, const std::vector< int > &subtasks, const std::vector< IntegerValue > &offsets, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands, Model *model)
void RegisterWith(GenericLiteralWatcher *watcher)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
void SetPropagatorPriority(int id, int priority)
int Register(PropagatorInterface *propagator)
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
IntegerValue UpperBound(IntegerVariable i) const
IntegerValue LowerBound(IntegerVariable i) const
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
int64_t CurrentMax() const
void Reset(int64_t bound)
Class that owns everything related to a particular optimization model.
IntegerValue EndMin(int t) const
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
const std::vector< TaskTime > & TaskByDecreasingEndMax()
void AddSizeMinReason(int t)
const std::vector< TaskTime > & TaskByIncreasingStartMin()
void AddStartMinReason(int t, IntegerValue lower_bound)
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 AddEndMinReason(int t, IntegerValue lower_bound)
bool IsAbsent(int t) const
ABSL_MUST_USE_RESULT bool ReportConflict()
const std::vector< AffineExpression > & Starts() const
const std::vector< ProfileEvent > & GetEnergyProfile()
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
Literal PresenceLiteral(int index) const
void AddEndMaxReason(int t, IntegerValue upper_bound)
const std::vector< AffineExpression > & Sizes() const
void SetTimeDirection(bool is_forward)
IntegerValue SizeMin(int t) const
const std::vector< AffineExpression > & Ends() const
IntegerValue EnergyMax(int t) const
IntegerValue EnergyMin(int t) const
void CacheAllEnergyValues()
void AddDemandMinReason(int t)
ABSL_MUST_USE_RESULT bool DecreaseEnergyMax(int t, IntegerValue value)
const std::vector< AffineExpression > & Demands() const
IntegerValue DemandMin(int t) const
void AddEnergyMinReason(int t)
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)
void AddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
IntegerType GetEnvelope() const
ReverseView< Container > reversed_view(const Container &c)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
void AddCumulativeOverloadChecker(AffineExpression capacity, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands, Model *model)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
Collection of objects used to extend the Constraint Solver library.
IntegerLiteral GreaterOrEqual(IntegerValue bound) const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)