Blog

Switching from CPLEX

Transform your complex business challenge into an optimized plan of action—powered by Gurobi’s world-leading solver technology.

Blog

Switching from CPLEX

Transform your complex business challenge into an optimized plan of action—powered by Gurobi’s world-leading solver technology.

Blog

Switching from CPLEX

Transform your complex business challenge into an optimized plan of action—powered by Gurobi’s world-leading solver technology.

Migrating from CPLEX™ includes:

  1. Building the model

  2. Setting Solver Parameters

  3. Computing and Extracting the Solution

In addition, you can also see a list of code examples, across a range of programming languages, on our code examples page.

Gurobi vs. CPLEX™: Building the Model

Any program that uses optimization must start by building an optimization model. While the exact details of how models are built depend on the programming language, the general concepts are similar in all of our supported languages. We'll focus on the concepts, and provide details when appropriate. The first two steps in describing an optimization problem, in both CPLEX and Gurobi, are to create an environment and a model. These are objects in our object-oriented interfaces, created using the GRBEnv and GRBModel constructors, respectively. They are pointers in our C interface, returned by our GRBloadenv() and GRBnewmodel() routines. The next step is generally to list your decision variables. This is done using the GRBaddvar() routine in C, and the addVar() method in our object-oriented interfaces. You can add one variable at a time, or you can add multiple variables (using GRBaddvars() or addVars()). We generally find it more convenient to add one variable at a time, and there is no performance penalty for doing so, but you may want to add multiple variables if your CPLEX program already does so.

One difference between Gurobi vs. CPLEX is that we use a "lazy update" approach. After making changes to a model, you need to call GRBupdatemodel/GRBModel.update in order for those changes to be visible. To be more specific, you'll need to call "update" after adding variables to the model, in order to use those variables in constraints. Our lazy update approach makes it easier and more efficient to build or modify a model, since you have complete control over when the actual changes take place. However, this difference between our interface and the CPLEX interface is something you'll need to remember. Decision variables have a number of attributes, including variable type (continuous, binary, etc.), lower bound, upper bound, etc. You have two choices for specifying these. The first is to input the desired attribute values when you create the variable (i.e., as arguments to addVar()). The second is to modify the attributes after the variable has been added to the model, using one of the various Gurobi set routines (e.g., GRBsetintattr() in C, GRBVar.set() in C++). Attributes are an important concept in the Gurobi interface. Rather than providing dozens of different routines for accessing and modifying the various attributes of a model, as is done in CPLEX, we handle them through a single interface. To give an example, below is the command, shown in a range of languages, you would use to change the upper bound on variable x to 1.0:

Language

Command

C

GRBsetdblattrelement(model, GRB_DBL_ATTR_UB, x_index, 1.0);

C++

x.set(GRB_DoubleAttr_UB, 1.0);

C#

x.Set(GRB.DoubleAttr.UB, 1.0);

Java

x.set(GRB.DoubleAttr.UB, 1.0);

Python

x.ub = 1.0

Similarly, to change the lower bound:

Language

Command

C

GRBsetdblattrelement(model, GRB_DBL_ATTR_LB, x_index, 1.0);

C++

x.set(GRB_DoubleAttr_LB, 1.0);

C#

x.Set(GRB.DoubleAttr.LB, 1.0);

Java

x.set(GRB.DoubleAttr.LB, 1.0);

Python

x.lb = 1.0

This attribute interface serves to both unify and simplify the various Gurobi interfaces. In general, if you are searching for a routine to match a CPLEX get/set routine, you are likely to find that capability in our attribute interface.

