Introduction to gurobipy#

Gurobi Optimizer is a mathematical optimization software library for solving mixed-integer linear, quadratic, and linear optimization problems.

Gurobipy is a package to write problems to be solved with Gurobi.

Gurobi software is not open but it allows you to get an Academic license

Note

If you have not yet set up Python on your computer, you can execute this tutorial in your browser via Google Colab. Click on the rocket in the top right corner and launch “Colab”. If that doesn’t work download the .ipynb file and import it in Google Colab.

Then install the following packages by executing the following command in a Jupyter cell at the top of the notebook.

!pip install gurobipy
  • We import gurobipy with prefix gp.

  • The specific module GRB is commonly imported separately, as it is used frequently.

import gurobipy as gp
from gurobipy import GRB

Example: Simple linear optimization problem#

Let’s use the following problem as an example:

\[\begin{split} \begin{align} \textrm{minimize} \quad &30x_1 + 20x_2 \\ \textrm{subject to} \quad &0.6x_1 + 0.2x_2 \geq 60 \\ &0.4x_1 + 0.8x_2 \geq 100 \\ &x_1 \geq 0, x_2 \geq 0 \\ \end{align} \end{split}\]
  • We initialize a model object in which we’ll store the problem.

model = gp.Model("My_LP_problem")
Restricted license - for non-production use only - expires 2026-11-23
  • Now, we can add variables to the model with the method model.addVar(lb=0.0, ub=float('inf'), vtype=GRB.CONTINUOUS, name="").

  • We can specify lower and upper bounds as well as domain using the arguments lb, ub, and vtype, respectively.

  • Note that the default lower bound is 0!

# Note that these two variables have the same bounds and domain
x_1 = model.addVar(lb=0, vtype=GRB.CONTINUOUS, name="x_1")
x_2 = model.addVar(name="x_2")
  • Generally, we add constraints with the model.addConstr(constr, name="") method.

  • In this case, the constraints are linear and here, we should use the model.addLConstr(constr, name="") method.

  • Here, it’s important to store the constraints in a meaningful way so you can easily access specific dual variables after solving.

  • Note, that in the GRBmodule, you can find the three signs GRB.GREATER_EQUAL, GRB.EQUAL, and GRB.LESS_EQUAL.

constraint_1 = model.addLConstr(0.6*x_1 + 0.2*x_2, GRB.GREATER_EQUAL, 60, name='constraint_1')
constraint_2 = model.addLConstr(0.4*x_1 + 0.8*x_2, GRB.GREATER_EQUAL, 100, name='constraint_2')
  • We define the objective function with the method model.setObjective(expr, sense=None).

  • Remember to set the sense argument!

model.setObjective(30*x_1 + 20*x_2, GRB.MINIMIZE)
  • Now, we can solve the optimization problem with the method model.optimize.

model.optimize()
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - "Ubuntu 24.04.2 LTS")

CPU model: AMD EPYC 7763 64-Core Processor, instruction set [SSE2|AVX|AVX2]
Thread count: 2 physical cores, 4 logical processors, using up to 4 threads

Optimize a model with 2 rows, 2 columns and 4 nonzeros
Model fingerprint: 0x20d42a0c
Coefficient statistics:
  Matrix range     [2e-01, 8e-01]
  Objective range  [2e+01, 3e+01]
  Bounds range     [0e+00, 0e+00]
  RHS range        [6e+01, 1e+02]
Presolve time: 0.00s
Presolved: 2 rows, 2 columns, 4 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    0.0000000e+00   1.600000e+02   0.000000e+00      0s
       2    3.9000000e+03   0.000000e+00   0.000000e+00      0s

Solved in 2 iterations and 0.01 seconds (0.00 work units)
Optimal objective  3.900000000e+03
  • We can check whether the problem was solved to optimality with model.status.

  • If so, we retrieve optimal objective function with model.ObjVal

  • and optimal primal and dual variable values with var.x and constr.Pi, respectively.

if model.status == GRB.OPTIMAL:
    optimal_objective = model.ObjVal
    optimal_x_1 = x_1.x
    optimal_x_2 = x_2.x
    optimal_dual_1 = constraint_1.Pi
    optimal_dual_2 = constraint_2.Pi
    print(f"optimal objective: {optimal_objective}")
    print(f"optimal value of {x_1.VarName}: {optimal_x_1}")
    print(f"optimal value of {x_2.VarName}: {optimal_x_2}")
    print(f"optimal value of dual for {constraint_1.constrName}: {optimal_dual_1}")
    print(f"optimal value of dual for {constraint_2.constrName}: {optimal_dual_2}")
else:
    print(f"optimization of {model.ModelName} was not successful")
optimal objective: 3900.0
optimal value of x_1: 70.0
optimal value of x_2: 90.0
optimal value of dual for constraint_1: 40.0
optimal value of dual for constraint_2: 15.0

Example: Adding quadratic constraints and absolute values for variables#

If we want to add quadratic constraints, we should use the model.addQConstr(constr, name="") method. You can also check this short video on setting quadratically constrained problems in gurobipy

If we want to use the absolute value of a variable we can define it as follows

m = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="m")
abs_m = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="abs_m")

from gurobipy import abs_
model.addConstr(abs_m == abs_(m), name='abs_m')
<gurobi.GenConstr *Awaiting Model Update*>