OR-Tools  8.1
intervals.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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_INTERVALS_H_
15 #define OR_TOOLS_SAT_INTERVALS_H_
16 
17 #include <functional>
18 #include <vector>
19 
20 #include "absl/types/span.h"
21 #include "ortools/base/int_type.h"
24 #include "ortools/base/logging.h"
25 #include "ortools/base/macros.h"
27 #include "ortools/sat/integer.h"
29 #include "ortools/sat/model.h"
32 #include "ortools/sat/sat_base.h"
33 #include "ortools/sat/sat_solver.h"
34 
35 namespace operations_research {
36 namespace sat {
37 
38 DEFINE_INT_TYPE(IntervalVariable, int32);
39 const IntervalVariable kNoIntervalVariable(-1);
40 
41 // This class maintains a set of intervals which correspond to three integer
42 // variables (start, end and size). It automatically registers with the
43 // PrecedencesPropagator the relation between the bounds of each interval and
44 // provides many helper functions to add precedences relation between intervals.
46  public:
48  : integer_trail_(model->GetOrCreate<IntegerTrail>()),
49  precedences_(model->GetOrCreate<PrecedencesPropagator>()) {}
50 
51  // Returns the current number of intervals in the repository.
52  // The interval will always be identified by an integer in [0, num_intervals).
53  int NumIntervals() const { return start_vars_.size(); }
54 
55  // Functions to add a new interval to the repository.
56  // - If size == kNoIntegerVariable, then the size is fixed to fixed_size.
57  // - If is_present != kNoLiteralIndex, then this is an optional interval.
58  IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end,
59  IntegerVariable size, IntegerValue fixed_size,
60  LiteralIndex is_present);
61 
62  // Returns whether or not a interval is optional and the associated literal.
63  bool IsOptional(IntervalVariable i) const {
64  return is_present_[i] != kNoLiteralIndex;
65  }
66  Literal IsPresentLiteral(IntervalVariable i) const {
67  return Literal(is_present_[i]);
68  }
69 
70  // The 3 integer variables associated to a interval.
71  // Fixed size intervals will have a kNoIntegerVariable as size.
72  //
73  // Note: For an optional interval, the start/end variables are propagated
74  // asssuming the interval is present. Because of that, these variables can
75  // cross each other or have an empty domain. If any of this happen, then the
76  // IsPresentLiteral() of this interval will be propagated to false.
77  IntegerVariable SizeVar(IntervalVariable i) const { return size_vars_[i]; }
78  IntegerVariable StartVar(IntervalVariable i) const { return start_vars_[i]; }
79  IntegerVariable EndVar(IntervalVariable i) const { return end_vars_[i]; }
80 
81  // Return the minimum size of the given IntervalVariable.
82  IntegerValue MinSize(IntervalVariable i) const {
83  const IntegerVariable size_var = size_vars_[i];
84  if (size_var == kNoIntegerVariable) return fixed_sizes_[i];
85  return integer_trail_->LowerBound(size_var);
86  }
87 
88  // Return the maximum size of the given IntervalVariable.
89  IntegerValue MaxSize(IntervalVariable i) const {
90  const IntegerVariable size_var = size_vars_[i];
91  if (size_var == kNoIntegerVariable) return fixed_sizes_[i];
92  return integer_trail_->UpperBound(size_var);
93  }
94 
95  // Utility function that returns a vector will all intervals.
96  std::vector<IntervalVariable> AllIntervals() const {
97  std::vector<IntervalVariable> result;
98  for (IntervalVariable i(0); i < NumIntervals(); ++i) {
99  result.push_back(i);
100  }
101  return result;
102  }
103 
104  private:
105  // External classes needed.
106  IntegerTrail* integer_trail_;
107  PrecedencesPropagator* precedences_;
108 
109  // Literal indicating if the tasks is executed. Tasks that are always executed
110  // will have a kNoLiteralIndex entry in this vector.
112 
113  // The integer variables for each tasks.
118 
119  DISALLOW_COPY_AND_ASSIGN(IntervalsRepository);
120 };
121 
122 // An helper struct to sort task by time. This is used by the
123 // SchedulingConstraintHelper but also by many scheduling propagators to sort
124 // tasks.
125 struct TaskTime {
127  IntegerValue time;
128  bool operator<(TaskTime other) const { return time < other.time; }
129  bool operator>(TaskTime other) const { return time > other.time; }
130 };
131 
132 // Helper class shared by the propagators that manage a given list of tasks.
133 //
134 // One of the main advantage of this class is that it allows to share the
135 // vectors of tasks sorted by various criteria between propagator for a faster
136 // code.
138  public:
139  // All the functions below refer to a task by its index t in the tasks
140  // vector given at construction.
141  SchedulingConstraintHelper(const std::vector<IntervalVariable>& tasks,
142  Model* model);
143 
144  // Temporary constructor.
145  // The class will not be usable until ResetFromSubset() is called.
146  //
147  // TODO(user): Remove this. It is a hack because the disjunctive class needs
148  // to fetch the maximum possible number of task at construction.
149  SchedulingConstraintHelper(int num_tasks, Model* model);
150 
151  // Resets the class to the same state as if it was constructed with
152  // the given subset of tasks from other.
154  absl::Span<const int> tasks);
155 
156  // Returns the number of task.
157  int NumTasks() const { return start_vars_.size(); }
158 
159  // Sets the time direction to either forward/backward. This will impact all
160  // the functions below.
161  void SetTimeDirection(bool is_forward);
162 
163  // Helpers for the current bounds on the current task time window.
164  // [ (size-min) ... (size-min) ]
165  // ^ ^ ^ ^
166  // start-min end-min start-max end-max
167  //
168  // Note that for tasks with variable sizes, we don't necessarily have
169  // size-min between the XXX-min and XXX-max value.
170  IntegerValue SizeMin(int t) const;
171  IntegerValue SizeMax(int t) const;
172  IntegerValue StartMin(int t) const;
173  IntegerValue StartMax(int t) const;
174  IntegerValue EndMin(int t) const;
175  IntegerValue EndMax(int t) const;
176 
177  // In the presence of tasks with a variable size, we do not necessarily
178  // have start_min + size_min = end_min, we can instead have a situation
179  // like:
180  // | |<--- size-min --->|
181  // ^ ^ ^
182  // start-min | end-min
183  // |
184  // We define the "shifted start min" to be the right most time such that
185  // we known that we must have min-size "energy" to the right of it if the
186  // task is present. Using it in our scheduling propagators allows to propagate
187  // more in the presence of tasks with variable size (or optional task
188  // where we also do not necessarily have start_min + size_min = end_min.
189  //
190  // To explain this shifted start min, one must use the AddEnergyAfterReason().
191  IntegerValue ShiftedStartMin(int t) const;
192 
193  bool StartIsFixed(int t) const;
194  bool EndIsFixed(int t) const;
195  bool SizeIsFixed(int t) const;
196 
197  // Returns true if the corresponding fact is known for sure. A normal task is
198  // always present. For optional task for which the presence is still unknown,
199  // both of these function will return false.
200  bool IsOptional(int t) const;
201  bool IsPresent(int t) const;
202  bool IsAbsent(int t) const;
203 
204  // Returns a string with the current task bounds.
205  std::string TaskDebugString(int t) const;
206 
207  // Sorts and returns the tasks in corresponding order at the time of the call.
208  // Note that we do not mean strictly-increasing/strictly-decreasing, there
209  // will be duplicate time values in these vectors.
210  //
211  // TODO(user): we could merge the first loop of IncrementalSort() with the
212  // loop that fill TaskTime.time at each call.
213  const std::vector<TaskTime>& TaskByIncreasingStartMin();
214  const std::vector<TaskTime>& TaskByIncreasingEndMin();
215  const std::vector<TaskTime>& TaskByDecreasingStartMax();
216  const std::vector<TaskTime>& TaskByDecreasingEndMax();
217  const std::vector<TaskTime>& TaskByIncreasingShiftedStartMin();
218 
219  // Functions to clear and then set the current reason.
220  void ClearReason();
221  void AddPresenceReason(int t);
222  void AddAbsenceReason(int t);
223  void AddSizeMinReason(int t);
224  void AddSizeMinReason(int t, IntegerValue lower_bound);
225  void AddStartMinReason(int t, IntegerValue lower_bound);
226  void AddStartMaxReason(int t, IntegerValue upper_bound);
227  void AddEndMinReason(int t, IntegerValue lower_bound);
228  void AddEndMaxReason(int t, IntegerValue upper_bound);
229  void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time);
230 
231  // Adds the reason why task "before" must be before task "after".
232  // That is StartMax(before) < EndMin(after).
233  void AddReasonForBeingBefore(int before, int after);
234 
235  // It is also possible to directly manipulates the underlying reason vectors
236  // that will be used when pushing something.
237  std::vector<Literal>* MutableLiteralReason() { return &literal_reason_; }
238  std::vector<IntegerLiteral>* MutableIntegerReason() {
239  return &integer_reason_;
240  }
241 
242  // Push something using the current reason. Note that IncreaseStartMin() will
243  // also increase the end-min, and DecreaseEndMax() will also decrease the
244  // start-max.
245  //
246  // Important: IncreaseStartMin() and DecreaseEndMax() can be called on an
247  // optional interval whose presence is still unknown and push a bound
248  // conditionned on its presence. The functions will do the correct thing
249  // depending on whether or not the start_min/end_max are optional variables
250  // whose presence implies the interval presence.
251  ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_min_start);
252  ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_max_end);
253  ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t);
254  ABSL_MUST_USE_RESULT bool PushTaskPresence(int t);
255  ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit);
256  ABSL_MUST_USE_RESULT bool ReportConflict();
257  ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t,
258  IntegerLiteral lit);
259 
260  // Returns the underlying integer variables.
261  const std::vector<IntegerVariable>& StartVars() const { return start_vars_; }
262  const std::vector<IntegerVariable>& EndVars() const { return end_vars_; }
263  const std::vector<IntegerVariable>& SizeVars() const { return size_vars_; }
264  IntegerVariable SizeVar(int index) const { return size_vars_[index]; }
267  return Literal(reason_for_presence_[index]);
268  }
269 
270  // Registers the given propagator id to be called if any of the tasks
271  // in this class change. Note that we do not watch size max though.
272  void WatchAllTasks(int id, GenericLiteralWatcher* watcher,
273  bool watch_start_max = true,
274  bool watch_end_max = true) const;
275 
276  // Manages the other helper (used by the diffn constraint).
277  //
278  // For each interval appearing in a reason on this helper, another reason
279  // will be added. This other reason specifies that on the other helper, the
280  // corresponding interval overlaps 'event'.
282  IntegerValue event) {
283  CHECK(other_helper != nullptr);
284  other_helper_ = other_helper;
285  event_for_other_helper_ = event;
286  }
287 
288  void ClearOtherHelper() { other_helper_ = nullptr; }
289 
290  // Adds to this helper reason all the explanation of the other helper.
291  // This checks that other_helper_ is null.
292  //
293  // This is used in the 2D energetic reasoning in the diffn constraint.
294  void ImportOtherReasons(const SchedulingConstraintHelper& other_helper);
295 
296  private:
297  void InitSortedVectors();
298 
299  // Internal function for IncreaseStartMin()/DecreaseEndMax().
300  bool PushIntervalBound(int t, IntegerLiteral lit);
301 
302  // This will be called on any interval that is part of a reason or
303  // a bound push. Since the last call to ClearReason(), for each unique
304  // t, we will add once to other_helper_ the reason for t containing
305  // the point event_for_other_helper_.
306  void AddOtherReason(int t);
307 
308  // Import the reasons on the other helper into this helper.
309  void ImportOtherReasons();
310 
311  Trail* trail_;
312  IntegerTrail* integer_trail_;
313  PrecedencesPropagator* precedences_;
314 
315  // The current direction of time, true for forward, false for backward.
316  bool current_time_direction_ = true;
317 
318  // All the underlying variables of the tasks.
319  // The vectors are indexed by the task index t.
320  std::vector<IntegerVariable> start_vars_;
321  std::vector<IntegerVariable> end_vars_;
322  std::vector<IntegerVariable> size_vars_;
323  std::vector<IntegerValue> fixed_sizes_;
324  std::vector<LiteralIndex> reason_for_presence_;
325 
326  // The negation of the start/end variable so that SetTimeDirection()
327  // can do its job in O(1) instead of calling NegationOf() on each entry.
328  std::vector<IntegerVariable> minus_start_vars_;
329  std::vector<IntegerVariable> minus_end_vars_;
330 
331  // Sorted vectors returned by the TasksBy*() functions.
332  std::vector<TaskTime> task_by_increasing_start_min_;
333  std::vector<TaskTime> task_by_increasing_end_min_;
334  std::vector<TaskTime> task_by_decreasing_start_max_;
335  std::vector<TaskTime> task_by_decreasing_end_max_;
336 
337  std::vector<TaskTime> task_by_increasing_shifted_start_min_;
338  std::vector<TaskTime> task_by_negated_shifted_end_max_;
339  int64 shifted_start_min_timestamp_ = -1;
340  int64 negated_shifted_end_max_timestamp_ = -1;
341 
342  // Reason vectors.
343  std::vector<Literal> literal_reason_;
344  std::vector<IntegerLiteral> integer_reason_;
345 
346  // Optional 'slave' helper used in the diffn constraint.
347  SchedulingConstraintHelper* other_helper_ = nullptr;
348  IntegerValue event_for_other_helper_;
349  std::vector<bool> already_added_to_other_reasons_;
350 };
351 
352 // =============================================================================
353 // SchedulingConstraintHelper inlined functions.
354 // =============================================================================
355 
356 inline IntegerValue SchedulingConstraintHelper::SizeMin(int t) const {
357  return size_vars_[t] == kNoIntegerVariable
358  ? fixed_sizes_[t]
359  : integer_trail_->LowerBound(size_vars_[t]);
360 }
361 
362 inline IntegerValue SchedulingConstraintHelper::SizeMax(int t) const {
363  return size_vars_[t] == kNoIntegerVariable
364  ? fixed_sizes_[t]
365  : integer_trail_->UpperBound(size_vars_[t]);
366 }
367 
368 inline bool SchedulingConstraintHelper::SizeIsFixed(int t) const {
369  return size_vars_[t] == kNoIntegerVariable
370  ? true
371  : integer_trail_->IsFixed(size_vars_[t]);
372 }
373 
374 inline IntegerValue SchedulingConstraintHelper::StartMin(int t) const {
375  return integer_trail_->LowerBound(start_vars_[t]);
376 }
377 
378 inline IntegerValue SchedulingConstraintHelper::StartMax(int t) const {
379  return integer_trail_->UpperBound(start_vars_[t]);
380 }
381 
382 inline IntegerValue SchedulingConstraintHelper::EndMin(int t) const {
383  return integer_trail_->LowerBound(end_vars_[t]);
384 }
385 
386 inline IntegerValue SchedulingConstraintHelper::EndMax(int t) const {
387  return integer_trail_->UpperBound(end_vars_[t]);
388 }
389 
390 // for optional interval, we don't necessarily have start + size = end.
391 inline IntegerValue SchedulingConstraintHelper::ShiftedStartMin(int t) const {
392  return std::max(StartMin(t), EndMin(t) - SizeMin(t));
393 }
394 
396  return StartMin(t) == StartMax(t);
397 }
398 
399 inline bool SchedulingConstraintHelper::EndIsFixed(int t) const {
400  return EndMin(t) == EndMax(t);
401 }
402 
403 inline bool SchedulingConstraintHelper::IsOptional(int t) const {
404  return reason_for_presence_[t] != kNoLiteralIndex;
405 }
406 
407 inline bool SchedulingConstraintHelper::IsPresent(int t) const {
408  if (reason_for_presence_[t] == kNoLiteralIndex) return true;
409  return trail_->Assignment().LiteralIsTrue(Literal(reason_for_presence_[t]));
410 }
411 
412 inline bool SchedulingConstraintHelper::IsAbsent(int t) const {
413  if (reason_for_presence_[t] == kNoLiteralIndex) return false;
414  return trail_->Assignment().LiteralIsFalse(Literal(reason_for_presence_[t]));
415 }
416 
418  integer_reason_.clear();
419  literal_reason_.clear();
420  if (other_helper_) {
421  other_helper_->ClearReason();
422  already_added_to_other_reasons_.assign(NumTasks(), false);
423  }
424 }
425 
427  DCHECK(IsPresent(t));
428  AddOtherReason(t);
429  if (reason_for_presence_[t] != kNoLiteralIndex) {
430  literal_reason_.push_back(Literal(reason_for_presence_[t]).Negated());
431  }
432 }
433 
435  DCHECK(IsAbsent(t));
436  AddOtherReason(t);
437  if (reason_for_presence_[t] != kNoLiteralIndex) {
438  literal_reason_.push_back(Literal(reason_for_presence_[t]));
439  }
440 }
441 
443  AddOtherReason(t);
444  if (size_vars_[t] != kNoIntegerVariable) {
445  integer_reason_.push_back(
446  integer_trail_->LowerBoundAsLiteral(size_vars_[t]));
447  }
448 }
449 
451  int t, IntegerValue lower_bound) {
452  AddOtherReason(t);
453  if (size_vars_[t] != kNoIntegerVariable) {
454  DCHECK_GE(SizeMin(t), lower_bound);
455  integer_reason_.push_back(
456  IntegerLiteral::GreaterOrEqual(size_vars_[t], lower_bound));
457  }
458 }
459 
461  int t, IntegerValue lower_bound) {
462  DCHECK_GE(StartMin(t), lower_bound);
463  AddOtherReason(t);
464  integer_reason_.push_back(
465  IntegerLiteral::GreaterOrEqual(start_vars_[t], lower_bound));
466 }
467 
469  int t, IntegerValue upper_bound) {
470  DCHECK_LE(StartMax(t), upper_bound);
471  AddOtherReason(t);
472  integer_reason_.push_back(
473  IntegerLiteral::LowerOrEqual(start_vars_[t], upper_bound));
474 }
475 
477  int t, IntegerValue lower_bound) {
478  AddOtherReason(t);
479  if (EndMin(t) < lower_bound) {
480  // This might happen if we used for the end_min the max between end_min
481  // and start_min + size_min. That is, the end_min assuming the task is
482  // present.
483  const IntegerValue size_min = SizeMin(t);
484  if (size_vars_[t] != kNoIntegerVariable) {
485  integer_reason_.push_back(
486  IntegerLiteral::GreaterOrEqual(size_vars_[t], size_min));
487  }
488  integer_reason_.push_back(
489  IntegerLiteral::GreaterOrEqual(start_vars_[t], lower_bound - size_min));
490  return;
491  }
492  integer_reason_.push_back(
493  IntegerLiteral::GreaterOrEqual(end_vars_[t], lower_bound));
494 }
495 
497  int t, IntegerValue upper_bound) {
498  DCHECK_LE(EndMax(t), upper_bound);
499  AddOtherReason(t);
500  integer_reason_.push_back(
501  IntegerLiteral::LowerOrEqual(end_vars_[t], upper_bound));
502 }
503 
505  int t, IntegerValue energy_min, IntegerValue time) {
506  AddOtherReason(t);
507  if (StartMin(t) >= time) {
508  integer_reason_.push_back(
509  IntegerLiteral::GreaterOrEqual(start_vars_[t], time));
510  } else {
511  integer_reason_.push_back(
512  IntegerLiteral::GreaterOrEqual(end_vars_[t], time + energy_min));
513  }
514  if (size_vars_[t] != kNoIntegerVariable) {
515  integer_reason_.push_back(
516  IntegerLiteral::GreaterOrEqual(size_vars_[t], energy_min));
517  }
518 }
519 
520 // =============================================================================
521 // Model based functions.
522 // =============================================================================
523 
524 inline std::function<IntegerVariable(const Model&)> StartVar(
525  IntervalVariable v) {
526  return [=](const Model& model) {
527  return model.Get<IntervalsRepository>()->StartVar(v);
528  };
529 }
530 
531 inline std::function<IntegerVariable(const Model&)> EndVar(IntervalVariable v) {
532  return [=](const Model& model) {
533  return model.Get<IntervalsRepository>()->EndVar(v);
534  };
535 }
536 
537 inline std::function<IntegerVariable(const Model&)> SizeVar(
538  IntervalVariable v) {
539  return [=](const Model& model) {
540  return model.Get<IntervalsRepository>()->SizeVar(v);
541  };
542 }
543 
544 inline std::function<int64(const Model&)> MinSize(IntervalVariable v) {
545  return [=](const Model& model) {
546  return model.Get<IntervalsRepository>()->MinSize(v).value();
547  };
548 }
549 
550 inline std::function<int64(const Model&)> MaxSize(IntervalVariable v) {
551  return [=](const Model& model) {
552  return model.Get<IntervalsRepository>()->MaxSize(v).value();
553  };
554 }
555 
556 inline std::function<bool(const Model&)> IsOptional(IntervalVariable v) {
557  return [=](const Model& model) {
558  return model.Get<IntervalsRepository>()->IsOptional(v);
559  };
560 }
561 
562 inline std::function<Literal(const Model&)> IsPresentLiteral(
563  IntervalVariable v) {
564  return [=](const Model& model) {
565  return model.Get<IntervalsRepository>()->IsPresentLiteral(v);
566  };
567 }
568 
569 inline std::function<IntervalVariable(Model*)> NewInterval(int64 min_start,
570  int64 max_end,
571  int64 size) {
572  return [=](Model* model) {
573  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
574  model->Add(NewIntegerVariable(min_start, max_end)),
575  model->Add(NewIntegerVariable(min_start, max_end)), kNoIntegerVariable,
576  IntegerValue(size), kNoLiteralIndex);
577  };
578 }
579 
580 inline std::function<IntervalVariable(Model*)> NewInterval(
581  IntegerVariable start, IntegerVariable end, IntegerVariable size) {
582  return [=](Model* model) {
583  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
584  start, end, size, IntegerValue(0), kNoLiteralIndex);
585  };
586 }
587 
588 inline std::function<IntervalVariable(Model*)> NewIntervalWithVariableSize(
589  int64 min_start, int64 max_end, int64 min_size, int64 max_size) {
590  return [=](Model* model) {
591  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
592  model->Add(NewIntegerVariable(min_start, max_end)),
593  model->Add(NewIntegerVariable(min_start, max_end)),
594  model->Add(NewIntegerVariable(min_size, max_size)), IntegerValue(0),
596  };
597 }
598 
599 inline std::function<IntervalVariable(Model*)> NewOptionalInterval(
600  int64 min_start, int64 max_end, int64 size, Literal is_present) {
601  return [=](Model* model) {
602  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
603  model->Add(NewIntegerVariable(min_start, max_end)),
604  model->Add(NewIntegerVariable(min_start, max_end)), kNoIntegerVariable,
605  IntegerValue(size), is_present.Index());
606  };
607 }
608 
609 inline std::function<IntervalVariable(Model*)>
611  int64 size, Literal is_present) {
612  return [=](Model* model) {
613  // Note that we need to mark the optionality first.
614  const IntegerVariable start =
615  model->Add(NewIntegerVariable(min_start, max_end));
616  const IntegerVariable end =
617  model->Add(NewIntegerVariable(min_start, max_end));
618  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
619  integer_trail->MarkIntegerVariableAsOptional(start, is_present);
620  integer_trail->MarkIntegerVariableAsOptional(end, is_present);
621  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
622  start, end, kNoIntegerVariable, IntegerValue(size), is_present.Index());
623  };
624 }
625 
626 inline std::function<IntervalVariable(Model*)> NewOptionalInterval(
627  IntegerVariable start, IntegerVariable end, IntegerVariable size,
628  Literal is_present) {
629  return [=](Model* model) {
630  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
631  start, end, size, IntegerValue(0), is_present.Index());
632  };
633 }
634 
635 inline std::function<IntervalVariable(Model*)>
637  int64 min_size, int64 max_size,
638  Literal is_present) {
639  return [=](Model* model) {
640  return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
641  model->Add(NewIntegerVariable(min_start, max_end)),
642  model->Add(NewIntegerVariable(min_start, max_end)),
643  model->Add(NewIntegerVariable(min_size, max_size)), IntegerValue(0),
644  is_present.Index());
645  };
646 }
647 
648 // This requires that all the alternatives are optional tasks.
649 inline std::function<void(Model*)> IntervalWithAlternatives(
650  IntervalVariable master, const std::vector<IntervalVariable>& members) {
651  return [=](Model* model) {
652  IntervalsRepository* intervals = model->GetOrCreate<IntervalsRepository>();
653 
654  std::vector<Literal> presences;
655  std::vector<IntegerValue> sizes;
656 
657  // Create an "exactly one executed" constraint on the alternatives.
658  std::vector<LiteralWithCoeff> sat_ct;
659  for (const IntervalVariable member : members) {
660  CHECK(intervals->IsOptional(member));
661  const Literal is_present = intervals->IsPresentLiteral(member);
662  sat_ct.push_back({is_present, Coefficient(1)});
663  model->Add(
664  Equality(model->Get(StartVar(master)), model->Get(StartVar(member))));
665  model->Add(
666  Equality(model->Get(EndVar(master)), model->Get(EndVar(member))));
667 
668  // TODO(user): IsOneOf() only work for members with fixed size.
669  // Generalize to an "int_var_element" constraint.
670  CHECK_EQ(intervals->SizeVar(member), kNoIntegerVariable);
671  presences.push_back(is_present);
672  sizes.push_back(intervals->MinSize(member));
673  }
674  if (intervals->SizeVar(master) != kNoIntegerVariable) {
675  model->Add(IsOneOf(intervals->SizeVar(master), presences, sizes));
676  }
677  model->Add(BooleanLinearConstraint(1, 1, &sat_ct));
678 
679  // Propagate from the candidate bounds to the master interval ones.
680  {
681  std::vector<IntegerVariable> starts;
682  starts.reserve(members.size());
683  for (const IntervalVariable member : members) {
684  starts.push_back(intervals->StartVar(member));
685  }
686  model->Add(
687  PartialIsOneOfVar(intervals->StartVar(master), starts, presences));
688  }
689  {
690  std::vector<IntegerVariable> ends;
691  ends.reserve(members.size());
692  for (const IntervalVariable member : members) {
693  ends.push_back(intervals->EndVar(member));
694  }
695  model->Add(PartialIsOneOfVar(intervals->EndVar(master), ends, presences));
696  }
697  };
698 }
699 
700 } // namespace sat
701 } // namespace operations_research
702 
703 #endif // OR_TOOLS_SAT_INTERVALS_H_
operations_research::sat::IntervalsRepository::CreateInterval
IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present)
Definition: intervals.cc:24
operations_research::sat::SchedulingConstraintHelper::StartMin
IntegerValue StartMin(int t) const
Definition: intervals.h:374
operations_research::sat::SchedulingConstraintHelper::AddSizeMinReason
void AddSizeMinReason(int t)
Definition: intervals.h:442
integral_types.h
operations_research::sat::IntegerTrail
Definition: integer.h:518
operations_research::sat::SchedulingConstraintHelper::MutableLiteralReason
std::vector< Literal > * MutableLiteralReason()
Definition: intervals.h:237
operations_research::sat::kNoIntegerVariable
const IntegerVariable kNoIntegerVariable(-1)
operations_research::sat::SchedulingConstraintHelper::SizeMax
IntegerValue SizeMax(int t) const
Definition: intervals.h:362
max
int64 max
Definition: alldiff_cst.cc:139
operations_research::sat::SchedulingConstraintHelper::TaskByIncreasingShiftedStartMin
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
Definition: intervals.cc:206
operations_research::sat::SchedulingConstraintHelper::IncreaseStartMin
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_min_start)
Definition: intervals.cc:311
operations_research::sat::SchedulingConstraintHelper::EndIsFixed
bool EndIsFixed(int t) const
Definition: intervals.h:399
operations_research::sat::kNoLiteralIndex
const LiteralIndex kNoLiteralIndex(-1)
operations_research::sat::SchedulingConstraintHelper::WatchAllTasks
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
Definition: intervals.cc:360
operations_research::sat::SizeVar
std::function< IntegerVariable(const Model &)> SizeVar(IntervalVariable v)
Definition: intervals.h:537
operations_research::sat::SchedulingConstraintHelper::EndMin
IntegerValue EndMin(int t) const
Definition: intervals.h:382
operations_research::sat::SchedulingConstraintHelper::PresenceLiteral
Literal PresenceLiteral(int index) const
Definition: intervals.h:265
operations_research::sat::IntervalsRepository::IntervalsRepository
IntervalsRepository(Model *model)
Definition: intervals.h:47
gtl::ITIVector< IntervalVariable, LiteralIndex >
operations_research::sat::IsPresentLiteral
std::function< Literal(const Model &)> IsPresentLiteral(IntervalVariable v)
Definition: intervals.h:562
logging.h
operations_research::sat::SchedulingConstraintHelper::SetOtherHelper
void SetOtherHelper(SchedulingConstraintHelper *other_helper, IntegerValue event)
Definition: intervals.h:281
operations_research::sat::StartVar
std::function< IntegerVariable(const Model &)> StartVar(IntervalVariable v)
Definition: intervals.h:524
operations_research::sat::TaskTime::operator>
bool operator>(TaskTime other) const
Definition: intervals.h:129
operations_research::sat::IntervalsRepository::EndVar
IntegerVariable EndVar(IntervalVariable i) const
Definition: intervals.h:79
model.h
operations_research::sat::SchedulingConstraintHelper::IsOptional
bool IsOptional(int t) const
Definition: intervals.h:403
operations_research::sat::SchedulingConstraintHelper::SetTimeDirection
void SetTimeDirection(bool is_forward)
Definition: intervals.cc:143
operations_research::sat::SchedulingConstraintHelper::TaskByDecreasingEndMax
const std::vector< TaskTime > & TaskByDecreasingEndMax()
Definition: intervals.cc:194
macros.h
operations_research::sat::IntervalsRepository::IsPresentLiteral
Literal IsPresentLiteral(IntervalVariable i) const
Definition: intervals.h:66
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::sat::SchedulingConstraintHelper::AddEnergyAfterReason
void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time)
Definition: intervals.h:504
operations_research::sat::VariablesAssignment::LiteralIsTrue
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:150
operations_research::sat::NewOptionalIntervalWithOptionalVariables
std::function< IntervalVariable(Model *)> NewOptionalIntervalWithOptionalVariables(int64 min_start, int64 max_end, int64 size, Literal is_present)
Definition: intervals.h:610
operations_research::sat::MinSize
std::function< int64(const Model &)> MinSize(IntervalVariable v)
Definition: intervals.h:544
operations_research::sat::SchedulingConstraintHelper::EndMax
IntegerValue EndMax(int t) const
Definition: intervals.h:386
operations_research::sat::IntegerLiteral::GreaterOrEqual
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1216
operations_research::sat::SchedulingConstraintHelper::AddStartMinReason
void AddStartMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:460
operations_research::sat::SchedulingConstraintHelper::TaskByDecreasingStartMax
const std::vector< TaskTime > & TaskByDecreasingStartMax()
Definition: intervals.cc:181
int64
int64_t int64
Definition: integral_types.h:34
sat_solver.h
index
int index
Definition: pack.cc:508
sat_base.h
int32
int int32
Definition: integral_types.h:33
operations_research::sat::SchedulingConstraintHelper::TaskByIncreasingStartMin
const std::vector< TaskTime > & TaskByIncreasingStartMin()
Definition: intervals.cc:157
operations_research::sat::DEFINE_INT_TYPE
DEFINE_INT_TYPE(ClauseIndex, int)
operations_research::sat::SchedulingConstraintHelper::ShiftedStartMin
IntegerValue ShiftedStartMin(int t) const
Definition: intervals.h:391
pb_constraint.h
operations_research::sat::IntegerTrail::MarkIntegerVariableAsOptional
void MarkIntegerVariableAsOptional(IntegerVariable i, Literal is_considered)
Definition: integer.h:617
operations_research::sat::GenericLiteralWatcher
Definition: integer.h:1075
operations_research::sat::IntervalsRepository::MaxSize
IntegerValue MaxSize(IntervalVariable i) const
Definition: intervals.h:89
operations_research::sat::SchedulingConstraintHelper::SizeIsFixed
bool SizeIsFixed(int t) const
Definition: intervals.h:368
operations_research::sat::MaxSize
std::function< int64(const Model &)> MaxSize(IntervalVariable v)
Definition: intervals.h:550
operations_research::sat::SchedulingConstraintHelper::SizeVar
IntegerVariable SizeVar(int index) const
Definition: intervals.h:264
operations_research::sat::BooleanLinearConstraint
std::function< void(Model *)> BooleanLinearConstraint(int64 lower_bound, int64 upper_bound, std::vector< LiteralWithCoeff > *cst)
Definition: sat_solver.h:847
operations_research::sat::SchedulingConstraintHelper::MutableIntegerReason
std::vector< IntegerLiteral > * MutableIntegerReason()
Definition: intervals.h:238
operations_research::sat::SchedulingConstraintHelper::ClearReason
void ClearReason()
Definition: intervals.h:417
operations_research::sat::NewIntegerVariable
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64 lb, int64 ub)
Definition: integer.h:1353
operations_research::sat::TaskTime
Definition: intervals.h:125
operations_research::sat::SchedulingConstraintHelper::ReportConflict
ABSL_MUST_USE_RESULT bool ReportConflict()
Definition: intervals.cc:355
operations_research::sat::IntervalWithAlternatives
std::function< void(Model *)> IntervalWithAlternatives(IntervalVariable master, const std::vector< IntervalVariable > &members)
Definition: intervals.h:649
operations_research::sat::SchedulingConstraintHelper
Definition: intervals.h:137
operations_research::sat::TaskTime::time
IntegerValue time
Definition: intervals.h:127
operations_research::sat::IntegerTrail::UpperBound
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1240
operations_research::sat::IntervalsRepository::NumIntervals
int NumIntervals() const
Definition: intervals.h:53
operations_research::sat::SchedulingConstraintHelper::StartMax
IntegerValue StartMax(int t) const
Definition: intervals.h:378
operations_research::sat::PrecedencesPropagator
Definition: precedences.h:51
int_type.h
operations_research::sat::NewOptionalIntervalWithVariableSize
std::function< IntervalVariable(Model *)> NewOptionalIntervalWithVariableSize(int64 min_start, int64 max_end, int64 min_size, int64 max_size, Literal is_present)
Definition: intervals.h:636
precedences.h
operations_research::sat::IsOneOf
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
Definition: integer_expr.cc:875
integer_expr.h
operations_research::sat::Trail::Assignment
const VariablesAssignment & Assignment() const
Definition: sat_base.h:380
operations_research::sat::IntervalsRepository::MinSize
IntegerValue MinSize(IntervalVariable i) const
Definition: intervals.h:82
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
operations_research::sat::SchedulingConstraintHelper::DecreaseEndMax
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_max_end)
Definition: intervals.cc:317
int_type_indexed_vector.h
operations_research::sat::PartialIsOneOfVar
std::function< void(Model *)> PartialIsOneOfVar(IntegerVariable target_var, const std::vector< IntegerVariable > &vars, const std::vector< Literal > &selectors)
Definition: cp_constraints.h:159
operations_research::sat::SchedulingConstraintHelper::IsAbsent
bool IsAbsent(int t) const
Definition: intervals.h:412
operations_research::sat::Literal::Index
LiteralIndex Index() const
Definition: sat_base.h:84
operations_research::sat::SchedulingConstraintHelper::AddAbsenceReason
void AddAbsenceReason(int t)
Definition: intervals.h:434
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
operations_research::sat::SchedulingConstraintHelper::PushTaskPresence
ABSL_MUST_USE_RESULT bool PushTaskPresence(int t)
Definition: intervals.cc:339
operations_research::sat::SchedulingConstraintHelper::NumTasks
int NumTasks() const
Definition: intervals.h:157
operations_research::sat::IntegerTrail::LowerBoundAsLiteral
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
Definition: integer.h:1266
operations_research::sat::SchedulingConstraintHelper::SizeVars
const std::vector< IntegerVariable > & SizeVars() const
Definition: intervals.h:263
operations_research::sat::SchedulingConstraintHelper::AddReasonForBeingBefore
void AddReasonForBeingBefore(int before, int after)
Definition: intervals.cc:227
operations_research::sat::IntegerLiteral
Definition: integer.h:153
operations_research::sat::IntervalsRepository::IsOptional
bool IsOptional(IntervalVariable i) const
Definition: intervals.h:63
cp_constraints.h
DCHECK
#define DCHECK(condition)
Definition: base/logging.h:884
operations_research::sat::SchedulingConstraintHelper::AddStartMaxReason
void AddStartMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:468
operations_research::sat::IntegerLiteral::LowerOrEqual
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1222
operations_research::sat::NewInterval
std::function< IntervalVariable(Model *)> NewInterval(int64 min_start, int64 max_end, int64 size)
Definition: intervals.h:569
operations_research::sat::SchedulingConstraintHelper::SchedulingConstraintHelper
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
Definition: intervals.cc:53
gtl::ITIVector::size
size_type size() const
Definition: int_type_indexed_vector.h:146
operations_research::sat::NewIntervalWithVariableSize
std::function< IntervalVariable(Model *)> NewIntervalWithVariableSize(int64 min_start, int64 max_end, int64 min_size, int64 max_size)
Definition: intervals.h:588
DCHECK_GE
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:889
model
GRBmodel * model
Definition: gurobi_interface.cc:269
operations_research::sat::Literal
Definition: sat_base.h:64
operations_research::sat::SchedulingConstraintHelper::ResetFromSubset
void ResetFromSubset(const SchedulingConstraintHelper &other, absl::Span< const int > tasks)
Definition: intervals.cc:97
operations_research::sat::SchedulingConstraintHelper::EndVars
const std::vector< IntegerVariable > & EndVars() const
Definition: intervals.h:262
operations_research::sat::SchedulingConstraintHelper::SizeMin
IntegerValue SizeMin(int t) const
Definition: intervals.h:356
operations_research::sat::IntervalsRepository::SizeVar
IntegerVariable SizeVar(IntervalVariable i) const
Definition: intervals.h:77
operations_research::sat::SchedulingConstraintHelper::StartVars
const std::vector< IntegerVariable > & StartVars() const
Definition: intervals.h:261
operations_research::sat::IsOptional
std::function< bool(const Model &)> IsOptional(IntervalVariable v)
Definition: intervals.h:556
operations_research::sat::SchedulingConstraintHelper::ClearOtherHelper
void ClearOtherHelper()
Definition: intervals.h:288
operations_research::sat::SchedulingConstraintHelper::IsPresent
bool IsPresent(int t) const
Definition: intervals.h:407
operations_research::sat::TaskTime::operator<
bool operator<(TaskTime other) const
Definition: intervals.h:128
operations_research::sat::IntervalsRepository
Definition: intervals.h:45
operations_research::sat::TaskTime::task_index
int task_index
Definition: intervals.h:126
operations_research::sat::SchedulingConstraintHelper::StartIsFixed
bool StartIsFixed(int t) const
Definition: intervals.h:395
operations_research::sat::IntervalsRepository::StartVar
IntegerVariable StartVar(IntervalVariable i) const
Definition: intervals.h:78
operations_research::sat::IntervalsRepository::AllIntervals
std::vector< IntervalVariable > AllIntervals() const
Definition: intervals.h:96
operations_research::sat::IntegerTrail::IsFixed
bool IsFixed(IntegerVariable i) const
Definition: integer.h:1244
operations_research::sat::SchedulingConstraintHelper::TaskDebugString
std::string TaskDebugString(int t) const
Definition: intervals.cc:404
operations_research::sat::SchedulingConstraintHelper::AddEndMinReason
void AddEndMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:476
operations_research::sat::Equality
std::function< void(Model *)> Equality(IntegerVariable v, int64 value)
Definition: integer.h:1451
operations_research::sat::SchedulingConstraintHelper::PushTaskAbsence
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
Definition: intervals.cc:323
operations_research::sat::IntegerTrail::LowerBound
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1236
DCHECK_LE
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:887
operations_research::sat::NewOptionalInterval
std::function< IntervalVariable(Model *)> NewOptionalInterval(int64 min_start, int64 max_end, int64 size, Literal is_present)
Definition: intervals.h:599
operations_research::sat::SchedulingConstraintHelper::TaskByIncreasingEndMin
const std::vector< TaskTime > & TaskByIncreasingEndMin()
Definition: intervals.cc:169
operations_research::sat::SchedulingConstraintHelper::AddEndMaxReason
void AddEndMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:496
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
integer.h
operations_research::sat::VariablesAssignment::LiteralIsFalse
bool LiteralIsFalse(Literal literal) const
Definition: sat_base.h:147
operations_research::sat::Trail
Definition: sat_base.h:233
operations_research::sat::EndVar
std::function< IntegerVariable(const Model &)> EndVar(IntervalVariable v)
Definition: intervals.h:531
operations_research::sat::kNoIntervalVariable
const IntervalVariable kNoIntervalVariable(-1)
time
int64 time
Definition: resource.cc:1683
operations_research::sat::SchedulingConstraintHelper::AddPresenceReason
void AddPresenceReason(int t)
Definition: intervals.h:426
operations_research::sat::SchedulingConstraintHelper::PushIntegerLiteral
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
Definition: intervals.cc:267
operations_research::sat::SchedulingConstraintHelper::PushIntegerLiteralIfTaskPresent
ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t, IntegerLiteral lit)
Definition: intervals.cc:272