OR-Tools  9.3
timetable.h
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_SAT_TIMETABLE_H_
15#define OR_TOOLS_SAT_TIMETABLE_H_
16
17#include <cstdint>
18#include <vector>
19
20#include "ortools/base/macros.h"
21#include "ortools/sat/integer.h"
23#include "ortools/sat/model.h"
25#include "ortools/util/rev.h"
27
28namespace operations_research {
29namespace sat {
30
31// Adds a reservoir constraint to the model. Note that to account for level not
32// containing zero at time zero, we might needs to create an artificial fixed
33// event.
34//
35// This instantiate one or more ReservoirTimeTabling class to perform the
36// propagation.
37void AddReservoirConstraint(std::vector<AffineExpression> times,
38 std::vector<IntegerValue> deltas,
39 std::vector<Literal> presences, int64_t min_level,
40 int64_t max_level, Model* model);
41
42// The piecewise constant function must be below the given capacity. The initial
43// function value is zero. Note that a negative capacity will thus be trivially
44// infeasible.
45//
46// Note that we take for the definition of the function at time t to be the sum
47// of all delta with time <= t. But because we check for the capacity over the
48// full horizon, we could have taken < t with no behavior change.
50 public:
51 ReservoirTimeTabling(const std::vector<AffineExpression>& times,
52 const std::vector<IntegerValue>& deltas,
53 const std::vector<Literal>& presences,
54 IntegerValue capacity, Model* model);
55
56 bool Propagate() final;
57
58 private:
59 // The rectangle will be ordered by start, and the end of each rectangle
60 // will be equal to the start of the next one. The height correspond to the
61 // one from start (inclusive) until the next one (exclusive).
62 struct ProfileRectangle {
63 ProfileRectangle() {}
64 ProfileRectangle(IntegerValue start, IntegerValue height)
65 : start(start), height(height) {}
66
67 bool operator<(const ProfileRectangle& other) const {
68 return start < other.start;
69 }
70
71 /* const */ IntegerValue start = IntegerValue(0);
72 /* const */ IntegerValue height = IntegerValue(0);
73 };
74
75 // Builds the profile and increases the lower bound of the capacity
76 // variable accordingly.
77 bool BuildProfile();
78
79 // Explanation of the profile minimum value at time t, eventually ignoring the
80 // given event.
81 void FillReasonForProfileAtGivenTime(IntegerValue t,
82 int event_to_ignore = -1);
83
84 // Tries to tighten the min/max time of the given event depending on the sign
85 // of the delta associated with this event.
86 bool TryToIncreaseMin(int event);
87 bool TryToDecreaseMax(int event);
88
89 // Input.
90 std::vector<AffineExpression> times_;
91 std::vector<IntegerValue> deltas_;
92 std::vector<Literal> presences_;
93 IntegerValue capacity_;
94
95 // Model class.
96 const VariablesAssignment& assignment_;
97 IntegerTrail* integer_trail_;
98
99 // Temporary data.
100 std::vector<Literal> literal_reason_;
101 std::vector<IntegerLiteral> integer_reason_;
102 std::vector<ProfileRectangle> profile_;
103};
104
105// A strongly quadratic version of Time Tabling filtering. This propagator
106// is similar to the CumulativeTimeTable propagator of the constraint solver.
108 public:
109 TimeTablingPerTask(const std::vector<AffineExpression>& demands,
110 AffineExpression capacity, IntegerTrail* integer_trail,
112
113 bool Propagate() final;
114
115 void RegisterWith(GenericLiteralWatcher* watcher);
116
117 private:
118 // The rectangle will be ordered by start, and the end of each rectangle
119 // will be equal to the start of the next one. The height correspond to the
120 // one from start (inclusive) until the next one (exclusive).
121 struct ProfileRectangle {
122 /* const */ IntegerValue start;
123 /* const */ IntegerValue height;
124
125 ProfileRectangle(IntegerValue start, IntegerValue height)
126 : start(start), height(height) {}
127
128 bool operator<(const ProfileRectangle& other) const {
129 return start < other.start;
130 }
131 };
132
133 // Builds the profile and increases the lower bound of the capacity
134 // variable accordingly.
135 bool BuildProfile();
136
137 // Reverses the profile. This is needed to reuse a given profile to update
138 // both the start and end times.
139 void ReverseProfile();
140
141 // Tries to increase the minimum start time of each task according to the
142 // current profile. This function can be called after ReverseProfile() and
143 // ReverseVariables to update the maximum end time of each task.
144 bool SweepAllTasks(bool is_forward);
145
146 // Tries to increase the minimum start time of task_id.
147 bool SweepTask(int task_id);
148
149 // Updates the starting time of task_id to right and explain it. The reason is
150 // all the mandatory parts contained in [left, right).
151 bool UpdateStartingTime(int task_id, IntegerValue left, IntegerValue right);
152
153 // Increases the minimum capacity to new_min and explain it. The reason is all
154 // the mandatory parts that overlap time.
155 bool IncreaseCapacity(IntegerValue time, IntegerValue new_min);
156
157 // Explains the state of the profile in the time interval [left, right). The
158 // reason is all the mandatory parts that overlap the interval. The current
159 // reason is not cleared when this method is called.
160 void AddProfileReason(IntegerValue left, IntegerValue right);
161
162 IntegerValue CapacityMin() const {
163 return integer_trail_->LowerBound(capacity_);
164 }
165
166 IntegerValue CapacityMax() const {
167 return integer_trail_->UpperBound(capacity_);
168 }
169
170 IntegerValue DemandMin(int task_id) const {
171 return integer_trail_->LowerBound(demands_[task_id]);
172 }
173
174 IntegerValue DemandMax(int task_id) const {
175 return integer_trail_->UpperBound(demands_[task_id]);
176 }
177
178 // Returns true if the tasks is present and has a mantatory part.
179 bool IsInProfile(int t) const {
180 return positions_in_profile_tasks_[t] < num_profile_tasks_;
181 }
182
183 // Number of tasks.
184 const int num_tasks_;
185
186 // The demand variables of the tasks.
187 std::vector<AffineExpression> demands_;
188
189 // Capacity of the resource.
190 const AffineExpression capacity_;
191
192 IntegerTrail* integer_trail_;
194
195 // Optimistic profile of the resource consumption over time.
196 std::vector<ProfileRectangle> profile_;
197 IntegerValue profile_max_height_;
198
199 // Reversible starting height of the reduced profile. This corresponds to the
200 // height of the leftmost profile rectangle that can be used for propagation.
201 IntegerValue starting_profile_height_;
202
203 // Reversible sets of tasks to consider for the forward (resp. backward)
204 // propagation. A task with a fixed start do not need to be considered for the
205 // forward pass, same for task with fixed end for the backward pass. It is why
206 // we use two sets.
207 std::vector<int> forward_tasks_to_sweep_;
208 std::vector<int> backward_tasks_to_sweep_;
209 int forward_num_tasks_to_sweep_;
210 int backward_num_tasks_to_sweep_;
211
212 // Reversible set (with random access) of tasks to consider for building the
213 // profile. The set contains the tasks in the [0, num_profile_tasks_) prefix
214 // of profile_tasks_. The positions of a task in profile_tasks_ is contained
215 // in positions_in_profile_tasks_.
216 std::vector<int> profile_tasks_;
217 std::vector<int> positions_in_profile_tasks_;
218 int num_profile_tasks_;
219
220 DISALLOW_COPY_AND_ASSIGN(TimeTablingPerTask);
221};
222
223} // namespace sat
224} // namespace operations_research
225
226#endif // OR_TOOLS_SAT_TIMETABLE_H_
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1449
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1445
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
ReservoirTimeTabling(const std::vector< AffineExpression > &times, const std::vector< IntegerValue > &deltas, const std::vector< Literal > &presences, IntegerValue capacity, Model *model)
Definition: timetable.cc:57
void RegisterWith(GenericLiteralWatcher *watcher)
Definition: timetable.cc:318
TimeTablingPerTask(const std::vector< AffineExpression > &demands, AffineExpression capacity, IntegerTrail *integer_trail, SchedulingConstraintHelper *helper)
Definition: timetable.cc:284
GRBmodel * model
void AddReservoirConstraint(std::vector< AffineExpression > times, std::vector< IntegerValue > deltas, std::vector< Literal > presences, int64_t min_level, int64_t max_level, Model *model)
Definition: timetable.cc:32
Collection of objects used to extend the Constraint Solver library.
int64_t time
Definition: resource.cc:1693
int64_t capacity
int64_t start