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

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

adjust to changes in CoinUtils? header files

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