diff --git a/src/constraint_solver/constraint_solver.cc b/src/constraint_solver/constraint_solver.cc index 27f121323b..2bbc46f528 100644 --- a/src/constraint_solver/constraint_solver.cc +++ b/src/constraint_solver/constraint_solver.cc @@ -267,6 +267,9 @@ class Queue { solver_->GetPropagationMonitor()->BeginDemonRun(demon); } solver_->demon_runs_[prio]++; + if (solver_->demon_runs_[prio] % 10000 == 0) { + solver_->TopPeriodicCheck(); + } demon->Run(solver_); if (instruments_demons_) { solver_->GetPropagationMonitor()->EndDemonRun(demon); diff --git a/src/constraint_solver/constraint_solver.h b/src/constraint_solver/constraint_solver.h index ae9f8794ab..138b933d1a 100644 --- a/src/constraint_solver/constraint_solver.h +++ b/src/constraint_solver/constraint_solver.h @@ -1451,6 +1451,10 @@ class Solver { int64 mod, IntVar* const y); + // Modulo constraint v % m == y + Constraint* MakeModuloConstraint(IntVar* const x, + IntVar* const mod, + IntVar* const y); // (l <= b <= u) Constraint* MakeBetweenCt(IntVar* const v, int64 l, int64 u); diff --git a/src/constraint_solver/constraints.cc b/src/constraint_solver/constraints.cc index 3e4564c1c0..8d41ec4532 100644 --- a/src/constraint_solver/constraints.cc +++ b/src/constraint_solver/constraints.cc @@ -859,10 +859,52 @@ class Modulo : public Constraint { IntVarIterator* const y_iterator_; std::vector to_remove_; }; + +class VariableModulo : public Constraint { + public: + VariableModulo(Solver* const solver, + IntVar* const x, + IntVar* const mod, + IntVar* const y) + : Constraint(solver), + x_(x), + mod_(mod), + y_(y) { + CHECK_NOTNULL(solver); + CHECK_NOTNULL(x); + CHECK_NOTNULL(mod); + CHECK_NOTNULL(y); + } + + virtual ~VariableModulo() {} + + virtual void Post() { + Solver* const s = solver(); + } + + virtual void InitialPropagate() { + mod_->SetMin(1); + } + + private: + IntVar* const x_; + IntVar* const mod_; + IntVar* const y_; +}; } // namespace Constraint* Solver::MakeModuloConstraint(IntVar* const x, int64 mod, IntVar* const y) { return RevAlloc(new Modulo(this, x, mod, y)); } + +Constraint* Solver::MakeModuloConstraint(IntVar* const x, + IntVar* const mod, + IntVar* const y) { + if (mod->Bound()) { + return MakeModuloConstraint(x, mod->Min(), y); + } else { + return RevAlloc(new VariableModulo(this, x, mod, y)); + } +} } // namespace operations_research