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"
52constexpr double kInf = std::numeric_limits<double>::infinity();
55 const ModelProto& model_proto) {
57 ModelStorage::FromModelProto(model_proto));
58 return std::make_unique<Model>(std::move(
storage));
62 : storage_(
std::make_shared<ModelStorage>(
name)) {}
68 const std::optional<absl::string_view> new_name)
const {
69 return std::make_unique<Model>(storage_->Clone(new_name));
76 const LinearConstraintId constraint =
storage()->AddLinearConstraint(
80 storage()->set_linear_constraint_coefficient(constraint,
87 std::vector<Variable> result;
89 for (
const VariableId var_id :
storage()->variables()) {
96 std::vector<Variable> result =
Variables();
97 std::sort(result.begin(), result.end(),
99 return l.typed_id() < r.typed_id();
107 std::vector<LinearConstraint> result;
108 for (
const LinearConstraintId constraint :
117 CheckModel(constraint.
storage());
118 std::vector<Variable> result;
127 std::vector<LinearConstraint> result;
137 std::sort(result.begin(), result.end(),
139 return l.typed_id() < r.typed_id();
146 CheckOptionalModel(objective.
storage());
150 for (
const auto& [var, coef] : objective.
terms()) {
152 var.typed_id(), coef);
158 CheckOptionalModel(objective.
storage());
162 for (
const auto& [var, coef] : objective.
linear_terms()) {
164 var.typed_id(), coef);
167 storage()->set_quadratic_objective_coefficient(
174 CheckOptionalModel(objective_terms.
storage());
175 storage()->set_objective_offset(
177 objective_terms.
offset() +
179 for (
const auto& [var, coef] : objective_terms.
terms()) {
180 storage()->set_linear_objective_coefficient(
188 CheckOptionalModel(objective_terms.
storage());
189 storage()->set_objective_offset(
191 objective_terms.
offset() +
193 for (
const auto& [var, coef] : objective_terms.
linear_terms()) {
194 storage()->set_linear_objective_coefficient(
200 storage()->set_quadratic_objective_coefficient(
202 coef +
storage()->quadratic_objective_coefficient(
204 vars.typed_id().second));
210 <<
"The objective function contains quadratic terms and cannot be "
211 "represented as a LinearExpression";
213 for (
const auto& [v, coef] :
222 for (
const auto& [v, coef] :
226 for (
const auto& [v1, v2, coef] :
235 std::vector<Objective> result;
245 std::sort(result.begin(), result.end(),
247 return l.typed_id() < r.typed_id();
255 CheckModel(objective.
storage());
256 CheckOptionalModel(expression.
storage());
260 for (
const auto [var, coef] : expression.
terms()) {
267 CheckModel(objective.
storage());
268 CheckOptionalModel(expression.
storage());
270 for (
const auto [var, coef] : expression.
terms()) {
278 CheckModel(objective.
storage());
279 std::vector<Variable> result;
280 result.reserve(
storage()->num_linear_objective_terms(objective.
typed_id()));
281 for (
const auto [var_id, unused] :
289 std::vector<Variable> result;
290 for (
const auto& [var_id1, var_id2, unused] :
299 return storage()->ExportModel(remove_names);
303 return std::make_unique<UpdateTracker>(storage_);
307 return storage()->ApplyUpdateProto(update_proto);
312 if (!model.
name().empty()) ostr <<
" " << model.
name();
316 ostr <<
" Objective:\n"
317 << (model.
is_maximize() ?
" maximize " :
" minimize ")
320 ostr <<
" Objectives:\n";
321 const auto stream_objective = [](std::ostream& ostr,
const Objective obj) {
322 ostr <<
" " << obj <<
" (priority " << obj.priority()
323 <<
"): " << (obj.maximize() ?
"maximize " :
"minimize ")
324 << obj.AsQuadraticExpression() <<
"\n";
328 stream_objective(ostr, obj);
332 ostr <<
" Linear constraints:\n";
334 ostr <<
" " << constraint <<
": " << constraint.AsBoundedLinearExpression()
339 ostr <<
" Quadratic constraints:\n";
342 ostr <<
" " << constraint <<
": "
343 << constraint.AsBoundedQuadraticExpression() <<
"\n";
348 ostr <<
" Second-order cone constraints:\n";
351 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
356 ostr <<
" SOS1 constraints:\n";
358 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
363 ostr <<
" SOS2 constraints:\n";
365 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
370 ostr <<
" Indicator constraints:\n";
373 ostr <<
" " << constraint <<
": " << constraint.ToString() <<
"\n";
377 ostr <<
" Variables:\n";
380 if (v.is_integer()) {
381 if (v.lower_bound() == 0 && v.upper_bound() == 1) {
382 ostr <<
" (binary)\n";
385 ostr <<
" (integer)";
388 if (v.lower_bound() == -
kInf) {
394 if (v.upper_bound() ==
kInf) {
408 const absl::string_view
name) {
412 linear_terms.
set(var.typed_id(), coeff);
415 for (
const auto& [var_ids, coeff] :
417 quadratic_terms.
set(var_ids.typed_id().first, var_ids.typed_id().second,
420 const QuadraticConstraintId
id =
424 .linear_terms = std::move(linear_terms),
425 .quadratic_terms = std::move(quadratic_terms),
426 .name = std::string(
name),
434 absl::Span<const LinearExpression> arguments_to_norm,
437 std::vector<LinearExpressionData> arguments_to_norm_data;
438 arguments_to_norm_data.reserve(arguments_to_norm.size());
440 CheckOptionalModel(expr.storage());
443 const SecondOrderConeConstraintId
id =
446 .arguments_to_norm = std::move(arguments_to_norm_data),
447 .name = std::string(
name),
456template <
typename SosData>
457SosData MakeSosData(
const std::vector<LinearExpression>& expressions,
458 std::vector<double> weights,
const absl::string_view name) {
459 std::vector<LinearExpressionData> storage_expressions;
460 storage_expressions.reserve(expressions.size());
463 storage_expr.
offset = expr.offset();
464 for (
const auto& [var, coeff] : expr.terms()) {
465 storage_expr.
coeffs.
set(var.typed_id(), coeff);
468 return SosData(std::move(storage_expressions), std::move(weights),
475 const std::vector<LinearExpression>& expressions,
476 std::vector<double> weights,
const absl::string_view
name) {
478 CheckOptionalModel(expr.storage());
480 const Sos1ConstraintId
id =
storage()->AddAtomicConstraint(
481 MakeSosData<Sos1ConstraintData>(expressions, std::move(weights),
name));
488 const std::vector<LinearExpression>& expressions,
489 std::vector<double> weights,
const absl::string_view
name) {
491 CheckOptionalModel(expr.storage());
493 const Sos2ConstraintId
id =
storage()->AddAtomicConstraint(
494 MakeSosData<Sos2ConstraintData>(expressions, std::move(weights),
name));
503 const bool activate_on_zero,
const absl::string_view
name) {
504 CheckModel(indicator_variable.
storage());
509 const IndicatorConstraintId
id =
513 .linear_terms = std::move(expr),
514 .indicator = indicator_variable.
typed_id(),
515 .activate_on_zero = activate_on_zero,
516 .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="")
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
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)
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.
std::unique_ptr< Model > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
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.
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
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
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
An object oriented wrapper for quadratic constraints in ModelStorage.
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