summaryrefslogtreecommitdiff
path: root/newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp')
-rw-r--r--newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp1342
1 files changed, 1342 insertions, 0 deletions
diff --git a/newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp b/newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp
new file mode 100644
index 0000000..3d95545
--- /dev/null
+++ b/newstructure/thirdparty/linux/include/coin/BonOsiTMINLPInterface.hpp
@@ -0,0 +1,1342 @@
+// (C) Copyright International Business Machines Corporation, Carnegie Mellon University 2004, 2007
+// All Rights Reserved.
+// This code is published under the Eclipse Public License.
+//
+// Authors :
+// Pierre Bonami, Carnegie Mellon University,
+// Carl D. Laird, Carnegie Mellon University,
+// Andreas Waechter, International Business Machines Corporation
+//
+// Date : 12/01/2004
+
+
+#ifndef OsiTMINLPInterface_H
+#define OsiTMINLPInterface_H
+
+#define INT_BIAS 0e-8
+
+#include <string>
+#include <iostream>
+
+#include "OsiSolverInterface.hpp"
+#include "CoinWarmStartBasis.hpp"
+
+#include "BonCutStrengthener.hpp"
+//#include "BonRegisteredOptions.hpp"
+
+namespace Bonmin {
+ class TMINLP;
+ class TMINLP2TNLP;
+ class TMINLP2OsiLP;
+ class TNLP2FPNLP;
+ class TNLPSolver;
+ class RegisteredOptions;
+ class StrongBranchingSolver;
+
+ /** Solvers for solving nonlinear programs.*/
+ enum Solver{
+ EIpopt=0 /** <a href="http://projects.coin-or.org/Ipopt"> Ipopt </a> interior point algorithm.*/,
+ EFilterSQP /** <a href="http://www-unix.mcs.anl.gov/~leyffer/solvers.html"> filterSQP </a> Sequential Quadratic Programming algorithm.*/,
+ EAll/** Use all solvers.*/
+ };
+/**
+ This is class provides an Osi interface for a Mixed Integer Linear Program
+ expressed as a TMINLP
+ (so that we can use it for example as the continuous solver in Cbc).
+*/
+
+class OsiTMINLPInterface : public OsiSolverInterface
+{
+ friend class BonminParam;
+
+public:
+
+ //#############################################################################
+
+ /**Error class to throw exceptions from OsiTMINLPInterface.
+ * Inherited from CoinError, we just want to have a different class to be able to catch
+ * errors thrown by OsiTMINLPInterface.
+ */
+class SimpleError : public CoinError
+ {
+ private:
+ SimpleError();
+
+ public:
+ ///Alternate constructor using strings
+ SimpleError(std::string message,
+ std::string methodName,
+ std::string f = std::string(),
+ int l = -1)
+ :
+ CoinError(message,methodName,std::string("OsiTMINLPInterface"), f, l)
+ {}
+ }
+ ;
+
+#ifdef __LINE__
+#define SimpleError(x, y) SimpleError((x), (y), __FILE__, __LINE__)
+#endif
+
+ // Error when problem is not solved
+ TNLPSolver::UnsolvedError * newUnsolvedError(int num, Ipopt::SmartPtr<TMINLP2TNLP> problem, std::string name){
+ return app_->newUnsolvedError(num, problem, name);
+ }
+ //#############################################################################
+
+ enum WarmStartModes{
+ None,
+ FakeBasis,
+ Optimum,
+ InteriorPoint};
+
+ /** Type of the messages specifically written by OsiTMINLPInterface.*/
+ enum MessagesTypes{
+ SOLUTION_FOUND/**found a feasible solution*/,
+ INFEASIBLE_SOLUTION_FOUND/**found an infeasible problem*/,
+ UNSOLVED_PROBLEM_FOUND/**found an unsolved problem*/,
+ WARNING_RESOLVING /** Warn that a problem is resolved*/,
+ WARN_SUCCESS_WS/** Problem not solved with warm start but solved without*/,
+ WARN_SUCCESS_RANDOM/** Subproblem not solve with warm start but solved with random point*/,
+ WARN_CONTINUING_ON_FAILURE/** a failure occured but is continuing*/,
+ SUSPECT_PROBLEM/** Output the number of the problem.*/,
+ SUSPECT_PROBLEM2/** Output the number of the problem.*/,
+ IPOPT_SUMMARY /** Output summary statistics on Ipopt solution.*/,
+ BETTER_SOL /** Found a better solution with random values.*/,
+ LOG_HEAD/** Head of "civilized" log.*/,
+ LOG_FIRST_LINE/** First line (first solve) of log.*/,
+ LOG_LINE/**standard line (retry solving) of log.*/,
+ ALTERNATE_OBJECTIVE/** Recomputed integer feasible with alternate objective function*/,
+ WARN_RESOLVE_BEFORE_INITIAL_SOLVE /** resolve() has been called but there
+ was no previous call to initialSolve().
+ */,
+ ERROR_NO_TNLPSOLVER /** Trying to access non-existent TNLPSolver*/,
+ WARNING_NON_CONVEX_OA /** Warn that there are equality or ranged constraints and OA may works bad.*/,
+ SOLVER_DISAGREE_STATUS /** Different solver gives different status for problem.*/,
+ SOLVER_DISAGREE_VALUE /** Different solver gives different optimal value for problem.*/,
+ OSITMINLPINTERFACE_DUMMY_END
+ };
+
+ //#############################################################################
+
+
+ /** Messages written by an OsiTMINLPInterface. */
+class Messages : public CoinMessages
+ {
+ public:
+ /// Constructor
+ Messages();
+ };
+
+
+ //#############################################################################
+
+
+ /**@name Constructors and destructors */
+ //@{
+ /// Default Constructor
+ OsiTMINLPInterface();
+
+ /** Facilitator to initialize interface. */
+ void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
+ Ipopt::SmartPtr<Ipopt::OptionsList> options,
+ Ipopt::SmartPtr<Ipopt::Journalist> journalist,
+ const std::string & prefix,
+ Ipopt::SmartPtr<TMINLP> tminlp);
+
+ /** Facilitator to initialize interface. */
+ void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
+ Ipopt::SmartPtr<Ipopt::OptionsList> options,
+ Ipopt::SmartPtr<Ipopt::Journalist> journalist,
+ Ipopt::SmartPtr<TMINLP> tminlp){
+ initialize(roptions, options, journalist, "bonmin.", tminlp);
+ }
+
+ /** Set the model to be solved by interface.*/
+ void setModel(Ipopt::SmartPtr<TMINLP> tminlp);
+ /** Set the solver to be used by interface.*/
+ void setSolver(Ipopt::SmartPtr<TNLPSolver> app);
+ /** Sets the TMINLP2TNLP to be used by the interface.*/
+ void use(Ipopt::SmartPtr<TMINLP2TNLP> tminlp2tnlp);
+ /** Copy constructor
+ */
+ OsiTMINLPInterface (const OsiTMINLPInterface &);
+
+ /** Virtual copy constructor */
+ OsiSolverInterface * clone(bool copyData = true) const;
+
+ /// Assignment operator
+ OsiTMINLPInterface & operator=(const OsiTMINLPInterface& rhs);
+
+ /// Destructor
+ virtual ~OsiTMINLPInterface ();
+
+
+ /// Read parameter file
+ void readOptionFile(const std::string & fileName);
+
+ /// Retrieve OsiTMINLPApplication option list
+ const Ipopt::SmartPtr<Ipopt::OptionsList> options() const;
+ /// Retrieve OsiTMINLPApplication option list
+ Ipopt::SmartPtr<Ipopt::OptionsList> options();
+
+ const char * prefix() const{
+ if(!IsValid(app_)) {
+ messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
+ return NULL;
+ }
+ else
+ return app_->prefix();
+ }
+ //@}
+ //---------------------------------------------------------------------------
+ /**@name Solve methods */
+ //@{
+ /// Solve initial continuous relaxation
+ virtual void initialSolve();
+
+ /// Solve initial continuous relaxation (precising from where)
+ virtual void initialSolve(const char * whereFrom);
+
+ /** Resolve the continuous relaxation after problem modification.
+ initialSolve may or may not have been called before this is called. In
+ any case, this must solve the problem, and speed the process up if it
+ can reuse any remnants of data that might exist from a previous solve.
+ */
+ virtual void resolve();
+
+ /** Resolve the continuous relaxation after problem modification.
+ initialSolve may or may not have been called before this is called. In
+ any case, this must solve the problem, and speed the process up if it
+ can reuse any remnants of data that might exist from a previous solve.
+ */
+ virtual void resolve(const char * whereFrom);
+
+ /** Resolve the problem with different random starting points to try to find
+ a better solution (only makes sense for a non-convex problem.*/
+ virtual void resolveForCost(int numretry, bool keepWs);
+
+ /** Method to be called when a problem has failed to be solved. Will try
+ to resolve it with different settings.
+ */
+ virtual void resolveForRobustness(int numretry);
+
+ /// Nescessary for compatibility with OsiSolverInterface but does nothing.
+ virtual void branchAndBound()
+ {
+ throw SimpleError("Function not implemented for OsiTMINLPInterface","branchAndBound()");
+ }
+ //@}
+
+
+
+ //---------------------------------------------------------------------------
+ ///@name Methods returning info on how the solution process terminated
+ //@{
+ /// Are there a numerical difficulties?
+ virtual bool isAbandoned() const;
+ /// Is optimality proven?
+ virtual bool isProvenOptimal() const;
+ /// Is primal infeasiblity proven?
+ virtual bool isProvenPrimalInfeasible() const;
+ /// Is dual infeasiblity proven?
+ virtual bool isProvenDualInfeasible() const;
+ /// Is the given primal objective limit reached?
+ virtual bool isPrimalObjectiveLimitReached() const;
+ /// Is the given dual objective limit reached?
+ virtual bool isDualObjectiveLimitReached() const;
+ /// Iteration limit reached?
+ virtual bool isIterationLimitReached() const;
+
+ ///Warn solver that branch-and-bound is continuing after a failure
+ void continuingOnAFailure()
+ {
+ hasContinuedAfterNlpFailure_ = true;
+ }
+
+
+ //Added by Claudia
+
+ double getNewCutoffDecr()
+ {
+ return newCutoffDecr;
+ }
+
+ void setNewCutoffDecr(double d)
+ {
+ newCutoffDecr = d;
+ }
+
+
+ /// Did we continue on a failure
+ bool hasContinuedOnAFailure()
+ {
+ return hasContinuedAfterNlpFailure_;
+ }
+ /// tell to ignore the failures (don't throw, don't fathom, don't report)
+ void ignoreFailures()
+ {
+ pretendFailIsInfeasible_ = 2;
+ }
+ /// Force current solution to be infeasible
+ void forceInfeasible()
+ {
+ problem_->set_obj_value(1e200);
+ }
+ /// Force current solution to be branched on (make it fractionnal with small objective)
+ void forceBranchable()
+ {
+ problem_->set_obj_value(-1e200);
+ problem_->force_fractionnal_sol();
+ }
+ //@}
+
+
+ //---------------------------------------------------------------------------
+ /**@name Parameter set/get methods
+
+ The set methods return true if the parameter was set to the given value,
+ false otherwise. There can be various reasons for failure: the given
+ parameter is not applicable for the solver (e.g., refactorization
+ frequency for the clp algorithm), the parameter is not yet implemented
+ for the solver or simply the value of the parameter is out of the range
+ the solver accepts. If a parameter setting call returns false check the
+ details of your solver.
+
+ The get methods return true if the given parameter is applicable for the
+ solver and is implemented. In this case the value of the parameter is
+ returned in the second argument. Otherwise they return false.
+ */
+ //@{
+ // Set an integer parameter
+ bool setIntParam(OsiIntParam key, int value);
+ // Set an double parameter
+ bool setDblParam(OsiDblParam key, double value);
+ // Set a string parameter
+ bool setStrParam(OsiStrParam key, const std::string & value);
+ // Get an integer parameter
+ bool getIntParam(OsiIntParam key, int& value) const;
+ // Get an double parameter
+ bool getDblParam(OsiDblParam key, double& value) const;
+ // Get a string parameter
+ bool getStrParam(OsiStrParam key, std::string& value) const;
+
+ // Get the push values for starting point
+ inline double getPushFact() const
+ {
+ return pushValue_;
+ }
+
+ //@}
+
+
+ //---------------------------------------------------------------------------
+ /**@name Problem information methods
+
+ These methods call the solver's query routines to return
+ information about the problem referred to by the current object.
+ Querying a problem that has no data associated with it result in
+ zeros for the number of rows and columns, and NULL pointers from
+ the methods that return vectors.
+
+ Const pointers returned from any data-query method are valid as
+ long as the data is unchanged and the solver is not called.
+ */
+ //@{
+ /// Get number of columns
+ virtual int getNumCols() const;
+
+ /// Get number of rows
+ virtual int getNumRows() const;
+
+ ///get name of variables
+ const OsiSolverInterface::OsiNameVec& getVarNames() ;
+ /// Get pointer to array[getNumCols()] of column lower bounds
+ virtual const double * getColLower() const;
+
+ /// Get pointer to array[getNumCols()] of column upper bounds
+ virtual const double * getColUpper() const;
+
+ /** Get pointer to array[getNumRows()] of row constraint senses.
+ <ul>
+ <li>'L': <= constraint
+ <li>'E': = constraint
+ <li>'G': >= constraint
+ <li>'R': ranged constraint
+ <li>'N': free constraint
+ </ul>
+ */
+ virtual const char * getRowSense() const;
+
+ /** Get pointer to array[getNumRows()] of rows right-hand sides
+ <ul>
+ <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
+ <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
+ <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
+ <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0
+ </ul>
+ */
+ virtual const double * getRightHandSide() const;
+
+ /** Get pointer to array[getNumRows()] of row ranges.
+ <ul>
+ <li> if rowsense()[i] == 'R' then
+ rowrange()[i] == rowupper()[i] - rowlower()[i]
+ <li> if rowsense()[i] != 'R' then
+ rowrange()[i] is 0.0
+ </ul>
+ */
+ virtual const double * getRowRange() const;
+
+ /// Get pointer to array[getNumRows()] of row lower bounds
+ virtual const double * getRowLower() const;
+
+ /// Get pointer to array[getNumRows()] of row upper bounds
+ virtual const double * getRowUpper() const;
+
+ /** Get objective function sense (1 for min (default), -1 for max)
+ * Always minimizes */
+ virtual double getObjSense() const
+ {
+ return 1;
+ }
+
+ /// Return true if column is continuous
+ virtual bool isContinuous(int colNumber) const;
+
+ /// Return true if column is binary
+ virtual bool isBinary(int columnNumber) const;
+
+ /** Return true if column is integer.
+ Note: This function returns true if the the column
+ is binary or a general integer.
+ */
+ virtual bool isInteger(int columnNumber) const;
+
+ /// Return true if column is general integer
+ virtual bool isIntegerNonBinary(int columnNumber) const;
+
+ /// Return true if column is binary and not fixed at either bound
+ virtual bool isFreeBinary(int columnNumber) const;
+
+ /// Get solver's value for infinity
+ virtual double getInfinity() const;
+
+ ///Get priorities on integer variables.
+ const int * getPriorities() const
+ {
+ const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
+ if(branch)
+ return branch->priorities;
+ else return NULL;
+ }
+ ///get prefered branching directions
+ const int * getBranchingDirections() const
+ {
+ const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
+ if(branch)
+ return branch->branchingDirections;
+ else return NULL;
+ }
+ const double * getUpPsCosts() const
+ {
+ const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
+ if(branch)
+ return branch->upPsCosts;
+ else return NULL;
+ }
+ const double * getDownPsCosts() const
+ {
+ const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
+ if(branch)
+ return branch->downPsCosts;
+ else return NULL;
+ }
+
+
+ //@}
+
+ /**@name Methods related to querying the solution */
+ //@{
+ /// Get pointer to array[getNumCols()] of primal solution vector
+ virtual const double * getColSolution() const;
+
+ /// Get pointer to array[getNumRows()] of dual prices
+ virtual const double * getRowPrice() const;
+
+ /// Get a pointer to array[getNumCols()] of reduced costs
+ virtual const double * getReducedCost() const;
+
+ /** Get pointer to array[getNumRows()] of row activity levels (constraint
+ matrix times the solution vector */
+ virtual const double * getRowActivity() const;
+
+
+ /** Get how many iterations it took to solve the problem (whatever
+ "iteration" mean to the solver.
+ * \todo Figure out what it could mean for Ipopt.
+ */
+ virtual int getIterationCount() const;
+
+ /** get total number of calls to solve.*/
+ int nCallOptimizeTNLP()
+ {
+ return nCallOptimizeTNLP_;
+ }
+ /** get total time taken to solve NLP's. */
+ double totalNlpSolveTime()
+ {
+ return totalNlpSolveTime_;
+ }
+ /** get total number of iterations */
+ int totalIterations()
+ {
+ return totalIterations_;
+ }
+
+
+ //@}
+ //-------------------------------------------------------------------------
+ /**@name Methods to modify the objective, bounds, and solution
+ */
+ //@{
+
+ /** Set a single column lower bound.
+ Use -getInfinity() for -infinity. */
+ virtual void setColLower( int elementIndex, double elementValue );
+
+ /** Set a single column upper bound.
+ Use getInfinity() for infinity. */
+ virtual void setColUpper( int elementIndex, double elementValue );
+
+ /** Set the lower bounds for all columns
+ array [getNumCols()] is an array of values for the objective.
+ */
+ virtual void setColLower(const double * array);
+
+ /** Set the upper bounds for all columns
+ array [getNumCols()] is an array of values for the objective.
+ */
+ virtual void setColUpper(const double * array);
+
+
+ /** Set a single row lower bound.
+ Use -getInfinity() for -infinity. */
+ virtual void setRowLower( int elementIndex, double elementValue );
+
+ /** Set a single row upper bound.
+ Use getInfinity() for infinity. */
+ virtual void setRowUpper( int elementIndex, double elementValue );
+
+ /** Set the type of a single row */
+ virtual void setRowType(int index, char sense, double rightHandSide,
+ double range);
+
+
+ /** \brief Set the objective function sense (disabled).
+ * (1 for min (default), -1 for max)
+ \todo Make it work.
+ \bug Can not treat maximisation problems. */
+ virtual void setObjSense(double s);
+
+ /** Set the primal solution variable values
+ Set the values for the starting point.
+ \warning getColSolution will never return this vector (unless it is optimal).
+ */
+ virtual void setColSolution(const double *colsol);
+
+ /** Set dual solution variable values.
+ set the values for the starting point.
+ \warning getRowPrice will never return this vector (unless it is optimal).
+ */
+ virtual void setRowPrice(const double * rowprice);
+
+ //@}
+
+
+ //---------------------------------------------------------------------------
+ /**@name WarmStart related methods (those should really do nothing for the moment)*/
+ //@{
+
+ /*! \brief Get an empty warm start object
+
+ This routine returns an empty CoinWarmStartBasis object. Its purpose is
+ to provide a way to give a client a warm start basis object of the
+ appropriate type, which can resized and modified as desired.
+ */
+ virtual CoinWarmStart *getEmptyWarmStart () const;
+
+ /** Get warmstarting information */
+ virtual CoinWarmStart* getWarmStart() const;
+
+ /** Set warmstarting information. Return true/false depending on whether
+ the warmstart information was accepted or not. */
+ virtual bool setWarmStart(const CoinWarmStart* warmstart);
+
+ void setWarmStartMode(int mode) {
+ warmStartMode_ = (WarmStartModes) mode;
+ }
+ WarmStartModes getWarmStartMode() {
+ return warmStartMode_;
+ }
+
+ void randomStartingPoint();
+
+ //Returns true if a basis is available
+ virtual bool basisIsAvailable() const
+ {
+ // Throw an exception
+ throw SimpleError("Needs coding for this interface", "basisIsAvailable");
+ }
+
+
+ //@}
+
+ //-------------------------------------------------------------------------
+ /**@name Methods to set variable type */
+ //@{
+ /** Set the index-th variable to be a continuous variable */
+ virtual void setContinuous(int index);
+ /** Set the index-th variable to be an integer variable */
+ virtual void setInteger(int index);
+ //@}
+
+ //Set numIterationSuspect_
+ void setNumIterationSuspect(int value)
+ {
+ numIterationSuspect_ = value;
+ }
+
+ /**@name Dummy functions
+ * Functions which have to be implemented in an OsiSolverInterface,
+ * but which do not do anything (but throwing exceptions) here in the case of a
+ * minlp solved using an nlp solver for continuous relaxations */
+ //@{
+
+ /** Cbc will understand that no matrix exsits if return -1
+ */
+ virtual int getNumElements() const
+ {
+ return -1;
+ }
+
+
+ /** This returns the objective function gradient at the current
+ * point. It seems to be required for Cbc's pseudo cost
+ * initialization
+ */
+ virtual const double * getObjCoefficients() const;
+
+ /** We have to keep this but it will return NULL.
+ */
+ virtual const CoinPackedMatrix * getMatrixByRow() const
+ {
+ return NULL;
+ }
+
+
+ /** We have to keep this but it will return NULL.
+ */
+ virtual const CoinPackedMatrix * getMatrixByCol() const
+ {
+ return NULL;
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void setObjCoeff( int elementIndex, double elementValue )
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "setObjCoeff");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void addCol(const CoinPackedVectorBase& vec,
+ const double collb, const double colub,
+ const double obj)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "addCol");
+ }
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void deleteCols(const int num, const int * colIndices)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "deleteCols");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void addRow(const CoinPackedVectorBase& vec,
+ const double rowlb, const double rowub)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "addRow");
+ }
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void addRow(const CoinPackedVectorBase& vec,
+ const char rowsen, const double rowrhs,
+ const double rowrng)
+ {
+ throw SimpleError("OsiTMINLPInterface model does not implement this function.",
+ "addRow");
+ }
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void deleteRows(const int num, const int * rowIndices)
+ {
+ if(num)
+ freeCachedRowRim();
+ problem_->removeCuts(num, rowIndices);
+ }
+
+
+ /** We have to keep this but it will throw an error
+ */
+ virtual void loadProblem(const CoinPackedMatrix& matrix,
+ const double* collb, const double* colub,
+ const double* obj,
+ const double* rowlb, const double* rowub)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "loadProblem");
+ }
+
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void assignProblem(CoinPackedMatrix*& matrix,
+ double*& collb, double*& colub, double*& obj,
+ double*& rowlb, double*& rowub)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "assignProblem");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void loadProblem(const CoinPackedMatrix& matrix,
+ const double* collb, const double* colub,
+ const double* obj,
+ const char* rowsen, const double* rowrhs,
+ const double* rowrng)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "loadProblem");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void assignProblem(CoinPackedMatrix*& matrix,
+ double*& collb, double*& colub, double*& obj,
+ char*& rowsen, double*& rowrhs,
+ double*& rowrng)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "assignProblem");
+ }
+
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void 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)
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "loadProblem");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void 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)
+ {
+ throw SimpleError("OsiTMINLPInterface model does not implement this function.",
+ "loadProblem");
+ }
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual int readMps(const char *filename,
+ const char *extension = "mps")
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "readMps");
+ }
+
+
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void writeMps(const char *filename,
+ const char *extension = "mps",
+ double objSense=0.0) const
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "writeMps");
+ }
+
+ /** Throws an error */
+ virtual std::vector<double*> getDualRays(int maxNumRays, bool fullRay = false) const
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "getDualRays");
+ }
+
+ /** Throws an error */
+ virtual std::vector<double*> getPrimalRays(int maxNumRays) const
+ {
+ throw SimpleError("OsiTMINLPInterface does not implement this function.",
+ "getPrimalRays");
+ }
+
+ //@}
+
+
+
+ //---------------------------------------------------------------------------
+
+
+
+ /**@name Control of Ipopt output
+ */
+ //@{
+ void setSolverOutputToDefault(){
+ app_->setOutputToDefault();}
+ void forceSolverOutput(int log_level){
+ app_->forceSolverOutput(log_level);}
+ //@}
+
+ /**@name Sets and Getss */
+ //@{
+ /// Get objective function value (can't use default)
+ virtual double getObjValue() const;
+
+ //@}
+
+ /** get pointer to the TMINLP2TNLP adapter */
+ const TMINLP2TNLP * problem() const
+ {
+ return GetRawPtr(problem_);
+ }
+
+ TMINLP2TNLP * problem()
+ {
+ return GetRawPtr(problem_);
+ }
+
+ const TMINLP * model() const
+ {
+ return GetRawPtr(tminlp_);
+ }
+
+ Bonmin::TMINLP * model()
+ {
+ return GetRawPtr(tminlp_);
+ }
+
+ const Bonmin::TNLPSolver * solver() const
+ {
+ return GetRawPtr(app_);
+ }
+
+ const std::list<Ipopt::SmartPtr<TNLPSolver> >& debug_apps() const{
+ return debug_apps_;
+ }
+
+ TNLPSolver * solver()
+ {
+ return GetRawPtr(app_);
+ }
+ /** \name Methods to build outer approximations */
+ //@{
+ /** \name Methods to build outer approximations */
+ //@{
+ /** \brief Extract a linear relaxation of the MINLP.
+ * Use user-provided point to build first-order outer-approximation constraints at the optimum.
+ * And put it in an OsiSolverInterface.
+ */
+ virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x,
+ bool getObj = 1);
+
+ /** Add constraint corresponding to objective function.*/
+ virtual void addObjectiveFunction(OsiSolverInterface &si, const double * x);
+#if 1
+ /** \brief Extract a linear relaxation of the MINLP.
+ * Solve the continuous relaxation and takes first-order outer-approximation constraints at the optimum.
+ * The put everything in an OsiSolverInterface.
+ */
+ virtual void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1,
+ bool solveNlp = 1){
+ if(solveNlp)
+ initialSolve("build initial OA");
+ extractLinearRelaxation(si, getColSolution(), getObj);
+ if(solveNlp){
+ app_->enableWarmStart();
+ setColSolution(problem()->x_sol());
+ setRowPrice(problem()->duals_sol());
+ }
+ }
+#endif
+ /** Get the outer approximation constraints at the current optimal point.
+ If x2 is different from NULL only add cuts violated by x2.
+ (Only get outer-approximations of nonlinear constraints of the problem.)*/
+ void getOuterApproximation(OsiCuts &cs, int getObj, const double * x2, bool global)
+{
+ getOuterApproximation(cs, getColSolution(), getObj, x2, global);
+}
+
+ /** Get the outer approximation constraints at provided point.
+ If x2 is different from NULL only add cuts violated by x2.
+ (Only get outer-approximations of nonlinear constraints of the problem.)*/
+ void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2, bool global){
+ getOuterApproximation(cs, x, getObj, x2, 0., global);}
+
+ /** Get the outer approximation constraints at provided point.
+ If x2 is different from NULL only add cuts violated by x2 by more than delta.
+ (Only get outer-approximations of nonlinear constraints of the problem.)*/
+ virtual void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2,
+ double theta, bool global);
+
+ /** Get the outer approximation at provided point for given constraint. */
+ virtual void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
+ const double * x,
+ const double * x2, bool global);
+
+ /** Get the outer approximation at current optimal point for given constraint. */
+ void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
+ const double * x2, bool global){
+ getConstraintOuterApproximation(cs, constraintNumber, getColSolution(),x2,global);
+ }
+
+
+/** Get a benders cut from solution.*/
+void getBendersCut(OsiCuts &cs, bool global);
+
+ /** Given a point x_bar this solves the problem of finding the point which minimize a convex
+ *combination between the distance to x_bar and the original objective function f(x):
+ * \f$ min a * (\sum\limits_{i=1}^n ||x_{ind[i]} -\overline{x}_i)||_L) + (1 - a)* s *f(x) \f$
+ * \return Distance between feasibility set a x_bar on components in ind
+ * \param n number of elements in array x_bar and ind
+ * \param s scaling of the original objective.
+ * \param a Combination to take between feasibility and original objective (must be between 0 and 1).
+ * \param L L-norm to use (can be either 1 or 2).
+ */
+ double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L);
+
+ /** Given a point x_bar this solves the problem of finding the point which minimize
+ * the distance to x_bar while satisfying the additional cutoff constraint:
+ * \f$ min \sum\limits_{i=1}^n ||x_{ind[i]} -\overline{x}_i)||_L$
+ * \return Distance between feasibility set a x_bar on components in ind
+ * \param n number of elements in array x_bar and ind
+ * \param L L-norm to use (can be either 1 or 2).
+ * \param cutoff objective function value of a known integer feasible solution
+ */
+ double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, int L, double cutoff);
+
+ /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will
+ solve it.*/
+ void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L);
+
+ /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will
+ solve it. This is to be used in the local branching heuristic */
+ void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind,
+ double rhs_local_branching_constraint);
+
+ /** switch back to solving original problem.*/
+ void switchToOriginalProblem();
+
+ /** round solution and check its feasibility.*/
+ void round_and_check(double tolerance,
+ OsiObject ** objects = 0, int nObjects = -1){
+ if(!problem_->check_solution(objects, nObjects)){
+ optimizationStatus_ = TNLPSolver::provenInfeasible;
+ }
+ }
+ //@}
+
+ /** \name output for OA cut generation
+ \todo All OA code here should be moved to a separate class sometime.*/
+ //@{
+ /** OA Messages types.*/
+ enum OaMessagesTypes {
+ CUT_NOT_VIOLATED_ENOUGH = 0/** Says that one cut has been generarted, where from, which is the violation.*/,
+ VIOLATED_OA_CUT_GENERATED/** Cut is not violated enough, give violation.*/,
+ OA_CUT_GENERATED/** Print the cut which has been generated.*/,
+ OA_MESSAGES_DUMMY_END/** Dummy end.*/};
+ /** Class to store OA Messages.*/
+ class OaMessages :public CoinMessages{
+ public:
+ /** Default constructor.*/
+ OaMessages();
+ };
+ /** Like a CoinMessageHandler but can print a cut also.*/
+ class OaMessageHandler : public CoinMessageHandler{
+ public:
+ /** Default constructor.*/
+ OaMessageHandler():CoinMessageHandler(){
+ }
+ /** Constructor to put to file pointer (fp won't be closed).*/
+ OaMessageHandler(FILE * fp):CoinMessageHandler(fp){
+ }
+ /** Destructor.*/
+ virtual ~OaMessageHandler(){
+ }
+ /** Copy constructor.*/
+ OaMessageHandler(const OaMessageHandler &other):
+ CoinMessageHandler(other){}
+ /** Constructor from a regular CoinMessageHandler.*/
+ OaMessageHandler(const CoinMessageHandler &other):
+ CoinMessageHandler(other){}
+ /** Assignment operator.*/
+ OaMessageHandler & operator=(const OaMessageHandler &rhs){
+ CoinMessageHandler::operator=(rhs);
+ return *this;}
+ /** Virtual copy */
+ virtual CoinMessageHandler* clone() const{
+ return new OaMessageHandler(*this);}
+ /** print an OsiRowCut.*/
+ void print(OsiRowCut &row);
+ };
+ void setOaMessageHandler(const CoinMessageHandler &handler){
+ delete oaHandler_;
+ oaHandler_ = new OaMessageHandler(handler);
+ }
+ //@}
+
+ //-----------------------------------------------------------------------
+ /** Apply a collection of cuts.
+ */
+ virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs,
+ double effectivenessLb = 0.0){
+ freeCachedRowRim();
+ problem_->addCuts(cs);
+ ApplyCutsReturnCode rc;
+ return rc;}
+
+ /** Add a collection of linear cuts to problem formulation.*/
+ virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts);
+
+
+ /** Add a collection of linear cuts to the problem formulation */
+ virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
+ {
+ if(numberCuts)
+ freeCachedRowRim();
+ problem_->addCuts(numberCuts, cuts);
+ }
+
+ /** Get infinity norm of constraint violation for x. Put into
+ obj the objective value of x.*/
+ double getConstraintsViolation(const double * x, double & obj);
+
+ /** Get infinity norm of constraint violation for x and error in objective
+ value where obj is the estimated objective value of x.*/
+ double getNonLinearitiesViolation(const double *x, const double obj);
+
+//---------------------------------------------------------------------------
+
+ void extractInterfaceParams();
+
+
+ /** To set some application specific defaults. */
+ virtual void setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options);
+
+ /** Register all possible options to Bonmin */
+ static void registerOptions (Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions);
+
+ Ipopt::SmartPtr<Bonmin::RegisteredOptions> regOptions(){
+ if(IsValid(app_))
+ return app_->roptions();
+ else
+ return NULL;
+ }
+
+ /** @name Methods related to strong branching */
+ //@{
+ /// Set the strong branching solver
+ void SetStrongBrachingSolver(Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver);
+ /// Create a hot start snapshot of the optimization process. In our
+ /// case, we initialize the StrongBrachingSolver.
+ virtual void markHotStart();
+ /// Optimize starting from the hot start snapshot. In our case, we
+ /// call the StrongBranchingSolver to give us an approximate
+ /// solution for the current state of the bounds
+ virtual void solveFromHotStart();
+ /// Delete the hot start snapshot. In our case we deactivate the
+ /// StrongBrachingSolver.
+ virtual void unmarkHotStart();
+ //@}
+
+ /// Get values of tiny_ and very_tiny_
+ void get_tolerances(double &tiny, double&very_tiny, double &rhsRelax, double &infty){
+ tiny = tiny_;
+ very_tiny = veryTiny_;
+ rhsRelax = rhsRelax_;
+ infty = infty_;
+ }
+
+ void set_linearizer(Ipopt::SmartPtr<TMINLP2OsiLP> linearizer);
+
+ Ipopt::SmartPtr<TMINLP2OsiLP> linearizer();
+protected:
+
+ //@}
+
+ enum RandomGenerationType{
+ uniform =0, perturb=1, perturb_suffix=2};
+ /// Initialize data structures for storing the jacobian
+ int initializeJacobianArrays();
+
+ ///@name Virtual callbacks for application specific stuff
+ //@{
+ virtual std::string appName()
+ {
+ return "bonmin";
+ }
+ //@}
+ ///@name Protected methods
+ //@{
+
+ /** Call Ipopt to solve or resolve the problem and check for errors.*/
+ void solveAndCheckErrors(bool doResolve, bool throwOnFailure,
+ const char * whereFrom);
+
+
+ /** Add a linear cut to the problem formulation.
+ */
+ virtual void applyRowCut( const OsiRowCut & rc )
+ {
+ const OsiRowCut * cut = &rc;
+ problem_->addCuts(1, &cut);
+ }
+ /** We have to keep this but it will throw an error.
+ */
+ virtual void applyColCut( const OsiColCut & cc )
+ {
+ throw SimpleError("Ipopt model does not implement this function.",
+ "applyColCut");
+ }
+
+// /** Read the name of the variables in an ampl .col file. */
+// void readVarNames() const;
+
+ //@}
+
+ /**@name Model and solver */
+ //@{
+ /** TMINLP model.*/
+ Ipopt::SmartPtr<TMINLP> tminlp_;
+ /** Adapter for a MINLP to a NLP */
+ Ipopt::SmartPtr<TMINLP2TNLP> problem_;
+ /** Problem currently optimized (may be problem_ or feasibilityProblem_)*/
+ Ipopt::SmartPtr<Ipopt::TNLP> problem_to_optimize_;
+ /** Is true if and only if in feasibility mode.*/
+ bool feasibility_mode_;
+ /** Solver for a TMINLP. */
+ Ipopt::SmartPtr<TNLPSolver> app_;
+
+ /** Alternate solvers for TMINLP.*/
+ std::list<Ipopt::SmartPtr<TNLPSolver> > debug_apps_;
+ /** Do we use the other solvers?*/
+ bool testOthers_;
+ //@}
+
+ /** Warmstart information for reoptimization */
+ CoinWarmStart* warmstart_;
+
+ /**@name Cached information on the problem */
+ //@{
+ /** Free cached data relative to variables */
+ void freeCachedColRim();
+ /** Free cached data relative to constraints */
+ void freeCachedRowRim();
+ /** Free all cached data*/
+ void freeCachedData();
+ /** Extract rowsense_ vector rhs_ vector and rowrange_ vector from the lower and upper bounds
+ * on the constraints */
+ void extractSenseRhsAndRange() const;
+ /// Pointer to dense vector of row sense indicators
+ mutable char *rowsense_;
+
+ /// Pointer to dense vector of row right-hand side values
+ mutable double *rhs_;
+
+ /// Pointer to dense vector of slack upper bounds for range constraints (undefined for non-range rows)
+ mutable double *rowrange_;
+ /** Pointer to dense vector of reduced costs
+ \warning Always 0. with Ipopt*/
+ mutable double *reducedCosts_;
+ /** DualObjectiveLimit is used to store the cutoff in Cbc*/
+ double OsiDualObjectiveLimit_;
+ /** does the file variable names exists (will check automatically).*/
+ mutable bool hasVarNamesFile_;
+ //@}
+ /// number of time NLP has been solved
+ int nCallOptimizeTNLP_;
+ /// Total solution time of NLP
+ double totalNlpSolveTime_;
+ /// toatal number of iterations
+ int totalIterations_;
+ /// max radius for random point
+ double maxRandomRadius_;
+ /// Method to pick a random starting point.
+ int randomGenerationType_;
+ /// Maximum perturbation value
+ double max_perturbation_;
+ /// Ipopt value for pushing initial point inside the bounds
+ double pushValue_;
+ /// Number of times problem will be resolved in initialSolve (root node)
+ int numRetryInitial_;
+ /// Number of times problem will be resolved in resolve
+ int numRetryResolve_;
+ /// Number of times infeasible problem will be resolved.
+ int numRetryInfeasibles_;
+ /// Number of times problem will be resolved in case of a failure
+ int numRetryUnsolved_;
+ /// If infeasibility for a problem is less than this, let's be carrefull. It might be feasible
+ double infeasibility_epsilon_;
+
+
+ //Added by Claudia
+ /// Dynamic cutOff_
+ int dynamicCutOff_;
+ /// coeff_var_threshold_
+ double coeff_var_threshold_;
+ /// first_perc_for_cutoff_decr_
+ double first_perc_for_cutoff_decr_;
+ /// second_perc_for_cutoff_decr_
+ double second_perc_for_cutoff_decr_;
+
+
+ /** Messages specific to an OsiTMINLPInterface. */
+ Messages messages_;
+ /** If not 0 when a problem is not solved (failed to be solved)
+ will pretend that it is infeasible. If == 1 will care
+ (i.e. record the fact issue messages to user), if ==2 don't care (somebody else will) */
+ int pretendFailIsInfeasible_;
+
+ mutable int pretendSucceededNext_;
+
+ /** did we ever continue optimization ignoring a failure. */
+ bool hasContinuedAfterNlpFailure_;
+ /** number iterations above which a problem is considered suspect (-1 is considered \f$+ \infty \f$).
+ If in a call to solve a problem takes more than that number of iterations it will be output to files.*/
+ int numIterationSuspect_ ;
+ /** Has problem been optimized since last change (include setColSolution).
+ If yes getColSolution will return Ipopt point, otherwise will return
+ initial point.*/
+ bool hasBeenOptimized_;
+ /** A fake objective function (all variables to 1) to please Cbc
+ pseudo costs initialization. AW: I changed this, it will now be
+ the objective gradient at current point. */
+ mutable double * obj_;
+ /** flag to say wether options have been printed or not.*/
+ static bool hasPrintedOptions;
+
+ /** Adapter for TNLP to a feasibility problem */
+ Ipopt::SmartPtr<TNLP2FPNLP> feasibilityProblem_;
+
+ /** Adapter for TMINLP to an Osi LP */
+ Ipopt::SmartPtr<TMINLP2OsiLP> linearizer_;
+
+ /** \name Arrays to store Jacobian matrix */
+ //@{
+ /** Row indices.*/
+ int * jRow_;
+ /** Column indices.*/
+ int * jCol_;
+ /** Values */
+ double * jValues_;
+ /** Number of elements.*/
+ int nnz_jac;
+ //@}
+
+ ///Store the types of the constraints (linear and nonlinear).
+ Ipopt::TNLP::LinearityType * constTypes_;
+ /** Number of nonlinear constraint
+ */
+ int nNonLinear_;
+ /** Value for small non-zero element which we will try to remove cleanly in OA cuts.*/
+ double tiny_;
+ /** Value for small non-zero element which we will take the risk to ignore in OA cuts.*/
+ double veryTiny_;
+ /** Amount by which to relax OA constraints RHSes*/
+ double rhsRelax_;
+ /** Value for infinity. */
+ double infty_;
+ /** status of last optimization. */
+ TNLPSolver::ReturnStatus optimizationStatus_;
+ /** Flag indicating if the warm start methods actually do something.*/
+ WarmStartModes warmStartMode_;
+ /** Is it the first solve (for random starting point at root options).*/
+ bool firstSolve_;
+ /** Object for strengthening cuts */
+ Ipopt::SmartPtr<CutStrengthener> cutStrengthener_;
+
+ /** \name output for OA cut generation
+ \todo All OA code here should be moved to a separate class sometime.*/
+ //@{
+ /** OA Messages.*/
+ OaMessages oaMessages_;
+ /** OA Message handler. */
+ OaMessageHandler * oaHandler_;
+ //@}
+
+ double newCutoffDecr;
+protected:
+ /** Facilitator to create an application. */
+ void createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
+ Ipopt::SmartPtr<Ipopt::OptionsList> options,
+ Ipopt::SmartPtr<Ipopt::Journalist> journalist,
+ const std::string & prefix);
+ ///Constructor without model only for derived classes
+ OsiTMINLPInterface(Ipopt::SmartPtr<TNLPSolver> app);
+
+ /** Internal set warm start.*/
+ bool internal_setWarmStart(const CoinWarmStart* ws);
+
+ /** internal get warm start.*/
+ CoinWarmStart* internal_getWarmStart() const;
+
+ /** Procedure that builds a fake basis. Only tries to make basis consistent with constraints activity.*/
+ CoinWarmStart* build_fake_basis() const;
+private:
+
+ /** solver to be used for all strong branching solves */
+ Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver_;
+ /** status of last optimization before hot start was marked. */
+ TNLPSolver::ReturnStatus optimizationStatusBeforeHotStart_;
+static const char * OPT_SYMB;
+static const char * FAILED_SYMB;
+static const char * INFEAS_SYMB;
+static const char * TIME_SYMB;
+static const char * UNBOUND_SYMB;
+ /** Get status as a char * for log.*/
+ const char * statusAsString(TNLPSolver::ReturnStatus r){
+ if(r == TNLPSolver::solvedOptimal || r == TNLPSolver::solvedOptimalTol){
+ return OPT_SYMB;}
+ else if(r == TNLPSolver::provenInfeasible){
+ return INFEAS_SYMB;}
+ else if(r == TNLPSolver::unbounded){
+ return UNBOUND_SYMB;}
+ else if(r == TNLPSolver::timeLimit){
+ return TIME_SYMB;}
+ else return FAILED_SYMB;
+ }
+ const char * statusAsString(){
+ return statusAsString(optimizationStatus_);}
+};
+}
+#endif