The next step in building an optimization model is generally to describe the linear constraints on your decision variables. Depending on the interface you are using, you can describe these constraints using a single constraint matrix, by adding groups of constraints, or by adding constraints one at a time. Again, we find it more convenient to add constraints one at a time, but we understand that it may simplify migration if you mimic your existing CPLEX approach. You will generally only use a single constraint matrix to specify your constraints if you are using the Gurobi C interface. You would do this with the GRBloadmodel() routine. The arguments to this routine are quite similar to the arguments to the CPLEX CPXcopylp() routine. Note that you can also add constraints individually in our C interface, using GRBaddconstr(). In our object-oriented interfaces, you can add individual linear constraints using the addConstr() method. The details depend on the language you are using. Our C++, .NET, and Python interfaces allow operator overloading, so you can add a linear constraint as follows:

Language

Command

C

int ind[ ] = {1, 3, 4};
double val[ ] = {1.0, 2.0, 1.0};
error = GRBaddconstr(model, 3, ind, val, GRB_EQUAL, 1.0, “New”);

C++

model.addConstr(x + y + 2*z <= 2);

C#

model.AddConstr(x + y + 2*z <= 2);

Python

model.addConstr(x + y + 2*z <= 2)

You can also build linear expression (GRBExpr) objects, add linear terms to these expressions (expr.addTerm()), and then add constraints using these expressions. In Java:

GRBLinExpr expr = new GRBLinExpr();

expr.addTerm(1.0, x); expr.addTerm(1.0, y); expr.addTerm(2.0, z);

model.addConstr(expr, GRB.LESS_EQUAL, 2.0);

Your model might contain other constraint types, including Special Ordered Set (SOS) constraints or quadratic constraints. The Gurobi interface contains routines that are quite similar to those in the CPLEX interface for each of these. We encourage you to browse our examples for details.

Setting Solver Parameters

When migrating an optimization model from CPLEX to Gurobi, you may need to set certain Gurobi parameters to match the parameters you have modified in CPLEX. One important point we'd like to make is that you shouldn't assume that you'll need to find a matching Gurobi parameter for every CPLEX parameter you've changed. Gurobi and CPLEX use different strategies and algorithms. Gurobi strategy tuning may differ from the CPLEX tuning you've done, and often it may not be necessary at all. We recommend that you start with default settings, and only change parameters when you observe specific behavior that you'd like to modify. The following table gives a high-level mapping for the most commonly used CPLEX parameters:

CPLEX parameter (C API)

Gurobi Parameter

CPX_PARAM_BARALG

BarHomogeneous

CPX_PARAM_BARCROSSALG

Crossover

CPX_PARAM_BAREPCOMP

BarConvTol

CPX_PARAM_BARQCPEPCOMP

BarQCPConvTol

CPX_PARAM_BRDIR

BranchDir

CPX_PARAM_CLIQUES

CliqueCuts

CPX_PARAM_COVERS

CoverCuts

CPX_PARAM_CUTPASS

CutPasses

CPX_PARAM_EPGAP

MIPGap

CPX_PARAM_EPAGAP

MIPGapAbs

CPX_PARAM_EPINT

IntFeasTol

CPX_PARAM_EPOPT

OptimalityTol

CPX_PARAM_FLOWCOVERS

FlowCoverCuts

CPX_PARAM_FPHEUR

PumpPasses

CPX_PARAM_FRACPASS

GomoryPasses

CPX_PARAM_GUBCOVERS

GUBCoverCuts

CPX_PARAM_HEURFREQ

Heuristics

CPX_PARAM_INTSOLLIM

SolutionLimit

CPX_PARAM_LPMETHOD

Method

CPX_PARAM_MIPEMPHASIS

MIPFocus

CPX_PARAM_MIRCUTS

MIRCuts

CPX_PARAM_NODEFILEIND

NodeFileStart

CPX_PARAM_POLISHAFTEREPGAP

ImproveStartGap*

CPX_PARAM_POLISHAFTERTIME

ImproveStartTime*

CPX_PARAM_PREDUAL

PreDual

CPX_PARAM_PREIND

Presolve

CPX_PARAM_RINSHEUR

RINS

CPX_PARAM_STARTALG

Method

CPX_PARAM_SUBALG

NodeMethod

CPX_PARAM_THREADS

Threads

CPX_PARAM_TIMELIMIT

