This section will work through a simple example in order to illustrate the use of Gurobi Python API and Gurobi Python Matrix API. The example builds a simple Mixed Integer Programming model, optimizes it, and outputs the optimal objective value.
Gurobi comes with a Python extension module called “gurobipy” that offers convenient object-oriented modeling constructs and an API to all Gurobi features. You can also install gurobipy into an existing Python installation or virtual environment (https://docs.python.org/3/library/venv.html). See How do I install Gurobi for Python?
This example builds a trivial MIP model, solves it, and prints the solution.
The example
Our example optimizes the following model:
maximize | x | + | y | + | 2 z | ||
subject to | x | + | 2 y | + | 3 z | <= | 4 |
x | + | y | >= | 1 | |||
x, y, z binary |
In the following sections, we will walk through the example, line by line, to understand how it achieves the desired result of optimizing the above model with the Gurobi Python API as well as Gurobi Python Matrix API.
The complete source code for our example model can be found:
For the Python interface
- Online: Example mip1.py
- Distribution: <installdir>/examples/python/mip1.py
For the Python matrix interface
-
- Online: Example matrix1.py
- Distribution: <installdir>/examples/python/matrix1.py>
Importing the Gurobi functions and classes
In the Python interface
The example begins by importing the Gurobi functions and classes:
import gurobipy as gp from gurobipy import GRB
The first line makes all Gurobi functions and classes available through a gp. prefix (e.g., gp.Model()). The second makes everything in class GRB available without a prefix (e.g., GRB.OPTIMAL). You can also start a program with from gurobipy import * to remove the need for the gp. prefix, but if your program uses multiple Python modules it is usually preferred to access each through its own prefix.
In order for these commands to succeed, the Python application needs to know how to find the Gurobi functions and classes. Recall that you have three options for installing them.
In the Python matrix interface
The example begins by importing the Gurobi functions and classes, as well as the NumPy and SciPy packages:
import gurobipy as gp from gurobipy import GRB import numpy as np import scipy.sparse as sp
Gurobi Python applications should always start with the first two lines. If you want to use the matrix interface, the last two lines are needed as well.
Creating the environment
In this example, we use the default environment. For non-default environments please consult How do I manage Gurobi environments in gurobipy?
Creating the model
In the Python interface
The first step in our example is to create a model. A Gurobi model holds a single optimization problem. It consists of a set of variables, a set of constraints, and the associated attributes (variable bounds, objective coefficients, variable integrality types, constraint senses, constraint right-hand side values, etc.). We start this example with an empty model object:
# Create a new model m = gp.Model("mip1")
This gp.Model takes the desired model name as its argument.
In the Python matrix interface
The first step in our example is to create a model. We start with an empty model object:
# Create a new model m = gp.Model("matrix1")
This gp.Model takes the desired model name as its argument.
Adding variables to the model
In the Python interface
The next step in our example is to add variables to the model.
# Create variables x = m.addVar(vtype=GRB.BINARY, name="x") y = m.addVar(vtype=GRB.BINARY, name="y") z = m.addVar(vtype=GRB.BINARY, name="z")
Variables are added through the Model.addVar method on a model object (or Model.addVars if you wish to add more than one at a time). A variable is always associated with a particular model.
Python allows you to pass arguments by position or by name. We've passed them by name here. Each variable gets a type (binary), and a name. We use the default values for the other arguments. Please refer to the online help (help(gp.Model.addVar) in the Gurobi Shell) for further details on Model.addVar.
In the Python matrix interface
The next step adds a matrix variable to the model:
# Create variables x = m.addMVar(shape=3, vtype=GRB.BINARY, name="x")
A matrix variable is added through the Model.addMVar method on a model object. In this case the matrix variable consists of a 1-D array of 3 binary variables. Variables are always associated with a particular model.
Adding constraints to the model
In the Python interface
The next step in the example is to add the linear constraints. The first constraint is added here:
# Add constraint: x + 2 y + 3 z <= 4 m.addConstr(x + 2 * y + 3 * z <= 4, "c0")
As with variables, constraints are always associated with a specific model. They are created using the Model.addConstr method on the model object.
We again use overloaded arithmetic operators to build linear expressions. The comparison operators are also overloaded to make it easier to build constraints.
The second argument to Model.addConstr gives the (optional) constraint name.
Again, this simple example builds the linear expression for the constraint in a single statement using an explicit list of terms. More complex programs will typically build the expression incrementally.
The second constraint is created in a similar manner:
# Add constraint: x + y >= 1 m.addConstr(x + y >= 1, "c1")
In the Python matrix interface
The next step in the example is to add our two linear constraints. This is done by building a sparse matrix that captures the constraint matrix:
# Build (sparse) constraint matrix val = np.array([1.0, 2.0, 3.0, -1.0, -1.0]) row = np.array([0, 0, 0, 1, 1]) col = np.array([0, 1, 2, 0, 1]) A = sp.csr_matrix((val, (row, col)), shape=(2, 3))
The matrix has two rows, one for each constraint, and three columns, one for each variable in our matrix variable. The row and col arrays gives the row and column indices for the 5 non-zero values in the sparse matrix, respectively. The val array gives the numerical values. Note that we multiply the greater-than constraint by -1 to transform it to a less-than constraint.
We also capture the right-hand side in a NumPy array:
# Build rhs vector rhs = np.array([4.0, -1.0])
We then use the overloaded @ operator to build a linear matrix expression, and then use the overloaded less-than-or-equal operator to add two constraints (one for each row in the matrix expression) using Model.addConstr:
# Add constraints m.addConstr(A @ x <= rhs, name="c")
Setting the objective
In the Python interface
The next step in the example is to set the optimization objective:
# Set objective m.setObjective(x + y + 2 * z, GRB.MAXIMIZE)
The objective is built here using overloaded operators and calling Model.setObjective. The Python API overloads the arithmetic operators to allow you to build linear and quadratic expressions involving Gurobi variables.
The second argument indicates that the sense is maximization.
Note that while this simple example builds the objective in a single statement using an explicit list of terms, more complex programs will typically build it incrementally. For example:
obj = gp.LinExpr() obj += x obj += y obj += 2 * z m.setObjective(obj, GRB.MAXIMIZE)
In the Python matrix interface
The next step is to set the optimization objective:
# Set objective obj = np.array([1.0, 1.0, 2.0]) m.setObjective(obj @ x, GRB.MAXIMIZE)
The objective is built here by computing a dot product between a constant vector and our matrix variable using the overloaded @ operator. Note that the constant vector must have the same length as our matrix variable.
The second argument indicates that the sense is maximization.
Optimizing the model
Now that the model has been built, the next step is to optimize it:
# Optimize model m.optimize()
This routine performs the optimization and populates several internal model attributes (including the status of the optimization, the solution, etc.).
Reporting the results
In the Python interface
Once the optimization is complete, we can query the values of the attributes. In particular, we can query the VarName and X variable attributes to obtain the name and solution value for each variable:
for v in m.getVars(): print('%s %g' % (v.VarName, v.X))
We can also query the ObjVal attribute on the model to obtain the objective value for the current solution:
print('Obj: %g' % m.ObjVal)
The names and types of all model, variable, and constraint attributes can be found under the Attributes section of the documentation. Type help(GRB.Attr) in the Gurobi Shell for details.
In the Python matrix interface
Once the optimization is complete, we can query the values of the attributes. In particular, we can query the X variable attributes to obtain the solution value for each variable:
print(x.X)
We can also query the ObjVal attribute on the model to obtain the objective value for the current solution:
print('Obj: %g' % m.ObjVal)
The names and types of all model, variable, and constraint attributes can be found in the online Python documentation. Type help(GRB.Attr) in the Gurobi Shell for details.
Cleaning up
In our other interfaces, we encourage you to explicitly dispose of your Gurobi environment when you are done using it in order to release the associated resources. Our recommendation in the Python interface is a bit more nuanced.
Most Gurobi Python programs use the default environment, which is automatically created when you first construct a Gurobi Model object and automatically disposed when your program ends. You can call disposeDefaultEnv() to dispose of it manually, but if you want detailed control of environments (for example, if you are using a Compute Server or the Gurobi Instant Cloud), we recommend that you work with explicit environment objects instead.
Please refer to the mip1_remote.py example for details on how you would do this.
Error reporting
Errors in the Gurobi Python interface are handled through the Python exception mechanism. In the example, all Gurobi statements are enclosed inside a try block, and any associated errors would be caught by the except block:
try:
# Formulate and solve model
except gp.GurobiError as e: print('Error code ' + str(e.errno) + ': ' + str(e)) except AttributeError: print('Encountered an attribute error')
Building and running the example
You can simply use the Gurobi interactive shell to run the examples by changing to the Gurobi Python example directory (<installdir>/examples/python) and issuing the following command::
gurobi.sh mip1.py
Please note that starting with version 11.0.2, the Gurobi Interactive Shell has been deprecated.
If you have installed gurobipy into an existing Python installation as described in the installation options, you should simply run these examples using this Python interpreter of your choice by issuing the command
python mip1.py
Comments
0 comments
Article is closed for comments.