source: stable/1.1/Bonmin/src/Interfaces/BonOsiTMINLPInterface.hpp @ 1524

Last change on this file since 1524 was 1524, checked in by pbonami, 10 years ago

Remove some unused option in OA add Claudi d'Ambrosio code

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