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
15
16#include <algorithm>
17#include <memory>
18#include <string>
19
20#include "ortools/sat/integer.h"
21#include "ortools/util/sort.h"
22
23namespace operations_research {
24namespace sat {
25
26IntervalVariable 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
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
94 InitSortedVectors();
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
148bool 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();
241}
242
243void 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
312const 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
324const 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
336const 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
349const 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
361const 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];
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.
445bool 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
529void 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
537void SchedulingConstraintHelper::ImportOtherReasons() {
538 if (other_helper_ != nullptr) ImportOtherReasons(*other_helper_);
539}
540
541void 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
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:491
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:887
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:889
#define DCHECK(condition)
Definition: base/logging.h:885
void WatchLiteral(Literal l, int id, int watch_index=-1)
Definition: integer.h:1422
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
Definition: integer.h:1430
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
Definition: integer.h:1454
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
Definition: integer.h:1448
void SetPropagatorPriority(int id, int priority)
Definition: integer.cc:2019
int Register(PropagatorInterface *propagator)
Definition: integer.cc:1996
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
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.h:849
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.cc:1142
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1349
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
Definition: integer.cc:846
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1345
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
void RegisterReversibleClass(ReversibleInterface *rev)
Definition: integer.h:872
AffineExpression End(IntervalVariable i) const
Definition: intervals.h:96
AffineExpression Start(IntervalVariable i) const
Definition: intervals.h:95
AffineExpression Size(IntervalVariable i) const
Definition: intervals.h:94
IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present)
Definition: intervals.cc:26
void AddTerm(IntegerVariable var, IntegerValue coeff)
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
bool PropagateOutgoingArcs(IntegerVariable var)
Definition: precedences.cc:96
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
Definition: intervals.cc:426
const std::vector< TaskTime > & TaskByDecreasingEndMax()
Definition: intervals.cc:350
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
Definition: intervals.cc:471
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
Definition: intervals.cc:67
const std::vector< TaskTime > & TaskByIncreasingStartMin()
Definition: intervals.cc:313
void AddStartMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:561
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
Definition: intervals.cc:508
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
Definition: intervals.cc:114
const std::vector< TaskTime > & TaskByIncreasingEndMin()
Definition: intervals.cc:325
ABSL_MUST_USE_RESULT bool ResetFromSubset(const SchedulingConstraintHelper &other, absl::Span< const int > tasks)
Definition: intervals.cc:218
ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t, IntegerLiteral lit)
Definition: intervals.cc:431
void RegisterWith(GenericLiteralWatcher *watcher)
Definition: intervals.cc:133
void AddEndMinReason(int t, IntegerValue lower_bound)
Definition: intervals.h:575
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
Definition: intervals.cc:453
IntegerValue GetMinOverlap(int t, IntegerValue start, IntegerValue end) const
Definition: intervals.cc:559
void AddSizeMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:554
void ImportOtherReasons(const SchedulingConstraintHelper &other_helper)
Definition: intervals.cc:541
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
Definition: intervals.cc:295
const std::vector< TaskTime > & TaskByDecreasingStartMax()
Definition: intervals.cc:337
ABSL_MUST_USE_RESULT bool PushTaskPresence(int t)
Definition: intervals.cc:487
void AddEndMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:583
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
Definition: intervals.cc:362
void AddReasonForBeingBefore(int before, int after)
Definition: intervals.cc:382
void AddStartMaxReason(int t, IntegerValue upper_bound)
Definition: intervals.h:568
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_end_max)
Definition: intervals.cc:462
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:263
const LiteralIndex kNoLiteralIndex(-1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
Definition: integer.h:1524
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
Definition: integer.h:1567
void LoadConditionalLinearConstraint(const absl::Span< const Literal > enforcement_literals, const LinearConstraint &cst, Model *model)
Definition: integer_expr.h:573
const IntegerVariable kNoIntegerVariable(-1)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:29
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
Definition: integer.h:1552
Collection of objects used to extend the Constraint Solver library.
void IncrementalSort(int max_comparisons, Iterator begin, Iterator end, Compare comp=Compare{}, bool is_stable=false)
Definition: sort.h:46