25#include "absl/base/nullability.h"
26#include "absl/log/check.h"
27#include "absl/log/die_if_null.h"
28#include "absl/status/status.h"
29#include "absl/status/statusor.h"
30#include "absl/strings/string_view.h"
31#include "absl/types/span.h"
54constexpr double kInf = std::numeric_limits<double>::infinity();
59 ModelStorage::FromModelProto(model_proto));
60 return std::make_unique<Model>(std::move(
storage));
64 : storage_(
std::make_shared<ModelStorage>(
name)) {}
67 : storage_(ABSL_DIE_IF_NULL(
std::move(
storage))) {}
70 const std::optional<absl::string_view> new_name)
const {
71 return std::make_unique<Model>(storage_->Clone(new_name));
82 storage()->set_linear_constraint_coefficient(constraint,
89 std::vector<Variable> result;
98 std::vector<Variable> result =
Variables();
99 std::sort(result.begin(), result.end(),
101 return l.typed_id() < r.typed_id();
109 std::vector<LinearConstraint> result;
119 CheckModel(constraint.
storage());
120 std::vector<Variable> result;
129 std::vector<LinearConstraint> result;
139 std::sort(result.begin(), result.end(),
141 return l.typed_id() < r.typed_id();
148 CheckOptionalModel(objective.
storage());
152 for (
const auto& [var, coef] : objective.
terms()) {
154 var.typed_id(), coef);
160 CheckOptionalModel(objective.
storage());
164 for (
const auto& [var, coef] : objective.
linear_terms()) {
166 var.typed_id(), coef);
169 storage()->set_quadratic_objective_coefficient(
176 CheckOptionalModel(objective_terms.
storage());
177 storage()->set_objective_offset(
179 objective_terms.
offset() +
181 for (
const auto& [var, coef] : objective_terms.
terms()) {
182 storage()->set_linear_objective_coefficient(
190 CheckOptionalModel(objective_terms.
storage());
191 storage()->set_objective_offset(
193 objective_terms.
offset() +
195 for (
const auto& [var, coef] : objective_terms.
linear_terms()) {
196 storage()->set_linear_objective_coefficient(
202 storage()->set_quadratic_objective_coefficient(
204 coef +
storage()->quadratic_objective_coefficient(
206 vars.typed_id().second));
212 <<
"The objective function contains quadratic terms and cannot be "
213 "represented as a LinearExpression";
215 for (
const auto& [v, coef] :
224 for (
const auto& [v, coef] :
228 for (
const auto& [v1, v2, coef] :
237 std::vector<Objective> result;
247 std::sort(result.begin(), result.end(),
249 return l.typed_id() < r.typed_id();
257 CheckModel(objective.
storage());
258 CheckOptionalModel(expression.
storage());
262 for (
const auto [var, coef] : expression.
terms()) {
269 CheckModel(objective.
storage());
270 CheckOptionalModel(expression.
storage());
272 for (
const auto [var, coef] : expression.
terms()) {
280 CheckModel(objective.
storage());
281 std::vector<Variable> result;
282 result.reserve(
storage()->num_linear_objective_terms(objective.
typed_id()));
283 for (
const auto [var_id, unused] :
291 std::vector<Variable> result;
292 for (
const auto& [var_id1, var_id2, unused] :
301 return storage()->ExportModel(remove_names);
305 return std::make_unique<UpdateTracker>(storage_);
309 return storage()->ApplyUpdateProto(update_proto);
314 if (!model.
name().empty()) ostr <<
" " << model.
name();
318 ostr <<
" Objective:\n"
319 << (model.
is_maximize() ?
" maximize " :
" minimize ")
322 ostr <<
" Objectives:\n";
323 const auto stream_objective = [](std::ostream& ostr,
const Objective obj) {
324 ostr <<
" " << obj <<
" (priority " << obj.priority()
325 <<
"): " << (obj.maximize() ?
"maximize " :
"minimize ")
326 << obj.AsQuadraticExpression() <<
"\n";
330 stream_objective(ostr, obj);
334 ostr <<
" Linear constraints:\n";
336 ostr <<
" " << constraint <<
": " << constraint.AsBoundedLinearExpression()
341 ostr <<
" Quadratic constraints:\n";
344 ostr <<
" " << constraint <<
": "
345 << constraint.AsBoundedQuadraticExpression() <<
"\n";
350 ostr <<
" Second-order cone constraints:\n";
353 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
358 ostr <<
" SOS1 constraints:\n";
360 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
365 ostr <<
" SOS2 constraints:\n";
367 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
372 ostr <<
" Indicator constraints:\n";
375 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
379 ostr <<
" Variables:\n";
382 if (v.is_integer()) {
383 if (v.lower_bound() == 0 && v.upper_bound() == 1) {
384 ostr <<
" (binary)\n";
387 ostr <<
" (integer)";
390 if (v.lower_bound() == -
kInf) {
396 if (v.upper_bound() ==
kInf) {
410 const absl::string_view
name) {
414 linear_terms.
set(var.typed_id(), coeff);
417 for (
const auto& [var_ids, coeff] :
419 quadratic_terms.
set(var_ids.typed_id().first, var_ids.typed_id().second,
426 .linear_terms = std::move(linear_terms),
427 .quadratic_terms = std::move(quadratic_terms),
428 .name = std::string(
name),
436 absl::Span<const LinearExpression> arguments_to_norm,
439 std::vector<LinearExpressionData> arguments_to_norm_data;
440 arguments_to_norm_data.reserve(arguments_to_norm.size());
442 CheckOptionalModel(expr.storage());
445 const SecondOrderConeConstraintId
id =
448 .arguments_to_norm = std::move(arguments_to_norm_data),
449 .name = std::string(
name),
458template <
typename SosData>
459SosData MakeSosData(
const std::vector<LinearExpression>& expressions,
460 std::vector<double> weights,
const absl::string_view name) {
461 std::vector<LinearExpressionData> storage_expressions;
462 storage_expressions.reserve(expressions.size());
465 storage_expr.
offset = expr.offset();
466 for (
const auto& [var, coeff] : expr.terms()) {
467 storage_expr.
coeffs.
set(var.typed_id(), coeff);
470 return SosData(std::move(storage_expressions), std::move(weights),
477 const std::vector<LinearExpression>& expressions,
478 std::vector<double> weights,
const absl::string_view
name) {
480 CheckOptionalModel(expr.storage());
482 const Sos1ConstraintId
id =
storage()->AddAtomicConstraint(
483 MakeSosData<Sos1ConstraintData>(expressions, std::move(weights),
name));
490 const std::vector<LinearExpression>& expressions,
491 std::vector<double> weights,
const absl::string_view
name) {
493 CheckOptionalModel(expr.storage());
495 const Sos2ConstraintId
id =
storage()->AddAtomicConstraint(
496 MakeSosData<Sos2ConstraintData>(expressions, std::move(weights),
name));
505 const bool activate_on_zero,
const absl::string_view
name) {
506 CheckModel(indicator_variable.
storage());
515 .linear_terms = std::move(expr),
516 .indicator = indicator_variable.
typed_id(),
517 .activate_on_zero = activate_on_zero,
518 .name = std::string(
name),
#define ASSIGN_OR_RETURN(lhs, rexpr)
const VariableMap< double > & terms() const
Returns the terms in this expression.
NullableModelStorageCPtr storage() const
ModelStorageCPtr storage() const
Sos1Constraint AddSos1Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
std::vector< IndicatorConstraint > SortedIndicatorConstraints() const
Objective auxiliary_objective(int64_t id) const
Will CHECK if has_auxiliary_objective(id) is false.
int64_t num_sos2_constraints() 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)
std::vector< Sos2Constraint > SortedSos2Constraints() const
std::vector< Sos1Constraint > SortedSos1Constraints() const
absl::string_view name() const
----------------------------— Variables --------------------------------—
int num_linear_constraints() const
std::vector< QuadraticConstraint > SortedQuadraticConstraints() const
SecondOrderConeConstraint AddSecondOrderConeConstraint(absl::Span< const LinearExpression > arguments_to_norm, const LinearExpression &upper_bound, absl::string_view name="")
------------------— Second-order cone constraints ----------------------—
std::vector< Variable > NonzeroVariablesInLinearObjective() const
std::vector< SecondOrderConeConstraint > SortedSecondOrderConeConstraints() const
std::vector< Objective > AuxiliaryObjectives() const
int64_t num_second_order_cone_constraints() 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.
int64_t num_sos1_constraints() 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.
ModelStorageCPtr storage() const
void set_objective_offset(double value)
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
std::vector< LinearConstraint > ColumnNonzeros(Variable variable) const
int64_t num_indicator_constraints() 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)
double upper_bound(Variable variable) const
Returns a variable upper bound.
std::vector< Variable > Variables() const
std::vector< Variable > NonzeroVariablesInQuadraticObjective() const
absl::Nonnull< std::unique_ptr< Model > > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
std::vector< Variable > SortedVariables() const
Model(absl::string_view name="")
Creates an empty minimization problem.
Objective primary_objective() const
LinearExpression ObjectiveAsLinearExpression() const
int64_t num_quadratic_constraints() 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 ------------------------—
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
double offset() const
Returns the constant offset of the objective.
const QuadraticTermMap< double > & quadratic_terms() 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)
An object oriented wrapper for quadratic constraints in ModelStorage.
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
ElementId< ElementType::kVariable > VariableId
constexpr ObjectiveId kPrimaryObjectiveId
ElementId< ElementType::kQuadraticConstraint > QuadraticConstraintId
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
ElementId< ElementType::kLinearConstraint > LinearConstraintId
LinearExpressionData FromLinearExpression(const LinearExpression &expression)
Converts a LinearExpression to the associated "raw ID" format.
ElementId< ElementType::kIndicatorConstraint > IndicatorConstraintId
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