diff --git a/constraint_solver/constraint_solver.h b/constraint_solver/constraint_solver.h index 9132c37cd3..9381ed5e47 100644 --- a/constraint_solver/constraint_solver.h +++ b/constraint_solver/constraint_solver.h @@ -402,7 +402,8 @@ class Solver { STARTS_AFTER_END, STARTS_AFTER_START, STARTS_AT_END, - STARTS_AT_START + STARTS_AT_START, + STAYS_IN_SYNC }; enum UnaryIntervalRelation { diff --git a/constraint_solver/constraint_solver.swig b/constraint_solver/constraint_solver.swig index 5d7b6373bf..6bb2f0950f 100644 --- a/constraint_solver/constraint_solver.swig +++ b/constraint_solver/constraint_solver.swig @@ -808,6 +808,12 @@ namespace operations_research { operations_research::Solver::STARTS_AT_START, other); } + Constraint* StaysInSync(IntervalVar* other) { + return self->solver()->MakeIntervalVarRelation(self, + operations_research::Solver::STAYS_IN_SYNC, + other); + } + } %extend Sequence { diff --git a/constraint_solver/timetabling.cc b/constraint_solver/timetabling.cc index ce942841d4..788492143c 100644 --- a/constraint_solver/timetabling.cc +++ b/constraint_solver/timetabling.cc @@ -41,7 +41,8 @@ const char* kBinaryNames[] = { "STARTS_AFTER_END", "STARTS_AFTER_START", "STARTS_AT_END", - "STARTS_AT_START" + "STARTS_AT_START", + "STAYS_IN_SYNC" }; } // namespace @@ -238,6 +239,16 @@ void IntervalBinaryRelation::InitialPropagate() { t2_->SetStartRange(t1_->StartMin(), t1_->StartMax()); } break; + case Solver::STAYS_IN_SYNC: + if (t2_->MustBePerformed() && t1_->MayBePerformed()) { + t1_->SetStartRange(t2_->StartMin(), t2_->StartMax()); + t1_->SetEndRange(t2_->EndMin(), t2_->EndMax()); + } + if (t1_->MustBePerformed() && t2_->MayBePerformed()) { + t2_->SetStartRange(t1_->StartMin(), t1_->StartMax()); + t2_->SetEndRange(t1_->EndMin(), t1_->EndMax()); + } + break; } } diff --git a/python/simple_meeting.py b/python/simple_meeting.py index 247defae29..0a03cc6493 100644 --- a/python/simple_meeting.py +++ b/python/simple_meeting.py @@ -146,12 +146,10 @@ def main(unused_argv): # All copies are in sync with the original meeting. for p in all_people: - solver.Add(meeting.StartsAtStart(people_meeting_copies[p])) - solver.Add(meeting.EndsAtEnd(people_meeting_copies[p])) + solver.Add(meeting.StaysInSync(people_meeting_copies[p])) for r in all_rooms: - solver.Add(meeting.StartsAtStart(room_meeting_copies[r])) - solver.Add(meeting.EndsAtEnd(room_meeting_copies[r])) + solver.Add(meeting.StaysInSync(room_meeting_copies[r])) # Synchronize persons_presence and meetings. for p in all_people: