Getting started with Gurobi in Microsoft Visual Studio

A guide on how to get up and running with Gurobi, a powerful software tool that is well suited to finding solutions to tough optimization problems encountered in industry and academic research.

In addition to finding good solutions within practical time scales, I was pleasantly surprised to discover how easy it was easy to use and configure within Microsoft Visual Studio. To apply the Gurobi tools to optimization problems, the developer simply makes calls to Gurobi Application Program Interfaces (APIs) at the appropriate places in the code, tweaking them to suit the application area.

The following steps demonstrate how to achieve this for a mixed integer programming problem:

1. Install & Licence Gurobi

Run the Gurobi installer file. At the time of writing this post, I installed 32-bit version of Gurobi 6.5.0, using the straightforward ‘vanilla’ installation:

gurobi1

… thereby installing Gurobi, and it’s contents to a default location:

gurobi2

2. Create a new Visual Studio project

I am using the Visual Studio 2013, though Gurobi should be suitable for versions 2010, 2012 and 2015 as well.

To keep things simple, open Visual Studio and create a new C++ empty project:

gurobi3

In your new project add the main.cpp source file as well:

gurobi4

3. Set the additional include directories

Before writing any code, set the Visual Studio project dependencies, starting with the additional include files it will need.

Right-click your project folder and select properties. In the dialog that appears, select C/C++ > General > Additional Include Directories. Set this value according to how you installed Gurobi. In my installation the include files are located in the folder ‘C:\gurobi650\win32\include’:

gurobi5

4. Set the library dependencies

Right-click your project folder and select properties. In the dialog that appears, select Linker > General > Additional Library Directories. Set the directory to the location of where your Gurobi library files are located. In my installation this location is C:\gurobi650\win32\lib:

gurobi6

In the same dialig, select the Linker > Input tab and set the variables needed for the Additional Dependencies. For this version 6.5.0 of Gurobi the additional dependencies needed are gurobi_c++mdd2013.lib and gurobi65.lib:

gurobi7

Once these are set click OK.

5. Write your optimization code

In the main.cpp file created earlier, copy in the C++ code that demonstrates how to solve a mixed integer programming problem:

/* Copyright 2015, Gurobi Optimization, Inc. */

/* This example formulates and solves the following simple MIP model:

	maximize    x + y  + 2z
	subject to  x + 2y + 3z <= 4
		        x + y >= 1
			    x, y, z binary
*/

#include "gurobi_c++.h"

int main(int argc, char *argv[])
{
	try 
	{
		GRBEnv env = GRBEnv();
		GRBModel model = GRBModel(env);

		// Set 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");

		model.update();

		// Set objective function: maximize x + y + 2z
		model.setObjective(x + y + 2 * z, GRB_MAXIMIZE);

		// Set constraints: 
		// x + 2y + 3z <= 4
		// x + y >= 1
		model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
		model.addConstr(x + y >= 1, "c1");

		// Run the optimizion
		model.optimize();

		std::cout << x.get(GRB_StringAttr_VarName) << " "
			      << x.get(GRB_DoubleAttr_X) << std::endl;
		std::cout << y.get(GRB_StringAttr_VarName) << " "
				  << y.get(GRB_DoubleAttr_X) << std::endl;
		std::cout << z.get(GRB_StringAttr_VarName) << " "
				  << z.get(GRB_DoubleAttr_X) << std::endl;

		std::cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;

	}
	catch (GRBException e) 
	{
		std::cout << "Error code = " 
			      << e.getErrorCode() 
				  << std::endl;
		std::cout << e.getMessage() << std::endl;
	}
	catch (...)
	{
		std::cout << "Exception during optimization" 
			      << std::endl;
	}

	return 0;
}

6. Run it!

The code constructs your Gurobi model, initializing it with the environment variable. The variables, constraints and objective function are set, and the optimization is run, thereby giving the values for [x,y,z] that optimize the objective function without violating the constraints:

gurobi8