14#ifndef OR_TOOLS_SAT_INTERVALS_H_
15#define OR_TOOLS_SAT_INTERVALS_H_
25#include "absl/base/attributes.h"
26#include "absl/container/flat_hash_map.h"
27#include "absl/log/check.h"
28#include "absl/strings/string_view.h"
29#include "absl/types/span.h"
80 IntegerVariable
size, IntegerValue fixed_size,
81 LiteralIndex is_present);
85 bool add_linear_relation =
false);
126 std::vector<IntervalVariable> result;
140 const std::vector<IntervalVariable>& variables,
141 bool register_as_disjunctive_helper =
false);
148 absl::Span<const AffineExpression> demands);
173 IntervalVariable
b)
const;
177 return disjunctive_helpers_;
188 cumulative_helpers_.push_back(helper);
191 return cumulative_helpers_;
213 absl::flat_hash_map<std::vector<IntervalVariable>,
217 std::pair<SchedulingConstraintHelper*, std::vector<AffineExpression>>,
219 demand_helper_repository_;
226 absl::flat_hash_map<std::pair<IntervalVariable, IntervalVariable>,
Literal>
227 disjunctive_precedences_;
228 absl::flat_hash_map<std::pair<AffineExpression, AffineExpression>,
Literal>
232 std::vector<SchedulingConstraintHelper*> disjunctive_helpers_;
233 std::vector<CumulativeHelper> cumulative_helpers_;
316 IntegerValue
SizeMin(
int t)
const {
return cached_size_min_[t]; }
321 IntegerValue
StartMin(
int t)
const {
return cached_start_min_[t]; }
322 IntegerValue
EndMin(
int t)
const {
return cached_end_min_[t]; }
323 IntegerValue
StartMax(
int t)
const {
return -cached_negated_start_max_[t]; }
324 IntegerValue
EndMax(
int t)
const {
return -cached_negated_end_max_[t]; }
351 return cached_shifted_start_min_[t];
357 return -cached_negated_shifted_end_max_[t];
379 int a,
int b,
bool add_reason_if_after =
false);
452 return &integer_reason_;
477 return interval_variables_;
479 absl::Span<const AffineExpression>
Starts()
const {
return starts_; }
480 absl::Span<const AffineExpression>
Ends()
const {
return ends_; }
481 absl::Span<const AffineExpression>
Sizes()
const {
return sizes_; }
498 absl::Span<const int> map_to_other_helper,
499 IntegerValue event) {
500 CHECK(other_helper !=
nullptr);
501 other_helper_ = other_helper;
502 map_to_other_helper_ = map_to_other_helper;
503 event_for_other_helper_ = event;
529 void InitSortedVectors();
530 ABSL_MUST_USE_RESULT
bool UpdateCachedValues(
int t);
539 void AddOtherReason(
int t);
542 void ImportOtherReasons();
552 bool current_time_direction_ =
true;
556 std::vector<IntervalVariable> interval_variables_;
557 std::vector<AffineExpression> starts_;
558 std::vector<AffineExpression> ends_;
559 std::vector<AffineExpression> sizes_;
560 std::vector<LiteralIndex> reason_for_presence_;
564 std::vector<AffineExpression> minus_starts_;
565 std::vector<AffineExpression> minus_ends_;
568 int64_t saved_num_backtracks_ = 0;
577 const std::unique_ptr<IntegerValue[]> cached_size_min_;
578 std::unique_ptr<IntegerValue[]> cached_start_min_;
579 std::unique_ptr<IntegerValue[]> cached_end_min_;
580 std::unique_ptr<IntegerValue[]> cached_negated_start_max_;
581 std::unique_ptr<IntegerValue[]> cached_negated_end_max_;
582 std::unique_ptr<IntegerValue[]> cached_shifted_start_min_;
583 std::unique_ptr<IntegerValue[]> cached_negated_shifted_end_max_;
586 std::vector<TaskTime> task_by_increasing_start_min_;
587 std::vector<TaskTime> task_by_decreasing_end_max_;
589 bool recompute_by_start_max_ =
true;
590 bool recompute_by_end_min_ =
true;
591 std::vector<TaskTime> task_by_increasing_negated_start_max_;
592 std::vector<TaskTime> task_by_increasing_end_min_;
595 bool recompute_energy_profile_ =
true;
596 std::vector<ProfileEvent> energy_profile_;
600 std::vector<CachedTaskBounds> task_by_increasing_shifted_start_min_;
601 std::vector<CachedTaskBounds> task_by_negated_shifted_end_max_;
602 bool recompute_shifted_start_min_ =
true;
603 bool recompute_negated_shifted_end_max_ =
true;
607 bool recompute_all_cache_ =
true;
611 std::vector<Literal> literal_reason_;
612 std::vector<IntegerLiteral> integer_reason_;
616 absl::Span<const int> map_to_other_helper_;
617 IntegerValue event_for_other_helper_;
618 std::vector<bool> already_added_to_other_reasons_;
621 std::vector<int> propagator_ids_;
650 const std::vector<AffineExpression>&
Demands()
const {
return demands_; }
673 IntegerValue
EnergyMin(
int t)
const {
return cached_energies_min_[t]; }
674 IntegerValue
EnergyMax(
int t)
const {
return cached_energies_max_[t]; }
683 IntegerValue window_end);
685 IntegerValue window_end);
696 return decomposed_energies_;
702 const std::vector<std::vector<LiteralValueValue>>& energies);
715 IntegerValue SimpleEnergyMin(
int t)
const;
716 IntegerValue LinearEnergyMin(
int t)
const;
717 IntegerValue SimpleEnergyMax(
int t)
const;
718 IntegerValue LinearEnergyMax(
int t)
const;
719 IntegerValue DecomposedEnergyMin(
int t)
const;
720 IntegerValue DecomposedEnergyMax(
int t)
const;
726 std::vector<AffineExpression> demands_;
730 std::vector<IntegerValue> cached_energies_min_;
731 std::vector<IntegerValue> cached_energies_max_;
732 std::vector<bool> energy_is_quadratic_;
736 std::vector<std::vector<LiteralValueValue>> decomposed_energies_;
740 std::vector<std::optional<LinearExpression>> linearized_energies_;
749 IntegerValue
end_max, IntegerValue size_min, IntegerValue demand_min,
750 absl::Span<const LiteralValueValue> filtered_energy,
751 IntegerValue window_start, IntegerValue window_end);
758 return integer_trail_->
IsFixed(starts_[t]);
762 return integer_trail_->
IsFixed(ends_[t]);
766 return integer_trail_->
IsFixed(sizes_[t]);
798 integer_reason_.clear();
799 literal_reason_.clear();
802 already_added_to_other_reasons_.assign(
NumTasks(),
false);
810 literal_reason_.push_back(
Literal(reason_for_presence_[t]).Negated());
818 literal_reason_.push_back(
Literal(reason_for_presence_[t]));
826inline void SchedulingConstraintHelper::AddGenericReason(
843 integer_reason_.push_back(c.LowerOrEqual(
upper_bound -
b.constant));
845 integer_reason_.push_back(
b.LowerOrEqual(
upper_bound - c.constant));
858 AddGenericReason(sizes_[t].Negated(), -
lower_bound, minus_ends_[t],
866 AddGenericReason(sizes_[t],
upper_bound, ends_[t], minus_starts_[t]);
873 AddGenericReason(minus_starts_[t], -
lower_bound, minus_ends_[t], sizes_[t]);
880 AddGenericReason(starts_[t],
upper_bound, ends_[t], sizes_[t].Negated());
888 sizes_[t].Negated());
904 int t, IntegerValue energy_min, IntegerValue
time) {
914 int t, IntegerValue time_min, IntegerValue time_max) {
915 const IntegerValue energy_min =
SizeMin(t);
916 CHECK_LE(time_min + energy_min, time_max);
922 if (
EndMax(t) <= time_max) {
934inline std::function<int64_t(
const Model&)>
MinSize(IntervalVariable v) {
935 return [=](
const Model&
model) {
936 return model.Get<IntervalsRepository>()->
MinSize(v).value();
940inline std::function<int64_t(
const Model&)>
MaxSize(IntervalVariable v) {
953 IntervalVariable v) {
959inline std::function<IntervalVariable(
Model*)>
NewInterval(int64_t min_start,
963 CHECK_LE(min_start +
size, max_end);
964 const IntegerVariable
start =
974inline std::function<IntervalVariable(Model*)>
NewInterval(
975 IntegerVariable
start, IntegerVariable
end, IntegerVariable
size) {
976 return [=](Model*
model) {
977 return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
983 int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size) {
984 return [=](Model*
model) {
985 return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
995 int64_t min_start, int64_t max_end, int64_t
size, Literal is_present) {
996 return [=](Model*
model) {
997 CHECK_LE(min_start +
size, max_end);
998 const IntegerVariable
start =
1016 IntegerVariable
start, IntegerVariable
end, IntegerVariable
size,
1017 Literal is_present) {
1018 return [=](Model*
model) {
1019 return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
1020 start,
end,
size, IntegerValue(0), is_present.Index());
1024inline std::function<IntervalVariable(Model*)>
1026 int64_t min_size, int64_t max_size,
1027 Literal is_present) {
1028 return [=](Model*
model) {
1029 return model->GetOrCreate<IntervalsRepository>()->CreateInterval(
1033 is_present.Index());
1040 std::vector<IntegerVariable>* vars);
1043 const AffineExpression& capacity, SchedulingDemandHelper* demands_helper,
1044 Model*
model, std::vector<IntegerVariable>* vars);
IntegerValue LowerBound(IntegerVariable i) const
Returns the current lower/upper bound of the given integer variable.
IntegerValue UpperBound(IntegerVariable i) const
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
Same as above but take in IntegerVariables instead of IntegerLiterals.
bool InPropagationLoop() const
bool IsFixed(IntegerVariable i) const
Checks if the variable is fixed.
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
Returns globally valid lower/upper bound on the given integer variable.
IntervalsRepository(const IntervalsRepository &)=delete
This type is neither copyable nor movable.
SchedulingDemandHelper * GetOrCreateDemandHelper(SchedulingConstraintHelper *helper, absl::Span< const AffineExpression > demands)
AffineExpression Start(IntervalVariable i) const
AffineExpression Size(IntervalVariable i) const
AffineExpression End(IntervalVariable i) const
bool IsAbsent(IntervalVariable i) const
const std::vector< CumulativeHelper > & AllCumulativeHelpers() const
void InitAllDecomposedEnergies()
Calls InitDecomposedEnergies on all SchedulingDemandHelper created.
Literal PresenceLiteral(IntervalVariable i) const
void CreateDisjunctivePrecedenceLiteral(IntervalVariable a, IntervalVariable b)
LiteralIndex GetPrecedenceLiteral(IntervalVariable a, IntervalVariable b) const
bool CreatePrecedenceLiteral(IntervalVariable a, IntervalVariable b)
const std::vector< SchedulingConstraintHelper * > & AllDisjunctiveHelpers() const
bool IsOptional(IntervalVariable i) const
Returns whether or not a interval is optional and the associated literal.
void RegisterCumulative(CumulativeHelper helper)
IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present)
IntegerValue MaxSize(IntervalVariable i) const
Return the maximum size of the given IntervalVariable.
IntegerValue MinSize(IntervalVariable i) const
Return the minimum size of the given IntervalVariable.
SchedulingConstraintHelper * GetOrCreateHelper(const std::vector< IntervalVariable > &variables, bool register_as_disjunctive_helper=false)
IntervalsRepository(Model *model)
IntervalsRepository & operator=(const IntervalsRepository &)=delete
std::vector< IntervalVariable > AllIntervals() const
Utility function that returns a vector will all intervals.
bool IsPresent(IntervalVariable i) const
Helper class to express a product as a linear constraint.
Base class for CP like propagators.
void AddPresenceReason(int t)
IntegerValue ShiftedEndMax(int t) const
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
absl::Span< const TaskTime > TaskByIncreasingStartMin()
void WatchAllTasks(int id, bool watch_max_side=true)
void AddReasonForBeingBefore(int before, int after)
Produces a relaxed reason for StartMax(before) < EndMin(after).
void AddEnergyAfterReason(int t, IntegerValue energy_min, IntegerValue time)
void AddStartMaxReason(int t, IntegerValue upper_bound)
ABSL_MUST_USE_RESULT bool IncreaseEndMin(int t, IntegerValue value)
IntegerValue ShiftedStartMin(int t) const
std::vector< IntegerLiteral > * MutableIntegerReason()
void RegisterWith(GenericLiteralWatcher *watcher)
absl::Span< const TaskTime > TaskByIncreasingNegatedStartMax()
bool SizeIsFixed(int t) const
SchedulingConstraintHelper(const std::vector< IntervalVariable > &tasks, Model *model)
void AddSizeMaxReason(int t, IntegerValue upper_bound)
IntegerValue StartMax(int t) const
bool PropagatePrecedence(int a, int b)
ABSL_MUST_USE_RESULT bool DecreaseEndMax(int t, IntegerValue value)
int NumTasks() const
Returns the number of task.
ABSL_MUST_USE_RESULT bool ReportConflict()
absl::Span< const AffineExpression > Sizes() const
ABSL_MUST_USE_RESULT bool PushLiteral(Literal l)
const std::vector< ProfileEvent > & GetEnergyProfile()
ABSL_MUST_USE_RESULT bool PushTaskAbsence(int t)
bool IsPresent(int t) const
void SetTimeDirection(bool is_forward)
ABSL_MUST_USE_RESULT bool PushIntegerLiteralIfTaskPresent(int t, IntegerLiteral lit)
Literal PresenceLiteral(int index) const
void AddSizeMinReason(int t)
absl::Span< const AffineExpression > Starts() const
void AddEndMaxReason(int t, IntegerValue upper_bound)
absl::Span< const AffineExpression > Ends() const
ABSL_MUST_USE_RESULT bool ResetFromSubset(const SchedulingConstraintHelper &other, absl::Span< const int > tasks)
ABSL_MUST_USE_RESULT bool IncreaseStartMin(int t, IntegerValue value)
IntegerValue SizeMax(int t) const
void AddEndMinReason(int t, IntegerValue lower_bound)
IntegerValue StartMin(int t) const
void ClearReason()
Functions to clear and then set the current reason.
bool InPropagationLoop() const
bool StartIsFixed(int t) const
IntegerValue SizeMin(int t) const
bool EndIsFixed(int t) const
IntegerValue LevelZeroStartMax(int t) const
absl::Span< const CachedTaskBounds > TaskByIncreasingShiftedStartMin()
absl::Span< const TaskTime > TaskByDecreasingEndMax()
ABSL_MUST_USE_RESULT bool SynchronizeAndSetTimeDirection(bool is_forward)
void SetOtherHelper(SchedulingConstraintHelper *other_helper, absl::Span< const int > map_to_other_helper, IntegerValue event)
ABSL_MUST_USE_RESULT bool PushTaskPresence(int t)
IntegerValue EndMax(int t) const
bool IsAbsent(int t) const
bool HasOtherHelper() const
IntegerValue EndMin(int t) const
bool IsOptional(int t) const
std::string TaskDebugString(int t) const
Returns a string with the current task bounds.
ABSL_MUST_USE_RESULT bool PushIntegerLiteral(IntegerLiteral lit)
void AddShiftedEndMaxReason(int t, IntegerValue upper_bound)
absl::Span< const IntervalVariable > IntervalVariables() const
Returns the underlying affine expressions.
IntegerValue GetCurrentMinDistanceBetweenTasks(int a, int b, bool add_reason_if_after=false)
IntegerValue LevelZeroEndMax(int t) const
IntegerValue GetMinOverlap(int t, IntegerValue start, IntegerValue end) const
std::vector< Literal > * MutableLiteralReason()
void AddStartMinReason(int t, IntegerValue lower_bound)
void AddEnergyMinInIntervalReason(int t, IntegerValue min, IntegerValue max)
IntegerValue LevelZeroStartMin(int t) const
absl::Span< const TaskTime > TaskByIncreasingEndMin()
int CurrentDecisionLevel() const
void AddAbsenceReason(int t)
bool CurrentTimeIsForward() const
void AddDemandMinReason(int t)
std::vector< LiteralValueValue > FilteredDecomposedEnergy(int index)
bool DemandIsFixed(int t) const
IntegerValue EnergyMinInWindow(int t, IntegerValue window_start, IntegerValue window_end)
IntegerValue LevelZeroDemandMin(int t) const
bool EnergyIsQuadratic(int t) const
const std::vector< std::vector< LiteralValueValue > > & DecomposedEnergies() const
void OverrideLinearizedEnergies(absl::Span< const LinearExpression > energies)
Visible for testing.
IntegerValue EnergyMax(int t) const
void AddEnergyMinReason(int t)
void InitDecomposedEnergies()
void AddEnergyMinInWindowReason(int t, IntegerValue window_start, IntegerValue window_end)
IntegerValue DemandMax(int t) const
void CacheAllEnergyValues()
SchedulingDemandHelper(absl::Span< const AffineExpression > demands, SchedulingConstraintHelper *helper, Model *model)
void OverrideDecomposedEnergies(const std::vector< std::vector< LiteralValueValue > > &energies)
const std::vector< AffineExpression > & Demands() const
ABSL_MUST_USE_RESULT bool DecreaseEnergyMax(int t, IntegerValue value)
IntegerValue DemandMin(int t) const
ABSL_MUST_USE_RESULT bool AddLinearizedDemand(int t, LinearConstraintBuilder *builder) const
IntegerValue EnergyMin(int t) const
int CurrentDecisionLevel() const
const VariablesAssignment & Assignment() const
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
std::function< int64_t(const Model &)> MaxSize(IntervalVariable v)
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::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Returns the vector of the negated variables.
std::function< IntervalVariable(Model *)> NewIntervalWithVariableSize(int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size)
std::function< IntervalVariable(Model *)> NewInterval(int64_t min_start, int64_t max_end, int64_t size)
const IntegerVariable kNoIntegerVariable(-1)
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
const IntervalVariable kNoIntervalVariable(-1)
std::function< IntervalVariable(Model *)> NewOptionalInterval(int64_t min_start, int64_t max_end, int64_t size, Literal is_present)
void AppendVariablesFromCapacityAndDemands(const AffineExpression &capacity, SchedulingDemandHelper *demands_helper, Model *model, std::vector< IntegerVariable > *vars)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::function< int64_t(const Model &)> MinSize(IntervalVariable v)
void AddIntegerVariableFromIntervals(SchedulingConstraintHelper *helper, Model *model, std::vector< IntegerVariable > *vars)
Cuts helpers.
std::function< bool(const Model &)> IsOptional(IntervalVariable v)
IntegerValue ComputeEnergyMinInWindow(IntegerValue start_min, IntegerValue start_max, IntegerValue end_min, IntegerValue end_max, IntegerValue size_min, IntegerValue demand_min, absl::Span< const LiteralValueValue > filtered_energy, IntegerValue window_start, IntegerValue window_end)
In SWIG mode, we don't want anything besides these top-level includes.
std::optional< int64_t > end
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
bool operator>(CachedTaskBounds other) const
LiteralIndex presence_lit
bool operator<(CachedTaskBounds other) const
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
SchedulingDemandHelper * demand_helper
AffineExpression capacity
SchedulingConstraintHelper * task_helper
bool operator<(const ProfileEvent &other) const
bool operator<(TaskTime other) const
bool operator>(TaskTime other) const