C++ API Overview
This section documents the Gurobi C++ interface. This manual begins with a quick overview of the classes exposed in the interface and the most important methods on those classes. It then continues with a comprehensive presentation of all of the available classes and methods.
If you are new to the Gurobi Optimizer, we suggest that you start with the Quick Start Guide or the Example Tour. These documents provide concrete examples of how to use the classes and methods described here.
The first step in using the Gurobi C++ interface is to create an environment object. Environments are represented using the GRBEnv class. An environment acts as the container for all data associated with a set of optimization runs. You will generally only need one environment object in your program.
For more advanced use cases, you can use an empty environment to create an uninitialized environment and then, programmatically, set all required options for your specific requirements. For further details see the Environment section.
You can create one or more optimization models within an environment. Each model is represented as an object of class GRBModel. A model consists of a set of decision variables (objects of class GRBVar), a linear or quadratic objective function on those variables (specified using GRBModel::setObjective), and a set of constraints on these variables (objects of class GRBConstr, GRBQConstr, GRBSOS, or GRBGenConstr). Each variable has an associated lower bound, upper bound, and type (continuous, binary, etc.). Each linear or quadratic constraint has an associated sense (less-than-or-equal, greater-than-or-equal, or equal), and right-hand side value. Refer to this section for more information on variables, constraints, and objectives.
Linear constraints are specified by building linear expressions (objects of class GRBLinExpr), and then specifying relationships between these expressions (for example, requiring that one expression be equal to another). Quadratic constraints are built in a similar fashion, but using quadratic expressions (objects of class GRBQuadExpr) instead.
An optimization model may be specified all at once, by loading the model from a file (using the appropriate GRBModel constructor), or built incrementally, by first constructing an empty object of class GRBModel and then subsequently calling GRBModel::addVar or GRBModel::addVars to add additional variables, and GRBModel::addConstr, GRBModel::addQConstr, GRBModel::addSOS, or any of the GRBModel::addGenConstrXxx methods to add constraints. Models are dynamic entities; you can always add or remove variables or constraints.
We often refer to the class of an optimization model. A model with a linear objective function, linear constraints, and continuous variables is a Linear Program (LP). If the objective is quadratic, the model is a Quadratic Program (QP). If any of the constraints are quadratic, the model is a Quadratically-Constrained Program (QCP). We will sometimes refer to a few special cases of QCP: QCPs with convex constraints, QCPs with non-convex constraints, bilinear programs, and Second-Order Cone Programs (SOCP). If the model contains any integer variables, semi-continuous variables, semi-integer variables, Special Ordered Set (SOS) constraints, or general constraints, the model is a Mixed Integer Program (MIP). We'll also sometimes discuss special cases of MIP, including Mixed Integer Linear Programs (MILP), Mixed Integer Quadratic Programs (MIQP), Mixed Integer Quadratically-Constrained Programs (MIQCP), and Mixed Integer Second-Order Cone Programs (MISOCP). The Gurobi Optimizer handles all of these model classes.
Solving a Model
Once you have built a model, you can call GRBModel::optimize to compute a solution. By default, optimize will use the concurrent optimizer to solve LP models, the barrier algorithm to solve QP models with convex objectives and QCP models with convex constraints, and the branch-and-cut algorithm otherwise. The solution is stored in a set of attributes of the model. These attributes can be queried using a set of attribute query methods on the GRBModel, GRBVar, GRBConstr, GRBQConstr, GRBSOS, and GRBGenConstr classes.
The Gurobi algorithms keep careful track of the state of the model, so calls to GRBModel::optimize will only perform further optimization if relevant data has changed since the model was last optimized. If you would like to discard previously computed solution information and restart the optimization from scratch without changing the model, you can call GRBModel::reset.
After a MIP model has been solved, you can call GRBModel::fixedModel to compute the associated fixed model. This model is identical to the original, except that the integer variables are fixed to their values in the MIP solution. If your model contains SOS constraints, some continuous variables that appear in these constraints may be fixed as well. In some applications, it can be useful to compute information on this fixed model (e.g., dual variables, sensitivity information, etc.), although you should be careful in how you interpret this information.
Multiple Solutions, Objectives, and Scenarios
By default, the Gurobi Optimizer assumes that your goal is to find one proven optimal solution to a single model with a single objective function. Gurobi provides the following features that allow you to relax these assumptions:
- Solution Pool: Allows you to find more solutions.
- Multiple Scenarios: Allows you to find solutions to multiple, related models.
- Multiple Objectives: Allows you to specify multiple objective functions and control the trade-off between them.
You have a few options if a model is found to be infeasible. You can try to diagnose the cause of the infeasibility, attempt to repair the infeasibility, or both. To obtain information that can be useful for diagnosing the cause of an infeasibility, call GRBModel::computeIIS to compute an Irreducible Inconsistent Subsystem (IIS). This method can be used for both continuous and MIP models, but you should be aware that the MIP version can be quite expensive. This method populates a set of IIS attributes.
To attempt to repair an infeasibility, call GRBModel::feasRelax to compute a feasibility relaxation for the model. This relaxation allows you to find a solution that minimizes the magnitude of the constraint violation.
Querying and Modifying Attributes
Most of the information associated with a Gurobi model is stored in a
set of attributes. Some attributes are associated with the variables
of the model, some with the constraints of the model, and some with
the model itself. To give a simple example, solving an optimization
model causes the
X variable attribute to be populated.
Attributes such as
X that are computed by the Gurobi optimizer
cannot be modified directly by the user, while others, such as the
variable lower bound (the
LB attribute) can.
Attributes are queried using
and modified using
Attributes are grouped into a set of enums by type
set() methods are overloaded, so the
type of the attribute determines the type of the returned value.
constr.get(GRB.DoubleAttr.RHS) returns a double,
constr.get(GRB.CharAttr.Sense) returns a char.
If you wish to retrieve attribute values for a set of variables or constraints, it is usually more efficient to use the array methods on the associated GRBModel object. Method GRBModel::get includes signatures that allow you to query or modify attribute values for arrays of variables or constraints.
The full list of attributes can be found in the Attributes section.
Additional Model Modification Information
Most modifications to an existing model are done through the attribute interface (e.g., changes to variable bounds, constraint right-hand sides, etc.). The main exceptions are modifications to the constraint matrix and the objective function.
The constraint matrix can be modified in a few ways. The first is to call the chgCoeffs method on a GRBModel object to change individual matrix coefficients. This method can be used to modify the value of an existing non-zero, to set an existing non-zero to zero, or to create a new non-zero. The constraint matrix is also modified when you remove a variable or constraint from the model (through the GRBModel::remove method). The non-zero values associated with the deleted constraint or variable are removed along with the constraint or variable itself.
The model objective function can also be modified in a few ways. The
easiest is to build an expression that captures the objective function
(a GRBLinExpr or
and then pass that expression to method
If you wish to modify the objective, you can simply call
setObjective again with a new
For linear objective functions, an alternative to
is to use the
Obj variable attribute to modify individual
linear objective coefficients.
If your variables have piecewise-linear objectives, you can specify
them using the GRBModel::setPWLObj
method. Call this method once for each relevant variable. The Gurobi
simplex solver includes algorithmic support for convex
piecewise-linear objective functions, so for continuous models you
should see a substantial performance benefit from using this feature.
To clear a previously specified piecewise-linear objective function,
simply set the
Obj attribute on the corresponding variable to
One important item to note about model modification in the Gurobi optimizer is that it is performed in a lazy fashion, meaning that modifications don't affect the model immediately. Rather, they are queued and applied later. If your program simply creates a model and solves it, you will probably never notice this behavior. However, if you ask for information about the model before your modifications have been applied, the details of the lazy update approach may be relevant to you.
As we just noted, model modifications (bound changes, right-hand side changes, objective changes, etc.) are placed in a queue. These queued modifications can be applied to the model in three different ways. The first is by an explicit call to GRBModel::update. The second is by a call to GRBModel::optimize. The third is by a call to GRBModel::write to write out the model. The first case gives you fine-grained control over when modifications are applied. The second and third make the assumption that you want all pending modifications to be applied before you optimize your model or write it to disk.
Why does the Gurobi interface behave in this manner? There are a few reasons. The first is that this approach makes it much easier to perform multiple modifications to a model, since the model remains unchanged between modifications. The second is that processing model modifications can be expensive, particularly in a Compute Server environment, where modifications require communication between machines. Thus, it is useful to have visibility into exactly when these modifications are applied. In general, if your program needs to make multiple modifications to the model, you should aim to make them in phases, where you make a set of modifications, then update, then make more modifications, then update again, etc. Updating after each individual modification can be extremely expensive.
If you forget to call update, your program won't crash. Your query will simply return the value of the requested data from the point of the last update. If the object you tried to query didn't exist then, you'll get a NOT_IN_MODEL exception instead.
The semantics of lazy updates have changed since earlier Gurobi versions. While the vast majority of programs are unaffected by this change, you can use the UpdateMode parameter to revert to the earlier behavior if you run into an issue.
The Gurobi optimizer provides a set of parameters that allow you to control many of the details of the optimization process. Factors like feasibility and optimality tolerances, choices of algorithms, strategies for exploring the MIP search tree, etc., can be controlled by modifying Gurobi parameters before beginning the optimization. Parameters can be of type int, double, or string.
The simplest way to set parameters is through the GRBModel::set method on the model object. Similarly, parameter values can be queried with GRBModel::get.
Parameters can also be set on the Gurobi environment object, using GRBEnv::set. Note that each model gets its own copy of the environment when it is created, so parameter changes to the original environment have no effect on existing models.
You can read a set of parameter settings from a file using GRBEnv::readParams, or write the set of changed parameters using GRBEnv::writeParams.
We also include an automated parameter tuning tool that explores many different sets of parameter changes in order to find a set that improves performance. You can call GRBModel::tune to invoke the tuning tool on a model. Refer to the parameter tuning tool section for more information.
The full list of Gurobi parameters can be found in the Parameters section.
Memory management must always be considered in C++ programs. In particular, the Gurobi library and the user program share the same C++ heap, so the user must be aware of certain aspects of how the Gurobi library uses this heap. The basic rules for managing memory when using the Gurobi optimizer are as follows:
- As with other dynamically allocated C++ objects,
GRBModel objects should be freed
using the associated destructors. In other words, given a
m, you should call
delete mwhen you are no longer using
- Objects that are associated with a model (e.g., GRBConstr, GRBQConstr, GRBSOS, GRBGenConstr, and GRBVar objects) are managed by the model. In particular, deleting a model will delete all of the associated objects. Similarly, removing an object from a model (using GRBModel::remove) will also delete the object.
- Some Gurobi methods return an array of objects or values.
returns an array of
GRBVarobjects. It is the user's responsibility to free the returned array (using
delete). The reference manual indicates when a method returns a heap-allocated result.
One consequence of these rules is that you must be careful not to use an object once it has been freed. This is no doubt quite clear for environments and models, where you call the destructors explicitly, but may be less clear for constraints and variables, which are implicitly deleted when the associated model is deleted.
Monitoring Progress - Logging and Callbacks
Progress of the optimization can be monitored through Gurobi logging. By default, Gurobi will send output to the screen. A few simple controls are available for modifying the default logging behavior. If you would like to direct output to a file as well as to the screen, specify the log file name in the GRBEnv constructor. You can modify the LogFile parameter if you wish to redirect the log to a different file after creating the environment object. The frequency of logging output can be controlled with the DisplayInterval parameter, and logging can be turned off entirely with the OutputFlag parameter. A detailed description of the Gurobi log file can be found in the Logging section.
More detailed progress monitoring can be done through the
allows you to receive a periodic callback from the Gurobi optimizer.
You do this by sub-classing
the GRBCallback abstract class,
and writing your own
callback() method on this class. You can
from within the callback to obtain additional information about the
state of the optimization.
Modifying Solver Behavior - Callbacks
Callbacks can also be used to modify the behavior of the Gurobi optimizer. The simplest control callback is GRBCallback::abort, which asks the optimizer to terminate at the earliest convenient point. Method GRBCallback::setSolution allows you to inject a feasible solution (or partial solution) during the solution of a MIP model. Methods GRBCallback::addCut and GRBCallback::addLazy allow you to add cutting planes and lazy constraints during a MIP optimization, respectively. Method GRBCallback::stopOneMultiObj allows you to interrupt the optimization process of one of the optimization steps in a multi-objective MIP problem without stopping the hierarchical optimization process.
Gurobi Compute Server enables programs to offload optimization computations onto dedicated servers. The Gurobi Cluster Manager adds a number of additional capabilities on top of this. One important one, batch optimization, allows you to build an optimization model with your client program, submit it to a Compute Server cluster (through the Cluster Manager), and later check on the status of the model and retrieve its solution. You can use a Batch object to make it easier to work with batches. For details on batches, please refer to the Batch Optimization section.
All of the methods in the Gurobi C++ library can throw an exception
of type GRBException. When an
exception occurs, additional information on the error can be obtained
by retrieving the error code (using method
GRBException::getErrorCode), or by retrieving the exception message
The list of possible error return codes can be found in
the Error Codes section.