Couenne.cpp
Go to the documentation of this file.
1 // $Id: Couenne.cpp 959 2013-05-24 04:43:23Z stefan $
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 #ifdef COIN_HAS_SCIP
41 #include "lpiswitch.h"
42 #endif
43 
44 
45 namespace Ipopt {
46  class OptionsList;
47  class Journalist;
48 }
49 
50 using Ipopt::SmartPtr;
51 
52 namespace Bonmin {
53  class RegisteredOptions;
54  class TMINLP;
55  class Bab;
56  class BabSetupBase;
57  class TNLPSolver;
58  class OsiTMINLPInterface;
59 }
60 
61 using namespace Couenne;
62 
63 // the maximum difference between a printed optimum and a CouNumber
64 #define PRINTED_PRECISION 1e-5
65 
66 using Ipopt::SmartPtr;
67 
68 static const int infeasible = 1;
69 
70 bool parseCommandLine(int argc, char* argv[], Ipopt::SmartPtr<Ipopt::OptionsList> options) {
71  assert(IsValid(options));
72 
73  if (argc==3 && strcmp(argv[1], "-AMPL")==0)
74  options->SetStringValue("nlfile", argv[2]);
75 
76  if (argc==3 && strcmp(argv[1], "-OSIL")==0)
77  options->SetStringValue("osilfile", argv[2]);
78 
79  return true;
80 }
81 
82 int main (int argc, char *argv[]) {
83  WindowsErrorPopupBlocker();
84 
85 #ifdef COIN_HAS_SCIP
86  SCIPlpiSwitchSetDefaultSolver();
87 #endif
88 
89  double time_start = CoinCpuTime();
90 
91  // register options to prepare for parsing the command line
94 #ifdef COIN_HAS_ASL
96 #endif
97 #ifdef COIN_HAS_OS
99 #endif
100 
101  SmartPtr<Ipopt::Journalist> jnlst = new Ipopt::Journalist();
102  // do not add journals yet, maybe the user wants to do so; but what if parsing the command line gives errors?
103 
104  SmartPtr<Ipopt::OptionsList> options = new Ipopt::OptionsList(GetRawPtr(roptions), jnlst);
105  if (!parseCommandLine(argc, argv, options))
106  return EXIT_FAILURE;
107 
108 
109 
110  CouenneUserInterface* userinterface = NULL;
111 
112  std::string dummy;
113 #ifdef COIN_HAS_ASL
114  if (!userinterface && options->GetStringValue("nlfile", dummy, "")) {
115  userinterface = new CouenneAmplInterface(options, jnlst);
116  ((CouenneAmplInterface*)userinterface) -> setRegisteredOptions(roptions); // for some reason the TMINLP constructor needs the registered options
117  }
118 #endif
119 #ifdef COIN_HAS_OS
120  if (!userinterface && options->GetStringValue("osilfile", dummy, "")) {
121  userinterface = new CouenneOSInterface();
122  }
123 #endif
124 
125  if (!userinterface) {
126  fprintf(stderr, "Error: No input file given.\n");
127  return EXIT_FAILURE;
128  }
129 
130  if (!userinterface->setupJournals())
131  return EXIT_FAILURE;
132 
133  CouenneProblem* problem = userinterface->getCouenneProblem();
134  if (!problem)
135  return EXIT_FAILURE;
136  problem->initOptions(options);
137 
138  SmartPtr<Bonmin::TMINLP> tminlp = userinterface->getTMINLP();
139  if (Ipopt::IsNull(tminlp))
140  return EXIT_FAILURE;
141 
142  try {
143  Bonmin::Bab bb;
144  bb.setUsingCouenne (true);
145 
146  CouenneSetup couenne;
147  couenne.setOptionsAndJournalist(roptions, options, jnlst);
148  if (!couenne.InitializeCouenne (NULL, problem, tminlp))
149  throw infeasible;
150 
151  double timeLimit = 0;
152  options -> GetNumericValue ("time_limit", timeLimit, "couenne.");
153  couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime, timeLimit - (time_start = (CoinCpuTime () - time_start)));
154 
155  if (!userinterface->addBabPlugins(bb))
156  return EXIT_FAILURE;
157 
158  bb (couenne); // do branch and bound
159 
160  // retrieve test value to check
161  double global_opt;
162  options -> GetNumericValue ("couenne_check", global_opt, "couenne.");
163 
164  if (global_opt < COUENNE_INFINITY) { // some value found in couenne.opt
165  double opt = bb.model (). getBestPossibleObjValue ();
166 
167  jnlst -> Printf(Ipopt::J_SUMMARY, J_PROBLEM, "Global Optimum Test on %-40s %s\n",
168  problem -> problemName ().c_str (),
169  (fabs (opt - global_opt) /
170  (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ?
171  "OK" : "FAILED");
172 
173  } else if (couenne.displayStats ()) { // print statistics
174 
175  int nr=-1, nt=-1;
176  double st=-1;
177 
178  CouenneCutGenerator* cg = NULL;
179  if (bb.model (). cutGenerators ())
180  cg = dynamic_cast <CouenneCutGenerator *> (bb.model (). cutGenerators () [0] -> generator ());
181  if (cg) cg -> getStats (nr, nt, st);
182  else jnlst -> Printf(Ipopt::J_WARNING, J_PROBLEM, "Warning: Could not get pointer to CouenneCutGenerator\n");
183 
184  jnlst -> Printf(Ipopt::J_SUMMARY, J_PROBLEM, "Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
185  "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
186  "%20e [lower] %20e [upper] %7d [nodes]\n",// %s %s\n",
187  problem -> problemName ().c_str (),
188  problem -> nOrigVars (),
189  problem -> nOrigIntVars(),
190  problem -> nOrigCons (),
191  problem -> nVars () - problem -> nOrigVars (),
192  nr, nt, st,
193  CoinCpuTime () - time_start,
194  cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
195  bb.model (). getBestPossibleObjValue (),
196  bb.model (). getObjValue (),
197  //bb.bestBound (),
198  //bb.bestObj (),
199  bb.numNodes ()
200  //bb.iterationCount (),
201  //status.c_str (), message.c_str ()
202  );
203  }
204 
205  if (!userinterface->writeSolution(bb))
206  return EXIT_FAILURE;
207 
209  E->writeDiffFiles();
210  E->printError(std::cerr);
211  //There has been a failure to solve a problem with Ipopt.
212  //And we will output file with information on what has been changed in the problem to make it fail.
213  //Now depending on what algorithm has been called (B-BB or other) the failed problem may be at different place.
214  // const OsiSolverInterface &si1 = (algo > 0) ? nlpSolver : *model.solver();
215 
217  std::cerr<<E.className()<<"::"<<E.methodName()
218  <<std::endl
219  <<E.message()<<std::endl;
220 
221  } catch(CoinError &E) {
222  std::cerr<<E.className()<<"::"<<E.methodName()
223  <<std::endl
224  <<E.message()<<std::endl;
225 
226  } catch (Ipopt::OPTION_INVALID &E) {
227  std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
228 
229  } catch (int generic_error) {
230  if (generic_error == infeasible)
231  jnlst->Printf(Ipopt::J_SUMMARY, J_PROBLEM, "problem infeasible\n");
232  }
233 
234  delete userinterface;
235 
236  return EXIT_SUCCESS;
237 }
238 
239 
240 
241 //int main (int argc, char **argv) {
242 
243 // read options
244 
245 // create problem
246 
247 // create bb solver
248 
249 // add cut generators
250 // add heuristics
251 // add branching rules
252 // add bound reduction
253 
254 // solve
255 
256 // print result
257 
258 // return retval;
259 //}
Cut Generator for linear convexifications.
static void registerAllOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register all Couenne options.
bool displayStats()
true if one wants to display statistics at the end of program
int main(int argc, char *argv[])
Definition: BB_tm.cpp:32
void setOptionsAndJournalist(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions, Ipopt::SmartPtr< Ipopt::OptionsList > options, Ipopt::SmartPtr< Ipopt::Journalist > journalist)
Set the value for options, output...
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
#define PRINTED_PRECISION
Definition: Couenne.cpp:64
Error class to throw exceptions from OsiTMINLPInterface.
void setDoubleParameter(const DoubleParameter &p, const double val)
modify parameter (used for MaxTime)
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
static const int infeasible
Definition: Couenne.cpp:68
#define COUENNE_INFINITY
We will throw this error when a problem is not solved.
bool InitializeCouenne(char **argv=NULL, CouenneProblem *couenneProb=NULL, Ipopt::SmartPtr< Bonmin::TMINLP > tminlp=NULL, CouenneInterface *ci=NULL, Bonmin::Bab *bb=NULL)
Initialize from command line arguments.
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.