diff --git a/constraint_solver/constraint_solver.cc b/constraint_solver/constraint_solver.cc index a9a7431f91..1b269def48 100644 --- a/constraint_solver/constraint_solver.cc +++ b/constraint_solver/constraint_solver.cc @@ -759,7 +759,8 @@ class Search { void EndFail(); void BeginInitialPropagation(); void EndInitialPropagation(); - bool RejectSolution(); + bool AtSolution(); + bool AcceptSolution(); void NoMoreSolutions(); bool LocalOptimum(); bool AcceptDelta(Assignment* delta, Assignment* deltadelta); @@ -1053,16 +1054,28 @@ void Search::EndInitialPropagation() { } } -bool Search::RejectSolution() { - bool res = false; +bool Search::AcceptSolution() { + bool valid = true; for (vector::iterator it = monitors_.begin(); it != monitors_.end(); ++it) { - if ((*it)->RejectSolution()) { - res = true; + if (!(*it)->AcceptSolution()) { + valid = false; } } - return res; + return valid; +} + +bool Search::AtSolution() { + bool should_continue = false; + for (vector::iterator it = monitors_.begin(); + it != monitors_.end(); + ++it) { + if ((*it)->AtSolution()) { + should_continue = true; + } + } + return should_continue; } void Search::NoMoreSolutions() { @@ -1090,7 +1103,9 @@ bool Search::AcceptDelta(Assignment* delta, Assignment* deltadelta) { for (vector::iterator it = monitors_.begin(); it != monitors_.end(); ++it) { - accept = accept && (*it)->AcceptDelta(delta, deltadelta); + if (!(*it)->AcceptDelta(delta, deltadelta)) { + accept = false; + } } return accept; } @@ -1177,7 +1192,8 @@ Solver::Solver(const string& name) greater_equal_var_cst_cache_(NULL), less_equal_var_cst_cache_(NULL), fail_decision_(new FailDecision()), - constraints_(0) { + constraints_(0), + solution_found_(false) { for (int i = 0; i < kNumPriorities; ++i) { demon_runs_[i] = 0; } @@ -1216,11 +1232,11 @@ string Solver::DebugString() const { case IN_SEARCH: out += "IN_SEARCH"; break; - case AFTER_SUCCESS: - out += "AFTER_SUCCESS"; + case AT_SOLUTION: + out += "AT_SOLUTION"; break; - case AFTER_FAILURE: - out += "AFTER_FAILURE"; + case NO_MORE_SOLUTIONS: + out += "NO_MORE_SOLUTIONS"; break; case PROBLEM_INFEASIBLE: out += "PROBLEM_INFEASIBLE"; @@ -1327,10 +1343,10 @@ void Solver::check_alloc_state() { switch (state_) { case OUTSIDE_SEARCH: case IN_SEARCH: - case AFTER_FAILURE: + case NO_MORE_SOLUTIONS: case PROBLEM_INFEASIBLE: break; - case AFTER_SUCCESS: + case AT_SOLUTION: LOG(FATAL) << "allocating at a leaf node"; } } @@ -1466,9 +1482,9 @@ bool Solver::Solve(DecisionBuilder* const db, int size) { NewSearch(db, monitors, size); searches_.back()->set_created_by_solve(true); // Overwrites default. - bool res = NextSolution(); + NextSolution(); EndSearch(); - return res; + return solution_found_; } void Solver::NewSearch(DecisionBuilder* const db, @@ -1534,6 +1550,7 @@ void Solver::NewSearch(DecisionBuilder* const db, BacktrackToSentinel(INITIAL_SEARCH_SENTINEL); state_ = OUTSIDE_SEARCH; + solution_found_ = false; // Push monitors and enter search. for (int i = 0; i < size; ++i) { @@ -1611,7 +1628,7 @@ void Solver::RestartSearch() { Search* const search = searches_.back(); CHECK_NE(0, search->sentinel_pushed_); if (searches_.size() == 1) { // top level. - CHECK(state_ == AFTER_SUCCESS || state_ == AFTER_FAILURE); + CHECK(state_ == AT_SOLUTION || state_ == NO_MORE_SOLUTIONS); if (search->sentinel_pushed_ > 1) { BacktrackToSentinel(ROOT_NODE_SENTINEL); } @@ -1727,11 +1744,11 @@ bool Solver::NextSolution() { switch (state_) { case PROBLEM_INFEASIBLE: return false; - case AFTER_FAILURE: + case NO_MORE_SOLUTIONS: return false; - case AFTER_SUCCESS: { + case AT_SOLUTION: { if (BacktrackOneLevel(&fd)) { // No more solutions. - state_ = AFTER_FAILURE; + state_ = NO_MORE_SOLUTIONS; return false; } state_ = IN_SEARCH; @@ -1822,11 +1839,17 @@ bool Solver::NextSolution() { } } search->IncrementSolutionCounter(); - if (search->RejectSolution()) { + if (search->AcceptSolution()) { + solution_found_ = true; + if (!search->AtSolution() || !CurrentlyInSolve()) { + result = true; + finish = true; + } else { + Fail(); + } + } else { Fail(); } - result = true; - finish = true; } CP_ON_FAIL { queue_->Clear(); if (search->should_finish()) { @@ -1860,7 +1883,7 @@ bool Solver::NextSolution() { search->ClearBuffer(); } if (top_level) { // Manage state after NextSolution(). - state_ = (result ? AFTER_SUCCESS : AFTER_FAILURE); + state_ = (result ? AT_SOLUTION : NO_MORE_SOLUTIONS); } return result; } @@ -1868,12 +1891,10 @@ bool Solver::NextSolution() { void Solver::EndSearch() { CHECK_EQ(1, searches_.size()); Search* const search = searches_.back(); - if (state_ != AFTER_SUCCESS) { // We keep the state of the solver in case - // of success for easy access of values of variables. - BacktrackToSentinel(INITIAL_SEARCH_SENTINEL); - } + BacktrackToSentinel(INITIAL_SEARCH_SENTINEL); search->ExitSearch(); search->Clear(); + state_ = OUTSIDE_SEARCH; } bool Solver::CheckAssignment(Assignment* const solution) { @@ -1922,14 +1943,14 @@ bool Solver::CheckAssignment(Assignment* const solution) { } bool Solver::NestedSolve(DecisionBuilder* const db, - bool restore, - const vector& monitors) { + bool restore, + const vector& monitors) { return NestedSolve(db, restore, monitors.data(), monitors.size()); } bool Solver::NestedSolve(DecisionBuilder* const db, - bool restore, - SearchMonitor* const m1) { + bool restore, + SearchMonitor* const m1) { vector monitors; monitors.push_back(m1); return NestedSolve(db, restore, monitors.data(), monitors.size()); @@ -1940,9 +1961,9 @@ bool Solver::NestedSolve(DecisionBuilder* const db, bool restore) { } bool Solver::NestedSolve(DecisionBuilder* const db, - bool restore, - SearchMonitor* const m1, - SearchMonitor* const m2) { + bool restore, + SearchMonitor* const m1, + SearchMonitor* const m2) { vector monitors; monitors.push_back(m1); monitors.push_back(m2); @@ -1950,10 +1971,10 @@ bool Solver::NestedSolve(DecisionBuilder* const db, } bool Solver::NestedSolve(DecisionBuilder* const db, - bool restore, - SearchMonitor* const m1, - SearchMonitor* const m2, - SearchMonitor* const m3) { + bool restore, + SearchMonitor* const m1, + SearchMonitor* const m2, + SearchMonitor* const m3) { vector monitors; monitors.push_back(m1); monitors.push_back(m2); @@ -1965,14 +1986,15 @@ bool Solver::NestedSolve(DecisionBuilder* const db, bool restore, SearchMonitor* const * monitors, int size) { - scoped_ptr new_search(new Search(this)); + Search new_search(this); for (int i = 0; i < size; ++i) { - new_search->push_monitor(monitors[i]); + new_search.push_monitor(monitors[i]); } - searches_.push_back(new_search.get()); - new_search->EnterSearch(); + searches_.push_back(&new_search); + searches_.back()->set_created_by_solve(true); // Overwrites default. + new_search.EnterSearch(); PushSentinel(INITIAL_SEARCH_SENTINEL); - new_search->set_decision_builder(db); + new_search.set_decision_builder(db); bool res = NextSolution(); if (res) { if (restore) { @@ -1981,8 +2003,8 @@ bool Solver::NestedSolve(DecisionBuilder* const db, JumpToSentinelWhenNested(); } } - new_search->ExitSearch(); - new_search->Clear(); + new_search.ExitSearch(); + new_search.Clear(); searches_.pop_back(); return res; } @@ -2067,7 +2089,8 @@ void SearchMonitor::BeginFail() {} void SearchMonitor::EndFail() {} void SearchMonitor::BeginInitialPropagation() {} void SearchMonitor::EndInitialPropagation() {} -bool SearchMonitor::RejectSolution() { return false; } +bool SearchMonitor::AcceptSolution() { return true; } +bool SearchMonitor::AtSolution() { return false; } void SearchMonitor::NoMoreSolutions() {} bool SearchMonitor::LocalOptimum() { return false; } bool SearchMonitor::AcceptDelta(Assignment* delta, diff --git a/constraint_solver/constraint_solver.h b/constraint_solver/constraint_solver.h index 26e7f229b2..cb661cf002 100644 --- a/constraint_solver/constraint_solver.h +++ b/constraint_solver/constraint_solver.h @@ -31,15 +31,17 @@ // s.AddConstraint(ct_heads); // DecisionBuilder* const db = s.Phase(p, r, Solver::CHOOSE_FIRST_UNBOUND, // Solver::ASSIGN_MIN_VALUE); -// s.Solve(db); +// s.NewSearch(db); +// CHECK(s.NextSolution()); // LG << "rabbits -> " << r->Value() << ", pheasants -> " << p->Value(); // LG << s.DebugString(); +// s.EndSearch(); // } // // which outputs: // rabbits -> 8, pheasants -> 12 // Solver(name = "pheasant", -// state = AFTER_SUCCESS, +// state = OUTSIDE_SEARCH, // branches = 0, // fails = 0, // decisions = 0 @@ -162,11 +164,11 @@ class Solver { // This enum represents the state of the solver w.r.t. the search. enum SolverState { - OUTSIDE_SEARCH, - IN_SEARCH, - AFTER_SUCCESS, - AFTER_FAILURE, - PROBLEM_INFEASIBLE + OUTSIDE_SEARCH, // Before search, after search. + IN_SEARCH, // Executing the search code. + AT_SOLUTION, // After successful NextSolution and before EndSearch. + NO_MORE_SOLUTIONS, // After failed NextSolution and before EndSearch. + PROBLEM_INFEASIBLE // After search, the model is infeasible. }; enum IntVarStrategy { @@ -310,9 +312,15 @@ class Solver { // search - // Top level solve using a decision builder and up to three search monitors, - // usually one for the objective, one for the limits and one to collect - // solutions. + // Top level solve using a decision builder and up to four search + // monitors, usually one for the objective, one for the limits and + // one to collect solutions. Please note that the search is + // backtracked when the Solve() exits. Thus, solutions and values + // should be exported either using a decision builder, or a solution + // collector. You can also decompose with a NewSearch(db), + // NextSolution(), EndSearch() and access each feasible solution + // after each successful call to NextSolution(). Solve() returns + // true if the search has found solutions, false otherwise. bool Solve(DecisionBuilder* const db, const vector& monitors); bool Solve(DecisionBuilder* const db, SearchMonitor* const * monitors, int size); @@ -1664,6 +1672,7 @@ class Solver { LessEqualCstCache* less_equal_var_cst_cache_; scoped_ptr fail_decision_; int constraints_; + bool solution_found_; DISALLOW_COPY_AND_ASSIGN(Solver); }; @@ -1918,10 +1927,15 @@ class SearchMonitor : public BaseObject { // After the initial propagation. virtual void EndInitialPropagation(); - // This method is called when a solution is found. If 'true' is - // returned, this last solution is discarded and the search proceeds - // with the next one. - virtual bool RejectSolution(); + // This method is called when a solution is found. It asserts of the + // solution is valid. A value of false indicate that the solution + // should be discarded. + virtual bool AcceptSolution(); + + // This method is called when a valid solution is found. If the + // return value is true, then search will resume after. If the result + // is false, then search will stop there.. + virtual bool AtSolution(); // When the search tree is finished. virtual void NoMoreSolutions(); @@ -2207,7 +2221,8 @@ class OptimizeVar : public SearchMonitor { virtual void EnterSearch(); virtual void RestartSearch(); virtual void RefuteDecision(Decision* d); - virtual bool RejectSolution(); + virtual bool AtSolution(); + virtual bool AcceptSolution(); virtual string DebugString() const; void ApplyBound(); diff --git a/constraint_solver/constraint_solver.swig b/constraint_solver/constraint_solver.swig index 3e6a10238c..e5824ebd51 100644 --- a/constraint_solver/constraint_solver.swig +++ b/constraint_solver/constraint_solver.swig @@ -232,6 +232,7 @@ class PyLNS : public BaseLNS { %rename (IsMemberVar) MakeIsMemberVar; %rename (LastSolutionCollector) MakeLastSolutionCollector; %rename (Limit) MakeLimit; +// Do not define MakeLocalSearchObjectiveFilter %rename (LocalSearchPhase) MakeLocalSearchPhase; %rename (LocalSearchPhaseParameters) MakeLocalSearchPhaseParameters; %rename (LubyRestart) MakeLubyRestart; @@ -1413,16 +1414,20 @@ class LongResultCallback2 { %rename (makeAllSolutionCollector) MakeAllSolutionCollector; %rename (makeAllowedAssignment) MakeAllowedAssignments; %rename (makeAssignVariableValue) MakeAssignVariableValue; +%rename (makeAssignVariableValues) MakeAssignVariableValues; %rename (makeAssignment) MakeAssignment; %rename (makeBestValueSolutionCollector) MakeBestValueSolutionCollector; %rename (makeBetweenCt) MakeBetweenCt; %rename (makeBoolVar) MakeBoolVar; +%rename (makeConstantRestart) MakeConstantRestart; %rename (makeConvexPiecewiseExpr) MakeConvexPiecewiseExpr; %rename (makeCount) MakeCount; %rename (makeCustomLimit) MakeCustomLimit; +%rename (makeDecisionBuilderFromAssignment) MakeDecisionBuilderFromAssignment; %rename (makeDistribute) MakeDistribute; %rename (makeElement) MakeElement; %rename (makeFailDecision) MakeFailDecision; +%rename (makeFalseConstraint) MakeFalseConstraint; %rename (makeFirstSolutionCollector) MakeFirstSolutionCollector; %rename (makeFixedDurationIntervalVar) MakeFixedDurationIntervalVar; %rename (makeFixedInterval) MakeFixedInterval; @@ -1432,8 +1437,11 @@ class LongResultCallback2 { %rename (makeIsBetweenCt) MakeIsBetweenCt; %rename (makeIsDifferentCstCt) MakeIsDifferentCstCt; %rename (makeIsDifferentCstVar) MakeIsDifferentCstVar; +%rename (makeIsDifferentCstCt) MakeIsDifferentCt; +%rename (makeIsDifferentCstVar) MakeIsDifferentVar; %rename (makeIsEqualCstCt) MakeIsEqualCstCt; %rename (makeIsEqualCstVar) MakeIsEqualCstVar; +%rename (makeIsEqualVar) MakeIsEqualCt; %rename (makeIsEqualVar) MakeIsEqualVar; %rename (makeIsGreaterCstCt) MakeIsGreaterCstCt; %rename (makeIsGreaterCstVar) MakeIsGreaterCstVar; @@ -1449,6 +1457,7 @@ class LongResultCallback2 { %rename (makeLimit) MakeLimit; %rename (makeLocalSearchObjectiveFilter) MakeLocalSearchObjectiveFilter; %rename (makeLocalSearchPhase) MakeLocalSearchPhase; +%rename (makeLocalSearchPhaseParameters) MakeLocalSearchPhaseParameters; %rename (makeLubyRestart) MakeLubyRestart; %rename (makeMapDomain) MakeMapDomain; %rename (makeMax) MakeMax; @@ -1459,10 +1468,10 @@ class LongResultCallback2 { %rename (makeNoCycle) MakeNoCycle; %rename (makeOperator) MakeOperator; %rename (makeOptimize) MakeOptimize; +%rename (makePack) MakePack; %rename (makePathCumul) MakePathCumul; %rename (makePhase) MakePhase; %rename (makeRestoreAssignment) MakeRestoreAssignment; -%rename (makeSolveOnce) MakeSolveOnce; %rename (makeScalProd) MakeScalProd; %rename (makeScalProdEquality) MakeScalProdEquality; %rename (makeScalProdGreaterOrEqual) MakeScalProdGreaterOrEqual; @@ -1472,12 +1481,17 @@ class LongResultCallback2 { %rename (makeSemiContinuousExpr) MakeSemiContinuousExpr; %rename (makeSequence) MakeSequence; %rename (makeSimulatedAnnealing) MakeSimulatedAnnealing; +%rename (makeSolveOnce) MakeSolveOnce; %rename (makeStoreAssignment) MakeStoreAssignment; %rename (makeSum) MakeSum; %rename (makeSumEquality) MakeSumEquality; %rename (makeSumGreaterOrEqual) MakeSumGreaterOrEqual; %rename (makeSumLessOrEqual) MakeSumLessOrEqual; +%rename (makeSymmetryManager) MakeSymmetryManager; %rename (makeTabuSearch) MakeTabuSearch; +%rename (makeTemporalDisjunction) MakeTemporalDisjunction; +%rename (makeTrueConstraint) MakeTrueConstraint; +// Java only. %rename (makeGuidedLocalSearch) MakeGuidedLocalSearch; %rename (value) Value; diff --git a/constraint_solver/constraint_solveri.h b/constraint_solver/constraint_solveri.h index 8918ac4fa1..23c9e9a594 100644 --- a/constraint_solver/constraint_solveri.h +++ b/constraint_solver/constraint_solveri.h @@ -416,21 +416,29 @@ class IntVarLocalSearchOperator : public LocalSearchOperator { public: IntVarLocalSearchOperator(const IntVar* const* vars, int size); virtual ~IntVarLocalSearchOperator(); + // This method should not be overridden. Override OnStart() instead which is + // called before exiting this method. virtual void Start(const Assignment* assignment); virtual bool IsIncremental() const { return false; } int Size() const { return size_; } + // Returns the value in the current assignment of the variable of given index. int64 Value(int64 index) const { DCHECK_LT(index, size_); return values_[index]; } + // Returns the variable of given index. + IntVar* Var(int64 index) const { return vars_[index]; } virtual bool SkipUnchanged(int index) const { return false; } protected: + // Called by Start() after synchronizing the operator with the current + // assignment. Should be overridden instead of Start() to avoid calling + // IntVarLocalSearchOperator::Start explicitly. + virtual void OnStart() {} int64 OldValue(int64 index) const { return old_values_[index]; } void SetValue(int64 index, int64 value); bool Activated(int64 index) const; void Activate(int64 index); void Deactivate(int64 index); - IntVar* Var(int64 index) const { return vars_[index]; } bool ApplyChanges(Assignment* delta, Assignment* deltadelta) const; void RevertChanges(bool incremental); void AddVars(const IntVar* const* vars, int size); @@ -454,7 +462,7 @@ class IntVarLocalSearchOperator : public LocalSearchOperator { // This is the base class for building an LNS operator. An LNS fragment is a // collection of variables which will be relaxed. Fragments are build with // NextFragment(), which returns false if there are no more fragments to build. -// Optionally one can redefine InitFragments, which is called from +// Optionally one can override InitFragments, which is called from // LocalSearchOperator::Start to initialize fragment data. // // Here's a sample relaxing each variable: @@ -483,10 +491,13 @@ class BaseLNS : public IntVarLocalSearchOperator { public: BaseLNS(const IntVar* const* vars, int size); virtual ~BaseLNS(); + // This method should not be overridden (it calls NextFragment()). virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); - virtual void Start(const Assignment* assignment); virtual void InitFragments(); virtual bool NextFragment(vector* fragment) = 0; + protected: + // This method should not be overridden. Override InitFragments() instead. + virtual void OnStart(); }; // ----- ChangeValue Operators ----- @@ -502,7 +513,8 @@ class ChangeValue : public IntVarLocalSearchOperator { virtual ~ChangeValue(); virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); virtual int64 ModifyValue(int64 index, int64 value) = 0; - virtual void Start(const Assignment* assignment); + protected: + virtual void OnStart(); private: int index_; }; @@ -520,7 +532,7 @@ class ChangeValue : public IntVarLocalSearchOperator { // - path iterators: operators need a given number of nodes to define a // neighbor; this class provides the iteration on a given number of (base) // nodes which can be used to define a neighbor (through the BaseNode method) -// Subclasses only need to redefine MakeNeighbor to create neighbors using +// Subclasses only need to override MakeNeighbor to create neighbors using // the services above (no direct manipulation of assignments). class PathOperator : public IntVarLocalSearchOperator { @@ -530,40 +542,44 @@ class PathOperator : public IntVarLocalSearchOperator { int size, int number_of_base_nodes); virtual ~PathOperator() {} - virtual void Start(const Assignment* assignement); virtual bool MakeNeighbor() = 0; virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); + + // TODO(user): Make the following methods protected. virtual bool SkipUnchanged(int index) const; + + // Returns the index of the node after the node of index node_index in the + // current assignment. + int64 Next(int64 node_index) const { + DCHECK(!IsPathEnd(node_index)); + return Value(node_index); + } + + // Returns the index of the path to which the node of index node_index + // belongs in the current assignment. + int64 Path(int64 node_index) const { + return ignore_path_vars_ ? 0LL : Value(node_index + number_of_nexts_); + } + + // Number of next variables. + int number_of_nexts() const { return number_of_nexts_; } protected: - // Returns the index of the variable corresponding to the ith base node + virtual void OnStart(); + // Called by OnStart() after initializing node information. Should be + // overriden instead of OnStart() to avoid calling PathOperator::OnStart + // explicitly. + virtual void OnNodeInitialization() {} + // Returns the index of the variable corresponding to the ith base node. int64 BaseNode(int i) const { return base_nodes_[i]; } int64 StartNode(int i) const { return path_starts_[base_paths_[i]]; } - // Returns the index of the node after i in the current assignment - int64 Next(int64 i) const { - DCHECK(!IsPathEnd(i)); - return Value(i); + int64 OldNext(int64 node_index) const { + DCHECK(!IsPathEnd(node_index)); + return OldValue(node_index); } - int64 OldNext(int64 i) const { - DCHECK(!IsPathEnd(i)); - return OldValue(i); - } - - int64 Path(int64 i) const { - if (ignore_path_vars_) { - return 0; - } else { - return Value(i + number_of_nexts_); - } - } - - int64 OldPath(int64 i) const { - if (ignore_path_vars_) { - return 0; - } else { - return OldValue(i + number_of_nexts_); - } + int64 OldPath(int64 node_index) const { + return ignore_path_vars_ ? 0LL : OldValue(node_index + number_of_nexts_); } // Moves the chain starting after the node before_chain and ending at the node @@ -739,7 +755,7 @@ class SearchLog : public SearchMonitor { virtual ~SearchLog(); virtual void EnterSearch(); virtual void ExitSearch(); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual void BeginFail(); virtual void NoMoreSolutions(); virtual void ApplyDecision(Decision* const decision); @@ -749,7 +765,7 @@ class SearchLog : public SearchMonitor { virtual void BeginInitialPropagation(); virtual void EndInitialPropagation(); protected: - /** Bottleneck function used for all UI related output. */ + /* Bottleneck function used for all UI related output. */ virtual void OutputLine(const string& line); private: static string MemoryUsage(); diff --git a/constraint_solver/expressions.cc b/constraint_solver/expressions.cc index c4bc8ca63b..959cb873a7 100644 --- a/constraint_solver/expressions.cc +++ b/constraint_solver/expressions.cc @@ -25,7 +25,9 @@ #include "util/bitset.h" DEFINE_bool(cp_disable_expression_optimization, false, - "disable special optimization when creating expressions"); + "Disable special optimization when creating expressions."); +DEFINE_bool(cp_share_int_consts, true, + "Share IntConst's with the same value."); #if defined(_MSC_VER) #pragma warning(disable : 4351 4355) @@ -1643,7 +1645,11 @@ IntVar* BuildDomainIntVar(Solver* const s, const int64* const values, int size, IntVar* Solver::MakeIntConst(int64 val, const string& name) { - if (name.empty() && + // If IntConst is going to be named after its creation, + // cp_share_int_consts should be set to false otherwise names can potentially + // be overwritten. + if (FLAGS_cp_share_int_consts && + name.empty() && val >= MIN_CACHED_INT_CONST && val <= MAX_CACHED_INT_CONST) { return cached_constants_[val - MIN_CACHED_INT_CONST]; } @@ -1651,10 +1657,7 @@ IntVar* Solver::MakeIntConst(int64 val, const string& name) { } IntVar* Solver::MakeIntConst(int64 val) { - if (val >= MIN_CACHED_INT_CONST && val <= MAX_CACHED_INT_CONST) { - return cached_constants_[val - MIN_CACHED_INT_CONST]; - } - return RevAlloc(new IntConst(this, val, "")); + return MakeIntConst(val, ""); } void Solver::InitCachedIntConstants() { diff --git a/constraint_solver/local_search.cc b/constraint_solver/local_search.cc index afe710a6a2..1530c73c6a 100644 --- a/constraint_solver/local_search.cc +++ b/constraint_solver/local_search.cc @@ -96,6 +96,7 @@ void IntVarLocalSearchOperator::Start(const Assignment* assignment) { activated_.Set(i, activated); was_activated_.Set(i, activated); } + OnStart(); } void IntVarLocalSearchOperator::SetValue(int64 index, int64 value) { @@ -190,8 +191,7 @@ bool BaseLNS::MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) { return false; } -void BaseLNS::Start(const Assignment* assignment) { - IntVarLocalSearchOperator::Start(assignment); +void BaseLNS::OnStart() { InitFragments(); } @@ -252,8 +252,7 @@ bool ChangeValue::MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) { return false; } -void ChangeValue::Start(const Assignment* assignment) { - IntVarLocalSearchOperator::Start(assignment); +void ChangeValue::OnStart() { index_ = 0; } @@ -296,9 +295,9 @@ PathOperator::PathOperator(const IntVar* const* next_vars, } } -void PathOperator::Start(const Assignment* assignment) { - IntVarLocalSearchOperator::Start(assignment); +void PathOperator::OnStart() { InitializeBaseNodes(); + OnNodeInitialization(); } bool PathOperator::MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) { @@ -539,11 +538,9 @@ class TwoOpt : public PathOperator { } virtual ~TwoOpt() {} virtual bool MakeNeighbor(); - virtual void Start(const Assignment* assignment) { - PathOperator::Start(assignment); - last_ = -1; - } virtual bool IsIncremental() const { return true; } + protected: + virtual void OnNodeInitialization() { last_ = -1; } private: int64 last_base_; int64 last_; @@ -720,15 +717,18 @@ class MakeActiveOperator : public PathOperator { int size) : PathOperator(vars, secondary_vars, size, 1), inactive_node_(0) {} virtual ~MakeActiveOperator() {} - virtual void Start(const Assignment* assignment); virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); virtual bool MakeNeighbor(); + protected: + virtual void OnNodeInitialization(); private: int inactive_node_; }; -void MakeActiveOperator::Start(const Assignment* assignment) { - PathOperator::Start(assignment); +// TODO(user): Add a base class for operators changing the state of a node +// (active/non-active) to factor outwhich share the same code in +// OnNodeInitialization(). +void MakeActiveOperator::OnNodeInitialization() { for (int i = 0; i < Size(); ++i) { if (IsInactive(i)) { inactive_node_ = i; @@ -795,15 +795,15 @@ class SwapActiveOperator : public PathOperator { int size) : PathOperator(vars, secondary_vars, size, 1), inactive_node_(0) {} virtual ~SwapActiveOperator() {} - virtual void Start(const Assignment* assignment); virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); virtual bool MakeNeighbor(); + protected: + virtual void OnNodeInitialization(); private: int inactive_node_; }; -void SwapActiveOperator::Start(const Assignment* assignment) { - PathOperator::Start(assignment); +void SwapActiveOperator::OnNodeInitialization() { for (int i = 0; i < Size(); ++i) { if (IsInactive(i)) { inactive_node_ = i; @@ -856,15 +856,15 @@ class ExtendedSwapActiveOperator : public PathOperator { int size) : PathOperator(vars, secondary_vars, size, 2), inactive_node_(0) {} virtual ~ExtendedSwapActiveOperator() {} - virtual void Start(const Assignment* assignment); virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta); virtual bool MakeNeighbor(); + protected: + virtual void OnNodeInitialization(); private: int inactive_node_; }; -void ExtendedSwapActiveOperator::Start(const Assignment* assignment) { - PathOperator::Start(assignment); +void ExtendedSwapActiveOperator::OnNodeInitialization() { for (int i = 0; i < Size(); ++i) { if (IsInactive(i)) { inactive_node_ = i; @@ -942,7 +942,7 @@ TSPOpt::TSPOpt(const IntVar* const* vars, bool TSPOpt::MakeNeighbor() { vector nodes; int64 chain_end = BaseNode(0); - int64 chain_path = (!ignore_path_vars_) ? Path(chain_end) : 0; + int64 chain_path = Path(chain_end); for (int i = 0; i < chain_length_ + 1; ++i) { nodes.push_back(chain_end); if (IsPathEnd(chain_end)) { @@ -1056,7 +1056,7 @@ bool TSPLns::MakeNeighbor() { vector meta_node_costs; int64 cost = 0; int64 node = StartNode(0); - int64 node_path = (!ignore_path_vars_) ? Path(node) : 0; + int64 node_path = Path(node); while (!IsPathEnd(node)) { int64 next = Next(node); if (ContainsKey(breaks_set, node)) { @@ -1116,13 +1116,12 @@ bool TSPLns::MakeNeighbor() { class NearestNeighbors { public: NearestNeighbors(Solver::IndexEvaluator3* evaluator, - const IntVar* const* vars, - const IntVar* const* secondary_vars, - int vars_size, int size); - void Initialize(const Assignment* assignment); + const PathOperator& path_operator, + int size); + void Initialize(); const vector& Neighbors(int index) const; private: - void ComputeNearest(int row, int path); + void ComputeNearest(int row); static void Pivot(int start, int end, int* neighbors, @@ -1132,9 +1131,7 @@ class NearestNeighbors { vector > neighbors_; Solver::IndexEvaluator3* evaluator_; - scoped_array vars_; - scoped_array secondary_vars_; - int vars_size_; + const PathOperator& path_operator_; const int size_; bool initialized_; @@ -1142,41 +1139,20 @@ class NearestNeighbors { }; NearestNeighbors::NearestNeighbors(Solver::IndexEvaluator3* evaluator, - const IntVar* const* vars, - const IntVar* const* secondary_vars, - int vars_size, + const PathOperator& path_operator, int size) : evaluator_(evaluator), - vars_(NULL), - secondary_vars_(NULL), - vars_size_(vars_size), + path_operator_(path_operator), size_(size), - initialized_(false) { - CHECK_GE(vars_size_, 0); - if (vars_size_ > 0) { - vars_.reset(new IntVar*[vars_size_]); - memcpy(vars_.get(), vars, vars_size_ * sizeof(*vars)); - if (secondary_vars != NULL) { - secondary_vars_.reset(new IntVar*[vars_size_]); - memcpy(secondary_vars_.get(), - secondary_vars, - vars_size_ * sizeof(*secondary_vars)); - } - } -} + initialized_(false) {} -void NearestNeighbors::Initialize(const Assignment* assignment) { +void NearestNeighbors::Initialize() { // TODO(user): recompute if node changes path ? if (!initialized_) { initialized_ = true; - for (int i = 0; i < vars_size_; ++i) { + for (int i = 0; i < path_operator_.number_of_nexts(); ++i) { neighbors_.push_back(vector()); - if (secondary_vars_.get() != NULL - && assignment->Bound(secondary_vars_[i])) { - ComputeNearest(i, assignment->Value(secondary_vars_[i])); - } else { - ComputeNearest(i, 0); - } + ComputeNearest(i); } } } @@ -1185,9 +1161,10 @@ const vector& NearestNeighbors::Neighbors(int index) const { return neighbors_[index]; } -void NearestNeighbors::ComputeNearest(int row, int path) { - // Find size_ nearest neighbors for row of index 'row' - const IntVar* var = vars_[row]; +void NearestNeighbors::ComputeNearest(int row) { + // Find size_ nearest neighbors for row of index 'row'. + const int path = path_operator_.Path(row); + const IntVar* var = path_operator_.Var(row); const int64 var_min = var->Min(); const int var_size = var->Max() - var_min + 1; scoped_array neighbors(new int[var_size]); @@ -1256,8 +1233,9 @@ class LinKernighan : public PathOperator { bool owner, // Owner of callback bool topt); virtual ~LinKernighan(); - virtual void Start(const Assignment* assignment); virtual bool MakeNeighbor(); + protected: + virtual void OnNodeInitialization(); private: static const int kNeighbors; @@ -1283,7 +1261,7 @@ LinKernighan::LinKernighan(const IntVar* const* vars, : PathOperator(vars, secondary_vars, size, 1), evaluator_(evaluator), owner_(owner), - neighbors_(evaluator, vars, secondary_vars, size, kNeighbors), + neighbors_(evaluator, *this, kNeighbors), topt_(topt) {} LinKernighan::~LinKernighan() { @@ -1292,16 +1270,15 @@ LinKernighan::~LinKernighan() { } } -void LinKernighan::Start(const Assignment* assignment) { - PathOperator::Start(assignment); - neighbors_.Initialize(assignment); +void LinKernighan::OnNodeInitialization() { + neighbors_.Initialize(); } bool LinKernighan::MakeNeighbor() { marked_.clear(); int64 node = BaseNode(0); if (IsPathEnd(node)) return false; - int64 path = (!ignore_path_vars_) ? Path(node) : 0; + int64 path = Path(node); int64 base = node; int64 next = Next(node); if (IsPathEnd(next)) return false; @@ -1373,7 +1350,7 @@ const int LinKernighan::kNeighbors = 5 + 1; bool LinKernighan::InFromOut(int64 in_i, int64 in_j, int64* out, int64* gain) { const vector& nexts = neighbors_.Neighbors(in_j); int64 best_gain = kint64min; - int64 path = (!ignore_path_vars_) ? Path(in_i) : 0; + int64 path = Path(in_i); int64 out_cost = evaluator_->Run(in_i, in_j, path); const int64 current_gain = *gain + out_cost; for (int k = 0; k < nexts.size(); ++k) { diff --git a/constraint_solver/search.cc b/constraint_solver/search.cc index 7ec9c57ad5..07430b92cc 100644 --- a/constraint_solver/search.cc +++ b/constraint_solver/search.cc @@ -71,7 +71,7 @@ void SearchLog::ExitSearch() { OutputLine(buffer); } -bool SearchLog::RejectSolution() { +bool SearchLog::AtSolution() { Maintain(); const int depth = solver()->SearchDepth(); string obj_str = ""; @@ -273,10 +273,14 @@ class SearchTrace : public SearchMonitor { virtual void EndInitialPropagation() { LG << prefix_ << " EndInitialPropagation()"; } - virtual bool RejectSolution() { - LG << prefix_ << " RejectSolution()"; + virtual bool AtSolution() { + LG << prefix_ << " AtSolution()"; return false; } + virtual bool AcceptSolution() { + LG << prefix_ << " AcceptSolution()"; + return true; + } virtual void NoMoreSolutions() { LG << prefix_ << " NoMoreSolutions()"; } @@ -1707,10 +1711,7 @@ class FirstSolutionCollector : public SolutionCollector { FirstSolutionCollector(Solver* const s, const Assignment* a); virtual ~FirstSolutionCollector(); virtual void EnterSearch(); - virtual bool RejectSolution(); - void Check(); - virtual void BeginNextDecision(DecisionBuilder* const b); - virtual void RefuteDecision(Decision* const d); + virtual bool AtSolution(); virtual string DebugString() const; private: bool done_; @@ -1728,26 +1729,12 @@ void FirstSolutionCollector::EnterSearch() { done_ = false; } -bool FirstSolutionCollector::RejectSolution() { +bool FirstSolutionCollector::AtSolution() { if (!done_) { PushSolution(); done_ = true; } - return true; -} - -void FirstSolutionCollector::Check() { - if (done_) { - solver()->Fail(); - } -} - -void FirstSolutionCollector::BeginNextDecision(DecisionBuilder* const b) { - Check(); -} - -void FirstSolutionCollector::RefuteDecision(Decision* const d) { - Check(); + return false; } string FirstSolutionCollector::DebugString() const { @@ -1769,7 +1756,7 @@ class LastSolutionCollector : public SolutionCollector { public: LastSolutionCollector(Solver* const s, const Assignment* a); virtual ~LastSolutionCollector(); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual string DebugString() const; }; @@ -1780,7 +1767,7 @@ LastSolutionCollector::LastSolutionCollector(Solver* const s, LastSolutionCollector::~LastSolutionCollector() {} -bool LastSolutionCollector::RejectSolution() { +bool LastSolutionCollector::AtSolution() { PopSolution(); PushSolution(); return true; @@ -1807,7 +1794,7 @@ class BestValueSolutionCollector : public SolutionCollector { bool maximize); virtual ~BestValueSolutionCollector() {} virtual void EnterSearch(); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual string DebugString() const; public: const bool maximize_; @@ -1827,7 +1814,7 @@ void BestValueSolutionCollector::EnterSearch() { best_ = maximize_ ? kint64min : kint64max; } -bool BestValueSolutionCollector::RejectSolution() { +bool BestValueSolutionCollector::AtSolution() { if (prototype_.get() != NULL) { const IntVar* objective = prototype_->Objective(); if (objective != NULL) { @@ -1865,7 +1852,7 @@ class AllSolutionCollector : public SolutionCollector { public: AllSolutionCollector(Solver* const s, const Assignment* a); virtual ~AllSolutionCollector(); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual string DebugString() const; }; @@ -1874,7 +1861,7 @@ AllSolutionCollector::AllSolutionCollector(Solver* const s, const Assignment* a) AllSolutionCollector::~AllSolutionCollector() {} -bool AllSolutionCollector::RejectSolution() { +bool AllSolutionCollector::AtSolution() { PushSolution(); return true; } @@ -1925,14 +1912,24 @@ void OptimizeVar::RefuteDecision(Decision* d) { ApplyBound(); } -bool OptimizeVar::RejectSolution() { +bool OptimizeVar::AcceptSolution() { + const int64 val = var_->Value(); + // This code should never returns false in sequential mode because + // ApplyBound should have been called before. In parallel, this is + // no longer true. That is why we keep it there, just in case. + return (maximize_ && val > best_) || (!maximize_ && val < best_); +} + +bool OptimizeVar::AtSolution() { int64 val = var_->Value(); if (maximize_) { - best_ = std::max(val, best_); + CHECK_GT(val, best_); + best_ = val; } else { - best_ = std::min(val, best_); + CHECK_LT(val, best_); + best_ = val; } - return solver()->CurrentlyInSolve(); + return true; } string OptimizeVar::DebugString() const { @@ -2016,7 +2013,7 @@ class TabuSearch : public Metaheuristic { virtual ~TabuSearch() {} virtual void EnterSearch(); virtual void ApplyDecision(Decision* d); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual bool LocalOptimum(); virtual void AcceptNeighbor(); virtual string DebugString() const { @@ -2140,7 +2137,7 @@ void TabuSearch::ApplyDecision(Decision* const d) { s->AddConstraint(s->MakeNonEquality(objective_, last_)); } -bool TabuSearch::RejectSolution() { +bool TabuSearch::AtSolution() { int64 val = objective_->Value(); if (maximize_) { best_ = std::max(val, best_); @@ -2167,7 +2164,7 @@ bool TabuSearch::RejectSolution() { } assignment_.Store(); - return solver()->CurrentlyInSolve(); + return true; } bool TabuSearch::LocalOptimum() { @@ -2247,7 +2244,7 @@ class SimulatedAnnealing : public Metaheuristic { virtual ~SimulatedAnnealing() {} virtual void EnterSearch(); virtual void ApplyDecision(Decision* d); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual bool LocalOptimum(); virtual void AcceptNeighbor(); virtual string DebugString() const { @@ -2298,7 +2295,7 @@ void SimulatedAnnealing::ApplyDecision(Decision* const d) { } } -bool SimulatedAnnealing::RejectSolution() { +bool SimulatedAnnealing::AtSolution() { const int64 val = objective_->Value(); if (maximize_) { best_ = std::max(val, best_); @@ -2306,7 +2303,7 @@ bool SimulatedAnnealing::RejectSolution() { best_ = std::min(val, best_); } current_ = val; - return solver()->CurrentlyInSolve(); + return true; } bool SimulatedAnnealing::LocalOptimum() { @@ -2458,7 +2455,7 @@ class GuidedLocalSearch : public Metaheuristic { virtual void EnterSearch(); virtual bool AcceptDelta(Assignment* delta, Assignment* deltadelta); virtual void ApplyDecision(Decision* d); - virtual bool RejectSolution(); + virtual bool AtSolution(); virtual bool LocalOptimum(); virtual int64 AssignmentElementPenalty(const Assignment& assignment, int index) = 0; @@ -2591,7 +2588,7 @@ void GuidedLocalSearch::ApplyDecision(Decision* const d) { } } -bool GuidedLocalSearch::RejectSolution() { +bool GuidedLocalSearch::AtSolution() { current_ = objective_->Value(); if (maximize_) { best_ = std::max(current_, best_); @@ -2602,7 +2599,7 @@ bool GuidedLocalSearch::RejectSolution() { current_ += penalized_objective_->Value(); } assignment_.Store(); - return solver()->CurrentlyInSolve(); + return true; } // GLS filtering; compute the penalized value corresponding to the delta and diff --git a/examples/cryptarithm.cc b/examples/cryptarithm.cc index afac249c17..5dfd12c44b 100644 --- a/examples/cryptarithm.cc +++ b/examples/cryptarithm.cc @@ -27,17 +27,17 @@ namespace operations_research { void Cryptoarithmetics() { - scoped_ptr solver(new Solver("cryptarithm")); + Solver solver("cryptarithm"); // model with carry - IntVar* s = solver->MakeIntVar(1, 9, "s"); - IntVar* m = solver->MakeIntVar(1, 9, "m"); - IntVar* o = solver->MakeIntVar(0, 9, "o"); - IntVar* e = solver->MakeIntVar(0, 9, "e"); - IntVar* n = solver->MakeIntVar(0, 9, "n"); - IntVar* d = solver->MakeIntVar(0, 9, "d"); - IntVar* r = solver->MakeIntVar(0, 9, "r"); - IntVar* y = solver->MakeIntVar(0, 9, "y"); + IntVar* s = solver.MakeIntVar(1, 9, "s"); + IntVar* m = solver.MakeIntVar(1, 9, "m"); + IntVar* o = solver.MakeIntVar(0, 9, "o"); + IntVar* e = solver.MakeIntVar(0, 9, "e"); + IntVar* n = solver.MakeIntVar(0, 9, "n"); + IntVar* d = solver.MakeIntVar(0, 9, "d"); + IntVar* r = solver.MakeIntVar(0, 9, "r"); + IntVar* y = solver.MakeIntVar(0, 9, "y"); vector letters; letters.push_back(s); @@ -49,35 +49,35 @@ void Cryptoarithmetics() { letters.push_back(r); letters.push_back(y); - solver->AddConstraint(solver->MakeAllDifferent(letters, false)); + solver.AddConstraint(solver.MakeAllDifferent(letters, false)); // carry variables - IntVar* c1 = solver->MakeIntVar(0, 1, "c1"); - IntVar* c2 = solver->MakeIntVar(0, 1, "c2"); - IntVar* c3 = solver->MakeIntVar(0, 1, "c3"); + IntVar* c1 = solver.MakeIntVar(0, 1, "c1"); + IntVar* c2 = solver.MakeIntVar(0, 1, "c2"); + IntVar* c3 = solver.MakeIntVar(0, 1, "c3"); // initial constraint is separated into four small constraints - IntVar* v1 = solver->MakeSum(e, d)->Var(); - IntVar* v2 = solver->MakeSum(y, solver->MakeProd(c1, 10))->Var(); - solver->AddConstraint(solver->MakeEquality(v1, v2)); + IntVar* v1 = solver.MakeSum(e, d)->Var(); + IntVar* v2 = solver.MakeSum(y, solver.MakeProd(c1, 10))->Var(); + solver.AddConstraint(solver.MakeEquality(v1, v2)); - v1 = solver->MakeSum(solver->MakeSum(c1, n), r)->Var(); - v2 = solver->MakeSum(e, solver->MakeProd(c2, 10))->Var(); - solver->AddConstraint(solver->MakeEquality(v1, v2)); + v1 = solver.MakeSum(solver.MakeSum(c1, n), r)->Var(); + v2 = solver.MakeSum(e, solver.MakeProd(c2, 10))->Var(); + solver.AddConstraint(solver.MakeEquality(v1, v2)); - v1 = solver->MakeSum(solver->MakeSum(c2, e), o)->Var(); - v2 = solver->MakeSum(n, solver->MakeProd(c3, 10))->Var(); - solver->AddConstraint(solver->MakeEquality(v1, v2)); + v1 = solver.MakeSum(solver.MakeSum(c2, e), o)->Var(); + v2 = solver.MakeSum(n, solver.MakeProd(c3, 10))->Var(); + solver.AddConstraint(solver.MakeEquality(v1, v2)); - v1 = solver->MakeSum(solver->MakeSum(c3, s), m)->Var(); - v2 = solver->MakeSum(o, solver->MakeProd(m, 10))->Var(); - solver->AddConstraint(solver->MakeEquality(v1, v2)); + v1 = solver.MakeSum(solver.MakeSum(c3, s), m)->Var(); + v2 = solver.MakeSum(o, solver.MakeProd(m, 10))->Var(); + solver.AddConstraint(solver.MakeEquality(v1, v2)); - DecisionBuilder* const db = solver->MakePhase(letters, - Solver::CHOOSE_FIRST_UNBOUND, - Solver::ASSIGN_MIN_VALUE); - - if (solver->Solve(db)) { + DecisionBuilder* const db = solver.MakePhase(letters, + Solver::CHOOSE_FIRST_UNBOUND, + Solver::ASSIGN_MIN_VALUE); + solver.NewSearch(db); + if (solver.NextSolution()) { CHECK_EQ(s->Value(), 9); CHECK_EQ(m->Value(), 1); CHECK_EQ(o->Value(), 0); @@ -96,8 +96,9 @@ void Cryptoarithmetics() { LG << "R=" << r->Value(); LG << "Y=" << y->Value(); } else { - LG << "Cannot solve problem: number of failures " << solver->failures(); + LG << "Cannot solve problem: number of failures " << solver.failures(); } + solver.EndSearch(); } } // namespace operations_research diff --git a/examples/magic_square.cc b/examples/magic_square.cc index f0f8953569..80e9ed797c 100644 --- a/examples/magic_square.cc +++ b/examples/magic_square.cc @@ -68,7 +68,8 @@ void MagicSquare(int grid_size) { Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE); - if (solver.Solve(db)) { + solver.NewSearch(db); + if (solver.NextSolution()) { for (int n = 0; n < grid_size; ++n) { string output; for (int m = 0; m < grid_size; ++m) { // extract row indices @@ -81,6 +82,7 @@ void MagicSquare(int grid_size) { } else { LG << "No solution found!"; } + solver.EndSearch(); } } // namespace operations_research @@ -96,4 +98,3 @@ int main(int argc, char **argv) { } return 0; } - diff --git a/examples/nqueens.cc b/examples/nqueens.cc index 98963ee005..f2d0b87a99 100644 --- a/examples/nqueens.cc +++ b/examples/nqueens.cc @@ -47,46 +47,6 @@ static const int kKnownUniqueSolutions = 19; namespace operations_research { -class MyFirstSolutionCollector : public SolutionCollector { - public: - MyFirstSolutionCollector(Solver* const s, const Assignment* a); - virtual ~MyFirstSolutionCollector(); - virtual void EnterSearch(); - virtual bool RejectSolution(); - virtual string DebugString() const; - private: - bool done_; -}; - -MyFirstSolutionCollector::MyFirstSolutionCollector(Solver* const s, - const Assignment* a) - : SolutionCollector(s, a), done_(false) {} - - -MyFirstSolutionCollector::~MyFirstSolutionCollector() {} - -void MyFirstSolutionCollector::EnterSearch() { - SolutionCollector::EnterSearch(); - done_ = false; -} - -bool MyFirstSolutionCollector::RejectSolution() { - if (!done_) { - PushSolution(); - done_ = true; - return false; - } - return true; -} - -string MyFirstSolutionCollector::DebugString() const { - if (prototype_.get() == NULL) { - return "MyFirstSolutionCollector()"; - } else { - return "MyFirstSolutionCollector(" + prototype_->DebugString() + ")"; - } -} - class NQueenSymmetry : public SymmetryBreaker { public: NQueenSymmetry(Solver* const s, const vector& vars) @@ -207,7 +167,7 @@ class R270 : public NQueenSymmetry { void NQueens(int size) { CHECK_GE(size, 1); Solver s("nqueens"); - + // model vector queens; for (int i = 0; i < size; ++i) { @@ -228,7 +188,7 @@ void NQueens(int size) { SolutionCollector* const c1 = s.MakeAllSolutionCollector(NULL); Assignment* const a = new Assignment(&s); // store first solution a->Add(queens); - SolutionCollector* const c2 = s.RevAlloc(new MyFirstSolutionCollector(&s, a)); + SolutionCollector* const c2 = s.MakeFirstSolutionCollector(a); delete a; vector monitors; monitors.push_back(c1); @@ -291,7 +251,6 @@ void NQueens(int size) { } } } - } // namespace operations_research int main(int argc, char **argv) { diff --git a/python/magic_sequence_distribute.py b/python/magic_sequence_distribute.py index ed58664ce2..7ea3755e58 100644 --- a/python/magic_sequence_distribute.py +++ b/python/magic_sequence_distribute.py @@ -36,10 +36,12 @@ def main(unused_argv): solver.Add(solver.Distribute(all_vars, all_values, all_vars)) solver.Add(solver.Sum(all_vars) == size) - solver.Solve(solver.Phase(all_vars, - solver.CHOOSE_FIRST_UNBOUND, - solver.ASSIGN_MIN_VALUE)) + solver.NewSearch(solver.Phase(all_vars, + solver.CHOOSE_FIRST_UNBOUND, + solver.ASSIGN_MIN_VALUE)) + solver.NextSolution() print all_vars + solver.EndSearch() if __name__ == '__main__': diff --git a/python/rabbit_pheasant.py b/python/rabbit_pheasant.py index b79b467371..b594dff949 100644 --- a/python/rabbit_pheasant.py +++ b/python/rabbit_pheasant.py @@ -43,13 +43,14 @@ def main(): solver.INT_VALUE_DEFAULT) # And solve. - solver.Solve(db) + solver.NewSearch(db) + solver.NextSolution() # Display output. - print solver print pheasant print rabbit - + solver.EndSearch() + print solver if __name__ == "__main__": main() diff --git a/python/sendmore.py b/python/sendmore.py index abfe3f3e81..0bde745557 100644 --- a/python/sendmore.py +++ b/python/sendmore.py @@ -49,9 +49,12 @@ def main(unused_argv): solver.Add(solver.AllDifferent(letters, True)) - solver.Solve(solver.Phase(letters, solver.INT_VAR_DEFAULT, - solver.INT_VALUE_DEFAULT)) + solver.NewSearch(solver.Phase(letters, + solver.INT_VAR_DEFAULT, + solver.INT_VALUE_DEFAULT)) + solver.NextSolution() print letters + solver.EndSearch() if __name__ == '__main__': diff --git a/python/zebra.py b/python/zebra.py index 62227328b3..bb9384b488 100644 --- a/python/zebra.py +++ b/python/zebra.py @@ -103,9 +103,10 @@ def main(unused_argv): tea, coffee, water, milk, fruit_juice, red, green, yellow, blue, ivory] - if solver.Solve(solver.Phase(all_vars, - solver.INT_VAR_DEFAULT, - solver.INT_VALUE_DEFAULT)): + solver.NewSearch(solver.Phase(all_vars, + solver.INT_VAR_DEFAULT, + solver.INT_VALUE_DEFAULT)) + if solver.NextSolution(): people = [englishman, spaniard, japanese, ukrainian, norwegian] water_drinker = [p for p in people if p.Value() == water.Value()][0] zebra_owner = [p for p in people if p.Value() == zebra.Value()][0] @@ -113,6 +114,7 @@ def main(unused_argv): print 'The %s owns the zebra.' % zebra_owner.name() else: print 'No solutions to the zebra problem, this is unusual!' + solver.EndSearch() if __name__ == '__main__':