Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
parameters.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright 2010-2025 Google LLC
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Configures the solving of an optimization model."""
16
17import dataclasses
18import datetime
19import enum
20from typing import Dict, Optional
21
22from ortools.pdlp import solvers_pb2 as pdlp_solvers_pb2
23from ortools.glop import parameters_pb2 as glop_parameters_pb2
24from ortools.math_opt import parameters_pb2 as math_opt_parameters_pb2
25from ortools.math_opt.solvers import glpk_pb2
26from ortools.math_opt.solvers import gurobi_pb2
27from ortools.math_opt.solvers import highs_pb2
28from ortools.math_opt.solvers import osqp_pb2
29from ortools.math_opt.solvers.gscip import gscip_pb2
30from ortools.sat import sat_parameters_pb2
31
32
33@enum.unique
34class SolverType(enum.Enum):
35 """The underlying solver to use.
36
37 This must stay synchronized with math_opt_parameters_pb2.SolverTypeProto.
38
39 Attributes:
40 GSCIP: Solving Constraint Integer Programs (SCIP) solver (third party).
41 Supports LP, MIP, and nonconvex integer quadratic problems. No dual data
42 for LPs is returned though. Prefer GLOP for LPs.
43 GUROBI: Gurobi solver (third party). Supports LP, MIP, and nonconvex integer
44 quadratic problems. Generally the fastest option, but has special
45 licensing, see go/gurobi-google for details.
46 GLOP: Google's Glop linear solver. Supports LP with primal and dual simplex
47 methods.
48 CP_SAT: Google's CP-SAT solver. Supports problems where all variables are
49 integer and bounded (or implied to be after presolve). Experimental
50 support to rescale and discretize problems with continuous variables.
51 MOE:begin_intracomment_strip
52 PDLP: Google's PDLP solver. Supports LP and convex diagonal quadratic
53 objectives. Uses first order methods rather than simplex. Can solve very
54 large problems.
55 MOE:end_intracomment_strip
56 GLPK: GNU Linear Programming Kit (GLPK) (third party). Supports MIP and LP.
57 Thread-safety: GLPK use thread-local storage for memory allocations. As a
58 consequence when using IncrementalSolver, the user must make sure that
59 instances are closed on the same thread as they are created or GLPK will
60 crash. To do so, use `with` or call IncrementalSolver#close(). It seems OK
61 to call IncrementalSolver#Solve() from another thread than the one used to
62 create the Solver but it is not documented by GLPK and should be avoided.
63 Of course these limitations do not apply to the solve() function that
64 recreates a new GLPK problem in the calling thread and destroys before
65 returning. When solving a LP with the presolver, a solution (and the
66 unbound rays) are only returned if an optimal solution has been found.
67 Else nothing is returned. See glpk-5.0/doc/glpk.pdf page #40 available
68 from glpk-5.0.tar.gz for details.
69 OSQP: The Operator Splitting Quadratic Program (OSQP) solver (third party).
70 Supports continuous problems with linear constraints and linear or convex
71 quadratic objectives. Uses a first-order method.
72 ECOS: The Embedded Conic Solver (ECOS) (third party). Supports LP and SOCP
73 problems. Uses interior point methods (barrier).
74 SCS: The Splitting Conic Solver (SCS) (third party). Supports LP and SOCP
75 problems. Uses a first-order method.
76 HIGHS: The HiGHS Solver (third party). Supports LP and MIP problems (convex
77 QPs are unimplemented).
78 SANTORINI: The Santorini Solver (first party). Supports MIP. Experimental,
79 do not use in production.
80 """
81
82 GSCIP = math_opt_parameters_pb2.SOLVER_TYPE_GSCIP
83 GUROBI = math_opt_parameters_pb2.SOLVER_TYPE_GUROBI
84 GLOP = math_opt_parameters_pb2.SOLVER_TYPE_GLOP
85 CP_SAT = math_opt_parameters_pb2.SOLVER_TYPE_CP_SAT
86 PDLP = math_opt_parameters_pb2.SOLVER_TYPE_PDLP
87 GLPK = math_opt_parameters_pb2.SOLVER_TYPE_GLPK
88 OSQP = math_opt_parameters_pb2.SOLVER_TYPE_OSQP
89 ECOS = math_opt_parameters_pb2.SOLVER_TYPE_ECOS
90 SCS = math_opt_parameters_pb2.SOLVER_TYPE_SCS
91 HIGHS = math_opt_parameters_pb2.SOLVER_TYPE_HIGHS
92 SANTORINI = math_opt_parameters_pb2.SOLVER_TYPE_SANTORINI
93
94
96 proto_value: math_opt_parameters_pb2.SolverTypeProto,
97) -> Optional[SolverType]:
98 if proto_value == math_opt_parameters_pb2.SOLVER_TYPE_UNSPECIFIED:
99 return None
100 return SolverType(proto_value)
101
102
104 solver_type: Optional[SolverType],
105) -> math_opt_parameters_pb2.SolverTypeProto:
106 if solver_type is None:
107 return math_opt_parameters_pb2.SOLVER_TYPE_UNSPECIFIED
108 return solver_type.value
109
110
111@enum.unique
112class LPAlgorithm(enum.Enum):
113 """Selects an algorithm for solving linear programs.
114
115 Attributes:
116 * UNPSECIFIED: No algorithm is selected.
117 * PRIMAL_SIMPLEX: The (primal) simplex method. Typically can provide primal
118 and dual solutions, primal/dual rays on primal/dual unbounded problems,
119 and a basis.
120 * DUAL_SIMPLEX: The dual simplex method. Typically can provide primal and
121 dual solutions, primal/dual rays on primal/dual unbounded problems, and a
122 basis.
123 * BARRIER: The barrier method, also commonly called an interior point method
124 (IPM). Can typically give both primal and dual solutions. Some
125 implementations can also produce rays on unbounded/infeasible problems. A
126 basis is not given unless the underlying solver does "crossover" and
127 finishes with simplex.
128 * FIRST_ORDER: An algorithm based around a first-order method. These will
129 typically produce both primal and dual solutions, and potentially also
130 certificates of primal and/or dual infeasibility. First-order methods
131 typically will provide solutions with lower accuracy, so users should take
132 care to set solution quality parameters (e.g., tolerances) and to validate
133 solutions.
134
135 This must stay synchronized with math_opt_parameters_pb2.LPAlgorithmProto.
136 """
137
138 PRIMAL_SIMPLEX = math_opt_parameters_pb2.LP_ALGORITHM_PRIMAL_SIMPLEX
139 DUAL_SIMPLEX = math_opt_parameters_pb2.LP_ALGORITHM_DUAL_SIMPLEX
140 BARRIER = math_opt_parameters_pb2.LP_ALGORITHM_BARRIER
141 FIRST_ORDER = math_opt_parameters_pb2.LP_ALGORITHM_FIRST_ORDER
142
143
145 proto_value: math_opt_parameters_pb2.LPAlgorithmProto,
146) -> Optional[LPAlgorithm]:
147 if proto_value == math_opt_parameters_pb2.LP_ALGORITHM_UNSPECIFIED:
148 return None
149 return LPAlgorithm(proto_value)
150
151
153 lp_algorithm: Optional[LPAlgorithm],
154) -> math_opt_parameters_pb2.LPAlgorithmProto:
155 if lp_algorithm is None:
156 return math_opt_parameters_pb2.LP_ALGORITHM_UNSPECIFIED
157 return lp_algorithm.value
158
159
160@enum.unique
161class Emphasis(enum.Enum):
162 """Effort level applied to an optional task while solving (see SolveParameters for use).
163
164 - OFF: disable this task.
165 - LOW: apply reduced effort.
166 - MEDIUM: typically the default setting (unless the default is off).
167 - HIGH: apply extra effort beyond MEDIUM.
168 - VERY_HIGH: apply the maximum effort.
169
170 Typically used as Optional[Emphasis]. It used to configure a solver feature as
171 follows:
172 * If a solver doesn't support the feature, only None will always be valid,
173 any other setting will give an invalid argument error (some solvers may
174 also accept OFF).
175 * If the solver supports the feature:
176 - When set to None, the underlying default is used.
177 - When the feature cannot be turned off, OFF will produce an error.
178 - If the feature is enabled by default, the solver default is typically
179 mapped to MEDIUM.
180 - If the feature is supported, LOW, MEDIUM, HIGH, and VERY HIGH will never
181 give an error, and will map onto their best match.
182
183 This must stay synchronized with math_opt_parameters_pb2.EmphasisProto.
184 """
185
186 OFF = math_opt_parameters_pb2.EMPHASIS_OFF
187 LOW = math_opt_parameters_pb2.EMPHASIS_LOW
188 MEDIUM = math_opt_parameters_pb2.EMPHASIS_MEDIUM
189 HIGH = math_opt_parameters_pb2.EMPHASIS_HIGH
190 VERY_HIGH = math_opt_parameters_pb2.EMPHASIS_VERY_HIGH
191
192
194 proto_value: math_opt_parameters_pb2.EmphasisProto,
195) -> Optional[Emphasis]:
196 if proto_value == math_opt_parameters_pb2.EMPHASIS_UNSPECIFIED:
197 return None
198 return Emphasis(proto_value)
199
200
202 emphasis: Optional[Emphasis],
203) -> math_opt_parameters_pb2.EmphasisProto:
204 if emphasis is None:
205 return math_opt_parameters_pb2.EMPHASIS_UNSPECIFIED
206 return emphasis.value
207
208
209@dataclasses.dataclass
211 """Gurobi specific parameters for solving.
212
213 See https://www.gurobi.com/documentation/9.1/refman/parameters.html for a list
214 of possible parameters.
215
216 Example use:
217 gurobi=GurobiParameters();
218 gurobi.param_values["BarIterLimit"] = "10";
219
220 With Gurobi, the order that parameters are applied can have an impact in rare
221 situations. Parameters are applied in the following order:
222 * LogToConsole is set from SolveParameters.enable_output.
223 * Any common parameters not overwritten by GurobiParameters.
224 * param_values in iteration order (insertion order).
225 We set LogToConsole first because setting other parameters can generate
226 output.
227 """
228
229 param_values: Dict[str, str] = dataclasses.field(default_factory=dict)
230
231 def to_proto(self) -> gurobi_pb2.GurobiParametersProto:
232 return gurobi_pb2.GurobiParametersProto(
233 parameters=[
234 gurobi_pb2.GurobiParametersProto.Parameter(name=key, value=val)
235 for key, val in self.param_values.items()
236 ]
237 )
238
239
240@dataclasses.dataclass
242 """GLPK specific parameters for solving.
243
244 Fields are optional to enable to capture user intention; if they set
245 explicitly a value to then no generic solve parameters will overwrite this
246 parameter. User specified solver specific parameters have priority on generic
247 parameters.
248
249 Attributes:
250 compute_unbound_rays_if_possible: Compute the primal or dual unbound ray
251 when the variable (structural or auxiliary) causing the unboundness is
252 identified (see glp_get_unbnd_ray()). The unset value is equivalent to
253 false. Rays are only available when solving linear programs, they are not
254 available for MIPs. On top of that they are only available when using a
255 simplex algorithm with the presolve disabled. A primal ray can only be
256 built if the chosen LP algorithm is LPAlgorithm.PRIMAL_SIMPLEX. Same for a
257 dual ray and LPAlgorithm.DUAL_SIMPLEX. The computation involves the basis
258 factorization to be available which may lead to extra computations/errors.
259 """
260
261 compute_unbound_rays_if_possible: Optional[bool] = None
262
263 def to_proto(self) -> glpk_pb2.GlpkParametersProto:
264 return glpk_pb2.GlpkParametersProto(
265 compute_unbound_rays_if_possible=self.compute_unbound_rays_if_possible
266 )
267
268
269@dataclasses.dataclass
271 """Parameters to control a single solve.
272
273 If a value is set in both common and solver specific field (e.g. gscip), the
274 solver specific setting is used.
275
276 Solver specific parameters for solvers other than the one in use are ignored.
277
278 Parameters that depends on the model (e.g. branching priority is set for each
279 variable) are passed in ModelSolveParameters.
280
281 See solve() and IncrementalSolver.solve() in solve.py for more details.
282
283 Attributes:
284 time_limit: The maximum time a solver should spend on the problem, or if
285 None, then the time limit is infinite. This value is not a hard limit,
286 solve time may slightly exceed this value. This parameter is always passed
287 to the underlying solver, the solver default is not used.
288 iteration_limit: Limit on the iterations of the underlying algorithm (e.g.
289 simplex pivots). The specific behavior is dependent on the solver and
290 algorithm used, but often can give a deterministic solve limit (further
291 configuration may be needed, e.g. one thread). Typically supported by LP,
292 QP, and MIP solvers, but for MIP solvers see also node_limit.
293 node_limit: Limit on the number of subproblems solved in enumerative search
294 (e.g. branch and bound). For many solvers this can be used to
295 deterministically limit computation (further configuration may be needed,
296 e.g. one thread). Typically for MIP solvers, see also iteration_limit.
297 cutoff_limit: The solver stops early if it can prove there are no primal
298 solutions at least as good as cutoff. On an early stop, the solver returns
299 TerminationReason.NO_SOLUTION_FOUND and with Limit.CUTOFF and is not
300 required to give any extra solution information. Has no effect on the
301 return value if there is no early stop. It is recommended that you use a
302 tolerance if you want solutions with objective exactly equal to cutoff to
303 be returned. See the user guide for more details and a comparison with
304 best_bound_limit.
305 objective_limit: The solver stops early as soon as it finds a solution at
306 least this good, with TerminationReason.FEASIBLE and Limit.OBJECTIVE.
307 best_bound_limit: The solver stops early as soon as it proves the best bound
308 is at least this good, with TerminationReason of FEASIBLE or
309 NO_SOLUTION_FOUND and Limit.OBJECTIVE. See the user guide for more details
310 and a comparison with cutoff_limit.
311 solution_limit: The solver stops early after finding this many feasible
312 solutions, with TerminationReason.FEASIBLE and Limit.SOLUTION. Must be
313 greater than zero if set. It is often used get the solver to stop on the
314 first feasible solution found. Note that there is no guarantee on the
315 objective value for any of the returned solutions. Solvers will typically
316 not return more solutions than the solution limit, but this is not
317 enforced by MathOpt, see also b/214041169. Currently supported for Gurobi
318 and SCIP, and for CP-SAT only with value 1.
319 enable_output: If the solver should print out its log messages.
320 threads: An integer >= 1, how many threads to use when solving.
321 random_seed: Seed for the pseudo-random number generator in the underlying
322 solver. Note that valid values depend on the actual solver:
323 * Gurobi: [0:GRB_MAXINT] (which as of Gurobi 9.0 is 2x10^9).
324 * GSCIP: [0:2147483647] (which is MAX_INT or kint32max or 2^31-1).
325 * GLOP: [0:2147483647] (same as above).
326 In all cases, the solver will receive a value equal to:
327 MAX(0, MIN(MAX_VALID_VALUE_FOR_SOLVER, random_seed)).
328 absolute_gap_tolerance: An absolute optimality tolerance (primarily) for MIP
329 solvers. The absolute GAP is the absolute value of the difference between:
330 * the objective value of the best feasible solution found,
331 * the dual bound produced by the search.
332 The solver can stop once the absolute GAP is at most
333 absolute_gap_tolerance (when set), and return TerminationReason.OPTIMAL.
334 Must be >= 0 if set. See also relative_gap_tolerance.
335 relative_gap_tolerance: A relative optimality tolerance (primarily) for MIP
336 solvers. The relative GAP is a normalized version of the absolute GAP
337 (defined on absolute_gap_tolerance), where the normalization is
338 solver-dependent, e.g. the absolute GAP divided by the objective value of
339 the best feasible solution found. The solver can stop once the relative
340 GAP is at most relative_gap_tolerance (when set), and return
341 TerminationReason.OPTIMAL. Must be >= 0 if set. See also
342 absolute_gap_tolerance.
343 solution_pool_size: Maintain up to `solution_pool_size` solutions while
344 searching. The solution pool generally has two functions:
345 * For solvers that can return more than one solution, this limits how
346 many solutions will be returned.
347 * Some solvers may run heuristics using solutions from the solution
348 pool, so changing this value may affect the algorithm's path.
349 To force the solver to fill the solution pool, e.g. with the n best
350 solutions, requires further, solver specific configuration.
351 lp_algorithm: The algorithm for solving a linear program. If UNSPECIFIED,
352 use the solver default algorithm. For problems that are not linear
353 programs but where linear programming is a subroutine, solvers may use
354 this value. E.g. MIP solvers will typically use this for the root LP solve
355 only (and use dual simplex otherwise).
356 presolve: Effort on simplifying the problem before starting the main
357 algorithm (e.g. simplex).
358 cuts: Effort on getting a stronger LP relaxation (MIP only). Note that in
359 some solvers, disabling cuts may prevent callbacks from having a chance to
360 add cuts at MIP_NODE.
361 heuristics: Effort in finding feasible solutions beyond those encountered in
362 the complete search procedure.
363 scaling: Effort in rescaling the problem to improve numerical stability.
364 gscip: GSCIP specific solve parameters.
365 gurobi: Gurobi specific solve parameters.
366 glop: Glop specific solve parameters.
367 cp_sat: CP-SAT specific solve parameters.
368 pdlp: PDLP specific solve parameters.
369 osqp: OSQP specific solve parameters. Users should prefer the generic
370 MathOpt parameters over OSQP-level parameters, when available: - Prefer
371 SolveParameters.enable_output to OsqpSettingsProto.verbose. - Prefer
372 SolveParameters.time_limit to OsqpSettingsProto.time_limit. - Prefer
373 SolveParameters.iteration_limit to OsqpSettingsProto.iteration_limit. - If
374 a less granular configuration is acceptable, prefer
375 SolveParameters.scaling to OsqpSettingsProto.
376 glpk: GLPK specific solve parameters.
377 highs: HiGHS specific solve parameters.
378 """ # fmt: skip
379
380 time_limit: Optional[datetime.timedelta] = None
381 iteration_limit: Optional[int] = None
382 node_limit: Optional[int] = None
383 cutoff_limit: Optional[float] = None
384 objective_limit: Optional[float] = None
385 best_bound_limit: Optional[float] = None
386 solution_limit: Optional[int] = None
387 enable_output: bool = False
388 threads: Optional[int] = None
389 random_seed: Optional[int] = None
390 absolute_gap_tolerance: Optional[float] = None
391 relative_gap_tolerance: Optional[float] = None
392 solution_pool_size: Optional[int] = None
393 lp_algorithm: Optional[LPAlgorithm] = None
394 presolve: Optional[Emphasis] = None
395 cuts: Optional[Emphasis] = None
396 heuristics: Optional[Emphasis] = None
397 scaling: Optional[Emphasis] = None
398 gscip: gscip_pb2.GScipParameters = dataclasses.field(
399 default_factory=gscip_pb2.GScipParameters
400 )
401 gurobi: GurobiParameters = dataclasses.field(default_factory=GurobiParameters)
402 glop: glop_parameters_pb2.GlopParameters = dataclasses.field(
403 default_factory=glop_parameters_pb2.GlopParameters
404 )
405 cp_sat: sat_parameters_pb2.SatParameters = dataclasses.field(
406 default_factory=sat_parameters_pb2.SatParameters
407 )
408 pdlp: pdlp_solvers_pb2.PrimalDualHybridGradientParams = dataclasses.field(
409 default_factory=pdlp_solvers_pb2.PrimalDualHybridGradientParams
410 )
411 osqp: osqp_pb2.OsqpSettingsProto = dataclasses.field(
412 default_factory=osqp_pb2.OsqpSettingsProto
413 )
414 glpk: GlpkParameters = dataclasses.field(default_factory=GlpkParameters)
415 highs: highs_pb2.HighsOptionsProto = dataclasses.field(
416 default_factory=highs_pb2.HighsOptionsProto
417 )
418
419 def to_proto(self) -> math_opt_parameters_pb2.SolveParametersProto:
420 """Returns a protocol buffer equivalent to this."""
421 result = math_opt_parameters_pb2.SolveParametersProto(
422 enable_output=self.enable_output,
423 lp_algorithm=lp_algorithm_to_proto(self.lp_algorithm),
424 presolve=emphasis_to_proto(self.presolve),
425 cuts=emphasis_to_proto(self.cuts),
426 heuristics=emphasis_to_proto(self.heuristics),
427 scaling=emphasis_to_proto(self.scaling),
428 gscip=self.gscip,
429 gurobi=self.gurobi.to_proto(),
430 glop=self.glop,
431 cp_sat=self.cp_sat,
432 pdlp=self.pdlp,
433 osqp=self.osqp,
434 glpk=self.glpk.to_proto(),
435 highs=self.highs,
436 )
437 if self.time_limit is not None:
438 result.time_limit.FromTimedelta(self.time_limit)
439 if self.iteration_limit is not None:
440 result.iteration_limit = self.iteration_limit
441 if self.node_limit is not None:
442 result.node_limit = self.node_limit
443 if self.cutoff_limit is not None:
444 result.cutoff_limit = self.cutoff_limit
445 if self.objective_limit is not None:
446 result.objective_limit = self.objective_limit
447 if self.best_bound_limit is not None:
448 result.best_bound_limit = self.best_bound_limit
449 if self.solution_limit is not None:
450 result.solution_limit = self.solution_limit
451 if self.threads is not None:
452 result.threads = self.threads
453 if self.random_seed is not None:
454 result.random_seed = self.random_seed
455 if self.absolute_gap_tolerance is not None:
456 result.absolute_gap_tolerance = self.absolute_gap_tolerance
457 if self.relative_gap_tolerance is not None:
458 result.relative_gap_tolerance = self.relative_gap_tolerance
459 if self.solution_pool_size is not None:
460 result.solution_pool_size = self.solution_pool_size
461 return result
glpk_pb2.GlpkParametersProto to_proto(self)
gurobi_pb2.GurobiParametersProto to_proto(self)
math_opt_parameters_pb2.SolveParametersProto to_proto(self)
Optional[Emphasis] emphasis_from_proto(math_opt_parameters_pb2.EmphasisProto proto_value)
math_opt_parameters_pb2.LPAlgorithmProto lp_algorithm_to_proto(Optional[LPAlgorithm] lp_algorithm)
Optional[SolverType] solver_type_from_proto(math_opt_parameters_pb2.SolverTypeProto proto_value)
Definition parameters.py:97
Optional[LPAlgorithm] lp_algorithm_from_proto(math_opt_parameters_pb2.LPAlgorithmProto proto_value)
math_opt_parameters_pb2.SolverTypeProto solver_type_to_proto(Optional[SolverType] solver_type)
math_opt_parameters_pb2.EmphasisProto emphasis_to_proto(Optional[Emphasis] emphasis)