Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
linear_solver.proto
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// Linear Programming Protocol Buffers.
15//
16// The protocol buffers below make it possible to store and transfer the
17// representation of Linear and Mixed-Integer Programs.
18//
19// A Linear Program (LP) is a mathematical optimization model with a linear
20// objective function, and linear equality and inequality constraints.
21// The goal is to achieve the best outcome (such as maximum profit or lowest
22// cost) by modeling the real-world problem at hand using linear functions.
23// In a Mixed Integer Program (MIP), some variables may also be constrained to
24// take integer values.
25//
26// Check ./linear_solver.h and Wikipedia for more detail:
27// http://en.wikipedia.org/wiki/Linear_programming
28
29syntax = "proto2";
30
31option java_package = "com.google.ortools.linearsolver";
32option java_multiple_files = true;
33
34import "ortools/util/optional_boolean.proto";
35
36package operations_research;
37
38// A variable is always constrained in the form:
39// lower_bound <= x <= upper_bound
40// where lower_bound and upper_bound:
41// - Can form a singleton: x = constant = lower_bound = upper_bound.
42// - Can form a finite interval: lower_bound <= x <= upper_bound. (x is boxed.)
43// - Can form a semi-infinite interval.
44// - lower_bound = -infinity: x <= upper_bound.
45// - upper_bound = +infinity: x >= lower_bound.
46// - Can form the infinite interval: lower_bound = -infinity and
47// upper_bound = +infinity, x is free.
48// MPVariableProto furthermore stores:
49// - The coefficient of the variable in the objective.
50// - Whether the variable is integer.
51message MPVariableProto {
52 // lower_bound must be <= upper_bound.
53 optional double lower_bound = 1 [default = -inf];
54 optional double upper_bound = 2 [default = inf];
55
56 // The coefficient of the variable in the objective. Must be finite.
57 optional double objective_coefficient = 3 [default = 0.0];
58
59 // True if the variable is constrained to be integer.
60 // Ignored if MPModelProto::solver_type is *LINEAR_PROGRAMMING*.
61 optional bool is_integer = 4 [default = false];
62
63 // The name of the variable.
64 optional string name = 5 [default = ""];
65
66 optional int32 branching_priority = 6 [default = 0];
67}
68
69// A linear constraint is always of the form:
70// lower_bound <= sum of linear term elements <= upper_bound,
71// where lower_bound and upper_bound:
72// - Can form a singleton: lower_bound == upper_bound. The constraint is an
73// equation.
74// - Can form a finite interval [lower_bound, upper_bound]. The constraint is
75// both lower- and upper-bounded, i.e. "boxed".
76// - Can form a semi-infinite interval. lower_bound = -infinity: the constraint
77// is upper-bounded. upper_bound = +infinity: the constraint is lower-bounded.
78// - Can form the infinite interval: lower_bound = -infinity and
79// upper_bound = +infinity. The constraint is free.
80message MPConstraintProto {
81 // var_index[i] is the variable index (w.r.t. to "variable" field of
82 // MPModelProto) of the i-th linear term involved in this constraint, and
83 // coefficient[i] is its coefficient. Only the terms with non-zero
84 // coefficients need to appear. var_index may not contain duplicates.
85 repeated int32 var_index = 6 [packed = true];
86 repeated double coefficient = 7 [packed = true]; // Must be finite.
87
88 // lower_bound must be <= upper_bound.
89 optional double lower_bound = 2 [default = -inf];
90 optional double upper_bound = 3 [default = inf];
91
92 // The name of the constraint.
93 optional string name = 4 [default = ""];
94
95 // [Advanced usage: do not use this if you don't know what you're doing.]
96 // A lazy constraint is handled differently by the core solving engine, but
97 // it does not change the result. It may or may not impact the performance.
98 // For more info see: http://tinyurl.com/lazy-constraints.
99 optional bool is_lazy = 5 [default = false];
100}
101
102// General constraints. See each individual proto type for more information.
103message MPGeneralConstraintProto {
104 // The name of the constraint.
105 optional string name = 1 [default = ""];
106
107 oneof general_constraint {
108 MPIndicatorConstraint indicator_constraint = 2;
109 MPSosConstraint sos_constraint = 3;
110 MPQuadraticConstraint quadratic_constraint = 4;
111 MPAbsConstraint abs_constraint = 5;
112 // All variables in "and" constraints must be Boolean.
113 // resultant_var = and(var_1, var_2... var_n)
114 MPArrayConstraint and_constraint = 6;
115 // All variables in "or" constraints must be Boolean.
116 // resultant_var = or(var_1, var_2... var_n)
117 MPArrayConstraint or_constraint = 7;
118 // resultant_var = min(var_1, var_2, ..., constant)
119 MPArrayWithConstantConstraint min_constraint = 8;
120 // resultant_var = max(var_1, var_2, ..., constant)
121 MPArrayWithConstantConstraint max_constraint = 9;
122 }
123}
124
125// Indicator constraints encode the activation or deactivation of linear
126// constraints given the value of one Boolean variable in the model. For
127// example:
128// y = 0 => 2 * x1 + 3 * x2 >= 42
129// The 2 * x1 + 3 * x2 >= 42 constraint is only active if the variable y is
130// equal to 0.
131// As of 2019/04, only SCIP, CP-SAT and Gurobi support this constraint type.
132message MPIndicatorConstraint {
133 // Variable index (w.r.t. the "variable" field of MPModelProto) of the Boolean
134 // variable used as indicator.
135 optional int32 var_index = 1;
136
137 // Value the above variable should take. Must be 0 or 1.
138 optional int32 var_value = 2;
139
140 // The constraint activated by the indicator variable.
141 optional MPConstraintProto constraint = 3;
142}
143
144// Special Ordered Set (SOS) constraints of type 1 or 2.
145// See https://en.wikipedia.org/wiki/Special_ordered_set
146// As of 2019/04, only SCIP and Gurobi support this constraint type.
147message MPSosConstraint {
148 enum Type {
149 // At most one variable in `var_index` must be non-zero.
150 SOS1_DEFAULT = 0;
151 // At most two consecutive variables from `var_index` can be non-zero (i.e.
152 // for some i, var_index[i] and var_index[i+1]). See
153 // https://en.wikipedia.org/wiki/Special_ordered_set#Types_of_SOS
154 SOS2 = 1;
155 }
156 optional Type type = 1 [default = SOS1_DEFAULT];
157
158 // Variable index (w.r.t. the "variable" field of MPModelProto) of the
159 // variables in the SOS.
160 repeated int32 var_index = 2;
161
162 // Optional: SOS weights. If non-empty, must be of the same size as
163 // "var_index", and strictly increasing. If empty and required by the
164 // underlying solver, the 1..n sequence will be given as weights.
165 // SUBTLE: The weights can help the solver make branch-and-bound decisions
166 // that fit the underlying optimization model: after each LP relaxation, it
167 // will compute the "average weight" of the SOS variables, weighted by value
168 // (this is confusing: here we're using the values as weights), and the binary
169 // branch decision will be: is the non-zero variable above or below that?
170 // (weights are strictly monotonous, so the "cutoff" average weight
171 // corresponds to a "cutoff" index in the var_index sequence).
172 repeated double weight = 3;
173}
174
175// Quadratic constraints of the form lb <= sum a_i x_i + sum b_ij x_i x_j <= ub,
176// where a, b, lb and ub are constants, and x are the model's variables.
177// Quadratic matrices that are Positive Semi-Definite, Second-Order Cones or
178// rotated Second-Order Cones are always accepted. Other forms may or may not be
179// accepted depending on the underlying solver used.
180// See https://scip.zib.de/doc/html/cons__quadratic_8h.php and
181// https://www.gurobi.com/documentation/9.0/refman/constraints.html#subsubsection:QuadraticConstraints
182message MPQuadraticConstraint {
183 // Sparse representation of linear terms in the quadratic constraint, where
184 // term i is var_index[i] * coefficient[i].
185 // `var_index` are variable indices w.r.t the "variable" field in
186 // MPModelProto, and should be unique.
187 repeated int32 var_index = 1;
188 repeated double coefficient = 2; // Must be finite.
189
190 // Sparse representation of quadratic terms in the quadratic constraint, where
191 // term i is qvar1_index[i] * qvar2_index[i] * qcoefficient[i].
192 // `qvar1_index` and `qvar2_index` are variable indices w.r.t the "variable"
193 // field in MPModelProto.
194 // `qvar1_index`, `qvar2_index` and `coefficients` must have the same size.
195 // If the same unordered pair (qvar1_index, qvar2_index) appears several
196 // times, the sum of all of the associated coefficients will be applied.
197 repeated int32 qvar1_index = 3;
198 repeated int32 qvar2_index = 4;
199 repeated double qcoefficient = 5; // Must be finite.
200
201 // lower_bound must be <= upper_bound.
202 optional double lower_bound = 6 [default = -inf];
203 optional double upper_bound = 7 [default = inf];
204}
205
206// Sets a variable's value to the absolute value of another variable.
207message MPAbsConstraint {
208 // Variable indices are relative to the "variable" field in MPModelProto.
209 // resultant_var = abs(var)
210 optional int32 var_index = 1;
211 optional int32 resultant_var_index = 2;
212}
213
214// Sets a variable's value equal to a function on a set of variables.
215message MPArrayConstraint {
216 // Variable indices are relative to the "variable" field in MPModelProto.
217 repeated int32 var_index = 1;
218 optional int32 resultant_var_index = 2;
219}
220
221// Sets a variable's value equal to a function on a set of variables and,
222// optionally, a constant.
223message MPArrayWithConstantConstraint {
224 // Variable indices are relative to the "variable" field in MPModelProto.
225 // resultant_var = f(var_1, var_2, ..., constant)
226 repeated int32 var_index = 1;
227 optional double constant = 2;
228 optional int32 resultant_var_index = 3;
229}
230
231// Quadratic part of a model's objective. Added with other objectives (such as
232// linear), this creates the model's objective function to be optimized.
233// Note: the linear part of the objective currently needs to be specified in the
234// MPVariableProto.objective_coefficient fields. If you'd rather have a
235// dedicated linear array here, talk to or-core-team@
236message MPQuadraticObjective {
237 // Sparse representation of quadratic terms in the objective function, where
238 // term i is qvar1_index[i] * qvar2_index[i] * coefficient[i].
239 // `qvar1_index` and `qvar2_index` are variable indices w.r.t the "variable"
240 // field in MPModelProto.
241 // `qvar1_index`, `qvar2_index` and `coefficients` must have the same size.
242 // If the same unordered pair (qvar1_index, qvar2_index) appears several
243 // times, the sum of all of the associated coefficients will be applied.
244 repeated int32 qvar1_index = 1;
245 repeated int32 qvar2_index = 2;
246 repeated double coefficient = 3; // Must be finite.
247}
248
249// This message encodes a partial (or full) assignment of the variables of a
250// MPModelProto problem. The indices in var_index should be unique and valid
251// variable indices of the associated problem.
252message PartialVariableAssignment {
253 repeated int32 var_index = 1 [packed = true];
254 repeated double var_value = 2 [packed = true];
255}
256
257// MPModelProto contains all the information for a Linear Programming model.
258message MPModelProto {
259 // All the variables appearing in the model.
260 repeated MPVariableProto variable = 3;
261
262 // All the constraints appearing in the model.
263 repeated MPConstraintProto constraint = 4;
264
265 // All the general constraints appearing in the model. Note that not all
266 // solvers support all types of general constraints.
267 repeated MPGeneralConstraintProto general_constraint = 7;
268
269 // True if the problem is a maximization problem. Minimize by default.
270 optional bool maximize = 1 [default = false];
271
272 // Offset for the objective function. Must be finite.
273 optional double objective_offset = 2 [default = 0.0];
274
275 // Optionally, a quadratic objective.
276 // As of 2019/06, only SCIP and Gurobi support quadratic objectives.
277 optional MPQuadraticObjective quadratic_objective = 8;
278
279 // Name of the model.
280 optional string name = 5 [default = ""];
281
282 // Solution hint.
283 //
284 // If a feasible or almost-feasible solution to the problem is already known,
285 // it may be helpful to pass it to the solver so that it can be used. A solver
286 // that supports this feature will try to use this information to create its
287 // initial feasible solution.
288 //
289 // Note that it may not always be faster to give a hint like this to the
290 // solver. There is also no guarantee that the solver will use this hint or
291 // try to return a solution "close" to this assignment in case of multiple
292 // optimal solutions.
293 optional PartialVariableAssignment solution_hint = 6;
294
295 // Annotations can be freely added by users who want to attach arbitrary
296 // payload to the model's variables or constraints.
297 message Annotation {
298 // The target of an Annotation is a single entity (e.g. a variable).
299 // Several Annotations may apply to the same entity.
300 enum TargetType {
301 VARIABLE_DEFAULT = 0;
302 CONSTRAINT = 1;
303 GENERAL_CONSTRAINT = 2;
304 }
305 optional TargetType target_type = 1;
306 // If both `target_index` and `target_name` are set, they must point to the
307 // same entity.
308 optional int32 target_index = 2; // Index in the MPModelProto.
309 optional string target_name = 3; // Alternate to index. Assumes uniqueness.
310
311 // The payload is a (key, value) string pair. Depending on the use cases,
312 // one of the two may be omitted.
313 optional string payload_key = 4;
314 optional string payload_value = 5;
315 }
316 repeated Annotation annotation = 9;
317}
318
319// To support 'unspecified' double value in proto3, the simplest is to wrap
320// any double value in a nested message (has_XXX works for message fields).
321message OptionalDouble {
322 optional double value = 1;
323}
324
325// MPSolverCommonParameters holds advanced usage parameters that apply to any of
326// the solvers we support.
327// All of the fields in this proto can have a value of unspecified. In this
328// case each inner solver will use their own safe defaults.
329// Some values won't be supported by some solvers. The behavior in that case is
330// not defined yet.
331message MPSolverCommonParameters {
332 // The solver stops if the relative MIP gap reaches this value or below.
333 // The relative MIP gap is an upper bound of the relative distance to the
334 // optimum, and it is defined as:
335 //
336 // abs(best_bound - incumbent) / abs(incumbent) [Gurobi]
337 // abs(best_bound - incumbent) / min(abs(best_bound), abs(incumbent)) [SCIP]
338 //
339 // where "incumbent" is the objective value of the best solution found so far
340 // (i.e., lowest when minimizing, highest when maximizing), and "best_bound"
341 // is the tightest bound of the objective determined so far (i.e., highest
342 // when minimizing, and lowest when maximizing). The MIP Gap is sensitive to
343 // objective offset. If the denominator is 0 the MIP Gap is INFINITY for SCIP
344 // and Gurobi. Of note, "incumbent" and "best bound" are called "primal bound"
345 // and "dual bound" in SCIP, respectively.
346 // Ask or-core-team@ for other solvers.
347 optional OptionalDouble relative_mip_gap = 1;
348
349 // Tolerance for primal feasibility of basic solutions: this is the maximum
350 // allowed error in constraint satisfiability.
351 // For SCIP this includes integrality constraints. For Gurobi it does not, you
352 // need to set the custom parameter IntFeasTol.
353 optional OptionalDouble primal_tolerance = 2;
354
355 // Tolerance for dual feasibility.
356 // For SCIP and Gurobi this is the feasibility tolerance for reduced costs in
357 // LP solution: reduced costs must all be smaller than this value in the
358 // improving direction in order for a model to be declared optimal.
359 // Not supported for other solvers.
360 optional OptionalDouble dual_tolerance = 3;
361
362 enum LPAlgorithmValues {
363 LP_ALGO_UNSPECIFIED = 0;
364 LP_ALGO_DUAL = 1; // Dual simplex.
365 LP_ALGO_PRIMAL = 2; // Primal simplex.
366 LP_ALGO_BARRIER = 3; // Barrier algorithm.
367 }
368
369 // Algorithm to solve linear programs.
370 // Ask or-core-team@ if you want to know what this does exactly.
371 optional LPAlgorithmValues lp_algorithm = 4 [default = LP_ALGO_UNSPECIFIED];
372
373 // Gurobi and SCIP enable presolve by default.
374 // Ask or-core-team@ for other solvers.
375 optional OptionalBoolean presolve = 5 [default = BOOL_UNSPECIFIED];
376
377 // Enable automatic scaling of matrix coefficients and objective. Available
378 // for Gurobi and GLOP.
379 // Ask or-core-team@ if you want more details.
380 optional OptionalBoolean scaling = 7 [default = BOOL_UNSPECIFIED];
381}
382
383// Encodes a full MPModelProto by way of referencing to a "baseline"
384// MPModelProto stored in a file, and a "delta" to apply to this model.
385message MPModelDeltaProto {
386 optional /*required*/ string baseline_model_file_path = 1;
387
388 // The variable protos listed here will override (via MergeFrom()) the ones
389 // in the baseline model: you only need to specify the fields that change.
390 // To add a new variable, add it with a new variable index (variable indices
391 // still need to span a dense integer interval).
392 // You can't "delete" a variable but you can "neutralize" it by fixing its
393 // value, setting its objective coefficient to zero, and by nullifying all
394 // the terms involving it in the constraints.
395 map<int32, MPVariableProto> variable_overrides = 2;
396
397 // Constraints can be changed (or added) in the same way as variables, see
398 // above. It's mostly like applying MergeFrom(), except that:
399 // - the "var_index" and "coefficient" fields will be overridden like a map:
400 // if a key pre-exists, we overwrite its value, otherwise we add it.
401 // - if you set the lower bound to -inf and the upper bound to +inf, thus
402 // effectively neutralizing the constraint, the solver will implicitly
403 // remove all of the constraint's terms.
404 map<int32, MPConstraintProto> constraint_overrides = 3;
405
406 // NOTE(user): We may also add more deltas, eg. objective offset.
407}
408
409// Next id: 18.
410message MPModelRequest {
411 // The model to be optimized by the server.
412 optional MPModelProto model = 1;
413
414 // The solver type, which will select a specific implementation, and will also
415 // impact the interpretation of the model (i.e. are we solving the problem
416 // as a mixed integer program or are we relaxing it as a continuous linear
417 // program?).
418 // This must remain consistent with MPSolver::OptimizationProblemType.
419 enum SolverType {
420 CLP_LINEAR_PROGRAMMING = 0;
421 GLOP_LINEAR_PROGRAMMING = 2; // Recommended default for LP models.
422 GLPK_LINEAR_PROGRAMMING = 1;
423 GUROBI_LINEAR_PROGRAMMING = 6; // Commercial, needs a valid license.
424 XPRESS_LINEAR_PROGRAMMING =
425 101; // Commercial, needs a valid license. NOLINT
426 CPLEX_LINEAR_PROGRAMMING = 10; // Commercial, needs a valid license. NOLINT
427 HIGHS_LINEAR_PROGRAMMING = 15;
428
429 SCIP_MIXED_INTEGER_PROGRAMMING = 3; // Recommended default for MIP models.
430 GLPK_MIXED_INTEGER_PROGRAMMING = 4;
431 CBC_MIXED_INTEGER_PROGRAMMING = 5;
432 GUROBI_MIXED_INTEGER_PROGRAMMING = 7; // Commercial, needs a valid license.
433 XPRESS_MIXED_INTEGER_PROGRAMMING =
434 102; // Commercial, needs a valid license. NOLINT
435 CPLEX_MIXED_INTEGER_PROGRAMMING =
436 11; // Commercial, needs a valid license. NOLINT
437 HIGHS_MIXED_INTEGER_PROGRAMMING = 16;
438 BOP_INTEGER_PROGRAMMING = 12;
439
440 // WARNING: This solver will currently interpret all variables as integer,
441 // so any solution you get will be valid, but the optimal might be far away
442 // for the real one (when you authorise non-integer value for continuous
443 // variables).
444 SAT_INTEGER_PROGRAMMING = 14; // Recommended for pure integer problems.
445
446 // In-house linear programming solver based on the primal-dual hybrid
447 // gradient method. Sometimes faster than Glop for medium-size problems and
448 // scales to much larger problems than Glop.
449 PDLP_LINEAR_PROGRAMMING = 8;
450 KNAPSACK_MIXED_INTEGER_PROGRAMMING = 13;
451 }
452 optional SolverType solver_type = 2 [default = GLOP_LINEAR_PROGRAMMING];
453
454 // Maximum time to be spent by the solver to solve 'model'. If the server is
455 // busy and the RPC's deadline_left is less than this, it will immediately
456 // give up and return an error, without even trying to solve.
457 //
458 // The client can use this to have a guarantee on how much time the
459 // solver will spend on the problem (unless it finds and proves
460 // an optimal solution more quickly).
461 //
462 // If not specified, the time limit on the solver is the RPC's deadline_left.
463 optional double solver_time_limit_seconds = 3;
464
465 // If this is set, then EnableOutput() will be set on the internal MPSolver
466 // that solves the model.
467 // WARNING: if you set this on a request to prod servers, it will be rejected
468 // and yield the RPC Application Error code MPSOLVER_SOLVER_TYPE_UNAVAILABLE.
469 optional bool enable_internal_solver_output = 4 [default = false];
470
471 // Advanced usage. Solver-specific parameters in the solver's own format,
472 // different for each solver. For example, if you use SCIP and you want to
473 // stop the solve earlier than the time limit if it reached a solution that is
474 // at most 1% away from the optimal, you can set this to "limits/gap=0.01".
475 //
476 // Note however that there is no "security" mechanism in place so it is up to
477 // the client to make sure that the given options don't make the solve
478 // non thread safe or use up too much memory for instance.
479 //
480 // If the option format is not understood by the solver, the request will be
481 // rejected and yield an RPC Application error with code
482 // MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS, unless you have set
483 // ignore_solver_specific_parameters_failure=true (in which case they are
484 // simply ignored).
485 optional string solver_specific_parameters = 5;
486 optional bool ignore_solver_specific_parameters_failure = 9 [default = false];
487
488 // Advanced usage: model "delta". If used, "model" must be unset. See the
489 // definition of MPModelDeltaProto.
490 optional MPModelDeltaProto model_delta = 8;
491
492 // Controls the recovery of additional solutions, if any, saved by the
493 // underlying solver back in the MPSolutionResponse.additional_solutions.
494 // The repeated field will be length
495 // min(populate_addition_solutions_up_to,
496 // #additional_solutions_available_in_underlying_solver)
497 // These additional solutions may have a worse objective than the main
498 // solution returned in the response.
499 optional int32 populate_additional_solutions_up_to = 11 [default = 0];
500}
501
502// Status returned by the solver. They follow a hierarchical nomenclature, to
503// allow us to add more enum values in the future. Clients should use
504// InCategory() to match these enums, with the following C++ pseudo-code:
505//
506// bool InCategory(MPSolverResponseStatus status, MPSolverResponseStatus cat) {
507// if (cat == MPSOLVER_OPTIMAL) return status == MPSOLVER_OPTIMAL;
508// while (status > cat) status >>= 4;
509// return status == cat;
510// }
511enum MPSolverResponseStatus {
512 // Normal responses -- the model was valid, and the solver ran.
513 // These statuses should be "somewhat" repeatable, modulo the fact that the
514 // solver's time limit makes it undeterministic, and could change a FEASIBLE
515 // model to an OPTIMAL and vice-versa (the others, except NOT_SOLVED, should
516 // normally be deterministic). Also, the solver libraries can be buggy.
517
518 // The solver found the proven optimal solution. This is what should be
519 // returned in most cases.
520 //
521 // WARNING: for historical reason, the value is zero, which means that this
522 // value can't have any subcategories.
523 MPSOLVER_OPTIMAL = 0x0;
524
525 // The solver had enough time to find some solution that satisfies all
526 // constraints, but it did not prove optimality (which means it may or may
527 // not have reached the optimal).
528 //
529 // This can happen for large LP models (Linear Programming), and is a frequent
530 // response for time-limited MIPs (Mixed Integer Programming). In the MIP
531 // case, the difference between the solution 'objective_value' and
532 // 'best_objective_bound' fields of the MPSolutionResponse will give an
533 // indication of how far this solution is from the optimal one.
534 MPSOLVER_FEASIBLE = 0x1;
535
536 // The model does not have any solution, according to the solver (which
537 // "proved" it, with the caveat that numerical proofs aren't actual proofs),
538 // or based on trivial considerations (eg. a variable whose lower bound is
539 // strictly greater than its upper bound).
540 MPSOLVER_INFEASIBLE = 0x2;
541
542 // There exist solutions that make the magnitude of the objective value
543 // as large as wanted (i.e. -infinity (resp. +infinity) for a minimization
544 // (resp. maximization) problem.
545 MPSOLVER_UNBOUNDED = 0x3;
546
547 // An error (most probably numerical) occurred.
548 // One likely cause for such errors is a large numerical range among variable
549 // coefficients (eg. 1e-16, 1e20), in which case one should try to shrink it.
550 MPSOLVER_ABNORMAL = 0x4;
551
552 // The solver did not have a chance to diagnose the model in one of the
553 // categories above.
554 MPSOLVER_NOT_SOLVED = 0x6;
555 // Like "NOT_SOLVED", but typically used by model validation functions
556 // returning a "model status", to enhance readability of the client code.
557 MPSOLVER_MODEL_IS_VALID = 0x61;
558 // The solve was interrupted by the user, and the solver didn't have time to
559 // return a proper status.
560 MPSOLVER_CANCELLED_BY_USER = 0x62;
561 // Special value: the solver status could not be properly translated and is
562 // unknown.
563 MPSOLVER_UNKNOWN_STATUS = 0x63;
564
565 // Model errors. These are always deterministic and repeatable.
566 // They should be accompanied with a string description of the error.
567 MPSOLVER_MODEL_INVALID = 0x5;
568 // Something is wrong with the fields "solution_hint_var_index" and/or
569 // "solution_hint_var_value".
570 MPSOLVER_MODEL_INVALID_SOLUTION_HINT = 0x54;
571 // Something is wrong with the solver_specific_parameters request field.
572 MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS = 0x55;
573
574 // Implementation error: the requested solver implementation is not
575 // available (see MPModelRequest.solver_type).
576 // The linear solver binary was probably not linked with the required library,
577 // eg //ortools/linear_solver:linear_solver_scip for SCIP.
578 MPSOLVER_SOLVER_TYPE_UNAVAILABLE = 0x7;
579 // Some of the selected options were incompatible, e.g. a cancellable solve
580 // was requested via SolverClient::SolveMipRemotely() with an underlying
581 // solver that doesn't support cancellation. status_str should contain a
582 // description of the issue.
583 MPSOLVER_INCOMPATIBLE_OPTIONS = 0x71;
584}
585
586message MPSolution {
587 optional double objective_value = 1;
588 repeated double variable_value = 2 [packed = true];
589}
590
591message MPSolveInfo {
592 // How much wall time (resp. user time) elapsed during the Solve() of the
593 // underlying solver library. "wall" time and "user" time are to be
594 // interpreted like for the "time" command in bash (see "help time").
595 // In particular, "user time" is CPU time and can be greater than wall time
596 // when using several threads.
597 optional double solve_wall_time_seconds = 1;
598 optional double solve_user_time_seconds = 2;
599}
600
601// Next id: 12.
602message MPSolutionResponse {
603 // Result of the optimization.
604 optional /*required*/ MPSolverResponseStatus status = 1
605 [default = MPSOLVER_UNKNOWN_STATUS];
606
607 // Human-readable string giving more details about the status. For example,
608 // when the status is MPSOLVER_INVALID_MODE, this can hold a description of
609 // why the model is invalid.
610 // This isn't always filled: don't depend on its value or even its presence.
611 optional string status_str = 7;
612
613 // Objective value corresponding to the "variable_value" below, taking into
614 // account the source "objective_offset" and "objective_coefficient".
615 // This is set iff 'status' is OPTIMAL or FEASIBLE.
616 optional double objective_value = 2;
617
618 // This field is only filled for MIP problems. For a minimization problem,
619 // this is a lower bound on the optimal objective value. For a maximization
620 // problem, it is an upper bound. It is only filled if the status is OPTIMAL
621 // or FEASIBLE. In the former case, best_objective_bound should be equal to
622 // objective_value (modulo numerical errors).
623 optional double best_objective_bound = 5;
624
625 // Variable values in the same order as the MPModelProto::variable field.
626 // This is a dense representation. These are set iff 'status' is OPTIMAL or
627 // FEASIBLE.
628 repeated double variable_value = 3 [packed = true];
629
630 // Contains extra information about the solve, populated if the underlying
631 // solver (and its interface) supports it. As of 2021/07/19 this is supported
632 // by SCIP and Gurobi proto solves.
633 optional MPSolveInfo solve_info = 10;
634
635 // Opaque solver-specific information.
636 // For the PDLP solver, this is a serialized pdlp::SolveLog proto.
637 optional bytes solver_specific_info = 11;
638
639 // [Advanced usage.]
640 // Values of the dual variables values in the same order as the
641 // MPModelProto::constraint field. This is a dense representation.
642 // These are not set if the problem was solved with a MIP solver (even if
643 // it is actually a linear program).
644 // These are set iff 'status' is OPTIMAL or FEASIBLE.
645 repeated double dual_value = 4 [packed = true];
646
647 // [Advanced usage.]
648 // Values of the reduced cost of the variables in the same order as the
649 // MPModelProto::variable. This is a dense representation.
650 // These are not set if the problem was solved with a MIP solver (even if it
651 // is actually a linear program).
652 // These are set iff 'status' is OPTIMAL or FEASIBLE.
653 repeated double reduced_cost = 6 [packed = true];
654
655 // [Advanced usage.]
656 // If `MPModelRequest.populate_additional_solutions_up_to` > 0, up to that
657 // number of additional solutions may be populated here, if available. These
658 // additional solutions are different than the main solution described by the
659 // above fields `objective_value` and `variable_value`.
660 repeated MPSolution additional_solutions = 8;
661}