source: trunk/Cbc/src/unitTest.cpp

Last change on this file was 2467, checked in by unxusr, 5 months ago

spaces after angles

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