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