source: stable/2.8/Cbc/src/unitTest.cpp @ 1870

Last change on this file since 1870 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
Line 
1/* $Id: unitTest.cpp 1668 2011-06-13 16:32:06Z forrest $ */
2// Copyright (C) 2002, 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// Test individual classes or groups of classes
7
8#include "CbcConfig.h"
9#include "CoinPragma.hpp"
10
11#include <cstdlib>
12#include <cassert>
13#include <vector>
14#include <iostream>
15#include <cstdio>
16
17#include "CoinHelperFunctions.hpp"
18#include "CoinFileIO.hpp"
19
20#ifdef COIN_HAS_CBC
21#include "OsiCbcSolverInterface.hpp"
22#endif
23#ifdef COIN_HAS_OSL
24#include "OsiOslSolverInterface.hpp"
25#endif
26#ifdef COIN_HAS_SPX
27#include "OsiSpxSolverInterface.hpp"
28#endif
29#ifdef COIN_HAS_DYLP
30#include "OsiDylpSolverInterface.hpp"
31#endif
32#ifdef COIN_HAS_GLPK
33#include "OsiGlpkSolverInterface.hpp"
34#endif
35#ifdef COIN_HAS_CLP
36#include "OsiClpSolverInterface.hpp"
37#endif
38#ifdef NDEBUG
39#undef NDEBUG
40#endif
41
42#include "CoinTime.hpp"
43// Function Prototypes. Function definitions is in this file.
44void testingMessage( const char * const msg );
45
46#ifdef COIN_HAS_CBC
47void CbcMiplibTest (const std::vector<OsiCbcSolverInterface*> & vecEmptySiP,
48                    const std::string & mpsDir)
49{
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    }
61    if (!doTest && CoinFileInput::haveGzipSupport())
62    {
63      test1 += ".gz";
64      fp = fopen(test1.c_str(), "r");
65      if (fp) {
66        doTest = true;
67        fclose(fp);
68      }
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    */
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) ;
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    */
102#define HOWMANY 1
103#if HOWMANY
104#if HOWMANY>1
105    PUSH_MPS("10teams", 230, 2025, 924, 917, 7)
106#endif
107    PUSH_MPS("air03", 124, 10757, 340160, 338864.25, 7)
108#if HOWMANY==3
109    PUSH_MPS("air04", 823, 8904, 56137, 55535.436, 8)
110    PUSH_MPS("air05", 426, 7195, 26374, 25877.609, 8)
111#endif
112    //    PUSH_MPS("arki001",1048,1388,7580813.0459,7579599.80787,7)
113    PUSH_MPS("bell3a", 123, 133, 878430.32, 862578.64, 7)
114#if HOWMANY>1
115    PUSH_MPS("bell5", 91, 104, 8966406.49, 8608417.95, 7)
116#endif
117    PUSH_MPS("blend2", 274, 353, 7.598985, 6.9156751140, 7)
118#if HOWMANY>1
119    PUSH_MPS("cap6000", 2176, 6000, -2451377, -2451537.325, 7)
120#endif
121    //    PUSH_MPS("dano3mip",3202,13873,728.1111,576.23162474,7)
122    //    PUSH_MPS("danoint",664,521,65.67,62.637280418,7)
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)
127#if HOWMANY==3
128    PUSH_MPS("fast0507", 507, 63009, 174, 172.14556668, 7)
129#endif
130    PUSH_MPS("fiber", 363, 1298, 405935.18000, 156082.51759, 7)
131#if HOWMANY>1
132    PUSH_MPS("fixnet6", 478, 878, 3983, 1200.88, 7)
133#endif
134    PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 7)
135    PUSH_MPS("gen", 780, 870, 112313, 112130.0, 7)
136#if HOWMANY>1
137    PUSH_MPS("gesa2", 1392, 1224, 25779856.372, 25476489.678, 7)
138    PUSH_MPS("gesa2_o", 1248, 1224, 25779856.372, 25476489.678, 7)
139#endif
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)
143#if HOWMANY==3
144    PUSH_MPS("harp2", 112, 2993, -73899798.00, -74353341.502, 7)
145#endif
146    PUSH_MPS("khb05250", 101, 1350, 106940226, 95919464.0, 7)
147#if HOWMANY>1
148    PUSH_MPS("l152lav", 97, 1989, 4722, 4656.36, 7)
149#endif
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)
153#if HOWMANY>1
154    PUSH_MPS("misc07", 212, 260, 2810, 1415.0, 7)
155    PUSH_MPS("mitre", 2054, 10724, 115155, 114740.5184, 7)
156#endif
157    PUSH_MPS("mod008", 6, 319, 307, 290.9, 7)
158    PUSH_MPS("mod010", 146, 2655, 6548, 6532.08, 7)
159#if HOWMANY==3
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)
163#endif
164#if HOWMANY>1
165    PUSH_MPS("nw04", 36, 87482, 16862, 16310.66667, 7)
166#endif
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)
172#if HOWMANY==3
173    PUSH_MPS("pk1", 45, 86, 11.0, 0.0, 7)
174#endif
175#if HOWMANY>1
176    PUSH_MPS("pp08a", 136, 240, 7350.0, 2748.3452381, 7)
177    PUSH_MPS("pp08aCUTS", 246, 240, 7350.0, 5480.6061563, 7)
178#endif
179#if HOWMANY==3
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 HOWMANY==3
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#if HOWMANY>1
193    PUSH_MPS("stein45", 331, 45, 30, 22.0, 7)
194#endif
195    PUSH_MPS("vpm1", 234, 378, 20, 15.4167, 7)
196    PUSH_MPS("vpm2", 234, 378, 13.75, 9.8892645972, 7)
197#endif
198#undef PUSH_MPS
199
200    /*
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) ;
210
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
224    /*
225      Open the main loops. Outer loop steps through MPS problems, inner loop
226      steps through solvers.
227    */
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.
236
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;
288        }
289    }
290
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    }
304}
305#endif  // COIN_HAS_CBC
306
307//----------------------------------------------------------------
308// unitTest  [-miplibDir=V2]
309//
310// where:
311//   -miplibDir: directory containing miplib files
312//       Default value V2="./examples/miplib3"
313//
314// All parameters are optional.
315//----------------------------------------------------------------
316
317int mainTest (int argc, const char *argv[])
318{
319    int i;
320
321
322    // define valid parameter keywords
323    std::set<std::string> definedKeyWords;
324    definedKeyWords.insert("-miplibDir");
325
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('=');
332
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;
355    }
356
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\\";
365#ifdef COIN_HAS_CBC
366
367    {
368        // Create vector of solver interfaces
369        std::vector<OsiCbcSolverInterface*> vecSi;
370        CbcStrategyDefault strategy(0);
371#   if COIN_HAS_OSL
372        OsiSolverInterface * oslSi = new OsiOslSolverInterface;
373        vecSi.push_back(new OsiCbcSolverInterface(oslSi, &strategy));
374#endif
375#   if COIN_HAS_SPX
376        OsiSolverInterface * spxSi = new OsiSpxSolverInterface;
377        vecSi.push_back(new OsiCbcSolverInterface(spxSi, &strategy));
378#endif
379#   if COIN_HAS_CLP
380        OsiSolverInterface *clpSi = new OsiClpSolverInterface ;
381        /* Quiet, already! */
382        clpSi->setHintParam(OsiDoReducePrint, true, OsiHintDo) ;
383        vecSi.push_back(new OsiCbcSolverInterface(clpSi, &strategy));
384#endif
385#   if COIN_HAS_DYLP
386        OsiSolverInterface * dylpSi = new OsiDylpSolverInterface;
387        vecSi.push_back(new OsiCbcSolverInterface(dylpSi, &strategy));
388#endif
389#   if COIN_HAS_GLPK
390        OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface;
391        vecSi.push_back(new OsiCbcSolverInterface(glpkSi, &strategy));
392#endif
393
394        testingMessage( "Testing some miplib stuff\n" );
395        CbcMiplibTest(vecSi, miplibDir);
396
397        unsigned int i;
398        for (i = 0; i < vecSi.size(); i++)
399            delete vecSi[i];
400    }
401#else   // COIN_HAS_CBC
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 ;
407#endif  // COIN_HAS_CBC
408    testingMessage( "All tests completed successfully\n" );
409    return 0;
410}
411
412
413// Display message on stdout and stderr
414void testingMessage( const char * const msg )
415{
416    std::cerr << msg << std::endl ;
417    // std::cout << msg << std::endl ;
418}
419
Note: See TracBrowser for help on using the repository browser.