replace old expression cache implementation; move and hide LocalSearch and NestedSolveDecision classes

This commit is contained in:
lperron@google.com
2011-09-08 00:36:56 +00:00
parent 0ad400e79c
commit 8ac92abf32
6 changed files with 312 additions and 396 deletions

View File

@@ -1304,13 +1304,10 @@ Solver::Solver(const string& name, const SolverParameters& parameters)
demon_monitor_(BuildDemonMonitor(parameters.profile_level)),
true_constraint_(NULL),
false_constraint_(NULL),
equality_var_cst_cache_(NULL),
unequality_var_cst_cache_(NULL),
greater_equal_var_cst_cache_(NULL),
less_equal_var_cst_cache_(NULL),
fail_decision_(new FailDecision()),
constraint_index_(0),
additional_constraint_index_(0) {
additional_constraint_index_(0),
model_cache_(NULL) {
Init();
}
@@ -1338,16 +1335,15 @@ Solver::Solver(const string& name)
demon_monitor_(BuildDemonMonitor(parameters_.profile_level)),
true_constraint_(NULL),
false_constraint_(NULL),
equality_var_cst_cache_(NULL),
unequality_var_cst_cache_(NULL),
greater_equal_var_cst_cache_(NULL),
less_equal_var_cst_cache_(NULL),
fail_decision_(new FailDecision()),
constraint_index_(0),
additional_constraint_index_(0) {
additional_constraint_index_(0),
model_cache_(NULL) {
Init();
}
extern ModelCache* BuildModelCache(Solver* const solver);
void Solver::Init() {
for (int i = 0; i < kNumPriorities; ++i) {
demon_runs_[i] = 0;
@@ -1356,9 +1352,9 @@ void Solver::Init() {
PushSentinel(SOLVER_CTOR_SENTINEL);
InitCachedIntConstants(); // to be called after the SENTINEL is set.
InitCachedConstraint(); // Cache the true constraint.
InitBoolVarCaches();
InitBuilders();
timer_->Restart();
model_cache_.reset(BuildModelCache(this));
}
Solver::~Solver() {

View File

@@ -114,9 +114,7 @@ class Demon;
class DemonMonitor;
class DemonProfiler;
class Dimension;
class EqualityVarCstCache;
class ExpressionCache;
class GreaterEqualCstCache;
class IntExpr;
class IntVar;
class IntVarAssignmentProto;
@@ -124,10 +122,10 @@ class IntVarElement;
class IntervalVar;
class IntervalVarAssignmentProto;
class IntervalVarElement;
class LessEqualCstCache;
class LocalSearchFilter;
class LocalSearchOperator;
class LocalSearchPhaseParameters;
class ModelCache;
class ModelVisitor;
class MPSolver;
class NoGoodManager;
@@ -145,7 +143,6 @@ class SolutionCollector;
class SolutionPool;
class Solver;
class SymmetryBreaker;
class UnequalityVarCstCache;
struct StateInfo;
struct Trail;
template <class T> class ConstPtrArray;
@@ -2275,6 +2272,8 @@ class Solver {
Demon* RegisterDemon(Demon* const d);
// Returns the active search, NULL outside search.
Search* ActiveSearch() const;
// Returns the cache of the model.
ModelCache* Cache() const;
friend class BaseIntExpr;
friend class Constraint;
@@ -2285,7 +2284,6 @@ class Solver {
friend class PropagationBaseObject;
friend class Queue;
friend class SearchMonitor;
friend class VarCstCache;
#ifndef SWIG
friend void InternalSaveBooleanVarValue(Solver* const, IntVar* const);
@@ -2345,7 +2343,6 @@ class Solver {
void InitCachedIntConstants();
void InitCachedConstraint();
void InitBoolVarCaches();
void InitBuilders();
void DeleteBuilders();
@@ -2393,11 +2390,6 @@ class Solver {
Constraint* true_constraint_;
Constraint* false_constraint_;
// status var caches:
EqualityVarCstCache* equality_var_cst_cache_;
UnequalityVarCstCache* unequality_var_cst_cache_;
GreaterEqualCstCache* greater_equal_var_cst_cache_;
LessEqualCstCache* less_equal_var_cst_cache_;
scoped_ptr<Decision> fail_decision_;
int constraint_index_;
int additional_constraint_index_;
@@ -2407,6 +2399,8 @@ class Solver {
hash_map<string, ConstraintBuilder*> constraint_builders_;
hash_map<string, IntervalVariableBuilder*> interval_builders_;
scoped_ptr<ModelCache> model_cache_;
DISALLOW_COPY_AND_ASSIGN(Solver);
};

View File

@@ -384,8 +384,6 @@ Demon* MakeDelayedConstraintDemon2(Solver* const s,
#endif // !defined(SWIG)
class NestedSolveDecision;
// ---------- Local search operators ----------
// A local search operator is an object which defines the neighborhood of a
@@ -707,56 +705,6 @@ class IntVarLocalSearchFilter : public LocalSearchFilter {
hash_map<const IntVar*, int64> var_to_index_;
};
// ----- Local search decision builder -----
// Given a first solution (resulting from either an initial assignment or the
// result of a decision builder), it searches for neighbors using a local
// search operator. The first solution corresponds to the first leaf of the
// search.
// The local search applies to the variables contained either in the assignment
// or the vector of variables passed.
class LocalSearch : public DecisionBuilder {
public:
LocalSearch(Assignment* const assignment,
SolutionPool* const pool,
LocalSearchOperator* const ls_operator,
DecisionBuilder* const sub_decision_builder,
SearchLimit* const limit,
const std::vector<LocalSearchFilter*>& filters);
// TODO(user): find a way to not have to pass vars here: redundant with
// variables in operators
LocalSearch(IntVar* const* vars,
int size,
SolutionPool* const pool,
DecisionBuilder* const first_solution,
LocalSearchOperator* const ls_operator,
DecisionBuilder* const sub_decision_builder,
SearchLimit* const limit,
const std::vector<LocalSearchFilter*>& filters);
virtual ~LocalSearch();
virtual Decision* Next(Solver* const solver);
virtual string DebugString() const {
return "LocalSearch";
}
virtual void Accept(ModelVisitor* const visitor) const;
protected:
void PushFirstSolutionDecision(DecisionBuilder* first_solution);
void PushLocalSearchDecision();
private:
Assignment* assignment_;
SolutionPool* const pool_;
LocalSearchOperator* const ls_operator_;
DecisionBuilder* const sub_decision_builder_;
std::vector<NestedSolveDecision*> nested_decisions_;
int nested_decision_index_;
SearchLimit* const limit_;
const std::vector<LocalSearchFilter*> filters_;
bool has_started_;
};
// ---------- SymmetryBreaker ----------
class SymmetryManager;
@@ -951,6 +899,10 @@ class ModelCache {
VAR_CONSTANT_MAX,
VAR_CONSTANT_MIN,
VAR_CONSTANT_SUM,
VAR_CONSTANT_IS_EQUAL,
VAR_CONSTANT_IS_NOT_EQUAL,
VAR_CONSTANT_IS_GREATER_OR_EQUAL,
VAR_CONSTANT_IS_LESS_OR_EQUAL,
VAR_CONSTANT_EXPRESSION_MAX,
};

View File

@@ -333,128 +333,6 @@ class IsEqualCstCt : public Constraint {
};
} // namespace
// ---------- VarCstCache ----------
class VarCstCache : public BaseObject {
public:
explicit VarCstCache(Solver* const s)
: solver_(s), size_(FLAGS_cache_initial_size), counter_(0) {
array_ = s->UnsafeRevAllocArray(new Cell*[size_]);
for (int i = 0; i < size_; ++i) {
array_[i] = NULL;
}
}
virtual ~VarCstCache() {}
void Insert(IntVar* const var,
int64 value,
IntVar* const boolvar) {
int code = HashCode(var, value) % size_;
Cell* tmp = array_[code];
while (tmp != NULL) {
if (tmp->value == value && tmp->var == var) {
return;
}
tmp = tmp->next;
}
UnsafeInsert(var, value, boolvar);
}
Solver* const solver() const { return solver_; }
protected:
IntVar* Find(IntVar* const var, int64 value) const {
int code = HashCode(var, value) % size_;
Cell* tmp = array_[code];
while (tmp) {
if (tmp->value == value && tmp->var == var) {
return tmp->boolvar;
}
tmp = tmp->next;
}
return NULL;
// TODO(user): bench optim that moves the found cell first in the list.
}
void UnsafeInsert(IntVar* const var, int64 value, IntVar* const boolvar) {
int code = HashCode(var, value) % size_;
Cell* tmp = array_[code];
Cell* cell = solver_->UnsafeRevAlloc(new Cell(var, value, boolvar, tmp));
solver_->SaveValue(reinterpret_cast<void**>(&array_[code]));
array_[code] = cell;
solver_->SaveAndAdd(&counter_, 1);
if (counter_ > 2 * size_) {
Double();
}
}
private:
struct Cell {
public:
Cell(IntVar* const v, int64 c, IntVar* b, Cell* n)
: var(v), value(c), boolvar(b), next(n) {}
IntVar* const var;
const int64 value;
IntVar* const boolvar;
Cell* next;
};
static uint64 HashCode(IntVar* const var, int64 value) {
return ((reinterpret_cast<uint64>(var) >> 4) * 3 + value * 5);
}
void Double() {
Cell** old_cell_array = array_;
const int old_size = size_;
solver_->SaveValue(&size_);
size_ *= 2;
solver_->SaveValue(reinterpret_cast<void**>(&array_));
array_ = solver_->UnsafeRevAllocArray(new Cell*[size_]);
for (int i = 0; i < size_; ++i) {
array_[i] = NULL;
}
for (int i = 0; i < old_size; ++i) {
Cell* tmp = old_cell_array[i];
while (tmp != NULL) {
Cell* to_reinsert = tmp;
tmp = tmp->next;
int code = HashCode(to_reinsert->var, to_reinsert->value) % size_;
Cell* new_next = array_[code];
solver_->SaveValue(reinterpret_cast<void**>(&to_reinsert->next));
to_reinsert->next = new_next;
array_[code] = to_reinsert;
}
}
}
Solver* const solver_;
Cell** array_;
int size_;
int counter_;
};
// ---------- EqualityVarCstCache ----------
class EqualityVarCstCache : public VarCstCache {
public:
explicit EqualityVarCstCache(Solver* const s) : VarCstCache(s) {}
virtual ~EqualityVarCstCache() {}
IntVar* VarEqCstStatus(IntVar* const var, int64 value) {
IntVar* boolvar = Find(var, value);
if (!boolvar) {
boolvar = solver()->MakeBoolVar(
StringPrintf("StatusVar<%s == %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
solver()->RevAlloc(new IsEqualCstCt(solver(), var, value, boolvar));
solver()->AddConstraint(maintain);
UnsafeInsert(var, value, boolvar);
}
return boolvar;
}
};
IntVar* Solver::MakeIsEqualCstVar(IntVar* const var, int64 value) {
if (value == var->Min()) {
return MakeIsLessOrEqualCstVar(var, value);
@@ -468,23 +346,47 @@ IntVar* Solver::MakeIsEqualCstVar(IntVar* const var, int64 value) {
if (var->Bound() && var->Value() == value) {
return MakeIntConst(1LL);
}
return equality_var_cst_cache_->VarEqCstStatus(var, value);
IntExpr* const cache = model_cache_->FindVarConstantExpression(
var,
value,
ModelCache::VAR_CONSTANT_IS_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
IntVar* const boolvar = MakeBoolVar(
StringPrintf("StatusVar<%s == %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
RevAlloc(new IsEqualCstCt(this, var, value, boolvar));
AddConstraint(maintain);
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_EQUAL);
return boolvar;
}
}
Constraint* Solver::MakeIsEqualCstCt(IntVar* const v, int64 c,
IntVar* const b) {
CHECK_EQ(this, v->solver());
CHECK_EQ(this, b->solver());
if (c == v->Min()) {
return MakeIsLessOrEqualCstCt(v, c, b);
Constraint* Solver::MakeIsEqualCstCt(IntVar* const var,
int64 value,
IntVar* const boolvar) {
CHECK_EQ(this, var->solver());
CHECK_EQ(this, boolvar->solver());
if (value == var->Min()) {
return MakeIsLessOrEqualCstCt(var, value, boolvar);
}
if (c == v->Max()) {
return MakeIsGreaterOrEqualCstCt(v, c, b);
if (value == var->Max()) {
return MakeIsGreaterOrEqualCstCt(var, value, boolvar);
}
// TODO(user) : what happens if the constraint is not posted?
// The cache becomes tainted.
equality_var_cst_cache_->Insert(v, c, b);
return RevAlloc(new IsEqualCstCt(this, v, c, b));
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_EQUAL);
return RevAlloc(new IsEqualCstCt(this, var, value, boolvar));
}
// ----- is_diff_cst Constraint -----
@@ -544,29 +446,6 @@ class IsDiffCstCt : public Constraint {
};
} // namespace
// ---------- UnequalityVarCstCache ----------
class UnequalityVarCstCache : public VarCstCache {
public:
explicit UnequalityVarCstCache(Solver* const s) : VarCstCache(s) {}
virtual ~UnequalityVarCstCache() {}
IntVar* VarNonEqCstStatus(IntVar* const var, int64 value) {
IntVar* boolvar = Find(var, value);
if (!boolvar) {
boolvar = solver()->MakeBoolVar(StringPrintf("StatusVar<%s == %"
GG_LL_FORMAT "d>",
var->name().c_str(),
value));
Constraint* const maintain =
solver()->RevAlloc(new IsDiffCstCt(solver(), var, value, boolvar));
solver()->AddConstraint(maintain);
UnsafeInsert(var, value, boolvar);
}
return boolvar;
}
};
IntVar* Solver::MakeIsDifferentCstVar(IntVar* const var, int64 value) {
if (value == var->Min()) {
return MakeIsGreaterOrEqualCstVar(var, value + 1);
@@ -580,21 +459,45 @@ IntVar* Solver::MakeIsDifferentCstVar(IntVar* const var, int64 value) {
if (var->Bound() && var->Value() == value) {
return MakeIntConst(0LL);
}
return unequality_var_cst_cache_->VarNonEqCstStatus(var, value);
IntExpr* const cache = model_cache_->FindVarConstantExpression(
var,
value,
ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
IntVar* const boolvar = MakeBoolVar(
StringPrintf("StatusVar<%s != %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
RevAlloc(new IsDiffCstCt(this, var, value, boolvar));
AddConstraint(maintain);
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
return boolvar;
}
}
Constraint* Solver::MakeIsDifferentCstCt(IntVar* const v, int64 c,
IntVar* const b) {
CHECK_EQ(this, v->solver());
CHECK_EQ(this, b->solver());
if (c == v->Min()) {
return MakeIsGreaterOrEqualCstCt(v, c + 1, b);
Constraint* Solver::MakeIsDifferentCstCt(IntVar* const var,
int64 value,
IntVar* const boolvar) {
CHECK_EQ(this, var->solver());
CHECK_EQ(this, boolvar->solver());
if (value == var->Min()) {
return MakeIsGreaterOrEqualCstCt(var, value + 1, boolvar);
}
if (c == v->Max()) {
return MakeIsLessOrEqualCstCt(v, c - 1, b);
if (value == var->Max()) {
return MakeIsLessOrEqualCstCt(var, value - 1, boolvar);
}
unequality_var_cst_cache_->Insert(v, c, b);
return RevAlloc(new IsDiffCstCt(this, v, c, b));
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_NOT_EQUAL);
return RevAlloc(new IsDiffCstCt(this, var, value, boolvar));
}
// ----- is_greater_equal_cst Constraint -----
@@ -652,31 +555,6 @@ class IsGreaterEqualCstCt : public Constraint {
};
} // namespace
// ---------- GreaterEqualCstCache ----------
class GreaterEqualCstCache : public VarCstCache {
public:
explicit GreaterEqualCstCache(Solver* const s) : VarCstCache(s) {}
virtual ~GreaterEqualCstCache() {}
IntVar* VarGreaterEqCstStatus(IntVar* const var, int64 value) {
IntVar* boolvar = Find(var, value);
if (!boolvar) {
boolvar = solver()->MakeBoolVar(
StringPrintf("StatusVar<%s >= %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
solver()->RevAlloc(new IsGreaterEqualCstCt(solver(),
var,
value,
boolvar));
solver()->AddConstraint(maintain);
UnsafeInsert(var, value, boolvar);
}
return boolvar;
}
};
IntVar* Solver::MakeIsGreaterOrEqualCstVar(IntVar* const var, int64 value) {
if (var->Min() >= value) {
return MakeIntConst(1LL);
@@ -684,19 +562,43 @@ IntVar* Solver::MakeIsGreaterOrEqualCstVar(IntVar* const var, int64 value) {
if (var->Max() < value) {
return MakeIntConst(0LL);
}
return greater_equal_var_cst_cache_->VarGreaterEqCstStatus(var, value);
IntExpr* const cache = model_cache_->FindVarConstantExpression(
var,
value,
ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
IntVar* const boolvar = MakeBoolVar(
StringPrintf("StatusVar<%s >= %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
RevAlloc(new IsGreaterEqualCstCt(this, var, value, boolvar));
AddConstraint(maintain);
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
return boolvar;
}
}
IntVar* Solver::MakeIsGreaterCstVar(IntVar* const var, int64 value) {
return greater_equal_var_cst_cache_->VarGreaterEqCstStatus(var, value + 1);
return MakeIsGreaterOrEqualCstVar(var, value + 1);
}
Constraint* Solver::MakeIsGreaterOrEqualCstCt(IntVar* const v, int64 c,
IntVar* const b) {
CHECK_EQ(this, v->solver());
CHECK_EQ(this, b->solver());
greater_equal_var_cst_cache_->Insert(v, c, b);
return RevAlloc(new IsGreaterEqualCstCt(this, v, c, b));
Constraint* Solver::MakeIsGreaterOrEqualCstCt(IntVar* const var,
int64 value,
IntVar* const boolvar) {
CHECK_EQ(this, var->solver());
CHECK_EQ(this, boolvar->solver());
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_GREATER_OR_EQUAL);
return RevAlloc(new IsGreaterEqualCstCt(this, var, value, boolvar));
}
Constraint* Solver::MakeIsGreaterCstCt(IntVar* const v, int64 c,
@@ -761,30 +663,6 @@ class IsLessEqualCstCt : public Constraint {
};
} // namespace
// ---------- LessEqualCstCache ----------
class LessEqualCstCache : public VarCstCache {
public:
explicit LessEqualCstCache(Solver* const s) : VarCstCache(s) {}
virtual ~LessEqualCstCache() {}
IntVar* VarLessEqCstStatus(IntVar* const var, int64 value) {
IntVar* boolvar = Find(var, value);
if (!boolvar) {
boolvar = solver()->MakeBoolVar(
StringPrintf("StatusVar<%s <= %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
solver()->RevAlloc(new IsLessEqualCstCt(solver(),
var,
value,
boolvar));
solver()->AddConstraint(maintain);
UnsafeInsert(var, value, boolvar);
}
return boolvar;
}
};
IntVar* Solver::MakeIsLessOrEqualCstVar(IntVar* const var, int64 value) {
if (var->Max() <= value) {
@@ -793,19 +671,43 @@ IntVar* Solver::MakeIsLessOrEqualCstVar(IntVar* const var, int64 value) {
if (var->Min() > value) {
return MakeIntConst(0LL);
}
return less_equal_var_cst_cache_->VarLessEqCstStatus(var, value);
IntExpr* const cache = model_cache_->FindVarConstantExpression(
var,
value,
ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
IntVar* const boolvar = MakeBoolVar(
StringPrintf("StatusVar<%s <= %" GG_LL_FORMAT "d>",
var->name().c_str(), value));
Constraint* const maintain =
RevAlloc(new IsLessEqualCstCt(this, var, value, boolvar));
AddConstraint(maintain);
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
return boolvar;
}
}
IntVar* Solver::MakeIsLessCstVar(IntVar* const var, int64 value) {
return MakeIsLessOrEqualCstVar(var, value - 1);
}
Constraint* Solver::MakeIsLessOrEqualCstCt(IntVar* const v, int64 c,
IntVar* const b) {
CHECK_EQ(this, v->solver());
CHECK_EQ(this, b->solver());
less_equal_var_cst_cache_->Insert(v, c, b);
return RevAlloc(new IsLessEqualCstCt(this, v, c, b));
Constraint* Solver::MakeIsLessOrEqualCstCt(IntVar* const var,
int64 value,
IntVar* const boolvar) {
CHECK_EQ(this, var->solver());
CHECK_EQ(this, boolvar->solver());
model_cache_->InsertVarConstantExpression(
boolvar,
var,
value,
ModelCache::VAR_CONSTANT_IS_LESS_OR_EQUAL);
return RevAlloc(new IsLessEqualCstCt(this, var, value, boolvar));
}
Constraint* Solver::MakeIsLessCstCt(IntVar* const v, int64 c,
@@ -1140,14 +1042,4 @@ IntVar* Solver::MakeIsMemberVar(IntVar* const var,
IntVar* Solver::MakeIsMemberVar(IntVar* const var, const std::vector<int>& values) {
return MakeIsMemberVar(var, values.data(), values.size());
}
// ---------- Init Caches ----------
void Solver::InitBoolVarCaches() {
equality_var_cst_cache_ = RevAlloc(new EqualityVarCstCache(this));
unequality_var_cst_cache_ = RevAlloc(new UnequalityVarCstCache(this));
greater_equal_var_cst_cache_ = RevAlloc(new GreaterEqualCstCache(this));
less_equal_var_cst_cache_ = RevAlloc(new LessEqualCstCache(this));
}
} // namespace operations_research

View File

@@ -2512,71 +2512,6 @@ LocalSearchFilter* Solver::MakeLocalSearchObjectiveFilter(
OperationFromEnum(op_enum)));
}
// ----- NestedSolve decision wrapper -----
// This decision calls a nested Solve on the given DecisionBuilder in its
// left branch; does nothing in the left branch.
// The state of the decision corresponds to the result of the nested Solve:
// DECISION_PENDING - Nested Solve not called yet
// DECISION_FAILED - Nested Solve failed
// DECISION_FOUND - Nested Solve succeeded
class NestedSolveDecision : public Decision {
public:
// This enum is used internally to tag states in the local search tree.
enum StateType {
DECISION_PENDING,
DECISION_FAILED,
DECISION_FOUND
};
NestedSolveDecision(DecisionBuilder* const db,
bool restore,
const std::vector<SearchMonitor*>& monitors);
NestedSolveDecision(DecisionBuilder* const db,
bool restore);
virtual ~NestedSolveDecision() {}
virtual void Apply(Solver* const solver);
virtual void Refute(Solver* const solver);
virtual string DebugString() const {
return "NestedSolveDecision";
}
int state() const { return state_; }
private:
DecisionBuilder* const db_;
bool restore_;
std::vector<SearchMonitor*> monitors_;
int state_;
};
NestedSolveDecision::NestedSolveDecision(DecisionBuilder* const db,
bool restore,
const std::vector<SearchMonitor*>& monitors)
: db_(db),
restore_(restore),
monitors_(monitors),
state_(DECISION_PENDING) {
CHECK(NULL != db);
}
NestedSolveDecision::NestedSolveDecision(DecisionBuilder* const db,
bool restore)
: db_(db), restore_(restore), state_(DECISION_PENDING) {
CHECK(NULL != db);
}
void NestedSolveDecision::Apply(Solver* const solver) {
CHECK(NULL != solver);
if (solver->NestedSolve(db_, restore_,
monitors_.data(), monitors_.size())) {
solver->SaveAndSetValue(&state_, static_cast<int>(DECISION_FOUND));
} else {
solver->SaveAndSetValue(&state_, static_cast<int>(DECISION_FAILED));
}
}
void NestedSolveDecision::Refute(Solver* const solver) {}
// ----- Finds a neighbor of the assignment passed -----
class FindOneNeighbor : public DecisionBuilder {
@@ -2849,8 +2784,123 @@ LocalSearchPhaseParameters* Solver::MakeLocalSearchPhaseParameters(
filters));
}
namespace {
// ----- NestedSolve decision wrapper -----
// This decision calls a nested Solve on the given DecisionBuilder in its
// left branch; does nothing in the left branch.
// The state of the decision corresponds to the result of the nested Solve:
// DECISION_PENDING - Nested Solve not called yet
// DECISION_FAILED - Nested Solve failed
// DECISION_FOUND - Nested Solve succeeded
class NestedSolveDecision : public Decision {
public:
// This enum is used internally to tag states in the local search tree.
enum StateType {
DECISION_PENDING,
DECISION_FAILED,
DECISION_FOUND
};
NestedSolveDecision(DecisionBuilder* const db,
bool restore,
const std::vector<SearchMonitor*>& monitors);
NestedSolveDecision(DecisionBuilder* const db,
bool restore);
virtual ~NestedSolveDecision() {}
virtual void Apply(Solver* const solver);
virtual void Refute(Solver* const solver);
virtual string DebugString() const {
return "NestedSolveDecision";
}
int state() const { return state_; }
private:
DecisionBuilder* const db_;
bool restore_;
std::vector<SearchMonitor*> monitors_;
int state_;
};
NestedSolveDecision::NestedSolveDecision(DecisionBuilder* const db,
bool restore,
const std::vector<SearchMonitor*>& monitors)
: db_(db),
restore_(restore),
monitors_(monitors),
state_(DECISION_PENDING) {
CHECK(NULL != db);
}
NestedSolveDecision::NestedSolveDecision(DecisionBuilder* const db,
bool restore)
: db_(db), restore_(restore), state_(DECISION_PENDING) {
CHECK(NULL != db);
}
void NestedSolveDecision::Apply(Solver* const solver) {
CHECK(NULL != solver);
if (solver->NestedSolve(db_, restore_,
monitors_.data(), monitors_.size())) {
solver->SaveAndSetValue(&state_, static_cast<int>(DECISION_FOUND));
} else {
solver->SaveAndSetValue(&state_, static_cast<int>(DECISION_FAILED));
}
}
void NestedSolveDecision::Refute(Solver* const solver) {}
// ----- Local search decision builder -----
// Given a first solution (resulting from either an initial assignment or the
// result of a decision builder), it searches for neighbors using a local
// search operator. The first solution corresponds to the first leaf of the
// search.
// The local search applies to the variables contained either in the assignment
// or the vector of variables passed.
class LocalSearch : public DecisionBuilder {
public:
LocalSearch(Assignment* const assignment,
SolutionPool* const pool,
LocalSearchOperator* const ls_operator,
DecisionBuilder* const sub_decision_builder,
SearchLimit* const limit,
const std::vector<LocalSearchFilter*>& filters);
// TODO(user): find a way to not have to pass vars here: redundant with
// variables in operators
LocalSearch(IntVar* const* vars,
int size,
SolutionPool* const pool,
DecisionBuilder* const first_solution,
LocalSearchOperator* const ls_operator,
DecisionBuilder* const sub_decision_builder,
SearchLimit* const limit,
const std::vector<LocalSearchFilter*>& filters);
virtual ~LocalSearch();
virtual Decision* Next(Solver* const solver);
virtual string DebugString() const {
return "LocalSearch";
}
virtual void Accept(ModelVisitor* const visitor) const;
protected:
void PushFirstSolutionDecision(DecisionBuilder* first_solution);
void PushLocalSearchDecision();
private:
Assignment* assignment_;
SolutionPool* const pool_;
LocalSearchOperator* const ls_operator_;
DecisionBuilder* const sub_decision_builder_;
std::vector<NestedSolveDecision*> nested_decisions_;
int nested_decision_index_;
SearchLimit* const limit_;
const std::vector<LocalSearchFilter*> filters_;
bool has_started_;
};
LocalSearch::LocalSearch(Assignment* const assignment,
SolutionPool* const pool,
LocalSearchOperator* const ls_operator,
@@ -3010,7 +3060,6 @@ void LocalSearch::PushLocalSearchDecision() {
solver->RevAlloc(new NestedSolveDecision(find_neighbors, false)));
}
namespace {
class DefaultSolutionPool : public SolutionPool {
public:
DefaultSolutionPool() : reference_assignment_(NULL) {}

View File

@@ -157,11 +157,12 @@ template <class C> void Double(C*** array_ptr, int* size_ptr) {
while (tmp != NULL) {
C* const to_reinsert = tmp;
tmp = tmp->next();
const uint64 code = to_reinsert->Hash();
to_reinsert->set_next((*array_ptr)[code]);
(*array_ptr)[code] = to_reinsert;
const uint64 position = to_reinsert->Hash() % (*size_ptr);
to_reinsert->set_next((*array_ptr)[position]);
(*array_ptr)[position] = to_reinsert;
}
}
delete [] (old_cell_array);
}
// ----- Cache objects built with 1 object -----
@@ -177,7 +178,12 @@ template <class C, class A1> class Cache1 {
~Cache1() {
for (int i = 0; i < size_; ++i) {
delete array_[i];
Cell* tmp = array_[i];
while (tmp != NULL) {
Cell* const to_delete = tmp;
tmp = tmp->next();
delete to_delete;
}
}
delete [] array_;
}
@@ -249,7 +255,12 @@ template <class C, class A1, class A2> class Cache2 {
~Cache2() {
for (int i = 0; i < size_; ++i) {
delete array_[i];
Cell* tmp = array_[i];
while (tmp != NULL) {
Cell* const to_delete = tmp;
tmp = tmp->next();
delete to_delete;
}
}
delete [] array_;
}
@@ -322,7 +333,12 @@ template <class C, class A1, class A2, class A3> class Cache3 {
~Cache3() {
for (int i = 0; i < size_; ++i) {
delete array_[i];
Cell* tmp = array_[i];
while (tmp != NULL) {
Cell* const to_delete = tmp;
tmp = tmp->next();
delete to_delete;
}
}
delete [] array_;
}
@@ -491,7 +507,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_CONSTANT_CONSTRAINT_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_constant_constraints_[type]->Find(var, value) == NULL) {
var_constant_constraints_[type]->UnsafeInsert(var, value, ct);
}
}
@@ -519,7 +536,10 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_constant_constant_constraints_[type]->Find(var,
value1,
value2) == NULL) {
var_constant_constant_constraints_[type]->UnsafeInsert(var,
value1,
value2,
@@ -549,7 +569,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var2 != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_VAR_CONSTRAINT_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_var_constraints_[type]->Find(var1, var2) == NULL) {
var_var_constraints_[type]->UnsafeInsert(var1, var2, ct);
}
}
@@ -571,7 +592,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_expressions_[type]->Find(var) == NULL) {
var_expressions_[type]->UnsafeInsert(var, expression);
}
}
@@ -597,7 +619,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_CONSTANT_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_constant_expressions_[type]->Find(var, value) == NULL) {
var_constant_expressions_[type]->UnsafeInsert(var, value, expression);
}
}
@@ -625,7 +648,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var2 != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_VAR_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_var_expressions_[type]->Find(var1, var2) == NULL) {
var_var_expressions_[type]->UnsafeInsert(var1, var2, expression);
}
}
@@ -653,7 +677,10 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_CONSTANT_CONSTANT_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_constant_constant_expressions_[type]->Find(var,
value1,
value2) == NULL) {
var_constant_constant_expressions_[type]->UnsafeInsert(var,
value1,
value2,
@@ -682,7 +709,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(var != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_CONSTANT_ARRAY_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_constant_array_expressions_[type]->Find(var, values) == NULL) {
var_constant_array_expressions_[type]->UnsafeInsert(var,
values,
expression);
@@ -706,7 +734,8 @@ class NonReversibleCache : public ModelCache {
DCHECK(expression != NULL);
DCHECK_GE(type, 0);
DCHECK_LT(type, VAR_ARRAY_EXPRESSION_MAX);
if (solver()->state() != Solver::IN_SEARCH) {
if (solver()->state() != Solver::IN_SEARCH &&
var_array_expressions_[type]->Find(vars) == NULL) {
var_array_expressions_[type]->UnsafeInsert(vars, expression);
}
}
@@ -729,4 +758,8 @@ class NonReversibleCache : public ModelCache {
ModelCache* BuildModelCache(Solver* const solver) {
return new NonReversibleCache(solver);
}
ModelCache* Solver::Cache() const {
return model_cache_.get();
}
} // namespace operations_research