source: trunk/Clp/test/OsiClpSolverInterfaceTest.cpp @ 1781

Last change on this file since 1781 was 1745, checked in by stefan, 8 years ago

remove now redundant counting of test failures; a bit more cleanup

File size: 59.8 KB
Line 
1// $Id$
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include "CoinPragma.hpp"
7
8//#include <cassert>
9//#include <cstdlib>
10//#include <cstdio>
11//#include <iostream>
12
13#include "OsiClpSolverInterface.hpp"
14#include "OsiUnitTests.hpp"
15#include "OsiCuts.hpp"
16#include "OsiRowCut.hpp"
17#include "OsiColCut.hpp"
18#include "CoinMessage.hpp"
19#include "ClpMessage.hpp"
20#include "ClpFactorization.hpp"
21#include "CoinModel.hpp"
22#include "CoinIndexedVector.hpp"
23
24//#############################################################################
25
26class OsiClpMessageTest :
27   public CoinMessageHandler {
28
29public:
30  virtual int print() ;
31  OsiClpMessageTest();
32};
33
34OsiClpMessageTest::OsiClpMessageTest() : CoinMessageHandler()
35{
36}
37int
38OsiClpMessageTest::print()
39{
40  if (currentMessage().externalNumber()==0&&currentSource()=="Clp") 
41    std::cout<<"This is not actually an advertisement by Dash Associates - just my feeble attempt to test message handling and language - JJHF"<<std::endl;
42  else if (currentMessage().externalNumber()==5&&currentSource()=="Osi") 
43    std::cout<<"End of search trapped"<<std::endl;
44  return CoinMessageHandler::print();
45}
46
47//--------------------------------------------------------------------------
48// test EKKsolution methods.
49void
50OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir)
51{
52  // Test default constructor
53  {
54    OsiClpSolverInterface m;
55    OSIUNITTEST_ASSERT_ERROR(m.rowsense_           == NULL, {}, "clp", "default constructor");
56    OSIUNITTEST_ASSERT_ERROR(m.rhs_                == NULL, {}, "clp", "default constructor");
57    OSIUNITTEST_ASSERT_ERROR(m.rowrange_           == NULL, {}, "clp", "default constructor");
58    OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_        == NULL, {}, "clp", "default constructor");
59    OSIUNITTEST_ASSERT_ERROR(m.ws_                 == NULL, {}, "clp", "default constructor");
60    OSIUNITTEST_ASSERT_ERROR(m.itlimOrig_       == 9999999, {}, "clp", "default constructor");
61    OSIUNITTEST_ASSERT_ERROR(m.lastAlgorithm_      == 0,    {}, "clp", "default constructor");
62    OSIUNITTEST_ASSERT_ERROR(m.integerInformation_ == NULL, {}, "clp", "default constructor");
63  }
64
65  {   
66    CoinRelFltEq eq;
67    OsiClpSolverInterface m;
68    std::string fn = mpsDir+"exmip1";
69    m.readMps(fn.c_str(),"mps");
70   
71    {
72      OsiClpSolverInterface im;   
73     
74      OSIUNITTEST_ASSERT_ERROR(im.getNumCols()  == 0,    {}, "clp", "default constructor");
75      OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "clp", "default constructor");
76
77      // Test reset
78      im.reset();
79      OSIUNITTEST_ASSERT_ERROR(im.rowsense_           == NULL, {}, "clp", "reset");
80      OSIUNITTEST_ASSERT_ERROR(im.rhs_                == NULL, {}, "clp", "reset");
81      OSIUNITTEST_ASSERT_ERROR(im.rowrange_           == NULL, {}, "clp", "reset");
82      OSIUNITTEST_ASSERT_ERROR(im.matrixByRow_        == NULL, {}, "clp", "reset");
83      OSIUNITTEST_ASSERT_ERROR(im.ws_                 == NULL, {}, "clp", "reset");
84      OSIUNITTEST_ASSERT_ERROR(im.itlimOrig_       == 9999999, {}, "clp", "reset");
85      OSIUNITTEST_ASSERT_ERROR(im.lastAlgorithm_      ==    0, {}, "clp", "reset");
86      OSIUNITTEST_ASSERT_ERROR(im.integerInformation_ == NULL, {}, "clp", "reset");
87    }
88   
89    // Test copy constructor and assignment operator
90    {
91      OsiClpSolverInterface lhs;
92      {     
93        OsiClpSolverInterface im(m);       
94       
95        OsiClpSolverInterface imC1(im);
96        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "clp", "copy constructor");
97        OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols()  == im.getNumCols(),  {}, "clp", "copy constructor");
98        OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows()  == im.getNumRows(),  {}, "clp", "copy constructor");
99       
100        OsiClpSolverInterface imC2(im);
101        OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "clp", "copy constructor");
102        OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols()  == im.getNumCols(),  {}, "clp", "copy constructor");
103        OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows()  == im.getNumRows(),  {}, "clp", "copy constructor");
104
105        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "clp", "copy constructor");
106       
107        lhs = imC2;
108      }
109
110      // Test that lhs has correct values even though rhs has gone out of scope
111      OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "clp", "assignment operator");
112      OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols()  == m.getNumCols(),  {}, "clp", "copy constructor");
113      OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows()  == m.getNumRows(),  {}, "clp", "copy constructor");
114    }
115
116    // Test clone
117    {
118      OsiClpSolverInterface clpSi(m);
119      OsiSolverInterface * siPtr = &clpSi;
120      OsiSolverInterface * siClone = siPtr->clone();
121      OsiClpSolverInterface * clpClone = dynamic_cast<OsiClpSolverInterface*>(siClone);
122     
123      OSIUNITTEST_ASSERT_ERROR(clpClone != NULL, {}, "clp", "clone");
124      OSIUNITTEST_ASSERT_ERROR(clpClone->getModelPtr() != clpSi.getModelPtr(), {}, "clp", "clone");
125      OSIUNITTEST_ASSERT_ERROR(clpClone->getNumRows() == clpSi.getNumRows(),   {}, "clp", "clone");
126      OSIUNITTEST_ASSERT_ERROR(clpClone->getNumCols() == m.getNumCols(),       {}, "clp", "clone");
127
128      delete siClone;
129    }
130 
131    // Test infinity
132    {
133      OsiClpSolverInterface si;
134      OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiClpInfinity, {}, "clp", "infinity");
135    }
136   
137    // Test some catches
138    if (!OsiClpHasNDEBUG())
139    {
140      OsiClpSolverInterface solver;
141      try {
142        solver.setObjCoeff(0,0.0);
143        OSIUNITTEST_ADD_OUTCOME("clp", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
144      }
145      catch (CoinError e) {
146        if (OsiUnitTest::verbosity >= 1)
147          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
148      }
149
150      std::string fn = mpsDir+"exmip1";
151      solver.readMps(fn.c_str(),"mps");
152      OSIUNITTEST_CATCH_ERROR(solver.setObjCoeff(0,0.0), {}, "clp", "setObjCoeff on nonempty model");
153
154      try {
155        int index[]={0,20};
156        double value[]={0.0,0.0,0.0,0.0};
157        solver.setColSetBounds(index,index+2,value);
158        OSIUNITTEST_ADD_OUTCOME("clp", "setColSetBounds on cols not in model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
159      }
160      catch (CoinError e) {
161        if (OsiUnitTest::verbosity >= 1)
162          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
163      }
164    }
165   
166    {
167      OsiClpSolverInterface clpSi(m);
168      int nc = clpSi.getNumCols();
169      int nr = clpSi.getNumRows();
170      const double * cl = clpSi.getColLower();
171      const double * cu = clpSi.getColUpper();
172      const double * rl = clpSi.getRowLower();
173      const double * ru = clpSi.getRowUpper();
174      OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "clp", "read and copy exmip1");
175      OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "clp", "read and copy exmip1");
176      OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "clp", "read and copy exmip1");
177      OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "clp", "read and copy exmip1");
178      OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "clp", "read and copy exmip1");
179      OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "clp", "read and copy exmip1");
180      OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "clp", "read and copy exmip1");
181      OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "clp", "read and copy exmip1");
182      OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "clp", "read and copy exmip1");
183      OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "clp", "read and copy exmip1");
184     
185      const double * cs = clpSi.getColSolution();
186      OSIUNITTEST_ASSERT_ERROR(eq(cs[0],2.5), {}, "clp", "read and copy exmip1");
187      OSIUNITTEST_ASSERT_ERROR(eq(cs[7],0.0), {}, "clp", "read and copy exmip1");
188     
189      OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "clp", "set col lower");
190      clpSi.setColLower( 3, 1.2345 );
191      OSIUNITTEST_ASSERT_ERROR( eq(cl[3],1.2345), {}, "clp", "set col lower");
192     
193      OSIUNITTEST_ASSERT_ERROR(!eq(clpSi.getColUpper()[4],10.2345), {}, "clp", "set col upper");
194      clpSi.setColUpper( 4, 10.2345 );
195      OSIUNITTEST_ASSERT_ERROR( eq(clpSi.getColUpper()[4],10.2345), {}, "clp", "set col upper");
196
197      double objValue = clpSi.getObjValue();
198      OSIUNITTEST_ASSERT_ERROR(eq(objValue,3.5), {}, "clp", "getObjValue() before solve");
199
200      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[0], 1.0), {}, "clp", "read and copy exmip1");
201      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[1], 0.0), {}, "clp", "read and copy exmip1");
202      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[2], 0.0), {}, "clp", "read and copy exmip1");
203      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[3], 0.0), {}, "clp", "read and copy exmip1");
204      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[4], 2.0), {}, "clp", "read and copy exmip1");
205      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[5], 0.0), {}, "clp", "read and copy exmip1");
206      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[6], 0.0), {}, "clp", "read and copy exmip1");
207      OSIUNITTEST_ASSERT_ERROR(eq(clpSi.getObjCoefficients()[7],-1.0), {}, "clp", "read and copy exmip1");
208    }
209   
210    // Test matrixByRow method
211    {
212      const OsiClpSolverInterface si(m);
213      const CoinPackedMatrix * smP = si.getMatrixByRow();
214
215      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  5, return, "clp", "getMatrixByRow: major dim");
216      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "clp", "getMatrixByRow: num elements");
217
218      CoinRelFltEq eq;
219      const double * ev = smP->getElements();
220      OSIUNITTEST_ASSERT_ERROR(eq(ev[0],   3.0), {}, "clp", "getMatrixByRow: elements");
221      OSIUNITTEST_ASSERT_ERROR(eq(ev[1],   1.0), {}, "clp", "getMatrixByRow: elements");
222      OSIUNITTEST_ASSERT_ERROR(eq(ev[2],  -2.0), {}, "clp", "getMatrixByRow: elements");
223      OSIUNITTEST_ASSERT_ERROR(eq(ev[3],  -1.0), {}, "clp", "getMatrixByRow: elements");
224      OSIUNITTEST_ASSERT_ERROR(eq(ev[4],  -1.0), {}, "clp", "getMatrixByRow: elements");
225      OSIUNITTEST_ASSERT_ERROR(eq(ev[5],   2.0), {}, "clp", "getMatrixByRow: elements");
226      OSIUNITTEST_ASSERT_ERROR(eq(ev[6],   1.1), {}, "clp", "getMatrixByRow: elements");
227      OSIUNITTEST_ASSERT_ERROR(eq(ev[7],   1.0), {}, "clp", "getMatrixByRow: elements");
228      OSIUNITTEST_ASSERT_ERROR(eq(ev[8],   1.0), {}, "clp", "getMatrixByRow: elements");
229      OSIUNITTEST_ASSERT_ERROR(eq(ev[9],   2.8), {}, "clp", "getMatrixByRow: elements");
230      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "clp", "getMatrixByRow: elements");
231      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],  5.6), {}, "clp", "getMatrixByRow: elements");
232      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],  1.0), {}, "clp", "getMatrixByRow: elements");
233      OSIUNITTEST_ASSERT_ERROR(eq(ev[13],  1.9), {}, "clp", "getMatrixByRow: elements");
234     
235      const int * mi = smP->getVectorStarts();
236      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "clp", "getMatrixByRow: vector starts");
237      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "clp", "getMatrixByRow: vector starts");
238      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "clp", "getMatrixByRow: vector starts");
239      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "clp", "getMatrixByRow: vector starts");
240      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "getMatrixByRow: vector starts");
241      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "getMatrixByRow: vector starts");
242     
243      const int * ei = smP->getIndices();
244      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "getMatrixByRow: indices");
245      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "getMatrixByRow: indices");
246      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "getMatrixByRow: indices");
247      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "getMatrixByRow: indices");
248      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "getMatrixByRow: indices");
249      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "getMatrixByRow: indices");
250      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "getMatrixByRow: indices");
251      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "getMatrixByRow: indices");
252      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "getMatrixByRow: indices");
253      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "getMatrixByRow: indices");
254      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "getMatrixByRow: indices");
255      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "getMatrixByRow: indices");
256      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "getMatrixByRow: indices");
257      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "getMatrixByRow: indices");
258    }
259
260    // Test adding several cuts
261    {
262      OsiClpSolverInterface fim;
263      std::string fn = mpsDir+"exmip1";
264      fim.readMps(fn.c_str(),"mps");
265      // exmip1.mps has 2 integer variables with index 2 & 3
266      fim.initialSolve();
267      OsiRowCut cuts[3];
268
269      // Generate one ineffective cut plus two trivial cuts
270      int c;
271      int nc = fim.getNumCols();
272      int *inx = new int[nc];
273      for (c=0;c<nc;c++) inx[c]=c;
274      double *el = new double[nc];
275      for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c);
276     
277      cuts[0].setRow(nc,inx,el);
278      cuts[0].setLb(-100.);
279      cuts[0].setUb(500.);
280      cuts[0].setEffectiveness(22);
281      el[4]=0.0; // to get inf later
282     
283      for (c=2;c<4;c++) {
284        el[0]=1.0;
285        inx[0]=c;
286        cuts[c-1].setRow(1,inx,el);
287        cuts[c-1].setLb(1.);
288        cuts[c-1].setUb(100.);
289        cuts[c-1].setEffectiveness(c);
290      }
291      fim.writeMps("x1.mps");
292      fim.applyRowCuts(3,cuts);
293      fim.writeMps("x2.mps");
294      // resolve - should get message about zero elements
295      fim.resolve();
296      fim.writeMps("x3.mps");
297      // check integer solution
298      const double * cs = fim.getColSolution();
299      CoinRelFltEq eq;
300      OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "clp", "add cuts");
301      OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "clp", "add cuts");
302      // check will find invalid matrix
303      el[0]=1.0/el[4];
304      inx[0]=0;
305      cuts[0].setRow(nc,inx,el);
306      cuts[0].setLb(-100.);
307      cuts[0].setUb(500.);
308      cuts[0].setEffectiveness(22);
309      fim.applyRowCut(cuts[0]);
310      // resolve - should get message about zero elements
311      fim.resolve();
312      OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "clp", "add cuts");
313      delete[]el;
314      delete[]inx;
315    }
316
317    // Test using bad basis
318    {
319      OsiClpSolverInterface fim;
320      std::string fn = mpsDir+"exmip1";
321      fim.readMps(fn.c_str(),"mps");
322      fim.initialSolve();
323      int numberRows = fim.getModelPtr()->numberRows();
324      int * rowStatus = new int[numberRows];
325      int numberColumns = fim.getModelPtr()->numberColumns();
326      int * columnStatus = new int[numberColumns];
327      fim.getBasisStatus(columnStatus,rowStatus);
328      for (int i=0; i<numberRows; i++)
329        rowStatus[i]=2;
330      fim.setBasisStatus(columnStatus,rowStatus);
331      fim.resolve();
332      delete [] rowStatus;
333      delete [] columnStatus;
334    }
335
336    // Test matrixByCol method
337    {
338      const OsiClpSolverInterface si(m);
339      const CoinPackedMatrix * smP = si.getMatrixByCol();
340     
341      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  8, return, "clp", "getMatrixByCol: major dim");
342      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim()    ==  5, return, "clp", "getMatrixByCol: minor dim");
343      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "clp", "getMatrixByCol: number of elements");
344      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "clp", "getMatrixByCol: vector starts size");
345
346      CoinRelFltEq eq;
347      const double * ev = smP->getElements();
348      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "getMatrixByCol: elements");
349      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "clp", "getMatrixByCol: elements");
350      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "clp", "getMatrixByCol: elements");
351      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "clp", "getMatrixByCol: elements");
352      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "clp", "getMatrixByCol: elements");
353      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "clp", "getMatrixByCol: elements");
354      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "clp", "getMatrixByCol: elements");
355      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "clp", "getMatrixByCol: elements");
356      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "clp", "getMatrixByCol: elements");
357      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "clp", "getMatrixByCol: elements");
358      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "clp", "getMatrixByCol: elements");
359      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "clp", "getMatrixByCol: elements");
360      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "clp", "getMatrixByCol: elements");
361      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "getMatrixByCol: elements");
362     
363      const CoinBigIndex * mi = smP->getVectorStarts();
364      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "clp", "getMatrixByCol: vector starts");
365      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  2, {}, "clp", "getMatrixByCol: vector starts");
366      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  4, {}, "clp", "getMatrixByCol: vector starts");
367      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  6, {}, "clp", "getMatrixByCol: vector starts");
368      OSIUNITTEST_ASSERT_ERROR(mi[4] ==  8, {}, "clp", "getMatrixByCol: vector starts");
369      OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "clp", "getMatrixByCol: vector starts");
370      OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "clp", "getMatrixByCol: vector starts");
371      OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "clp", "getMatrixByCol: vector starts");
372      OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "clp", "getMatrixByCol: vector starts");
373     
374      const int * ei = smP->getIndices();
375      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "getMatrixByCol: indices");
376      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "clp", "getMatrixByCol: indices");
377      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "clp", "getMatrixByCol: indices");
378      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "clp", "getMatrixByCol: indices");
379      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "clp", "getMatrixByCol: indices");
380      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "clp", "getMatrixByCol: indices");
381      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "clp", "getMatrixByCol: indices");
382      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "clp", "getMatrixByCol: indices");
383      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "clp", "getMatrixByCol: indices");
384      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "clp", "getMatrixByCol: indices");
385      OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "clp", "getMatrixByCol: indices");
386      OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "clp", "getMatrixByCol: indices");
387      OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "clp", "getMatrixByCol: indices");
388      OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "clp", "getMatrixByCol: indices");
389    }
390
391    //--------------
392    // Test rowsense, rhs, rowrange, matrixByRow
393    {
394      OsiClpSolverInterface lhs;
395      {     
396        OsiClpSolverInterface siC1(m);
397        OSIUNITTEST_ASSERT_WARNING(siC1.rowrange_ == NULL, {}, "clp", "row range");
398        OSIUNITTEST_ASSERT_WARNING(siC1.rowsense_ == NULL, {}, "clp", "row sense");
399        OSIUNITTEST_ASSERT_WARNING(siC1.rhs_ == NULL, {}, "clp", "right hand side");
400        OSIUNITTEST_ASSERT_WARNING(siC1.matrixByRow_ == NULL, {}, "clp", "matrix by row");
401
402        const char   * siC1rs  = siC1.getRowSense();
403        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "clp", "row sense");
404        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "clp", "row sense");
405        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "clp", "row sense");
406        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "clp", "row sense");
407        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "clp", "row sense");
408
409        const double * siC1rhs = siC1.getRightHandSide();
410        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "clp", "right hand side");
411        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "clp", "right hand side");
412        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "clp", "right hand side");
413        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "clp", "right hand side");
414        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "clp", "right hand side");
415
416        const double * siC1rr  = siC1.getRowRange();
417        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "clp", "row range");
418        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "clp", "row range");
419        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "clp", "row range");
420        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "clp", "row range");
421        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "clp", "row range");
422
423        const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow();
424        OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "clp", "matrix by row");
425        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim()    ==  5, return, "clp", "matrix by row: major dim");
426        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "clp", "matrix by row: num elements");
427
428        const double * ev = siC1mbr->getElements();
429        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "matrix by row: elements");
430        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "clp", "matrix by row: elements");
431        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "clp", "matrix by row: elements");
432        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "clp", "matrix by row: elements");
433        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "clp", "matrix by row: elements");
434        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "clp", "matrix by row: elements");
435        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "clp", "matrix by row: elements");
436        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "clp", "matrix by row: elements");
437        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "clp", "matrix by row: elements");
438        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "clp", "matrix by row: elements");
439        OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "clp", "matrix by row: elements");
440        OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "clp", "matrix by row: elements");
441        OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "clp", "matrix by row: elements");
442        OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "matrix by row: elements");
443
444        const CoinBigIndex * mi = siC1mbr->getVectorStarts();
445        OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "clp", "matrix by row: vector starts");
446        OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "clp", "matrix by row: vector starts");
447        OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "clp", "matrix by row: vector starts");
448        OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "clp", "matrix by row: vector starts");
449        OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "matrix by row: vector starts");
450        OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "matrix by row: vector starts");
451
452        const int * ei = siC1mbr->getIndices();
453        OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "matrix by row: indices");
454        OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "matrix by row: indices");
455        OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "matrix by row: indices");
456        OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "matrix by row: indices");
457        OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "matrix by row: indices");
458        OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "matrix by row: indices");
459        OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "matrix by row: indices");
460        OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "matrix by row: indices");
461        OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "matrix by row: indices");
462        OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "matrix by row: indices");
463        OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "matrix by row: indices");
464        OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "matrix by row: indices");
465        OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "matrix by row: indices");
466        OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "matrix by row: indices");
467
468        OSIUNITTEST_ASSERT_WARNING(siC1rs  == siC1.getRowSense(), {}, "clp", "row sense");
469        OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "clp", "right hand side");
470        OSIUNITTEST_ASSERT_WARNING(siC1rr  == siC1.getRowRange(), {}, "clp", "row range");
471
472        // Change CLP Model by adding free row
473        OsiRowCut rc;
474        rc.setLb(-COIN_DBL_MAX);
475        rc.setUb( COIN_DBL_MAX);
476        OsiCuts cuts;
477        cuts.insert(rc);
478        siC1.applyCuts(cuts);
479
480        // Since model was changed, test that cached data is now freed.
481        OSIUNITTEST_ASSERT_ERROR(siC1.rowrange_ == NULL, {}, "clp", "free cached data after adding row");
482        OSIUNITTEST_ASSERT_ERROR(siC1.rowsense_ == NULL, {}, "clp", "free cached data after adding row");
483        OSIUNITTEST_ASSERT_ERROR(siC1.rhs_ == NULL, {}, "clp", "free cached data after adding row");
484        // siC1.matrixByRow_ is updated, so it does not have to be NULL
485
486        siC1rs  = siC1.getRowSense();
487        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "clp", "row sense after adding row");
488        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "clp", "row sense after adding row");
489        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "clp", "row sense after adding row");
490        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "clp", "row sense after adding row");
491        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "clp", "row sense after adding row");
492        OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "clp", "row sense after adding row");
493
494        siC1rhs = siC1.getRightHandSide();
495        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "clp", "right hand side after adding row");
496        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "clp", "right hand side after adding row");
497        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "clp", "right hand side after adding row");
498        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "clp", "right hand side after adding row");
499        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "clp", "right hand side after adding row");
500        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "clp", "right hand side after adding row");
501
502        siC1rr  = siC1.getRowRange();
503        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "clp", "row range after adding row");
504        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "clp", "row range after adding row");
505        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "clp", "row range after adding row");
506        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "clp", "row range after adding row");
507        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "clp", "row range after adding row");
508        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "clp", "row range after adding row");
509
510        lhs = siC1;
511      }
512      // Test that lhs has correct values even though siC1 has gone out of scope
513      OSIUNITTEST_ASSERT_ERROR(lhs.rowrange_ == NULL, {}, "clp", "freed origin after assignment");
514      OSIUNITTEST_ASSERT_ERROR(lhs.rowsense_ == NULL, {}, "clp", "freed origin after assignment");
515      OSIUNITTEST_ASSERT_ERROR(lhs.rhs_ == NULL, {}, "clp", "freed origin after assignment");
516      OSIUNITTEST_ASSERT_ERROR(lhs.matrixByRow_ == NULL, {}, "clp", "freed origin after assignment");
517
518      const char * lhsrs  = lhs.getRowSense();
519      OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "clp", "row sense after assignment");
520      OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "clp", "row sense after assignment");
521      OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "clp", "row sense after assignment");
522      OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "clp", "row sense after assignment");
523      OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "clp", "row sense after assignment");
524      OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "clp", "row sense after assignment");
525     
526      const double * lhsrhs = lhs.getRightHandSide();
527      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "clp", "right hand side after assignment");
528      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "clp", "right hand side after assignment");
529      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "clp", "right hand side after assignment");
530      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "clp", "right hand side after assignment");
531      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "clp", "right hand side after assignment");
532      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "clp", "right hand side after assignment");
533     
534      const double *lhsrr = lhs.getRowRange();
535      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "clp", "row range after assignment");
536      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "clp", "row range after assignment");
537      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "clp", "row range after assignment");
538      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "clp", "row range after assignment");
539      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "clp", "row range after assignment");
540      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "clp", "row range after assignment");
541     
542      const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow();
543      OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "clp", "matrix by row after assignment");
544      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim()    ==  6, return, "clp", "matrix by row after assignment: major dim");
545      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "clp", "matrix by row after assignment: num elements");
546
547      const double * ev = lhsmbr->getElements();
548      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "matrix by row after assignment: elements");
549      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "clp", "matrix by row after assignment: elements");
550      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "clp", "matrix by row after assignment: elements");
551      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "clp", "matrix by row after assignment: elements");
552      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "clp", "matrix by row after assignment: elements");
553      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "clp", "matrix by row after assignment: elements");
554      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "clp", "matrix by row after assignment: elements");
555      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "clp", "matrix by row after assignment: elements");
556      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "clp", "matrix by row after assignment: elements");
557      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "clp", "matrix by row after assignment: elements");
558      OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "clp", "matrix by row after assignment: elements");
559      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "clp", "matrix by row after assignment: elements");
560      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "clp", "matrix by row after assignment: elements");
561      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "matrix by row after assignment: elements");
562     
563      const CoinBigIndex * mi = lhsmbr->getVectorStarts();
564      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "clp", "matrix by row after assignment: vector starts");
565      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "clp", "matrix by row after assignment: vector starts");
566      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "clp", "matrix by row after assignment: vector starts");
567      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "clp", "matrix by row after assignment: vector starts");
568      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "matrix by row after assignment: vector starts");
569      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "matrix by row after assignment: vector starts");
570     
571      const int * ei = lhsmbr->getIndices();
572      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "matrix by row after assignment: indices");
573      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "matrix by row after assignment: indices");
574      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "matrix by row after assignment: indices");
575      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "matrix by row after assignment: indices");
576      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "matrix by row after assignment: indices");
577      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "matrix by row after assignment: indices");
578      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "matrix by row after assignment: indices");
579      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "matrix by row after assignment: indices");
580      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "matrix by row after assignment: indices");
581      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "matrix by row after assignment: indices");
582      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "matrix by row after assignment: indices");
583      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "matrix by row after assignment: indices");
584      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "matrix by row after assignment: indices");
585      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "matrix by row after assignment: indices");
586    }
587  }
588
589  // Test add/delete columns
590  {   
591    OsiClpSolverInterface m;
592    std::string fn = mpsDir+"p0033";
593    m.readMps(fn.c_str(),"mps");
594    double inf = m.getInfinity();
595
596    CoinPackedVector c0;
597    c0.insert(0, 4);
598    c0.insert(1, 1);
599    m.addCol(c0, 0, inf, 3);
600    m.initialSolve();
601    double objValue = m.getObjValue();
602    CoinRelFltEq eq(1.0e-2);
603    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after adding col");
604
605    // Try deleting first column
606    int * d = new int[1];
607    d[0]=0;
608    m.deleteCols(1,d);
609    delete [] d;
610    d=NULL;
611    m.resolve();
612    objValue = m.getObjValue();
613    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting first col");
614
615    // Try deleting column we added
616    int iCol = m.getNumCols()-1;
617    m.deleteCols(1,&iCol);
618    m.resolve();
619    objValue = m.getObjValue();
620    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col");
621  }
622
623  // Test branch and bound
624  {   
625    OsiClpSolverInterface m;
626    std::string fn = mpsDir+"p0033";
627    m.readMps(fn.c_str(),"mps");
628    // reduce printout
629    m.setHintParam(OsiDoReducePrint,true,OsiHintTry);
630    // test maximization
631    int n  = m.getNumCols();
632    int i;
633    double * obj2 = new double[n];
634    const double * obj = m.getObjCoefficients();
635    for (i=0;i<n;i++) {
636      obj2[i]=-obj[i];
637    }
638    m.setObjective(obj2);
639    delete [] obj2;
640    m.setObjSense(-1.0);
641    // Save bounds
642    double * saveUpper = CoinCopyOfArray(m.getColUpper(),n);
643    double * saveLower = CoinCopyOfArray(m.getColLower(),n);
644    m.branchAndBound();
645    // reset bounds
646    m.setColUpper(saveUpper);
647    m.setColLower(saveLower);
648    delete [] saveUpper;
649    delete [] saveLower;
650    // reset cutoff - otherwise we won't get solution
651    m.setDblParam(OsiDualObjectiveLimit,-COIN_DBL_MAX);
652    m.branchAndBound();
653    double objValue = m.getObjValue();
654    CoinRelFltEq eq(1.0e-2);
655    OSIUNITTEST_ASSERT_ERROR(eq(objValue,-3089), {}, "clp", "branch and bound");
656    const double * cs = m.getColSolution();
657    if( OsiUnitTest::verbosity >= 2 )
658      for ( i=0;i<n;i++) {
659        if (cs[i]>1.0e-7)
660          printf("%d has value %g\n",i,cs[i]);
661    }
662  }
663
664  // Test infeasible bounds
665  {
666    OsiClpSolverInterface solver;
667    std::string fn = mpsDir+"exmip1";
668    solver.readMps(fn.c_str(),"mps");
669    int index[]={0};
670    double value[]={1.0,0.0};
671    solver.setColSetBounds(index,index+1,value);
672    solver.setHintParam(OsiDoPresolveInInitial, false, OsiHintDo);
673    solver.initialSolve();
674    OSIUNITTEST_ASSERT_ERROR(!solver.isProvenOptimal(), {}, "clp", "infeasible bounds");
675  }
676
677  // Build a model
678  {   
679    OsiClpSolverInterface model;
680    std::string fn = mpsDir+"p0033";
681    model.readMps(fn.c_str(),"mps");
682    // Point to data
683    int numberRows = model.getNumRows();
684    const double * rowLower = model.getRowLower();
685    const double * rowUpper = model.getRowUpper();
686    int numberColumns = model.getNumCols();
687    const double * columnLower = model.getColLower();
688    const double * columnUpper = model.getColUpper();
689    const double * columnObjective = model.getObjCoefficients();
690    // get row copy
691    CoinPackedMatrix rowCopy = *model.getMatrixByRow();
692    const int * column = rowCopy.getIndices();
693    const int * rowLength = rowCopy.getVectorLengths();
694    const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
695    const double * element = rowCopy.getElements();
696   
697    // solve
698    model.initialSolve();
699    // Now build new model
700    CoinModel build;
701    // Row bounds
702    int iRow;
703    for (iRow=0;iRow<numberRows;iRow++) {
704      build.setRowBounds(iRow,rowLower[iRow],rowUpper[iRow]);
705      build.setRowName(iRow,model.getRowName(iRow).c_str());
706    }
707    // Column bounds and objective
708    int iColumn;
709    for (iColumn=0;iColumn<numberColumns;iColumn++) {
710      build.setColumnLower(iColumn,columnLower[iColumn]);
711      build.setColumnUpper(iColumn,columnUpper[iColumn]);
712      build.setObjective(iColumn,columnObjective[iColumn]);
713      build.setColumnName(iColumn,model.getColName(iColumn).c_str());
714    }
715    // Adds elements one by one by row (backwards by row)
716    for (iRow=numberRows-1;iRow>=0;iRow--) {
717      int start = rowStart[iRow];
718      for (int j=start;j<start+rowLength[iRow];j++) 
719        build(iRow,column[j],element[j]);
720    }
721    // Now create Model
722    OsiClpSolverInterface model2;
723    model2.loadFromCoinModel(build);
724    model2.initialSolve();
725    // Save - should be continuous
726    model2.writeMps("continuous");
727    int * whichInteger = new int[numberColumns];
728    for (iColumn=0;iColumn<numberColumns;iColumn++) 
729      whichInteger[iColumn]=iColumn;
730    // mark as integer
731    model2.setInteger(whichInteger,numberColumns);
732    delete [] whichInteger;
733    // save - should be integer
734    model2.writeMps("integer");
735    // check names are there
736    if (OsiUnitTest::verbosity >= 1)
737      for (iColumn=0;iColumn<numberColumns;iColumn++)
738        printf("%d name %s\n",iColumn,model2.getColName(iColumn).c_str());
739   
740    // Now do with strings attached
741    // Save build to show how to go over rows
742    CoinModel saveBuild = build;
743    build = CoinModel();
744    // Column bounds
745    for (iColumn=0;iColumn<numberColumns;iColumn++) {
746      build.setColumnLower(iColumn,columnLower[iColumn]);
747      build.setColumnUpper(iColumn,columnUpper[iColumn]);
748    }
749    // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
750    // Pick up from saveBuild (for no reason at all)
751    for (iColumn=0;iColumn<numberColumns;iColumn++) {
752      double value = saveBuild.objective(iColumn);
753      if (iColumn*2<numberColumns) {
754        build.setObjective(iColumn,columnObjective[iColumn]);
755      } else {
756        // create as string
757        char temp[100];
758        sprintf(temp,"%g + abs(%g*multiplier)",value,value);
759        build.setObjective(iColumn,temp);
760      }
761    }
762    // It then adds rows one by one but for half the rows sets their values
763    //      with multiplier of "1.0+1.5*multiplier"
764    for (iRow=0;iRow<numberRows;iRow++) {
765      if (iRow*2<numberRows) {
766        // add row in simple way
767        int start = rowStart[iRow];
768        build.addRow(rowLength[iRow],column+start,element+start,
769                     rowLower[iRow],rowUpper[iRow]);
770      } else {
771        // As we have to add one by one let's get from saveBuild
772        CoinModelLink triple=saveBuild.firstInRow(iRow);
773        while (triple.column()>=0) {
774          int iColumn = triple.column();
775          if (iColumn*2<numberColumns) {
776            // just value as normal
777            build(iRow,triple.column(),triple.value());
778          } else {
779            // create as string
780            char temp[100];
781            sprintf(temp,"%g + (1.5*%g*multiplier)",triple.value(), triple.value());
782            build(iRow,iColumn,temp);
783          }
784          triple=saveBuild.next(triple);
785        }
786        // but remember to do rhs
787        build.setRowLower(iRow,rowLower[iRow]);
788        build.setRowUpper(iRow,rowUpper[iRow]);
789      }
790    }
791    // If small switch on error printing
792    if (numberColumns<50)
793      build.setLogLevel(1);
794    // should fail as we never set multiplier
795    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) != 0, {}, "clp", "build model with missing multipliers");
796    build.associateElement("multiplier",0.0);
797    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) == 0, {}, "clp", "build model");
798    model2.initialSolve();
799    // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
800    for (double multiplier=0.0;multiplier<2.0;multiplier+= 0.1) {
801      build.associateElement("multiplier",multiplier);
802      OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build,true) == 0, {}, "clp", "build model with increasing multiplier");
803      model2.resolve();
804    }
805  }
806
807  // Solve an lp by hand
808  {   
809    OsiClpSolverInterface m;
810    std::string fn = mpsDir+"p0033";
811    m.readMps(fn.c_str(),"mps");
812    m.setObjSense(-1.0);
813    m.getModelPtr()->messageHandler()->setLogLevel(4);
814    m.initialSolve();
815    m.getModelPtr()->factorization()->maximumPivots(5);
816    m.setObjSense(1.0);
817    // clone to test pivot as well as primalPivot
818    OsiSolverInterface * mm =m.clone();
819    // enable special mode
820    m.enableSimplexInterface(true);
821    // need to do after clone
822    mm->enableSimplexInterface(true);
823    // we happen to know that variables are 0-1 and rows are L
824    int numberIterations=0;
825    int numberColumns = m.getNumCols();
826    int numberRows = m.getNumRows();
827    double * fakeCost = new double[numberColumns];
828    double * duals = new double [numberRows];
829    double * djs = new double [numberColumns];
830    const double * solution = m.getColSolution();
831    memcpy(fakeCost,m.getObjCoefficients(),numberColumns*sizeof(double));
832    while (1) {
833      const double * dj;
834      const double * dual;
835      if ((numberIterations&1)==0) {
836        // use given ones
837        dj = m.getReducedCost();
838        dual = m.getRowPrice();
839      } else {
840        // create
841        dj = djs;
842        dual = duals;
843        m.getReducedGradient(djs,duals,fakeCost);
844      }
845      int i;
846      int colIn=9999;
847      int direction=1;
848      double best=1.0e-6;
849      // find most negative reduced cost
850      // Should check basic - but should be okay on this problem
851      for (i=0;i<numberRows;i++) {
852        double value=dual[i];
853        if (value>best) {
854          direction=-1;
855          best=value;
856          colIn=-i-1;
857        }
858      }
859      for (i=0;i<numberColumns;i++) {
860        double value=dj[i];
861        if (value<-best&&solution[i]<1.0e-6) {
862          direction=1;
863          best=-value;
864          colIn=i;
865        } else if (value>best&&solution[i]>1.0-1.0e-6) {
866          direction=-1;
867          best=value;
868          colIn=i;
869        }
870      }
871      if (colIn==9999)
872        break; // should be optimal
873      int colOut;
874      int outStatus;
875      double theta;
876      OSIUNITTEST_ASSERT_ERROR(m.primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL) == 0, {}, "clp", "solve model by hand");
877      if (OsiUnitTest::verbosity >= 1)
878        printf("out %d, direction %d theta %g\n", colOut,outStatus,theta);
879      if (colIn!=colOut) {
880        OSIUNITTEST_ASSERT_ERROR(mm->pivot(colIn,colOut,outStatus) >= 0, {}, "clp", "solve model by hand");
881      } else {
882        // bound flip (so pivot does not make sense)
883        OSIUNITTEST_ASSERT_ERROR(mm->primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL) == 0, {}, "clp", "solve model by hand");
884      }
885      numberIterations++;
886    }
887    delete mm;
888    delete [] fakeCost;
889    delete [] duals;
890    delete [] djs;
891    // exit special mode
892    m.disableSimplexInterface();
893    m.getModelPtr()->messageHandler()->setLogLevel(4);
894    m.messageHandler()->setLogLevel(0);
895    m.resolve();
896    OSIUNITTEST_ASSERT_ERROR(m.getIterationCount() == 0, {}, "clp", "resolve after solving model by hand");
897    m.setObjSense(-1.0);
898    m.initialSolve();
899  }
900
901# if 0
902/*
903  This section stops working without setObjectiveAndRefresh. Assertion failure
904  down in the guts of clp, likely due to reduced costs not properly updated.
905  Leave the code in for a bit so it's easily recoverable if anyone actually
906  yells about the loss. There was no response to a public announcement
907  of intent to delete, but sometimes it takes a whack on the head to get
908  peoples' attention. At some point, it'd be good to come back through and
909  make this work again. -- lh, 100828 --
910*/
911  // Do parametrics on the objective by hand
912  {
913    std::cout << " Beginning Osi Simplex mode 2 ... " << std::endl ;
914    OsiClpSolverInterface m;
915    std::string fn = mpsDir+"p0033";
916    m.readMps(fn.c_str(),"mps");
917    ClpSimplex * simplex = m.getModelPtr();
918    simplex->messageHandler()->setLogLevel(4);
919    m.initialSolve();
920    simplex->factorization()->maximumPivots(5);
921    simplex->messageHandler()->setLogLevel(63);
922    m.setObjSense(1.0);
923    // enable special mode
924    m.enableSimplexInterface(true);
925    int numberIterations=0;
926    int numberColumns = m.getNumCols();
927    int numberRows = m.getNumRows();
928    double * changeCost = new double[numberColumns];
929    double * duals = new double [numberRows];
930    double * djs = new double [numberColumns];
931    // As getReducedGradient mucks about with innards of Clp get arrays to save
932    double * dualsNow = new double [numberRows];
933    double * djsNow = new double [numberColumns];
934   
935    const double * solution = m.getColSolution();
936    int i;
937    // Set up change cost
938    for (i=0;i<numberColumns;i++)
939      changeCost[i]=1.0+0.1*i;;
940    // Range of investigation
941    double totalChange=100.0;
942    double totalDone=0.0;
943    while (true) {
944      std::cout << " Starting iterations ... " << std::endl ;
945      // Save current
946      // (would be more accurate to start from scratch)
947      memcpy(djsNow, m.getReducedCost(),numberColumns*sizeof(double));
948      memcpy(dualsNow,m.getRowPrice(),numberRows*sizeof(double));
949      // Get reduced gradient of changeCost
950      m.getReducedGradient(djs,duals,changeCost);
951      int colIn=9999;
952      int direction=1;
953      // We are going up to totalChange but we have done some
954      double best=totalChange-totalDone;
955      // find best ratio
956      // Should check basic - but should be okay on this problem
957      // We are cheating here as we know L rows
958      // Really should be using L and U status but I modified from previous example
959      for (i=0;i<numberRows;i++) {
960        if (simplex->getRowStatus(i)==ClpSimplex::basic) {
961          assert (fabs(dualsNow[i])<1.0e-4&&fabs(duals[i])<1.0e-4);
962        } else {
963          assert (dualsNow[i]<1.0e-4);
964          if (duals[i]>1.0e-8) {
965            if (dualsNow[i]+best*duals[i]>0.0) {
966              best = CoinMax(-dualsNow[i]/duals[i],0.0);
967              direction=-1;
968              colIn=-i-1;
969            }
970          }
971        }
972      }
973      for (i=0;i<numberColumns;i++) {
974        if (simplex->getColumnStatus(i)==ClpSimplex::basic) {
975          assert (fabs(djsNow[i])<1.0e-4&&fabs(djs[i])<1.0e-4);
976        } else {
977          if (solution[i]<1.0e-6) {
978            assert (djsNow[i]>-1.0e-4);
979            if (djs[i]<-1.0e-8) {
980              if (djsNow[i]+best*djs[i]<0.0) {
981                best = CoinMax(-djsNow[i]/djs[i],0.0);
982                direction=1;
983                colIn=i;
984              }
985            }
986          } else if (solution[i]>1.0-1.0e-6) {
987            assert (djsNow[i]<1.0e-4);
988            if (djs[i]>1.0e-8) {
989              if (djsNow[i]+best*djs[i]>0.0) {
990                best = CoinMax(-djsNow[i]/djs[i],0.0);
991                direction=-1;
992                colIn=i;
993              }
994            }
995          }
996        }
997      }
998      if (colIn==9999)
999        break; // should be optimal
1000      // update objective - djs is spare array
1001      const double * obj = m.getObjCoefficients();
1002      for (i=0;i<numberColumns;i++) {
1003        djs[i]=obj[i]+best*changeCost[i];
1004      }
1005      totalDone += best;
1006      printf("Best change %g, total %g\n",best,totalDone);
1007      m.setObjectiveAndRefresh(djs);
1008      int colOut;
1009      int outStatus;
1010      double theta;
1011      int returnCode=m.primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL);
1012      assert (!returnCode);
1013      double objValue = m.getObjValue(); // printed one may not be accurate
1014      printf("in %d out %d, direction %d theta %g, objvalue %g\n",
1015             colIn,colOut,outStatus,theta,objValue);
1016      numberIterations++;
1017    }
1018    // update objective to totalChange- djs is spare array
1019    const double * obj = m.getObjCoefficients();
1020    double best = totalChange-totalDone;
1021    for (i=0;i<numberColumns;i++) {
1022      djs[i]=obj[i]+best*changeCost[i];
1023    }
1024    delete [] changeCost;
1025    delete [] duals;
1026    delete [] djs;
1027    delete [] dualsNow;
1028    delete [] djsNow;
1029    // exit special mode
1030    std::cout << " Finished simplex mode 2 ; checking result." << std::endl ;
1031    m.disableSimplexInterface();
1032    simplex->messageHandler()->setLogLevel(4);
1033    m.resolve();
1034    assert (!m.getIterationCount());
1035  }
1036# endif
1037
1038  // Solve an lp when interface is on
1039  {   
1040    OsiClpSolverInterface m;
1041    std::string fn = mpsDir+"p0033";
1042    m.readMps(fn.c_str(),"mps");
1043    // enable special mode
1044    m.setHintParam(OsiDoScale,false,OsiHintDo);
1045    m.setHintParam(OsiDoPresolveInInitial,false,OsiHintDo);
1046    m.setHintParam(OsiDoDualInInitial,false,OsiHintDo);
1047    m.setHintParam(OsiDoPresolveInResolve,false,OsiHintDo);
1048    m.setHintParam(OsiDoDualInResolve,false,OsiHintDo);
1049    m.enableSimplexInterface(true);
1050    m.initialSolve();
1051  }
1052
1053  // Check tableau stuff when simplex interface is on
1054  {   
1055    OsiClpSolverInterface m;
1056    /*
1057       Wolsey : Page 130
1058       max 4x1 -  x2
1059       7x1 - 2x2    <= 14
1060       x2    <= 3
1061       2x1 - 2x2    <= 3
1062       x1 in Z+, x2 >= 0
1063    */
1064   
1065    double inf_ = m.getInfinity();
1066    int n_cols = 2;
1067    int n_rows = 3;
1068   
1069    double obj[2] = {-4.0, 1.0};
1070    double collb[2] = {0.0, 0.0};
1071    double colub[2] = {inf_, inf_};
1072    double rowlb[3] = {-inf_, -inf_, -inf_};
1073    double rowub[3] = {14.0, 3.0, 3.0};
1074   
1075    int rowIndices[5] =  {0,     2,    0,    1,    2};
1076    int colIndices[5] =  {0,     0,    1,    1,    1};
1077    double elements[5] = {7.0, 2.0, -2.0,  1.0, -2.0};
1078    CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5);
1079   
1080    m.loadProblem(M, collb, colub, obj, rowlb, rowub);
1081    m.enableSimplexInterface(true);
1082   
1083    m.initialSolve();
1084   
1085    //check that the tableau matches wolsey (B-1 A)
1086    // slacks in second part of binvA
1087    double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double));
1088   
1089    if (OsiUnitTest::verbosity >= 2)
1090      printf("B-1 A");
1091    int i;
1092    for( i = 0; i < n_rows; i++){
1093      m.getBInvARow(i, binvA,binvA+n_cols);
1094      if (OsiUnitTest::verbosity >= 2) {
1095        printf("\nrow: %d -> ",i);
1096        for(int j=0; j < n_cols+n_rows; j++)
1097          printf("%g, ", binvA[j]);
1098      }
1099    }
1100    if (OsiUnitTest::verbosity >= 2) {
1101      printf("\n");
1102      printf("And by column");
1103    }
1104    for( i = 0; i < n_cols+n_rows; i++){
1105      m.getBInvACol(i, binvA);
1106      if (OsiUnitTest::verbosity >= 2) {
1107        printf("\ncolumn: %d -> ",i);
1108        for(int j=0; j < n_rows; j++)
1109          printf("%g, ", binvA[j]);
1110      }
1111    }
1112    if (OsiUnitTest::verbosity >= 2)
1113      printf("\n");
1114
1115    // and when doing as expert
1116    m.setSpecialOptions(m.specialOptions()|512);
1117    ClpSimplex * clp = m.getModelPtr();
1118    /* Do twice -
1119       first time with enableSimplexInterface still set
1120       then without and with scaling
1121    */
1122    for (int iPass=0;iPass<2;iPass++) {
1123      const double * rowScale = clp->rowScale();
1124      const double * columnScale = clp->columnScale();
1125#     if 0
1126      if (!iPass)
1127        assert (!rowScale);
1128      else
1129        assert (rowScale); // only true for this example
1130#     endif
1131      /* has to be exactly correct as in OsiClpsolverInterface.cpp
1132         (also redo each pass as may change
1133      */
1134      CoinIndexedVector * rowArray = clp->rowArray(1);
1135      CoinIndexedVector * columnArray = clp->columnArray(0);
1136      int n;
1137      int * which;
1138      double * array;
1139      if (OsiUnitTest::verbosity >= 2)
1140        printf("B-1 A");
1141      for( i = 0; i < n_rows; i++){
1142        m.getBInvARow(i, binvA,binvA+n_cols);
1143        if (OsiUnitTest::verbosity >= 2)
1144          printf("\nrow: %d -> ",i);
1145        int j;
1146        // First columns
1147        n = columnArray->getNumElements();
1148        which = columnArray->getIndices();
1149        array = columnArray->denseVector();
1150        for(j=0; j < n; j++){
1151          int k=which[j];
1152          if (OsiUnitTest::verbosity >= 2) {
1153            if (!columnScale) {
1154              printf("(%d %g), ", k, array[k]);
1155            } else {
1156              printf("(%d %g), ", k, array[k]/columnScale[k]);
1157            }
1158          }
1159          // zero out
1160          array[k]=0.0;
1161        }
1162        // say empty
1163        columnArray->setNumElements(0);
1164        // and check (would not be in any production code)
1165        columnArray->checkClear();
1166        // now rows
1167        n = rowArray->getNumElements();
1168        which = rowArray->getIndices();
1169        array = rowArray->denseVector();
1170        for(j=0; j < n; j++){
1171          int k=which[j];
1172          if (OsiUnitTest::verbosity >= 2) {
1173            if (!rowScale) {
1174              printf("(%d %g), ", k+n_cols, array[k]);
1175            } else {
1176              printf("(%d %g), ", k+n_cols, array[k]*rowScale[k]);
1177            }
1178          }
1179          // zero out
1180          array[k]=0.0;
1181        }
1182        // say empty
1183        rowArray->setNumElements(0);
1184        // and check (would not be in any production code)
1185        rowArray->checkClear();
1186      }
1187      if (OsiUnitTest::verbosity >= 2) {
1188        printf("\n");
1189        printf("And by column (trickier)");
1190      }
1191      const int * pivotVariable = clp->pivotVariable();
1192      for( i = 0; i < n_cols+n_rows; i++){
1193        m.getBInvACol(i, binvA);
1194        if (OsiUnitTest::verbosity >= 2)
1195          printf("\ncolumn: %d -> ",i);
1196        n = rowArray->getNumElements();
1197        which = rowArray->getIndices();
1198        array = rowArray->denseVector();
1199        for(int j=0; j < n; j++){
1200          int k=which[j];
1201          // need to know pivot variable for +1/-1 (slack) and row/column scaling
1202          int pivot = pivotVariable[k];
1203          if (OsiUnitTest::verbosity >= 2) {
1204            if (pivot<n_cols) {
1205              // scaled coding is in just in case
1206              if (!columnScale) {
1207                printf("(%d %g), ", k, array[k]);
1208              } else {
1209                printf("(%d %g), ", k, array[k]*columnScale[pivot]);
1210              }
1211            } else {
1212              if (!rowScale) {
1213                printf("(%d %g), ", k, -array[k]);
1214              } else {
1215                printf("(%d %g), ", k, -array[k]/rowScale[pivot-n_cols]);
1216              }
1217            }
1218          }
1219          // zero out
1220          array[k]=0.0;
1221        }
1222        // say empty
1223        rowArray->setNumElements(0);
1224        // and check (would not be in any production code)
1225        rowArray->checkClear();
1226      }
1227      if (OsiUnitTest::verbosity >= 2)
1228        printf("\n");
1229      // now deal with next pass
1230      if (!iPass) {
1231        m.disableSimplexInterface();
1232        // see if we can get scaling for testing
1233        clp->scaling(1);
1234        m.enableFactorization();
1235      } else {
1236        // may not be needed - but cleaner
1237        m.disableFactorization();
1238      }
1239    }
1240    m.setSpecialOptions(m.specialOptions()&~512);
1241    free(binvA);
1242    // Do using newer interface
1243    m.enableFactorization();
1244    {
1245      CoinIndexedVector * rowArray = new CoinIndexedVector(n_rows);
1246      CoinIndexedVector * columnArray = new CoinIndexedVector(n_cols);
1247      int n;
1248      int * which;
1249      double * array;
1250      if (OsiUnitTest::verbosity >= 2)
1251        printf("B-1 A");
1252      for( i = 0; i < n_rows; i++){
1253        m.getBInvARow(i, columnArray,rowArray);
1254        if (OsiUnitTest::verbosity >= 2)
1255          printf("\nrow: %d -> ",i);
1256        int j;
1257        // First columns
1258        n = columnArray->getNumElements();
1259        which = columnArray->getIndices();
1260        array = columnArray->denseVector();
1261        for(j=0; j < n; j++){
1262          int k=which[j];
1263          if (OsiUnitTest::verbosity >= 2)
1264            printf("(%d %g), ", k, array[k]);
1265          // zero out
1266          array[k]=0.0;
1267        }
1268        // say empty (if I had not zeroed array[k] I would use ->clear())
1269        columnArray->setNumElements(0);
1270        // and check (would not be in any production code)
1271        columnArray->checkClear();
1272        // now rows
1273        n = rowArray->getNumElements();
1274        which = rowArray->getIndices();
1275        array = rowArray->denseVector();
1276        for(j=0; j < n; j++){
1277          int k=which[j];
1278          if (OsiUnitTest::verbosity >= 2)
1279            printf("(%d %g), ", k+n_cols, array[k]);
1280          // zero out
1281          array[k]=0.0;
1282        }
1283        // say empty
1284        rowArray->setNumElements(0);
1285        // and check (would not be in any production code)
1286        rowArray->checkClear();
1287      }
1288      if (OsiUnitTest::verbosity >= 2) {
1289        printf("\n");
1290        printf("And by column");
1291      }
1292      for( i = 0; i < n_cols+n_rows; i++){
1293        m.getBInvACol(i, rowArray);
1294        if (OsiUnitTest::verbosity >= 2)
1295          printf("\ncolumn: %d -> ",i);
1296        n = rowArray->getNumElements();
1297        which = rowArray->getIndices();
1298        array = rowArray->denseVector();
1299        for(int j=0; j < n; j++){
1300          int k=which[j];
1301          if (OsiUnitTest::verbosity >= 2)
1302            printf("(%d %g), ", k, array[k]);
1303          // zero out
1304          array[k]=0.0;
1305        }
1306        // say empty
1307        rowArray->setNumElements(0);
1308        // and check (would not be in any production code)
1309        rowArray->checkClear();
1310      }
1311      if (OsiUnitTest::verbosity >= 2)
1312        printf("\n");
1313      delete rowArray;
1314      delete columnArray;
1315    }
1316    // may not be needed - but cleaner
1317    m.disableFactorization();
1318  }
1319
1320  // Check tableau stuff when simplex interface is off
1321  {   
1322    OsiClpSolverInterface m;
1323    /*
1324       Wolsey : Page 130
1325       max 4x1 -  x2
1326       7x1 - 2x2    <= 14
1327       x2    <= 3
1328       2x1 - 2x2    <= 3
1329       x1 in Z+, x2 >= 0
1330    */
1331   
1332    double inf_ = m.getInfinity();
1333    int n_cols = 2;
1334    int n_rows = 3;
1335   
1336    double obj[2] = {-4.0, 1.0};
1337    double collb[2] = {0.0, 0.0};
1338    double colub[2] = {inf_, inf_};
1339    double rowlb[3] = {-inf_, -inf_, -inf_};
1340    double rowub[3] = {14.0, 3.0, 3.0};
1341   
1342    int rowIndices[5] =  {0,     2,    0,    1,    2};
1343    int colIndices[5] =  {0,     0,    1,    1,    1};
1344    double elements[5] = {7.0, 2.0, -2.0,  1.0, -2.0};
1345    CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5);
1346   
1347    m.loadProblem(M, collb, colub, obj, rowlb, rowub);
1348    // Test with scaling
1349    m.setHintParam(OsiDoScale,true);
1350    // Tell code to keep factorization
1351    m.setupForRepeatedUse(3,0);
1352   
1353    m.initialSolve();
1354    // Repeated stuff only in resolve
1355    // m.resolve(); (now in both (just for (3,0))
1356   
1357    //check that the tableau matches wolsey (B-1 A)
1358    // slacks in second part of binvA
1359    double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double));
1360    // and getBasics
1361    int * pivots = new int[n_rows];
1362    m.getBasics(pivots);
1363   
1364    if (OsiUnitTest::verbosity >= 2)
1365      printf("B-1 A");
1366    int i;
1367    for( i = 0; i < n_rows; i++){
1368      m.getBInvARow(i, binvA,binvA+n_cols);
1369      if (OsiUnitTest::verbosity >= 2) {
1370        printf("\nrow: %d (pivot %d) -> ",i,pivots[i]);
1371        for(int j=0; j < n_cols+n_rows; j++)
1372          printf("%g, ", binvA[j]);
1373      }
1374    }
1375    if (OsiUnitTest::verbosity >= 2) {
1376      printf("\n");
1377      printf("And by column");
1378    }
1379    for( i = 0; i < n_cols+n_rows; i++){
1380      m.getBInvACol(i, binvA);
1381      if (OsiUnitTest::verbosity >= 2) {
1382        printf("\ncolumn: %d -> ",i);
1383        for(int j=0; j < n_rows; j++)
1384          printf("%g, ", binvA[j]);
1385      }
1386    }
1387    if (OsiUnitTest::verbosity >= 2)
1388      printf("\n");
1389    free(binvA);
1390    delete [] pivots;
1391  }
1392
1393  // Do common solverInterface testing
1394  {
1395    OsiClpSolverInterface m;
1396    OsiSolverInterfaceCommonUnitTest(&m, mpsDir, netlibDir);
1397  }
1398}
Note: See TracBrowser for help on using the repository browser.