14#ifndef OR_TOOLS_SAT_INTERVALS_H_
15#define OR_TOOLS_SAT_INTERVALS_H_
22#include "absl/types/span.h"
63 IntervalVariable
CreateInterval(IntegerVariable start, IntegerVariable end,
64 IntegerVariable size, IntegerValue fixed_size,
65 LiteralIndex is_present);
68 LiteralIndex is_present,
69 bool add_linear_relation);
99 IntegerVariable
SizeVar(IntervalVariable i)
const {
104 return sizes_[i].var;
106 IntegerVariable
StartVar(IntervalVariable i)
const {
111 return starts_[i].var;
113 IntegerVariable
EndVar(IntervalVariable i)
const {
122 IntegerValue
MinSize(IntervalVariable i)
const {
127 IntegerValue
MaxSize(IntervalVariable i)
const {
133 std::vector<IntervalVariable> result;
226 IntegerValue
SizeMin(
int t)
const {
return cached_size_min_[t]; }
231 IntegerValue
StartMin(
int t)
const {
return cached_start_min_[t]; }
232 IntegerValue
EndMin(
int t)
const {
return cached_end_min_[t]; }
233 IntegerValue
StartMax(
int t)
const {
return -cached_negated_start_max_[t]; }
234 IntegerValue
EndMax(
int t)
const {
return -cached_negated_end_max_[t]; }
251 return cached_shifted_start_min_[t];
257 return -cached_negated_shifted_end_max_[t];
274 IntegerValue
GetMinOverlap(
int t, IntegerValue start, IntegerValue end)
const;
314 return &integer_reason_;
326 ABSL_MUST_USE_RESULT
bool IncreaseStartMin(
int t, IntegerValue new_start_min);
327 ABSL_MUST_USE_RESULT
bool DecreaseEndMax(
int t, IntegerValue new_end_max);
336 const std::vector<AffineExpression>&
Starts()
const {
return starts_; }
337 const std::vector<AffineExpression>&
Ends()
const {
return ends_; }
338 const std::vector<AffineExpression>&
Sizes()
const {
return sizes_; }
347 bool watch_start_max =
true,
348 bool watch_end_max =
true)
const;
356 absl::Span<const int> map_to_other_helper,
357 IntegerValue event) {
358 CHECK(other_helper !=
nullptr);
359 other_helper_ = other_helper;
360 map_to_other_helper_ = map_to_other_helper;
361 event_for_other_helper_ = event;
383 void InitSortedVectors();
384 ABSL_MUST_USE_RESULT
bool UpdateCachedValues(
int t);
393 void AddOtherReason(
int t);
396 void ImportOtherReasons();
403 bool current_time_direction_ =
true;
407 std::vector<AffineExpression> starts_;
408 std::vector<AffineExpression> ends_;
409 std::vector<AffineExpression> sizes_;
410 std::vector<LiteralIndex> reason_for_presence_;
414 std::vector<AffineExpression> minus_starts_;
415 std::vector<AffineExpression> minus_ends_;
418 int previous_level_ = 0;
421 std::vector<IntegerValue> cached_size_min_;
422 std::vector<IntegerValue> cached_start_min_;
423 std::vector<IntegerValue> cached_end_min_;
424 std::vector<IntegerValue> cached_negated_start_max_;
425 std::vector<IntegerValue> cached_negated_end_max_;
426 std::vector<IntegerValue> cached_shifted_start_min_;
427 std::vector<IntegerValue> cached_negated_shifted_end_max_;
430 std::vector<TaskTime> task_by_increasing_start_min_;
431 std::vector<TaskTime> task_by_increasing_end_min_;
432 std::vector<TaskTime> task_by_decreasing_start_max_;
433 std::vector<TaskTime> task_by_decreasing_end_max_;
437 std::vector<TaskTime> task_by_increasing_shifted_start_min_;
438 std::vector<TaskTime> task_by_negated_shifted_end_max_;
439 bool recompute_shifted_start_min_ =
true;
440 bool recompute_negated_shifted_end_max_ =
true;
444 bool recompute_all_cache_ =
true;
445 std::vector<bool> recompute_cache_;
448 std::vector<Literal> literal_reason_;
449 std::vector<IntegerLiteral> integer_reason_;
453 absl::Span<const int> map_to_other_helper_;
454 IntegerValue event_for_other_helper_;
455 std::vector<bool> already_added_to_other_reasons_;
463 return integer_trail_->
IsFixed(starts_[t]);
467 return integer_trail_->
IsFixed(ends_[t]);
471 return integer_trail_->
IsFixed(sizes_[t]);
489 integer_reason_.clear();
490 literal_reason_.clear();
493 already_added_to_other_reasons_.assign(
NumTasks(),
false);
501 literal_reason_.push_back(
Literal(reason_for_presence_[t]).Negated());
509 literal_reason_.push_back(
Literal(reason_for_presence_[t]));
517inline void SchedulingConstraintHelper::AddGenericReason(
540 slack, {IntegerValue(1), IntegerValue(1)},
550 AddGenericReason(sizes_[t].Negated(), -
lower_bound, minus_ends_[t],
558 AddGenericReason(sizes_[t],
upper_bound, ends_[t], minus_starts_[t]);
565 AddGenericReason(minus_starts_[t], -
lower_bound, minus_ends_[t], sizes_[t]);
572 AddGenericReason(starts_[t],
upper_bound, ends_[t], sizes_[t].Negated());
579 AddGenericReason(minus_ends_[t], -
lower_bound, minus_starts_[t],
580 sizes_[t].Negated());
587 AddGenericReason(ends_[t],
upper_bound, starts_[t], sizes_[t]);
591 int t, IntegerValue energy_min, IntegerValue
time) {
601 int t, IntegerValue time_min, IntegerValue time_max) {
602 const IntegerValue energy_min =
SizeMin(t);
603 CHECK_LE(time_min + energy_min, time_max);
609 if (
EndMax(t) <= time_max) {
622 IntervalVariable v) {
628inline std::function<IntegerVariable(
const Model&)>
EndVar(IntervalVariable v) {
635 IntervalVariable v) {
641inline std::function<int64_t(
const Model&)>
MinSize(IntervalVariable v) {
647inline std::function<int64_t(
const Model&)>
MaxSize(IntervalVariable v) {
660 IntervalVariable v) {
678 IntegerVariable start, IntegerVariable end, IntegerVariable size) {
686 int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size) {
697 int64_t min_start, int64_t max_end, int64_t size,
Literal is_present) {
702 IntegerValue(size), is_present.
Index());
706inline std::function<IntervalVariable(Model*)>
708 int64_t size,
Literal is_present) {
711 const IntegerVariable start =
713 const IntegerVariable end =
717 integer_trail->MarkIntegerVariableAsOptional(end, is_present);
724 IntegerVariable start, IntegerVariable end, IntegerVariable size,
728 start, end, size, IntegerValue(0), is_present.
Index());
732inline std::function<IntervalVariable(Model*)>
734 int64_t min_size, int64_t max_size,
747 IntervalVariable parent,
const std::vector<IntervalVariable>& members) {
752 std::vector<Literal> presences;
753 std::vector<IntegerValue> sizes;
756 std::vector<LiteralWithCoeff> sat_ct;
757 for (
const IntervalVariable member : members) {
759 const Literal is_present = intervals->PresenceLiteral(member);
768 CHECK(integer_trail->IsFixed(intervals->Size(member)));
769 presences.push_back(is_present);
770 sizes.push_back(intervals->MinSize(member));
773 model->Add(
IsOneOf(intervals->SizeVar(parent), presences, sizes));
779 std::vector<IntegerVariable> starts;
780 starts.reserve(members.size());
781 for (
const IntervalVariable member : members) {
782 starts.push_back(intervals->StartVar(member));
788 std::vector<IntegerVariable> ends;
789 ends.reserve(members.size());
790 for (
const IntervalVariable member : members) {
791 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)
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)
DEFINE_INT_TYPE(ClauseIndex, int)
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.
IntegerLiteral LowerOrEqual(IntegerValue bound) const
bool operator<(TaskTime other) const
bool operator>(TaskTime other) const