This section will work through a simple example in order to illustrate the use of the Gurobi .NET API. The example builds a simple Mixed Integer Programming model, optimizes it, and outputs the optimal objective value.
A variety of books and websites are available for learning the language (for example, the Microsoft online C# documentation).
While C# programs have historically only run on Windows machines, Microsoft has released an open-source, cross-platform .NET implementation (.NET Core) that allows you to run C# programs on Linux and macOS as well. You will find the Gurobi library that supports .NET Core 2 in <installdir>/lib/gurobi120.netstandard20.dll. For more information on how to obtain and use .NET Core, please refer to the .NET Tutorial.
The example
Our example optimizes the following model:
maximize | x | + | y | + | 2 z | ||
subject to | x | + | 2 y | + | 3 z | ≤ | 4 |
x | + | y | ≥ | 1 | |||
x, y, z binary |
In the following sections, we will walk through the example, line by line, to understand how it achieves the desired result of optimizing the above model.
The complete source code for our example can be found in:
- Online: Example mip1_cs.cs
- Distribution: <installdir>/examples/c#/mip1_cs.cs
Importing the Gurobi functions and classes
The example begins by importing the Gurobi namespace (using Gurobi). Gurobi .NET applications should always start with this line.
Creating the environment
The first executable statement in our example obtains a Gurobi environment (using the GRBEnv constructor):
// Create an empty environment, set options and start GRBEnv env = new GRBEnv(true); env.Set("LogFile", "mip1.log"); env.Start();
In this case, we create an empty environment, select a log file to use (using GRBEnv.Set), and start the environment for later use (using GRBEnv.Start).
Later calls to create an optimization model will always require an active environment, so environment creation is typically the first step in a Gurobi application.
Creating the model
Once an environment has been created, the next step is to create a model. A Gurobi model holds a single optimization problem. It consists of a set of variables, a set of constraints, and the associated attributes (variable bounds, objective coefficients, variable types, constraint senses, constraint right-hand side values, etc.). The first step towards building a model that contains all of this information is to create an empty model object:
// Create empty model GRBModel model = new GRBModel(env);
The GRBModel constructor takes the previously created environment as its argument.
Adding variables to the model
The next step in our example is to add variables to the model.
// Create variables GRBVar x = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "x"); GRBVar y = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "y"); GRBVar z = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "z");
Variables are added through the GRBModel.AddVar method on a model object (or GRBModel.AddVars if you wish to add more than one at a time). A variable is always associated with a particular model.
The first and second arguments to the GRBModel.AddVar call are the variable lower and upper bounds, respectively. The third argument is the linear objective coefficient (zero here - we'll set the objective later). The fourth argument is the variable type. Our variables are all binary in this example. The final argument is the name of the variable.
The GRBModel.AddVar method has been overloaded to accept several different argument lists. Please refer to the Gurobi Reference Manual for further details.
Adding constraints to the model
The next step in the example is to add the linear constraints:
// Add constraint: x + 2 y + 3 z <= 4 model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c0");
As with variables, constraints are always associated with a specific model. They are created using the GRBModel.AddConstr or GRBModel.AddConstrs methods on the model object.
We again use overloaded arithmetic operators to build linear expressions. The comparison operators are also overloaded to make it easier to build constraints.
The second argument to GRBModel.AddConstr gives the constraint name.
The Gurobi .NET interface also allows you to add constraints by building linear expressions in a term-by-term fashion using GRBLinExpr:
// Add constraint: x + y >= 1
GRBLinExpr expr = 0.0; expr.AddTerm(1.0, x); expr.AddTerm(1.0, y); model.AddConstr(expr, GRB.GREATER_EQUAL, 1.0, "c1");
This particular GRBModel.AddConstr signature takes a linear expression that captures the left-hand side of the constraint as its first argument, the sense of the constraint as its second argument, and a linear expression that captures the right-hand side of the constraint as its third argument. The constraint name is given as the fourth argument.
Setting the objective
The next step in the example is to set the optimization objective:
// Set objective: maximize x + y + 2 z model.SetObjective(x + y + 2 * z, GRB.MAXIMIZE);
The objective is built here using overloaded operators and GRBModel.SetObjective. The C# API overloads the arithmetic operators to allow you to build linear and quadratic expressions involving Gurobi variables.
The second argument indicates that the sense is maximization.
Note that while this simple example builds the objective in a single statement using an explicit list of terms, more complex programs will typically build it incrementally. For example:
GRBLinExpr obj = 0.0; obj.AddTerm(1.0, x); obj.AddTerm(1.0, y); obj.AddTerm(2.0, z); model.SetObjective(obj, GRB.MAXIMIZE);
Optimizing the model
Now that the model has been built, the next step is to optimize it:
// Optimize model model.Optimize();
This routine performs the optimization and populates several internal model attributes (including the status of the optimization, the solution, etc.).
Reporting the results
Once the optimization is complete, we can query the values of the attributes (which are implemented as .NET properties). In particular, we can query the VarName and X attributes to obtain the name and solution value for each variable:
Console.WriteLine(x.VarName + " " + x.X); Console.WriteLine(y.VarName + " " + y.X);
We can also query the ObjVal attribute on the model to obtain the objective value for the current solution:
Console.WriteLine("Obj: " + model.ObjVal);
The names and types of all model, variable, and constraint attributes can be found under the Attributes section of the documentation.
Error reporting
Errors in the Gurobi .NET interface are handled through the .NET exception mechanism. In the example, all Gurobi statements are enclosed inside a try block, and any associated errors would be caught by the catch block:
try {
// Formulate and solve model
} catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message) }
Building and running the example
The C# and Visual Basic example directories (<installdir>/examples/c# and <installdir>/examples/vb) contain a number of examples. We encourage you to browse and modify them in order to become more familiar with the Gurobi .NET interface. We also encourage you to read the Gurobi Example Tour for more information.
To run the C# examples on Linux and macOS, you can use the Visual Studio project file, dotnetcore2.csproj (in <installdir>/examples/build/DOTNETCore2), or you can use our standard example Makefile (in <installdir>/examples/build). To run the full set of examples using the Makefile, just execute the command make run_dotnet. You can also run an individual example with make run_mip1_cs.
On Windows, you can use the CS_examples_2015.sln, CS_examples_2017.sln, or CS_examples_2019.sln solution files in <installdir>/examples/build to build and run the example with Visual Studio 2015, 2017, or 2019, respectively. Clicking on the mip1_cs project, and then selecting Run from theBuild menu will compile and run the example.
Alternatively, you can find a .NET Core 2 based project file dotnetcore2.csproj under <installdir>/examples/build/DOTNETCore2 together with the mip1_cs example. By executing dotnet run in this directory you can build and run the mip1_cs example. (It is possible to exchange this example with any other example provided in <installdir>/examples/c# by replacing the file mip1_cs.cs with the corresponding .cs example file.)
Comments
0 comments
Article is closed for comments.