14 #ifndef OR_TOOLS_SAT_INTERVALS_H_
15 #define OR_TOOLS_SAT_INTERVALS_H_
23 #include "absl/base/attributes.h"
24 #include "absl/strings/string_view.h"
69 IntegerVariable size, IntegerValue fixed_size,
70 LiteralIndex is_present);
73 LiteralIndex is_present,
74 bool add_linear_relation);
104 IntegerVariable
SizeVar(IntervalVariable i)
const {
106 CHECK_EQ(sizes_[i].coeff, 1);
107 CHECK_EQ(sizes_[i].constant, 0);
109 return sizes_[i].var;
111 IntegerVariable
StartVar(IntervalVariable i)
const {
113 CHECK_EQ(starts_[i].coeff, 1);
114 CHECK_EQ(starts_[i].constant, 0);
116 return starts_[i].var;
118 IntegerVariable
EndVar(IntervalVariable i)
const {
120 CHECK_EQ(ends_[i].coeff, 1);
121 CHECK_EQ(ends_[i].constant, 0);
127 IntegerValue
MinSize(IntervalVariable i)
const {
132 IntegerValue
MaxSize(IntervalVariable i)
const {
138 std::vector<IntervalVariable> result;
148 const std::vector<IntervalVariable>& variables);
167 absl::flat_hash_map<std::vector<IntervalVariable>,
242 IntegerValue
SizeMin(
int t)
const {
return cached_size_min_[t]; }
247 IntegerValue
StartMin(
int t)
const {
return cached_start_min_[t]; }
248 IntegerValue
EndMin(
int t)
const {
return cached_end_min_[t]; }
249 IntegerValue
StartMax(
int t)
const {
return -cached_negated_start_max_[t]; }
250 IntegerValue
EndMax(
int t)
const {
return -cached_negated_end_max_[t]; }
267 return cached_shifted_start_min_[t];
273 return -cached_negated_shifted_end_max_[t];
349 return &integer_reason_;
373 const std::vector<AffineExpression>&
Starts()
const {
return starts_; }
374 const std::vector<AffineExpression>&
Ends()
const {
return ends_; }
375 const std::vector<AffineExpression>&
Sizes()
const {
return sizes_; }
384 bool watch_start_max =
true,
385 bool watch_end_max =
true)
const;
393 absl::Span<const int> map_to_other_helper,
394 IntegerValue event) {
395 CHECK(other_helper !=
nullptr);
396 other_helper_ = other_helper;
397 map_to_other_helper_ = map_to_other_helper;
398 event_for_other_helper_ = event;
420 void InitSortedVectors();
421 ABSL_MUST_USE_RESULT
bool UpdateCachedValues(
int t);
430 void AddOtherReason(
int t);
433 void ImportOtherReasons();
440 bool current_time_direction_ =
true;
444 std::vector<AffineExpression> starts_;
445 std::vector<AffineExpression> ends_;
446 std::vector<AffineExpression> sizes_;
447 std::vector<LiteralIndex> reason_for_presence_;
451 std::vector<AffineExpression> minus_starts_;
452 std::vector<AffineExpression> minus_ends_;
455 int previous_level_ = 0;
458 std::vector<IntegerValue> cached_size_min_;
459 std::vector<IntegerValue> cached_start_min_;
460 std::vector<IntegerValue> cached_end_min_;
461 std::vector<IntegerValue> cached_negated_start_max_;
462 std::vector<IntegerValue> cached_negated_end_max_;
463 std::vector<IntegerValue> cached_shifted_start_min_;
464 std::vector<IntegerValue> cached_negated_shifted_end_max_;
467 std::vector<TaskTime> task_by_increasing_start_min_;
468 std::vector<TaskTime> task_by_increasing_end_min_;
469 std::vector<TaskTime> task_by_decreasing_start_max_;
470 std::vector<TaskTime> task_by_decreasing_end_max_;
473 bool recompute_energy_profile_ =
true;
474 std::vector<ProfileEvent> energy_profile_;
478 std::vector<TaskTime> task_by_increasing_shifted_start_min_;
479 std::vector<TaskTime> task_by_negated_shifted_end_max_;
480 bool recompute_shifted_start_min_ =
true;
481 bool recompute_negated_shifted_end_max_ =
true;
485 bool recompute_all_cache_ =
true;
486 std::vector<bool> recompute_cache_;
489 std::vector<Literal> literal_reason_;
490 std::vector<IntegerLiteral> integer_reason_;
494 absl::Span<const int> map_to_other_helper_;
495 IntegerValue event_for_other_helper_;
496 std::vector<bool> already_added_to_other_reasons_;
521 const std::vector<AffineExpression>&
Demands()
const {
return demands_; }
544 IntegerValue
EnergyMin(
int t)
const {
return cached_energies_min_[t]; }
545 IntegerValue
EnergyMax(
int t)
const {
return cached_energies_max_[t]; }
554 IntegerValue window_end);
556 IntegerValue window_end);
567 return decomposed_energies_;
572 const std::vector<LinearExpression>& energies);
574 const std::vector<std::vector<LiteralValueValue>>& energies);
583 IntegerValue SimpleEnergyMin(
int t)
const;
584 IntegerValue LinearEnergyMin(
int t)
const;
585 IntegerValue SimpleEnergyMax(
int t)
const;
586 IntegerValue LinearEnergyMax(
int t)
const;
587 IntegerValue DecomposedEnergyMin(
int t)
const;
588 IntegerValue DecomposedEnergyMax(
int t)
const;
593 std::vector<AffineExpression> demands_;
597 std::vector<IntegerValue> cached_energies_min_;
598 std::vector<IntegerValue> cached_energies_max_;
599 std::vector<bool> energy_is_quadratic_;
603 std::vector<std::vector<LiteralValueValue>> decomposed_energies_;
607 std::vector<std::optional<LinearExpression>> linearized_energies_;
616 IntegerValue
end_max, IntegerValue size_min, IntegerValue demand_min,
617 const std::vector<LiteralValueValue>& filtered_energy,
618 IntegerValue window_start, IntegerValue window_end);
625 return integer_trail_->
IsFixed(starts_[t]);
629 return integer_trail_->
IsFixed(ends_[t]);
633 return integer_trail_->
IsFixed(sizes_[t]);
651 integer_reason_.clear();
652 literal_reason_.clear();
655 already_added_to_other_reasons_.assign(
NumTasks(),
false);
663 literal_reason_.push_back(
Literal(reason_for_presence_[t]).Negated());
671 literal_reason_.push_back(
Literal(reason_for_presence_[t]));
679 inline void SchedulingConstraintHelper::AddGenericReason(
711 AddGenericReason(sizes_[t].Negated(), -
lower_bound, minus_ends_[t],
719 AddGenericReason(sizes_[t],
upper_bound, ends_[t], minus_starts_[t]);
726 AddGenericReason(minus_starts_[t], -
lower_bound, minus_ends_[t], sizes_[t]);
733 AddGenericReason(starts_[t],
upper_bound, ends_[t], sizes_[t].Negated());
740 AddGenericReason(minus_ends_[t], -
lower_bound, minus_starts_[t],
741 sizes_[t].Negated());
748 AddGenericReason(ends_[t],
upper_bound, starts_[t], sizes_[t]);
752 int t, IntegerValue energy_min, IntegerValue
time) {
762 int t, IntegerValue time_min, IntegerValue time_max) {
763 const IntegerValue energy_min =
SizeMin(t);
764 CHECK_LE(time_min + energy_min, time_max);
770 if (
EndMax(t) <= time_max) {
783 IntervalVariable v) {
789 inline std::function<IntegerVariable(
const Model&)>
EndVar(IntervalVariable v) {
796 IntervalVariable v) {
802 inline std::function<int64_t(
const Model&)>
MinSize(IntervalVariable v) {
808 inline std::function<int64_t(
const Model&)>
MaxSize(IntervalVariable v) {
821 IntervalVariable v) {
839 IntegerVariable
start, IntegerVariable
end, IntegerVariable size) {
847 int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size) {
858 int64_t min_start, int64_t max_end, int64_t size,
Literal is_present) {
863 IntegerValue(size), is_present.
Index());
867 inline std::function<IntervalVariable(Model*)>
869 int64_t size,
Literal is_present) {
872 const IntegerVariable
start =
874 const IntegerVariable
end =
878 integer_trail->MarkIntegerVariableAsOptional(
end, is_present);
885 IntegerVariable
start, IntegerVariable
end, IntegerVariable size,
893 inline std::function<IntervalVariable(Model*)>
895 int64_t min_size, int64_t max_size,
908 IntervalVariable parent,
const std::vector<IntervalVariable>& members) {
913 std::vector<Literal> presences;
914 std::vector<IntegerValue> sizes;
917 std::vector<LiteralWithCoeff> sat_ct;
918 for (
const IntervalVariable member : members) {
920 const Literal is_present = intervals->PresenceLiteral(member);
929 CHECK(integer_trail->IsFixed(intervals->Size(member)));
930 presences.push_back(is_present);
931 sizes.push_back(intervals->MinSize(member));
934 model->Add(
IsOneOf(intervals->SizeVar(parent), presences, sizes));
940 std::vector<IntegerVariable> starts;
941 starts.reserve(members.size());
942 for (
const IntervalVariable member : members) {
943 starts.push_back(intervals->StartVar(member));
949 std::vector<IntegerVariable> ends;
950 ends.reserve(members.size());
951 for (
const IntervalVariable member : members) {
952 ends.push_back(intervals->EndVar(member));
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
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
std::vector< IntervalVariable > AllIntervals() const
bool IsAbsent(IntervalVariable i) const
bool IsOptional(IntervalVariable i) const
SchedulingConstraintHelper * GetOrCreateHelper(const std::vector< IntervalVariable > &variables)
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.
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< TaskTime > & TaskByDecreasingEndMax()
void SetLevel(int level) final
std::vector< Literal > * MutableLiteralReason()
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue value)
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue value)
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 IncreaseEndMin(int t, IntegerValue value)
std::vector< IntegerLiteral > * MutableIntegerReason()
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
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()
ABSL_MUST_USE_RESULT bool PushLiteral(Literal l)
const std::vector< AffineExpression > & Starts() const
void SetOtherHelper(SchedulingConstraintHelper *other_helper, absl::Span< const int > map_to_other_helper, IntegerValue event)
bool IsOptional(int t) const
const std::vector< ProfileEvent > & GetEnergyProfile()
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)
const std::vector< AffineExpression > & Sizes() const
void AddStartMaxReason(int t, IntegerValue upper_bound)
void SetTimeDirection(bool is_forward)
IntegerValue SizeMax(int t) const
IntegerValue SizeMin(int t) const
const std::vector< AffineExpression > & Ends() const
bool EnergyIsQuadratic(int t) const
void OverrideLinearizedEnergies(const std::vector< LinearExpression > &energies)
IntegerValue EnergyMax(int t) const
SchedulingDemandHelper(std::vector< AffineExpression > demands, SchedulingConstraintHelper *helper, Model *model)
bool DemandIsFixed(int t) const
void AddEnergyMinInWindowReason(int t, IntegerValue window_start, IntegerValue window_end)
ABSL_MUST_USE_RESULT bool AddLinearizedDemand(int t, LinearConstraintBuilder *builder) const
const std::vector< std::vector< LiteralValueValue > > & DecomposedEnergies() const
IntegerValue DemandMax(int t) const
std::vector< LiteralValueValue > FilteredDecomposedEnergy(int index)
IntegerValue EnergyMin(int t) const
void CacheAllEnergyValues()
void AddDemandMinReason(int t)
ABSL_MUST_USE_RESULT bool DecreaseEnergyMax(int t, IntegerValue value)
const std::vector< AffineExpression > & Demands() const
void OverrideDecomposedEnergies(const std::vector< std::vector< LiteralValueValue >> &energies)
IntegerValue DemandMin(int t) const
IntegerValue EnergyMinInWindow(int t, IntegerValue window_start, IntegerValue window_end)
void AddEnergyMinReason(int t)
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< IntegerVariable(const Model &)> SizeVar(IntervalVariable v)
DEFINE_STRONG_INDEX_TYPE(ClauseIndex)
std::function< IntervalVariable(Model *)> NewInterval(int64_t min_start, int64_t max_end, int64_t size)
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 *)> PartialIsOneOfVar(IntegerVariable target_var, const std::vector< IntegerVariable > &vars, const std::vector< Literal > &selectors)
std::function< void(Model *)> IsOneOf(IntegerVariable var, const std::vector< Literal > &selectors, const std::vector< IntegerValue > &values)
const IntegerVariable kNoIntegerVariable(-1)
const IntervalVariable kNoIntervalVariable(-1)
std::function< IntegerVariable(const Model &)> EndVar(IntervalVariable v)
std::function< IntervalVariable(Model *)> NewIntervalWithVariableSize(int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size)
std::function< int64_t(const Model &)> MinSize(IntervalVariable v)
std::function< int64_t(const Model &)> MaxSize(IntervalVariable v)
std::function< bool(const Model &)> IsOptional(IntervalVariable v)
std::function< void(Model *)> BooleanLinearConstraint(int64_t lower_bound, int64_t upper_bound, std::vector< LiteralWithCoeff > *cst)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
IntegerValue ComputeEnergyMinInWindow(IntegerValue start_min, IntegerValue start_max, IntegerValue end_min, IntegerValue end_max, IntegerValue size_min, IntegerValue demand_min, const std::vector< LiteralValueValue > &filtered_energy, IntegerValue window_start, IntegerValue window_end)
std::function< IntegerVariable(const Model &)> StartVar(IntervalVariable v)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
std::function< void(Model *)> IntervalWithAlternatives(IntervalVariable parent, const std::vector< IntervalVariable > &members)
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)
Collection of objects used to extend the Constraint Solver library.
std::optional< int64_t > end
IntegerLiteral LowerOrEqual(IntegerValue bound) const
bool operator<(const ProfileEvent &other) const
bool operator<(TaskTime other) const
bool operator>(TaskTime other) const