source: trunk/Test/unitTest.cpp @ 2

Last change on this file since 2 was 2, checked in by ladanyi, 16 years ago

Import of Coin Branch-and-Cut (formerly known as Sbb)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.4 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3// Test individual classes or groups of classes
4
5#if defined(_MSC_VER)
6// Turn off compiler warning about long names
7#  pragma warning(disable:4786)
8#endif
9
10#include <cstdlib>
11#include <cassert>
12#include <vector>
13#include <iostream>
14#include <cstdio>
15
16#include "CoinPackedMatrix.hpp"
17#include "CoinWarmStartBasis.hpp"
18#include "OsiSolverInterface.hpp"
19#include "CbcModel.hpp"
20#ifdef COIN_USE_OSL
21#include "OsiOslSolverInterface.hpp"
22#endif
23#ifdef COIN_USE_XPR
24#include "OsiXprSolverInterface.hpp"
25#endif
26#ifdef COIN_USE_CPX
27#include "OsiCpxSolverInterface.hpp"
28#endif
29#ifdef COIN_USE_SPX
30#include "OsiSpxSolverInterface.hpp"
31#endif
32#ifdef COIN_USE_DYLP
33#include "OsiDylpSolverInterface.hpp"
34#endif
35#ifdef COIN_USE_GLPK
36#include "OsiGlpkSolverInterface.hpp"
37#endif
38#ifdef COIN_USE_CLP
39#include "OsiClpSolverInterface.hpp"
40#endif
41   #define CUTS
42#ifdef CUTS
43#include "CglCutGenerator.hpp"
44#include "CglGomory.hpp"
45#include "CglProbing.hpp"
46#include "CglKnapsackCover.hpp"
47#include "CglOddHole.hpp"
48#endif
49#ifdef NDEBUG
50#undef NDEBUG
51#endif
52
53#include <time.h>
54#if !defined(_MSC_VER)
55#include <sys/times.h>
56#include <sys/resource.h>
57#include <unistd.h>
58#endif
59
60static double cpuTime()
61{
62  double cpu_temp;
63#if defined(_MSC_VER)
64  unsigned int ticksnow;        /* clock_t is same as int */
65 
66  ticksnow = (unsigned int)clock();
67 
68  cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC);
69#else
70  struct rusage usage;
71  getrusage(RUSAGE_SELF,&usage);
72  cpu_temp = usage.ru_utime.tv_sec;
73  cpu_temp += 1.0e-6*((double) usage.ru_utime.tv_usec);
74#endif
75  return cpu_temp;
76}
77// Function Prototypes. Function definitions is in this file.
78void testingMessage( const char * const msg );
79
80void CbcUnitTest
81  (const std::vector<OsiSolverInterface*> & vecEmptySiP,
82   const std::string & mpsDir)
83
84{ int i ;
85  unsigned int m ;
86
87/*
88  Vectors to hold test problem names and characteristics. The objective value
89  after optimization (objValue) must agree to the specified tolerance
90  (objValueTol).
91*/
92  std::vector<std::string> mpsName ;
93  std::vector<int> nRows ;
94  std::vector<int> nCols ;
95  std::vector<double> objValueC ;
96  std::vector<double> objValue ;
97  std::vector<int> strategy ;
98/*
99  And a macro to make the vector creation marginally readable.
100*/
101#define PUSH_MPS(zz_mpsName_zz,\
102                 zz_nRows_zz,zz_nCols_zz,zz_objValue_zz,zz_objValueC_zz, \
103                 zz_strategy_zz) \
104  mpsName.push_back(zz_mpsName_zz) ; \
105  nRows.push_back(zz_nRows_zz) ; \
106  nCols.push_back(zz_nCols_zz) ; \
107  objValueC.push_back(zz_objValueC_zz) ; \
108  strategy.push_back(zz_strategy_zz) ; \
109  objValue.push_back(zz_objValue_zz) ;
110
111/*
112  Load up the problem vector. Note that the row counts here include the
113  objective function.
114
115  Strategy is bit function - at present
116  1 - gomory
117  2 - probing
118  4 - knapsack
119  8 - oddhole
120  1024 - switch OFF strong branching
121*/
122  PUSH_MPS("10teams",230,2025,924,917,7)
123    PUSH_MPS("air03",124,10757,340160,338864.25,7)
124#if 0
125    PUSH_MPS("air04",823,8904,56137,55535.436,8)
126    PUSH_MPS("air05",426,7195,26374,25877.609,8)
127#endif
128    //    PUSH_MPS("arki001",1048,1388,7580813.0459,7579599.80787,7)
129    PUSH_MPS("bell3a",123,133,878430.32,862578.64,7)
130    PUSH_MPS("bell5",91,104,8966406.49,8608417.95,7)
131    PUSH_MPS("blend2",274,353,7.598985,6.9156751140,7)
132    PUSH_MPS("cap6000",2176,6000,-2451377,-2451537.325,7)
133    //    PUSH_MPS("dano3mip",3202,13873,728.1111,576.23162474,7)
134    //PUSH_MPS("danoint",664,521,65.67,62.637280418,7)
135    PUSH_MPS("dcmulti",290,548,188182,183975.5397,7)
136    PUSH_MPS("dsbmip",1182,1886,-305.19817501,-305.19817501,7)
137    PUSH_MPS("egout",98,141,568.101,149.589,7)
138    PUSH_MPS("enigma",21,100,0.0,0.0,7)
139#if 0
140    PUSH_MPS("fast0507",507,63009,174,172.14556668,7)
141#endif
142    PUSH_MPS("fiber",363,1298,405935.18000,156082.51759,7)
143    PUSH_MPS("fixnet6",478,878,3983,1200.88,7)
144    PUSH_MPS("flugpl",18,18,1201500,1167185.7,7)
145    PUSH_MPS("gen",780,870,112313,112130.0,7)
146    PUSH_MPS("gesa2",1392,1224,25779856.372,25476489.678,7)
147    PUSH_MPS("gesa2_o",1248,1224,25779856.372,25476489.678,7)
148    PUSH_MPS("gesa3",1368,1152,27991042.648,27833632.451,7)
149    PUSH_MPS("gesa3_o",1224,1152,27991042.648,27833632.451,7)
150    PUSH_MPS("gt2",29,188,21166.000,13460.233074,7)
151#if 0
152    PUSH_MPS("harp2",112,2993,-73899798.00,-74353341.502,7)
153#endif
154    PUSH_MPS("khb05250",101,1350,106940226,95919464.0,7)
155    PUSH_MPS("l152lav",97,1989,4722,4656.36,7)
156    PUSH_MPS("lseu",28,89,1120,834.68,7)
157    PUSH_MPS("misc03",96,160,3360,1910.,7)
158    PUSH_MPS("misc06",820,1808,12850.8607,12841.6,7)
159    PUSH_MPS("misc07",212,260,2810,1415.0,7)
160    PUSH_MPS("mitre",2054,10724,115155,114740.5184,7)
161    PUSH_MPS("mod008",6,319,307,290.9,7)
162    PUSH_MPS("mod010",146,2655,6548,6532.08,7)
163#if 0
164    PUSH_MPS("mod011",4480,10958,-54558535,-62121982.55,7)
165    PUSH_MPS("modglob",291,422,20740508,20430947.,7)
166    PUSH_MPS("noswot",182,128,-43,-43.0,7)
167#endif
168    PUSH_MPS("nw04",36,87482,16862,16310.66667,7)
169    PUSH_MPS("p0033",16,33,3089,2520.57,7)
170    PUSH_MPS("p0201",133,201,7615,6875.0,7)
171    PUSH_MPS("p0282",241,282,258411,176867.50,7)
172    PUSH_MPS("p0548",176,548,8691,315.29,7)
173    PUSH_MPS("p2756",755,2756,3124,2688.75,7)
174#if 0
175    PUSH_MPS("pk1",45,86,11.0,0.0,7)
176#endif
177    PUSH_MPS("pp08a",136,240,7350.0,2748.3452381,7)
178    PUSH_MPS("pp08aCUTS",246,240,7350.0,5480.6061563,7)
179#if 0
180    PUSH_MPS("qiu",1192,840,-132.873137,-931.638857,7)
181#endif
182    PUSH_MPS("qnet1",503,1541,16029.692681,14274.102667,7)
183    PUSH_MPS("qnet1_o",456,1541,16029.692681,12095.571667,7)
184    PUSH_MPS("rentacar",6803,9557,30356761,28806137.644,7)
185    PUSH_MPS("rgn",24,180,82.1999,48.7999,7)
186#if 0
187    PUSH_MPS("rout",291,556,1077.56,981.86428571,7)
188    PUSH_MPS("set1ch",492,712,54537.75,32007.73,7)
189#endif
190    //    PUSH_MPS("seymour",4944,1372,423,403.84647413,7)
191    PUSH_MPS("stein27",118,27,18,13.0,7)
192    PUSH_MPS("stein45",331,45,30,22.0,7)
193    PUSH_MPS("vpm1",234,378,20,15.4167,7)
194    PUSH_MPS("vpm2",234,378,13.75,9.8892645972,7)
195
196#undef PUSH_MPS
197
198/*
199  Create a vector of solver interfaces that we can use to run the test
200  problems. The strategy is to create a fresh clone of the `empty' solvers
201  from vecEmptySiP for each problem, then proceed in stages: read the MPS
202  file, solve the problem, check the solution. If there are multiple
203  solvers in vecSiP, the results of each solver are compared with its
204  neighbors in the vector.
205*/
206  std::vector<OsiSolverInterface*> vecSiP(vecEmptySiP.size()) ;
207
208  // Create vector to store a name for each solver interface
209  // and a count on the number of problems the solver intface solved.
210  std::vector<std::string> siName;
211  std::vector<int> numProbSolved;
212  std::vector<double> timeTaken;
213  const int vecsize = vecSiP.size();
214  for ( i=0; i<vecsize; i++ ) {
215    siName.push_back("");
216    numProbSolved.push_back(0);
217    timeTaken.push_back(0.0);
218  }
219
220/*
221  Open the main loop to step through the MPS problems.
222*/
223  for (m = 0 ; m < mpsName.size() ; m++)
224  { std::cerr << "  processing mps file: " << mpsName[m] 
225      << " (" << m+1 << " out of " << mpsName.size() << ")" << std::endl ;
226/*
227  Stage 1: Read the MPS file into each solver interface.
228
229  Fill vecSiP with fresh clones of the solvers and read in the MPS file. As
230  a basic check, make sure the size of the constraint matrix is correct.
231*/
232    for (i = vecSiP.size()-1 ; i >= 0 ; --i)
233    { vecSiP[i] = vecEmptySiP[i]->clone() ;
234     
235      std::string fn = mpsDir+mpsName[m] ;
236      vecSiP[i]->readMps(fn.c_str(),"") ;
237     
238      vecSiP[i]->setObjSense(1.0) ;
239     
240      int nr = vecSiP[i]->getNumRows() ;
241      int nc = vecSiP[i]->getNumCols() ;
242      assert(nr == nRows[m]) ;
243      assert(nc == nCols[m]) ; } 
244/*
245  Stage 2: Call each solver to solve the problem.
246
247  We call each solver, then check the return code and objective.
248
249*/
250
251    for (i = 0 ; i < static_cast<int>(vecSiP.size()) ; ++i)
252    {
253      double startTime = cpuTime();
254#     ifdef COIN_USE_CLP
255      { 
256        OsiClpSolverInterface * si =
257          dynamic_cast<OsiClpSolverInterface *>(vecSiP[i]) ;
258        if (si != NULL )  {   
259          siName[i]="OsiClpSolverInterface";
260        }
261      }
262#     endif
263#     ifdef COIN_USE_DYLP
264      { 
265        OsiDylpSolverInterface * si =
266          dynamic_cast<OsiDylpSolverInterface *>(vecSiP[i]) ;
267        if (si != NULL )  {   
268          siName[i]="OsiDylpSolverInterface";
269          // Is this an MPS file that OsiDylpSolverInterface handles
270          if ( mpsName[m]=="cycle" ||
271               mpsName[m]=="d6cube" ||
272               mpsName[m]=="fit1d" || 
273               mpsName[m]=="grow15" || 
274               mpsName[m]=="grow22" || 
275               mpsName[m]=="maros" || 
276               mpsName[m]=="pilot" || 
277               mpsName[m]=="pilot4" || 
278               mpsName[m]=="pilotnov" || 
279               mpsName[m]=="wood1p" )break ; 
280        }
281      }
282#     endif
283#     ifdef COIN_USE_XPR
284      { 
285        OsiXprSolverInterface * si =
286          dynamic_cast<OsiXprSolverInterface *>(vecSiP[i]) ;
287        if (si != NULL )  {   
288          siName[i]="OsiXprSolverInterface";
289        }
290      }
291#     endif
292#     ifdef COIN_USE_CPX
293      { 
294        OsiCpxSolverInterface * si =
295          dynamic_cast<OsiCpxSolverInterface *>(vecSiP[i]) ;
296        if (si != NULL )  {   
297          siName[i]="OsiCpxSolverInterface";
298        }
299      }
300#     endif
301#     ifdef COIN_USE_SPX
302      { 
303        OsiSpxSolverInterface * si =
304          dynamic_cast<OsiSpxSolverInterface *>(vecSiP[i]) ;
305        if (si != NULL )  {   
306          siName[i]="OsiSpxSolverInterface";
307        }
308      }
309#     endif
310#     ifdef COIN_USE_OSL
311      { 
312        OsiOslSolverInterface * si =
313          dynamic_cast<OsiOslSolverInterface *>(vecSiP[i]) ;
314        if (si != NULL )  {   
315          siName[i]="OsiOslSolverInterface";
316        }
317      }
318#     endif
319     
320      vecSiP[i]->initialSolve() ;
321      CbcModel integerSolver(*vecSiP[i]);
322      // Set up likely cut generators and defaults
323      CglGomory try1;
324      CglProbing try2;
325      try2.setUsingObjective(true);
326      try2.setMaxPass(3);
327      try2.setMaxProbe(100);
328      try2.setMaxLook(50);
329      CglKnapsackCover try3;
330      CglOddHole try4;
331      try4.setMinimumViolation(0.005);
332      try4.setMinimumViolationPer(0.0002);
333      try4.setMaximumEntries(100);
334     
335      if ((strategy[m]&1)!=0)
336        integerSolver.addCutGenerator(&try1,-1,"Gomory");
337      if ((strategy[m]&2)!=0)
338        integerSolver.addCutGenerator(&try2,-1,"Probing");
339      if ((strategy[m]&4)!=0)
340        integerSolver.addCutGenerator(&try3,-1,"Knapsack");
341      if ((strategy[m]&8)!=0)
342        integerSolver.addCutGenerator(&try4,-1,"OddHole");
343      if ((strategy[m]&1024)!=0)
344        integerSolver.setNumberStrong(0);
345      integerSolver.messageHandler()->setLogLevel(1);
346#     ifdef COIN_USE_CLP
347      { 
348        OsiClpSolverInterface * si =
349          dynamic_cast<OsiClpSolverInterface *>(integerSolver.solver()) ;
350        if (si != NULL )  {   
351          integerSolver.solver()->messageHandler()->setLogLevel(0);
352        }
353      }
354#endif
355#     ifdef COIN_USE_OSL
356      { 
357        OsiOslSolverInterface * si =
358          dynamic_cast<OsiOslSolverInterface *>(integerSolver.solver()) ;
359        if (si != NULL )  {   
360          ekk_messagesPrintOff(si->getModelPtr(),1,4000);
361        }
362      }
363#endif
364      integerSolver.setMaximumNodes(50000);
365      integerSolver.branchAndBound();
366      integerSolver.solver()->resolve();
367     
368      double timeOfSolution = cpuTime()-startTime;
369      if (integerSolver.solver()->isProvenOptimal()) { 
370        double soln = integerSolver.solver()->getObjValue();       
371        CoinRelFltEq eq(1.0e-3) ;
372        if (eq(soln,objValue[m])) { 
373          std::cerr
374            <<siName[i]<<" "
375            << soln << " = " << objValue[m] << " ; okay";
376          numProbSolved[i]++;
377        } else  { 
378          std::cerr <<siName[i] <<" " <<soln << " != " <<objValue[m] << "; error=" ;
379          std::cerr <<fabs(objValue[m] - soln); 
380        }
381      } else {
382        if (integerSolver.solver()->isProvenPrimalInfeasible()) 
383          std::cerr << "error; primal infeasible" ;
384        else if (integerSolver.solver()->isProvenDualInfeasible()) 
385          std::cerr << "error; dual infeasible" ;
386        else if (integerSolver.solver()->isIterationLimitReached()) 
387          std::cerr << "error; iteration limit" ;
388        else if (integerSolver.solver()->isAbandoned()) 
389          std::cerr << "error; abandoned" ;
390        else 
391          std::cerr << "error; unknown" ;
392      }
393      std::cerr<<" - took " <<timeOfSolution<<" seconds."<<std::endl; 
394      timeTaken[i] += timeOfSolution;
395    }
396    /*
397    Delete the used solver interfaces so we can reload fresh clones for the
398              next problem.
399    */
400    //for (i = vecSiP.size()-1 ; i >= 0 ; --i) delete vecSiP[i] ;
401  }
402
403  const int siName_size = siName.size();
404  for ( i=0; i<siName_size; i++ ) {
405    std::cerr
406      <<siName[i] 
407      <<" solved " 
408      <<numProbSolved[i]
409      <<" out of "
410      <<objValue.size()
411      <<" and took "
412      <<timeTaken[i]
413      <<" seconds."
414      <<std::endl;
415  } 
416}
417
418//----------------------------------------------------------------
419// unitTest [-mpsDir=V1] [-miplibDir=V2]
420//
421// where:
422//   -mpsDir: directory containing mps test files
423//       Default value V1="../Mps/Sample"   
424//   -miplibDir: directory containing miplib files
425//       Default value V2="./Samples/miplib3"
426//
427// All parameters are optional.
428//----------------------------------------------------------------
429
430int mainTest (int argc, const char *argv[])
431{
432  int i;
433
434#ifdef COIN_USE_XPR
435  OsiXprSolverInterface::setLogFileName("xprCallTrace.txt");
436#endif
437
438  // define valid parameter keywords
439  std::set<std::string> definedKeyWords;
440  definedKeyWords.insert("-mpsDir");
441  definedKeyWords.insert("-miplibDir");
442
443  // Create a map of parameter keys and associated data
444  std::map<std::string,std::string> parms;
445  for ( i=1; i<argc; i++ ) {
446    std::string parm(argv[i]);
447    std::string key,value;
448    unsigned int  eqPos = parm.find('=');
449
450    // Does parm contain and '='
451    if ( eqPos==std::string::npos ) {
452      //Parm does not contain '='
453      key = parm;
454    }
455    else {
456      key=parm.substr(0,eqPos);
457      value=parm.substr(eqPos+1);
458    }
459
460    // Is specifed key valid?
461    if ( definedKeyWords.find(key) == definedKeyWords.end() ) {
462      // invalid key word.
463      // Write help text
464      std::cerr <<"Undefined parameter \"" <<key <<"\".\n";
465      std::cerr <<"Correct usage: \n";
466      std::cerr <<"  unitTest [-mpsDir=V1] [-miplibDir=V2] [-testOsiSolverInterface]\n";
467      std::cerr <<"  where:\n";
468      std::cerr <<"    -mpsDir: directory containing mps test files\n";
469      std::cerr <<"        Default value V1=\"../Mps/Sample\"\n";
470      std::cerr <<"    -miplibDir: directory containing miplib files\n";
471      std::cerr <<"        Default value V2=\"./Samples/miplib3\"\n";
472      return 1;
473    }
474    parms[key]=value;
475  }
476 
477  const char dirsep =  CoinFindDirSeparator();
478  // Set directory containing mps data files.
479  std::string mpsDir;
480  if (parms.find("-mpsDir") != parms.end())
481    mpsDir=parms["-mpsDir"] + dirsep;
482  else 
483    mpsDir = dirsep == '/' ? "../Mps/Sample/" : "..\\Mps\\Sample\\";
484 
485  // Set directory containing miplib data files.
486  std::string miplibDir;
487  if (parms.find("-miplibDir") != parms.end())
488    miplibDir=parms["-miplibDir"] + dirsep;
489  else 
490    miplibDir = dirsep == '/' ? "./Samples/miplib3/" : ".\\Samples\\miplib3\\";
491
492  {
493    // Create vector of solver interfaces
494    std::vector<OsiSolverInterface*> vecSi;
495#   if COIN_USE_OSL
496    OsiSolverInterface * oslSi = new OsiOslSolverInterface;
497    vecSi.push_back(oslSi);
498#endif
499#   if COIN_USE_XPR
500    OsiSolverInterface * xprSi = new OsiXprSolverInterface;
501    vecSi.push_back(xprSi);
502#endif
503#   if COIN_USE_CPX
504    OsiSolverInterface * cpxSi = new OsiCpxSolverInterface;
505    vecSi.push_back(cpxSi);
506#endif
507#   if COIN_USE_SPX
508    OsiSolverInterface * spxSi = new OsiSpxSolverInterface;
509    vecSi.push_back(spxSi);
510#endif
511#   if COIN_USE_CLP
512    OsiSolverInterface * clpSi = new OsiClpSolverInterface;
513    vecSi.push_back(clpSi);
514#endif
515#   if COIN_USE_DYLP
516    OsiSolverInterface * dylpSi = new OsiDylpSolverInterface;
517    vecSi.push_back(dylpSi);
518#endif
519#   if COIN_USE_GLPK
520    OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface;
521    vecSi.push_back(glpkSi);
522#endif
523
524    testingMessage( "Testing some miplib stuff\n" );
525    CbcUnitTest(vecSi,miplibDir);
526
527    unsigned int i;
528    for (i=0; i<vecSi.size(); i++)
529      delete vecSi[i];
530  }
531  testingMessage( "All tests completed successfully\n" );
532  return 0;
533}
534
535 
536// Display message on stdout and stderr
537void testingMessage( const char * const msg )
538{
539  std::cerr <<msg;
540  //cout <<endl <<"*****************************************"
541  //     <<endl <<msg <<endl;
542}
543
Note: See TracBrowser for help on using the repository browser.