Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// IWYU pragma: private, include "ortools/math_opt/cpp/math_opt.h"
15// IWYU pragma: friend "ortools/math_opt/cpp/.*"
16
17#ifndef OR_TOOLS_MATH_OPT_CPP_MODEL_H_
18#define OR_TOOLS_MATH_OPT_CPP_MODEL_H_
19
20#include <cstdint>
21#include <memory>
22#include <optional>
23#include <ostream>
24#include <vector>
25
26#include "absl/base/nullability.h"
27#include "absl/log/check.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"
37#include "ortools/math_opt/constraints/sos/sos1_constraint.h" // IWYU pragma: export
38#include "ortools/math_opt/constraints/sos/sos2_constraint.h" // IWYU pragma: export
41#include "ortools/math_opt/cpp/linear_constraint.h" // IWYU pragma: export
42#include "ortools/math_opt/cpp/objective.h" // IWYU pragma: export
43#include "ortools/math_opt/cpp/update_tracker.h" // IWYU pragma: export
44#include "ortools/math_opt/cpp/variable_and_expressions.h" // IWYU pragma: export
45#include "ortools/math_opt/model.pb.h" // IWYU pragma: export
46#include "ortools/math_opt/model_update.pb.h" // IWYU pragma: export
47#include "ortools/math_opt/storage/model_storage.h" // IWYU pragma: export
48#include "ortools/math_opt/storage/model_storage_types.h" // IWYU pragma: export
49
50namespace operations_research {
51namespace math_opt {
52
53// A C++ API for building optimization problems.
54//
55// Warning: Variable and LinearConstraint (along with all other constraint
56// objects) are value types, see "Memory Model" below.
57//
58// A simple example:
59//
60// Model the problem:
61// max 2.0 * x + y
62// s.t. x + y <= 1.5
63// x in {0.0, 1.0}
64// y in [0.0, 2.5]
65//
66// math_opt::Model model("my_model");
67// const math_opt::Variable x = model.AddBinaryVariable("x");
68// const math_opt::Variable y = model.AddContinuousVariable(0.0, 2.5, "y");
69// // We can directly use linear combinations of variables ...
70// model.AddLinearConstraint(x + y <= 1.5, "c");
71// // ... or build them incrementally.
72// math_opt::LinearExpression objective_expression;
73// objective_expression += 2 * x;
74// objective_expression += y;
75// model.Maximize(objective_expression);
76// ASSIGN_OR_RETURN(const math_opt::SolveResult result,
77// Solve(model, math_opt::SolverType::kGscip));
78// switch (result.termination.reason) {
79// case math_opt::TerminationReason::kOptimal:
80// case math_opt::TerminationReason::kFeasible:
81// std::cout << "objective value: " << result.objective_value() << std::endl
82// << "value for variable x: " << result.variable_values().at(x)
83// << std::endl;
84// return absl::OkStatus();
85// default:
86// return util::InternalErrorBuilder()
87// << "model failed to solve: " << result.termination;
88// }
89//
90// Memory model:
91//
92// Variable, LinearConstraint, QuadraticConstraint, etc. are value types that
93// represent references to the underlying Model object. They don't hold any of
94// the actual model data, they can be copied, and they should be passed by
95// value. They can be regenerated arbitrarily from Model. Model holds all the
96// data.
97//
98// As a consequence of Variable and LinearConstraint holding back pointers,
99// Model is not copyable or movable. Users needing to copy a Model can call
100// Model::Clone() (this will create a new Model with no update trackers), and
101// users needing to move a Model should wrap it in a std::unique_ptr.
102//
103// Performance:
104//
105// This class is a thin wrapper around ModelStorage (for incrementally building
106// the model and reading it back, and producing the Model proto). Operations for
107// building/reading/modifying the problem typically run in O(read/write size)
108// and rely on hashing, see the ModelStorage documentation for details. At
109// solve time (if you are solving locally) beware that there will be (at least)
110// three copies of the model in memory, ModelStorage, the Model proto, and the
111// underlying solver's copy(/ies). Note that the Model proto is reclaimed before
112// the underlying solver begins solving.
113class Model {
114 public:
115 // Returns a model from the input proto. Returns a failure status if the input
116 // proto is invalid.
117 //
118 // On top of loading a model from a MathOpt ModelProto, this function can also
119 // be used to load a model from other formats using the functions in
120 // math_opt/io/ like ReadMpsFile().
121 //
122 // See ExportModel() to get the proto of a Model. See ApplyUpdateProto() to
123 // apply an update to the model.
124 //
125 // Usage example reading an MPS file:
126 // ASSIGN_OR_RETURN(const ModelProto model_proto, ReadMpsFile(path));
127 // ASSIGN_OR_RETURN(const std::unique_ptr<Model> model,
128 // Model::FromModelProto(model_proto));
129 static absl::StatusOr<std::unique_ptr<Model>> FromModelProto(
130 const ModelProto& model_proto);
131
132 // Creates an empty minimization problem.
133 explicit Model(absl::string_view name = "");
134
135 // Creates a model from the existing model storage.
136 //
137 // This constructor is used when loading a model, for example from a
138 // ModelProto or an MPS file. Note that in those cases the FromModelProto()
139 // should be used.
140 explicit Model(absl::Nonnull<std::unique_ptr<ModelStorage>> storage);
141
142 Model(const Model&) = delete;
143 Model& operator=(const Model&) = delete;
144
145 // Returns a clone of this model, optionally changing the model's name.
146 //
147 // The variables and constraints have the same integer ids. The clone will
148 // also not reused any id of variable/constraint that was deleted in the
149 // original.
150 //
151 // That said, the Variable and LinearConstraint reference objects are model
152 // specific. Hence the ones linked to the original model must NOT be used with
153 // the clone. The Variable and LinearConstraint reference objects for the
154 // clone can be obtained using:
155 // * the variable() and linear_constraint() methods on the ids from the old
156 // Variable and LinearConstraint objects.
157 // * in increasing id order using SortedVariables() and
158 // SortedLinearConstraints()
159 // * in an arbitrary order using Variables() and LinearConstraints().
160 //
161 // Note that the returned model does not have any update tracker.
162 absl::Nonnull<std::unique_ptr<Model>> Clone(
163 std::optional<absl::string_view> new_name = std::nullopt) const;
164
165 inline absl::string_view name() const;
166
168 // Variable methods
170
171 // Adds a variable to the model and returns a reference to it.
172 inline Variable AddVariable(double lower_bound, double upper_bound,
173 bool is_integer, absl::string_view name = "");
174
175 // Adds a continuous unbounded variable to the model.
176 inline Variable AddVariable(absl::string_view name = "");
177
178 // Adds a variable to the model with domain {0, 1}.
179 inline Variable AddBinaryVariable(absl::string_view name = "");
180
181 // Adds a variable to the model with domain [lower_bound, upper_bound].
183 absl::string_view name = "");
184
185 // Adds a variable to the model that can take integer values between
186 // lower_bound and upper_bound (inclusive).
188 absl::string_view name = "");
189
190 // Removes a variable from the model.
191 //
192 // It is an error to use any reference to this variable after this operation.
193 // Runs in O(#constraints containing the variable).
194 inline void DeleteVariable(Variable variable);
195
196 // The number of variables in the model.
197 //
198 // Equal to the number of variables created minus the number of variables
199 // deleted.
200 inline int num_variables() const;
201
202 // The returned id of the next call to AddVariable.
203 //
204 // Equal to the number of variables created.
205 inline int64_t next_variable_id() const;
206
207 // Returns true if this id has been created and not yet deleted.
208 inline bool has_variable(int64_t id) const;
209
210 // Returns true if this id has been created and not yet deleted.
211 inline bool has_variable(VariableId id) const;
212
213 // Will CHECK if has_variable(id) is false.
214 inline Variable variable(int64_t id) const;
215
216 // Will CHECK if has_variable(id) is false.
217 inline Variable variable(VariableId id) const;
218
219 // Returns the variable name.
220 inline absl::string_view name(Variable variable) const;
221
222 // Sets a variable lower bound.
223 inline void set_lower_bound(Variable variable, double lower_bound);
224
225 // Returns a variable lower bound.
226 inline double lower_bound(Variable variable) const;
227
228 // Sets a variable upper bound.
229 inline void set_upper_bound(Variable variable, double upper_bound);
230
231 // Returns a variable upper bound.
232 inline double upper_bound(Variable variable) const;
233
234 // Sets the integrality of a variable.
235 inline void set_is_integer(Variable variable, bool is_integer);
236
237 // Makes the input variable integer.
238 inline void set_integer(Variable variable);
239
240 // Makes the input variable continuous.
241 inline void set_continuous(Variable variable);
242
243 // Returns the integrality of a variable.
244 inline bool is_integer(Variable variable) const;
245
246 // Returns all the existing (created and not deleted) variables in the model
247 // in an arbitrary order.
248 std::vector<Variable> Variables() const;
249
250 // Returns all the existing (created and not deleted) variables in the model,
251 // sorted by id.
252 std::vector<Variable> SortedVariables() const;
253
254 // Returns an error if `variable` is from another model or the id is not in
255 // this model (typically, if it was deleted).
256 inline absl::Status ValidateExistingVariableOfThisModel(
257 Variable variable) const;
258
259 std::vector<LinearConstraint> ColumnNonzeros(Variable variable) const;
260
262 // LinearConstraint methods
264
265 // Adds a linear constraint to the model with bounds [-inf, +inf].
266 inline LinearConstraint AddLinearConstraint(absl::string_view name = "");
267
268 // Adds a linear constraint with bounds [lower_bound, upper_bound].
270 double upper_bound,
271 absl::string_view name = "");
272
273 // Adds a linear constraint from the given bounded linear expression.
274 //
275 // Usage:
276 // Model model = ...;
277 // const Variable x = ...;
278 // const Variable y = ...;
279 // model.AddLinearConstraint(3 <= 2 * x + y + 1 <= 5, "c");
280 // // The new constraint formula is:
281 // // 3 - 1 <= 2 * x + y <= 5 - 1
282 // // Which is:
283 // // 2 <= 2 * x + y <= 4
284 // // since the offset has been removed from bounds.
285 //
286 // model.AddLinearConstraint(2 * x + y == x + 5 * z + 3);
287 // model.AddLinearConstraint(x >= 5);
289 const BoundedLinearExpression& bounded_expr, absl::string_view name = "");
290
291 // Removes a linear constraint from the model.
292 //
293 // It is an error to use any reference to this linear constraint after this
294 // operation. Runs in O(#variables in the linear constraint).
295 inline void DeleteLinearConstraint(LinearConstraint constraint);
296
297 // The number of linear constraints in the model.
298 //
299 // Equal to the number of linear constraints created minus the number of
300 // linear constraints deleted.
301 inline int num_linear_constraints() const;
302
303 // The returned id of the next call to AddLinearConstraint.
304 //
305 // Equal to the number of linear constraints created.
306 inline int64_t next_linear_constraint_id() const;
307
308 // Returns true if this id has been created and not yet deleted.
309 inline bool has_linear_constraint(int64_t id) const;
310
311 // Returns true if this id has been created and not yet deleted.
312 inline bool has_linear_constraint(LinearConstraintId id) const;
313
314 // Will CHECK if has_linear_constraint(id) is false.
315 inline LinearConstraint linear_constraint(int64_t id) const;
316
317 // Will CHECK if has_linear_constraint(id) is false.
319
320 // Returns the linear constraint name.
321 inline absl::string_view name(LinearConstraint constraint) const;
322
323 // Sets a linear constraint lower bound.
324 inline void set_lower_bound(LinearConstraint constraint, double lower_bound);
325
326 // Returns a linear constraint lower bound.
327 inline double lower_bound(LinearConstraint constraint) const;
328
329 // Sets a linear constraint upper bound.
330 inline void set_upper_bound(LinearConstraint constraint, double upper_bound);
331
332 // Returns a linear constraint upper bound.
333 inline double upper_bound(LinearConstraint constraint) const;
334
335 // Setting a value to 0.0 will delete the {constraint, variable} pair from the
336 // underlying sparse matrix representation (and has no effect if the pair is
337 // not present).
338 inline void set_coefficient(LinearConstraint constraint, Variable variable,
339 double value);
340
341 // Returns 0.0 if the variable is not used in the constraint.
342 inline double coefficient(LinearConstraint constraint,
343 Variable variable) const;
344
345 inline bool is_coefficient_nonzero(LinearConstraint constraint,
346 Variable variable) const;
347
348 std::vector<Variable> RowNonzeros(LinearConstraint constraint) const;
349
350 // Returns all the existing (created and not deleted) linear constraints in
351 // the model in an arbitrary order.
352 std::vector<LinearConstraint> LinearConstraints() const;
353
354 // Returns all the existing (created and not deleted) linear constraints in
355 // the model sorted by id.
356 std::vector<LinearConstraint> SortedLinearConstraints() const;
357
358 // Returns an error if `linear_constraint` is from another model or the id is
359 // not in this model (typically, if it was deleted).
362
364 // QuadraticConstraint methods
366
367 // Adds a quadratic constraint from the given bounded quadratic expression.
368 //
369 // Usage:
370 // Model model = ...;
371 // const Variable x = ...;
372 // const Variable y = ...;
373 // model.AddQuadraticConstraint(2 * x * x + y + 1 <= 5, "q");
374 // model.AddQuadraticConstraint(2 * x * x + y * y == x + 5 * z + 3);
375 // model.AddQuadraticConstraint(x * y >= 5);
377 const BoundedQuadraticExpression& bounded_expr,
378 absl::string_view name = "");
379
380 // Removes a quadratic constraint from the model.
381 //
382 // It is an error to use any reference to this quadratic constraint after this
383 // operation. Runs in O(#linear or quadratic terms appearing in constraint).
384 inline void DeleteQuadraticConstraint(QuadraticConstraint constraint);
385
386 // The number of quadratic constraints in the model.
387 //
388 // Equal to the number of quadratic constraints created minus the number of
389 // quadratic constraints deleted.
390 inline int64_t num_quadratic_constraints() const;
391
392 // The returned id of the next call to AddQuadraticConstraint.
393 inline int64_t next_quadratic_constraint_id() const;
394
395 // Returns true if this id has been created and not yet deleted.
396 inline bool has_quadratic_constraint(int64_t id) const;
397
398 // Returns true if this id has been created and not yet deleted.
400
401 // Will CHECK if has_quadratic_constraint(id) is false.
402 inline QuadraticConstraint quadratic_constraint(int64_t id) const;
403
404 // Will CHECK if has_quadratic_constraint(id) is false.
406 QuadraticConstraintId id) const;
407
408 // Returns all the existing (created and not deleted) quadratic constraints in
409 // the model in an arbitrary order.
410 inline std::vector<QuadraticConstraint> QuadraticConstraints() const;
411
412 // Returns all the existing (created and not deleted) quadratic constraints in
413 // the model sorted by id.
414 inline std::vector<QuadraticConstraint> SortedQuadraticConstraints() const;
415
417 // SecondOrderConeConstraint methods
419
420 // Adds a second-order cone constraint to the model of the form
421 // ||arguments_to_norm||₂ ≤ upper_bound.
422 //
423 // Usage:
424 // Model model = ...;
425 // const Variable x = ...;
426 // const Variable y = ...;
427 // model.AddSecondOrderConeConstraint({x, y}, 1.0, "soc");
428 // model.AddSecondOrderConeConstraint({1.0, 3 * y - x}, 2 * x);
430 absl::Span<const LinearExpression> arguments_to_norm,
431 const LinearExpression& upper_bound, absl::string_view name = "");
432
433 // Removes a second-order cone constraint from the model.
434 //
435 // It is an error to use any reference to this second-order cone constraint
436 // after this operation. Runs in O(#linear terms appearing in constraint).
438 SecondOrderConeConstraint constraint);
439
440 // The number of second-order cone constraints in the model.
441 //
442 // Equal to the number of second-order cone constraints created minus the
443 // number of second-order cone constraints deleted.
444 inline int64_t num_second_order_cone_constraints() const;
445
446 // The returned id of the next call to AddSecondOrderConeConstraint.
447 inline int64_t next_second_order_cone_constraint_id() const;
448
449 // Returns true if this id has been created and not yet deleted.
450 inline bool has_second_order_cone_constraint(int64_t id) const;
451
452 // Returns true if this id has been created and not yet deleted.
454 SecondOrderConeConstraintId id) const;
455
456 // Will CHECK if has_second_order_cone_constraint(id) is false.
458 int64_t id) const;
459
460 // Will CHECK if has_second_order_cone_constraint(id) is false.
462 SecondOrderConeConstraintId id) const;
463
464 // Returns all the existing (created and not deleted) second-order cone
465 // constraints in the model in an arbitrary order.
466 inline std::vector<SecondOrderConeConstraint> SecondOrderConeConstraints()
467 const;
468
469 // Returns all the existing (created and not deleted) second-order cone
470 // constraints in the model sorted by id.
471 inline std::vector<SecondOrderConeConstraint>
473
475 // Sos1Constraint methods
477
478 // Adds an SOS1 constraint to the model: at most one of the `expressions` may
479 // take a nonzero value.
480 //
481 // The `weights` are an implementation detail in the solver used to order the
482 // `expressions`; see the Gurobi documentation for more detail:
483 // https://www.gurobi.com/documentation/9.5/refman/constraints.html#subsubsection:SOSConstraints
484 //
485 // These `weights` must either be empty or the same length as `expressions`.
486 // If it is empty, default weights of 1, 2, ... will be used.
487 //
488 // Usage:
489 // Model model = ...;
490 // const Variable x = ...;
491 // const Variable y = ...;
492 // model.AddSos1Constraint({x, y}, {}, "c");
493 // model.AddSos1Constraint({1 - 2 * x, y}, {3, 2});
495 const std::vector<LinearExpression>& expressions,
496 std::vector<double> weights = {}, absl::string_view name = "");
497
498 // Removes an SOS1 constraint from the model.
499 //
500 // It is an error to use any reference to this SOS1 constraint after this
501 // operation. Runs in O(#terms in all expressions).
502 inline void DeleteSos1Constraint(Sos1Constraint constraint);
503
504 // The number of SOS1 constraints in the model.
505 //
506 // Equal to the number of SOS1 constraints created minus the number of SOS1
507 // constraints deleted.
508 inline int64_t num_sos1_constraints() const;
509
510 // The returned id of the next call to AddSos1Constraint.
511 inline int64_t next_sos1_constraint_id() const;
512
513 // Returns true if this id has been created and not yet deleted.
514 inline bool has_sos1_constraint(int64_t id) const;
515
516 // Returns true if this id has been created and not yet deleted.
517 inline bool has_sos1_constraint(Sos1ConstraintId id) const;
518
519 // Will CHECK if has_sos1_constraint(id) is false.
520 inline Sos1Constraint sos1_constraint(int64_t id) const;
521
522 // Will CHECK if has_sos1_constraint(id) is false.
523 inline Sos1Constraint sos1_constraint(Sos1ConstraintId id) const;
524
525 // Returns all the existing (created and not deleted) SOS1 constraints in the
526 // model in an arbitrary order.
527 inline std::vector<Sos1Constraint> Sos1Constraints() const;
528
529 // Returns all the existing (created and not deleted) SOS1 constraints in the
530 // model sorted by id.
531 inline std::vector<Sos1Constraint> SortedSos1Constraints() const;
532
534 // Sos2Constraint methods
536
537 // Adds an SOS2 constraint to the model: at most two of the `expressions` may
538 // take a nonzero value, and they must be adjacent in their ordering.
539 //
540 // The `weights` are an implementation detail in the solver used to order the
541 // `expressions`; see the Gurobi documentation for more detail:
542 // https://www.gurobi.com/documentation/9.5/refman/constraints.html#subsubsection:SOSConstraints
543 //
544 // These `weights` must either be empty or the same length as `expressions`.
545 // If it is empty, default weights of 1, 2, ... will be used.
546 //
547 // Usage:
548 // Model model = ...;
549 // const Variable x = ...;
550 // const Variable y = ...;
551 // model.AddSos2Constraint({x, y}, {}, "c");
552 // model.AddSos2Constraint({1 - 2 * x, y}, {3, 2});
554 const std::vector<LinearExpression>& expressions,
555 std::vector<double> weights = {}, absl::string_view name = "");
556
557 // Removes an SOS2 constraint from the model.
558 //
559 // It is an error to use any reference to this SOS2 constraint after this
560 // operation. Runs in O(#terms in all expressions).
561 inline void DeleteSos2Constraint(Sos2Constraint constraint);
562
563 // The number of SOS2 constraints in the model.
564 //
565 // Equal to the number of SOS2 constraints created minus the number of SOS2
566 // constraints deleted.
567 inline int64_t num_sos2_constraints() const;
568
569 // The returned id of the next call to AddSos2Constraint.
570 inline int64_t next_sos2_constraint_id() const;
571
572 // Returns true if this id has been created and not yet deleted.
573 inline bool has_sos2_constraint(int64_t id) const;
574
575 // Returns true if this id has been created and not yet deleted.
576 inline bool has_sos2_constraint(Sos2ConstraintId id) const;
577
578 // Will CHECK if has_sos2_constraint(id) is false.
579 inline Sos2Constraint sos2_constraint(int64_t id) const;
580
581 // Will CHECK if has_sos2_constraint(id) is false.
582 inline Sos2Constraint sos2_constraint(Sos2ConstraintId id) const;
583
584 // Returns all the existing (created and not deleted) SOS2 constraints in the
585 // model in an arbitrary order.
586 inline std::vector<Sos2Constraint> Sos2Constraints() const;
587
588 // Returns all the existing (created and not deleted) SOS2 constraints in the
589 // model sorted by id.
590 inline std::vector<Sos2Constraint> SortedSos2Constraints() const;
591
593 // IndicatorConstraint methods
595
596 // Adds an indicator constraint to the model.
597 //
598 // Assume for the moment that `activate_on_zero == false` (the default value).
599 // * If `indicator_variable == 1`, then `implied_constraint` must hold.
600 // * If `indicator_variable == 0`, then `implied_constraint` need not hold.
601 // Alternatively, if `activate_on_zero = true`, flip the 1 and 0 above.
602 //
603 // The `indicator_variable` is expected to be a binary variable in the model.
604 // If this is not the case, the solver may elect to either implicitly add the
605 // binary constraint, or reject the model.
606 //
607 // Usage:
608 // Model model = ...;
609 // const Variable x = model.AddBinaryVariable("x");
610 // const Variable y = model.AddBinaryVariable("y");
611 // model.AddIndicatorConstraint(x, y <= 0);
612 // model.AddIndicatorConstraint(y, x >= 2, true, "c");
613 IndicatorConstraint AddIndicatorConstraint(
614 Variable indicator_variable,
615 const BoundedLinearExpression& implied_constraint,
616 bool activate_on_zero = false, absl::string_view name = {});
617
618 // Removes an indicator constraint from the model.
619 //
620 // It is an error to use any reference to this indicator constraint after this
621 // operation. Runs in O(#terms in implied constraint).
622 inline void DeleteIndicatorConstraint(IndicatorConstraint constraint);
623
624 // The number of indicator constraints in the model.
625 //
626 // Equal to the number of indicator constraints created minus the number of
627 // indicator constraints deleted.
628 inline int64_t num_indicator_constraints() const;
629
630 // The returned id of the next call to AddIndicatorConstraint.
631 inline int64_t next_indicator_constraint_id() const;
632
633 // Returns true if this id has been created and not yet deleted.
634 inline bool has_indicator_constraint(int64_t id) const;
635
636 // Returns true if this id has been created and not yet deleted.
638
639 // Will CHECK if has_indicator_constraint(id) is false.
640 inline IndicatorConstraint indicator_constraint(int64_t id) const;
641
642 // Will CHECK if has_indicator_constraint(id) is false.
643 inline IndicatorConstraint indicator_constraint(
644 IndicatorConstraintId id) const;
645
646 // Returns all the existing (created and not deleted) indicator constraints in
647 // the model in an arbitrary order.
648 inline std::vector<IndicatorConstraint> IndicatorConstraints() const;
649
650 // Returns all the existing (created and not deleted) indicator constraints in
651 // the model sorted by id.
652 inline std::vector<IndicatorConstraint> SortedIndicatorConstraints() const;
653
655 // Objective methods
657
658 // Sets the objective to maximize the provided expression.
659 inline void Maximize(double objective);
660 // Sets the objective to maximize the provided expression.
661 inline void Maximize(Variable objective);
662 // Sets the objective to maximize the provided expression.
663 inline void Maximize(LinearTerm objective);
664 // Sets the objective to maximize the provided expression.
665 inline void Maximize(const LinearExpression& objective);
666 // Sets the objective to maximize the provided expression.
667 inline void Maximize(const QuadraticExpression& objective);
668
669 // Sets the objective to minimize the provided expression.
670 inline void Minimize(double objective);
671 // Sets the objective to minimize the provided expression.
672 inline void Minimize(Variable objective);
673 // Sets the objective to minimize the provided expression.
674 inline void Minimize(LinearTerm objective);
675 // Sets the objective to minimize the provided expression.
676 inline void Minimize(const LinearExpression& objective);
677 // Sets the objective to minimize the provided expression.
678 inline void Minimize(const QuadraticExpression& objective);
679
680 // Sets the objective to optimize the provided expression.
681 inline void SetObjective(double objective, bool is_maximize);
682 // Sets the objective to optimize the provided expression.
683 inline void SetObjective(Variable objective, bool is_maximize);
684 // Sets the objective to optimize the provided expression.
685 inline void SetObjective(LinearTerm objective, bool is_maximize);
686 // Sets the objective to optimize the provided expression.
687 void SetObjective(const LinearExpression& objective, bool is_maximize);
688 // Sets the objective to optimize the provided expression.
689 void SetObjective(const QuadraticExpression& objective, bool is_maximize);
690
691 // Adds the provided expression terms to the objective.
692 inline void AddToObjective(double objective);
693 // Adds the provided expression terms to the objective.
694 inline void AddToObjective(Variable objective);
695 // Adds the provided expression terms to the objective.
696 inline void AddToObjective(LinearTerm objective);
697 // Adds the provided expression terms to the objective.
698 void AddToObjective(const LinearExpression& objective);
699 // Adds the provided expression terms to the objective.
700 void AddToObjective(const QuadraticExpression& objective);
701
702 // NOTE: This will CHECK fail if the objective has quadratic terms.
703 LinearExpression ObjectiveAsLinearExpression() const;
704 QuadraticExpression ObjectiveAsQuadraticExpression() const;
705
706 // Returns an object referring to the primary objective in the model. Can be
707 // used with the multi-objective API in the same way that an auxiliary
708 // objective can be.
709 inline Objective primary_objective() const;
710
711 // Returns 0.0 if this variable has no linear objective coefficient.
712 inline double objective_coefficient(Variable variable) const;
713
714 // Returns 0.0 if this variable pair has no quadratic objective coefficient.
715 // The order of the variables does not matter.
716 inline double objective_coefficient(Variable first_variable,
717 Variable second_variable) const;
718
719 // Setting a value to 0.0 will delete the variable from the underlying sparse
720 // representation (and has no effect if the variable is not present).
721 inline void set_objective_coefficient(Variable variable, double value);
722
723 // Set quadratic objective terms for the product of two variables. Setting a
724 // value to 0.0 will delete the variable pair from the underlying sparse
725 // representation (and has no effect if the pair is not present). The order of
726 // the variables does not matter.
727 inline void set_objective_coefficient(Variable first_variable,
728 Variable second_variable, double value);
729
730 // Sets the objective offset, linear terms, and quadratic terms of the
731 // objective to zero. The name, direction, and priority are unchanged.
732 // Equivalent to SetObjective(0.0, is_maximize()).
733 //
734 // Runs in O(#linear and quadratic objective terms with nonzero coefficient).
735 inline void clear_objective();
736
738 inline bool is_objective_coefficient_nonzero(Variable first_variable,
739 Variable second_variable) const;
740
741 inline double objective_offset() const;
742
743 inline void set_objective_offset(double value);
744
745 inline bool is_maximize() const;
746
747 inline void set_maximize();
748 inline void set_minimize();
749
750 // Prefer set_maximize() and set_minimize() above for more readable code.
751 inline void set_is_maximize(bool is_maximize);
752
753 // Returns all variables that have a nonzero coefficient in the linear part of
754 // the primary objective. Result is not sorted.
755 inline std::vector<Variable> NonzeroVariablesInLinearObjective() const;
756 // Returns all variables that have a nonzero coefficient in the quadratic part
757 // of the primary objective. Result is not sorted.
758 std::vector<Variable> NonzeroVariablesInQuadraticObjective() const;
759
761 // Auxiliary objective methods
762 //
763 // This is an API for creating and deleting auxiliary objectives. To modify
764 // them, use the multi-objective API below.
766
767 // Adds an empty (== 0) auxiliary minimization objective to the model.
768 inline Objective AddAuxiliaryObjective(int64_t priority,
769 absl::string_view name = {});
770 // Adds `expression` as an auxiliary objective to the model.
771 inline Objective AddAuxiliaryObjective(const LinearExpression& expression,
772 bool is_maximize, int64_t priority,
773 absl::string_view name = {});
774 // Adds `expression` as an auxiliary maximization objective to the model.
775 inline Objective AddMaximizationObjective(const LinearExpression& expression,
776 int64_t priority,
777 absl::string_view name = {});
778 // Adds `expression` as an auxiliary minimization objective to the model.
779 inline Objective AddMinimizationObjective(const LinearExpression& expression,
780 int64_t priority,
781 absl::string_view name = {});
782
783 // Removes an auxiliary objective from the model.
784 //
785 // It is an error to use any reference to this auxiliary objective after this
786 // operation. Runs in O(1) time.
787 //
788 // Will CHECK-fail if `objective` is from another model, has already been
789 // deleted, or is a primary objective.
790 inline void DeleteAuxiliaryObjective(Objective objective);
791
792 // The number of auxiliary objectives in the model.
793 //
794 // Equal to the number of auxiliary objectives created minus the number of
795 // auxiliary objectives deleted.
796 inline int64_t num_auxiliary_objectives() const;
797
798 // The returned id of the next call to AddAuxiliaryObjectve.
799 inline int64_t next_auxiliary_objective_id() const;
800
801 // Returns true if this id has been created and not yet deleted.
802 inline bool has_auxiliary_objective(int64_t id) const;
803
804 // Returns true if this id has been created and not yet deleted.
805 inline bool has_auxiliary_objective(AuxiliaryObjectiveId id) const;
806
807 // Will CHECK if has_auxiliary_objective(id) is false.
808 inline Objective auxiliary_objective(int64_t id) const;
809
810 // Will CHECK if has_auxiliary_objective(id) is false.
811 inline Objective auxiliary_objective(AuxiliaryObjectiveId id) const;
812
813 // Returns all the existing (created and not deleted) auxiliary objectives in
814 // the model in an arbitrary order.
815 std::vector<Objective> AuxiliaryObjectives() const;
816
817 // Returns all the existing (created and not deleted) auxiliary objectives in
818 // the model sorted by id.
819 std::vector<Objective> SortedAuxiliaryObjectives() const;
820
822 // Multi-objective methods
823 //
824 // This is an API for setting objective properties (for either primary or
825 // auxiliary objectives). Only linear objectives are supported through this
826 // API. To query objective properties, use the methods on `Objective`.
828
829 // Sets `objective` to be maximizing `expression`.
830 inline void Maximize(Objective objective, const LinearExpression& expression);
831 // Sets `objective` to be minimizing `expression`.
832 inline void Minimize(Objective objective, const LinearExpression& expression);
833 // Sets the objective to optimize the provided expression.
834 void SetObjective(Objective objective, const LinearExpression& expression,
835 bool is_maximize);
836
837 // Adds the provided expression terms to the objective.
838 void AddToObjective(Objective objective, const LinearExpression& expression);
839
840 // Sets the priority for an objective (lower is more important). `priority`
841 // must be nonnegative.
842 inline void set_objective_priority(Objective objective, int64_t priority);
843
844 // Setting a value to 0.0 will delete the variable from the underlying sparse
845 // representation (and has no effect if the variable is not present).
846 inline void set_objective_coefficient(Objective objective, Variable variable,
847 double value);
848
849 inline void set_objective_offset(Objective objective, double value);
850
851 inline void set_maximize(Objective objective);
852 inline void set_minimize(Objective objective);
853
854 // Prefer set_maximize() and set_minimize() above for more readable code.
855 inline void set_is_maximize(Objective objective, bool is_maximize);
856
857 // Returns all variables that have a nonzero coefficient in the linear part of
858 // the `objective`. Result is not sorted.
859 std::vector<Variable> NonzeroVariablesInLinearObjective(
860 Objective objective) const;
861
862 // Returns a proto representation of the optimization model.
863 //
864 // See FromModelProto() to build a Model from a proto.
865 ModelProto ExportModel(bool remove_names = false) const;
866
867 // Returns a tracker that can be used to generate a ModelUpdateProto with the
868 // updates that happened since the last checkpoint. The tracker initial
869 // checkpoint corresponds to the current state of the model.
870 //
871 // The returned UpdateTracker keeps a reference to this model. See the
872 // implications in the documentation of the UpdateTracker class.
873 //
874 // Thread-safety: this method must not be used while modifying the model
875 // (variables, constraints, ...). The user is expected to use proper
876 // synchronization primitive to serialize changes to the model and the use of
877 // this method.
878 std::unique_ptr<UpdateTracker> NewUpdateTracker();
879
880 // Apply the provided update to this model. Returns a failure if the update is
881 // not valid.
882 //
883 // As with FromModelProto(), duplicated names are ignored.
884 //
885 // Note that it takes O(num_variables + num_constraints) extra memory and
886 // execution to apply the update (due to the need to build a ModelSummary). So
887 // even a small update will have some cost.
888 absl::Status ApplyUpdateProto(const ModelUpdateProto& update_proto);
889
890 // TODO(user): expose a way to efficiently iterate through the nonzeros of
891 // the linear constraint matrix.
892
893 // Returns a pointer to the underlying model storage.
894 //
895 // This API is for internal use only and regular users should have no need for
896 // it.
897 ModelStorageCPtr storage() const { return storage_.get(); }
898
899 // Returns a pointer to the underlying model storage.
900 //
901 // This API is for internal use only and regular users should have no need for
902 // it.
903 ModelStoragePtr storage() { return storage_.get(); }
904
905 // Prints the objective, the constraints and the variables of the model over
906 // several lines in a human-readable way. Includes a new line at the end of
907 // the model.
908 friend std::ostream& operator<<(std::ostream& ostr, const Model& model);
909
910 private:
911 // Asserts (with CHECK) that the input pointer is either nullptr or that it
912 // points to the same model as storage_.
913 //
914 // Use CheckModel() when nullptr is not a valid value.
915 inline void CheckOptionalModel(NullableModelStorageCPtr other_storage) const;
916
917 // Asserts (with CHECK) that the input pointer is the same as storage_.
918 //
919 // Use CheckOptionalModel() if nullptr is a valid value too.
920 inline void CheckModel(ModelStorageCPtr other_storage) const;
921
922 // Don't use storage_ directly; prefer to use storage() so that const member
923 // functions don't have modifying access to the underlying storage.
924 //
925 // We use a shared_ptr here so that the UpdateTracker class can have a
926 // weak_ptr on the ModelStorage. This let it have a destructor that don't
927 // crash when called after the destruction of the associated Model.
928 const absl::Nonnull<std::shared_ptr<ModelStorage>> storage_;
929};
930
932// Inline function implementations
934
935// ------------------------------- Variables -----------------------------------
936
937absl::string_view Model::name() const { return storage()->name(); }
938
939Variable Model::AddVariable(const absl::string_view name) {
940 return Variable(storage(), storage()->AddVariable(name));
941}
942Variable Model::AddVariable(const double lower_bound, const double upper_bound,
943 const bool is_integer,
944 const absl::string_view name) {
946 is_integer, name));
947}
948
949Variable Model::AddBinaryVariable(const absl::string_view name) {
950 return AddVariable(0.0, 1.0, true, name);
951}
952
953Variable Model::AddContinuousVariable(const double lower_bound,
954 const double upper_bound,
955 const absl::string_view name) {
956 return AddVariable(lower_bound, upper_bound, false, name);
957}
958
960 const double upper_bound,
961 const absl::string_view name) {
962 return AddVariable(lower_bound, upper_bound, true, name);
963}
966 CheckModel(variable.storage());
967 storage()->DeleteVariable(variable.typed_id());
968}
969
970int Model::num_variables() const { return storage()->num_variables(); }
972int64_t Model::next_variable_id() const {
973 return storage()->next_variable_id().value();
974}
976bool Model::has_variable(const int64_t id) const {
977 return id < 0 ? false : has_variable(VariableId(id));
978}
979
980bool Model::has_variable(const VariableId id) const {
981 return storage()->has_variable(id);
982}
983
984Variable Model::variable(const int64_t id) const {
985 return variable(VariableId(id));
986}
988Variable Model::variable(const VariableId id) const {
989 CHECK(has_variable(id)) << "No variable with id: " << id.value();
990 return Variable(storage(), id);
991}
993absl::string_view Model::name(const Variable variable) const {
994 CheckModel(variable.storage());
995 return storage()->variable_name(variable.typed_id());
996}
997
999 CheckModel(variable.storage());
1000 storage()->set_variable_lower_bound(variable.typed_id(), lower_bound);
1001}
1003double Model::lower_bound(const Variable variable) const {
1004 CheckModel(variable.storage());
1005 return storage()->variable_lower_bound(variable.typed_id());
1007
1008void Model::set_upper_bound(const Variable variable, double upper_bound) {
1009 CheckModel(variable.storage());
1010 storage()->set_variable_upper_bound(variable.typed_id(), upper_bound);
1011}
1012
1013double Model::upper_bound(const Variable variable) const {
1014 CheckModel(variable.storage());
1015 return storage()->variable_upper_bound(variable.typed_id());
1016}
1017
1018void Model::set_is_integer(const Variable variable, bool is_integer) {
1019 CheckModel(variable.storage());
1020 storage()->set_variable_is_integer(variable.typed_id(), is_integer);
1021}
1022
1023void Model::set_integer(const Variable variable) {
1024 set_is_integer(variable, true);
1026
1027void Model::set_continuous(const Variable variable) {
1028 set_is_integer(variable, false);
1029}
1031bool Model::is_integer(const Variable variable) const {
1032 CheckModel(variable.storage());
1033 return storage()->is_variable_integer(variable.typed_id());
1034}
1036// -------------------------- Linear constraints -------------------------------
1037
1039 Variable variable) const {
1040 // TODO(b/239810718): use << for Variable once it does not CHECK.
1041 if (storage_.get() != variable.storage()) {
1043 << "variable with id " << variable.id()
1044 << " is from a different model";
1048 << "variable with id " << variable.id()
1049 << " is not found in this model (it was probably deleted)";
1050 }
1051 return absl::OkStatus();
1052}
1057LinearConstraint Model::AddLinearConstraint(const double lower_bound,
1058 const double upper_bound,
1059 const absl::string_view name) {
1062}
1063
1064void Model::DeleteLinearConstraint(const LinearConstraint constraint) {
1065 CheckModel(constraint.storage());
1066 storage()->DeleteLinearConstraint(constraint.typed_id());
1067}
1068
1070 return storage()->num_linear_constraints();
1071}
1072
1073int64_t Model::next_linear_constraint_id() const {
1074 return storage()->next_linear_constraint_id().value();
1075}
1077bool Model::has_linear_constraint(const int64_t id) const {
1078 return id < 0 ? false : has_linear_constraint(LinearConstraintId(id));
1080
1082 return storage()->has_linear_constraint(id);
1083}
1084
1085LinearConstraint Model::linear_constraint(const int64_t id) const {
1086 CHECK_GE(id, 0) << "negative linear constraint id: " << id;
1088}
1089
1092 << "No linear constraint with id: " << id.value();
1093 return LinearConstraint(storage(), id);
1094}
1096absl::string_view Model::name(const LinearConstraint constraint) const {
1097 CheckModel(constraint.storage());
1098 return storage()->linear_constraint_name(constraint.typed_id());
1100
1101void Model::set_lower_bound(const LinearConstraint constraint,
1102 double lower_bound) {
1103 CheckModel(constraint.storage());
1104 storage()->set_linear_constraint_lower_bound(constraint.typed_id(),
1105 lower_bound);
1106}
1108double Model::lower_bound(const LinearConstraint constraint) const {
1109 CheckModel(constraint.storage());
1110 return storage()->linear_constraint_lower_bound(constraint.typed_id());
1111}
1113void Model::set_upper_bound(const LinearConstraint constraint,
1114 const double upper_bound) {
1115 CheckModel(constraint.storage());
1116 storage()->set_linear_constraint_upper_bound(constraint.typed_id(),
1117 upper_bound);
1119
1120double Model::upper_bound(const LinearConstraint constraint) const {
1121 CheckModel(constraint.storage());
1122 return storage()->linear_constraint_upper_bound(constraint.typed_id());
1124
1126 LinearConstraint linear_constraint) const {
1127 // TODO(b/239810718): use << for LinearConstraint once it does not CHECK.
1128 if (storage_.get() != linear_constraint.storage()) {
1130 << "linear constraint with id " << linear_constraint.id()
1131 << " is from a different model";
1132 }
1135 << "linear constraint with id " << linear_constraint.id()
1136 << " is not found in this model (it was probably deleted)";
1137 }
1138 return absl::OkStatus();
1139}
1140
1141void Model::set_coefficient(const LinearConstraint constraint,
1142 const Variable variable, const double value) {
1143 CheckModel(constraint.storage());
1144 CheckModel(variable.storage());
1145 storage()->set_linear_constraint_coefficient(constraint.typed_id(),
1146 variable.typed_id(), value);
1148
1149double Model::coefficient(const LinearConstraint constraint,
1150 const Variable variable) const {
1151 CheckModel(constraint.storage());
1152 CheckModel(variable.storage());
1153 return storage()->linear_constraint_coefficient(constraint.typed_id(),
1154 variable.typed_id());
1155}
1156
1157bool Model::is_coefficient_nonzero(const LinearConstraint constraint,
1158 const Variable variable) const {
1159 CheckModel(constraint.storage());
1160 CheckModel(variable.storage());
1161 return storage()->is_linear_constraint_coefficient_nonzero(
1162 constraint.typed_id(), variable.typed_id());
1164
1165// ------------------------- Quadratic constraints -----------------------------
1166
1168 CheckModel(constraint.storage());
1169 storage()->DeleteAtomicConstraint(constraint.typed_id());
1170}
1172int64_t Model::num_quadratic_constraints() const {
1173 return storage()->num_constraints<QuadraticConstraintId>();
1174}
1175
1177 return storage()->next_constraint_id<QuadraticConstraintId>().value();
1178}
1180bool Model::has_quadratic_constraint(const int64_t id) const {
1182}
1183
1185 return storage()->has_constraint(id);
1186}
1187
1188QuadraticConstraint Model::quadratic_constraint(const int64_t id) const {
1189 CHECK_GE(id, 0) << "negative quadratic constraint id: " << id;
1191}
1192
1194 const QuadraticConstraintId id) const {
1195 CHECK(has_quadratic_constraint(id))
1196 << "No quadratic constraint with id: " << id.value();
1197 return QuadraticConstraint(storage(), id);
1199
1200std::vector<QuadraticConstraint> Model::QuadraticConstraints() const {
1203
1204std::vector<QuadraticConstraint> Model::SortedQuadraticConstraints() const {
1207
1208// --------------------- Second-order cone constraints -------------------------
1209
1211 const SecondOrderConeConstraint constraint) {
1212 CheckModel(constraint.storage());
1213 storage()->DeleteAtomicConstraint(constraint.typed_id());
1214}
1217 return storage()->num_constraints<SecondOrderConeConstraintId>();
1218}
1219
1221 return storage()->next_constraint_id<SecondOrderConeConstraintId>().value();
1223
1224bool Model::has_second_order_cone_constraint(const int64_t id) const {
1225 return id < 0 ? false
1227 SecondOrderConeConstraintId(id));
1228}
1229
1231 const SecondOrderConeConstraintId id) const {
1232 return storage()->has_constraint(id);
1233}
1234
1236 const int64_t id) const {
1237 return second_order_cone_constraint(SecondOrderConeConstraintId(id));
1241 const SecondOrderConeConstraintId id) const {
1243 << "No second-order cone constraint with id: " << id.value();
1244 return SecondOrderConeConstraint(storage(), id);
1245}
1247std::vector<SecondOrderConeConstraint> Model::SecondOrderConeConstraints()
1248 const {
1250}
1251
1252std::vector<SecondOrderConeConstraint> Model::SortedSecondOrderConeConstraints()
1253 const {
1255}
1256
1257// --------------------------- SOS1 constraints --------------------------------
1258
1259void Model::DeleteSos1Constraint(const Sos1Constraint constraint) {
1260 CheckModel(constraint.storage());
1261 storage()->DeleteAtomicConstraint(constraint.typed_id());
1263
1264int64_t Model::num_sos1_constraints() const {
1265 return storage()->num_constraints<Sos1ConstraintId>();
1266}
1267
1268int64_t Model::next_sos1_constraint_id() const {
1269 return storage()->next_constraint_id<Sos1ConstraintId>().value();
1270}
1271
1272bool Model::has_sos1_constraint(const int64_t id) const {
1273 return id < 0 ? false : has_sos1_constraint(Sos1ConstraintId(id));
1275
1276bool Model::has_sos1_constraint(const Sos1ConstraintId id) const {
1277 return storage()->has_constraint(id);
1278}
1279
1280Sos1Constraint Model::sos1_constraint(const int64_t id) const {
1281 return sos1_constraint(Sos1ConstraintId(id));
1282}
1283
1284Sos1Constraint Model::sos1_constraint(const Sos1ConstraintId id) const {
1285 CHECK(has_sos1_constraint(id))
1286 << "No SOS1 constraint with id: " << id.value();
1287 return Sos1Constraint(storage(), id);
1288}
1289
1290std::vector<Sos1Constraint> Model::Sos1Constraints() const {
1292}
1293
1294std::vector<Sos1Constraint> Model::SortedSos1Constraints() const {
1296}
1297
1298// --------------------------- SOS2 constraints --------------------------------
1299
1300void Model::DeleteSos2Constraint(const Sos2Constraint constraint) {
1301 CheckModel(constraint.storage());
1302 storage()->DeleteAtomicConstraint(constraint.typed_id());
1303}
1304
1305int64_t Model::num_sos2_constraints() const {
1306 return storage()->num_constraints<Sos2ConstraintId>();
1307}
1308
1309int64_t Model::next_sos2_constraint_id() const {
1310 return storage()->next_constraint_id<Sos2ConstraintId>().value();
1311}
1313bool Model::has_sos2_constraint(const int64_t id) const {
1314 return id < 0 ? false : has_sos2_constraint(Sos2ConstraintId(id));
1315}
1317bool Model::has_sos2_constraint(const Sos2ConstraintId id) const {
1318 return storage()->has_constraint(id);
1319}
1320
1321Sos2Constraint Model::sos2_constraint(const int64_t id) const {
1322 return sos2_constraint(Sos2ConstraintId(id));
1323}
1324
1325Sos2Constraint Model::sos2_constraint(const Sos2ConstraintId id) const {
1326 CHECK(has_sos2_constraint(id))
1327 << "No SOS2 constraint with id: " << id.value();
1328 return Sos2Constraint(storage(), id);
1329}
1330
1331std::vector<Sos2Constraint> Model::Sos2Constraints() const {
1333}
1334
1335std::vector<Sos2Constraint> Model::SortedSos2Constraints() const {
1337}
1338
1339// --------------------------- Indicator constraints ---------------------------
1340
1342 CheckModel(constraint.storage());
1343 storage()->DeleteAtomicConstraint(constraint.typed_id());
1344}
1345
1346int64_t Model::num_indicator_constraints() const {
1347 return storage()->num_constraints<IndicatorConstraintId>();
1348}
1349
1351 return storage()->next_constraint_id<IndicatorConstraintId>().value();
1352}
1354bool Model::has_indicator_constraint(const int64_t id) const {
1356}
1359 return storage()->has_constraint(id);
1360}
1361
1362IndicatorConstraint Model::indicator_constraint(const int64_t id) const {
1367 const IndicatorConstraintId id) const {
1369 << "No indicator constraint with id: " << id.value();
1370 return IndicatorConstraint(storage(), id);
1371}
1373std::vector<IndicatorConstraint> Model::IndicatorConstraints() const {
1375}
1377std::vector<IndicatorConstraint> Model::SortedIndicatorConstraints() const {
1379}
1381// ------------------------------- Objective -----------------------------------
1382
1383void Model::Maximize(const double objective) {
1384 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1385}
1386void Model::Maximize(const Variable objective) {
1387 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1389void Model::Maximize(const LinearTerm objective) {
1390 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1391}
1392void Model::Maximize(const LinearExpression& objective) {
1393 SetObjective(objective, /*is_maximize=*/true);
1394}
1395void Model::Maximize(const QuadraticExpression& objective) {
1396 SetObjective(objective, /*is_maximize=*/true);
1397}
1398
1399void Model::Minimize(const double objective) {
1400 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1401}
1402void Model::Minimize(const Variable objective) {
1403 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1404}
1405void Model::Minimize(const LinearTerm objective) {
1406 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1407}
1408void Model::Minimize(const LinearExpression& objective) {
1409 SetObjective(objective, /*is_maximize=*/false);
1410}
1411void Model::Minimize(const QuadraticExpression& objective) {
1412 SetObjective(objective, /*is_maximize=*/false);
1413}
1415void Model::SetObjective(const double objective, const bool is_maximize) {
1416 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1418void Model::SetObjective(const Variable objective, const bool is_maximize) {
1419 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1420}
1421void Model::SetObjective(const LinearTerm objective, const bool is_maximize) {
1422 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1423}
1425void Model::AddToObjective(const double objective) {
1426 AddToObjective(LinearExpression(objective));
1428void Model::AddToObjective(const Variable objective) {
1429 AddToObjective(LinearExpression(objective));
1431void Model::AddToObjective(const LinearTerm objective) {
1432 AddToObjective(LinearExpression(objective));
1436 return Objective::Primary(storage());
1438
1439double Model::objective_coefficient(const Variable variable) const {
1440 CheckModel(variable.storage());
1441 return storage()->linear_objective_coefficient(kPrimaryObjectiveId,
1442 variable.typed_id());
1444
1445double Model::objective_coefficient(const Variable first_variable,
1446 const Variable second_variable) const {
1447 CheckModel(first_variable.storage());
1448 CheckModel(second_variable.storage());
1449 return storage()->quadratic_objective_coefficient(kPrimaryObjectiveId,
1450 first_variable.typed_id(),
1451 second_variable.typed_id());
1452}
1455 const double value) {
1456 CheckModel(variable.storage());
1457 storage()->set_linear_objective_coefficient(kPrimaryObjectiveId,
1458 variable.typed_id(), value);
1459}
1460
1462 const Variable second_variable,
1463 const double value) {
1464 CheckModel(first_variable.storage());
1465 CheckModel(second_variable.storage());
1466 storage()->set_quadratic_objective_coefficient(
1468 second_variable.typed_id(), value);
1469}
1470
1472 storage()->clear_objective(kPrimaryObjectiveId);
1473}
1474
1475bool Model::is_objective_coefficient_nonzero(const Variable variable) const {
1476 CheckModel(variable.storage());
1477 return storage()->is_linear_objective_coefficient_nonzero(
1478 kPrimaryObjectiveId, variable.typed_id());
1479}
1480
1482 const Variable first_variable, const Variable second_variable) const {
1483 CheckModel(first_variable.storage());
1484 CheckModel(second_variable.storage());
1485 return storage()->is_quadratic_objective_coefficient_nonzero(
1486 kPrimaryObjectiveId, first_variable.typed_id(),
1487 second_variable.typed_id());
1488}
1489
1490double Model::objective_offset() const {
1491 return storage()->objective_offset(kPrimaryObjectiveId);
1492}
1494void Model::set_objective_offset(const double value) {
1495 storage()->set_objective_offset(kPrimaryObjectiveId, value);
1496}
1498bool Model::is_maximize() const {
1499 return storage()->is_maximize(kPrimaryObjectiveId);
1500}
1501
1502void Model::set_maximize() { storage()->set_maximize(kPrimaryObjectiveId); }
1504void Model::set_minimize() { storage()->set_minimize(kPrimaryObjectiveId); }
1505
1506void Model::set_is_maximize(const bool is_maximize) {
1507 storage()->set_is_maximize(kPrimaryObjectiveId, is_maximize);
1508}
1509
1510std::vector<Variable> Model::NonzeroVariablesInLinearObjective() const {
1513
1514// -------------------------- Auxiliary objectives -----------------------------
1515
1517 const absl::string_view name) {
1519 storage()->AddAuxiliaryObjective(priority, name));
1523 const bool is_maximize,
1524 const int64_t priority,
1525 const absl::string_view name) {
1526 const Objective obj = AddAuxiliaryObjective(priority, name);
1527 SetObjective(obj, expression, is_maximize);
1528 return obj;
1529}
1530
1532 const int64_t priority,
1533 const absl::string_view name) {
1534 return AddAuxiliaryObjective(expression, /*is_maximize=*/true, priority,
1535 name);
1536}
1537
1539 const int64_t priority,
1540 const absl::string_view name) {
1541 return AddAuxiliaryObjective(expression, /*is_maximize=*/false, priority,
1542 name);
1543}
1545void Model::DeleteAuxiliaryObjective(const Objective objective) {
1546 CheckModel(objective.storage());
1547 CHECK(!objective.is_primary()) << "cannot delete primary objective";
1548 const AuxiliaryObjectiveId id = *objective.typed_id();
1549 CHECK(storage()->has_auxiliary_objective(id))
1550 << "cannot delete unrecognized auxiliary objective id: " << id;
1551 storage()->DeleteAuxiliaryObjective(id);
1552}
1554int64_t Model::num_auxiliary_objectives() const {
1555 return storage()->num_auxiliary_objectives();
1556}
1557
1558int64_t Model::next_auxiliary_objective_id() const {
1559 return storage()->next_auxiliary_objective_id().value();
1561
1562bool Model::has_auxiliary_objective(const int64_t id) const {
1563 return id < 0 ? false : has_auxiliary_objective(AuxiliaryObjectiveId(id));
1564}
1565
1567 return storage()->has_auxiliary_objective(id);
1568}
1569
1570Objective Model::auxiliary_objective(const int64_t id) const {
1571 CHECK_GE(id, 0) << "negative auxiliary objective id: " << id;
1573}
1574
1575Objective Model::auxiliary_objective(const AuxiliaryObjectiveId id) const {
1577 << "unrecognized auxiliary objective id: " << id;
1578 return Objective::Auxiliary(storage(), id);
1579}
1581// ---------------------------- Multi-objective --------------------------------
1582
1583void Model::Maximize(const Objective objective,
1584 const LinearExpression& expression) {
1585 SetObjective(objective, expression, /*is_maximize=*/true);
1586}
1587
1588void Model::Minimize(const Objective objective,
1589 const LinearExpression& expression) {
1590 SetObjective(objective, expression, /*is_maximize=*/false);
1591}
1593void Model::set_objective_priority(const Objective objective,
1594 const int64_t priority) {
1595 CheckModel(objective.storage());
1596 storage()->set_objective_priority(objective.typed_id(), priority);
1598
1599void Model::set_objective_coefficient(const Objective objective,
1600 const Variable variable,
1601 const double value) {
1602 CheckModel(objective.storage());
1603 CheckModel(variable.storage());
1604 storage()->set_linear_objective_coefficient(objective.typed_id(),
1605 variable.typed_id(), value);
1606}
1607
1608void Model::set_objective_offset(const Objective objective,
1609 const double value) {
1610 CheckModel(objective.storage());
1611 storage()->set_objective_offset(objective.typed_id(), value);
1612}
1613
1614void Model::set_maximize(const Objective objective) {
1615 set_is_maximize(objective, /*is_maximize=*/true);
1616}
1617
1618void Model::set_minimize(const Objective objective) {
1619 set_is_maximize(objective, /*is_maximize=*/false);
1620}
1622void Model::set_is_maximize(const Objective objective, const bool is_maximize) {
1623 CheckModel(objective.storage());
1624 storage()->set_is_maximize(objective.typed_id(), is_maximize);
1625}
1626
1627void Model::CheckOptionalModel(
1628 const NullableModelStorageCPtr other_storage) const {
1629 if (other_storage != nullptr) {
1630 CHECK_EQ(other_storage, storage())
1632 }
1633}
1634
1635void Model::CheckModel(const ModelStorageCPtr other_storage) const {
1637}
1638
1639} // namespace math_opt
1640} // namespace operations_research
1641
1642#endif // OR_TOOLS_MATH_OPT_CPP_MODEL_H_
int64_t value() const
Returns the raw id value.
Definition elements.h:77
Sos1Constraint AddSos1Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
Definition model.cc:476
void set_lower_bound(Variable variable, double lower_bound)
Sets a variable lower bound.
Definition model.h:1020
std::vector< IndicatorConstraint > SortedIndicatorConstraints() const
Definition model.h:1399
Objective auxiliary_objective(int64_t id) const
Will CHECK if has_auxiliary_objective(id) is false.
Definition model.h:1592
bool has_auxiliary_objective(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1584
int64_t num_sos2_constraints() const
Definition model.h:1327
QuadraticConstraint AddQuadraticConstraint(const BoundedQuadraticExpression &bounded_expr, absl::string_view name="")
----------------------— Quadratic constraints --------------------------—
Definition model.cc:408
Sos2Constraint AddSos2Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
------------------------— SOS2 constraints -----------------------------—
Definition model.cc:489
ModelProto ExportModel(bool remove_names=false) const
Definition model.cc:300
bool has_variable(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:998
std::vector< SecondOrderConeConstraint > SecondOrderConeConstraints() const
Definition model.h:1269
int64_t next_quadratic_constraint_id() const
The returned id of the next call to AddQuadraticConstraint.
Definition model.h:1198
friend std::ostream & operator<<(std::ostream &ostr, const Model &model)
Definition model.cc:312
int64_t next_auxiliary_objective_id() const
The returned id of the next call to AddAuxiliaryObjectve.
Definition model.h:1580
int64_t next_linear_constraint_id() const
Definition model.h:1095
void DeleteSecondOrderConeConstraint(SecondOrderConeConstraint constraint)
------------------— Second-order cone constraints ----------------------—
Definition model.h:1232
static absl::StatusOr< std::unique_ptr< Model > > FromModelProto(const ModelProto &model_proto)
Definition model.cc:56
std::vector< Sos2Constraint > SortedSos2Constraints() const
Definition model.h:1357
bool is_integer(Variable variable) const
Returns the integrality of a variable.
Definition model.h:1053
void set_continuous(Variable variable)
Makes the input variable continuous.
Definition model.h:1049
bool has_sos1_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1294
std::vector< Sos1Constraint > SortedSos1Constraints() const
Definition model.h:1316
absl::string_view name() const
----------------------------— Variables --------------------------------—
Definition model.h:959
void DeleteQuadraticConstraint(QuadraticConstraint constraint)
----------------------— Quadratic constraints --------------------------—
Definition model.h:1189
std::vector< QuadraticConstraint > SortedQuadraticConstraints() const
Definition model.h:1226
void set_coefficient(LinearConstraint constraint, Variable variable, double value)
Definition model.h:1163
double lower_bound(Variable variable) const
Returns a variable lower bound.
Definition model.h:1025
SecondOrderConeConstraint AddSecondOrderConeConstraint(absl::Span< const LinearExpression > arguments_to_norm, const LinearExpression &upper_bound, absl::string_view name="")
------------------— Second-order cone constraints ----------------------—
Definition model.cc:435
std::vector< Variable > NonzeroVariablesInLinearObjective() const
Definition model.h:1532
std::vector< SecondOrderConeConstraint > SortedSecondOrderConeConstraints() const
Definition model.h:1274
SecondOrderConeConstraint second_order_cone_constraint(int64_t id) const
Will CHECK if has_second_order_cone_constraint(id) is false.
Definition model.h:1257
int64_t next_indicator_constraint_id() const
The returned id of the next call to AddIndicatorConstraint.
Definition model.h:1372
std::vector< Objective > AuxiliaryObjectives() const
Definition model.cc:236
int64_t next_second_order_cone_constraint_id() const
The returned id of the next call to AddSecondOrderConeConstraint.
Definition model.h:1242
int64_t num_second_order_cone_constraints() const
Definition model.h:1238
std::unique_ptr< UpdateTracker > NewUpdateTracker()
Definition model.cc:304
std::vector< LinearConstraint > SortedLinearConstraints() const
Definition model.cc:137
Objective AddMinimizationObjective(const LinearExpression &expression, int64_t priority, absl::string_view name={})
Adds expression as an auxiliary minimization objective to the model.
Definition model.h:1560
bool has_sos2_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1335
void Maximize(double objective)
Sets the objective to maximize the provided expression.
Definition model.h:1405
std::vector< Sos1Constraint > Sos1Constraints() const
Definition model.h:1312
absl::Status ValidateExistingLinearConstraintOfThisModel(LinearConstraint linear_constraint) const
Definition model.h:1147
void set_is_maximize(bool is_maximize)
Prefer set_maximize() and set_minimize() above for more readable code.
Definition model.h:1528
int64_t num_sos1_constraints() const
Definition model.h:1286
bool has_indicator_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1376
bool has_quadratic_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1202
Variable variable(int64_t id) const
Will CHECK if has_variable(id) is false.
Definition model.h:1006
QuadraticExpression ObjectiveAsQuadraticExpression() const
Definition model.cc:222
Model & operator=(const Model &)=delete
void AddToObjective(double objective)
Adds the provided expression terms to the objective.
Definition model.h:1447
Variable AddVariable(double lower_bound, double upper_bound, bool is_integer, absl::string_view name="")
Adds a variable to the model and returns a reference to it.
Definition model.h:964
Objective AddAuxiliaryObjective(int64_t priority, absl::string_view name={})
Adds an empty (== 0) auxiliary minimization objective to the model.
Definition model.h:1538
bool has_linear_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1099
void DeleteAuxiliaryObjective(Objective objective)
Definition model.h:1567
ModelStorageCPtr storage() const
Definition model.h:917
void set_objective_priority(Objective objective, int64_t priority)
Definition model.h:1615
void set_objective_offset(double value)
Definition model.h:1516
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
Definition model.cc:308
int64_t next_sos2_constraint_id() const
The returned id of the next call to AddSos2Constraint.
Definition model.h:1331
std::vector< LinearConstraint > ColumnNonzeros(Variable variable) const
Definition model.cc:106
void DeleteLinearConstraint(LinearConstraint constraint)
Definition model.h:1086
int64_t num_indicator_constraints() const
Definition model.h:1368
std::vector< QuadraticConstraint > QuadraticConstraints() const
Definition model.h:1222
void DeleteSos1Constraint(Sos1Constraint constraint)
------------------------— SOS1 constraints -----------------------------—
Definition model.h:1281
bool has_second_order_cone_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1246
void Minimize(double objective)
Sets the objective to minimize the provided expression.
Definition model.h:1421
std::vector< LinearConstraint > LinearConstraints() const
Definition model.cc:128
std::vector< Objective > SortedAuxiliaryObjectives() const
Definition model.cc:245
int64_t num_auxiliary_objectives() const
Definition model.h:1576
void DeleteIndicatorConstraint(IndicatorConstraint constraint)
------------------------— Indicator constraints ------------------------—
Definition model.h:1363
Variable AddIntegerVariable(double lower_bound, double upper_bound, absl::string_view name="")
Definition model.h:981
LinearConstraint linear_constraint(int64_t id) const
Will CHECK if has_linear_constraint(id) is false.
Definition model.h:1107
void set_objective_coefficient(Variable variable, double value)
Definition model.h:1476
Variable AddBinaryVariable(absl::string_view name="")
Adds a variable to the model with domain {0, 1}.
Definition model.h:971
double upper_bound(Variable variable) const
Returns a variable upper bound.
Definition model.h:1035
std::vector< Variable > Variables() const
Definition model.cc:88
void DeleteSos2Constraint(Sos2Constraint constraint)
------------------------— SOS2 constraints -----------------------------—
Definition model.h:1322
std::vector< Variable > NonzeroVariablesInQuadraticObjective() const
Definition model.cc:290
absl::Nonnull< std::unique_ptr< Model > > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
Definition model.cc:69
bool is_objective_coefficient_nonzero(Variable variable) const
Definition model.h:1497
double coefficient(LinearConstraint constraint, Variable variable) const
Returns 0.0 if the variable is not used in the constraint.
Definition model.h:1171
void set_upper_bound(Variable variable, double upper_bound)
Sets a variable upper bound.
Definition model.h:1030
std::vector< Sos2Constraint > Sos2Constraints() const
Definition model.h:1353
int64_t next_sos1_constraint_id() const
The returned id of the next call to AddSos1Constraint.
Definition model.h:1290
std::vector< Variable > SortedVariables() const
Definition model.cc:97
void set_integer(Variable variable)
Makes the input variable integer.
Definition model.h:1045
Model(absl::string_view name="")
Creates an empty minimization problem.
Definition model.cc:63
Variable AddContinuousVariable(double lower_bound, double upper_bound, absl::string_view name="")
Adds a variable to the model with domain [lower_bound, upper_bound].
Definition model.h:975
std::vector< IndicatorConstraint > IndicatorConstraints() const
Definition model.h:1395
double objective_coefficient(Variable variable) const
Returns 0.0 if this variable has no linear objective coefficient.
Definition model.h:1461
void DeleteVariable(Variable variable)
Definition model.h:987
absl::Status ValidateExistingVariableOfThisModel(Variable variable) const
-----------------------— Linear constraints ----------------------------—
Definition model.h:1060
Objective AddMaximizationObjective(const LinearExpression &expression, int64_t priority, absl::string_view name={})
Adds expression as an auxiliary maximization objective to the model.
Definition model.h:1553
Objective primary_objective() const
Definition model.h:1457
IndicatorConstraint indicator_constraint(int64_t id) const
Will CHECK if has_indicator_constraint(id) is false.
Definition model.h:1384
LinearExpression ObjectiveAsLinearExpression() const
Definition model.cc:210
Sos2Constraint sos2_constraint(int64_t id) const
Will CHECK if has_sos2_constraint(id) is false.
Definition model.h:1343
int64_t num_quadratic_constraints() const
Definition model.h:1194
bool is_coefficient_nonzero(LinearConstraint constraint, Variable variable) const
Definition model.h:1179
QuadraticConstraint quadratic_constraint(int64_t id) const
Will CHECK if has_quadratic_constraint(id) is false.
Definition model.h:1210
void SetObjective(double objective, bool is_maximize)
Sets the objective to optimize the provided expression.
Definition model.h:1437
IndicatorConstraint AddIndicatorConstraint(Variable indicator_variable, const BoundedLinearExpression &implied_constraint, bool activate_on_zero=false, absl::string_view name={})
------------------------— Indicator constraints ------------------------—
Definition model.cc:502
void set_is_integer(Variable variable, bool is_integer)
Sets the integrality of a variable.
Definition model.h:1040
LinearConstraint AddLinearConstraint(absl::string_view name="")
Adds a linear constraint to the model with bounds [-inf, +inf].
Definition model.h:1076
std::vector< Variable > RowNonzeros(LinearConstraint constraint) const
Definition model.cc:117
Sos1Constraint sos1_constraint(int64_t id) const
Will CHECK if has_sos1_constraint(id) is false.
Definition model.h:1302
static Objective Primary(ModelStorageCPtr storage)
Returns an object that refers to the primary objective of the model.
Definition objective.h:215
static Objective Auxiliary(ModelStorageCPtr storage, AuxiliaryObjectiveId id)
Returns an object that refers to an auxiliary objective of the model.
Definition objective.h:219
constexpr absl::string_view kObjectsFromOtherModelStorage
Definition key_types.h:157
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
absl::Nonnull< const ModelStorage * > ModelStorageCPtr
std::vector< ConstraintType > AtomicConstraints(const ModelStorage &storage)
Definition model_util.h:57
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).
Definition matchers.h:468
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
Definition elements.h:266
std::vector< ConstraintType > SortedAtomicConstraints(const ModelStorage &storage)
Definition model_util.h:69
ElementId< ElementType::kVariable > VariableId
Definition elements.h:264
constexpr ObjectiveId kPrimaryObjectiveId
absl::Nonnull< ModelStorage * > ModelStoragePtr
ElementId< ElementType::kQuadraticConstraint > QuadraticConstraintId
Definition elements.h:267
ElementId< ElementType::kLinearConstraint > LinearConstraintId
Definition elements.h:265
ElementId< ElementType::kIndicatorConstraint > IndicatorConstraintId
Definition elements.h:268
absl::Nullable< const ModelStorage * > NullableModelStorageCPtr
In SWIG mode, we don't want anything besides these top-level includes.
StatusBuilder InvalidArgumentErrorBuilder()
A LinearExpression with upper and lower bounds.
A QuadraticExpression with upper and lower bounds.
A term in an sum of variables multiplied by coefficients.