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:
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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__':
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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__':
|
||||
|
||||
@@ -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__':
|
||||
|
||||
Reference in New Issue
Block a user