Files
ortools-clone/ortools/math_opt/cpp/model.h
Corentin Le Molgat f98afa8e42 Add missing STL include
2022-07-22 16:25:40 +02:00

813 lines
32 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.
#ifndef OR_TOOLS_MATH_OPT_CPP_MODEL_H_
#define OR_TOOLS_MATH_OPT_CPP_MODEL_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "ortools/base/logging.h"
#include "ortools/base/status_builder.h"
#include "ortools/math_opt/cpp/key_types.h"
#include "ortools/math_opt/cpp/linear_constraint.h" // IWYU pragma: export
#include "ortools/math_opt/cpp/update_tracker.h" // IWYU pragma: export
#include "ortools/math_opt/cpp/variable_and_expressions.h" // IWYU pragma: export
#include "ortools/math_opt/model.pb.h" // IWYU pragma: export
#include "ortools/math_opt/model_update.pb.h" // IWYU pragma: export
#include "ortools/math_opt/storage/model_storage.h"
#include "ortools/math_opt/storage/model_storage_types.h"
namespace operations_research {
namespace math_opt {
// A C++ API for building optimization problems.
//
// Warning: Variable and LinearConstraint are value types, see "Memory Model"
// below.
//
// A simple example:
//
// Model the problem:
// max 2.0 * x + y
// s.t. x + y <= 1.5
// x in {0.0, 1.0}
// y in [0.0, 2.5]
//
// math_opt::Model model("my_model");
// const math_opt::Variable x = model.AddBinaryVariable("x");
// const math_opt::Variable y = model.AddContinuousVariable(0.0, 2.5, "y");
// // We can directly use linear combinations of variables ...
// model.AddLinearConstraint(x + y <= 1.5, "c");
// // ... or build them incrementally.
// math_opt::LinearExpression objective_expression;
// objective_expression += 2 * x;
// objective_expression += y;
// model.Maximize(objective_expression);
// ASSIGN_OR_RETURN(const math_opt::SolveResult result,
// Solve(model, math_opt::SolverType::kGscip));
// switch (result.termination.reason) {
// case math_opt::TerminationReason::kOptimal:
// case math_opt::TerminationReason::kFeasible:
// std::cout << "objective value: " << result.objective_value() << std::endl
// << "value for variable x: " << result.variable_values().at(x)
// << std::endl;
// return absl::OkStatus();
// default:
// return util::InternalErrorBuilder()
// << "model failed to solve: " << result.termination;
// }
//
// Memory model:
//
// Variable and LinearConstraint are value types that represent references to
// the underlying Model object. They don't hold any of the actual model data,
// they can be copied, and they should be passed by value. They can be
// regenerated arbitrarily from Model. Model holds all the data.
//
// Performance:
//
// This class is a thin wrapper around ModelStorage (for incrementally building
// the model and reading it back, and producing the Model proto) and Solver (for
// consuming the Model proto to solve the optimization problem). Operations for
// building/reading/modifying the problem typically run in O(read/write size)
// and rely on hashing, see the indexed model documentation for details. At
// solve time (if you are solving locally) beware that there will be (at least)
// three copies of the model in memory, ModelStorage, the Model proto, and the
// underlying solver's copy(/ies). Note that the Model proto is reclaimed before
// the underlying solver begins solving.
class Model {
public:
// Returns a model from the input proto. Returns a failure status if the input
// proto is invalid.
//
// On top of loading a model from a MathOpt ModelProto, this function can also
// be used to load a model from other formats using the functions in
// math_opt/io/ like ReadMpsFile().
//
// See ExportModel() to get the proto of a Model. See ApplyUpdateProto() to
// apply an update to the model.
//
// Usage example reading an MPS file:
// ASSIGN_OR_RETURN(const ModelProto model_proto, ReadMpsFile(path));
// ASSIGN_OR_RETURN(const std::unique_ptr<Model> model,
// Model::FromModelProto(model_proto));
static absl::StatusOr<std::unique_ptr<Model>> FromModelProto(
const ModelProto& model_proto);
// Creates an empty minimization problem.
explicit Model(absl::string_view name = "");
// Creates a model from the existing model storage.
//
// This constructor is used when loading a model, for example from a
// ModelProto or an MPS file. Note that in those cases the FromModelProto()
// should be used.
explicit Model(std::unique_ptr<ModelStorage> storage);
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
// Returns a clone of this model, optionally changing the model's name.
//
// The variables and constraints have the same integer ids. The clone will
// also not reused any id of variable/constraint that was deleted in the
// original.
//
// That said, the Variable and LinearConstraint reference objects are model
// specific. Hence the ones linked to the original model must NOT be used with
// the clone. The Variable and LinearConstraint reference objects for the
// clone can be obtained using:
// * the variable() and linear_constraint() methods on the ids from the old
// Variable and LinearConstraint objects.
// * in increasing id order using SortedVariables() and
// SortedLinearConstraints()
// * in an arbitrary order using Variables() and LinearConstraints().
//
// Note that the returned model does not have any update tracker.
std::unique_ptr<Model> Clone(
std::optional<absl::string_view> new_name = std::nullopt) const;
inline const std::string& name() const;
// Adds a variable to the model and returns a reference to it.
inline Variable AddVariable(double lower_bound, double upper_bound,
bool is_integer, absl::string_view name = "");
// Adds a continuous unbounded variable to the model.
inline Variable AddVariable(absl::string_view name = "");
// Adds an variable to the model with domain {0, 1}.
inline Variable AddBinaryVariable(absl::string_view name = "");
// Adds a variable to the model with domain [lower_bound, upper_bound].
inline Variable AddContinuousVariable(double lower_bound, double upper_bound,
absl::string_view name = "");
// Adds a variable to the model that can take integer values between
// lower_bound and upper_bound (inclusive).
inline Variable AddIntegerVariable(double lower_bound, double upper_bound,
absl::string_view name = "");
// Removes a variable from the model.
//
// It is an error to use any reference to this variable after this operation.
// Runs in O(#constraints containing the variable).
inline void DeleteVariable(Variable variable);
// The number of variables in the model.
//
// Equal to the number of variables created minus the number of variables
// deleted.
inline int num_variables() const;
// The returned id of the next call to AddVariable.
//
// Equal to the number of variables created.
inline int64_t next_variable_id() const;
// Returns true if this id has been created and not yet deleted.
inline bool has_variable(int64_t id) const;
// Returns true if this id has been created and not yet deleted.
inline bool has_variable(VariableId id) const;
// Will CHECK if has_variable(id) is false.
inline Variable variable(int64_t id) const;
// Will CHECK if has_variable(id) is false.
inline Variable variable(VariableId id) const;
// Returns the variable name.
inline const std::string& name(Variable variable) const;
// Sets a variable lower bound.
inline void set_lower_bound(Variable variable, double lower_bound);
// Returns a variable lower bound.
inline double lower_bound(Variable variable) const;
// Sets a variable upper bound.
inline void set_upper_bound(Variable variable, double upper_bound);
// Returns a variable upper bound.
inline double upper_bound(Variable variable) const;
// Sets the integrality of a variable.
inline void set_is_integer(Variable variable, bool is_integer);
// Makes the input variable integer.
inline void set_integer(Variable variable);
// Makes the input variable continuous.
inline void set_continuous(Variable variable);
// Returns the integrality of a variable.
inline bool is_integer(Variable variable) const;
// Returns all the existing (created and not deleted) variables in the model
// in an arbitrary order.
std::vector<Variable> Variables() const;
// Returns all the existing (created and not deleted) variables in the model,
// sorted by id.
std::vector<Variable> SortedVariables() const;
std::vector<LinearConstraint> ColumnNonzeros(Variable variable) const;
// Adds a linear constraint to the model with bounds [-inf, +inf].
inline LinearConstraint AddLinearConstraint(absl::string_view name = "");
// Adds a linear constraint with bounds [lower_bound, upper_bound].
inline LinearConstraint AddLinearConstraint(double lower_bound,
double upper_bound,
absl::string_view name = "");
// Adds a linear constraint from the given bounded linear expression.
//
// Usage:
// Model model = ...;
// const Variable x = ...;
// const Variable y = ...;
// model.AddLinearConstraint(3 <= 2 * x + y + 1 <= 5, "c");
// // The new constraint formula is:
// // 3 - 1 <= 2 * x + y <= 5 - 1
// // Which is:
// // 2 <= 2 * x + y <= 4
// // since the offset has been removed from bounds.
//
// model.AddLinearConstraint(2 * x + y == x + 5 * z + 3);
// model.AddLinearConstraint(x >= 5);
LinearConstraint AddLinearConstraint(
const BoundedLinearExpression& bounded_expr, absl::string_view name = "");
// Removes a linear constraint from the model.
//
// It is an error to use any reference to this linear constraint after this
// operation. Runs in O(#variables in the linear constraint).
inline void DeleteLinearConstraint(LinearConstraint constraint);
// The number of linear constraints in the model.
//
// Equal to the number of linear constraints created minus the number of
// linear constraints deleted.
inline int num_linear_constraints() const;
// The returned id of the next call to AddLinearConstraint.
//
// Equal to the number of linear constraints created.
inline int64_t next_linear_constraint_id() const;
// Returns true if this id has been created and not yet deleted.
inline bool has_linear_constraint(int64_t id) const;
// Returns true if this id has been created and not yet deleted.
inline bool has_linear_constraint(LinearConstraintId id) const;
// Will CHECK if has_linear_constraint(id) is false.
inline LinearConstraint linear_constraint(int64_t id) const;
// Will CHECK if has_linear_constraint(id) is false.
inline LinearConstraint linear_constraint(LinearConstraintId id) const;
// Returns the linear constraint name.
inline const std::string& name(LinearConstraint constraint) const;
// Sets a linear constraint lower bound.
inline void set_lower_bound(LinearConstraint constraint, double lower_bound);
// Returns a linear constraint lower bound.
inline double lower_bound(LinearConstraint constraint) const;
// Sets a linear constraint upper bound.
inline void set_upper_bound(LinearConstraint constraint, double upper_bound);
// Returns a linear constraint upper bound.
inline double upper_bound(LinearConstraint constraint) const;
// Setting a value to 0.0 will delete the {constraint, variable} pair from the
// underlying sparse matrix representation (and has no effect if the pair is
// not present).
inline void set_coefficient(LinearConstraint constraint, Variable variable,
double value);
// Returns 0.0 if the variable is not used in the constraint.
inline double coefficient(LinearConstraint constraint,
Variable variable) const;
inline bool is_coefficient_nonzero(LinearConstraint constraint,
Variable variable) const;
std::vector<Variable> RowNonzeros(LinearConstraint constraint) const;
BoundedLinearExpression AsBoundedLinearExpression(
LinearConstraint constraint) const;
// Returns all the existing (created and not deleted) linear constraints in
// the model in an arbitrary order.
std::vector<LinearConstraint> LinearConstraints() const;
// Returns all the existing (created and not deleted) linear constraints in
// the model sorted by id.
std::vector<LinearConstraint> SortedLinearConstraints() const;
// Sets the objective to maximize the provided expression.
inline void Maximize(double objective);
// Sets the objective to maximize the provided expression.
inline void Maximize(Variable objective);
// Sets the objective to maximize the provided expression.
inline void Maximize(LinearTerm objective);
// Sets the objective to maximize the provided expression.
inline void Maximize(const LinearExpression& objective);
// Sets the objective to maximize the provided expression.
inline void Maximize(const QuadraticExpression& objective);
// Sets the objective to minimize the provided expression.
inline void Minimize(double objective);
// Sets the objective to minimize the provided expression.
inline void Minimize(Variable objective);
// Sets the objective to minimize the provided expression.
inline void Minimize(LinearTerm objective);
// Sets the objective to minimize the provided expression.
inline void Minimize(const LinearExpression& objective);
// Sets the objective to minimize the provided expression.
inline void Minimize(const QuadraticExpression& objective);
// Sets the objective to optimize the provided expression.
inline void SetObjective(double objective, bool is_maximize);
// Sets the objective to optimize the provided expression.
inline void SetObjective(Variable objective, bool is_maximize);
// Sets the objective to optimize the provided expression.
inline void SetObjective(LinearTerm objective, bool is_maximize);
// Sets the objective to optimize the provided expression.
void SetObjective(const LinearExpression& objective, bool is_maximize);
// Sets the objective to optimize the provided expression.
void SetObjective(const QuadraticExpression& objective, bool is_maximize);
// Adds the provided expression terms to the objective.
inline void AddToObjective(double objective);
// Adds the provided expression terms to the objective.
inline void AddToObjective(Variable objective);
// Adds the provided expression terms to the objective.
inline void AddToObjective(LinearTerm objective);
// Adds the provided expression terms to the objective.
void AddToObjective(const LinearExpression& objective);
// Adds the provided expression terms to the objective.
void AddToObjective(const QuadraticExpression& objective);
// NOTE: This will CHECK fail if the objective has quadratic terms.
LinearExpression ObjectiveAsLinearExpression() const;
QuadraticExpression ObjectiveAsQuadraticExpression() const;
// Returns 0.0 if this variable has no linear objective coefficient.
inline double objective_coefficient(Variable variable) const;
// Returns 0.0 if this variable pair has no quadratic objective coefficient.
// The order of the variables does not matter.
inline double objective_coefficient(Variable first_variable,
Variable second_variable) const;
// Setting a value to 0.0 will delete the variable from the underlying sparse
// representation (and has no effect if the variable is not present).
inline void set_objective_coefficient(Variable variable, double value);
// Set quadratic objective terms for the product of two variables. Setting a
// value to 0.0 will delete the variable pair from the underlying sparse
// representation (and has no effect if the pair is not present). The order of
// the variables does not matter.
inline void set_objective_coefficient(Variable first_variable,
Variable second_variable, double value);
// Equivalent to calling set_linear_coefficient(v, 0.0) for every variable
// with nonzero objective coefficient.
//
// Runs in O(#linear and quadratic objective terms with nonzero coefficient).
inline void clear_objective();
inline bool is_objective_coefficient_nonzero(Variable variable) const;
inline bool is_objective_coefficient_nonzero(Variable first_variable,
Variable second_variable) const;
inline double objective_offset() const;
inline void set_objective_offset(double value);
inline bool is_maximize() const;
inline void set_maximize();
inline void set_minimize();
// Prefer set_maximize() and set_minimize() above for more readable code.
inline void set_is_maximize(bool is_maximize);
// Returns a proto representation of the optimization model.
//
// See FromModelProto() to build a Model from a proto.
ModelProto ExportModel() const;
// Returns a tracker that can be used to generate a ModelUpdateProto with the
// updates that happened since the last checkpoint. The tracker initial
// checkpoint corresponds to the current state of the model.
//
// The returned UpdateTracker keeps a reference to this model. See the
// implications in the documentation of the UpdateTracker class.
//
// Thread-safety: this method must not be used while modifying the model
// (variables, constraints, ...). The user is expected to use proper
// synchronization primitive to serialize changes to the model and the use of
// this method.
std::unique_ptr<UpdateTracker> NewUpdateTracker();
// Apply the provided update to this model. Returns a failure if the update is
// not valid.
//
// As with FromModelProto(), duplicated names are ignored.
//
// Note that it takes O(num_variables + num_constraints) extra memory and
// execution to apply the update (due to the need to build a ModelSummary). So
// even a small update will have some cost.
absl::Status ApplyUpdateProto(const ModelUpdateProto& update_proto);
// TODO(user): expose a way to efficiently iterate through the nonzeros of
// the linear constraint matrix.
// Returns a pointer to the underlying model storage.
//
// This API is for internal use only and regular users should have no need for
// it.
const ModelStorage* storage() const { return storage_.get(); }
// Returns a pointer to the underlying model storage.
//
// This API is for internal use only and regular users should have no need for
// it.
ModelStorage* storage() { return storage_.get(); }
// Prints the objective, the constraints and the variables of the model over
// several lines in a human-readable way. Includes a new line at the end of
// the model.
friend std::ostream& operator<<(std::ostream& ostr, const Model& model);
private:
// Asserts (with CHECK) that the input pointer is either nullptr or that it
// points to the same model as storage_.
//
// Use CheckModel() when nullptr is not a valid value.
inline void CheckOptionalModel(const ModelStorage* other_storage) const;
// Asserts (with CHECK) that the input pointer is the same as storage_.
//
// Use CheckOptionalModel() if nullptr is a valid value too.
inline void CheckModel(const ModelStorage* other_storage) const;
// Don't use storage_ directly; prefer to use storage() so that const member
// functions don't have modifying access to the underlying storage.
//
// We use a shared_ptr here so that the UpdateTracker class can have a
// weak_ptr on the ModelStorage. This let it have a destructor that don't
// crash when called after the destruction of the associated Model.
const std::shared_ptr<ModelStorage> storage_;
};
////////////////////////////////////////////////////////////////////////////////
// Inline function implementations
////////////////////////////////////////////////////////////////////////////////
const std::string& Model::name() const { return storage()->name(); }
Variable Model::AddVariable(const absl::string_view name) {
return Variable(storage(), storage()->AddVariable(name));
}
Variable Model::AddVariable(const double lower_bound, const double upper_bound,
const bool is_integer,
const absl::string_view name) {
return Variable(storage(), storage()->AddVariable(lower_bound, upper_bound,
is_integer, name));
}
Variable Model::AddBinaryVariable(const absl::string_view name) {
return AddVariable(0.0, 1.0, true, name);
}
Variable Model::AddContinuousVariable(const double lower_bound,
const double upper_bound,
const absl::string_view name) {
return AddVariable(lower_bound, upper_bound, false, name);
}
Variable Model::AddIntegerVariable(const double lower_bound,
const double upper_bound,
const absl::string_view name) {
return AddVariable(lower_bound, upper_bound, true, name);
}
void Model::DeleteVariable(const Variable variable) {
CheckModel(variable.storage());
storage()->DeleteVariable(variable.typed_id());
}
int Model::num_variables() const { return storage()->num_variables(); }
int64_t Model::next_variable_id() const {
return storage()->next_variable_id().value();
}
bool Model::has_variable(const int64_t id) const {
return has_variable(VariableId(id));
}
bool Model::has_variable(const VariableId id) const {
return storage()->has_variable(id);
}
Variable Model::variable(const int64_t id) const {
return variable(VariableId(id));
}
Variable Model::variable(const VariableId id) const {
CHECK(has_variable(id)) << "No variable with id: " << id.value();
return Variable(storage(), id);
}
const std::string& Model::name(const Variable variable) const {
CheckModel(variable.storage());
return storage()->variable_name(variable.typed_id());
}
void Model::set_lower_bound(const Variable variable, double lower_bound) {
CheckModel(variable.storage());
storage()->set_variable_lower_bound(variable.typed_id(), lower_bound);
}
double Model::lower_bound(const Variable variable) const {
CheckModel(variable.storage());
return storage()->variable_lower_bound(variable.typed_id());
}
void Model::set_upper_bound(const Variable variable, double upper_bound) {
CheckModel(variable.storage());
storage()->set_variable_upper_bound(variable.typed_id(), upper_bound);
}
double Model::upper_bound(const Variable variable) const {
CheckModel(variable.storage());
return storage()->variable_upper_bound(variable.typed_id());
}
void Model::set_is_integer(const Variable variable, bool is_integer) {
CheckModel(variable.storage());
storage()->set_variable_is_integer(variable.typed_id(), is_integer);
}
void Model::set_integer(const Variable variable) {
set_is_integer(variable, true);
}
void Model::set_continuous(const Variable variable) {
set_is_integer(variable, false);
}
bool Model::is_integer(const Variable variable) const {
CheckModel(variable.storage());
return storage()->is_variable_integer(variable.typed_id());
}
LinearConstraint Model::AddLinearConstraint(const absl::string_view name) {
return LinearConstraint(storage(), storage()->AddLinearConstraint(name));
}
LinearConstraint Model::AddLinearConstraint(const double lower_bound,
const double upper_bound,
const absl::string_view name) {
return LinearConstraint(storage(), storage()->AddLinearConstraint(
lower_bound, upper_bound, name));
}
void Model::DeleteLinearConstraint(const LinearConstraint constraint) {
CheckModel(constraint.storage());
storage()->DeleteLinearConstraint(constraint.typed_id());
}
int Model::num_linear_constraints() const {
return storage()->num_linear_constraints();
}
int64_t Model::next_linear_constraint_id() const {
return storage()->next_linear_constraint_id().value();
}
bool Model::has_linear_constraint(const int64_t id) const {
return has_linear_constraint(LinearConstraintId(id));
}
bool Model::has_linear_constraint(const LinearConstraintId id) const {
return storage()->has_linear_constraint(id);
}
LinearConstraint Model::linear_constraint(const int64_t id) const {
return linear_constraint(LinearConstraintId(id));
}
LinearConstraint Model::linear_constraint(const LinearConstraintId id) const {
CHECK(has_linear_constraint(id))
<< "No linear constraint with id: " << id.value();
return LinearConstraint(storage(), id);
}
const std::string& Model::name(const LinearConstraint constraint) const {
CheckModel(constraint.storage());
return storage()->linear_constraint_name(constraint.typed_id());
}
void Model::set_lower_bound(const LinearConstraint constraint,
double lower_bound) {
CheckModel(constraint.storage());
storage()->set_linear_constraint_lower_bound(constraint.typed_id(),
lower_bound);
}
double Model::lower_bound(const LinearConstraint constraint) const {
CheckModel(constraint.storage());
return storage()->linear_constraint_lower_bound(constraint.typed_id());
}
void Model::set_upper_bound(const LinearConstraint constraint,
const double upper_bound) {
CheckModel(constraint.storage());
storage()->set_linear_constraint_upper_bound(constraint.typed_id(),
upper_bound);
}
double Model::upper_bound(const LinearConstraint constraint) const {
CheckModel(constraint.storage());
return storage()->linear_constraint_upper_bound(constraint.typed_id());
}
void Model::set_coefficient(const LinearConstraint constraint,
const Variable variable, const double value) {
CheckModel(constraint.storage());
CheckModel(variable.storage());
storage()->set_linear_constraint_coefficient(constraint.typed_id(),
variable.typed_id(), value);
}
double Model::coefficient(const LinearConstraint constraint,
const Variable variable) const {
CheckModel(constraint.storage());
CheckModel(variable.storage());
return storage()->linear_constraint_coefficient(constraint.typed_id(),
variable.typed_id());
}
bool Model::is_coefficient_nonzero(const LinearConstraint constraint,
const Variable variable) const {
CheckModel(constraint.storage());
CheckModel(variable.storage());
return storage()->is_linear_constraint_coefficient_nonzero(
constraint.typed_id(), variable.typed_id());
}
void Model::Maximize(const double objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/true);
}
void Model::Maximize(const Variable objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/true);
}
void Model::Maximize(const LinearTerm objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/true);
}
void Model::Maximize(const LinearExpression& objective) {
SetObjective(objective, /*is_maximize=*/true);
}
void Model::Maximize(const QuadraticExpression& objective) {
SetObjective(objective, /*is_maximize=*/true);
}
void Model::Minimize(const double objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/false);
}
void Model::Minimize(const Variable objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/false);
}
void Model::Minimize(const LinearTerm objective) {
SetObjective(LinearExpression(objective), /*is_maximize=*/false);
}
void Model::Minimize(const LinearExpression& objective) {
SetObjective(objective, /*is_maximize=*/false);
}
void Model::Minimize(const QuadraticExpression& objective) {
SetObjective(objective, /*is_maximize=*/false);
}
void Model::SetObjective(const double objective, const bool is_maximize) {
SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
}
void Model::SetObjective(const Variable objective, const bool is_maximize) {
SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
}
void Model::SetObjective(const LinearTerm objective, const bool is_maximize) {
SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
}
void Model::AddToObjective(const double objective) {
AddToObjective(LinearExpression(objective));
}
void Model::AddToObjective(const Variable objective) {
AddToObjective(LinearExpression(objective));
}
void Model::AddToObjective(const LinearTerm objective) {
AddToObjective(LinearExpression(objective));
}
double Model::objective_coefficient(const Variable variable) const {
CheckModel(variable.storage());
return storage()->linear_objective_coefficient(variable.typed_id());
}
double Model::objective_coefficient(const Variable first_variable,
const Variable second_variable) const {
CheckModel(first_variable.storage());
CheckModel(second_variable.storage());
return storage()->quadratic_objective_coefficient(first_variable.typed_id(),
second_variable.typed_id());
}
void Model::set_objective_coefficient(const Variable variable,
const double value) {
CheckModel(variable.storage());
storage()->set_linear_objective_coefficient(variable.typed_id(), value);
}
void Model::set_objective_coefficient(const Variable first_variable,
const Variable second_variable,
const double value) {
CheckModel(first_variable.storage());
CheckModel(second_variable.storage());
storage()->set_quadratic_objective_coefficient(
first_variable.typed_id(), second_variable.typed_id(), value);
}
void Model::clear_objective() { storage()->clear_objective(); }
bool Model::is_objective_coefficient_nonzero(const Variable variable) const {
CheckModel(variable.storage());
return storage()->is_linear_objective_coefficient_nonzero(
variable.typed_id());
}
bool Model::is_objective_coefficient_nonzero(
const Variable first_variable, const Variable second_variable) const {
CheckModel(first_variable.storage());
CheckModel(second_variable.storage());
return storage()->is_quadratic_objective_coefficient_nonzero(
first_variable.typed_id(), second_variable.typed_id());
}
double Model::objective_offset() const { return storage()->objective_offset(); }
void Model::set_objective_offset(const double value) {
storage()->set_objective_offset(value);
}
bool Model::is_maximize() const { return storage()->is_maximize(); }
void Model::set_maximize() { storage()->set_maximize(); }
void Model::set_minimize() { storage()->set_minimize(); }
void Model::set_is_maximize(const bool is_maximize) {
storage()->set_is_maximize(is_maximize);
}
void Model::CheckOptionalModel(const ModelStorage* const other_storage) const {
if (other_storage != nullptr) {
CHECK_EQ(other_storage, storage())
<< internal::kObjectsFromOtherModelStorage;
}
}
void Model::CheckModel(const ModelStorage* const other_storage) const {
CHECK_EQ(other_storage, storage()) << internal::kObjectsFromOtherModelStorage;
}
} // namespace math_opt
} // namespace operations_research
#endif // OR_TOOLS_MATH_OPT_CPP_MODEL_H_