CouenneSolver.cpp
Go to the documentation of this file.
1 // $Id: CouenneSolver.cpp 530 2011-03-12 16:52:06Z pbelotti $
2 //
3 // (C) Copyright International Business Machines Corporation and Carnegie Mellon University 2006, 2007
4 // All Rights Reserved.
5 // This code is published under the Eclipse Public License (EPL).
6 //
7 // Authors :
8 // Pietro Belotti, Lehigh University
9 // Stefan Vigerske, Humboldt University
10 //
11 // Date : 07/06/2009
12 
13 //#include "CouenneConfig.h"
14 
15 #include <cstdlib>
16 
17 #include "CoinPragma.hpp"
18 #include "CoinError.hpp"
19 #include "CoinTime.hpp"
20 
21 #include "CouenneUserInterface.hpp"
22 #ifdef COIN_HAS_ASL
23 #include "CouenneAmplInterface.hpp"
24 #endif
25 #ifdef COIN_HAS_OS
26 #include "CouenneOSInterface.hpp"
27 #endif
28 
29 #include "BonRegisteredOptions.hpp"
30 #include "BonCbc.hpp"
31 
32 #include "BonCouenneSetup.hpp"
33 #include "BonCouenneInterface.hpp"
34 
35 // for printing of statistics
36 #include "CbcCutGenerator.hpp"
37 #include "CouenneCutGenerator.hpp"
38 #include "CouenneProblem.hpp"
39 
40 using namespace Couenne;
41 
42 // the maximum difference between a printed optimum and a CouNumber
43 #define PRINTED_PRECISION 1e-5
44 
45 using Ipopt::SmartPtr;
46 
47 static const int infeasible = 1;
48 
49 bool parseCommandLine(int argc, char* argv[], Ipopt::SmartPtr<Ipopt::OptionsList> options) {
50  assert(IsValid(options));
51 
52  if (argc==3 && strcmp(argv[1], "-AMPL")==0)
53  options->SetStringValue("nlfile", argv[2]);
54 
55  if (argc==3 && strcmp(argv[1], "-OSIL")==0)
56  options->SetStringValue("osilfile", argv[2]);
57 
58  return true;
59 }
60 
61 int main (int argc, char *argv[]) {
62  WindowsErrorPopupBlocker();
63 
64  double time_start = CoinCpuTime();
65 
66  // register options to prepare for parsing the command line
68  Bonmin::CouenneSetup::registerAllOptions(roptions);
69 #ifdef COIN_HAS_ASL
71 #endif
72 #ifdef COIN_HAS_OS
74 #endif
75 
76  SmartPtr<Ipopt::Journalist> jnlst = new Ipopt::Journalist();
77  // do not add journals yet, maybe the user wants to do so; but what if parsing the command line gives errors?
78 
79  SmartPtr<Ipopt::OptionsList> options = new Ipopt::OptionsList(GetRawPtr(roptions), jnlst);
80  if (!parseCommandLine(argc, argv, options))
81  return EXIT_FAILURE;
82 
83 
84 
85  CouenneUserInterface* userinterface = NULL;
86 
87  std::string dummy;
88 #ifdef COIN_HAS_ASL
89  if (!userinterface && options->GetStringValue("nlfile", dummy, "")) {
90  userinterface = new CouenneAmplInterface(options, jnlst);
91  ((CouenneAmplInterface*)userinterface) -> setRegisteredOptions(roptions); // for some reason the TMINLP constructor needs the registered options
92  }
93 #endif
94 #ifdef COIN_HAS_OS
95  if (!userinterface && options->GetStringValue("osilfile", dummy, "")) {
96  userinterface = new CouenneOSInterface();
97  }
98 #endif
99 
100  if (!userinterface) {
101  fprintf(stderr, "Error: No input file given.\n");
102  return EXIT_FAILURE;
103  }
104 
105  if (!userinterface->setupJournals())
106  return EXIT_FAILURE;
107 
108  CouenneProblem* problem = userinterface->getCouenneProblem();
109  if (!problem)
110  return EXIT_FAILURE;
111  problem->initOptions(options);
112 
113  SmartPtr<Bonmin::TMINLP> tminlp = userinterface->getTMINLP();
114  if (Ipopt::IsNull(tminlp))
115  return EXIT_FAILURE;
116 
117  try {
118  Bonmin::Bab bb;
119  bb.setUsingCouenne (true);
120 
121  Bonmin::CouenneSetup couenne;
122  couenne.setOptionsAndJournalist(roptions, options, jnlst);
123  if (!couenne.InitializeCouenne (NULL, problem, tminlp))
124  throw infeasible;
125 
126  double timeLimit = 0;
127  options -> GetNumericValue ("time_limit", timeLimit, "couenne.");
128  couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime, timeLimit - (time_start = (CoinCpuTime () - time_start)));
129 
130  if (!userinterface->addBabPlugins(bb))
131  return EXIT_FAILURE;
132 
133  bb (couenne); // do branch and bound
134 
135  // retrieve test value to check
136  double global_opt;
137  options -> GetNumericValue ("couenne_check", global_opt, "couenne.");
138 
139  if (global_opt < COUENNE_INFINITY) { // some value found in couenne.opt
140  double opt = bb.model (). getBestPossibleObjValue ();
141 
142  jnlst -> Printf(Ipopt::J_SUMMARY, J_PROBLEM, "Global Optimum Test on %-40s %s\n",
143  problem -> problemName ().c_str (),
144  (fabs (opt - global_opt) /
145  (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ?
146  "OK" : "FAILED");
147 
148  } else if (couenne.displayStats ()) { // print statistics
149 
150  int nr=-1, nt=-1;
151  double st=-1;
152 
153  CouenneCutGenerator* cg = NULL;
154  if (bb.model (). cutGenerators ())
155  cg = dynamic_cast <CouenneCutGenerator *> (bb.model (). cutGenerators () [0] -> generator ());
156  if (cg) cg -> getStats (nr, nt, st);
157  else jnlst -> Printf(Ipopt::J_WARNING, J_PROBLEM, "Warning: Could not get pointer to CouenneCutGenerator\n");
158 
159  jnlst -> Printf(Ipopt::J_SUMMARY, J_PROBLEM, "Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
160  "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
161  "%20e [lower] %20e [upper] %7d [nodes]\n",// %s %s\n",
162  problem -> problemName ().c_str (),
163  problem -> nOrigVars (),
164  problem -> nOrigIntVars(),
165  problem -> nOrigCons (),
166  problem -> nVars () - problem -> nOrigVars (),
167  nr, nt, st,
168  CoinCpuTime () - time_start,
169  cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
170  bb.model (). getBestPossibleObjValue (),
171  bb.model (). getObjValue (),
172  //bb.bestBound (),
173  //bb.bestObj (),
174  bb.numNodes ()
175  //bb.iterationCount (),
176  //status.c_str (), message.c_str ()
177  );
178  }
179 
180  if (!userinterface->writeSolution(bb))
181  return EXIT_FAILURE;
182 
184  E->writeDiffFiles();
185  E->printError(std::cerr);
186  //There has been a failure to solve a problem with Ipopt.
187  //And we will output file with information on what has been changed in the problem to make it fail.
188  //Now depending on what algorithm has been called (B-BB or other) the failed problem may be at different place.
189  // const OsiSolverInterface &si1 = (algo > 0) ? nlpSolver : *model.solver();
190 
192  std::cerr<<E.className()<<"::"<<E.methodName()
193  <<std::endl
194  <<E.message()<<std::endl;
195 
196  } catch(CoinError &E) {
197  std::cerr<<E.className()<<"::"<<E.methodName()
198  <<std::endl
199  <<E.message()<<std::endl;
200 
201  } catch (Ipopt::OPTION_INVALID &E) {
202  std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
203 
204  } catch (int generic_error) {
205  if (generic_error == infeasible)
206  jnlst->Printf(Ipopt::J_SUMMARY, J_PROBLEM, "problem infeasible\n");
207  }
208 
209  delete userinterface;
210 
211  return EXIT_SUCCESS;
212 }
Cut Generator for linear convexifications.
static const int infeasible
int main(int argc, char *argv[])
Definition: BB_tm.cpp:32
bool IsValid(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:465
void writeDiffFiles(const std::string prefix=std::string()) const
write files with differences between input model and this one
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
virtual bool addBabPlugins(Bonmin::Bab &bab)
Called after B&amp;B object is setup.
virtual Ipopt::SmartPtr< Bonmin::TMINLP > getTMINLP()=0
Should return the problem to solve as TMINLP.
void initOptions(Ipopt::SmartPtr< Ipopt::OptionsList > options)
initializes parameters like doOBBT
Error class to throw exceptions from OsiTMINLPInterface.
virtual bool writeSolution(Bonmin::Bab &bab)
Called after B&amp;B finished.
virtual bool setupJournals()
Setup journals for printing.
bool IsNull(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:471
virtual CouenneProblem * getCouenneProblem()=0
Should return the problem to solve in algebraic form.
Class for MINLP problems with symbolic information.
void printError(std::ostream &os)
Print error message.
U * GetRawPtr(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:452
#define COUENNE_INFINITY
We will throw this error when a problem is not solved.
#define PRINTED_PRECISION
fint nt
int numNodes() const
return the total number of nodes explored.
Definition: BonCbc.hpp:67
const Ipopt::EJournalCategory J_PROBLEM(Ipopt::J_USER4)
bool parseCommandLine(int argc, char *argv[], Ipopt::SmartPtr< Ipopt::OptionsList > options)
Definition: Couenne.cpp:70
const CbcModel & model() const
Get cbc model used to solve.
Definition: BonCbc.hpp:87
Class to add a few more information to Ipopt::RegisteredOptions.