Solve() now backtracks at the end/ RejectSolution on SearchMonitor is now split into AcceptSolution() and AtSolution/ There is a new virtual OnStart() on neighborhoods/Examples were tweaked to adapt to the new API

This commit is contained in:
lperron@google.com
2010-10-06 16:04:31 +00:00
parent e0c66e81da
commit 672aa0605c
14 changed files with 310 additions and 296 deletions

View File

@@ -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<SearchMonitor*>::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<SearchMonitor*>::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<SearchMonitor*>::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<SearchMonitor*>& monitors) {
bool restore,
const vector<SearchMonitor*>& 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<SearchMonitor*> 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<SearchMonitor*> 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<SearchMonitor*> 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<Search> 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,

View File

@@ -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<SearchMonitor*>& 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<Decision> 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();

View File

@@ -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;

View File

@@ -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<int>* 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();

View File

@@ -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() {

View File

@@ -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<int64> 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<int64> 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<int>& 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<vector<int> > neighbors_;
Solver::IndexEvaluator3* evaluator_;
scoped_array<IntVar*> vars_;
scoped_array<IntVar*> 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<int>());
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<int>& 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<int> 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<int>& 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) {

View File

@@ -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

View File

@@ -27,17 +27,17 @@
namespace operations_research {
void Cryptoarithmetics() {
scoped_ptr<Solver> 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<IntVar*> 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

View File

@@ -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;
}

View File

@@ -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<IntVar*>& vars)
@@ -207,7 +167,7 @@ class R270 : public NQueenSymmetry {
void NQueens(int size) {
CHECK_GE(size, 1);
Solver s("nqueens");
// model
vector<IntVar*> 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<SearchMonitor*> monitors;
monitors.push_back(c1);
@@ -291,7 +251,6 @@ void NQueens(int size) {
}
}
}
} // namespace operations_research
int main(int argc, char **argv) {

View File

@@ -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__':

View File

@@ -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()

View File

@@ -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__':

View File

@@ -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__':