source: trunk/Cbc/test/OsiCbcSolverInterfaceTest.cpp @ 1574

Last change on this file since 1574 was 1574, checked in by lou, 8 years ago

Change to EPL license notice.

File size: 31.9 KB
Line 
1// $Id$
2// Copyright (C) 2005, 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#if defined(_MSC_VER)
7// Turn off compiler warning about long names
8#  pragma warning(disable:4786)
9#endif
10
11#ifdef NDEBUG
12#undef NDEBUG
13#endif
14
15#include "OsiConfig.h"
16
17#include <cassert>
18//#include <cstdlib>
19//#include <cstdio>
20//#include <iostream>
21
22#include "OsiCbcSolverInterface.hpp"
23#include "OsiCuts.hpp"
24#include "OsiRowCut.hpp"
25#include "OsiColCut.hpp"
26#include "CoinMessage.hpp"
27#include "CoinModel.hpp"
28#ifdef COIN_HAS_OSL
29#include "OsiOslSolverInterface.hpp"
30#endif
31
32//#############################################################################
33
34namespace {
35CoinPackedMatrix &BuildExmip1Mtx ()
36/*
37  Simple function to build a packed matrix for the exmip1 example used in
38  tests. The function exists solely to hide the intermediate variables.
39  Probably could be written as an initialised declaration.
40  See COIN/Mps/Sample/exmip1.mps for a human-readable presentation.
41
42  Ordered triples seem easiest. They're listed in row-major order.
43*/
44
45{ int rowndxs[] = { 0, 0, 0, 0, 0,
46                    1, 1,
47                    2, 2,
48                    3, 3,
49                    4, 4, 4 } ;
50  int colndxs[] = { 0, 1, 3, 4, 7,
51                    1, 2,
52                    2, 5,
53                    3, 6,
54                    0, 4, 7 } ;
55  double coeffs[] = { 3.0, 1.0, -2.0, -1.0, -1.0,
56                      2.0, 1.1,
57                      1.0, 1.0,
58                      2.8, -1.2,
59                      5.6, 1.0, 1.9 } ;
60
61  static CoinPackedMatrix exmip1mtx =
62    CoinPackedMatrix(true,&rowndxs[0],&colndxs[0],&coeffs[0],14) ;
63
64  return (exmip1mtx) ; }
65}
66
67//--------------------------------------------------------------------------
68// test solution methods.
69int
70OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir)
71{
72 
73 
74  {   
75    CoinRelFltEq eq;
76    OsiCbcSolverInterface m;
77    std::string fn = mpsDir+"exmip1";
78    m.readMps(fn.c_str(),"mps");
79
80    {
81      OsiCbcSolverInterface im;   
82     
83      assert( im.getNumCols() == 0 ); 
84     
85      assert( im.getModelPtr()!=NULL );
86    }
87   
88    // Test copy constructor and assignment operator
89    {
90      OsiCbcSolverInterface lhs;
91      {     
92        OsiCbcSolverInterface im(m);       
93       
94        OsiCbcSolverInterface imC1(im);
95        assert( imC1.getModelPtr()!=im.getModelPtr() );
96        assert( imC1.getNumCols() == im.getNumCols() );
97        assert( imC1.getNumRows() == im.getNumRows() );   
98       
99        OsiCbcSolverInterface imC2(im);
100        assert( imC2.getModelPtr()!=im.getModelPtr() );
101        assert( imC2.getNumCols() == im.getNumCols() );
102        assert( imC2.getNumRows() == im.getNumRows() ); 
103       
104        assert( imC2.getModelPtr()!=imC1.getModelPtr() );
105       
106        lhs=imC2;
107      }
108      // Test that lhs has correct values even though rhs has gone out of scope
109     
110      assert( lhs.getModelPtr() != m.getModelPtr() );
111      assert( lhs.getNumCols() == m.getNumCols() );
112      assert( lhs.getNumRows() == m.getNumRows() );     
113    }
114    // Test clone
115    {
116      OsiCbcSolverInterface oslSi(m);
117      OsiSolverInterface * siPtr = &oslSi;
118      OsiSolverInterface * siClone = siPtr->clone();
119      OsiCbcSolverInterface * oslClone = dynamic_cast<OsiCbcSolverInterface*>(siClone);
120      assert( oslClone != NULL );
121      assert( oslClone->getModelPtr() != oslSi.getModelPtr() );
122      assert( oslClone->getNumRows() == oslSi.getNumRows() );
123      assert( oslClone->getNumCols() == m.getNumCols() );
124     
125      delete siClone;
126    }
127 
128    // test infinity
129    {
130      OsiCbcSolverInterface si;
131      assert( eq(si.getInfinity(),OsiCbcInfinity));
132    }     
133   
134    // Test setting solution
135    {
136      OsiCbcSolverInterface m1(m);
137      int i;
138
139      double * cs = new double[m1.getNumCols()];
140      for ( i = 0;  i < m1.getNumCols();  i++ ) 
141        cs[i] = i + .5;
142      m1.setColSolution(cs);
143      for ( i = 0;  i < m1.getNumCols();  i++ ) 
144        assert(m1.getColSolution()[i] == i + .5);
145     
146      double * rs = new double[m1.getNumRows()];
147      for ( i = 0;  i < m1.getNumRows();  i++ ) 
148        rs[i] = i - .5;
149      m1.setRowPrice(rs);
150      for ( i = 0;  i < m1.getNumRows();  i++ ) 
151        assert(m1.getRowPrice()[i] == i - .5);
152
153      delete [] cs;
154      delete [] rs;
155    }
156   
157   
158    // Test fraction Indices
159    {
160      OsiCbcSolverInterface fim;
161      std::string fn = mpsDir+"exmip1";
162      fim.readMps(fn.c_str(),"mps");
163      // exmip1.mps has 2 integer variables with index 2 & 3
164      assert(  fim.isContinuous(0) );
165      assert(  fim.isContinuous(1) );
166      assert( !fim.isContinuous(2) );
167      assert( !fim.isContinuous(3) );
168      assert(  fim.isContinuous(4) );
169     
170      assert( !fim.isInteger(0) );
171      assert( !fim.isInteger(1) );
172      assert(  fim.isInteger(2) );
173      assert(  fim.isInteger(3) );
174      assert( !fim.isInteger(4) );
175     
176      assert( !fim.isBinary(0) );
177      assert( !fim.isBinary(1) );
178      assert(  fim.isBinary(2) );
179      assert(  fim.isBinary(3) );
180      assert( !fim.isBinary(4) );
181     
182      assert( !fim.isIntegerNonBinary(0) );
183      assert( !fim.isIntegerNonBinary(1) );
184      assert( !fim.isIntegerNonBinary(2) );
185      assert( !fim.isIntegerNonBinary(3) );
186      assert( !fim.isIntegerNonBinary(4) );
187
188    }
189    // Test some catches
190      if (!OsiCbcHasNDEBUG())
191    { bool thrown ;
192
193      thrown = false ;
194      OsiCbcSolverInterface solver;
195      try {
196        solver.setObjCoeff(0,0.0);
197      }
198      catch (CoinError e) {
199        std::cout<<"Correct throw"<<std::endl;
200        thrown = true ;
201      }
202      assert( thrown == true ) ;
203
204      std::string fn = mpsDir+"exmip1";
205      solver.readMps(fn.c_str(),"mps");
206      try {
207        solver.setObjCoeff(0,0.0);
208      }
209      catch (CoinError e) {
210        std::cout<<"** Incorrect throw"<<std::endl;
211        abort();
212      }
213
214      thrown = false ;
215      try {
216        int index[]={0,20};
217        double value[]={0.0,0.0,0.0,0.0};
218        solver.setColSetBounds(index,index+2,value);
219      }
220      catch (CoinError e) {
221        std::cout<<"Correct throw"<<std::endl;
222        thrown = true ;
223      }
224      assert( thrown == true ) ;
225    }
226    // Test apply cuts method
227    {     
228      OsiCbcSolverInterface im(m);
229      OsiCuts cuts;
230     
231      // Generate some cuts
232      {
233        // Get number of rows and columns in model
234        int nr=im.getNumRows();
235        int nc=im.getNumCols();
236        assert( nr == 5 );
237        assert( nc == 8 );
238       
239        // Generate a valid row cut from thin air
240        int c;
241        {
242          int *inx = new int[nc];
243          for (c=0;c<nc;c++) inx[c]=c;
244          double *el = new double[nc];
245          for (c=0;c<nc;c++) el[c]=((double)c)*((double)c);
246         
247          OsiRowCut rc;
248          rc.setRow(nc,inx,el);
249          rc.setLb(-100.);
250          rc.setUb(100.);
251          rc.setEffectiveness(22);
252         
253          cuts.insert(rc);
254          delete[]el;
255          delete[]inx;
256        }
257       
258        // Generate valid col cut from thin air
259        {
260          const double * oslColLB = im.getColLower();
261          const double * oslColUB = im.getColUpper();
262          int *inx = new int[nc];
263          for (c=0;c<nc;c++) inx[c]=c;
264          double *lb = new double[nc];
265          double *ub = new double[nc];
266          for (c=0;c<nc;c++) lb[c]=oslColLB[c]+0.001;
267          for (c=0;c<nc;c++) ub[c]=oslColUB[c]-0.001;
268         
269          OsiColCut cc;
270          cc.setLbs(nc,inx,lb);
271          cc.setUbs(nc,inx,ub);
272         
273          cuts.insert(cc);
274          delete [] ub;
275          delete [] lb;
276          delete [] inx;
277        }
278       
279        {
280          // Generate a row and column cut which are ineffective
281          OsiRowCut * rcP= new OsiRowCut;
282          rcP->setEffectiveness(-1.);
283          cuts.insert(rcP);
284          assert(rcP==NULL);
285         
286          OsiColCut * ccP= new OsiColCut;
287          ccP->setEffectiveness(-12.);
288          cuts.insert(ccP);
289          assert(ccP==NULL);
290        }
291        {
292          //Generate inconsistent Row cut
293          OsiRowCut rc;
294          const int ne=1;
295          int inx[ne]={-10};
296          double el[ne]={2.5};
297          rc.setRow(ne,inx,el);
298          rc.setLb(3.);
299          rc.setUb(4.);
300          assert(!rc.consistent());
301          cuts.insert(rc);
302        }
303        {
304          //Generate inconsistent col cut
305          OsiColCut cc;
306          const int ne=1;
307          int inx[ne]={-10};
308          double el[ne]={2.5};
309          cc.setUbs(ne,inx,el);
310          assert(!cc.consistent());
311          cuts.insert(cc);
312        }
313        {
314          // Generate row cut which is inconsistent for model m
315          OsiRowCut rc;
316          const int ne=1;
317          int inx[ne]={10};
318          double el[ne]={2.5};
319          rc.setRow(ne,inx,el);
320          assert(rc.consistent());
321          assert(!rc.consistent(im));
322          cuts.insert(rc);
323        }
324        {
325          // Generate col cut which is inconsistent for model m
326          OsiColCut cc;
327          const int ne=1;
328          int inx[ne]={30};
329          double el[ne]={2.0};
330          cc.setLbs(ne,inx,el);
331          assert(cc.consistent());
332          assert(!cc.consistent(im));
333          cuts.insert(cc);
334        }
335        {
336          // Generate col cut which is infeasible
337          OsiColCut cc;
338          const int ne=1;
339          int inx[ne]={0};
340          double el[ne]={2.0};
341          cc.setUbs(ne,inx,el);
342          cc.setEffectiveness(1000.);
343          assert(cc.consistent());
344          assert(cc.consistent(im));
345          assert(cc.infeasible(im));
346          cuts.insert(cc);
347        }
348      }
349      assert(cuts.sizeRowCuts()==4);
350      assert(cuts.sizeColCuts()==5);
351     
352      OsiSolverInterface::ApplyCutsReturnCode rc = im.applyCuts(cuts);
353      assert( rc.getNumIneffective() == 2 );
354      assert( rc.getNumApplied() == 2 );
355      assert( rc.getNumInfeasible() == 1 );
356      assert( rc.getNumInconsistentWrtIntegerModel() == 2 );
357      assert( rc.getNumInconsistent() == 2 );
358      assert( cuts.sizeCuts() == rc.getNumIneffective() +
359        rc.getNumApplied() +
360        rc.getNumInfeasible() +
361        rc.getNumInconsistentWrtIntegerModel() +
362        rc.getNumInconsistent() );
363    }
364   
365    {   
366      OsiCbcSolverInterface oslSi(m);
367      int nc = oslSi.getNumCols();
368      int nr = oslSi.getNumRows();
369      const double * cl = oslSi.getColLower();
370      const double * cu = oslSi.getColUpper();
371      const double * rl = oslSi.getRowLower();
372      const double * ru = oslSi.getRowUpper();
373      assert( nc == 8 );
374      assert( nr == 5 );
375      assert( eq(cl[0],2.5) );
376      assert( eq(cl[1],0.0) );
377      assert( eq(cu[1],4.1) );
378      assert( eq(cu[2],1.0) );
379      assert( eq(rl[0],2.5) );
380      assert( eq(rl[4],3.0) );
381      assert( eq(ru[1],2.1) );
382      assert( eq(ru[4],15.0) );
383     
384      const double * cs = oslSi.getColSolution();
385      assert( eq(cs[0],2.5) );
386      assert( eq(cs[7],0.0) );
387     
388      assert( !eq(cl[3],1.2345) );
389      oslSi.setColLower( 3, 1.2345 );
390      assert( eq(oslSi.getColLower()[3],1.2345) );
391     
392      assert( !eq(cu[4],10.2345) );
393      oslSi.setColUpper( 4, 10.2345 );
394      assert( eq(oslSi.getColUpper()[4],10.2345) );
395      // LH: Objective will depend on how underlying solver constructs and
396      // LH: maintains initial solution.
397      double objValue = oslSi.getObjValue();
398      assert( eq(objValue,3.5) || eq(objValue,10.5) );
399
400      assert( eq( oslSi.getObjCoefficients()[0],  1.0) );
401      assert( eq( oslSi.getObjCoefficients()[1],  0.0) );
402      assert( eq( oslSi.getObjCoefficients()[2],  0.0) );
403      assert( eq( oslSi.getObjCoefficients()[3],  0.0) );
404      assert( eq( oslSi.getObjCoefficients()[4],  2.0) );
405      assert( eq( oslSi.getObjCoefficients()[5],  0.0) );
406      assert( eq( oslSi.getObjCoefficients()[6],  0.0) );
407      assert( eq( oslSi.getObjCoefficients()[7], -1.0) );
408    }
409   
410    // Test matrixByRow method
411    { 
412      const OsiCbcSolverInterface si(m);
413      const CoinPackedMatrix * smP = si.getMatrixByRow();
414      // LL:      const OsiCbcPackedMatrix * osmP = dynamic_cast<const OsiCbcPackedMatrix*>(smP);
415      // LL: assert( osmP!=NULL );
416
417#ifdef OSICBC_TEST_MTX_STRUCTURE
418
419      CoinRelFltEq eq;
420      const double * ev = smP->getElements();
421      assert( eq(ev[0],   3.0) );
422      assert( eq(ev[1],   1.0) );
423      assert( eq(ev[2],  -2.0) );
424      assert( eq(ev[3],  -1.0) );
425      assert( eq(ev[4],  -1.0) );
426      assert( eq(ev[5],   2.0) );
427      assert( eq(ev[6],   1.1) );
428      assert( eq(ev[7],   1.0) );
429      assert( eq(ev[8],   1.0) );
430      assert( eq(ev[9],   2.8) );
431      assert( eq(ev[10], -1.2) );
432      assert( eq(ev[11],  5.6) );
433      assert( eq(ev[12],  1.0) );
434      assert( eq(ev[13],  1.9) );
435     
436      const CoinBigIndex * mi = smP->getVectorStarts();
437      assert( mi[0]==0 );
438      assert( mi[1]==5 );
439      assert( mi[2]==7 );
440      assert( mi[3]==9 );
441      assert( mi[4]==11 );
442      assert( mi[5]==14 );
443     
444      const int * ei = smP->getIndices();
445      assert( ei[0]  ==  0 );
446      assert( ei[1]  ==  1 );
447      assert( ei[2]  ==  3 );
448      assert( ei[3]  ==  4 );
449      assert( ei[4]  ==  7 );
450      assert( ei[5]  ==  1 );
451      assert( ei[6]  ==  2 );
452      assert( ei[7]  ==  2 );
453      assert( ei[8]  ==  5 );
454      assert( ei[9]  ==  3 );
455      assert( ei[10] ==  6 );
456      assert( ei[11] ==  0 );
457      assert( ei[12] ==  4 );
458      assert( ei[13] ==  7 );   
459
460#else   // OSICBC_TEST_MTX_STRUCTURE
461
462      CoinPackedMatrix exmip1Mtx ;
463      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
464      assert( exmip1Mtx.isEquivalent(*smP) ) ;
465
466#endif  // OSICBC_TEST_MTX_STRUCTURE
467
468      assert( smP->getMajorDim() == 5 );
469      assert( smP->getMinorDim() == 8 );
470      assert( smP->getNumElements() == 14 );
471      assert( smP->getSizeVectorStarts() == 6 );
472    }
473
474    // Test adding several cuts, and handling of a coefficient of infinity
475    // in the constraint matrix.
476    {
477      OsiCbcSolverInterface fim;
478      std::string fn = mpsDir+"exmip1";
479      fim.readMps(fn.c_str(),"mps");
480      // exmip1.mps has 2 integer variables with index 2 & 3
481      fim.initialSolve();
482      OsiRowCut cuts[3];
483     
484     
485      // Generate one ineffective cut plus two trivial cuts
486      int c;
487      int nc = fim.getNumCols();
488      int *inx = new int[nc];
489      for (c=0;c<nc;c++) inx[c]=c;
490      double *el = new double[nc];
491      for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c);
492     
493      cuts[0].setRow(nc,inx,el);
494      cuts[0].setLb(-100.);
495      cuts[0].setUb(500.);
496      cuts[0].setEffectiveness(22);
497      el[4]=0.0; // to get inf later
498     
499      for (c=2;c<4;c++) {
500        el[0]=1.0;
501        inx[0]=c;
502        cuts[c-1].setRow(1,inx,el);
503        cuts[c-1].setLb(1.);
504        cuts[c-1].setUb(100.);
505        cuts[c-1].setEffectiveness(c);
506      }
507      fim.writeMps("x1.mps");
508      fim.applyRowCuts(3,cuts);
509      fim.writeMps("x2.mps");
510      // resolve - should get message about zero elements
511      fim.resolve();
512      fim.writeMps("x3.mps");
513      // check integer solution
514      const double * cs = fim.getColSolution();
515      CoinRelFltEq eq;
516      assert( eq(cs[2],   1.0) );
517      assert( eq(cs[3],   1.0) );
518      // check will find invalid matrix
519      el[0]=1.0/el[4];
520      inx[0]=0;
521      cuts[0].setRow(nc,inx,el);
522      cuts[0].setLb(-100.);
523      cuts[0].setUb(500.);
524      cuts[0].setEffectiveness(22);
525      fim.applyRowCut(cuts[0]);
526      // resolve - should get message about zero elements
527      fim.resolve();
528      assert (fim.isAbandoned());
529      delete[]el;
530      delete[]inx;
531    }
532
533        // Test matrixByCol method
534    {
535 
536      const OsiCbcSolverInterface si(m);
537      const CoinPackedMatrix * smP = si.getMatrixByCol();
538      // LL:      const OsiCbcPackedMatrix * osmP = dynamic_cast<const OsiCbcPackedMatrix*>(smP);
539      // LL: assert( osmP!=NULL );
540     
541#ifdef OSICBC_TEST_MTX_STRUCTURE
542
543      CoinRelFltEq eq;
544      const double * ev = smP->getElements();
545      assert( eq(ev[0],   3.0) );
546      assert( eq(ev[1],   5.6) );
547      assert( eq(ev[2],   1.0) );
548      assert( eq(ev[3],   2.0) );
549      assert( eq(ev[4],   1.1) );
550      assert( eq(ev[5],   1.0) );
551      assert( eq(ev[6],  -2.0) );
552      assert( eq(ev[7],   2.8) );
553      assert( eq(ev[8],  -1.0) );
554      assert( eq(ev[9],   1.0) );
555      assert( eq(ev[10],  1.0) );
556      assert( eq(ev[11], -1.2) );
557      assert( eq(ev[12], -1.0) );
558      assert( eq(ev[13],  1.9) );
559     
560      const CoinBigIndex * mi = smP->getVectorStarts();
561      assert( mi[0]==0 );
562      assert( mi[1]==2 );
563      assert( mi[2]==4 );
564      assert( mi[3]==6 );
565      assert( mi[4]==8 );
566      assert( mi[5]==10 );
567      assert( mi[6]==11 );
568      assert( mi[7]==12 );
569      assert( mi[8]==14 );
570     
571      const int * ei = smP->getIndices();
572      assert( ei[0]  ==  0 );
573      assert( ei[1]  ==  4 );
574      assert( ei[2]  ==  0 );
575      assert( ei[3]  ==  1 );
576      assert( ei[4]  ==  1 );
577      assert( ei[5]  ==  2 );
578      assert( ei[6]  ==  0 );
579      assert( ei[7]  ==  3 );
580      assert( ei[8]  ==  0 );
581      assert( ei[9]  ==  4 );
582      assert( ei[10] ==  2 );
583      assert( ei[11] ==  3 );
584      assert( ei[12] ==  0 );
585      assert( ei[13] ==  4 );   
586     
587#else // OSICBC_TEST_MTX_STRUCTURE
588
589      CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx() ;
590      assert( exmip1Mtx.isEquivalent(*smP) ) ;
591
592#endif  // OSICBC_TEST_MTX_STRUCTURE     
593
594      assert( smP->getMajorDim() == 8 ); 
595      assert( smP->getMinorDim() == 5 );
596      assert( smP->getNumElements() == 14 );
597      assert( smP->getSizeVectorStarts() == 9 );
598    }
599
600    //--------------
601    // Test rowsense, rhs, rowrange, matrixByRow, solver assignment
602    {
603      OsiCbcSolverInterface lhs;
604      {     
605
606        OsiCbcSolverInterface siC1(m);     
607        const char   * siC1rs  = siC1.getRowSense();
608        assert( siC1rs[0]=='G' );
609        assert( siC1rs[1]=='L' );
610        assert( siC1rs[2]=='E' );
611        assert( siC1rs[3]=='R' );
612        assert( siC1rs[4]=='R' );
613       
614        const double * siC1rhs = siC1.getRightHandSide();
615        assert( eq(siC1rhs[0],2.5) );
616        assert( eq(siC1rhs[1],2.1) );
617        assert( eq(siC1rhs[2],4.0) );
618        assert( eq(siC1rhs[3],5.0) );
619        assert( eq(siC1rhs[4],15.) ); 
620       
621        const double * siC1rr  = siC1.getRowRange();
622        assert( eq(siC1rr[0],0.0) );
623        assert( eq(siC1rr[1],0.0) );
624        assert( eq(siC1rr[2],0.0) );
625        assert( eq(siC1rr[3],5.0-1.8) );
626        assert( eq(siC1rr[4],15.0-3.0) );
627       
628        const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow();
629        assert( siC1mbr != NULL );
630
631#ifdef OSICBC_TEST_MTX_STRUCTURE
632
633        const double * ev = siC1mbr->getElements();
634        assert( eq(ev[0],   3.0) );
635        assert( eq(ev[1],   1.0) );
636        assert( eq(ev[2],  -2.0) );
637        assert( eq(ev[3],  -1.0) );
638        assert( eq(ev[4],  -1.0) );
639        assert( eq(ev[5],   2.0) );
640        assert( eq(ev[6],   1.1) );
641        assert( eq(ev[7],   1.0) );
642        assert( eq(ev[8],   1.0) );
643        assert( eq(ev[9],   2.8) );
644        assert( eq(ev[10], -1.2) );
645        assert( eq(ev[11],  5.6) );
646        assert( eq(ev[12],  1.0) );
647        assert( eq(ev[13],  1.9) );
648       
649        const CoinBigIndex * mi = siC1mbr->getVectorStarts();
650        assert( mi[0]==0 );
651        assert( mi[1]==5 );
652        assert( mi[2]==7 );
653        assert( mi[3]==9 );
654        assert( mi[4]==11 );
655        assert( mi[5]==14 );
656       
657        const int * ei = siC1mbr->getIndices();
658        assert( ei[0]  ==  0 );
659        assert( ei[1]  ==  1 );
660        assert( ei[2]  ==  3 );
661        assert( ei[3]  ==  4 );
662        assert( ei[4]  ==  7 );
663        assert( ei[5]  ==  1 );
664        assert( ei[6]  ==  2 );
665        assert( ei[7]  ==  2 );
666        assert( ei[8]  ==  5 );
667        assert( ei[9]  ==  3 );
668        assert( ei[10] ==  6 );
669        assert( ei[11] ==  0 );
670        assert( ei[12] ==  4 );
671        assert( ei[13] ==  7 );   
672
673#else   // OSICBC_TEST_MTX_STRUCTURE
674
675        CoinPackedMatrix exmip1Mtx ;
676        exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
677        assert( exmip1Mtx.isEquivalent(*siC1mbr) ) ;
678
679#endif  // OSICBC_TEST_MTX_STRUCTURE
680
681        assert( siC1mbr->getMajorDim() == 5 ); 
682        assert( siC1mbr->getMinorDim() == 8 );
683        assert( siC1mbr->getNumElements() == 14 );
684        assert( siC1mbr->getSizeVectorStarts()==6 );
685
686        assert( siC1rs  == siC1.getRowSense() );
687        assert( siC1rhs == siC1.getRightHandSide() );
688        assert( siC1rr  == siC1.getRowRange() );
689
690        // Change OSL Model by adding free row
691        OsiRowCut rc;
692        rc.setLb(-DBL_MAX);
693        rc.setUb( DBL_MAX);
694        OsiCuts cuts;
695        cuts.insert(rc);
696        siC1.applyCuts(cuts);
697             
698       
699        siC1rs  = siC1.getRowSense();
700        assert( siC1rs[0]=='G' );
701        assert( siC1rs[1]=='L' );
702        assert( siC1rs[2]=='E' );
703        assert( siC1rs[3]=='R' );
704        assert( siC1rs[4]=='R' );
705        assert( siC1rs[5]=='N' );
706
707        siC1rhs = siC1.getRightHandSide();
708        assert( eq(siC1rhs[0],2.5) );
709        assert( eq(siC1rhs[1],2.1) );
710        assert( eq(siC1rhs[2],4.0) );
711        assert( eq(siC1rhs[3],5.0) );
712        assert( eq(siC1rhs[4],15.) ); 
713        assert( eq(siC1rhs[5],0.0 ) ); 
714
715        siC1rr  = siC1.getRowRange();
716        assert( eq(siC1rr[0],0.0) );
717        assert( eq(siC1rr[1],0.0) );
718        assert( eq(siC1rr[2],0.0) );
719        assert( eq(siC1rr[3],5.0-1.8) );
720        assert( eq(siC1rr[4],15.0-3.0) );
721        assert( eq(siC1rr[5],0.0) );
722   
723        lhs=siC1;
724      }
725      // Test that lhs has correct values even though siC1 has gone out of scope   
726     
727      const char * lhsrs  = lhs.getRowSense();
728      assert( lhsrs[0]=='G' );
729      assert( lhsrs[1]=='L' );
730      assert( lhsrs[2]=='E' );
731      assert( lhsrs[3]=='R' );
732      assert( lhsrs[4]=='R' );
733      assert( lhsrs[5]=='N' );
734     
735      const double * lhsrhs = lhs.getRightHandSide();
736      assert( eq(lhsrhs[0],2.5) );
737      assert( eq(lhsrhs[1],2.1) );
738      assert( eq(lhsrhs[2],4.0) );
739      assert( eq(lhsrhs[3],5.0) );
740      assert( eq(lhsrhs[4],15.) ); 
741      assert( eq(lhsrhs[5],0.0) ); 
742     
743      const double *lhsrr  = lhs.getRowRange();
744      assert( eq(lhsrr[0],0.0) );
745      assert( eq(lhsrr[1],0.0) );
746      assert( eq(lhsrr[2],0.0) );
747      assert( eq(lhsrr[3],5.0-1.8) );
748      assert( eq(lhsrr[4],15.0-3.0) );
749      assert( eq(lhsrr[5],0.0) );     
750     
751      const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow();
752      assert( lhsmbr != NULL );       
753
754#ifdef OSICBC_TEST_MTX_STRUCTURE
755
756      const double * ev = lhsmbr->getElements();
757      assert( eq(ev[0],   3.0) );
758      assert( eq(ev[1],   1.0) );
759      assert( eq(ev[2],  -2.0) );
760      assert( eq(ev[3],  -1.0) );
761      assert( eq(ev[4],  -1.0) );
762      assert( eq(ev[5],   2.0) );
763      assert( eq(ev[6],   1.1) );
764      assert( eq(ev[7],   1.0) );
765      assert( eq(ev[8],   1.0) );
766      assert( eq(ev[9],   2.8) );
767      assert( eq(ev[10], -1.2) );
768      assert( eq(ev[11],  5.6) );
769      assert( eq(ev[12],  1.0) );
770      assert( eq(ev[13],  1.9) );
771     
772      const CoinBigIndex * mi = lhsmbr->getVectorStarts();
773      assert( mi[0]==0 );
774      assert( mi[1]==5 );
775      assert( mi[2]==7 );
776      assert( mi[3]==9 );
777      assert( mi[4]==11 );
778      assert( mi[5]==14 );
779     
780      const int * ei = lhsmbr->getIndices();
781      assert( ei[0]  ==  0 );
782      assert( ei[1]  ==  1 );
783      assert( ei[2]  ==  3 );
784      assert( ei[3]  ==  4 );
785      assert( ei[4]  ==  7 );
786      assert( ei[5]  ==  1 );
787      assert( ei[6]  ==  2 );
788      assert( ei[7]  ==  2 );
789      assert( ei[8]  ==  5 );
790      assert( ei[9]  ==  3 );
791      assert( ei[10] ==  6 );
792      assert( ei[11] ==  0 );
793      assert( ei[12] ==  4 );
794      assert( ei[13] ==  7 );   
795
796#else   // OSICBC_TEST_MTX_STRUCTURE
797
798/*
799  This admittedly looks bogus, but it's the equivalent operation on the matrix
800  for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no
801  coefficients).
802*/
803      CoinPackedMatrix exmip1Mtx ;
804      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
805      CoinPackedVector freeRow ;
806      exmip1Mtx.appendRow(freeRow) ;
807      assert( exmip1Mtx.isEquivalent(*lhsmbr) ) ;
808
809#endif  // OSICBC_TEST_MTX_STRUCTURE
810     
811      int md = lhsmbr->getMajorDim();
812      assert(  md == 6 ); 
813      assert( lhsmbr->getNumElements() == 14 );
814    }
815   
816  }
817
818  // Test add/delete columns
819  {   
820    OsiCbcSolverInterface m;
821    std::string fn = mpsDir+"p0033";
822    m.readMps(fn.c_str(),"mps");
823    double inf = m.getInfinity();
824
825    CoinPackedVector c0;
826    c0.insert(0, 4);
827    c0.insert(1, 1);
828    m.addCol(c0, 0, inf, 3);
829    m.initialSolve();
830    double objValue = m.getObjValue();
831    CoinRelFltEq eq(1.0e-2);
832    assert( eq(objValue,2520.57) );
833    // Try deleting first column that's nonbasic at lower bound (0).
834    int * d = new int[1];
835    CoinWarmStartBasis *cwsb =
836        dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
837    assert(cwsb) ;
838    CoinWarmStartBasis::Status stati ;
839    int iCol ;
840    for (iCol = 0 ;  iCol < cwsb->getNumStructural() ; iCol++)
841    { stati = cwsb->getStructStatus(iCol) ;
842      if (stati == CoinWarmStartBasis::atLowerBound) break ; }
843    d[0]=iCol;
844    m.deleteCols(1,d);
845    delete [] d;
846    delete cwsb;
847    d=NULL;
848    m.resolve();
849    objValue = m.getObjValue();
850    assert( eq(objValue,2520.57) );
851    // Try deleting column we added. If basic, go to initialSolve as deleting
852    // basic variable trashes basis required for warm start.
853    iCol = m.getNumCols()-1;
854    cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
855    stati =  cwsb->getStructStatus(iCol) ;
856    delete cwsb;
857    m.deleteCols(1,&iCol);
858    if (stati == CoinWarmStartBasis::basic)
859    { m.initialSolve() ; }
860    else
861    { m.resolve(); }
862    objValue = m.getObjValue();
863    assert( eq(objValue,2520.57) );
864
865  }
866  // Test matt
867  if (fopen("../Cbc/matt.mps","r")) {   
868    OsiCbcSolverInterface m;
869    m.readMps("../Cbc/matt","mps");
870    m.setHintParam(OsiDoPresolveInResolve, true, OsiHintDo);
871    m.resolve();
872   
873    std::vector<double *> rays = m.getDualRays(1);
874    std::cout << "Dual Ray: " << std::endl;
875    for(int i = 0; i < m.getNumRows(); i++){
876      if(fabs(rays[0][i]) > 0.00001)
877        std::cout << i << " : " << rays[0][i] << std::endl;
878    }
879   
880    std::cout << "isProvenOptimal = " << m.isProvenOptimal() << std::endl;
881    std::cout << "isProvenPrimalInfeasible = " << m.isProvenPrimalInfeasible()
882         << std::endl;
883   
884    delete [] rays[0];
885   
886  }
887
888  // Build a model
889  {   
890    OsiCbcSolverInterface model;
891    std::string fn = mpsDir+"p0033";
892    model.readMps(fn.c_str(),"mps");
893    // Point to data
894    int numberRows = model.getNumRows();
895    const double * rowLower = model.getRowLower();
896    const double * rowUpper = model.getRowUpper();
897    int numberColumns = model.getNumCols();
898    const double * columnLower = model.getColLower();
899    const double * columnUpper = model.getColUpper();
900    const double * columnObjective = model.getObjCoefficients();
901    // get row copy
902    CoinPackedMatrix rowCopy = *model.getMatrixByRow();
903    const int * column = rowCopy.getIndices();
904    const int * rowLength = rowCopy.getVectorLengths();
905    const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
906    const double * element = rowCopy.getElements();
907   
908    // solve
909    model.initialSolve();
910    // Now build new model
911    CoinModel build;
912    // Row bounds
913    int iRow;
914    for (iRow=0;iRow<numberRows;iRow++) {
915      build.setRowBounds(iRow,rowLower[iRow],rowUpper[iRow]);
916    }
917    // Column bounds and objective
918    int iColumn;
919    for (iColumn=0;iColumn<numberColumns;iColumn++) {
920      build.setColumnLower(iColumn,columnLower[iColumn]);
921      build.setColumnUpper(iColumn,columnUpper[iColumn]);
922      build.setObjective(iColumn,columnObjective[iColumn]);
923    }
924    // Adds elements one by one by row (backwards by row)
925    for (iRow=numberRows-1;iRow>=0;iRow--) {
926      int start = rowStart[iRow];
927      for (int j=start;j<start+rowLength[iRow];j++) 
928        build(iRow,column[j],element[j]);
929    }
930    // Now create Model
931    OsiCbcSolverInterface model2;
932    model2.loadFromCoinModel(build);
933    model2.initialSolve();
934    // Save - should be continuous
935    model2.writeMps("continuous");
936    int * whichInteger = new int[numberColumns];
937    for (iColumn=0;iColumn<numberColumns;iColumn++) 
938      whichInteger[iColumn]=iColumn;
939    // mark as integer
940    model2.setInteger(whichInteger,numberColumns);
941    delete [] whichInteger;
942    // save - should be integer
943    model2.writeMps("integer");
944   
945    // Now do with strings attached
946    // Save build to show how to go over rows
947    CoinModel saveBuild = build;
948    build = CoinModel();
949    // Column bounds
950    for (iColumn=0;iColumn<numberColumns;iColumn++) {
951      build.setColumnLower(iColumn,columnLower[iColumn]);
952      build.setColumnUpper(iColumn,columnUpper[iColumn]);
953    }
954    // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
955    // Pick up from saveBuild (for no reason at all)
956    for (iColumn=0;iColumn<numberColumns;iColumn++) {
957      double value = saveBuild.objective(iColumn);
958      if (iColumn*2<numberColumns) {
959        build.setObjective(iColumn,columnObjective[iColumn]);
960      } else {
961        // create as string
962        char temp[100];
963        sprintf(temp,"%g + abs(%g*multiplier)",value,value);
964        build.setObjective(iColumn,temp);
965      }
966    }
967    // It then adds rows one by one but for half the rows sets their values
968    //      with multiplier of "1.0+1.5*multiplier"
969    for (iRow=0;iRow<numberRows;iRow++) {
970      if (iRow*2<numberRows) {
971        // add row in simple way
972        int start = rowStart[iRow];
973        build.addRow(rowLength[iRow],column+start,element+start,
974                     rowLower[iRow],rowUpper[iRow]);
975      } else {
976        // As we have to add one by one let's get from saveBuild
977        CoinModelLink triple=saveBuild.firstInRow(iRow);
978        while (triple.column()>=0) {
979          int iColumn = triple.column();
980          if (iColumn*2<numberColumns) {
981            // just value as normal
982            build(iRow,triple.column(),triple.value());
983          } else {
984            // create as string
985            char temp[100];
986            sprintf(temp,"%g + (1.5*%g*multiplier)",triple.value(), triple.value());
987            build(iRow,iColumn,temp);
988          }
989          triple=saveBuild.next(triple);
990        }
991        // but remember to do rhs
992        build.setRowLower(iRow,rowLower[iRow]);
993        build.setRowUpper(iRow,rowUpper[iRow]);
994      }
995    }
996    // If small switch on error printing
997    if (numberColumns<50)
998      build.setLogLevel(1);
999    int numberErrors=model2.loadFromCoinModel(build);
1000    // should fail as we never set multiplier
1001    assert (numberErrors);
1002    build.associateElement("multiplier",0.0);
1003    numberErrors=model2.loadFromCoinModel(build);
1004    assert (!numberErrors);
1005    model2.initialSolve();
1006    // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
1007    for (double multiplier=0.0;multiplier<2.0;multiplier+= 0.1) {
1008      build.associateElement("multiplier",multiplier);
1009      numberErrors=model2.loadFromCoinModel(build,true);
1010      assert (!numberErrors);
1011      model2.resolve();
1012    }
1013  }
1014  // branch and bound
1015  {   
1016    OsiCbcSolverInterface m;
1017    std::string fn = mpsDir+"p0033";
1018    m.readMps(fn.c_str(),"mps");
1019    m.initialSolve();
1020    //m.messageHandler()->setLogLevel(0);
1021    m.getModelPtr()->messageHandler()->setLogLevel(0);
1022    m.branchAndBound();
1023  }
1024  // branch and bound using CbcModel!!!!!!!
1025  {   
1026    OsiCbcSolverInterface mm;
1027    OsiCbcSolverInterface m(&mm);
1028    std::string fn = mpsDir+"p0033";
1029    m.readMps(fn.c_str(),"mps");
1030    m.initialSolve();
1031    m.branchAndBound();
1032  }
1033#ifdef COIN_HAS_OSL
1034  // branch and bound using OSL
1035  {   
1036    OsiOslSolverInterface mmm;
1037    OsiCbcSolverInterface mm(&mmm);
1038    CbcStrategyNull strategy;
1039    OsiCbcSolverInterface m(&mm,&strategy);
1040    std::string fn = mpsDir+"p0033";
1041    m.readMps(fn.c_str(),"mps");
1042    //m.initialSolve();
1043    m.branchAndBound();
1044  }
1045#endif
1046  int errCnt = 0;
1047  // Do common solverInterface testing
1048  {
1049    OsiCbcSolverInterface m;
1050    errCnt += OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
1051  }
1052  {
1053    OsiCbcSolverInterface mm;
1054    OsiCbcSolverInterface m(&mm);
1055    errCnt += OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
1056  }
1057#ifdef COIN_HAS_OSL
1058  {
1059    OsiOslSolverInterface mm;
1060    OsiCbcSolverInterface m(&mm);
1061    errCnt += OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
1062  }
1063#endif
1064  return errCnt;
1065}
Note: See TracBrowser for help on using the repository browser.