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