14#ifndef OR_TOOLS_SAT_INTERVALS_H_
15#define OR_TOOLS_SAT_INTERVALS_H_
22#include "absl/base/attributes.h"
23#include "absl/strings/string_view.h"
24#include "absl/types/span.h"
67 IntegerVariable size, IntegerValue fixed_size,
68 LiteralIndex is_present);
71 LiteralIndex is_present,
72 bool add_linear_relation);
102 IntegerVariable
SizeVar(IntervalVariable i)
const {
107 return sizes_[i].var;
109 IntegerVariable
StartVar(IntervalVariable i)
const {
114 return starts_[i].var;
116 IntegerVariable
EndVar(IntervalVariable i)
const {
125 IntegerValue
MinSize(IntervalVariable i)
const {
130 IntegerValue
MaxSize(IntervalVariable i)
const {
136 std::vector<IntervalVariable> result;
229 IntegerValue
SizeMin(
int t)
const {
return cached_size_min_[t]; }
234 IntegerValue
StartMin(
int t)
const {
return cached_start_min_[t]; }
235 IntegerValue
EndMin(
int t)
const {
return cached_end_min_[t]; }
236 IntegerValue
StartMax(
int t)
const {
return -cached_negated_start_max_[t]; }
237 IntegerValue
EndMax(
int t)
const {
return -cached_negated_end_max_[t]; }
254 return cached_shifted_start_min_[t];
260 return -cached_negated_shifted_end_max_[t];
317 return &integer_reason_;
329 ABSL_MUST_USE_RESULT
bool IncreaseStartMin(
int t, IntegerValue new_start_min);
330 ABSL_MUST_USE_RESULT
bool DecreaseEndMax(
int t, IntegerValue new_end_max);
339 const std::vector<AffineExpression>&
Starts()
const {
return starts_; }
340 const std::vector<AffineExpression>&
Ends()
const {
return ends_; }
341 const std::vector<AffineExpression>&
Sizes()
const {
return sizes_; }
350 bool watch_start_max =
true,
351 bool watch_end_max =
true)
const;
359 absl::Span<const int> map_to_other_helper,
360 IntegerValue event) {
361 CHECK(other_helper !=
nullptr);
362 other_helper_ = other_helper;
363 map_to_other_helper_ = map_to_other_helper;
364 event_for_other_helper_ = event;
386 void InitSortedVectors();
387 ABSL_MUST_USE_RESULT
bool UpdateCachedValues(
int t);
396 void AddOtherReason(
int t);
399 void ImportOtherReasons();
406 bool current_time_direction_ =
true;
410 std::vector<AffineExpression> starts_;
411 std::vector<AffineExpression> ends_;
412 std::vector<AffineExpression> sizes_;
413 std::vector<LiteralIndex> reason_for_presence_;
417 std::vector<AffineExpression> minus_starts_;
418 std::vector<AffineExpression> minus_ends_;
421 int previous_level_ = 0;
424 std::vector<IntegerValue> cached_size_min_;
425 std::vector<IntegerValue> cached_start_min_;
426 std::vector<IntegerValue> cached_end_min_;
427 std::vector<IntegerValue> cached_negated_start_max_;
428 std::vector<IntegerValue> cached_negated_end_max_;
429 std::vector<IntegerValue> cached_shifted_start_min_;
430 std::vector<IntegerValue> cached_negated_shifted_end_max_;
433 std::vector<TaskTime> task_by_increasing_start_min_;
434 std::vector<TaskTime> task_by_increasing_end_min_;
435 std::vector<TaskTime> task_by_decreasing_start_max_;
436 std::vector<TaskTime> task_by_decreasing_end_max_;
440 std::vector<TaskTime> task_by_increasing_shifted_start_min_;
441 std::vector<TaskTime> task_by_negated_shifted_end_max_;
442 bool recompute_shifted_start_min_ =
true;
443 bool recompute_negated_shifted_end_max_ =
true;
447 bool recompute_all_cache_ =
true;
448 std::vector<bool> recompute_cache_;
451 std::vector<Literal> literal_reason_;
452 std::vector<IntegerLiteral> integer_reason_;
456 absl::Span<const int> map_to_other_helper_;
457 IntegerValue event_for_other_helper_;
458 std::vector<bool> already_added_to_other_reasons_;
466 return integer_trail_->
IsFixed(starts_[t]);
470 return integer_trail_->
IsFixed(ends_[t]);
474 return integer_trail_->
IsFixed(sizes_[t]);
492 integer_reason_.clear();
493 literal_reason_.clear();
496 already_added_to_other_reasons_.assign(
NumTasks(),
false);
504 literal_reason_.push_back(
Literal(reason_for_presence_[t]).Negated());
512 literal_reason_.push_back(
Literal(reason_for_presence_[t]));
520inline void SchedulingConstraintHelper::AddGenericReason(
543 slack, {IntegerValue(1), IntegerValue(1)},
553 AddGenericReason(sizes_[t].Negated(), -
lower_bound, minus_ends_[t],
561 AddGenericReason(sizes_[t],
upper_bound, ends_[t], minus_starts_[t]);
568 AddGenericReason(minus_starts_[t], -
lower_bound, minus_ends_[t], sizes_[t]);
575 AddGenericReason(starts_[t],
upper_bound, ends_[t], sizes_[t].Negated());
582 AddGenericReason(minus_ends_[t], -
lower_bound, minus_starts_[t],
583 sizes_[t].Negated());
590 AddGenericReason(ends_[t],
upper_bound, starts_[t], sizes_[t]);
594 int t, IntegerValue energy_min, IntegerValue
time) {
604 int t, IntegerValue time_min, IntegerValue time_max) {
605 const IntegerValue energy_min =
SizeMin(t);
606 CHECK_LE(time_min + energy_min, time_max);
612 if (
EndMax(t) <= time_max) {
625 IntervalVariable v) {
631inline std::function<IntegerVariable(
const Model&)>
EndVar(IntervalVariable v) {
638 IntervalVariable v) {
644inline std::function<int64_t(
const Model&)>
MinSize(IntervalVariable v) {
650inline std::function<int64_t(
const Model&)>
MaxSize(IntervalVariable v) {
663 IntervalVariable v) {
681 IntegerVariable
start, IntegerVariable
end, IntegerVariable size) {
689 int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size) {
700 int64_t min_start, int64_t max_end, int64_t size,
Literal is_present) {
705 IntegerValue(size), is_present.
Index());
709inline std::function<IntervalVariable(Model*)>
711 int64_t size,
Literal is_present) {
714 const IntegerVariable
start =
716 const IntegerVariable
end =
720 integer_trail->MarkIntegerVariableAsOptional(
end, is_present);
727 IntegerVariable
start, IntegerVariable
end, IntegerVariable size,
735inline std::function<IntervalVariable(Model*)>
737 int64_t min_size, int64_t max_size,
750 IntervalVariable parent,
const std::vector<IntervalVariable>& members) {
755 std::vector<Literal> presences;
756 std::vector<IntegerValue> sizes;
759 std::vector<LiteralWithCoeff> sat_ct;
760 for (
const IntervalVariable member : members) {
762 const Literal is_present = intervals->PresenceLiteral(member);
771 CHECK(integer_trail->IsFixed(intervals->Size(member)));
772 presences.push_back(is_present);
773 sizes.push_back(intervals->MinSize(member));
776 model->Add(
IsOneOf(intervals->SizeVar(parent), presences, sizes));
782 std::vector<IntegerVariable> starts;
783 starts.reserve(members.size());
784 for (
const IntervalVariable member : members) {
785 starts.push_back(intervals->StartVar(member));
791 std::vector<IntegerVariable> ends;
792 ends.reserve(members.size());
793 for (
const IntervalVariable member : members) {
794 ends.push_back(intervals->EndVar(member));
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
An Assignment is a variable -> domains mapping, used to report solutions to the user.
bool IsFixed(IntegerVariable i) const
bool InPropagationLoop() const
IntegerValue UpperBound(IntegerVariable i) const
void MarkIntegerVariableAsOptional(IntegerVariable i, Literal is_considered)
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
IntegerValue LowerBound(IntegerVariable i) const
bool IsOptional(IntegerVariable i) const
IntegerVariable SizeVar(IntervalVariable i) const
AffineExpression End(IntervalVariable i) const
IntegerValue MaxSize(IntervalVariable i) const
AffineExpression Start(IntervalVariable i) const
Literal PresenceLiteral(IntervalVariable i) const
std::vector< IntervalVariable > AllIntervals() const
IntegerVariable StartVar(IntervalVariable i) const
IntegerValue MinSize(IntervalVariable i) const
IntervalsRepository(Model *model)
IntegerVariable EndVar(IntervalVariable i) const
bool IsPresent(IntervalVariable i) const
AffineExpression Size(IntervalVariable i) const
bool IsAbsent(IntervalVariable i) const
bool IsOptional(IntervalVariable i) const
IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present)
LiteralIndex Index() const
Class that owns everything related to a particular optimization model.
std::vector< Literal > * MutableLiteralReason()
bool StartIsFixed(int t) const
IntegerValue ShiftedStartMin(int t) const
IntegerValue EndMin(int t) const
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
const std::vector< AffineExpression > & Starts() const
const std::vector< TaskTime > & TaskByDecreasingEndMax()
std::vector< IntegerLiteral > * MutableIntegerReason()
void SetLevel(int level) final
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
void AddSizeMinReason(int t)
const std::vector< TaskTime > & TaskByIncreasingStartMin()
void AddStartMinReason(int t, IntegerValue lower_bound)
void WatchAllTasks(int id, GenericLiteralWatcher *watcher, bool watch_start_max=true, bool watch_end_max=true) const
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
void AddPresenceReason(int t)
const std::vector< TaskTime > & TaskByIncreasingEndMin()
ABSL_MUST_USE_RESULT bool ResetFromSubset(const SchedulingConstraintHelper &other, absl::Span< const int > tasks)
bool IsPresent(int t) const
IntegerValue ShiftedEndMax(int t) const
bool SizeIsFixed(int t) const
void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time)
bool InPropagationLoop() const
ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t, IntegerLiteral lit)
void RegisterWith(GenericLiteralWatcher *watcher)
std::string TaskDebugString(int t) const
void AddEndMinReason(int t, IntegerValue lower_bound)
bool EndIsFixed(int t) const
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue new_start_min)
const std::vector< AffineExpression > & Sizes() const
IntegerValue GetMinOverlap(int t, IntegerValue start, IntegerValue end) const
bool IsAbsent(int t) const
void AddSizeMaxReason(int t, IntegerValue upper_bound)
IntegerValue EndMax(int t) const
ABSL_MUST_USE_RESULT bool ReportConflict()
void SetOtherHelper(SchedulingConstraintHelper *other_helper, absl::Span< const int > map_to_other_helper, IntegerValue event)
bool IsOptional(int t) const
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
IntegerValue StartMin(int t) const
const std::vector< TaskTime > & TaskByDecreasingStartMax()
ABSL_MUST_USE_RESULT bool PushTaskPresence(int t)
void AddAbsenceReason(int t)
Literal PresenceLiteral(int index) const
void AddEndMaxReason(int t, IntegerValue upper_bound)
void AddEnergyMinInIntervalReason(int t, IntegerValue min, IntegerValue max)
IntegerValue StartMax(int t) const
const std::vector< TaskTime > & TaskByIncreasingShiftedStartMin()
void AddReasonForBeingBefore(int before, int after)
void AddStartMaxReason(int t, IntegerValue upper_bound)
void SetTimeDirection(bool is_forward)
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue new_end_max)
const std::vector< AffineExpression > & Ends() const
IntegerValue SizeMax(int t) const
IntegerValue SizeMin(int t) const
const VariablesAssignment & Assignment() const
bool LiteralIsTrue(Literal literal) const
bool LiteralIsFalse(Literal literal) const
std::tuple< int64_t, int64_t, const double > Coefficient
std::function< int64_t(const Model &)> MaxSize(IntervalVariable v)
std::function< IntegerVariable(const Model &)> SizeVar(IntervalVariable v)
DEFINE_STRONG_INDEX_TYPE(ClauseIndex)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
std::function< IntervalVariable(Model *)> NewOptionalIntervalWithVariableSize(int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size, Literal is_present)
std::function< Literal(const Model &)> IsPresentLiteral(IntervalVariable v)
const LiteralIndex kNoLiteralIndex(-1)
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
std::function< IntervalVariable(Model *)> NewIntervalWithVariableSize(int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size)
std::function< IntegerVariable(const Model &)> EndVar(IntervalVariable v)
std::function< void(Model *)> PartialIsOneOfVar(IntegerVariable target_var, const std::vector< IntegerVariable > &vars, const std::vector< Literal > &selectors)
std::function< IntervalVariable(Model *)> NewInterval(int64_t min_start, int64_t max_end, int64_t size)
const IntegerVariable kNoIntegerVariable(-1)
const IntervalVariable kNoIntervalVariable(-1)
std::function< IntervalVariable(Model *)> NewOptionalInterval(int64_t min_start, int64_t max_end, int64_t size, Literal is_present)
std::function< IntervalVariable(Model *)> NewOptionalIntervalWithOptionalVariables(int64_t min_start, int64_t max_end, int64_t size, Literal is_present)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< IntegerVariable(const Model &)> StartVar(IntervalVariable v)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::function< int64_t(const Model &)> MinSize(IntervalVariable v)
std::function< void(Model *)> BooleanLinearConstraint(int64_t lower_bound, int64_t upper_bound, std::vector< LiteralWithCoeff > *cst)
std::function< void(Model *)> IntervalWithAlternatives(IntervalVariable parent, const std::vector< IntervalVariable > &members)
std::function< bool(const Model &)> IsOptional(IntervalVariable v)
Collection of objects used to extend the Constraint Solver library.
std::optional< int64_t > end
IntegerLiteral LowerOrEqual(IntegerValue bound) const
bool operator<(TaskTime other) const
bool operator>(TaskTime other) const