265 lines
8.6 KiB
C++
265 lines
8.6 KiB
C++
// Copyright 2010-2022 Google LLC
|
|
// 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 <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "absl/container/flat_hash_map.h"
|
|
#include "absl/container/flat_hash_set.h"
|
|
#include "ortools/base/integral_types.h"
|
|
#include "ortools/base/logging.h"
|
|
#include "ortools/base/macros.h"
|
|
#include "ortools/base/map_util.h"
|
|
#include "ortools/base/stl_util.h"
|
|
#include "ortools/constraint_solver/constraint_solver.h"
|
|
#include "ortools/constraint_solver/constraint_solveri.h"
|
|
|
|
namespace operations_research {
|
|
// ---------- ArgumentHolder ----------
|
|
|
|
const std::string& ArgumentHolder::TypeName() const { return type_name_; }
|
|
|
|
void ArgumentHolder::SetTypeName(const std::string& type_name) {
|
|
type_name_ = type_name;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntegerArgument(const std::string& arg_name,
|
|
int64_t value) {
|
|
integer_argument_[arg_name] = value;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntegerArrayArgument(
|
|
const std::string& arg_name, const std::vector<int64_t>& values) {
|
|
integer_array_argument_[arg_name] = values;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntegerMatrixArgument(const std::string& arg_name,
|
|
const IntTupleSet& values) {
|
|
std::pair<std::string, IntTupleSet> to_insert =
|
|
std::make_pair(arg_name, values);
|
|
matrix_argument_.insert(to_insert);
|
|
}
|
|
|
|
void ArgumentHolder::SetIntegerExpressionArgument(const std::string& arg_name,
|
|
IntExpr* const expr) {
|
|
integer_expression_argument_[arg_name] = expr;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntegerVariableArrayArgument(
|
|
const std::string& arg_name, const std::vector<IntVar*>& vars) {
|
|
integer_variable_array_argument_[arg_name] = vars;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntervalArgument(const std::string& arg_name,
|
|
IntervalVar* const var) {
|
|
interval_argument_[arg_name] = var;
|
|
}
|
|
|
|
void ArgumentHolder::SetIntervalArrayArgument(
|
|
const std::string& arg_name, const std::vector<IntervalVar*>& vars) {
|
|
interval_array_argument_[arg_name] = vars;
|
|
}
|
|
|
|
void ArgumentHolder::SetSequenceArgument(const std::string& arg_name,
|
|
SequenceVar* const var) {
|
|
sequence_argument_[arg_name] = var;
|
|
}
|
|
|
|
void ArgumentHolder::SetSequenceArrayArgument(
|
|
const std::string& arg_name, const std::vector<SequenceVar*>& vars) {
|
|
sequence_array_argument_[arg_name] = vars;
|
|
}
|
|
|
|
bool ArgumentHolder::HasIntegerExpressionArgument(
|
|
const std::string& arg_name) const {
|
|
return integer_expression_argument_.contains(arg_name);
|
|
}
|
|
|
|
bool ArgumentHolder::HasIntegerVariableArrayArgument(
|
|
const std::string& arg_name) const {
|
|
return integer_variable_array_argument_.contains(arg_name);
|
|
}
|
|
|
|
int64_t ArgumentHolder::FindIntegerArgumentWithDefault(
|
|
const std::string& arg_name, int64_t def) const {
|
|
return gtl::FindWithDefault(integer_argument_, arg_name, def);
|
|
}
|
|
|
|
int64_t ArgumentHolder::FindIntegerArgumentOrDie(
|
|
const std::string& arg_name) const {
|
|
return gtl::FindOrDie(integer_argument_, arg_name);
|
|
}
|
|
|
|
const std::vector<int64_t>& ArgumentHolder::FindIntegerArrayArgumentOrDie(
|
|
const std::string& arg_name) const {
|
|
return gtl::FindOrDie(integer_array_argument_, arg_name);
|
|
}
|
|
|
|
IntExpr* ArgumentHolder::FindIntegerExpressionArgumentOrDie(
|
|
const std::string& arg_name) const {
|
|
return gtl::FindOrDie(integer_expression_argument_, arg_name);
|
|
}
|
|
|
|
const std::vector<IntVar*>&
|
|
ArgumentHolder::FindIntegerVariableArrayArgumentOrDie(
|
|
const std::string& arg_name) const {
|
|
return gtl::FindOrDie(integer_variable_array_argument_, arg_name);
|
|
}
|
|
|
|
const IntTupleSet& ArgumentHolder::FindIntegerMatrixArgumentOrDie(
|
|
const std::string& arg_name) const {
|
|
return gtl::FindOrDie(matrix_argument_, arg_name);
|
|
}
|
|
|
|
// ---------- ModelParser ---------
|
|
|
|
ModelParser::ModelParser() {}
|
|
|
|
ModelParser::~ModelParser() { CHECK(holders_.empty()); }
|
|
|
|
void ModelParser::BeginVisitModel(const std::string& solver_name) {
|
|
PushArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::EndVisitModel(const std::string& solver_name) {
|
|
PopArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::BeginVisitConstraint(const std::string& type_name,
|
|
const Constraint* const constraint) {
|
|
PushArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::EndVisitConstraint(const std::string& type_name,
|
|
const Constraint* const constraint) {
|
|
// Constraint parsing is usually done here.
|
|
PopArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::BeginVisitIntegerExpression(const std::string& type_name,
|
|
const IntExpr* const expr) {
|
|
PushArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::EndVisitIntegerExpression(const std::string& type_name,
|
|
const IntExpr* const expr) {
|
|
// Expression parsing is usually done here.
|
|
PopArgumentHolder();
|
|
}
|
|
|
|
void ModelParser::VisitIntegerVariable(const IntVar* const variable,
|
|
IntExpr* const delegate) {
|
|
// Usual place for parsing.
|
|
}
|
|
|
|
void ModelParser::VisitIntegerVariable(const IntVar* const variable,
|
|
const std::string& operation,
|
|
int64_t value, IntVar* const delegate) {
|
|
delegate->Accept(this);
|
|
// Usual place for parsing.
|
|
}
|
|
|
|
void ModelParser::VisitIntervalVariable(const IntervalVar* const variable,
|
|
const std::string& operation,
|
|
int64_t value,
|
|
IntervalVar* const delegate) {
|
|
if (delegate != nullptr) {
|
|
delegate->Accept(this);
|
|
}
|
|
// Usual place for parsing.
|
|
}
|
|
|
|
void ModelParser::VisitSequenceVariable(const SequenceVar* const variable) {
|
|
// Usual place for parsing.
|
|
}
|
|
|
|
// Integer arguments
|
|
void ModelParser::VisitIntegerArgument(const std::string& arg_name,
|
|
int64_t value) {
|
|
Top()->SetIntegerArgument(arg_name, value);
|
|
}
|
|
|
|
void ModelParser::VisitIntegerArrayArgument(
|
|
const std::string& arg_name, const std::vector<int64_t>& values) {
|
|
Top()->SetIntegerArrayArgument(arg_name, values);
|
|
}
|
|
|
|
void ModelParser::VisitIntegerMatrixArgument(const std::string& arg_name,
|
|
const IntTupleSet& values) {
|
|
Top()->SetIntegerMatrixArgument(arg_name, values);
|
|
}
|
|
|
|
// Variables.
|
|
void ModelParser::VisitIntegerExpressionArgument(const std::string& arg_name,
|
|
IntExpr* const argument) {
|
|
Top()->SetIntegerExpressionArgument(arg_name, argument);
|
|
argument->Accept(this);
|
|
}
|
|
|
|
void ModelParser::VisitIntegerVariableArrayArgument(
|
|
const std::string& arg_name, const std::vector<IntVar*>& arguments) {
|
|
Top()->SetIntegerVariableArrayArgument(arg_name, arguments);
|
|
for (int i = 0; i < arguments.size(); ++i) {
|
|
arguments[i]->Accept(this);
|
|
}
|
|
}
|
|
|
|
// Visit interval argument.
|
|
void ModelParser::VisitIntervalArgument(const std::string& arg_name,
|
|
IntervalVar* const argument) {
|
|
Top()->SetIntervalArgument(arg_name, argument);
|
|
argument->Accept(this);
|
|
}
|
|
|
|
void ModelParser::VisitIntervalArrayArgument(
|
|
const std::string& arg_name, const std::vector<IntervalVar*>& arguments) {
|
|
Top()->SetIntervalArrayArgument(arg_name, arguments);
|
|
for (int i = 0; i < arguments.size(); ++i) {
|
|
arguments[i]->Accept(this);
|
|
}
|
|
}
|
|
|
|
// Visit sequence argument.
|
|
void ModelParser::VisitSequenceArgument(const std::string& arg_name,
|
|
SequenceVar* const argument) {
|
|
Top()->SetSequenceArgument(arg_name, argument);
|
|
argument->Accept(this);
|
|
}
|
|
|
|
void ModelParser::VisitSequenceArrayArgument(
|
|
const std::string& arg_name, const std::vector<SequenceVar*>& arguments) {
|
|
Top()->SetSequenceArrayArgument(arg_name, arguments);
|
|
for (int i = 0; i < arguments.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
|