1 //-----------------------------------------------------------------------------
2 // name:     OSI Interface for GUROBI
3 // template: OSI Cplex Interface written by T. Achterberg
4 // author:   Stefan Vigerske
5 //           Humboldt University Berlin
6 // license:  this file may be freely distributed under the terms of EPL
7 // comments: please scan this file for '???' and 'TODO' and read the comments
8 //-----------------------------------------------------------------------------
9 // Copyright (C) 2009 Humboldt University Berlin and others.
10 // Corporation and others.  All Rights Reserved.
11 
12 #include "CoinPragma.hpp"
13 #include "OsiConfig.h"
14 
15 //#include <cassert>
16 //#include <iostream>
17 
18 #include "OsiUnitTests.hpp"
19 #include "OsiGrbSolverInterface.hpp"
20 #include "OsiCuts.hpp"
21 #include "OsiRowCut.hpp"
22 #include "OsiColCut.hpp"
23 #include "CoinPackedMatrix.hpp"
24 
25 // Added so build windows build with dsp files works,
26 // when not building with gurobi.
27 #ifdef COIN_HAS_GRB
28 #include "gurobi_c.h"
29 
30 //--------------------------------------------------------------------------
OsiGrbSolverInterfaceUnitTest(const std::string & mpsDir,const std::string & netlibDir)31 void OsiGrbSolverInterfaceUnitTest( const std::string & mpsDir, const std::string & netlibDir )
32 {
33   // Test default constructor
34   {
35     OsiGrbSolverInterface m;
36     OSIUNITTEST_ASSERT_ERROR(m.obj_         == NULL, {}, "gurobi", "default constructor");
37     OSIUNITTEST_ASSERT_ERROR(m.collower_    == NULL, {}, "gurobi", "default constructor");
38     OSIUNITTEST_ASSERT_ERROR(m.colupper_    == NULL, {}, "gurobi", "default constructor");
39     OSIUNITTEST_ASSERT_ERROR(m.coltype_     == NULL, {}, "gurobi", "default constructor");
40     OSIUNITTEST_ASSERT_ERROR(m.colspace_    ==    0, {}, "gurobi", "default constructor");
41     OSIUNITTEST_ASSERT_ERROR(m.rowsense_    == NULL, {}, "gurobi", "default constructor");
42     OSIUNITTEST_ASSERT_ERROR(m.rhs_         == NULL, {}, "gurobi", "default constructor");
43     OSIUNITTEST_ASSERT_ERROR(m.rowrange_    == NULL, {}, "gurobi", "default constructor");
44     OSIUNITTEST_ASSERT_ERROR(m.rowlower_    == NULL, {}, "gurobi", "default constructor");
45     OSIUNITTEST_ASSERT_ERROR(m.rowupper_    == NULL, {}, "gurobi", "default constructor");
46     OSIUNITTEST_ASSERT_ERROR(m.colsol_      == NULL, {}, "gurobi", "default constructor");
47     OSIUNITTEST_ASSERT_ERROR(m.rowsol_      == NULL, {}, "gurobi", "default constructor");
48     OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_ == NULL, {}, "gurobi", "default constructor");
49     OSIUNITTEST_ASSERT_ERROR(m.matrixByCol_ == NULL, {}, "gurobi", "default constructor");
50     OSIUNITTEST_ASSERT_ERROR(m.getNumCols() ==    0, {}, "gurobi", "default constructor");
51     OSIUNITTEST_ASSERT_ERROR(m.getApplicationData() == NULL, {}, "gurobi", "default constructor");
52     int i=2346;
53     m.setApplicationData(&i);
54     OSIUNITTEST_ASSERT_ERROR(*((int *)(m.getApplicationData())) == i, {}, "gurobi", "default constructor");
55   }
56 
57   {
58     CoinRelFltEq eq;
59     OsiGrbSolverInterface m;
60     std::string fn = mpsDir+"exmip1";
61     m.readMps(fn.c_str(),"mps");
62 
63     {
64       OSIUNITTEST_ASSERT_ERROR(m.getNumCols() == 8, {}, "gurobi", "exmip1 read");
65       const CoinPackedMatrix * colCopy = m.getMatrixByCol();
66       OSIUNITTEST_ASSERT_ERROR(colCopy->getNumCols()  == 8, {}, "gurobi", "exmip1 matrix");
67       OSIUNITTEST_ASSERT_ERROR(colCopy->getMajorDim() == 8, {}, "gurobi", "exmip1 matrix");
68       OSIUNITTEST_ASSERT_ERROR(colCopy->getNumRows()  == 5, {}, "gurobi", "exmip1 matrix");
69       OSIUNITTEST_ASSERT_ERROR(colCopy->getMinorDim() == 5, {}, "gurobi", "exmip1 matrix");
70       OSIUNITTEST_ASSERT_ERROR(colCopy->getVectorLengths()[7] == 2, {}, "gurobi", "exmip1 matrix");
71       CoinPackedMatrix revColCopy;
72       revColCopy.reverseOrderedCopyOf(*colCopy);
73       CoinPackedMatrix rev2ColCopy;
74       rev2ColCopy.reverseOrderedCopyOf(revColCopy);
75       OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getNumCols()  == 8, {}, "gurobi", "twice reverse matrix copy");
76       OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getMajorDim() == 8, {}, "gurobi", "twice reverse matrix copy");
77       OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getNumRows()  == 5, {}, "gurobi", "twice reverse matrix copy");
78       OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getMinorDim() == 5, {}, "gurobi", "twice reverse matrix copy");
79       OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getVectorLengths()[7] == 2, {}, "gurobi", "twice reverse matrix copy");
80     }
81 
82     // Test copy constructor and assignment operator
83     {
84       OsiGrbSolverInterface lhs;
85       {
86         OsiGrbSolverInterface im(m);
87 
88         OsiGrbSolverInterface imC1(im);
89         OSIUNITTEST_ASSERT_ERROR(imC1.lp_          != im.lp_,           {}, "gurobi", "copy constructor");
90         OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols() == im.getNumCols(),  {}, "gurobi", "copy constructor");
91         OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows() == im.getNumRows(),  {}, "gurobi", "copy constructor");
92 
93         OsiGrbSolverInterface imC2(im);
94         OSIUNITTEST_ASSERT_ERROR(imC2.lp_          != im.lp_,           {}, "gurobi", "copy constructor");
95         OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols() == im.getNumCols(),  {}, "gurobi", "copy constructor");
96         OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows() == im.getNumRows(),  {}, "gurobi", "copy constructor");
97 
98         OSIUNITTEST_ASSERT_ERROR(imC1.lp_ != imC2.lp_, {}, "gurobi", "copy constructor");
99 
100         lhs = imC2;
101       }
102 
103       // Test that lhs has correct values even though rhs has gone out of scope
104       OSIUNITTEST_ASSERT_ERROR(lhs.lp_          != m.lp_,           {}, "gurobi", "assignment operator");
105       OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(),  {}, "gurobi", "copy constructor");
106       OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(),  {}, "gurobi", "copy constructor");
107     }
108 
109     // Test clone
110     {
111       OsiGrbSolverInterface gurobiSi(m);
112       OsiSolverInterface * siPtr = &gurobiSi;
113       OsiSolverInterface * siClone = siPtr->clone();
114       OsiGrbSolverInterface * gurobiClone = dynamic_cast<OsiGrbSolverInterface*>(siClone);
115       OSIUNITTEST_ASSERT_ERROR(gurobiClone != NULL, {}, "gurobi", "clone");
116       OSIUNITTEST_ASSERT_ERROR(gurobiClone->lp_          != gurobiSi.lp_, {}, "gurobi", "clone");
117       OSIUNITTEST_ASSERT_ERROR(gurobiClone->getNumRows() == gurobiSi.getNumRows(), {}, "gurobi", "clone");
118       OSIUNITTEST_ASSERT_ERROR(gurobiClone->getNumCols() == m.getNumCols(), {}, "gurobi", "clone");
119 
120       delete siClone;
121     }
122 
123     // test infinity
124     {
125       OsiGrbSolverInterface si;
126       OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == GRB_INFINITY, {}, "gurobi", "value for infinity");
127     }
128 
129 
130     {
131       OsiGrbSolverInterface gurobiSi(m);
132       int nc = gurobiSi.getNumCols();
133       int nr = gurobiSi.getNumRows();
134       const double * cl = gurobiSi.getColLower();
135       const double * cu = gurobiSi.getColUpper();
136       const double * rl = gurobiSi.getRowLower();
137       const double * ru = gurobiSi.getRowUpper();
138 
139       OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "gurobi", "read and copy exmip1");
140       OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "gurobi", "read and copy exmip1");
141       OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "gurobi", "read and copy exmip1");
142       OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "gurobi", "read and copy exmip1");
143       OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "gurobi", "read and copy exmip1");
144       OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "gurobi", "read and copy exmip1");
145       OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "gurobi", "read and copy exmip1");
146       OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "gurobi", "read and copy exmip1");
147       OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "gurobi", "read and copy exmip1");
148       OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "gurobi", "read and copy exmip1");
149 
150       double newCs[8] = {1., 2., 3., 4., 5., 6., 7., 8.};
151       gurobiSi.setColSolution(newCs);
152       const double * cs = gurobiSi.getColSolution();
153       OSIUNITTEST_ASSERT_ERROR(eq(cs[0],1.0), {}, "gurobi", "set col solution");
154       OSIUNITTEST_ASSERT_ERROR(eq(cs[7],8.0), {}, "gurobi", "set col solution");
155 #if 0 // TODO set and copy of solutions not supported by OsiGrb currently
156       {
157         OsiGrbSolverInterface solnSi(gurobiSi);
158         const double * cs = solnSi.getColSolution();
159         OSIUNITTEST_ASSERT_ERROR(eq(cs[0],1.0), {}, "gurobi", "set col solution and copy");
160         OSIUNITTEST_ASSERT_ERROR(eq(cs[7],8.0), {}, "gurobi", "set col solution and copy");
161       }
162 #endif
163 
164       OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "gurobi", "set col lower");
165       gurobiSi.setColLower( 3, 1.2345 );
166       OSIUNITTEST_ASSERT_ERROR( eq(cl[3],1.2345), {}, "gurobi", "set col lower");
167 
168       OSIUNITTEST_ASSERT_ERROR(!eq(cu[4],10.2345), {}, "gurobi", "set col upper");
169       gurobiSi.setColUpper( 4, 10.2345 );
170       OSIUNITTEST_ASSERT_ERROR( eq(cu[4],10.2345), {}, "gurobi", "set col upper");
171 
172       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[0], 1.0), {}, "gurobi", "read and copy exmip1");
173       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[1], 0.0), {}, "gurobi", "read and copy exmip1");
174       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[2], 0.0), {}, "gurobi", "read and copy exmip1");
175       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[3], 0.0), {}, "gurobi", "read and copy exmip1");
176       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[4], 2.0), {}, "gurobi", "read and copy exmip1");
177       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[5], 0.0), {}, "gurobi", "read and copy exmip1");
178       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[6], 0.0), {}, "gurobi", "read and copy exmip1");
179       OSIUNITTEST_ASSERT_ERROR(eq(gurobiSi.getObjCoefficients()[7],-1.0), {}, "gurobi", "read and copy exmip1");
180     }
181 
182     // Test getMatrixByRow method
183     {
184       const OsiGrbSolverInterface si(m);
185       const CoinPackedMatrix * smP = si.getMatrixByRow();
186 
187       OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  5, return, "gurobi", "getMatrixByRow: major dim");
188       OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "gurobi", "getMatrixByRow: num elements");
189 
190       CoinRelFltEq eq;
191       const double * ev = smP->getElements();
192       OSIUNITTEST_ASSERT_ERROR(eq(ev[0],   3.0), {}, "gurobi", "getMatrixByRow: elements");
193       OSIUNITTEST_ASSERT_ERROR(eq(ev[1],   1.0), {}, "gurobi", "getMatrixByRow: elements");
194       OSIUNITTEST_ASSERT_ERROR(eq(ev[2],  -2.0), {}, "gurobi", "getMatrixByRow: elements");
195       OSIUNITTEST_ASSERT_ERROR(eq(ev[3],  -1.0), {}, "gurobi", "getMatrixByRow: elements");
196       OSIUNITTEST_ASSERT_ERROR(eq(ev[4],  -1.0), {}, "gurobi", "getMatrixByRow: elements");
197       OSIUNITTEST_ASSERT_ERROR(eq(ev[5],   2.0), {}, "gurobi", "getMatrixByRow: elements");
198       OSIUNITTEST_ASSERT_ERROR(eq(ev[6],   1.1), {}, "gurobi", "getMatrixByRow: elements");
199       OSIUNITTEST_ASSERT_ERROR(eq(ev[7],   1.0), {}, "gurobi", "getMatrixByRow: elements");
200       OSIUNITTEST_ASSERT_ERROR(eq(ev[8],   1.0), {}, "gurobi", "getMatrixByRow: elements");
201       OSIUNITTEST_ASSERT_ERROR(eq(ev[9],   2.8), {}, "gurobi", "getMatrixByRow: elements");
202       OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "gurobi", "getMatrixByRow: elements");
203       OSIUNITTEST_ASSERT_ERROR(eq(ev[11],  5.6), {}, "gurobi", "getMatrixByRow: elements");
204       OSIUNITTEST_ASSERT_ERROR(eq(ev[12],  1.0), {}, "gurobi", "getMatrixByRow: elements");
205       OSIUNITTEST_ASSERT_ERROR(eq(ev[13],  1.9), {}, "gurobi", "getMatrixByRow: elements");
206 
207       const int * mi = smP->getVectorStarts();
208       OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "gurobi", "getMatrixByRow: vector starts");
209       OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "gurobi", "getMatrixByRow: vector starts");
210       OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "gurobi", "getMatrixByRow: vector starts");
211       OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "gurobi", "getMatrixByRow: vector starts");
212       OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "gurobi", "getMatrixByRow: vector starts");
213       OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "gurobi", "getMatrixByRow: vector starts");
214 
215       const int * ei = smP->getIndices();
216       OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "gurobi", "getMatrixByRow: indices");
217       OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "gurobi", "getMatrixByRow: indices");
218       OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "gurobi", "getMatrixByRow: indices");
219       OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "gurobi", "getMatrixByRow: indices");
220       OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "gurobi", "getMatrixByRow: indices");
221       OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "gurobi", "getMatrixByRow: indices");
222       OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "gurobi", "getMatrixByRow: indices");
223       OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "gurobi", "getMatrixByRow: indices");
224       OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "gurobi", "getMatrixByRow: indices");
225       OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "gurobi", "getMatrixByRow: indices");
226       OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "gurobi", "getMatrixByRow: indices");
227       OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "gurobi", "getMatrixByRow: indices");
228       OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "gurobi", "getMatrixByRow: indices");
229       OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "gurobi", "getMatrixByRow: indices");
230     }
231     //--------------
232     // Test rowsense, rhs, rowrange, getMatrixByRow
233     {
234       OsiGrbSolverInterface lhs;
235       {
236         OsiGrbSolverInterface siC1(m);
237         OSIUNITTEST_ASSERT_WARNING(siC1.obj_ == NULL, {}, "gurobi", "objective");
238         OSIUNITTEST_ASSERT_WARNING(siC1.collower_ == NULL, {}, "gurobi", "col lower");
239         OSIUNITTEST_ASSERT_WARNING(siC1.colupper_ == NULL, {}, "gurobi", "col upper");
240         OSIUNITTEST_ASSERT_WARNING(siC1.rowrange_ == NULL, {}, "gurobi", "row range");
241         OSIUNITTEST_ASSERT_WARNING(siC1.rowsense_ == NULL, {}, "gurobi", "row sense");
242         OSIUNITTEST_ASSERT_WARNING(siC1.rowlower_ == NULL, {}, "gurobi", "row lower");
243         OSIUNITTEST_ASSERT_WARNING(siC1.rowupper_ == NULL, {}, "gurobi", "row upper");
244         OSIUNITTEST_ASSERT_WARNING(siC1.rhs_ == NULL, {}, "gurobi", "right hand side");
245         OSIUNITTEST_ASSERT_WARNING(siC1.matrixByRow_ == NULL, {}, "gurobi", "matrix by row");
246 //TODO        OSIUNITTEST_ASSERT_WARNING(siC1.colsol_ != NULL, {}, "gurobi", "col solution");
247 //TODO        OSIUNITTEST_ASSERT_WARNING(siC1.rowsol_ != NULL, {}, "gurobi", "row solution");
248 
249         const char   * siC1rs  = siC1.getRowSense();
250         OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "gurobi", "row sense");
251         OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "gurobi", "row sense");
252         OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "gurobi", "row sense");
253         OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "gurobi", "row sense");
254         OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "gurobi", "row sense");
255 
256         const double * siC1rhs = siC1.getRightHandSide();
257         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "gurobi", "right hand side");
258         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "gurobi", "right hand side");
259         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "gurobi", "right hand side");
260         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "gurobi", "right hand side");
261         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "gurobi", "right hand side");
262 
263         const double * siC1rr  = siC1.getRowRange();
264         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "gurobi", "row range");
265         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "gurobi", "row range");
266         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "gurobi", "row range");
267         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "gurobi", "row range");
268         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "gurobi", "row range");
269 
270         const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow();
271         OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "gurobi", "matrix by row");
272         OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim()    ==  5, return, "gurobi", "matrix by row: major dim");
273         OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "gurobi", "matrix by row: num elements");
274 
275         const double * ev = siC1mbr->getElements();
276         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "gurobi", "matrix by row: elements");
277         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "gurobi", "matrix by row: elements");
278         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "gurobi", "matrix by row: elements");
279         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "gurobi", "matrix by row: elements");
280         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "gurobi", "matrix by row: elements");
281         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "gurobi", "matrix by row: elements");
282         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "gurobi", "matrix by row: elements");
283         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "gurobi", "matrix by row: elements");
284         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "gurobi", "matrix by row: elements");
285         OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "gurobi", "matrix by row: elements");
286         OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "gurobi", "matrix by row: elements");
287         OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "gurobi", "matrix by row: elements");
288         OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "gurobi", "matrix by row: elements");
289         OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "gurobi", "matrix by row: elements");
290 
291         const CoinBigIndex * mi = siC1mbr->getVectorStarts();
292         OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "gurobi", "matrix by row: vector starts");
293         OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "gurobi", "matrix by row: vector starts");
294         OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "gurobi", "matrix by row: vector starts");
295         OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "gurobi", "matrix by row: vector starts");
296         OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "gurobi", "matrix by row: vector starts");
297         OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "gurobi", "matrix by row: vector starts");
298 
299         const int * ei = siC1mbr->getIndices();
300         OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "gurobi", "matrix by row: indices");
301         OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "gurobi", "matrix by row: indices");
302         OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "gurobi", "matrix by row: indices");
303         OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "gurobi", "matrix by row: indices");
304         OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "gurobi", "matrix by row: indices");
305         OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "gurobi", "matrix by row: indices");
306         OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "gurobi", "matrix by row: indices");
307         OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "gurobi", "matrix by row: indices");
308         OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "gurobi", "matrix by row: indices");
309         OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "gurobi", "matrix by row: indices");
310         OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "gurobi", "matrix by row: indices");
311         OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "gurobi", "matrix by row: indices");
312         OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "gurobi", "matrix by row: indices");
313         OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "gurobi", "matrix by row: indices");
314 
315         OSIUNITTEST_ASSERT_WARNING(siC1rs  == siC1.getRowSense(), {}, "gurobi", "row sense");
316         OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "gurobi", "right hand side");
317         OSIUNITTEST_ASSERT_WARNING(siC1rr  == siC1.getRowRange(), {}, "gurobi", "row range");
318 
319 #if 0 // TODO: free rows not really supported by OsiGrb
320         // Change GUROBI Model by adding free row
321         OsiRowCut rc;
322         rc.setLb(-COIN_DBL_MAX);
323         rc.setUb( COIN_DBL_MAX);
324         OsiCuts cuts;
325         cuts.insert(rc);
326         siC1.applyCuts(cuts);
327 
328         // Since model was changed, test that cached data is now freed.
329         OSIUNITTEST_ASSERT_ERROR(siC1.obj_ == NULL, {}, "gurobi", "objective");
330         OSIUNITTEST_ASSERT_ERROR(siC1.collower_ == NULL, {}, "gurobi", "col lower");
331         OSIUNITTEST_ASSERT_ERROR(siC1.colupper_ == NULL, {}, "gurobi", "col upper");
332         OSIUNITTEST_ASSERT_ERROR(siC1.rowrange_ == NULL, {}, "gurobi", "free cached data after adding row");
333         OSIUNITTEST_ASSERT_ERROR(siC1.rowsense_ == NULL, {}, "gurobi", "free cached data after adding row");
334         OSIUNITTEST_ASSERT_ERROR(siC1.rowlower_ == NULL, {}, "gurobi", "row lower");
335         OSIUNITTEST_ASSERT_ERROR(siC1.rowupper_ == NULL, {}, "gurobi", "row upper");
336         OSIUNITTEST_ASSERT_ERROR(siC1.rhs_ == NULL, {}, "gurobi", "free cached data after adding row");
337         OSIUNITTEST_ASSERT_ERROR(siC1.matrixByRow_ == NULL, {}, "gurobi", "free cached data after adding row");
338         OSIUNITTEST_ASSERT_ERROR(siC1.matrixByCol_ == NULL, {}, "gurobi", "free cached data after adding row");
339         OSIUNITTEST_ASSERT_ERROR(siC1.colsol_ == NULL, {}, "gurobi", "free cached data after adding row");
340         OSIUNITTEST_ASSERT_ERROR(siC1.rowsol_ == NULL, {}, "gurobi", "free cached data after adding row");
341 
342         siC1rs  = siC1.getRowSense();
343         OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "gurobi", "row sense after adding row");
344         OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "gurobi", "row sense after adding row");
345         OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "gurobi", "row sense after adding row");
346         OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "gurobi", "row sense after adding row");
347         OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "gurobi", "row sense after adding row");
348         OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "gurobi", "row sense after adding row");
349 
350         siC1rhs = siC1.getRightHandSide();
351         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "gurobi", "right hand side after adding row");
352         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "gurobi", "right hand side after adding row");
353         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "gurobi", "right hand side after adding row");
354         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "gurobi", "right hand side after adding row");
355         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "gurobi", "right hand side after adding row");
356         OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "gurobi", "right hand side after adding row");
357 
358         siC1rr  = siC1.getRowRange();
359         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "gurobi", "row range after adding row");
360         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "gurobi", "row range after adding row");
361         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "gurobi", "row range after adding row");
362         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "gurobi", "row range after adding row");
363         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "gurobi", "row range after adding row");
364         OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "gurobi", "row range after adding row");
365 #endif
366         lhs = siC1;
367       }
368       // Test that lhs has correct values even though siC1 has gone out of scope
369       OSIUNITTEST_ASSERT_ERROR(lhs.obj_ == NULL, {}, "gurobi", "freed origin after assignment");
370       OSIUNITTEST_ASSERT_ERROR(lhs.collower_ == NULL, {}, "gurobi", "freed origin after assignment");
371       OSIUNITTEST_ASSERT_ERROR(lhs.colupper_ == NULL, {}, "gurobi", "freed origin after assignment");
372       OSIUNITTEST_ASSERT_ERROR(lhs.rowrange_ == NULL, {}, "gurobi", "freed origin after assignment");
373       OSIUNITTEST_ASSERT_ERROR(lhs.rowsense_ == NULL, {}, "gurobi", "freed origin after assignment");
374       OSIUNITTEST_ASSERT_ERROR(lhs.rowlower_ == NULL, {}, "gurobi", "freed origin after assignment");
375       OSIUNITTEST_ASSERT_ERROR(lhs.rowupper_ == NULL, {}, "gurobi", "freed origin after assignment");
376       OSIUNITTEST_ASSERT_ERROR(lhs.rhs_ == NULL, {}, "gurobi", "freed origin after assignment");
377       OSIUNITTEST_ASSERT_ERROR(lhs.matrixByRow_ == NULL, {}, "gurobi", "freed origin after assignment");
378       OSIUNITTEST_ASSERT_ERROR(lhs.matrixByCol_ == NULL, {}, "gurobi", "freed origin after assignment");
379 //TODO      OSIUNITTEST_ASSERT_ERROR(lhs.colsol_ != NULL, {}, "gurobi", "freed origin after assignment");
380 //TODO      OSIUNITTEST_ASSERT_ERROR(lhs.rowsol_ != NULL, {}, "gurobi", "freed origin after assignment");
381 
382 #if 0 // TODO: free rows not really supported by OsiGrb
383       const char * lhsrs  = lhs.getRowSense();
384       OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "gurobi", "row sense after assignment");
385       OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "gurobi", "row sense after assignment");
386       OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "gurobi", "row sense after assignment");
387       OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "gurobi", "row sense after assignment");
388       OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "gurobi", "row sense after assignment");
389       OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "gurobi", "row sense after assignment");
390 
391       const double * lhsrhs = lhs.getRightHandSide();
392       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "gurobi", "right hand side after assignment");
393       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "gurobi", "right hand side after assignment");
394       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "gurobi", "right hand side after assignment");
395       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "gurobi", "right hand side after assignment");
396       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "gurobi", "right hand side after assignment");
397       OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "gurobi", "right hand side after assignment");
398 
399       const double *lhsrr = lhs.getRowRange();
400       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "gurobi", "row range after assignment");
401       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "gurobi", "row range after assignment");
402       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "gurobi", "row range after assignment");
403       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "gurobi", "row range after assignment");
404       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "gurobi", "row range after assignment");
405       OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "gurobi", "row range after assignment");
406 
407       const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow();
408       OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "gurobi", "matrix by row after assignment");
409       OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim()    ==  6, return, "gurobi", "matrix by row after assignment: major dim");
410       OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "gurobi", "matrix by row after assignment: num elements");
411 
412       const double * ev = lhsmbr->getElements();
413       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "gurobi", "matrix by row after assignment: elements");
414       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "gurobi", "matrix by row after assignment: elements");
415       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "gurobi", "matrix by row after assignment: elements");
416       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "gurobi", "matrix by row after assignment: elements");
417       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "gurobi", "matrix by row after assignment: elements");
418       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "gurobi", "matrix by row after assignment: elements");
419       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "gurobi", "matrix by row after assignment: elements");
420       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "gurobi", "matrix by row after assignment: elements");
421       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "gurobi", "matrix by row after assignment: elements");
422       OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "gurobi", "matrix by row after assignment: elements");
423       OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "gurobi", "matrix by row after assignment: elements");
424       OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "gurobi", "matrix by row after assignment: elements");
425       OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "gurobi", "matrix by row after assignment: elements");
426       OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "gurobi", "matrix by row after assignment: elements");
427 
428       const CoinBigIndex * mi = lhsmbr->getVectorStarts();
429       OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "gurobi", "matrix by row after assignment: vector starts");
430       OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "gurobi", "matrix by row after assignment: vector starts");
431       OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "gurobi", "matrix by row after assignment: vector starts");
432       OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "gurobi", "matrix by row after assignment: vector starts");
433       OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "gurobi", "matrix by row after assignment: vector starts");
434       OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "gurobi", "matrix by row after assignment: vector starts");
435 
436       const int * ei = lhsmbr->getIndices();
437       OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "gurobi", "matrix by row after assignment: indices");
438       OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "gurobi", "matrix by row after assignment: indices");
439       OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "gurobi", "matrix by row after assignment: indices");
440       OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "gurobi", "matrix by row after assignment: indices");
441       OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "gurobi", "matrix by row after assignment: indices");
442       OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "gurobi", "matrix by row after assignment: indices");
443       OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "gurobi", "matrix by row after assignment: indices");
444       OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "gurobi", "matrix by row after assignment: indices");
445       OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "gurobi", "matrix by row after assignment: indices");
446       OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "gurobi", "matrix by row after assignment: indices");
447       OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "gurobi", "matrix by row after assignment: indices");
448       OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "gurobi", "matrix by row after assignment: indices");
449       OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "gurobi", "matrix by row after assignment: indices");
450       OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "gurobi", "matrix by row after assignment: indices");
451 #endif
452     }
453   }
454 
455   // Do common solverInterface testing by calling the
456   // base class testing method.
457   {
458     OsiGrbSolverInterface m;
459     OsiSolverInterfaceCommonUnitTest(&m, mpsDir, netlibDir);
460   }
461 }
462 #endif
463