source: trunk/Cbc/src/unitTest.cpp @ 2014

Last change on this file since 2014 was 1668, checked in by stefan, 8 years ago

use CoinFileIO::have*Support to decide whether compressed files can be read

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