source: stable/2.7/Cbc/src/unitTest.cpp @ 1577

Last change on this file since 1577 was 1573, checked in by lou, 9 years ago

Change to EPL license notice.

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