Google OR-Tools v9.11
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-2024 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 <string>
25#include <vector>
26
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(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 std::unique_ptr<Model> Clone(
163 std::optional<absl::string_view> new_name = std::nullopt) const;
164
165 inline const std::string& 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 const std::string& 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.
318 inline LinearConstraint linear_constraint(LinearConstraintId id) const;
319
320 // Returns the linear constraint name.
321 inline const std::string& 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.
399 inline bool has_quadratic_constraint(QuadraticConstraintId id) const;
400
401 // Will CHECK if has_quadratic_constraint(id) is false.
402 inline QuadraticConstraint quadratic_constraint(int64_t id) const;
403
404 // Will CHECK if has_quadratic_constraint(id) is false.
406 QuadraticConstraintId id) const;
407
408 // Returns all the existing (created and not deleted) quadratic constraints in
409 // the model in an arbitrary order.
410 inline std::vector<QuadraticConstraint> QuadraticConstraints() const;
411
412 // Returns all the existing (created and not deleted) quadratic constraints in
413 // the model sorted by id.
414 inline std::vector<QuadraticConstraint> SortedQuadraticConstraints() const;
415
417 // SecondOrderConeConstraint methods
419
420 // Adds a second-order cone constraint to the model of the form
421 // ||arguments_to_norm||₂ ≤ upper_bound.
422 //
423 // Usage:
424 // Model model = ...;
425 // const Variable x = ...;
426 // const Variable y = ...;
427 // model.AddSecondOrderConeConstraint({x, y}, 1.0, "soc");
428 // model.AddSecondOrderConeConstraint({1.0, 3 * y - x}, 2 * x);
430 absl::Span<const LinearExpression> arguments_to_norm,
431 const LinearExpression& upper_bound, absl::string_view name = "");
432
433 // Removes a second-order cone constraint from the model.
434 //
435 // It is an error to use any reference to this second-order cone constraint
436 // after this operation. Runs in O(#linear terms appearing in constraint).
438 SecondOrderConeConstraint constraint);
439
440 // The number of second-order cone constraints in the model.
441 //
442 // Equal to the number of second-order cone constraints created minus the
443 // number of second-order cone constraints deleted.
444 inline int64_t num_second_order_cone_constraints() const;
445
446 // The returned id of the next call to AddSecondOrderConeConstraint.
447 inline int64_t next_second_order_cone_constraint_id() const;
448
449 // Returns true if this id has been created and not yet deleted.
450 inline bool has_second_order_cone_constraint(int64_t id) const;
451
452 // Returns true if this id has been created and not yet deleted.
454 SecondOrderConeConstraintId id) const;
455
456 // Will CHECK if has_second_order_cone_constraint(id) is false.
458 int64_t id) const;
459
460 // Will CHECK if has_second_order_cone_constraint(id) is false.
462 SecondOrderConeConstraintId id) const;
463
464 // Returns all the existing (created and not deleted) second-order cone
465 // constraints in the model in an arbitrary order.
466 inline std::vector<SecondOrderConeConstraint> SecondOrderConeConstraints()
467 const;
468
469 // Returns all the existing (created and not deleted) second-order cone
470 // constraints in the model sorted by id.
471 inline std::vector<SecondOrderConeConstraint>
473
475 // Sos1Constraint methods
477
478 // Adds an SOS1 constraint to the model: at most one of the `expressions` may
479 // take a nonzero value.
480 //
481 // The `weights` are an implementation detail in the solver used to order the
482 // `expressions`; see the Gurobi documentation for more detail:
483 // https://www.gurobi.com/documentation/9.5/refman/constraints.html#subsubsection:SOSConstraints
484 //
485 // These `weights` must either be empty or the same length as `expressions`.
486 // If it is empty, default weights of 1, 2, ... will be used.
487 //
488 // Usage:
489 // Model model = ...;
490 // const Variable x = ...;
491 // const Variable y = ...;
492 // model.AddSos1Constraint({x, y}, {}, "c");
493 // model.AddSos1Constraint({1 - 2 * x, y}, {3, 2});
495 const std::vector<LinearExpression>& expressions,
496 std::vector<double> weights = {}, absl::string_view name = "");
497
498 // Removes an SOS1 constraint from the model.
499 //
500 // It is an error to use any reference to this SOS1 constraint after this
501 // operation. Runs in O(#terms in all expressions).
502 inline void DeleteSos1Constraint(Sos1Constraint constraint);
503
504 // The number of SOS1 constraints in the model.
505 //
506 // Equal to the number of SOS1 constraints created minus the number of SOS1
507 // constraints deleted.
508 inline int64_t num_sos1_constraints() const;
509
510 // The returned id of the next call to AddSos1Constraint.
511 inline int64_t next_sos1_constraint_id() const;
512
513 // Returns true if this id has been created and not yet deleted.
514 inline bool has_sos1_constraint(int64_t id) const;
515
516 // Returns true if this id has been created and not yet deleted.
517 inline bool has_sos1_constraint(Sos1ConstraintId id) const;
518
519 // Will CHECK if has_sos1_constraint(id) is false.
520 inline Sos1Constraint sos1_constraint(int64_t id) const;
521
522 // Will CHECK if has_sos1_constraint(id) is false.
523 inline Sos1Constraint sos1_constraint(Sos1ConstraintId id) const;
524
525 // Returns all the existing (created and not deleted) SOS1 constraints in the
526 // model in an arbitrary order.
527 inline std::vector<Sos1Constraint> Sos1Constraints() const;
528
529 // Returns all the existing (created and not deleted) SOS1 constraints in the
530 // model sorted by id.
531 inline std::vector<Sos1Constraint> SortedSos1Constraints() const;
532
534 // Sos2Constraint methods
536
537 // Adds an SOS2 constraint to the model: at most two of the `expressions` may
538 // take a nonzero value, and they must be adjacent in their ordering.
539 //
540 // The `weights` are an implementation detail in the solver used to order the
541 // `expressions`; see the Gurobi documentation for more detail:
542 // https://www.gurobi.com/documentation/9.5/refman/constraints.html#subsubsection:SOSConstraints
543 //
544 // These `weights` must either be empty or the same length as `expressions`.
545 // If it is empty, default weights of 1, 2, ... will be used.
546 //
547 // Usage:
548 // Model model = ...;
549 // const Variable x = ...;
550 // const Variable y = ...;
551 // model.AddSos2Constraint({x, y}, {}, "c");
552 // model.AddSos2Constraint({1 - 2 * x, y}, {3, 2});
554 const std::vector<LinearExpression>& expressions,
555 std::vector<double> weights = {}, absl::string_view name = "");
556
557 // Removes an SOS2 constraint from the model.
558 //
559 // It is an error to use any reference to this SOS2 constraint after this
560 // operation. Runs in O(#terms in all expressions).
561 inline void DeleteSos2Constraint(Sos2Constraint constraint);
562
563 // The number of SOS2 constraints in the model.
564 //
565 // Equal to the number of SOS2 constraints created minus the number of SOS2
566 // constraints deleted.
567 inline int64_t num_sos2_constraints() const;
568
569 // The returned id of the next call to AddSos2Constraint.
570 inline int64_t next_sos2_constraint_id() const;
571
572 // Returns true if this id has been created and not yet deleted.
573 inline bool has_sos2_constraint(int64_t id) const;
574
575 // Returns true if this id has been created and not yet deleted.
576 inline bool has_sos2_constraint(Sos2ConstraintId id) const;
577
578 // Will CHECK if has_sos2_constraint(id) is false.
579 inline Sos2Constraint sos2_constraint(int64_t id) const;
580
581 // Will CHECK if has_sos2_constraint(id) is false.
582 inline Sos2Constraint sos2_constraint(Sos2ConstraintId id) const;
583
584 // Returns all the existing (created and not deleted) SOS2 constraints in the
585 // model in an arbitrary order.
586 inline std::vector<Sos2Constraint> Sos2Constraints() const;
587
588 // Returns all the existing (created and not deleted) SOS2 constraints in the
589 // model sorted by id.
590 inline std::vector<Sos2Constraint> SortedSos2Constraints() const;
591
593 // IndicatorConstraint methods
595
596 // Adds an indicator constraint to the model.
597 //
598 // Assume for the moment that `activate_on_zero == false` (the default value).
599 // * If `indicator_variable == 1`, then `implied_constraint` must hold.
600 // * If `indicator_variable == 0`, then `implied_constraint` need not hold.
601 // Alternatively, if `activate_on_zero = true`, flip the 1 and 0 above.
602 //
603 // The `indicator_variable` is expected to be a binary variable in the model.
604 // If this is not the case, the solver may elect to either implicitly add the
605 // binary constraint, or reject the model.
606 //
607 // Usage:
608 // Model model = ...;
609 // const Variable x = model.AddBinaryVariable("x");
610 // const Variable y = model.AddBinaryVariable("y");
611 // model.AddIndicatorConstraint(x, y <= 0);
612 // model.AddIndicatorConstraint(y, x >= 2, true, "c");
613 IndicatorConstraint AddIndicatorConstraint(
614 Variable indicator_variable,
615 const BoundedLinearExpression& implied_constraint,
616 bool activate_on_zero = false, absl::string_view name = {});
617
618 // Removes an indicator constraint from the model.
619 //
620 // It is an error to use any reference to this indicator constraint after this
621 // operation. Runs in O(#terms in implied constraint).
622 inline void DeleteIndicatorConstraint(IndicatorConstraint constraint);
623
624 // The number of indicator constraints in the model.
625 //
626 // Equal to the number of indicator constraints created minus the number of
627 // indicator constraints deleted.
628 inline int64_t num_indicator_constraints() const;
629
630 // The returned id of the next call to AddIndicatorConstraint.
631 inline int64_t next_indicator_constraint_id() const;
632
633 // Returns true if this id has been created and not yet deleted.
634 inline bool has_indicator_constraint(int64_t id) const;
635
636 // Returns true if this id has been created and not yet deleted.
637 inline bool has_indicator_constraint(IndicatorConstraintId id) const;
638
639 // Will CHECK if has_indicator_constraint(id) is false.
640 inline IndicatorConstraint indicator_constraint(int64_t id) const;
641
642 // Will CHECK if has_indicator_constraint(id) is false.
643 inline IndicatorConstraint indicator_constraint(
644 IndicatorConstraintId id) const;
645
646 // Returns all the existing (created and not deleted) indicator constraints in
647 // the model in an arbitrary order.
648 inline std::vector<IndicatorConstraint> IndicatorConstraints() const;
649
650 // Returns all the existing (created and not deleted) indicator constraints in
651 // the model sorted by id.
652 inline std::vector<IndicatorConstraint> SortedIndicatorConstraints() const;
653
655 // Objective methods
657
658 // Sets the objective to maximize the provided expression.
659 inline void Maximize(double objective);
660 // Sets the objective to maximize the provided expression.
661 inline void Maximize(Variable objective);
662 // Sets the objective to maximize the provided expression.
663 inline void Maximize(LinearTerm objective);
664 // Sets the objective to maximize the provided expression.
665 inline void Maximize(const LinearExpression& objective);
666 // Sets the objective to maximize the provided expression.
667 inline void Maximize(const QuadraticExpression& objective);
668
669 // Sets the objective to minimize the provided expression.
670 inline void Minimize(double objective);
671 // Sets the objective to minimize the provided expression.
672 inline void Minimize(Variable objective);
673 // Sets the objective to minimize the provided expression.
674 inline void Minimize(LinearTerm objective);
675 // Sets the objective to minimize the provided expression.
676 inline void Minimize(const LinearExpression& objective);
677 // Sets the objective to minimize the provided expression.
678 inline void Minimize(const QuadraticExpression& objective);
679
680 // Sets the objective to optimize the provided expression.
681 inline void SetObjective(double objective, bool is_maximize);
682 // Sets the objective to optimize the provided expression.
683 inline void SetObjective(Variable objective, bool is_maximize);
684 // Sets the objective to optimize the provided expression.
685 inline void SetObjective(LinearTerm objective, bool is_maximize);
686 // Sets the objective to optimize the provided expression.
687 void SetObjective(const LinearExpression& objective, bool is_maximize);
688 // Sets the objective to optimize the provided expression.
689 void SetObjective(const QuadraticExpression& objective, bool is_maximize);
690
691 // Adds the provided expression terms to the objective.
692 inline void AddToObjective(double objective);
693 // Adds the provided expression terms to the objective.
694 inline void AddToObjective(Variable objective);
695 // Adds the provided expression terms to the objective.
696 inline void AddToObjective(LinearTerm objective);
697 // Adds the provided expression terms to the objective.
698 void AddToObjective(const LinearExpression& objective);
699 // Adds the provided expression terms to the objective.
700 void AddToObjective(const QuadraticExpression& objective);
701
702 // NOTE: This will CHECK fail if the objective has quadratic terms.
703 LinearExpression ObjectiveAsLinearExpression() const;
704 QuadraticExpression ObjectiveAsQuadraticExpression() const;
705
706 // Returns an object referring to the primary objective in the model. Can be
707 // used with the multi-objective API in the same way that an auxiliary
708 // objective can be.
709 inline Objective primary_objective() const;
710
711 // Returns 0.0 if this variable has no linear objective coefficient.
712 inline double objective_coefficient(Variable variable) const;
713
714 // Returns 0.0 if this variable pair has no quadratic objective coefficient.
715 // The order of the variables does not matter.
716 inline double objective_coefficient(Variable first_variable,
717 Variable second_variable) const;
718
719 // Setting a value to 0.0 will delete the variable from the underlying sparse
720 // representation (and has no effect if the variable is not present).
721 inline void set_objective_coefficient(Variable variable, double value);
722
723 // Set quadratic objective terms for the product of two variables. Setting a
724 // value to 0.0 will delete the variable pair from the underlying sparse
725 // representation (and has no effect if the pair is not present). The order of
726 // the variables does not matter.
727 inline void set_objective_coefficient(Variable first_variable,
728 Variable second_variable, double value);
729
730 // Sets the objective offset, linear terms, and quadratic terms of the
731 // objective to zero. The name, direction, and priority are unchanged.
732 // Equivalent to SetObjective(0.0, is_maximize()).
733 //
734 // Runs in O(#linear and quadratic objective terms with nonzero coefficient).
735 inline void clear_objective();
736
737 inline bool is_objective_coefficient_nonzero(Variable variable) const;
738 inline bool is_objective_coefficient_nonzero(Variable first_variable,
739 Variable second_variable) const;
740
741 inline double objective_offset() const;
742
743 inline void set_objective_offset(double value);
744
745 inline bool is_maximize() const;
746
747 inline void set_maximize();
748 inline void set_minimize();
749
750 // Prefer set_maximize() and set_minimize() above for more readable code.
751 inline void set_is_maximize(bool is_maximize);
752
754 // Auxiliary objective methods
755 //
756 // This is an API for creating and deleting auxiliary objectives. To modify
757 // them, use the multi-objective API below.
759
760 // Adds an empty (== 0) auxiliary minimization objective to the model.
761 inline Objective AddAuxiliaryObjective(int64_t priority,
762 absl::string_view name = {});
763 // Adds `expression` as an auxiliary objective to the model.
764 inline Objective AddAuxiliaryObjective(const LinearExpression& expression,
765 bool is_maximize, int64_t priority,
766 absl::string_view name = {});
767 // Adds `expression` as an auxiliary maximization objective to the model.
768 inline Objective AddMaximizationObjective(const LinearExpression& expression,
769 int64_t priority,
770 absl::string_view name = {});
771 // Adds `expression` as an auxiliary minimization objective to the model.
772 inline Objective AddMinimizationObjective(const LinearExpression& expression,
773 int64_t priority,
774 absl::string_view name = {});
775
776 // Removes an auxiliary objective from the model.
777 //
778 // It is an error to use any reference to this auxiliary objective after this
779 // operation. Runs in O(1) time.
780 //
781 // Will CHECK-fail if `objective` is from another model, has already been
782 // deleted, or is a primary objective.
783 inline void DeleteAuxiliaryObjective(Objective objective);
784
785 // The number of auxiliary objectives in the model.
786 //
787 // Equal to the number of auxiliary objectives created minus the number of
788 // auxiliary objectives deleted.
789 inline int64_t num_auxiliary_objectives() const;
790
791 // The returned id of the next call to AddAuxiliaryObjectve.
792 inline int64_t next_auxiliary_objective_id() const;
793
794 // Returns true if this id has been created and not yet deleted.
795 inline bool has_auxiliary_objective(int64_t id) const;
796
797 // Returns true if this id has been created and not yet deleted.
798 inline bool has_auxiliary_objective(AuxiliaryObjectiveId id) const;
799
800 // Will CHECK if has_auxiliary_objective(id) is false.
801 inline Objective auxiliary_objective(int64_t id) const;
802
803 // Will CHECK if has_auxiliary_objective(id) is false.
804 inline Objective auxiliary_objective(AuxiliaryObjectiveId id) const;
805
806 // Returns all the existing (created and not deleted) auxiliary objectives in
807 // the model in an arbitrary order.
808 std::vector<Objective> AuxiliaryObjectives() const;
809
810 // Returns all the existing (created and not deleted) auxiliary objectives in
811 // the model sorted by id.
812 std::vector<Objective> SortedAuxiliaryObjectives() const;
813
815 // Multi-objective methods
816 //
817 // This is an API for setting objective properties (for either primary or
818 // auxiliary objectives). Only linear objectives are supported through this
819 // API. To query objective properties, use the methods on `Objective`.
821
822 // Sets `objective` to be maximizing `expression`.
823 inline void Maximize(Objective objective, const LinearExpression& expression);
824 // Sets `objective` to be minimizing `expression`.
825 inline void Minimize(Objective objective, const LinearExpression& expression);
826 // Sets the objective to optimize the provided expression.
827 void SetObjective(Objective objective, const LinearExpression& expression,
828 bool is_maximize);
829
830 // Adds the provided expression terms to the objective.
831 void AddToObjective(Objective objective, const LinearExpression& expression);
832
833 // Sets the priority for an objective (lower is more important). `priority`
834 // must be nonnegative.
835 inline void set_objective_priority(Objective objective, int64_t priority);
836
837 // Setting a value to 0.0 will delete the variable from the underlying sparse
838 // representation (and has no effect if the variable is not present).
839 inline void set_objective_coefficient(Objective objective, Variable variable,
840 double value);
841
842 inline void set_objective_offset(Objective objective, double value);
843
844 inline void set_maximize(Objective objective);
845 inline void set_minimize(Objective objective);
846
847 // Prefer set_maximize() and set_minimize() above for more readable code.
848 inline void set_is_maximize(Objective objective, bool is_maximize);
849
850 // Returns a proto representation of the optimization model.
851 //
852 // See FromModelProto() to build a Model from a proto.
853 ModelProto ExportModel(bool remove_names = false) const;
854
855 // Returns a tracker that can be used to generate a ModelUpdateProto with the
856 // updates that happened since the last checkpoint. The tracker initial
857 // checkpoint corresponds to the current state of the model.
858 //
859 // The returned UpdateTracker keeps a reference to this model. See the
860 // implications in the documentation of the UpdateTracker class.
861 //
862 // Thread-safety: this method must not be used while modifying the model
863 // (variables, constraints, ...). The user is expected to use proper
864 // synchronization primitive to serialize changes to the model and the use of
865 // this method.
866 std::unique_ptr<UpdateTracker> NewUpdateTracker();
867
868 // Apply the provided update to this model. Returns a failure if the update is
869 // not valid.
870 //
871 // As with FromModelProto(), duplicated names are ignored.
872 //
873 // Note that it takes O(num_variables + num_constraints) extra memory and
874 // execution to apply the update (due to the need to build a ModelSummary). So
875 // even a small update will have some cost.
876 absl::Status ApplyUpdateProto(const ModelUpdateProto& update_proto);
877
878 // TODO(user): expose a way to efficiently iterate through the nonzeros of
879 // the linear constraint matrix.
880
881 // Returns a pointer to the underlying model storage.
882 //
883 // This API is for internal use only and regular users should have no need for
884 // it.
885 const ModelStorage* storage() const { return storage_.get(); }
886
887 // Returns a pointer to the underlying model storage.
888 //
889 // This API is for internal use only and regular users should have no need for
890 // it.
891 ModelStorage* storage() { return storage_.get(); }
892
893 // Prints the objective, the constraints and the variables of the model over
894 // several lines in a human-readable way. Includes a new line at the end of
895 // the model.
896 friend std::ostream& operator<<(std::ostream& ostr, const Model& model);
897
898 private:
899 // Asserts (with CHECK) that the input pointer is either nullptr or that it
900 // points to the same model as storage_.
901 //
902 // Use CheckModel() when nullptr is not a valid value.
903 inline void CheckOptionalModel(const ModelStorage* other_storage) const;
904
905 // Asserts (with CHECK) that the input pointer is the same as storage_.
906 //
907 // Use CheckOptionalModel() if nullptr is a valid value too.
908 inline void CheckModel(const ModelStorage* other_storage) const;
909
910 // Don't use storage_ directly; prefer to use storage() so that const member
911 // functions don't have modifying access to the underlying storage.
912 //
913 // We use a shared_ptr here so that the UpdateTracker class can have a
914 // weak_ptr on the ModelStorage. This let it have a destructor that don't
915 // crash when called after the destruction of the associated Model.
916 const std::shared_ptr<ModelStorage> storage_;
917};
918
920// Inline function implementations
922
923// ------------------------------- Variables -----------------------------------
924
925const std::string& Model::name() const { return storage()->name(); }
926
927Variable Model::AddVariable(const absl::string_view name) {
928 return Variable(storage(), storage()->AddVariable(name));
929}
930Variable Model::AddVariable(const double lower_bound, const double upper_bound,
931 const bool is_integer,
932 const absl::string_view name) {
933 return Variable(storage(), storage()->AddVariable(lower_bound, upper_bound,
934 is_integer, name));
935}
936
937Variable Model::AddBinaryVariable(const absl::string_view name) {
938 return AddVariable(0.0, 1.0, true, name);
939}
940
941Variable Model::AddContinuousVariable(const double lower_bound,
942 const double upper_bound,
943 const absl::string_view name) {
944 return AddVariable(lower_bound, upper_bound, false, name);
945}
946
948 const double upper_bound,
949 const absl::string_view name) {
950 return AddVariable(lower_bound, upper_bound, true, name);
951}
953void Model::DeleteVariable(const Variable variable) {
954 CheckModel(variable.storage());
955 storage()->DeleteVariable(variable.typed_id());
956}
957
958int Model::num_variables() const { return storage()->num_variables(); }
960int64_t Model::next_variable_id() const {
961 return storage()->next_variable_id().value();
962}
964bool Model::has_variable(const int64_t id) const {
965 return has_variable(VariableId(id));
966}
967
968bool Model::has_variable(const VariableId id) const {
969 return storage()->has_variable(id);
970}
971
972Variable Model::variable(const int64_t id) const {
973 return variable(VariableId(id));
974}
976Variable Model::variable(const VariableId id) const {
977 CHECK(has_variable(id)) << "No variable with id: " << id.value();
978 return Variable(storage(), id);
979}
981const std::string& Model::name(const Variable variable) const {
982 CheckModel(variable.storage());
983 return storage()->variable_name(variable.typed_id());
984}
985
986void Model::set_lower_bound(const Variable variable, double lower_bound) {
987 CheckModel(variable.storage());
988 storage()->set_variable_lower_bound(variable.typed_id(), lower_bound);
989}
991double Model::lower_bound(const Variable variable) const {
992 CheckModel(variable.storage());
993 return storage()->variable_lower_bound(variable.typed_id());
995
996void Model::set_upper_bound(const Variable variable, double upper_bound) {
997 CheckModel(variable.storage());
998 storage()->set_variable_upper_bound(variable.typed_id(), upper_bound);
999}
1000
1001double Model::upper_bound(const Variable variable) const {
1002 CheckModel(variable.storage());
1003 return storage()->variable_upper_bound(variable.typed_id());
1004}
1005
1006void Model::set_is_integer(const Variable variable, bool is_integer) {
1007 CheckModel(variable.storage());
1008 storage()->set_variable_is_integer(variable.typed_id(), is_integer);
1009}
1010
1011void Model::set_integer(const Variable variable) {
1012 set_is_integer(variable, true);
1014
1015void Model::set_continuous(const Variable variable) {
1016 set_is_integer(variable, false);
1017}
1019bool Model::is_integer(const Variable variable) const {
1020 CheckModel(variable.storage());
1021 return storage()->is_variable_integer(variable.typed_id());
1022}
1024// -------------------------- Linear constraints -------------------------------
1025
1027 Variable variable) const {
1028 // TODO(b/239810718): use << for Variable once it does not CHECK.
1029 if (storage_.get() != variable.storage()) {
1031 << "variable with id " << variable.id()
1032 << " is from a different model";
1036 << "variable with id " << variable.id()
1037 << " is not found in this model (it was probably deleted)";
1038 }
1039 return absl::OkStatus();
1040}
1046 const double upper_bound,
1047 const absl::string_view name) {
1050}
1051
1052void Model::DeleteLinearConstraint(const LinearConstraint constraint) {
1053 CheckModel(constraint.storage());
1054 storage()->DeleteLinearConstraint(constraint.typed_id());
1055}
1056
1058 return storage()->num_linear_constraints();
1059}
1060
1061int64_t Model::next_linear_constraint_id() const {
1062 return storage()->next_linear_constraint_id().value();
1063}
1065bool Model::has_linear_constraint(const int64_t id) const {
1066 return has_linear_constraint(LinearConstraintId(id));
1068
1069bool Model::has_linear_constraint(const LinearConstraintId id) const {
1070 return storage()->has_linear_constraint(id);
1071}
1072
1073LinearConstraint Model::linear_constraint(const int64_t id) const {
1074 return linear_constraint(LinearConstraintId(id));
1075}
1076
1077LinearConstraint Model::linear_constraint(const LinearConstraintId id) const {
1078 CHECK(has_linear_constraint(id))
1079 << "No linear constraint with id: " << id.value();
1080 return LinearConstraint(storage(), id);
1081}
1082
1083const std::string& Model::name(const LinearConstraint constraint) const {
1084 CheckModel(constraint.storage());
1085 return storage()->linear_constraint_name(constraint.typed_id());
1086}
1088void Model::set_lower_bound(const LinearConstraint constraint,
1089 double lower_bound) {
1090 CheckModel(constraint.storage());
1091 storage()->set_linear_constraint_lower_bound(constraint.typed_id(),
1092 lower_bound);
1093}
1094
1095double Model::lower_bound(const LinearConstraint constraint) const {
1096 CheckModel(constraint.storage());
1097 return storage()->linear_constraint_lower_bound(constraint.typed_id());
1098}
1100void Model::set_upper_bound(const LinearConstraint constraint,
1101 const double upper_bound) {
1102 CheckModel(constraint.storage());
1103 storage()->set_linear_constraint_upper_bound(constraint.typed_id(),
1104 upper_bound);
1106
1107double Model::upper_bound(const LinearConstraint constraint) const {
1108 CheckModel(constraint.storage());
1109 return storage()->linear_constraint_upper_bound(constraint.typed_id());
1111
1113 LinearConstraint linear_constraint) const {
1114 // TODO(b/239810718): use << for LinearConstraint once it does not CHECK.
1115 if (storage_.get() != linear_constraint.storage()) {
1117 << "linear constraint with id " << linear_constraint.id()
1118 << " is from a different model";
1119 }
1122 << "linear constraint with id " << linear_constraint.id()
1123 << " is not found in this model (it was probably deleted)";
1124 }
1125 return absl::OkStatus();
1126}
1127
1128void Model::set_coefficient(const LinearConstraint constraint,
1129 const Variable variable, const double value) {
1130 CheckModel(constraint.storage());
1131 CheckModel(variable.storage());
1132 storage()->set_linear_constraint_coefficient(constraint.typed_id(),
1135
1136double Model::coefficient(const LinearConstraint constraint,
1137 const Variable variable) const {
1138 CheckModel(constraint.storage());
1139 CheckModel(variable.storage());
1140 return storage()->linear_constraint_coefficient(constraint.typed_id(),
1141 variable.typed_id());
1142}
1143
1144bool Model::is_coefficient_nonzero(const LinearConstraint constraint,
1145 const Variable variable) const {
1146 CheckModel(constraint.storage());
1147 CheckModel(variable.storage());
1148 return storage()->is_linear_constraint_coefficient_nonzero(
1149 constraint.typed_id(), variable.typed_id());
1151
1152// ------------------------- Quadratic constraints -----------------------------
1153
1155 CheckModel(constraint.storage());
1156 storage()->DeleteAtomicConstraint(constraint.typed_id());
1157}
1159int64_t Model::num_quadratic_constraints() const {
1160 return storage()->num_constraints<QuadraticConstraintId>();
1161}
1162
1164 return storage()->next_constraint_id<QuadraticConstraintId>().value();
1165}
1167bool Model::has_quadratic_constraint(const int64_t id) const {
1168 return has_quadratic_constraint(QuadraticConstraintId(id));
1169}
1170
1171bool Model::has_quadratic_constraint(const QuadraticConstraintId id) const {
1172 return storage()->has_constraint(id);
1173}
1174
1175QuadraticConstraint Model::quadratic_constraint(const int64_t id) const {
1176 return quadratic_constraint(QuadraticConstraintId(id));
1177}
1178
1180 const QuadraticConstraintId id) const {
1182 << "No quadratic constraint with id: " << id.value();
1183 return QuadraticConstraint(storage(), id);
1184}
1186std::vector<QuadraticConstraint> Model::QuadraticConstraints() const {
1188}
1190std::vector<QuadraticConstraint> Model::SortedQuadraticConstraints() const {
1192}
1194// --------------------- Second-order cone constraints -------------------------
1195
1197 const SecondOrderConeConstraint constraint) {
1198 CheckModel(constraint.storage());
1199 storage()->DeleteAtomicConstraint(constraint.typed_id());
1200}
1203 return storage()->num_constraints<SecondOrderConeConstraintId>();
1204}
1205
1207 return storage()->next_constraint_id<SecondOrderConeConstraintId>().value();
1209
1210bool Model::has_second_order_cone_constraint(const int64_t id) const {
1211 return has_second_order_cone_constraint(SecondOrderConeConstraintId(id));
1215 const SecondOrderConeConstraintId id) const {
1216 return storage()->has_constraint(id);
1217}
1220 const int64_t id) const {
1221 return second_order_cone_constraint(SecondOrderConeConstraintId(id));
1222}
1223
1225 const SecondOrderConeConstraintId id) const {
1227 << "No second-order cone constraint with id: " << id.value();
1229}
1230
1231std::vector<SecondOrderConeConstraint> Model::SecondOrderConeConstraints()
1235
1236std::vector<SecondOrderConeConstraint> Model::SortedSecondOrderConeConstraints()
1237 const {
1239}
1240
1241// --------------------------- SOS1 constraints --------------------------------
1242
1243void Model::DeleteSos1Constraint(const Sos1Constraint constraint) {
1244 CheckModel(constraint.storage());
1245 storage()->DeleteAtomicConstraint(constraint.typed_id());
1247
1248int64_t Model::num_sos1_constraints() const {
1249 return storage()->num_constraints<Sos1ConstraintId>();
1250}
1251
1252int64_t Model::next_sos1_constraint_id() const {
1253 return storage()->next_constraint_id<Sos1ConstraintId>().value();
1254}
1255
1256bool Model::has_sos1_constraint(const int64_t id) const {
1257 return has_sos1_constraint(Sos1ConstraintId(id));
1259
1260bool Model::has_sos1_constraint(const Sos1ConstraintId id) const {
1261 return storage()->has_constraint(id);
1262}
1263
1264Sos1Constraint Model::sos1_constraint(const int64_t id) const {
1265 return sos1_constraint(Sos1ConstraintId(id));
1266}
1267
1268Sos1Constraint Model::sos1_constraint(const Sos1ConstraintId id) const {
1269 CHECK(has_sos1_constraint(id))
1270 << "No SOS1 constraint with id: " << id.value();
1271 return Sos1Constraint(storage(), id);
1272}
1273
1274std::vector<Sos1Constraint> Model::Sos1Constraints() const {
1276}
1277
1278std::vector<Sos1Constraint> Model::SortedSos1Constraints() const {
1280}
1281
1282// --------------------------- SOS2 constraints --------------------------------
1283
1284void Model::DeleteSos2Constraint(const Sos2Constraint constraint) {
1285 CheckModel(constraint.storage());
1286 storage()->DeleteAtomicConstraint(constraint.typed_id());
1287}
1288
1289int64_t Model::num_sos2_constraints() const {
1290 return storage()->num_constraints<Sos2ConstraintId>();
1291}
1292
1293int64_t Model::next_sos2_constraint_id() const {
1294 return storage()->next_constraint_id<Sos2ConstraintId>().value();
1295}
1297bool Model::has_sos2_constraint(const int64_t id) const {
1298 return has_sos2_constraint(Sos2ConstraintId(id));
1299}
1301bool Model::has_sos2_constraint(const Sos2ConstraintId id) const {
1302 return storage()->has_constraint(id);
1303}
1304
1305Sos2Constraint Model::sos2_constraint(const int64_t id) const {
1306 return sos2_constraint(Sos2ConstraintId(id));
1307}
1308
1309Sos2Constraint Model::sos2_constraint(const Sos2ConstraintId id) const {
1310 CHECK(has_sos2_constraint(id))
1311 << "No SOS2 constraint with id: " << id.value();
1312 return Sos2Constraint(storage(), id);
1313}
1314
1315std::vector<Sos2Constraint> Model::Sos2Constraints() const {
1317}
1318
1319std::vector<Sos2Constraint> Model::SortedSos2Constraints() const {
1321}
1322
1323// --------------------------- Indicator constraints ---------------------------
1324
1326 CheckModel(constraint.storage());
1327 storage()->DeleteAtomicConstraint(constraint.typed_id());
1328}
1329
1330int64_t Model::num_indicator_constraints() const {
1331 return storage()->num_constraints<IndicatorConstraintId>();
1332}
1333
1335 return storage()->next_constraint_id<IndicatorConstraintId>().value();
1336}
1338bool Model::has_indicator_constraint(const int64_t id) const {
1339 return has_indicator_constraint(IndicatorConstraintId(id));
1340}
1342bool Model::has_indicator_constraint(const IndicatorConstraintId id) const {
1343 return storage()->has_constraint(id);
1344}
1345
1346IndicatorConstraint Model::indicator_constraint(const int64_t id) const {
1347 return indicator_constraint(IndicatorConstraintId(id));
1348}
1349
1351 const IndicatorConstraintId id) const {
1353 << "No indicator constraint with id: " << id.value();
1354 return IndicatorConstraint(storage(), id);
1355}
1357std::vector<IndicatorConstraint> Model::IndicatorConstraints() const {
1359}
1361std::vector<IndicatorConstraint> Model::SortedIndicatorConstraints() const {
1363}
1365// ------------------------------- Objective -----------------------------------
1366
1367void Model::Maximize(const double objective) {
1368 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1369}
1370void Model::Maximize(const Variable objective) {
1371 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1373void Model::Maximize(const LinearTerm objective) {
1374 SetObjective(LinearExpression(objective), /*is_maximize=*/true);
1375}
1376void Model::Maximize(const LinearExpression& objective) {
1377 SetObjective(objective, /*is_maximize=*/true);
1378}
1379void Model::Maximize(const QuadraticExpression& objective) {
1380 SetObjective(objective, /*is_maximize=*/true);
1381}
1382
1383void Model::Minimize(const double objective) {
1384 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1385}
1386void Model::Minimize(const Variable objective) {
1387 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1388}
1389void Model::Minimize(const LinearTerm objective) {
1390 SetObjective(LinearExpression(objective), /*is_maximize=*/false);
1391}
1392void Model::Minimize(const LinearExpression& objective) {
1393 SetObjective(objective, /*is_maximize=*/false);
1394}
1395void Model::Minimize(const QuadraticExpression& objective) {
1396 SetObjective(objective, /*is_maximize=*/false);
1397}
1399void Model::SetObjective(const double objective, const bool is_maximize) {
1400 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1402void Model::SetObjective(const Variable objective, const bool is_maximize) {
1403 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1404}
1405void Model::SetObjective(const LinearTerm objective, const bool is_maximize) {
1406 SetObjective(LinearExpression(objective), /*is_maximize=*/is_maximize);
1407}
1409void Model::AddToObjective(const double objective) {
1410 AddToObjective(LinearExpression(objective));
1412void Model::AddToObjective(const Variable objective) {
1413 AddToObjective(LinearExpression(objective));
1415void Model::AddToObjective(const LinearTerm objective) {
1416 AddToObjective(LinearExpression(objective));
1420 return Objective::Primary(storage());
1422
1423double Model::objective_coefficient(const Variable variable) const {
1424 CheckModel(variable.storage());
1425 return storage()->linear_objective_coefficient(kPrimaryObjectiveId,
1426 variable.typed_id());
1428
1429double Model::objective_coefficient(const Variable first_variable,
1430 const Variable second_variable) const {
1431 CheckModel(first_variable.storage());
1432 CheckModel(second_variable.storage());
1433 return storage()->quadratic_objective_coefficient(kPrimaryObjectiveId,
1434 first_variable.typed_id(),
1435 second_variable.typed_id());
1436}
1438void Model::set_objective_coefficient(const Variable variable,
1439 const double value) {
1440 CheckModel(variable.storage());
1441 storage()->set_linear_objective_coefficient(kPrimaryObjectiveId,
1443}
1444
1446 const Variable second_variable,
1447 const double value) {
1448 CheckModel(first_variable.storage());
1449 CheckModel(second_variable.storage());
1450 storage()->set_quadratic_objective_coefficient(
1452 second_variable.typed_id(), value);
1453}
1454
1456 storage()->clear_objective(kPrimaryObjectiveId);
1457}
1458
1459bool Model::is_objective_coefficient_nonzero(const Variable variable) const {
1460 CheckModel(variable.storage());
1461 return storage()->is_linear_objective_coefficient_nonzero(
1463}
1464
1466 const Variable first_variable, const Variable second_variable) const {
1467 CheckModel(first_variable.storage());
1468 CheckModel(second_variable.storage());
1469 return storage()->is_quadratic_objective_coefficient_nonzero(
1470 kPrimaryObjectiveId, first_variable.typed_id(),
1471 second_variable.typed_id());
1472}
1473
1474double Model::objective_offset() const {
1475 return storage()->objective_offset(kPrimaryObjectiveId);
1476}
1478void Model::set_objective_offset(const double value) {
1479 storage()->set_objective_offset(kPrimaryObjectiveId, value);
1480}
1482bool Model::is_maximize() const {
1483 return storage()->is_maximize(kPrimaryObjectiveId);
1484}
1485
1486void Model::set_maximize() { storage()->set_maximize(kPrimaryObjectiveId); }
1488void Model::set_minimize() { storage()->set_minimize(kPrimaryObjectiveId); }
1489
1490void Model::set_is_maximize(const bool is_maximize) {
1491 storage()->set_is_maximize(kPrimaryObjectiveId, is_maximize);
1492}
1493
1494// -------------------------- Auxiliary objectives -----------------------------
1495
1497 const absl::string_view name) {
1499 storage()->AddAuxiliaryObjective(priority, name));
1503 const bool is_maximize,
1504 const int64_t priority,
1505 const absl::string_view name) {
1506 const Objective obj = AddAuxiliaryObjective(priority, name);
1507 SetObjective(obj, expression, is_maximize);
1508 return obj;
1509}
1512 const int64_t priority,
1513 const absl::string_view name) {
1514 return AddAuxiliaryObjective(expression, /*is_maximize=*/true, priority,
1515 name);
1516}
1517
1519 const int64_t priority,
1520 const absl::string_view name) {
1521 return AddAuxiliaryObjective(expression, /*is_maximize=*/false, priority,
1522 name);
1523}
1525void Model::DeleteAuxiliaryObjective(const Objective objective) {
1526 CheckModel(objective.storage());
1527 CHECK(!objective.is_primary()) << "cannot delete primary objective";
1528 const AuxiliaryObjectiveId id = *objective.typed_id();
1529 CHECK(storage()->has_auxiliary_objective(id))
1530 << "cannot delete unrecognized auxiliary objective id: " << id;
1531 storage()->DeleteAuxiliaryObjective(id);
1532}
1534int64_t Model::num_auxiliary_objectives() const {
1535 return storage()->num_auxiliary_objectives();
1536}
1537
1538int64_t Model::next_auxiliary_objective_id() const {
1539 return storage()->next_auxiliary_objective_id().value();
1541
1542bool Model::has_auxiliary_objective(const int64_t id) const {
1543 return has_auxiliary_objective(AuxiliaryObjectiveId(id));
1544}
1545
1546bool Model::has_auxiliary_objective(const AuxiliaryObjectiveId id) const {
1547 return storage()->has_auxiliary_objective(id);
1548}
1549
1550Objective Model::auxiliary_objective(const int64_t id) const {
1551 return auxiliary_objective(AuxiliaryObjectiveId(id));
1552}
1553
1554Objective Model::auxiliary_objective(const AuxiliaryObjectiveId id) const {
1555 CHECK(has_auxiliary_objective(id))
1556 << "unrecognized auxiliary objective id: " << id;
1557 return Objective::Auxiliary(storage(), id);
1558}
1559
1560// ---------------------------- Multi-objective --------------------------------
1561
1562void Model::Maximize(const Objective objective,
1563 const LinearExpression& expression) {
1564 SetObjective(objective, expression, /*is_maximize=*/true);
1565}
1566
1567void Model::Minimize(const Objective objective,
1568 const LinearExpression& expression) {
1569 SetObjective(objective, expression, /*is_maximize=*/false);
1570}
1571
1573 const int64_t priority) {
1574 CheckModel(objective.storage());
1575 storage()->set_objective_priority(objective.typed_id(), priority);
1577
1578void Model::set_objective_coefficient(const Objective objective,
1579 const Variable variable,
1580 const double value) {
1581 CheckModel(objective.storage());
1582 CheckModel(variable.storage());
1583 storage()->set_linear_objective_coefficient(objective.typed_id(),
1585}
1586
1587void Model::set_objective_offset(const Objective objective,
1588 const double value) {
1589 CheckModel(objective.storage());
1590 storage()->set_objective_offset(objective.typed_id(), value);
1591}
1592
1593void Model::set_maximize(const Objective objective) {
1594 set_is_maximize(objective, /*is_maximize=*/true);
1595}
1596
1597void Model::set_minimize(const Objective objective) {
1598 set_is_maximize(objective, /*is_maximize=*/false);
1599}
1601void Model::set_is_maximize(const Objective objective, const bool is_maximize) {
1602 CheckModel(objective.storage());
1603 storage()->set_is_maximize(objective.typed_id(), is_maximize);
1604}
1605
1606void Model::CheckOptionalModel(const ModelStorage* const other_storage) const {
1607 if (other_storage != nullptr) {
1608 CHECK_EQ(other_storage, storage())
1610 }
1611}
1612
1613void Model::CheckModel(const ModelStorage* const other_storage) const {
1614 CHECK_EQ(other_storage, storage()) << internal::kObjectsFromOtherModelStorage;
1616
1617} // namespace math_opt
1618} // namespace operations_research
1620#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:451
void set_lower_bound(Variable variable, double lower_bound)
Sets a variable lower bound.
Definition model.h:1008
std::vector< IndicatorConstraint > SortedIndicatorConstraints() const
Definition model.h:1383
Objective auxiliary_objective(int64_t id) const
Will CHECK if has_auxiliary_objective(id) is false.
Definition model.h:1572
bool has_auxiliary_objective(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1564
int64_t num_sos2_constraints() const
Definition model.h:1311
const ModelStorage * storage() const
Definition model.h:905
QuadraticConstraint AddQuadraticConstraint(const BoundedQuadraticExpression &bounded_expr, absl::string_view name="")
----------------------— Quadratic constraints --------------------------—
Definition model.cc:383
Sos2Constraint AddSos2Constraint(const std::vector< LinearExpression > &expressions, std::vector< double > weights={}, absl::string_view name="")
------------------------— SOS2 constraints -----------------------------—
Definition model.cc:464
ModelProto ExportModel(bool remove_names=false) const
Definition model.cc:275
bool has_variable(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:986
std::vector< SecondOrderConeConstraint > SecondOrderConeConstraints() const
Definition model.h:1253
int64_t next_quadratic_constraint_id() const
The returned id of the next call to AddQuadraticConstraint.
Definition model.h:1185
friend std::ostream & operator<<(std::ostream &ostr, const Model &model)
Definition model.cc:287
int64_t next_auxiliary_objective_id() const
The returned id of the next call to AddAuxiliaryObjectve.
Definition model.h:1560
int64_t next_linear_constraint_id() const
Definition model.h:1083
void DeleteSecondOrderConeConstraint(SecondOrderConeConstraint constraint)
------------------— Second-order cone constraints ----------------------—
Definition model.h:1218
static absl::StatusOr< std::unique_ptr< Model > > FromModelProto(const ModelProto &model_proto)
Definition model.cc:53
std::vector< Sos2Constraint > SortedSos2Constraints() const
Definition model.h:1341
bool is_integer(Variable variable) const
Returns the integrality of a variable.
Definition model.h:1041
void set_continuous(Variable variable)
Makes the input variable continuous.
Definition model.h:1037
bool has_sos1_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1278
std::vector< Sos1Constraint > SortedSos1Constraints() const
Definition model.h:1300
void DeleteQuadraticConstraint(QuadraticConstraint constraint)
----------------------— Quadratic constraints --------------------------—
Definition model.h:1176
std::vector< QuadraticConstraint > SortedQuadraticConstraints() const
Definition model.h:1212
void set_coefficient(LinearConstraint constraint, Variable variable, double value)
Definition model.h:1150
double lower_bound(Variable variable) const
Returns a variable lower bound.
Definition model.h:1013
SecondOrderConeConstraint AddSecondOrderConeConstraint(absl::Span< const LinearExpression > arguments_to_norm, const LinearExpression &upper_bound, absl::string_view name="")
------------------— Second-order cone constraints ----------------------—
Definition model.cc:410
std::vector< SecondOrderConeConstraint > SortedSecondOrderConeConstraints() const
Definition model.h:1258
SecondOrderConeConstraint second_order_cone_constraint(int64_t id) const
Will CHECK if has_second_order_cone_constraint(id) is false.
Definition model.h:1241
int64_t next_indicator_constraint_id() const
The returned id of the next call to AddIndicatorConstraint.
Definition model.h:1356
std::vector< Objective > AuxiliaryObjectives() const
Definition model.cc:233
int64_t next_second_order_cone_constraint_id() const
The returned id of the next call to AddSecondOrderConeConstraint.
Definition model.h:1228
int64_t num_second_order_cone_constraints() const
Definition model.h:1224
std::unique_ptr< UpdateTracker > NewUpdateTracker()
Definition model.cc:279
std::vector< LinearConstraint > SortedLinearConstraints() const
Definition model.cc:134
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:1540
bool has_sos2_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1319
void Maximize(double objective)
Sets the objective to maximize the provided expression.
Definition model.h:1389
std::vector< Sos1Constraint > Sos1Constraints() const
Definition model.h:1296
absl::Status ValidateExistingLinearConstraintOfThisModel(LinearConstraint linear_constraint) const
Definition model.h:1134
void set_is_maximize(bool is_maximize)
Prefer set_maximize() and set_minimize() above for more readable code.
Definition model.h:1512
std::unique_ptr< Model > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
Definition model.cc:66
int64_t num_sos1_constraints() const
Definition model.h:1270
bool has_indicator_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1360
bool has_quadratic_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1189
Variable variable(int64_t id) const
Will CHECK if has_variable(id) is false.
Definition model.h:994
QuadraticExpression ObjectiveAsQuadraticExpression() const
Definition model.cc:219
Model & operator=(const Model &)=delete
void AddToObjective(double objective)
Adds the provided expression terms to the objective.
Definition model.h:1431
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:952
Objective AddAuxiliaryObjective(int64_t priority, absl::string_view name={})
Adds an empty (== 0) auxiliary minimization objective to the model.
Definition model.h:1518
bool has_linear_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1087
void DeleteAuxiliaryObjective(Objective objective)
Definition model.h:1547
void set_objective_priority(Objective objective, int64_t priority)
Definition model.h:1594
void set_objective_offset(double value)
Definition model.h:1500
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
Definition model.cc:283
int64_t next_sos2_constraint_id() const
The returned id of the next call to AddSos2Constraint.
Definition model.h:1315
std::vector< LinearConstraint > ColumnNonzeros(Variable variable) const
Definition model.cc:103
void DeleteLinearConstraint(LinearConstraint constraint)
Definition model.h:1074
int64_t num_indicator_constraints() const
Definition model.h:1352
std::vector< QuadraticConstraint > QuadraticConstraints() const
Definition model.h:1208
void DeleteSos1Constraint(Sos1Constraint constraint)
------------------------— SOS1 constraints -----------------------------—
Definition model.h:1265
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:1232
void Minimize(double objective)
Sets the objective to minimize the provided expression.
Definition model.h:1405
std::vector< LinearConstraint > LinearConstraints() const
Definition model.cc:125
std::vector< Objective > SortedAuxiliaryObjectives() const
Definition model.cc:242
int64_t num_auxiliary_objectives() const
Definition model.h:1556
void DeleteIndicatorConstraint(IndicatorConstraint constraint)
------------------------— Indicator constraints ------------------------—
Definition model.h:1347
Variable AddIntegerVariable(double lower_bound, double upper_bound, absl::string_view name="")
Definition model.h:969
LinearConstraint linear_constraint(int64_t id) const
Will CHECK if has_linear_constraint(id) is false.
Definition model.h:1095
void set_objective_coefficient(Variable variable, double value)
Definition model.h:1460
Variable AddBinaryVariable(absl::string_view name="")
Adds a variable to the model with domain {0, 1}.
Definition model.h:959
double upper_bound(Variable variable) const
Returns a variable upper bound.
Definition model.h:1023
std::vector< Variable > Variables() const
Definition model.cc:85
void DeleteSos2Constraint(Sos2Constraint constraint)
------------------------— SOS2 constraints -----------------------------—
Definition model.h:1306
bool is_objective_coefficient_nonzero(Variable variable) const
Definition model.h:1481
double coefficient(LinearConstraint constraint, Variable variable) const
Returns 0.0 if the variable is not used in the constraint.
Definition model.h:1158
void set_upper_bound(Variable variable, double upper_bound)
Sets a variable upper bound.
Definition model.h:1018
std::vector< Sos2Constraint > Sos2Constraints() const
Definition model.h:1337
int64_t next_sos1_constraint_id() const
The returned id of the next call to AddSos1Constraint.
Definition model.h:1274
std::vector< Variable > SortedVariables() const
Definition model.cc:94
void set_integer(Variable variable)
Makes the input variable integer.
Definition model.h:1033
Model(absl::string_view name="")
Creates an empty minimization problem.
Definition model.cc:60
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:963
std::vector< IndicatorConstraint > IndicatorConstraints() const
Definition model.h:1379
double objective_coefficient(Variable variable) const
Returns 0.0 if this variable has no linear objective coefficient.
Definition model.h:1445
void DeleteVariable(Variable variable)
Definition model.h:975
absl::Status ValidateExistingVariableOfThisModel(Variable variable) const
-----------------------— Linear constraints ----------------------------—
Definition model.h:1048
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:1533
Objective primary_objective() const
Definition model.h:1441
IndicatorConstraint indicator_constraint(int64_t id) const
Will CHECK if has_indicator_constraint(id) is false.
Definition model.h:1368
LinearExpression ObjectiveAsLinearExpression() const
Definition model.cc:207
Sos2Constraint sos2_constraint(int64_t id) const
Will CHECK if has_sos2_constraint(id) is false.
Definition model.h:1327
int64_t num_quadratic_constraints() const
Definition model.h:1181
bool is_coefficient_nonzero(LinearConstraint constraint, Variable variable) const
Definition model.h:1166
QuadraticConstraint quadratic_constraint(int64_t id) const
Will CHECK if has_quadratic_constraint(id) is false.
Definition model.h:1197
void SetObjective(double objective, bool is_maximize)
Sets the objective to optimize the provided expression.
Definition model.h:1421
IndicatorConstraint AddIndicatorConstraint(Variable indicator_variable, const BoundedLinearExpression &implied_constraint, bool activate_on_zero=false, absl::string_view name={})
------------------------— Indicator constraints ------------------------—
Definition model.cc:477
void set_is_integer(Variable variable, bool is_integer)
Sets the integrality of a variable.
Definition model.h:1028
const std::string & name() const
----------------------------— Variables --------------------------------—
Definition model.h:947
LinearConstraint AddLinearConstraint(absl::string_view name="")
Adds a linear constraint to the model with bounds [-inf, +inf].
Definition model.h:1064
std::vector< Variable > RowNonzeros(LinearConstraint constraint) const
Definition model.cc:114
Sos1Constraint sos1_constraint(int64_t id) const
Will CHECK if has_sos1_constraint(id) is false.
Definition model.h:1286
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
const std::string name
A name for logging purposes.
int64_t value
double upper_bound
double lower_bound
GRBmodel * model
constexpr absl::string_view kObjectsFromOtherModelStorage
Definition key_types.h:156
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()
int64_t coefficient
A LinearExpression with upper and lower bounds.
A QuadraticExpression with upper and lower bounds.
A term in an sum of variables multiplied by coefficients.