25#include "absl/log/check.h"
26#include "absl/status/status.h"
27#include "absl/status/statusor.h"
28#include "absl/strings/string_view.h"
29#include "absl/types/span.h"
51constexpr double kInf = std::numeric_limits<double>::infinity();
54 const ModelProto& model_proto) {
56 ModelStorage::FromModelProto(model_proto));
57 return std::make_unique<Model>(std::move(
storage));
61 : storage_(
std::make_shared<ModelStorage>(
name)) {}
64 : storage_(
std::move(storage)) {}
67 const std::optional<absl::string_view> new_name)
const {
68 return std::make_unique<Model>(storage_->Clone(new_name));
75 const LinearConstraintId constraint =
storage()->AddLinearConstraint(
79 storage()->set_linear_constraint_coefficient(constraint,
86 std::vector<Variable> result;
88 for (
const VariableId var_id :
storage()->variables()) {
95 std::vector<Variable> result =
Variables();
96 std::sort(result.begin(), result.end(),
98 return l.typed_id() < r.typed_id();
106 std::vector<LinearConstraint> result;
107 for (
const LinearConstraintId constraint :
116 CheckModel(constraint.
storage());
117 std::vector<Variable> result;
126 std::vector<LinearConstraint> result;
136 std::sort(result.begin(), result.end(),
138 return l.typed_id() < r.typed_id();
144 const bool is_maximize) {
145 CheckOptionalModel(objective.
storage());
156 const bool is_maximize) {
157 CheckOptionalModel(objective.
storage());
166 storage()->set_quadratic_objective_coefficient(
173 CheckOptionalModel(objective_terms.
storage());
174 storage()->set_objective_offset(
176 objective_terms.
offset() +
178 for (
const auto& [
var,
coef] : objective_terms.
terms()) {
179 storage()->set_linear_objective_coefficient(
187 CheckOptionalModel(objective_terms.
storage());
188 storage()->set_objective_offset(
190 objective_terms.
offset() +
193 storage()->set_linear_objective_coefficient(
199 storage()->set_quadratic_objective_coefficient(
203 vars.typed_id().second));
209 <<
"The objective function contains quadratic terms and cannot be "
210 "represented as a LinearExpression";
212 for (
const auto& [v,
coef] :
221 for (
const auto& [v,
coef] :
225 for (
const auto& [v1, v2,
coef] :
234 std::vector<Objective> result;
244 std::sort(result.begin(), result.end(),
246 return l.typed_id() < r.typed_id();
253 const bool is_maximize) {
254 CheckModel(objective.
storage());
255 CheckOptionalModel(expression.
storage());
266 CheckModel(objective.
storage());
267 CheckOptionalModel(expression.
storage());
276 return storage()->ExportModel(remove_names);
280 return std::make_unique<UpdateTracker>(storage_);
284 return storage()->ApplyUpdateProto(update_proto);
289 if (!
model.name().empty()) ostr <<
" " <<
model.name();
292 if (
model.num_auxiliary_objectives() == 0) {
293 ostr <<
" Objective:\n"
294 << (
model.is_maximize() ?
" maximize " :
" minimize ")
295 <<
model.ObjectiveAsQuadraticExpression() <<
"\n";
297 ostr <<
" Objectives:\n";
298 const auto stream_objective = [](std::ostream& ostr,
const Objective obj) {
299 ostr <<
" " << obj <<
" (priority " << obj.priority()
300 <<
"): " << (obj.maximize() ?
"maximize " :
"minimize ")
301 << obj.AsQuadraticExpression() <<
"\n";
303 stream_objective(ostr,
model.primary_objective());
305 stream_objective(ostr, obj);
309 ostr <<
" Linear constraints:\n";
311 ostr <<
" " << constraint <<
": " << constraint.AsBoundedLinearExpression()
315 if (
model.num_quadratic_constraints() > 0) {
316 ostr <<
" Quadratic constraints:\n";
318 model.SortedQuadraticConstraints()) {
319 ostr <<
" " << constraint <<
": "
320 << constraint.AsBoundedQuadraticExpression() <<
"\n";
324 if (
model.num_second_order_cone_constraints() > 0) {
325 ostr <<
" Second-order cone constraints:\n";
327 model.SortedSecondOrderConeConstraints()) {
328 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
332 if (
model.num_sos1_constraints() > 0) {
333 ostr <<
" SOS1 constraints:\n";
335 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
339 if (
model.num_sos2_constraints() > 0) {
340 ostr <<
" SOS2 constraints:\n";
342 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
346 if (
model.num_indicator_constraints() > 0) {
347 ostr <<
" Indicator constraints:\n";
349 model.SortedIndicatorConstraints()) {
350 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
354 ostr <<
" Variables:\n";
357 if (v.is_integer()) {
358 if (v.lower_bound() == 0 && v.upper_bound() == 1) {
359 ostr <<
" (binary)\n";
362 ostr <<
" (integer)";
365 if (v.lower_bound() == -
kInf) {
371 if (v.upper_bound() ==
kInf) {
385 const absl::string_view
name) {
389 linear_terms.
set(
var.typed_id(), coeff);
392 for (
const auto& [var_ids, coeff] :
394 quadratic_terms.
set(var_ids.typed_id().first, var_ids.typed_id().second,
397 const QuadraticConstraintId
id =
401 .linear_terms = std::move(linear_terms),
402 .quadratic_terms = std::move(quadratic_terms),
403 .name = std::string(
name),
411 absl::Span<const LinearExpression> arguments_to_norm,
414 std::vector<LinearExpressionData> arguments_to_norm_data;
415 arguments_to_norm_data.reserve(arguments_to_norm.size());
417 CheckOptionalModel(expr.storage());
420 const SecondOrderConeConstraintId
id =
423 .arguments_to_norm = std::move(arguments_to_norm_data),
424 .name = std::string(
name),
433template <
typename SosData>
434SosData MakeSosData(
const std::vector<LinearExpression>& expressions,
435 std::vector<double> weights,
const absl::string_view
name) {
436 std::vector<LinearExpressionData> storage_expressions;
437 storage_expressions.reserve(expressions.size());
440 storage_expr.
offset = expr.offset();
441 for (
const auto& [
var, coeff] : expr.terms()) {
445 return SosData(std::move(storage_expressions), std::move(weights),
452 const std::vector<LinearExpression>& expressions,
453 std::vector<double> weights,
const absl::string_view
name) {
455 CheckOptionalModel(expr.storage());
457 const Sos1ConstraintId
id =
storage()->AddAtomicConstraint(
458 MakeSosData<Sos1ConstraintData>(expressions, std::move(weights),
name));
465 const std::vector<LinearExpression>& expressions,
466 std::vector<double> weights,
const absl::string_view
name) {
468 CheckOptionalModel(expr.storage());
470 const Sos2ConstraintId
id =
storage()->AddAtomicConstraint(
471 MakeSosData<Sos2ConstraintData>(expressions, std::move(weights),
name));
480 const bool activate_on_zero,
const absl::string_view
name) {
481 CheckModel(indicator_variable.
storage());
486 const IndicatorConstraintId
id =
490 .linear_terms = std::move(expr),
491 .indicator = indicator_variable.
typed_id(),
492 .activate_on_zero = activate_on_zero,
493 .name = std::string(
name),
#define ASSIGN_OR_RETURN(lhs, rexpr)
const ModelStorage * storage() const
LinearConstraintId typed_id() const
const ModelStorage * storage() const
const VariableMap< double > & terms() const
Returns the terms in this expression.
Sos1Constraint AddSos1Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
Objective auxiliary_objective(int64_t id) const
Will CHECK if has_auxiliary_objective(id) is false.
const ModelStorage * storage() const
QuadraticConstraint AddQuadraticConstraint(const BoundedQuadraticExpression &bounded_expr, absl::string_view name="")
----------------------— Quadratic constraints --------------------------—
Sos2Constraint AddSos2Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
------------------------— SOS2 constraints -----------------------------—
ModelProto ExportModel(bool remove_names=false) const
static absl::StatusOr< std::unique_ptr< Model > > FromModelProto(const ModelProto &model_proto)
int num_linear_constraints() const
SecondOrderConeConstraint AddSecondOrderConeConstraint(absl::Span< const LinearExpression > arguments_to_norm, const LinearExpression &upper_bound, absl::string_view name="")
------------------— Second-order cone constraints ----------------------—
std::vector< Objective > AuxiliaryObjectives() const
std::unique_ptr< UpdateTracker > NewUpdateTracker()
std::vector< LinearConstraint > SortedLinearConstraints() const
int num_variables() const
void set_is_maximize(bool is_maximize)
Prefer set_maximize() and set_minimize() above for more readable code.
std::unique_ptr< Model > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
Variable variable(int64_t id) const
Will CHECK if has_variable(id) is false.
QuadraticExpression ObjectiveAsQuadraticExpression() const
void AddToObjective(double objective)
Adds the provided expression terms to the objective.
void set_objective_offset(double value)
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
std::vector< LinearConstraint > ColumnNonzeros(Variable variable) const
std::vector< LinearConstraint > LinearConstraints() const
std::vector< Objective > SortedAuxiliaryObjectives() const
int64_t num_auxiliary_objectives() const
void set_objective_coefficient(Variable variable, double value)
std::vector< Variable > Variables() const
std::vector< Variable > SortedVariables() const
Model(absl::string_view name="")
Creates an empty minimization problem.
LinearExpression ObjectiveAsLinearExpression() const
double objective_offset() const
void SetObjective(double objective, bool is_maximize)
Sets the objective to optimize the provided expression.
IndicatorConstraint AddIndicatorConstraint(Variable indicator_variable, const BoundedLinearExpression &implied_constraint, bool activate_on_zero=false, absl::string_view name={})
------------------------— Indicator constraints ------------------------—
const std::string & name() const
----------------------------— Variables --------------------------------—
LinearConstraint AddLinearConstraint(absl::string_view name="")
Adds a linear constraint to the model with bounds [-inf, +inf].
std::vector< Variable > RowNonzeros(LinearConstraint constraint) const
double coefficient(Variable variable) const
Returns the linear coefficient for the variable in the model.
ObjectiveId typed_id() const
const ModelStorage * storage() const
Returns a const-pointer to the underlying storage object for the model.
double offset() const
Returns the constant offset of the objective.
const QuadraticTermMap< double > & quadratic_terms() const
const ModelStorage * storage() const
const VariableMap< double > & linear_terms() const
bool set(VariableId id, double coeff)
Returns true if the stored value changes.
bool set(VariableId first, VariableId second, double value)
VariableId typed_id() const
const ModelStorage * storage() const
const std::string name
A name for logging purposes.
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
constexpr ObjectiveId kPrimaryObjectiveId
LinearExpressionData FromLinearExpression(const LinearExpression &expression)
Converts a LinearExpression to the associated "raw ID" format.
In SWIG mode, we don't want anything besides these top-level includes.
A LinearExpression with upper and lower bounds.
double upper_bound_minus_offset() const
LinearExpression expression
double lower_bound_minus_offset() const
A QuadraticExpression with upper and lower bounds.
double upper_bound_minus_offset() const
QuadraticExpression expression
double lower_bound_minus_offset() const
SparseCoefficientMap coeffs