From ed927ca9ea0c27bc7e45ef705605d28f4fdf18a1 Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Sun, 10 Jun 2012 09:51:16 +0000 Subject: [PATCH] support for domain splitting value strategy --- src/constraint_solver/constraint_solver.h | 12 +++- src/constraint_solver/search.cc | 77 ++++++++++++++++++----- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/constraint_solver/constraint_solver.h b/src/constraint_solver/constraint_solver.h index 138b933d1a..3550f4defe 100644 --- a/src/constraint_solver/constraint_solver.h +++ b/src/constraint_solver/constraint_solver.h @@ -452,8 +452,8 @@ class Solver { CHOOSE_PATH, }; - // This enum describes the strategy used to select the next variable value to - // set. + // This enum describes the strategy used to select the next decision + // to apply on this variable. enum IntValueStrategy { // The default behavior is ASSIGN_MIN_VALUE. INT_VALUE_DEFAULT, @@ -474,6 +474,14 @@ class Solver { // of the domain of the selected variable. // The center is defined as (min + max) / 2. ASSIGN_CENTER_VALUE, + + // Split the domain in two around the center, and choose the lower + // part first. + SPLIT_LOWER_HALF, + + // Split the domain in two around the center, and choose the lower + // part first. + SPLIT_UPPER_HALF, }; // This enum is used by Solver::MakePhase to specify how to select variables diff --git a/src/constraint_solver/search.cc b/src/constraint_solver/search.cc index 98ec96860c..dfa116f799 100644 --- a/src/constraint_solver/search.cc +++ b/src/constraint_solver/search.cc @@ -1215,10 +1215,15 @@ int64 RandomValueSelector::Select(const IntVar* const v, int64 id) { class CenterValueSelector : public ValueSelector { public: - CenterValueSelector() {} + CenterValueSelector(const string& name) : name_(name) {} virtual ~CenterValueSelector() {} virtual int64 Select(const IntVar* const v, int64 id); - string DebugString() const { return "AssignCenter"; } + string DebugString() const { + return name_; + } + + private: + const string name_; }; int64 CenterValueSelector::Select(const IntVar* const v, int64 id) { @@ -1756,8 +1761,15 @@ Decision* Solver::MakeAssignVariablesValues(const std::vector& vars, namespace { class BaseAssignVariables : public DecisionBuilder { public: - explicit BaseAssignVariables(BaseVariableAssignmentSelector* const selector) - : selector_(selector) {} + enum Mode { + ASSIGN, + SPLIT_LOWER, + SPLIT_UPPER, + }; + + explicit BaseAssignVariables(BaseVariableAssignmentSelector* const selector, + Mode mode) + : selector_(selector), mode_(mode) {} virtual ~BaseAssignVariables(); virtual Decision* Next(Solver* const s); virtual string DebugString() const; @@ -1765,7 +1777,8 @@ class BaseAssignVariables : public DecisionBuilder { const IntVar* const* vars, int size, VariableSelector* const var_selector, - ValueSelector* const value_selector); + ValueSelector* const value_selector, + BaseAssignVariables::Mode mode); static VariableSelector* MakeVariableSelector(Solver* const s, const IntVar* const* vars, int size, @@ -1830,7 +1843,13 @@ class BaseAssignVariables : public DecisionBuilder { value_selector = s->RevAlloc(new RandomValueSelector); break; case Solver::ASSIGN_CENTER_VALUE: - value_selector = s->RevAlloc(new CenterValueSelector); + value_selector = s->RevAlloc(new CenterValueSelector("AssignCenter")); + break; + case Solver::SPLIT_LOWER_HALF: + value_selector = s->RevAlloc(new CenterValueSelector("SplitLower")); + break; + case Solver::SPLIT_UPPER_HALF: + value_selector = s->RevAlloc(new CenterValueSelector("SplitUpper")); break; default: LOG(FATAL) << "Unknown int value strategy " << val_str; @@ -1845,6 +1864,7 @@ class BaseAssignVariables : public DecisionBuilder { protected: BaseVariableAssignmentSelector* const selector_; + const Mode mode_; }; BaseAssignVariables::~BaseAssignVariables() {} @@ -1854,7 +1874,14 @@ Decision* BaseAssignVariables::Next(Solver* const s) { IntVar* const var = selector_->SelectVariable(s, &id); if (NULL != var) { const int64 value = selector_->SelectValue(var, id); - return s->RevAlloc(new AssignOneVariableValue(var, value)); + switch (mode_) { + case ASSIGN: + return s->RevAlloc(new AssignOneVariableValue(var, value)); + case SPLIT_LOWER: + return s->RevAlloc(new SplitOneVariable(var, value, true)); + case SPLIT_UPPER: + return s->RevAlloc(new SplitOneVariable(var, value, false)); + } } return NULL; } @@ -1868,10 +1895,11 @@ BaseAssignVariables::MakePhase(Solver* const s, const IntVar* const* vars, int size, VariableSelector* const var_selector, - ValueSelector* const value_selector) { + ValueSelector* const value_selector, + BaseAssignVariables::Mode mode) { BaseVariableAssignmentSelector* selector = s->RevAlloc(new VariableAssignmentSelector(var_selector, value_selector)); - return s->RevAlloc(new BaseAssignVariables(selector)); + return s->RevAlloc(new BaseAssignVariables(selector, mode)); } } // namespace @@ -1919,6 +1947,16 @@ DecisionBuilder* Solver::MakePhase(IntVar* const v0, return MakePhase(vars, var_str, val_str); } +BaseAssignVariables::Mode ChooseMode(Solver::IntValueStrategy val_str) { + BaseAssignVariables::Mode mode = BaseAssignVariables::ASSIGN; + if (val_str == Solver::SPLIT_LOWER_HALF) { + mode = BaseAssignVariables::SPLIT_LOWER; + } else if (val_str == Solver::SPLIT_UPPER_HALF) { + mode = BaseAssignVariables::SPLIT_UPPER; + } + return mode; +} + DecisionBuilder* Solver::MakePhase(const std::vector& vars, Solver::IntVarStrategy var_str, Solver::IntValueStrategy val_str) { @@ -1933,7 +1971,8 @@ DecisionBuilder* Solver::MakePhase(const std::vector& vars, vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + ChooseMode(val_str)); } DecisionBuilder* Solver::MakePhase(const std::vector& vars, @@ -1950,7 +1989,8 @@ DecisionBuilder* Solver::MakePhase(const std::vector& vars, vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + ChooseMode(val_str)); } DecisionBuilder* Solver::MakePhase( @@ -1969,7 +2009,8 @@ DecisionBuilder* Solver::MakePhase( vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + BaseAssignVariables::ASSIGN); } DecisionBuilder* Solver::MakePhase( @@ -1988,7 +2029,8 @@ DecisionBuilder* Solver::MakePhase( vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + BaseAssignVariables::ASSIGN); } DecisionBuilder* Solver::MakePhase( @@ -2008,7 +2050,8 @@ DecisionBuilder* Solver::MakePhase( vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + BaseAssignVariables::ASSIGN); } DecisionBuilder* Solver::MakePhase( @@ -2028,7 +2071,8 @@ DecisionBuilder* Solver::MakePhase( vars.data(), vars.size(), var_selector, - value_selector); + value_selector, + BaseAssignVariables::ASSIGN); } DecisionBuilder* Solver::MakePhase(const std::vector& vars, @@ -2062,7 +2106,8 @@ DecisionBuilder* Solver::MakePhase(const std::vector& vars, break; } } - return RevAlloc(new BaseAssignVariables(selector)); + return RevAlloc(new BaseAssignVariables(selector, + BaseAssignVariables::ASSIGN)); } // ----- AssignAllVariablesFromAssignment decision builder -----