16 #include "absl/strings/str_format.h"
28 const char* kUnaryNames[] = {
29 "ENDS_AFTER",
"ENDS_AT",
"ENDS_BEFORE",
"STARTS_AFTER",
30 "STARTS_AT",
"STARTS_BEFORE",
"CROSS_DATE",
"AVOID_DATE",
33 const char* kBinaryNames[] = {
34 "ENDS_AFTER_END",
"ENDS_AFTER_START",
"ENDS_AT_END",
35 "ENDS_AT_START",
"STARTS_AFTER_END",
"STARTS_AFTER_START",
36 "STARTS_AT_END",
"STARTS_AT_START",
"STAYS_IN_SYNC"};
38 class IntervalUnaryRelation :
public Constraint {
40 IntervalUnaryRelation(Solver*
const s, IntervalVar*
const t,
int64 d,
41 Solver::UnaryIntervalRelation rel)
42 : Constraint(s), t_(t), d_(d), rel_(rel) {}
43 ~IntervalUnaryRelation()
override {}
47 void InitialPropagate()
override;
49 std::string DebugString()
const override {
50 return absl::StrFormat(
"(%s %s %d)", t_->DebugString(), kUnaryNames[rel_],
54 void Accept(ModelVisitor*
const visitor)
const override {
55 visitor->BeginVisitConstraint(ModelVisitor::kIntervalUnaryRelation,
this);
56 visitor->VisitIntervalArgument(ModelVisitor::kIntervalArgument, t_);
57 visitor->VisitIntegerArgument(ModelVisitor::kRelationArgument, rel_);
58 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, d_);
59 visitor->EndVisitConstraint(ModelVisitor::kIntervalUnaryRelation,
this);
63 IntervalVar*
const t_;
65 const Solver::UnaryIntervalRelation rel_;
68 void IntervalUnaryRelation::Post() {
69 if (t_->MayBePerformed()) {
70 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
75 void IntervalUnaryRelation::InitialPropagate() {
76 if (t_->MayBePerformed()) {
78 case Solver::ENDS_AFTER:
82 t_->SetEndRange(d_, d_);
84 case Solver::ENDS_BEFORE:
87 case Solver::STARTS_AFTER:
90 case Solver::STARTS_AT:
91 t_->SetStartRange(d_, d_);
94 case Solver::STARTS_BEFORE:
97 case Solver::CROSS_DATE:
101 case Solver::AVOID_DATE:
102 if (t_->EndMin() > d_) {
104 }
else if (t_->StartMax() < d_) {
113 Constraint* Solver::MakeIntervalVarRelation(IntervalVar*
const t,
114 Solver::UnaryIntervalRelation r,
116 return RevAlloc(
new IntervalUnaryRelation(
this, t, d, r));
122 class IntervalBinaryRelation :
public Constraint {
124 IntervalBinaryRelation(Solver*
const s, IntervalVar*
const t1,
125 IntervalVar*
const t2,
126 Solver::BinaryIntervalRelation rel,
int64 delay)
127 : Constraint(s), t1_(t1), t2_(t2), rel_(rel), delay_(delay) {}
128 ~IntervalBinaryRelation()
override {}
130 void Post()
override;
132 void InitialPropagate()
override;
134 std::string DebugString()
const override {
135 return absl::StrFormat(
"(%s %s %s)", t1_->DebugString(), kBinaryNames[rel_],
139 void Accept(ModelVisitor*
const visitor)
const override {
140 visitor->BeginVisitConstraint(ModelVisitor::kIntervalBinaryRelation,
this);
141 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
142 visitor->VisitIntegerArgument(ModelVisitor::kRelationArgument, rel_);
143 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
144 visitor->EndVisitConstraint(ModelVisitor::kIntervalBinaryRelation,
this);
148 IntervalVar*
const t1_;
149 IntervalVar*
const t2_;
150 const Solver::BinaryIntervalRelation rel_;
154 void IntervalBinaryRelation::Post() {
155 if (t1_->MayBePerformed() && t2_->MayBePerformed()) {
156 Demon* d = solver()->MakeConstraintInitialPropagateCallback(
this);
157 t1_->WhenAnything(d);
158 t2_->WhenAnything(d);
163 void IntervalBinaryRelation::InitialPropagate() {
164 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
166 case Solver::ENDS_AFTER_END:
167 t1_->SetEndMin(t2_->EndMin() + delay_);
169 case Solver::ENDS_AFTER_START:
170 t1_->SetEndMin(t2_->StartMin() + delay_);
172 case Solver::ENDS_AT_END:
173 t1_->SetEndRange(t2_->EndMin() + delay_, t2_->EndMax() + delay_);
175 case Solver::ENDS_AT_START:
176 t1_->SetEndRange(t2_->StartMin() + delay_, t2_->StartMax() + delay_);
178 case Solver::STARTS_AFTER_END:
179 t1_->SetStartMin(t2_->EndMin() + delay_);
181 case Solver::STARTS_AFTER_START:
182 t1_->SetStartMin(t2_->StartMin() + delay_);
184 case Solver::STARTS_AT_END:
185 t1_->SetStartRange(t2_->EndMin() + delay_, t2_->EndMax() + delay_);
187 case Solver::STARTS_AT_START:
188 t1_->SetStartRange(t2_->StartMin() + delay_, t2_->StartMax() + delay_);
190 case Solver::STAYS_IN_SYNC:
191 t1_->SetStartRange(t2_->StartMin() + delay_, t2_->StartMax() + delay_);
192 t1_->SetEndRange(t2_->EndMin() + delay_, t2_->EndMax() + delay_);
197 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
199 case Solver::ENDS_AFTER_END:
200 t2_->SetEndMax(t1_->EndMax() - delay_);
202 case Solver::ENDS_AFTER_START:
203 t2_->SetStartMax(t1_->EndMax() - delay_);
205 case Solver::ENDS_AT_END:
206 t2_->SetEndRange(t1_->EndMin() - delay_, t1_->EndMax() - delay_);
208 case Solver::ENDS_AT_START:
209 t2_->SetStartRange(t1_->EndMin() - delay_, t1_->EndMax() - delay_);
211 case Solver::STARTS_AFTER_END:
212 t2_->SetEndMax(t1_->StartMax() - delay_);
214 case Solver::STARTS_AFTER_START:
215 t2_->SetStartMax(t1_->StartMax() - delay_);
217 case Solver::STARTS_AT_END:
218 t2_->SetEndRange(t1_->StartMin() - delay_, t1_->StartMax() - delay_);
220 case Solver::STARTS_AT_START:
221 t2_->SetStartRange(t1_->StartMin() - delay_, t1_->StartMax() - delay_);
223 case Solver::STAYS_IN_SYNC:
224 t2_->SetStartRange(t1_->StartMin() - delay_, t1_->StartMax() - delay_);
225 t2_->SetEndRange(t1_->EndMin() - delay_, t1_->EndMax() - delay_);
232 Constraint* Solver::MakeIntervalVarRelation(IntervalVar*
const t1,
233 Solver::BinaryIntervalRelation r,
234 IntervalVar*
const t2) {
235 return RevAlloc(
new IntervalBinaryRelation(
this, t1, t2, r, 0));
238 Constraint* Solver::MakeIntervalVarRelationWithDelay(
239 IntervalVar*
const t1, Solver::BinaryIntervalRelation r,
240 IntervalVar*
const t2,
int64 delay) {
241 return RevAlloc(
new IntervalBinaryRelation(
this, t1, t2, r, delay));
247 class TemporalDisjunction :
public Constraint {
249 enum State { ONE_BEFORE_TWO, TWO_BEFORE_ONE, UNDECIDED };
251 TemporalDisjunction(Solver*
const s, IntervalVar*
const t1,
252 IntervalVar*
const t2, IntVar*
const alt)
253 : Constraint(s), t1_(t1), t2_(t2), alt_(alt), state_(UNDECIDED) {}
254 ~TemporalDisjunction()
override {}
256 void Post()
override;
257 void InitialPropagate()
override;
258 std::string DebugString()
const override;
263 void Decide(State s);
266 void Accept(ModelVisitor*
const visitor)
const override {
267 visitor->BeginVisitConstraint(ModelVisitor::kIntervalDisjunction,
this);
268 visitor->VisitIntervalArgument(ModelVisitor::kLeftArgument, t1_);
269 visitor->VisitIntervalArgument(ModelVisitor::kRightArgument, t2_);
270 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
272 visitor->EndVisitConstraint(ModelVisitor::kIntervalDisjunction,
this);
276 IntervalVar*
const t1_;
277 IntervalVar*
const t2_;
282 void TemporalDisjunction::Post() {
283 Solver*
const s = solver();
286 t1_->WhenAnything(d);
289 t2_->WhenAnything(d);
290 if (alt_ !=
nullptr) {
297 void TemporalDisjunction::InitialPropagate() {
298 if (alt_ !=
nullptr) {
299 alt_->SetRange(0, 1);
301 if (alt_ !=
nullptr && alt_->Bound()) {
309 std::string TemporalDisjunction::DebugString()
const {
311 (out = absl::StrFormat(
"TemporalDisjunction(%s, %s", t1_->DebugString(),
312 t2_->DebugString()));
313 if (alt_ !=
nullptr) {
314 absl::StrAppendFormat(&out,
" => %s", alt_->DebugString());
320 void TemporalDisjunction::TryToDecide() {
321 DCHECK_EQ(UNDECIDED, state_);
322 if (t1_->MayBePerformed() && t2_->MayBePerformed() &&
323 (t1_->MustBePerformed() || t2_->MustBePerformed())) {
324 if (t1_->EndMin() > t2_->StartMax()) {
325 Decide(TWO_BEFORE_ONE);
326 }
else if (t2_->EndMin() > t1_->StartMax()) {
327 Decide(ONE_BEFORE_TWO);
332 void TemporalDisjunction::RangeDemon1() {
334 case ONE_BEFORE_TWO: {
335 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
336 t2_->SetStartMin(t1_->EndMin());
340 case TWO_BEFORE_ONE: {
341 if (t1_->MustBePerformed() && t2_->MayBePerformed()) {
342 t2_->SetEndMax(t1_->StartMax());
352 void TemporalDisjunction::RangeDemon2() {
353 if (t1_->MayBePerformed() || t2_->MayBePerformed()) {
355 case ONE_BEFORE_TWO: {
356 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
357 t1_->SetEndMax(t2_->StartMax());
361 case TWO_BEFORE_ONE: {
362 if (t2_->MustBePerformed() && t1_->MayBePerformed()) {
363 t1_->SetStartMin(t2_->EndMin());
374 void TemporalDisjunction::RangeAlt() {
375 DCHECK(alt_ !=
nullptr);
376 if (alt_->Value() == 0) {
377 Decide(ONE_BEFORE_TWO);
379 Decide(TWO_BEFORE_ONE);
383 void TemporalDisjunction::Decide(State s) {
385 DCHECK_NE(s, UNDECIDED);
386 if (state_ != UNDECIDED && state_ != s) {
389 solver()->SaveValue(
reinterpret_cast<int*
>(&state_));
391 if (alt_ !=
nullptr) {
392 if (s == ONE_BEFORE_TWO) {
403 Constraint* Solver::MakeTemporalDisjunction(IntervalVar*
const t1,
404 IntervalVar*
const t2,
406 return RevAlloc(
new TemporalDisjunction(
this, t1, t2, alt));
409 Constraint* Solver::MakeTemporalDisjunction(IntervalVar*
const t1,
410 IntervalVar*
const t2) {
411 return RevAlloc(
new TemporalDisjunction(
this, t1, t2,
nullptr));