Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

unitTest.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 // Test individual classes or groups of classes
00004 
00005 #if defined(_MSC_VER)
00006 // Turn off compiler warning about long names
00007 #  pragma warning(disable:4786)
00008 #endif
00009 
00010 #include <cstdlib>
00011 #include <cassert>
00012 #include <vector>
00013 #include <iostream>
00014 #include <cstdio>
00015 
00016 #include "CoinPackedMatrix.hpp"
00017 #include "CoinWarmStartBasis.hpp"
00018 #include "OsiSolverInterface.hpp"
00019 #include "SbbModel.hpp"
00020 #ifdef COIN_USE_OSL
00021 #include "OsiOslSolverInterface.hpp"
00022 #endif
00023 #ifdef COIN_USE_XPR
00024 #include "OsiXprSolverInterface.hpp"
00025 #endif
00026 #ifdef COIN_USE_CPX
00027 #include "OsiCpxSolverInterface.hpp"
00028 #endif
00029 #ifdef COIN_USE_SPX
00030 #include "OsiSpxSolverInterface.hpp"
00031 #endif
00032 #ifdef COIN_USE_DYLP
00033 #include "OsiDylpSolverInterface.hpp"
00034 #endif
00035 #ifdef COIN_USE_GLPK
00036 #include "OsiGlpkSolverInterface.hpp"
00037 #endif
00038 #ifdef COIN_USE_CLP
00039 #include "OsiClpSolverInterface.hpp"
00040 #endif
00041    #define CUTS
00042 #ifdef CUTS
00043 #include "CglCutGenerator.hpp"
00044 #include "CglGomory.hpp"
00045 #include "CglProbing.hpp"
00046 #include "CglKnapsackCover.hpp"
00047 #include "CglOddHole.hpp"
00048 #endif
00049 #ifdef NDEBUG
00050 #undef NDEBUG
00051 #endif
00052 
00053 #include <time.h>
00054 #if !defined(_MSC_VER)
00055 #include <sys/times.h>
00056 #include <sys/resource.h>
00057 #include <unistd.h>
00058 #endif
00059 
00060 static double cpuTime()
00061 {
00062   double cpu_temp;
00063 #if defined(_MSC_VER)
00064   unsigned int ticksnow;        /* clock_t is same as int */
00065   
00066   ticksnow = (unsigned int)clock();
00067   
00068   cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC);
00069 #else
00070   struct rusage usage;
00071   getrusage(RUSAGE_SELF,&usage);
00072   cpu_temp = usage.ru_utime.tv_sec;
00073   cpu_temp += 1.0e-6*((double) usage.ru_utime.tv_usec);
00074 #endif
00075   return cpu_temp;
00076 }
00077 // Function Prototypes. Function definitions is in this file.
00078 void testingMessage( const char * const msg );
00079 
00080 void SbbUnitTest
00081   (const std::vector<OsiSolverInterface*> & vecEmptySiP,
00082    const std::string & mpsDir)
00083 
00084 { int i ;
00085   unsigned int m ;
00086 
00087 /*
00088   Vectors to hold test problem names and characteristics. The objective value
00089   after optimization (objValue) must agree to the specified tolerance
00090   (objValueTol).
00091 */
00092   std::vector<std::string> mpsName ;
00093   std::vector<int> nRows ;
00094   std::vector<int> nCols ;
00095   std::vector<double> objValueC ;
00096   std::vector<double> objValue ;
00097   std::vector<int> strategy ;
00098 /*
00099   And a macro to make the vector creation marginally readable.
00100 */
00101 #define PUSH_MPS(zz_mpsName_zz,\
00102                  zz_nRows_zz,zz_nCols_zz,zz_objValue_zz,zz_objValueC_zz, \
00103                  zz_strategy_zz) \
00104   mpsName.push_back(zz_mpsName_zz) ; \
00105   nRows.push_back(zz_nRows_zz) ; \
00106   nCols.push_back(zz_nCols_zz) ; \
00107   objValueC.push_back(zz_objValueC_zz) ; \
00108   strategy.push_back(zz_strategy_zz) ; \
00109   objValue.push_back(zz_objValue_zz) ;
00110 
00111 /*
00112   Load up the problem vector. Note that the row counts here include the
00113   objective function.
00114 
00115   Strategy is bit function - at present
00116   1 - gomory
00117   2 - probing
00118   4 - knapsack
00119   8 - oddhole
00120   1024 - switch OFF strong branching
00121 */
00122   PUSH_MPS("10teams",230,2025,924,917,7)
00123     PUSH_MPS("air03",124,10757,340160,338864.25,7)
00124 #if 0
00125     PUSH_MPS("air04",823,8904,56137,55535.436,8)
00126     PUSH_MPS("air05",426,7195,26374,25877.609,8)
00127 #endif
00128     //    PUSH_MPS("arki001",1048,1388,7580813.0459,7579599.80787,7)
00129     PUSH_MPS("bell3a",123,133,878430.32,862578.64,7)
00130     PUSH_MPS("bell5",91,104,8966406.49,8608417.95,7)
00131     PUSH_MPS("blend2",274,353,7.598985,6.9156751140,7)
00132     PUSH_MPS("cap6000",2176,6000,-2451377,-2451537.325,7)
00133     //    PUSH_MPS("dano3mip",3202,13873,728.1111,576.23162474,7)
00134     //PUSH_MPS("danoint",664,521,65.67,62.637280418,7)
00135     PUSH_MPS("dcmulti",290,548,188182,183975.5397,7)
00136     PUSH_MPS("dsbmip",1182,1886,-305.19817501,-305.19817501,7)
00137     PUSH_MPS("egout",98,141,568.101,149.589,7)
00138     PUSH_MPS("enigma",21,100,0.0,0.0,7)
00139 #if 0
00140     PUSH_MPS("fast0507",507,63009,174,172.14556668,7)
00141 #endif
00142     PUSH_MPS("fiber",363,1298,405935.18000,156082.51759,7)
00143     PUSH_MPS("fixnet6",478,878,3983,1200.88,7)
00144     PUSH_MPS("flugpl",18,18,1201500,1167185.7,7)
00145     PUSH_MPS("gen",780,870,112313,112130.0,7)
00146     PUSH_MPS("gesa2",1392,1224,25779856.372,25476489.678,7)
00147     PUSH_MPS("gesa2_o",1248,1224,25779856.372,25476489.678,7)
00148     PUSH_MPS("gesa3",1368,1152,27991042.648,27833632.451,7)
00149     PUSH_MPS("gesa3_o",1224,1152,27991042.648,27833632.451,7)
00150     PUSH_MPS("gt2",29,188,21166.000,13460.233074,7)
00151 #if 0
00152     PUSH_MPS("harp2",112,2993,-73899798.00,-74353341.502,7)
00153 #endif
00154     PUSH_MPS("khb05250",101,1350,106940226,95919464.0,7)
00155     PUSH_MPS("l152lav",97,1989,4722,4656.36,7)
00156     PUSH_MPS("lseu",28,89,1120,834.68,7)
00157     PUSH_MPS("misc03",96,160,3360,1910.,7)
00158     PUSH_MPS("misc06",820,1808,12850.8607,12841.6,7)
00159     PUSH_MPS("misc07",212,260,2810,1415.0,7)
00160     PUSH_MPS("mitre",2054,10724,115155,114740.5184,7)
00161     PUSH_MPS("mod008",6,319,307,290.9,7)
00162     PUSH_MPS("mod010",146,2655,6548,6532.08,7)
00163 #if 0
00164     PUSH_MPS("mod011",4480,10958,-54558535,-62121982.55,7)
00165     PUSH_MPS("modglob",291,422,20740508,20430947.,7)
00166     PUSH_MPS("noswot",182,128,-43,-43.0,7)
00167 #endif
00168     PUSH_MPS("nw04",36,87482,16862,16310.66667,7)
00169     PUSH_MPS("p0033",16,33,3089,2520.57,7)
00170     PUSH_MPS("p0201",133,201,7615,6875.0,7)
00171     PUSH_MPS("p0282",241,282,258411,176867.50,7)
00172     PUSH_MPS("p0548",176,548,8691,315.29,7)
00173     PUSH_MPS("p2756",755,2756,3124,2688.75,7)
00174 #if 0
00175     PUSH_MPS("pk1",45,86,11.0,0.0,7)
00176 #endif
00177     PUSH_MPS("pp08a",136,240,7350.0,2748.3452381,7)
00178     PUSH_MPS("pp08aCUTS",246,240,7350.0,5480.6061563,7)
00179 #if 0
00180     PUSH_MPS("qiu",1192,840,-132.873137,-931.638857,7)
00181 #endif
00182     PUSH_MPS("qnet1",503,1541,16029.692681,14274.102667,7)
00183     PUSH_MPS("qnet1_o",456,1541,16029.692681,12095.571667,7)
00184     PUSH_MPS("rentacar",6803,9557,30356761,28806137.644,7)
00185     PUSH_MPS("rgn",24,180,82.1999,48.7999,7)
00186 #if 0
00187     PUSH_MPS("rout",291,556,1077.56,981.86428571,7)
00188     PUSH_MPS("set1ch",492,712,54537.75,32007.73,7)
00189 #endif
00190     //    PUSH_MPS("seymour",4944,1372,423,403.84647413,7)
00191     PUSH_MPS("stein27",118,27,18,13.0,7)
00192     PUSH_MPS("stein45",331,45,30,22.0,7)
00193     PUSH_MPS("vpm1",234,378,20,15.4167,7)
00194     PUSH_MPS("vpm2",234,378,13.75,9.8892645972,7)
00195 
00196 #undef PUSH_MPS
00197 
00198 /*
00199   Create a vector of solver interfaces that we can use to run the test
00200   problems. The strategy is to create a fresh clone of the `empty' solvers
00201   from vecEmptySiP for each problem, then proceed in stages: read the MPS
00202   file, solve the problem, check the solution. If there are multiple
00203   solvers in vecSiP, the results of each solver are compared with its
00204   neighbors in the vector.
00205 */
00206   std::vector<OsiSolverInterface*> vecSiP(vecEmptySiP.size()) ;
00207 
00208   // Create vector to store a name for each solver interface
00209   // and a count on the number of problems the solver intface solved.
00210   std::vector<std::string> siName;
00211   std::vector<int> numProbSolved;
00212   std::vector<double> timeTaken;
00213   const int vecsize = vecSiP.size();
00214   for ( i=0; i<vecsize; i++ ) {
00215     siName.push_back("");
00216     numProbSolved.push_back(0);
00217     timeTaken.push_back(0.0);
00218   }
00219 
00220 /*
00221   Open the main loop to step through the MPS problems.
00222 */
00223   for (m = 0 ; m < mpsName.size() ; m++)
00224   { std::cerr << "  processing mps file: " << mpsName[m] 
00225       << " (" << m+1 << " out of " << mpsName.size() << ")" << std::endl ;
00226 /*
00227   Stage 1: Read the MPS file into each solver interface.
00228 
00229   Fill vecSiP with fresh clones of the solvers and read in the MPS file. As
00230   a basic check, make sure the size of the constraint matrix is correct.
00231 */
00232     for (i = vecSiP.size()-1 ; i >= 0 ; --i)
00233     { vecSiP[i] = vecEmptySiP[i]->clone() ;
00234       
00235       std::string fn = mpsDir+mpsName[m] ;
00236       vecSiP[i]->readMps(fn.c_str(),"") ;
00237       
00238       vecSiP[i]->setObjSense(1.0) ;
00239       
00240       int nr = vecSiP[i]->getNumRows() ;
00241       int nc = vecSiP[i]->getNumCols() ;
00242       assert(nr == nRows[m]) ;
00243       assert(nc == nCols[m]) ; } 
00244 /*
00245   Stage 2: Call each solver to solve the problem.
00246 
00247   We call each solver, then check the return code and objective.
00248 
00249 */
00250 
00251     for (i = 0 ; i < static_cast<int>(vecSiP.size()) ; ++i)
00252     {
00253       double startTime = cpuTime();
00254 #     ifdef COIN_USE_CLP
00255       { 
00256         OsiClpSolverInterface * si =
00257           dynamic_cast<OsiClpSolverInterface *>(vecSiP[i]) ;
00258         if (si != NULL )  {    
00259           siName[i]="OsiClpSolverInterface";
00260         }
00261       }
00262 #     endif
00263 #     ifdef COIN_USE_DYLP
00264       { 
00265         OsiDylpSolverInterface * si =
00266           dynamic_cast<OsiDylpSolverInterface *>(vecSiP[i]) ;
00267         if (si != NULL )  {    
00268           siName[i]="OsiDylpSolverInterface";
00269           // Is this an MPS file that OsiDylpSolverInterface handles
00270           if ( mpsName[m]=="cycle" ||
00271                mpsName[m]=="d6cube" ||
00272                mpsName[m]=="fit1d" || 
00273                mpsName[m]=="grow15" || 
00274                mpsName[m]=="grow22" || 
00275                mpsName[m]=="maros" || 
00276                mpsName[m]=="pilot" || 
00277                mpsName[m]=="pilot4" || 
00278                mpsName[m]=="pilotnov" || 
00279                mpsName[m]=="wood1p" )break ; 
00280         }
00281       }
00282 #     endif
00283 #     ifdef COIN_USE_XPR
00284       { 
00285         OsiXprSolverInterface * si =
00286           dynamic_cast<OsiXprSolverInterface *>(vecSiP[i]) ;
00287         if (si != NULL )  {    
00288           siName[i]="OsiXprSolverInterface";
00289         }
00290       }
00291 #     endif
00292 #     ifdef COIN_USE_CPX
00293       { 
00294         OsiCpxSolverInterface * si =
00295           dynamic_cast<OsiCpxSolverInterface *>(vecSiP[i]) ;
00296         if (si != NULL )  {    
00297           siName[i]="OsiCpxSolverInterface";
00298         }
00299       }
00300 #     endif
00301 #     ifdef COIN_USE_SPX
00302       { 
00303         OsiSpxSolverInterface * si =
00304           dynamic_cast<OsiSpxSolverInterface *>(vecSiP[i]) ;
00305         if (si != NULL )  {    
00306           siName[i]="OsiSpxSolverInterface";
00307         }
00308       }
00309 #     endif
00310 #     ifdef COIN_USE_OSL
00311       { 
00312         OsiOslSolverInterface * si =
00313           dynamic_cast<OsiOslSolverInterface *>(vecSiP[i]) ;
00314         if (si != NULL )  {    
00315           siName[i]="OsiOslSolverInterface";
00316         }
00317       }
00318 #     endif
00319       
00320       vecSiP[i]->initialSolve() ;
00321       SbbModel integerSolver(*vecSiP[i]);
00322       // Set up likely cut generators and defaults
00323       CglGomory try1;
00324       CglProbing try2;
00325       try2.setUsingObjective(true);
00326       try2.setMaxPass(3);
00327       try2.setMaxProbe(100);
00328       try2.setMaxLook(50);
00329       CglKnapsackCover try3;
00330       CglOddHole try4;
00331       try4.setMinimumViolation(0.005);
00332       try4.setMinimumViolationPer(0.0002);
00333       try4.setMaximumEntries(100);
00334       
00335       if ((strategy[m]&1)!=0)
00336         integerSolver.addCutGenerator(&try1,-1,"Gomory");
00337       if ((strategy[m]&2)!=0)
00338         integerSolver.addCutGenerator(&try2,-1,"Probing");
00339       if ((strategy[m]&4)!=0)
00340         integerSolver.addCutGenerator(&try3,-1,"Knapsack");
00341       if ((strategy[m]&8)!=0)
00342         integerSolver.addCutGenerator(&try4,-1,"OddHole");
00343       if ((strategy[m]&1024)!=0)
00344         integerSolver.setNumberStrong(0);
00345       integerSolver.messageHandler()->setLogLevel(1);
00346 #     ifdef COIN_USE_CLP
00347       { 
00348         OsiClpSolverInterface * si =
00349           dynamic_cast<OsiClpSolverInterface *>(integerSolver.solver()) ;
00350         if (si != NULL )  {   
00351           integerSolver.solver()->messageHandler()->setLogLevel(0);
00352         }
00353       }
00354 #endif
00355 #     ifdef COIN_USE_OSL
00356       { 
00357         OsiOslSolverInterface * si =
00358           dynamic_cast<OsiOslSolverInterface *>(integerSolver.solver()) ;
00359         if (si != NULL )  {    
00360           ekk_messagesPrintOff(si->getModelPtr(),1,4000);
00361         }
00362       }
00363 #endif
00364       integerSolver.setMaximumNodes(50000);
00365       integerSolver.branchAndBound();
00366       integerSolver.solver()->resolve();
00367       
00368       double timeOfSolution = cpuTime()-startTime;
00369       if (integerSolver.solver()->isProvenOptimal()) { 
00370         double soln = integerSolver.solver()->getObjValue();       
00371         CoinRelFltEq eq(1.0e-3) ;
00372         if (eq(soln,objValue[m])) { 
00373           std::cerr 
00374             <<siName[i]<<" "
00375             << soln << " = " << objValue[m] << " ; okay";
00376           numProbSolved[i]++;
00377         } else  { 
00378           std::cerr <<siName[i] <<" " <<soln << " != " <<objValue[m] << "; error=" ;
00379           std::cerr <<fabs(objValue[m] - soln); 
00380         }
00381       } else {
00382         if (integerSolver.solver()->isProvenPrimalInfeasible())  
00383           std::cerr << "error; primal infeasible" ;
00384         else if (integerSolver.solver()->isProvenDualInfeasible())  
00385           std::cerr << "error; dual infeasible" ;
00386         else if (integerSolver.solver()->isIterationLimitReached()) 
00387           std::cerr << "error; iteration limit" ;
00388         else if (integerSolver.solver()->isAbandoned()) 
00389           std::cerr << "error; abandoned" ;
00390         else  
00391           std::cerr << "error; unknown" ;
00392       }
00393       std::cerr<<" - took " <<timeOfSolution<<" seconds."<<std::endl; 
00394       timeTaken[i] += timeOfSolution;
00395     }
00396     /*
00397     Delete the used solver interfaces so we can reload fresh clones for the
00398               next problem.
00399     */
00400     //for (i = vecSiP.size()-1 ; i >= 0 ; --i) delete vecSiP[i] ;
00401   }
00402 
00403   const int siName_size = siName.size();
00404   for ( i=0; i<siName_size; i++ ) {
00405     std::cerr 
00406       <<siName[i] 
00407       <<" solved " 
00408       <<numProbSolved[i]
00409       <<" out of "
00410       <<objValue.size()
00411       <<" and took "
00412       <<timeTaken[i]
00413       <<" seconds."
00414       <<std::endl;
00415   } 
00416 }
00417 
00418 //----------------------------------------------------------------
00419 // unitTest [-mpsDir=V1] [-miplibDir=V2]
00420 // 
00421 // where:
00422 //   -mpsDir: directory containing mps test files
00423 //       Default value V1="../Mps/Sample"    
00424 //   -miplibDir: directory containing miplib files
00425 //       Default value V2="./Samples/miplib3"
00426 //
00427 // All parameters are optional.
00428 //----------------------------------------------------------------
00429 
00430 int mainTest (int argc, const char *argv[])
00431 {
00432   int i;
00433 
00434 #ifdef COIN_USE_XPR
00435   OsiXprSolverInterface::setLogFileName("xprCallTrace.txt");
00436 #endif
00437 
00438   // define valid parameter keywords
00439   std::set<std::string> definedKeyWords;
00440   definedKeyWords.insert("-mpsDir");
00441   definedKeyWords.insert("-miplibDir");
00442 
00443   // Create a map of parameter keys and associated data
00444   std::map<std::string,std::string> parms;
00445   for ( i=1; i<argc; i++ ) {
00446     std::string parm(argv[i]);
00447     std::string key,value;
00448     unsigned int  eqPos = parm.find('=');
00449 
00450     // Does parm contain and '='
00451     if ( eqPos==std::string::npos ) {
00452       //Parm does not contain '='
00453       key = parm;
00454     }
00455     else {
00456       key=parm.substr(0,eqPos);
00457       value=parm.substr(eqPos+1);
00458     }
00459 
00460     // Is specifed key valid?
00461     if ( definedKeyWords.find(key) == definedKeyWords.end() ) {
00462       // invalid key word.
00463       // Write help text
00464       std::cerr <<"Undefined parameter \"" <<key <<"\".\n";
00465       std::cerr <<"Correct usage: \n";
00466       std::cerr <<"  unitTest [-mpsDir=V1] [-miplibDir=V2] [-testOsiSolverInterface]\n";
00467       std::cerr <<"  where:\n";
00468       std::cerr <<"    -mpsDir: directory containing mps test files\n";
00469       std::cerr <<"        Default value V1=\"../Mps/Sample\"\n";
00470       std::cerr <<"    -miplibDir: directory containing miplib files\n";
00471       std::cerr <<"        Default value V2=\"./Samples/miplib3\"\n";
00472       return 1;
00473     }
00474     parms[key]=value;
00475   }
00476   
00477   const char dirsep =  CoinFindDirSeparator();
00478   // Set directory containing mps data files.
00479   std::string mpsDir;
00480   if (parms.find("-mpsDir") != parms.end())
00481     mpsDir=parms["-mpsDir"] + dirsep;
00482   else 
00483     mpsDir = dirsep == '/' ? "../Mps/Sample/" : "..\\Mps\\Sample\\";
00484  
00485   // Set directory containing miplib data files.
00486   std::string miplibDir;
00487   if (parms.find("-miplibDir") != parms.end())
00488     miplibDir=parms["-miplibDir"] + dirsep;
00489   else 
00490     miplibDir = dirsep == '/' ? "./Samples/miplib3/" : ".\\Samples\\miplib3\\";
00491 
00492   {
00493     // Create vector of solver interfaces
00494     std::vector<OsiSolverInterface*> vecSi;
00495 #   if COIN_USE_OSL
00496     OsiSolverInterface * oslSi = new OsiOslSolverInterface;
00497     vecSi.push_back(oslSi);
00498 #endif
00499 #   if COIN_USE_XPR
00500     OsiSolverInterface * xprSi = new OsiXprSolverInterface;
00501     vecSi.push_back(xprSi);
00502 #endif
00503 #   if COIN_USE_CPX
00504     OsiSolverInterface * cpxSi = new OsiCpxSolverInterface;
00505     vecSi.push_back(cpxSi);
00506 #endif
00507 #   if COIN_USE_SPX
00508     OsiSolverInterface * spxSi = new OsiSpxSolverInterface;
00509     vecSi.push_back(spxSi);
00510 #endif
00511 #   if COIN_USE_CLP
00512     OsiSolverInterface * clpSi = new OsiClpSolverInterface;
00513     vecSi.push_back(clpSi);
00514 #endif
00515 #   if COIN_USE_DYLP
00516     OsiSolverInterface * dylpSi = new OsiDylpSolverInterface;
00517     vecSi.push_back(dylpSi);
00518 #endif
00519 #   if COIN_USE_GLPK
00520     OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface;
00521     vecSi.push_back(glpkSi);
00522 #endif
00523 
00524     testingMessage( "Testing some miplib stuff\n" );
00525     SbbUnitTest(vecSi,miplibDir);
00526 
00527     unsigned int i;
00528     for (i=0; i<vecSi.size(); i++)
00529       delete vecSi[i];
00530   }
00531   testingMessage( "All tests completed successfully\n" );
00532   return 0;
00533 }
00534 
00535  
00536 // Display message on stdout and stderr
00537 void testingMessage( const char * const msg )
00538 {
00539   std::cerr <<msg;
00540   //cout <<endl <<"*****************************************"
00541   //     <<endl <<msg <<endl;
00542 }
00543 

Generated on Wed Dec 3 14:36:22 2003 for Sbb by doxygen 1.3.5