Gurobi Example Tour

Download as pdf or txt
Download as pdf or txt
You are on page 1of 487

GUROBI OPTIMIZER

EXAMPLE TOUR

c 2013, Gurobi Optimization, Inc.


Version 5.5, Copyright

Contents

1 Introduction

2 Example tour
2.1 Load and solve a model from a file .
2.2 Build a model . . . . . . . . . . . . .
2.3 Modify a model . . . . . . . . . . . .
2.4 Change parameters . . . . . . . . . .
2.5 Automated Parameter Tuning . . . .
2.6 Diagnose and cope with infeasibility
2.7 MIP starts . . . . . . . . . . . . . . .
2.8 Model-Data Separation in Python . .
2.9 Callbacks . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

8
11
12
14
16
17
17
18
19
20

3 Example Source Code


3.1 C Examples . . . . . .
callback_c.c . .
dense_c.c . . .
diet_c.c . . . .
facility_c.c . .
feasopt_c.c . .
fixanddive_c.c
lp_c.c . . . . .
lpmethod_c.c .
lpmod_c.c . . .
mip1_c.c . . .
mip2_c.c . . .
params_c.c . .
qcp_c.c . . . .
qp_c.c . . . . .
sensitivity_c.c
sos_c.c . . . .
sudoku_c.c . .
tsp_c.c . . . .
tune_c.c . . . .
workforce1_c.c
workforce2_c.c
workforce3_c.c
workforce4_c.c
3.2 C++ Examples . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

22
22
22
28
32
37
43
47
52
55
57
61
64
69
73
77
81
84
87
92
100
102
107
113
120
128

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

3.3

callback_c++.cpp .
dense_c++.cpp . . .
diet_c++.cpp . . .
facility_c++.cpp . .
feasopt_c++.cpp . .
fixanddive_c++.cpp
lp_c++.cpp . . . . .
lpmethod_c++.cpp
lpmod_c++.cpp . .
mip1_c++.cpp . . .
mip2_c++.cpp . . .
params_c++.cpp . .
sensitivity_c++.cpp
qcp_c++.cpp . . . .
qp_c++.cpp . . . .
sos_c++.cpp . . . .
sudoku_c++.cpp . .
tsp_c++.cpp . . . .
tune_c++.cpp . . .
workforce1_c++.cpp
workforce2_c++.cpp
workforce3_c++.cpp
workforce4_c++.cpp
Java Examples . . . . . . .
Callback.java . . . .
Dense.java . . . . . .
Diet.java . . . . . . .
Facility.java . . . . .
Feasopt.java . . . . .
Fixanddive.java . . .
Lp.java . . . . . . .
Lpmethod.java . . .
Lpmod.java . . . . .
Mip1.java . . . . . .
Mip2.java . . . . . .
Params.java . . . . .
Qcp.java . . . . . . .
Qp.java . . . . . . .
Sensitivity.java . . .
Sos.java . . . . . . .
Sudoku.java . . . . .
Tsp.java . . . . . . .
Tune.java . . . . . .
Workforce1.java . . .
Workforce2.java . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

128
132
135
139
144
146
149
151
153
156
158
161
164
167
169
171
173
177
183
185
189
194
199
205
205
208
211
214
218
220
223
225
227
230
232
235
237
239
242
244
246
250
255
257
260
3

3.4

3.5

Workforce3.java .
Workforce4.java .
C# Examples . . . . . .
callback_cs.cs . .
dense_cs.cs . . .
diet_cs.cs . . . .
facility_cs.cs . .
feasopt_cs.cs . .
fixanddive_cs.cs
lp_cs.cs . . . . .
lpmethod_cs.cs .
lpmod_cs.cs . . .
mip1_cs.cs . . .
mip2_cs.cs . . .
params_cs.cs . .
qcp_cs.cs . . . .
qp_cs.cs . . . . .
sensitivity_cs.cs
sos_cs.cs . . . .
sudoku_cs.cs . .
tsp_cs.cs . . . .
tune_cs.cs . . . .
workforce1_cs.cs
workforce2_cs.cs
workforce3_cs.cs
workforce4_cs.cs
Visual Basic Examples .
callback_vb.vb .
dense_vb.vb . .
diet_vb.vb . . .
facility_vb.vb . .
feasopt_vb.vb .
fixanddive_vb.vb
lp_vb.vb . . . .
lpmethod_vb.vb
lpmod_vb.vb . .
mip1_vb.vb . . .
mip2_vb.vb . . .
params_vb.vb .
qcp_vb.vb . . .
qp_vb.vb . . . .
sensitivity_vb.vb
sos_vb.vb . . . .
sudoku_vb.vb .
tsp_vb.vb . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

264
268
273
273
276
279
282
286
288
291
293
295
298
300
303
305
307
310
312
314
318
323
325
328
332
336
341
341
344
347
350
354
356
359
361
363
366
368
371
373
375
377
379
381
385

3.6

3.7

3.8

tune_vb.vb . . . .
workforce1_vb.vb
workforce2_vb.vb
workforce3_vb.vb
workforce4_vb.vb
Python Examples . . . . .
callback.py . . . .
custom.py . . . . .
dense.py . . . . . .
diet.py . . . . . . .
diet2.py . . . . . .
diet3.py . . . . . .
diet4.py . . . . . .
dietmodel.py . . .
facility.py . . . . .
feasopt.py . . . . .
fixanddive.py . . .
lp.py . . . . . . . .
lpmethod.py . . . .
lpmod.py . . . . .
mip1.py . . . . . .
mip2.py . . . . . .
netflow.py . . . . .
params.py . . . . .
qcp.py . . . . . . .
qp.py . . . . . . .
sensitivity.py . . .
sos.py . . . . . . .
sudoku.py . . . . .
tsp.py . . . . . . .
tune.py . . . . . .
workforce1.py . . .
workforce2.py . . .
workforce3.py . . .
workforce4.py . . .
MATLAB Examples . . .
diet.m . . . . . . .
linprog.m . . . . .
lp.m . . . . . . . .
lp2.m . . . . . . .
mip1.m . . . . . .
qcp.m . . . . . . .
qp.m . . . . . . . .
sos.m . . . . . . .
R Examples . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

390
392
395
399
403
408
408
410
411
413
416
418
419
421
423
426
428
430
431
432
434
436
438
441
443
444
446
448
450
453
456
457
460
463
466
470
470
473
476
477
478
479
480
481
482
5

lp.R .
lp2.R .
mip.R
qcp.R
qp.R .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

482
484
485
486
487

Introduction

The GurobiTM distribution includes an extensive set of examples that illustrate commonly used
features of the Gurobi libraries. Most examples have versions for C, C++, C#, Java, Visual Basic,
and Python. A few, however, illustrate features that are specific to the Python interface.
This document provides a brief tour of these examples. We wont go through each example in
detail. Instead, well start with an Overview of the set of tasks that you are likely to want to perform
with the Gurobi Optimizer. Later sections will then describe how specific examples accomplish each
of these tasks. We suggest that you browse the example source code (in a text editor, or in another
browser window) while reading this document. This document includes Source Code for all of the
examples, in all available languages. Source files are also available in the examples directory of the
Gurobi distribution.
R and R interfaces: our interfaces to these
A brief note for users of the Gurobi MATLAB
languages are built around the assumption that you will use the rich matrix-oriented capabilities of
the underlying languages to build your optimization models. Thus, our examples for these languages
dont attempt to show you how to build models. We have instead chosen to provide a few simple
examples that demonstrate how to pass matrices into our interface.
If you would like further details on any of the Gurobi routines used in these examples, please
consult the Gurobi Reference Manual.

Example tour

This document provides a quick guided tour of the Gurobi examples; we will try to highlight some
of the most important features of these examples. Full source code is provided in this document, so
you are free to explore the examples in full detail.
Wherever possible, we try to discuss the examples in a manner that is independent of programming languages. We will refer to each example using a brief, language independent name.
You will need to map this name to the specific source file name for your language. For example,
the facility example corresponds to six different implementations, one in C (facility_c.c), one
in C++ (facility_c++.cpp), one in Java (Facility.java), one in C# (facility_cs.cs), one in Visual
Basic (facility_vb.vb), and one in Python (facility.py). If you would like to look at the language
implementation for a particular example, please refer to the appropriate example source file.
The Gurobi examples
The following is a list of all of the examples included in the Gurobi distribution. The source code
for these examples can be found in the examples directory of the distribution, or in the Source Code
section of this document.
callback - Demonstrates the use of Gurobi callbacks.
dense - Solves a model stored using dense matrices. We dont recommend that you use dense
matrices for your models, but this example may be helpful if your data is already in this
format.
diet - Builds and solves the classic diet problem. Demonstrates model construction and simple
model modification - after the initial model is solved, a constraint is added to limit the number
of dairy servings.
diet2, diet3, diet4, dietmodel - Python-only variants of the diet example that illustrate
model-data separation.
facility - Simple facility location model: given a set of plants and a set of warehouses, with
transportation costs between them, this example finds the least expensive set of plants to open
in order to satisfy product demand. This example demonstrates the use of MIP starts the
example computes an initial, heuristic solution and passes that solution to the MIP solver.
feasopt - Reads a MIP model from a file, adds artificial slack variables to relax each constraint,
and then minimizes the sum of the artificial variables. It then computes the same relaxation
using the feasibility relaxation feature. The example demonstrates simple model modification
by adding slack variables. It also demonstrates the feasibility relaxation feature.
fixanddive - Implements a simple MIP heuristic. It reads a MIP model from a file, relaxes the
integrality conditions, and then solves the relaxation. It then chooses a set of integer variables
that take integer or nearly integer values in the relaxation, fixes them to the nearest integer,
8

and solves the relaxation again. This process is repeated until the relaxation is either integer
feasible or linearly infeasible. The example demonstrates different types of model modification
(relaxing integrality conditions, changing variable bounds, etc.).
lp - A very simple example that reads a continuous model from a file, optimizes it, and writes
the solution to a file. If the model is infeasible, it writes an Irreducible Inconsistent Subsystem
(IIS) instead.
lpmethod - Demonstrates the use of different LP algorithms. Reads a continuous model from
a file and solves it using multiple algorithms, reporting which is the quickest for that model.
lpmod - Demonstrates the use of advanced starts in LP. Reads a continuous model from a
file, solves it, and then modifies one variable bound. The resulting model is then solved in two
different ways: starting from the solution of the original model, or restarting from scratch.
mip1 - Builds a trivial MIP model, solves it, and prints the solution.
mip2 - Reads a MIP model from a file, optimizes it, and then solves the fixed version of the
MIP model.
netflow - A Python-only example that solves a multi-commodity network flow model. It
demonstrates the use of several Python modeling constructs, including dictionaries, tuples,
and tuplelist objects.
params - Demonstrates the use of Gurobi parameters. Reads a MIP model from a file, and
then spends 5 seconds solving the model with each of four different values of the MIPFocus
parameter. It compares the optimality gaps for the four different runs, and continues with
the MIPFocus value that produced the smallest gap.
qp - Builds a trivial QP model, solves it, converts it to an MIQP model, and solves it again.
qcp - Builds and solves a trivial QCP model.
sensitivity - MIP sensitivity analysis. Reads a MIP model, solves it, and then computes the
objective impact of fixing each binary variable in the model to 0 or 1. Demonstrates simple
MIP model modification by changing variable bounds.
sos - Builds and solves a trivial SOS models.
sudoku - Reads a Sudoku puzzle dataset from a file, builds a MIP model to solve that model,
solves it, and prints the solution.
tsp - Solves a traveling salesman problem using lazy constraints.
tune - Uses the parameter tuning tool to search for improved parameter settings for a model.
workforce1 - Formulates and solves a workforce scheduling model. If the model is infeasible,
the example computes and prints an Irreducible Inconsistent Subsystem (IIS).
9

workforce2 - An enhancement of workforce1. This example solves the same workforce


scheduling model, but if the model is infeasible, it computes an IIS, removes one of the
associated constraints from the model, and re-solves. This process is repeated until the model
becomes feasible. Demonstrates constraint removal.
workforce3 - A different enhancement of workforce1. This example solves the same workforce scheduling model, but if the model is infeasible, it adds artificial variables to each constraint and minimizes the sum of the artificial variables. This corresponds to finding the
minimum total change in the right-hand side vector required in order to make the model
feasible. Demonstrates variable addition.
workforce4 - An enhancement of workforce3. This example solves the same workforce
scheduling model, but it starts with artificial variables in each constraint. It first minimizes
the sum of the artificial variables. Then, it introduces a new quadratic objective to balance the
workload among the workers. Demonstrates optimization with multiple objective functions.
The example tour
The easiest place to start your introduction to the Gurobi examples is probably with the examples
that load and solve a model from a file. These demonstrate the most basic capabilities of the Gurobi
libraries. They also demonstrate the use of model attributes, which are an important concept in
the Gurobi optimizer.
Once you are comfortable with these examples, you should move on to the examples that build
a model from scratch. These show you how to create variables and constraints, and add them to an
optimization model. They also illustrate the use of lazy updates, which you will need to understand
in order to use the Gurobi libraries.
The next topic covered in this document is model modification. The Gurobi distribution includes
examples that add and remove constraints, add variables, and change variable types, bounds and
objective coefficients. You modify a model in much the same way that you build a model from
scratch, but there are some important differences involving the use of the solution information.
Next, this document covers parameter changes. The params example shows you how to change
parameters, and in particular how to use different parameter settings for different models.
On a related note, the tuning section demonstrates the use of our automated tuning tool. This
tool searches for parameter settings that improve performance on a particular model.
The infeasibility section considers a few examples that cope with model infeasibility. Some use
an Irreducible Inconsistent Subsystem (IIS) to handle the infeasibility, while others relax constraints.
One useful MIP feature that is worth understanding is MIP starts. A MIP start allows you to
specify a known feasible solution to the MIP solver. The solution provides a bound on the objective
of the best possible solution, which can help to limit the MIP search. The solution also provides a
potential start point for the local search heuristics that are utilized by the Gurobi MIP solver.
It is possible to achieve model-data separation when using our Python interface, as is often done
in modeling languages, but you need to make use of Python modules to do so. The model-data
separation section provides an example of how this is done. It considers two versions of the diet
example, which obtain model data from very different places. Both use the same file to formulate
and solve the actual optimization model on that data.
The final topic we cover in this document is Gurobi callbacks. Callbacks allow the user to obtain
periodic progress information related to the optimization.
10

2.1

Load and solve a model from a file

Examples: callback, feasopt, fixanddive, lp, lpmethod, lpmod, mip2, params, sensitivity
One of the most basic tasks you can perform with the Gurobi libraries is to read a model from
a file, optimize it, and report the result. The lp (lp_c.c, lp_c++.cpp, lp_cs.cs, Lp.java, lp.py,
lp_vb.vb) and mip2 (mip2_c.c, mip2_c++.cpp, mip2_cs.cs, Mip2.java, mip2.py, mip2_vb.vb)
examples are simple illustratations of how this is done in the various supported Gurobi languages.
While the specifics vary from one language to another, the basic structure remains the same for all
languages.
After initializing the Gurobi environment, the examples begin by reading the model from the
specified file. In C, you call the GRBreadmodel() function:
error = GRBreadmodel(masterenv, argv[1], &model);
In C++, this is done by constructing a GRBModel object:
GRBModel model = GRBModel(env, argv[1]);
In C# and Java, this is also done by constructing a GRBModel object:
GRBModel model = new GRBModel(env, args[0]);
In Python, this is done via the read global function:
model = read(sys.argv[1])
The next step is to invoke the Gurobi optimizer on the model. In C, you call GRBoptimize()
on the model variable:
error = GRBoptimize(model);
In C++, Java, and Python, this is accomplished by calling the optimize method on the model
object:
model.optimize();
In C#, the first letter of the method name is capitalized:
model.Optimize();
A successful optimize call populates a set of solution attributes in the model. For example, once
the call completes, the X variable attribute contains the solution value for each variable. Similarly,
for continuous models, the Pi constraint attribute contains the dual value for each constraint.
The examples then retrieve the value of the model Status attribute to determine the result of
the optimization. In the lp example, an optimal solution is written to a solution file (model.sol).
There are many other things you can do once you have read and solved the model. For example,
lp checks the solution status which is highly recommended. If the model is found to be infeasible,
this example computes an Irreducible Inconsistent Subsystem (IIS) to isolate the source of the
infeasibility.
11

2.2

Build a model

Examples: diet, facility, mip1, qcp, qp, sos, sudoku, workforce1, workforce2, workforce3, workforce4
Several of the Gurobi examples build models from scratch. We start by focusing on two, mip1
and 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 GRBModel 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 GRBModel constructor 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 addVar method on the Model object (AddVar in C#). In
Java, this looks like:
GRBVar x = model.addVar(0.0, 1.0, -1.0, GRB.BINARY, "x");
The new variables 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, model.update() in C++, Java, and Python, model.Update() in C#). Model modifications
are performed in a lazy fashion in the Gurobi optimizer they dont 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 doesnt support operator overloading, you build
an expression as follows:
12

GRBLinExpr expr = new GRBLinExpr();


expr.addTerm(1.0, x); expr.addTerm(2.0, y); expr.addTerm(3.0, z);
You then use the addConstr method on the Model object 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 GRBaddsos function:
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 object:
model.addSOS(sosv1, soswt1, GRB.SOS_TYPE1);
Once the model has been built, the typical next step is to optimize it (using GRBoptimize in
C, model.optimize in C++, Java, and Python, or model.Optimize in C#). You can then query
the X attribute on the variables to retrieve the solution (and the 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);
In C++:
cout <<
<<
cout <<
<<
cout <<
<<

x.get(GRB_StringAttr_VarName) << " "


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

In Java:
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));
In C#:
13

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));
In Python:
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 get and 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 doesnt have array query routines. Python is an interpreted language,
and overheads associated with queries on individual attributes are a small contributor to overall
runtime.

2.3

Modify a model

Examples: diet, feasopt, fixanddive, lpmod, sensitivity, workforce3, workforce4


This section considers model modification. Modification can take many forms, including adding
constraints or variables, deleting constraints or variables, modifying constraint and variable attributes, changing constraint coefficients, etc. Here is a sample of some types of model modification.
diet
This example builds a linear model that solves the classic diet problem: to find the minimum cost
diet that satisfies a set of daily nutritional requirements. Once the model has been formulated and
solved, the example adds an additional constraint to limit the number of servings of dairy products,
and solves the model again. Lets focus on the model modification.
Adding constraints to a model that has already been solved is no different from adding constraints
when constructing an initial model. In Python, we can introduce a limit of 6 dairy servings through
the following constraint:
m.addConstr(buy[7] + buy[8] <= 6, "limit_dairy")
For linear models, the previously computed solution can be used as an efficient warm start for
the modified model. The Gurobi solver retains the previous solution, so the next optimize call
automatically starts from the previous solution.
14

lpmod
Changing a variable bound is also straightforward. The lpmod example changes a single variable
bound, then re-solves the model in two different ways. A variable bound can be changed by modifying the UB or LB attribute of the variable. In C:
error = GRBsetdblattrelement(model, GRB_DBL_ATTR_UB, var, 0.0);
In Python:
minVar.ub = 0
The model is re-solved simply by calling the optimize method again. For a continuous model, this
starts the optimization from the previous solution. To illustrate the difference when solving the
model from an initial, unsolved state, the lpmod example calls the reset function. In C:
error = GRBresetmodel(model);
In C++, Java, and Python:
m.reset()
In C#:
m.Reset()
When we call the optimize method after resetting the model, optimization starts from scratch.
Although the difference in computation time is insignificant for this tiny example, the warm start
can make a big difference for larger models.
fixanddive
The fixanddive example provides another example of bound modification. In this case, we repeatedly modify a set of variable bounds, utilizing warm starts each time. In C, variables are fixed as
follows:
for (j = 0; j < nfix; ++j)
{
fixval = floor(fractional[j].X + 0.5);
error = GRBsetdblattrelement(model, "LB", fractional[j].index, fixval);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", fractional[j].index, fixval);
if (error) goto QUIT;
}
In Python, they are fixed as follows:
for i in range(nfix):
v = fractional[i]
fixval = int(v.x + 0.5)
v.lb = fixval
v.ub = fixval
Again, the subsequent call to optimize starts from the previous solution.
15

sensitivity
The sensitivity example computes the amount by which the optimal objective changes if each
binary variable is fixed at either 0 or 1. For each binary variable, the example creates and solves a
copy of the model with new upper and lower bounds. This example is a MIP, so Gurobi can not
make use of advanced start information. As a result, the model is solved from scratch after each
bound modification.
feasopt
The last modification example we consider is feasopt, which adds variables to existing constraints
and also changes the optimization objective. Setting the objective to zero is straightforward: simply
call setObjective with a zero argument:
m.setObjective(0)
Adding new variables is somewhat more complex. In the example, we want to add artificial variable(s) to each constraint in order to allow the constraint to be relaxed. We use two artificial
variables for equality constraints and one for all other constraints. The Python code for adding a
single artificial variable to constraint c is:
feasModel.addVar(obj=1.0, name="ArtP_" + c.Constrname, column=Column([1], [c]))
We use the column argument of the addVar method to specify the set of constraints in which the new
variable participates, as well as the associated coefficients. In this example, the new variable only
participates in the constraint to be relaxed. Default values are used here for all variables attributes
except the objective and the variable name.

2.4

Change parameters

Examples: callback, fixanddive, lp, lpmethod, mip2, params, sensitivity


This section illustrates the use of Gurobi parameters. Example params reads a MIP model from
a file, then solves the model using four different values of the MIPFocus parameter, running for five
seconds per value (MIPFocus chooses the high-level strategy that the MIP solver uses to solve the
problem). It then chooses the parameter value that produced the smallest MIP gap, and continues
solving the model until it achieves optimality.
The mechanics of setting a parameter are quite simple. To set the MIPFocus parameter in C, do
the following:
GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_MIPFOCUS, i);
In C++:
model.getEnv().set(GRB_IntParam_MIPFocus, i);
In Java:
model.getEnv().set(GRB.IntParam.MIPFocus, i);
In C#:
model.GetEnv().Set(GRB.IntParam.MIPFocus, i);
16

In Python:
model.params.MIPFocus = i
Note how parameter settings affect the behavior of the different models. When we set the
TimeLimit parameter on the base model, then make a copy of that model, the parameter setting is
carried over to the copy. The copy gets its own environment that is a copy of the original. When we
set the MIPFocus parameter on the copy, that parameter change has no effect on the other copies,
nor on the original model.

2.5

Automated Parameter Tuning

Example: tune
The next example we consider is tune, which demonstrates the use of our automated parameter
tuning tool. This tool searches for parameter settings that improve performance on a model. While
you would typically invoke the tool through the command line, using our grbtune program, it can
also be invoked from our APIs. Well provide only a cursory description of the tool here. We
recommend that you consult the Parameter Tuning Tool section of the Gurobi Reference Manual
for more precise details.
Our tuning example demonstrates a typical use of the tuning tool. You would start by invoking
the tool on a model. In C:
error = GRBtunemodel(model);
In Java:
model.tune();
This routine solves the model multiple times, with different parameter settings, to find settings that
improve performance.
Once tuning is complete, you would then use GetTuneResult to retrieve the result. In C:
error = GRBgettuneresult(model, 0);
In Java:
model.getTuneResult(0);
The numerical argument indicates which tuning result to retrieve (0 is the best result, 1 is the
second-best, etc.). This routine loads the requested parameter set into the environment associated
with the argument model.
Once the tune parameter settings have been loaded into the model, you can then call Optimize
to use these parameters to solve the model, or you can call Write to write these parameters to a
.prm file.

2.6

Diagnose and cope with infeasibility

Examples: feasopt, lp, workforce1, workforce2, workforce3, workforce4


When solving optimization models, there are some situations where the specified constraints
cannot be satisfied. When this happens, you often need to either identify and repair the root cause
17

of the infeasibility, or alternatively find a set of constraints to relax in order to obtain a feasible
model. The workforce1, workforce2, and workforce3 illustrate these different strategies.
Starting with the simplest of the three examples, workforce1 formulates a simple workforce
scheduling model and solves it. If the model is infeasible, it computes an Irreducible Inconsistent
Subsystem (IIS). The user can then inspect this information to understand and hopefully address
the source of the infeasibility in the model.
Example workforce2 is similar, except that if the model is infeasible, the example repeatedly
identifies an IIS and removes one of the associated constraints from the model until the model
becomes feasible. Note that it is sufficient to remove one constraint from the IIS to address that
source of infeasibility, but that one IIS may not capture all sources of infeasibility. It is therefore
necessary to repeat the process until the model is feasible.
Example workforce3 takes a different approach to addressing infeasibility. Rather than identifying and removing IIS members, it allows the constraints of the model to be relaxed. Like the
feasopt example, an artificial variable is added to each constraint. The example sets the objective
on the original variables to zero, and then solves a model that minimizes the total magnitude of the
constraint relaxation.
The feasopt example demonstrates another approach to relaxing an infeasible model. It computes a feasibility relaxation for the infeasible model. A feasibility relaxation is a model that, when
solved, minimizes the amount by which the solution violates the bounds and linear constraints of
the original model. This method is invoked as follows:
In C:
error = GRBfeasrelax(feasmodel, GRB_FEASRELAX_LINEAR, 1,
NULL, NULL, rhspen, &feasobj);
In C++:
feasmodel1.feasRelax(GRB_FEASRELAX_LINEAR, true, false, true);
In C#:
feasmodel1.FeasRelax(GRB.FEASRELAX_LINEAR, true, false, true);
In Java:
feasmodel1.feasRelax(GRB.FEASRELAX_LINEAR, true, false, true);
In Python:
feasmodel1.FeasRelaxS(0, True, False, True);
The arguments to this method select the objective function for the relaxed model, the specific
set of bounds and constraints that are allowed to be relaxed, and the penalties for relaxing specific
bounds and constraints.

2.7

MIP starts

Example: facility
A MIP modeler often knows how to compute a feasible solution to their problem. In cases where
the MIP solver is slow in finding an initial feasible solution, it can helpful for the modeler to provide
18

a feasible solution along with the model itself. This is done through the Start attribute on the
variables. This is illustrated in the facility example.
The facility example solves a simple facility location problem. The model contains a set
of warehouses, and a set of plants that produce the products required in the warehouses. Each
plant has a maximum production capacity and a fixed operating cost. Additionally, there is a cost
associated with shipping products from a plant to a warehouse. The goal is to decide which plants
should satisfy the demand for the product, given the associated capacities and costs.
The example uses a simple heuristic for choosing an initial solution: it closes the plant with the
highest fixed cost. The associated solution may not be optimal, but it could produce a reasonable
starting solution for the MIP optimization. The MIP start is passed to the MIP solver by setting
the Start attribute before the optimization begins. In C, we set the start attribute to open all
plants using the following code:
for (p = 0; p < nPlants; ++p)
{
error = GRBsetdblattrelement(model, "Start", opencol(p), 1.0);
if (error) goto QUIT;
}
In Python:
for p in range(nPlants):
open[p].start = 1.0
When you run the example, the MIP solver reports that the start produced a feasible initial
solution:
Loaded MIP start with objective 210500
This initial solution turns out to be optimal for the sample data. Although the computation
difference is insignificant for this tiny example, providing a good starting solution can sometimes
help for more difficult models.
Note that the MIP start in this example only specifies values for some of the variables the
variables that determine which plants to leave open and which plants to close. The Gurobi MIP
solve uses whatever start information is provided to try to construct a complete solution.

2.8

Model-Data Separation in Python

Examples: diet2.py, diet3.py, diet4.py


When building an optimization model in a modeling language, it is typical to separate the
optimization model itself from the data used to create an instance of the model. These two model
ingredients are often stored in completely different files. We show how a similar result can be
achieved in our Python interface with our diet2.py, diet3.py, and diet4.py examples. These
examples illustrate alternate approaches to providing data to the optimization model: diet2.py
embeds the data in the source file, diet3.py reads the data from an SQL database (using the
Python sqlite3 package), and diet4.py reads the data from an Excel spreadsheet (using the
Python xlrd package). dietmodel.py contains the optimization model itself. The same model is
used by diet2.py, diet3.py, and diet4.py.
19

The key construct that enables the separation of the model from the data is the Python module.
A module is simply a set of functions and variables, stored in a file. You import a module into
a program using the import statement. diet2.py, diet3.py, and diet4.py all populate a set of
variables, and then pass them to the solve function of the dietmodel module using the following
pair of statements:
import dietmodel
dietmodel.solve(categories, minNutrition, maxNutrition, foods, cost, nutritionValues)
The first statement imports the dietmodel module, which must be stored in file dietmodel.py
in the current directory. The second passes the model data to the solve function in the newly
imported module.

2.9

Callbacks

Example: callback
The final example we consider is callback, which demonstrates the use of Gurobi callbacks.
Callbacks are used to report on the progress of the optimization or to modify the behavior of the
Gurobi solver. To use a callback, the user writes a routine that implements the desired behavior.
The routine is passed to the Gurobi optimizer when optimization begins, and the routine is called
regularly during the optimization process. One argument of the user routine is a where value, which
indicates from where in the optimization process the callback is invoked. The user callback routine
can call the optimization library to query certain values. We refer the reader to the callback section
of the Gurobi Reference Manual for more precise details.
Our callback example implements a simple termination scheme: the user passes a node count
into the callback, and the callback asks the optimizer to terminate when that node count is reached.
This is implemented in C as follows:
GRBcbget(cbdata, where, GRB_CB_MIP_NODCNT, &nodecnt);
if (nodecnt > limit)
GRBterminate(model);
In Python, this is implemented as:
nodecnt = model.cbGet(GRB.callback.MIP_NODCNT)
if nodecnt > model._mynodelimit:
model.terminate()
To obtain the current node count, the user routine calls the cbget routine (the GRBcbget function
in C, or the cbGet method on the model object in C++, C#, Java, and Python).
Our callback example also prints progress information. In C:
GRBcbget(cbdata, where, GRB_CB_MIP_NODCNT, &nodecnt);
if (nodecnt - mydata->lastmsg >= 100) {
...
printf("%7.0f ...", nodecnt, ...);
}
In Python:
20

nodecnt = model.cbGet(GRB.callback.MIP_NODCNT)
if nodecnt % 100 == 0:
print int(nodecnt), ...
Again, the user callback calls the cbGet routine to query the state of the optimization.

21

Example Source Code

We have included source code for all of the distributed examples in this section. The identical
example source code is included in the examples directory in the Gurobi distribution.

3.1

C Examples

This section includes source code for all of the Gurobi C examples. The same source code can be
found in the examples/c directory of the Gurobi distribution.

callback_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP or a MIP from a file, sets a callback
to monitor the optimization progress and to output some progress
information to the screen and to a log file. If it is a MIP and 10%
gap is reached, then it aborts */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

/* Define structure to pass my data to the callback function */


struct callback_data {
double lastnode;
double lastiter;
FILE
*logfile;
double *solution;
};
int __stdcall
mycallback(GRBmodel *model,
void
*cbdata,
int
where,
void
*usrdata)
{
struct callback_data *mydata = (struct callback_data *) usrdata;
char *msg;
22

if (where == GRB_CB_POLLING) {
/* Ignore polling callback */
} else if (where == GRB_CB_MESSAGE) {
GRBcbget(cbdata, where, GRB_CB_MSG_STRING, &msg);
fprintf(mydata->logfile, "%s", msg);
} else if (where == GRB_CB_SIMPLEX) {
double pinf, dinf, obj, itrcnt;
int
ispert;
char
ch;
GRBcbget(cbdata, where, GRB_CB_SPX_ITRCNT, &itrcnt);
if (itrcnt - mydata->lastiter >= 100) {
mydata->lastiter = itrcnt;
GRBcbget(cbdata, where, GRB_CB_SPX_ISPERT, &ispert);
GRBcbget(cbdata, where, GRB_CB_SPX_OBJVAL, &obj);
GRBcbget(cbdata, where, GRB_CB_SPX_PRIMINF, &pinf);
GRBcbget(cbdata, where, GRB_CB_SPX_DUALINF, &dinf);
if
(ispert == 0) ch = ;
else if (ispert == 1) ch = S;
else
ch = P;
printf("%7.0f %14.7e%c %13.6e %13.6e\n", itrcnt, obj, ch, pinf, dinf);
}
} else if (where == GRB_CB_PRESOLVE) {
int cdels, rdels;
GRBcbget(cbdata, where, GRB_CB_PRE_COLDEL, &cdels);
GRBcbget(cbdata, where, GRB_CB_PRE_ROWDEL, &rdels);
if (cdels || rdels) {
printf("%7d columns and %7d rows are removed\n", cdels, rdels);
}
} else if (where == GRB_CB_MIP) {
double objbst, objbnd, nodecnt, actnodes, itrcnt;
int
cutcnt, solcnt;
GRBcbget(cbdata, where, GRB_CB_MIP_NODCNT, &nodecnt);
if (nodecnt - mydata->lastnode >= 100) {
mydata->lastnode = nodecnt;
GRBcbget(cbdata, where, GRB_CB_MIP_OBJBST, &objbst);
GRBcbget(cbdata, where, GRB_CB_MIP_OBJBND, &objbnd);
/* if gap is small, then quit */
if (fabs(objbst - objbnd) < 0.1 * (1.0 + fabs(objbst))) {
printf("Stop early - 10%% gap achieved\n");
GRBterminate(model);
}
GRBcbget(cbdata, where, GRB_CB_MIP_NODLFT, &actnodes);
GRBcbget(cbdata, where, GRB_CB_MIP_ITRCNT, &itrcnt);
GRBcbget(cbdata, where, GRB_CB_MIP_SOLCNT, &solcnt);

23

GRBcbget(cbdata, where, GRB_CB_MIP_CUTCNT, &cutcnt);


printf("%7.0f %7.0f %8.0f %13.6e %13.6e %7d %7d\n",
nodecnt, actnodes, itrcnt, objbst, objbnd, solcnt, cutcnt);
}
} else if (where == GRB_CB_MIPSOL) {
double obj, nodecnt;
int solcnt;
GRBcbget(cbdata, where, GRB_CB_MIPSOL_OBJ, &obj);
GRBcbget(cbdata, where, GRB_CB_MIPSOL_NODCNT, &nodecnt);
GRBcbget(cbdata, where, GRB_CB_MIPSOL_SOLCNT, &solcnt);
GRBcbget(cbdata, where, GRB_CB_MIPSOL_SOL, mydata->solution);
printf("**** New solution at node %.0f, obj %g, sol %d, x[0] = %.2f ****\n",
nodecnt, obj, solcnt, mydata->solution[0]);
} else if (where == GRB_CB_BARRIER) {
double primobj, dualobj, priminf, dualinf, compl;
int iter;
GRBcbget(cbdata, where, GRB_CB_BARRIER_ITRCNT, &iter);
GRBcbget(cbdata, where, GRB_CB_BARRIER_PRIMOBJ, &primobj);
GRBcbget(cbdata, where, GRB_CB_BARRIER_DUALOBJ, &dualobj);
GRBcbget(cbdata, where, GRB_CB_BARRIER_PRIMINF, &priminf);
GRBcbget(cbdata, where, GRB_CB_BARRIER_DUALINF, &dualinf);
GRBcbget(cbdata, where, GRB_CB_BARRIER_COMPL,
&compl);
printf("Barrier iter: %d %.4e %.4e %.4e %.4e %.4e\n",
iter, primobj, dualobj, priminf, dualinf, compl);
}
return 0;
}
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
int
vars, optimstatus;
double
objval;
struct callback_data mydata;
mydata.lastnode
mydata.lastiter
mydata.logfile
mydata.solution

24

=
=
=
=

-GRB_INFINITY;
-GRB_INFINITY;
NULL;
NULL;

if (argc < 2) {
fprintf(stderr, "Usage: callback_c filename\n");
goto QUIT;
}
mydata.logfile = fopen("cb.log", "w");
if (!mydata.logfile) {
fprintf(stderr, "Cannot open cb.log for callback message\n");
goto QUIT;
}
/* Create environment */
error = GRBloadenv(&env, NULL);
if (error) goto QUIT;
/* Turn off display */
error = GRBsetintparam(env, GRB_INT_PAR_OUTPUTFLAG, 0);
if (error) goto QUIT;
/* Read model from file */
error = GRBreadmodel(env, argv[1], &model);
if (error) goto QUIT;
/* Allocate space for solution */
error = GRBgetintattr(model, GRB_INT_ATTR_NUMVARS, &vars);
if (error) goto QUIT;
mydata.solution = malloc(vars*sizeof(double));
if (mydata.solution == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
exit(1);
}
/* Set callback function */
error = GRBsetcallbackfunc(model, mycallback, (void *) &mydata);
if (error) goto QUIT;
/* Solve model */

25

error = GRBoptimize(model);
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL)
printf("Optimal objective: %.4e\n", objval);
else if (optimstatus == GRB_INF_OR_UNBD)
printf("Model is infeasible or unbounded\n");
else
printf("Optimization was stopped early\n");
printf("\n");
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Close file */
if (mydata.logfile)
fclose(mydata.logfile);
/* Free solution */
if (mydata.solution)
free(mydata.solution);
/* Free model */
GRBfreemodel(model);
/* Free environment */

26

GRBfreeenv(env);
return 0;
}

27

dense_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.
*/
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
/*
Solve an LP/QP/MILP/MIQP represented using dense matrices. This
routine assumes that A and Q are both stored in row-major order.
It returns 1 if the optimization succeeds. When successful,
it returns the optimal objective value in objvalP, and the
optimal solution vector in solution.
*/
static int
dense_optimize(GRBenv *env,
int
rows,
int
cols,
double *c,
/*
double *Q,
/*
double *A,
/*
char
*sense, /*
double *rhs,
/*
double *lb,
/*
double *ub,
/*
char
*vtype, /*
double *solution,
double *objvalP)
{
GRBmodel *model = NULL;
int
i, j, optimstatus;
int
error = 0;
28

linear portion of objective function */


quadratic portion of objective function */
constraint matrix */
constraint senses */
RHS vector */
variable lower bounds */
variable upper bounds */
variable types (continuous, binary, etc.) */

int

success = 0;

/* Create an empty model */


error = GRBnewmodel(env, &model, "dense", cols, c, lb, ub, vtype, NULL);
if (error) goto QUIT;
error = GRBaddconstrs(model, rows, 0, NULL, NULL, NULL, sense, rhs, NULL);
if (error) goto QUIT;
/* Integrate new rows and columns */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Populate A matrix */
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (A[i*cols+j] != 0) {
error = GRBchgcoeffs(model, 1, &i, &j, &A[i*cols+j]);
if (error) goto QUIT;
}
}
}
/* Populate Q matrix */
if (Q) {
for (i = 0; i < cols; i++) {
for (j = 0; j < cols; j++) {
if (Q[i*cols+j] != 0) {
error = GRBaddqpterms(model, 1, &i, &j, &Q[i*cols+j]);
if (error) goto QUIT;
}
}
}
}
/* Integrate new coefficients */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Write model to dense.lp */

29

error = GRBwrite(model, "dense.lp");


if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, objvalP);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, cols, solution);
if (error) goto QUIT;
success = 1;
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
return success;
}
int
main(int
argc,
char *argv[])
{

30

GRBenv *env
int
error
double c[]
double Q[3][3]
double A[2][3]
char
sense[]
double rhs[]
double lb[]
double sol[3];
int
solved;
double objval;

=
=
=
=
=
=
=
=

NULL;
0;
{1, 1, 0};
{{1, 1, 0}, {0, 1, 1}, {0, 0, 1}};
{{1, 2, 3}, {1, 1, 0}};
{>, >};
{4, 1};
{0, 0, 0};

/* Create environment */
error = GRBloadenv(&env, "dense.log");
if (error) goto QUIT;
/* Solve the model */
solved = dense_optimize(env, 2, 3, c, &Q[0][0], &A[0][0], sense, rhs, lb,
NULL, NULL, sol, &objval);
if (solved)
printf("Solved: x=%.4f, y=%.4f, z=%.4f\n", sol[0], sol[1], sol[2]);
QUIT:
/* Free environment */
GRBfreeenv(env);
return 0;
}

31

diet_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve the classic diet model, showing how to add constraints
to an existing model. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int printSolution(GRBmodel* model, int nCategories, int nFoods);

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
int
i, j;
int
*cbeg, *cind, idx;
double
*cval, *rhs;
char
*sense;
/* Nutrition guidelines, based on
USDA Dietary Guidelines for Americans, 2005
http://www.health.gov/DietaryGuidelines/dga2005/ */
const int nCategories = 4;
char *Categories[] =
{ "calories", "protein", "fat", "sodium" };
double minNutrition[] = { 1800, 91, 0, 0 };
double maxNutrition[] = { 2200, GRB_INFINITY, 65, 1779 };
/* Set of foods */
const int nFoods = 9;
char* Foods[] =
{ "hamburger", "chicken", "hot dog", "fries",
"macaroni", "pizza", "salad", "milk", "ice cream" };
double cost[] =
{ 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59 };
/* Nutrition values for the foods */
32

double nutritionValues[][4] = {
{
{
{
{
{
{
{
{
{

410,
420,
560,
380,
320,
320,
320,
100,
330,

24, 26, 730 },


32, 10, 1190 },
20, 32, 1800 },
4, 19, 270 },
12, 10, 930 },
15, 12, 820 },
31, 12, 1230 },
8, 2.5, 125 },
8, 10, 180 }

};
/* Create environment */
error = GRBloadenv(&env, "diet.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "diet", nFoods + nCategories,
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize decision variables for the foods to buy */
for (j = 0; j < nFoods; ++j)
{
error = GRBsetdblattrelement(model, "Obj", j, cost[j]);
if (error) goto QUIT;
error = GRBsetstrattrelement(model, "VarName", j, Foods[j]);
if (error) goto QUIT;
}
/* Initialize decision variables for the nutrition information,
which we limit via bounds */
for (j = 0; j < nCategories; ++j)
{
error = GRBsetdblattrelement(model, "LB", j + nFoods, minNutrition[j]);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", j + nFoods, maxNutrition[j]);
if (error) goto QUIT;
error = GRBsetstrattrelement(model, "VarName", j + nFoods, Categories[j]);
if (error) goto QUIT;
}
/* The objective is to minimize the costs */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;

33

/* Nutrition constraints */
cbeg = malloc(sizeof(int) * nCategories);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * nCategories * (nFoods + 1));
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * nCategories * (nFoods + 1));
if (!cval) goto QUIT;
rhs = malloc(sizeof(double) * nCategories);
if (!rhs) goto QUIT;
sense = malloc(sizeof(char) * nCategories);
if (!sense) goto QUIT;
idx = 0;
for (i = 0; i < nCategories; ++i)
{
cbeg[i] = idx;
rhs[i] = 0.0;
sense[i] = GRB_EQUAL;
for (j = 0; j < nFoods; ++j)
{
cind[idx] = j;
cval[idx++] = nutritionValues[j][i];
}
cind[idx] = nFoods + i;
cval[idx++] = -1.0;
}
error = GRBaddconstrs(model, nCategories, idx, cbeg, cind, cval, sense,
rhs, Categories);
if (error) goto QUIT;
/* Solve */
error = GRBoptimize(model);
if (error) goto QUIT;
error = printSolution(model, nCategories, nFoods);
if (error) goto QUIT;
printf("\nAdding constraint: at most 6 servings of dairy\n");
cind[0] = 7;
cval[0] = 1.0;
cind[1] = 8;
cval[1] = 1.0;
error = GRBaddconstr(model, 2, cind, cval, GRB_LESS_EQUAL, 6.0,
"limit_dairy");
if (error) goto QUIT;

34

/* Solve */
error = GRBoptimize(model);
if (error) goto QUIT;
error = printSolution(model, nCategories, nFoods);
if (error) goto QUIT;

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(cbeg);
free(cind);
free(cval);
free(rhs);
free(sense);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}
int printSolution(GRBmodel* model, int nCategories, int nFoods)
{
int error, status, i, j;
double obj, x;
char* vname;
error = GRBgetintattr(model, "Status", &status);

35

if (error) return error;


if (status == GRB_OPTIMAL)
{
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) return error;
printf("\nCost: %f\n\nBuy:\n", obj);
for (j = 0; j < nFoods; ++j)
{
error = GRBgetdblattrelement(model, "X", j, &x);
if (error) return error;
if (x > 0.0001)
{
error = GRBgetstrattrelement(model, "VarName", j, &vname);
if (error) return error;
printf("%s %f\n", vname, x);
}
}
printf("\nNutrition:\n");
for (i = 0; i < nCategories; ++i)
{
error = GRBgetdblattrelement(model, "X", i + nFoods, &x);
if (error) return error;
error = GRBgetstrattrelement(model, "VarName", i + nFoods, &vname);
if (error) return error;
printf("%s %f\n", vname, x);
}
}
else
{
printf("No solution\n");
}
return 0;
}

36

facility_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Facility location: a company currently ships its product from 5 plants
to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.
*/
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

#define opencol(p)
#define transportcol(w,p)
#define MAXSTR

p
nPlants*(w+1)+p
128

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
int
p, w, col;
int
*cbeg = NULL;
int
*cind = NULL;
int
idx, rowct;
double
*cval = NULL;
double
*rhs = NULL;
char
*sense = NULL;
char
vname[MAXSTR];
int
cnamect = 0;
char
**cname = NULL;
double
maxFixed = -GRB_INFINITY, sol, obj;
/* Number of plants and warehouses */
const int nPlants = 5;
const int nWarehouses = 4;
37

/* Warehouse demand in thousands of units */


double Demand[] = { 15, 18, 14, 20 };
/* Plant capacity in thousands of units */
double Capacity[] = { 20, 22, 17, 19, 18 };
/* Fixed costs for each plant */
double FixedCosts[] =
{ 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double TransCosts[4][5] = {
{ 4000, 2000, 3000,
{ 2500, 2600, 3400,
{ 1200, 1800, 2600,
{ 2200, 2600, 3100,
};

2500,
3000,
4100,
3700,

4500
4000
3000
3200

},
},
},
}

/* Create environment */
error = GRBloadenv(&env, "facility.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "facility", nPlants * (nWarehouses + 1),
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize decision variables for plant open variables */
for (p = 0; p < nPlants; ++p)
{
col = opencol(p);
error = GRBsetcharattrelement(model, "VType", col, GRB_BINARY);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "Obj", col, FixedCosts[p]);
if (error) goto QUIT;
sprintf(vname, "Open%i", p);
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;
}
/* Initialize decision variables for transportation decision variables:
how much to transport from a plant p to a warehouse w */
for (w = 0; w < nWarehouses; ++w)
{

38

for (p = 0; p < nPlants; ++p)


{
col = transportcol(w, p);
error = GRBsetdblattrelement(model, "Obj", col, TransCosts[w][p]);
if (error) goto QUIT;
sprintf(vname, "Trans%i.%i", p, w);
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;
}
}
/* The objective is to minimize the total fixed and variable costs */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;
/* Make space for constraint data */
rowct = (nPlants > nWarehouses) ? nPlants : nWarehouses;
cbeg = malloc(sizeof(int) * rowct);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * (nPlants * (nWarehouses + 1)));
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * (nPlants * (nWarehouses + 1)));
if (!cval) goto QUIT;
rhs = malloc(sizeof(double) * rowct);
if (!rhs) goto QUIT;
sense = malloc(sizeof(char) * rowct);
if (!sense) goto QUIT;
cname = calloc(rowct, sizeof(char*));
if (!cname) goto QUIT;
/* Production constraints
Note that the limit sets the production to zero if
the plant is closed */
idx = 0;
for (p = 0; p < nPlants; ++p)
{
cbeg[p] = idx;
rhs[p] = 0.0;
sense[p] = GRB_LESS_EQUAL;
cname[p] = malloc(sizeof(char) * MAXSTR);
if (!cname[p]) goto QUIT;
cnamect++;
sprintf(cname[p], "Capacity%i", p);
for (w = 0; w < nWarehouses; ++w)
{

39

cind[idx] = transportcol(w, p);


cval[idx++] = 1.0;
}
cind[idx] = opencol(p);
cval[idx++] = -Capacity[p];
}
error = GRBaddconstrs(model, nPlants, idx, cbeg, cind, cval, sense,
rhs, cname);
if (error) goto QUIT;
/* Demand constraints */
idx = 0;
for (w = 0; w < nWarehouses; ++w)
{
cbeg[w] = idx;
sense[w] = GRB_EQUAL;
sprintf(cname[w], "Demand%i", w);
for (p = 0; p < nPlants; ++p)
{
cind[idx] = transportcol(w, p);
cval[idx++] = 1.0;
}
}
error = GRBaddconstrs(model, nWarehouses, idx, cbeg, cind, cval, sense,
Demand, cname);
if (error) goto QUIT;
/* Guess at the starting point: close the plant with the highest
fixed costs; open all others */
/* First, open all plants */
for (p = 0; p < nPlants; ++p)
{
error = GRBsetdblattrelement(model, "Start", opencol(p), 1.0);
if (error) goto QUIT;
}
/* Now close the plant with the highest fixed cost */
printf("Initial guess:\n");
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] > maxFixed)
{
maxFixed = FixedCosts[p];
}

40

}
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] == maxFixed)
{
error = GRBsetdblattrelement(model, "Start", opencol(p), 0.0);
if (error) goto QUIT;
printf("Closing plant %i\n\n", p);
break;
}
}
/* Use barrier to solve root relaxation */
error = GRBsetintparam(GRBgetenv(model),
GRB_INT_PAR_METHOD,
GRB_METHOD_BARRIER);
if (error) goto QUIT;
/* Solve */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Print solution */
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("\nTOTAL COSTS: %f\n", obj);
printf("SOLUTION:\n");
for (p = 0; p < nPlants; ++p)
{
error = GRBgetdblattrelement(model, "X", opencol(p), &sol);
if (error) goto QUIT;
if (sol == 1.0)
{
printf("Plant %i open:\n", p);
for (w = 0; w < nWarehouses; ++w)
{
error = GRBgetdblattrelement(model, "X", transportcol(w, p), &sol);
if (error) goto QUIT;
if (sol > 0.0001)
{
printf(" Transport %f units to warehouse %i\n", sol, w);
}
}
}
else

41

{
printf("Plant %i closed!\n", p);
}
}

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(cbeg);
free(cind);
free(cval);
free(rhs);
free(sense);
for (p = 0; p < cnamect; ++p) {
free(cname[p]);
}
free(cname);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

42

feasopt_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, adds artificial
variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables. */
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
<string.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model
= NULL;
GRBmodel *feasmodel = NULL;
double
*rhspen
= NULL;
int
error = 0;
int
i, j;
int
numvars, numconstrs;
char
sense;
int
vind[1];
double
vval[1];
double
feasobj;
char
*cname, *vname;
if (argc < 2)
{
fprintf(stderr, "Usage: feasopt_c filename\n");
exit(1);
}
error = GRBloadenv(&env, "feasopt.log");
if (error) goto QUIT;
error = GRBreadmodel(env, argv[1], &model);
43

if (error) goto QUIT;


/* Create a copy to use FeasRelax feature later */
feasmodel = GRBcopymodel(model);
if (error) goto QUIT;
/* clear objective */
error = GRBgetintattr(model, "NumVars", &numvars);
if (error) goto QUIT;
for (j = 0; j < numvars; ++j)
{
error = GRBsetdblattrelement(model, "Obj", j, 0.0);
if (error) goto QUIT;
}
/* add slack variables */
error = GRBgetintattr(model, "NumConstrs", &numconstrs);
if (error) goto QUIT;
for (i = 0; i < numconstrs; ++i)
{
error = GRBgetcharattrelement(model, "Sense", i, &sense);
if (error) goto QUIT;
if (sense != >)
{
error = GRBgetstrattrelement(model, "ConstrName", i, &cname);
if (error) goto QUIT;
vname = malloc(sizeof(char) * (6 + strlen(cname)));
if (!vname) goto QUIT;
strcpy(vname, "ArtN_");
strcat(vname, cname);
vind[0] = i;
vval[0] = -1.0;
error = GRBaddvar(model, 1, vind, vval, 1.0, 0.0, GRB_INFINITY,
GRB_CONTINUOUS, vname);
if (error) goto QUIT;
free(vname);
}
if (sense != <)
{
error = GRBgetstrattrelement(model, "ConstrName", i, &cname);
if (error) goto QUIT;
vname = malloc(sizeof(char) * (6 + strlen(cname)));
if (!vname) goto QUIT;
strcpy(vname, "ArtP_");

44

strcat(vname, cname);
vind[0] = i;
vval[0] = 1.0;
error = GRBaddvar(model, 1, vind, vval, 1.0, 0.0, GRB_INFINITY,
GRB_CONTINUOUS, vname);
if (error) goto QUIT;
free(vname);
}
}
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* optimize modified model */
error = GRBwrite(model, "feasopt.lp");
if (error) goto QUIT;
error = GRBoptimize(model);
if (error) goto QUIT;
/* Use FeasRelax feature */
rhspen = (double *) malloc(numconstrs*sizeof(double));
if (rhspen == NULL) {
printf("ERROR: out of memory\n");
goto QUIT;
}
/* set penalties for artificial variables */
for (i = 0; i < numconstrs; i++) rhspen[i] = 1;
/* create a FeasRelax model with the original objective recovered
and enforcement on minimum of aretificial variables */
error = GRBfeasrelax(feasmodel, GRB_FEASRELAX_LINEAR, 1,
NULL, NULL, rhspen, &feasobj);
if (error) goto QUIT;
/* optimize FeasRelax model */
error = GRBwrite(feasmodel, "feasopt1.lp");
if (error) goto QUIT;
error = GRBoptimize(feasmodel);
if (error) goto QUIT;

QUIT:

45

/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free models, env and etc. */
if (rhspen) free(rhspen);
GRBfreemodel(model);
GRBfreemodel(feasmodel);
GRBfreeenv(env);
return 0;
}

46

fixanddive_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Implement a simple MIP heuristic. Relax the model,
sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

typedef struct
{
int index;
double X;
}
var_t ;
int vcomp(const void* v1, const void* v2);

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL, *modelenv = NULL;
GRBmodel *model = NULL;
int
error = 0;
int
j, iter, nfix;
int
numvars, numintvars, numfractional;
int
*intvars = NULL;
int
status;
char
vtype, *vname;
double
sol, obj, fixval;
var_t
*fractional = NULL;
if (argc < 2)
{
fprintf(stderr, "Usage: fixanddive_c filename\n");
exit(1);
}

47

error = GRBloadenv(&env, "fixanddive.log");


if (error) goto QUIT;
/* Read model */
error = GRBreadmodel(env, argv[1], &model);
if (error) goto QUIT;
/* Collect integer variables and relax them */
error = GRBgetintattr(model, "NumVars", &numvars);
if (error) goto QUIT;
error = GRBgetintattr(model, "NumIntVars", &numintvars);
if (error) goto QUIT;
intvars = malloc(sizeof(int) * numintvars);
if (!intvars) goto QUIT;
fractional = malloc(sizeof(var_t) * numintvars);
if (!fractional) goto QUIT;
numfractional = 0;
for (j = 0; j < numvars; j++)
{
error = GRBgetcharattrelement(model, "VType", j, &vtype);
if (error) goto QUIT;
if (vtype != GRB_CONTINUOUS)
{
intvars[numfractional++] = j;
error = GRBsetcharattrelement(model, "VType", j, GRB_CONTINUOUS);
if (error) goto QUIT;
}
}
modelenv = GRBgetenv(model);
if (!modelenv) goto QUIT;
error = GRBsetintparam(modelenv, "OutputFlag", 0);
if (error) goto QUIT;
error = GRBoptimize(model);
if (error) goto QUIT;
/* Perform multiple iterations. In each iteration, identify the first
quartile of integer variables that are closest to an integer value
in the relaxation, fix them to the nearest integer, and repeat. */
for (iter = 0; iter < 1000; ++iter)
{
/* create a list of fractional variables, sorted in order of
increasing distance from the relaxation solution to the nearest

48

integer value */
numfractional = 0;
for (j = 0; j < numintvars; ++j)
{
error = GRBgetdblattrelement(model, "X", intvars[j], &sol);
if (error) goto QUIT;
if (fabs(sol - floor(sol + 0.5)) > 1e-5)
{
fractional[numfractional].index = intvars[j];
fractional[numfractional++].X = sol;
}
}
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("Iteration %i, obj %f, fractional %i\n",
iter, obj, numfractional);
if (numfractional == 0)
{
printf("Found feasible solution - objective %f\n", obj);
break;
}
/* Fix the first quartile to the nearest integer value */
qsort(fractional, numfractional, sizeof(var_t), vcomp);
nfix = numfractional / 4;
nfix = (nfix > 1) ? nfix : 1;
for (j = 0; j < nfix; ++j)
{
fixval = floor(fractional[j].X + 0.5);
error = GRBsetdblattrelement(model, "LB", fractional[j].index, fixval);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", fractional[j].index, fixval);
if (error) goto QUIT;
error = GRBgetstrattrelement(model, "VarName",
fractional[j].index, &vname);
if (error) goto QUIT;
printf(" Fix %s to %f ( rel %f )\n", vname, fixval, fractional[j].X);
}
error = GRBoptimize(model);
if (error) goto QUIT;

49

/* Check optimization result */


error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if (status != GRB_OPTIMAL)
{
printf("Relaxation is infeasible\n");
break;
}
}

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(intvars);
free(fractional);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

int vcomp(const void* v1, const void* v2)


{
double sol1, sol2, frac1, frac2;
sol1 = fabs(((var_t *)v1)->X);
sol2 = fabs(((var_t *)v2)->X);
frac1 = fabs(sol1 - floor(sol1 + 0.5));

50

frac2 = fabs(sol2 - floor(sol2 + 0.5));


return (frac1 < frac2) ? -1 : ((frac1 == frac2) ? 0 : 1);
}

51

lp_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*masterenv = NULL;
GRBmodel *model
= NULL;
GRBenv
*modelenv = NULL;
int
error
= 0;
int
optimstatus;
double
objval;
if (argc < 2) {
fprintf(stderr, "Usage: lp_c filename\n");
exit(1);
}
/* Create environment */
error = GRBloadenv(&masterenv, "lp.log");
if (error) goto QUIT;
/* Read model from file */
error = GRBreadmodel(masterenv, argv[1], &model);
if (error) goto QUIT;
/* Solve model */
error = GRBoptimize(model);
if (error) goto QUIT;

52

/* Capture solution information */


error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
/* If model is infeasible or unbounded, turn off presolve and resolve */
if (optimstatus == GRB_INF_OR_UNBD) {
modelenv = GRBgetenv(model);
if (!modelenv) {
fprintf(stderr, "Error: could not get model environment\n");
goto QUIT;
}
/* Change parameter on model environment. The model now has
a copy of the master environment, so changing the master will
no longer affect the model. */
error = GRBsetintparam(modelenv, "PRESOLVE", 0);
if (error) goto QUIT;
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
}
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
printf("Optimal objective: %.4e\n\n", objval);
} else if (optimstatus == GRB_INFEASIBLE) {
printf("Model is infeasible\n\n");
error = GRBcomputeIIS(model);
if (error) goto QUIT;
error = GRBwrite(model, "model.ilp");
if (error) goto QUIT;
} else if (optimstatus == GRB_UNBOUNDED) {
printf("Model is unbounded\n\n");
} else {
printf("Optimization was stopped with status = %d\n\n", optimstatus);
}

53

QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(masterenv));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(masterenv);
return 0;
}

54

lpmethod_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve a model with different values of the Method parameter;
show which value gives the shortest solve time. */
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int
argc,
char *argv[])
{
GRBenv
*env = NULL, *menv;
GRBmodel *m = NULL;
int
error = 0;
int
i;
int
optimstatus;
int
bestMethod = -1;
double
bestTime;
if (argc < 2)
{
fprintf(stderr, "Usage: lpmethod_c filename\n");
exit(1);
}
error = GRBloadenv(&env, "lpmethod.log");
if (error) goto QUIT;
/* Read model */
error = GRBreadmodel(env, argv[1], &m);
if (error) goto QUIT;
menv = GRBgetenv(m);
error = GRBgetdblparam(menv, "TimeLimit", &bestTime);
if (error) goto QUIT;
/* Solve the model with different values of Method */
for (i = 0; i <= 2; ++i)
{
error = GRBresetmodel(m);
if (error) goto QUIT;
error = GRBsetintparam(menv, "Method", i);
if (error) goto QUIT;
55

error = GRBoptimize(m);
if (error) goto QUIT;
error = GRBgetintattr(m, "Status", &optimstatus);
if (error) goto QUIT;
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(m, "Runtime", &bestTime);
if (error) goto QUIT;
bestMethod = i;
/* Reduce the TimeLimit parameter to save time
with other methods */
error = GRBsetdblparam(menv, "TimeLimit", bestTime);
if (error) goto QUIT;
}
}
/* Report which method was fastest */
if (bestMethod == -1) {
printf("Unable to solve this model\n");
} else {
printf("Solved in %f seconds with Method: %i\n",
bestTime, bestMethod);
}
QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(m);
/* Free environment */
GRBfreeenv(env);
return 0;
}

56

lpmod_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch). */
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
<string.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
int
j;
int
numvars, isMIP, status, minVar = 0;
double
minVal = GRB_INFINITY, sol, lb;
char
*varname;
double
warmCount, warmTime, coldCount, coldTime;
if (argc < 2)
{
fprintf(stderr, "Usage: lpmod_c filename\n");
exit(1);
}
error = GRBloadenv(&env, "lpmod.log");
if (error) goto QUIT;
/* Read model and determine whether it is an LP */
error = GRBreadmodel(env, argv[1], &model);
if (error) goto QUIT;
error = GRBgetintattr(model, "IsMIP", &isMIP);
if (error) goto QUIT;
if (isMIP)
{
printf("The model is not a linear program\n");
57

goto QUIT;
}
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) ||
(status == GRB_UNBOUNDED))
{
printf("The model cannot be solved because it is ");
printf("infeasible or unbounded\n");
goto QUIT;
}
if (status != GRB_OPTIMAL)
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
/* Find the smallest variable value */
error = GRBgetintattr(model, "NumVars", &numvars);
if (error) goto QUIT;
for (j = 0; j < numvars; ++j)
{
error = GRBgetdblattrelement(model, "X", j, &sol);
if (error) goto QUIT;
error = GRBgetdblattrelement(model, "LB", j, &lb);
if (error) goto QUIT;
if ((sol > 0.0001) && (sol < minVal) &&
(lb == 0.0))
{
minVal = sol;
minVar = j;
}
}
error = GRBgetstrattrelement(model, "VarName", minVar, &varname);
if (error) goto QUIT;
printf("\n*** Setting %s from %f to zero ***\n\n", varname, minVal);
error = GRBsetdblattrelement(model, "LB", minVar, 0.0);
if (error) goto QUIT;

58

/* Solve from this starting point */


error = GRBoptimize(model);
if (error) goto QUIT;
/* Save iteration & time info */
error = GRBgetdblattr(model, "IterCount", &warmCount);
if (error) goto QUIT;
error = GRBgetdblattr(model, "Runtime", &warmTime);
if (error) goto QUIT;
/* Reset the model and resolve */
printf("\n*** Resetting and solving ");
printf("without an advanced start ***\n\n");
error = GRBresetmodel(model);
if (error) goto QUIT;
error = GRBoptimize(model);
if (error) goto QUIT;
/* Save iteration & time info */
error = GRBgetdblattr(model, "IterCount", &coldCount);
if (error) goto QUIT;
error = GRBgetdblattr(model, "Runtime", &coldTime);
if (error) goto QUIT;
printf("\n*** Warm start: %f iterations, %f seconds\n",
warmCount, warmTime);
printf("*** Cold start: %f iterations, %f seconds\n",
coldCount, coldTime);

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);

59

/* Free environment */
GRBfreeenv(env);
return 0;
}

60

mip1_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple MIP model:
maximize
subject to

x +
y + 2 z
x + 2 y + 3 z <= 4
x +
y
>= 1
x, y, z binary

*/
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
double
sol[3];
int
ind[3];
double
val[3];
double
obj[3];
char
vtype[3];
int
optimstatus;
double
objval;
/* Create environment */
error = GRBloadenv(&env, "mip1.log");
if (error) goto QUIT;
/* Create an empty model */
error = GRBnewmodel(env, &model, "mip1", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;

/* Add variables */
obj[0] = -1; obj[1] = -1; obj[2] = -2;
vtype[0] = GRB_BINARY; vtype[1] = GRB_BINARY; vtype[2] = GRB_BINARY;
61

error = GRBaddvars(model, 3, 0, NULL, NULL, NULL, obj, NULL, NULL, vtype,


NULL);
if (error) goto QUIT;
/* Integrate new variables */
error = GRBupdatemodel(model);
if (error) goto QUIT;

/* First constraint: x + 2 y + 3 z <= 4 */


ind[0] = 0; ind[1] = 1; ind[2] = 2;
val[0] = 1; val[1] = 2; val[2] = 3;
error = GRBaddconstr(model, 3, ind, val, GRB_LESS_EQUAL, 4.0, "c0");
if (error) goto QUIT;
/* Second constraint: x + y >= 1 */
ind[0] = 0; ind[1] = 1;
val[0] = 1; val[1] = 1;
error = GRBaddconstr(model, 2, ind, val, GRB_GREATER_EQUAL, 1.0, "c1");
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Write model to mip1.lp */
error = GRBwrite(model, "mip1.lp");
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, sol);

62

if (error) goto QUIT;


printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.0f, y=%.0f, z=%.0f\n", sol[0], sol[1], sol[2]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

63

mip2_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, solves it and
prints the objective values from all feasible solutions
generated while solving the MIP. Then it creates the fixed
model and solves that model. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
GRBmodel *fixed = NULL;
int
error = 0;
int
ismip;
int
j, k, solcount, numvars;
double
objn, vobj, xn;
int
optimstatus, foptimstatus;
double
objval, fobjval;
char
*varname;
double
x;
/* To change settings for a loaded model, we need to get
the model environment, which will be freed when the model
is freed. */
GRBenv

*menv, *fenv;

if (argc < 2) {
fprintf(stderr, "Usage: mip2_c filename\n");
exit(1);
}
/* Create environment */
error = GRBloadenv(&env, "mip2.log");
if (error) goto QUIT;

64

/* Read model from file */


error = GRBreadmodel(env, argv[1], &model);
if (error) goto QUIT;
error = GRBgetintattr(model, "IsMIP", &ismip);
if (error) goto QUIT;
if (ismip == 0) {
printf("Model is not a MIP\n");
goto QUIT;
}
/* Get model environment */
menv = GRBgetenv(model);
if (!menv) {
fprintf(stderr, "Error: could not get model environment\n");
goto QUIT;
}
/* Solve model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
printf("Optimal objective: %.4e\n\n", objval);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n\n");
goto QUIT;
} else if (optimstatus == GRB_INFEASIBLE) {
printf("Model is infeasible\n\n");
goto QUIT;
} else if (optimstatus == GRB_UNBOUNDED) {
printf("Model is unbounded\n\n");
goto QUIT;

65

} else {
printf("Optimization was stopped with status = %d\n\n", optimstatus);
goto QUIT;
}
/* Iterate over the solutions and compute the objectives */
error = GRBsetintparam(menv, "OutputFlag", 0);
if (error) goto QUIT;
error = GRBgetintattr(model, "SolCount", &solcount);
if (error) goto QUIT;
error = GRBgetintattr(model, "NumVars", &numvars);
if (error) goto QUIT;
printf("\n");
for ( k = 0; k < solcount; ++k ) {
error = GRBsetintparam(menv, "SolutionNumber", k);
objn = 0.0;
for ( j = 0; j < numvars; ++j ) {
error = GRBgetdblattrelement(model, "Obj", j, &vobj);
if (error) goto QUIT;
error = GRBgetdblattrelement(model, "Xn", j, &xn);
if (error) goto QUIT;
objn += vobj * xn;
}
printf("Solution %i has objective: %f\n", k, objn);
}
printf("\n");
error = GRBsetintparam(menv, "OutputFlag", 1);
if (error) goto QUIT;
/* Create a fixed model, turn off presolve and solve */
fixed = GRBfixedmodel(model);
if (!fixed) {
fprintf(stderr, "Error: could not create fixed model\n");
goto QUIT;
}
fenv = GRBgetenv(fixed);
if (!fenv) {
fprintf(stderr, "Error: could not get fixed model environment\n");
goto QUIT;
}

66

error = GRBsetintparam(fenv, "PRESOLVE", 0);


if (error) goto QUIT;
error = GRBoptimize(fixed);
if (error) goto QUIT;
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &foptimstatus);
if (error) goto QUIT;
if (foptimstatus != GRB_OPTIMAL) {
fprintf(stderr, "Error: fixed model isnt optimal\n");
goto QUIT;
}
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &fobjval);
if (error) goto QUIT;
if (fabs(fobjval - objval) > 1.0e-6 * (1.0 + fabs(objval))) {
fprintf(stderr, "Error: objective values are different\n");
}
/* Print values of nonzero variables */
for ( j = 0; j < numvars; ++j ) {
error = GRBgetstrattrelement(fixed, "VarName", j, &varname);
if (error) goto QUIT;
error = GRBgetdblattrelement(fixed, "X", j, &x);
if (error) goto QUIT;
if (x != 0.0) {
printf("%s %f\n", varname, x);
}
}

QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free models */

67

GRBfreemodel(model);
GRBfreemodel(fixed);
/* Free environment */
GRBfreeenv(env);
return 0;
}

68

params_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Use parameters that are associated with a model.
A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.
*/
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int gap(GRBmodel*, double*);


int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL, *baseenv = NULL, *menv = NULL, *bestenv = NULL;
GRBmodel *base = NULL, *m = NULL, *bestModel = NULL;
int
error = 0;
int
i;
int
ismip;
int
mipfocus;
double
bestGap = GRB_INFINITY, currGap;
if (argc < 2)
{
fprintf(stderr, "Usage: params_c filename\n");
exit(1);
}
error = GRBloadenv(&env, "params.log");
if (error) goto QUIT;
/* Read model and verify that it is a MIP */
error = GRBreadmodel(env, argv[1], &base);
if (error) goto QUIT;
error = GRBgetintattr(base, "IsMIP", &ismip);
if (error) goto QUIT;
if (ismip == 0)
{
69

printf("The model is not an integer program\n");


goto QUIT;
}
/* Set a 5 second time limit */
baseenv = GRBgetenv(base);
if (!baseenv) goto QUIT;
error = GRBsetdblparam(baseenv, "TimeLimit", 5);
if (error) goto QUIT;
/* Now solve the model with different values of MIPFocus */
for (i = 0; i <= 3; ++i)
{
m = GRBcopymodel(base);
if (!m) goto QUIT;
menv = GRBgetenv(m);
if (!menv) goto QUIT;
error = GRBsetintparam(menv, "MIPFocus", i);
if (error) goto QUIT;
error = GRBoptimize(m);
if (error) goto QUIT;
error = gap(m, &currGap);
if (error) goto QUIT;
if (bestModel == NULL || bestGap > currGap)
{
GRBfreemodel(bestModel);
bestModel = m;
bestGap = currGap;
}
else
{
GRBfreemodel(m);
}
}
/* Finally, reset the time limit and continue to solve the
best model to optimality */
bestenv = GRBgetenv(bestModel);
if (!bestenv) goto QUIT;
error = GRBsetdblparam(bestenv, "TimeLimit", GRB_INFINITY);
if (error) goto QUIT;
error = GRBoptimize(bestModel);
if (error) goto QUIT;
error = GRBgetintparam(bestenv, "MIPFocus", &mipfocus);
if (error) goto QUIT;

70

printf("Solved with MIPFocus: %i\n", mipfocus);


QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free models */
GRBfreemodel(bestModel);
GRBfreemodel(base);
/* Free environment */
GRBfreeenv(env);
return 0;
}

/* Simple function to determine the MIP gap */


int gap(GRBmodel *model, double *gap)
{
int error;
int solcount;
double objval, objbound;
error = GRBgetintattr(model, "SolCount", &solcount);
if (error) return error;
error = GRBgetdblattr(model, "ObjVal", &objval);
if (error) return error;
if ((solcount == 0) || (fabs(objval) < 1e-6))
{
*gap = GRB_INFINITY;
return 0;
}
error = GRBgetdblattr(model, "ObjBound", &objbound);
if (error) return error;

71

*gap = fabs(objbound - objval) / fabs(objval);


return 0;
}

72

qcp_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QCP model:
maximize
subject to

x
x + y + z = 1
x^2 + y^2 <= z^2 (second-order cone)
x^2 <= yz
(rotated second-order cone)

*/
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
double
sol[3];
int
ind[3];
double
val[3];
double
obj[] = {1, 0, 0};
int
qrow[3];
int
qcol[3];
double
qval[3];
int
optimstatus;
double
objval;
/* Create environment */
error = GRBloadenv(&env, "qcp.log");
if (error) goto QUIT;
/* Create an empty model */
error = GRBnewmodel(env, &model, "qcp", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;

/* Add variables */

73

error = GRBaddvars(model, 3, 0, NULL, NULL, NULL, obj, NULL, NULL, NULL,


NULL);
if (error) goto QUIT;
/* Change sense to maximization */
error = GRBsetintattr(model, GRB_INT_ATTR_MODELSENSE, GRB_MAXIMIZE);
if (error) goto QUIT;
/* Integrate new variables */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Linear constraint: x + y + z = 1 */
ind[0] = 0; ind[1] = 1; ind[2] = 2;
val[0] = 1; val[1] = 1; val[2] = 1;
error = GRBaddconstr(model, 3, ind, val, GRB_EQUAL, 1.0, "c0");
if (error) goto QUIT;
/* Cone: x^2 + y^2 <= z^2 */
qrow[0] = 0; qcol[0] = 0; qval[0] = 1.0;
qrow[1] = 1; qcol[1] = 1; qval[1] = 1.0;
qrow[2] = 2; qcol[2] = 2; qval[2] = -1.0;
error = GRBaddqconstr(model, 0, NULL, NULL, 3, qrow, qcol, qval,
GRB_LESS_EQUAL, 0.0, "qc0");
if (error) goto QUIT;
/* Rotated cone: x^2 <= yz */
qrow[0] = 0; qcol[0] = 0; qval[0] = 1.0;
qrow[1] = 1; qcol[1] = 2; qval[1] = -1.0;
error = GRBaddqconstr(model, 0, NULL, NULL, 2, qrow, qcol, qval,
GRB_LESS_EQUAL, 0.0, "qc1");
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;

74

/* Write model to qcp.lp */


error = GRBwrite(model, "qcp.lp");
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, sol);
if (error) goto QUIT;
printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.2f, y=%.2f, z=%.2f\n", sol[0], sol[1], sol[2]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);

75

return 0;
}

76

qp_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x^2 + x*y + y^2 + y*z + z^2 + 2 x


x + 2 y + 3 z >= 4
x +
y
>= 1

It solves it once as a continuous model, and once as an integer model.


*/
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
double
sol[3];
int
ind[3];
double
val[3];
int
qrow[5];
int
qcol[5];
double
qval[5];
char
vtype[3];
int
optimstatus;
double
objval;
/* Create environment */
error = GRBloadenv(&env, "qp.log");
if (error) goto QUIT;
/* Create an empty model */
error = GRBnewmodel(env, &model, "qp", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Add variables */

77

error = GRBaddvars(model, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,


NULL);
if (error) goto QUIT;
/* Integrate new variables */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Quadratic objective terms */
qrow[0] = 0; qrow[1] = 0; qrow[2] = 1; qrow[3] = 1; qrow[4] = 2;
qcol[0] = 0; qcol[1] = 1; qcol[2] = 1; qcol[3] = 2; qcol[4] = 2;
qval[0] = 1; qval[1] = 1; qval[2] = 1; qval[3] = 1; qval[4] = 1;
error = GRBaddqpterms(model, 5, qrow, qcol, qval);
if (error) goto QUIT;
/* Linear objective term */
error = GRBsetdblattrelement(model, GRB_DBL_ATTR_OBJ, 0, 2.0);
if (error) goto QUIT;
/* First constraint: x + 2 y + 3 z <= 4 */
ind[0] = 0; ind[1] = 1; ind[2] = 2;
val[0] = 1; val[1] = 2; val[2] = 3;
error = GRBaddconstr(model, 3, ind, val, GRB_GREATER_EQUAL, 4.0, "c0");
if (error) goto QUIT;
/* Second constraint: x + y >= 1 */
ind[0] = 0; ind[1] = 1;
val[0] = 1; val[1] = 1;
error = GRBaddconstr(model, 2, ind, val, GRB_GREATER_EQUAL, 1.0, "c1");
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Write model to qp.lp */

78

error = GRBwrite(model, "qp.lp");


if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, sol);
if (error) goto QUIT;
printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.4f, y=%.4f, z=%.4f\n", sol[0], sol[1], sol[2]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}

/* Modify variable types */


vtype[0] = GRB_INTEGER; vtype[1] = GRB_INTEGER; vtype[2] = GRB_INTEGER;
error = GRBsetcharattrarray(model, GRB_CHAR_ATTR_VTYPE, 0, 3, vtype);
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Write model to qp2.lp */
error = GRBwrite(model, "qp2.lp");
if (error) goto QUIT;
/* Capture solution information */

79

error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);


if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, sol);
if (error) goto QUIT;
printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.4f, y=%.4f, z=%.4f\n", sol[0], sol[1], sol[2]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

80

sensitivity_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Simple MIP sensitivity analysis example.
For each integer variable, fix it to its lower and upper bound
and check the impact on the objective. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*env = NULL, *aenv;
GRBmodel *a = NULL, *b = NULL;
int
error = 0;
int
i, numvars, status;
char
vtype, *vname;
double
x, bnd, aobj, bobj, objchg;
if (argc < 2)
{
fprintf(stderr, "Usage: sensitivity_c filename\n");
exit(1);
}
error = GRBloadenv(&env, "sensitivity.log");
if (error) goto QUIT;
/* Read model */
error = GRBreadmodel(env, argv[1], &a);
if (error) goto QUIT;
error = GRBoptimize(a);
if (error) goto QUIT;
error = GRBgetdblattr(a, "ObjVal", &aobj);
if (error) goto QUIT;
aenv = GRBgetenv(a);
if (!aenv) goto QUIT;
error = GRBsetintparam(aenv, "OutputFlag", 0);
if (error) goto QUIT;
/* Iterate over all variables */
81

error = GRBgetintattr(a, "NumVars", &numvars);


if (error) goto QUIT;
for (i = 0; i < numvars; ++i)
{
error = GRBgetcharattrelement(a, "VType", i, &vtype);
if (error) goto QUIT;
if (vtype == GRB_BINARY)
{
/* Create clone and fix variable */
b = GRBcopymodel(a);
if (!b) goto QUIT;
error = GRBgetstrattrelement(a, "VarName", i, &vname);
if (error) goto QUIT;
error = GRBgetdblattrelement(a, "X", i, &x);
if (error) goto QUIT;
error = GRBgetdblattrelement(a, "LB", i, &bnd);
if (error) goto QUIT;
if (x - bnd < 0.5)
{
error = GRBgetdblattrelement(b, "UB", i, &bnd);
if (error) goto QUIT;
error = GRBsetdblattrelement(b, "LB", i, bnd);
if (error) goto QUIT;
}
else
{
error = GRBgetdblattrelement(b, "LB", i, &bnd);
if (error) goto QUIT;
error = GRBsetdblattrelement(b, "UB", i, bnd);
if (error) goto QUIT;
}
error = GRBoptimize(b);
if (error) goto QUIT;
error = GRBgetintattr(b, "Status", &status);
if (error) goto QUIT;
if (status == GRB_OPTIMAL)
{
error = GRBgetdblattr(b, "ObjVal", &bobj);
if (error) goto QUIT;
objchg = bobj - aobj;
if (objchg < 0)

82

{
objchg = 0;
}
printf("Objective sensitivity for variable %s is %f\n", vname, objchg);
}
else
{
printf("Objective sensitivity for variable %s is infinite\n", vname);
}
GRBfreemodel(b);
b = NULL;
}
}

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free models */
GRBfreemodel(a);
GRBfreemodel(b);
/* Free environment */
GRBfreeenv(env);
return 0;
}

83

sos_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example creates a very simple Special Ordered Set (SOS) model.
The model consists of 3 continuous variables, no linear constraints,
and a pair of SOS constraints of type 1. */
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0;
double
x[3];
double
obj[3];
double
ub[3];
int
sostype[2];
int
sosbeg[2];
int
sosind[4];
double
soswt[4];
int
optimstatus;
double
objval;
int
zero = 0;
/* Create environment */
error = GRBloadenv(&env, "sos.log");
if (error) goto QUIT;
/* Create an empty model */
error = GRBnewmodel(env, &model, "sos", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;

/* Add variables */
obj[0] = -2; obj[1] = -1; obj[2] = -1;
ub[0] = 1.0; ub[1] = 1.0; ub[2] = 2.0;
error = GRBaddvars(model, 3, 0, NULL, NULL, NULL, obj, NULL, ub, NULL,
84

NULL);
if (error) goto QUIT;
/* Integrate new variables */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Build first SOS1: x0=0 or x1=0 */
sosind[0] = 0; sosind[1] = 1;
soswt[0] = 1.0; soswt[1] = 2.0;
sosbeg[0] = 0; sostype[0] = GRB_SOS_TYPE1;
/* Build second SOS1: x0=0 or x2=0 */
sosind[2] = 0; sosind[3] = 2;
soswt[2] = 1.0; soswt[3] = 2.0;
sosbeg[1] = 2; sostype[1] = GRB_SOS_TYPE1;
/* Add SOSs to model */
error = GRBaddsos(model, 2, 4, sostype, sosbeg, sosind, soswt);
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Write model to sos.lp */
error = GRBwrite(model, "sos.lp");
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 3, x);
if (error) goto QUIT;

85

printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL) {
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.4f, y=%.4f, z=%.4f\n", x[0], x[1], x[2]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

86

sudoku_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/*
Sudoku example.
The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.
In the MIP formulation, binary variables x[i,j,v] indicate whether
cell <i,j> takes value v. The constraints are as follows:
1. Each cell must take exactly one value (sum_v x[i,j,v] = 1)
2. Each value is used exactly once per row (sum_i x[i,j,v] = 1)
3. Each value is used exactly once per column (sum_j x[i,j,v] = 1)
4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1)
*/
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<string.h>
"gurobi_c.h"

#define SUBDIM 3
#define DIM
(SUBDIM*SUBDIM)
int
main(int
argc,
char *argv[])
{
FILE
*fp
= NULL;
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
board[DIM][DIM];
char
inputline[100];
int
ind[DIM];
double
val[DIM];
double
lb[DIM*DIM*DIM];
char
vtype[DIM*DIM*DIM];
char
*names[DIM*DIM*DIM];
char
namestorage[10*DIM*DIM*DIM];
char
*cursor;
int
optimstatus;
double
objval;
int
zero = 0;
87

int
int

i, j, v, ig, jg, count;


error = 0;

if (argc < 2) {
fprintf(stderr, "Usage: sudoku_c datafile\n");
exit(1);
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Error: unable to open input file %s\n", argv[1]);
exit(1);
}
for (i = 0; i < DIM; i++) {
fgets(inputline, 100, fp);
if (strlen(inputline) < 9) {
fprintf(stderr, "Error: not enough board positions specified\n");
exit(1);
}
for (j = 0; j < DIM; j++) {
board[i][j] = (int) inputline[j] - (int) 1;
if (board[i][j] < 0 || board[i][j] >= DIM)
board[i][j] = -1;
}
}
/* Create an empty model */
cursor = namestorage;
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
for (v = 0; v < DIM; v++) {
if (board[i][j] == v)
lb[i*DIM*DIM+j*DIM+v] = 1;
else
lb[i*DIM*DIM+j*DIM+v] = 0;
vtype[i*DIM*DIM+j*DIM+v] = GRB_BINARY;
names[i*DIM*DIM+j*DIM+v] = cursor;
sprintf(names[i*DIM*DIM+j*DIM+v], "x[%d,%d,%d]", i, j, v+1);
cursor += strlen(names[i*DIM*DIM+j*DIM+v]) + 1;
}
}
}

88

/* Create environment */
error = GRBloadenv(&env, "sudoku.log");
if (error) goto QUIT;
/* Create new model */
error = GRBnewmodel(env, &model, "sudoku", DIM*DIM*DIM, NULL, lb, NULL,
vtype, names);
if (error) goto QUIT;
/* Each cell gets a value */
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
for (v = 0; v < DIM; v++) {
ind[v] = i*DIM*DIM + j*DIM + v;
val[v] = 1.0;
}
error = GRBaddconstr(model, DIM, ind, val, GRB_EQUAL, 1.0, NULL);
if (error) goto QUIT;
}
}
/* Each value must appear once in each row */
for (v = 0; v < DIM; v++) {
for (j = 0; j < DIM; j++) {
for (i = 0; i < DIM; i++) {
ind[i] = i*DIM*DIM + j*DIM + v;
val[i] = 1.0;
}
error = GRBaddconstr(model, DIM, ind, val, GRB_EQUAL, 1.0, NULL);
if (error) goto QUIT;
}
}
/* Each value must appear once in each column */
for (v = 0; v < DIM; v++) {
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {

89

ind[j] = i*DIM*DIM + j*DIM + v;


val[j] = 1.0;
}
error = GRBaddconstr(model, DIM, ind, val, GRB_EQUAL, 1.0, NULL);
if (error) goto QUIT;
}
}
/* Each value must appear once in each subgrid */
for (v = 0; v < DIM; v++) {
for (ig = 0; ig < SUBDIM; ig++) {
for (jg = 0; jg < SUBDIM; jg++) {
count = 0;
for (i = ig*SUBDIM; i < (ig+1)*SUBDIM; i++) {
for (j = jg*SUBDIM; j < (jg+1)*SUBDIM; j++) {
ind[count] = i*DIM*DIM + j*DIM + v;
val[count] = 1.0;
count++;
}
}
error = GRBaddconstr(model, DIM, ind, val, GRB_EQUAL, 1.0, NULL);
if (error) goto QUIT;
}
}
}
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Write model to sudoku.lp */
error = GRBwrite(model, "sudoku.lp");
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);

90

if (error) goto QUIT;


printf("\nOptimization complete\n");
if (optimstatus == GRB_OPTIMAL)
printf("Optimal objective: %.4e\n", objval);
else if (optimstatus == GRB_INF_OR_UNBD)
printf("Model is infeasible or unbounded\n");
else
printf("Optimization was stopped early\n");
printf("\n");
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

91

tsp_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/*
Solve a traveling salesman problem on a randomly generated set of
points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every node. The lazy constraint callback
adds new constraints to cut them off.
*/
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

/* Define structure to pass data to the callback function */


struct callback_data {
int n;
};

/* Given an integer-feasible solution sol, find the smallest


sub-tour. Result is returned in tour, and length is
returned in tourlenP. */
static void
findsubtour(int
n,
double *sol,
int
*tourlenP,
int
*tour)
{
int i, node, len, start;
int bestind, bestlen;
int *seen = NULL;
seen = (int *) malloc(n*sizeof(int));
if (seen == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}

92

for (i = 0; i < n; i++)


seen[i] = 0;
start
= 0;
bestlen = n+1;
bestind = -1;
while (start < n) {
for (node = 0; node < n; node++)
if (seen[node] == 0)
break;
if (node == n)
break;
for (len = 0; len < n; len++) {
tour[start+len] = node;
seen[node] = 1;
for (i = 0; i < n; i++) {
if (sol[node*n+i] > 0.5 && !seen[i]) {
node = i;
break;
}
}
if (i == n) {
len++;
if (len < bestlen) {
bestlen = len;
bestind = start;
}
start += len;
break;
}
}
}
for (i = 0; i < bestlen; i++)
tour[i] = tour[bestind+i];
*tourlenP = bestlen;
free(seen);
}

/* Subtour elimination callback. Whenever a feasible solution is found,


find the shortest subtour, and add a subtour elimination constraint
if that tour doesnt visit every node. */

93

int __stdcall
subtourelim(GRBmodel *model,
void
*cbdata,
int
where,
void
*usrdata)
{
struct callback_data *mydata = (struct callback_data *) usrdata;
int n = mydata->n;
int *tour = NULL;
double *sol = NULL;
int i, j, len, nz;
int error = 0;
if (where == GRB_CB_MIPSOL) {
sol = (double *) malloc(n*n*sizeof(double));
tour = (int *)
malloc(n*sizeof(int));
if (sol == NULL || tour == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
GRBcbget(cbdata, where, GRB_CB_MIPSOL_SOL, sol);
findsubtour(n, sol, &len, tour);
if (len < n) {
int
*ind = NULL;
double *val = NULL;
ind = (int *)
malloc(len*(len-1)/2*sizeof(int));
val = (double *) malloc(len*(len-1)/2*sizeof(double));
if (ind == NULL || val == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
/* Add subtour elimination constraint */
nz = 0;
for (i = 0; i <
for (j = i+1;
ind[nz++] =
for (i = 0; i <
val[i] = 1.0;

94

len; i++)
j < len; j++)
tour[i]*n+tour[j];
nz; i++)

error = GRBcblazy(cbdata, nz, ind, val, GRB_LESS_EQUAL, len-1);


free(ind);
free(val);
}
free(sol);
free(tour);
}
return error;
}
/* Euclidean distance between points i and j. */
static double
distance(double *x,
double *y,
int
i,
int
j)
{
double dx = x[i] - x[j];
double dy = y[i] - y[j];
return sqrt(dx*dx + dy*dy);
}
int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
i, j, len, n, solcount;
int
error = 0;
char
name[100];
double
*x = NULL;
double
*y = NULL;
int
*ind = NULL;
double
*val = NULL;
struct callback_data mydata;
if (argc < 2) {
fprintf(stderr, "Usage: tsp_c size\n");

95

exit(1);
}
n = atoi(argv[1]);
if (n == 0) {
fprintf(stderr, "Argument must be a positive integer.\n");
} else if (n > 100) {
printf("It will be a challenge to solve a TSP this large.\n");
}
x
y
ind
val

=
=
=
=

(double *) malloc(n*sizeof(double));
(double *) malloc(n*sizeof(double));
(int *)
malloc(n*sizeof(int));
(double *) malloc(n*sizeof(double));

if (x == NULL || y == NULL || ind == NULL || val == NULL) {


fprintf(stderr, "Out of memory\n");
exit(1);
}
/* Create random points */
for (i = 0; i < n; i++) {
x[i] = ((double) rand())/RAND_MAX;
y[i] = ((double) rand())/RAND_MAX;
}
/* Create environment */
error = GRBloadenv(&env, "tsp.log");
if (error) goto QUIT;
/* Create an empty model */
error = GRBnewmodel(env, &model, "tsp", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;

/* Add variables - one for every pair of nodes */


for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
sprintf(name, "x_%d_%d", i, j);
error = GRBaddvar(model, 0, NULL, NULL, distance(x, y, i, j),
0.0, 1.0, GRB_BINARY, name);

96

if (error) goto QUIT;


}
}
/* Integrate new variables */
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Degree-2 constraints */
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
ind[j] = i*n+j;
val[j] = 1.0;
}
sprintf(name, "deg2_%d", i);
error = GRBaddconstr(model, n, ind, val, GRB_EQUAL, 2, name);
if (error) goto QUIT;
}
/* Forbid edge from node back to itself */
for (i = 0; i < n; i++) {
error = GRBsetdblattrelement(model, GRB_DBL_ATTR_UB, i*n+i, 0);
if (error) goto QUIT;
}
/* Symmetric TSP */
for (i = 0; i < n; i++) {
for (j = 0; j < i; j++) {
ind[0] = i*n+j;
ind[1] = i+j*n;
val[0] = 1;
val[1] = -1;
error = GRBaddconstr(model, 2, ind, val, GRB_EQUAL, 0, NULL);
if (error) goto QUIT;
}
}
/* Set callback function */

97

mydata.n = n;
error = GRBsetcallbackfunc(model, subtourelim, (void *) &mydata);
if (error) goto QUIT;
/* Must set LazyConstraints parameter when using lazy constraints */
error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_LAZYCONSTRAINTS, 1);
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Extract solution */
error = GRBgetintattr(model, GRB_INT_ATTR_SOLCOUNT, &solcount);
if (error) goto QUIT;
if (solcount > 0) {
int *tour = NULL;
double *sol = NULL;
sol = (double *) malloc(n*n*sizeof(double));
tour = (int *) malloc(n*sizeof(int));
if (sol == NULL || tour == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, n*n, sol);
if (error) goto QUIT;
/* Print tour */
findsubtour(n, sol, &len, tour);
printf("Tour: ");
for (i = 0; i < len; i++)
printf("%d ", tour[i]);
printf("\n");
free(tour);
free(sol);

98

}
QUIT:
/* Free data */
free(x);
free(y);
free(ind);
free(val);
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

99

tune_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a model from a file and tunes it.
It then writes the best parameter settings to a file
and solves the model using these parameters. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
tuneresultcount;
int
error = 0;
if (argc < 2) {
fprintf(stderr, "Usage: tune_c filename\n");
exit(1);
}
/* Create environment */
error = GRBloadenv(&env, "tune_c.log");
if (error) goto QUIT;
/* Read model from file */
error = GRBreadmodel(env, argv[1], &model);
if (error) goto QUIT;
/* Set the TuneResults parameter to 1 */
error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_TUNERESULTS, 1);
if (error) goto QUIT;
/* Tune the model */
error = GRBtunemodel(model);
if (error) goto QUIT;
100

/* Get the number of tuning results */


error = GRBgetintattr(model, GRB_INT_ATTR_TUNE_RESULTCOUNT, &tuneresultcount);
if (error) goto QUIT;
if (tuneresultcount > 0) {
/* Load the best tuned parameters into the models environment */
error = GRBgettuneresult(model, 0);
if (error) goto QUIT;
/* Write tuned parameters to a file */
error = GRBwrite(model, "tune.prm");
if (error) goto QUIT;
/* Solve the model using the tuned parameters */
error = GRBoptimize(model);
if (error) goto QUIT;
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

101

workforce1_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts
besides what is reported via IIS. */
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
"gurobi_c.h"

#define xcol(w,s)
#define MAXSTR

nShifts*w+s
128

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0, status;
int
s, w, col;
int
*cbeg = NULL;
int
*cind = NULL;
int
idx;
double
*cval = NULL;
char
*sense = NULL;
char
vname[MAXSTR];
double
obj;
int
i, iis, numconstrs;
char
*cname;
/* Sample data */
const int nShifts = 14;
const int nWorkers = 7;
/* Sets of days and workers */
char* Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
102

char* Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
/* Number of workers required for each shift */
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
/* Amount each worker is paid to work one shift */
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
/* Worker availability: 0 if the
double availability[][14] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1,

worker is unavailable for a shift */


1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

/* Create environment */
error = GRBloadenv(&env, "workforce1.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "workforce1", nWorkers * nShifts,
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize assignment decision variables:
x[w][s] == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP. */
for (w = 0; w < nWorkers; ++w)
{
for (s = 0; s < nShifts; ++s)
{
col = xcol(w, s);
sprintf(vname, "%s.%s", Workers[w], Shifts[s]);
error = GRBsetdblattrelement(model, "UB", col, availability[w][s]);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "Obj", col, pay[w]);
if (error) goto QUIT;
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;

103

}
}
/* The objective is to minimize the total pay costs */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;
/* Make space for constraint data */
cbeg = malloc(sizeof(int) * nShifts);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * nShifts * nWorkers);
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * nShifts * nWorkers);
if (!cval) goto QUIT;
sense = malloc(sizeof(char) * nShifts);
if (!sense) goto QUIT;
/* Constraint: assign exactly shiftRequirements[s] workers
to each shift s */
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cbeg[s] = idx;
sense[s] = GRB_EQUAL;
for (w = 0; w < nWorkers; ++w)
{
cind[idx] = xcol(w, s);
cval[idx++] = 1.0;
}
}
error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense,
shiftRequirements, Shifts);
if (error) goto QUIT;
/* Optimize */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if (status == GRB_UNBOUNDED)
{
printf("The model cannot be solved because it is unbounded\n");
goto QUIT;
}
if (status == GRB_OPTIMAL)

104

{
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("The optimal objective is %f\n", obj);
goto QUIT;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
/* do IIS */
printf("The model is infeasible; computing IIS\n");
error = GRBcomputeIIS(model);
if (error) goto QUIT;
printf("\nThe following constraint(s) cannot be satisfied:\n");
error = GRBgetintattr(model, "NumConstrs", &numconstrs);
if (error) goto QUIT;
for (i = 0; i < numconstrs; ++i)
{
error = GRBgetintattrelement(model, "IISConstr", i, &iis);
if (error) goto QUIT;
if (iis)
{
error = GRBgetstrattrelement(model, "ConstrName", i, &cname);
if (error) goto QUIT;
printf("%s\n", cname);
}
}

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */

105

free(cbeg);
free(cind);
free(cval);
free(sense);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

106

workforce2_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS iteratively to
find all conflicting constraints. */
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
<string.h>
"gurobi_c.h"

#define xcol(w,s)
#define MAXSTR

nShifts*w+s
128

int
main(int
argc,
char *argv[])
{
GRBenv
*env
= NULL;
GRBmodel *model = NULL;
int
error = 0, status;
int
s, w, col;
int
*cbeg = NULL;
int
*cind = NULL;
int
idx;
double
*cval = NULL;
char
*sense = NULL;
char
vname[MAXSTR];
double
obj;
int
i, iis, numconstrs, numremoved = 0;
char
*cname;
char
**removed = NULL;
/* Sample data */
const int nShifts = 14;
const int nWorkers = 7;
/* Sets of days and workers */
char* Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
107

"Sun14" };
char* Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
/* Number of workers required for each shift */
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
/* Amount each worker is paid to work one shift */
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
/* Worker availability: 0 if the
double availability[][14] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1,

worker is unavailable for a shift */


1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

/* Create environment */
error = GRBloadenv(&env, "workforce2.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "workforce2", nWorkers * nShifts,
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize assignment decision variables:
x[w][s] == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP. */
for (w = 0; w < nWorkers; ++w)
{
for (s = 0; s < nShifts; ++s)
{
col = xcol(w, s);
sprintf(vname, "%s.%s", Workers[w], Shifts[s]);
error = GRBsetdblattrelement(model, "UB", col, availability[w][s]);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "Obj", col, pay[w]);
if (error) goto QUIT;
error = GRBsetstrattrelement(model, "VarName", col, vname);

108

if (error) goto QUIT;


}
}
/* The objective is to minimize the total pay costs */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;
/* Make space for constraint data */
cbeg = malloc(sizeof(int) * nShifts);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * nShifts * nWorkers);
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * nShifts * nWorkers);
if (!cval) goto QUIT;
sense = malloc(sizeof(char) * nShifts);
if (!sense) goto QUIT;
/* Constraint: assign exactly shiftRequirements[s] workers
to each shift s */
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cbeg[s] = idx;
sense[s] = GRB_EQUAL;
for (w = 0; w < nWorkers; ++w)
{
cind[idx] = xcol(w, s);
cval[idx++] = 1.0;
}
}
error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense,
shiftRequirements, Shifts);
if (error) goto QUIT;
/* Optimize */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if (status == GRB_UNBOUNDED)
{
printf("The model cannot be solved because it is unbounded\n");
goto QUIT;
}

109

if (status == GRB_OPTIMAL)
{
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("The optimal objective is %f\n", obj);
goto QUIT;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
/* do IIS */
printf("The model is infeasible; computing IIS\n");
/* Loop until we reduce to a model that can be solved */
error = GRBgetintattr(model, "NumConstrs", &numconstrs);
if (error) goto QUIT;
removed = calloc(numconstrs, sizeof(char*));
if (!removed) goto QUIT;
while (1)
{
error = GRBcomputeIIS(model);
if (error) goto QUIT;
printf("\nThe following constraint cannot be satisfied:\n");
for (i = 0; i < numconstrs; ++i)
{
error = GRBgetintattrelement(model, "IISConstr", i, &iis);
if (error) goto QUIT;
if (iis)
{
error = GRBgetstrattrelement(model, "ConstrName", i, &cname);
if (error) goto QUIT;
printf("%s\n", cname);
/* Remove a single constraint from the model */
removed[numremoved] = malloc(sizeof(char) * (1+strlen(cname)));
if (!removed[numremoved]) goto QUIT;
strcpy(removed[numremoved++], cname);
cind[0] = i;
error = GRBdelconstrs(model, 1, cind);
if (error) goto QUIT;
break;
}
}

110

printf("\n");
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if (status == GRB_UNBOUNDED)
{
printf("The model cannot be solved because it is unbounded\n");
goto QUIT;
}
if (status == GRB_OPTIMAL)
{
break;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
}
printf("\nThe following constraints were removed to get a feasible LP:\n");
for (i = 0; i < numremoved; ++i)
{
printf("%s ", removed[i]);
}
printf("\n");

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(cbeg);
free(cind);

111

free(cval);
free(sense);
for (i=0; i<numremoved; ++i) {
free(removed[i]);
}
free(removed);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

112

workforce3_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed. */
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
<string.h>
"gurobi_c.h"

#define xcol(w,s)
#define MAXSTR

nShifts*w+s
128

int
main(int
argc,
char *argv[])
{
GRBenv
*env = NULL;
GRBmodel *model = NULL;
int
error = 0, status;
int
s, w, col;
int
*cbeg = NULL;
int
*cind = NULL;
int
idx;
double
*cval = NULL;
char
*sense = NULL;
char
vname[MAXSTR];
double
obj;
int
i, j, numvars, numconstrs;
int
*vbeg = NULL;
int
*vind = NULL;
double
*vval = NULL;
double
*vobj = NULL;
double
sol;
char
*cname, *sname;
int
varnamesct = 0;
char
**varnames = NULL;
/* Sample data */
113

const int nShifts = 14;


const int nWorkers = 7;
/* Sets of days and workers */
char* Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
char* Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
/* Number of workers required for each shift */
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
/* Amount each worker is paid to work one shift */
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
/* Worker availability: 0 if the
double availability[][14] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1,

worker is unavailable for a shift */


1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

/* Create environment */
error = GRBloadenv(&env, "workforce3.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "workforce3", nWorkers * nShifts,
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize assignment decision variables:
x[w][s] == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP. */
for (w = 0; w < nWorkers; ++w)
{
for (s = 0; s < nShifts; ++s)
{

114

col = xcol(w, s);


sprintf(vname, "%s.%s", Workers[w],
error = GRBsetdblattrelement(model,
if (error) goto QUIT;
error = GRBsetdblattrelement(model,
if (error) goto QUIT;
error = GRBsetstrattrelement(model,
if (error) goto QUIT;

Shifts[s]);
"UB", col, availability[w][s]);
"Obj", col, pay[w]);
"VarName", col, vname);

}
}
/* The objective is to minimize the total pay costs */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;
/* Make space for constraint data */
cbeg = malloc(sizeof(int) * nShifts);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * nShifts * nWorkers);
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * nShifts * nWorkers);
if (!cval) goto QUIT;
sense = malloc(sizeof(char) * nShifts);
if (!sense) goto QUIT;
/* Constraint: assign exactly shiftRequirements[s] workers
to each shift s */
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cbeg[s] = idx;
sense[s] = GRB_EQUAL;
for (w = 0; w < nWorkers; ++w)
{
cind[idx] = xcol(w, s);
cval[idx++] = 1.0;
}
}
error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense,
shiftRequirements, Shifts);
if (error) goto QUIT;
/* Optimize */
error = GRBoptimize(model);
if (error) goto QUIT;

115

error = GRBgetintattr(model, "Status", &status);


if (error) goto QUIT;
if (status == GRB_UNBOUNDED)
{
printf("The model cannot be solved because it is unbounded\n");
goto QUIT;
}
if (status == GRB_OPTIMAL)
{
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("The optimal objective is %f\n", obj);
goto QUIT;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
/* Add slack variables to make the model feasible */
printf("The model is infeasible; adding slack variables\n");
/* Determine the matrix size before adding the slacks */
error = GRBgetintattr(model, "NumVars", &numvars);
if (error) goto QUIT;
error = GRBgetintattr(model, "NumConstrs", &numconstrs);
if (error) goto QUIT;
/* Set original objective coefficients to zero */
for (j = 0; j < numvars; ++j)
{
error = GRBsetdblattrelement(model, "Obj", j, 0.0);
if (error) goto QUIT;
}
/* Add a new slack variable to each shift constraint so that the shifts
can be satisfied */
vbeg = malloc(sizeof(int) * numconstrs);
if (!vbeg) goto QUIT;
vind = malloc(sizeof(int) * numconstrs);
if (!vind) goto QUIT;
vval = malloc(sizeof(double) * numconstrs);
if (!vval) goto QUIT;
vobj = malloc(sizeof(double) * numconstrs);

116

if (!vobj) goto QUIT;


varnames = calloc(numconstrs, sizeof(char*));
if (!varnames) goto QUIT;
for (i = 0; i < numconstrs; ++i)
{
vbeg[i] = i;
vind[i] = i;
vval[i] = 1.0;
vobj[i] = 1.0;
error = GRBgetstrattrelement(model, "ConstrName", i, &cname);
if (error) goto QUIT;
varnames[i] = malloc(sizeof(char*) * (6 + strlen(cname)));
if (!varnames[i]) goto QUIT;
varnamesct++;
strcpy(varnames[i], cname);
strcat(varnames[i], "Slack");
}
error = GRBaddvars(model, numconstrs, numconstrs,
vbeg, vind, vval, vobj, NULL, NULL, NULL, varnames);
if (error) goto QUIT;
error = GRBupdatemodel(model);
if (error) goto QUIT;
/* Solve the model with slacks */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "Status", &status);
if (error) goto QUIT;
if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) ||
(status == GRB_UNBOUNDED))
{
printf("The model with slacks cannot be solved "
"because it is infeasible or unbounded\n");
goto QUIT;
}
if (status != GRB_OPTIMAL)
{
printf("Optimization was stopped with status %i\n", status);
goto QUIT;
}
printf("\nSlack values:\n");
for (j = numvars; j < numvars + numconstrs; ++j)
{

117

error = GRBgetdblattrelement(model, "X", j, &sol);


if (error) goto QUIT;
if (sol > 1e-6)
{
error = GRBgetstrattrelement(model, "VarName", j, &sname);
if (error) goto QUIT;
printf("%s = %f\n", sname, sol);
}
}
QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(cbeg);
free(cind);
free(cval);
free(sense);
free(vbeg);
free(vind);
free(vval);
free(vobj);
for (i = 0; i < varnamesct; ++i)
{
free(varnames[i]);
}
free(varnames);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);

118

return 0;
}

119

workforce4_c.c
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. We use Pareto optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers. */
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<math.h>
<string.h>
"gurobi_c.h"

int solveAndPrint(GRBmodel* model,


int nShifts, int nWorkers, char** Workers,
int* status);

#define
#define
#define
#define
#define
#define
#define

xcol(w,s)
slackcol(s)
totSlackcol
totShiftscol(w)
avgShiftscol
diffShiftscol(w)
MAXSTR
128

nShifts*w+s
nShifts*nWorkers+s
nShifts*(nWorkers+1)
nShifts*(nWorkers+1)+1+w
(nShifts+1)*(nWorkers+1)
(nShifts+1)*(nWorkers+1)+1+w

int
main(int
argc,
char *argv[])
{
GRBenv
*env = NULL;
GRBmodel *model = NULL;
int
error = 0, status;
int
s, w, col;
int
*cbeg = NULL;
int
*cind = NULL;
int
idx;
double
*cval = NULL;
char
*sense = NULL;
char
vname[MAXSTR], cname[MAXSTR];
double
val;

120

/* Sample data */
const int nShifts = 14;
const int nWorkers = 7;
/* Sets of days and workers */
char* Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
char* Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
/* Number of workers required for each shift */
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
/* Worker availability: 0 if the
double availability[][14] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1,

worker is unavailable for a shift */


1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

/* Create environment */
error = GRBloadenv(&env, "workforce4.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "workforce4",
(nShifts + 1) * (nWorkers + 1),
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize assignment decision variables:
x[w][s] == 1 if worker w is assigned to shift s.
This is no longer a pure assignment model, so we must
use binary variables. */
for (w = 0; w < nWorkers; ++w)
{
for (s = 0; s < nShifts; ++s)
{
col = xcol(w, s);

121

sprintf(vname, "%s.%s", Workers[w], Shifts[s]);


error = GRBsetcharattrelement(model, "VType", col, GRB_BINARY);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", col, availability[w][s]);
if (error) goto QUIT;
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;
}
}
/* Initialize slack decision variables */
for (s = 0; s < nShifts; ++s)
{
sprintf(vname, "%sSlack", Shifts[s]);
error = GRBsetstrattrelement(model, "VarName", slackcol(s), vname);
if (error) goto QUIT;
}
/* Initialize total slack decision variable */
error = GRBsetstrattrelement(model, "VarName", totSlackcol, "totSlack");
if (error) goto QUIT;
/* Initialize variables to count the total shifts worked by each worker */
for (w = 0; w < nWorkers; ++w)
{
sprintf(vname, "%sTotShifts", Workers[w]);
error = GRBsetstrattrelement(model, "VarName", totShiftscol(w), vname);
if (error) goto QUIT;
}
/* The objective is to minimize the sum of the slacks */
error = GRBsetintattr(model, "ModelSense", 1);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "Obj", totSlackcol, 1.0);
if (error) goto QUIT;
/* Make space for constraint data */
cbeg = malloc(sizeof(int) * nShifts);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * nShifts * (nWorkers + 1));
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * nShifts * (nWorkers + 1));
if (!cval) goto QUIT;
sense = malloc(sizeof(char) * nShifts);
if (!sense) goto QUIT;

122

/* Constraint: assign exactly shiftRequirements[s] workers


to each shift s, plus the slack */
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cbeg[s] = idx;
sense[s] = GRB_EQUAL;
for (w = 0; w < nWorkers; ++w)
{
cind[idx] = xcol(w, s);
cval[idx++] = 1.0;
}
cind[idx] = slackcol(s);
cval[idx++] = 1.0;
}
error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense,
shiftRequirements, Shifts);
if (error) goto QUIT;
/* Constraint: set totSlack column equal to the total slack */
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cind[idx] = slackcol(s);
cval[idx++] = 1.0;
}
cind[idx] = totSlackcol;
cval[idx++] = -1.0;
error = GRBaddconstr(model, idx, cind, cval, GRB_EQUAL,
0.0, "totSlack");
if (error) goto QUIT;
/* Constraint: compute the total number of shifts for each worker */
for (w = 0; w < nWorkers; ++w)
{
idx = 0;
for (s = 0; s < nShifts; ++s)
{
cind[idx] = xcol(w,s);
cval[idx++] = 1.0;
}
sprintf(cname, "totShifts%s", Workers[w]);
cind[idx] = totShiftscol(w);
cval[idx++] = -1.0;

123

error = GRBaddconstr(model, idx, cind, cval, GRB_EQUAL, 0.0, cname);


if (error) goto QUIT;
}
/* Optimize */
error = solveAndPrint(model, nShifts, nWorkers, Workers, &status);
if (error) goto QUIT;
if (status != GRB_OPTIMAL) goto QUIT;
/* Constrain the slack by setting its upper and lower bounds */
error = GRBgetdblattrelement(model, "X", totSlackcol, &val);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", totSlackcol, val);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "LB", totSlackcol, val);
if (error) goto QUIT;
/* Variable to count the average number of shifts worked */
error = GRBaddvar(model, 0, NULL, NULL, 0, 0, GRB_INFINITY, GRB_CONTINUOUS,
"avgShifts");
if (error) goto QUIT;
/* Variables to count the difference from average for each worker;
note that these variables can take negative values. */
error = GRBaddvars(model, nWorkers, 0, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL);
if (error) goto QUIT;
error = GRBupdatemodel(model);
if (error) goto QUIT;
for (w = 0; w < nWorkers; ++w)
{
sprintf(vname, "%sDiff", Workers[w]);
error = GRBsetstrattrelement(model, "VarName", diffShiftscol(w), vname);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "LB", diffShiftscol(w), -GRB_INFINITY);
if (error) goto QUIT;
}
/* Constraint: compute the average number of shifts worked */
idx = 0;
for (w = 0; w < nWorkers; ++w) {
cind[idx] = totShiftscol(w);
cval[idx++] = 1.0;

124

}
cind[idx] = avgShiftscol;
cval[idx++] = -nWorkers;
error = GRBaddconstr(model, idx, cind, cval, GRB_EQUAL, 0.0, "avgShifts");
if (error) goto QUIT;
// Constraint: compute the difference from the average number of shifts
for (w = 0; w < nWorkers; ++w) {
cind[0] = totShiftscol(w);
cval[0] = 1.0;
cind[1] = avgShiftscol;
cval[1] = -1.0;
cind[2] = diffShiftscol(w);
cval[2] = -1.0;
sprintf(cname, "%sDiff", Workers[w]);
error = GRBaddconstr(model, 3, cind, cval, GRB_EQUAL, 0.0, cname);
if (error) goto QUIT;
}
/* Objective: minimize the sum of the square of the difference from the
average number of shifts worked */
error = GRBsetdblattrelement(model, "Obj", totSlackcol, 0.0);
if (error) goto QUIT;
for (w = 0; w < nWorkers; ++w)
{
cind[w] = diffShiftscol(w);
cval[w] = 1.0;
}
error = GRBaddqpterms(model, nWorkers, cind, cind, cval);
if (error) goto QUIT;
/* Optimize */
error = solveAndPrint(model, nShifts, nWorkers, Workers, &status);
if (error) goto QUIT;
if (status != GRB_OPTIMAL) goto QUIT;

QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));

125

exit(1);
}
/* Free data */
free(cbeg);
free(cind);
free(cval);
free(sense);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}

int solveAndPrint(GRBmodel* model,


int nShifts, int nWorkers, char** Workers,
int* status)
{
int error, w;
double val;
error = GRBoptimize(model);
if (error) return error;
error = GRBgetintattr(model, "Status", status);
if (error) return error;
if ((*status == GRB_INF_OR_UNBD) || (*status == GRB_INFEASIBLE) ||
(*status == GRB_UNBOUNDED))
{
printf("The model cannot be solved "
"because it is infeasible or unbounded\n");
return 0;
}
if (*status != GRB_OPTIMAL)
{
printf("Optimization was stopped with status %i\n", *status);

126

return 0;
}
/* Print total slack and the number of shifts worked for each worker */
error = GRBgetdblattrelement(model, "X", totSlackcol, &val);
if (error) return error;
printf("\nTotal slack required: %f\n", val);
for (w = 0; w < nWorkers; ++w)
{
error = GRBgetdblattrelement(model, "X", totShiftscol(w), &val);
if (error) return error;
printf("%s worked %f shifts\n", Workers[w], val);
}
printf("\n");
return 0;
}

127

3.2

C++ Examples

This section includes source code for all of the Gurobi C++ examples. The same source code can
be found in the examples/c++ directory of the Gurobi distribution.

callback_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP or a MIP from a file, sets a callback
to monitor the optimization progress and to output some progress
information to the screen and to a log file. If it is a MIP and 10%
gap is reached, then it aborts */
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
class mycallback: public GRBCallback
{
public:
GRBVar* vars;
int numvars;
double lastnode;
double lastiter;
mycallback(GRBVar* xvars, int xnumvars) {
vars = xvars;
numvars = xnumvars;
lastnode = lastiter = -1;
}
protected:
void callback () {
try {
if (where == GRB_CB_MESSAGE) {
// Message callback
string msg = getStringInfo(GRB_CB_MSG_STRING);
cout << msg;
} else if (where == GRB_CB_PRESOLVE) {
// Presolve callback
int cdels = getIntInfo(GRB_CB_PRE_COLDEL);
int rdels = getIntInfo(GRB_CB_PRE_ROWDEL);
cout << cdels << " columns and " << rdels
<< " rows are removed" << endl;
} else if (where == GRB_CB_SIMPLEX) {
// Simplex callback
double itcnt = getDoubleInfo(GRB_CB_SPX_ITRCNT);
128

if (itcnt - lastiter >= 100) {


lastiter = itcnt;
double obj = getDoubleInfo(GRB_CB_SPX_OBJVAL);
double pinf = getDoubleInfo(GRB_CB_SPX_PRIMINF);
double dinf = getDoubleInfo(GRB_CB_SPX_DUALINF);
int ispert = getIntInfo(GRB_CB_SPX_ISPERT);
char ch;
if (ispert == 0)
ch = ;
else if (ispert == 1) ch = S;
else
ch = P;
cout << itcnt << " " << obj << ch << " " << pinf
<< " " << dinf << endl;
}
} else if (where == GRB_CB_MIP) {
// General MIP callback
double nodecnt = getDoubleInfo(GRB_CB_MIP_NODCNT);
if (nodecnt - lastnode >= 100) {
lastnode = nodecnt;
double objbst = getDoubleInfo(GRB_CB_MIP_OBJBST);
double objbnd = getDoubleInfo(GRB_CB_MIP_OBJBND);
if (fabs(objbst - objbnd) < 0.1 * (1.0 + fabs(objbst)))
abort();
int actnodes = (int) getDoubleInfo(GRB_CB_MIP_NODLFT);
int itcnt
= (int) getDoubleInfo(GRB_CB_MIP_ITRCNT);
int solcnt
= getIntInfo(GRB_CB_MIP_SOLCNT);
int cutcnt
= getIntInfo(GRB_CB_MIP_CUTCNT);
cout << nodecnt << " " << actnodes << " " << itcnt << " "
<< objbst << " " << objbnd << " " << solcnt << " "
<< cutcnt << endl;
}
} else if (where == GRB_CB_MIPSOL) {
// MIP solution callback
double obj
= getDoubleInfo(GRB_CB_MIPSOL_OBJ);
int
nodecnt = (int) getDoubleInfo(GRB_CB_MIPSOL_NODCNT);
double* x = getSolution(vars, numvars);
cout << "**** New solution at node " << nodecnt << ", obj "
<< obj << ", x[0] = " << x[0] << "****" << endl;
delete[] x;
}
} catch (GRBException e) {
cout << "Error number: " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during callback" << endl;
}

129

}
};
int
main(int
argc,
char *argv[])
{
if (argc < 2) {
cout << "Usage: callback_c++ filename" << endl;
return 1;
}
GRBEnv *env = 0;
GRBVar *vars = 0;
try {
env = new GRBEnv();
GRBModel model = GRBModel(*env, argv[1]);
model.getEnv().set(GRB_IntParam_OutputFlag, 0);
int numvars = model.get(GRB_IntAttr_NumVars);
vars = model.getVars();
// Create a callback object and associate it with the model
mycallback cb = mycallback(vars, numvars);
model.setCallback(&cb);
model.optimize();
for (int j = 0; j < numvars; j++) {
GRBVar v = vars[j];
cout << v.get(GRB_StringAttr_VarName) << " "
<< v.get(GRB_DoubleAttr_X) << endl;
}
} catch (GRBException e) {
cout << "Error number: " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during optimization" << endl;
}
delete[] vars;
delete env;

130

return 0;
}

131

dense_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.
*/
#include "gurobi_c++.h"
using namespace std;
static bool
dense_optimize(GRBEnv* env,
int
rows,
int
cols,
double* c,
/* linear portion of objective function */
double* Q,
/* quadratic portion of objective function */
double* A,
/* constraint matrix */
char*
sense, /* constraint senses */
double* rhs,
/* RHS vector */
double* lb,
/* variable lower bounds */
double* ub,
/* variable upper bounds */
char*
vtype, /* variable types (continuous, binary, etc.) */
double* solution,
double* objvalP)
{
GRBModel model = GRBModel(*env);
int i, j;
bool success = false;
/* Add variables to the model */
GRBVar* vars = model.addVars(lb, ub, NULL, vtype, NULL, cols);
model.update();
/* Populate A matrix */
for (i = 0; i < rows; i++) {
132

GRBLinExpr lhs = 0;
for (j = 0; j < cols; j++)
if (A[i*cols+j] != 0)
lhs += A[i*cols+j]*vars[j];
model.addConstr(lhs, sense[i], rhs[i]);
}
GRBQuadExpr obj = 0;
for (j = 0; j < cols; j++)
obj += c[j]*vars[j];
for (i = 0; i < cols; i++)
for (j = 0; j < cols; j++)
if (Q[i*cols+j] != 0)
obj += Q[i*cols+j]*vars[i]*vars[j];
model.setObjective(obj);
model.update();
model.write("dense.lp");
model.optimize();
if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
*objvalP = model.get(GRB_DoubleAttr_ObjVal);
for (i = 0; i < cols; i++)
solution[i] = vars[i].get(GRB_DoubleAttr_X);
success = true;
}
delete[] vars;
return success;
}
int
main(int
argc,
char *argv[])
{
GRBEnv* env = 0;
try {
env = new GRBEnv();
double c[] = {1, 1, 0};
double Q[3][3] = {{1, 1, 0}, {0, 1, 1}, {0, 0, 1}};
double A[2][3] = {{1, 2, 3}, {1, 1, 0}};

133

char
double
double
bool
double

sense[] = {>, >};


rhs[]
= {4, 1};
lb[]
= {0, 0, 0};
success;
objval, sol[3];

success = dense_optimize(env, 2, 3, c, &Q[0][0], &A[0][0], sense, rhs,


lb, NULL, NULL, sol, &objval);
cout << "x: " << sol[0] << " y: " << sol[1] << " z: " << sol[2] << endl;
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch(...) {
cout << "Exception during optimization" << endl;
}
delete env;
return 0;
}

134

diet_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve the classic diet model, showing how to add constraints
to an existing model. */
#include "gurobi_c++.h"
using namespace std;
void printSolution(GRBModel& model, int nCategories, int nFoods,
GRBVar* buy, GRBVar* nutrition) throw(GRBException);
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBVar* nutrition = 0;
GRBVar* buy = 0;
try
{
// Nutrition guidelines, based on
// USDA Dietary Guidelines for Americans, 2005
// http://www.health.gov/DietaryGuidelines/dga2005/
const int nCategories = 4;
string Categories[] =
{ "calories", "protein", "fat", "sodium" };
double minNutrition[] = { 1800, 91, 0, 0 };
double maxNutrition[] = { 2200, GRB_INFINITY, 65, 1779 };
// Set of foods
const int nFoods = 9;
string Foods[] =
{ "hamburger", "chicken", "hot dog", "fries",
"macaroni", "pizza", "salad", "milk", "ice cream" };
double cost[] =
{ 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59 };
// Nutrition values for the foods
double nutritionValues[][nCategories] = {
{ 410, 24, 26, 730 },
{ 420, 32, 10, 1190 },
{ 560, 20, 32, 1800 },
{ 380, 4, 19, 270 },

//
//
//
//

hamburger
chicken
hot dog
fries
135

{
{
{
{
{

320,
320,
320,
100,
330,

12, 10, 930 },


15, 12, 820 },
31, 12, 1230 },
8, 2.5, 125 },
8, 10, 180 }

//
//
//
//
//

macaroni
pizza
salad
milk
ice cream

};
// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "diet");
// Create decision variables for the nutrition information,
// which we limit via bounds
nutrition = model.addVars(minNutrition, maxNutrition, 0, 0,
Categories, nCategories);
// Create decision variables for the foods to buy
buy = model.addVars(0, 0, cost, 0, Foods, nFoods);
// The objective is to minimize the costs
model.set(GRB_IntAttr_ModelSense, 1);
// Update model to integrate new variables
model.update();
// Nutrition constraints
for (int i = 0; i < nCategories; ++i)
{
GRBLinExpr ntot = 0;
for (int j = 0; j < nFoods; ++j)
{
ntot += nutritionValues[j][i] * buy[j];
}
model.addConstr(ntot == nutrition[i], Categories[i]);
}
// Solve
model.optimize();
printSolution(model, nCategories, nFoods, buy, nutrition);
cout << "\nAdding constraint: at most 6 servings of dairy" << endl;
model.addConstr(buy[7] + buy[8] <= 6.0, "limit_dairy");
// Solve

136

model.optimize();
printSolution(model, nCategories, nFoods, buy, nutrition);
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] nutrition;
delete[] buy;
delete env;
return 0;
}
void printSolution(GRBModel& model, int nCategories, int nFoods,
GRBVar* buy, GRBVar* nutrition) throw(GRBException)
{
if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL)
{
cout << "\nCost: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
cout << "\nBuy:" << endl;
for (int j = 0; j < nFoods; ++j)
{
if (buy[j].get(GRB_DoubleAttr_X) > 0.0001)
{
cout << buy[j].get(GRB_StringAttr_VarName) << " " <<
buy[j].get(GRB_DoubleAttr_X) << endl;
}
}
cout << "\nNutrition:" << endl;
for (int i = 0; i < nCategories; ++i)
{
cout << nutrition[i].get(GRB_StringAttr_VarName) << " " <<
nutrition[i].get(GRB_DoubleAttr_X) << endl;
}
}
else
{
cout << "No solution" << endl;

137

}
}

138

facility_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Facility location: a company currently ships its product from 5 plants
to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.
*/
#include "gurobi_c++.h"
#include <sstream>
using namespace std;
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBVar* open = 0;
GRBVar** transport = 0;
int transportCt = 0;
try
{
// Number of plants and warehouses
const int nPlants = 5;
const int nWarehouses = 4;
// Warehouse demand in thousands of units
double Demand[] = { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double Capacity[] = { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double FixedCosts[] =
{ 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double TransCosts[][nPlants] = {
{ 4000, 2000, 3000, 2500, 4500 },
139

{ 2500, 2600, 3400, 3000, 4000 },


{ 1200, 1800, 2600, 4100, 3000 },
{ 2200, 2600, 3100, 3700, 3200 }
};
// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "facility");
// Plant open decision variables: open[p] == 1 if plant p is open.
open = model.addVars(nPlants, GRB_BINARY);
model.update();
int p;
for (p = 0; p < nPlants; ++p)
{
ostringstream vname;
vname << "Open" << p;
open[p].set(GRB_DoubleAttr_Obj, FixedCosts[p]);
open[p].set(GRB_StringAttr_VarName, vname.str());
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
transport = new GRBVar* [nWarehouses];
int w;
for (w = 0; w < nWarehouses; ++w)
{
transport[w] = model.addVars(nPlants);
transportCt++;
model.update();
for (p = 0; p < nPlants; ++p)
{
ostringstream vname;
vname << "Trans" << p << "." << w;
transport[w][p].set(GRB_DoubleAttr_Obj, TransCosts[w][p]);
transport[w][p].set(GRB_StringAttr_VarName, vname.str());
}
}
// The objective is to minimize the total fixed and variable costs
model.set(GRB_IntAttr_ModelSense, 1);
// Update model to integrate new variables
model.update();

140

// Production constraints
// Note that the right-hand limit sets the production to zero if
// the plant is closed
for (p = 0; p < nPlants; ++p)
{
GRBLinExpr ptot = 0;
for (w = 0; w < nWarehouses; ++w)
{
ptot += transport[w][p];
}
ostringstream cname;
cname << "Capacity" << p;
model.addConstr(ptot <= Capacity[p] * open[p], cname.str());
}
// Demand constraints
for (w = 0; w < nWarehouses; ++w)
{
GRBLinExpr dtot = 0;
for (p = 0; p < nPlants; ++p)
{
dtot += transport[w][p];
}
ostringstream cname;
cname << "Demand" << w;
model.addConstr(dtot == Demand[w], cname.str());
}
// Guess at the starting point: close the plant with the highest
// fixed costs; open all others
// First, open all plants
for (p = 0; p < nPlants; ++p)
{
open[p].set(GRB_DoubleAttr_Start, 1.0);
}
// Now close the plant with the highest fixed cost
cout << "Initial guess:" << endl;
double maxFixed = -GRB_INFINITY;
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] > maxFixed)
{

141

maxFixed = FixedCosts[p];
}
}
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] == maxFixed)
{
open[p].set(GRB_DoubleAttr_Start, 0.0);
cout << "Closing plant " << p << endl << endl;
break;
}
}
// Use barrier to solve root relaxation
model.getEnv().set(GRB_IntParam_Method, GRB_METHOD_BARRIER);
// Solve
model.optimize();
// Print solution
cout << "\nTOTAL COSTS: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
cout << "SOLUTION:" << endl;
for (p = 0; p < nPlants; ++p)
{
if (open[p].get(GRB_DoubleAttr_X) == 1.0)
{
cout << "Plant " << p << " open:" << endl;
for (w = 0; w < nWarehouses; ++w)
{
if (transport[w][p].get(GRB_DoubleAttr_X) > 0.0001)
{
cout << " Transport " <<
transport[w][p].get(GRB_DoubleAttr_X) <<
" units to warehouse " << w << endl;
}
}
}
else
{
cout << "Plant " << p << " closed!" << endl;
}
}
}
catch (GRBException e)

142

{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] open;
for (int i = 0; i < transportCt; ++i) {
delete[] transport[i];
}
delete[] transport;
delete env;
return 0;
}

143

feasopt_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, adds artificial
variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables. */
#include "gurobi_c++.h"
using namespace std;
int
main(int argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: feasopt_c++ filename" << endl;
return 1;
}
GRBEnv* env = 0;
GRBConstr* c = 0;
try
{
env = new GRBEnv();
GRBModel feasmodel = GRBModel(*env, argv[1]);
// Create a copy to use FeasRelax feature later */
GRBModel feasmodel1 = GRBModel(feasmodel);
// clear objective
feasmodel.setObjective(GRBLinExpr(0.0));
// add slack variables
c = feasmodel.getConstrs();
for (int i = 0; i < feasmodel.get(GRB_IntAttr_NumConstrs); ++i)
{
char sense = c[i].get(GRB_CharAttr_Sense);
if (sense != >)
{
144

double coef = -1.0;


feasmodel.addVar(0.0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, 1,
&c[i], &coef, "ArtN_" +
c[i].get(GRB_StringAttr_ConstrName));
}
if (sense != <)
{
double coef = 1.0;
feasmodel.addVar(0.0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, 1,
&c[i], &coef, "ArtP_" +
c[i].get(GRB_StringAttr_ConstrName));
}
}
feasmodel.update();
// optimize modified model
feasmodel.write("feasopt.lp");
feasmodel.optimize();
// use FeasRelax feature */
feasmodel1.feasRelax(GRB_FEASRELAX_LINEAR, true, false, true);
feasmodel1.write("feasopt1.lp");
feasmodel1.optimize();
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Error during optimization" << endl;
}
delete[] c;
delete env;
return 0;
}

145

fixanddive_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Implement a simple MIP heuristic. Relax the model,
sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible. */
#include "gurobi_c++.h"
#include <algorithm>
#include <cmath>
#include <deque>
using namespace std;
bool vcomp(GRBVar*, GRBVar*) throw(GRBException);
int
main(int argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: fixanddive_c++ filename" << endl;
return 1;
}
GRBEnv* env = 0;
GRBVar* x = 0;
try
{
// Read model
env = new GRBEnv();
GRBModel model = GRBModel(*env, argv[1]);
// Collect integer variables and relax them
// Note that we use GRBVar* to copy variables
deque<GRBVar*> intvars;
x = model.getVars();
for (int j = 0; j < model.get(GRB_IntAttr_NumVars); ++j)
{
if (x[j].get(GRB_CharAttr_VType) != GRB_CONTINUOUS)
{
intvars.push_back(&x[j]);
x[j].set(GRB_CharAttr_VType, GRB_CONTINUOUS);
146

}
}
model.getEnv().set(GRB_IntParam_OutputFlag, 0);
model.optimize();
// Perform multiple iterations. In each iteration, identify the first
// quartile of integer variables that are closest to an integer value
// in the relaxation, fix them to the nearest integer, and repeat.
for (int iter = 0; iter < 1000; ++iter)
{
// create a list of fractional variables, sorted in order of
// increasing distance from the relaxation solution to the nearest
// integer value
deque<GRBVar*> fractional;
for (size_t j = 0; j < intvars.size(); ++j)
{
double sol = fabs(intvars[j]->get(GRB_DoubleAttr_X));
if (fabs(sol - floor(sol + 0.5)) > 1e-5)
{
fractional.push_back(intvars[j]);
}
}
cout << "Iteration " << iter << ", obj " <<
model.get(GRB_DoubleAttr_ObjVal) << ", fractional " <<
fractional.size() << endl;
if (fractional.size() == 0)
{
cout << "Found feasible solution - objective " <<
model.get(GRB_DoubleAttr_ObjVal) << endl;
break;
}
// Fix the first quartile to the nearest integer value
sort(fractional.begin(), fractional.end(), vcomp);
int nfix = fractional.size() / 4;
nfix = (nfix > 1) ? nfix : 1;
for (int i = 0; i < nfix; ++i)
{
GRBVar* v = fractional[i];

147

double fixval = floor(v->get(GRB_DoubleAttr_X) + 0.5);


v->set(GRB_DoubleAttr_LB, fixval);
v->set(GRB_DoubleAttr_UB, fixval);
cout << " Fix " << v->get(GRB_StringAttr_VarName) << " to " <<
fixval << " ( rel " << v->get(GRB_DoubleAttr_X) << " )" <<
endl;
}
model.optimize();
// Check optimization result
if (model.get(GRB_IntAttr_Status) != GRB_OPTIMAL)
{
cout << "Relaxation is infeasible" << endl;
break;
}
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Error during optimization" << endl;
}
delete[] x;
delete env;
return 0;
}

bool vcomp(GRBVar* v1,


GRBVar* v2) throw(GRBException)
{
double sol1 = fabs(v1->get(GRB_DoubleAttr_X));
double sol2 = fabs(v2->get(GRB_DoubleAttr_X));
double frac1 = fabs(sol1 - floor(sol1 + 0.5));
double frac2 = fabs(sol2 - floor(sol2 + 0.5));
return (frac1 < frac2);
}

148

lp_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file */
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
if (argc < 2) {
cout << "Usage: lp_c++ filename" << endl;
return 1;
}
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env, argv[1]);
model.optimize();
int optimstatus = model.get(GRB_IntAttr_Status);
if (optimstatus == GRB_INF_OR_UNBD) {
model.getEnv().set(GRB_IntParam_Presolve, 0);
model.optimize();
optimstatus = model.get(GRB_IntAttr_Status);
}
if (optimstatus == GRB_OPTIMAL) {
double objval = model.get(GRB_DoubleAttr_ObjVal);
cout << "Optimal objective: " << objval << endl;
} else if (optimstatus == GRB_INFEASIBLE) {
cout << "Model is infeasible" << endl;
// compute and write out IIS
model.computeIIS();
model.write("model.ilp");
149

} else
cout
} else
cout

if
<<
{
<<
<<

(optimstatus == GRB_UNBOUNDED) {
"Model is unbounded" << endl;
"Optimization was stopped with status = "
optimstatus << endl;

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

150

lpmethod_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve a model with different values of the Method parameter;
show which value gives the shortest solve time. */
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: lpmethod_c++ filename" << endl;
return 1;
}
try {
// Read model
GRBEnv env = GRBEnv();
GRBModel m = GRBModel(env, argv[1]);
GRBEnv menv = m.getEnv();
// Solve the model with different values of Method
int
bestMethod = -1;
double bestTime = menv.get(GRB_DoubleParam_TimeLimit);
for (int i = 0; i <= 2; ++i) {
m.reset();
menv.set(GRB_IntParam_Method, i);
m.optimize();
if (m.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
bestTime = m.get(GRB_DoubleAttr_Runtime);
bestMethod = i;
// Reduce the TimeLimit parameter to save time
// with other methods
menv.set(GRB_DoubleParam_TimeLimit, bestTime);
}
}
// Report which method was fastest
if (bestMethod == -1) {
cout << "Unable to solve this model" << endl;
151

} else {
cout << "Solved in " << bestTime
<< " seconds with Method: " << bestMethod << endl;
}
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch(...) {
cout << "Exception during optimization" << endl;
}
return 0;
}

152

lpmod_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch). */
#include "gurobi_c++.h"
using namespace std;
int
main(int argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: lpmod_c++ filename" << endl;
return 1;
}
GRBEnv* env = 0;
GRBVar* v = 0;
try
{
// Read model and determine whether it is an LP
env = new GRBEnv();
GRBModel model = GRBModel(*env, argv[1]);
if (model.get(GRB_IntAttr_IsMIP) != 0)
{
cout << "The model is not a linear program" << endl;
return 1;
}
model.optimize();
int status = model.get(GRB_IntAttr_Status);
if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) ||
(status == GRB_UNBOUNDED))
{
cout << "The model cannot be solved because it is "
<< "infeasible or unbounded" << endl;
return 1;
153

}
if (status != GRB_OPTIMAL)
{
cout << "Optimization was stopped with status " << status << endl;
return 0;
}
// Find the smallest variable value
double minVal = GRB_INFINITY;
int minVar = 0;
v = model.getVars();
for (int j = 0; j < model.get(GRB_IntAttr_NumVars); ++j)
{
double sol = v[j].get(GRB_DoubleAttr_X);
if ((sol > 0.0001) && (sol < minVal) &&
(v[j].get(GRB_DoubleAttr_LB) == 0.0))
{
minVal = sol;
minVar = j;
}
}
cout << "\n*** Setting " << v[minVar].get(GRB_StringAttr_VarName)
<< " from " << minVal << " to zero ***" << endl << endl;
v[minVar].set(GRB_DoubleAttr_UB, 0.0);
// Solve from this starting point
model.optimize();
// Save iteration & time info
double warmCount = model.get(GRB_DoubleAttr_IterCount);
double warmTime = model.get(GRB_DoubleAttr_Runtime);
// Reset the model and resolve
cout << "\n*** Resetting and solving "
<< "without an advanced start ***\n" << endl;
model.reset();
model.optimize();
// Save iteration & time info
double coldCount = model.get(GRB_DoubleAttr_IterCount);
double coldTime = model.get(GRB_DoubleAttr_Runtime);
cout << "\n*** Warm start: " << warmCount << " iterations, " <<

154

warmTime << " seconds" << endl;


cout << "*** Cold start: " << coldCount << " iterations, " <<
coldTime << " seconds" << endl;
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Error during optimization" << endl;
}
delete[] v;
delete env;
return 0;
}

155

mip1_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple MIP model:
maximize
subject to

x +
y + 2 z
x + 2 y + 3 z <= 4
x +
y
>= 1
x, y, z binary

*/
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
// 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");
// Integrate new variables
model.update();
// Set objective: maximize x + y + 2 z
model.setObjective(x + y + 2 * z, GRB_MAXIMIZE);
// Add constraint: x + 2 y + 3 z <= 4
model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
// Add constraint: x + y >= 1
model.addConstr(x + y >= 1, "c1");

156

// Optimize model
model.optimize();
cout <<
<<
cout <<
<<
cout <<
<<

x.get(GRB_StringAttr_VarName) << " "


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

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


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

157

mip2_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, solves it and
prints the objective values from all feasible solutions
generated while solving the MIP. Then it creates the fixed
model and solves that model. */
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
int
main(int
argc,
char *argv[])
{
if (argc < 2) {
cout << "Usage: mip2_c++ filename" << endl;
return 1;
}
GRBEnv *env = 0;
GRBVar *vars = 0, *fvars = 0;
try {
env = new GRBEnv();
GRBModel model = GRBModel(*env, argv[1]);
if (model.get(GRB_IntAttr_IsMIP) == 0) {
throw GRBException("Model is not a MIP");
}
model.optimize();
int optimstatus = model.get(GRB_IntAttr_Status);
cout << "Optimization complete" << endl;
double objval = 0;
if (optimstatus == GRB_OPTIMAL) {
objval = model.get(GRB_DoubleAttr_ObjVal);
cout << "Optimal objective: " << objval << endl;
} else if (optimstatus == GRB_INF_OR_UNBD) {
cout << "Model is infeasible or unbounded" << endl;
return 0;
} else if (optimstatus == GRB_INFEASIBLE) {
cout << "Model is infeasible" << endl;
158

return 0;
} else if (optimstatus == GRB_UNBOUNDED) {
cout << "Model is unbounded" << endl;
return 0;
} else {
cout << "Optimization was stopped with status = "
<< optimstatus << endl;
return 0;
}
/* Iterate over the solutions and compute the objectives */
int numvars = model.get(GRB_IntAttr_NumVars);
vars = model.getVars();
model.getEnv().set(GRB_IntParam_OutputFlag, 0);
cout << endl;
for ( int k = 0; k < model.get(GRB_IntAttr_SolCount); ++k ) {
model.getEnv().set(GRB_IntParam_SolutionNumber, k);
double objn = 0.0;
for (int j = 0; j < numvars; j++) {
GRBVar v = vars[j];
objn += v.get(GRB_DoubleAttr_Obj) * v.get(GRB_DoubleAttr_Xn);
}
cout << "Solution " << k << " has objective: " << objn << endl;
}
cout << endl;
model.getEnv().set(GRB_IntParam_OutputFlag, 1);
/* Create a fixed model, turn off presolve and solve */
GRBModel fixed = model.fixedModel();
fixed.getEnv().set(GRB_IntParam_Presolve, 0);
fixed.optimize();
int foptimstatus = fixed.get(GRB_IntAttr_Status);
if (foptimstatus != GRB_OPTIMAL) {
cerr << "Error: fixed model isnt optimal" << endl;
return 0;
}

159

double fobjval = fixed.get(GRB_DoubleAttr_ObjVal);


if (fabs(fobjval - objval) > 1.0e-6 * (1.0 + fabs(objval))) {
cerr << "Error: objective values are different" << endl;
return 0;
}
/* Print values of nonzero variables */
fvars = fixed.getVars();
for (int j = 0; j < numvars; j++) {
GRBVar v = fvars[j];
if (v.get(GRB_DoubleAttr_X) != 0.0) {
cout << v.get(GRB_StringAttr_VarName) << " "
<< v.get(GRB_DoubleAttr_X) << endl;
}
}
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during optimization" << endl;
}
delete[] fvars;
delete[] vars;
delete env;
return 0;
}

160

params_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Use parameters that are associated with a model.
A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.
*/
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
double gap(GRBModel *model) throw(GRBException);
int
main(int argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: params_c++ filename" << endl;
return 1;
}
GRBEnv* env = 0;
GRBModel *bestModel = 0, *m = 0;
try
{
// Read model and verify that it is a MIP
env = new GRBEnv();
GRBModel base = GRBModel(*env, argv[1]);
if (base.get(GRB_IntAttr_IsMIP) == 0)
{
cout << "The model is not an integer program" << endl;
return 1;
}
// Set a 5 second time limit
base.getEnv().set(GRB_DoubleParam_TimeLimit, 5);
// Now solve the model with different values of MIPFocus,
// using a pointer to save the best model
double bestGap = GRB_INFINITY;
161

for (int i = 0; i <= 3; ++i)


{
m = new GRBModel(base);
m->getEnv().set(GRB_IntParam_MIPFocus, i);
m->optimize();
if (bestModel == 0 || bestGap > gap(m))
{
delete bestModel;
bestModel = m;
m = 0;
bestGap = gap(bestModel);
}
else
{
delete m;
m = 0;
}
}
// Finally, reset the time limit and continue to solve the
// best model to optimality
bestModel->getEnv().set(GRB_DoubleParam_TimeLimit, GRB_INFINITY);
bestModel->optimize();
cout << "Solved with MIPFocus: " <<
bestModel->getEnv().get(GRB_IntParam_MIPFocus) << endl;
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Error during optimization" << endl;
}
delete
delete
delete
return

bestModel;
m;
env;
0;

}
// Simple function to determine the MIP gap
double gap(GRBModel *model) throw(GRBException)

162

{
if ((model->get(GRB_IntAttr_SolCount) == 0) ||
(fabs(model->get(GRB_DoubleAttr_ObjVal)) < 1e-6))
{
return GRB_INFINITY;
}
return fabs(model->get(GRB_DoubleAttr_ObjBound) model->get(GRB_DoubleAttr_ObjVal)) /
fabs(model->get(GRB_DoubleAttr_ObjVal));
}

163

sensitivity_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Simple MIP sensitivity analysis example.
For each integer variable, fix it to its lower and upper bound
and check the impact on the objective. */
#include "gurobi_c++.h"
using namespace std;
int
main(int argc,
char *argv[])
{
if (argc < 2)
{
cout << "Usage: sensitivity_c++ filename" << endl;
return 1;
}
GRBEnv* env = 0;
GRBVar* avars = 0;
GRBVar* bv = 0;
try
{
// Read model
env = new GRBEnv();
GRBModel a = GRBModel(*env, argv[1]);
a.optimize();
a.getEnv().set(GRB_IntParam_OutputFlag, 0);
// Extract variables from model
avars = a.getVars();
for (int i = 0; i < a.get(GRB_IntAttr_NumVars); ++i)
{
GRBVar v = avars[i];
if (v.get(GRB_CharAttr_VType) == GRB_BINARY)
{
// Create clone and fix variable
GRBModel b = GRBModel(a);
bv = b.getVars();
if (v.get(GRB_DoubleAttr_X) - v.get(GRB_DoubleAttr_LB) < 0.5)
{
164

bv[i].set(GRB_DoubleAttr_LB, bv[i].get(GRB_DoubleAttr_UB));
}
else
{
bv[i].set(GRB_DoubleAttr_UB, bv[i].get(GRB_DoubleAttr_LB));
}
delete[] bv;
bv = 0;
b.optimize();
if (b.get(GRB_IntAttr_Status) == GRB_OPTIMAL)
{
double objchg =
b.get(GRB_DoubleAttr_ObjVal) - a.get(GRB_DoubleAttr_ObjVal);
if (objchg < 0)
{
objchg = 0;
}
cout << "Objective sensitivity for variable " <<
v.get(GRB_StringAttr_VarName) << " is " << objchg << endl;
}
else
{
cout << "Objective sensitivity for variable " <<
v.get(GRB_StringAttr_VarName) << " is infinite" << endl;
}
}
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Error during optimization" << endl;
}
delete[] avars;
delete[] bv;
delete env;

165

return 0;
}

166

qcp_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QCP model:
maximize
subject to

x
x + y + z = 1
x^2 + y^2 <= z^2 (second-order cone)
x^2 <= yz
(rotated second-order cone)

*/
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
// Create variables
GRBVar x = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "x");
GRBVar y = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "y");
GRBVar z = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "z");
// Integrate new variables
model.update();
// Set objective
GRBLinExpr obj = x;
model.setObjective(obj, GRB_MAXIMIZE);
// Add linear constraint: x + y + z = 1
model.addConstr(x + y + z == 1, "c0");
// Add second-order cone: x^2 + y^2 <= z^2
model.addQConstr(x*x + y*y <= z*z, "qc0");
167

// Add rotated cone: x^2 <= yz


model.addQConstr(x*x <= y*z, "qc1");
// Optimize model
model.optimize();
cout <<
<<
cout <<
<<
cout <<
<<

x.get(GRB_StringAttr_VarName) << " "


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

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


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

168

qp_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x^2 + x*y + y^2 + y*z + z^2 + 2 x


x + 2 y + 3 z >= 4
x +
y
>= 1

It solves it once as a continuous model, and once as an integer model.


*/
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
// Create variables
GRBVar x = model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, "x");
GRBVar y = model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, "y");
GRBVar z = model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, "z");
// Integrate new variables
model.update();
// Set objective
GRBQuadExpr obj = x*x + x*y + y*y + y*z + z*z + 2*x;
model.setObjective(obj);
// Add constraint: x + 2 y + 3 z >= 4
model.addConstr(x + 2 * y + 3 * z >= 4, "c0");
// Add constraint: x + y >= 1

169

model.addConstr(x + y >= 1, "c1");


// Optimize model
model.optimize();
cout <<
<<
cout <<
<<
cout <<
<<

x.get(GRB_StringAttr_VarName) << " "


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

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


// Change variable types to integer
x.set(GRB_CharAttr_VType, GRB_INTEGER);
y.set(GRB_CharAttr_VType, GRB_INTEGER);
z.set(GRB_CharAttr_VType, GRB_INTEGER);
// Optimize model
model.optimize();
cout <<
<<
cout <<
<<
cout <<
<<

x.get(GRB_StringAttr_VarName) << " "


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

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


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

170

sos_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example creates a very simple Special Ordered Set (SOS) model.
The model consists of 3 continuous variables, no linear constraints,
and a pair of SOS constraints of type 1. */
#include "gurobi_c++.h"
using namespace std;
int
main(int
argc,
char *argv[])
{
GRBEnv *env = 0;
GRBVar *x = 0;
try {
env = new GRBEnv();
GRBModel model = GRBModel(*env);
// Create variables
double ub[]
= {1, 1, 2};
double obj[]
= {-2, -1, -1};
string names[] = {"x0", "x1", "x2"};
x = model.addVars(NULL, ub, obj, NULL, names, 3);
// Integrate new variables
model.update();
// Add first SOS1: x0=0 or x1=0
GRBVar sosv1[] = {x[0], x[1]};
double soswt1[] = {1, 2};
model.addSOS(sosv1, soswt1, 2, GRB_SOS_TYPE1);
// Add second SOS1: x0=0 or x2=0 */
GRBVar sosv2[] = {x[0], x[2]};
double soswt2[] = {1, 2};

171

model.addSOS(sosv2, soswt2, 2, GRB_SOS_TYPE1);


// Optimize model
model.optimize();
for (int i = 0; i < 3; i++)
cout << x[i].get(GRB_StringAttr_VarName) << " "
<< x[i].get(GRB_DoubleAttr_X) << endl;
cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch(...) {
cout << "Exception during optimization" << endl;
}
delete[] x;
delete env;
return 0;
}

172

sudoku_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/*
Sudoku example.
The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.
In the MIP formulation, binary variables x[i,j,v] indicate whether
cell <i,j> takes value v. The constraints are as follows:
1. Each cell must take exactly one value (sum_v x[i,j,v] = 1)
2. Each value is used exactly once per row (sum_i x[i,j,v] = 1)
3. Each value is used exactly once per column (sum_j x[i,j,v] = 1)
4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1)
*/
#include "gurobi_c++.h"
#include <sstream>
using namespace std;
#define sd 3
#define n (sd*sd)
string itos(int i) {stringstream s; s << i; return s.str(); }
int
main(int
argc,
char *argv[])
{
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
GRBVar vars[n][n][n];
int i, j, v;
// Create 3-D array of model variables
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
for (v = 0; v < n; v++) {
string s = "G_" + itos(i) + "_" + itos(j) + "_" + itos(v);
vars[i][j][v] = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, s);
173

}
}
}
// Integrate variables into model
model.update();
// Add constraints
// Each cell must take one value
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
GRBLinExpr expr = 0;
for (v = 0; v < n; v++)
expr += vars[i][j][v];
string s = "V_" + itos(i) + "_" + itos(j);
model.addConstr(expr, GRB_EQUAL, 1.0, s);
}
}
// Each value appears once per row
for (i = 0; i < n; i++) {
for (v = 0; v < n; v++) {
GRBLinExpr expr = 0;
for (j = 0; j < n; j++)
expr += vars[i][j][v];
string s = "R_" + itos(i) + "_" + itos(v);
model.addConstr(expr == 1.0, s);
}
}
// Each value appears once per column
for (j = 0; j < n; j++) {
for (v = 0; v < n; v++) {
GRBLinExpr expr = 0;
for (i = 0; i < n; i++)
expr += vars[i][j][v];
string s = "C_" + itos(j) + "_" + itos(v);
model.addConstr(expr == 1.0, s);
}
}

174

// Each value appears once per sub-grid


for (v = 0; v < n; v++) {
for (int i0 = 0; i0 < sd; i0++) {
for (int j0 = 0; j0 < sd; j0++) {
GRBLinExpr expr = 0;
for (int i1 = 0; i1 < sd; i1++) {
for (int j1 = 0; j1 < sd; j1++) {
expr += vars[i0*sd+i1][j0*sd+j1][v];
}
}
string s = "Sub_" + itos(v) + "_" + itos(i0) + "_" + itos(j0);
model.addConstr(expr == 1.0, s);
}
}
}
// Fix variables associated with pre-specified cells
char input[10];
for (i = 0; i < n; i++) {
cin >> input;
for (j = 0; j < n; j++) {
int val = (int) input[j] - 48 - 1; // 0-based
if (val >= 0)
vars[i][j][val].set(GRB_DoubleAttr_LB, 1.0);
}
}
// Optimize model
model.optimize();
// Write model to file
model.write("sudoku.lp");
cout << endl;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
for (v = 0; v < n; v++) {
if (vars[i][j][v].get(GRB_DoubleAttr_X) > 0.5)

175

cout << v+1;


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

176

tsp_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve a traveling salesman problem on a randomly generated set of
points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every node. The lazy constraint callback
adds new constraints to cut them off. */
#include "gurobi_c++.h"
#include <cstdlib>
#include <cmath>
#include <sstream>
using namespace std;
string itos(int i) {stringstream s; s << i; return s.str(); }
double distance(double* x, double* y, int i, int j);
void findsubtour(int n, double** sol, int* tourlenP, int* tour);
// Subtour elimination callback. Whenever a feasible solution is found,
// find the smallest subtour, and add a subtour elimination constraint
// if the tour doesnt visit every node.
class subtourelim: public GRBCallback
{
public:
GRBVar** vars;
int n;
subtourelim(GRBVar** xvars, int xn) {
vars = xvars;
n
= xn;
}
protected:
void callback() {
try {
if (where == GRB_CB_MIPSOL) {
// Found an integer feasible solution - does it visit every node?
double **x = new double*[n];
int *tour = new int[n];
int i, j, len;
for (i = 0; i < n; i++)
x[i] = getSolution(vars[i], n);
findsubtour(n, x, &len, tour);
177

if (len < n) {
// Add subtour elimination constraint
GRBLinExpr expr = 0;
for (i = 0; i < len; i++)
for (j = 0; j < len; j++)
expr += vars[tour[i]][tour[j]];
addLazy(expr <= len-1);
}
for (i = 0; i < n; i++)
delete[] x[i];
delete[] x;
delete[] tour;
}
} catch (GRBException e) {
cout << "Error number: " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during callback" << endl;
}
}
};
// Given an integer-feasible solution sol, find the smallest
// sub-tour. Result is returned in tour, and length is
// returned in tourlenP.
void
findsubtour(int
n,
double** sol,
int*
tourlenP,
int*
tour)
{
bool* seen = new bool[n];
int bestind, bestlen;
int i, node, len, start;
for (i = 0; i < n; i++)
seen[i] = false;
start = 0;
bestlen = n+1;
bestind = -1;
node = 0;

178

while (start < n) {


for (node = 0; node < n; node++)
if (!seen[node])
break;
if (node == n)
break;
for (len = 0; len < n; len++) {
tour[start+len] = node;
seen[node] = true;
for (i = 0; i < n; i++) {
if (sol[node][i] > 0.5 && !seen[i]) {
node = i;
break;
}
}
if (i == n) {
len++;
if (len < bestlen) {
bestlen = len;
bestind = start;
}
start += len;
break;
}
}
}
for (i = 0; i < bestlen; i++)
tour[i] = tour[bestind+i];
*tourlenP = bestlen;
delete[] seen;
}
// Euclidean distance between points i and j.
double
distance(double* x,
double* y,
int
i,
int
j)
{
double dx = x[i]-x[j];
double dy = y[i]-y[j];

179

return sqrt(dx*dx+dy*dy);
}
int
main(int
argc,
char *argv[])
{
if (argc < 2) {
cout << "Usage: tsp_c++ size" << endl;
return 1;
}
int n = atoi(argv[1]);
double* x = new double[n];
double* y = new double[n];
int i;
for (i = 0; i < n; i++) {
x[i] = ((double) rand())/RAND_MAX;
y[i] = ((double) rand())/RAND_MAX;
}
GRBEnv *env = NULL;
GRBVar **vars = new GRBVar*[n];
try {
int j;
env = new GRBEnv();
GRBModel model = GRBModel(*env);
// Must set LazyConstraints parameter when using lazy constraints
model.getEnv().set(GRB_IntParam_LazyConstraints, 1);
// Create binary decision variables
for (i = 0; i < n; i++)
vars[i] = model.addVars(n);
model.update();
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
vars[i][j].set(GRB_CharAttr_VType, GRB_BINARY);
vars[i][j].set(GRB_DoubleAttr_Obj, distance(x, y, i, j));

180

vars[i][j].set(GRB_StringAttr_VarName, "x_"+itos(i)+"_"+itos(j));
}
}
// Integrate new variables
model.update();
// Degree-2 constraints
for (i = 0; i < n; i++) {
GRBLinExpr expr = 0;
for (j = 0; j < n; j++)
expr += vars[i][j];
model.addConstr(expr == 2, "deg2_"+itos(i));
}
// Forbid edge from node back to itself
for (i = 0; i < n; i++)
vars[i][i].set(GRB_DoubleAttr_UB, 0);
// Symmetric TSP
for (i = 0; i < n; i++)
for (j = 0; j < i; j++)
model.addConstr(vars[i][j] == vars[j][i]);
// Set callback function
subtourelim cb = subtourelim(vars, n);
model.setCallback(&cb);
// Optimize model
model.optimize();
// Extract solution
if (model.get(GRB_IntAttr_SolCount) > 0) {
double **sol = new double*[n];
for (i = 0; i < n; i++)
sol[i] = model.get(GRB_DoubleAttr_X, vars[i], n);
int* tour = new int[n];

181

int len;
findsubtour(n, sol, &len, tour);
cout << "Tour: ";
for (i = 0; i < len; i++)
cout << tour[i] << " ";
cout << endl;
for (i = 0; i < n; i++)
delete[] sol[i];
delete[] sol;
delete[] tour;
}
} catch (GRBException e) {
cout << "Error number: " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during optimization" << endl;
}
for (i = 0; i < n; i++)
delete[] vars[i];
delete[] vars;
delete[] x;
delete[] y;
delete env;
return 0;
}

182

tune_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a model from a file and tunes it.
It then writes the best parameter settings to a file
and solves the model using these parameters. */
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
int
main(int
argc,
char *argv[])
{
if (argc < 2) {
cout << "Usage: tune_c++ filename" << endl;
return 1;
}
GRBEnv *env = 0;
try {
env = new GRBEnv();
// Read model from file
GRBModel model = GRBModel(*env, argv[1]);
GRBEnv menv = model.getEnv();
// Set the TuneResults parameter to 1
menv.set(GRB_IntParam_TuneResults, 1);
// Tune the model
model.tune();
// Get the number of tuning results
int resultcount = model.get(GRB_IntAttr_TuneResultCount);
if (resultcount > 0) {
// Load the tuned parameters into the models environment
183

model.getTuneResult(0);
// Write tuned parameters to a file
model.write("tune.prm");
// Solve the model using the tuned parameters
model.optimize();
}
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch (...) {
cout << "Error during tuning" << endl;
}
delete env;
return 0;
}

184

workforce1_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts
besides what is reported via IIS. */
#include "gurobi_c++.h"
#include <sstream>
using namespace std;
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBConstr* c = 0;
GRBVar** x = 0;
int xCt = 0;
try
{
// Sample data
const int nShifts = 14;
const int nWorkers = 7;
// Sets of days and workers
string Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
// Number of workers required for each shift
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][nShifts] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
185

{
{
{
{
{
{

1,
0,
0,
1,
1,
1,

1,
0,
1,
1,
1,
1,

0,
1,
1,
1,
1,
1,

0,
1,
0,
1,
0,
0,

1,
1,
1,
1,
0,
1,

1,
0,
1,
0,
1,
1,

0,
1,
0,
1,
0,
1,

1,
1,
1,
1,
1,
1,

0,
1,
1,
1,
1,
1,

0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
0,
1,

0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,

0
1
1
1
1
1

},
},
},
},
},
} };

// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
x = new GRBVar*[nWorkers];
for (int w = 0; w < nWorkers; ++w)
{
x[w] = model.addVars(nShifts);
xCt++;
model.update();
for (int s = 0; s < nShifts; ++s)
{
ostringstream vname;
vname << Workers[w] << "." << Shifts[s];
x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]);
x[w][s].set(GRB_DoubleAttr_Obj, pay[w]);
x[w][s].set(GRB_StringAttr_VarName, vname.str());
}
}
// The objective is to minimize the total pay costs
model.set(GRB_IntAttr_ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s)
{
GRBLinExpr lhs = 0;
for (int w = 0; w < nWorkers; ++w)
{
lhs += x[w][s];

186

}
model.addConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Optimize
model.optimize();
int status = model.get(GRB_IntAttr_Status);
if (status == GRB_UNBOUNDED)
{
cout << "The model cannot be solved "
<< "because it is unbounded" << endl;
return 1;
}
if (status == GRB_OPTIMAL)
{
cout << "The optimal objective is " <<
model.get(GRB_DoubleAttr_ObjVal) << endl;
return 0;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
cout << "Optimization was stopped with status " << status << endl;
return 1;
}
// do IIS
cout << "The model is infeasible; computing IIS" << endl;
model.computeIIS();
cout << "\nThe following constraint(s) "
<< "cannot be satisfied:" << endl;
c = model.getConstrs();
for (int i = 0; i < model.get(GRB_IntAttr_NumConstrs); ++i)
{
if (c[i].get(GRB_IntAttr_IISConstr) == 1)
{
cout << c[i].get(GRB_StringAttr_ConstrName) << endl;
}
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}

187

catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] c;
for (int i = 0; i < xCt; ++i) {
delete[] x[i];
}
delete[] x;
delete env;
return 0;
}

188

workforce2_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS iteratively to
find all conflicting constraints. */
#include "gurobi_c++.h"
#include <sstream>
#include <deque>
using namespace std;
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBConstr* c = 0;
GRBVar** x = 0;
int xCt = 0;
try
{
// Sample data
const int nShifts = 14;
const int nWorkers = 7;
// Sets of days and workers
string Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
// Number of workers required for each shift
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][nShifts] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
189

{
{
{
{
{
{

1,
0,
0,
1,
1,
1,

1,
0,
1,
1,
1,
1,

0,
1,
1,
1,
1,
1,

0,
1,
0,
1,
0,
0,

1,
1,
1,
1,
0,
1,

1,
0,
1,
0,
1,
1,

0,
1,
0,
1,
0,
1,

1,
1,
1,
1,
1,
1,

0,
1,
1,
1,
1,
1,

0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
0,
1,

0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,

0
1
1
1
1
1

},
},
},
},
},
} };

// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
x = new GRBVar*[nWorkers];
for (int w = 0; w < nWorkers; ++w)
{
x[w] = model.addVars(nShifts);
xCt++;
model.update();
for (int s = 0; s < nShifts; ++s)
{
ostringstream vname;
vname << Workers[w] << "." << Shifts[s];
x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]);
x[w][s].set(GRB_DoubleAttr_Obj, pay[w]);
x[w][s].set(GRB_StringAttr_VarName, vname.str());
}
}
// The objective is to minimize the total pay costs
model.set(GRB_IntAttr_ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s)
{
GRBLinExpr lhs = 0;
for (int w = 0; w < nWorkers; ++w)
{
lhs += x[w][s];

190

}
model.addConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Optimize
model.optimize();
int status = model.get(GRB_IntAttr_Status);
if (status == GRB_UNBOUNDED)
{
cout << "The model cannot be solved "
<< "because it is unbounded" << endl;
return 1;
}
if (status == GRB_OPTIMAL)
{
cout << "The optimal objective is " <<
model.get(GRB_DoubleAttr_ObjVal) << endl;
return 0;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
cout << "Optimization was stopped with status " << status << endl;
return 1;
}
// do IIS
cout << "The model is infeasible; computing IIS" << endl;
deque<string> removed;
// Loop until we reduce to a model that can be solved
while (1)
{
model.computeIIS();
cout << "\nThe following constraint cannot be satisfied:" << endl;
c = model.getConstrs();
for (int i = 0; i < model.get(GRB_IntAttr_NumConstrs); ++i)
{
if (c[i].get(GRB_IntAttr_IISConstr) == 1)
{
cout << c[i].get(GRB_StringAttr_ConstrName) << endl;
// Remove a single constraint from the model
removed.push_back(c[i].get(GRB_StringAttr_ConstrName));
model.remove(c[i]);
break;
}

191

}
delete[] c;
c = 0;
cout << endl;
model.optimize();
status = model.get(GRB_IntAttr_Status);
if (status == GRB_UNBOUNDED)
{
cout << "The model cannot be solved because it is unbounded" << endl;
return 0;
}
if (status == GRB_OPTIMAL)
{
break;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
cout << "Optimization was stopped with status " << status << endl;
return 1;
}
}
cout << "\nThe following constraints were removed "
<< "to get a feasible LP:" << endl;
for (deque<string>::iterator r = removed.begin();
r != removed.end();
++r)
{
cout << *r << " ";
}
cout << endl;
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}

192

delete[] c;
for (int i = 0; i < xCt; ++i) {
delete[] x[i];
}
delete[] x;
delete env;
return 0;
}

193

workforce3_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed. */
#include "gurobi_c++.h"
#include <sstream>
#include <deque>
using namespace std;
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBConstr* c = 0;
GRBVar** x = 0;
int xCt = 0;
try
{
// Sample data
const int nShifts = 14;
const int nWorkers = 7;
// Sets of days and workers
string Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
// Number of workers required for each shift
double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][nShifts] =
194

{ {
{
{
{
{
{
{

0,
1,
0,
0,
1,
1,
1,

1,
1,
0,
1,
1,
1,
1,

1,
0,
1,
1,
1,
1,
1,

0,
0,
1,
0,
1,
0,
0,

1,
1,
1,
1,
1,
0,
1,

0,
1,
0,
1,
0,
1,
1,

1,
0,
1,
0,
1,
0,
1,

0,
1,
1,
1,
1,
1,
1,

1,
0,
1,
1,
1,
1,
1,

1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
x = new GRBVar*[nWorkers];
for (int w = 0; w < nWorkers; ++w)
{
x[w] = model.addVars(nShifts);
xCt++;
model.update();
for (int s = 0; s < nShifts; ++s)
{
ostringstream vname;
vname << Workers[w] << "." << Shifts[s];
x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]);
x[w][s].set(GRB_DoubleAttr_Obj, pay[w]);
x[w][s].set(GRB_StringAttr_VarName, vname.str());
}
}
// The objective is to minimize the total pay costs
model.set(GRB_IntAttr_ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s)
{
GRBLinExpr lhs = 0;
for (int w = 0; w < nWorkers; ++w)
{

195

lhs += x[w][s];
}
model.addConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Optimize
model.optimize();
int status = model.get(GRB_IntAttr_Status);
if (status == GRB_UNBOUNDED)
{
cout << "The model cannot be solved "
<< "because it is unbounded" << endl;
return 1;
}
if (status == GRB_OPTIMAL)
{
cout << "The optimal objective is " <<
model.get(GRB_DoubleAttr_ObjVal) << endl;
return 0;
}
if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE))
{
cout << "Optimization was stopped with status " << status << endl;
return 1;
}
// Add slack variables to make the model feasible
cout << "The model is infeasible; adding slack variables" << endl;
// Set original objective coefficients to zero
model.setObjective(GRBLinExpr(0.0));
// Add a new slack variable to each shift constraint so that the shifts
// can be satisfied
deque<GRBVar> slacks;
c = model.getConstrs();
for (int i = 0; i < model.get(GRB_IntAttr_NumConstrs); ++i)
{
GRBColumn col;
col.addTerm(1.0, c[i]);
GRBVar newvar =
model.addVar(0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, col,
c[i].get(GRB_StringAttr_ConstrName) + "Slack");
slacks.push_back(newvar);
}

196

// Solve the model with slacks


model.optimize();
status = model.get(GRB_IntAttr_Status);
if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) ||
(status == GRB_UNBOUNDED))
{
cout << "The model with slacks cannot be solved " <<
"because it is infeasible or unbounded" << endl;
return 1;
}
if (status != GRB_OPTIMAL)
{
cout << "Optimization was stopped with status " << status << endl;
return 1;
}
cout << "\nSlack values:" << endl;
for (deque<GRBVar>::iterator sv = slacks.begin();
sv != slacks.end();
++sv)
{
if (sv->get(GRB_DoubleAttr_X) > 1e-6)
{
cout << sv->get(GRB_StringAttr_VarName) << " = " <<
sv->get(GRB_DoubleAttr_X) << endl;
}
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] c;
for (int i = 0; i < xCt; ++i) {
delete[] x[i];
}

197

delete[] x;
delete env;
return 0;
}

198

workforce4_c++.cpp
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. We use Pareto optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers. */
#include "gurobi_c++.h"
#include <sstream>
using namespace std;
int solveAndPrint(GRBModel& model, GRBVar& totSlack,
int nWorkers, string* Workers,
GRBVar* totShifts) throw(GRBException);
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBConstr* c = 0;
GRBVar* v = 0;
GRBVar** x = 0;
GRBVar* slacks = 0;
GRBVar* totShifts = 0;
GRBVar* diffShifts = 0;
int xCt = 0;
try
{
// Sample data
const int nShifts = 14;
const int nWorkers = 7;
// Sets of days and workers
string Shifts[] =
{ "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string Workers[] =
{ "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
// Number of workers required for each shift
199

double shiftRequirements[] =
{ 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Worker availability: 0 if the
double availability[][nShifts] =
{ { 0, 1, 1, 0, 1, 0, 1, 0, 1,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1,

worker is unavailable for a shift


1,
0,
1,
1,
0,
0,
1,

1,
1,
1,
1,
1,
0,
1,

1,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1
0
1
1
1
1
1

},
},
},
},
},
},
} };

// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. This is no longer a pure assignment model, so we must
// use binary variables.
x = new GRBVar*[nWorkers];
int s, w;
for (w = 0; w < nWorkers; ++w)
{
x[w] = model.addVars(nShifts);
xCt++;
model.update();
for (s = 0; s < nShifts; ++s)
{
ostringstream vname;
vname << Workers[w] << "." << Shifts[s];
x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]);
x[w][s].set(GRB_CharAttr_VType, GRB_BINARY);
x[w][s].set(GRB_StringAttr_VarName, vname.str());
}
}
// Slack variables for each shift constraint so that the shifts can
// be satisfied
slacks = model.addVars(nShifts);
model.update();
for (s = 0; s < nShifts; ++s)
{
ostringstream vname;

200

vname << Shifts[s] << "Slack";


slacks[s].set(GRB_StringAttr_VarName, vname.str());
}
// Variable to represent the total slack
GRBVar totSlack = model.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS,
"totSlack");
// Variables to count the total shifts worked by each worker
totShifts = model.addVars(nWorkers);
model.update();
for (w = 0; w < nWorkers; ++w)
{
ostringstream vname;
vname << Workers[w] << "TotShifts";
totShifts[w].set(GRB_StringAttr_VarName, vname.str());
}
// Update model to integrate new variables
model.update();
GRBLinExpr lhs;
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (s = 0; s < nShifts; ++s)
{
lhs = 0;
lhs += slacks[s];
for (w = 0; w < nWorkers; ++w)
{
lhs += x[w][s];
}
model.addConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Constraint: set totSlack equal to the total slack
lhs = 0;
for (s = 0; s < nShifts; ++s)
{
lhs += slacks[s];
}
model.addConstr(lhs == totSlack, "totSlack");
// Constraint: compute the total number of shifts for each worker

201

for (w = 0; w < nWorkers; ++w) {


lhs = 0;
for (s = 0; s < nShifts; ++s) {
lhs += x[w][s];
}
ostringstream vname;
vname << "totShifts" << Workers[w];
model.addConstr(lhs == totShifts[w], vname.str());
}
// Objective: minimize the total slack
GRBLinExpr obj = 0;
obj += totSlack;
model.setObjective(obj);
// Optimize
int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB_OPTIMAL)
{
return 1;
}
// Constrain the slack by setting its upper and lower bounds
totSlack.set(GRB_DoubleAttr_UB, totSlack.get(GRB_DoubleAttr_X));
totSlack.set(GRB_DoubleAttr_LB, totSlack.get(GRB_DoubleAttr_X));
// Variable to count the average number of shifts worked
GRBVar avgShifts =
model.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS, "avgShifts");
// Variables to count the difference from average for each worker;
// note that these variables can take negative values.
diffShifts = model.addVars(nWorkers);
model.update();
for (w = 0; w < nWorkers; ++w) {
ostringstream vname;
vname << Workers[w] << "Diff";
diffShifts[w].set(GRB_StringAttr_VarName, vname.str());
diffShifts[w].set(GRB_DoubleAttr_LB, -GRB_INFINITY);
}
// Update model to integrate new variables
model.update();
// Constraint: compute the average number of shifts worked

202

lhs = 0;
for (w = 0; w < nWorkers; ++w) {
lhs += totShifts[w];
}
model.addConstr(lhs == nWorkers * avgShifts, "avgShifts");
// Constraint: compute the difference from the average number of shifts
for (w = 0; w < nWorkers; ++w) {
lhs = 0;
lhs += totShifts[w];
lhs -= avgShifts;
ostringstream vname;
vname << Workers[w] << "Diff";
model.addConstr(lhs == diffShifts[w], vname.str());
}
// Objective: minimize the sum of the square of the difference from the
// average number of shifts worked
GRBQuadExpr qobj;
for (w = 0; w < nWorkers; ++w) {
qobj += diffShifts[w] * diffShifts[w];
}
model.setObjective(qobj);
// Optimize
status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB_OPTIMAL)
{
return 1;
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] c;
delete[] v;
for (int i = 0; i < xCt; ++i) {

203

delete[] x[i];
}
delete[] x;
delete[] slacks;
delete[] totShifts;
delete[] diffShifts;
delete env;
return 0;
}
int solveAndPrint(GRBModel& model, GRBVar& totSlack,
int nWorkers, string* Workers,
GRBVar* totShifts) throw(GRBException)
{
model.optimize();
int status = model.get(GRB_IntAttr_Status);
if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) ||
(status == GRB_UNBOUNDED))
{
cout << "The model cannot be solved " <<
"because it is infeasible or unbounded" << endl;
return status;
}
if (status != GRB_OPTIMAL)
{
cout << "Optimization was stopped with status " << status << endl;
return status;
}
// Print total slack and the number of shifts worked for each worker
cout << endl << "Total slack required: " <<
totSlack.get(GRB_DoubleAttr_X) << endl;
for (int w = 0; w < nWorkers; ++w) {
cout << Workers[w] << " worked " <<
totShifts[w].get(GRB_DoubleAttr_X) << " shifts" << endl;
}
cout << endl;
return status;
}

204

3.3

Java Examples

This section includes source code for all of the Gurobi Java examples. The same source code can
be found in the examples/java directory of the Gurobi distribution.

Callback.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP or a MIP from a file, sets a callback
to monitor the optimization progress and to output some progress
information to the screen and to a log file. If it is a MIP and 10%
gap is reached, then it aborts */
import gurobi.*;
public class Callback extends GRBCallback {
private GRBVar[] vars;
private double
lastnode;
private double
lastiter;
public Callback(GRBVar[] xvars) {
vars = xvars;
lastnode = lastiter = -1;
}
protected void callback() {
try {
if (where == GRB.CB_MESSAGE) {
// Message callback
String st = getStringInfo(GRB.CB_MSG_STRING);
if (st != null) System.out.print(st);
} else if (where == GRB.CB_PRESOLVE) {
// Presolve callback
int cdels = getIntInfo(GRB.CB_PRE_COLDEL);
int rdels = getIntInfo(GRB.CB_PRE_ROWDEL);
System.out.println(cdels+" columns and "+rdels+" rows are removed");
} else if (where == GRB.CB_SIMPLEX) {
// Simplex callback
double itcnt = getDoubleInfo(GRB.CB_SPX_ITRCNT);
if (itcnt - lastiter >= 100) {
lastiter = itcnt;
double obj = getDoubleInfo(GRB.CB_SPX_OBJVAL);
double pinf = getDoubleInfo(GRB.CB_SPX_PRIMINF);
double dinf = getDoubleInfo(GRB.CB_SPX_DUALINF);
int ispert = getIntInfo(GRB.CB_SPX_ISPERT);
205

char ch;
if (ispert == 0)
ch = ;
else if (ispert == 1) ch = S;
else
ch = P;
System.out.println(itcnt+" "+ obj + ch + "

"+pinf + " " + dinf);


}
} else if (where == GRB.CB_MIP) {
// General MIP callback
double nodecnt = getDoubleInfo(GRB.CB_MIP_NODCNT);
if (nodecnt - lastnode >= 100) {
lastnode = nodecnt;
double objbst = getDoubleInfo(GRB.CB_MIP_OBJBST);
double objbnd = getDoubleInfo(GRB.CB_MIP_OBJBND);
if (Math.abs(objbst - objbnd) < 0.1 * (1.0 + Math.abs(objbst)))
abort();
int actnodes = (int) getDoubleInfo(GRB.CB_MIP_NODLFT);
int itcnt
= (int) getDoubleInfo(GRB.CB_MIP_ITRCNT);
int solcnt
= getIntInfo(GRB.CB_MIP_SOLCNT);
int cutcnt
= getIntInfo(GRB.CB_MIP_CUTCNT);
System.out.println(nodecnt + " " + actnodes + " " + itcnt + " "
+ objbst + " " + objbnd + " " + solcnt + " " + cutcnt);
}
} else if (where == GRB.CB_MIPSOL) {
// MIP solution callback
double obj
= getDoubleInfo(GRB.CB_MIPSOL_OBJ);
int
nodecnt = (int) getDoubleInfo(GRB.CB_MIPSOL_NODCNT);
double[] x = getSolution(vars);
System.out.println("**** New solution at node " + nodecnt + ", obj "
+ obj + ", x[0] = " + x[0] + "****");
}
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Callback filename");
System.exit(1);
}
try {

206

GRBEnv
GRBModel

env
= new GRBEnv();
model = new GRBModel(env, args[0]);

model.getEnv().set(GRB.IntParam.OutputFlag, 0);
GRBVar[] vars

= model.getVars();

// Create a callback object and associate it with the model


model.setCallback(new Callback(vars));
model.optimize();
double[] x
= model.get(GRB.DoubleAttr.X, vars);
String[] vnames = model.get(GRB.StringAttr.VarName, vars);
for (int j = 0; j < vars.length; j++) {
if (x[j] != 0.0) System.out.println(vnames[j] + " " + x[j]);
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
}
}

207

Dense.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.
*/
import gurobi.*;
public class Dense {
protected static boolean
dense_optimize(GRBEnv
int
int
double[]
double[][]
double[][]
char[]
double[]
double[]
double[]
char[]
double[]

env,
rows,
cols,
c,
// linear portion of objective function
Q,
// quadratic portion of objective function
A,
// constraint matrix
sense, // constraint senses
rhs,
// RHS vector
lb,
// variable lower bounds
ub,
// variable upper bounds
vtype, // variable types (continuous, binary, etc.)
solution) {

boolean success = false;


try {
GRBModel model = new GRBModel(env);
// Add variables to the model
GRBVar[] vars = model.addVars(lb, ub, null, vtype, null);
model.update();
// Populate A matrix

208

for (int i = 0; i < rows; i++) {


GRBLinExpr expr = new GRBLinExpr();
for (int j = 0; j < cols; j++)
if (A[i][j] != 0)
expr.addTerm(A[i][j], vars[j]);
model.addConstr(expr, sense[i], rhs[i], "");
}
// Populate objective
GRBQuadExpr obj = new GRBQuadExpr();
if (Q != null) {
for (int i = 0; i < cols; i++)
for (int j = 0; j < cols; j++)
if (Q[i][j] != 0)
obj.addTerm(Q[i][j], vars[i], vars[j]);
for (int j = 0; j < cols; j++)
if (c[j] != 0)
obj.addTerm(c[j], vars[j]);
model.setObjective(obj);
}
// Solve model
model.optimize();
// Extract solution
if (model.get(GRB.IntAttr.Status) == GRB.OPTIMAL) {
success = true;
for (int j = 0; j < cols; j++)
solution[j] = vars[j].get(GRB.DoubleAttr.X);
}
model.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
return success;
}

209

public static void main(String[] args) {


try {
GRBEnv env = new GRBEnv();
double c[] = new double[] {1, 1, 0};
double Q[][] = new double[][] {{1, 1, 0}, {0, 1, 1}, {0, 0, 1}};
double A[][] = new double[][] {{1, 2, 3}, {1, 1, 0}};
char sense[] = new char[] {>, >};
double rhs[] = new double[] {4, 1};
double lb[] = new double[] {0, 0, 0};
boolean success;
double sol[] = new double[3];

success = dense_optimize(env, 2, 3, c, Q, A, sense, rhs,


lb, null, null, sol);
if (success) {
System.out.println("x: " + sol[0] + ", y: " + sol[1] + ", z: " + sol[2]);
}
// Dispose of environment
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
}
}

210

Diet.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve the classic diet model, showing how to add constraints
to an existing model. */
import gurobi.*;
public class Diet {
public static void main(String[] args) {
try {
// Nutrition guidelines, based on
// USDA Dietary Guidelines for Americans, 2005
// http://www.health.gov/DietaryGuidelines/dga2005/
String Categories[] =
new String[] { "calories", "protein", "fat", "sodium" };
int nCategories = Categories.length;
double minNutrition[] = new double[] { 1800, 91, 0, 0 };
double maxNutrition[] = new double[] { 2200, GRB.INFINITY, 65, 1779 };
// Set of foods
String Foods[] =
new String[] { "hamburger", "chicken", "hot dog", "fries",
"macaroni", "pizza", "salad", "milk", "ice cream" };
int nFoods = Foods.length;
double cost[] =
new double[] { 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89,
1.59 };
// Nutrition values for the foods
double nutritionValues[][] = new double[][] {
{ 410, 24, 26, 730 },
// hamburger
{ 420, 32, 10, 1190 }, // chicken
{ 560, 20, 32, 1800 }, // hot dog
{ 380, 4, 19, 270 },
// fries
{ 320, 12, 10, 930 },
// macaroni
{ 320, 15, 12, 820 },
// pizza
{ 320, 31, 12, 1230 }, // salad
{ 100, 8, 2.5, 125 },
// milk
{ 330, 8, 10, 180 }
// ice cream
};
// Model
211

GRBEnv env = new GRBEnv();


GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "diet");
// Create decision variables for the nutrition information,
// which we limit via bounds
GRBVar[] nutrition = new GRBVar[nCategories];
for (int i = 0; i < nCategories; ++i) {
nutrition[i] =
model.addVar(minNutrition[i], maxNutrition[i], 0, GRB.CONTINUOUS,
Categories[i]);
}
// Create decision variables for the foods to buy
GRBVar[] buy = new GRBVar[nFoods];
for (int j = 0; j < nFoods; ++j) {
buy[j] =
model.addVar(0, GRB.INFINITY, cost[j], GRB.CONTINUOUS, Foods[j]);
}
// The objective is to minimize the costs
model.set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.update();
// Nutrition constraints
for (int i = 0; i < nCategories; ++i) {
GRBLinExpr ntot = new GRBLinExpr();
for (int j = 0; j < nFoods; ++j) {
ntot.addTerm(nutritionValues[j][i], buy[j]);
}
model.addConstr(ntot, GRB.EQUAL, nutrition[i], Categories[i]);
}
// Solve
model.optimize();
printSolution(model, buy, nutrition);
System.out.println("\nAdding constraint: at most 6 servings of dairy");
GRBLinExpr lhs = new GRBLinExpr();
lhs.addTerm(1.0, buy[7]);
lhs.addTerm(1.0, buy[8]);
model.addConstr(lhs, GRB.LESS_EQUAL, 6.0, "limit_dairy");

212

// Solve
model.optimize();
printSolution(model, buy, nutrition);
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
private static void printSolution(GRBModel model, GRBVar[] buy,
GRBVar[] nutrition) throws GRBException {
if (model.get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
System.out.println("\nCost: " + model.get(GRB.DoubleAttr.ObjVal));
System.out.println("\nBuy:");
for (int j = 0; j < buy.length; ++j) {
if (buy[j].get(GRB.DoubleAttr.X) > 0.0001) {
System.out.println(buy[j].get(GRB.StringAttr.VarName) + " " +
buy[j].get(GRB.DoubleAttr.X));
}
}
System.out.println("\nNutrition:");
for (int i = 0; i < nutrition.length; ++i) {
System.out.println(nutrition[i].get(GRB.StringAttr.VarName) + " " +
nutrition[i].get(GRB.DoubleAttr.X));
}
} else {
System.out.println("No solution");
}
}
}

213

Facility.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Facility location: a company currently ships its product from 5 plants
to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.
*/
import gurobi.*;
public class Facility {
public static void main(String[] args) {
try {
// Warehouse demand in thousands of units
double Demand[] = new double[] { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double Capacity[] = new double[] { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double FixedCosts[] =
new double[] { 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double TransCosts[][] =
new double[][] { { 4000, 2000, 3000, 2500, 4500 },
{ 2500, 2600, 3400, 3000, 4000 },
{ 1200, 1800, 2600, 4100, 3000 },
{ 2200, 2600, 3100, 3700, 3200 } };
// Number of plants and warehouses
int nPlants = Capacity.length;
int nWarehouses = Demand.length;
// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "facility");
214

// Plant open decision variables: open[p] == 1 if plant p is open.


GRBVar[] open = new GRBVar[nPlants];
for (int p = 0; p < nPlants; ++p) {
open[p] = model.addVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
GRBVar[][] transport = new GRBVar[nWarehouses][nPlants];
for (int w = 0; w < nWarehouses; ++w) {
for (int p = 0; p < nPlants; ++p) {
transport[w][p] =
model.addVar(0, GRB.INFINITY, TransCosts[w][p], GRB.CONTINUOUS,
"Trans" + p + "." + w);
}
}
// The objective is to minimize the total fixed and variable costs
model.set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.update();
// Production constraints
// Note that the right-hand limit sets the production to zero if
// the plant is closed
for (int p = 0; p < nPlants; ++p) {
GRBLinExpr ptot = new GRBLinExpr();
for (int w = 0; w < nWarehouses; ++w) {
ptot.addTerm(1.0, transport[w][p]);
}
GRBLinExpr limit = new GRBLinExpr();
limit.addTerm(Capacity[p], open[p]);
model.addConstr(ptot, GRB.LESS_EQUAL, limit, "Capacity" + p);
}
// Demand constraints
for (int w = 0; w < nWarehouses; ++w) {
GRBLinExpr dtot = new GRBLinExpr();
for (int p = 0; p < nPlants; ++p) {
dtot.addTerm(1.0, transport[w][p]);
}
model.addConstr(dtot, GRB.EQUAL, Demand[w], "Demand" + w);
}

215

// Guess at the starting point: close the plant with the highest
// fixed costs; open all others
// First, open all plants
for (int p = 0; p < nPlants; ++p) {
open[p].set(GRB.DoubleAttr.Start, 1.0);
}
// Now close the plant with the highest fixed cost
System.out.println("Initial guess:");
double maxFixed = -GRB.INFINITY;
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] > maxFixed) {
maxFixed = FixedCosts[p];
}
}
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] == maxFixed) {
open[p].set(GRB.DoubleAttr.Start, 0.0);
System.out.println("Closing plant " + p + "\n");
break;
}
}
// Use barrier to solve root relaxation
model.getEnv().set(GRB.IntParam.Method, GRB.METHOD_BARRIER);
// Solve
model.optimize();
// Print solution
System.out.println("\nTOTAL COSTS: " + model.get(GRB.DoubleAttr.ObjVal));
System.out.println("SOLUTION:");
for (int p = 0; p < nPlants; ++p) {
if (open[p].get(GRB.DoubleAttr.X) == 1.0) {
System.out.println("Plant " + p + " open:");
for (int w = 0; w < nWarehouses; ++w) {
if (transport[w][p].get(GRB.DoubleAttr.X) > 0.0001) {
System.out.println(" Transport " +
transport[w][p].get(GRB.DoubleAttr.X) +
" units to warehouse " + w);
}
}
} else {

216

System.out.println("Plant " + p + " closed!");


}
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

217

Feasopt.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, adds artificial
variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables. */
import gurobi.*;
public class Feasopt {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Feasopt filename");
System.exit(1);
}
try {
GRBEnv env = new GRBEnv();
GRBModel feasmodel = new GRBModel(env, args[0]);
// Create a copy to use FeasRelax feature later */
GRBModel feasmodel1 = new GRBModel(feasmodel);
// Clear objective
feasmodel.setObjective(new GRBLinExpr());
// Add slack variables
GRBConstr[] c = feasmodel.getConstrs();
for (int i = 0; i < c.length; ++i) {
char sense = c[i].get(GRB.CharAttr.Sense);
if (sense != >) {
GRBConstr[] constrs = new GRBConstr[] { c[i] };
double[] coeffs = new double[] { -1 };
feasmodel.addVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, constrs,
coeffs, "ArtN_" +
c[i].get(GRB.StringAttr.ConstrName));
}
if (sense != <) {
GRBConstr[] constrs = new GRBConstr[] { c[i] };
218

double[] coeffs = new double[] { 1 };


feasmodel.addVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, constrs,
coeffs, "ArtP_" +
c[i].get(GRB.StringAttr.ConstrName));
}
}
feasmodel.update();
// Optimize modified model
feasmodel.write("feasopt.lp");
feasmodel.optimize();
// use FeasRelax feature */
feasmodel1.feasRelax(GRB.FEASRELAX_LINEAR, true, false, true);
feasmodel1.write("feasopt1.lp");
feasmodel1.optimize();
// Dispose of model and environment
feasmodel1.dispose();
feasmodel.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

219

Fixanddive.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Implement a simple MIP heuristic. Relax the model,
sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible. */
import gurobi.*;
import java.util.*;
public class Fixanddive {
public static void main(String[] args) {
// Comparison class used to sort variable list based on relaxation
// fractionality
class FractionalCompare implements Comparator<GRBVar> {
public int compare(GRBVar v1, GRBVar v2) {
try {
double sol1 = Math.abs(v1.get(GRB.DoubleAttr.X));
double sol2 = Math.abs(v2.get(GRB.DoubleAttr.X));
double frac1 = Math.abs(sol1 - Math.floor(sol1 + 0.5));
double frac2 = Math.abs(sol2 - Math.floor(sol2 + 0.5));
if (frac1 < frac2) {
return -1;
} else if (frac1 == frac2) {
return 0;
} else {
return 1;
}
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
return 0;
}
}
if (args.length < 1) {
System.out.println("Usage: java Fixanddive filename");
System.exit(1);
}

220

try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
// Collect integer variables and relax them
ArrayList<GRBVar> intvars = new ArrayList<GRBVar>();
for (GRBVar v : model.getVars()) {
if (v.get(GRB.CharAttr.VType) != GRB.CONTINUOUS) {
intvars.add(v);
v.set(GRB.CharAttr.VType, GRB.CONTINUOUS);
}
}
model.getEnv().set(GRB.IntParam.OutputFlag, 0);
model.optimize();
// Perform multiple iterations. In each iteration, identify the first
// quartile of integer variables that are closest to an integer value
// in the relaxation, fix them to the nearest integer, and repeat.
for (int iter = 0; iter < 1000; ++iter) {
// create a list of fractional variables, sorted in order of
// increasing distance from the relaxation solution to the nearest
// integer value
ArrayList<GRBVar> fractional = new ArrayList<GRBVar>();
for (GRBVar v : intvars) {
double sol = Math.abs(v.get(GRB.DoubleAttr.X));
if (Math.abs(sol - Math.floor(sol + 0.5)) > 1e-5) {
fractional.add(v);
}
}
System.out.println("Iteration " + iter + ", obj " +
model.get(GRB.DoubleAttr.ObjVal) + ", fractional " +
fractional.size());
if (fractional.size() == 0) {
System.out.println("Found feasible solution - objective " +
model.get(GRB.DoubleAttr.ObjVal));
break;
}

221

// Fix the first quartile to the nearest integer value


Collections.sort(fractional, new FractionalCompare());
int nfix = Math.max(fractional.size() / 4, 1);
for (int i = 0; i < nfix; ++i) {
GRBVar v = fractional.get(i);
double fixval = Math.floor(v.get(GRB.DoubleAttr.X) + 0.5);
v.set(GRB.DoubleAttr.LB, fixval);
v.set(GRB.DoubleAttr.UB, fixval);
System.out.println(" Fix " + v.get(GRB.StringAttr.VarName) +
" to " + fixval + " ( rel " + v.get(GRB.DoubleAttr.X) + " )");
}
model.optimize();
// Check optimization result
if (model.get(GRB.IntAttr.Status) != GRB.Status.OPTIMAL) {
System.out.println("Relaxation is infeasible");
break;
}
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

222

Lp.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file */
import gurobi.*;
public class Lp {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Lp filename");
System.exit(1);
}
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
model.optimize();
int optimstatus = model.get(GRB.IntAttr.Status);
if (optimstatus == GRB.Status.INF_OR_UNBD) {
model.getEnv().set(GRB.IntParam.Presolve, 0);
model.optimize();
optimstatus = model.get(GRB.IntAttr.Status);
}
if (optimstatus == GRB.Status.OPTIMAL) {
double objval = model.get(GRB.DoubleAttr.ObjVal);
System.out.println("Optimal objective: " + objval);
} else if (optimstatus == GRB.Status.INFEASIBLE) {
System.out.println("Model is infeasible");
// Compute and write out IIS
model.computeIIS();
model.write("model.ilp");
} else if (optimstatus == GRB.Status.UNBOUNDED) {
System.out.println("Model is unbounded");
} else {
223

System.out.println("Optimization was stopped with status = "


+ optimstatus);
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

224

Lpmethod.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve a model with different values of the Method parameter;
show which value gives the shortest solve time. */
import gurobi.*;
public class Lpmethod {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Lpmethod filename");
System.exit(1);
}
try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
GRBEnv menv = model.getEnv();
// Solve the model with different values of Method
int bestMethod = -1;
double bestTime = menv.get(GRB.DoubleParam.TimeLimit);
for (int i = 0; i <= 2; ++i) {
model.reset();
menv.set(GRB.IntParam.Method, i);
model.optimize();
if (model.get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
bestTime = model.get(GRB.DoubleAttr.Runtime);
bestMethod = i;
// Reduce the TimeLimit parameter to save time
// with other methods
menv.set(GRB.DoubleParam.TimeLimit, bestTime);
}
}
// Report which method was fastest
if (bestMethod == -1) {
System.out.println("Unable to solve this model");
} else {
System.out.println("Solved in " + bestTime
+ " seconds with Method: " + bestMethod);
225

}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". "
+ e.getMessage());
}
}
}

226

Lpmod.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch). */
import gurobi.*;
public class Lpmod {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Lpmod filename");
System.exit(1);
}
try {
// Read model and determine whether it is an LP
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
if (model.get(GRB.IntAttr.IsMIP) != 0) {
System.out.println("The model is not a linear program");
System.exit(1);
}
model.optimize();
int status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.INF_OR_UNBD ||
status == GRB.Status.INFEASIBLE ||
status == GRB.Status.UNBOUNDED
) {
System.out.println("The model cannot be solved because it is "
+ "infeasible or unbounded");
System.exit(1);
}
if (status != GRB.Status.OPTIMAL) {
System.out.println("Optimization was stopped with status " + status);
System.exit(0);
}

227

// Find the smallest variable value


double minVal = GRB.INFINITY;
GRBVar minVar = null;
for (GRBVar v : model.getVars()) {
double sol = v.get(GRB.DoubleAttr.X);
if ((sol > 0.0001) && (sol < minVal) &&
(v.get(GRB.DoubleAttr.LB) == 0.0)) {
minVal = sol;
minVar = v;
}
}
System.out.println("\n*** Setting " +
minVar.get(GRB.StringAttr.VarName) + " from " + minVal +
" to zero ***\n");
minVar.set(GRB.DoubleAttr.UB, 0.0);
// Solve from this starting point
model.optimize();
// Save iteration & time info
double warmCount = model.get(GRB.DoubleAttr.IterCount);
double warmTime = model.get(GRB.DoubleAttr.Runtime);
// Reset the model and resolve
System.out.println("\n*** Resetting and solving "
+ "without an advanced start ***\n");
model.reset();
model.optimize();
double coldCount = model.get(GRB.DoubleAttr.IterCount);
double coldTime = model.get(GRB.DoubleAttr.Runtime);
System.out.println("\n*** Warm start: " + warmCount + " iterations, " +
warmTime + " seconds");
System.out.println("*** Cold start: " + coldCount + " iterations, " +
coldTime + " seconds");
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());

228

}
}
}

229

Mip1.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple MIP model:
maximize
subject to

x +
y + 2 z
x + 2 y + 3 z <= 4
x +
y
>= 1
x, y, z binary

*/
import gurobi.*;
public class Mip1 {
public static void main(String[] args) {
try {
GRBEnv
env
= new GRBEnv("mip1.log");
GRBModel model = new GRBModel(env);
// 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");
// Integrate new variables
model.update();
// Set objective: maximize x + y + 2 z
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(1.0, y); expr.addTerm(2.0, z);
model.setObjective(expr, GRB.MAXIMIZE);
// Add constraint: x + 2 y + 3 z <= 4
expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(2.0, y); expr.addTerm(3.0, z);
model.addConstr(expr, GRB.LESS_EQUAL, 4.0, "c0");
// Add constraint: x + y >= 1
expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(1.0, y);
230

model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "c1");


// Optimize model
model.optimize();
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));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal));
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

231

Mip2.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, solves it and
prints the objective values from all feasible solutions
generated while solving the MIP. Then it creates the fixed
model and solves that model. */
import gurobi.*;
public class Mip2 {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Mip2 filename");
System.exit(1);
}
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
if (model.get(GRB.IntAttr.IsMIP) == 0) {
System.out.println("Model is not a MIP");
System.exit(1);
}
model.optimize();
int optimstatus = model.get(GRB.IntAttr.Status);
double objval = 0;
if (optimstatus == GRB.Status.OPTIMAL) {
objval = model.get(GRB.DoubleAttr.ObjVal);
System.out.println("Optimal objective: " + objval);
} else if (optimstatus == GRB.Status.INF_OR_UNBD) {
System.out.println("Model is infeasible or unbounded");
return;
} else if (optimstatus == GRB.Status.INFEASIBLE) {
System.out.println("Model is infeasible");
return;
} else if (optimstatus == GRB.Status.UNBOUNDED) {
System.out.println("Model is unbounded");
return;
} else {
System.out.println("Optimization was stopped with status = "
+ optimstatus);
232

return;
}
/* Iterate over the solutions and compute the objectives */
GRBVar[] vars = model.getVars();
model.getEnv().set(GRB.IntParam.OutputFlag, 0);
System.out.println();
for (int k = 0; k < model.get(GRB.IntAttr.SolCount); ++k) {
model.getEnv().set(GRB.IntParam.SolutionNumber, k);
double objn = 0.0;
for (int j = 0; j < vars.length; j++) {
objn += vars[j].get(GRB.DoubleAttr.Obj)
* vars[j].get(GRB.DoubleAttr.Xn);
}
System.out.println("Solution " + k + " has objective: " + objn);
}
System.out.println();
model.getEnv().set(GRB.IntParam.OutputFlag, 1);
/* Create a fixed model, turn off presolve and solve */
GRBModel fixed = model.fixedModel();
fixed.getEnv().set(GRB.IntParam.Presolve, 0);
fixed.optimize();
int foptimstatus = fixed.get(GRB.IntAttr.Status);
if (foptimstatus != GRB.Status.OPTIMAL) {
System.err.println("Error: fixed model isnt optimal");
return;
}
double fobjval = fixed.get(GRB.DoubleAttr.ObjVal);
if (Math.abs(fobjval - objval) > 1.0e-6 * (1.0 + Math.abs(objval))) {
System.err.println("Error: objective values are different");
return;
}
GRBVar[] fvars

= fixed.getVars();

233

double[] x
= fixed.get(GRB.DoubleAttr.X, fvars);
String[] vnames = fixed.get(GRB.StringAttr.VarName, fvars);
for (int j = 0; j < fvars.length; j++) {
if (x[j] != 0.0) {
System.out.println(vnames[j] + " " + x[j]);
}
}
// Dispose of models and environment
fixed.dispose();
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". "
+ e.getMessage());
}
}
}

234

Params.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Use parameters that are associated with a model.
A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.
*/
import gurobi.*;
public class Params {
// Simple function to determine the MIP gap
private static double gap(GRBModel model) throws GRBException {
if ((model.get(GRB.IntAttr.SolCount) == 0) ||
(Math.abs(model.get(GRB.DoubleAttr.ObjVal)) < 1e-6)) {
return GRB.INFINITY;
}
return Math.abs(model.get(GRB.DoubleAttr.ObjBound) model.get(GRB.DoubleAttr.ObjVal)) /
Math.abs(model.get(GRB.DoubleAttr.ObjVal));
}
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Params filename");
System.exit(1);
}
try {
// Read model and verify that it is a MIP
GRBEnv env = new GRBEnv();
GRBModel base = new GRBModel(env, args[0]);
if (base.get(GRB.IntAttr.IsMIP) == 0) {
System.out.println("The model is not an integer program");
System.exit(1);
}
// Set a 5 second time limit
base.getEnv().set(GRB.DoubleParam.TimeLimit, 5);
// Now solve the model with different values of MIPFocus
235

double bestGap = GRB.INFINITY;


GRBModel bestModel = null;
for (int i = 0; i <= 3; ++i) {
GRBModel m = new GRBModel(base);
m.getEnv().set(GRB.IntParam.MIPFocus, i);
m.optimize();
if (bestModel == null || bestGap > gap(m)) {
bestModel = m;
bestGap = gap(bestModel);
}
}
// Finally, reset the time limit and continue to solve the
// best model to optimality
bestModel.getEnv().set(GRB.DoubleParam.TimeLimit, GRB.INFINITY);
bestModel.optimize();
System.out.println("Solved with MIPFocus: " +
bestModel.getEnv().get(GRB.IntParam.MIPFocus));
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

236

Qcp.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QCP model:
maximize
subject to

x
x + y + z = 1
x^2 + y^2 <= z^2 (second-order cone)
x^2 <= yz
(rotated second-order cone)

*/
import gurobi.*;
public class Qcp {
public static void main(String[] args) {
try {
GRBEnv
env
= new GRBEnv("qcp.log");
GRBModel model = new GRBModel(env);
// Create variables
GRBVar x = model.addVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.addVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.addVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "z");
// Integrate new variables
model.update();
// Set objective
GRBLinExpr obj = new GRBLinExpr();
obj.addTerm(1.0, x);
model.setObjective(obj, GRB.MAXIMIZE);
// Add linear constraint: x + y + z = 1
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(1.0, y); expr.addTerm(1.0, z);
model.addConstr(expr, GRB.EQUAL, 1.0, "c0");
// Add second-order cone: x^2 + y^2 <= z^2
GRBQuadExpr qexpr = new GRBQuadExpr();
qexpr.addTerm(1.0, x, x);
237

qexpr.addTerm(1.0, y, y);
qexpr.addTerm(-1.0, z, z);
model.addQConstr(qexpr, GRB.LESS_EQUAL, 0.0, "qc0");
// Add rotated cone: x^2 <= yz
qexpr = new GRBQuadExpr();
qexpr.addTerm(1.0, x, x);
qexpr.addTerm(-1.0, y, z);
model.addQConstr(qexpr, GRB.LESS_EQUAL, 0.0, "qc1");
// Optimize model
model.optimize();
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));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal) + " " +
obj.getValue());
System.out.println();
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

238

Qp.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x^2 + x*y + y^2 + y*z + z^2 + 2 x


x + 2 y + 3 z >= 4
x +
y
>= 1

It solves it once as a continuous model, and once as an integer model.


*/
import gurobi.*;
public class Qp
public static
try {
GRBEnv
GRBModel

{
void main(String[] args) {
env
= new GRBEnv("qp.log");
model = new GRBModel(env);

// Create variables
GRBVar x = model.addVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.addVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.addVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "z");
// Integrate new variables
model.update();
// Set objective
GRBQuadExpr obj = new GRBQuadExpr();
obj.addTerm(1.0, x, x);
obj.addTerm(1.0, x, y);
obj.addTerm(1.0, y, y);
obj.addTerm(1.0, y, z);
obj.addTerm(1.0, z, z);
obj.addTerm(2.0, x);
model.setObjective(obj);
// Add constraint: x + 2 y + 3 z >= 4
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(2.0, y); expr.addTerm(3.0, z);
239

model.addConstr(expr, GRB.GREATER_EQUAL, 4.0, "c0");


// Add constraint: x + y >= 1
expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(1.0, y);
model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "c1");
// Optimize model
model.optimize();
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));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal) + " " +
obj.getValue());
System.out.println();

// Change variable types to integer


x.set(GRB.CharAttr.VType, GRB.INTEGER);
y.set(GRB.CharAttr.VType, GRB.INTEGER);
z.set(GRB.CharAttr.VType, GRB.INTEGER);
// Optimize again
model.optimize();
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));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal) + " " +
obj.getValue());
// Dispose of model and environment

240

model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

241

Sensitivity.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Simple MIP sensitivity analysis example.
For each integer variable, fix it to its lower and upper bound
and check the impact on the objective. */
import gurobi.*;
public class Sensitivity {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Sensitivity filename");
System.exit(1);
}
try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel a = new GRBModel(env, args[0]);
a.optimize();
a.getEnv().set(GRB.IntParam.OutputFlag, 0);
// Extract variables from model
GRBVar[] avars = a.getVars();
for (int i = 0; i < avars.length; ++i) {
GRBVar v = avars[i];
if (v.get(GRB.CharAttr.VType) == GRB.BINARY) {
// Create clone and fix variable
GRBModel b = new GRBModel(a);
GRBVar bv = b.getVars()[i];
if (v.get(GRB.DoubleAttr.X) - v.get(GRB.DoubleAttr.LB) < 0.5) {
bv.set(GRB.DoubleAttr.LB, bv.get(GRB.DoubleAttr.UB));
} else {
bv.set(GRB.DoubleAttr.UB, bv.get(GRB.DoubleAttr.LB));
}
b.optimize();
if (b.get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
double objchg =
242

b.get(GRB.DoubleAttr.ObjVal) - a.get(GRB.DoubleAttr.ObjVal);
if (objchg < 0) {
objchg = 0;
}
System.out.println("Objective sensitivity for variable " +
v.get(GRB.StringAttr.VarName) + " is " + objchg);
} else {
System.out.println("Objective sensitivity for variable " +
v.get(GRB.StringAttr.VarName) + " is infinite");
}
// Dispose of model
b.dispose();
}
}
// Dispose of model and environment
a.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

243

Sos.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example creates a very simple Special Ordered Set (SOS) model.
The model consists of 3 continuous variables, no linear constraints,
and a pair of SOS constraints of type 1. */
import gurobi.*;
public class Sos {
public static void main(String[] args) {
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
// Create variables
double ub[]
= {1, 1, 2};
double obj[]
= {-2, -1, -1};
String names[] = {"x0", "x1", "x2"};
GRBVar[] x = model.addVars(null, ub, obj, null, names);
// Integrate new variables
model.update();
// Add first SOS1: x0=0 or x1=0
GRBVar sosv1[] = {x[0], x[1]};
double soswt1[] = {1, 2};
model.addSOS(sosv1, soswt1, GRB.SOS_TYPE1);
// Add second SOS1: x0=0 or x2=0
GRBVar sosv2[] = {x[0], x[2]};
double soswt2[] = {1, 2};
model.addSOS(sosv2, soswt2, GRB.SOS_TYPE1);
// Optimize model
model.optimize();
244

for (int i = 0; i < 3; i++)


System.out.println(x[i].get(GRB.StringAttr.VarName) + " "
+ x[i].get(GRB.DoubleAttr.X));
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

245

Sudoku.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/*
Sudoku example.
The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.
In the MIP formulation, binary variables x[i,j,v] indicate whether
cell <i,j> takes value v. The constraints are as follows:
1. Each cell must take exactly one value (sum_v x[i,j,v] = 1)
2. Each value is used exactly once per row (sum_i x[i,j,v] = 1)
3. Each value is used exactly once per column (sum_j x[i,j,v] = 1)
4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1)
*/
import gurobi.*;
import java.io.*;
public class Sudoku {
public static void main(String[] args) {
int n = 9;
int s = 3;
if (args.length < 1) {
System.out.println("Usage: java Sudoku filename");
System.exit(1);
}
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
// Create 3-D array of model variables
GRBVar[][][] vars = new GRBVar[n][n][n];
for (int i =
for (int j
for (int
String

0; i < n; i++) {
= 0; j < n; j++) {
v = 0; v < n; v++) {
st = "G_" + String.valueOf(i) + "_" + String.valueOf(j)
+ "_" + String.valueOf(v);
vars[i][j][v] = model.addVar(0.0, 1.0, 0.0, GRB.BINARY, st);

246

}
}
}
// Integrate variables into model
model.update();
// Add constraints
GRBLinExpr expr;
// Each cell must take one value
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
expr = new GRBLinExpr();
expr.addTerms(null, vars[i][j]);
String st = "V_" + String.valueOf(i) + "_" + String.valueOf(j);
model.addConstr(expr, GRB.EQUAL, 1.0, st);
}
}
// Each value appears once per row
for (int i = 0; i < n; i++) {
for (int v = 0; v < n; v++) {
expr = new GRBLinExpr();
for (int j = 0; j < n; j++)
expr.addTerm(1.0, vars[i][j][v]);
String st = "R_" + String.valueOf(i) + "_" + String.valueOf(v);
model.addConstr(expr, GRB.EQUAL, 1.0, st);
}
}
// Each value appears once per column
for (int j = 0; j < n; j++) {
for (int v = 0; v < n; v++) {
expr = new GRBLinExpr();
for (int i = 0; i < n; i++)
expr.addTerm(1.0, vars[i][j][v]);
String st = "C_" + String.valueOf(j) + "_" + String.valueOf(v);
model.addConstr(expr, GRB.EQUAL, 1.0, st);
}

247

}
// Each value appears once per sub-grid
for (int v = 0; v < n; v++) {
for (int i0 = 0; i0 < s; i0++) {
for (int j0 = 0; j0 < s; j0++) {
expr = new GRBLinExpr();
for (int i1 = 0; i1 < s; i1++) {
for (int j1 = 0; j1 < s; j1++) {
expr.addTerm(1.0, vars[i0*s+i1][j0*s+j1][v]);
}
}
String st = "Sub_" + String.valueOf(v) + "_" + String.valueOf(i0)
+ "_" + String.valueOf(j0);
model.addConstr(expr, GRB.EQUAL, 1.0, st);
}
}
}
// Update model
model.update();
// Fix variables associated with pre-specified cells
File file = new File(args[0]);
FileInputStream fis = new FileInputStream(file);
byte[] input = new byte[n];
for (int i = 0; i < n; i++) {
fis.read(input);
for (int j = 0; j < n; j++) {
int val = (int) input[j] - 48 - 1; // 0-based
if (val >= 0)
vars[i][j][val].set(GRB.DoubleAttr.LB, 1.0);
}
// read the endline byte
fis.read();
}
// Optimize model
model.optimize();

248

// Write model to file


model.write("sudoku.lp");
double[][][] x = model.get(GRB.DoubleAttr.X, vars);
System.out.println();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int v = 0; v < n; v++) {
if (x[i][j][v] > 0.5) {
System.out.print(v+1);
}
}
}
System.out.println();
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
} catch (IOException e) {
System.out.println("IO Error");
}
}
}

249

Tsp.java
/* Copyright 2013, Gurobi Optimization, Inc. */
//
//
//
//
//
//

Solve a traveling salesman problem on a randomly generated set of


points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every node. The lazy constraint callback
adds new constraints to cut them off.

import gurobi.*;
public class Tsp extends GRBCallback {
private GRBVar[][] vars;
public Tsp(GRBVar[][] xvars) {
vars = xvars;
}
// Subtour elimination callback. Whenever a feasible solution is found,
// find the subtour that contains node 0, and add a subtour elimination
// constraint if the tour doesnt visit every node.
protected void callback() {
try {
if (where == GRB.CB_MIPSOL) {
// Found an integer feasible solution - does it visit every node?
int n = vars.length;
int[] tour = findsubtour(getSolution(vars));
if (tour.length < n) {
// Add subtour elimination constraint
GRBLinExpr expr = new GRBLinExpr();
for (int i = 0; i < tour.length; i++)
for (int j = i+1; j < tour.length; j++)
expr.addTerm(1.0, vars[tour[i]][tour[j]]);
addLazy(expr, GRB.LESS_EQUAL, tour.length-1);
}
}
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
}
250

// Given an integer-feasible solution sol, return the smallest


// sub-tour (as a list of node indices).
protected static int[] findsubtour(double[][] sol)
{
int n = sol.length;
boolean[] seen = new boolean[n];
int[] tour = new int[n];
int bestind, bestlen;
int i, node, len, start;
for (i = 0; i < n; i++)
seen[i] = false;
start = 0;
bestlen = n+1;
bestind = -1;
node = 0;
while (start < n) {
for (node = 0; node < n; node++)
if (!seen[node])
break;
if (node == n)
break;
for (len = 0; len < n; len++) {
tour[start+len] = node;
seen[node] = true;
for (i = 0; i < n; i++) {
if (sol[node][i] > 0.5 && !seen[i]) {
node = i;
break;
}
}
if (i == n) {
len++;
if (len < bestlen) {
bestlen = len;
bestind = start;
}
start += len;
break;
}
}
}

251

int result[] = new int[bestlen];


for (i = 0; i < bestlen; i++)
result[i] = tour[bestind+i];
return result;
}
// Euclidean distance between points i and j
protected static double distance(double[]
double[]
int
int
double dx = x[i]-x[j];
double dy = y[i]-y[j];
return Math.sqrt(dx*dx+dy*dy);
}

x,
y,
i,
j) {

public static void main(String[] args) {


if (args.length < 1) {
System.out.println("Usage: java Tsp ncities");
System.exit(1);
}
int n = Integer.parseInt(args[0]);
try {
GRBEnv
env
= new GRBEnv();
GRBModel model = new GRBModel(env);
// Must set LazyConstraints parameter when using lazy constraints
model.getEnv().set(GRB.IntParam.LazyConstraints, 1);
double[] x = new double[n];
double[] y = new double[n];
for (int i = 0; i < n; i++) {
x[i] = Math.random();
y[i] = Math.random();
}
// Create variables

252

GRBVar[][] vars = new GRBVar[n][n];


for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
vars[i][j] = model.addVar(0.0, 1.0, distance(x, y, i, j),
GRB.BINARY,
"x"+String.valueOf(i)+"_"+String.valueOf(j));
// Integrate variables
model.update();
// Degree-2 constraints
for (int i = 0; i < n; i++) {
GRBLinExpr expr = new GRBLinExpr();
for (int j = 0; j < n; j++)
expr.addTerm(1.0, vars[i][j]);
model.addConstr(expr, GRB.EQUAL, 2.0, "deg2_"+String.valueOf(i));
}
// Forbid edge from node back to itself
for (int i = 0; i < n; i++)
vars[i][i].set(GRB.DoubleAttr.UB, 0.0);
// Symmetric TSP
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
model.addConstr(vars[i][j], GRB.EQUAL, vars[j][i], "");
model.setCallback(new Tsp(vars));
model.optimize();
if (model.get(GRB.IntAttr.SolCount) > 0) {
int[] tour = findsubtour(model.get(GRB.DoubleAttr.X, vars));
System.out.print("Tour: ");
for (int i = 0; i < tour.length; i++)
System.out.print(String.valueOf(tour[i]) + " ");
System.out.println();
}
// Dispose of model and environment

253

model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
e.printStackTrace();
}
}
}

254

Tune.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a model from a file and tunes it.
It then writes the best parameter settings to a file
and solves the model using these parameters. */
import gurobi.*;
public class Tune {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java Tune filename");
System.exit(1);
}
try {
GRBEnv env = new GRBEnv();
// Read model from file
GRBModel model = new GRBModel(env, args[0]);
// Set the TuneResults parameter to 1
model.getEnv().set(GRB.IntParam.TuneResults, 1);
// Tune the model
model.tune();
// Get the number of tuning results
int resultcount = model.get(GRB.IntAttr.TuneResultCount);
if (resultcount > 0) {
// Load the tuned parameters into the models environment
model.getTuneResult(0);
// Write the tuned parameters to a file
model.write("tune.prm");
// Solve the model using the tuned parameters
model.optimize();
}
// Dispose of model and environment
255

model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". "
+ e.getMessage());
}
}
}

256

Workforce1.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts
besides what is reported via IIS. */
import gurobi.*;
public class Workforce1 {
public static void main(String[] args) {
try {
// Sample data
// Sets of days and workers
String Shifts[] =
new String[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
String Workers[] =
new String[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.length;
int nWorkers = Workers.length;
// Number of workers required for each shift
double shiftRequirements[] =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][] =
new double[][] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
// Model
257

GRBEnv env = new GRBEnv();


GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[][] x = new GRBVar[nWorkers][nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w][s] =
model.addVar(0, availability[w][s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = new GRBLinExpr();
for (int w = 0; w < nWorkers; ++w) {
lhs.addTerm(1.0, x[w][s]);
}
model.addConstr(lhs, GRB.EQUAL, shiftRequirements[s], Shifts[s]);
}
// Optimize
model.optimize();
int status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
System.out.println("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
System.out.println("The optimal objective is " +
model.get(GRB.DoubleAttr.ObjVal));
return;
}

258

if (status != GRB.Status.INF_OR_UNBD &&


status != GRB.Status.INFEASIBLE
){
System.out.println("Optimization was stopped with status " + status);
return;
}
// Compute IIS
System.out.println("The model is infeasible; computing IIS");
model.computeIIS();
System.out.println("\nThe following constraint(s) "
+ "cannot be satisfied:");
for (GRBConstr c : model.getConstrs()) {
if (c.get(GRB.IntAttr.IISConstr) == 1) {
System.out.println(c.get(GRB.StringAttr.ConstrName));
}
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

259

Workforce2.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS iteratively to
find all conflicting constraints. */
import gurobi.*;
import java.util.*;
public class Workforce2 {
public static void main(String[] args) {
try {
// Sample data
// Sets of days and workers
String Shifts[] =
new String[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
String Workers[] =
new String[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.length;
int nWorkers = Workers.length;
// Number of workers required for each shift
double shiftRequirements[] =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][] =
new double[][] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
// Model
260

GRBEnv env = new GRBEnv();


GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[][] x = new GRBVar[nWorkers][nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w][s] =
model.addVar(0, availability[w][s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = new GRBLinExpr();
for (int w = 0; w < nWorkers; ++w) {
lhs.addTerm(1.0, x[w][s]);
}
model.addConstr(lhs, GRB.EQUAL, shiftRequirements[s], Shifts[s]);
}
// Optimize
model.optimize();
int status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
System.out.println("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
System.out.println("The optimal objective is " +
model.get(GRB.DoubleAttr.ObjVal));
return;
}

261

if (status != GRB.Status.INF_OR_UNBD &&


status != GRB.Status.INFEASIBLE
) {
System.out.println("Optimization was stopped with status " + status);
return;
}
// Do IIS
System.out.println("The model is infeasible; computing IIS");
LinkedList<String> removed = new LinkedList<String>();
// Loop until we reduce to a model that can be solved
while (true) {
model.computeIIS();
System.out.println("\nThe following constraint cannot be satisfied:");
for (GRBConstr c : model.getConstrs()) {
if (c.get(GRB.IntAttr.IISConstr) == 1) {
System.out.println(c.get(GRB.StringAttr.ConstrName));
// Remove a single constraint from the model
removed.add(c.get(GRB.StringAttr.ConstrName));
model.remove(c);
break;
}
}
System.out.println();
model.optimize();
status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
System.out.println("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
break;
}
if (status != GRB.Status.INF_OR_UNBD &&
status != GRB.Status.INFEASIBLE
) {
System.out.println("Optimization was stopped with status " +
status);
return;
}
}
System.out.println("\nThe following constraints were removed "

262

+ "to get a feasible LP:");


for (String s : removed) {
System.out.print(s + " ");
}
System.out.println();
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

263

Workforce3.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed. */
import gurobi.*;
import java.util.*;
public class Workforce3 {
public static void main(String[] args) {
try {
// Sample data
// Sets of days and workers
String Shifts[] =
new String[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
String Workers[] =
new String[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.length;
int nWorkers = Workers.length;
// Number of workers required for each shift
double shiftRequirements[] =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double pay[] = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][] =
new double[][] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };

264

// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[][] x = new GRBVar[nWorkers][nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w][s] =
model.addVar(0, availability[w][s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
LinkedList<GRBConstr> reqCts = new LinkedList<GRBConstr>();
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = new GRBLinExpr();
for (int w = 0; w < nWorkers; ++w) {
lhs.addTerm(1.0, x[w][s]);
}
GRBConstr newCt =
model.addConstr(lhs, GRB.EQUAL, shiftRequirements[s], Shifts[s]);
reqCts.add(newCt);
}
// Optimize
model.optimize();
int status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
System.out.println("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {

265

System.out.println("The optimal objective is " +


model.get(GRB.DoubleAttr.ObjVal));
return;
}
if (status != GRB.Status.INF_OR_UNBD &&
status != GRB.Status.INFEASIBLE
) {
System.out.println("Optimization was stopped with status " + status);
return;
}
// Add slack variables to make the model feasible
System.out.println("The model is infeasible; adding slack variables");
// Set original objective coefficients to zero
model.setObjective(new GRBLinExpr());
// Add a new slack variable to each shift constraint so that the shifts
// can be satisfied
LinkedList<GRBVar> slacks = new LinkedList<GRBVar>();
for (GRBConstr c : reqCts) {
GRBColumn col = new GRBColumn();
col.addTerm(1.0, c);
GRBVar newvar =
model.addVar(0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, col,
c.get(GRB.StringAttr.ConstrName) + "Slack");
slacks.add(newvar);
}
// Solve the model with slacks
model.optimize();
status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.INF_OR_UNBD ||
status == GRB.Status.INFEASIBLE ||
status == GRB.Status.UNBOUNDED
) {
System.out.println("The model with slacks cannot be solved "
+ "because it is infeasible or unbounded");
return;
}
if (status != GRB.Status.OPTIMAL) {
System.out.println("Optimization was stopped with status " + status);
return;
}
System.out.println("\nSlack values:");
for (GRBVar sv : slacks) {

266

if (sv.get(GRB.DoubleAttr.X) > 1e-6) {


System.out.println(sv.get(GRB.StringAttr.VarName) + " = " +
sv.get(GRB.DoubleAttr.X));
}
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}

267

Workforce4.java
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. We use Pareto optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers. */
import gurobi.*;
public class Workforce4 {
public static void main(String[] args) {
try {
// Sample data
// Sets of days and workers
String Shifts[] =
new String[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
String Workers[] =
new String[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.length;
int nWorkers = Workers.length;
// Number of workers required for each shift
double shiftRequirements[] =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Worker availability: 0 if the worker is unavailable for a shift
double availability[][] =
new double[][] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
268

model.set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. This is no longer a pure assignment model, so we must
// use binary variables.
GRBVar[][] x = new GRBVar[nWorkers][nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w][s] =
model.addVar(0, availability[w][s], 0, GRB.BINARY,
Workers[w] + "." + Shifts[s]);
}
}
// Slack variables for each shift constraint so that the shifts can
// be satisfied
GRBVar[] slacks = new GRBVar[nShifts];
for (int s = 0; s < nShifts; ++s) {
slacks[s] =
model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
Shifts[s] + "Slack");
}
// Variable to represent the total slack
GRBVar totSlack = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
"totSlack");
// Variables to count the total shifts worked by each worker
GRBVar[] totShifts = new GRBVar[nWorkers];
for (int w = 0; w < nWorkers; ++w) {
totShifts[w] = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
Workers[w] + "TotShifts");
}
// Update model to integrate new variables
model.update();
GRBLinExpr lhs;
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s, plus the slack
for (int s = 0; s < nShifts; ++s) {
lhs = new GRBLinExpr();
lhs.addTerm(1.0, slacks[s]);
for (int w = 0; w < nWorkers; ++w) {

269

lhs.addTerm(1.0, x[w][s]);
}
model.addConstr(lhs, GRB.EQUAL, shiftRequirements[s], Shifts[s]);
}
// Constraint: set totSlack equal to the total slack
lhs = new GRBLinExpr();
lhs.addTerm(-1.0, totSlack);
for (int s = 0; s < nShifts; ++s) {
lhs.addTerm(1.0, slacks[s]);
}
model.addConstr(lhs, GRB.EQUAL, 0, "totSlack");
// Constraint: compute the total number of shifts for each worker
for (int w = 0; w < nWorkers; ++w) {
lhs = new GRBLinExpr();
lhs.addTerm(-1.0, totShifts[w]);
for (int s = 0; s < nShifts; ++s) {
lhs.addTerm(1.0, x[w][s]);
}
model.addConstr(lhs, GRB.EQUAL, 0, "totShifts" + Workers[w]);
}
// Objective: minimize the total slack
GRBLinExpr obj = new GRBLinExpr();
obj.addTerm(1.0, totSlack);
model.setObjective(obj);
// Optimize
int status =
solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB.Status.OPTIMAL ) {
return;
}
// Constrain the slack by setting its upper and lower bounds
totSlack.set(GRB.DoubleAttr.UB, totSlack.get(GRB.DoubleAttr.X));
totSlack.set(GRB.DoubleAttr.LB, totSlack.get(GRB.DoubleAttr.X));
// Variable to count the average number of shifts worked
GRBVar avgShifts =
model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "avgShifts");
// Variables to count the difference from average for each worker;
// note that these variables can take negative values.

270

GRBVar[] diffShifts = new GRBVar[nWorkers];


for (int w = 0; w < nWorkers; ++w) {
diffShifts[w] = model.addVar(-GRB.INFINITY, GRB.INFINITY, 0,
GRB.CONTINUOUS, Workers[w] + "Diff");
}
// Update model to integrate new variables
model.update();
// Constraint: compute the average number of shifts worked
lhs = new GRBLinExpr();
lhs.addTerm(-nWorkers, avgShifts);
for (int w = 0; w < nWorkers; ++w) {
lhs.addTerm(1.0, totShifts[w]);
}
model.addConstr(lhs, GRB.EQUAL, 0, "avgShifts");
// Constraint: compute the difference from the average number of shifts
for (int w = 0; w < nWorkers; ++w) {
lhs = new GRBLinExpr();
lhs.addTerm(-1, diffShifts[w]);
lhs.addTerm(-1, avgShifts);
lhs.addTerm( 1, totShifts[w]);
model.addConstr(lhs, GRB.EQUAL, 0, Workers[w] + "Diff");
}
// Objective: minimize the sum of the square of the difference from the
// average number of shifts worked
GRBQuadExpr qobj = new GRBQuadExpr();
for (int w = 0; w < nWorkers; ++w) {
qobj.addTerm(1.0, diffShifts[w], diffShifts[w]);
}
model.setObjective(qobj);
// Optimize
status =
solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB.Status.OPTIMAL ) {
return;
}
// Dispose of model and environment
model.dispose();
env.dispose();

271

} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
private static int solveAndPrint(GRBModel model, GRBVar totSlack,
int nWorkers, String[] Workers,
GRBVar[] totShifts) throws GRBException {
model.optimize();
int status = model.get(GRB.IntAttr.Status);
if (status == GRB.Status.INF_OR_UNBD ||
status == GRB.Status.INFEASIBLE ||
status == GRB.Status.UNBOUNDED
) {
System.out.println("The model cannot be solved "
+ "because it is infeasible or unbounded");
return status;
}
if (status != GRB.Status.OPTIMAL ) {
System.out.println("Optimization was stopped with status " + status);
return status;
}
// Print total slack and the number of shifts worked for each worker
System.out.println("\nTotal slack required: " +
totSlack.get(GRB.DoubleAttr.X));
for (int w = 0; w < nWorkers; ++w) {
System.out.println(Workers[w] + " worked " +
totShifts[w].get(GRB.DoubleAttr.X) + " shifts");
}
System.out.println("\n");
return status;
}
}

272

3.4

C# Examples

This section includes source code for all of the Gurobi C# examples. The same source code can be
found in the examples/c# directory of the Gurobi distribution.

callback_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP or a MIP from a file, sets a callback
to monitor the optimization progress and to output some progress
information to the screen and to a log file. If it is a MIP and 10%
gap is reached, then it aborts. */
using System;
using Gurobi;
class callback_cs : GRBCallback
{
private GRBVar[] vars;
private double
lastnode;
private double
lastiter;
public callback_cs(GRBVar[] xvars)
{
vars = xvars;
lastnode = lastiter = -1;
}
protected override void Callback()
{
try {
if (where == GRB.Callback.MESSAGE) {
// Message callback
string st = GetStringInfo(GRB.Callback.MSG_STRING);
if (st != null) Console.Write(st);
} else if (where == GRB.Callback.PRESOLVE) {
// Presolve callback
int cdels = GetIntInfo(GRB.Callback.PRE_COLDEL);
int rdels = GetIntInfo(GRB.Callback.PRE_ROWDEL);
Console.WriteLine(cdels+" columns and "+rdels+" rows are removed");
} else if (where == GRB.Callback.SIMPLEX) {
// Simplex callback
double itcnt = GetDoubleInfo(GRB.Callback.SPX_ITRCNT);
if (itcnt - lastiter >= 100) {
lastiter = itcnt;
273

double obj = GetDoubleInfo(GRB.Callback.SPX_OBJVAL);


double pinf = GetDoubleInfo(GRB.Callback.SPX_PRIMINF);
double dinf = GetDoubleInfo(GRB.Callback.SPX_DUALINF);
int ispert = GetIntInfo(GRB.Callback.SPX_ISPERT);
char ch;
if (ispert == 0)
ch = ;
else if (ispert == 1) ch = S;
else
ch = P;
Console.WriteLine(itcnt+" "+ obj + ch + " "+pinf + "

" + dinf);

}
} else if (where == GRB.Callback.MIP) {
// General MIP callback
double nodecnt = GetDoubleInfo(GRB.Callback.MIP_NODCNT);
if (nodecnt - lastnode >= 100) {
lastnode = nodecnt;
double objbst = GetDoubleInfo(GRB.Callback.MIP_OBJBST);
double objbnd = GetDoubleInfo(GRB.Callback.MIP_OBJBND);
if (Math.Abs(objbst - objbnd) < 0.1 * (1.0 + Math.Abs(objbst)))
Abort();
int actnodes = (int) GetDoubleInfo(GRB.Callback.MIP_NODLFT);
int itcnt
= (int) GetDoubleInfo(GRB.Callback.MIP_ITRCNT);
int solcnt
= GetIntInfo(GRB.Callback.MIP_SOLCNT);
int cutcnt
= GetIntInfo(GRB.Callback.MIP_CUTCNT);
Console.WriteLine(nodecnt + " " + actnodes + " " + itcnt + " "
+ objbst + " " + objbnd + " " + solcnt + " " + cutcnt);
}
} else if (where == GRB.Callback.MIPSOL) {
// MIP solution callback
double obj
= GetDoubleInfo(GRB.Callback.MIPSOL_OBJ);
int
nodecnt = (int) GetDoubleInfo(GRB.Callback.MIPSOL_NODCNT);
double[] x = GetSolution(vars);
Console.WriteLine("**** New solution at node " + nodecnt + ", obj "
+ obj + ", x[0] = " + x[0] + "****");
}
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
Console.WriteLine(e.StackTrace);
}
}
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: callback_cs filename");
return;

274

}
try {
GRBEnv
GRBModel

env
= new GRBEnv();
model = new GRBModel(env, args[0]);

GRBVar[] vars

= model.GetVars();

// Create a callback object and associate it with the model


model.SetCallback(new callback_cs(vars));
model.Optimize();
double[] x
= model.Get(GRB.DoubleAttr.X, vars);
string[] vnames = model.Get(GRB.StringAttr.VarName, vars);
for (int j = 0; j < vars.Length; j++) {
if (x[j] != 0.0) Console.WriteLine(vnames[j] + " " + x[j]);
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
Console.WriteLine(e.StackTrace);
}
}
}

275

dense_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.
*/
using System;
using Gurobi;
class dense_cs {
protected static bool
dense_optimize(GRBEnv
int
int
double[]
double[,]
double[,]
char[]
double[]
double[]
double[]
char[]
double[]

env,
rows,
cols,
c,
// linear portion of objective function
Q,
// quadratic portion of objective function
A,
// constraint matrix
sense, // constraint senses
rhs,
// RHS vector
lb,
// variable lower bounds
ub,
// variable upper bounds
vtype, // variable types (continuous, binary, etc.)
solution) {

bool success = false;


try {
GRBModel model = new GRBModel(env);
// Add variables to the model
GRBVar[] vars = model.AddVars(lb, ub, null, vtype, null);
model.Update();
// Populate A matrix
276

for (int i = 0; i < rows; i++) {


GRBLinExpr expr = new GRBLinExpr();
for (int j = 0; j < cols; j++)
if (A[i,j] != 0)
expr.AddTerm(A[i,j], vars[j]); // Note: += would be much slower
model.AddConstr(expr, sense[i], rhs[i], "");
}
// Populate objective
GRBQuadExpr obj = new GRBQuadExpr();
if (Q != null) {
for (int i = 0; i < cols; i++)
for (int j = 0; j < cols; j++)
if (Q[i,j] != 0)
obj.AddTerm(Q[i,j], vars[i], vars[j]); // Note: += would be much slower
for (int j = 0; j < cols; j++)
if (c[j] != 0)
obj.AddTerm(c[j], vars[j]); // Note: += would be much slower
model.SetObjective(obj);
}
// Solve model
model.Optimize();
// Extract solution
if (model.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
success = true;
for (int j = 0; j < cols; j++)
solution[j] = vars[j].Get(GRB.DoubleAttr.X);
}
model.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
return success;
}

277

public static void Main(String[] args) {


try {
GRBEnv env = new GRBEnv();
double[] c = new double[] {1, 1, 0};
double[,] Q = new double[,] {{1, 1, 0}, {0, 1, 1}, {0, 0, 1}};
double[,] A = new double[,] {{1, 2, 3}, {1, 1, 0}};
char[] sense = new char[] {>, >};
double[] rhs = new double[] {4, 1};
double[] lb = new double[] {0, 0, 0};
bool success;
double[] sol = new double[3];
success = dense_optimize(env, 2, 3, c, Q, A, sense, rhs,
lb, null, null, sol);
if (success) {
Console.WriteLine("x: " + sol[0] + ", y: " + sol[1] + ", z: " + sol[2]);
}
// Dispose of environment
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

278

diet_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve the classic diet model, showing how to add constraints
to an existing model. */
using System;
using Gurobi;
class diet_cs
{
static void Main()
{
try {
// Nutrition guidelines, based on
// USDA Dietary Guidelines for Americans, 2005
// http://www.health.gov/DietaryGuidelines/dga2005/
string[] Categories =
new string[] { "calories", "protein", "fat", "sodium" };
int nCategories = Categories.Length;
double[] minNutrition = new double[] { 1800, 91, 0, 0 };
double[] maxNutrition = new double[] { 2200, GRB.INFINITY, 65, 1779 };
// Set of foods
string[] Foods =
new string[] { "hamburger", "chicken", "hot dog", "fries",
"macaroni", "pizza", "salad", "milk", "ice cream" };
int nFoods = Foods.Length;
double[] cost =
new double[] { 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89,
1.59 };
// Nutrition values for the
double[,] nutritionValues =
{ 410, 24, 26, 730 },
{ 420, 32, 10, 1190 },
{ 560, 20, 32, 1800 },
{ 380, 4, 19, 270 },
{ 320, 12, 10, 930 },
{ 320, 15, 12, 820 },
{ 320, 31, 12, 1230 },
{ 100, 8, 2.5, 125 },
{ 330, 8, 10, 180 }
};

foods
new double[,] {
// hamburger
// chicken
// hot dog
// fries
// macaroni
// pizza
// salad
// milk
// ice cream

279

// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.Set(GRB.StringAttr.ModelName, "diet");
// Create decision variables for the nutrition information,
// which we limit via bounds
GRBVar[] nutrition = new GRBVar[nCategories];
for (int i = 0; i < nCategories; ++i) {
nutrition[i] =
model.AddVar(minNutrition[i], maxNutrition[i], 0, GRB.CONTINUOUS,
Categories[i]);
}
// Create decision variables for the foods to buy
GRBVar[] buy = new GRBVar[nFoods];
for (int j = 0; j < nFoods; ++j) {
buy[j] =
model.AddVar(0, GRB.INFINITY, cost[j], GRB.CONTINUOUS, Foods[j]);
}
// The objective is to minimize the costs
model.Set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.Update();
// Nutrition constraints
for (int i = 0; i < nCategories; ++i) {
GRBLinExpr ntot = 0.0;
for (int j = 0; j < nFoods; ++j)
ntot += nutritionValues[j,i] * buy[j];
model.AddConstr(ntot == nutrition[i], Categories[i]);
}
// Solve
model.Optimize();
PrintSolution(model, buy, nutrition);
Console.WriteLine("\nAdding constraint: at most 6 servings of dairy");
model.AddConstr(buy[7] + buy[8] <= 6.0, "limit_dairy");
// Solve
model.Optimize();

280

PrintSolution(model, buy, nutrition);


// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
private static void PrintSolution(GRBModel model, GRBVar[] buy,
GRBVar[] nutrition) {
if (model.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
Console.WriteLine("\nCost: " + model.Get(GRB.DoubleAttr.ObjVal));
Console.WriteLine("\nBuy:");
for (int j = 0; j < buy.Length; ++j) {
if (buy[j].Get(GRB.DoubleAttr.X) > 0.0001) {
Console.WriteLine(buy[j].Get(GRB.StringAttr.VarName) + " " +
buy[j].Get(GRB.DoubleAttr.X));
}
}
Console.WriteLine("\nNutrition:");
for (int i = 0; i < nutrition.Length; ++i) {
Console.WriteLine(nutrition[i].Get(GRB.StringAttr.VarName) + " " +
nutrition[i].Get(GRB.DoubleAttr.X));
}
} else {
Console.WriteLine("No solution");
}
}
}

281

facility_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Facility location: a company currently ships its product from 5 plants
to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.
*/
using System;
using Gurobi;
class facility_cs
{
static void Main()
{
try {
// Warehouse demand in thousands of units
double[] Demand = new double[] { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double[] Capacity = new double[] { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double[] FixedCosts =
new double[] { 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per
double[,] TransCosts =
new double[,] { { 4000,
{ 2500, 2600, 3400,
{ 1200, 1800, 2600,
{ 2200, 2600, 3100,

thousand units
2000,
3000,
4100,
3700,

// Number of plants and warehouses


int nPlants = Capacity.Length;
int nWarehouses = Demand.Length;
// Model
GRBEnv env = new GRBEnv();
282

3000, 2500, 4500 },


4000 },
3000 },
3200 } };

GRBModel model = new GRBModel(env);


model.Set(GRB.StringAttr.ModelName, "facility");
// Plant open decision variables: open[p] == 1 if plant p is open.
GRBVar[] open = new GRBVar[nPlants];
for (int p = 0; p < nPlants; ++p) {
open[p] = model.AddVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
GRBVar[,] transport = new GRBVar[nWarehouses,nPlants];
for (int w = 0; w < nWarehouses; ++w) {
for (int p = 0; p < nPlants; ++p) {
transport[w,p] =
model.AddVar(0, GRB.INFINITY, TransCosts[w,p], GRB.CONTINUOUS,
"Trans" + p + "." + w);
}
}
// The objective is to minimize the total fixed and variable costs
model.Set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.Update();
// Production constraints
// Note that the right-hand limit sets the production to zero if
// the plant is closed
for (int p = 0; p < nPlants; ++p) {
GRBLinExpr ptot = 0.0;
for (int w = 0; w < nWarehouses; ++w)
ptot += transport[w,p];
model.AddConstr(ptot <= Capacity[p] * open[p], "Capacity" + p);
}
// Demand constraints
for (int w = 0; w < nWarehouses; ++w) {
GRBLinExpr dtot = 0.0;
for (int p = 0; p < nPlants; ++p)
dtot += transport[w,p];
model.AddConstr(dtot == Demand[w], "Demand" + w);
}
// Guess at the starting point: close the plant with the highest

283

// fixed costs; open all others


// First, open all plants
for (int p = 0; p < nPlants; ++p) {
open[p].Set(GRB.DoubleAttr.Start, 1.0);
}
// Now close the plant with the highest fixed cost
Console.WriteLine("Initial guess:");
double maxFixed = -GRB.INFINITY;
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] > maxFixed) {
maxFixed = FixedCosts[p];
}
}
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] == maxFixed) {
open[p].Set(GRB.DoubleAttr.Start, 0.0);
Console.WriteLine("Closing plant " + p + "\n");
break;
}
}
// Use barrier to solve root relaxation
model.GetEnv().Set(GRB.IntParam.Method, GRB.METHOD_BARRIER);
// Solve
model.Optimize();
// Print solution
Console.WriteLine("\nTOTAL COSTS: " + model.Get(GRB.DoubleAttr.ObjVal));
Console.WriteLine("SOLUTION:");
for (int p = 0; p < nPlants; ++p) {
if (open[p].Get(GRB.DoubleAttr.X) == 1.0) {
Console.WriteLine("Plant " + p + " open:");
for (int w = 0; w < nWarehouses; ++w) {
if (transport[w,p].Get(GRB.DoubleAttr.X) > 0.0001) {
Console.WriteLine(" Transport " +
transport[w,p].Get(GRB.DoubleAttr.X) +
" units to warehouse " + w);
}
}
} else {
Console.WriteLine("Plant " + p + " closed!");
}

284

}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

285

feasopt_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, adds artificial
variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables. */
using Gurobi;
using System;
class feasopt_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: feasopt_cs filename");
return;
}
try {
GRBEnv env = new GRBEnv();
GRBModel feasmodel = new GRBModel(env, args[0]);
// Create a copy to use FeasRelax feature later */
GRBModel feasmodel1 = new GRBModel(feasmodel);
// Clear objective
feasmodel.SetObjective(new GRBLinExpr());
// Add slack variables
GRBConstr[] c = feasmodel.GetConstrs();
for (int i = 0; i < c.Length; ++i) {
char sense = c[i].Get(GRB.CharAttr.Sense);
if (sense != >) {
GRBConstr[] constrs = new GRBConstr[] { c[i] };
double[] coeffs = new double[] { -1 };
feasmodel.AddVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, constrs,
coeffs, "ArtN_" + c[i].Get(GRB.StringAttr.ConstrName));
}
if (sense != <) {
286

GRBConstr[] constrs = new GRBConstr[] { c[i] };


double[] coeffs = new double[] { 1 };
feasmodel.AddVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, constrs,
coeffs, "ArtP_" +
c[i].Get(GRB.StringAttr.ConstrName));
}
}
feasmodel.Update();
// Optimize modified model
feasmodel.Write("feasopt.lp");
feasmodel.Optimize();
// Use FeasRelax feature */
feasmodel1.FeasRelax(GRB.FEASRELAX_LINEAR, true, false, true);
feasmodel1.Write("feasopt1.lp");
feasmodel1.Optimize();
// Dispose of model and env
feasmodel1.Dispose();
feasmodel.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

287

fixanddive_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Implement a simple MIP heuristic. Relax the model,
sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible. */
using System;
using System.Collections.Generic;
using Gurobi;
class fixanddive_cs
{
// Comparison class used to sort variable list based on relaxation
// fractionality
class FractionalCompare : IComparer<GRBVar>
{
public int Compare(GRBVar v1, GRBVar v2)
{
try {
double sol1 = Math.Abs(v1.Get(GRB.DoubleAttr.X));
double sol2 = Math.Abs(v2.Get(GRB.DoubleAttr.X));
double frac1 = Math.Abs(sol1 - Math.Floor(sol1 + 0.5));
double frac2 = Math.Abs(sol2 - Math.Floor(sol2 + 0.5));
if (frac1 < frac2) {
return -1;
} else if (frac1 > frac2) {
return 1;
} else {
return 0;
}
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
return 0;
}
}
static void Main(string[] args)
{
if (args.Length < 1) {
288

Console.Out.WriteLine("Usage: fixanddive_cs filename");


return;
}
try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
// Collect integer variables and relax them
List<GRBVar> intvars = new List<GRBVar>();
foreach (GRBVar v in model.GetVars()) {
if (v.Get(GRB.CharAttr.VType) != GRB.CONTINUOUS) {
intvars.Add(v);
v.Set(GRB.CharAttr.VType, GRB.CONTINUOUS);
}
}
model.GetEnv().Set(GRB.IntParam.OutputFlag, 0);
model.Optimize();
// Perform multiple iterations. In each iteration, identify the first
// quartile of integer variables that are closest to an integer value
// in the relaxation, fix them to the nearest integer, and repeat.
for (int iter = 0; iter < 1000; ++iter) {
// create a list of fractional variables, sorted in order of
// increasing distance from the relaxation solution to the nearest
// integer value
List<GRBVar> fractional = new List<GRBVar>();
foreach (GRBVar v in intvars) {
double sol = Math.Abs(v.Get(GRB.DoubleAttr.X));
if (Math.Abs(sol - Math.Floor(sol + 0.5)) > 1e-5) {
fractional.Add(v);
}
}
Console.WriteLine("Iteration " + iter + ", obj " +
model.Get(GRB.DoubleAttr.ObjVal) + ", fractional " +
fractional.Count);
if (fractional.Count == 0) {
Console.WriteLine("Found feasible solution - objective " +

289

model.Get(GRB.DoubleAttr.ObjVal));
break;
}
// Fix the first quartile to the nearest integer value
fractional.Sort(new FractionalCompare());
int nfix = Math.Max(fractional.Count / 4, 1);
for (int i = 0; i < nfix; ++i) {
GRBVar v = fractional[i];
double fixval = Math.Floor(v.Get(GRB.DoubleAttr.X) + 0.5);
v.Set(GRB.DoubleAttr.LB, fixval);
v.Set(GRB.DoubleAttr.UB, fixval);
Console.WriteLine(" Fix " + v.Get(GRB.StringAttr.VarName) +
" to " + fixval + " ( rel " + v.Get(GRB.DoubleAttr.X) + " )");
}
model.Optimize();
// Check optimization result
if (model.Get(GRB.IntAttr.Status) != GRB.Status.OPTIMAL) {
Console.WriteLine("Relaxation is infeasible");
break;
}
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

290

lp_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file. */
using System;
using Gurobi;
class lp_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: lp_cs filename");
return;
}
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
model.Optimize();
int optimstatus = model.Get(GRB.IntAttr.Status);
if (optimstatus == GRB.Status.INF_OR_UNBD) {
model.GetEnv().Set(GRB.IntParam.Presolve, 0);
model.Optimize();
optimstatus = model.Get(GRB.IntAttr.Status);
}
if (optimstatus == GRB.Status.OPTIMAL) {
double objval = model.Get(GRB.DoubleAttr.ObjVal);
Console.WriteLine("Optimal objective: " + objval);
} else if (optimstatus == GRB.Status.INFEASIBLE) {
Console.WriteLine("Model is infeasible");
// compute and write out IIS
model.ComputeIIS();
model.Write("model.ilp");
291

} else if (optimstatus == GRB.Status.UNBOUNDED) {


Console.WriteLine("Model is unbounded");
} else {
Console.WriteLine("Optimization was stopped with status = "
+ optimstatus);
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

292

lpmethod_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Solve a model with different values of the Method parameter;
show which value gives the shortest solve time. */
using System;
using Gurobi;
class lpmethod_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: lpmethod_cs filename");
return;
}
try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
GRBEnv menv = model.GetEnv();
// Solve the model with different values of Method
int bestMethod = -1;
double bestTime = menv.Get(GRB.DoubleParam.TimeLimit);
for (int i = 0; i <= 2; ++i)
{
model.Reset();
menv.Set(GRB.IntParam.Method, i);
model.Optimize();
if (model.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL)
{
bestTime = model.Get(GRB.DoubleAttr.Runtime);
bestMethod = i;
// Reduce the TimeLimit parameter to save time
// with other methods
menv.Set(GRB.DoubleParam.TimeLimit, bestTime);
}
}
// Report which method was fastest
if (bestMethod == -1) {
Console.WriteLine("Unable to solve this model");
293

} else {
Console.WriteLine("Solved in " + bestTime
+ " seconds with Method: " + bestMethod);
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

294

lpmod_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads an LP model from a file and solves it.
If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch). */
using System;
using Gurobi;
class lpmod_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: lpmod_cs filename");
return;
}
try {
// Read model and determine whether it is an LP
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
if (model.Get(GRB.IntAttr.IsMIP) != 0) {
Console.WriteLine("The model is not a linear program");
Environment.Exit(1);
}
model.Optimize();
int status = model.Get(GRB.IntAttr.Status);
if ((status == GRB.Status.INF_OR_UNBD) ||
(status == GRB.Status.INFEASIBLE) ||
(status == GRB.Status.UNBOUNDED)) {
Console.WriteLine("The model cannot be solved because it is "
+ "infeasible or unbounded");
Environment.Exit(1);
}
if (status != GRB.Status.OPTIMAL) {
Console.WriteLine("Optimization was stopped with status " + status);
Environment.Exit(0);
295

}
// Find the smallest variable value
double minVal = GRB.INFINITY;
GRBVar minVar = null;
foreach (GRBVar v in model.GetVars()) {
double sol = v.Get(GRB.DoubleAttr.X);
if ((sol > 0.0001) && (sol < minVal) &&
(v.Get(GRB.DoubleAttr.LB) == 0.0)) {
minVal = sol;
minVar = v;
}
}
Console.WriteLine("\n*** Setting " +
minVar.Get(GRB.StringAttr.VarName) + " from " + minVal +
" to zero ***\n");
minVar.Set(GRB.DoubleAttr.UB, 0.0);
// Solve from this starting point
model.Optimize();
// Save iteration & time info
double warmCount = model.Get(GRB.DoubleAttr.IterCount);
double warmTime = model.Get(GRB.DoubleAttr.Runtime);
// Reset the model and resolve
Console.WriteLine("\n*** Resetting and solving "
+ "without an advanced start ***\n");
model.Reset();
model.Optimize();
double coldCount = model.Get(GRB.DoubleAttr.IterCount);
double coldTime = model.Get(GRB.DoubleAttr.Runtime);
Console.WriteLine("\n*** Warm start: " + warmCount + " iterations, " +
warmTime + " seconds");
Console.WriteLine("*** Cold start: " + coldCount + " iterations, " +
coldTime + " seconds");
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {

296

Console.WriteLine("Error code: " + e.ErrorCode + ". " +


e.Message);
}
}
}

297

mip1_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple MIP model:
maximize
subject to

x +
y + 2 z
x + 2 y + 3 z <= 4
x +
y
>= 1
x, y, z binary

*/
using System;
using Gurobi;
class mip1_cs
{
static void Main()
{
try {
GRBEnv
env
= new GRBEnv("mip1.log");
GRBModel model = new GRBModel(env);
// 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");
// Integrate new variables
model.Update();
// Set objective: maximize x + y + 2 z
model.SetObjective(x + y + 2 * z, GRB.MAXIMIZE);
// Add constraint: x + 2 y + 3 z <= 4
model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c0");
// Add constraint: x + y >= 1
model.AddConstr(x + y >= 1.0, "c1");
// Optimize model
298

model.Optimize();
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));
Console.WriteLine("Obj: " + model.Get(GRB.DoubleAttr.ObjVal));
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

299

mip2_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a MIP model from a file, solves it and
prints the objective values from all feasible solutions
generated while solving the MIP. Then it creates the fixed
model and solves that model. */
using System;
using Gurobi;
class mip2_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: mip2_cs filename");
return;
}
try {
GRBEnv
env
= new GRBEnv();
GRBModel model = new GRBModel(env, args[0]);
if (model.Get(GRB.IntAttr.IsMIP) == 0) {
Console.WriteLine("Model is not a MIP");
return;
}
model.Optimize();
int optimstatus = model.Get(GRB.IntAttr.Status);
double objval = 0;
if (optimstatus == GRB.Status.OPTIMAL) {
objval = model.Get(GRB.DoubleAttr.ObjVal);
Console.WriteLine("Optimal objective: " + objval);
} else if (optimstatus == GRB.Status.INF_OR_UNBD) {
Console.WriteLine("Model is infeasible or unbounded");
return;
} else if (optimstatus == GRB.Status.INFEASIBLE) {
Console.WriteLine("Model is infeasible");
return;
} else if (optimstatus == GRB.Status.UNBOUNDED) {
Console.WriteLine("Model is unbounded");
return;
} else {
300

Console.WriteLine("Optimization was stopped with status = "


+ optimstatus);
return;
}
/* Iterate over the solutions and compute the objectives */
GRBVar[] vars = model.GetVars();
model.GetEnv().Set(GRB.IntParam.OutputFlag, 0);
Console.WriteLine();
for (int k = 0; k < model.Get(GRB.IntAttr.SolCount); ++k) {
model.GetEnv().Set(GRB.IntParam.SolutionNumber, k);
double objn = 0.0;
for (int j = 0; j < vars.Length; j++) {
objn += vars[j].Get(GRB.DoubleAttr.Obj)
* vars[j].Get(GRB.DoubleAttr.Xn);
}
Console.WriteLine("Solution " + k + " has objective: " + objn);
}
Console.WriteLine();
model.GetEnv().Set(GRB.IntParam.OutputFlag, 1);
/* Create a fixed model, turn off presolve and solve */
GRBModel fixedmodel = model.FixedModel();
fixedmodel.GetEnv().Set(GRB.IntParam.Presolve, 0);
fixedmodel.Optimize();
int foptimstatus = fixedmodel.Get(GRB.IntAttr.Status);
if (foptimstatus != GRB.Status.OPTIMAL) {
Console.WriteLine("Error: fixed model isnt optimal");
return;
}
double fobjval = fixedmodel.Get(GRB.DoubleAttr.ObjVal);
if (Math.Abs(fobjval - objval) > 1.0e-6 * (1.0 + Math.Abs(objval))) {
Console.WriteLine("Error: objective values are different");
return;

301

}
GRBVar[] fvars = fixedmodel.GetVars();
double[] x
= fixedmodel.Get(GRB.DoubleAttr.X, fvars);
string[] vnames = fixedmodel.Get(GRB.StringAttr.VarName, fvars);
for (int j = 0; j < fvars.Length; j++) {
if (x[j] != 0.0) Console.WriteLine(vnames[j] + " " + x[j]);
}
// Dispose of models and env
fixedmodel.Dispose();
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

302

params_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Use parameters that are associated with a model.
A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.
*/
using System;
using Gurobi;
class params_cs
{
// Simple function to determine the MIP gap
private static double Gap(GRBModel model) {
if ((model.Get(GRB.IntAttr.SolCount) == 0) ||
(Math.Abs(model.Get(GRB.DoubleAttr.ObjVal)) < 1e-6)) {
return GRB.INFINITY;
}
return Math.Abs(model.Get(GRB.DoubleAttr.ObjBound) model.Get(GRB.DoubleAttr.ObjVal)) /
Math.Abs(model.Get(GRB.DoubleAttr.ObjVal));
}
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: params_cs filename");
return;
}
try {
// Read model and verify that it is a MIP
GRBEnv env = new GRBEnv();
GRBModel basemodel = new GRBModel(env, args[0]);
if (basemodel.Get(GRB.IntAttr.IsMIP) == 0) {
Console.WriteLine("The model is not an integer program");
Environment.Exit(1);
}
// Set a 5 second time limit
basemodel.GetEnv().Set(GRB.DoubleParam.TimeLimit, 5);

303

// Now solve the model with different values of MIPFocus


double bestGap = GRB.INFINITY;
GRBModel bestModel = null;
for (int i = 0; i <= 3; ++i) {
GRBModel m = new GRBModel(basemodel);
m.GetEnv().Set(GRB.IntParam.MIPFocus, i);
m.Optimize();
if (bestModel == null || bestGap > Gap(m)) {
bestModel = m;
bestGap = Gap(bestModel);
}
}
// Finally, reset the time limit and continue to solve the
// best model to optimality
bestModel.GetEnv().Set(GRB.DoubleParam.TimeLimit, GRB.INFINITY);
bestModel.Optimize();
Console.WriteLine("Solved with MIPFocus: " +
bestModel.GetEnv().Get(GRB.IntParam.MIPFocus));
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

304

qcp_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QCP model:
maximize
subject to

x
x + y + z = 1
x^2 + y^2 <= z^2 (second-order cone)
x^2 <= yz
(rotated second-order cone)

*/
using System;
using Gurobi;
class qcp_cs
{
static void Main()
{
try {
GRBEnv
env
= new GRBEnv("qcp.log");
GRBModel model = new GRBModel(env);
// Create variables
GRBVar x = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "z");
// Integrate new variables
model.Update();
// Set objective
GRBLinExpr obj = x;
model.SetObjective(obj, GRB.MAXIMIZE);
// Add linear constraint: x + y + z = 1
model.AddConstr(x + y + z == 1.0, "c0");
// Add second-order cone: x^2 + y^2 <= z^2
model.AddQConstr(x*x + y*y <= z*z, "qc0");

305

// Add rotated cone: x^2 <= yz


model.AddQConstr(x*x <= y*z, "qc1");
// Optimize model
model.Optimize();
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));
Console.WriteLine("Obj: " + model.Get(GRB.DoubleAttr.ObjVal) + " " +
obj.Value);
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

306

qp_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example formulates and solves the following simple QP model:
minimize
subject to

x^2 + x*y + y^2 + y*z + z^2 + 2 x


x + 2 y + 3 z >= 4
x +
y
>= 1

It solves it once as a continuous model, and once as an integer model.


*/
using System;
using Gurobi;
class qp_cs
{
static void Main()
{
try {
GRBEnv
env
= new GRBEnv("qp.log");
GRBModel model = new GRBModel(env);
// Create variables
GRBVar x = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "z");
// Integrate new variables
model.Update();
// Set objective
GRBQuadExpr obj = x*x + x*y + y*y + y*z + z*z + 2*x;
model.SetObjective(obj);
// Add constraint: x + 2 y + 3 z >= 4
model.AddConstr(x + 2 * y + 3 * z >= 4.0, "c0");
// Add constraint: x + y >= 1
model.AddConstr(x + y >= 1.0, "c1");
307

// Optimize model
model.Optimize();
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));
Console.WriteLine("Obj: " + model.Get(GRB.DoubleAttr.ObjVal) + " " +
obj.Value);

// Change variable types to integer


x.Set(GRB.CharAttr.VType, GRB.INTEGER);
y.Set(GRB.CharAttr.VType, GRB.INTEGER);
z.Set(GRB.CharAttr.VType, GRB.INTEGER);
// Optimize model
model.Optimize();
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));
Console.WriteLine("Obj: " + model.Get(GRB.DoubleAttr.ObjVal) + " " +
obj.Value);
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}

308

}
}

309

sensitivity_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Simple MIP sensitivity analysis example.
For each integer variable, fix it to its lower and upper bound
and check the impact on the objective. */
using System;
using Gurobi;
class sensitivity_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: sensitivity_cs filename");
return;
}
try {
// Read model
GRBEnv env = new GRBEnv();
GRBModel a = new GRBModel(env, args[0]);
a.Optimize();
a.GetEnv().Set(GRB.IntParam.OutputFlag, 0);
// Extract variables from model
GRBVar[] avars = a.GetVars();
for (int i = 0; i < avars.Length; ++i) {
GRBVar v = avars[i];
if (v.Get(GRB.CharAttr.VType) == GRB.BINARY) {
// Create clone and fix variable
GRBModel b = new GRBModel(a);
GRBVar bv = b.GetVars()[i];
if (v.Get(GRB.DoubleAttr.X) - v.Get(GRB.DoubleAttr.LB) < 0.5) {
bv.Set(GRB.DoubleAttr.LB, bv.Get(GRB.DoubleAttr.UB));
} else {
bv.Set(GRB.DoubleAttr.UB, bv.Get(GRB.DoubleAttr.LB));
}
b.Optimize();
if (b.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) {
310

double objchg =
b.Get(GRB.DoubleAttr.ObjVal) - a.Get(GRB.DoubleAttr.ObjVal);
if (objchg < 0) {
objchg = 0;
}
Console.WriteLine("Objective sensitivity for variable " +
v.Get(GRB.StringAttr.VarName) + " is " + objchg);
} else {
Console.WriteLine("Objective sensitivity for variable " +
v.Get(GRB.StringAttr.VarName) + " is infinite");
}
// Dispose of model
b.Dispose();
}
}
// Dispose of model and env
a.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

311

sos_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example creates a very simple Special Ordered Set (SOS) model.
The model consists of 3 continuous variables, no linear constraints,
and a pair of SOS constraints of type 1. */
using System;
using Gurobi;
class sos_cs
{
static void Main()
{
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
// Create variables
double[] ub
= {1, 1, 2};
double[] obj
= {-2, -1, -1};
string[] names = {"x0", "x1", "x2"};
GRBVar[] x = model.AddVars(null, ub, obj, null, names);
// Integrate new variables
model.Update();
// Add first SOS1: x0=0 or x1=0
GRBVar[] sosv1 = {x[0], x[1]};
double[] soswt1 = {1, 2};
model.AddSOS(sosv1, soswt1, GRB.SOS_TYPE1);
// Add second SOS1: x0=0 or x2=0
GRBVar[] sosv2 = {x[0], x[2]};
double[] soswt2 = {1, 2};
model.AddSOS(sosv2, soswt2, GRB.SOS_TYPE1);

312

// Optimize model
model.Optimize();
for (int i = 0; i < 3; i++)
Console.WriteLine(x[i].Get(GRB.StringAttr.VarName) + " "
+ x[i].Get(GRB.DoubleAttr.X));
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

313

sudoku_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/*
Sudoku example.
The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.
In the MIP formulation, binary variables x[i,j,v] indicate whether
cell <i,j> takes value v. The constraints are as follows:
1. Each cell must take exactly one value (sum_v x[i,j,v] = 1)
2. Each value is used exactly once per row (sum_i x[i,j,v] = 1)
3. Each value is used exactly once per column (sum_j x[i,j,v] = 1)
4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1)
*/
using System;
using System.IO;
using Gurobi;
class sudoku_cs
{
static void Main(string[] args)
{
int n = 9;
int s = 3;
if (args.Length < 1) {
Console.Out.WriteLine("Usage: sudoku_cs filename");
return;
}
try {
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
// Create 3-D array of model variables
GRBVar[,,] vars = new GRBVar[n,n,n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
314

for (int v = 0; v < n; v++) {


string st = "G_" + i.ToString() + "_" + j.ToString()
+ "_" + v.ToString();
vars[i,j,v] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, st);
}
}
}
// Integrate variables into model
model.Update();
// Add constraints
GRBLinExpr expr;
// Each cell must take one value
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
expr = 0.0;
for (int v = 0; v < n; v++)
expr += vars[i,j,v];
string st = "V_" + i.ToString() + "_" + j.ToString();
model.AddConstr(expr == 1.0, st);
}
}
// Each value appears once per row
for (int i = 0; i < n; i++) {
for (int v = 0; v < n; v++) {
expr = 0.0;
for (int j = 0; j < n; j++)
expr += vars[i,j,v];
string st = "R_" + i.ToString() + "_" + v.ToString();
model.AddConstr(expr == 1.0, st);
}
}
// Each value appears once per column
for (int j = 0; j < n; j++) {
for (int v = 0; v < n; v++) {
expr = 0.0;

315

for (int i = 0; i < n; i++)


expr += vars[i,j,v];
string st = "C_" + j.ToString() + "_" + v.ToString();
model.AddConstr(expr == 1.0, st);
}
}
// Each value appears once per sub-grid
for (int v = 0; v < n; v++) {
for (int i0 = 0; i0 < s; i0++) {
for (int j0 = 0; j0 < s; j0++) {
expr = 0.0;
for (int i1 = 0; i1 < s; i1++) {
for (int j1 = 0; j1 < s; j1++) {
expr += vars[i0*s+i1,j0*s+j1,v];
}
}
string st = "Sub_" + v.ToString() + "_" + i0.ToString()
+ "_" + j0.ToString();
model.AddConstr(expr == 1.0, st);
}
}
}
// Update model
model.Update();
// Fix variables associated with pre-specified cells
StreamReader sr = File.OpenText(args[0]);
for (int i = 0; i < n; i++) {
string input = sr.ReadLine();
for (int j = 0; j < n; j++) {
int val = (int) input[j] - 48 - 1; // 0-based
if (val >= 0)
vars[i,j,val].Set(GRB.DoubleAttr.LB, 1.0);
}
}
// Optimize model

316

model.Optimize();
// Write model to file
model.Write("sudoku.lp");
double[,,] x = model.Get(GRB.DoubleAttr.X, vars);
Console.WriteLine();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int v = 0; v < n; v++) {
if (x[i,j,v] > 0.5) {
Console.Write(v+1);
}
}
}
Console.WriteLine();
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

317

tsp_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
//
//
//
//
//
//

Solve a traveling salesman problem on a randomly generated set of


points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every node. The lazy constraint callback
adds new constraints to cut them off.

using System;
using Gurobi;
class tsp_cs : GRBCallback {
private GRBVar[,] vars;
public tsp_cs(GRBVar[,] xvars) {
vars = xvars;
}
// Subtour elimination callback. Whenever a feasible solution is found,
// find the smallest subtour, and add a subtour elimination
// constraint if the tour doesnt visit every node.
protected override void Callback() {
try {
if (where == GRB.Callback.MIPSOL) {
// Found an integer feasible solution - does it visit every node?
int n = vars.GetLength(0);
int[] tour = findsubtour(GetSolution(vars));
if (tour.Length < n) {
// Add subtour elimination constraint
GRBLinExpr expr = 0;
for (int i = 0; i < tour.Length; i++)
for (int j = i+1; j < tour.Length; j++)
expr += vars[tour[i], tour[j]];
AddLazy(expr <= tour.Length-1);
}
}
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
Console.WriteLine(e.StackTrace);
}
318

}
// Given an integer-feasible solution sol, return the smallest
// sub-tour (as a list of node indices).
protected static int[] findsubtour(double[,] sol)
{
int n = sol.GetLength(0);
bool[] seen = new bool[n];
int[] tour = new int[n];
int bestind, bestlen;
int i, node, len, start;
for (i = 0; i < n; i++)
seen[i] = false;
start = 0;
bestlen = n+1;
bestind = -1;
node = 0;
while (start < n) {
for (node = 0; node < n; node++)
if (!seen[node])
break;
if (node == n)
break;
for (len = 0; len < n; len++) {
tour[start+len] = node;
seen[node] = true;
for (i = 0; i < n; i++) {
if (sol[node, i] > 0.5 && !seen[i]) {
node = i;
break;
}
}
if (i == n) {
len++;
if (len < bestlen) {
bestlen = len;
bestind = start;
}
start += len;
break;
}
}

319

}
for (i = 0; i < bestlen; i++)
tour[i] = tour[bestind+i];
System.Array.Resize(ref tour, bestlen);
return tour;
}
// Euclidean distance between points i and j
protected static double distance(double[]
double[]
int
int
double dx = x[i]-x[j];
double dy = y[i]-y[j];
return Math.Sqrt(dx*dx+dy*dy);
}

x,
y,
i,
j) {

public static void Main(String[] args) {


if (args.Length < 1) {
Console.WriteLine("Usage: tsp_cs nnodes");
return;
}
int n = Convert.ToInt32(args[0]);
try {
GRBEnv
env
= new GRBEnv();
GRBModel model = new GRBModel(env);
// Must set LazyConstraints parameter when using lazy constraints
model.GetEnv().Set(GRB.IntParam.LazyConstraints, 1);
double[] x = new double[n];
double[] y = new double[n];
Random r
for (int
x[i] =
y[i] =
}

320

= new Random();
i = 0; i < n; i++) {
r.NextDouble();
r.NextDouble();

// Create variables
GRBVar[,] vars = new GRBVar[n, n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
vars[i, j] = model.AddVar(0.0, 1.0, distance(x, y, i, j),
GRB.BINARY, "x"+i+"_"+j);
// Integrate variables
model.Update();
// Degree-2 constraints
for (int i = 0; i < n; i++) {
GRBLinExpr expr = 0;
for (int j = 0; j < n; j++)
expr += vars[i, j];
model.AddConstr(expr == 2.0, "deg2_"+i);
}
// Forbid edge from node back to itself
for (int i = 0; i < n; i++)
vars[i, i].Set(GRB.DoubleAttr.UB, 0.0);
// Symmetric TSP
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
model.AddConstr(vars[i, j]== vars[j, i], "");
model.SetCallback(new tsp_cs(vars));
model.Optimize();
if (model.Get(GRB.IntAttr.SolCount) > 0) {
int[] tour = findsubtour(model.Get(GRB.DoubleAttr.X, vars));
Console.Write("Tour: ");
for (int i = 0; i < tour.Length; i++)
Console.Write(tour[i] + " ");
Console.WriteLine();
}

321

// Dispose of model and environment


model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
Console.WriteLine(e.StackTrace);
}
}
}

322

tune_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* This example reads a model from a file and tunes it.
It then writes the best parameter settings to a file
and solves the model using these parameters. */
using System;
using Gurobi;
class tune_cs
{
static void Main(string[] args)
{
if (args.Length < 1) {
Console.Out.WriteLine("Usage: tune_cs filename");
return;
}
try {
GRBEnv env = new GRBEnv();
// Read model from file
GRBModel model = new GRBModel(env, args[0]);
// Set the TuneResults parameter to 1
model.GetEnv().Set(GRB.IntParam.TuneResults, 1);
// Tune the model
model.Tune();
// Get the number of tuning results
int resultcount = model.Get(GRB.IntAttr.TuneResultCount);
if (resultcount > 0) {
// Load the tuned parameters into the models environment
model.GetTuneResult(0);
// Write the tuned parameters to a file
model.Write("tune.prm");
// Solve the model using the tuned parameters
model.Optimize();
}
323

// Dispose of model and environment


model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}

324

workforce1_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts
besides what is reported via IIS. */
using System;
using Gurobi;
class workforce1_cs
{
static void Main()
{
try {
// Sample data
// Sets of days and workers
string[] Shifts =
new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string[] Workers =
new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.Length;
int nWorkers = Workers.Length;
// Number of workers required for each shift
double[] shiftRequirements =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker
double[,] availability =
new double[,] { { 0, 1, 1, 0, 1, 0,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,

is unavailable for a shift


1,
1,
1,
1,
1,
0,
1,

0,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1, 1, 1, 1, 1 },
0 },
1 },
1 },
1 },
1 },
1 } };
325

// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.Set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[,] x = new GRBVar[nWorkers,nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w,s] =
model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.Update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = 0.0;
for (int w = 0; w < nWorkers; ++w)
lhs += x[w, s];
model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Optimize
model.Optimize();
int status = model.Get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
Console.WriteLine("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
Console.WriteLine("The optimal objective is " +
model.Get(GRB.DoubleAttr.ObjVal));
return;

326

}
if ((status != GRB.Status.INF_OR_UNBD) &&
(status != GRB.Status.INFEASIBLE)) {
Console.WriteLine("Optimization was stopped with status " + status);
return;
}
// Do IIS
Console.WriteLine("The model is infeasible; computing IIS");
model.ComputeIIS();
Console.WriteLine("\nThe following constraint(s) "
+ "cannot be satisfied:");
foreach (GRBConstr c in model.GetConstrs()) {
if (c.Get(GRB.IntAttr.IISConstr) == 1) {
Console.WriteLine(c.Get(GRB.StringAttr.ConstrName));
}
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

327

workforce2_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS iteratively to
find all conflicting constraints. */
using System;
using System.Collections.Generic;
using Gurobi;
class workforce2_cs
{
static void Main()
{
try {
// Sample data
// Sets of days and workers
string[] Shifts =
new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string[] Workers =
new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.Length;
int nWorkers = Workers.Length;
// Number of workers required for each shift
double[] shiftRequirements =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker
double[,] availability =
new double[,] { { 0, 1, 1, 0, 1, 0,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
328

is unavailable for a shift


1,
1,
1,
1,
1,
0,
1,

0,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1, 1, 1, 1, 1 },
0 },
1 },
1 },
1 },
1 },
1 } };

// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.Set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[,] x = new GRBVar[nWorkers,nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w,s] =
model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.Update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = 0.0;
for (int w = 0; w < nWorkers; ++w)
lhs += x[w, s];
model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Optimize
model.Optimize();
int status = model.Get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
Console.WriteLine("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
Console.WriteLine("The optimal objective is " +
model.Get(GRB.DoubleAttr.ObjVal));
return;

329

}
if ((status != GRB.Status.INF_OR_UNBD) &&
(status != GRB.Status.INFEASIBLE)) {
Console.WriteLine("Optimization was stopped with status " + status);
return;
}
// Do IIS
Console.WriteLine("The model is infeasible; computing IIS");
LinkedList<string> removed = new LinkedList<string>();
// Loop until we reduce to a model that can be solved
while (true) {
model.ComputeIIS();
Console.WriteLine("\nThe following constraint cannot be satisfied:");
foreach (GRBConstr c in model.GetConstrs()) {
if (c.Get(GRB.IntAttr.IISConstr) == 1) {
Console.WriteLine(c.Get(GRB.StringAttr.ConstrName));
// Remove a single constraint from the model
removed.AddFirst(c.Get(GRB.StringAttr.ConstrName));
model.Remove(c);
break;
}
}
Console.WriteLine();
model.Optimize();
status = model.Get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
Console.WriteLine("The model cannot be solved "
+ "because it is unbounded");
return;
}
if (status == GRB.Status.OPTIMAL) {
break;
}
if ((status != GRB.Status.INF_OR_UNBD) &&
(status != GRB.Status.INFEASIBLE)) {
Console.WriteLine("Optimization was stopped with status " +
status);
return;
}
}

330

Console.WriteLine("\nThe following constraints were removed "


+ "to get a feasible LP:");
foreach (string s in removed) {
Console.Write(s + " ");
}
Console.WriteLine();
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

331

workforce3_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed. */
using System;
using System.Collections.Generic;
using Gurobi;
class workforce3_cs
{
static void Main()
{
try {
// Sample data
// Sets of days and workers
string[] Shifts =
new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string[] Workers =
new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.Length;
int nWorkers = Workers.Length;
// Number of workers required for each shift
double[] shiftRequirements =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Amount each worker is paid to work one shift
double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };
// Worker availability: 0 if the worker
double[,] availability =
new double[,] { { 0, 1, 1, 0, 1, 0,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0,
332

is unavailable for a shift


1,
1,
1,
1,
1,
0,

0,
0,
1,
1,
0,
1,

1,
1,
1,
1,
1,
1,

1, 1, 1, 1, 1 },
0 },
1 },
1 },
1 },
1 },

{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.Set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. Since an assignment model always produces integer
// solutions, we use continuous variables and solve as an LP.
GRBVar[,] x = new GRBVar[nWorkers,nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w,s] =
model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS,
Workers[w] + "." + Shifts[s]);
}
}
// The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1);
// Update model to integrate new variables
model.Update();
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s
LinkedList<GRBConstr> reqCts = new LinkedList<GRBConstr>();
for (int s = 0; s < nShifts; ++s) {
GRBLinExpr lhs = 0.0;
for (int w = 0; w < nWorkers; ++w)
lhs += x[w,s];
GRBConstr newCt =
model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
reqCts.AddFirst(newCt);
}
// Optimize
model.Optimize();
int status = model.Get(GRB.IntAttr.Status);
if (status == GRB.Status.UNBOUNDED) {
Console.WriteLine("The model cannot be solved "
+ "because it is unbounded");
return;
}

333

if (status == GRB.Status.OPTIMAL) {
Console.WriteLine("The optimal objective is " +
model.Get(GRB.DoubleAttr.ObjVal));
return;
}
if ((status != GRB.Status.INF_OR_UNBD) &&
(status != GRB.Status.INFEASIBLE)) {
Console.WriteLine("Optimization was stopped with status " + status);
return;
}
// Add slack variables to make the model feasible
Console.WriteLine("The model is infeasible; adding slack variables");
// Set original objective coefficients to zero
model.SetObjective(new GRBLinExpr());
// Add a new slack variable to each shift constraint so that the shifts
// can be satisfied
LinkedList<GRBVar> slacks = new LinkedList<GRBVar>();
foreach (GRBConstr c in reqCts) {
GRBColumn col = new GRBColumn();
col.AddTerm(1.0, c);
GRBVar newvar =
model.AddVar(0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, col,
c.Get(GRB.StringAttr.ConstrName) + "Slack");
slacks.AddFirst(newvar);
}
// Solve the model with slacks
model.Optimize();
status = model.Get(GRB.IntAttr.Status);
if ((status == GRB.Status.INF_OR_UNBD) ||
(status == GRB.Status.INFEASIBLE) ||
(status == GRB.Status.UNBOUNDED)) {
Console.WriteLine("The model with slacks cannot be solved "
+ "because it is infeasible or unbounded");
return;
}
if (status != GRB.Status.OPTIMAL) {
Console.WriteLine("Optimization was stopped with status " + status);
return;
}
Console.WriteLine("\nSlack values:");

334

foreach (GRBVar sv in slacks) {


if (sv.Get(GRB.DoubleAttr.X) > 1e-6) {
Console.WriteLine(sv.Get(GRB.StringAttr.VarName) + " = " +
sv.Get(GRB.DoubleAttr.X));
}
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}
}
}

335

workforce4_cs.cs
/* Copyright 2013, Gurobi Optimization, Inc. */
/* Assign workers to shifts; each worker may or may not be available on a
particular day. We use Pareto optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers. */
using System;
using Gurobi;
class workforce4_cs
{
static void Main()
{
try {
// Sample data
// Sets of days and workers
string[] Shifts =
new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
"Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
"Sun14" };
string[] Workers =
new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };
int nShifts = Shifts.Length;
int nWorkers = Workers.Length;
// Number of workers required for each shift
double[] shiftRequirements =
new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };
// Worker availability: 0 if the worker
double[,] availability =
new double[,] { { 0, 1, 1, 0, 1, 0,
{ 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1,
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 1,
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0,
{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
// Model
336

is unavailable for a shift


1,
1,
1,
1,
1,
0,
1,

0,
0,
1,
1,
0,
1,
1,

1,
1,
1,
1,
1,
1,
1,

1, 1, 1, 1, 1 },
0 },
1 },
1 },
1 },
1 },
1 } };

GRBEnv env = new GRBEnv();


GRBModel model = new GRBModel(env);
model.Set(GRB.StringAttr.ModelName, "assignment");
// Assignment variables: x[w][s] == 1 if worker w is assigned
// to shift s. This is no longer a pure assignment model, so we must
// use binary variables.
GRBVar[,] x = new GRBVar[nWorkers, nShifts];
for (int w = 0; w < nWorkers; ++w) {
for (int s = 0; s < nShifts; ++s) {
x[w,s] =
model.AddVar(0, availability[w,s], 0, GRB.BINARY,
Workers[w] + "." + Shifts[s]);
}
}
// Slack variables for each shift constraint so that the shifts can
// be satisfied
GRBVar[] slacks = new GRBVar[nShifts];
for (int s = 0; s < nShifts; ++s) {
slacks[s] =
model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
Shifts[s] + "Slack");
}
// Variable to represent the total slack
GRBVar totSlack = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
"totSlack");
// Variables to count the total shifts worked by each worker
GRBVar[] totShifts = new GRBVar[nWorkers];
for (int w = 0; w < nWorkers; ++w) {
totShifts[w] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
Workers[w] + "TotShifts");
}
// Update model to integrate new variables
model.Update();
GRBLinExpr lhs;
// Constraint: assign exactly shiftRequirements[s] workers
// to each shift s, plus the slack
for (int s = 0; s < nShifts; ++s) {
lhs = new GRBLinExpr();

337

lhs += slacks[s];
for (int w = 0; w < nWorkers; ++w) {
lhs += x[w, s];
}
model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
}
// Constraint: set totSlack equal to the total slack
lhs = new GRBLinExpr();
for (int s = 0; s < nShifts; ++s) {
lhs += slacks[s];
}
model.AddConstr(lhs == totSlack, "totSlack");
// Constraint: compute the total number of shifts for each worker
for (int w = 0; w < nWorkers; ++w) {
lhs = new GRBLinExpr();
for (int s = 0; s < nShifts; ++s) {
lhs += x[w, s];
}
model.AddConstr(lhs == totShifts[w], "totShifts" + Workers[w]);
}
// Objective: minimize the total slack
GRBLinExpr obj = new GRBLinExpr();
obj += totSlack;
model.SetObjective(obj);
// Optimize
int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB.Status.OPTIMAL) {
return;
}
// Constrain the slack by setting its upper and lower bounds
totSlack.Set(GRB.DoubleAttr.UB, totSlack.Get(GRB.DoubleAttr.X));
totSlack.Set(GRB.DoubleAttr.LB, totSlack.Get(GRB.DoubleAttr.X));
// Variable to count the average number of shifts worked
GRBVar avgShifts =
model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "avgShifts");
// Variables to count the difference from average for each worker;
// note that these variables can take negative values.
GRBVar[] diffShifts = new GRBVar[nWorkers];

338

for (int w = 0; w < nWorkers; ++w) {


diffShifts[w] = model.AddVar(-GRB.INFINITY, GRB.INFINITY, 0,
GRB.CONTINUOUS, Workers[w] + "Diff");
}
// Update model to integrate new variables
model.Update();
// Constraint: compute the average number of shifts worked
lhs = new GRBLinExpr();
for (int w = 0; w < nWorkers; ++w) {
lhs.AddTerm(1.0, totShifts[w]);
}
model.AddConstr(lhs == nWorkers * avgShifts, "avgShifts");
// Constraint: compute the difference from the average number of shifts
for (int w = 0; w < nWorkers; ++w) {
lhs = new GRBLinExpr();
lhs += totShifts[w];
lhs -= avgShifts;
model.AddConstr(lhs == diffShifts[w], Workers[w] + "Diff");
}
// Objective: minimize the sum of the square of the difference from the
// average number of shifts worked
GRBQuadExpr qobj = new GRBQuadExpr();
for (int w = 0; w < nWorkers; ++w) {
qobj += diffShifts[w] * diffShifts[w];
}
model.SetObjective(qobj);
// Optimize
status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
if (status != GRB.Status.OPTIMAL) {
return;
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " +
e.Message);
}

339

}
private static int solveAndPrint(GRBModel model, GRBVar totSlack,
int nWorkers, String[] Workers,
GRBVar[] totShifts)
{
model.Optimize();
int status = model.Get(GRB.IntAttr.Status);
if ((status == GRB.Status.INF_OR_UNBD) ||
(status == GRB.Status.INFEASIBLE) ||
(status == GRB.Status.UNBOUNDED)) {
Console.WriteLine("The model cannot be solved "
+ "because it is infeasible or unbounded");
return status;
}
if (status != GRB.Status.OPTIMAL) {
Console.WriteLine("Optimization was stopped with status " + status);
return status;
}
// Print total slack and the number of shifts worked for each worker
Console.WriteLine("\nTotal slack required: " +
totSlack.Get(GRB.DoubleAttr.X));
for (int w = 0; w < nWorkers; ++w) {
Console.WriteLine(Workers[w] + " worked " +
totShifts[w].Get(GRB.DoubleAttr.X) + " shifts");
}
Console.WriteLine("\n");
return status;
}
}

340

3.5

Visual Basic Examples

This section includes source code for all of the Gurobi Visual Basic examples. The same source
code can be found in the examples/vb directory of the Gurobi distribution.

callback_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example reads an LP or a MIP from a file, sets a callback
to monitor the optimization progress and to output some progress
information to the screen and to a log file. If it is a MIP and 10%
gap is reached, then it aborts.

Imports System
Imports Gurobi
Class callback_vb
Inherits GRBCallback
Private vars As GRBVar()
Private lastnode As Double
Private lastiter As Double
Public Sub New(ByVal xvars As GRBVar())
vars = xvars
lastnode = lastiter = -1
End Sub
Protected Overloads Overrides Sub Callback()
Try
If where = GRB.Callback.PRESOLVE Then
Presolve callback
Dim cdels As Integer = GetIntInfo(GRB.Callback.PRE_COLDEL)
Dim rdels As Integer = GetIntInfo(GRB.Callback.PRE_ROWDEL)
Console.WriteLine(cdels & " columns and " & rdels & " rows are removed")
ElseIf where = GRB.Callback.SIMPLEX Then
Simplex callback
Dim itcnt As Double = GetDoubleInfo(GRB.Callback.SPX_ITRCNT)
If itcnt Mod - lastiter >= 100 Then
lastiter = itcnt
Dim obj As Double = GetDoubleInfo(GRB.Callback.SPX_OBJVAL)
Dim pinf As Double = GetDoubleInfo(GRB.Callback.SPX_PRIMINF)
Dim dinf As Double = GetDoubleInfo(GRB.Callback.SPX_DUALINF)
Dim ispert As Integer = GetIntInfo(GRB.Callback.SPX_ISPERT)
Dim ch As Char
If ispert = 0 Then
341

ch = " "c
ElseIf ispert = 1 Then
ch = "S"c
Else
ch = "P"c
End If
Console.WriteLine(itcnt & " " & obj & ch & " " & pinf & " " & dinf)
End If
ElseIf where = GRB.Callback.MIP Then
General MIP callback
Dim nodecnt As Double = GetDoubleInfo(GRB.Callback.MIP_NODCNT)
If nodecnt - lastnode >= 100 Then
lastnode = nodecnt
Dim objbst As Double = GetDoubleInfo(GRB.Callback.MIP_OBJBST)
Dim objbnd As Double = GetDoubleInfo(GRB.Callback.MIP_OBJBND)
If Math.Abs(objbst - objbnd) < 0.1 * (1.0R + Math.Abs(objbst)) Then
Abort()
End If
Dim actnodes As Integer = CInt(GetDoubleInfo(GRB.Callback.MIP_NODLFT))
Dim itcnt As Integer = CInt(GetDoubleInfo(GRB.Callback.MIP_ITRCNT))
Dim solcnt As Integer = GetIntInfo(GRB.Callback.MIP_SOLCNT)
Dim cutcnt As Integer = GetIntInfo(GRB.Callback.MIP_CUTCNT)
Console.WriteLine(nodecnt & " " & actnodes & " " & itcnt & " " & _
objbst & " " & objbnd & " " & solcnt & " " & cutcnt)
End If
ElseIf where = GRB.Callback.MIPSOL Then
MIP solution callback
Dim obj As Double = GetDoubleInfo(GRB.Callback.MIPSOL_OBJ)
Dim nodecnt As Integer = CInt(GetDoubleInfo(GRB.Callback.MIPSOL_NODCNT))
Dim x As Double() = GetSolution(vars)
Console.WriteLine("**** New solution at node " & nodecnt & ", obj " & _
obj & ", x(0) = " & x(0) & "****")
End If
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
Console.WriteLine(e.StackTrace)
End Try
End Sub
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: callback_vb filename")
Return
End If

342

Try
Dim env As New GRBEnv()
Dim model As New GRBModel(env, args(0))
Dim vars As GRBVar() = model.GetVars()
Create a callback object and associate it with the model
model.SetCallback(New callback_vb(vars))
model.Optimize()
Dim x As Double() = model.Get(GRB.DoubleAttr.X, vars)
Dim vnames As String() = model.Get(GRB.StringAttr.VarName, vars)
For j As Integer = 0 To vars.Length - 1
If x(j) <> 0.0R Then
Console.WriteLine(vnames(j) & " " & x(j))
End If
Next
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
Console.WriteLine(e.StackTrace)
End Try
End Sub
End Class

343

dense_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example formulates and solves the following simple QP model:
minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.

Imports Gurobi
Class dense_vb
Protected Shared Function _
dense_optimize(env As GRBEnv, _
rows As Integer, _
cols As Integer, _
c As Double(), _
Q As Double(,), _
A As Double(,), _
sense As Char(), _
rhs As Double(), _
lb As Double(), _
ub As Double(), _
vtype As Char(), _
solution As Double()) As Boolean
Dim success As Boolean = False
Try
Dim model As New GRBModel(env)
Add variables to the model
Dim vars As GRBVar() = model.AddVars(lb, ub, Nothing, vtype, Nothing)
model.Update()
Populate A matrix
For i As Integer = 0 To rows - 1
344

Dim expr As New GRBLinExpr()


For j As Integer = 0 To cols - 1
If A(i, j) <> 0 Then
expr.AddTerm(A(i, j), vars(j))
End If
Next
model.AddConstr(expr, sense(i), rhs(i), "")
Next
Populate objective
Dim obj As New GRBQuadExpr()
If Q IsNot Nothing Then
For i As Integer = 0 To cols - 1
For j As Integer = 0 To cols - 1
If Q(i, j) <> 0 Then
obj.AddTerm(Q(i, j), vars(i), vars(j))
End If
Next
Next
For j As Integer = 0 To cols - 1
If c(j) <> 0 Then
obj.AddTerm(c(j), vars(j))
End If
Next
model.SetObjective(obj)
End If
Solve model
model.Optimize()
Extract solution
If model.Get(GRB.IntAttr.Status) = GRB.Status.OPTIMAL Then
success = True
For j As Integer = 0 To cols - 1
solution(j) = vars(j).Get(GRB.DoubleAttr.X)
Next
End If
model.Dispose()
Catch e As GRBException

345

Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
Return success
End Function
Public Shared Sub Main(args As String())
Try
Dim env As New GRBEnv()
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim

c As Double() = New Double() {1, 1, 0}


Q As Double(,) = New Double(,) {{1, 1, 0}, {0, 1, 1}, {0, 0, 1}}
A As Double(,) = New Double(,) {{1, 2, 3}, {1, 1, 0}}
sense As Char() = New Char() {">"C, ">"C}
rhs As Double() = New Double() {4, 1}
lb As Double() = New Double() {0, 0, 0}
success As Boolean
sol As Double() = New Double(2) {}

success = dense_optimize(env, 2, 3, c, Q, A, sense, rhs, lb, Nothing, _


Nothing, sol)
If success Then
Console.WriteLine("x: " & sol(0) & ", y: " & sol(1) & ", z: " & sol(2))
End If
Dispose of environment
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

346

diet_vb.vb
Copyright 2013, Gurobi Optimization, Inc.
Solve the classic diet model, showing how to add constraints
to an existing model.
Imports System
Imports Gurobi
Class diet_vb
Shared Sub Main()
Try
Nutrition guidelines, based on
USDA Dietary Guidelines for Americans, 2005
http://www.health.gov/DietaryGuidelines/dga2005/
Dim Categories As String() = New String() {"calories", "protein", "fat", _
"sodium"}
Dim nCategories As Integer = Categories.Length
Dim minNutrition As Double() = New Double() {1800, 91, 0, 0}
Dim maxNutrition As Double() = New Double() {2200, GRB.INFINITY, 65, 1779}
Set of foods
Dim Foods As String() = New String() {"hamburger", "chicken", "hot dog", _
"fries", "macaroni", "pizza", _
"salad", "milk", "ice cream"}
Dim nFoods As Integer = Foods.Length
Dim cost As Double() = New Double() {2.49, 2.89, 1.5R, 1.89, 2.09, 1.99, _
2.49, 0.89, 1.59}
Nutrition values for the foods
hamburger
chicken
hot dog
fries
macaroni
pizza
salad
milk
ice cream
Dim nutritionValues As Double(,) = New Double(,) {{410,
{420,
{560,
{380,
{320,

24, 26, 730}, _


32, 10, 1190}, _
20, 32, 1800}, _
4, 19, 270}, _
12, 10, 930}, _
347

{320,
{320,
{100,
{330,

15, 12, 820}, _


31, 12, 1230}, _
8, 2.5, 125}, _
8, 10, 180}}

Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.Set(GRB.StringAttr.ModelName, "diet")
Create decision variables for the nutrition information,
which we limit via bounds
Dim nutrition As GRBVar() = New GRBVar(nCategories - 1) {}
For i As Integer = 0 To nCategories - 1
nutrition(i) = model.AddVar(minNutrition(i), maxNutrition(i), 0, _
GRB.CONTINUOUS, Categories(i))
Next
Create decision variables for the foods to buy
Dim buy As GRBVar() = New GRBVar(nFoods - 1) {}
For j As Integer = 0 To nFoods - 1
buy(j) = model.AddVar(0, GRB.INFINITY, cost(j), GRB.CONTINUOUS, _
Foods(j))
Next
The objective is to minimize the costs
model.Set(GRB.IntAttr.ModelSense, 1)
Update model to integrate new variables
model.Update()
Nutrition constraints
For i As Integer = 0 To nCategories - 1
Dim ntot As GRBLinExpr = 0
For j As Integer = 0 To nFoods - 1
ntot += nutritionValues(j, i) * buy(j)
Next
model.AddConstr(ntot = nutrition(i), Categories(i))
Next
Solve
model.Optimize()
PrintSolution(model, buy, nutrition)
Console.WriteLine(vbLf & "Adding constraint: at most 6 servings of dairy")

348

model.AddConstr(buy(7) + buy(8) <= 6, "limit_dairy")


Solve
model.Optimize()
PrintSolution(model, buy, nutrition)
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
Private Shared Sub PrintSolution(ByVal model As GRBModel, ByVal buy As GRBVar(), _
ByVal nutrition As GRBVar())
If model.Get(GRB.IntAttr.Status) = GRB.Status.OPTIMAL Then
Console.WriteLine(vbLf & "Cost: " & model.Get(GRB.DoubleAttr.ObjVal))
Console.WriteLine(vbLf & "Buy:")
For j As Integer = 0 To buy.Length - 1
If buy(j).Get(GRB.DoubleAttr.X) > 0.0001 Then
Console.WriteLine(buy(j).Get(GRB.StringAttr.VarName) & " " & _
buy(j).Get(GRB.DoubleAttr.X))
End If
Next
Console.WriteLine(vbLf & "Nutrition:")
For i As Integer = 0 To nutrition.Length - 1
Console.WriteLine(nutrition(i).Get(GRB.StringAttr.VarName) & " " & _
nutrition(i).Get(GRB.DoubleAttr.X))
Next
Else
Console.WriteLine("No solution")
End If
End Sub
End Class

349

facility_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Facility location: a company currently ships its product from 5 plants
to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.

Imports System
Imports Gurobi
Class facility_vb
Shared Sub Main()
Try
Warehouse demand in thousands of units
Dim Demand As Double() = New Double() {15, 18, 14, 20}
Plant capacity in thousands of units
Dim Capacity As Double() = New Double() {20, 22, 17, 19, 18}
Fixed costs for each plant
Dim FixedCosts As Double() = New Double() {12000, 15000, 17000, 13000, _
16000}
Transportation costs per thousand units
Dim TransCosts As Double(,) = New Double(,) {{4000,
{2500,
{1200,
{2200,

2000,
2600,
1800,
2600,

3000,
3400,
2600,
3100,

2500,
3000,
4100,
3700,

Number of plants and warehouses


Dim nPlants As Integer = Capacity.Length
Dim nWarehouses As Integer = Demand.Length
Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.Set(GRB.StringAttr.ModelName, "facility")
Plant open decision variables: open(p) == 1 if plant p is open.
350

4500}, _
4000}, _
3000}, _
3200}}

Dim open As GRBVar() = New GRBVar(nPlants - 1) {}


For p As Integer = 0 To nPlants - 1
open(p) = model.AddVar(0, 1, FixedCosts(p), GRB.BINARY, "Open" & p)
Next
Transportation decision variables: how much to transport from
a plant p to a warehouse w
Dim transport As GRBVar(,) = New GRBVar(nWarehouses - 1, nPlants - 1) {}
For w As Integer = 0 To nWarehouses - 1
For p As Integer = 0 To nPlants - 1
transport(w, p) = model.AddVar(0, GRB.INFINITY, _
TransCosts(w, p), GRB.CONTINUOUS, _
"Trans" & p & "." & w)
Next
Next
The objective is to minimize the total fixed and variable costs
model.Set(GRB.IntAttr.ModelSense, 1)
Update model to integrate new variables
model.Update()
Production constraints
Note that the right-hand limit sets the production to zero if
the plant is closed
For p As Integer = 0 To nPlants - 1
Dim ptot As GRBLinExpr = 0
For w As Integer = 0 To nWarehouses - 1
ptot += transport(w, p)
Next
model.AddConstr(ptot <= Capacity(p) * open(p), "Capacity" & p)
Next
Demand constraints
For w As Integer = 0 To nWarehouses - 1
Dim dtot As GRBLinExpr = 0
For p As Integer = 0 To nPlants - 1
dtot += transport(w, p)
Next
model.AddConstr(dtot = Demand(w), "Demand" & w)
Next
Guess at the starting point: close the plant with the highest
fixed costs; open all others

351

First, open all plants


For p As Integer = 0 To nPlants - 1
open(p).Set(GRB.DoubleAttr.Start, 1.0)
Next
Now close the plant with the highest fixed cost
Console.WriteLine("Initial guess:")
Dim maxFixed As Double = -GRB.INFINITY
For p As Integer = 0 To nPlants - 1
If FixedCosts(p) > maxFixed Then
maxFixed = FixedCosts(p)
End If
Next
For p As Integer = 0 To nPlants - 1
If FixedCosts(p) = maxFixed Then
open(p).Set(GRB.DoubleAttr.Start, 0.0)
Console.WriteLine("Closing plant " & p & vbLf)
Exit For
End If
Next
Use barrier to solve root relaxation
model.GetEnv().Set(GRB.IntParam.Method, GRB.METHOD_BARRIER)
Solve
model.Optimize()
Print solution
Console.WriteLine(vbLf & "TOTAL COSTS: " & model.Get(GRB.DoubleAttr.ObjVal))
Console.WriteLine("SOLUTION:")
For p As Integer = 0 To nPlants - 1
If open(p).Get(GRB.DoubleAttr.X) = 1.0 Then
Console.WriteLine("Plant " & p & " open:")
For w As Integer = 0 To nWarehouses - 1
If transport(w, p).Get(GRB.DoubleAttr.X) > 0.0001 Then
Console.WriteLine(" Transport " & _
transport(w, p).Get(GRB.DoubleAttr.X) & _
" units to warehouse " & w)
End If
Next
Else
Console.WriteLine("Plant " & p & " closed!")
End If
Next

352

Dispose of model and env


model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

353

feasopt_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example reads a MIP model from a file, adds artificial
variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables.

Imports Gurobi
Imports System
Class feasopt_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: feasopt_vb filename")
Return
End If
Try
Dim env As New GRBEnv()
Dim feasmodel As New GRBModel(env, args(0))
Create a copy to use FeasRelax feature later
Dim feasmodel1 As New GRBModel(feasmodel)
Clear objective
feasmodel.SetObjective(New GRBLinExpr())
Add slack variables
Dim c As GRBConstr() = feasmodel.GetConstrs()
For i As Integer = 0 To c.Length - 1
Dim sense As Char = c(i).Get(GRB.CharAttr.Sense)
If sense <> ">"c Then
Dim constrs As GRBConstr() = New GRBConstr() {c(i)}
Dim coeffs As Double() = New Double() {-1}
feasmodel.AddVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, _
constrs, coeffs, _
"ArtN_" & c(i).Get(GRB.StringAttr.ConstrName))
End If
If sense <> "<"c Then
354

Dim constrs As GRBConstr() = New GRBConstr() {c(i)}


Dim coeffs As Double() = New Double() {1}
feasmodel.AddVar(0.0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, _
constrs, coeffs, _
"ArtP_" & c(i).Get(GRB.StringAttr.ConstrName))
End If
Next
feasmodel.Update()
Optimize modified model
feasmodel.Write("feasopt.lp")
feasmodel.Optimize()
Use FeasRelax feature */
feasmodel1.FeasRelax(GRB.FEASRELAX_LINEAR, true, false, true)
feasmodel1.Write("feasopt1.lp")
feasmodel1.Optimize()
Dispose of model and env
feasmodel1.Dispose()
feasmodel.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

355

fixanddive_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Implement a simple MIP heuristic. Relax the model,
sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible.

Imports System
Imports System.Collections.Generic
Imports Gurobi
Class fixanddive_vb
Comparison class used to sort variable list based on relaxation
fractionality
Private Class FractionalCompare : Implements IComparer(Of GRBVar)
Public Function Compare(ByVal v1 As GRBVar, ByVal v2 As GRBVar) As Integer _
Implements IComparer(Of Gurobi.GRBVar).Compare
Try
Dim sol1 As Double = Math.Abs(v1.Get(GRB.DoubleAttr.X))
Dim sol2 As Double = Math.Abs(v2.Get(GRB.DoubleAttr.X))
Dim frac1 As Double = Math.Abs(sol1 - Math.Floor(sol1 + 0.5))
Dim frac2 As Double = Math.Abs(sol2 - Math.Floor(sol2 + 0.5))
If frac1 < frac2 Then
Return -1
ElseIf frac1 > frac2 Then
Return 1
Else
Return 0
End If
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
Return 0
End Function
End Class
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: fixanddive_vb filename")
Return
End If
356

Try
Read model
Dim env As New GRBEnv()
Dim model As New GRBModel(env, args(0))
Collect integer variables and relax them
Dim intvars As New List(Of GRBVar)()
For Each v As GRBVar In model.GetVars()
If v.Get(GRB.CharAttr.VType) <> GRB.CONTINUOUS Then
intvars.Add(v)
v.Set(GRB.CharAttr.VType, GRB.CONTINUOUS)
End If
Next
model.GetEnv().Set(GRB.IntParam.OutputFlag, 0)
model.Optimize()
Perform multiple iterations. In each iteration, identify the first
quartile of integer variables that are closest to an integer value
in the relaxation, fix them to the nearest integer, and repeat.
For iter As Integer = 0 To 999
create a list of fractional variables, sorted in order of
increasing distance from the relaxation solution to the nearest
integer value
Dim fractional As New List(Of GRBVar)()
For Each v As GRBVar In intvars
Dim sol As Double = Math.Abs(v.Get(GRB.DoubleAttr.X))
If Math.Abs(sol - Math.Floor(sol + 0.5)) > 0.00001 Then
fractional.Add(v)
End If
Next
Console.WriteLine("Iteration " & iter & ", obj " & _
model.Get(GRB.DoubleAttr.ObjVal) & _
", fractional " & fractional.Count)
If fractional.Count = 0 Then
Console.WriteLine("Found feasible solution - objective " & _
model.Get(GRB.DoubleAttr.ObjVal))
Exit For
End If

357

Fix the first quartile to the nearest integer value


fractional.Sort(New FractionalCompare())
Dim nfix As Integer = Math.Max(fractional.Count / 4, 1)
For i As Integer = 0 To nfix - 1
Dim v As GRBVar = fractional(i)
Dim fixval As Double = Math.Floor(v.Get(GRB.DoubleAttr.X) + 0.5)
v.Set(GRB.DoubleAttr.LB, fixval)
v.Set(GRB.DoubleAttr.UB, fixval)
Console.WriteLine(" Fix " & v.Get(GRB.StringAttr.VarName) & _
" to " & fixval & _
" ( rel " & v.Get(GRB.DoubleAttr.X) & " )")
Next
model.Optimize()
Check optimization result
If model.Get(GRB.IntAttr.Status) <> GRB.Status.OPTIMAL Then
Console.WriteLine("Relaxation is infeasible")
Exit For
End If
Next
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " + e.Message)
End Try
End Sub
End Class

358

lp_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example reads an LP model from a file and solves it.
If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file.

Imports System
Imports Gurobi
Class lp_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: lp_vb filename")
Return
End If
Try
Dim env As GRBEnv = New GRBEnv("lp1.log")
Dim model As GRBModel = New GRBModel(env, args(0))
model.Optimize()
Dim optimstatus As Integer = model.Get(GRB.IntAttr.Status)
If optimstatus = GRB.Status.INF_OR_UNBD Then
model.GetEnv().Set(GRB.IntParam.Presolve, 0)
model.Optimize()
optimstatus = model.Get(GRB.IntAttr.Status)
End If
If optimstatus = GRB.Status.OPTIMAL Then
Dim objval As Double = model.Get(GRB.DoubleAttr.ObjVal)
Console.WriteLine("Optimal objective: " & objval)
ElseIf optimstatus = GRB.Status.INFEASIBLE Then
Console.WriteLine("Model is infeasible")
model.ComputeIIS()
model.Write("model.ilp")
ElseIf optimstatus = GRB.Status.UNBOUNDED Then
Console.WriteLine("Model is unbounded")
Else
Console.WriteLine("Optimization was stopped with status = " & _
359

optimstatus)
End If
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

360

lpmethod_vb.vb
Copyright 2013, Gurobi Optimization, Inc.

Solve a model with different values of the Method parameter;


show which value gives the shortest solve time.
Imports System
Imports Gurobi
Class lpmethod_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: lpmethod_vb filename")
Return
End If
Try
Read model and verify that it is a MIP
Dim env As New GRBEnv()
Dim model As New GRBModel(env, args(0))
Dim menv As GRBEnv = model.GetEnv()
Solve the model with different values of Method
Dim bestMethod As Integer = -1
Dim bestTime As Double = menv.get(GRB.DoubleParam.TimeLimit)
For i As Integer = 0 To 2
model.Reset()
menv.Set(GRB.IntParam.Method, i)
model.Optimize()
If model.Get(GRB.IntAttr.Status) = GRB.Status.OPTIMAL Then
bestTime = model.Get(GRB.DoubleAttr.Runtime)
bestMethod = i
Reduce the TimeLimit parameter to save time
with other methods
menv.Set(GRB.DoubleParam.TimeLimit, bestTime)
End If
Next
Report which method was fastest
If bestMethod = -1 Then
Console.WriteLine("Unable to solve this model")
Else
Console.WriteLine("Solved in " & bestTime & _
361

" seconds with Method: " & bestMethod)


End If
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

362

lpmod_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example reads an LP model from a file and solves it.
If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch).

Imports System
Imports Gurobi
Class lpmod_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: lpmod_vb filename")
Return
End If
Try
Read model and determine whether it is an LP
Dim env As New GRBEnv()
Dim model As New GRBModel(env, args(0))
If model.Get(GRB.IntAttr.IsMIP) <> 0 Then
Console.WriteLine("The model is not a linear program")
Environment.Exit(1)
End If
model.Optimize()
Dim status As Integer = model.Get(GRB.IntAttr.Status)
If (status = GRB.Status.INF_OR_UNBD) OrElse _
(status = GRB.Status.INFEASIBLE) OrElse _
(status = GRB.Status.UNBOUNDED) Then
Console.WriteLine("The model cannot be solved because it is " & _
"infeasible or unbounded")
Environment.Exit(1)
End If
If status <> GRB.Status.OPTIMAL Then
Console.WriteLine("Optimization was stopped with status " & status)
Environment.Exit(0)
End If
363

Find the smallest variable value


Dim minVal As Double = GRB.INFINITY
Dim minVar As GRBVar = Nothing
For Each v As GRBVar In model.GetVars()
Dim sol As Double = v.Get(GRB.DoubleAttr.X)
If (sol > 0.0001) AndAlso _
(sol < minVal) AndAlso _
(v.Get(GRB.DoubleAttr.LB) = 0.0) Then
minVal = sol
minVar = v
End If
Next
Console.WriteLine(vbLf & "*** Setting " & _
minVar.Get(GRB.StringAttr.VarName) & _
" from " & minVal & " to zero ***" & vbLf)
minVar.Set(GRB.DoubleAttr.UB, 0)
Solve from this starting point
model.Optimize()
Save iteration & time info
Dim warmCount As Double = model.Get(GRB.DoubleAttr.IterCount)
Dim warmTime As Double = model.Get(GRB.DoubleAttr.Runtime)
Reset the model and resolve
Console.WriteLine(vbLf & "*** Resetting and solving " & _
"without an advanced start ***" & vbLf)
model.Reset()
model.Optimize()
Dim coldCount As Double = model.Get(GRB.DoubleAttr.IterCount)
Dim coldTime As Double = model.Get(GRB.DoubleAttr.Runtime)
Console.WriteLine(vbLf & "*** Warm start: " & warmCount & _
" iterations, " & warmTime & " seconds")
Console.WriteLine("*** Cold start: " & coldCount & " iterations, " & _
coldTime & " seconds")
Dispose of model and env
model.Dispose()
env.Dispose()

364

Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

365

mip1_vb.vb
Copyright 2013, Gurobi Optimization, Inc.

This example formulates and solves the following simple MIP model:

maximize
x +
y + 2 z

subject to x + 2 y + 3 z <= 4

x +
y
>= 1

x, y, z binary
Imports System
Imports Gurobi
Class mip1_vb
Shared Sub Main()
Try
Dim env As GRBEnv = New GRBEnv("mip1.log")
Dim model As GRBModel = New GRBModel(env)
Create variables
Dim x As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "x")
Dim y As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "y")
Dim z As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "z")
Integrate new variables
model.Update()
Set objective: maximize x + y + 2 z
model.SetObjective(x + y + 2 * z, GRB.MAXIMIZE)
Add constraint: x + 2 y + 3 z <= 4
model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c0")
Add constraint: x + y >= 1
model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c1")
Optimize model
model.Optimize()

366

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))
Console.WriteLine("Obj: " & model.Get(GRB.DoubleAttr.ObjVal))
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

367

mip2_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example reads a MIP model from a file, solves it and
prints the objective values from all feasible solutions
generated while solving the MIP. Then it creates the fixed
model and solves that model.

Imports System
Imports Gurobi
Class mip2_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: mip2_vb filename")
Return
End If
Try
Dim env As GRBEnv = New GRBEnv("lp1.log")
Dim model As GRBModel = New GRBModel(env, args(0))
If model.Get(GRB.IntAttr.IsMIP) = 0 Then
Console.WriteLine("Model is not a MIP")
Return
End If
model.Optimize()
Dim optimstatus As Integer = model.Get(GRB.IntAttr.Status)
If optimstatus = GRB.Status.INF_OR_UNBD Then
model.GetEnv().Set(GRB.IntParam.Presolve, 0)
model.Optimize()
optimstatus = model.Get(GRB.IntAttr.Status)
End If
Dim objval As Double
If optimstatus = GRB.Status.OPTIMAL Then
objval = model.Get(GRB.DoubleAttr.ObjVal)
Console.WriteLine("Optimal objective: " & objval)
ElseIf optimstatus = GRB.Status.INFEASIBLE Then
368

Console.WriteLine("Model is infeasible")
model.ComputeIIS()
model.Write("model.ilp")
Return
ElseIf optimstatus = GRB.Status.UNBOUNDED Then
Console.WriteLine("Model is unbounded")
Return
Else
Console.WriteLine("Optimization was stopped with status = " & _
optimstatus)
Return
End If
Iterate over the solutions and compute the objectives
Dim vars() As GRBVar = model.GetVars()
model.GetEnv().Set(GRB.IntParam.OutputFlag, 0)
Console.WriteLine()
For k As Integer = 0 To model.Get(GRB.IntAttr.SolCount) - 1
model.GetEnv().Set(GRB.IntParam.SolutionNumber, k)
Dim objn As Double = 0.0
For j As Integer = 0 To vars.Length - 1
objn += vars(j).Get(GRB.DoubleAttr.Obj) * _
vars(j).Get(GRB.DoubleAttr.Xn)
Next
Console.WriteLine("Solution " & k & " has objective: " & objn)
Next
Console.WriteLine()
model.GetEnv().Set(GRB.IntParam.OutputFlag, 1)
Solve fixed model
Dim fixedmodel As GRBModel = model.FixedModel()
fixedmodel.GetEnv().Set(GRB.IntParam.Presolve, 0)
fixedmodel.Optimize()
Dim foptimstatus As Integer = fixedmodel.Get(GRB.IntAttr.Status)
If foptimstatus <> GRB.Status.OPTIMAL Then
Console.WriteLine("Error: fixed model isnt optimal")
Return
End If
Dim fobjval As Double = fixedmodel.Get(GRB.DoubleAttr.ObjVal)

369

If Math.Abs(fobjval - objval) > 0.000001 * (1.0 + Math.Abs(objval)) Then


End If
Dim fvars() As GRBVar = fixedmodel.GetVars()
Dim x() As Double = fixedmodel.Get(GRB.DoubleAttr.X, fvars)
Dim vnames() As String = fixedmodel.Get(GRB.StringAttr.VarName, fvars)
For j As Integer = 0 To fvars.Length - 1
If x(j) <> 0 Then
Console.WriteLine(vnames(j) & " " & x(j))
End If
Next
Dispose of models and env
fixedmodel.Dispose()
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

370

params_vb.vb
Copyright 2013, Gurobi Optimization, Inc.

Use parameters that are associated with a model.


A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.
Imports System
Imports Gurobi
Class params_vb
Simple function to determine the MIP gap
Private Shared Function Gap(ByVal model As GRBModel) As Double
If (model.Get(GRB.IntAttr.SolCount) = 0) OrElse _
(Math.Abs(model.Get(GRB.DoubleAttr.ObjVal)) < 0.000001) Then
Return GRB.INFINITY
End If
Return Math.Abs(model.Get(GRB.DoubleAttr.ObjBound) - _
model.Get(GRB.DoubleAttr.ObjVal)) / _
Math.Abs(model.Get(GRB.DoubleAttr.ObjVal))
End Function
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: params_vb filename")
Return
End If
Try
Read model and verify that it is a MIP
Dim env As New GRBEnv()
Dim basemodel As New GRBModel(env, args(0))
If basemodel.Get(GRB.IntAttr.IsMIP) = 0 Then
Console.WriteLine("The model is not an integer program")
Environment.Exit(1)
End If
Set a 5 second time limit
basemodel.GetEnv().Set(GRB.DoubleParam.TimeLimit, 5)
Now solve the model with different values of MIPFocus
Dim bestGap As Double = GRB.INFINITY
371

Dim bestModel As GRBModel = Nothing


For i As Integer = 0 To 3
Dim m As New GRBModel(basemodel)
m.GetEnv().Set(GRB.IntParam.MIPFocus, i)
m.Optimize()
If bestModel Is Nothing OrElse bestGap > Gap(m) Then
bestModel = m
bestGap = Gap(bestModel)
End If
Next
Finally, reset the time limit and continue to solve the
best model to optimality
bestModel.GetEnv().Set(GRB.DoubleParam.TimeLimit, GRB.INFINITY)
bestModel.Optimize()
Console.WriteLine("Solved with MIPFocus: " & _
bestModel.GetEnv().Get(GRB.IntParam.MIPFocus))
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

372

qcp_vb.vb
Copyright 2013, Gurobi Optimization, Inc.
This example formulates and solves the following simple QCP model:

maximize
x

subject to x + y + z = 1

x^2 + y^2 <= z^2 (second-order cone)

x^2 <= yz
(rotated second-order cone)
Imports Gurobi
Class qcp_cs
Shared Sub Main()
Try
Dim env As New GRBEnv("qcp.log")
Dim model As New GRBModel(env)
Create variables
Dim x As GRBVar = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "x")
Dim y As GRBVar = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "y")
Dim z As GRBVar = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "z")
Integrate new variables
model.Update()
Set objective
Dim obj As GRBLinExpr = x
model.SetObjective(obj, GRB.MAXIMIZE)
Add linear constraint: x + y + z = 1
model.AddConstr(x + y + z = 1.0, "c0")
Add second-order cone: x^2 + y^2 <= z^2
model.AddQConstr(x * x + y * y <= z * z, "qc0")
Add rotated cone: x^2 <= yz
model.AddQConstr(x * x <= y * z, "qc1")

373

Optimize model
model.Optimize()
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))
Console.WriteLine("Obj: " & model.Get(GRB.DoubleAttr.ObjVal) & " " & _
obj.Value)
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

374

qp_vb.vb
Copyright 2013, Gurobi Optimization, Inc.
This example formulates and solves the following simple QP model:

minimize
x^2 + x*y + y^2 + y*z + z^2 + 2 x

subject to x + 2 y + 3 z >= 4

x +
y
>= 1

It solves it once as a continuous model, and once as an integer model.

Imports Gurobi
Class qp_vb
Shared Sub Main()
Try
Dim env As New GRBEnv("qp.log")
Dim model As New GRBModel(env)
Create variables
Dim x As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "x")
Dim y As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "y")
Dim z As GRBVar = model.AddVar(0.0, 1.0, 0.0, GRB.CONTINUOUS, "z")
Integrate new variables
model.Update()
Set objective
Dim obj As New GRBQuadExpr()
obj = x*x + x*y + y*y + y*z + z*z + 2*x
model.SetObjective(obj)
Add constraint: x + 2 y + 3 z >= 4
model.AddConstr(x + 2 * y + 3 * z >= 4.0, "c0")
Add constraint: x + y >= 1
model.AddConstr(x + y >= 1.0, "c1")
Optimize model
375

model.Optimize()
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))
Console.WriteLine("Obj: " & model.Get(GRB.DoubleAttr.ObjVal) & _
" " & obj.Value)

Change variable types to integer


x.Set(GRB.CharAttr.VType, GRB.INTEGER)
y.Set(GRB.CharAttr.VType, GRB.INTEGER)
z.Set(GRB.CharAttr.VType, GRB.INTEGER)
Optimize model
model.Optimize()
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))
Console.WriteLine("Obj: " & model.Get(GRB.DoubleAttr.ObjVal) & _
" " & obj.Value)
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

376

sensitivity_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Simple MIP sensitivity analysis example.
For each integer variable, fix it to its lower and upper bound
and check the impact on the objective.

Imports System
Imports Gurobi
Class sensitivity_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: sensitivity_vb filename")
Return
End If
Try
Read model
Dim env As New GRBEnv()
Dim a As New GRBModel(env, args(0))
a.Optimize()
a.GetEnv().Set(GRB.IntParam.OutputFlag, 0)
Extract variables from model
Dim avars As GRBVar() = a.GetVars()
For i As Integer = 0 To avars.Length - 1
Dim v As GRBVar = avars(i)
If v.Get(GRB.CharAttr.VType) = GRB.BINARY Then
Create clone and fix variable
Dim b As New GRBModel(a)
Dim bv As GRBVar = b.GetVars()(i)
If v.Get(GRB.DoubleAttr.X) - v.Get(GRB.DoubleAttr.LB) < 0.5 Then
bv.Set(GRB.DoubleAttr.LB, bv.Get(GRB.DoubleAttr.UB))
Else
bv.Set(GRB.DoubleAttr.UB, bv.Get(GRB.DoubleAttr.LB))
End If
b.Optimize()
If b.Get(GRB.IntAttr.Status) = GRB.Status.OPTIMAL Then
Dim objchg As Double = b.Get(GRB.DoubleAttr.ObjVal) - _
377

a.Get(GRB.DoubleAttr.ObjVal)
If objchg < 0 Then
objchg = 0
End If
Console.WriteLine("Objective sensitivity for variable " & _
v.Get(GRB.StringAttr.VarName) & _
" is " & objchg)
Else
Console.WriteLine("Objective sensitivity for variable " & _
v.Get(GRB.StringAttr.VarName) & _
" is infinite")
End If
Dispose of model
b.Dispose()
End If
Next
Dispose of model and env
a.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " + e.Message)
End Try
End Sub
End Class

378

sos_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


This example creates a very simple Special Ordered Set (SOS) model.
The model consists of 3 continuous variables, no linear constraints,
and a pair of SOS constraints of type 1.

Imports System
Imports Gurobi
Class sos_vb
Shared Sub Main()
Try
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
Create variables
Dim ub As Double() = {1, 1, 2}
Dim obj As Double() = {-2, -1, -1}
Dim names As String() = {"x0", "x1", "x2"}
Dim x As GRBVar() = model.AddVars(Nothing, ub, obj, Nothing, names)
Integrate new variables
model.Update()
Add first SOS1: x0=0 or x1=0
Dim sosv1 As GRBVar() = {x(0), x(1)}
Dim soswt1 As Double() = {1, 2}
model.AddSOS(sosv1, soswt1, GRB.SOS_TYPE1)
Add second SOS1: x0=0 or x2=0
Dim sosv2 As GRBVar() = {x(0), x(2)}
Dim soswt2 As Double() = {1, 2}
model.AddSOS(sosv2, soswt2, GRB.SOS_TYPE1)
Optimize model
model.Optimize()
379

For i As Integer = 0 To 2
Console.WriteLine(x(i).Get(GRB.StringAttr.VarName) & " " & _
x(i).Get(GRB.DoubleAttr.X))
Next
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

380

sudoku_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Sudoku example.
The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.

In the MIP formulation, binary variables x(i,j,v) indicate whether


cell <i,j> takes value v. The constraints are as follows:

1. Each cell must take exactly one value (sum_v x(i,j,v) = 1)

2. Each value is used exactly once per row (sum_i x(i,j,v) = 1)

3. Each value is used exactly once per column (sum_j x(i,j,v) = 1)

4. Each value is used exactly once per 3x3 subgrid (sum_grid x(i,j,v) = 1)
Imports System
Imports System.IO
Imports Gurobi
Class sudoku_vb
Shared Sub Main(ByVal args as String())
Dim n As Integer = 9
Dim s As Integer = 3
If args.Length < 1 Then
Console.WriteLine("Usage: sudoku_vb filename")
Return
End If
Try
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
Create 3-D array of model variables
Dim vars As GRBVar(,,) = New GRBVar(n - 1, n - 1, n - 1) {}
For i As Integer = 0 To n - 1
For j As Integer = 0 To n - 1
For v As Integer = 0 To n - 1
Dim st As String = "G_" & i & "_" & j & "_" & v
vars(i, j, v) = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, st)
Next
381

Next
Next
Integrate variables into model
model.Update()
Add constraints
Dim expr As GRBLinExpr
Each cell must take one value
For i As Integer = 0 To n - 1
For j As Integer = 0 To n - 1
expr = 0
For v As Integer = 0 To n - 1
expr += vars(i, j, v)
Next
Dim st As String = "V_" & i & "_" & j
model.AddConstr(expr = 1, st)
Next
Next
Each value appears once per row
For i As Integer = 0 To n - 1
For v As Integer = 0 To n - 1
expr = 0
For j As Integer = 0 To n - 1
expr += vars(i, j, v)
Next
Dim st As String = "R_" & i & "_" & v
model.AddConstr(expr = 1, st)
Next
Next
Each value appears once per column
For j As Integer = 0 To n - 1
For v As Integer = 0 To n - 1
expr = 0
For i As Integer = 0 To n - 1
expr += vars(i, j, v)
Next

382

Dim st As String = "C_" & j & "_" & v


model.AddConstr(expr = 1, st)
Next
Next
Each value appears once per sub-grid
For v As Integer = 0 To n - 1
For i0 As Integer = 0 To s - 1
For j0 As Integer = 0 To s - 1
expr = 0
For i1 As Integer = 0 To s - 1
For j1 As Integer = 0 To s - 1
expr += vars(i0 * s + i1, j0 * s + j1, v)
Next
Next
Dim st As String = "Sub_" & v & "_" & i0 & "_" & j0
model.AddConstr(expr = 1, st)
Next
Next
Next
Update model
model.Update()
Fix variables associated with pre-specified cells
Dim sr As StreamReader = File.OpenText(args(0))
For i As Integer = 0 To n - 1
Dim input As String = sr.ReadLine()
For j As Integer = 0 To n - 1
Dim val As Integer = Microsoft.VisualBasic.Asc(input(j)) - 48 - 1
0-based
If val >= 0 Then
vars(i, j, val).Set(GRB.DoubleAttr.LB, 1.0)
End If
Next
Next
Optimize model
model.Optimize()

383

Write model to file


model.Write("sudoku.lp")
Dim x As Double(,,) = model.Get(GRB.DoubleAttr.X, vars)
Console.WriteLine()
For i As Integer = 0 To n - 1
For j As Integer = 0 To n For v As Integer = 0 To
If x(i, j, v) > 0.5
Console.Write(v
End If
Next
Next
Console.WriteLine()
Next

1
n - 1
Then
+ 1)

Dispose of model and env


model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

384

tsp_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Solve a traveling salesman problem on a randomly generated set of
points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every node. The lazy constraint callback
adds new constraints to cut them off.

Imports Gurobi
Class tsp_vb
Inherits GRBCallback
Private vars As GRBVar(,)
Public Sub New(xvars As GRBVar(,))
vars = xvars
End Sub
Subtour elimination callback.
Whenever a feasible solution is found,
find the smallest subtour, and add a subtour elimination constraint
if the tour doesnt visit every node.
Protected Overrides Sub Callback()
Try
If where = GRB.Callback.MIPSOL Then
Found an integer feasible solution - does it visit every node?
Dim n As Integer = vars.GetLength(0)
Dim tour As Integer() = findsubtour(GetSolution(vars))
If tour.Length < n Then
Add subtour elimination constraint
Dim expr As GRBLinExpr = 0
For i As Integer = 0 To tour.Length - 1
For j As Integer = 0 To tour.Length - 1
expr += vars(tour(i), tour(j))
Next
Next
AddLazy(expr <= tour.Length - 1)
End If
End If
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
385

Console.WriteLine(e.StackTrace)
End Try
End Sub
Given an integer-feasible solution sol, returns the smallest
sub-tour (as a list of node indices).
Protected Shared Function findsubtour(sol As Double(,)) As Integer()
Dim n As Integer = sol.GetLength(0)
Dim seen As Boolean() = New Boolean(n - 1) {}
Dim tour As Integer() = New Integer(n - 1) {}
Dim bestind As Integer, bestlen As Integer
Dim i As Integer, node As Integer, len As Integer, start As Integer
For i = 0 To n - 1
seen(i) = False
Next
start = 0
bestlen = n+1
bestind = -1
node = 0
While start < n
For node = 0 To n - 1
if Not seen(node)
Exit For
End if
Next
if node = n
Exit While
End if
For len = 0 To n - 1
tour(start+len) = node
seen(node) = true
For i = 0 To n - 1
if sol(node, i) > 0.5 AndAlso Not seen(i)
node = i
Exit For
End If
Next
If i = n
len = len + 1
If len < bestlen
bestlen = len
bestind = start

386

End If
start = start + len
Exit For
End If
Next
End While
For i = 0 To bestlen - 1
tour(i) = tour(bestind+i)
Next
System.Array.Resize(tour, bestlen)
Return tour
End Function
Euclidean distance between points i and j
Protected Shared Function distance(x As Double(), y As Double(), _
i As Integer, j As Integer) As Double
Dim dx As Double = x(i) - x(j)
Dim dy As Double = y(i) - y(j)
Return Math.Sqrt(dx * dx + dy * dy)
End Function
Public Shared Sub Main(args As String())
If args.Length < 1 Then
Console.WriteLine("Usage: tsp_vb nnodes")
Return
End If
Dim n As Integer = Convert.ToInt32(args(0))
Try
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
Must set LazyConstraints parameter when using lazy constraints
model.GetEnv().Set(GRB.IntParam.LazyConstraints, 1)
Dim x As Double() = New Double(n - 1) {}
Dim y As Double() = New Double(n - 1) {}
Dim r As New Random()

387

For i As Integer = 0 To n - 1
x(i) = r.NextDouble()
y(i) = r.NextDouble()
Next
Create variables
Dim vars As GRBVar(,) = New GRBVar(n - 1, n - 1) {}
For i As Integer = 0 To n - 1
For j As Integer = 0 To n - 1
vars(i, j) = model.AddVar(0.0, 1.0, distance(x, y, i, j), _
GRB.BINARY, "x" & i & "_" & j)
Next
Next
Integrate variables
model.Update()
Degree-2 constraints
For i As Integer = 0 To n - 1
Dim expr As GRBLinExpr = 0
For j As Integer = 0 To n - 1
expr += vars(i, j)
Next
model.AddConstr(expr = 2.0, "deg2_" & i)
Next
Forbid edge from node back to itself
For i As Integer = 0 To n - 1
vars(i, i).Set(GRB.DoubleAttr.UB, 0.0)
Next
Symmetric TSP
For i As Integer = 0 To n - 1
For j As Integer = 0 To i - 1
model.AddConstr(vars(i, j) = vars(j, i), "")
Next
Next
model.SetCallback(New tsp_vb(vars))

388

model.Optimize()
If model.Get(GRB.IntAttr.SolCount) > 0 Then
Dim tour As Integer() = findsubtour(model.Get(GRB.DoubleAttr.X, vars))
Console.Write("Tour: ")
For i As Integer = 0 To tour.Length - 1
Console.Write(tour(i) & " ")
Next
Console.WriteLine()
End If
Dispose of model and environment
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
Console.WriteLine(e.StackTrace)
End Try
End Sub
End Class

389

tune_vb.vb

Copyright 2013, Gurobi Optimization, Inc. */


This example reads a model from a file and tunes it.
It then writes the best parameter settings to a file
and solves the model using these parameters.

Imports System
Imports Gurobi
Class tune_vb
Shared Sub Main(ByVal args As String())
If args.Length < 1 Then
Console.Out.WriteLine("Usage: tune_vb filename")
Return
End If
Try
Dim env As New GRBEnv()
Read model from file
Dim model As New GRBModel(env, args(0))
Set the TuneResults parameter to 1
model.GetEnv().Set(GRB.IntParam.TuneResults, 1)
Tune the model
model.Tune()
Get the number of tuning results
Dim resultcount As Integer = model.Get(GRB.IntAttr.TuneResultCount)
If resultcount > 0 Then
Load the tuned parameters into the models environment
model.GetTuneResult(0)
Write the tuned parameters to a file
model.Write("tune.prm")
Solve the model using the tuned parameters
model.Optimize()
End If

390

Dispose of model and environment


model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

391

workforce1_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts
besides what is reported via IIS.

Imports System
Imports Gurobi
Class workforce1_vb
Shared Sub Main()
Try
Sample data
Sets of days and workers
Dim Shifts As String() = New String() {"Mon1", "Tue2", "Wed3", "Thu4", _
"Fri5", "Sat6", "Sun7", "Mon8", _
"Tue9", "Wed10", "Thu11", _
"Fri12", "Sat13", "Sun14"}
Dim Workers As String() = New String() {"Amy", "Bob", "Cathy", "Dan", _
"Ed", "Fred", "Gu"}
Dim nShifts As Integer = Shifts.Length
Dim nWorkers As Integer = Workers.Length
Number of workers required for each shift
Dim shiftRequirements As Double() = New Double() {3, 2, 4, 4, 5, 6, _
5, 2, 2, 3, 4, 6, _
7, 5}
Amount each worker is paid to work one shift
Dim pay As Double() = New Double() {10, 12, 10, 8, 8, 9, 11}
Worker availability: 0 if the worker is unavailable for a shift
Dim availability As Double(,) = New Double(,) { _
{0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1}, _
{1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0}, _
{0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, _
{0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, _
{1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1}, _
{1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1}, _
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

392

Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.Set(GRB.StringAttr.ModelName, "assignment")
Assignment variables: x(w)(s) == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP.
Dim x As GRBVar(,) = New GRBVar(nWorkers - 1, nShifts - 1) {}
For w As Integer = 0 To nWorkers - 1
For s As Integer = 0 To nShifts - 1
x(w, s) = model.AddVar(0, availability(w, s), pay(w), _
GRB.CONTINUOUS, _
Workers(w) & "." & Shifts(s))
Next
Next
The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1)
Update model to integrate new variables
model.Update()
Constraint: assign exactly shiftRequirements(s) workers
to each shift s
For s As Integer = 0 To nShifts - 1
Dim lhs As GRBLinExpr = 0
For w As Integer = 0 To nWorkers - 1
lhs += x(w, s)
Next
model.AddConstr(lhs = shiftRequirements(s), Shifts(s))
Next
Optimize
model.Optimize()
Dim status As Integer = model.Get(GRB.IntAttr.Status)
If status = GRB.Status.UNBOUNDED Then
Console.WriteLine("The model cannot be solved " & _
"because it is unbounded")
Exit Sub
End If
If status = GRB.Status.OPTIMAL Then
Console.WriteLine("The optimal objective is " & _
model.Get(GRB.DoubleAttr.ObjVal))
Exit Sub

393

End If
If (status <> GRB.Status.INF_OR_UNBD) AndAlso _
(status <> GRB.Status.INFEASIBLE) Then
Console.WriteLine("Optimization was stopped with status " & status)
Exit Sub
End If
Do IIS
Console.WriteLine("The model is infeasible; computing IIS")
model.ComputeIIS()
Console.WriteLine(vbLf & "The following constraint(s) " & _
"cannot be satisfied:")
For Each c As GRBConstr In model.GetConstrs()
If c.Get(GRB.IntAttr.IISConstr) = 1 Then
Console.WriteLine(c.Get(GRB.StringAttr.ConstrName))
End If
Next
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

394

workforce2_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, use IIS iteratively to
find all conflicting constraints.

Imports System
Imports System.Collections.Generic
Imports Gurobi
Class workforce2_vb
Shared Sub Main()
Try
Sample data
Sets of days and workers
Dim Shifts As String() = New String() {"Mon1", "Tue2", "Wed3", "Thu4", _
"Fri5", "Sat6", "Sun7", "Mon8", _
"Tue9", "Wed10", "Thu11", _
"Fri12", "Sat13", "Sun14"}
Dim Workers As String() = New String() {"Amy", "Bob", "Cathy", "Dan", _
"Ed", "Fred", "Gu"}
Dim nShifts As Integer = Shifts.Length
Dim nWorkers As Integer = Workers.Length
Number of workers required for each shift
Dim shiftRequirements As Double() = New Double() {3, 2, 4, 4, 5, 6, _
5, 2, 2, 3, 4, 6, _
7, 5}
Amount each worker is paid to work one shift
Dim pay As Double() = New Double() {10, 12, 10, 8, 8, 9, 11}
Worker availability: 0 if the worker is unavailable for a shift
Dim availability As Double(,) = New Double(,) { _
{0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1}, _
{1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0}, _
{0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, _
{0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, _
{1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1}, _
{1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1}, _
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

395

Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.Set(GRB.StringAttr.ModelName, "assignment")
Assignment variables: x(w)(s) == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP.
Dim x As GRBVar(,) = New GRBVar(nWorkers - 1, nShifts - 1) {}
For w As Integer = 0 To nWorkers - 1
For s As Integer = 0 To nShifts - 1
x(w, s) = model.AddVar(0, availability(w, s), pay(w), _
GRB.CONTINUOUS, _
Workers(w) & "." & Shifts(s))
Next
Next
The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1)
Update model to integrate new variables
model.Update()
Constraint: assign exactly shiftRequirements(s) workers
to each shift s
For s As Integer = 0 To nShifts - 1
Dim lhs As GRBLinExpr = 0
For w As Integer = 0 To nWorkers - 1
lhs += x(w, s)
Next
model.AddConstr(lhs = shiftRequirements(s), Shifts(s))
Next
Optimize
model.Optimize()
Dim status As Integer = model.Get(GRB.IntAttr.Status)
If status = GRB.Status.UNBOUNDED Then
Console.WriteLine("The model cannot be solved " & _
"because it is unbounded")
Exit Sub
End If
If status = GRB.Status.OPTIMAL Then
Console.WriteLine("The optimal objective is " & _
model.Get(GRB.DoubleAttr.ObjVal))
Exit Sub

396

End If
If (status <> GRB.Status.INF_OR_UNBD) AndAlso _
(status <> GRB.Status.INFEASIBLE) Then
Console.WriteLine("Optimization was stopped with status " & status)
Exit Sub
End If
Do IIS
Console.WriteLine("The model is infeasible; computing IIS")
Dim removed As LinkedList(Of String) = New LinkedList(Of String)()
Loop until we reduce to a model that can be solved
While True
model.ComputeIIS()
Console.WriteLine(vbLf & "The following constraint cannot be satisfied:")
For Each c As GRBConstr In model.GetConstrs()
If c.Get(GRB.IntAttr.IISConstr) = 1 Then
Console.WriteLine(c.Get(GRB.StringAttr.ConstrName))
Remove a single constraint from the model
removed.AddFirst(c.Get(GRB.StringAttr.ConstrName))
model.Remove(c)
Exit For
End If
Next
Console.WriteLine()
model.Optimize()
status = model.Get(GRB.IntAttr.Status)
If status = GRB.Status.UNBOUNDED Then
Console.WriteLine("The model cannot be solved " & _
"because it is unbounded")
Exit Sub
End If
If status = GRB.Status.OPTIMAL Then
Exit While
End If
If (status <> GRB.Status.INF_OR_UNBD) AndAlso _
(status <> GRB.Status.INFEASIBLE) Then
Console.WriteLine("Optimization was stopped with status " & _
status)
Exit Sub
End If
End While

397

Console.WriteLine(vbLf & "The following constraints were removed " & _


"to get a feasible LP:")
For Each s As String In removed
Console.Write(s & " ")
Next
Console.WriteLine()
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

398

workforce3_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Assign workers to shifts; each worker may or may not be available on a
particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed.

Imports System
Imports System.Collections.Generic
Imports Gurobi
Class workforce3_vb
Shared Sub Main()
Try
Sample data
Sets of days and workers
Dim Shifts As String() = New String() {"Mon1", "Tue2", "Wed3", "Thu4", _
"Fri5", "Sat6", "Sun7", "Mon8", _
"Tue9", "Wed10", "Thu11", _
"Fri12", "Sat13", "Sun14"}
Dim Workers As String() = New String() {"Amy", "Bob", "Cathy", "Dan", _
"Ed", "Fred", "Gu"}
Dim nShifts As Integer = Shifts.Length
Dim nWorkers As Integer = Workers.Length
Number of workers required for each shift
Dim shiftRequirements As Double() = New Double() {3, 2, 4, 4, 5, 6, _
5, 2, 2, 3, 4, 6, _
7, 5}
Amount each worker is paid to work one shift
Dim pay As Double() = New Double() {10, 12, 10, 8, 8, 9, 11}
Worker availability: 0 if the worker is unavailable for a shift
Dim availability As Double(,) = New Double(,) { _
{0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1}, _
{1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0}, _
{0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, _
{0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, _
{1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1}, _
{1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1}, _
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}
399

Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.Set(GRB.StringAttr.ModelName, "assignment")
Assignment variables: x(w)(s) == 1 if worker w is assigned
to shift s. Since an assignment model always produces integer
solutions, we use continuous variables and solve as an LP.
Dim x As GRBVar(,) = New GRBVar(nWorkers - 1, nShifts - 1) {}
For w As Integer = 0 To nWorkers - 1
For s As Integer = 0 To nShifts - 1
x(w, s) = model.AddVar(0, availability(w, s), pay(w), _
GRB.CONTINUOUS, _
Workers(w) & "." & Shifts(s))
Next
Next
The objective is to minimize the total pay costs
model.Set(GRB.IntAttr.ModelSense, 1)
Update model to integrate new variables
model.Update()
Constraint: assign exactly shiftRequirements(s) workers
to each shift s
Dim reqCts As New LinkedList(Of GRBConstr)()
For s As Integer = 0 To nShifts - 1
Dim lhs As GRBLinExpr = 0
For w As Integer = 0 To nWorkers - 1
lhs += x(w, s)
Next
Dim newCt As GRBConstr = model.AddConstr(lhs = shiftRequirements(s), _
Shifts(s))
reqCts.AddFirst(newCt)
Next
Optimize
model.Optimize()
Dim status As Integer = model.Get(GRB.IntAttr.Status)
If status = GRB.Status.UNBOUNDED Then
Console.WriteLine("The model cannot be solved " & _
"because it is unbounded")
Exit Sub
End If

400

If status = GRB.Status.OPTIMAL Then


Console.WriteLine("The optimal objective is " & _
model.Get(GRB.DoubleAttr.ObjVal))
Exit Sub
End If
If (status <> GRB.Status.INF_OR_UNBD) AndAlso _
(status <> GRB.Status.INFEASIBLE) Then
Console.WriteLine("Optimization was stopped with status " & status)
Exit Sub
End If
Add slack variables to make the model feasible
Console.WriteLine("The model is infeasible; adding slack variables")
Set original objective coefficients to zero
model.SetObjective(New GRBLinExpr())
Add a new slack variable to each shift constraint so that the shifts
can be satisfied
Dim slacks As New LinkedList(Of GRBVar)()
For Each c As GRBConstr In reqCts
Dim col As New GRBColumn()
col.AddTerm(1.0, c)
Dim newvar As GRBVar = model.AddVar(0, GRB.INFINITY, 1.0, _
GRB.CONTINUOUS, col, _
c.Get(GRB.StringAttr.ConstrName) & _
"Slack")
slacks.AddFirst(newvar)
Next
Solve the model with slacks
model.Optimize()
status = model.Get(GRB.IntAttr.Status)
If (status = GRB.Status.INF_OR_UNBD) OrElse _
(status = GRB.Status.INFEASIBLE) OrElse _
(status = GRB.Status.UNBOUNDED) Then
Console.WriteLine("The model with slacks cannot be solved " & _
"because it is infeasible or unbounded")
Exit Sub
End If
If status <> GRB.Status.OPTIMAL Then
Console.WriteLine("Optimization was stopped with status " & status)
Exit Sub
End If

401

Console.WriteLine(vbLf & "Slack values:")


For Each sv As GRBVar In slacks
If sv.Get(GRB.DoubleAttr.X) > 0.000001 Then
Console.WriteLine(sv.Get(GRB.StringAttr.VarName) & " = " & _
sv.Get(GRB.DoubleAttr.X))
End If
Next
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class

402

workforce4_vb.vb

Copyright 2013, Gurobi Optimization, Inc.


Assign workers to shifts; each worker may or may not be available on a
particular day. We use Pareto optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers.

Imports System
Imports Gurobi
Class workforce4_vb
Shared Sub Main()
Try
Sample data
Sets of days and workers
Dim Shifts As String() = New String() {"Mon1", "Tue2", "Wed3", "Thu4", _
"Fri5", "Sat6", "Sun7", "Mon8", _
"Tue9", "Wed10", "Thu11", _
"Fri12", "Sat13", "Sun14"}
Dim Workers As String() = New String() {"Amy", "Bob", "Cathy", "Dan", _
"Ed", "Fred", "Gu"}
Dim nShifts As Integer = Shifts.Length
Dim nWorkers As Integer = Workers.Length
Number of workers required for each shift
Dim shiftRequirements As Double() = New Double() {3, 2, 4, 4, 5, 6, _
5, 2, 2, 3, 4, 6, _
7, 5}
Worker availability: 0 if the worker is unavailable for a shift
Dim availability As Double(,) = New Double(,) { _
{0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1}, _
{1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0}, _
{0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, _
{0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, _
{1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1}, _
{1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1}, _
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}
Model
Dim env As New GRBEnv()
403

Dim model As New GRBModel(env)


model.Set(GRB.StringAttr.ModelName, "assignment")
Assignment variables: x(w)(s) == 1 if worker w is assigned
to shift s. This is no longer a pure assignment model, so we
must use binary variables.
Dim x As GRBVar(,) = New GRBVar(nWorkers - 1, nShifts - 1) {}
For w As Integer = 0 To nWorkers - 1
For s As Integer = 0 To nShifts - 1
x(w, s) = model.AddVar(0, availability(w, s), 0, _
GRB.BINARY, _
Workers(w) & "." & Shifts(s))
Next
Next
Add a new slack variable to each shift constraint so that the
shifts can be satisfied
Dim slacks As GRBVar() = New GRBVar(nShifts - 1) {}
For s As Integer = 0 To nShifts - 1
slacks(s) = _
model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, _
Shifts(s) & "Slack")
Next
Variable to represent the total slack
Dim totSlack As GRBVar = model.AddVar(0, GRB.INFINITY, 0, _
GRB.CONTINUOUS, "totSlack")
Variables to count the total shifts worked by each worker
Dim totShifts As GRBVar() = New GRBVar(nWorkers - 1) {}
For w As Integer = 0 To nWorkers - 1
totShifts(w) = _
model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, _
Workers(w) & "TotShifts")
Next
Update model to integrate new variables
model.Update()
Dim lhs As GRBLinExpr
Constraint: assign exactly shiftRequirements(s) workers
to each shift s, plus the slack
For s As Integer = 0 To nShifts - 1
lhs = 0

404

lhs += slacks(s)
For w As Integer = 0 To nWorkers - 1
lhs += x(w, s)
Next
model.AddConstr(lhs = shiftRequirements(s), Shifts(s))
Next
Constraint: set totSlack equal to the total slack
lhs = 0
For s As Integer = 0 To nShifts - 1
lhs += slacks(s)
Next
model.AddConstr(lhs = totSlack, "totSlack")
Constraint: compute the total number of shifts for each worker
For w As Integer = 0 To nWorkers - 1
lhs = 0
For s As Integer = 0 To nShifts - 1
lhs += x(w, s)
Next
model.AddConstr(lhs = totShifts(w), "totShifts" & Workers(w))
Next
Objective: minimize the total slack
Dim obj As GRBLinExpr = New GRBLinExpr
obj += totSlack
model.SetObjective(obj)
Optimize
Dim status As Integer = _
solveAndPrint(model, totSlack, nWorkers, Workers, totShifts)
If status <> GRB.Status.OPTIMAL Then
Exit Sub
End If
Constrain the slack by setting its upper and lower bounds
totSlack.Set(GRB.DoubleAttr.UB, totSlack.Get(GRB.DoubleAttr.X))
totSlack.Set(GRB.DoubleAttr.LB, totSlack.Get(GRB.DoubleAttr.X))
Variable to count the average number of shifts worked
Dim avgShifts As GRBVar = model.AddVar(0, GRB.INFINITY, 0, _
GRB.CONTINUOUS, "avgShifts")
Variables to count the difference from average for each worker;
note that these variables can take negative values.

405

Dim diffShifts As GRBVar() = New GRBVar(nWorkers - 1) {}


For w As Integer = 0 To nWorkers - 1
diffShifts(w) = _
model.AddVar(-GRB.INFINITY, GRB.INFINITY, 0, _
GRB.CONTINUOUS, Workers(w) & "Diff")
Next
Update model to integrate new variables
model.Update()
Constraint: compute the average number of shifts worked
lhs = 0
For w As Integer = 0 To nWorkers - 1
lhs += totShifts(w)
Next
model.AddConstr(lhs = nWorkers * avgShifts, "avgShifts")
Constraint: compute the difference from the average number of shifts
For w As Integer = 0 To nWorkers - 1
lhs = 0
lhs += totShifts(w)
lhs -= avgShifts
model.AddConstr(lhs = diffShifts(w), Workers(w) & "Diff")
Next
Objective: minimize the sum of the square of the difference
from the average number of shifts worked
Dim qobj As GRBQuadExpr = New GRBQuadExpr
For w As Integer = 0 To nWorkers - 1
qobj += diffShifts(w) * diffShifts(w)
Next
model.SetObjective(qobj)
Optimize
status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts)
If status <> GRB.Status.OPTIMAL Then
Exit Sub
End If
Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)

406

End Try
End Sub
Private Shared Function solveAndPrint(ByVal model As GRBModel, _
ByVal totSlack As GRBVar, _
ByVal nWorkers As Integer, _
ByVal Workers As String(), _
ByVal totShifts As GRBVar()) As Integer
model.Optimize()
Dim status As Integer = model.Get(GRB.IntAttr.Status)
solveAndPrint = status
If (status = GRB.Status.INF_OR_UNBD) OrElse _
(status = GRB.Status.INFEASIBLE) OrElse _
(status = GRB.Status.UNBOUNDED) Then
Console.WriteLine("The model cannot be solved because " & _
"it is infeasible or unbounded")
Exit Function
End If
If status <> GRB.Status.OPTIMAL Then
Console.WriteLine("Optimization was stopped with status " _
& status)
Exit Function
End If
Print total slack and the number of shifts worked for each worker
Console.WriteLine(vbLf & "Total slack required: " & _
totSlack.Get(GRB.DoubleAttr.X))
For w As Integer = 0 To nWorkers - 1
Console.WriteLine(Workers(w) & " worked " & _
totShifts(w).Get(GRB.DoubleAttr.X) & _
" shifts")
Next
Console.WriteLine(vbLf)
End Function
End Class

407

3.6

Python Examples

This section includes source code for all of the Gurobi Python examples. The same source code can
be found in the examples/python directory of the Gurobi distribution.

callback.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

This example reads an LP or a MIP from a file, sets a callback


to monitor the optimization progress, and outputs progress
information to the screen and to the log file. If the input model
is a MIP, the callback aborts the optimization after 10000 nodes have
been explored.

import sys
from gurobipy import *

# Define callback function


def mycallback(model, where):
if where == GRB.callback.PRESOLVE:
# Presolve callback
print Removed, model.cbGet(GRB.callback.PRE_COLDEL), columns and, \
model.cbGet(GRB.callback.PRE_ROWDEL), rows
elif where == GRB.callback.SIMPLEX:
# Simplex callback
itcnt = model.cbGet(GRB.callback.SPX_ITRCNT)
if itcnt - model._lastiter >= 100:
model._lastiter = itcnt
obj = model.cbGet(GRB.callback.SPX_OBJVAL)
pinf = model.cbGet(GRB.callback.SPX_PRIMINF)
dinf = model.cbGet(GRB.callback.SPX_DUALINF)
pert = model.cbGet(GRB.callback.SPX_ISPERT)
if pert == 0:
ch =
elif pert == 1:
ch = S
else:
ch = P
print int(itcnt), obj, ch, pinf, dinf
elif where == GRB.callback.MIP:
408

# General MIP callback


nodecnt = model.cbGet(GRB.callback.MIP_NODCNT)
if nodecnt - model._lastnode >= 100:
model._lastnode = nodecnt
objbst = model.cbGet(GRB.callback.MIP_OBJBST)
objbnd = model.cbGet(GRB.callback.MIP_OBJBND)
print int(nodecnt), objbst, objbnd
if nodecnt > model._mynodelimit:
model.terminate()
elif where == GRB.callback.MIPSOL:
# MIP solution callback
obj
= model.cbGet(GRB.callback.MIPSOL_OBJ)
nodecnt = int(model.cbGet(GRB.callback.MIPSOL_NODCNT))
print *** New solution at node, nodecnt, objective, obj
print model.cbGetSolution(model.getVars())
elif where == GRB.callback.MIPNODE:
# MIP node callback
print *** New node
if model.cbGet(GRB.callback.MIPNODE_STATUS) == GRB.status.OPTIMAL:
x = model.cbGetNodeRel(model.getVars())
model.cbSetSolution(model.getVars(), x)
if len(sys.argv) < 2:
print Usage: callback.py filename
quit()
# Read and solve model
model = read(sys.argv[1])
# Pass data into my callback function
model._mynodelimit = 10000
model._lastnode = -1
model._lastiter = -1
model.params.heuristics = 0
model.optimize(mycallback)

409

custom.py
#
#
#
#
#
#
#
#

Copyright 2013, Gurobi Optimization, Inc.


Interactive shell customization example
Define a set of customizations for the Gurobi shell.
Type from custom import * to import them into your shell.

from gurobipy import *

# custom read command --- change directory as appropriate


def myread(name):
return read(/home/jones/models/ + name)

# simple termination callback


def mycallback(model, where):
if where == GRB.callback.MIP:
time = model.cbGet(GRB.callback.RUNTIME)
best = model.cbGet(GRB.callback.MIP_OBJBST)
if time > 10 and best < GRB.INFINITY:
model.terminate()

# custom optimize() function that uses callback


def myopt(model):
model.optimize(mycallback)

410

dense.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#
#
#
#
#

This example formulates and solves the following simple QP model:


minimize
subject to

x + y + x^2 + x*y + y^2 + y*z + z^2


x + 2 y + 3 z >= 4
x +
y
>= 1

The example illustrates the use of dense matrices to store A and Q


(and dense vectors for the other relevant data). We dont recommend
that you use dense matrices, but this example may be helpful if you
already have your data in this format.

import sys
from gurobipy import *
def dense_optimize(rows, cols, c, Q, A, sense, rhs, lb, ub, vtype,
solution):
model = Model()
# Add variables to model
for j in range(cols):
model.addVar(lb=lb[j], ub=ub[j], vtype=vtype[j])
model.update()
vars = model.getVars()
# Populate A matrix
for i in range(rows):
expr = LinExpr()
for j in range(cols):
if A[i][j] != 0:
expr += A[i][j]*vars[j]
model.addConstr(expr, sense[i], rhs[i])
# Populate objective
obj = QuadExpr()
for i in range(cols):
for j in range(cols):
if Q[i][j] != 0:
obj += Q[i][j]*vars[i]*vars[j]
for j in range(cols):
411

if c[j] != 0:
obj += c[j]*vars[j]
model.setObjective(obj)
# Write model to a file
model.update()
model.write(dense.lp)
# Solve
model.optimize()
if model.status == GRB.OPTIMAL:
x = model.getAttr(x, vars)
for i in range(cols):
solution[i] = x[i]
return True
else:
return False

# Put model data into dense matrices


c = [1, 1, 0]
Q = [[1, 1, 0], [0, 1, 1], [0, 0, 1]]
A = [[1, 2, 3], [1, 1, 0]]
sense = [GRB.GREATER_EQUAL, GRB.GREATER_EQUAL]
rhs = [4, 1]
lb = [0, 0, 0]
ub = [GRB.INFINITY, GRB.INFINITY, GRB.INFINITY]
vtype = [GRB.CONTINUOUS, GRB.CONTINUOUS, GRB.CONTINUOUS]
sol = [0]*3
# Optimize
success = dense_optimize(2, 3, c, Q, A, sense, rhs, lb, ub, vtype, sol)
if success:
print x: , sol[0], y: , sol[1], z: , sol[2]

412

diet.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# Solve the classic diet model, showing how to add constraints
# to an existing model.
from gurobipy import *
# Nutrition guidelines, based on
# USDA Dietary Guidelines for Americans, 2005
# http://www.health.gov/DietaryGuidelines/dga2005/
categories, minNutrition, maxNutrition = multidict({
calories: [1800, 2200],
protein: [91, GRB.INFINITY],
fat:
[0, 65],
sodium:
[0, 1779] })
foods, cost = multidict({
hamburger: 2.49,
chicken:
2.89,
hot dog:
1.50,
fries:
1.89,
macaroni: 2.09,
pizza:
1.99,
salad:
2.49,
milk:
0.89,
ice cream: 1.59 })
# Nutrition values for the foods
nutritionValues = {
(hamburger, calories): 410,
(hamburger, protein): 24,
(hamburger, fat):
26,
(hamburger, sodium):
730,
(chicken,
calories): 420,
(chicken,
protein): 32,
(chicken,
fat):
10,
(chicken,
sodium):
1190,
(hot dog,
calories): 560,
(hot dog,
protein): 20,
(hot dog,
fat):
32,
(hot dog,
sodium):
1800,
413

(fries,
(fries,
(fries,
(fries,
(macaroni,
(macaroni,
(macaroni,
(macaroni,
(pizza,
(pizza,
(pizza,
(pizza,
(salad,
(salad,
(salad,
(salad,
(milk,
(milk,
(milk,
(milk,
(ice cream,
(ice cream,
(ice cream,
(ice cream,

calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):

380,
4,
19,
270,
320,
12,
10,
930,
320,
15,
12,
820,
320,
31,
12,
1230,
100,
8,
2.5,
125,
330,
8,
10,
180 }

# Model
m = Model("diet")
# Create decision variables for the nutrition information,
# which we limit via bounds
nutrition = {}
for c in categories:
nutrition[c] = m.addVar(lb=minNutrition[c], ub=maxNutrition[c], name=c)
# Create decision variables for the foods to buy
buy = {}
for f in foods:
buy[f] = m.addVar(obj=cost[f], name=f)
# The objective is to minimize the costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()

414

# Nutrition constraints
for c in categories:
m.addConstr(
quicksum(nutritionValues[f,c] * buy[f] for f in foods) == nutrition[c],
c)

def printSolution():
if m.status == GRB.status.OPTIMAL:
print \nCost:, m.objVal
print \nBuy:
buyx = m.getAttr(x, buy)
nutritionx = m.getAttr(x, nutrition)
for f in foods:
if buy[f].x > 0.0001:
print f, buyx[f]
print \nNutrition:
for c in categories:
print c, nutritionx[c]
else:
print No solution
# Solve
m.optimize()
printSolution()
print \nAdding constraint: at most 6 servings of dairy
m.addConstr(buy[milk] + buy[ice cream] <= 6, "limit_dairy")
# Solve
m.optimize()
printSolution()

415

diet2.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#

Separate the model (dietmodel.py) from the data file (diet2.py), so


that the model can be solved with different data files.
Nutrition guidelines, based on
USDA Dietary Guidelines for Americans, 2005
http://www.health.gov/DietaryGuidelines/dga2005/

from gurobipy import *


categories, minNutrition, maxNutrition = multidict({
calories: [1800, 2200],
protein: [91, GRB.INFINITY],
fat:
[0, 65],
sodium:
[0, 1779] })
foods, cost = multidict({
hamburger: 2.49,
chicken:
2.89,
hot dog:
1.50,
fries:
1.89,
macaroni: 2.09,
pizza:
1.99,
salad:
2.49,
milk:
0.89,
ice cream: 1.59 })
# Nutrition values for the foods
nutritionValues = {
(hamburger, calories): 410,
(hamburger, protein): 24,
(hamburger, fat):
26,
(hamburger, sodium):
730,
(chicken,
calories): 420,
(chicken,
protein): 32,
(chicken,
fat):
10,
(chicken,
sodium):
1190,
(hot dog,
calories): 560,
(hot dog,
protein): 20,
(hot dog,
fat):
32,
(hot dog,
sodium):
1800,
416

(fries,
(fries,
(fries,
(fries,
(macaroni,
(macaroni,
(macaroni,
(macaroni,
(pizza,
(pizza,
(pizza,
(pizza,
(salad,
(salad,
(salad,
(salad,
(milk,
(milk,
(milk,
(milk,
(ice cream,
(ice cream,
(ice cream,
(ice cream,

calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):
calories):
protein):
fat):
sodium):

380,
4,
19,
270,
320,
12,
10,
930,
320,
15,
12,
820,
320,
31,
12,
1230,
100,
8,
2.5,
125,
330,
8,
10,
180 }

import dietmodel
dietmodel.solve(categories, minNutrition, maxNutrition,
foods, cost, nutritionValues)

417

diet3.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

Use a SQLite database with the diet model (dietmodel.py). The database
(diet.db) can be recreated using the included SQL script (diet.sql).
Note that this example reads an external data file (..\data\diet.db).
As a result, it must be run from the distribution directory.

import os
import sqlite3
from gurobipy import *
con = sqlite3.connect(os.path.join(.., data, diet.db))
cur = con.cursor()
cur.execute(select category,minnutrition,maxnutrition from categories)
result = cur.fetchall()
categories, minNutrition, maxNutrition = multidict(
(cat,[minv,maxv]) for cat,minv,maxv in result)
cur.execute(select food,cost from foods)
result = cur.fetchall()
foods, cost = multidict(result)
cur.execute(select food,category,value from nutrition)
result = cur.fetchall()
nutritionValues = dict(((f,c),v) for f,c,v in result)
con.close()
import dietmodel
dietmodel.solve(categories, minNutrition, maxNutrition,
foods, cost, nutritionValues)

418

diet4.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#
#
#
#

Read diet model data from an Excel spreadsheet (diet.xls).


Pass the imported data into the diet model (dietmodel.py).
Note that this example reads an external data file (..\data\diet.xls).
As a result, it must be run from the distribution directory.
This example requires Python package xlrd, which isnt included
in most Python distributions. You can obtain it from
http://pypi.python.org/pypi/xlrd.

import os
import xlrd
book = xlrd.open_workbook(os.path.join("..", "data", "diet.xls"))
sh = book.sheet_by_name("Categories")
categories = []
minNutrition = {}
maxNutrition = {}
i = 1
while True:
try:
c = sh.cell_value(i, 0)
categories.append(c)
minNutrition[c] = sh.cell_value(i,1)
maxNutrition[c] = sh.cell_value(i,2)
i = i + 1
except IndexError:
break
sh = book.sheet_by_name("Foods")
foods = []
cost = {}
i = 1
while True:
try:
f = sh.cell_value(i, 0)
foods.append(f)
cost[f] = sh.cell_value(i,1)
i = i + 1
419

except IndexError:
break
sh = book.sheet_by_name("Nutrition")
nutritionValues = {}
for i in range(len(foods)):
for j in range(len(categories)):
nutritionValues[foods[i],categories[j]] = sh.cell_value(i+1,j+1)
import dietmodel
dietmodel.solve(categories, minNutrition, maxNutrition,
foods, cost, nutritionValues)

420

dietmodel.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

Solve the classic diet model. This file implements


a function that formulates and solves the model,
but it contains no model data. The data is
passed in by the calling program. Run example diet2.py,
diet3.py, or diet4.py to invoke this function.

from gurobipy import *

def solve(categories, minNutrition, maxNutrition, foods, cost,


nutritionValues):
# Model
m = Model("diet")
# Create decision variables for the nutrition information,
# which we limit via bounds
nutrition = {}
for c in categories:
nutrition[c] = m.addVar(lb=minNutrition[c], ub=maxNutrition[c], name=c)
# Create decision variables for the foods to buy
buy = {}
for f in foods:
buy[f] = m.addVar(obj=cost[f], name=f)
# The objective is to minimize the costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()
# Nutrition constraints
for c in categories:
m.addConstr(
quicksum(nutritionValues[f,c] * buy[f] for f in foods) ==
nutrition[c], c)
def printSolution():
if m.status == GRB.status.OPTIMAL:
print \nCost:, m.objVal
421

print \nBuy:
for f in foods:
if buy[f].x > 0.0001:
print f, buy[f].x
print \nNutrition:
for c in categories:
print c, nutrition[c].x
else:
print No solution
# Solve
m.optimize()
printSolution()
print \nAdding constraint: at most 6 servings of dairy
m.addConstr(buy[milk] + buy[ice cream] <= 6, "limit_dairy")
# Solve
m.optimize()
printSolution()

422

facility.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#
#
#
#
#
#

Facility location: a company currently ships its product from 5 plants


to 4 warehouses. It is considering closing some plants to reduce
costs. What plant(s) should the company close, in order to minimize
transportation and fixed costs?
Note that this example uses lists instead of dictionaries. Since
it does not work with sparse data, lists are a reasonable option.
Based on an example from Frontline Systems:
http://www.solver.com/disfacility.htm
Used with permission.

from gurobipy import *


# Warehouse demand in thousands of units
demand = [15, 18, 14, 20]
# Plant capacity in thousands of units
capacity = [20, 22, 17, 19, 18]
# Fixed costs for each plant
fixedCosts = [12000, 15000, 17000, 13000, 16000]
# Transportation costs per
transCosts = [[4000, 2000,
[2500, 2600,
[1200, 1800,
[2200, 2600,

thousand units
3000, 2500, 4500],
3400, 3000, 4000],
2600, 4100, 3000],
3100, 3700, 3200]]

# Range of plants and warehouses


plants = range(len(capacity))
warehouses = range(len(demand))
# Model
m = Model("facility")
# Plant open decision variables: open[p] == 1 if plant p is open.
open = []
for p in plants:
open.append(m.addVar(vtype=GRB.BINARY, name="Open%d" % p))
423

# Transportation decision variables: how much to transport from


# a plant p to a warehouse w
transport = []
for w in warehouses:
transport.append([])
for p in plants:
transport[w].append(m.addVar(obj=transCosts[w][p],
name="Trans%d.%d" % (p, w)))
# The objective is to minimize the total fixed and variable costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()
# Set optimization objective - minimize sum of fixed costs
m.setObjective(quicksum([fixedCosts[p]*open[p] for p in plants]))
# Production constraints
# Note that the right-hand limit sets the production to zero if the plant
# is closed
for p in plants:
m.addConstr(
quicksum(transport[w][p] for w in warehouses) <= capacity[p] * open[p],
"Capacity%d" % p)
# Demand constraints
for w in warehouses:
m.addConstr(quicksum(transport[w][p] for p in plants) == demand[w],
"Demand%d" % w)
# Guess at the starting point: close the plant with the highest fixed costs;
# open all others
# First, open all plants
for p in plants:
open[p].start = 1.0
# Now close the plant with the highest fixed cost
print Initial guess:
maxFixed = max(fixedCosts)
for p in plants:
if fixedCosts[p] == maxFixed:
open[p].start = 0.0

424

print Closing plant, p


break
print
# Use barrier to solve root relaxation
m.params.method = 2
# Solve
m.optimize()
# Print solution
print \nTOTAL COSTS:, m.objVal
print SOLUTION:
for p in plants:
if open[p].x == 1.0:
print Plant, p, open:
for w in warehouses:
if transport[w][p].x > 0:
print Transport, transport[w][p].x, units to warehouse, w
else:
print Plant, p, closed!

425

feasopt.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#
#
#
#

This example reads a MIP model from a file, adds artificial


variables to each constraint, and then minimizes the sum of the
artificial variables. A solution with objective zero corresponds
to a feasible solution to the input model.
We can also use FeasRelax feature to do it. In this example, we
use minrelax=1, i.e. optimizing the returned model finds a solution
that minimizes the original objective, but only from among those
solutions that minimize the sum of the artificial variables.

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: feasopt.py filename
quit()
feasmodel = gurobi.read(sys.argv[1])
#create a copy to use FeasRelax feature later
feasmodel1 = feasmodel.copy()
# clear objective
feasmodel.setObjective(0.0)
# add slack variables
for c in feasmodel.getConstrs():
sense = c.sense
if sense != >:
feasmodel.addVar(obj=1.0, name="ArtN_" + c.constrName,
column=Column([-1], [c]))
if sense != <:
feasmodel.addVar(obj=1.0, name="ArtP_" + c.constrName,
column=Column([1], [c]))
feasmodel.update()

426

# optimize modified model


feasmodel.write(feasopt.lp)
feasmodel.optimize()
# use FeasRelax feature
feasmodel1.feasRelaxS(0, True, False, True);
feasmodel1.write("feasopt1.lp");
feasmodel1.optimize();

427

fixanddive.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

Implement a simple MIP heuristic. Relax the model,


sort variables based on fractionality, and fix the 25% of
the fractional variables that are closest to integer variables.
Repeat until either the relaxation is integer feasible or
linearly infeasible.

import sys
from gurobipy import *

# Comparison function used to sort variable list based on relaxation


# fractionality
def compare(v1, v2):
sol1 = v1.x
sol2 = v2.x
frac1 = abs(sol1-int(sol1+0.5))
frac2 = abs(sol2-int(sol2+0.5))
if frac1 <= frac2:
return -1
else:
return +1

if len(sys.argv) < 2:
print Usage: fixanddive.py filename
quit()
# Read model
model = gurobi.read(sys.argv[1])
# Collect integer variables and relax them
intvars = []
for v in model.getVars():
if v.vType != GRB.CONTINUOUS:
intvars += [v]
v.vType = GRB.CONTINUOUS
model.params.outputFlag = 0
428

model.optimize()

# Perform multiple iterations. In each iteration, identify the first


# quartile of integer variables that are closest to an integer value in the
# relaxation, fix them to the nearest integer, and repeat.
for iter in range(1000):
# create a list of fractional variables, sorted in order of increasing
# distance from the relaxation solution to the nearest integer value
fractional = []
for v in intvars:
sol = v.x
if abs(sol - int(sol+0.5)) > 1e-5:
fractional += [v]
fractional.sort(compare)
print Iteration, iter, , obj , model.objVal, , fractional,
print len(fractional)
if len(fractional) == 0:
print Found feasible solution - objective, model.objVal
break

# Fix the first quartile to the nearest integer value


nfix = max(len(fractional)/4, 1)
for i in range(nfix):
v = fractional[i]
fixval = int(v.x+0.5)
v.lb = fixval
v.ub = fixval
print Fix, v.varName, to, fixval, ( rel, v.x, )
model.optimize()
# Check optimization result
if model.status != GRB.status.OPTIMAL:
print Relaxation is infeasible
break

429

lp.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

This example reads an LP model from a file and solves it.


If the model is infeasible or unbounded, the example turns off
presolve and solves the model again. If the model is infeasible,
the example computes an Irreducible Infeasible Subsystem (IIS),
and writes it to a file

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: lp.py filename
quit()
# Read and solve model
model = read(sys.argv[1])
model.optimize()
if model.status == GRB.status.INF_OR_UNBD:
# Turn presolve off to determine whether model is infeasible
# or unbounded
model.setParam(GRB.param.presolve, 0)
model.optimize()
if model.status == GRB.status.OPTIMAL:
print Optimal objective:, model.objVal
model.write(model.sol)
exit(0)
elif model.status != GRB.status.INFEASIBLE:
print Optimization was stopped with status, model.status
exit(0)

# Model is infeasible - compute an Irreducible Infeasible Subsystem (IIS)


print
print "Model is infeasible"
model.computeIIS()
model.write("model.ilp")
print "IIS written to file model.ilp"
430

lpmethod.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# Solve a model with different values of the Method parameter;
# show which value gives the shortest solve time.
import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: lpmethod.py filename
quit()
# Read model
m = read(sys.argv[1])
# Solve the model with different values of Method
bestTime = m.params.timeLimit
bestMethod = -1
for i in range(3):
m.reset()
m.params.method = i
m.optimize()
if m.status == GRB.status.OPTIMAL:
bestTime = m.Runtime
bestMethod = i
# Reduce the TimeLimit parameter to save time with other methods
m.params.timeLimit = bestTime
# Report which method was fastest
if bestMethod == -1:
print Unable to solve this model
else:
print Solved in, bestTime, seconds with Method:, bestMethod

431

lpmod.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

This example reads an LP model from a file and solves it.


If the model can be solved, then it finds the smallest positive variable,
sets its upper bound to zero, and resolves the model two ways:
first with an advanced start, then without an advanced start
(i.e. from scratch).

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: lpmod.py filename
quit()
# Read model and determine whether it is an LP
model = read(sys.argv[1])
if model.isMIP == 1:
print The model is not a linear program
exit(1)
model.optimize()
status = model.status
if status == GRB.status.INF_OR_UNBD or status == GRB.status.INFEASIBLE \
or status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is infeasible or unbounded
exit(1)
if status != GRB.status.OPTIMAL:
print Optimization was stopped with status, status
exit(0)
# Find the smallest variable value
minVal = GRB.INFINITY
for v in model.getVars():
if v.x > 0.0001 and v.x < minVal and v.lb == 0.0:
minVal = v.x
minVar = v

432

print \n*** Setting, minVar.varName, from, minVal, to zero ***\n


minVar.ub = 0.0
# Solve from this starting point
model.optimize()
# Save iteration & time info
warmCount = model.IterCount
warmTime = model.Runtime
# Reset the model and resolve
print \n*** Resetting and solving without an advanced start ***\n
model.reset()
model.optimize()
coldCount = model.IterCount
coldTime = model.Runtime
print
print *** Warm start:, warmCount, iterations,, warmTime, seconds
print *** Cold start:, coldCount, iterations,, coldTime, seconds

433

mip1.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# This example formulates and solves the following simple MIP model:
# maximize
#
x +
y + 2 z
# subject to
#
x + 2 y + 3 z <= 4
#
x +
y
>= 1
# x, y, z binary
from gurobipy import *
try:
# Create a new model
m = Model("mip1")
#
x
y
z

Create variables
= m.addVar(vtype=GRB.BINARY, name="x")
= m.addVar(vtype=GRB.BINARY, name="y")
= m.addVar(vtype=GRB.BINARY, name="z")

# Integrate new variables


m.update()
# Set objective
m.setObjective(x + y + 2 * z, GRB.MAXIMIZE)
# Add constraint: x + 2 y + 3 z <= 4
m.addConstr(x + 2 * y + 3 * z <= 4, "c0")
# Add constraint: x + y >= 1
m.addConstr(x + y >= 1, "c1")
m.optimize()
for v in m.getVars():
print v.varName, v.x
print Obj:, m.objVal

434

except GurobiError:
print Error reported

435

mip2.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#

This example reads a MIP model from a file, solves it and prints
the objective values from all feasible solutions generated while
solving the MIP. Then it creates the associated fixed model and
solves that model.

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: mip2.py filename
quit()
# Read and solve model
model = read(sys.argv[1])
if model.isMIP == 0:
print Model is not a MIP
exit(0)
model.optimize()
if model.status == GRB.status.OPTIMAL:
print Optimal objective:, model.objVal
elif model.status == GRB.status.INF_OR_UNBD:
print Model is infeasible or unbounded
exit(0)
elif model.status == GRB.status.INFEASIBLE:
print Model is infeasible
exit(0)
elif model.status == GRB.status.UNBOUNDED:
print Model is unbounded
exit(0)
else:
print Optimization ended with status, model.status
exit(0)
# Iterate over the solutions and compute the objectives
model.params.outputFlag = 0
print
436

for k in range(model.solCount):
model.params.solutionNumber = k
objn = 0
for v in model.getVars():
objn += v.obj * v.xn
print Solution, k, has objective:, objn
print
model.params.outputFlag = 1
fixed = model.fixed()
fixed.params.presolve = 0
fixed.optimize()
if fixed.status != GRB.status.OPTIMAL:
print "Error: fixed model isnt optimal"
exit(1)
diff = model.objVal - fixed.objVal
if abs(diff) > 1e-6 * (1.0 + abs(model.objVal)):
print Error: objective values are different
exit(1)
# Print values of nonzero variables
for v in fixed.getVars():
if v.x != 0:
print v.varName, v.x

437

netflow.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#
#
#

Solve a multi-commodity flow problem. Two products (Pencils and Pens)


are produced in 2 cities (Detroit and Denver) and must be sent to
warehouses in 3 cities (Boston, New York, and Seattle) to
satisfy demand (inflow[h,i]).
Flows on the transportation network must respect arc capacity constraints
(capacity[i,j]). The objective is to minimize the sum of the arc
transportation costs (cost[i,j]).

from gurobipy import *


# Model data
commodities = [Pencils, Pens]
nodes = [Detroit, Denver, Boston, New York, Seattle]
arcs, capacity = multidict({
(Detroit, Boston):
100,
(Detroit, New York): 80,
(Detroit, Seattle): 120,
(Denver, Boston):
120,
(Denver, New York): 120,
(Denver, Seattle): 120 })
arcs = tuplelist(arcs)
cost = {
(Pencils,
(Pencils,
(Pencils,
(Pencils,
(Pencils,
(Pencils,
(Pens,
(Pens,
(Pens,
(Pens,
(Pens,
(Pens,
inflow = {
438

Detroit,
Detroit,
Detroit,
Denver,
Denver,
Denver,
Detroit,
Detroit,
Detroit,
Denver,
Denver,
Denver,

Boston):
New York):
Seattle):
Boston):
New York):
Seattle):
Boston):
New York):
Seattle):
Boston):
New York):
Seattle):

10,
20,
60,
40,
40,
30,
20,
20,
80,
60,
70,
30 }

(Pencils,
(Pencils,
(Pencils,
(Pencils,
(Pencils,
(Pens,
(Pens,
(Pens,
(Pens,
(Pens,

Detroit):
Denver):
Boston):
New York):
Seattle):
Detroit):
Denver):
Boston):
New York):
Seattle):

50,
60,
-50,
-50,
-10,
60,
40,
-40,
-30,
-30 }

# Create optimization model


m = Model(netflow)
# Create variables
flow = {}
for h in commodities:
for i,j in arcs:
flow[h,i,j] = m.addVar(ub=capacity[i,j], obj=cost[h,i,j],
name=flow_%s_%s_%s % (h, i, j))
m.update()
# Arc capacity constraints
for i,j in arcs:
m.addConstr(quicksum(flow[h,i,j] for h in commodities) <= capacity[i,j],
cap_%s_%s % (i, j))
# Flow conservation constraints
for h in commodities:
for j in nodes:
m.addConstr(
quicksum(flow[h,i,j] for i,j in arcs.select(*,j)) +
inflow[h,j] ==
quicksum(flow[h,j,k] for j,k in arcs.select(j,*)),
node_%s_%s % (h, j))
# Compute optimal solution
m.optimize()
# Print solution
if m.status == GRB.status.OPTIMAL:
solution = m.getAttr(x, flow)
for h in commodities:
print \nOptimal flows for, h, :
for i,j in arcs:

439

if solution[h,i,j] > 0:
print i, ->, j, :, solution[h,i,j]

440

params.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

Use parameters that are associated with a model.


A MIP is solved for 5 seconds with different sets of parameters.
The one with the smallest MIP gap is selected, and the optimization
is resumed until the optimal solution is found.

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: params.py filename
quit()

# Simple function to determine the MIP gap


def gap(model):
if model.solCount == 0 or abs(model.objVal) < 1e-6:
return GRB.INFINITY
return abs(model.objBound - model.objVal)/abs(model.objVal)
# Read model and verify that it is a MIP
base = read(sys.argv[1])
if base.isMIP == 0:
print The model is not an integer program
exit(1)
# Set a 5 second time limit
base.params.timeLimit = 5
# Now solve the model with different values of MIPFocus
bestGap = GRB.INFINITY
bestModel = None
for i in range(4):
m = base.copy()
m.params.MIPFocus = i
m.optimize()
if bestModel == None or bestGap > gap(m):
bestModel = m
bestGap = gap(bestModel)

441

# Finally, reset the time limit and continue to solve the


# best model to optimality
bestModel.params.timeLimit = "default"
bestModel.optimize()
print Solved with MIPFocus:, bestModel.params.MIPFocus

442

qcp.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# This example formulates and solves the following simple QCP model:
#
maximize
x
#
subject to x + y + z = 1
#
x^2 + y^2 <= z^2 (second-order cone)
#
x^2 <= yz
(rotated second-order cone)
from gurobipy import *
# Create a new model
m = Model("qcp")
#
x
y
z

Create variables
= m.addVar(name="x")
= m.addVar(name="y")
= m.addVar(name="z")

# Integrate new variables


m.update()
# Set objective: x
obj = 1.0*x
m.setObjective(obj, GRB.MAXIMIZE)
# Add constraint: x + y + z = 1
m.addConstr(x + y + z == 1, "c0")
# Add second-order cone: x^2 + y^2 <= z^2
m.addQConstr(x*x + y*y <= z*z, "qc0")
# Add rotated cone: x^2 <= yz
m.addQConstr(x*x <= y*z, "qc1")
m.optimize()
for v in m.getVars():
print v.varName, v.x
print Obj:, obj.getValue()

443

qp.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# This example formulates and solves the following simple QP model:
# minimize
#
x^2 + x*y + y^2 + y*z + z^2 + 2 x
# subject to
#
x + 2 y + 3 z >= 4
#
x +
y
>= 1
#
# It solves it once as a continuous model, and once as an integer model.
from gurobipy import *
# Create a new model
m = Model("qp")
#
x
y
z

Create variables
= m.addVar(ub=1.0, name="x")
= m.addVar(ub=1.0, name="y")
= m.addVar(ub=1.0, name="z")

# Integrate new variables


m.update()
# Set objective: x^2 + x*y + y^2 + y*z + z^2 + 2 x
obj = x*x + x*y + y*y + y*z + z*z + 2*x
m.setObjective(obj)
# Add constraint: x + 2 y + 3 z <= 4
m.addConstr(x + 2 * y + 3 * z >= 4, "c0")
# Add constraint: x + y >= 1
m.addConstr(x + y >= 1, "c1")
m.optimize()
for v in m.getVars():
print v.varName, v.x
print Obj:, obj.getValue()
x.vType = GRB.INTEGER
444

y.vType = GRB.INTEGER
z.vType = GRB.INTEGER
m.optimize()
for v in m.getVars():
print v.varName, v.x
print Obj:, obj.getValue()

445

sensitivity.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# Simple MIP sensitivity analysis example.
# For each integer variable, fix it to its lower and upper bound
# and check the impact on the objective.
import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: sensitivity.py filename
quit()

a = gurobi.read(sys.argv[1])
a.optimize()
a.params.outputFlag = 0
# Extract variables from model
avars = a.getVars()
# Iterate through binary variables in model
for i in range(len(avars)):
v = avars[i]
if v.vType == GRB.BINARY:
# Create clone and fix variable
b = a.copy()
bv = b.getVars()[i]
if v.x - v.lb < 0.5:
bv.lb = bv.ub
else:
bv.ub = bv.lb
b.optimize()
if b.status == GRB.status.OPTIMAL:
objchg = b.objVal - a.objVal
if objchg < 0:
446

objchg = 0
print Objective sensitivity for variable, v.varName, is, objchg
else:
print Objective sensitivity for variable, v.varName, \
is infinite

447

sos.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# This example creates a very simple Special Ordered Set (SOS) model.
# The model consists of 3 continuous variables, no linear constraints,
# and a pair of SOS constraints of type 1.
from gurobipy import *
try:
# Create a new model
model = Model("sos")
# Create variables
x0 = model.addVar(ub=1.0, name="x0")
x1 = model.addVar(ub=1.0, name="x1")
x2 = model.addVar(ub=2.0, name="x2")
# Integrate new variables
model.update()
# Set objective
model.setObjective(2 * x0 + x1 + x2, GRB.MAXIMIZE)
# Add first SOS: x0 = 0 or x1 = 0
model.addSOS(GRB.SOS_TYPE1, [x0, x1], [1, 2])
# Add second SOS: x0 = 0 or x2 = 0
model.addSOS(GRB.SOS_TYPE1, [x0, x2], [1, 2])
model.optimize()
for v in model.getVars():
print v.varName, v.x
print Obj:, model.objVal
except GurobiError:
448

print Encountered an error

449

sudoku.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# Sudoku example.
#
#
#
#
#
#
#
#
#
#
#

The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid
of 3x3 grids. Each cell in the grid must take a value from 0 to 9.
No two grid cells in the same row, column, or 3x3 subgrid may take the
same value.
In the MIP formulation, binary variables x[i,j,v] indicate whether
cell <i,j> takes value v. The constraints are as follows:
1. Each cell must take exactly one value (sum_v x[i,j,v] = 1)
2. Each value is used exactly once per row (sum_i x[i,j,v] = 1)
3. Each value is used exactly once per column (sum_j x[i,j,v] = 1)
4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1)

import sys
import math
from gurobipy import *
if len(sys.argv) < 2:
print Usage: sudoku.py filename
quit()
f = open(sys.argv[1])
grid = f.read().split()
n = len(grid[0])
s = int(math.sqrt(n))

# 3-D array of variables will be indexed by (i,j,v) tuples


vars = {}

# Create our 3-D array of model variables


model = Model(sudoku)
for i in range(n):
450

for j in range(n):
for v in range(n):
vars[i,j,v] = model.addVar(vtype=GRB.BINARY,
name=G_+ str(i)+_+str(j)+_+str(v))
# Update model to integrate new variables
model.update()

# Fix variables associated with cells whose values are pre-specified


for i in range(n):
for j in range(n):
if grid[i][j] != .:
v = int(grid[i][j]) - 1
model.addConstr(vars[i,j,v] == 1, Fix_ + str(i) + _ + str(j))
# Each cell must take one value
for i in range(n):
for j in range(n):
model.addConstr(quicksum([vars[i,j,v] for v in range(n)]) == 1,
V_ + str(i) + _ + str(j))
# Each value appears once per row
for i in range(n):
for v in range(n):
model.addConstr(quicksum([vars[i,j,v] for j in range(n)]) == 1,
R_ + str(i) + _ + str(v))
# Each value appears once per column
for j in range(n):
for v in range(n):
model.addConstr(quicksum([vars[i,j,v] for i in range(n)]) == 1,
C_ + str(j) + _ + str(v))
# Each value appears once per subgrid
for v in range(n):
for i0 in range(s):
for j0 in range(s):
subgrid = [vars[i,j,v] for i in range(i0*s, (i0+1)*s)

451

for j in range(j0*s, (j0+1)*s)]


model.addConstr(quicksum(subgrid) == 1,
Sub_ + str(i0) + _ + str(j0) + _ + str(v))
model.optimize()
model.write(sudoku.lp)
print
print Solution:
print
# Retrieve optimization result
solution = model.getAttr(X, vars)
for i in range(n):
sol =
for j in range(n):
for v in range(n):
if solution[i,j,v] > 0.5:
sol += str(v+1)
print sol

452

tsp.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#
#

Solve a traveling salesman problem on a randomly generated set of


points using lazy constraints.
The base MIP model only includes
degree-2 constraints, requiring each node to have exactly
two incident edges. Solutions to this model may contain subtours tours that dont visit every city. The lazy constraint callback
adds new constraints to cut them off.

import sys
import math
import random
from gurobipy import *

# Callback - use lazy constraints to eliminate sub-tours


def subtourelim(model, where):
if where == GRB.callback.MIPSOL:
selected = []
# make a list of edges selected in the solution
for i in range(n):
sol = model.cbGetSolution([model._vars[i,j] for j in range(n)])
selected += [(i,j) for j in range(n) if sol[j] > 0.5]
# find the shortest cycle in the selected edge list
tour = subtour(selected)
if len(tour) < n:
# add a subtour elimination constraint
expr = 0
for i in range(len(tour)):
for j in range(i+1, len(tour)):
expr += model._vars[tour[i], tour[j]]
model.cbLazy(expr <= len(tour)-1)

# Euclidean distance between two points


def distance(points, i, j):
dx = points[i][0] - points[j][0]
dy = points[i][1] - points[j][1]
return math.sqrt(dx*dx + dy*dy)

453

# Given a list of edges, finds the shortest subtour


def subtour(edges):
visited = [False]*n
cycles = []
lengths = []
selected = [[] for i in range(n)]
for x,y in edges:
selected[x].append(y)
while True:
current = visited.index(False)
thiscycle = [current]
while True:
visited[current] = True
neighbors = [x for x in selected[current] if not visited[x]]
if len(neighbors) == 0:
break
current = neighbors[0]
thiscycle.append(current)
cycles.append(thiscycle)
lengths.append(len(thiscycle))
if sum(lengths) == n:
break
return cycles[lengths.index(min(lengths))]

# Parse argument
if len(sys.argv) < 2:
print Usage: tsp.py npoints
exit(1)
n = int(sys.argv[1])
# Create n random points
random.seed(1)
points = []
for i in range(n):
points.append((random.randint(0,100),random.randint(0,100)))
m = Model()

# Create variables

454

vars = {}
for i in range(n):
for j in range(i+1):
vars[i,j] = m.addVar(obj=distance(points, i, j), vtype=GRB.BINARY,
name=e+str(i)+_+str(j))
vars[j,i] = vars[i,j]
m.update()

# Add degree-2 constraint, and forbid loops


for i in range(n):
m.addConstr(quicksum(vars[i,j] for j in range(n)) == 2)
vars[i,i].ub = 0
m.update()

# Optimize model
m._vars = vars
m.params.LazyConstraints = 1
m.optimize(subtourelim)
solution = m.getAttr(x, vars)
selected = [(i,j) for i in range(n) for j in range(n) if solution[i,j] > 0.5]
assert len(subtour(selected)) == n
print
print Optimal tour:, subtour(selected)
print Optimal cost:, m.objVal
print

455

tune.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#

This example reads a model from a file and tunes it.


It then writes the best parameter settings to a file
and solves the model using these parameters.

import sys
from gurobipy import *
if len(sys.argv) < 2:
print Usage: tune.py filename
quit()
# Read the model
model = read(sys.argv[1])
# Set the TuneResults parameter to 1
model.params.tuneResults = 1
# Tune the model
model.tune()
if model.tuneResultCount > 0:
# Load the best tuned parameters into the model
model.getTuneResult(0)
# Write tuned parameters to a file
model.write(tune.prm)
# Solve the model using the tuned parameters
model.optimize()

456

workforce1.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#

Assign workers to shifts; each worker may or may not be available on a


particular day. If the problem cannot be solved, use IIS to find a set of
conflicting constraints. Note that there may be additional conflicts besides
what is reported via IIS.

from gurobipy import *


# Number of workers required for each shift
shifts, shiftRequirements = multidict({
"Mon1": 3,
"Tue2": 2,
"Wed3": 4,
"Thu4": 4,
"Fri5": 5,
"Sat6": 6,
"Sun7": 5,
"Mon8": 2,
"Tue9": 2,
"Wed10": 3,
"Thu11": 4,
"Fri12": 6,
"Sat13": 7,
"Sun14": 5 })
# Amount each worker is paid to work one shift
workers, pay = multidict({
"Amy":
10,
"Bob":
12,
"Cathy": 10,
"Dan":
8,
"Ed":
8,
"Fred": 9,
"Gu":
11 })
# Worker availability
availability = tuplelist([
(Amy, Tue2), (Amy, Wed3), (Amy, Fri5), (Amy, Sun7),
(Amy, Tue9), (Amy, Wed10), (Amy, Thu11), (Amy, Fri12),
(Amy, Sat13), (Amy, Sun14), (Bob, Mon1), (Bob, Tue2),
(Bob, Fri5), (Bob, Sat6), (Bob, Mon8), (Bob, Thu11),
457

(Bob, Sat13), (Cathy, Wed3), (Cathy, Thu4), (Cathy, Fri5),


(Cathy, Sun7), (Cathy, Mon8), (Cathy, Tue9), (Cathy, Wed10),
(Cathy, Thu11), (Cathy, Fri12), (Cathy, Sat13),
(Cathy, Sun14), (Dan, Tue2), (Dan, Wed3), (Dan, Fri5),
(Dan, Sat6), (Dan, Mon8), (Dan, Tue9), (Dan, Wed10),
(Dan, Thu11), (Dan, Fri12), (Dan, Sat13), (Dan, Sun14),
(Ed, Mon1), (Ed, Tue2), (Ed, Wed3), (Ed, Thu4),
(Ed, Fri5), (Ed, Sun7), (Ed, Mon8), (Ed, Tue9),
(Ed, Thu11), (Ed, Sat13), (Ed, Sun14), (Fred, Mon1),
(Fred, Tue2), (Fred, Wed3), (Fred, Sat6), (Fred, Mon8),
(Fred, Tue9), (Fred, Fri12), (Fred, Sat13), (Fred, Sun14),
(Gu, Mon1), (Gu, Tue2), (Gu, Wed3), (Gu, Fri5),
(Gu, Sat6), (Gu, Sun7), (Gu, Mon8), (Gu, Tue9),
(Gu, Wed10), (Gu, Thu11), (Gu, Fri12), (Gu, Sat13),
(Gu, Sun14)
])
# Model
m = Model("assignment")
# Assignment variables: x[w,s] == 1 if worker w is assigned to shift s.
# Since an assignment model always produces integer solutions, we use
# continuous variables and solve as an LP.
x = {}
for w,s in availability:
x[w,s] = m.addVar(ub=1, obj=pay[w], name=w+"."+s)
# The objective is to minimize the total pay costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()
# Constraint: assign exactly shiftRequirements[s] workers to each shift s
reqCts = {}
for s in shifts:
reqCts[s] = m.addConstr(
quicksum(x[w,s] for w,s in availability.select(*, s)) ==
shiftRequirements[s], s)
# Optimize
m.optimize()
status = m.status
if status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is unbounded

458

exit(0)
if status == GRB.status.OPTIMAL:
print The optimal objective is, m.objVal
exit(0)
if status != GRB.status.INF_OR_UNBD and status != GRB.status.INFEASIBLE:
print Optimization was stopped with status, status
exit(0)
# do IIS
print The model is infeasible; computing IIS
m.computeIIS()
print \nThe following constraint(s) cannot be satisfied:
for c in m.getConstrs():
if c.IISConstr:
print c.constrName

459

workforce2.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# Assign workers to shifts; each worker may or may not be available on a
# particular day. If the problem cannot be solved, use IIS iteratively to
# find all conflicting constraints.
from gurobipy import *
# Number of workers required for each shift
shifts, shiftRequirements = multidict({
"Mon1": 3,
"Tue2": 2,
"Wed3": 4,
"Thu4": 4,
"Fri5": 5,
"Sat6": 6,
"Sun7": 5,
"Mon8": 2,
"Tue9": 2,
"Wed10": 3,
"Thu11": 4,
"Fri12": 6,
"Sat13": 7,
"Sun14": 5 })
# Amount each worker is paid to work one shift
workers, pay = multidict({
"Amy":
10,
"Bob":
12,
"Cathy": 10,
"Dan":
8,
"Ed":
8,
"Fred": 9,
"Gu":
11 })
# Worker availability
availability = tuplelist([
(Amy, Tue2), (Amy, Wed3), (Amy, Fri5), (Amy, Sun7),
(Amy, Tue9), (Amy, Wed10), (Amy, Thu11), (Amy, Fri12),
(Amy, Sat13), (Amy, Sun14), (Bob, Mon1), (Bob, Tue2),
(Bob, Fri5), (Bob, Sat6), (Bob, Mon8), (Bob, Thu11),
(Bob, Sat13), (Cathy, Wed3), (Cathy, Thu4), (Cathy, Fri5),
460

(Cathy, Sun7), (Cathy, Mon8), (Cathy, Tue9), (Cathy, Wed10),


(Cathy, Thu11), (Cathy, Fri12), (Cathy, Sat13),
(Cathy, Sun14), (Dan, Tue2), (Dan, Wed3), (Dan, Fri5),
(Dan, Sat6), (Dan, Mon8), (Dan, Tue9), (Dan, Wed10),
(Dan, Thu11), (Dan, Fri12), (Dan, Sat13), (Dan, Sun14),
(Ed, Mon1), (Ed, Tue2), (Ed, Wed3), (Ed, Thu4),
(Ed, Fri5), (Ed, Sun7), (Ed, Mon8), (Ed, Tue9),
(Ed, Thu11), (Ed, Sat13), (Ed, Sun14), (Fred, Mon1),
(Fred, Tue2), (Fred, Wed3), (Fred, Sat6), (Fred, Mon8),
(Fred, Tue9), (Fred, Fri12), (Fred, Sat13), (Fred, Sun14),
(Gu, Mon1), (Gu, Tue2), (Gu, Wed3), (Gu, Fri5),
(Gu, Sat6), (Gu, Sun7), (Gu, Mon8), (Gu, Tue9),
(Gu, Wed10), (Gu, Thu11), (Gu, Fri12), (Gu, Sat13),
(Gu, Sun14)
])
# Model
m = Model("assignment")
# Assignment variables: x[w,s] == 1 if worker w is assigned to shift s.
# Since an assignment model always produces integer solutions, we use
# continuous variables and solve as an LP.
x = {}
for w,s in availability:
x[w,s] = m.addVar(ub=1, obj=pay[w], name=w+"."+s)
# The objective is to minimize the total pay costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()
# Constraint: assign exactly shiftRequirements[s] workers to each shift s
reqCts = {}
for s in shifts:
reqCts[s] = m.addConstr(
quicksum(x[w,s] for w,s in availability.select(*, s)) ==
shiftRequirements[s], s)
# Optimize
m.optimize()
status = m.status
if status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is unbounded
exit(0)

461

if status == GRB.status.OPTIMAL:
print The optimal objective is, m.objVal
exit(0)
if status != GRB.status.INF_OR_UNBD and status != GRB.status.INFEASIBLE:
print Optimization was stopped with status, status
exit(0)
# do IIS
print The model is infeasible; computing IIS
removed = []
# Loop until we reduce to a model that can be solved
while True:
m.computeIIS()
print \nThe following constraint cannot be satisfied:
for c in m.getConstrs():
if c.IISConstr:
print c.constrName
# Remove a single constraint from the model
removed.append(c.constrName)
m.remove(c)
break
print
m.optimize()
status = m.status
if status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is unbounded
exit(0)
if status == GRB.status.OPTIMAL:
break
if status != GRB.status.INF_OR_UNBD and status != GRB.status.INFEASIBLE:
print Optimization was stopped with status, status
exit(0)
print \nThe following constraints were removed to get a feasible LP:
print removed

462

workforce3.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#

Assign workers to shifts; each worker may or may not be available on a


particular day. If the problem cannot be solved, add slack variables
to determine which constraints cannot be satisfied, and how much
they need to be relaxed.

from gurobipy import *


# Number of workers required for each shift
shifts, shiftRequirements = multidict({
"Mon1": 3,
"Tue2": 2,
"Wed3": 4,
"Thu4": 4,
"Fri5": 5,
"Sat6": 6,
"Sun7": 5,
"Mon8": 2,
"Tue9": 2,
"Wed10": 3,
"Thu11": 4,
"Fri12": 6,
"Sat13": 7,
"Sun14": 5 })
# Amount each worker is paid to work one shift
workers, pay = multidict({
"Amy":
10,
"Bob":
12,
"Cathy": 10,
"Dan":
8,
"Ed":
8,
"Fred": 9,
"Gu":
11 })
# Worker availability
availability = tuplelist([
(Amy, Tue2), (Amy, Wed3), (Amy, Fri5), (Amy, Sun7),
(Amy, Tue9), (Amy, Wed10), (Amy, Thu11), (Amy, Fri12),
(Amy, Sat13), (Amy, Sun14), (Bob, Mon1), (Bob, Tue2),
(Bob, Fri5), (Bob, Sat6), (Bob, Mon8), (Bob, Thu11),
463

(Bob, Sat13), (Cathy, Wed3), (Cathy, Thu4), (Cathy, Fri5),


(Cathy, Sun7), (Cathy, Mon8), (Cathy, Tue9), (Cathy, Wed10),
(Cathy, Thu11), (Cathy, Fri12), (Cathy, Sat13),
(Cathy, Sun14), (Dan, Tue2), (Dan, Wed3), (Dan, Fri5),
(Dan, Sat6), (Dan, Mon8), (Dan, Tue9), (Dan, Wed10),
(Dan, Thu11), (Dan, Fri12), (Dan, Sat13), (Dan, Sun14),
(Ed, Mon1), (Ed, Tue2), (Ed, Wed3), (Ed, Thu4),
(Ed, Fri5), (Ed, Sun7), (Ed, Mon8), (Ed, Tue9),
(Ed, Thu11), (Ed, Sat13), (Ed, Sun14), (Fred, Mon1),
(Fred, Tue2), (Fred, Wed3), (Fred, Sat6), (Fred, Mon8),
(Fred, Tue9), (Fred, Fri12), (Fred, Sat13), (Fred, Sun14),
(Gu, Mon1), (Gu, Tue2), (Gu, Wed3), (Gu, Fri5),
(Gu, Sat6), (Gu, Sun7), (Gu, Mon8), (Gu, Tue9),
(Gu, Wed10), (Gu, Thu11), (Gu, Fri12), (Gu, Sat13),
(Gu, Sun14)
])
# Model
m = Model("assignment")
# Assignment variables: x[w,s] == 1 if worker w is assigned to shift s.
# Since an assignment model always produces integer solutions, we use
# continuous variables and solve as an LP.
x = {}
for w,s in availability:
x[w,s] = m.addVar(ub=1, obj=pay[w], name=w+"."+s)
# The objective is to minimize the total pay costs
m.modelSense = GRB.MINIMIZE
# Update model to integrate new variables
m.update()
# Constraint: assign exactly shiftRequirements[s] workers to each shift s
reqCts = {}
for s in shifts:
reqCts[s] = m.addConstr(
quicksum(x[w,s] for w,s in availability.select(*, s)) ==
shiftRequirements[s], s)
# Optimize
m.optimize()
status = m.status
if status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is unbounded

464

exit(0)
if status == GRB.status.OPTIMAL:
print The optimal objective is, m.objVal
exit(0)
if status != GRB.status.INF_OR_UNBD and status != GRB.status.INFEASIBLE:
print Optimization was stopped with status, status
exit(0)

# Add slack variables to make the model feasible


print The model is infeasible; adding slack variables
# Set original objective coefficients to zero
m.setObjective(0.0)
# Add a new slack variable to each shift constraint so that the shifts can
# be satisfied
slacks = {}
for s,c in reqCts.items():
slacks[s] = m.addVar(obj=1.0, name=s+"Slack", column=Column([1], [c]))
# Solve the model with slacks
m.optimize()
status = m.status
if status == GRB.status.INF_OR_UNBD or status == GRB.status.INFEASIBLE \
or status == GRB.status.UNBOUNDED:
print The model with slacks cannot be solved \
because it is infeasible or unbounded
exit(1)
if status != GRB.status.OPTIMAL:
print Optimization was stopped with status, status
exit(1)
print \nSlack values:
for sv in slacks.values():
if sv.x > 1e-6:
print sv.varName, =, sv.x

465

workforce4.py
#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
#
#
#
#
#

Assign workers to shifts; each worker may or may not be available on a


particular day. We use lexicographic optimization to solve the model:
first, we minimize the linear sum of the slacks. Then, we constrain
the sum of the slacks, and we minimize a quadratic objective that
tries to balance the workload among the workers.

from gurobipy import *


# Number of workers required for each shift
shifts, shiftRequirements = multidict({
"Mon1": 3,
"Tue2": 2,
"Wed3": 4,
"Thu4": 4,
"Fri5": 5,
"Sat6": 6,
"Sun7": 5,
"Mon8": 2,
"Tue9": 2,
"Wed10": 3,
"Thu11": 4,
"Fri12": 6,
"Sat13": 7,
"Sun14": 5 })
# Amount each worker is paid to work one shift
workers, pay = multidict({
"Amy":
10,
"Bob":
12,
"Cathy": 10,
"Dan":
8,
"Ed":
8,
"Fred": 9,
"Gu":
11 })
# Worker availability
availability = tuplelist([
(Amy, Tue2), (Amy, Wed3), (Amy, Fri5), (Amy, Sun7),
(Amy, Tue9), (Amy, Wed10), (Amy, Thu11), (Amy, Fri12),
(Amy, Sat13), (Amy, Sun14), (Bob, Mon1), (Bob, Tue2),
466

(Bob, Fri5), (Bob, Sat6), (Bob, Mon8), (Bob, Thu11),


(Bob, Sat13), (Cathy, Wed3), (Cathy, Thu4), (Cathy, Fri5),
(Cathy, Sun7), (Cathy, Mon8), (Cathy, Tue9), (Cathy, Wed10),
(Cathy, Thu11), (Cathy, Fri12), (Cathy, Sat13),
(Cathy, Sun14), (Dan, Tue2), (Dan, Wed3), (Dan, Fri5),
(Dan, Sat6), (Dan, Mon8), (Dan, Tue9), (Dan, Wed10),
(Dan, Thu11), (Dan, Fri12), (Dan, Sat13), (Dan, Sun14),
(Ed, Mon1), (Ed, Tue2), (Ed, Wed3), (Ed, Thu4),
(Ed, Fri5), (Ed, Sun7), (Ed, Mon8), (Ed, Tue9),
(Ed, Thu11), (Ed, Sat13), (Ed, Sun14), (Fred, Mon1),
(Fred, Tue2), (Fred, Wed3), (Fred, Sat6), (Fred, Mon8),
(Fred, Tue9), (Fred, Fri12), (Fred, Sat13), (Fred, Sun14),
(Gu, Mon1), (Gu, Tue2), (Gu, Wed3), (Gu, Fri5),
(Gu, Sat6), (Gu, Sun7), (Gu, Mon8), (Gu, Tue9),
(Gu, Wed10), (Gu, Thu11), (Gu, Fri12), (Gu, Sat13),
(Gu, Sun14)
])
# Model
m = Model("assignment")
# Assignment variables: x[w,s] == 1 if worker w is assigned to shift s.
# This is no longer a pure assignment model, so we must use binary variables.
x = {}
for w,s in availability:
x[w,s] = m.addVar(vtype=GRB.BINARY, obj=pay[w], name=w+"."+s)
# Slack variables for each shift constraint so that the shifts can
# be satisfied
slacks = {}
for s in shifts:
slacks[s] = m.addVar(name=s+"Slack")
# Variable to represent the total slack
totSlack = m.addVar(name="totSlack")
# Variables to count the total shifts worked by each worker
totShifts = {}
for w in workers:
totShifts[w] = m.addVar(name=w+"TotShifts")
# Update model to integrate new variables
m.update()
# Constraint: assign exactly shiftRequirements[s] workers to each shift s,

467

# plus the slack


for s in shifts:
m.addConstr(slacks[s] +
quicksum(x[w,s] for w,s in availability.select(*, s)) ==
shiftRequirements[s], s)
# Constraint: set totSlack equal to the total slack
m.addConstr(totSlack == quicksum(slacks[s] for s in shifts), "totSlack")
# Constraint: compute the total number of shifts for each worker
for w in workers:
m.addConstr(totShifts[w] ==
quicksum(x[w,s] for w,s in availability.select(w, *)),
"totShifts" + w)
# Objective: minimize the total slack
# Note that this replaces the previous pay objective coefficients
m.setObjective(totSlack)

# Optimize
def solveAndPrint():
m.optimize()
status = m.status
if status == GRB.status.INF_OR_UNBD or status == GRB.status.INFEASIBLE \
or status == GRB.status.UNBOUNDED:
print The model cannot be solved because it is infeasible or \
unbounded
exit(1)
if status != GRB.status.OPTIMAL:
print Optimization was stopped with status, status
exit(0)
# Print total slack and the number of shifts worked for each worker
print
print Total slack required:, totSlack.x
for w in workers:
print w, "worked", totShifts[w].x, "shifts"
print
solveAndPrint()
# Constrain the slack by setting its upper and lower bounds
totSlack.ub = totSlack.x

468

totSlack.lb = totSlack.x
# Variable to count the average number of shifts worked
avgShifts = m.addVar(name="avgShifts")
# Variables to count the difference from average for each worker;
# note that these variables can take negative values.
diffShifts = {}
for w in workers:
diffShifts[w] = \
m.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY, name=w+"Diff")
# Update model to integrate new variables
m.update()
# Constraint: compute the average number of shifts worked
m.addConstr(len(workers) * avgShifts ==
quicksum(totShifts[w] for w in workers),
"avgShifts")
# Constraint: compute the difference from the average number of shifts
for w in workers:
m.addConstr(diffShifts[w] == totShifts[w] - avgShifts, w + "Diff")
# Objective: minimize the sum of the square of the difference from the
# average number of shifts worked
m.setObjective(quicksum(diffShifts[w]*diffShifts[w] for w in workers))
# Optimize
solveAndPrint()

469

3.7

MATLAB Examples

This section includes source code for all of the Gurobi MATLAB examples. The same source code
can be found in the examples/matlab directory of the Gurobi distribution.

diet.m
function diet()
% diet Solve the classic diet model
% Copyright 2013, Gurobi Optimization, Inc

% Nutrition guidelines, based on


% USDA Dietary Guidelines for Americans, 2005
% http://www.health.gov/DietaryGuidelines/dga2005/
ncategories = 4;
categories = {calories; protein; fat; sodium};
%
minNutrition maxNutrition
categorynutrition = [ 1800 2200;
% calories
91
inf;
% protein
0
65;
% fat
0
1779]; % sodium
nfoods = 9;
foods = {hamburger;
chicken;
hot dog;
fries;
macaroni;
pizza;
salad;
milk;
ice cream};
foodcost = [2.49;
2.89;
1.50;
1.89;
2.09;
1.99;
2.49;
0.89;
1.59];

470

%
%
%
%
%
%
%
%
%

hamburger
chicken
hot dog
fries
macaroni
pizza
salad
milk
ice cream

% calories protein fat sodium


nutritionValues = [ 410
24
26 730;
420
32
10 1190;
560
20
32 1800;
380
4
19 270;
320
12
10 930;
320
15
12 820;
320
31
12 1230;
100
8
2.5 125;
330
8
10 180];
nutritionValues = sparse(nutritionValues);
model.modelName = diet;

%
%
%
%
%
%
%
%
%

hamburger
chicken
hot dog
fries
macaroni
pizza
salad
milk
ice cream

% The variables are layed out as [ buy; nutrition]


model.obj
= [ foodcost;
zeros(ncategories, 1)];
model.lb
= [ zeros(nfoods, 1); categorynutrition(:, 1)];
model.ub
= [ inf(nfoods, 1); categorynutrition(:, 2)];
model.A
= [ nutritionValues -speye(ncategories)];
model.rhs
= zeros(ncategories, 1);
model.sense = repmat(=, ncategories, 1);

function printSolution(result)
if strcmp(result.status, OPTIMAL)
buy
= result.x(1:nfoods);
nutrition = result.x(nfoods+1:nfoods+ncategories);
fprintf(\nCost: %f\n, result.objval);
fprintf(\nBuy:\n)
for f=1:nfoods
if buy(f) > 0.0001
fprintf(%10s %g\n, foods{f}, buy(f));
end
end
fprintf(\nNutrition:\n)
for c=1:ncategories
fprintf(%10s %g\n, categories{c}, nutrition(c));
end
else
fprintf(No solution\n);
end
end
% Solve
results = gurobi(model);
printSolution(results);

471

fprintf(\nAdding constraint at most 6 servings of dairy\n)


milk = find(strcmp(milk, foods));
icecream = find(strcmp(ice cream, foods));
model.A(end+1,:) = sparse([1; 1], [milk; icecream], 1, ...
1, nfoods + ncategories);
model.rhs(end+1) = 6;
model.sense(end+1) = <;
% Solve
results = gurobi(model);
printSolution(results)
end

472

linprog.m
function [x, fval, exitflag] = linprog(f, A, b, Aeq, beq, lb, ub)
%LINPROG A linear programming example using the Gurobi MATLAB interface
%
%
This example is based on the linprog interface defined in the
%
MATLAB Optimization Toolbox. The Optimization Toolbox
%
is a registered trademark of The MathWorks, Inc.
%
%
x = LINPROG(f,A,b) solves the linear programming problem:
%
%
minimize
f*x
%
subject to
A*x <= b
%
%
%
x = LINPROG(f,A,b,Aeq,beq) solves the problem:
%
%
minimize
f*x
%
subject to
A*x <= b,
%
Aeq*x == beq.
%
%
x = LINPROG(f,A,b,Aeq,beq,lb,ub) solves the problem:
%
%
minimize
f*x
%
subject to
A*x <= b,
%
Aeq*x == beq,
%
lb <=
x <= ub.
%
%
You can set lb(j) = -inf, if x(j) has no lower bound,
%
and ub(j) = inf, if x(j) has no upper bound.
%
%
[x, fval] = LINPROG(f, A, b) returns the objective value
%
at the solution. That is, fval = f*x.
%
%
[x, fval, exitflag] = LINPROG(f, A, b) returns an exitflag
%
containing the status of the optimization. The values for
%
exitflag and corresponding status codes are:
%
1 - OPTIMAL,
%
0 - ITERATION_LIMIT,
%
-2 - INFEASIBLE,
%
-3 - UNBOUNDED.
%
if nargin < 3
error(linprog(f, A, b))
end
473

if nargin > 7
error(linprog(f, A, b, Aeq, beq, lb, ub));
end
n = size(A, 2);
model.obj = f;
if nargin < 4
model.A = A;
model.rhs = b;
model.sense = <;
else
model.A = [A; Aeq];
model.rhs = [b; beq];
model.sense = [repmat(<, size(A,1), 1); repmat(=, size(Aeq,1), 1)];
end
if nargin < 6
model.lb = -inf(n,1);
else
model.lb = lb;
end
if nargin == 7
model.ub = ub;
end
params.outputflag = 0;
result = gurobi(model, params);

if strcmp(result.status, OPTIMAL)
exitflag = 1;
elseif strcmp(result.status, ITERATION_LIMIT)
exitflag = 0;
elseif strcmp(result.status, INF_OR_UNBD)
params.dualreductions = 0;
result = gurobi(model, params);
if strcmp(result.status, INFEASIBLE)
exitflag = -2;
elseif strcmp(result.status, UNBOUNDED)
exitflag = -3;
else

474

exitflag = nan;
end
else
exitflag = nan;
end

if isfield(result, x)
x = result.x;
else
x = nan(n,1);
end
if isfield(result, objval)
fval = result.objval;
else
fval = nan;
end

475

lp.m
% Copyright 2013, Gurobi Optimization, Inc.
%
% This example formulates and solves the following simple LP model:
% maximize
%
x + 2 y + 3 z
% subject to
%
x +
y
<= 1
%
y +
z <= 1
%
clear model;
model.A = sparse([1 1 0; 0 1 1]);
model.obj = [1 2 3];
model.modelsense = Max;
model.rhs = [1 1];
model.sense = [ < <];
result = gurobi(model)
disp(result.objval);
disp(result.x);
% Alterantive representation of A - as sparse triplet matrix
i = [1; 1; 2; 2];
j = [1; 2; 2; 3];
x = [1; 1; 1; 1];
model.A = sparse(i, j, x, 2, 3);
clear params;
params.method = 2;
params.timelimit = 100;
result = gurobi(model, params);
disp(result.objval);
disp(result.x)

476

lp2.m
% Copyright 2013, Gurobi Optimization, Inc.
%
% Formulate a simple linear program, solve it, and then solve it
% again using the optimal basis.
clear model;
model.A = sparse([1 3 4; 8 2 3]);
model.obj = [1 2 3];
model.rhs = [4 7];
model.sense = [> >];
% First solve requires a few simplex iterations
result = gurobi(model)
model.vbasis = result.vbasis;
model.cbasis = result.cbasis;
% Second solve - start from an optimal basis, so no iterations
result = gurobi(model)

477

mip1.m
% Copyright 2013, Gurobi Optimization, Inc.
% This example formulates and solves the following simple MIP model:
% maximize
%
x +
y + 2 z
% subject to
%
x + 2 y + 3 z <= 4
%
x +
y
>= 1
% x, y, z binary
names = {x; y; z};
try
clear model;
model.A = sparse([1 2 3; 1 1 0]);
model.obj = [1 1 2];
model.rhs = [4; 1];
model.sense = <>;
model.vtype = B;
model.modelsense = max;
clear params;
params.outputflag = 0;
params.resultfile = mip1.lp;
result = gurobi(model, params);
disp(result)
for v=1:length(names)
fprintf(%s %d\n, names{v}, result.x(v));
end
fprintf(Obj: %e\n, result.objval);
catch gurobiError
fprintf(Error reported\n);
end

478

qcp.m
% Copyright 2013, Gurobi Optimization, Inc.
% This example formulates and solves the following simple QCP model:
% maximize
%
x
% subject to
%
x + y + z = 1
%
x^2 + y^2 <= z^2 (second-order cone)
%
x^2 <= yz
(rotated second-order cone)
clear model
names = {x, y, z};
% Set objective: x
model.obj = [ 1 0 0 ];
model.modelsense = max;
% Add constraint: x + y + z = 1
model.A
= sparse([1 1 1]);
model.rhs = 1;
model.sense = =;
% Add second-order cone: x^2 + y^2 <= z^2
model.quadcon(1).Qc = sparse([ 1 0 0;
0 1 0;
0 0 -1]);
model.quadcon(1).q = zeros(3,1);
model.quadcon(1).rhs = 0.0;
% Add rotated cone: x^2 <= yz
model.quadcon(2).Qc = sparse([ 1 0 0;
0 0 -1;
0 0 0]);
model.quadcon(2).q = zeros(3,1);
model.quadcon(2).rhs = 0;
result = gurobi(model);
for j=1:3
fprintf(%s %e\n, names{j}, result.x(j))
end
fprintf(Obj: %e\n, result.objval);

479

qp.m
% Copyright 2013, Gurobi Optimization, Inc.
% This example formulates and solves the following simple QP model:
% minimize
%
x^2 + x*y + y^2 + y*z + z^2 + 2 x
% subject to
%
x + 2 y + 3 z >= 4
%
x +
y
>= 1
%
% It solves it once as a continuous model, and once as an integer
% model.
names = {x, y, z};
clear model;
model.Q = sparse([1 0.5 0; 0.5 1 0.5; 0 0.5 1]);
model.A = sparse([1 2 3; 1 1 0]);
model.obj = [2 0 0];
model.rhs = [4 1];
model.sense = >;
results = gurobi(model);
for v=1:length(names)
fprintf(%s %e\n, names{v}, results.x(v));
end
fprintf(Obj: %e\n, results.objval);
model.vtype = B;
results

= gurobi(model);

for v=1:length(names)
fprintf(%s %e\n, names{v}, results.x(v));
end
fprintf(Obj: %e\n, results.objval);

480

sos.m
% Copyright 2013, Gurobi Optimization, Inc.
% This example creates a very simple Special Ordered Set (SOS)
% model. The model consists of 3 continuous variables, no linear
% constraints, and a pair of SOS constraints of type 1.
try
clear model;
model.ub = [1 1 2];
model.obj = [2 1 1];
model.modelsense = Max;
model.A = sparse(1,3);
model.rhs = 0;
model.sense = =;
% Add first SOS: x1 = 0 or x2 = 0
model.sos(1).type = 1;
model.sos(1).index = [1 2];
model.sos(1).weights = [1 2];
% Add second SOS: x1 = 0 or x3 = 0
model.sos(2).type = 1;
model.sos(2).index = [1 3];
model.sos(2).weights = [1 2];
result = gurobi(model);
for i=1:3
fprintf(x%d %e\n, i, result.x(i))
end
fprintf(Obj: %e\n, result.objval);
catch gurobiError
fprintf(Encountered an error\n)
end

481

3.8

R Examples

This section includes source code for all of the Gurobi R examples. The same source code can be
found in the examples/R directory of the Gurobi distribution.

lp.R
# Copyright 2013, Gurobi Optimization, Inc.
#
# This example formulates and solves the following simple LP model:
# maximize
#
x + 2 y + 3 z
# subject to
#
x +
y
<= 1
#
y +
z <= 1
library("Matrix")
library("gurobi")
model <- list()
model$A
model$obj
model$modelsense
model$rhs
model$sense

<<<<<-

matrix(c(1,1,0,0,1,1), nrow=2, byrow=T)


c(1,1,2)
"max"
c(1,1)
c(<=, <=)

result <- gurobi(model)


print(result$objval)
print(result$x)
# Second option for A - as a sparseMatrix (using the Matrix package)...
model$A <- spMatrix(2, 3, c(1, 1, 2, 2), c(1, 2, 2, 3), c(1, 1, 1, 1))
params <- list(Method=2, TimeLimit=100)
result <- gurobi(model, params)
print(result$objval)
print(result$x)
# Third option for A - as a sparse triplet matrix (using the slam package)...
model$A <- simple_triplet_matrix(c(1, 1, 2, 2), c(1, 2, 2, 3), c(1, 1, 1, 1))
482

params <- list(Method=2, TimeLimit=100)


result <- gurobi(model, params)
print(result$objval)
print(result$x)

483

lp2.R
# Copyright 2013, Gurobi Optimization, Inc.
#
# Formulate a simple linear program, solve it, and then solve it
# again using the optimal basis.
library("gurobi")
model <- list()
model$A
model$obj
model$rhs
model$sense

<<<<-

matrix(c(1,3,4,8,2,3), nrow=2, byrow=T)


c(1,2,3)
c(4,7)
c(>=, >=)

# First solve - requires a few simplex iterations


result <- gurobi(model)
model$vbasis <- result$vbasis
model$cbasis <- result$cbasis
# Second solve - start from optimal basis, so no iterations
result <- gurobi(model)

484

mip.R
# Copyright 2013, Gurobi Optimization, Inc.
#
# This example formulates and solves the following simple MIP model:
# maximize
#
x +
y + 2 z
# subject to
#
x + 2 y + 3 z <= 4
#
x +
y
>= 1
#
x, y, z binary
library("gurobi")
model <- list()
model$A
model$obj
model$modelsense
model$rhs
model$sense
model$vtype

<<<<<<-

matrix(c(1,2,3,1,1,0), nrow=2, ncol=3, byrow=T)


c(1,1,2)
"max"
c(4,1)
c(<=, >=)
B

params <- list(OutputFlag=0)


result <- gurobi(model, params)
print(Solution:)
print(result$objval)
print(result$x)

485

qcp.R
# Copyright 2013, Gurobi Optimization, Inc.
#
# This example formulates and solves the following simple QCP model:
# minimize
#
x^2 + x*y + y^2 + y*z + z^2
# subject to
#
x + 2 y + 3z
>= 4
#
x +
y
>= 1
#
t = 0.7071
#
[ x ^ 2 + y ^ 2 - t ^ 2 ] < = 0 (a second-order cone constraint)
library("gurobi")
model <- list()
model$A
model$Q
model$cones
model$obj
model$rhs
model$sense

<<<<<<-

matrix(c(1,2,3,0,1,1,0,0,0,0,0,1), nrow=3, byrow=T)


matrix(c(2,1,0,0,1,2,1,0,0,1,2,0,0,0,0,0), nrow=4, byrow=T)
list(list(4,1,2))
c(1,2,3,0)
c(4,1,0.717067811)
c(>=, >=, =)

result <- gurobi(model)


print(result$objval)
print(result$x)

486

qp.R
# Copyright 2013, Gurobi Optimization, Inc.
#
# This example formulates and solves the following simple QP model:
# minimize
#
x^2 + x*y + y^2 + y*z + z^2 + 2 x
# subject to
#
x + 2 y + 3z >= 4
#
x +
y
>= 1
library("gurobi")
model <- list()
model$A
model$Q
model$obj
model$rhs
model$sense

<<<<<-

matrix(c(1,2,3,1,1,0), nrow=2, byrow=T)


matrix(c(2,1,0,1,2,1,0,1,2), nrow=3, byrow=T)
c(2,0,0)
c(4,1)
c(>=, >=)

result <- gurobi(model)


print(result$objval)
print(result$x)

487

You might also like