new LS operator to reach a given assignment
This commit is contained in:
@@ -1796,6 +1796,23 @@ class Solver {
|
||||
int number_of_variables,
|
||||
int32 seed);
|
||||
|
||||
// Creates a local search operator that tries to move the assignment of some
|
||||
// variables toward a target. The target is given as an Assignment. This
|
||||
// operator generates neighbors in which the only difference compared to the
|
||||
// current state is that one variable that belongs to the target assignment is
|
||||
// set to its target value.
|
||||
LocalSearchOperator* MakeMoveTowardTargetOperator(const Assignment& target);
|
||||
|
||||
// Creates a local search operator that tries to move the assignment of some
|
||||
// variables toward a target. The target is given either as two vectors: a
|
||||
// vector of variables and a vector of associated target values. The two
|
||||
// vectors should be of the same length. This operator generates neighbors in
|
||||
// which the only difference compared to the current state is that one
|
||||
// variable that belongs to the given vector is set to its target value.
|
||||
LocalSearchOperator* MakeMoveTowardTargetOperator(
|
||||
const vector<IntVar*>& variables,
|
||||
const vector<int64>& target_values);
|
||||
|
||||
// Creates a local search operator which concatenates a vector of operators.
|
||||
// Each operator from the vector is called sequentially. By default, when a
|
||||
// neighbor is found the neighborhood exploration restarts from the last
|
||||
@@ -3186,6 +3203,7 @@ template <class V, class E> class AssignmentContainer {
|
||||
DCHECK(found);
|
||||
return Element(index);
|
||||
}
|
||||
const vector<E>& elements() const { return elements_; }
|
||||
E& MutableElement(int index) { return elements_[index]; }
|
||||
const E& Element(int index) const { return elements_[index]; }
|
||||
int Size() const { return elements_.size(); }
|
||||
@@ -3239,7 +3257,13 @@ class Assignment : public PropagationBaseObject {
|
||||
return int_var_container_.Empty() && interval_var_container_.Empty();
|
||||
}
|
||||
int Size() const {
|
||||
return int_var_container_.Size() + interval_var_container_.Size();
|
||||
return NumIntVars() + NumIntervalVars();
|
||||
}
|
||||
int NumIntVars() const {
|
||||
return int_var_container_.Size();
|
||||
}
|
||||
int NumIntervalVars() const {
|
||||
return interval_var_container_.Size();
|
||||
}
|
||||
void Store();
|
||||
void Restore();
|
||||
|
||||
@@ -414,6 +414,7 @@ class LocalSearchOperator : public BaseObject {
|
||||
|
||||
class IntVarLocalSearchOperator : public LocalSearchOperator {
|
||||
public:
|
||||
IntVarLocalSearchOperator();
|
||||
IntVarLocalSearchOperator(const IntVar* const* vars, int size);
|
||||
virtual ~IntVarLocalSearchOperator();
|
||||
// This method should not be overridden. Override OnStart() instead which is
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "constraint_solver/constraint_solveri.h"
|
||||
#include "graph/hamiltonian_path.h"
|
||||
|
||||
|
||||
DEFINE_int32(cp_local_search_sync_frequency, 16,
|
||||
"Frequency of checks for better solutions in the solution pool.");
|
||||
|
||||
@@ -40,6 +41,17 @@ namespace operations_research {
|
||||
|
||||
// ----- Base operator class for operators manipulating IntVars -----
|
||||
|
||||
IntVarLocalSearchOperator::IntVarLocalSearchOperator()
|
||||
: vars_(NULL),
|
||||
size_(0),
|
||||
values_(NULL),
|
||||
old_values_(NULL),
|
||||
activated_(0, false),
|
||||
was_activated_(0, false),
|
||||
has_changed_(0, false),
|
||||
has_delta_changed_(0, false),
|
||||
cleared_(true) {}
|
||||
|
||||
IntVarLocalSearchOperator::IntVarLocalSearchOperator(const IntVar* const* vars,
|
||||
int size)
|
||||
: vars_(NULL),
|
||||
@@ -51,8 +63,8 @@ IntVarLocalSearchOperator::IntVarLocalSearchOperator(const IntVar* const* vars,
|
||||
has_changed_(size, false),
|
||||
has_delta_changed_(size, false),
|
||||
cleared_(true) {
|
||||
AddVars(vars, size);
|
||||
CHECK_GE(size_, 0);
|
||||
AddVars(vars, size);
|
||||
}
|
||||
|
||||
IntVarLocalSearchOperator::~IntVarLocalSearchOperator() {}
|
||||
@@ -290,6 +302,94 @@ LocalSearchOperator* Solver::MakeRandomLNSOperator(const IntVar* const* vars,
|
||||
return RevAlloc(new RandomLNS(vars, size, number_of_variables, seed));
|
||||
}
|
||||
|
||||
// ----- Move Toward Target Local Search operator -----
|
||||
|
||||
// A local search operator that compares the current assignment with a target
|
||||
// one, and that generates neighbors corresponding to a single variable being
|
||||
// changed from its current value to its target value.
|
||||
class MoveTowardTargetLS: public IntVarLocalSearchOperator {
|
||||
public:
|
||||
explicit MoveTowardTargetLS(const vector<IntVar*>& variables,
|
||||
const vector<int64>& target_values)
|
||||
: IntVarLocalSearchOperator(variables.data(), variables.size()),
|
||||
target_(target_values),
|
||||
// Initialize variable_index_ at the number of the of variables minus
|
||||
// one, so that the first to be tried (after one increment) is the one
|
||||
// of index 0.
|
||||
variable_index_(Size() - 1) {
|
||||
CHECK_EQ(target_values.size(), variables.size()) << "Illegal arguments.";
|
||||
}
|
||||
|
||||
virtual ~MoveTowardTargetLS() {}
|
||||
virtual void OnStart() {
|
||||
// Do not change the value of variable_index_: this way, we keep going from
|
||||
// where we last modified something. This is because we expect that most
|
||||
// often, the variables we have just checked are less likely to be able
|
||||
// to be changed to their target values than the ones we have not yet
|
||||
// checked.
|
||||
//
|
||||
// Consider the case where oddly indexed variables can be assigned to their
|
||||
// target values (no matter in what order they are considered), while even
|
||||
// indexed ones cannot. Restarting at index 0 each time an odd-indexed
|
||||
// variable is modified will cause a total of Theta(n^2) neighbors to be
|
||||
// generated, while not restarting will produce only Theta(n) neighbors.
|
||||
CHECK_GE(variable_index_, 0);
|
||||
CHECK_LT(variable_index_, Size());
|
||||
num_var_since_last_start_ = 0;
|
||||
}
|
||||
|
||||
// Make a neighbor assigning one variable to its target value.
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (num_var_since_last_start_ < Size()) {
|
||||
++num_var_since_last_start_;
|
||||
variable_index_ = (variable_index_ + 1) % Size();
|
||||
const int64 target_value = target_.at(variable_index_);
|
||||
const int64 current_value = OldValue(variable_index_);
|
||||
if (current_value != target_value) {
|
||||
RevertChanges(false);
|
||||
SetValue(variable_index_, target_value);
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Target values
|
||||
const vector<int64> target_;
|
||||
|
||||
// Index of the next variable to try to restore
|
||||
int64 variable_index_;
|
||||
|
||||
// Number of variables checked since the last call to OnStart().
|
||||
int64 num_var_since_last_start_;
|
||||
};
|
||||
|
||||
LocalSearchOperator* Solver::MakeMoveTowardTargetOperator(
|
||||
const Assignment& target) {
|
||||
typedef vector<IntVarElement> Elements;
|
||||
const Elements& elements = target.IntVarContainer().elements();
|
||||
// Copy target values and construct the vector of variables
|
||||
vector<IntVar*> vars;
|
||||
vector<int64> values;
|
||||
vars.reserve(target.NumIntVars());
|
||||
values.reserve(target.NumIntVars());
|
||||
for (ConstIter<Elements> it(elements); !it.at_end(); ++it) {
|
||||
vars.push_back(it->Var());
|
||||
values.push_back(it->Value());
|
||||
}
|
||||
return MakeMoveTowardTargetOperator(vars, values);
|
||||
}
|
||||
|
||||
LocalSearchOperator* Solver::MakeMoveTowardTargetOperator(
|
||||
const vector<IntVar*>& variables,
|
||||
const vector<int64>& target_values) {
|
||||
return RevAlloc(new MoveTowardTargetLS(variables, target_values));
|
||||
}
|
||||
|
||||
// ----- ChangeValue Operators -----
|
||||
|
||||
ChangeValue::ChangeValue(const IntVar* const* vars, int size)
|
||||
|
||||
Reference in New Issue
Block a user