32 : num_tasks_(helper->NumTasks()),
36 integer_trail_(integer_trail) {
38 mandatory_energy_before_end_max_.resize(num_tasks_);
39 mandatory_energy_before_start_min_.resize(num_tasks_);
42 size_free_.resize(num_tasks_);
43 energy_free_.resize(num_tasks_);
47 const int id = watcher->
Register(
this);
50 for (
int t = 0; t < num_tasks_; t++) {
57 const int64_t old_timestamp = integer_trail_->
num_enqueues();
60 if (!TimeTableEdgeFindingPass())
return false;
63 if (!TimeTableEdgeFindingPass())
return false;
66 if (old_timestamp == integer_trail_->
num_enqueues())
break;
71void TimeTableEdgeFinding::BuildTimeTable() {
76 for (
const auto task_time :
78 const int t = task_time.task_index;
80 if (task_time.time < helper_->
EndMin(t)) {
81 scp_.push_back(task_time);
87 const int t = task_time.task_index;
89 if (helper_->
StartMax(t) < task_time.time) {
90 ecp_.push_back(task_time);
96 const std::vector<TaskTime>& by_decreasing_end_max =
98 const std::vector<TaskTime>& by_start_min =
101 IntegerValue height = IntegerValue(0);
102 IntegerValue
energy = IntegerValue(0);
106 IntegerValue previous_time = IntegerValue(0);
111 int index_emax = num_tasks_ - 1;
113 while (index_emax >= 0) {
116 IntegerValue
time = by_decreasing_end_max[index_emax].time;
117 if (index_smin < num_tasks_) {
120 if (index_scp < scp_.size()) {
123 if (index_ecp < ecp_.size()) {
129 previous_time =
time;
132 while (index_smin < num_tasks_ && by_start_min[index_smin].
time ==
time) {
133 mandatory_energy_before_start_min_[by_start_min[index_smin].task_index] =
139 while (index_emax >= 0 && by_decreasing_end_max[index_emax].
time ==
time) {
140 mandatory_energy_before_end_max_[by_decreasing_end_max[index_emax]
146 while (index_scp < scp_.size() && scp_[index_scp].time ==
time) {
147 height += DemandMin(scp_[index_scp].task_index);
152 while (index_ecp < ecp_.size() && ecp_[index_ecp].time ==
time) {
153 height -= DemandMin(ecp_[index_ecp].task_index);
159bool TimeTableEdgeFinding::TimeTableEdgeFindingPass() {
162 for (
int t = 0; t < num_tasks_; ++t) {
167 size_free_[t] = helper_->
SizeMin(t);
171 energy_free_[t] = size_free_[t] * DemandMin(t);
183 const int end_task = end_task_time.task_index;
186 if (!helper_->
IsPresent(end_task))
continue;
187 if (energy_free_[end_task] == 0)
continue;
190 if (end_task_time.time == previous_end)
continue;
191 previous_end = end_task_time.time;
194 IntegerValue energy_free_parts = IntegerValue(0);
199 IntegerValue free_energy_of_max_task_in_window(0);
204 const int begin_task = begin_task_time.task_index;
207 if (!helper_->
IsPresent(begin_task))
continue;
208 if (energy_free_[begin_task] == 0)
continue;
212 const IntegerValue begin = begin_task_time.time;
213 const IntegerValue
end = end_task_time.time;
216 if (
end <= begin)
continue;
237 energy_free_parts += energy_free_[begin_task];
239 const IntegerValue demand_min = DemandMin(begin_task);
240 const IntegerValue extra_energy =
241 std::min(size_free_[begin_task], (
end - begin)) * demand_min;
245 const IntegerValue free_energy_in_window =
250 if (extra_energy > extra_energy_required_by_max_task) {
251 max_task = begin_task;
252 extra_energy_required_by_max_task = extra_energy;
256 energy_free_parts += free_energy_of_max_task_in_window;
257 free_energy_of_max_task_in_window = free_energy_in_window;
259 energy_free_parts += free_energy_in_window;
267 if (max_task == -1)
continue;
270 const IntegerValue interval_energy = CapacityMax() * (
end - begin);
271 const IntegerValue energy_mandatory =
272 mandatory_energy_before_end_max_[end_task] -
273 mandatory_energy_before_start_min_[begin_task];
274 const IntegerValue available_energy =
275 interval_energy - energy_free_parts - energy_mandatory;
278 if (extra_energy_required_by_max_task <= available_energy)
continue;
286 const IntegerValue mandatory_in =
std::max(
291 const IntegerValue new_start =
292 end - mandatory_in - (available_energy / DemandMin(max_task));
295 if (helper_->
StartMin(max_task) < new_start) {
296 if (!IncreaseStartMin(begin,
end, max_task, new_start))
return false;
304bool TimeTableEdgeFinding::IncreaseStartMin(IntegerValue begin,
305 IntegerValue
end,
int task_index,
306 IntegerValue new_start) {
312 mutable_reason->push_back(
319 mutable_reason->push_back(
326 for (
int t = 0; t < num_tasks_; ++t) {
327 if (t == task_index)
continue;
329 if (helper_->
EndMax(t) <= begin)
continue;
333 mutable_reason->push_back(
#define DCHECK_EQ(val1, val2)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
int Register(PropagatorInterface *propagator)
int64_t num_enqueues() const
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
IntegerValue EndMin(int t) const
const std::vector< TaskTime > & TaskByDecreasingEndMax()
std::vector< IntegerLiteral > * MutableIntegerReason()
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)
const std::vector< TaskTime > & TaskByIncreasingEndMin()
bool IsPresent(int t) const
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
IntegerValue EndMax(int t) const
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
IntegerValue SizeMin(int t) const
void RegisterWith(GenericLiteralWatcher *watcher)
TimeTableEdgeFinding(const std::vector< AffineExpression > &demands, AffineExpression capacity, SchedulingConstraintHelper *helper, IntegerTrail *integer_trail)
ReverseView< Container > reversed_view(const Container &c)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
Collection of objects used to extend the Constraint Solver library.
std::optional< int64_t > end