17#include "absl/log/check.h"
18#include "absl/strings/str_format.h"
27const char* kUnaryNames[] = {
28 "ENDS_AFTER",
"ENDS_AT",
"ENDS_BEFORE",
"STARTS_AFTER",
29 "STARTS_AT",
"STARTS_BEFORE",
"CROSS_DATE",
"AVOID_DATE",
32const char* kBinaryNames[] = {
33 "ENDS_AFTER_END",
"ENDS_AFTER_START",
"ENDS_AT_END",
34 "ENDS_AT_START",
"STARTS_AFTER_END",
"STARTS_AFTER_START",
35 "STARTS_AT_END",
"STARTS_AT_START",
"STAYS_IN_SYNC"};
37class IntervalUnaryRelation :
public Constraint {
39 IntervalUnaryRelation(Solver*
const s, IntervalVar*
const t, int64_t d,
41 : Constraint(s), t_(t), d_(d), rel_(rel) {}
42 ~IntervalUnaryRelation()
override {}
46 void InitialPropagate()
override;
48 std::string DebugString()
const override {
49 return absl::StrFormat(
"(%s %s %d)", t_->DebugString(), kUnaryNames[rel_],
53 void Accept(ModelVisitor*
const visitor)
const override {
62 IntervalVar*
const t_;
67void IntervalUnaryRelation::Post() {
69 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
74void IntervalUnaryRelation::InitialPropagate() {
77 case Solver::ENDS_AFTER:
83 case Solver::ENDS_BEFORE:
86 case Solver::STARTS_AFTER:
89 case Solver::STARTS_AT:
93 case Solver::STARTS_BEFORE:
96 case Solver::CROSS_DATE:
100 case Solver::AVOID_DATE:
115 return RevAlloc(
new IntervalUnaryRelation(
this, t, d, r));
121class IntervalBinaryRelation :
public Constraint {
126 :
Constraint(s), t1_(t1), t2_(t2), rel_(rel), delay_(delay) {}
127 ~IntervalBinaryRelation()
override {}
129 void Post()
override;
131 void InitialPropagate()
override;
133 std::string DebugString()
const override {
134 return absl::StrFormat(
"(%s %s %s)", t1_->
DebugString(), kBinaryNames[rel_],
138 void Accept(ModelVisitor*
const visitor)
const override {
139 visitor->BeginVisitConstraint(ModelVisitor::kIntervalBinaryRelation,
this);
140 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
141 visitor->VisitIntegerArgument(ModelVisitor::kRelationArgument, rel_);
142 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
143 visitor->EndVisitConstraint(ModelVisitor::kIntervalBinaryRelation,
this);
147 IntervalVar*
const t1_;
148 IntervalVar*
const t2_;
149 const Solver::BinaryIntervalRelation rel_;
150 const int64_t delay_;
153void IntervalBinaryRelation::Post() {
155 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
162void IntervalBinaryRelation::InitialPropagate() {
165 case Solver::ENDS_AFTER_END:
168 case Solver::ENDS_AFTER_START:
171 case Solver::ENDS_AT_END:
174 case Solver::ENDS_AT_START:
177 case Solver::STARTS_AFTER_END:
180 case Solver::STARTS_AFTER_START:
183 case Solver::STARTS_AT_END:
186 case Solver::STARTS_AT_START:
189 case Solver::STAYS_IN_SYNC:
198 case Solver::ENDS_AFTER_END:
201 case Solver::ENDS_AFTER_START:
204 case Solver::ENDS_AT_END:
207 case Solver::ENDS_AT_START:
210 case Solver::STARTS_AFTER_END:
213 case Solver::STARTS_AFTER_START:
216 case Solver::STARTS_AT_END:
219 case Solver::STARTS_AT_START:
222 case Solver::STAYS_IN_SYNC:
234 return RevAlloc(
new IntervalBinaryRelation(
this, t1, t2, r, 0));
240 return RevAlloc(
new IntervalBinaryRelation(
this, t1, t2, r, delay));
246class TemporalDisjunction :
public Constraint {
248 enum State { ONE_BEFORE_TWO, TWO_BEFORE_ONE, UNDECIDED };
250 TemporalDisjunction(Solver*
const s, IntervalVar*
const t1,
251 IntervalVar*
const t2, IntVar*
const alt)
252 : Constraint(s), t1_(t1), t2_(t2), alt_(alt), state_(UNDECIDED) {}
253 ~TemporalDisjunction()
override {}
255 void Post()
override;
256 void InitialPropagate()
override;
257 std::string DebugString()
const override;
262 void Decide(State s);
265 void Accept(ModelVisitor*
const visitor)
const override {
266 visitor->BeginVisitConstraint(ModelVisitor::kIntervalDisjunction,
this);
267 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
268 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
269 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
271 visitor->EndVisitConstraint(ModelVisitor::kIntervalDisjunction,
this);
275 IntervalVar*
const t1_;
276 IntervalVar*
const t2_;
281void TemporalDisjunction::Post() {
282 Solver*
const s = solver();
289 if (alt_ !=
nullptr) {
296void TemporalDisjunction::InitialPropagate() {
297 if (alt_ !=
nullptr) {
300 if (alt_ !=
nullptr && alt_->
Bound()) {
308std::string TemporalDisjunction::DebugString()
const {
310 (out = absl::StrFormat(
"TemporalDisjunction(%s, %s", t1_->
DebugString(),
312 if (alt_ !=
nullptr) {
313 absl::StrAppendFormat(&out,
" => %s", alt_->
DebugString());
319void TemporalDisjunction::TryToDecide() {
320 DCHECK_EQ(UNDECIDED, state_);
324 Decide(TWO_BEFORE_ONE);
326 Decide(ONE_BEFORE_TWO);
331void TemporalDisjunction::RangeDemon1() {
333 case ONE_BEFORE_TWO: {
339 case TWO_BEFORE_ONE: {
351void TemporalDisjunction::RangeDemon2() {
354 case ONE_BEFORE_TWO: {
360 case TWO_BEFORE_ONE: {
373void TemporalDisjunction::RangeAlt() {
374 DCHECK(alt_ !=
nullptr);
375 if (alt_->
Value() == 0) {
376 Decide(ONE_BEFORE_TWO);
378 Decide(TWO_BEFORE_ONE);
382void TemporalDisjunction::Decide(State s) {
384 DCHECK_NE(s, UNDECIDED);
385 if (state_ != UNDECIDED && state_ != s) {
388 solver()->SaveValue(
reinterpret_cast<int*
>(&state_));
390 if (alt_ !=
nullptr) {
391 if (s == ONE_BEFORE_TWO) {
405 return RevAlloc(
new TemporalDisjunction(
this, t1, t2, alt));
410 return RevAlloc(
new TemporalDisjunction(
this, t1, t2,
nullptr));
virtual void SetValue(int64_t v)
This method sets the value of the expression.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual void SetRange(int64_t l, int64_t u)
This method sets both the min and the max of the expression.
virtual void WhenRange(Demon *d)=0
Attach a demon that will watch the min or the max of the expression.
virtual int64_t Value() const =0
virtual void SetEndRange(int64_t mi, int64_t ma)=0
virtual int64_t EndMax() const =0
virtual int64_t EndMin() const =0
These methods query, set, and watch the end position of the interval var.
virtual void SetEndMax(int64_t m)=0
virtual void SetStartRange(int64_t mi, int64_t ma)=0
virtual void SetStartMax(int64_t m)=0
void WhenAnything(Demon *d)
Attaches a demon awakened when anything about this interval changes.
virtual int64_t StartMax() const =0
virtual bool MayBePerformed() const =0
virtual void SetEndMin(int64_t m)=0
virtual void SetStartMin(int64_t m)=0
virtual int64_t StartMin() const =0
virtual bool MustBePerformed() const =0
static const char kRelationArgument[]
static const char kIntervalUnaryRelation[]
static const char kValueArgument[]
static const char kIntervalArgument[]
std::string DebugString() const override
For the time being, Solver is neither MT_SAFE nor MT_HOT.
Constraint * MakeTemporalDisjunction(IntervalVar *t1, IntervalVar *t2, IntVar *alt)
Constraint * MakeIntervalVarRelationWithDelay(IntervalVar *t1, BinaryIntervalRelation r, IntervalVar *t2, int64_t delay)
Constraint * MakeIntervalVarRelation(IntervalVar *t, UnaryIntervalRelation r, int64_t d)
In SWIG mode, we don't want anything besides these top-level includes.
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)