Google OR-Tools v9.15
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 ORTOOLS_MATH_OPT_CPP_MODEL_H_
18#define ORTOOLS_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 // For Xpress see
485 // https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/XPRSaddsets.html
486 //
487 // These `weights` must either be empty or the same length as `expressions`.
488 // If it is empty, default weights of 1, 2, ... will be used.
489 //
490 // Usage:
491 // Model model = ...;
492 // const Variable x = ...;
493 // const Variable y = ...;
494 // model.AddSos1Constraint({x, y}, {}, "c");
495 // model.AddSos1Constraint({1 - 2 * x, y}, {3, 2});
497 const std::vector<LinearExpression>& expressions,
498 std::vector<double> weights = {}, absl::string_view name = "");
499
500 // Removes an SOS1 constraint from the model.
501 //
502 // It is an error to use any reference to this SOS1 constraint after this
503 // operation. Runs in O(#terms in all expressions).
504 inline void DeleteSos1Constraint(Sos1Constraint constraint);
505
506 // The number of SOS1 constraints in the model.
507 //
508 // Equal to the number of SOS1 constraints created minus the number of SOS1
509 // constraints deleted.
510 inline int64_t num_sos1_constraints() const;
511
512 // The returned id of the next call to AddSos1Constraint.
513 inline int64_t next_sos1_constraint_id() const;
514
515 // Returns true if this id has been created and not yet deleted.
516 inline bool has_sos1_constraint(int64_t id) const;
517
518 // Returns true if this id has been created and not yet deleted.
519 inline bool has_sos1_constraint(Sos1ConstraintId id) const;
520
521 // Will CHECK if has_sos1_constraint(id) is false.
522 inline Sos1Constraint sos1_constraint(int64_t id) const;
523
524 // Will CHECK if has_sos1_constraint(id) is false.
525 inline Sos1Constraint sos1_constraint(Sos1ConstraintId id) const;
526
527 // Returns all the existing (created and not deleted) SOS1 constraints in the
528 // model in an arbitrary order.
529 inline std::vector<Sos1Constraint> Sos1Constraints() const;
530
531 // Returns all the existing (created and not deleted) SOS1 constraints in the
532 // model sorted by id.
533 inline std::vector<Sos1Constraint> SortedSos1Constraints() const;
534
536 // Sos2Constraint methods
538
539 // Adds an SOS2 constraint to the model: at most two of the `expressions` may
540 // take a nonzero value, and they must be adjacent in their ordering.
541 //
542 // The `weights` are an implementation detail in the solver used to order the
543 // `expressions`; see the Gurobi documentation for more detail:
544 // https://www.gurobi.com/documentation/9.5/refman/constraints.html#subsubsection:SOSConstraints
545 // For Xpress see
546 // https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/XPRSaddsets.html
547 //
548 // These `weights` must either be empty or the same length as `expressions`.
549 // If it is empty, default weights of 1, 2, ... will be used.
550 //
551 // Usage:
552 // Model model = ...;
553 // const Variable x = ...;
554 // const Variable y = ...;
555 // model.AddSos2Constraint({x, y}, {}, "c");
556 // model.AddSos2Constraint({1 - 2 * x, y}, {3, 2});
558 const std::vector<LinearExpression>& expressions,
559 std::vector<double> weights = {}, absl::string_view name = "");
560
561 // Removes an SOS2 constraint from the model.
562 //
563 // It is an error to use any reference to this SOS2 constraint after this
564 // operation. Runs in O(#terms in all expressions).
565 inline void DeleteSos2Constraint(Sos2Constraint constraint);
566
567 // The number of SOS2 constraints in the model.
568 //
569 // Equal to the number of SOS2 constraints created minus the number of SOS2
570 // constraints deleted.
571 inline int64_t num_sos2_constraints() const;
572
573 // The returned id of the next call to AddSos2Constraint.
574 inline int64_t next_sos2_constraint_id() const;
575
576 // Returns true if this id has been created and not yet deleted.
577 inline bool has_sos2_constraint(int64_t id) const;
578
579 // Returns true if this id has been created and not yet deleted.
580 inline bool has_sos2_constraint(Sos2ConstraintId id) const;
581
582 // Will CHECK if has_sos2_constraint(id) is false.
583 inline Sos2Constraint sos2_constraint(int64_t id) const;
584
585 // Will CHECK if has_sos2_constraint(id) is false.
586 inline Sos2Constraint sos2_constraint(Sos2ConstraintId id) const;
587
588 // Returns all the existing (created and not deleted) SOS2 constraints in the
589 // model in an arbitrary order.
590 inline std::vector<Sos2Constraint> Sos2Constraints() const;
591
592 // Returns all the existing (created and not deleted) SOS2 constraints in the
593 // model sorted by id.
594 inline std::vector<Sos2Constraint> SortedSos2Constraints() const;
595
597 // IndicatorConstraint methods
599
600 // Adds an indicator constraint to the model.
601 //
602 // Assume for the moment that `activate_on_zero == false` (the default value).
603 // * If `indicator_variable == 1`, then `implied_constraint` must hold.
604 // * If `indicator_variable == 0`, then `implied_constraint` need not hold.
605 // Alternatively, if `activate_on_zero = true`, flip the 1 and 0 above.
606 //
607 // The `indicator_variable` is expected to be a binary variable in the model.
608 // If this is not the case, the solver may elect to either implicitly add the
609 // binary constraint, or reject the model.
610 //
611 // Usage:
612 // Model model = ...;
613 // const Variable x = model.AddBinaryVariable("x");
614 // const Variable y = model.AddBinaryVariable("y");
615 // model.AddIndicatorConstraint(x, y <= 0);
616 // model.AddIndicatorConstraint(y, x >= 2, true, "c");
617 IndicatorConstraint AddIndicatorConstraint(
618 Variable indicator_variable,
619 const BoundedLinearExpression& implied_constraint,
620 bool activate_on_zero = false, absl::string_view name = {});
621
622 // Removes an indicator constraint from the model.
623 //
624 // It is an error to use any reference to this indicator constraint after this
625 // operation. Runs in O(#terms in implied constraint).
626 inline void DeleteIndicatorConstraint(IndicatorConstraint constraint);
627
628 // The number of indicator constraints in the model.
629 //
630 // Equal to the number of indicator constraints created minus the number of
631 // indicator constraints deleted.
632 inline int64_t num_indicator_constraints() const;
633
634 // The returned id of the next call to AddIndicatorConstraint.
635 inline int64_t next_indicator_constraint_id() const;
636
637 // Returns true if this id has been created and not yet deleted.
638 inline bool has_indicator_constraint(int64_t id) const;
639
640 // Returns true if this id has been created and not yet deleted.
642
643 // Will CHECK if has_indicator_constraint(id) is false.
644 inline IndicatorConstraint indicator_constraint(int64_t id) const;
645
646 // Will CHECK if has_indicator_constraint(id) is false.
647 inline IndicatorConstraint indicator_constraint(
648 IndicatorConstraintId id) const;
649
650 // Returns all the existing (created and not deleted) indicator constraints in
651 // the model in an arbitrary order.
652 inline std::vector<IndicatorConstraint> IndicatorConstraints() const;
653
654 // Returns all the existing (created and not deleted) indicator constraints in
655 // the model sorted by id.
656 inline std::vector<IndicatorConstraint> SortedIndicatorConstraints() const;
657
659 // Objective methods
661
662 // Sets the objective to maximize the provided expression.
663 inline void Maximize(double objective);
664 // Sets the objective to maximize the provided expression.
665 inline void Maximize(Variable objective);
666 // Sets the objective to maximize the provided expression.
667 inline void Maximize(LinearTerm objective);
668 // Sets the objective to maximize the provided expression.
669 inline void Maximize(const LinearExpression& objective);
670 // Sets the objective to maximize the provided expression.
671 inline void Maximize(const QuadraticExpression& objective);
672
673 // Sets the objective to minimize the provided expression.
674 inline void Minimize(double objective);
675 // Sets the objective to minimize the provided expression.
676 inline void Minimize(Variable objective);
677 // Sets the objective to minimize the provided expression.
678 inline void Minimize(LinearTerm objective);
679 // Sets the objective to minimize the provided expression.
680 inline void Minimize(const LinearExpression& objective);
681 // Sets the objective to minimize the provided expression.
682 inline void Minimize(const QuadraticExpression& objective);
683
684 // Sets the objective to optimize the provided expression.
685 inline void SetObjective(double objective, bool is_maximize);
686 // Sets the objective to optimize the provided expression.
687 inline void SetObjective(Variable objective, bool is_maximize);
688 // Sets the objective to optimize the provided expression.
689 inline void SetObjective(LinearTerm objective, bool is_maximize);
690 // Sets the objective to optimize the provided expression.
691 void SetObjective(const LinearExpression& objective, bool is_maximize);
692 // Sets the objective to optimize the provided expression.
693 void SetObjective(const QuadraticExpression& objective, bool is_maximize);
694
695 // Adds the provided expression terms to the objective.
696 inline void AddToObjective(double objective);
697 // Adds the provided expression terms to the objective.
698 inline void AddToObjective(Variable objective);
699 // Adds the provided expression terms to the objective.
700 inline void AddToObjective(LinearTerm objective);
701 // Adds the provided expression terms to the objective.
702 void AddToObjective(const LinearExpression& objective);
703 // Adds the provided expression terms to the objective.
704 void AddToObjective(const QuadraticExpression& objective);
705
706 // NOTE: This will CHECK fail if the objective has quadratic terms.
707 LinearExpression ObjectiveAsLinearExpression() const;
708 QuadraticExpression ObjectiveAsQuadraticExpression() const;
709
710 // Returns an object referring to the primary objective in the model. Can be
711 // used with the multi-objective API in the same way that an auxiliary
712 // objective can be.
713 inline Objective primary_objective() const;
714
715 // Returns 0.0 if this variable has no linear objective coefficient.
716 inline double objective_coefficient(Variable variable) const;
717
718 // Returns 0.0 if this variable pair has no quadratic objective coefficient.
719 // The order of the variables does not matter.
720 inline double objective_coefficient(Variable first_variable,
721 Variable second_variable) const;
722
723 // Setting a value to 0.0 will delete the variable from the underlying sparse
724 // representation (and has no effect if the variable is not present).
725 inline void set_objective_coefficient(Variable variable, double value);
726
727 // Set quadratic objective terms for the product of two variables. Setting a
728 // value to 0.0 will delete the variable pair from the underlying sparse
729 // representation (and has no effect if the pair is not present). The order of
730 // the variables does not matter.
731 inline void set_objective_coefficient(Variable first_variable,
732 Variable second_variable, double value);
733
734 // Sets the objective offset, linear terms, and quadratic terms of the
735 // objective to zero. The name, direction, and priority are unchanged.
736 // Equivalent to SetObjective(0.0, is_maximize()).
737 //
738 // Runs in O(#linear and quadratic objective terms with nonzero coefficient).
739 inline void clear_objective();
740
742 inline bool is_objective_coefficient_nonzero(Variable first_variable,
743 Variable second_variable) const;
744
745 inline double objective_offset() const;
746
747 inline void set_objective_offset(double value);
748
749 inline bool is_maximize() const;
750
751 inline void set_maximize();
752 inline void set_minimize();
753
754 // Prefer set_maximize() and set_minimize() above for more readable code.
755 inline void set_is_maximize(bool is_maximize);
756
757 // Returns all variables that have a nonzero coefficient in the linear part of
758 // the primary objective. Result is not sorted.
759 inline std::vector<Variable> NonzeroVariablesInLinearObjective() const;
760 // Returns all variables that have a nonzero coefficient in the quadratic part
761 // of the primary objective. Result is not sorted.
762 std::vector<Variable> NonzeroVariablesInQuadraticObjective() const;
763
765 // Auxiliary objective methods
766 //
767 // This is an API for creating and deleting auxiliary objectives. To modify
768 // them, use the multi-objective API below.
770
771 // Adds an empty (== 0) auxiliary minimization objective to the model.
772 inline Objective AddAuxiliaryObjective(int64_t priority,
773 absl::string_view name = {});
774 // Adds `expression` as an auxiliary objective to the model.
775 inline Objective AddAuxiliaryObjective(const LinearExpression& expression,
776 bool is_maximize, int64_t priority,
777 absl::string_view name = {});
778 // Adds `expression` as an auxiliary maximization objective to the model.
779 inline Objective AddMaximizationObjective(const LinearExpression& expression,
780 int64_t priority,
781 absl::string_view name = {});
782 // Adds `expression` as an auxiliary minimization objective to the model.
783 inline Objective AddMinimizationObjective(const LinearExpression& expression,
784 int64_t priority,
785 absl::string_view name = {});
786
787 // Removes an auxiliary objective from the model.
788 //
789 // It is an error to use any reference to this auxiliary objective after this
790 // operation. Runs in O(1) time.
791 //
792 // Will CHECK-fail if `objective` is from another model, has already been
793 // deleted, or is a primary objective.
794 inline void DeleteAuxiliaryObjective(Objective objective);
795
796 // The number of auxiliary objectives in the model.
797 //
798 // Equal to the number of auxiliary objectives created minus the number of
799 // auxiliary objectives deleted.
800 inline int64_t num_auxiliary_objectives() const;
801
802 // The returned id of the next call to AddAuxiliaryObjectve.
803 inline int64_t next_auxiliary_objective_id() const;
804
805 // Returns true if this id has been created and not yet deleted.
806 inline bool has_auxiliary_objective(int64_t id) const;
807
808 // Returns true if this id has been created and not yet deleted.
809 inline bool has_auxiliary_objective(AuxiliaryObjectiveId id) const;
810
811 // Will CHECK if has_auxiliary_objective(id) is false.
812 inline Objective auxiliary_objective(int64_t id) const;
813
814 // Will CHECK if has_auxiliary_objective(id) is false.
815 inline Objective auxiliary_objective(AuxiliaryObjectiveId id) const;
816
817 // Returns all the existing (created and not deleted) auxiliary objectives in
818 // the model in an arbitrary order.
819 std::vector<Objective> AuxiliaryObjectives() const;
820
821 // Returns all the existing (created and not deleted) auxiliary objectives in
822 // the model sorted by id.
823 std::vector<Objective> SortedAuxiliaryObjectives() const;
824
826 // Multi-objective methods
827 //
828 // This is an API for setting objective properties (for either primary or
829 // auxiliary objectives). Only linear objectives are supported through this
830 // API. To query objective properties, use the methods on `Objective`.
832
833 // Sets `objective` to be maximizing `expression`.
834 inline void Maximize(Objective objective, const LinearExpression& expression);
835 // Sets `objective` to be minimizing `expression`.
836 inline void Minimize(Objective objective, const LinearExpression& expression);
837 // Sets the objective to optimize the provided expression.
838 void SetObjective(Objective objective, const LinearExpression& expression,
839 bool is_maximize);
840
841 // Adds the provided expression terms to the objective.
842 void AddToObjective(Objective objective, const LinearExpression& expression);
843
844 // Sets the priority for an objective (lower is more important). `priority`
845 // must be nonnegative.
846 inline void set_objective_priority(Objective objective, int64_t priority);
847
848 // Setting a value to 0.0 will delete the variable from the underlying sparse
849 // representation (and has no effect if the variable is not present).
850 inline void set_objective_coefficient(Objective objective, Variable variable,
851 double value);
852
853 inline void set_objective_offset(Objective objective, double value);
854
855 inline void set_maximize(Objective objective);
856 inline void set_minimize(Objective objective);
857
858 // Prefer set_maximize() and set_minimize() above for more readable code.
859 inline void set_is_maximize(Objective objective, bool is_maximize);
860
861 // Returns all variables that have a nonzero coefficient in the linear part of
862 // the `objective`. Result is not sorted.
863 std::vector<Variable> NonzeroVariablesInLinearObjective(
864 Objective objective) const;
865
866 // Returns a proto representation of the optimization model.
867 //
868 // See FromModelProto() to build a Model from a proto.
869 ModelProto ExportModel(bool remove_names = false) const;
870
871 // Returns a tracker that can be used to generate a ModelUpdateProto with the
872 // updates that happened since the last checkpoint. The tracker initial
873 // checkpoint corresponds to the current state of the model.
874 //
875 // The returned UpdateTracker keeps a reference to this model. See the
876 // implications in the documentation of the UpdateTracker class.
877 //
878 // Thread-safety: this method must not be used while modifying the model
879 // (variables, constraints, ...). The user is expected to use proper
880 // synchronization primitive to serialize changes to the model and the use of
881 // this method.
882 std::unique_ptr<UpdateTracker> NewUpdateTracker();
883
884 // Apply the provided update to this model. Returns a failure if the update is
885 // not valid.
886 //
887 // As with FromModelProto(), duplicated names are ignored.
888 //
889 // Note that it takes O(num_variables + num_constraints) extra memory and
890 // execution to apply the update (due to the need to build a ModelSummary). So
891 // even a small update will have some cost.
892 absl::Status ApplyUpdateProto(const ModelUpdateProto& update_proto);
893
894 // TODO(user): expose a way to efficiently iterate through the nonzeros of
895 // the linear constraint matrix.
896
897 // Returns a pointer to the underlying model storage.
898 //
899 // This API is for internal use only and regular users should have no need for
900 // it.
901 ModelStorageCPtr storage() const { return storage_.get(); }
902
903 // Returns a pointer to the underlying model storage.
904 //
905 // This API is for internal use only and regular users should have no need for
906 // it.
907 ModelStoragePtr storage() { return storage_.get(); }
908
909 // Prints the objective, the constraints and the variables of the model over
910 // several lines in a human-readable way. Includes a new line at the end of
911 // the model.
912 friend std::ostream& operator<<(std::ostream& ostr, const Model& model);
913
914 private:
915 // Asserts (with CHECK) that the input pointer is either nullptr or that it
916 // points to the same model as storage_.
917 //
918 // Use CheckModel() when nullptr is not a valid value.
919 inline void CheckOptionalModel(NullableModelStorageCPtr other_storage) const;
920
921 // Asserts (with CHECK) that the input pointer is the same as storage_.
922 //
923 // Use CheckOptionalModel() if nullptr is a valid value too.
924 inline void CheckModel(ModelStorageCPtr other_storage) const;
925
926 // Don't use storage_ directly; prefer to use storage() so that const member
927 // functions don't have modifying access to the underlying storage.
928 //
929 // We use a shared_ptr here so that the UpdateTracker class can have a
930 // weak_ptr on the ModelStorage. This let it have a destructor that don't
931 // crash when called after the destruction of the associated Model.
932 const absl_nonnull std::shared_ptr<ModelStorage> storage_;
933};
934
936// Inline function implementations
938
939// ------------------------------- Variables -----------------------------------
940
941absl::string_view Model::name() const { return storage()->name(); }
942
943Variable Model::AddVariable(const absl::string_view name) {
944 return Variable(storage(), storage()->AddVariable(name));
945}
946Variable Model::AddVariable(const double lower_bound, const double upper_bound,
947 const bool is_integer,
948 const absl::string_view name) {
950 is_integer, name));
951}
952
953Variable Model::AddBinaryVariable(const absl::string_view name) {
954 return AddVariable(0.0, 1.0, true, name);
955}
956
957Variable Model::AddContinuousVariable(const double lower_bound,
958 const double upper_bound,
959 const absl::string_view name) {
960 return AddVariable(lower_bound, upper_bound, false, name);
961}
962
964 const double upper_bound,
965 const absl::string_view name) {
966 return AddVariable(lower_bound, upper_bound, true, name);
967}
970 CheckModel(variable.storage());
971 storage()->DeleteVariable(variable.typed_id());
972}
973
974int Model::num_variables() const { return storage()->num_variables(); }
976int64_t Model::next_variable_id() const {
977 return storage()->next_variable_id().value();
978}
980bool Model::has_variable(const int64_t id) const {
981 return id < 0 ? false : has_variable(VariableId(id));
982}
983
984bool Model::has_variable(const VariableId id) const {
985 return storage()->has_variable(id);
986}
987
988Variable Model::variable(const int64_t id) const {
989 return variable(VariableId(id));
990}
992Variable Model::variable(const VariableId id) const {
993 CHECK(has_variable(id)) << "No variable with id: " << id.value();
994 return Variable(storage(), id);
995}
997absl::string_view Model::name(const Variable variable) const {
998 CheckModel(variable.storage());
999 return storage()->variable_name(variable.typed_id());
1000}
1001
1003 CheckModel(variable.storage());
1004 storage()->set_variable_lower_bound(variable.typed_id(), lower_bound);
1005}
1007double Model::lower_bound(const Variable variable) const {
1008 CheckModel(variable.storage());
1009 return storage()->variable_lower_bound(variable.typed_id());
1011
1012void Model::set_upper_bound(const Variable variable, double upper_bound) {
1013 CheckModel(variable.storage());
1014 storage()->set_variable_upper_bound(variable.typed_id(), upper_bound);
1015}
1016
1017double Model::upper_bound(const Variable variable) const {
1018 CheckModel(variable.storage());
1019 return storage()->variable_upper_bound(variable.typed_id());
1020}
1021
1022void Model::set_is_integer(const Variable variable, bool is_integer) {
1023 CheckModel(variable.storage());
1024 storage()->set_variable_is_integer(variable.typed_id(), is_integer);
1025}
1026
1027void Model::set_integer(const Variable variable) {
1028 set_is_integer(variable, true);
1030
1031void Model::set_continuous(const Variable variable) {
1032 set_is_integer(variable, false);
1033}
1035bool Model::is_integer(const Variable variable) const {
1036 CheckModel(variable.storage());
1037 return storage()->is_variable_integer(variable.typed_id());
1038}
1040// -------------------------- Linear constraints -------------------------------
1041
1043 Variable variable) const {
1044 // TODO(b/239810718): use << for Variable once it does not CHECK.
1045 if (storage_.get() != variable.storage()) {
1047 << "variable with id " << variable.id()
1048 << " is from a different model";
1052 << "variable with id " << variable.id()
1053 << " is not found in this model (it was probably deleted)";
1054 }
1055 return absl::OkStatus();
1056}
1061LinearConstraint Model::AddLinearConstraint(const double lower_bound,
1062 const double upper_bound,
1063 const absl::string_view name) {
1066}
1067
1068void Model::DeleteLinearConstraint(const LinearConstraint constraint) {
1069 CheckModel(constraint.storage());
1070 storage()->DeleteLinearConstraint(constraint.typed_id());
1071}
1072
1074 return storage()->num_linear_constraints();
1075}
1076
1077int64_t Model::next_linear_constraint_id() const {
1078 return storage()->next_linear_constraint_id().value();
1079}
1081bool Model::has_linear_constraint(const int64_t id) const {
1082 return id < 0 ? false : has_linear_constraint(LinearConstraintId(id));
1084
1086 return storage()->has_linear_constraint(id);
1087}
1088
1089LinearConstraint Model::linear_constraint(const int64_t id) const {
1090 CHECK_GE(id, 0) << "negative linear constraint id: " << id;
1092}
1093
1096 << "No linear constraint with id: " << id.value();
1097 return LinearConstraint(storage(), id);
1098}
1100absl::string_view Model::name(const LinearConstraint constraint) const {
1101 CheckModel(constraint.storage());
1102 return storage()->linear_constraint_name(constraint.typed_id());
1104
1105void Model::set_lower_bound(const LinearConstraint constraint,
1106 double lower_bound) {
1107 CheckModel(constraint.storage());
1108 storage()->set_linear_constraint_lower_bound(constraint.typed_id(),
1109 lower_bound);
1110}
1112double Model::lower_bound(const LinearConstraint constraint) const {
1113 CheckModel(constraint.storage());
1114 return storage()->linear_constraint_lower_bound(constraint.typed_id());
1115}
1117void Model::set_upper_bound(const LinearConstraint constraint,
1118 const double upper_bound) {
1119 CheckModel(constraint.storage());
1120 storage()->set_linear_constraint_upper_bound(constraint.typed_id(),
1121 upper_bound);
1123
1124double Model::upper_bound(const LinearConstraint constraint) const {
1125 CheckModel(constraint.storage());
1126 return storage()->linear_constraint_upper_bound(constraint.typed_id());
1128
1130 LinearConstraint linear_constraint) const {
1131 // TODO(b/239810718): use << for LinearConstraint once it does not CHECK.
1132 if (storage_.get() != linear_constraint.storage()) {
1134 << "linear constraint with id " << linear_constraint.id()
1135 << " is from a different model";
1136 }
1139 << "linear constraint with id " << linear_constraint.id()
1140 << " is not found in this model (it was probably deleted)";
1141 }
1142 return absl::OkStatus();
1143}
1144
1145void Model::set_coefficient(const LinearConstraint constraint,
1146 const Variable variable, const double value) {
1147 CheckModel(constraint.storage());
1148 CheckModel(variable.storage());
1149 storage()->set_linear_constraint_coefficient(constraint.typed_id(),
1150 variable.typed_id(), value);
1152
1153double Model::coefficient(const LinearConstraint constraint,
1154 const Variable variable) const {
1155 CheckModel(constraint.storage());
1156 CheckModel(variable.storage());
1157 return storage()->linear_constraint_coefficient(constraint.typed_id(),
1158 variable.typed_id());
1159}
1160
1161bool Model::is_coefficient_nonzero(const LinearConstraint constraint,
1162 const Variable variable) const {
1163 CheckModel(constraint.storage());
1164 CheckModel(variable.storage());
1165 return storage()->is_linear_constraint_coefficient_nonzero(
1166 constraint.typed_id(), variable.typed_id());
1168
1169// ------------------------- Quadratic constraints -----------------------------
1170
1172 CheckModel(constraint.storage());
1173 storage()->DeleteAtomicConstraint(constraint.typed_id());
1174}
1176int64_t Model::num_quadratic_constraints() const {
1177 return storage()->num_constraints<QuadraticConstraintId>();
1178}
1179
1181 return storage()->next_constraint_id<QuadraticConstraintId>().value();
1182}
1184bool Model::has_quadratic_constraint(const int64_t id) const {
1186}
1187
1189 return storage()->has_constraint(id);
1190}
1191
1192QuadraticConstraint Model::quadratic_constraint(const int64_t id) const {
1193 CHECK_GE(id, 0) << "negative quadratic constraint id: " << id;
1195}
1196
1198 const QuadraticConstraintId id) const {
1199 CHECK(has_quadratic_constraint(id))
1200 << "No quadratic constraint with id: " << id.value();
1201 return QuadraticConstraint(storage(), id);
1203
1204std::vector<QuadraticConstraint> Model::QuadraticConstraints() const {
1207
1208std::vector<QuadraticConstraint> Model::SortedQuadraticConstraints() const {
1211
1212// --------------------- Second-order cone constraints -------------------------
1213
1215 const SecondOrderConeConstraint constraint) {
1216 CheckModel(constraint.storage());
1217 storage()->DeleteAtomicConstraint(constraint.typed_id());
1218}
1221 return storage()->num_constraints<SecondOrderConeConstraintId>();
1222}
1223
1225 return storage()->next_constraint_id<SecondOrderConeConstraintId>().value();
1227
1228bool Model::has_second_order_cone_constraint(const int64_t id) const {
1229 return id < 0 ? false
1231 SecondOrderConeConstraintId(id));
1232}
1233
1235 const SecondOrderConeConstraintId id) const {
1236 return storage()->has_constraint(id);
1237}
1238
1240 const int64_t id) const {
1241 return second_order_cone_constraint(SecondOrderConeConstraintId(id));
1245 const SecondOrderConeConstraintId id) const {
1247 << "No second-order cone constraint with id: " << id.value();
1248 return SecondOrderConeConstraint(storage(), id);
1249}
1251std::vector<SecondOrderConeConstraint> Model::SecondOrderConeConstraints()
1252 const {
1254}
1255
1256std::vector<SecondOrderConeConstraint> Model::SortedSecondOrderConeConstraints()
1257 const {
1259}
1260
1261// --------------------------- SOS1 constraints --------------------------------
1262
1263void Model::DeleteSos1Constraint(const Sos1Constraint constraint) {
1264 CheckModel(constraint.storage());
1265 storage()->DeleteAtomicConstraint(constraint.typed_id());
1267
1268int64_t Model::num_sos1_constraints() const {
1269 return storage()->num_constraints<Sos1ConstraintId>();
1270}
1271
1272int64_t Model::next_sos1_constraint_id() const {
1273 return storage()->next_constraint_id<Sos1ConstraintId>().value();
1274}
1275
1276bool Model::has_sos1_constraint(const int64_t id) const {
1277 return id < 0 ? false : has_sos1_constraint(Sos1ConstraintId(id));
1279
1280bool Model::has_sos1_constraint(const Sos1ConstraintId id) const {
1281 return storage()->has_constraint(id);
1282}
1283
1284Sos1Constraint Model::sos1_constraint(const int64_t id) const {
1285 return sos1_constraint(Sos1ConstraintId(id));
1286}
1287
1288Sos1Constraint Model::sos1_constraint(const Sos1ConstraintId id) const {
1289 CHECK(has_sos1_constraint(id))
1290 << "No SOS1 constraint with id: " << id.value();
1291 return Sos1Constraint(storage(), id);
1292}
1293
1294std::vector<Sos1Constraint> Model::Sos1Constraints() const {
1296}
1297
1298std::vector<Sos1Constraint> Model::SortedSos1Constraints() const {
1300}
1301
1302// --------------------------- SOS2 constraints --------------------------------
1303
1304void Model::DeleteSos2Constraint(const Sos2Constraint constraint) {
1305 CheckModel(constraint.storage());
1306 storage()->DeleteAtomicConstraint(constraint.typed_id());
1307}
1308
1309int64_t Model::num_sos2_constraints() const {
1310 return storage()->num_constraints<Sos2ConstraintId>();
1311}
1312
1313int64_t Model::next_sos2_constraint_id() const {
1314 return storage()->next_constraint_id<Sos2ConstraintId>().value();
1315}
1317bool Model::has_sos2_constraint(const int64_t id) const {
1318 return id < 0 ? false : has_sos2_constraint(Sos2ConstraintId(id));
1319}
1321bool Model::has_sos2_constraint(const Sos2ConstraintId id) const {
1322 return storage()->has_constraint(id);
1323}
1324
1325Sos2Constraint Model::sos2_constraint(const int64_t id) const {
1326 return sos2_constraint(Sos2ConstraintId(id));
1327}
1328
1329Sos2Constraint Model::sos2_constraint(const Sos2ConstraintId id) const {
1330 CHECK(has_sos2_constraint(id))
1331 << "No SOS2 constraint with id: " << id.value();
1332 return Sos2Constraint(storage(), id);
1333}
1334
1335std::vector<Sos2Constraint> Model::Sos2Constraints() const {
1337}
1338
1339std::vector<Sos2Constraint> Model::SortedSos2Constraints() const {
1341}
1342
1343// --------------------------- Indicator constraints ---------------------------
1344
1346 CheckModel(constraint.storage());
1347 storage()->DeleteAtomicConstraint(constraint.typed_id());
1348}
1349
1350int64_t Model::num_indicator_constraints() const {
1351 return storage()->num_constraints<IndicatorConstraintId>();
1352}
1353
1355 return storage()->next_constraint_id<IndicatorConstraintId>().value();
1356}
1358bool Model::has_indicator_constraint(const int64_t id) const {
1360}
1363 return storage()->has_constraint(id);
1364}
1365
1366IndicatorConstraint Model::indicator_constraint(const int64_t id) const {
1371 const IndicatorConstraintId id) const {
1373 << "No indicator constraint with id: " << id.value();
1374 return IndicatorConstraint(storage(), id);
1375}
1377std::vector<IndicatorConstraint> Model::IndicatorConstraints() const {
1379}
1381std::vector<IndicatorConstraint> Model::SortedIndicatorConstraints() const {
1383}
1385// ------------------------------- Objective -----------------------------------
1386
1387void Model::Maximize(const double objective) {
1388 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1389}
1390void Model::Maximize(const Variable objective) {
1391 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1393void Model::Maximize(const LinearTerm objective) {
1394 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1395}
1396void Model::Maximize(const LinearExpression& objective) {
1397 SetObjective(objective, /*is_maximize=*/true);
1398}
1399void Model::Maximize(const QuadraticExpression& objective) {
1400 SetObjective(objective, /*is_maximize=*/true);
1401}
1402
1403void Model::Minimize(const double objective) {
1404 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1405}
1406void Model::Minimize(const Variable objective) {
1407 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1408}
1409void Model::Minimize(const LinearTerm objective) {
1410 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1411}
1412void Model::Minimize(const LinearExpression& objective) {
1413 SetObjective(objective, /*is_maximize=*/false);
1414}
1415void Model::Minimize(const QuadraticExpression& objective) {
1416 SetObjective(objective, /*is_maximize=*/false);
1417}
1419void Model::SetObjective(const double objective, const bool is_maximize) {
1420 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1422void Model::SetObjective(const Variable objective, const bool is_maximize) {
1423 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1424}
1425void Model::SetObjective(const LinearTerm objective, const bool is_maximize) {
1426 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1427}
1429void Model::AddToObjective(const double objective) {
1430 AddToObjective(LinearExpression(objective));
1432void Model::AddToObjective(const Variable objective) {
1433 AddToObjective(LinearExpression(objective));
1435void Model::AddToObjective(const LinearTerm objective) {
1436 AddToObjective(LinearExpression(objective));
1440 return Objective::Primary(storage());
1442
1443double Model::objective_coefficient(const Variable variable) const {
1444 CheckModel(variable.storage());
1445 return storage()->linear_objective_coefficient(kPrimaryObjectiveId,
1446 variable.typed_id());
1448
1449double Model::objective_coefficient(const Variable first_variable,
1450 const Variable second_variable) const {
1451 CheckModel(first_variable.storage());
1452 CheckModel(second_variable.storage());
1453 return storage()->quadratic_objective_coefficient(kPrimaryObjectiveId,
1454 first_variable.typed_id(),
1455 second_variable.typed_id());
1456}
1459 const double value) {
1460 CheckModel(variable.storage());
1461 storage()->set_linear_objective_coefficient(kPrimaryObjectiveId,
1462 variable.typed_id(), value);
1463}
1464
1466 const Variable second_variable,
1467 const double value) {
1468 CheckModel(first_variable.storage());
1469 CheckModel(second_variable.storage());
1470 storage()->set_quadratic_objective_coefficient(
1472 second_variable.typed_id(), value);
1473}
1474
1476 storage()->clear_objective(kPrimaryObjectiveId);
1477}
1478
1479bool Model::is_objective_coefficient_nonzero(const Variable variable) const {
1480 CheckModel(variable.storage());
1481 return storage()->is_linear_objective_coefficient_nonzero(
1482 kPrimaryObjectiveId, variable.typed_id());
1483}
1484
1486 const Variable first_variable, const Variable second_variable) const {
1487 CheckModel(first_variable.storage());
1488 CheckModel(second_variable.storage());
1489 return storage()->is_quadratic_objective_coefficient_nonzero(
1490 kPrimaryObjectiveId, first_variable.typed_id(),
1491 second_variable.typed_id());
1492}
1493
1494double Model::objective_offset() const {
1495 return storage()->objective_offset(kPrimaryObjectiveId);
1496}
1498void Model::set_objective_offset(const double value) {
1499 storage()->set_objective_offset(kPrimaryObjectiveId, value);
1500}
1502bool Model::is_maximize() const {
1503 return storage()->is_maximize(kPrimaryObjectiveId);
1504}
1505
1506void Model::set_maximize() { storage()->set_maximize(kPrimaryObjectiveId); }
1508void Model::set_minimize() { storage()->set_minimize(kPrimaryObjectiveId); }
1509
1510void Model::set_is_maximize(const bool is_maximize) {
1511 storage()->set_is_maximize(kPrimaryObjectiveId, is_maximize);
1512}
1513
1514std::vector<Variable> Model::NonzeroVariablesInLinearObjective() const {
1517
1518// -------------------------- Auxiliary objectives -----------------------------
1519
1521 const absl::string_view name) {
1523 storage()->AddAuxiliaryObjective(priority, name));
1527 const bool is_maximize,
1528 const int64_t priority,
1529 const absl::string_view name) {
1530 const Objective obj = AddAuxiliaryObjective(priority, name);
1531 SetObjective(obj, expression, is_maximize);
1532 return obj;
1533}
1534
1536 const int64_t priority,
1537 const absl::string_view name) {
1538 return AddAuxiliaryObjective(expression, /*is_maximize=*/true, priority,
1539 name);
1540}
1541
1543 const int64_t priority,
1544 const absl::string_view name) {
1545 return AddAuxiliaryObjective(expression, /*is_maximize=*/false, priority,
1546 name);
1547}
1549void Model::DeleteAuxiliaryObjective(const Objective objective) {
1550 CheckModel(objective.storage());
1551 CHECK(!objective.is_primary()) << "cannot delete primary objective";
1552 const AuxiliaryObjectiveId id = *objective.typed_id();
1553 CHECK(storage()->has_auxiliary_objective(id))
1554 << "cannot delete unrecognized auxiliary objective id: " << id;
1555 storage()->DeleteAuxiliaryObjective(id);
1556}
1558int64_t Model::num_auxiliary_objectives() const {
1559 return storage()->num_auxiliary_objectives();
1560}
1561
1562int64_t Model::next_auxiliary_objective_id() const {
1563 return storage()->next_auxiliary_objective_id().value();
1565
1566bool Model::has_auxiliary_objective(const int64_t id) const {
1567 return id < 0 ? false : has_auxiliary_objective(AuxiliaryObjectiveId(id));
1568}
1569
1571 return storage()->has_auxiliary_objective(id);
1572}
1573
1574Objective Model::auxiliary_objective(const int64_t id) const {
1575 CHECK_GE(id, 0) << "negative auxiliary objective id: " << id;
1577}
1578
1579Objective Model::auxiliary_objective(const AuxiliaryObjectiveId id) const {
1581 << "unrecognized auxiliary objective id: " << id;
1582 return Objective::Auxiliary(storage(), id);
1583}
1585// ---------------------------- Multi-objective --------------------------------
1586
1587void Model::Maximize(const Objective objective,
1588 const LinearExpression& expression) {
1589 SetObjective(objective, expression, /*is_maximize=*/true);
1590}
1591
1592void Model::Minimize(const Objective objective,
1593 const LinearExpression& expression) {
1594 SetObjective(objective, expression, /*is_maximize=*/false);
1595}
1597void Model::set_objective_priority(const Objective objective,
1598 const int64_t priority) {
1599 CheckModel(objective.storage());
1600 storage()->set_objective_priority(objective.typed_id(), priority);
1602
1603void Model::set_objective_coefficient(const Objective objective,
1604 const Variable variable,
1605 const double value) {
1606 CheckModel(objective.storage());
1607 CheckModel(variable.storage());
1608 storage()->set_linear_objective_coefficient(objective.typed_id(),
1609 variable.typed_id(), value);
1610}
1611
1612void Model::set_objective_offset(const Objective objective,
1613 const double value) {
1614 CheckModel(objective.storage());
1615 storage()->set_objective_offset(objective.typed_id(), value);
1616}
1617
1618void Model::set_maximize(const Objective objective) {
1619 set_is_maximize(objective, /*is_maximize=*/true);
1620}
1621
1622void Model::set_minimize(const Objective objective) {
1623 set_is_maximize(objective, /*is_maximize=*/false);
1624}
1626void Model::set_is_maximize(const Objective objective, const bool is_maximize) {
1627 CheckModel(objective.storage());
1628 storage()->set_is_maximize(objective.typed_id(), is_maximize);
1629}
1630
1631void Model::CheckOptionalModel(
1632 const NullableModelStorageCPtr other_storage) const {
1633 if (other_storage != nullptr) {
1634 CHECK_EQ(other_storage, storage())
1636 }
1637}
1638
1639void Model::CheckModel(const ModelStorageCPtr other_storage) const {
1641}
1642
1643} // namespace math_opt
1644} // namespace operations_research
1645
1646#endif // ORTOOLS_MATH_OPT_CPP_MODEL_H_
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)
Definition model.h:1024
std::vector< IndicatorConstraint > SortedIndicatorConstraints() const
Definition model.h:1403
Objective auxiliary_objective(int64_t id) const
Definition model.h:1596
bool has_auxiliary_objective(int64_t id) const
Definition model.h:1588
int64_t num_sos2_constraints() const
Definition model.h:1331
QuadraticConstraint AddQuadraticConstraint(const BoundedQuadraticExpression &bounded_expr, absl::string_view name="")
Definition model.cc:408
Sos2Constraint AddSos2Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
Definition model.cc:489
ModelProto ExportModel(bool remove_names=false) const
Definition model.cc:300
bool has_variable(int64_t id) const
Definition model.h:1002
std::vector< SecondOrderConeConstraint > SecondOrderConeConstraints() const
Definition model.h:1273
int64_t next_quadratic_constraint_id() const
Definition model.h:1202
friend std::ostream & operator<<(std::ostream &ostr, const Model &model)
Definition model.cc:312
int64_t next_auxiliary_objective_id() const
Definition model.h:1584
int64_t next_linear_constraint_id() const
Definition model.h:1099
void DeleteSecondOrderConeConstraint(SecondOrderConeConstraint constraint)
Definition model.h:1236
static absl::StatusOr< std::unique_ptr< Model > > FromModelProto(const ModelProto &model_proto)
Definition model.cc:56
std::vector< Sos2Constraint > SortedSos2Constraints() const
Definition model.h:1361
bool is_integer(Variable variable) const
Definition model.h:1057
void set_continuous(Variable variable)
Definition model.h:1053
bool has_sos1_constraint(int64_t id) const
Definition model.h:1298
std::vector< Sos1Constraint > SortedSos1Constraints() const
Definition model.h:1320
absl::string_view name() const
Definition model.h:963
void DeleteQuadraticConstraint(QuadraticConstraint constraint)
Definition model.h:1193
std::vector< QuadraticConstraint > SortedQuadraticConstraints() const
Definition model.h:1230
void set_coefficient(LinearConstraint constraint, Variable variable, double value)
Definition model.h:1167
double lower_bound(Variable variable) const
Definition model.h:1029
SecondOrderConeConstraint AddSecondOrderConeConstraint(absl::Span< const LinearExpression > arguments_to_norm, const LinearExpression &upper_bound, absl::string_view name="")
Definition model.cc:435
std::vector< Variable > NonzeroVariablesInLinearObjective() const
Definition model.h:1536
std::vector< SecondOrderConeConstraint > SortedSecondOrderConeConstraints() const
Definition model.h:1278
SecondOrderConeConstraint second_order_cone_constraint(int64_t id) const
Definition model.h:1261
int64_t next_indicator_constraint_id() const
Definition model.h:1376
std::vector< Objective > AuxiliaryObjectives() const
Definition model.cc:236
int64_t next_second_order_cone_constraint_id() const
Definition model.h:1246
int64_t num_second_order_cone_constraints() const
Definition model.h:1242
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={})
Definition model.h:1564
bool has_sos2_constraint(int64_t id) const
Definition model.h:1339
void Maximize(double objective)
Definition model.h:1409
std::vector< Sos1Constraint > Sos1Constraints() const
Definition model.h:1316
absl::Status ValidateExistingLinearConstraintOfThisModel(LinearConstraint linear_constraint) const
Definition model.h:1151
void set_is_maximize(bool is_maximize)
Definition model.h:1532
int64_t num_sos1_constraints() const
Definition model.h:1290
bool has_indicator_constraint(int64_t id) const
Definition model.h:1380
bool has_quadratic_constraint(int64_t id) const
Definition model.h:1206
Variable variable(int64_t id) const
Definition model.h:1010
QuadraticExpression ObjectiveAsQuadraticExpression() const
Definition model.cc:222
Model & operator=(const Model &)=delete
void AddToObjective(double objective)
Definition model.h:1451
Variable AddVariable(double lower_bound, double upper_bound, bool is_integer, absl::string_view name="")
Definition model.h:968
Objective AddAuxiliaryObjective(int64_t priority, absl::string_view name={})
Definition model.h:1542
bool has_linear_constraint(int64_t id) const
Definition model.h:1103
void DeleteAuxiliaryObjective(Objective objective)
Definition model.h:1571
ModelStorageCPtr storage() const
Definition model.h:921
void set_objective_priority(Objective objective, int64_t priority)
Definition model.h:1619
void set_objective_offset(double value)
Definition model.h:1520
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
Definition model.cc:308
int64_t next_sos2_constraint_id() const
Definition model.h:1335
std::vector< LinearConstraint > ColumnNonzeros(Variable variable) const
Definition model.cc:106
void DeleteLinearConstraint(LinearConstraint constraint)
Definition model.h:1090
int64_t num_indicator_constraints() const
Definition model.h:1372
std::vector< QuadraticConstraint > QuadraticConstraints() const
Definition model.h:1226
void DeleteSos1Constraint(Sos1Constraint constraint)
Definition model.h:1285
bool has_second_order_cone_constraint(int64_t id) const
Definition model.h:1250
void Minimize(double objective)
Definition model.h:1425
std::vector< LinearConstraint > LinearConstraints() const
Definition model.cc:128
std::vector< Objective > SortedAuxiliaryObjectives() const
Definition model.cc:245
absl_nonnull std::unique_ptr< Model > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
Definition model.cc:69
int64_t num_auxiliary_objectives() const
Definition model.h:1580
void DeleteIndicatorConstraint(IndicatorConstraint constraint)
Definition model.h:1367
Variable AddIntegerVariable(double lower_bound, double upper_bound, absl::string_view name="")
Definition model.h:985
LinearConstraint linear_constraint(int64_t id) const
Definition model.h:1111
void set_objective_coefficient(Variable variable, double value)
Definition model.h:1480
Variable AddBinaryVariable(absl::string_view name="")
Definition model.h:975
double upper_bound(Variable variable) const
Definition model.h:1039
std::vector< Variable > Variables() const
Definition model.cc:88
void DeleteSos2Constraint(Sos2Constraint constraint)
Definition model.h:1326
std::vector< Variable > NonzeroVariablesInQuadraticObjective() const
Definition model.cc:290
bool is_objective_coefficient_nonzero(Variable variable) const
Definition model.h:1501
double coefficient(LinearConstraint constraint, Variable variable) const
Definition model.h:1175
void set_upper_bound(Variable variable, double upper_bound)
Definition model.h:1034
std::vector< Sos2Constraint > Sos2Constraints() const
Definition model.h:1357
int64_t next_sos1_constraint_id() const
Definition model.h:1294
std::vector< Variable > SortedVariables() const
Definition model.cc:97
void set_integer(Variable variable)
Definition model.h:1049
Model(absl::string_view name="")
Definition model.cc:63
Variable AddContinuousVariable(double lower_bound, double upper_bound, absl::string_view name="")
Definition model.h:979
std::vector< IndicatorConstraint > IndicatorConstraints() const
Definition model.h:1399
double objective_coefficient(Variable variable) const
Definition model.h:1465
void DeleteVariable(Variable variable)
Definition model.h:991
absl::Status ValidateExistingVariableOfThisModel(Variable variable) const
Definition model.h:1064
Objective AddMaximizationObjective(const LinearExpression &expression, int64_t priority, absl::string_view name={})
Definition model.h:1557
Objective primary_objective() const
Definition model.h:1461
IndicatorConstraint indicator_constraint(int64_t id) const
Definition model.h:1388
LinearExpression ObjectiveAsLinearExpression() const
Definition model.cc:210
Sos2Constraint sos2_constraint(int64_t id) const
Definition model.h:1347
int64_t num_quadratic_constraints() const
Definition model.h:1198
bool is_coefficient_nonzero(LinearConstraint constraint, Variable variable) const
Definition model.h:1183
QuadraticConstraint quadratic_constraint(int64_t id) const
Definition model.h:1214
void SetObjective(double objective, bool is_maximize)
Definition model.h:1441
IndicatorConstraint AddIndicatorConstraint(Variable indicator_variable, const BoundedLinearExpression &implied_constraint, bool activate_on_zero=false, absl::string_view name={})
Definition model.cc:502
void set_is_integer(Variable variable, bool is_integer)
Definition model.h:1044
LinearConstraint AddLinearConstraint(absl::string_view name="")
Definition model.h:1080
std::vector< Variable > RowNonzeros(LinearConstraint constraint) const
Definition model.cc:117
Sos1Constraint sos1_constraint(int64_t id) const
Definition model.h:1306
static Objective Primary(ModelStorageCPtr storage)
Definition objective.h:215
static Objective Auxiliary(ModelStorageCPtr storage, AuxiliaryObjectiveId id)
Definition objective.h:219
constexpr absl::string_view kObjectsFromOtherModelStorage
Definition key_types.h:157
const ModelStorage *absl_nonnull 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
Definition matchers.h:467
ModelStorage *absl_nonnull ModelStoragePtr
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
Definition elements.h:82
std::vector< ConstraintType > SortedAtomicConstraints(const ModelStorage &storage)
Definition model_util.h:69
ElementId< ElementType::kVariable > VariableId
Definition elements.h:80
constexpr ObjectiveId kPrimaryObjectiveId
ElementId< ElementType::kQuadraticConstraint > QuadraticConstraintId
Definition elements.h:83
ElementId< ElementType::kLinearConstraint > LinearConstraintId
Definition elements.h:81
const ModelStorage *absl_nullable NullableModelStorageCPtr
ElementId< ElementType::kIndicatorConstraint > IndicatorConstraintId
Definition elements.h:84
OR-Tools root namespace.
StatusBuilder InvalidArgumentErrorBuilder()