Gurobi
Gurobi 🔗 is an industry-leading solver for mathematical optimization.
Solvers​
Model | Solvers |
---|---|
Quadratic Unconstrained Binary Optimization (QUBO) | gurobi.qubo |
Mathematical Programming System (MPS) | gurobi.mps |
Linear Programming (LP) | gurobi.lp |
Quadratic Unconstrained Binary Optimization (QUBO)​
from strangeworks_optimization import StrangeworksOptimizer
from strangeworks_optimization_models.parameter_models import GurobiParameterModel
from dimod import BinaryQuadraticModel
linear = {1: -2, 2: -2, 3: -3, 4: -3, 5: -2}
quadratic = {(1, 2): 2, (1, 3): 2, (2, 4): 2, (3, 4): 2, (3, 5): 2, (4, 5): 2}
model = BinaryQuadraticModel(linear, quadratic, "BINARY")
solver = "gurobi.qubo"
options = GurobiParameterModel(TimeLimit=60)
so = StrangeworksOptimizer(model=model, solver=solver, options=options)
sw_job = so.run()
print(f"Job slug: {sw_job.slug}")
print(f"Job status: {so.status(sw_job.slug)}")
results = so.results(sw_job.slug)
Mathematical Programming System (MPS)​
A standard format for linear and mixed-integer programming problems.
from strangeworks_optimization import StrangeworksOptimizer
from strangeworks_optimization_models.problem_models import MPSFile
from strangeworks_optimization_models.parameter_models import GurobiParameterModel
model = MPSFile.read_file("example.mps")
solver = "gurobi.mps"
options = GurobiParameterModel(TimeLimit=60)
so = StrangeworksOptimizer(model=model, solver=solver, options=options)
sw_job = so.run()
print(f"Job slug: {sw_job.slug}")
print(f"Job status: {so.status(sw_job.slug)}")
results = so.results(sw_job.slug)
Presolve​
The aim of presolving is to reduce the problem size, improve numerical stability, and enhance the overall efficiency of the solver.
On Gurobi presolving takes place by default when solving MPS problems with gurobi.mps
. It is possible to presolve first separately using the gurobi.presolve
solver.
To see the full list of presolve parameters, refer to the GurobiParameterModel section.
from strangeworks_optimization import StrangeworksOptimizer
from strangeworks_optimization_models.parameter_models import GurobiParameterModel
from strangeworks_optimization_models.problem_models import MPSFile
so = StrangeworksOptimizer(
model = MPSFile.read_file("example.mps"),
solver = "gurobi.presolve",
options = GurobiParameterModel(Presolve=2),
)
sw_job = so.run()
presolved_model = so.results(sw_job.slug)
The returned presolved model is a remote file and can be submitted directly to gurobi.mps
for solving.
so = StrangeworksOptimizer(
model = presolved_model,
solver = "gurobi.mps",
options = GurobiParameterModel(TimeLimit=60)
)
sw_job = so.run()
results = so.results(sw_job.slug)
Linear Programming (LP)​
from strangeworks_optimization import StrangeworksOptimizer
from strangeworks_optimization_models.parameter_models import GurobiParameterModel
from strangeworks_optimization_models.problem_models import LpFile
model = LpFile.read_file("example.lp")
options = GurobiParameterModel(TimeLimit=60)
so = StrangeworksOptimizer(model=model, solver="gurobi.lp", options=options)
sw_job = so.run()
results = so.results(sw_job.slug)
Gurobi Model Object​
Can be submitted to the Gurobi MPS solver by first using the Model.write()
method.
import strangeworks as sw
import gurobipy as gp
from gurobipy import GRB
import numpy as np
import tempfile
sw.authenticate(api_key)
Q = [[-1, 2, 0], [0, -1, 2], [0, 0, -1]]
num_vars = np.shape(Q)[0]
Qnew = {}
for i in range(num_vars):
for j in range(num_vars):
Qnew[(i, j)] = Q[i][j]
Q = Qnew
m = gp.Model("Label")
# Collect the variables and construct the objective function (the qubo)
vs = [m.addVar(name=str(i), vtype=GRB.BINARY) for i in range(num_vars)]
obj = gp.QuadExpr()
for i in range(num_vars):
for j in range(num_vars):
if Q[i, j] != 0:
obj += Q[i, j] * vs[i] * vs[j]
# Run optimizer and get solutions
m.setObjective(obj, GRB.MINIMIZE)
with tempfile.NamedTemporaryFile(suffix=".mps") as temp_file:
file_path = temp_file.name
m.write(file_path)
sw_model = MPSFile.read_file(file_path)
so = StrangeworksOptimizer(model=sw_model, solver="gurobi.mps")
job = so.run()
results = so.results(job.slug)
print(results.solution)
Parameters​
from strangeworks_optimization_models.parameter_models import GurobiParameterModel
options = GurobiParameterModel(
.....
)
Below are some of the parameter groups that can be used to control the behavior of the Gurobi solver. There are plenty more parameter groups available.
Termination​
These parameters control the conditions under which the solver will terminate.
Gurobi Termination Parameters 🔗.
Name | Description | Type | Default | Values (Range) |
---|---|---|---|---|
BarIterLimit | Limits the number of iterations the barrier algorithm will perform. | int | 1000 | [0, MAXINT] |
BestBdStop | Stops optimization once the best objective bound is at least this good. | double | Infinity | [-Infinity, Infinity] |
BestObjStop | Stops optimization once a solution with an objective value this good is found. | double | -Infinity | [-Infinity, Infinity] |
Cutoff | Sets a threshold objective value; optimization stops if no better value is possible. | double | Infinity for minimization, -Infinity for maximization | [-Infinity, Infinity] |
IterationLimit | Restricts the number of simplex iterations to prevent excessive computation. | int | Infinity | [0, Infinity] |
MemLimit | Sets the maximum amount of memory the solver may use, in GB. | double | None | [0, Infinity] |
NodeLimit | Imposes a limit on the number of MIP nodes explored in the search tree. | int | None | [0, Infinity] |
SoftMemLimit | Sets a soft limit on the memory usage, allowing for minimal overages. | double | None | [0, Infinity] |
SolutionLimit | Stops optimization after finding a specified number of feasible solutions. | int | None | [1, MAXINT] |
TimeLimit | Specifies the maximum time (in seconds) the solver should run. | double | None | [0, Infinity] |
WorkLimit | Limits the amount of "work" (an abstract measure of effort) the solver can perform. | int | None | [0, Infinity] |
Tolerances​
These parameters control the feasibility and optimality tolerances. The feasibility tolerance is the maximum amount by which a constraint can be violated, and the optimality tolerance is the maximum amount by which the objective function can be improved.
Name | Description | Type | Default | Values (Range) |
---|---|---|---|---|
BarConvTol | Tolerance used by the barrier algorithm to determine convergence. | float | 1e-8 | [0.0, 1.0] |
BarQCPConvTol | Tolerance for convergence when solving Quadratically Constrained Programs using the barrier method. | float | 1e-6 | [0.0, 1.0] |
FeasibilityTol | Tolerance for primal feasibility in the optimization. | float | 1e-6 | [1e-9, 1e-2] |
IntFeasTol | Tolerance to determine if an integer variable is at its bound. | float | 1e-5 | [1e-9, 1e-1] |
MarkowitzTol | Controls the threshold for numerical pivoting in the simplex algorithms. | float | 0.0078125 | [1e-4, 0.999] |
MIPGap | Relative gap between the lower and upper bounds for terminating MIP optimization. | float | 1e-4 | [0.0, Infinity] |
MIPGapAbs | Absolute gap between the lower and upper bounds for terminating MIP optimization. | float | 1e-10 | [0.0, Infinity] |
OptimalityTol | Tolerance for dual feasibility in the optimization. | float | 1e-6 | [1e-9, 1e-2] |
PSDTol | Tolerance used to check the positive semi-definiteness in optimization. | float | 1e-6 | [0, Infinity] |
Presolve​
Presolve is the process of simplifying MPS problems before solving.
Problems are presolved by default when submitted to gurobi.mps
but it is possible to presolve first separately using the gurobi.presolve
solver.
In either case, these parameters control the presolve phase of the optimization.
Gurobi Presolve Parameters 🔗.
Name | Description | Type | Default | Values (Range) |
---|---|---|---|---|
AggFill | Specifies the level of fill allowed during presolve aggregation. | int | -1 | [-1, MAXINT] |
Aggregate | Controls the aggregation level in presolve: off, moderate, or aggressive. | bool | 1 | [0, 2] |
DualReductions | Enables or disables dual reductions during presolve. | bool | 1 | [0, 1] |
PreCrush | Allows translation of user constraints into equivalent presolved model constraints. | bool | 0 | [0, 1] |
PreDepRow | Enables or disables dependent row reduction in presolve. | bool | 1 | [0, 1] |
PreDual | Determines whether to dualize the problem during presolve. | bool | 0 | [0, 1] |
PreMIQCPForm | Specifies the form of the presolved Mixed Integer Quadratically Constrained Program (MIQCP). | int | 0 | [0, 1] |
PrePasses | Sets the maximum number of presolve passes. | int | -1 | [-1, MAXINT] |
PreQLinearize | Determines whether to linearize the quadratic terms in objective and constraints during presolve. | bool | 0 | [0, 1] |
Presolve | Sets the presolve level to control the aggressiveness of the presolve process. | int | -1 | [-1, 2] |
PreSOS1BigM | Specifies the largest coefficient allowed in SOS1 (Special Ordered Sets type 1) reformulations. | float | 1e6 | [0, Infinity] |
PreSOS1Encoding | Controls the encoding method used for SOS1 reformulations. | int | -1 | [-1, 2] |
PreSOS2BigM | Specifies the largest coefficient allowed in SOS2 (Special Ordered Sets type 2) reformulations. | float | 1e6 | [0, Infinity] |
PreSOS2Encoding | Controls the encoding method used for SOS2 reformulations. | int | -1 | [-1, 2] |
PreSparsify | Enables or disables the sparsification of the problem during presolve to reduce size without altering the optimal solution significantly. | bool | 0 | [0, 1] |