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