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

Last change on this file since 1740 was 1740, checked in by stefan, 9 years ago

convert osi unittest to use new TestOutcomes? facility

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