clean up protocol on local search; regroup model visitors code
This commit is contained in:
@@ -27,104 +27,7 @@
|
||||
|
||||
namespace operations_research {
|
||||
namespace {
|
||||
|
||||
class ArgumentHolder {
|
||||
public:
|
||||
struct Matrix {
|
||||
Matrix() : values(NULL), rows(0), columns(0) {}
|
||||
// We do not take ownership as the data will only be used temporarly.
|
||||
Matrix(const int64 * const * v, int r, int c)
|
||||
: values(v), rows(r), columns(c) {}
|
||||
const int64* const * values;
|
||||
int rows;
|
||||
int columns;
|
||||
};
|
||||
|
||||
const string& type_name() const {
|
||||
return type_name_;
|
||||
}
|
||||
|
||||
void set_type_name(const string& type_name) {
|
||||
type_name_ = type_name;
|
||||
}
|
||||
|
||||
void SetIntegerMatrixArgument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns) {
|
||||
matrix_argument_[arg_name] = Matrix(values, rows, columns);
|
||||
}
|
||||
|
||||
void SetIntegerExpressionArgument(const string& arg_name,
|
||||
const IntExpr* const expr) {
|
||||
integer_expression_argument_[arg_name] = expr;
|
||||
}
|
||||
|
||||
void SetIntegerVariableArrayArgument(const string& arg_name,
|
||||
const IntVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
integer_variable_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetIntervalArgument(const string& arg_name,
|
||||
const IntervalVar* const var) {
|
||||
interval_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void SetIntervalArrayArgument(const string& arg_name,
|
||||
const IntervalVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
interval_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetSequenceArgument(const string& arg_name,
|
||||
const SequenceVar* const var) {
|
||||
sequence_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void SetSequenceArrayArgument(const string& arg_name,
|
||||
const SequenceVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
sequence_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasIntegerExpressionArgument(const string& arg_name) const {
|
||||
return ContainsKey(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
const IntExpr* FindIntegerExpressionArgumentOrDie(
|
||||
const string& arg_name) const {
|
||||
return FindOrDie(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
const std::vector<const IntVar*>& FindIntegerVariableArrayArgumentOrDie(
|
||||
const string& arg_name) {
|
||||
return FindOrDie(integer_variable_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
const Matrix& FindIntegerMatrixArgumentOrDie(const string& arg_name) const {
|
||||
return FindOrDie(matrix_argument_, arg_name);
|
||||
}
|
||||
|
||||
private:
|
||||
string type_name_;
|
||||
hash_map<string, const IntExpr*> integer_expression_argument_;
|
||||
hash_map<string, const IntervalVar*> interval_argument_;
|
||||
hash_map<string, const SequenceVar*> sequence_argument_;
|
||||
hash_map<string,
|
||||
std::vector<const IntVar*> > integer_variable_array_argument_;
|
||||
hash_map<string, std::vector<const IntervalVar*> > interval_array_argument_;
|
||||
hash_map<string, std::vector<const SequenceVar*> > sequence_array_argument_;
|
||||
hash_map<string, Matrix> matrix_argument_;
|
||||
};
|
||||
|
||||
class CollectVariablesVisitor : public ModelVisitor {
|
||||
class CollectVariablesVisitor : public ModelParser {
|
||||
public:
|
||||
CollectVariablesVisitor(std::vector<IntVar*>* const primary_integer_variables,
|
||||
std::vector<IntVar*>* const secondary_integer_variables,
|
||||
@@ -135,14 +38,8 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
sequences_(sequence_variables),
|
||||
intervals_(interval_variables) {}
|
||||
|
||||
virtual ~CollectVariablesVisitor() {
|
||||
CHECK(holders_.empty());
|
||||
}
|
||||
virtual ~CollectVariablesVisitor() {}
|
||||
|
||||
// Header/footers.
|
||||
virtual void BeginVisitModel(const string& solver_name) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
virtual void EndVisitModel(const string& solver_name) {
|
||||
PopArgumentHolder();
|
||||
@@ -152,11 +49,6 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
sequences_->assign(sequence_set_.begin(), sequence_set_.end());
|
||||
}
|
||||
|
||||
virtual void BeginVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
virtual void EndVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint) {
|
||||
if (type_name.compare(ModelVisitor::kLinkExprVar) == 0 ||
|
||||
@@ -169,22 +61,22 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
type_name.compare(ModelVisitor::kIsLessOrEqual) == 0) {
|
||||
IntExpr* const target_expr =
|
||||
const_cast<IntExpr*>(
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kTargetArgument));
|
||||
IntVar* const target_var = target_expr->Var();
|
||||
IgnoreIntegerVariable(target_var);
|
||||
} else if (type_name.compare(ModelVisitor::kCountEqual) == 0 &&
|
||||
top()->HasIntegerExpressionArgument(
|
||||
Top()->HasIntegerExpressionArgument(
|
||||
ModelVisitor::kCountArgument)) {
|
||||
IntExpr* const count_expr =
|
||||
const_cast<IntExpr*>(
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kCountArgument));
|
||||
IntVar* const count_var = count_expr->Var();
|
||||
IgnoreIntegerVariable(count_var);
|
||||
} else if (type_name.compare(ModelVisitor::kAllowedAssignments) == 0) {
|
||||
const ArgumentHolder::Matrix& matrix =
|
||||
top()->FindIntegerMatrixArgumentOrDie(ModelVisitor::kTuplesArgument);
|
||||
Top()->FindIntegerMatrixArgumentOrDie(ModelVisitor::kTuplesArgument);
|
||||
std::vector<hash_set<int> > counters(matrix.columns);
|
||||
for (int i = 0; i < matrix.rows; ++i) {
|
||||
for (int j = 0; j < matrix.columns; ++j) {
|
||||
@@ -194,7 +86,7 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
for (int j = 0; j < matrix.columns; ++j) {
|
||||
if (counters[j].size() == matrix.rows) {
|
||||
const std::vector<const IntVar*>& vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kVarsArgument);
|
||||
for (int k = 0; k < matrix.columns; ++k) {
|
||||
if (j != k) {
|
||||
@@ -206,21 +98,21 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
}
|
||||
} else if (type_name.compare(ModelVisitor::kNoCycle) == 0) {
|
||||
const std::vector<const IntVar*>& vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kActiveArgument);
|
||||
for (int i = 0; i < vars.size(); ++i) {
|
||||
IgnoreIntegerVariable(const_cast<IntVar*>(vars[i]));
|
||||
}
|
||||
} else if (type_name.compare(ModelVisitor::kPathCumul) == 0) {
|
||||
const std::vector<const IntVar*>& vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kActiveArgument);
|
||||
for (int i = 0; i < vars.size(); ++i) {
|
||||
IgnoreIntegerVariable(const_cast<IntVar*>(vars[i]));
|
||||
}
|
||||
} else if (type_name.compare(ModelVisitor::kDistribute) == 0) {
|
||||
const std::vector<const IntVar*>& vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kCardsArgument);
|
||||
for (int i = 0; i < vars.size(); ++i) {
|
||||
IgnoreIntegerVariable(const_cast<IntVar*>(vars[i]));
|
||||
@@ -229,16 +121,6 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
PopArgumentHolder();
|
||||
}
|
||||
|
||||
virtual void BeginVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
virtual void EndVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr) {
|
||||
PopArgumentHolder();
|
||||
}
|
||||
|
||||
virtual void VisitIntegerVariable(const IntVar* const variable,
|
||||
const IntExpr* const delegate) {
|
||||
IntVar* const var = const_cast<IntVar*>(variable);
|
||||
@@ -293,80 +175,7 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
// Integer arguments
|
||||
virtual void VisitIntegerMatrixArgument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns) {
|
||||
top()->SetIntegerMatrixArgument(arg_name, values, rows, columns);
|
||||
}
|
||||
|
||||
// Variables.
|
||||
virtual void VisitIntegerExpressionArgument(
|
||||
const string& arg_name,
|
||||
const IntExpr* const argument) {
|
||||
top()->SetIntegerExpressionArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
virtual void VisitIntegerVariableArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntVar* const * arguments,
|
||||
int size) {
|
||||
top()->SetIntegerVariableArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit interval argument.
|
||||
virtual void VisitIntervalArgument(const string& arg_name,
|
||||
const IntervalVar* const argument) {
|
||||
top()->SetIntervalArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
virtual void VisitIntervalArrayArgument(const string& arg_name,
|
||||
const IntervalVar* const * arguments,
|
||||
int size) {
|
||||
top()->SetIntervalArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit sequence argument.
|
||||
virtual void VisitSequenceArgument(const string& arg_name,
|
||||
const SequenceVar* const argument) {
|
||||
top()->SetSequenceArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
virtual void VisitSequenceArrayArgument(const string& arg_name,
|
||||
const SequenceVar* const * arguments,
|
||||
int size) {
|
||||
top()->SetSequenceArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void PushArgumentHolder() {
|
||||
holders_.push_back(new ArgumentHolder);
|
||||
}
|
||||
|
||||
void PopArgumentHolder() {
|
||||
CHECK(!holders_.empty());
|
||||
delete holders_.back();
|
||||
holders_.pop_back();
|
||||
}
|
||||
|
||||
ArgumentHolder* top() const {
|
||||
CHECK(!holders_.empty());
|
||||
return holders_.back();
|
||||
}
|
||||
|
||||
void IgnoreIntegerVariable(IntVar* const var) {
|
||||
primary_set_.erase(var);
|
||||
secondary_set_.erase(var);
|
||||
@@ -386,7 +195,6 @@ class CollectVariablesVisitor : public ModelVisitor {
|
||||
hash_set<IntVar*> ignored_set_;
|
||||
hash_set<SequenceVar*> sequence_set_;
|
||||
hash_set<IntervalVar*> interval_set_;
|
||||
std::vector<ArgumentHolder*> holders_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -1060,7 +1060,7 @@ DecisionBuilder* Solver::MakeApplyBranchSelector(
|
||||
}
|
||||
|
||||
int Solver::SolveDepth() const {
|
||||
return searches_.size() - 1;
|
||||
return state_ == OUTSIDE_SEARCH ? 0 : searches_.size() - 1;
|
||||
}
|
||||
|
||||
int Solver::SearchDepth() const {
|
||||
@@ -1297,7 +1297,23 @@ void Search::Accept(ModelVisitor* const visitor) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalOptimumReached(Search* const search) {
|
||||
return search->LocalOptimum();
|
||||
}
|
||||
|
||||
bool AcceptDelta(Search* const search,
|
||||
Assignment* delta,
|
||||
Assignment* deltadelta) {
|
||||
return search->AcceptDelta(delta, deltadelta);
|
||||
}
|
||||
|
||||
void AcceptNeighbor(Search* const search) {
|
||||
search->AcceptNeighbor();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// ---------- Fail Decision ----------
|
||||
|
||||
class FailDecision : public Decision {
|
||||
@@ -1430,7 +1446,7 @@ void Solver::Init() {
|
||||
|
||||
Solver::~Solver() {
|
||||
// solver destructor called with searches open.
|
||||
CHECK_EQ(1, SolveDepth());
|
||||
CHECK_EQ(2, searches_.size());
|
||||
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
||||
|
||||
StateInfo info;
|
||||
@@ -1439,14 +1455,7 @@ Solver::~Solver() {
|
||||
DCHECK_EQ(finalType, SENTINEL);
|
||||
// Not popping initial SENTINEL in Solver destructor.
|
||||
DCHECK_EQ(info.int_info, SOLVER_CTOR_SENTINEL);
|
||||
|
||||
Search* search = searches_.back();
|
||||
searches_.pop_back();
|
||||
CHECK_EQ(0, SolveDepth())
|
||||
<< "non empty list of searches when ending the solver";
|
||||
delete search;
|
||||
CHECK_EQ(1, searches_.size());
|
||||
delete searches_.back();
|
||||
STLDeleteElements(&searches_);
|
||||
DeleteDemonProfiler(demon_profiler_);
|
||||
DeleteBuilders();
|
||||
}
|
||||
@@ -1510,18 +1519,6 @@ int64 Solver::solutions() const {
|
||||
return TopLevelSearch()->solution_counter();
|
||||
}
|
||||
|
||||
bool Solver::LocalOptimum() {
|
||||
return TopLevelSearch()->LocalOptimum();
|
||||
}
|
||||
|
||||
bool Solver::AcceptDelta(Assignment* delta, Assignment* deltadelta) {
|
||||
return TopLevelSearch()->AcceptDelta(delta, deltadelta);
|
||||
}
|
||||
|
||||
void Solver::AcceptNeighbor() {
|
||||
return TopLevelSearch()->AcceptNeighbor();
|
||||
}
|
||||
|
||||
void Solver::TopPeriodicCheck() {
|
||||
TopLevelSearch()->PeriodicCheck();
|
||||
}
|
||||
@@ -1938,7 +1935,7 @@ void Solver::NewSearch(DecisionBuilder* const db,
|
||||
search->EnterSearch();
|
||||
|
||||
// Push sentinel and set decision builder.
|
||||
DCHECK_EQ(1, SolveDepth());
|
||||
DCHECK_EQ(2, searches_.size());
|
||||
PushSentinel(INITIAL_SEARCH_SENTINEL);
|
||||
search->set_decision_builder(db);
|
||||
}
|
||||
@@ -2063,10 +2060,10 @@ void Solver::BacktrackToSentinel(int magic_code) {
|
||||
void Solver::JumpToSentinelWhenNested() {
|
||||
CHECK_GT(SolveDepth(), 1) << "calling JumpToSentinel from top level";
|
||||
Search* c = searches_.back();
|
||||
Search* p = searches_[SolveDepth() - 2];
|
||||
Search* p = ParentSearch();
|
||||
bool found = false;
|
||||
while (!c->marker_stack_.empty()) {
|
||||
StateMarker* m = c->marker_stack_.back();
|
||||
StateMarker* const m = c->marker_stack_.back();
|
||||
if (m->type_ == REVERSIBLE_ACTION) {
|
||||
p->marker_stack_.push_back(m);
|
||||
} else {
|
||||
@@ -2119,9 +2116,10 @@ class ReverseDecision : public Decision {
|
||||
bool Solver::NextSolution() {
|
||||
Search* const search = searches_.back();
|
||||
Decision* fd = NULL;
|
||||
const bool top_level = (SolveDepth() == 1);
|
||||
const int solve_depth = SolveDepth();
|
||||
const bool top_level = solve_depth <= 1;
|
||||
|
||||
if (top_level && state_ == OUTSIDE_SEARCH && !search->decision_builder()) {
|
||||
if (solve_depth == 0 && !search->decision_builder()) {
|
||||
LOG(WARNING) << "NextSolution() called without a NewSearch before";
|
||||
return false;
|
||||
}
|
||||
@@ -2282,7 +2280,7 @@ bool Solver::NextSolution() {
|
||||
}
|
||||
|
||||
void Solver::EndSearch() {
|
||||
CHECK_EQ(1, SolveDepth());
|
||||
CHECK_EQ(2, searches_.size());
|
||||
Search* const search = searches_.back();
|
||||
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
||||
search->ExitSearch();
|
||||
@@ -2310,7 +2308,8 @@ bool Solver::CheckAssignment(Assignment* const solution) {
|
||||
search->EnterSearch();
|
||||
|
||||
// Push sentinel and set decision builder.
|
||||
DCHECK_EQ(1, SolveDepth());
|
||||
DCHECK_EQ(0, SolveDepth());
|
||||
DCHECK_EQ(2, searches_.size());
|
||||
PushSentinel(INITIAL_SEARCH_SENTINEL);
|
||||
search->BeginInitialPropagation();
|
||||
CP_TRY(search) {
|
||||
|
||||
@@ -2665,12 +2665,6 @@ class Solver {
|
||||
Solver::LocalSearchFilterBound filter_enum,
|
||||
Solver::LocalSearchOperation op_enum);
|
||||
|
||||
// Ensures communication of local optima between monitors and search
|
||||
bool LocalOptimum();
|
||||
// Checks with monitors if delta is acceptable
|
||||
bool AcceptDelta(Assignment* delta, Assignment* deltadelta);
|
||||
// Ensures communication of accepted neighbors between monitors and search
|
||||
void AcceptNeighbor();
|
||||
// Performs PeriodicCheck on the top-level search; can be called from a nested
|
||||
// solve to check top-level limits for instance.
|
||||
void TopPeriodicCheck();
|
||||
@@ -2881,6 +2875,14 @@ class Solver {
|
||||
Search* TopLevelSearch() const {
|
||||
return searches_.at(1);
|
||||
}
|
||||
// Returns the Search object which is the parent of the active search, i.e.
|
||||
// the search below the top of the stack. If the active search is at the
|
||||
// bottom of the stack, returns the active search.
|
||||
Search* ParentSearch() const {
|
||||
const size_t search_size = searches_.size();
|
||||
DCHECK_GT(search_size, 1);
|
||||
return searches_[search_size - 2];
|
||||
}
|
||||
|
||||
// Naming
|
||||
string GetName(const PropagationBaseObject* object);
|
||||
|
||||
@@ -1617,6 +1617,154 @@ class DependencyGraph : public BaseObject {
|
||||
std::vector<DependencyGraphNode*> managed_nodes_;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Argument Holder: useful when visiting a model.
|
||||
#if !defined(SWIG)
|
||||
class ArgumentHolder {
|
||||
public:
|
||||
// Internal structure to store an integer matrix.
|
||||
struct Matrix {
|
||||
Matrix() : values(NULL), rows(0), columns(0) {}
|
||||
// We do not take ownership as the data will only be used temporarly.
|
||||
Matrix(const int64 * const * v, int r, int c)
|
||||
: values(v), rows(r), columns(c) {}
|
||||
const int64* const * values;
|
||||
int rows;
|
||||
int columns;
|
||||
};
|
||||
|
||||
// Type of the argument.
|
||||
const string& TypeName() const;
|
||||
void SetTypeName(const string& type_name);
|
||||
|
||||
// Setters.
|
||||
void SetIntegerArgument(const string& arg_name, int64 value);
|
||||
void SetIntegerArrayArgument(const string& arg_name,
|
||||
const int64* const values,
|
||||
int size);
|
||||
void SetIntegerMatrixArgument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns);
|
||||
void SetIntegerExpressionArgument(const string& arg_name,
|
||||
const IntExpr* const expr);
|
||||
void SetIntegerVariableArrayArgument(const string& arg_name,
|
||||
const IntVar* const * const vars,
|
||||
int size);
|
||||
void SetIntervalArgument(const string& arg_name,
|
||||
const IntervalVar* const var);
|
||||
void SetIntervalArrayArgument(const string& arg_name,
|
||||
const IntervalVar* const * const vars,
|
||||
int size);
|
||||
void SetSequenceArgument(const string& arg_name,
|
||||
const SequenceVar* const var);
|
||||
void SetSequenceArrayArgument(const string& arg_name,
|
||||
const SequenceVar* const * const vars,
|
||||
int size);
|
||||
|
||||
// Checks if arguments exist.
|
||||
bool HasIntegerExpressionArgument(const string& arg_name) const;
|
||||
bool HasIntegerVariableArrayArgument(const string& arg_name) const;
|
||||
|
||||
// Getters.
|
||||
int64 FindIntegerArgumentWithDefault(
|
||||
const string& arg_name,
|
||||
int64 def) const;
|
||||
int64 FindIntegerArgumentOrDie(const string& arg_name) const;
|
||||
const std::vector<int64>& FindIntegerArrayArgumentOrDie(
|
||||
const string& arg_name) const;
|
||||
const Matrix& FindIntegerMatrixArgumentOrDie(const string& arg_name) const;
|
||||
|
||||
const IntExpr* FindIntegerExpressionArgumentOrDie(
|
||||
const string& arg_name) const;
|
||||
const std::vector<const IntVar*>& FindIntegerVariableArrayArgumentOrDie(
|
||||
const string& arg_name) const;
|
||||
|
||||
private:
|
||||
string type_name_;
|
||||
hash_map<string, int64> integer_argument_;
|
||||
hash_map<string, std::vector<int64> > integer_array_argument_;
|
||||
hash_map<string, Matrix> matrix_argument_;
|
||||
hash_map<string, const IntExpr*> integer_expression_argument_;
|
||||
hash_map<string, const IntervalVar*> interval_argument_;
|
||||
hash_map<string, const SequenceVar*> sequence_argument_;
|
||||
hash_map<string, std::vector<const IntVar*> > integer_variable_array_argument_;
|
||||
hash_map<string, std::vector<const IntervalVar*> > interval_array_argument_;
|
||||
hash_map<string, std::vector<const SequenceVar*> > sequence_array_argument_;
|
||||
};
|
||||
|
||||
// Model Parser
|
||||
|
||||
class ModelParser : public ModelVisitor {
|
||||
public:
|
||||
ModelParser();
|
||||
|
||||
virtual ~ModelParser();
|
||||
|
||||
// Header/footers.
|
||||
virtual void BeginVisitModel(const string& solver_name);
|
||||
virtual void EndVisitModel(const string& solver_name);
|
||||
virtual void BeginVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint);
|
||||
virtual void EndVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint);
|
||||
virtual void BeginVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr);
|
||||
virtual void EndVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr);
|
||||
virtual void VisitIntegerVariable(const IntVar* const variable,
|
||||
const IntExpr* const delegate);
|
||||
virtual void VisitIntegerVariable(const IntVar* const variable,
|
||||
const string& operation,
|
||||
int64 value,
|
||||
const IntVar* const delegate);
|
||||
virtual void VisitIntervalVariable(const IntervalVar* const variable,
|
||||
const string& operation,
|
||||
const IntervalVar* const delegate);
|
||||
virtual void VisitIntervalVariable(const IntervalVar* const variable,
|
||||
const string& operation,
|
||||
const IntervalVar* const * delegates,
|
||||
int size);
|
||||
virtual void VisitSequenceVariable(const SequenceVar* const variable);
|
||||
// Integer arguments
|
||||
virtual void VisitIntegerArgument(const string& arg_name, int64 value);
|
||||
virtual void VisitIntegerArrayArgument(const string& arg_name,
|
||||
const int64* const values,
|
||||
int size);
|
||||
virtual void VisitIntegerMatrixArgument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns);
|
||||
// Variables.
|
||||
virtual void VisitIntegerExpressionArgument(
|
||||
const string& arg_name,
|
||||
const IntExpr* const argument);
|
||||
virtual void VisitIntegerVariableArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntVar* const * arguments,
|
||||
int size);
|
||||
// Visit interval argument.
|
||||
virtual void VisitIntervalArgument(const string& arg_name,
|
||||
const IntervalVar* const argument);
|
||||
virtual void VisitIntervalArrayArgument(const string& arg_name,
|
||||
const IntervalVar* const * arguments,
|
||||
int size);
|
||||
// Visit sequence argument.
|
||||
virtual void VisitSequenceArgument(const string& arg_name,
|
||||
const SequenceVar* const argument);
|
||||
virtual void VisitSequenceArrayArgument(const string& arg_name,
|
||||
const SequenceVar* const * arguments,
|
||||
int size);
|
||||
|
||||
protected:
|
||||
void PushArgumentHolder();
|
||||
void PopArgumentHolder();
|
||||
ArgumentHolder* Top() const;
|
||||
|
||||
private:
|
||||
std::vector<ArgumentHolder*> holders_;
|
||||
};
|
||||
#endif // SWIG
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "constraint_solver/constraint_solver.h"
|
||||
#include "constraint_solver/constraint_solveri.h"
|
||||
#include "linear_solver/linear_solver.h"
|
||||
#include "util/string_array.h"
|
||||
|
||||
@@ -121,134 +122,11 @@ class SimplexConnection : public SearchMonitor {
|
||||
|
||||
typedef hash_map<const IntExpr*, MPVariable*> ExprTranslation;
|
||||
|
||||
// ----- Context to represent a linear sum -----
|
||||
|
||||
class ArgumentHolder {
|
||||
public:
|
||||
struct Matrix {
|
||||
Matrix() : values(NULL), rows(0), columns(0) {}
|
||||
Matrix(const int64 * const * v, int r, int c)
|
||||
: values(v), rows(r), columns(c) {}
|
||||
const int64* const * values;
|
||||
int rows;
|
||||
int columns;
|
||||
};
|
||||
|
||||
const string& type_name() const {
|
||||
return type_name_;
|
||||
}
|
||||
|
||||
void set_type_name(const string& type_name) {
|
||||
type_name_ = type_name;
|
||||
}
|
||||
|
||||
void set_integer_argument(const string& arg_name, int64 value) {
|
||||
integer_argument_[arg_name] = value;
|
||||
}
|
||||
|
||||
void set_integer_array_argument(const string& arg_name,
|
||||
const int64* const values,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
integer_array_argument_[arg_name].push_back(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void set_integer_matrix_argument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns) {
|
||||
matrix_argument_[arg_name] = Matrix(values, rows, columns);
|
||||
}
|
||||
|
||||
void set_integer_expression_argument(const string& arg_name,
|
||||
const IntExpr* const expr) {
|
||||
integer_expression_argument_[arg_name] = expr;
|
||||
}
|
||||
|
||||
void set_integer_variable_array_argument(const string& arg_name,
|
||||
const IntVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
integer_variable_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void set_interval_argument(const string& arg_name,
|
||||
const IntervalVar* const var) {
|
||||
interval_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void set_interval_array_argument(const string& arg_name,
|
||||
const IntervalVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
interval_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void set_sequence_argument(const string& arg_name,
|
||||
const SequenceVar* const var) {
|
||||
sequence_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void set_sequence_array_argument(const string& arg_name,
|
||||
const SequenceVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
sequence_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const IntExpr* FindIntegerExpressionArgumentOrDie(const string& arg_name) {
|
||||
return FindOrDie(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
const std::vector<const IntVar*>& FindIntegerVariableArrayArgumentOrDie(
|
||||
const string& arg_name) {
|
||||
return FindOrDie(integer_variable_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
int64 FindIntegerArgumentOrDie(const string& arg_name) {
|
||||
return FindOrDie(integer_argument_, arg_name);
|
||||
}
|
||||
|
||||
const std::vector<int64>& FindIntegerArrayArgumentOrDie(
|
||||
const string& arg_name) {
|
||||
return FindOrDie(integer_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
const Matrix& FindIntegerMatrixArgumentOrDie(const string& arg_name) {
|
||||
return FindOrDie(matrix_argument_, arg_name);
|
||||
}
|
||||
|
||||
bool HasIntegerExpression(const string& arg_name) {
|
||||
return ContainsKey(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
bool HasIntegerVariableArray(const string& arg_name) {
|
||||
return ContainsKey(integer_variable_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
private:
|
||||
string type_name_;
|
||||
hash_map<string, const IntExpr*> integer_expression_argument_;
|
||||
hash_map<string, const IntervalVar*> interval_argument_;
|
||||
hash_map<string, const SequenceVar*> sequence_argument_;
|
||||
hash_map<string,
|
||||
std::vector<const IntVar*> > integer_variable_array_argument_;
|
||||
hash_map<string, std::vector<const IntervalVar*> > interval_array_argument_;
|
||||
hash_map<string, std::vector<const SequenceVar*> > sequence_array_argument_;
|
||||
hash_map<string, int64> integer_argument_;
|
||||
hash_map<string, std::vector<int64> > integer_array_argument_;
|
||||
hash_map<string, Matrix> matrix_argument_;
|
||||
};
|
||||
|
||||
#define IS_TYPE(type, tag) type.compare(ModelVisitor::tag) == 0
|
||||
|
||||
// ----- Actual Linearization -----
|
||||
|
||||
class Linearizer : public ModelVisitor {
|
||||
class Linearizer : public ModelParser {
|
||||
public:
|
||||
Linearizer(MPSolver* const mp_solver,
|
||||
ExprTranslation* tr,
|
||||
@@ -372,7 +250,7 @@ class Linearizer : public ModelVisitor {
|
||||
// Visit integer arguments.
|
||||
virtual void VisitIntegerArgument(const string& arg_name, int64 value) {
|
||||
if (DoVisit()) {
|
||||
top()->set_integer_argument(arg_name, value);
|
||||
Top()->SetIntegerArgument(arg_name, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +258,7 @@ class Linearizer : public ModelVisitor {
|
||||
const int64* const values,
|
||||
int size) {
|
||||
if (DoVisit()) {
|
||||
top()->set_integer_array_argument(arg_name, values, size);
|
||||
Top()->SetIntegerArrayArgument(arg_name, values, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +267,7 @@ class Linearizer : public ModelVisitor {
|
||||
int rows,
|
||||
int columns) {
|
||||
if (DoVisit()) {
|
||||
top()->set_integer_matrix_argument(arg_name, values, rows, columns);
|
||||
Top()->SetIntegerMatrixArgument(arg_name, values, rows, columns);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +276,7 @@ class Linearizer : public ModelVisitor {
|
||||
const string& arg_name,
|
||||
const IntExpr* const argument) {
|
||||
if (DoVisit()) {
|
||||
top()->set_integer_expression_argument(arg_name, argument);
|
||||
Top()->SetIntegerExpressionArgument(arg_name, argument);
|
||||
VisitSubExpression(argument);
|
||||
}
|
||||
}
|
||||
@@ -408,7 +286,7 @@ class Linearizer : public ModelVisitor {
|
||||
const IntVar* const * arguments,
|
||||
int size) {
|
||||
if (DoVisit()) {
|
||||
top()->set_integer_variable_array_argument(arg_name, arguments, size);
|
||||
Top()->SetIntegerVariableArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
VisitSubExpression(arguments[i]);
|
||||
}
|
||||
@@ -446,36 +324,6 @@ class Linearizer : public ModelVisitor {
|
||||
actives_.pop_back();
|
||||
}
|
||||
|
||||
void PushArgumentHolder() {
|
||||
holders_.push_back(new ArgumentHolder);
|
||||
}
|
||||
|
||||
void PopArgumentHolder() {
|
||||
CHECK(!holders_.empty());
|
||||
delete holders_.back();
|
||||
holders_.pop_back();
|
||||
STLDeleteElements(&extensions_);
|
||||
extensions_.clear();
|
||||
}
|
||||
|
||||
void PushExtension(const string& type_name) {
|
||||
PushActive(true);
|
||||
PushArgumentHolder();
|
||||
holders_.back()->set_type_name(type_name);
|
||||
}
|
||||
|
||||
void PopAndSaveExtension() {
|
||||
CHECK(!holders_.empty());
|
||||
extensions_.push_back(holders_.back());
|
||||
holders_.pop_back();
|
||||
PopActive();
|
||||
}
|
||||
|
||||
ArgumentHolder* top() const {
|
||||
CHECK(!holders_.empty());
|
||||
return holders_.back();
|
||||
}
|
||||
|
||||
void RegisterExpression(const IntExpr* const cp_expr) {
|
||||
if (!ContainsKey(*translation_, cp_expr)) {
|
||||
MPVariable* const mp_var = mp_solver_->MakeIntVar(cp_expr->Min(),
|
||||
@@ -505,60 +353,60 @@ class Linearizer : public ModelVisitor {
|
||||
void VisitBinaryRowConstraint(double lhs, double rhs) {
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(lhs, rhs);
|
||||
const IntExpr* const left =
|
||||
top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kLeftArgument);
|
||||
Top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kLeftArgument);
|
||||
const IntExpr* const right =
|
||||
top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kRightArgument);
|
||||
Top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kRightArgument);
|
||||
ct->SetCoefficient(Translated(left), 1.0);
|
||||
ct->SetCoefficient(Translated(right), -1.0);
|
||||
}
|
||||
|
||||
void VisitUnaryRowConstraint(double lhs, double rhs) {
|
||||
const IntExpr* const expr =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument);
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(lhs, rhs);
|
||||
ct->SetCoefficient(Translated(expr), 1.0);
|
||||
}
|
||||
|
||||
void VisitEquality() {
|
||||
if (top()->HasIntegerExpression(ModelVisitor::kLeftArgument)) {
|
||||
if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
|
||||
VisitBinaryRowConstraint(0.0, 0.0);
|
||||
} else {
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
VisitUnaryRowConstraint(value, value);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitLessOrEqual() {
|
||||
if (top()->HasIntegerExpression(ModelVisitor::kLeftArgument)) {
|
||||
if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
|
||||
VisitBinaryRowConstraint(-mp_solver_->infinity(), 0.0);
|
||||
} else {
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
VisitUnaryRowConstraint(-mp_solver_->infinity(), value);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitGreaterOrEqual() {
|
||||
if (top()->HasIntegerExpression(ModelVisitor::kLeftArgument)) {
|
||||
if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
|
||||
VisitBinaryRowConstraint(0.0, mp_solver_->infinity());
|
||||
} else {
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
VisitUnaryRowConstraint(value, mp_solver_->infinity());
|
||||
}
|
||||
}
|
||||
|
||||
void VisitScalProdLessOrEqual() {
|
||||
const std::vector<const IntVar*>& cp_vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kVarsArgument);
|
||||
const std::vector<int64>& cp_coefficients =
|
||||
top()->FindIntegerArrayArgumentOrDie(
|
||||
Top()->FindIntegerArrayArgumentOrDie(
|
||||
ModelVisitor::kCoefficientsArgument);
|
||||
const int64 constant =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
MPConstraint* const ct =
|
||||
mp_solver_->MakeRowConstraint(-mp_solver_->infinity(),
|
||||
constant);
|
||||
@@ -571,10 +419,10 @@ class Linearizer : public ModelVisitor {
|
||||
}
|
||||
|
||||
void VisitSum(const IntExpr* const cp_expr) {
|
||||
if (top()->HasIntegerVariableArray(ModelVisitor::kVarsArgument)) {
|
||||
if (Top()->HasIntegerVariableArrayArgument(ModelVisitor::kVarsArgument)) {
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
const std::vector<const IntVar*>& cp_vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kVarsArgument);
|
||||
for (int i = 0; i < cp_vars.size(); ++i) {
|
||||
MPVariable* const mp_var = Translated(cp_vars[i]);
|
||||
@@ -582,13 +430,14 @@ class Linearizer : public ModelVisitor {
|
||||
}
|
||||
RegisterExpression(cp_expr);
|
||||
ct->SetCoefficient(Translated(cp_expr), -1.0);
|
||||
} else if (top()->HasIntegerExpression(ModelVisitor::kLeftArgument)) {
|
||||
} else if (Top()->HasIntegerExpressionArgument(
|
||||
ModelVisitor::kLeftArgument)) {
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
const IntExpr* const left =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kLeftArgument);
|
||||
const IntExpr* const right =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kRightArgument);
|
||||
if (left != right) {
|
||||
ct->SetCoefficient(Translated(left), 1.0);
|
||||
@@ -600,10 +449,10 @@ class Linearizer : public ModelVisitor {
|
||||
ct->SetCoefficient(Translated(cp_expr), -1.0);
|
||||
} else {
|
||||
const IntExpr* const expr =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument);
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(-value, -value);
|
||||
ct->SetCoefficient(Translated(expr), 1.0);
|
||||
RegisterExpression(cp_expr);
|
||||
@@ -613,10 +462,10 @@ class Linearizer : public ModelVisitor {
|
||||
|
||||
void VisitScalProd(const IntExpr* const cp_expr) {
|
||||
const std::vector<const IntVar*>& cp_vars =
|
||||
top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
Top()->FindIntegerVariableArrayArgumentOrDie(
|
||||
ModelVisitor::kVarsArgument);
|
||||
const std::vector<int64>& cp_coefficients =
|
||||
top()->FindIntegerArrayArgumentOrDie(
|
||||
Top()->FindIntegerArrayArgumentOrDie(
|
||||
ModelVisitor::kCoefficientsArgument);
|
||||
CHECK_EQ(cp_vars.size(), cp_coefficients.size());
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
@@ -630,13 +479,13 @@ class Linearizer : public ModelVisitor {
|
||||
}
|
||||
|
||||
void VisitDifference(const IntExpr* const cp_expr) {
|
||||
if (top()->HasIntegerExpression(ModelVisitor::kLeftArgument)) {
|
||||
if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
const IntExpr* const left =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kLeftArgument);
|
||||
const IntExpr* const right =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kRightArgument);
|
||||
ct->SetCoefficient(Translated(left), 1.0);
|
||||
ct->SetCoefficient(Translated(right), -1.0);
|
||||
@@ -644,10 +493,10 @@ class Linearizer : public ModelVisitor {
|
||||
ct->SetCoefficient(Translated(cp_expr), -1.0);
|
||||
} else {
|
||||
const IntExpr* const expr =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument);
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(value, value);
|
||||
ct->SetCoefficient(Translated(expr), 1.0);
|
||||
RegisterExpression(cp_expr);
|
||||
@@ -657,7 +506,7 @@ class Linearizer : public ModelVisitor {
|
||||
|
||||
void VisitOpposite(const IntExpr* const cp_expr) {
|
||||
const IntExpr* const expr =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument);
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
ct->SetCoefficient(Translated(expr), 1.0);
|
||||
@@ -666,12 +515,13 @@ class Linearizer : public ModelVisitor {
|
||||
}
|
||||
|
||||
void VisitProduct(const IntExpr* const cp_expr) {
|
||||
if (top()->HasIntegerExpression(ModelVisitor::kExpressionArgument)) {
|
||||
if (Top()->HasIntegerExpressionArgument(
|
||||
ModelVisitor::kExpressionArgument)) {
|
||||
const IntExpr* const expr =
|
||||
top()->FindIntegerExpressionArgumentOrDie(
|
||||
Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument);
|
||||
const int64 value =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
|
||||
MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
|
||||
ct->SetCoefficient(Translated(expr), value);
|
||||
RegisterExpression(cp_expr);
|
||||
@@ -687,9 +537,9 @@ class Linearizer : public ModelVisitor {
|
||||
|
||||
void VisitObjective() {
|
||||
*maximize_ =
|
||||
top()->FindIntegerArgumentOrDie(ModelVisitor::kMaximizeArgument);
|
||||
Top()->FindIntegerArgumentOrDie(ModelVisitor::kMaximizeArgument);
|
||||
*objective_ =
|
||||
const_cast<IntExpr*>(top()->FindIntegerExpressionArgumentOrDie(
|
||||
const_cast<IntExpr*>(Top()->FindIntegerExpressionArgumentOrDie(
|
||||
ModelVisitor::kExpressionArgument))->Var();
|
||||
mp_solver_->SetObjectiveCoefficient(Translated(*objective_), 1.0);
|
||||
mp_solver_->SetOptimizationDirection(*maximize_);
|
||||
@@ -699,8 +549,6 @@ class Linearizer : public ModelVisitor {
|
||||
ExprTranslation* const translation_;
|
||||
IntVar** objective_;
|
||||
bool* maximize_;
|
||||
std::vector<ArgumentHolder*> holders_;
|
||||
std::vector<ArgumentHolder*> extensions_;
|
||||
std::vector<bool> actives_;
|
||||
};
|
||||
|
||||
|
||||
@@ -636,7 +636,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
const string& arg_name,
|
||||
const IntExpr* const argument) {
|
||||
top()->set_integer_expression_argument(arg_name,
|
||||
FindExpressionIndex(argument));
|
||||
FindExpressionIndexOrDie(argument));
|
||||
}
|
||||
|
||||
virtual void VisitIntegerVariableArrayArgument(
|
||||
@@ -645,7 +645,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
int size) {
|
||||
std::vector<int> indices;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
indices.push_back(FindExpressionIndex(arguments[i]));
|
||||
indices.push_back(FindExpressionIndexOrDie(arguments[i]));
|
||||
}
|
||||
top()->set_integer_variable_array_argument(arg_name,
|
||||
indices.data(),
|
||||
@@ -655,7 +655,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
virtual void VisitIntervalArgument(
|
||||
const string& arg_name,
|
||||
const IntervalVar* argument) {
|
||||
top()->set_interval_argument(arg_name, FindIntervalIndex(argument));
|
||||
top()->set_interval_argument(arg_name, FindIntervalIndexOrDie(argument));
|
||||
}
|
||||
|
||||
virtual void VisitIntervalArrayArgument(
|
||||
@@ -664,7 +664,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
int size) {
|
||||
std::vector<int> indices;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
indices.push_back(FindIntervalIndex(arguments[i]));
|
||||
indices.push_back(FindIntervalIndexOrDie(arguments[i]));
|
||||
}
|
||||
top()->set_interval_array_argument(arg_name,
|
||||
indices.data(),
|
||||
@@ -674,7 +674,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
virtual void VisitSequenceArgument(
|
||||
const string& arg_name,
|
||||
const SequenceVar* argument) {
|
||||
top()->set_sequence_argument(arg_name, FindSequenceIndex(argument));
|
||||
top()->set_sequence_argument(arg_name, FindSequenceIndexOrDie(argument));
|
||||
}
|
||||
|
||||
virtual void VisitSequenceArrayArgument(
|
||||
@@ -683,7 +683,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
int size) {
|
||||
std::vector<int> indices;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
indices.push_back(FindSequenceIndex(arguments[i]));
|
||||
indices.push_back(FindSequenceIndexOrDie(arguments[i]));
|
||||
}
|
||||
top()->set_sequence_array_argument(arg_name,
|
||||
indices.data(),
|
||||
@@ -701,7 +701,8 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(
|
||||
TagIndex(ModelVisitor::kExpressionArgument));
|
||||
sub_proto->set_integer_expression_index(FindExpressionIndex(delegate));
|
||||
sub_proto->set_integer_expression_index(
|
||||
FindExpressionIndexOrDie(delegate));
|
||||
} else {
|
||||
const int index = model_proto_->expressions_size();
|
||||
CPIntegerExpressionProto* const var_proto =
|
||||
@@ -744,7 +745,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(
|
||||
TagIndex(ModelVisitor::kVariableArgument));
|
||||
sub_proto->set_integer_expression_index(FindExpressionIndex(delegate));
|
||||
sub_proto->set_integer_expression_index(FindExpressionIndexOrDie(delegate));
|
||||
CPArgumentProto* const value_proto = var_proto->add_arguments();
|
||||
value_proto->set_argument_index(TagIndex(operation));
|
||||
value_proto->set_integer_value(value);
|
||||
@@ -760,7 +761,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
var_proto->set_type_index(TagIndex(ModelVisitor::kIntervalVariable));
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(TagIndex(operation));
|
||||
sub_proto->set_interval_index(FindIntervalIndex(delegate));
|
||||
sub_proto->set_interval_index(FindIntervalIndexOrDie(delegate));
|
||||
} else {
|
||||
const int index = model_proto_->intervals_size();
|
||||
CPIntervalVariableProto* const var_proto = model_proto_->add_intervals();
|
||||
@@ -816,7 +817,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(TagIndex(operation));
|
||||
for (int i = 0; i < size; ++i) {
|
||||
sub_proto->add_interval_array(FindIntervalIndex(delegates[i]));
|
||||
sub_proto->add_interval_array(FindIntervalIndexOrDie(delegates[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,7 +833,7 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
sub_proto->set_argument_index(TagIndex(ModelVisitor::kIntervalsArgument));
|
||||
for (int i = 0; i < sequence->size(); ++i) {
|
||||
IntervalVar* const interval = sequence->Interval(i);
|
||||
sub_proto->add_interval_array(FindIntervalIndex(interval));
|
||||
sub_proto->add_interval_array(FindIntervalIndexOrDie(interval));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,22 +943,16 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
return holders_.back();
|
||||
}
|
||||
|
||||
int FindExpressionIndex(const IntExpr* const expression) const {
|
||||
const int result = FindWithDefault(expression_map_, expression, -1);
|
||||
CHECK_NE(-1, result);
|
||||
return result;
|
||||
int FindExpressionIndexOrDie(const IntExpr* const expression) const {
|
||||
return FindOrDie(expression_map_, expression);
|
||||
}
|
||||
|
||||
int FindIntervalIndex(const IntervalVar* const interval) const {
|
||||
const int result = FindWithDefault(interval_map_, interval, -1);
|
||||
CHECK_NE(-1, result);
|
||||
return result;
|
||||
int FindIntervalIndexOrDie(const IntervalVar* const interval) const {
|
||||
return FindOrDie(interval_map_, interval);
|
||||
}
|
||||
|
||||
int FindSequenceIndex(const SequenceVar* const sequence) const {
|
||||
const int result = FindWithDefault(sequence_map_, sequence, -1);
|
||||
CHECK_NE(-1, result);
|
||||
return result;
|
||||
int FindSequenceIndexOrDie(const SequenceVar* const sequence) const {
|
||||
return FindOrDie(sequence_map_, sequence);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,22 @@ DEFINE_int32(cp_local_search_tsp_lns_size, 10,
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
// Utility methods to ensure the communication between local search and the
|
||||
// search.
|
||||
|
||||
// Returns true if a local optimum has been reached and that it cannot be
|
||||
// improved.
|
||||
bool LocalOptimumReached(Search* const search);
|
||||
|
||||
// Returns true if the search accepts the delta (actually checking this by
|
||||
// calling AcceptDelta on the monitors of the search).
|
||||
bool AcceptDelta(Search* const search,
|
||||
Assignment* delta,
|
||||
Assignment* deltadelta);
|
||||
|
||||
// Notifies the search that a neighbor has been accepted by local search.
|
||||
void AcceptNeighbor(Search* const search);
|
||||
|
||||
// ----- Base operator class for operators manipulating IntVars -----
|
||||
|
||||
IntVarLocalSearchOperator::IntVarLocalSearchOperator()
|
||||
@@ -2830,7 +2846,8 @@ Decision* FindOneNeighbor::Next(Solver* const solver) {
|
||||
// to resync filters on non-incremental (empty) moves.
|
||||
// TODO(user): Don't call both if no filter is incremental and one
|
||||
// of them returned false.
|
||||
const bool mh_filter = solver->AcceptDelta(delta, deltadelta);
|
||||
const bool mh_filter =
|
||||
AcceptDelta(solver->ParentSearch(), delta, deltadelta);
|
||||
const bool move_filter = FilterAccept(delta, deltadelta);
|
||||
if (mh_filter && move_filter) {
|
||||
solver->filtered_neighbors_ += 1;
|
||||
@@ -2845,7 +2862,7 @@ Decision* FindOneNeighbor::Next(Solver* const solver) {
|
||||
}
|
||||
} else {
|
||||
if (neighbor_found_) {
|
||||
solver->AcceptNeighbor();
|
||||
AcceptNeighbor(solver->ParentSearch());
|
||||
// Keeping the code in case a performance problem forces us to
|
||||
// use the old code with a zero test on pool_.
|
||||
// reference_assignment_->Copy(assignment_);
|
||||
@@ -3208,7 +3225,7 @@ Decision* LocalSearch::Next(Solver* const solver) {
|
||||
const int state = decision->state();
|
||||
switch (state) {
|
||||
case NestedSolveDecision::DECISION_FAILED: {
|
||||
if (!solver->LocalOptimum()) {
|
||||
if (!LocalOptimumReached(solver->ActiveSearch())) {
|
||||
nested_decision_index_ = -1; // Stop the search
|
||||
}
|
||||
solver->Fail();
|
||||
|
||||
@@ -1186,6 +1186,8 @@ RoutingModel::GetSelectedFirstSolutionStrategy() const {
|
||||
return ROUTING_PATH_CHEAPEST_ARC;
|
||||
} else if (FLAGS_routing_first_solution.compare("AllUnperformed") == 0) {
|
||||
return ROUTING_ALL_UNPERFORMED;
|
||||
} else if (FLAGS_routing_first_solution.compare("BestInsertion") == 0) {
|
||||
return ROUTING_BEST_INSERTION;
|
||||
}
|
||||
return first_solution_strategy_;
|
||||
}
|
||||
@@ -1963,19 +1965,32 @@ void RoutingModel::SetUpSearch() {
|
||||
kint64max);
|
||||
|
||||
std::vector<LocalSearchOperator*> operators = extra_operators_;
|
||||
LocalSearchOperator* insertion_operator = NULL;
|
||||
if (pickup_delivery_pairs_.size() > 0) {
|
||||
const IntVar* const* vehicle_vars =
|
||||
homogeneous_costs_ ? NULL : vehicle_vars_.get();
|
||||
operators.push_back(MakePairActive(solver_.get(),
|
||||
nexts_.get(),
|
||||
vehicle_vars,
|
||||
pickup_delivery_pairs_,
|
||||
size));
|
||||
insertion_operator = MakePairActive(solver_.get(),
|
||||
nexts_.get(),
|
||||
vehicle_vars,
|
||||
pickup_delivery_pairs_,
|
||||
size);
|
||||
operators.push_back(insertion_operator);
|
||||
operators.push_back(MakePairRelocate(solver_.get(),
|
||||
nexts_.get(),
|
||||
vehicle_vars,
|
||||
pickup_delivery_pairs_,
|
||||
size));
|
||||
} else {
|
||||
if (homogeneous_costs_) {
|
||||
insertion_operator = solver_->MakeOperator(nexts_.get(),
|
||||
size,
|
||||
Solver::MAKEACTIVE);
|
||||
} else {
|
||||
insertion_operator = solver_->MakeOperator(nexts_.get(),
|
||||
vehicle_vars_.get(),
|
||||
size,
|
||||
Solver::MAKEACTIVE);
|
||||
}
|
||||
}
|
||||
if (vehicles_ > 1) {
|
||||
if (!FLAGS_routing_no_relocate) {
|
||||
@@ -2034,62 +2049,6 @@ void RoutingModel::SetUpSearch() {
|
||||
Solver::CHOOSE_FIRST_UNBOUND,
|
||||
Solver::ASSIGN_MIN_VALUE);
|
||||
|
||||
DecisionBuilder* first_solution = finalize_solution;
|
||||
switch (GetSelectedFirstSolutionStrategy()) {
|
||||
case ROUTING_GLOBAL_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_GLOBAL_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost),
|
||||
Solver::CHOOSE_STATIC_GLOBAL_BEST);
|
||||
break;
|
||||
case ROUTING_LOCAL_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_LOCAL_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_FIRST_UNBOUND,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost));
|
||||
break;
|
||||
case ROUTING_PATH_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_PATH_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_PATH,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost));
|
||||
break;
|
||||
case ROUTING_EVALUATOR_STRATEGY:
|
||||
LG << "Using ROUTING_EVALUATOR_STRATEGY";
|
||||
CHECK(first_solution_evaluator_ != NULL);
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_PATH,
|
||||
NewPermanentCallback(
|
||||
first_solution_evaluator_.get(),
|
||||
&Solver::IndexEvaluator2::Run));
|
||||
break;
|
||||
case ROUTING_DEFAULT_STRATEGY:
|
||||
LG << "Using DEFAULT";
|
||||
break;
|
||||
case ROUTING_ALL_UNPERFORMED:
|
||||
first_solution =
|
||||
solver_->RevAlloc(new AllUnperformed(this));
|
||||
break;
|
||||
default:
|
||||
LOG(WARNING) << "Unknown argument for routing_first_solution, "
|
||||
"using default";
|
||||
}
|
||||
if (FLAGS_routing_use_first_solution_dive) {
|
||||
DecisionBuilder* apply =
|
||||
solver_->MakeApplyBranchSelector(NewPermanentCallback(&LeftDive));
|
||||
first_solution = solver_->Compose(apply, first_solution);
|
||||
}
|
||||
|
||||
std::vector<LocalSearchFilter*> filters;
|
||||
if (FLAGS_routing_use_objective_filter) {
|
||||
if (homogeneous_costs_) {
|
||||
@@ -2145,6 +2104,92 @@ void RoutingModel::SetUpSearch() {
|
||||
ls_limit_,
|
||||
filters);
|
||||
|
||||
DecisionBuilder* first_solution = finalize_solution;
|
||||
switch (GetSelectedFirstSolutionStrategy()) {
|
||||
case ROUTING_GLOBAL_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_GLOBAL_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost),
|
||||
Solver::CHOOSE_STATIC_GLOBAL_BEST);
|
||||
break;
|
||||
case ROUTING_LOCAL_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_LOCAL_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_FIRST_UNBOUND,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost));
|
||||
break;
|
||||
case ROUTING_PATH_CHEAPEST_ARC:
|
||||
LG << "Using ROUTING_PATH_CHEAPEST_ARC";
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_PATH,
|
||||
NewPermanentCallback(
|
||||
this,
|
||||
&RoutingModel::GetFirstSolutionCost));
|
||||
break;
|
||||
case ROUTING_EVALUATOR_STRATEGY:
|
||||
LG << "Using ROUTING_EVALUATOR_STRATEGY";
|
||||
CHECK(first_solution_evaluator_ != NULL);
|
||||
first_solution =
|
||||
solver_->MakePhase(nexts_.get(), size,
|
||||
Solver::CHOOSE_PATH,
|
||||
NewPermanentCallback(
|
||||
first_solution_evaluator_.get(),
|
||||
&Solver::IndexEvaluator2::Run));
|
||||
break;
|
||||
case ROUTING_DEFAULT_STRATEGY:
|
||||
LG << "Using DEFAULT";
|
||||
break;
|
||||
case ROUTING_ALL_UNPERFORMED:
|
||||
first_solution =
|
||||
solver_->RevAlloc(new AllUnperformed(this));
|
||||
break;
|
||||
case ROUTING_BEST_INSERTION: {
|
||||
LG << "Using ROUTING_BEST_INSERTION";
|
||||
SearchLimit* const ls_limit = solver_->MakeLimit(time_limit_ms_,
|
||||
kint64max,
|
||||
kint64max,
|
||||
kint64max,
|
||||
true);
|
||||
DecisionBuilder* const finalize =
|
||||
solver_->MakeSolveOnce(finalize_solution, lns_limit_);
|
||||
LocalSearchPhaseParameters* const insertion_parameters =
|
||||
solver_->MakeLocalSearchPhaseParameters(
|
||||
insertion_operator,
|
||||
finalize,
|
||||
ls_limit,
|
||||
filters);
|
||||
std::vector<SearchMonitor*> monitors;
|
||||
monitors.push_back(limit_);
|
||||
first_solution = solver_->MakeNestedOptimize(
|
||||
solver_->MakeLocalSearchPhase(
|
||||
nexts_.get(),
|
||||
size,
|
||||
solver_->RevAlloc(new AllUnperformed(this)),
|
||||
insertion_parameters),
|
||||
assignment_,
|
||||
false,
|
||||
FLAGS_routing_optimization_step,
|
||||
monitors);
|
||||
first_solution = solver_->Compose(first_solution, finalize);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(WARNING) << "Unknown argument for routing_first_solution, "
|
||||
"using default";
|
||||
}
|
||||
if (FLAGS_routing_use_first_solution_dive) {
|
||||
DecisionBuilder* apply =
|
||||
solver_->MakeApplyBranchSelector(NewPermanentCallback(&LeftDive));
|
||||
first_solution = solver_->Compose(apply, first_solution);
|
||||
}
|
||||
|
||||
if (FLAGS_routing_dfs) {
|
||||
solve_db_ = finalize_solution;
|
||||
} else {
|
||||
|
||||
@@ -198,7 +198,11 @@ class RoutingModel {
|
||||
ROUTING_EVALUATOR_STRATEGY,
|
||||
// Make all node inactive. Only finds a solution if nodes are optional (are
|
||||
// element of a disjunction constraint with a finite penalty cost).
|
||||
ROUTING_ALL_UNPERFORMED
|
||||
ROUTING_ALL_UNPERFORMED,
|
||||
// Iteratively build a solution by inserting nodes at their cheapest (best)
|
||||
// position. As of 2/2012, only works on models with optional nodes
|
||||
// (with finite penalty costs).
|
||||
ROUTING_BEST_INSERTION
|
||||
};
|
||||
|
||||
// Metaheuristics used to guide the search. Apart greedy descent, they will
|
||||
|
||||
311
constraint_solver/visitor.cc
Normal file
311
constraint_solver/visitor.cc
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright 2010-2011 Google
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "base/hash.h"
|
||||
#include "base/hash.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/integral_types.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "base/concise_iterator.h"
|
||||
#include "base/map-util.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "constraint_solver/constraint_solver.h"
|
||||
#include "constraint_solver/constraint_solveri.h"
|
||||
|
||||
namespace operations_research {
|
||||
// ---------- ArgumentHolder ----------
|
||||
|
||||
const string& ArgumentHolder::TypeName() const {
|
||||
return type_name_;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetTypeName(const string& type_name) {
|
||||
type_name_ = type_name;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntegerArgument(const string& arg_name, int64 value) {
|
||||
integer_argument_[arg_name] = value;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntegerArrayArgument(
|
||||
const string& arg_name,
|
||||
const int64* const values,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
integer_array_argument_[arg_name].push_back(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntegerMatrixArgument(
|
||||
const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns) {
|
||||
matrix_argument_[arg_name] = Matrix(values, rows, columns);
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntegerExpressionArgument(
|
||||
const string& arg_name,
|
||||
const IntExpr* const expr) {
|
||||
integer_expression_argument_[arg_name] = expr;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntegerVariableArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
integer_variable_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntervalArgument(
|
||||
const string& arg_name,
|
||||
const IntervalVar* const var) {
|
||||
interval_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetIntervalArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntervalVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
interval_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetSequenceArgument(
|
||||
const string& arg_name,
|
||||
const SequenceVar* const var) {
|
||||
sequence_argument_[arg_name] = var;
|
||||
}
|
||||
|
||||
void ArgumentHolder::SetSequenceArrayArgument(
|
||||
const string& arg_name,
|
||||
const SequenceVar* const * const vars,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
sequence_array_argument_[arg_name].push_back(vars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ArgumentHolder::HasIntegerExpressionArgument(
|
||||
const string& arg_name) const {
|
||||
return ContainsKey(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
bool ArgumentHolder::HasIntegerVariableArrayArgument(
|
||||
const string& arg_name) const {
|
||||
return ContainsKey(integer_variable_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
|
||||
int64 ArgumentHolder::FindIntegerArgumentWithDefault(
|
||||
const string& arg_name,
|
||||
int64 def) const {
|
||||
return FindWithDefault(integer_argument_, arg_name, def);
|
||||
}
|
||||
|
||||
int64 ArgumentHolder::FindIntegerArgumentOrDie(const string& arg_name) const {
|
||||
return FindOrDie(integer_argument_, arg_name);
|
||||
}
|
||||
|
||||
const std::vector<int64>& ArgumentHolder::FindIntegerArrayArgumentOrDie(
|
||||
const string& arg_name) const {
|
||||
return FindOrDie(integer_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
|
||||
const IntExpr* ArgumentHolder::FindIntegerExpressionArgumentOrDie(
|
||||
const string& arg_name) const {
|
||||
return FindOrDie(integer_expression_argument_, arg_name);
|
||||
}
|
||||
|
||||
const std::vector<const IntVar*>&
|
||||
ArgumentHolder::FindIntegerVariableArrayArgumentOrDie(
|
||||
const string& arg_name) const {
|
||||
return FindOrDie(integer_variable_array_argument_, arg_name);
|
||||
}
|
||||
|
||||
const ArgumentHolder::Matrix& ArgumentHolder::FindIntegerMatrixArgumentOrDie(
|
||||
const string& arg_name) const {
|
||||
return FindOrDie(matrix_argument_, arg_name);
|
||||
}
|
||||
|
||||
// ---------- ModelParser ---------
|
||||
|
||||
ModelParser::ModelParser() {}
|
||||
|
||||
ModelParser::~ModelParser() {
|
||||
CHECK(holders_.empty());
|
||||
}
|
||||
|
||||
void ModelParser::BeginVisitModel(const string& solver_name) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::EndVisitModel(const string& solver_name) {
|
||||
PopArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::BeginVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::EndVisitConstraint(const string& type_name,
|
||||
const Constraint* const constraint) {
|
||||
// Constraint parsing is usually done here.
|
||||
PopArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::BeginVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr) {
|
||||
PushArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::EndVisitIntegerExpression(const string& type_name,
|
||||
const IntExpr* const expr) {
|
||||
// Expression parsing is usually done here.
|
||||
PopArgumentHolder();
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntegerVariable(const IntVar* const variable,
|
||||
const IntExpr* const delegate) {
|
||||
// Usual place for parsing.
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntegerVariable(const IntVar* const variable,
|
||||
const string& operation,
|
||||
int64 value,
|
||||
const IntVar* const delegate) {
|
||||
delegate->Accept(this);
|
||||
// Usual place for parsing.
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntervalVariable(const IntervalVar* const variable,
|
||||
const string& operation,
|
||||
const IntervalVar* const delegate) {
|
||||
if (delegate != NULL) {
|
||||
delegate->Accept(this);
|
||||
}
|
||||
// Usual place for parsing.
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntervalVariable(const IntervalVar* const variable,
|
||||
const string& operation,
|
||||
const IntervalVar* const * delegates,
|
||||
int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
delegates[i]->Accept(this);
|
||||
}
|
||||
// Usual place for parsing.
|
||||
}
|
||||
|
||||
void ModelParser::VisitSequenceVariable(const SequenceVar* const variable) {
|
||||
// Usual place for parsing.
|
||||
}
|
||||
|
||||
// Integer arguments
|
||||
void ModelParser::VisitIntegerArgument(const string& arg_name, int64 value) {
|
||||
Top()->SetIntegerArgument(arg_name, value);
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntegerArrayArgument(const string& arg_name,
|
||||
const int64* const values,
|
||||
int size) {
|
||||
Top()->SetIntegerArrayArgument(arg_name, values, size);
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntegerMatrixArgument(const string& arg_name,
|
||||
const int64* const * const values,
|
||||
int rows,
|
||||
int columns) {
|
||||
Top()->SetIntegerMatrixArgument(arg_name, values, rows, columns);
|
||||
}
|
||||
|
||||
// Variables.
|
||||
void ModelParser::VisitIntegerExpressionArgument(
|
||||
const string& arg_name,
|
||||
const IntExpr* const argument) {
|
||||
Top()->SetIntegerExpressionArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntegerVariableArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntVar* const * arguments,
|
||||
int size) {
|
||||
Top()->SetIntegerVariableArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit interval argument.
|
||||
void ModelParser::VisitIntervalArgument(
|
||||
const string& arg_name,
|
||||
const IntervalVar* const argument) {
|
||||
Top()->SetIntervalArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
void ModelParser::VisitIntervalArrayArgument(
|
||||
const string& arg_name,
|
||||
const IntervalVar* const * arguments,
|
||||
int size) {
|
||||
Top()->SetIntervalArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit sequence argument.
|
||||
void ModelParser::VisitSequenceArgument(
|
||||
const string& arg_name,
|
||||
const SequenceVar* const argument) {
|
||||
Top()->SetSequenceArgument(arg_name, argument);
|
||||
argument->Accept(this);
|
||||
}
|
||||
|
||||
void ModelParser::VisitSequenceArrayArgument(
|
||||
const string& arg_name,
|
||||
const SequenceVar* const * arguments,
|
||||
int size) {
|
||||
Top()->SetSequenceArrayArgument(arg_name, arguments, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
arguments[i]->Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelParser::PushArgumentHolder() {
|
||||
holders_.push_back(new ArgumentHolder);
|
||||
}
|
||||
|
||||
void ModelParser::PopArgumentHolder() {
|
||||
CHECK(!holders_.empty());
|
||||
delete holders_.back();
|
||||
holders_.pop_back();
|
||||
}
|
||||
|
||||
ArgumentHolder* ModelParser::Top() const {
|
||||
CHECK(!holders_.empty());
|
||||
return holders_.back();
|
||||
}
|
||||
} // namespace operations_research
|
||||
@@ -171,7 +171,8 @@ CONSTRAINT_SOLVER_LIB_OS = \
|
||||
objs/timetabling.$O\
|
||||
objs/trace.$O\
|
||||
objs/tree_monitor.$O\
|
||||
objs/utilities.$O
|
||||
objs/utilities.$O \
|
||||
objs/visitor.$O
|
||||
|
||||
objs/alldiff_cst.$O:constraint_solver/alldiff_cst.cc
|
||||
$(CCC) $(CFLAGS) -c constraint_solver/alldiff_cst.cc $(OBJOUT)objs/alldiff_cst.$O
|
||||
@@ -295,6 +296,9 @@ objs/tree_monitor.$O:constraint_solver/tree_monitor.cc
|
||||
objs/utilities.$O:constraint_solver/utilities.cc
|
||||
$(CCC) $(CFLAGS) -c constraint_solver/utilities.cc $(OBJOUT)objs/utilities.$O
|
||||
|
||||
objs/visitor.$O:constraint_solver/visitor.cc
|
||||
$(CCC) $(CFLAGS) -c constraint_solver/visitor.cc $(OBJOUT)objs/visitor.$O
|
||||
|
||||
$(LIBPREFIX)constraint_solver.$(LIBSUFFIX): $(CONSTRAINT_SOLVER_LIB_OS)
|
||||
$(LINKCMD) $(LINKPREFIX)$(LIBPREFIX)constraint_solver.$(LIBSUFFIX) $(CONSTRAINT_SOLVER_LIB_OS)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user