OR-Tools  9.1
intervals.cc
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 #include "ortools/sat/intervals.h"
15 
16 #include <algorithm>
17 #include <memory>
18 #include <string>
19 
20 #include "ortools/sat/integer.h"
21 #include "ortools/util/sort.h"
22 
23 namespace operations_research {
24 namespace sat {
25 
26 IntervalVariable IntervalsRepository::CreateInterval(IntegerVariable start,
27  IntegerVariable end,
28  IntegerVariable size,
29  IntegerValue fixed_size,
30  LiteralIndex is_present) {
32  size == kNoIntegerVariable
33  ? AffineExpression(fixed_size)
34  : AffineExpression(size),
35  is_present, /*add_linear_relation=*/true);
36 }
37 
39  AffineExpression end,
40  AffineExpression size,
41  LiteralIndex is_present,
42  bool add_linear_relation) {
43  // Create the interval.
44  const IntervalVariable i(starts_.size());
45  starts_.push_back(start);
46  ends_.push_back(end);
47  sizes_.push_back(size);
48  is_present_.push_back(is_present);
49 
50  std::vector<Literal> enforcement_literals;
51  if (is_present != kNoLiteralIndex) {
52  enforcement_literals.push_back(Literal(is_present));
53  }
54 
55  if (add_linear_relation) {
56  LinearConstraintBuilder builder(model_, IntegerValue(0), IntegerValue(0));
57  builder.AddTerm(Start(i), IntegerValue(1));
58  builder.AddTerm(Size(i), IntegerValue(1));
59  builder.AddTerm(End(i), IntegerValue(-1));
60  LoadConditionalLinearConstraint(enforcement_literals, builder.Build(),
61  model_);
62  }
63 
64  return i;
65 }
66 
68  const std::vector<IntervalVariable>& tasks, Model* model)
69  : trail_(model->GetOrCreate<Trail>()),
70  integer_trail_(model->GetOrCreate<IntegerTrail>()),
71  precedences_(model->GetOrCreate<PrecedencesPropagator>()) {
72  starts_.clear();
73  ends_.clear();
74  minus_ends_.clear();
75  minus_starts_.clear();
76  sizes_.clear();
77  reason_for_presence_.clear();
78 
79  auto* repository = model->GetOrCreate<IntervalsRepository>();
80  for (const IntervalVariable i : tasks) {
81  if (repository->IsOptional(i)) {
82  reason_for_presence_.push_back(repository->PresenceLiteral(i).Index());
83  } else {
84  reason_for_presence_.push_back(kNoLiteralIndex);
85  }
86  sizes_.push_back(repository->Size(i));
87  starts_.push_back(repository->Start(i));
88  ends_.push_back(repository->End(i));
89  minus_starts_.push_back(repository->Start(i).Negated());
90  minus_ends_.push_back(repository->End(i).Negated());
91  }
92 
93  RegisterWith(model->GetOrCreate<GenericLiteralWatcher>());
94  InitSortedVectors();
95  if (!SynchronizeAndSetTimeDirection(true)) {
96  model->GetOrCreate<SatSolver>()->NotifyThatModelIsUnsat();
97  }
98 }
99 
101  Model* model)
102  : trail_(model->GetOrCreate<Trail>()),
103  integer_trail_(model->GetOrCreate<IntegerTrail>()),
104  precedences_(model->GetOrCreate<PrecedencesPropagator>()) {
105  starts_.resize(num_tasks);
106  CHECK_EQ(NumTasks(), num_tasks);
107 }
108 
110  recompute_all_cache_ = true;
111  return true;
112 }
113 
115  const std::vector<int>& watch_indices) {
116  for (const int t : watch_indices) recompute_cache_[t] = true;
117  return true;
118 }
119 
121  // If there was an Untrail before, we need to refresh the cache so that
122  // we never have value from lower in the search tree.
123  //
124  // TODO(user): We could be smarter here, but then this is not visible in our
125  // cpu_profile since we call many times IncrementalPropagate() for each new
126  // decision, but just call Propagate() once after each Untrail().
127  if (level < previous_level_) {
128  recompute_all_cache_ = true;
129  }
130  previous_level_ = level;
131 }
132 
134  const int id = watcher->Register(this);
135  const int num_tasks = starts_.size();
136  for (int t = 0; t < num_tasks; ++t) {
137  watcher->WatchIntegerVariable(sizes_[t].var, id, t);
138  watcher->WatchIntegerVariable(starts_[t].var, id, t);
139  watcher->WatchIntegerVariable(ends_[t].var, id, t);
140  }
141  watcher->SetPropagatorPriority(id, 0);
142 
143  // Note that it is important to register with the integer_trail_ so we are
144  // ALWAYS called before any propagator that depends on this helper.
145  integer_trail_->RegisterReversibleClass(this);
146 }
147 
148 bool SchedulingConstraintHelper::UpdateCachedValues(int t) {
149  recompute_cache_[t] = false;
150  if (IsAbsent(t)) return true;
151 
152  IntegerValue smin = integer_trail_->LowerBound(starts_[t]);
153  IntegerValue smax = integer_trail_->UpperBound(starts_[t]);
154  IntegerValue emin = integer_trail_->LowerBound(ends_[t]);
155  IntegerValue emax = integer_trail_->UpperBound(ends_[t]);
156 
157  // We take the max for the corner case where the size of an optional interval
158  // is used elsewhere and has a domain with negative value.
159  //
160  // TODO(user): maybe we should just disallow size with a negative domain, but
161  // is is harder to enforce if we have a linear expression for size.
162  IntegerValue dmin =
163  std::max(IntegerValue(0), integer_trail_->LowerBound(sizes_[t]));
164  IntegerValue dmax = integer_trail_->UpperBound(sizes_[t]);
165 
166  // Detect first if we have a conflict using the relation start + size = end.
167  if (dmax < 0) {
168  AddSizeMaxReason(t, dmax);
169  return PushTaskAbsence(t);
170  }
171  if (smin + dmin - emax > 0) {
172  ClearReason();
173  AddStartMinReason(t, smin);
174  AddSizeMinReason(t, dmin);
175  AddEndMaxReason(t, emax);
176  return PushTaskAbsence(t);
177  }
178  if (smax + dmax - emin < 0) {
179  ClearReason();
180  AddStartMaxReason(t, smax);
181  AddSizeMaxReason(t, dmax);
182  AddEndMinReason(t, emin);
183  return PushTaskAbsence(t);
184  }
185 
186  // Sometimes, for optional interval with non-optional bounds, this propagation
187  // give tighter bounds. We always consider the value assuming
188  // the interval is present.
189  //
190  // Note that this is also useful in case not everything was propagated. Note
191  // also that since there is no conflict, we reach the fix point in one pass.
192  smin = std::max(smin, emin - dmax);
193  smax = std::min(smax, emax - dmin);
194  dmin = std::max(dmin, emin - smax);
195  emin = std::max(emin, smin + dmin);
196  emax = std::min(emax, smax + dmax);
197 
198  cached_start_min_[t] = smin;
199  cached_end_min_[t] = emin;
200  cached_negated_start_max_[t] = -smax;
201  cached_negated_end_max_[t] = -emax;
202  cached_size_min_[t] = dmin;
203 
204  // Note that we use the cached value here for EndMin()/StartMax().
205  const IntegerValue new_shifted_start_min = EndMin(t) - dmin;
206  if (new_shifted_start_min != cached_shifted_start_min_[t]) {
207  recompute_shifted_start_min_ = true;
208  cached_shifted_start_min_[t] = new_shifted_start_min;
209  }
210  const IntegerValue new_negated_shifted_end_max = -(StartMax(t) + dmin);
211  if (new_negated_shifted_end_max != cached_negated_shifted_end_max_[t]) {
212  recompute_negated_shifted_end_max_ = true;
213  cached_negated_shifted_end_max_[t] = new_negated_shifted_end_max;
214  }
215  return true;
216 }
217 
219  const SchedulingConstraintHelper& other, absl::Span<const int> tasks) {
220  current_time_direction_ = other.current_time_direction_;
221 
222  const int num_tasks = tasks.size();
223  starts_.resize(num_tasks);
224  ends_.resize(num_tasks);
225  minus_ends_.resize(num_tasks);
226  minus_starts_.resize(num_tasks);
227  sizes_.resize(num_tasks);
228  reason_for_presence_.resize(num_tasks);
229  for (int i = 0; i < num_tasks; ++i) {
230  const int t = tasks[i];
231  starts_[i] = other.starts_[t];
232  ends_[i] = other.ends_[t];
233  minus_ends_[i] = other.minus_ends_[t];
234  minus_starts_[i] = other.minus_starts_[t];
235  sizes_[i] = other.sizes_[t];
236  reason_for_presence_[i] = other.reason_for_presence_[t];
237  }
238 
239  InitSortedVectors();
240  return SynchronizeAndSetTimeDirection(true);
241 }
242 
243 void SchedulingConstraintHelper::InitSortedVectors() {
244  const int num_tasks = starts_.size();
245 
246  recompute_all_cache_ = true;
247  recompute_cache_.resize(num_tasks, true);
248 
249  cached_shifted_start_min_.resize(num_tasks);
250  cached_negated_shifted_end_max_.resize(num_tasks);
251  cached_size_min_.resize(num_tasks);
252  cached_start_min_.resize(num_tasks);
253  cached_end_min_.resize(num_tasks);
254  cached_negated_start_max_.resize(num_tasks);
255  cached_negated_end_max_.resize(num_tasks);
256 
257  task_by_increasing_start_min_.resize(num_tasks);
258  task_by_increasing_end_min_.resize(num_tasks);
259  task_by_decreasing_start_max_.resize(num_tasks);
260  task_by_decreasing_end_max_.resize(num_tasks);
261  task_by_increasing_shifted_start_min_.resize(num_tasks);
262  task_by_negated_shifted_end_max_.resize(num_tasks);
263  for (int t = 0; t < num_tasks; ++t) {
264  task_by_increasing_start_min_[t].task_index = t;
265  task_by_increasing_end_min_[t].task_index = t;
266  task_by_decreasing_start_max_[t].task_index = t;
267  task_by_decreasing_end_max_[t].task_index = t;
268  task_by_increasing_shifted_start_min_[t].task_index = t;
269  task_by_negated_shifted_end_max_[t].task_index = t;
270  }
271 
272  recompute_shifted_start_min_ = true;
273  recompute_negated_shifted_end_max_ = true;
274 }
275 
277  if (current_time_direction_ != is_forward) {
278  current_time_direction_ = is_forward;
279 
280  std::swap(starts_, minus_ends_);
281  std::swap(ends_, minus_starts_);
282 
283  std::swap(task_by_increasing_start_min_, task_by_decreasing_end_max_);
284  std::swap(task_by_increasing_end_min_, task_by_decreasing_start_max_);
285  std::swap(task_by_increasing_shifted_start_min_,
286  task_by_negated_shifted_end_max_);
287 
288  std::swap(cached_start_min_, cached_negated_end_max_);
289  std::swap(cached_end_min_, cached_negated_start_max_);
290  std::swap(cached_shifted_start_min_, cached_negated_shifted_end_max_);
291  std::swap(recompute_shifted_start_min_, recompute_negated_shifted_end_max_);
292  }
293 }
294 
296  bool is_forward) {
297  SetTimeDirection(is_forward);
298  if (recompute_all_cache_) {
299  for (int t = 0; t < recompute_cache_.size(); ++t) {
300  if (!UpdateCachedValues(t)) return false;
301  }
302  } else {
303  for (int t = 0; t < recompute_cache_.size(); ++t) {
304  if (recompute_cache_[t])
305  if (!UpdateCachedValues(t)) return false;
306  }
307  }
308  recompute_all_cache_ = false;
309  return true;
310 }
311 
312 const std::vector<TaskTime>&
314  const int num_tasks = NumTasks();
315  for (int i = 0; i < num_tasks; ++i) {
316  TaskTime& ref = task_by_increasing_start_min_[i];
317  ref.time = StartMin(ref.task_index);
318  }
319  IncrementalSort(task_by_increasing_start_min_.begin(),
320  task_by_increasing_start_min_.end());
321  return task_by_increasing_start_min_;
322 }
323 
324 const std::vector<TaskTime>&
326  const int num_tasks = NumTasks();
327  for (int i = 0; i < num_tasks; ++i) {
328  TaskTime& ref = task_by_increasing_end_min_[i];
329  ref.time = EndMin(ref.task_index);
330  }
331  IncrementalSort(task_by_increasing_end_min_.begin(),
332  task_by_increasing_end_min_.end());
333  return task_by_increasing_end_min_;
334 }
335 
336 const std::vector<TaskTime>&
338  const int num_tasks = NumTasks();
339  for (int i = 0; i < num_tasks; ++i) {
340  TaskTime& ref = task_by_decreasing_start_max_[i];
341  ref.time = StartMax(ref.task_index);
342  }
343  IncrementalSort(task_by_decreasing_start_max_.begin(),
344  task_by_decreasing_start_max_.end(),
345  std::greater<TaskTime>());
346  return task_by_decreasing_start_max_;
347 }
348 
349 const std::vector<TaskTime>&
351  const int num_tasks = NumTasks();
352  for (int i = 0; i < num_tasks; ++i) {
353  TaskTime& ref = task_by_decreasing_end_max_[i];
354  ref.time = EndMax(ref.task_index);
355  }
356  IncrementalSort(task_by_decreasing_end_max_.begin(),
357  task_by_decreasing_end_max_.end(), std::greater<TaskTime>());
358  return task_by_decreasing_end_max_;
359 }
360 
361 const std::vector<TaskTime>&
363  if (recompute_shifted_start_min_) {
364  recompute_shifted_start_min_ = false;
365  const int num_tasks = NumTasks();
366  bool is_sorted = true;
367  IntegerValue previous = kMinIntegerValue;
368  for (int i = 0; i < num_tasks; ++i) {
369  TaskTime& ref = task_by_increasing_shifted_start_min_[i];
370  ref.time = ShiftedStartMin(ref.task_index);
371  is_sorted = is_sorted && ref.time >= previous;
372  previous = ref.time;
373  }
374  if (is_sorted) return task_by_increasing_shifted_start_min_;
375  IncrementalSort(task_by_increasing_shifted_start_min_.begin(),
376  task_by_increasing_shifted_start_min_.end());
377  }
378  return task_by_increasing_shifted_start_min_;
379 }
380 
381 // Produces a relaxed reason for StartMax(before) < EndMin(after).
383  int after) {
384  AddOtherReason(before);
385  AddOtherReason(after);
386 
387  std::vector<IntegerVariable> vars;
388 
389  // Reason for StartMax(before).
390  const IntegerValue smax_before = StartMax(before);
391  if (smax_before >= integer_trail_->UpperBound(starts_[before])) {
392  if (starts_[before].var != kNoIntegerVariable) {
393  vars.push_back(NegationOf(starts_[before].var));
394  }
395  } else {
396  if (ends_[before].var != kNoIntegerVariable) {
397  vars.push_back(NegationOf(ends_[before].var));
398  }
399  if (sizes_[before].var != kNoIntegerVariable) {
400  vars.push_back(sizes_[before].var);
401  }
402  }
403 
404  // Reason for EndMin(after);
405  const IntegerValue emin_after = EndMin(after);
406  if (emin_after <= integer_trail_->LowerBound(ends_[after])) {
407  if (ends_[after].var != kNoIntegerVariable) {
408  vars.push_back(ends_[after].var);
409  }
410  } else {
411  if (starts_[after].var != kNoIntegerVariable) {
412  vars.push_back(starts_[after].var);
413  }
414  if (sizes_[after].var != kNoIntegerVariable) {
415  vars.push_back(sizes_[after].var);
416  }
417  }
418 
419  DCHECK_LT(smax_before, emin_after);
420  const IntegerValue slack = emin_after - smax_before - 1;
421  integer_trail_->AppendRelaxedLinearReason(
422  slack, std::vector<IntegerValue>(vars.size(), IntegerValue(1)), vars,
423  &integer_reason_);
424 }
425 
427  CHECK(other_helper_ == nullptr);
428  return integer_trail_->Enqueue(lit, literal_reason_, integer_reason_);
429 }
430 
432  int t, IntegerLiteral lit) {
433  if (IsAbsent(t)) return true;
434  AddOtherReason(t);
436  if (IsOptional(t)) {
437  return integer_trail_->ConditionalEnqueue(
438  PresenceLiteral(t), lit, &literal_reason_, &integer_reason_);
439  }
440  return integer_trail_->Enqueue(lit, literal_reason_, integer_reason_);
441 }
442 
443 // We also run directly the precedence propagator for this variable so that when
444 // we push an interval start for example, we have a chance to push its end.
445 bool SchedulingConstraintHelper::PushIntervalBound(int t, IntegerLiteral lit) {
446  if (!PushIntegerLiteralIfTaskPresent(t, lit)) return false;
447  if (IsAbsent(t)) return true;
448  if (!precedences_->PropagateOutgoingArcs(lit.var)) return false;
449  if (!UpdateCachedValues(t)) return false;
450  return true;
451 }
452 
454  IntegerValue new_start_min) {
455  if (starts_[t].var == kNoIntegerVariable) {
456  if (new_start_min > starts_[t].constant) return PushTaskAbsence(t);
457  return true;
458  }
459  return PushIntervalBound(t, starts_[t].GreaterOrEqual(new_start_min));
460 }
461 
463  IntegerValue new_end_max) {
464  if (ends_[t].var == kNoIntegerVariable) {
465  if (new_end_max < ends_[t].constant) return PushTaskAbsence(t);
466  return true;
467  }
468  return PushIntervalBound(t, ends_[t].LowerOrEqual(new_end_max));
469 }
470 
472  if (IsAbsent(t)) return true;
473  if (!IsOptional(t)) return ReportConflict();
474 
475  AddOtherReason(t);
476 
477  if (IsPresent(t)) {
478  literal_reason_.push_back(Literal(reason_for_presence_[t]).Negated());
479  return ReportConflict();
480  }
482  integer_trail_->EnqueueLiteral(Literal(reason_for_presence_[t]).Negated(),
483  literal_reason_, integer_reason_);
484  return true;
485 }
486 
488  DCHECK_NE(reason_for_presence_[t], kNoLiteralIndex);
489  DCHECK(!IsPresent(t));
490 
491  AddOtherReason(t);
492 
493  if (IsAbsent(t)) {
494  literal_reason_.push_back(Literal(reason_for_presence_[t]));
495  return ReportConflict();
496  }
498  integer_trail_->EnqueueLiteral(Literal(reason_for_presence_[t]),
499  literal_reason_, integer_reason_);
500  return true;
501 }
502 
505  return integer_trail_->ReportConflict(literal_reason_, integer_reason_);
506 }
507 
509  GenericLiteralWatcher* watcher,
510  bool watch_start_max,
511  bool watch_end_max) const {
512  const int num_tasks = starts_.size();
513  for (int t = 0; t < num_tasks; ++t) {
514  watcher->WatchLowerBound(starts_[t], id);
515  watcher->WatchLowerBound(ends_[t], id);
516  watcher->WatchLowerBound(sizes_[t], id);
517  if (watch_start_max) {
518  watcher->WatchUpperBound(starts_[t], id);
519  }
520  if (watch_end_max) {
521  watcher->WatchUpperBound(ends_[t], id);
522  }
523  if (!IsPresent(t) && !IsAbsent(t)) {
524  watcher->WatchLiteral(Literal(reason_for_presence_[t]), id);
525  }
526  }
527 }
528 
529 void SchedulingConstraintHelper::AddOtherReason(int t) {
530  if (other_helper_ == nullptr || already_added_to_other_reasons_[t]) return;
531  already_added_to_other_reasons_[t] = true;
532  const int mapped_t = map_to_other_helper_[t];
533  other_helper_->AddStartMaxReason(mapped_t, event_for_other_helper_);
534  other_helper_->AddEndMinReason(mapped_t, event_for_other_helper_ + 1);
535 }
536 
537 void SchedulingConstraintHelper::ImportOtherReasons() {
538  if (other_helper_ != nullptr) ImportOtherReasons(*other_helper_);
539 }
540 
541 void SchedulingConstraintHelper::ImportOtherReasons(
542  const SchedulingConstraintHelper& other_helper) {
543  literal_reason_.insert(literal_reason_.end(),
544  other_helper.literal_reason_.begin(),
545  other_helper.literal_reason_.end());
546  integer_reason_.insert(integer_reason_.end(),
547  other_helper.integer_reason_.begin(),
548  other_helper.integer_reason_.end());
549 }
550 
552  return absl::StrCat("t=", t, " is_present=", IsPresent(t), " size=[",
553  SizeMin(t).value(), ",", SizeMax(t).value(), "]",
554  " start=[", StartMin(t).value(), ",", StartMax(t).value(),
555  "]", " end=[", EndMin(t).value(), ",", EndMax(t).value(),
556  "]");
557 }
558 
560  IntegerValue start,
561  IntegerValue end) const {
562  return std::min(std::min(end - start, SizeMin(t)),
563  std::min(EndMin(t) - start, end - StartMax(t)));
564 }
565 
566 } // namespace sat
567 } // namespace operations_research
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
Definition: intervals.cc:67
#define CHECK(condition)
Definition: base/logging.h:491
void AddEndMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:583
ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t, IntegerLiteral lit)
Definition: intervals.cc:431
void AddStartMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:561
void IncrementalSort(int max_comparisons, Iterator begin, Iterator end, Compare comp=Compare{}, bool is_stable=false)
Definition: sort.h:46
int64_t min
Definition: alldiff_cst.cc:139
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
Definition: intervals.cc:295
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
Definition: intervals.cc:426
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
const std::vector< TaskTime > & TaskByDecreasingEndMax()
Definition: intervals.cc:350
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
Definition: integer.cc:846
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.h:849
AffineExpression Size(IntervalVariable i) const
Definition: intervals.h:94
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1345
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:263
ABSL_MUST_USE_RESULT bool PushTaskPresence(int t)
Definition: intervals.cc:487
void AddReasonForBeingBefore(int before, int after)
Definition: intervals.cc:382
GRBmodel * model
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
Definition: intervals.cc:508
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
Definition: intervals.cc:362
void ImportOtherReasons(const SchedulingConstraintHelper &other_helper)
Definition: intervals.cc:541
void AddTerm(IntegerVariable var, IntegerValue coeff)
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
Definition: intervals.cc:453
void AddStartMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:568
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
Definition: intervals.cc:114
void AddEndMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:575
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.cc:1028
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
Definition: integer.h:1567
bool PropagateOutgoingArcs(IntegerVariable var)
Definition: precedences.cc:96
int64_t max
Definition: alldiff_cst.cc:140
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
Definition: integer.h:1430
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_end_max)
Definition: intervals.cc:462
AffineExpression End(IntervalVariable i) const
Definition: intervals.h:96
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:887
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
Definition: intervals.cc:471
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
Definition: integer.h:1552
void SetPropagatorPriority(int id, int priority)
Definition: integer.cc:2019
void push_back(const value_type &x)
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.cc:1142
void WatchLiteral(Literal l, int id, int watch_index=-1)
Definition: integer.h:1422
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
ABSL_MUST_USE_RESULT bool ConditionalEnqueue(Literal lit, IntegerLiteral i_lit, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason)
Definition: integer.cc:1035
IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present)
Definition: intervals.cc:26
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:29
IntegerValue GetMinOverlap(int t, IntegerValue start, IntegerValue end) const
Definition: intervals.cc:559
#define DCHECK(condition)
Definition: base/logging.h:885
void RegisterReversibleClass(ReversibleInterface *rev)
Definition: integer.h:872
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
Definition: integer.h:1524
const std::vector< TaskTime > & TaskByIncreasingStartMin()
Definition: intervals.cc:313
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
Definition: integer.h:1454
int Register(PropagatorInterface *propagator)
Definition: integer.cc:1996
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1349
Collection of objects used to extend the Constraint Solver library.
const IntegerVariable kNoIntegerVariable(-1)
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
Definition: integer.h:1448
const LiteralIndex kNoLiteralIndex(-1)
IntVar * var
Definition: expr_array.cc:1874
AffineExpression Start(IntervalVariable i) const
Definition: intervals.h:95
ABSL_MUST_USE_RESULT bool ResetFromSubset(const SchedulingConstraintHelper &other, absl::Span< const int > tasks)
Definition: intervals.cc:218
const std::vector< TaskTime > & TaskByIncreasingEndMin()
Definition: intervals.cc:325
const std::vector< TaskTime > & TaskByDecreasingStartMax()
Definition: intervals.cc:337
void LoadConditionalLinearConstraint(const absl::Span< const Literal > enforcement_literals, const LinearConstraint &cst, Model *model)
Definition: integer_expr.h:575
int64_t value
void RegisterWith(GenericLiteralWatcher *watcher)
Definition: intervals.cc:133
void AddSizeMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:554
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:889