source: trunk/Test/unitTest.cpp @ 277

Last change on this file since 277 was 277, checked in by lou, 14 years ago

Revise cbc build process for better control of solvers included in build
(COIN_USE_XXX -> CBC_USE_XXX). Add CbcEventHandler? for independence from
clp.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 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 "CoinHelperFunctions.hpp"
17
18#ifdef CBC_USE_CBC
19#include "OsiCbcSolverInterface.hpp"
20#endif
21#ifdef CBC_USE_OSL
22#include "OsiOslSolverInterface.hpp"
23#endif
24#ifdef CBC_USE_SPX
25#include "OsiSpxSolverInterface.hpp"
26#endif
27#ifdef CBC_USE_DYLP
28#include "OsiDylpSolverInterface.hpp"
29#endif
30#ifdef CBC_USE_GLPK
31#include "OsiGlpkSolverInterface.hpp"
32#endif
33#ifdef CBC_USE_CLP
34#include "OsiClpSolverInterface.hpp"
35#endif
36#ifdef NDEBUG
37#undef NDEBUG
38#endif
39
40#include "CoinTime.hpp"
41// Function Prototypes. Function definitions is in this file.
42void testingMessage( const char * const msg );
43
44#ifdef CBC_USE_CBC
45void CbcUnitTest (const std::vector<OsiCbcSolverInterface*> & vecEmptySiP,
46                  const std::string & mpsDir)
47{
48  int i ;
49  unsigned int m ;
50  // See if files exist
51  FILE * fp;
52  bool doTest=false;
53  std::string test1 = mpsDir +"p0033";
54  fp=fopen(test1.c_str(),"r");
55  if (fp) {
56    doTest=true;
57    fclose(fp);
58  }
59#ifdef COIN_USE_ZLIB
60  test1 += ".gz";
61  fp=fopen(test1.c_str(),"r");
62  if (fp) {
63    doTest=true;
64    fclose(fp);
65  }
66#endif
67  if (!doTest)
68    return;
69  /*
70    Vectors to hold test problem names and characteristics. The objective value
71    after optimization (objValue) must agree to the specified tolerance
72    (objValueTol).
73  */
74  std::vector<std::string> mpsName ;
75  std::vector<int> nRows ;
76  std::vector<int> nCols ;
77  std::vector<double> objValueC ;
78  std::vector<double> objValue ;
79  std::vector<int> strategy ;
80  /*
81    And a macro to make the vector creation marginally readable.
82  */
83#define PUSH_MPS(zz_mpsName_zz,\
84                 zz_nRows_zz,zz_nCols_zz,zz_objValue_zz,zz_objValueC_zz, \
85                 zz_strategy_zz) \
86  mpsName.push_back(zz_mpsName_zz) ; \
87  nRows.push_back(zz_nRows_zz) ; \
88  nCols.push_back(zz_nCols_zz) ; \
89  objValueC.push_back(zz_objValueC_zz) ; \
90  strategy.push_back(zz_strategy_zz) ; \
91  objValue.push_back(zz_objValue_zz) ;
92 
93  /*
94    Load up the problem vector. Note that the row counts here include the
95    objective function.
96 
97    Set HOWMANY to 0 for no test, 1 for some, 2 for many, 3 for all.
98  */
99#define HOWMANY 1
100#if HOWMANY
101#if HOWMANY>1
102    PUSH_MPS("10teams",230,2025,924,917,7)
103#endif
104    PUSH_MPS("air03",124,10757,340160,338864.25,7)
105#if HOWMANY==3
106    PUSH_MPS("air04",823,8904,56137,55535.436,8)
107    PUSH_MPS("air05",426,7195,26374,25877.609,8)
108#endif
109    //    PUSH_MPS("arki001",1048,1388,7580813.0459,7579599.80787,7)
110    PUSH_MPS("bell3a",123,133,878430.32,862578.64,7)
111#if HOWMANY>1
112    PUSH_MPS("bell5",91,104,8966406.49,8608417.95,7)
113#endif
114    PUSH_MPS("blend2",274,353,7.598985,6.9156751140,7)
115#if HOWMANY>1
116    PUSH_MPS("cap6000",2176,6000,-2451377,-2451537.325,7)
117#endif
118    //    PUSH_MPS("dano3mip",3202,13873,728.1111,576.23162474,7)
119    //    PUSH_MPS("danoint",664,521,65.67,62.637280418,7)
120    PUSH_MPS("dcmulti",290,548,188182,183975.5397,7)
121    PUSH_MPS("dsbmip",1182,1886,-305.19817501,-305.19817501,7)
122    PUSH_MPS("egout",98,141,568.101,149.589,7)
123    PUSH_MPS("enigma",21,100,0.0,0.0,7)
124#if HOWMANY==3
125    PUSH_MPS("fast0507",507,63009,174,172.14556668,7)
126#endif
127    PUSH_MPS("fiber",363,1298,405935.18000,156082.51759,7)
128#if HOWMANY>1
129    PUSH_MPS("fixnet6",478,878,3983,1200.88,7)
130#endif
131    PUSH_MPS("flugpl",18,18,1201500,1167185.7,7)
132    PUSH_MPS("gen",780,870,112313,112130.0,7)
133#if HOWMANY>1
134    PUSH_MPS("gesa2",1392,1224,25779856.372,25476489.678,7)
135    PUSH_MPS("gesa2_o",1248,1224,25779856.372,25476489.678,7)
136#endif
137    PUSH_MPS("gesa3",1368,1152,27991042.648,27833632.451,7)
138    PUSH_MPS("gesa3_o",1224,1152,27991042.648,27833632.451,7)
139    PUSH_MPS("gt2",29,188,21166.000,13460.233074,7)
140#if HOWMANY==3
141    PUSH_MPS("harp2",112,2993,-73899798.00,-74353341.502,7)
142#endif
143    PUSH_MPS("khb05250",101,1350,106940226,95919464.0,7)
144#if HOWMANY>1
145    PUSH_MPS("l152lav",97,1989,4722,4656.36,7)
146#endif
147    PUSH_MPS("lseu",28,89,1120,834.68,7)
148    PUSH_MPS("misc03",96,160,3360,1910.,7)
149    PUSH_MPS("misc06",820,1808,12850.8607,12841.6,7)
150#if HOWMANY>1
151    PUSH_MPS("misc07",212,260,2810,1415.0,7)
152    PUSH_MPS("mitre",2054,10724,115155,114740.5184,7)
153#endif
154    PUSH_MPS("mod008",6,319,307,290.9,7)
155    PUSH_MPS("mod010",146,2655,6548,6532.08,7)
156#if HOWMANY==3
157    PUSH_MPS("mod011",4480,10958,-54558535,-62121982.55,7)
158    PUSH_MPS("modglob",291,422,20740508,20430947.,7)
159    PUSH_MPS("noswot",182,128,-43,-43.0,7)
160#endif
161#if HOWMANY>1
162    PUSH_MPS("nw04",36,87482,16862,16310.66667,7)
163#endif
164    PUSH_MPS("p0033",16,33,3089,2520.57,7)
165    PUSH_MPS("p0201",133,201,7615,6875.0,7)
166    PUSH_MPS("p0282",241,282,258411,176867.50,7)
167    PUSH_MPS("p0548",176,548,8691,315.29,7)
168    PUSH_MPS("p2756",755,2756,3124,2688.75,7)
169#if HOWMANY==3
170    PUSH_MPS("pk1",45,86,11.0,0.0,7)
171#endif
172#if HOWMANY>1
173    PUSH_MPS("pp08a",136,240,7350.0,2748.3452381,7)
174    PUSH_MPS("pp08aCUTS",246,240,7350.0,5480.6061563,7)
175#endif
176#if HOWMANY==3
177    PUSH_MPS("qiu",1192,840,-132.873137,-931.638857,7)
178#endif
179    PUSH_MPS("qnet1",503,1541,16029.692681,14274.102667,7)
180    PUSH_MPS("qnet1_o",456,1541,16029.692681,12095.571667,7)
181    PUSH_MPS("rentacar",6803,9557,30356761,28806137.644,7)
182    PUSH_MPS("rgn",24,180,82.1999,48.7999,7)
183#if HOWMANY==3
184    PUSH_MPS("rout",291,556,1077.56,981.86428571,7)
185    PUSH_MPS("set1ch",492,712,54537.75,32007.73,7)
186#endif
187    //    PUSH_MPS("seymour",4944,1372,423,403.84647413,7)
188    PUSH_MPS("stein27",118,27,18,13.0,7)
189#if HOWMANY>1
190    PUSH_MPS("stein45",331,45,30,22.0,7)
191#endif
192    PUSH_MPS("vpm1",234,378,20,15.4167,7)
193    PUSH_MPS("vpm2",234,378,13.75,9.8892645972,7)
194#endif
195#undef PUSH_MPS
196   
197  /*
198    Create a vector of solver interfaces that we can use to run the test
199    problems. The strategy is to create a fresh clone of the `empty' solvers
200    from vecEmptySiP for each problem, then proceed in stages: read the MPS
201    file, solve the problem, check the solution. If there are multiple
202    solvers in vecSiP, the results of each solver are compared with its
203    neighbors in the vector.
204  */
205  int numberSolvers=vecEmptySiP.size();
206  std::vector<OsiSolverInterface*> vecSiP(numberSolvers) ;
207
208  // Create vector to store a name for each solver interface
209  // and a count on the number of problems the solver interface solved.
210  std::vector<std::string> siName;
211  std::vector<int> numProbSolved;
212  std::vector<double> timeTaken;
213  for ( i=0; i<numberSolvers; i++ ) {
214    std::string name;
215    vecEmptySiP[i]->getStrParam(OsiSolverName,name);
216    siName.push_back(name);
217    numProbSolved.push_back(0);
218    timeTaken.push_back(0.0);
219  }
220 
221  /*
222    Open the main loops. Outer loop steps through MPS problems, inner loop
223    steps through solvers.
224  */
225  for (m = 0 ; m < mpsName.size() ; m++)
226  { std::cerr << "  processing mps file: " << mpsName[m] 
227              << " (" << m+1 << " out of " << mpsName.size() << ")"
228              << std::endl ;
229    for (i = vecSiP.size()-1 ; i >= 0 ; --i) {
230      vecSiP[i] = vecEmptySiP[i]->clone() ;
231    /*
232      Stage 1: Read the MPS file into the solver interface.
233
234      As a basic check, make sure the size of the constraint matrix is correct.
235    */
236     
237      std::string fn = mpsDir+mpsName[m] ;
238      vecSiP[i]->readMps(fn.c_str(),"") ;
239     
240      vecSiP[i]->setObjSense(1.0) ;
241     
242      int nr = vecSiP[i]->getNumRows() ;
243      int nc = vecSiP[i]->getNumCols() ;
244      assert(nr == nRows[m]) ;
245      assert(nc == nCols[m]) ;
246    /*
247      Stage 2: Call the solver to get a solution for the LP relaxation.
248    */
249      double startTime = CoinCpuTime();
250      OsiCbcSolverInterface * integerSolver =
251        dynamic_cast<OsiCbcSolverInterface *>(vecSiP[i]) ;
252      assert(integerSolver);
253      integerSolver->initialSolve();
254    /*
255      Stage 3: Call the solver to perform branch and cut.
256     
257      We call each solver, then check the return code and objective.
258      Limits are 50000 nodes and one hour of time.
259    */
260
261      integerSolver->setMaximumNodes(50000);
262      integerSolver->setMaximumSeconds(60*60);
263      integerSolver->getModelPtr()->messageHandler()->setLogLevel(1) ;
264      integerSolver->branchAndBound();
265     
266      double timeOfSolution = CoinCpuTime()-startTime;
267      if (!integerSolver->status()) { 
268        double soln = integerSolver->getObjValue();       
269        CoinRelFltEq eq(1.0e-3) ;
270        if (eq(soln,objValue[m])) { 
271          std::cerr
272            <<siName[i]<<" "
273            << soln << " = " << objValue[m] << " ; okay";
274          numProbSolved[i]++;
275        } else  { 
276          std::cerr <<siName[i] <<" " <<soln << " != " <<objValue[m] << "; error=" ;
277          std::cerr <<fabs(objValue[m] - soln); 
278        }
279      } else {
280        std::cerr << "error; too many nodes" ;
281      }
282      std::cerr<<" - took " <<timeOfSolution<<" seconds."<<std::endl; 
283      timeTaken[i] += timeOfSolution;
284      delete integerSolver;
285    }
286  }
287
288  const int siName_size = siName.size();
289  for ( i=0; i<siName_size; i++ ) {
290    std::cerr
291      <<siName[i] 
292      <<" solved " 
293      <<numProbSolved[i]
294      <<" out of "
295      <<objValue.size()
296      <<" and took "
297      <<timeTaken[i]
298      <<" seconds."
299      <<std::endl;
300  } 
301}
302#endif
303//----------------------------------------------------------------
304// unitTest  [-miplibDir=V2]
305//
306// where:
307//   -miplibDir: directory containing miplib files
308//       Default value V2="./Samples/miplib3"
309//
310// All parameters are optional.
311//----------------------------------------------------------------
312
313int mainTest (int argc, const char *argv[])
314{
315  int i;
316
317
318  // define valid parameter keywords
319  std::set<std::string> definedKeyWords;
320  definedKeyWords.insert("-miplibDir");
321
322  // Create a map of parameter keys and associated data
323  std::map<std::string,std::string> parms;
324  for ( i=1; i<argc; i++ ) {
325    std::string parm(argv[i]);
326    std::string key,value;
327    unsigned int  eqPos = parm.find('=');
328
329    // Does parm contain and '='
330    if ( eqPos==std::string::npos ) {
331      //Parm does not contain '='
332      key = parm;
333    }
334    else {
335      key=parm.substr(0,eqPos);
336      value=parm.substr(eqPos+1);
337    }
338
339    // Is specifed key valid?
340    if ( definedKeyWords.find(key) == definedKeyWords.end() ) {
341      // invalid key word.
342      // Write help text
343      std::cerr <<"Undefined parameter \"" <<key <<"\".\n";
344      std::cerr <<"Correct usage: \n";
345      std::cerr <<"  unitTest [-miplibDir=V2] \n";
346      std::cerr <<"  where:\n";
347      std::cerr <<"    -miplibDir: directory containing miplib files\n";
348      std::cerr <<"        Default value V2=\"./Samples/miplib3\"\n";
349      return 1;
350    }
351    parms[key]=value;
352  }
353 
354  const char dirsep =  CoinFindDirSeparator();
355 
356  // Set directory containing miplib data files.
357  std::string miplibDir;
358  if (parms.find("-miplibDir") != parms.end())
359    miplibDir=parms["-miplibDir"] + dirsep;
360  else 
361    miplibDir = dirsep == '/' ? "./Samples/miplib3/" : ".\\Samples\\miplib3\\";
362#ifdef CBC_USE_CBC
363
364  {
365    // Create vector of solver interfaces
366    std::vector<OsiCbcSolverInterface*> vecSi;
367    CbcStrategyDefault strategy(false);
368#   if CBC_USE_OSL
369    OsiSolverInterface * oslSi = new OsiOslSolverInterface;
370    vecSi.push_back(new OsiCbcSolverInterface(oslSi,&strategy));
371#endif
372#   if CBC_USE_SPX
373    OsiSolverInterface * spxSi = new OsiSpxSolverInterface;
374    vecSi.push_back(new OsiCbcSolverInterface(spxSi,&strategy));
375#endif
376#   if CBC_USE_CLP
377    OsiSolverInterface *clpSi = new OsiClpSolverInterface ;
378    /* Quiet, already! */
379    clpSi->setHintParam(OsiDoReducePrint,true,OsiHintDo) ;
380    vecSi.push_back(new OsiCbcSolverInterface(clpSi,&strategy));
381#endif
382#   if CBC_USE_DYLP
383    OsiSolverInterface * dylpSi = new OsiDylpSolverInterface;
384    vecSi.push_back(new OsiCbcSolverInterface(dylpSi,&strategy));
385#endif
386#   if CBC_USE_GLPK
387    OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface;
388    vecSi.push_back(new OsiCbcSolverInterface(glpkSi,&strategy));
389#endif
390
391    testingMessage( "Testing some miplib stuff\n" );
392    CbcUnitTest(vecSi,miplibDir);
393
394    unsigned int i;
395    for (i=0; i<vecSi.size(); i++)
396      delete vecSi[i];
397  }
398#endif
399  testingMessage( "All tests completed successfully\n" );
400  return 0;
401}
402
403 
404// Display message on stdout and stderr
405void testingMessage( const char * const msg )
406{
407  std::cerr << msg << std::endl ;
408  // std::cout << msg << std::endl ;
409}
410
Note: See TracBrowser for help on using the repository browser.