Switching from CPLEX

This page covers migrating from CPLEX™ to Gurobi. While the steps are similar, if you are interested in migrating from XPRESS to Gurobi, please visit our switching from XPRESS page. Also, if you are using OPL, pleae visit our switching from OPL page.

This page covers three topics:

  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.


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 and 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.