OR-Tools  9.6
timetable.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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/sat/model.h"
24 #include "ortools/sat/sat_base.h"
25 #include "ortools/util/rev.h"
27 
28 namespace operations_research {
29 namespace 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.
37 void AddReservoirConstraint(std::vector<AffineExpression> times,
38  std::vector<AffineExpression> 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<AffineExpression>& 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<AffineExpression> 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.
107 //
108 // TODO(user): Use SchedulingDemandHelper. In particular, if we know the task
109 // is from a set of fixed alternatives, we might be able to push it more.
111  public:
114  SchedulingDemandHelper* demands, Model* model);
115 
116  bool Propagate() final;
117 
118  void RegisterWith(GenericLiteralWatcher* watcher);
119 
120  private:
121  // The rectangle will be ordered by start, and the end of each rectangle
122  // will be equal to the start of the next one. The height correspond to the
123  // one from start (inclusive) until the next one (exclusive).
124  struct ProfileRectangle {
125  /* const */ IntegerValue start;
126  /* const */ IntegerValue height;
127 
128  ProfileRectangle(IntegerValue start, IntegerValue height)
129  : start(start), height(height) {}
130 
131  bool operator<(const ProfileRectangle& other) const {
132  return start < other.start;
133  }
134  };
135 
136  // Builds the profile and increases the lower bound of the capacity
137  // variable accordingly.
138  bool BuildProfile();
139 
140  // Reverses the profile. This is needed to reuse a given profile to update
141  // both the start and end times.
142  void ReverseProfile();
143 
144  // Tries to increase the minimum start time of each task according to the
145  // current profile. This function can be called after ReverseProfile() and
146  // ReverseVariables to update the maximum end time of each task.
147  bool SweepAllTasks();
148 
149  // Tries to increase the minimum start time of task_id. This assumes tasks are
150  // processed by increasing start_min so that the starting profile_index only
151  // increase.
152  bool SweepTask(int task_id, IntegerValue initial_start_min,
153  IntegerValue conflict_height, int* profile_index);
154 
155  // Updates the starting time of task_id to right and explain it. The reason is
156  // all the mandatory parts contained in [left, right).
157  bool UpdateStartingTime(int task_id, IntegerValue left, IntegerValue right);
158 
159  // Increases the minimum capacity to new_min and explain it. The reason is all
160  // the mandatory parts that overlap time.
161  bool IncreaseCapacity(IntegerValue time, IntegerValue new_min);
162 
163  // Explains the state of the profile in the time interval [left, right) that
164  // allow to push task_id. The reason is all the mandatory parts that overlap
165  // the interval. The current reason is not cleared when this method is called.
166  void AddProfileReason(int task_id, IntegerValue left, IntegerValue right,
167  IntegerValue capacity_threshold);
168 
169  IntegerValue CapacityMin() const {
170  return integer_trail_->LowerBound(capacity_);
171  }
172 
173  IntegerValue CapacityMax() const {
174  return integer_trail_->UpperBound(capacity_);
175  }
176 
177  // Returns true if the tasks is present and has a mantatory part.
178  bool IsInProfile(int t) const {
179  return positions_in_profile_tasks_[t] < num_profile_tasks_;
180  }
181 
182  // Number of tasks.
183  const int num_tasks_;
184 
185  // Capacity of the resource.
186  const AffineExpression capacity_;
187 
189  SchedulingDemandHelper* demands_;
190  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 set (with random access) of tasks to consider for building the
197  // profile. The set contains the tasks in the [0, num_profile_tasks_) prefix
198  // of profile_tasks_. The positions of a task in profile_tasks_ is contained
199  // in positions_in_profile_tasks_.
200  std::vector<int> profile_tasks_;
201  std::vector<int> positions_in_profile_tasks_;
202  int num_profile_tasks_;
203 
204  // Statically computed.
205  // This allow to simplify the profile for common usage.
206  bool has_demand_equal_to_capacity_ = false;
207  IntegerValue initial_max_demand_;
208 
209  DISALLOW_COPY_AND_ASSIGN(TimeTablingPerTask);
210 };
211 
212 } // namespace sat
213 } // namespace operations_research
214 
215 #endif // OR_TOOLS_SAT_TIMETABLE_H_
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1561
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1557
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
ReservoirTimeTabling(const std::vector< AffineExpression > &times, const std::vector< AffineExpression > &deltas, const std::vector< Literal > &presences, IntegerValue capacity, Model *model)
Definition: timetable.cc:55
void RegisterWith(GenericLiteralWatcher *watcher)
Definition: timetable.cc:346
TimeTablingPerTask(AffineExpression capacity, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands, Model *model)
Definition: timetable.cc:310
int64_t height
GRBmodel * model
void AddReservoirConstraint(std::vector< AffineExpression > times, std::vector< AffineExpression > 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:1694
int64_t capacity
int64_t start