From 8885a7ecb89c66068bfeca6040aae834351b3998 Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Mon, 10 Sep 2012 08:37:41 +0000 Subject: [PATCH] fast path for normal demons --- src/constraint_solver/constraint_solver.cc | 53 ++++++++++++++++- src/constraint_solver/constraint_solver.h | 2 + src/constraint_solver/expressions.cc | 68 ++++++++++++++++------ 3 files changed, 104 insertions(+), 19 deletions(-) diff --git a/src/constraint_solver/constraint_solver.cc b/src/constraint_solver/constraint_solver.cc index 78e55a2a1b..0b5c11d316 100644 --- a/src/constraint_solver/constraint_solver.cc +++ b/src/constraint_solver/constraint_solver.cc @@ -260,6 +260,22 @@ class Queue { } } + void ProcessNormalDemon(Demon* const demon) { + if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) { + solver_->TopPeriodicCheck(); + } + demon->Run(solver_); + } + + void ProcessInstrumentedNormalDemon(Demon* const demon) { + solver_->GetPropagationMonitor()->BeginDemonRun(demon); + if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) { + solver_->TopPeriodicCheck(); + } + demon->Run(solver_); + solver_->GetPropagationMonitor()->EndDemonRun(demon); + } + void Process() { if (!in_process_) { in_process_ = true; @@ -275,7 +291,11 @@ class Queue { void Execute(Demon* const demon) { if (demon->stamp() < stamp_) { if (demon->priority() == Solver::NORMAL_PRIORITY) { - ProcessOneDemon(demon); + if (!instruments_demons_) { + ProcessNormalDemon(demon); + } else { + ProcessInstrumentedNormalDemon(demon); + } } else { DCHECK_EQ(demon->priority(), Solver::DELAYED_PRIORITY); demon->set_stamp(stamp_); @@ -284,6 +304,29 @@ class Queue { } } + void ExecuteAll(const SimpleRevFIFO& demons) { + if (!instruments_demons_) { + for (SimpleRevFIFO::Iterator it(&demons); it.ok(); ++it) { + Demon* const demon = *it; + if (demon->stamp() < stamp_) { + DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY); + if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) { + solver_->TopPeriodicCheck(); + } + demon->Run(solver_); + } + } + } else { + for (SimpleRevFIFO::Iterator it(&demons); it.ok(); ++it) { + Demon* const demon = *it; + if (demon->stamp() < stamp_) { + DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY); + ProcessInstrumentedNormalDemon(demon); + } + } + } + } + void EnqueueVar(Demon* const demon) { DCHECK(demon->priority() == Solver::VAR_PRIORITY); if (demon->stamp() < stamp_) { @@ -1633,6 +1676,10 @@ void Solver::Execute(Demon* const d) { queue_->Execute(d); } +void Solver::ExecuteAll(const SimpleRevFIFO& demons) { + queue_->ExecuteAll(demons); +} + uint64 Solver::stamp() const { return queue_->stamp(); } @@ -2558,6 +2605,10 @@ string PropagationBaseObject::BaseName() const { return ""; } +void PropagationBaseObject::ExecuteAll(const SimpleRevFIFO& demons) { + solver_->ExecuteAll(demons); +} + // ---------- Decision Builder ---------- string DecisionBuilder::DebugString() const { diff --git a/src/constraint_solver/constraint_solver.h b/src/constraint_solver/constraint_solver.h index bfc2eb7d60..5028663a3b 100644 --- a/src/constraint_solver/constraint_solver.h +++ b/src/constraint_solver/constraint_solver.h @@ -2844,6 +2844,7 @@ class Solver { void EnqueueVar(Demon* const d); void EnqueueDelayedDemon(Demon* const d); void Execute(Demon* const d); + void ExecuteAll(const SimpleRevFIFO& demons); void UnfreezeQueue(); void set_queue_action_on_fail(Action* a); void set_queue_cleaner_on_fail(IntVar* const var); @@ -3031,6 +3032,7 @@ class PropagationBaseObject : public BaseObject { void EnqueueDelayedDemon(Demon* const d) { solver_->EnqueueDelayedDemon(d); } void EnqueueVar(Demon* const d) { solver_->EnqueueVar(d); } void Execute(Demon* const d) { solver_->Execute(d); } + void ExecuteAll(const SimpleRevFIFO& demons); // This method sets a callback that will be called if a failure // happens during the propagation of the queue. diff --git a/src/constraint_solver/expressions.cc b/src/constraint_solver/expressions.cc index 5af592612a..74c8165f1c 100644 --- a/src/constraint_solver/expressions.cc +++ b/src/constraint_solver/expressions.cc @@ -753,17 +753,32 @@ class DomainIntVar : public IntVar { void CreateBits(); virtual void WhenBound(Demon* d) { if (min_.Value() != max_.Value()) { - bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + if (d->priority() == Solver::DELAYED_PRIORITY) { + delayed_bound_demons_.PushIfNotTop(solver(), + solver()->RegisterDemon(d)); + } else { + bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + } } } virtual void WhenRange(Demon* d) { if (min_.Value() != max_.Value()) { - range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + if (d->priority() == Solver::DELAYED_PRIORITY) { + delayed_range_demons_.PushIfNotTop(solver(), + solver()->RegisterDemon(d)); + } else { + range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + } } } virtual void WhenDomain(Demon* d) { if (min_.Value() != max_.Value()) { - domain_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + if (d->priority() == Solver::DELAYED_PRIORITY) { + delayed_domain_demons_.PushIfNotTop(solver(), + solver()->RegisterDemon(d)); + } else { + domain_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + } } } @@ -952,6 +967,9 @@ class DomainIntVar : public IntVar { SimpleRevFIFO bound_demons_; SimpleRevFIFO range_demons_; SimpleRevFIFO domain_demons_; + SimpleRevFIFO delayed_bound_demons_; + SimpleRevFIFO delayed_range_demons_; + SimpleRevFIFO delayed_domain_demons_; QueueHandler handler_; bool in_process_; BitSet* bits_; @@ -1801,17 +1819,26 @@ void DomainIntVar::Process() { new_min_ = min_.Value(); new_max_ = max_.Value(); if (min_.Value() == max_.Value()) { - for (SimpleRevFIFO::Iterator it(&bound_demons_); it.ok(); ++it) { - Execute(*it); + ExecuteAll(bound_demons_); + for (SimpleRevFIFO::Iterator it(&delayed_bound_demons_); + it.ok(); + ++it) { + EnqueueDelayedDemon(*it); } } if (min_.Value() != OldMin() || max_.Value() != OldMax()) { - for (SimpleRevFIFO::Iterator it(&range_demons_); it.ok(); ++it) { - Execute(*it); + ExecuteAll(range_demons_); + for (SimpleRevFIFO::Iterator it(&delayed_range_demons_); + it.ok(); + ++it) { + EnqueueDelayedDemon(*it); } } - for (SimpleRevFIFO::Iterator it(&domain_demons_); it.ok(); ++it) { - Execute(*it); + ExecuteAll(domain_demons_); + for (SimpleRevFIFO::Iterator it(&delayed_domain_demons_); + it.ok(); + ++it) { + EnqueueDelayedDemon(*it); } clear_queue_action_on_fail(); ClearInProcess(); @@ -1915,18 +1942,19 @@ class BooleanVar : public IntVar { virtual void RemoveInterval(int64 l, int64 u); virtual void WhenBound(Demon* d) { if (value_ == kUnboundBooleanVarValue) { - bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + if (d->priority() == Solver::DELAYED_PRIORITY) { + delayed_bound_demons_.PushIfNotTop(solver(), + solver()->RegisterDemon(d)); + } else { + bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); + } } } virtual void WhenRange(Demon* d) { - if (value_ == kUnboundBooleanVarValue) { - bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); - } + WhenRange(d); } virtual void WhenDomain(Demon* d) { - if (value_ == kUnboundBooleanVarValue) { - bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d)); - } + WhenRange(d); } void Process(); void Push() { @@ -2006,6 +2034,7 @@ class BooleanVar : public IntVar { private: int value_; SimpleRevFIFO bound_demons_; + SimpleRevFIFO delayed_bound_demons_; Handler handler_; }; @@ -2077,8 +2106,11 @@ void BooleanVar::RemoveInterval(int64 l, int64 u) { void BooleanVar::Process() { DCHECK_NE(value_, kUnboundBooleanVarValue); - for (SimpleRevFIFO::Iterator it(&bound_demons_); it.ok(); ++it) { - Execute(*it); + ExecuteAll(bound_demons_); + for (SimpleRevFIFO::Iterator it(&delayed_bound_demons_); + it.ok(); + ++it) { + EnqueueDelayedDemon(*it); } }