1 // (C) Copyright International Business Machines Corporation, Carnegie Mellon University 2004, 2007
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // Pierre Bonami, Carnegie Mellon University,
7 // Carl D. Laird, Carnegie Mellon University,
8 // Andreas Waechter, International Business Machines Corporation
9 //
10 // Date : 12/01/2004
11 
12 
13 #ifndef OsiTMINLPInterface_H
14 #define OsiTMINLPInterface_H
15 
16 #define INT_BIAS 0e-8
17 
18 #include <string>
19 #include <iostream>
20 
21 #include "OsiSolverInterface.hpp"
22 #include "CoinWarmStartBasis.hpp"
23 
24 #include "BonCutStrengthener.hpp"
25 //#include "BonRegisteredOptions.hpp"
26 
27 namespace Bonmin {
28   class TMINLP;
29   class TMINLP2TNLP;
30   class TMINLP2OsiLP;
31   class TNLP2FPNLP;
32   class TNLPSolver;
33   class RegisteredOptions;
34   class StrongBranchingSolver;
35 
36   /** Solvers for solving nonlinear programs.*/
37   enum Solver{
38     EIpopt=0 /** <a href="http://projects.coin-or.org/Ipopt"> Ipopt </a> interior point algorithm.*/,
39     EFilterSQP /** <a href="http://www-unix.mcs.anl.gov/~leyffer/solvers.html"> filterSQP </a> Sequential Quadratic Programming algorithm.*/,
40     EAll/** Use all solvers.*/
41   };
42 /**
43    This is class provides an Osi interface for a Mixed Integer Linear Program
44    expressed as a TMINLP
45    (so that we can use it for example as the continuous solver in Cbc).
46 */
47 
48 class OsiTMINLPInterface : public OsiSolverInterface
49 {
50   friend class BonminParam;
51 
52 public:
53 
54   //#############################################################################
55 
56   /**Error class to throw exceptions from OsiTMINLPInterface.
57    * Inherited from CoinError, we just want to have a different class to be able to catch
58    * errors thrown by OsiTMINLPInterface.
59   */
60 class SimpleError : public CoinError
61   {
62   private:
63     SimpleError();
64 
65   public:
66     ///Alternate constructor using strings
SimpleError(std::string message,std::string methodName,std::string f=std::string (),int l=-1)67     SimpleError(std::string message,
68         std::string methodName,
69 	std::string f = std::string(),
70 	int l = -1)
71         :
72         CoinError(message,methodName,std::string("OsiTMINLPInterface"), f, l)
73     {}
74   }
75   ;
76 
77 #ifdef __LINE__
78 #define SimpleError(x, y) SimpleError((x), (y), __FILE__, __LINE__)
79 #endif
80 
81   // Error when problem is not solved
newUnsolvedError(int num,Ipopt::SmartPtr<TMINLP2TNLP> problem,std::string name)82   TNLPSolver::UnsolvedError * newUnsolvedError(int num, Ipopt::SmartPtr<TMINLP2TNLP> problem, std::string name){
83     return app_->newUnsolvedError(num, problem, name);
84   }
85   //#############################################################################
86 
87   enum WarmStartModes{
88    None,
89    FakeBasis,
90    Optimum,
91    InteriorPoint};
92 
93   /** Type of the messages specifically written by OsiTMINLPInterface.*/
94   enum MessagesTypes{
95     SOLUTION_FOUND/**found a feasible solution*/,
96     INFEASIBLE_SOLUTION_FOUND/**found an infeasible problem*/,
97     UNSOLVED_PROBLEM_FOUND/**found an unsolved problem*/,
98     WARNING_RESOLVING /** Warn that a problem is resolved*/,
99     WARN_SUCCESS_WS/** Problem not solved with warm start but solved without*/,
100     WARN_SUCCESS_RANDOM/** Subproblem not solve with warm start but solved with random point*/,
101     WARN_CONTINUING_ON_FAILURE/** a failure occured but is continuing*/,
102     SUSPECT_PROBLEM/** Output the number of the problem.*/,
103     SUSPECT_PROBLEM2/** Output the number of the problem.*/,
104     IPOPT_SUMMARY /** Output summary statistics on Ipopt solution.*/,
105     BETTER_SOL /** Found a better solution with random values.*/,
106     LOG_HEAD/** Head of "civilized" log.*/,
107     LOG_FIRST_LINE/** First line (first solve) of log.*/,
108     LOG_LINE/**standard line (retry solving) of log.*/,
109     ALTERNATE_OBJECTIVE/** Recomputed integer feasible with alternate objective function*/,
110     WARN_RESOLVE_BEFORE_INITIAL_SOLVE /** resolve() has been called but there
111                                               was no previous call to initialSolve().
112                                          */,
113     ERROR_NO_TNLPSOLVER /** Trying to access non-existent TNLPSolver*/,
114     WARNING_NON_CONVEX_OA /** Warn that there are equality or ranged constraints and OA may works bad.*/,
115     SOLVER_DISAGREE_STATUS /** Different solver gives different status for problem.*/,
116     SOLVER_DISAGREE_VALUE /** Different solver gives different optimal value for problem.*/,
117     OSITMINLPINTERFACE_DUMMY_END
118   };
119 
120   //#############################################################################
121 
122 
123   /** Messages written by an OsiTMINLPInterface. */
124 class Messages : public CoinMessages
125   {
126   public:
127     /// Constructor
128     Messages();
129   };
130 
131 
132   //#############################################################################
133 
134 
135   /**@name Constructors and destructors */
136   //@{
137   /// Default Constructor
138   OsiTMINLPInterface();
139 
140   /** Facilitator to initialize interface. */
141   void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
142                   Ipopt::SmartPtr<Ipopt::OptionsList> options,
143                   Ipopt::SmartPtr<Ipopt::Journalist> journalist,
144                   const std::string & prefix,
145                   Ipopt::SmartPtr<TMINLP> tminlp);
146 
147   /** Facilitator to initialize interface. */
initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,Ipopt::SmartPtr<Ipopt::OptionsList> options,Ipopt::SmartPtr<Ipopt::Journalist> journalist,Ipopt::SmartPtr<TMINLP> tminlp)148   void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
149                   Ipopt::SmartPtr<Ipopt::OptionsList> options,
150                   Ipopt::SmartPtr<Ipopt::Journalist> journalist,
151                   Ipopt::SmartPtr<TMINLP> tminlp){
152      initialize(roptions, options, journalist, "bonmin.", tminlp);
153   }
154 
155   /** Set the model to be solved by interface.*/
156   void setModel(Ipopt::SmartPtr<TMINLP> tminlp);
157   /** Set the solver to be used by interface.*/
158   void setSolver(Ipopt::SmartPtr<TNLPSolver> app);
159   /** Sets the TMINLP2TNLP to be used by the interface.*/
160   void use(Ipopt::SmartPtr<TMINLP2TNLP> tminlp2tnlp);
161   /** Copy constructor
162   */
163   OsiTMINLPInterface (const OsiTMINLPInterface &);
164 
165   /** Virtual copy constructor */
166   OsiSolverInterface * clone(bool copyData = true) const;
167 
168   /// Assignment operator
169   OsiTMINLPInterface & operator=(const OsiTMINLPInterface& rhs);
170 
171   /// Destructor
172   virtual ~OsiTMINLPInterface ();
173 
174 
175   /// Read parameter file
176   void readOptionFile(const std::string & fileName);
177 
178   /// Retrieve OsiTMINLPApplication option list
179   const Ipopt::SmartPtr<Ipopt::OptionsList> options() const;
180   /// Retrieve OsiTMINLPApplication option list
181   Ipopt::SmartPtr<Ipopt::OptionsList> options();
182 
prefix() const183   const char * prefix() const{
184   if(!IsValid(app_)) {
185     messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
186     return NULL;
187   }
188   else
189     return app_->prefix();
190   }
191   //@}
192   //---------------------------------------------------------------------------
193   /**@name Solve methods */
194   //@{
195   /// Solve initial continuous relaxation
196   virtual void initialSolve();
197 
198   /// Solve initial continuous relaxation (precising from where)
199   virtual void initialSolve(const char * whereFrom);
200 
201   /** Resolve the continuous relaxation after problem modification.
202       initialSolve may or may not have been called before this is called. In
203       any case, this must solve the problem, and speed the process up if it
204       can reuse any remnants of data that might exist from a previous solve.
205    */
206   virtual void resolve();
207 
208   /** Resolve the continuous relaxation after problem modification.
209       initialSolve may or may not have been called before this is called. In
210       any case, this must solve the problem, and speed the process up if it
211       can reuse any remnants of data that might exist from a previous solve.
212    */
213   virtual void resolve(const char * whereFrom);
214 
215   /** Resolve the problem with different random starting points to try to find
216       a better solution (only makes sense for a non-convex problem.*/
217   virtual void resolveForCost(int numretry, bool keepWs);
218 
219   /** Method to be called when a problem has failed to be solved. Will try
220       to resolve it with different settings.
221   */
222   virtual void resolveForRobustness(int numretry);
223 
224   /// Nescessary for compatibility with OsiSolverInterface but does nothing.
branchAndBound()225   virtual void branchAndBound()
226   {
227     throw SimpleError("Function not implemented for OsiTMINLPInterface","branchAndBound()");
228   }
229   //@}
230 
231 
232 
233   //---------------------------------------------------------------------------
234   ///@name Methods returning info on how the solution process terminated
235   //@{
236   /// Are there a numerical difficulties?
237   virtual bool isAbandoned() const;
238   /// Is optimality proven?
239   virtual bool isProvenOptimal() const;
240   /// Is primal infeasiblity proven?
241   virtual bool isProvenPrimalInfeasible() const;
242   /// Is dual infeasiblity proven?
243   virtual bool isProvenDualInfeasible() const;
244   /// Is the given primal objective limit reached?
245   virtual bool isPrimalObjectiveLimitReached() const;
246   /// Is the given dual objective limit reached?
247   virtual bool isDualObjectiveLimitReached() const;
248   /// Iteration limit reached?
249   virtual bool isIterationLimitReached() const;
250 
251   ///Warn solver that branch-and-bound is continuing after a failure
continuingOnAFailure()252   void continuingOnAFailure()
253   {
254     hasContinuedAfterNlpFailure_ = true;
255   }
256 
257 
258   //Added by Claudia
259 
getNewCutoffDecr()260   double getNewCutoffDecr()
261   {
262     return newCutoffDecr;
263   }
264 
setNewCutoffDecr(double d)265   void setNewCutoffDecr(double d)
266   {
267     newCutoffDecr = d;
268   }
269 
270 
271   /// Did we continue on a failure
hasContinuedOnAFailure()272   bool hasContinuedOnAFailure()
273   {
274     return hasContinuedAfterNlpFailure_;
275   }
276   /// tell to ignore the failures (don't throw, don't fathom, don't report)
ignoreFailures()277   void ignoreFailures()
278   {
279     pretendFailIsInfeasible_ = 2;
280   }
281   /// Force current solution to be infeasible
forceInfeasible()282   void forceInfeasible()
283   {
284     problem_->set_obj_value(1e200);
285   }
286   /// Force current solution to be branched on (make it fractionnal with small objective)
forceBranchable()287   void forceBranchable()
288   {
289     problem_->set_obj_value(-1e200);
290     problem_->force_fractionnal_sol();
291   }
292   //@}
293 
294 
295   //---------------------------------------------------------------------------
296   /**@name Parameter set/get methods
297 
298      The set methods return true if the parameter was set to the given value,
299      false otherwise. There can be various reasons for failure: the given
300      parameter is not applicable for the solver (e.g., refactorization
301      frequency for the clp algorithm), the parameter is not yet implemented
302      for the solver or simply the value of the parameter is out of the range
303      the solver accepts. If a parameter setting call returns false check the
304      details of your solver.
305 
306      The get methods return true if the given parameter is applicable for the
307      solver and is implemented. In this case the value of the parameter is
308      returned in the second argument. Otherwise they return false.
309   */
310   //@{
311   // Set an integer parameter
312   bool setIntParam(OsiIntParam key, int value);
313   // Set an double parameter
314   bool setDblParam(OsiDblParam key, double value);
315   // Set a string parameter
316   bool setStrParam(OsiStrParam key, const std::string & value);
317   // Get an integer parameter
318   bool getIntParam(OsiIntParam key, int& value) const;
319   // Get an double parameter
320   bool getDblParam(OsiDblParam key, double& value) const;
321   // Get a string parameter
322   bool getStrParam(OsiStrParam key, std::string& value) const;
323 
324   // Get the push values for starting point
getPushFact() const325   inline double getPushFact() const
326   {
327     return pushValue_;
328   }
329 
330   //@}
331 
332 
333   //---------------------------------------------------------------------------
334   /**@name Problem information methods
335 
336      These methods call the solver's query routines to return
337      information about the problem referred to by the current object.
338      Querying a problem that has no data associated with it result in
339      zeros for the number of rows and columns, and NULL pointers from
340      the methods that return vectors.
341 
342      Const pointers returned from any data-query method are valid as
343      long as the data is unchanged and the solver is not called.
344   */
345   //@{
346   /// Get number of columns
347   virtual int getNumCols() const;
348 
349   /// Get number of rows
350   virtual int getNumRows() const;
351 
352   ///get name of variables
353   const OsiSolverInterface::OsiNameVec& getVarNames() ;
354   /// Get pointer to array[getNumCols()] of column lower bounds
355   virtual const double * getColLower() const;
356 
357   /// Get pointer to array[getNumCols()] of column upper bounds
358   virtual const double * getColUpper() const;
359 
360   /** Get pointer to array[getNumRows()] of row constraint senses.
361       <ul>
362       <li>'L': <= constraint
363       <li>'E': =  constraint
364       <li>'G': >= constraint
365       <li>'R': ranged constraint
366       <li>'N': free constraint
367       </ul>
368   */
369   virtual const char * getRowSense() const;
370 
371   /** Get pointer to array[getNumRows()] of rows right-hand sides
372       <ul>
373       <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
374       <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
375       <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
376       <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0
377       </ul>
378   */
379   virtual const double * getRightHandSide() const;
380 
381   /** Get pointer to array[getNumRows()] of row ranges.
382       <ul>
383       <li> if rowsense()[i] == 'R' then
384       rowrange()[i] == rowupper()[i] - rowlower()[i]
385       <li> if rowsense()[i] != 'R' then
386       rowrange()[i] is 0.0
387       </ul>
388   */
389   virtual const double * getRowRange() const;
390 
391   /// Get pointer to array[getNumRows()] of row lower bounds
392   virtual const double * getRowLower() const;
393 
394   /// Get pointer to array[getNumRows()] of row upper bounds
395   virtual const double * getRowUpper() const;
396 
397   /** Get objective function sense (1 for min (default), -1 for max)
398    * Always minimizes */
getObjSense() const399   virtual double getObjSense() const
400   {
401     return 1;
402   }
403 
404   /// Return true if column is continuous
405   virtual bool isContinuous(int colNumber) const;
406 
407   /// Return true if column is binary
408   virtual bool isBinary(int columnNumber) const;
409 
410   /** Return true if column is integer.
411       Note: This function returns true if the the column
412       is binary or a general integer.
413   */
414   virtual bool isInteger(int columnNumber) const;
415 
416   /// Return true if column is general integer
417   virtual bool isIntegerNonBinary(int columnNumber) const;
418 
419   /// Return true if column is binary and not fixed at either bound
420   virtual bool isFreeBinary(int columnNumber) const;
421 
422   /// Get solver's value for infinity
423   virtual double getInfinity() const;
424 
425   ///Get priorities on integer variables.
getPriorities() const426   const int * getPriorities() const
427   {
428     const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
429     if(branch)
430       return branch->priorities;
431     else return NULL;
432   }
433   ///get prefered branching directions
getBranchingDirections() const434   const int * getBranchingDirections() const
435   {
436     const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
437     if(branch)
438       return branch->branchingDirections;
439     else return NULL;
440   }
getUpPsCosts() const441   const double * getUpPsCosts() const
442   {
443     const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
444     if(branch)
445     return branch->upPsCosts;
446     else return NULL;
447   }
getDownPsCosts() const448   const double * getDownPsCosts() const
449   {
450     const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
451     if(branch)
452     return branch->downPsCosts;
453     else return NULL;
454   }
455 
456 
457   //@}
458 
459   /**@name Methods related to querying the solution */
460   //@{
461   /// Get pointer to array[getNumCols()] of primal solution vector
462   virtual const double * getColSolution() const;
463 
464   /// Get pointer to array[getNumRows()] of dual prices
465   virtual const double * getRowPrice() const;
466 
467   /// Get a pointer to array[getNumCols()] of reduced costs
468   virtual const double * getReducedCost() const;
469 
470   /** Get pointer to array[getNumRows()] of row activity levels (constraint
471       matrix times the solution vector */
472   virtual const double * getRowActivity() const;
473 
474 
475   /** Get how many iterations it took to solve the problem (whatever
476       "iteration" mean to the solver.
477       * \todo Figure out what it could mean for Ipopt.
478       */
479   virtual int getIterationCount() const;
480 
481   /** get total number of calls to solve.*/
nCallOptimizeTNLP()482   int nCallOptimizeTNLP()
483   {
484     return nCallOptimizeTNLP_;
485   }
486   /** get total time taken to solve NLP's. */
totalNlpSolveTime()487   double totalNlpSolveTime()
488   {
489     return totalNlpSolveTime_;
490   }
491   /** get total number of iterations */
totalIterations()492   int totalIterations()
493   {
494     return totalIterations_;
495   }
496 
497 
498   //@}
499   //-------------------------------------------------------------------------
500   /**@name Methods to modify the objective, bounds, and solution
501   */
502   //@{
503 
504   /** Set a single column lower bound.
505       Use -getInfinity() for -infinity. */
506   virtual void setColLower( int elementIndex, double elementValue );
507 
508   /** Set a single column upper bound.
509       Use getInfinity() for infinity. */
510   virtual void setColUpper( int elementIndex, double elementValue );
511 
512   /** Set the lower bounds for all columns
513       array [getNumCols()] is an array of values for the objective.
514   */
515   virtual void setColLower(const double * array);
516 
517   /** Set the upper bounds for all columns
518       array [getNumCols()] is an array of values for the objective.
519   */
520   virtual void setColUpper(const double * array);
521 
522 
523   /** Set a single row lower bound.
524       Use -getInfinity() for -infinity. */
525   virtual void setRowLower( int elementIndex, double elementValue );
526 
527   /** Set a single row upper bound.
528       Use getInfinity() for infinity. */
529   virtual void setRowUpper( int elementIndex, double elementValue );
530 
531   /** Set the type of a single row */
532   virtual void setRowType(int index, char sense, double rightHandSide,
533       double range);
534 
535 
536   /** \brief Set the objective function sense (disabled).
537    * (1 for min (default), -1 for max)
538    \todo Make it work.
539    \bug Can not treat maximisation problems. */
540   virtual void setObjSense(double s);
541 
542   /** Set the primal solution variable values
543       Set the values for the starting point.
544       \warning getColSolution will never return this vector (unless it is optimal).
545   */
546   virtual void setColSolution(const double *colsol);
547 
548   /** Set dual solution variable values.
549       set the values for the starting point.
550       \warning getRowPrice will never return this vector (unless it is optimal).
551   */
552   virtual void setRowPrice(const double * rowprice);
553 
554   //@}
555 
556 
557   //---------------------------------------------------------------------------
558   /**@name WarmStart related methods (those should really do nothing for the moment)*/
559   //@{
560 
561   /*! \brief Get an empty warm start object
562 
563   This routine returns an empty CoinWarmStartBasis object. Its purpose is
564   to provide a way to give a client a warm start basis object of the
565   appropriate type, which can resized and modified as desired.
566   */
567   virtual CoinWarmStart *getEmptyWarmStart () const;
568 
569   /** Get warmstarting information */
570   virtual CoinWarmStart* getWarmStart() const;
571 
572   /** Set warmstarting information. Return true/false depending on whether
573       the warmstart information was accepted or not. */
574   virtual bool setWarmStart(const CoinWarmStart* warmstart);
575 
setWarmStartMode(int mode)576   void setWarmStartMode(int mode) {
577     warmStartMode_ = (WarmStartModes) mode;
578   }
getWarmStartMode()579   WarmStartModes getWarmStartMode() {
580     return warmStartMode_;
581   }
582 
583   void randomStartingPoint();
584 
585   //Returns true if a basis is available
basisIsAvailable() const586   virtual bool basisIsAvailable() const
587   {
588     // Throw an exception
589     throw SimpleError("Needs coding for this interface", "basisIsAvailable");
590   }
591 
592 
593   //@}
594 
595   //-------------------------------------------------------------------------
596   /**@name Methods to set variable type */
597   //@{
598   /** Set the index-th variable to be a continuous variable */
599   virtual void setContinuous(int index);
600   /** Set the index-th variable to be an integer variable */
601   virtual void setInteger(int index);
602   //@}
603 
604   //Set numIterationSuspect_
setNumIterationSuspect(int value)605   void setNumIterationSuspect(int value)
606   {
607     numIterationSuspect_ = value;
608   }
609 
610   /**@name Dummy functions
611    * Functions which have to be implemented in an OsiSolverInterface,
612    * but which do not do anything (but throwing exceptions) here in the case of a
613    * minlp solved using an nlp solver for continuous relaxations */
614   //@{
615 
616   /** Cbc will understand that no matrix exsits if return -1
617   */
getNumElements() const618   virtual int getNumElements() const
619   {
620     return -1;
621   }
622 
623 
624   /** This returns the objective function gradient at the current
625    *  point.  It seems to be required for Cbc's pseudo cost
626    *  initialization
627   */
628   virtual const double * getObjCoefficients() const;
629 
630   /** We have to keep this but it will return NULL.
631    */
getMatrixByRow() const632   virtual const CoinPackedMatrix * getMatrixByRow() const
633   {
634       return NULL;
635   }
636 
637 
638   /** We have to keep this but it will return NULL.
639    */
getMatrixByCol() const640   virtual const CoinPackedMatrix * getMatrixByCol() const
641   {
642       return NULL;
643   }
644 
645   /** We have to keep this but it will throw an error.
646   */
setObjCoeff(int elementIndex,double elementValue)647   virtual void setObjCoeff( int elementIndex, double elementValue )
648   {
649     throw SimpleError("OsiTMINLPInterface does not implement this function.",
650         "setObjCoeff");
651   }
652 
653   /** We have to keep this but it will throw an error.
654   */
addCol(const CoinPackedVectorBase & vec,const double collb,const double colub,const double obj)655   virtual void addCol(const CoinPackedVectorBase& vec,
656       const double collb, const double colub,
657       const double obj)
658   {
659     throw SimpleError("OsiTMINLPInterface does not implement this function.",
660         "addCol");
661   }
662   /** We have to keep this but it will throw an error.
663   */
deleteCols(const int num,const int * colIndices)664   virtual void deleteCols(const int num, const int * colIndices)
665   {
666     throw SimpleError("OsiTMINLPInterface does not implement this function.",
667         "deleteCols");
668   }
669 
670   /** We have to keep this but it will throw an error.
671   */
addRow(const CoinPackedVectorBase & vec,const double rowlb,const double rowub)672   virtual void addRow(const CoinPackedVectorBase& vec,
673       const double rowlb, const double rowub)
674   {
675     throw SimpleError("OsiTMINLPInterface does not implement this function.",
676         "addRow");
677   }
678   /** We have to keep this but it will throw an error.
679   */
addRow(const CoinPackedVectorBase & vec,const char rowsen,const double rowrhs,const double rowrng)680   virtual void addRow(const CoinPackedVectorBase& vec,
681       const char rowsen, const double rowrhs,
682       const double rowrng)
683   {
684     throw SimpleError("OsiTMINLPInterface model does not implement this function.",
685         "addRow");
686   }
687   /** We have to keep this but it will throw an error.
688   */
deleteRows(const int num,const int * rowIndices)689   virtual void deleteRows(const int num, const int * rowIndices)
690   {
691     if(num)
692       freeCachedRowRim();
693      problem_->removeCuts(num, rowIndices);
694   }
695 
696 
697   /** We have to keep this but it will throw an error
698   */
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)699   virtual void loadProblem(const CoinPackedMatrix& matrix,
700       const double* collb, const double* colub,
701       const double* obj,
702       const double* rowlb, const double* rowub)
703   {
704     throw SimpleError("OsiTMINLPInterface does not implement this function.",
705         "loadProblem");
706   }
707 
708 
709   /** We have to keep this but it will throw an error.
710   */
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,double * & rowlb,double * & rowub)711   virtual void assignProblem(CoinPackedMatrix*& matrix,
712       double*& collb, double*& colub, double*& obj,
713       double*& rowlb, double*& rowub)
714   {
715     throw SimpleError("OsiTMINLPInterface does not implement this function.",
716         "assignProblem");
717   }
718 
719   /** We have to keep this but it will throw an error.
720   */
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)721   virtual void loadProblem(const CoinPackedMatrix& matrix,
722       const double* collb, const double* colub,
723       const double* obj,
724       const char* rowsen, const double* rowrhs,
725       const double* rowrng)
726   {
727     throw SimpleError("OsiTMINLPInterface does not implement this function.",
728         "loadProblem");
729   }
730 
731   /** We have to keep this but it will throw an error.
732   */
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,char * & rowsen,double * & rowrhs,double * & rowrng)733   virtual void assignProblem(CoinPackedMatrix*& matrix,
734       double*& collb, double*& colub, double*& obj,
735       char*& rowsen, double*& rowrhs,
736       double*& rowrng)
737   {
738     throw SimpleError("OsiTMINLPInterface does not implement this function.",
739         "assignProblem");
740   }
741 
742 
743   /** We have to keep this but it will throw an error.
744   */
loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)745   virtual void loadProblem(const int numcols, const int numrows,
746       const int* start, const int* index,
747       const double* value,
748       const double* collb, const double* colub,
749       const double* obj,
750       const double* rowlb, const double* rowub)
751   {
752     throw SimpleError("OsiTMINLPInterface does not implement this function.",
753         "loadProblem");
754   }
755 
756   /** We have to keep this but it will throw an error.
757   */
loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)758   virtual void loadProblem(const int numcols, const int numrows,
759       const int* start, const int* index,
760       const double* value,
761       const double* collb, const double* colub,
762       const double* obj,
763       const char* rowsen, const double* rowrhs,
764       const double* rowrng)
765   {
766     throw SimpleError("OsiTMINLPInterface model does not implement this function.",
767         "loadProblem");
768   }
769 
770   /** We have to keep this but it will throw an error.
771   */
readMps(const char * filename,const char * extension="mps")772   virtual int readMps(const char *filename,
773       const char *extension = "mps")
774   {
775     throw SimpleError("OsiTMINLPInterface does not implement this function.",
776         "readMps");
777   }
778 
779 
780   /** We have to keep this but it will throw an error.
781   */
writeMps(const char * filename,const char * extension="mps",double objSense=0.0) const782   virtual void writeMps(const char *filename,
783       const char *extension = "mps",
784       double objSense=0.0) const
785   {
786     throw SimpleError("OsiTMINLPInterface does not implement this function.",
787         "writeMps");
788   }
789 
790   /** Throws an error */
getDualRays(int maxNumRays,bool fullRay=false) const791   virtual std::vector<double*> getDualRays(int maxNumRays, bool fullRay = false) const
792   {
793     throw SimpleError("OsiTMINLPInterface does not implement this function.",
794         "getDualRays");
795   }
796 
797   /** Throws an error */
getPrimalRays(int maxNumRays) const798   virtual std::vector<double*> getPrimalRays(int maxNumRays) const
799   {
800     throw SimpleError("OsiTMINLPInterface does not implement this function.",
801         "getPrimalRays");
802   }
803 
804   //@}
805 
806 
807 
808   //---------------------------------------------------------------------------
809 
810 
811 
812   /**@name Control of Ipopt output
813    */
814   //@{
setSolverOutputToDefault()815   void setSolverOutputToDefault(){
816   app_->setOutputToDefault();}
forceSolverOutput(int log_level)817   void forceSolverOutput(int log_level){
818   app_->forceSolverOutput(log_level);}
819   //@}
820 
821   /**@name Sets and Getss */
822   //@{
823   /// Get objective function value (can't use default)
824   virtual double getObjValue() const;
825 
826   //@}
827 
828   /** get pointer to the TMINLP2TNLP adapter */
problem() const829   const TMINLP2TNLP * problem() const
830   {
831     return GetRawPtr(problem_);
832   }
833 
problem()834   TMINLP2TNLP * problem()
835   {
836     return GetRawPtr(problem_);
837   }
838 
model() const839   const TMINLP * model() const
840   {
841     return GetRawPtr(tminlp_);
842   }
843 
model()844   Bonmin::TMINLP * model()
845   {
846     return GetRawPtr(tminlp_);
847   }
848 
solver() const849   const Bonmin::TNLPSolver * solver() const
850   {
851     return GetRawPtr(app_);
852   }
853 
debug_apps() const854   const std::list<Ipopt::SmartPtr<TNLPSolver> >& debug_apps() const{
855     return debug_apps_;
856   }
857 
solver()858   TNLPSolver * solver()
859   {
860     return GetRawPtr(app_);
861   }
862   /** \name Methods to build outer approximations */
863   //@{
864   /** \name Methods to build outer approximations */
865   //@{
866   /** \brief Extract a linear relaxation of the MINLP.
867    * Use user-provided point to build first-order outer-approximation constraints at the optimum.
868    * And put it in an OsiSolverInterface.
869    */
870   virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x,
871                                        bool getObj = 1);
872 
873   /** Add constraint corresponding to objective function.*/
874   virtual void addObjectiveFunction(OsiSolverInterface &si, const double * x);
875 #if 1
876   /** \brief Extract a linear relaxation of the MINLP.
877    * Solve the continuous relaxation and takes first-order outer-approximation constraints at the optimum.
878    * The put everything in an OsiSolverInterface.
879    */
extractLinearRelaxation(OsiSolverInterface & si,bool getObj=1,bool solveNlp=1)880   virtual void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1,
881                                        bool solveNlp = 1){
882      if(solveNlp)
883        initialSolve("build initial OA");
884      extractLinearRelaxation(si, getColSolution(), getObj);
885      if(solveNlp){
886         app_->enableWarmStart();
887         setColSolution(problem()->x_sol());
888         setRowPrice(problem()->duals_sol());
889      }
890    }
891 #endif
892   /** Get the outer approximation constraints at the current optimal point.
893       If x2 is different from NULL only add cuts violated by x2.
894    (Only get outer-approximations of nonlinear constraints of the problem.)*/
getOuterApproximation(OsiCuts & cs,int getObj,const double * x2,bool global)895   void getOuterApproximation(OsiCuts &cs, int getObj, const double * x2, bool global)
896 {
897   getOuterApproximation(cs, getColSolution(), getObj, x2, global);
898 }
899 
900   /** Get the outer approximation constraints at provided point.
901       If x2 is different from NULL only add cuts violated by x2.
902    (Only get outer-approximations of nonlinear constraints of the problem.)*/
getOuterApproximation(OsiCuts & cs,const double * x,int getObj,const double * x2,bool global)903   void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2, bool global){
904     getOuterApproximation(cs, x, getObj, x2, 0., global);}
905 
906   /** Get the outer approximation constraints at provided point.
907       If x2 is different from NULL only add cuts violated by x2 by more than delta.
908    (Only get outer-approximations of nonlinear constraints of the problem.)*/
909   virtual void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2,
910                                      double theta, bool global);
911 
912  /** Get the outer approximation at provided point for given constraint. */
913   virtual void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
914                                                const double * x,
915                                                const double * x2, bool global);
916 
917  /** Get the outer approximation at current optimal point for given constraint. */
getConstraintOuterApproximation(OsiCuts & cs,int constraintNumber,const double * x2,bool global)918   void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
919                                        const double * x2, bool global){
920      getConstraintOuterApproximation(cs, constraintNumber, getColSolution(),x2,global);
921   }
922 
923 
924 /** Get a benders cut from solution.*/
925 void getBendersCut(OsiCuts &cs, bool global);
926 
927   /** Given a point x_bar this solves the problem of finding the point which minimize a convex
928     *combination between the distance to  x_bar and the original objective function f(x):
929    * \f$ min a * (\sum\limits_{i=1}^n  ||x_{ind[i]} -\overline{x}_i)||_L) + (1 - a)* s *f(x) \f$
930    * \return Distance between feasibility set a x_bar on components in ind
931    * \param n number of elements in array x_bar and ind
932    * \param s scaling of the original objective.
933    * \param a Combination to take between feasibility and original objective (must be between 0 and 1).
934    * \param L L-norm to use (can be either 1 or 2).
935    */
936   double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L);
937 
938   /** Given a point x_bar this solves the problem of finding the point which minimize
939     * the distance to x_bar while satisfying the additional cutoff constraint:
940    * \f$ min \sum\limits_{i=1}^n  ||x_{ind[i]} -\overline{x}_i)||_L$
941    * \return Distance between feasibility set a x_bar on components in ind
942    * \param n number of elements in array x_bar and ind
943    * \param L L-norm to use (can be either 1 or 2).
944    * \param cutoff objective function value of a known integer feasible solution
945    */
946   double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, int L, double cutoff);
947 
948   /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will
949       solve it.*/
950   void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L);
951 
952   /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will
953       solve it. This is to be used in the local branching heuristic */
954   void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind,
955 				  double rhs_local_branching_constraint);
956 
957   /** switch back to solving original problem.*/
958   void switchToOriginalProblem();
959 
960   /** round solution and check its feasibility.*/
round_and_check(double tolerance,OsiObject ** objects=0,int nObjects=-1)961   void round_and_check(double tolerance,
962                        OsiObject ** objects = 0, int nObjects = -1){
963     if(!problem_->check_solution(objects, nObjects)){
964       optimizationStatus_ = TNLPSolver::provenInfeasible;
965     }
966   }
967   //@}
968 
969   /** \name output for OA cut generation
970        \todo All OA code here should be moved to a separate class sometime.*/
971   //@{
972   /** OA Messages types.*/
973   enum OaMessagesTypes {
974     CUT_NOT_VIOLATED_ENOUGH = 0/** Says that one cut has been generarted, where from, which is the violation.*/,
975     VIOLATED_OA_CUT_GENERATED/** Cut is not violated enough, give violation.*/,
976     OA_CUT_GENERATED/** Print the cut which has been generated.*/,
977     OA_MESSAGES_DUMMY_END/** Dummy end.*/};
978   /** Class to store OA Messages.*/
979   class OaMessages :public CoinMessages{
980      public:
981      /** Default constructor.*/
982      OaMessages();
983   };
984   /** Like a CoinMessageHandler but can print a cut also.*/
985   class OaMessageHandler : public CoinMessageHandler{
986     public:
987     /** Default constructor.*/
OaMessageHandler()988     OaMessageHandler():CoinMessageHandler(){
989     }
990     /** Constructor to put to file pointer (fp won't be closed).*/
OaMessageHandler(FILE * fp)991     OaMessageHandler(FILE * fp):CoinMessageHandler(fp){
992     }
993     /** Destructor.*/
~OaMessageHandler()994     virtual ~OaMessageHandler(){
995     }
996     /** Copy constructor.*/
OaMessageHandler(const OaMessageHandler & other)997     OaMessageHandler(const OaMessageHandler &other):
998     CoinMessageHandler(other){}
999     /** Constructor from a regular CoinMessageHandler.*/
OaMessageHandler(const CoinMessageHandler & other)1000     OaMessageHandler(const CoinMessageHandler &other):
1001     CoinMessageHandler(other){}
1002     /** Assignment operator.*/
operator =(const OaMessageHandler & rhs)1003     OaMessageHandler & operator=(const OaMessageHandler &rhs){
1004        CoinMessageHandler::operator=(rhs);
1005        return *this;}
1006     /** Virtual copy */
clone() const1007     virtual CoinMessageHandler* clone() const{
1008       return new OaMessageHandler(*this);}
1009     /** print an OsiRowCut.*/
1010     void print(OsiRowCut &row);
1011   };
setOaMessageHandler(const CoinMessageHandler & handler)1012   void setOaMessageHandler(const CoinMessageHandler &handler){
1013     delete oaHandler_;
1014     oaHandler_ = new OaMessageHandler(handler);
1015   }
1016   //@}
1017 
1018     //-----------------------------------------------------------------------
1019     /** Apply a collection of cuts.
1020     */
applyCuts(const OsiCuts & cs,double effectivenessLb=0.0)1021     virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs,
1022 					  double effectivenessLb = 0.0){
1023        freeCachedRowRim();
1024       problem_->addCuts(cs);
1025       ApplyCutsReturnCode rc;
1026       return rc;}
1027 
1028    /** Add a collection of linear cuts to problem formulation.*/
1029   virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts);
1030 
1031 
1032   /** Add a collection of linear cuts to the problem formulation */
applyRowCuts(int numberCuts,const OsiRowCut ** cuts)1033   virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
1034   {
1035     if(numberCuts)
1036       freeCachedRowRim();
1037     problem_->addCuts(numberCuts, cuts);
1038   }
1039 
1040  /** Get infinity norm of constraint violation for x. Put into
1041      obj the objective value of x.*/
1042  double getConstraintsViolation(const double * x, double & obj);
1043 
1044   /** Get infinity norm of constraint violation for x and error in objective
1045       value where obj is the estimated objective value of x.*/
1046   double getNonLinearitiesViolation(const double *x, const double obj);
1047 
1048 //---------------------------------------------------------------------------
1049 
1050   void extractInterfaceParams();
1051 
1052 
1053   /** To set some application specific defaults. */
1054   virtual void setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options);
1055 
1056   /** Register all possible options to Bonmin */
1057   static void registerOptions (Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions);
1058 
regOptions()1059   Ipopt::SmartPtr<Bonmin::RegisteredOptions> regOptions(){
1060     if(IsValid(app_))
1061       return app_->roptions();
1062     else
1063       return NULL;
1064   }
1065 
1066   /** @name Methods related to strong branching */
1067   //@{
1068   /// Set the strong branching solver
1069   void SetStrongBrachingSolver(Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver);
1070   /// Create a hot start snapshot of the optimization process.  In our
1071   /// case, we initialize the StrongBrachingSolver.
1072   virtual void markHotStart();
1073   /// Optimize starting from the hot start snapshot. In our case, we
1074   /// call the StrongBranchingSolver to give us an approximate
1075   /// solution for the current state of the bounds
1076   virtual void solveFromHotStart();
1077   /// Delete the hot start snapshot. In our case we deactivate the
1078   /// StrongBrachingSolver.
1079   virtual void unmarkHotStart();
1080   //@}
1081 
1082   /// Get values of tiny_ and very_tiny_
get_tolerances(double & tiny,double & very_tiny,double & rhsRelax,double & infty)1083   void get_tolerances(double &tiny, double&very_tiny, double &rhsRelax, double &infty){
1084     tiny = tiny_;
1085     very_tiny = veryTiny_;
1086     rhsRelax = rhsRelax_;
1087     infty = infty_;
1088   }
1089 
1090   void set_linearizer(Ipopt::SmartPtr<TMINLP2OsiLP> linearizer);
1091 
1092   Ipopt::SmartPtr<TMINLP2OsiLP> linearizer();
1093 protected:
1094 
1095   //@}
1096 
1097   enum RandomGenerationType{
1098     uniform =0, perturb=1, perturb_suffix=2};
1099   /// Initialize data structures for storing the jacobian
1100   int initializeJacobianArrays();
1101 
1102   ///@name Virtual callbacks for application specific stuff
1103   //@{
appName()1104   virtual std::string  appName()
1105   {
1106     return "bonmin";
1107   }
1108   //@}
1109   ///@name Protected methods
1110   //@{
1111 
1112   /** Call Ipopt to solve or resolve the problem and check for errors.*/
1113   void solveAndCheckErrors(bool doResolve, bool throwOnFailure,
1114       const char * whereFrom);
1115 
1116 
1117   /** Add a linear cut to the problem formulation.
1118   */
applyRowCut(const OsiRowCut & rc)1119   virtual void applyRowCut( const OsiRowCut & rc )
1120   {
1121     const OsiRowCut * cut = &rc;
1122     problem_->addCuts(1, &cut);
1123   }
1124   /** We have to keep this but it will throw an error.
1125   */
applyColCut(const OsiColCut & cc)1126   virtual void applyColCut( const OsiColCut & cc )
1127   {
1128     throw SimpleError("Ipopt model does not implement this function.",
1129         "applyColCut");
1130   }
1131 
1132 //  /** Read the name of the variables in an ampl .col file. */
1133 //  void readVarNames() const;
1134 
1135   //@}
1136 
1137   /**@name Model and solver */
1138   //@{
1139   /** TMINLP model.*/
1140   Ipopt::SmartPtr<TMINLP> tminlp_;
1141   /** Adapter for a MINLP to a NLP */
1142   Ipopt::SmartPtr<TMINLP2TNLP> problem_;
1143   /** Problem currently optimized (may be problem_ or feasibilityProblem_)*/
1144   Ipopt::SmartPtr<Ipopt::TNLP> problem_to_optimize_;
1145   /** Is true if and only if in feasibility mode.*/
1146   bool feasibility_mode_;
1147   /** Solver for a TMINLP. */
1148   Ipopt::SmartPtr<TNLPSolver> app_;
1149 
1150   /** Alternate solvers for TMINLP.*/
1151   std::list<Ipopt::SmartPtr<TNLPSolver> > debug_apps_;
1152   /** Do we use the other solvers?*/
1153   bool testOthers_;
1154   //@}
1155 
1156   /** Warmstart information for reoptimization */
1157   CoinWarmStart* warmstart_;
1158 
1159   /**@name Cached information on the problem */
1160   //@{
1161   /** Free cached data relative to variables */
1162   void freeCachedColRim();
1163   /** Free cached data relative to constraints */
1164   void freeCachedRowRim();
1165   /** Free all cached data*/
1166   void freeCachedData();
1167   /** Extract rowsense_ vector rhs_ vector and rowrange_ vector from the lower and upper bounds
1168    *  on the constraints */
1169   void extractSenseRhsAndRange() const;
1170   /// Pointer to dense vector of row sense indicators
1171   mutable char    *rowsense_;
1172 
1173   /// Pointer to dense vector of row right-hand side values
1174   mutable double  *rhs_;
1175 
1176   /// Pointer to dense vector of slack upper bounds for range constraints (undefined for non-range rows)
1177   mutable double  *rowrange_;
1178   /** Pointer to dense vector of reduced costs
1179       \warning Always 0. with Ipopt*/
1180   mutable double  *reducedCosts_;
1181   /** DualObjectiveLimit is used to store the cutoff in Cbc*/
1182   double OsiDualObjectiveLimit_;
1183   /** does the file variable names exists (will check automatically).*/
1184   mutable bool hasVarNamesFile_;
1185   //@}
1186   /// number of time NLP has been solved
1187   int nCallOptimizeTNLP_;
1188   /// Total solution time of NLP
1189   double totalNlpSolveTime_;
1190   /// toatal number of iterations
1191   int totalIterations_;
1192   /// max radius for random point
1193   double maxRandomRadius_;
1194   /// Method to pick a random starting point.
1195   int randomGenerationType_;
1196   /// Maximum perturbation value
1197   double max_perturbation_;
1198   /// Ipopt value for pushing initial point inside the bounds
1199   double pushValue_;
1200   /// Number of times problem will be resolved in initialSolve (root node)
1201   int numRetryInitial_;
1202   /// Number of times problem will be resolved in resolve
1203   int numRetryResolve_;
1204   /// Number of times infeasible problem will be resolved.
1205   int numRetryInfeasibles_;
1206   /// Number of times problem will be resolved in case of a failure
1207   int numRetryUnsolved_;
1208   /// If infeasibility for a problem is less than this, let's be carrefull. It might be feasible
1209   double infeasibility_epsilon_;
1210 
1211 
1212   //Added by Claudia
1213   /// Dynamic cutOff_
1214   int dynamicCutOff_;
1215   /// coeff_var_threshold_
1216   double coeff_var_threshold_;
1217   /// first_perc_for_cutoff_decr_
1218   double first_perc_for_cutoff_decr_;
1219   /// second_perc_for_cutoff_decr_
1220   double second_perc_for_cutoff_decr_;
1221 
1222 
1223   /** Messages specific to an OsiTMINLPInterface. */
1224   Messages messages_;
1225   /** If not 0 when a problem is not solved (failed to be solved)
1226       will pretend that it is infeasible. If == 1 will care
1227       (i.e. record the fact issue messages to user), if ==2 don't care (somebody else will) */
1228   int pretendFailIsInfeasible_;
1229 
1230   mutable int pretendSucceededNext_;
1231 
1232   /** did we ever continue optimization ignoring a failure. */
1233   bool hasContinuedAfterNlpFailure_;
1234   /** number iterations above which a problem is considered suspect (-1 is considered \f$+ \infty \f$).
1235   	If in a call to solve a problem takes more than that number of iterations it will be output to files.*/
1236   int numIterationSuspect_ ;
1237   /** Has problem been optimized since last change (include setColSolution).
1238      If yes getColSolution will return Ipopt point, otherwise will return
1239      initial point.*/
1240   bool hasBeenOptimized_;
1241   /** A fake objective function (all variables to 1) to please Cbc
1242       pseudo costs initialization.  AW: I changed this, it will now be
1243       the objective gradient at current point. */
1244   mutable double * obj_;
1245   /** flag to say wether options have been printed or not.*/
1246   static bool hasPrintedOptions;
1247 
1248   /** Adapter for TNLP to a feasibility problem */
1249   Ipopt::SmartPtr<TNLP2FPNLP> feasibilityProblem_;
1250 
1251   /** Adapter for TMINLP to an Osi LP  */
1252   Ipopt::SmartPtr<TMINLP2OsiLP> linearizer_;
1253 
1254   /** \name Arrays to store Jacobian matrix */
1255   //@{
1256   /** Row indices.*/
1257   int * jRow_;
1258   /** Column indices.*/
1259   int * jCol_;
1260   /** Values */
1261   double * jValues_;
1262   /** Number of elements.*/
1263   int nnz_jac;
1264   //@}
1265 
1266   ///Store the types of the constraints (linear and nonlinear).
1267   Ipopt::TNLP::LinearityType * constTypes_;
1268   /** Number of nonlinear constraint
1269    */
1270   int nNonLinear_;
1271   /** Value for small non-zero element which we will try to remove cleanly in OA cuts.*/
1272   double tiny_;
1273   /** Value for small non-zero element which we will take the risk to ignore in OA cuts.*/
1274   double veryTiny_;
1275   /** Amount by which to relax OA constraints RHSes*/
1276   double rhsRelax_;
1277   /** Value for infinity. */
1278   double infty_;
1279   /** status of last optimization. */
1280   TNLPSolver::ReturnStatus optimizationStatus_;
1281   /** Flag indicating if the warm start methods actually do something.*/
1282   WarmStartModes warmStartMode_;
1283   /** Is it the first solve (for random starting point at root options).*/
1284   bool firstSolve_;
1285   /** Object for strengthening cuts */
1286   Ipopt::SmartPtr<CutStrengthener> cutStrengthener_;
1287 
1288   /** \name output for OA cut generation
1289        \todo All OA code here should be moved to a separate class sometime.*/
1290   //@{
1291   /** OA Messages.*/
1292   OaMessages oaMessages_;
1293   /** OA Message handler. */
1294   OaMessageHandler * oaHandler_;
1295   //@}
1296 
1297   double newCutoffDecr;
1298 protected:
1299   /** Facilitator to create an application. */
1300   void createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
1301                          Ipopt::SmartPtr<Ipopt::OptionsList> options,
1302                          Ipopt::SmartPtr<Ipopt::Journalist> journalist,
1303                          const std::string & prefix);
1304   ///Constructor without model only for derived classes
1305   OsiTMINLPInterface(Ipopt::SmartPtr<TNLPSolver> app);
1306 
1307   /** Internal set warm start.*/
1308   bool internal_setWarmStart(const CoinWarmStart* ws);
1309 
1310   /** internal get warm start.*/
1311   CoinWarmStart* internal_getWarmStart() const;
1312 
1313   /** Procedure that builds a fake basis. Only tries to make basis consistent with constraints activity.*/
1314   CoinWarmStart* build_fake_basis() const;
1315 private:
1316 
1317   /** solver to be used for all strong branching solves */
1318   Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver_;
1319   /** status of last optimization before hot start was marked. */
1320   TNLPSolver::ReturnStatus optimizationStatusBeforeHotStart_;
1321 static const char * OPT_SYMB;
1322 static const char * FAILED_SYMB;
1323 static const char * INFEAS_SYMB;
1324 static const char * TIME_SYMB;
1325 static const char * UNBOUND_SYMB;
1326   /** Get status as a char * for log.*/
statusAsString(TNLPSolver::ReturnStatus r)1327   const char * statusAsString(TNLPSolver::ReturnStatus r){
1328     if(r == TNLPSolver::solvedOptimal || r == TNLPSolver::solvedOptimalTol){
1329       return OPT_SYMB;}
1330     else if(r == TNLPSolver::provenInfeasible){
1331       return INFEAS_SYMB;}
1332     else if(r == TNLPSolver::unbounded){
1333       return UNBOUND_SYMB;}
1334     else if(r == TNLPSolver::timeLimit){
1335       return TIME_SYMB;}
1336     else return FAILED_SYMB;
1337   }
statusAsString()1338   const char * statusAsString(){
1339     return statusAsString(optimizationStatus_);}
1340 };
1341 }
1342 #endif
1343