TimeLimit

CPX_PARAM_VARSEL

VarBranch

CPX_PARAM_ZEROHALFCUTS

ZeroHalfCuts

*Gurobi uses a different algorithm, but achieves a similar result. Again, this is just a partial list of the parameters you might be using in CPLEX. If you are modifying a parameter that isn't on this list, we encourage you to browse the list of Gurobi parameters in our Reference Manual

Once you know which parameters you would like to change, the code required to change them is straightforward. In C, you call GRBsetintparam/GRBsetdblparam/GRBsetstringparam. In our object-oriented interfaces, you call the set() method on the GRBEnv object. One point that sometimes trips people up when migrating from CPLEX to Gurobi is that Gurobi gives each model its own copy of a Gurobi environment, thus allowing each model to have its own parameter settings. In CPLEX, all models use the same parameter values. The simplest approach to managing this is to set parameters for a model as follows:

Language

Command

C

error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONLIMIT, 1);

C++

model.getEnv().set(GRB_IntParam_SolutionLimit, 1);

C#

model.GetEnv().Set(GRB.IntParam.SolutionLimit, 1);

Java

model.getEnv().set(GRB.IntParam.SolutionLimit, 1);

Python

model.params.solutionLimit = 1

Computing and Extracting the Solution

Once you have formulated your optimization model and set solver parameters, the last step is to compute a solution. You do this by calling GRBoptimize() in C, or GRBModel.optimize() in our object-oriented interfaces. The optimization will complete when one of your requested termination conditions (optimality gap, time limit, solution limit, etc.) are met. You should always check the status of the optimization once it completes. Again, rather than providing dozens of get/set routines, we return the status as an attribute of the model. You query it with the appropriate attribute get routine. For example:

Language

Command

C

error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &status);
if (status == GRB_OPTIMAL) …

C++

if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) …

C#

if (model.Get(GRB.IntAttr.Status) == GRB.OPTIMAL) …

Java

if (model.get(GRB.IntAttr.Status) == GRB.OPTIMAL) …

Python

if model.status == GRB.OPTIMAL: …

The computed values for the decision variables are also attributes:

Language

Command

C

error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, x_index, &xvalue);
printf(“Value for variable x is %g\n”, xvalue);

C++

cout << “Value for variable x is: ” << x.get(GRB_DoubleAttr_X) << endl;

C#

Console.WriteLine(“Value for variable x is: ” + x.Get(GRB.DoubleAttr.X));

Java

System.out.println(“Value for variable x is: ” + x.get(GRB.DoubleAttr.X));

Python

print(’Value for variable x is:‘,x.x)

You can also retrieve other solution information, including the objective value, constraint slacks, and dual variables (when available), all using the attribute interface. Let us reiterate that if you are looking to map a CPLEX get/set function to Gurobi, you will probably find its equivalent in our attribute interface. Of course, finding a proven optimal solution isn’t the only possible outcome. For example, you may find that your model is infeasible. If you are using the CPLEX conflict refiner to help diagnose infeasibility, Gurobi offers the same functionality through our Irreducible Inconsistent Subsystem (IIS) routines (GRBcomputeIIS() in C; model.computeIIS() in the object-oriented interfaces). If you are using the CPLEX feasopt feature to find a minimum-cost relaxation of the constraints in the model, you can use the Gurobi feasRelax feature (GRBfeasrelax() in C; model.feasRelax in the object-oriented interfaces).

Conclusion

We encourage you to browse the Gurobi examples in the Example Tour to get a more concrete sense of how the Gurobi interfaces are structured. Customers have told us that, once you understand a few key concepts, the migration process is straightforward and typically quite quick.

Start Solving with Gurobi

Try Gurobi on your own optimization models and see how it performs on real decision problems.

Start Solving with Gurobi

Try Gurobi on your own optimization models and see how it performs on real decision problems.

Start Solving with Gurobi

Try Gurobi on your own optimization models and see how it performs on real decision problems.