Several of the Gurobi examples build models from scratch. We start by
focusing on two,
sos, which build very simple
models to illustrate the basic process.
Typically, the first step in building a model is to create an empty
model. This is done using the
GRBnewmodel function in C:
error = GRBnewmodel(env, &model, "mip1", 0, NULL, NULL, NULL, NULL);You can optionally create a set of variables when you create the model, as well as specifying bounds, objective coefficients, and names for these variables. These examples add new variables separately.
In C++, C#, and Java, you create a new model using the
constructor. In Java, this looks like:
GRBModel model = new GRBModel(env);In Python, the class is called
Model, and its constructor is similar to the
GRBModelconstructor for C++ and Java.
Once the model has been created, the typical next step is to add
variables. In C, you use the
GRBaddvars function to add
one or more variables:
error = GRBaddvars(model, 3, 0, NULL, NULL, NULL, obj, NULL, NULL, vtype, NULL);In C++, Java, and Python, you use the
addVarmethod on the
AddVarin C#). In Java, this looks like:
GRBVar x = model.addVar(0.0, 1.0, -1.0, GRB.BINARY, "x");The new variable's lower bound, upper bound, objective coefficient, type, and name are specified as arguments. In C++ and Python, you can omit these arguments and use default values; see the Gurobi Reference Manual for details.
After adding variables to the model, the next step is to call the
update function (
GRBupdatemodel() in C,
in C++, Java, and Python,
model.Update() in C#). Model
modifications are performed in a lazy fashion in the Gurobi
optimizer -- they don't affect the model until the next update or
optimize call. You cannot utilize the new variables (e.g., in
constraints) until you call the update function.
The next step is to add constraints to the model. Linear constraints
are added through the
GRBaddconstr function in C:
error = GRBaddconstr(model, 3, ind, val, GRB_LESS_EQUAL, 4.0, "c0");To add a linear constraint in C, you must specify a list of variable indices and coefficients for the left-hand side, a sense for the constraint (e.g.,
GRB_LESS_EQUAL), and a right-hand side constant. You can also give the constraint a name; if you omit the name, Gurobi will assign a default name for the constraint.
In C++, C#, Java, and Python, you build a linear constraint by first building linear expressions for the left- and right-hand sides. In Java, which doesn't support operator overloading, you build an expression as follows:
GRBLinExpr expr = new GRBLinExpr(); expr.addTerm(1.0, x); expr.addTerm(2.0, y); expr.addTerm(3.0, z);You then use the
addConstrmethod on the
Modelobject to add a constraint using these linear expressions for the left- and right-hand sides:
model.addConstr(expr, GRB_LESS_EQUAL, 4.0, "c0");
For C++, C#, and Python, the standard mathematical operators such as +, *, <= have been overloaded so that the linear expression resembles a traditional mathematical expression. In C++:
model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
Adding an special ordered set (SOS) constraint is similar. In C, you add one
or more SOS constraint using the
error = GRBaddsos(model, 1, 2, sostype, sosbeg, sosind, soswt);For each SOS constraint, you must specify a list of members and a weight for each member.
In C++, C#, Java, and Python, you use the
addSOS method on the
model.addSOS(sosv1, soswt1, GRB.SOS_TYPE1);
Once the model has been built, the typical next step is to optimize it
GRBoptimize in C,
model.optimize in C++,
Java, and Python, or
model.Optimize in C#). You can then query
X attribute on the variables to retrieve the solution (and
VarName attribute to retrieve the variable name for each
variable). In C, the
X attribute is retrieved as follows:
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, sol);
cout << x.get(GRB_StringAttr_VarName) << " " << x.get(GRB_DoubleAttr_X) << endl; cout << y.get(GRB_StringAttr_VarName) << " " << y.get(GRB_DoubleAttr_X) << endl; cout << z.get(GRB_StringAttr_VarName) << " " << z.get(GRB_DoubleAttr_X) << endl;
System.out.println(x.get(GRB.StringAttr.VarName) + " " + x.get(GRB.DoubleAttr.X)); System.out.println(y.get(GRB.StringAttr.VarName) + " " + y.get(GRB.DoubleAttr.X)); System.out.println(z.get(GRB.StringAttr.VarName) + " " + z.get(GRB.DoubleAttr.X));
Console.WriteLine(x.Get(GRB.StringAttr.VarName) + " " + x.Get(GRB.DoubleAttr.X)); Console.WriteLine(y.Get(GRB.StringAttr.VarName) + " " + y.Get(GRB.DoubleAttr.X)); Console.WriteLine(z.Get(GRB.StringAttr.VarName) + " " + z.Get(GRB.DoubleAttr.X));
for v in m.getVars(): print v.varName, v.x
When querying or modifying attribute values for an array of
constraints or variables, it is generally more efficient to perform
the action on the whole array at once. This is quite natural in the C
interface, where most of the attribute routines take array arguments.
In the C++, C#, and Java interface, you can use the
set methods on the
Model object to work directly with
arrays of attribute values. In the
sudoku Java example, this
is done as follows:
double x = model.get(GRB.DoubleAttr.X, vars);Note that the Python interface doesn't have array query routines. Python is an interpreted language, and overheads associated with queries on individual attributes are a small contributor to overall runtime.