In addition, you can also see a list of code examples, across a range of programming languages, on our code examples page.
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.
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 |
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).
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.
GUROBI NEWSLETTER
Latest news and releases
Choose the evaluation license that fits you best, and start working with our Expert Team for technical guidance and support.
Request free trial hours, so you can see how quickly and easily a model can be solved on the cloud.