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