00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef IpoptInterface_H
00014 #define IpoptInterface_H
00015
00016 #include "BonminConfig.h"
00017
00018 #include <string>
00019 #include <iostream>
00020
00021 #include "OsiSolverInterface.hpp"
00022 #include "CoinWarmStartBasis.hpp"
00023
00024 #include "TMINLP.hpp"
00025 #include "TMINLP2TNLP.hpp"
00026 #include "TNLP2FPNLP.hpp"
00027 #ifdef COIN_HAS_GAMSLINKS
00028 #include "CoinMessageHandler2Journal.hpp"
00029 #endif
00030 #include "IpIpoptApplication.hpp"
00031
00032
00038 class IpoptInterface : public OsiSolverInterface
00039 {
00040 friend class BonminParam;
00041
00042 public:
00043
00044
00045
00050 class SimpleError : public CoinError
00051 {
00052 public:
00054 SimpleError(std::string message,
00055 std::string methodName)
00056 :
00057 CoinError(message,methodName,std::string("IpoptInterface"))
00058 {}
00060 SimpleError (const char * message,
00061 const char * methodName)
00062 :
00063 CoinError(message,methodName,"IpoptInterface")
00064 {}
00065
00066 private:
00067 SimpleError();
00068 }
00069 ;
00070
00071
00072
00075 class UnsolvedError
00076 {
00077 public:
00079 UnsolvedError(int errorNum_ = 10000);
00081 void printError(std::ostream & os);
00083 const std::string& errorName() const;
00084 private:
00085 int errorNum_;
00086 static std::string errorNames [17];
00087 }
00088 ;
00089
00090
00091
00092
00093
00095 enum MessagesTypes{
00096 SOLUTION_FOUND,
00097 INFEASIBLE_SOLUTION_FOUND,
00098 UNSOLVED_PROBLEM_FOUND,
00099 WARNING_RESOLVING ,
00100 WARN_SUCCESS_WS,
00101 WARN_SUCCESS_RANDOM,
00102 WARN_CONTINUING_ON_FAILURE,
00103 SUSPECT_PROBLEM,
00104 SUSPECT_PROBLEM2,
00105 IPOPT_SUMMARY ,
00106 BETTER_SOL ,
00107 LOG_HEAD,
00108 LOG_FIRST_LINE,
00109 LOG_LINE,
00110 WARN_RESOLVE_BEFORE_INITIAL_SOLVE ,
00113 WARN_NONCONVEX_OA,
00114 WARN_FREEDOM,
00115 IPOTPINTERFACE_DUMMY_END
00116 };
00117
00118
00119
00120
00122 class Messages : public CoinMessages
00123 {
00124 public:
00126 Messages();
00127 };
00128
00129
00130
00131
00132
00135
00136 IpoptInterface();
00140 IpoptInterface (Ipopt::SmartPtr<Ipopt::TMINLP> tminlp
00141 #ifdef COIN_HAS_GAMSLINKS
00142 , CoinMessageHandler* messageHandler=NULL
00143 #endif
00144 );
00146 virtual OsiSolverInterface * clone(bool CopyData=true) const;
00147
00150 IpoptInterface (const IpoptInterface &);
00151
00153 IpoptInterface & operator=(const IpoptInterface& rhs);
00154
00156 virtual ~IpoptInterface ();
00157
00158
00160 Ipopt::SmartPtr<Ipopt::OptionsList> retrieve_options();
00161
00163 void register_ALL_options (Ipopt::SmartPtr<Ipopt::RegisteredOptions> roptions);
00164
00166 void set_ipopt_minlp_default(SmartPtr<OptionsList> Options);
00167
00169 void readOptionFile(const char * fileName);
00171
00172 void extractInterfaceParams();
00173
00174
00177
00178 virtual void initialSolve();
00179
00183 virtual void resolve();
00184
00187 void resolveForCost(int numretry);
00188
00192 void resolveForRobustness(int numretry);
00193
00195 virtual void branchAndBound()
00196 {
00197 throw SimpleError("Function not implemented for IpoptInterface","branchAndBound()");
00198 }
00200
00201
00202
00203
00205
00206
00207 virtual bool isAbandoned() const;
00209 virtual bool isProvenOptimal() const;
00211 virtual bool isProvenPrimalInfeasible() const;
00213 virtual bool isProvenDualInfeasible() const;
00215 virtual bool isPrimalObjectiveLimitReached() const;
00217 virtual bool isDualObjectiveLimitReached() const;
00219 virtual bool isIterationLimitReached() const;
00221 Ipopt::ApplicationReturnStatus getOptStatus() const
00222 {
00223 return optimization_status_;
00224 }
00225
00227 void continuingOnAFailure()
00228 {
00229 hasContinuedAfterNlpFailure_ = true;
00230 }
00232 bool hasContinuedOnAFailure()
00233 {
00234 return hasContinuedAfterNlpFailure_;
00235 }
00237 void ignoreFailures()
00238 {
00239 pretendFailIsInfeasible_ = 2;
00240 }
00242 void forceInfeasible()
00243 {
00244 problem_->set_obj_value(1e200);
00245 }
00247 void forceBranchable()
00248 {
00249 problem_->set_obj_value(-1e200);
00250 problem_->force_fractionnal_sol();
00251 }
00253
00254
00255
00271
00272 bool setIntParam(OsiIntParam key, int value);
00273
00274 bool setDblParam(OsiDblParam key, double value);
00275
00276 bool setStrParam(OsiStrParam key, const std::string & value);
00277
00278 bool getIntParam(OsiIntParam key, int& value) const;
00279
00280 bool getDblParam(OsiDblParam key, double& value) const;
00281
00282 bool getStrParam(OsiStrParam key, std::string& value) const;
00283
00284
00285 inline double getPushFact() const
00286 {
00287 return pushValue_;
00288 }
00289
00291
00292
00307
00308 virtual int getNumCols() const;
00309
00311 virtual int getNumRows() const;
00312
00314 const std::string * getVarNames() const;
00316 virtual const double * getColLower() const;
00317
00319 virtual const double * getColUpper() const;
00320
00330 virtual const char * getRowSense() const;
00331
00340 virtual const double * getRightHandSide() const;
00341
00350 virtual const double * getRowRange() const;
00351
00353 virtual const double * getRowLower() const;
00354
00356 virtual const double * getRowUpper() const;
00357
00360 virtual double getObjSense() const
00361 {
00362 return 1;
00363 }
00364
00366 virtual bool isContinuous(int colNumber) const;
00367
00369 virtual bool isBinary(int columnNumber) const;
00370
00375 virtual bool isInteger(int columnNumber) const;
00376
00378 virtual bool isIntegerNonBinary(int columnNumber) const;
00379
00381 virtual bool isFreeBinary(int columnNumber) const;
00382
00384 virtual double getInfinity() const;
00385
00387 const int * getPriorities() const
00388 {
00389 const Ipopt::TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00390 if(branch)
00391 return branch->priorities;
00392 else return NULL;
00393 }
00395 const int * getBranchingDirections() const
00396 {
00397 const Ipopt::TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00398 if(branch)
00399 return branch->branchingDirections;
00400 else return NULL;
00401 }
00402 const double * getUpPsCosts() const
00403 {
00404 const Ipopt::TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00405 if(branch)
00406 return branch->upPsCosts;
00407 else return NULL;
00408 }
00409 const double * getDownPsCosts() const
00410 {
00411 const Ipopt::TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00412 if(branch)
00413 return branch->downPsCosts;
00414 else return NULL;
00415 }
00416
00417
00419
00422
00423 virtual const double * getColSolution() const;
00424
00431 virtual const double * getRowPrice() const;
00432
00434 virtual const double * getReducedCost() const;
00435
00438 virtual const double * getRowActivity() const;
00439
00440
00443 virtual int getIterationCount() const;
00444
00446 int nCallOptimizeTNLP()
00447 {
00448 return nCallOptimizeTNLP_;
00449 }
00451 double totalNlpSolveTime()
00452 {
00453 return totalNlpSolveTime_;
00454 }
00456 int totalIterations()
00457 {
00458 return totalIterations_;
00459 }
00460
00461
00463
00467
00470 virtual void setColLower( int elementIndex, double elementValue );
00471
00474 virtual void setColUpper( int elementIndex, double elementValue );
00475
00476
00477
00480 virtual void setRowLower( int elementIndex, double elementValue );
00481
00484 virtual void setRowUpper( int elementIndex, double elementValue );
00485
00487 virtual void setRowType(int index, char sense, double rightHandSide,
00488 double range);
00489
00490
00495 virtual void setObjSense(double s);
00496
00501 virtual void setColSolution(const double *colsol);
00502
00510 virtual void setRowPrice(const double * rowprice);
00511
00513
00514
00515
00518
00525 CoinWarmStart *getEmptyWarmStart () const;
00526
00528 virtual CoinWarmStart* getWarmStart() const;
00529
00532 virtual bool setWarmStart(const CoinWarmStart* warmstart);
00533
00534
00535 void setWarmStartOptions()
00536 {
00537
00538 app_->Options()->SetStringValue("warm_start_init_point", "yes");
00539 }
00540 void unsetWarmStartOptions()
00541 {
00542
00543 app_->Options()->SetStringValue("warm_start_init_point", "no");
00544 problem_->resetStartingPoint();
00545 }
00546
00547 void randomStartingPoint();
00548
00549
00550 virtual bool basisIsAvailable() const
00551 {
00552
00553 throw SimpleError("Needs coding for this interface", "basisIsAvailable");
00554 }
00555
00556
00558
00559
00563 virtual void setContinuous(int index);
00565 virtual void setInteger(int index);
00567
00568
00569 void setNumIterationSuspect(int value)
00570 {
00571 numIterationSuspect_ = value;
00572 }
00573
00579
00582 virtual int getNumElements() const
00583 {
00584 return -1;
00585 }
00586
00587
00590 virtual const double * getObjCoefficients() const
00591 {
00592 if(!obj_)
00593 throw SimpleError("Ipopt model does not implement this function (function irelevant in an minlp).",
00594 "getObjCoefficients");
00595 return obj_;
00596 }
00597
00600 virtual const CoinPackedMatrix * getMatrixByRow() const
00601 {
00602 throw CoinError("Ipopt model does not implement this function.",
00603 "getMatrixByRow()","IpoptInterface");
00604 }
00605
00606
00609 virtual const CoinPackedMatrix * getMatrixByCol() const
00610 {
00611 throw CoinError("Ipopt model does not implement this function.",
00612 "getMatrixByCol()","IpoptInterface");
00613 }
00614
00617 virtual void setObjCoeff( int elementIndex, double elementValue )
00618 {
00619 throw CoinError("Ipopt model does not implement this function.",
00620 "setObjCoeff","IpoptInterface");
00621 }
00622
00625 virtual void addCol(const CoinPackedVectorBase& vec,
00626 const double collb, const double colub,
00627 const double obj)
00628 {
00629 throw CoinError("Ipopt model does not implement this function.",
00630 "addCol","IpoptInterface");
00631 }
00634 virtual void deleteCols(const int num, const int * colIndices)
00635 {
00636 throw CoinError("Ipopt model does not implement this function.",
00637 "deleteCols","IpoptInterface");
00638 }
00639
00642 virtual void addRow(const CoinPackedVectorBase& vec,
00643 const double rowlb, const double rowub)
00644 {
00645 throw CoinError("Ipopt model does not implement this function.",
00646 "addRow","IpoptInterface");
00647 }
00650 virtual void addRow(const CoinPackedVectorBase& vec,
00651 const char rowsen, const double rowrhs,
00652 const double rowrng)
00653 {
00654 throw CoinError("Ipopt model does not implement this function.",
00655 "addRow","IpoptInterface");
00656 }
00659 virtual void deleteRows(const int num, const int * rowIndices)
00660 {
00661 if(num>0)
00662 throw CoinError("Ipopt model does not implement this function.",
00663 "deleteRows","IpoptInterface");
00664 }
00665
00668 virtual void loadProblem(const CoinPackedMatrix& matrix,
00669 const double* collb, const double* colub,
00670 const double* obj,
00671 const double* rowlb, const double* rowub)
00672 {
00673 throw CoinError("Ipopt model does not implement this function.",
00674 "loadProblem","IpoptInterface");
00675 }
00676
00677
00680 virtual void assignProblem(CoinPackedMatrix*& matrix,
00681 double*& collb, double*& colub, double*& obj,
00682 double*& rowlb, double*& rowub)
00683 {
00684 throw CoinError("Ipopt model does not implement this function.",
00685 "assignProblem","IpoptInterface");
00686 }
00687
00690 virtual void loadProblem(const CoinPackedMatrix& matrix,
00691 const double* collb, const double* colub,
00692 const double* obj,
00693 const char* rowsen, const double* rowrhs,
00694 const double* rowrng)
00695 {
00696 throw CoinError("Ipopt model does not implement this function.",
00697 "loadProblem","IpoptInterface");
00698 }
00699
00702 virtual void assignProblem(CoinPackedMatrix*& matrix,
00703 double*& collb, double*& colub, double*& obj,
00704 char*& rowsen, double*& rowrhs,
00705 double*& rowrng)
00706 {
00707 throw CoinError("Ipopt model does not implement this function.",
00708 "assignProblem","IpoptInterface");
00709 }
00710
00711
00714 virtual void loadProblem(const int numcols, const int numrows,
00715 const int* start, const int* index,
00716 const double* value,
00717 const double* collb, const double* colub,
00718 const double* obj,
00719 const double* rowlb, const double* rowub)
00720 {
00721 throw CoinError("Ipopt model does not implement this function.",
00722 "loadProblem","IpoptInterface");
00723 }
00724
00727 virtual void loadProblem(const int numcols, const int numrows,
00728 const int* start, const int* index,
00729 const double* value,
00730 const double* collb, const double* colub,
00731 const double* obj,
00732 const char* rowsen, const double* rowrhs,
00733 const double* rowrng)
00734 {
00735 throw CoinError("Ipopt model does not implement this function.",
00736 "loadProblem","IpoptInterface");
00737 }
00738
00741 virtual int readMps(const char *filename,
00742 const char *extension = "mps")
00743 {
00744 throw CoinError("Ipopt model does not implement this function.",
00745 "readMps","IpoptInterface");
00746 }
00747
00748
00751 virtual void writeMps(const char *filename,
00752 const char *extension = "mps",
00753 double objSense=0.0) const
00754 {
00755 throw CoinError("Ipopt model does not implement this function.",
00756 "writeMps","IpoptInterface");
00757 }
00758
00760 virtual std::vector<double*> getDualRays(int maxNumRays) const
00761 {
00762 throw SimpleError("Ipopt model does not implement this function.",
00763 "getDualRays");
00764 }
00765
00767 virtual std::vector<double*> getPrimalRays(int maxNumRays) const
00768 {
00769 throw CoinError("Ipopt model does not implement this function.",
00770 "getPrimalRays","IpoptInterface");
00771 }
00772
00774
00775
00776
00777
00778
00782 void turnOffIpoptOutput();
00783 void turnOnIpoptOutput();
00784 #ifdef COIN_HAS_GAMSLINKS
00785 void passInMessageHandler(CoinMessageHandler* messageHandler);
00786 #endif
00787
00788
00791
00792 virtual double getObjValue() const;
00793
00795
00797 const Ipopt::TMINLP2TNLP * problem() const
00798 {
00799 return GetRawPtr(problem_);
00800 }
00801
00802 const Ipopt::TMINLP * model() const
00803 {
00804 return GetRawPtr(tminlp_);
00805 }
00806
00813 void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1);
00814
00817 void getOuterApproximation(OsiCuts &cs, bool getObj = 1);
00818
00826 double getFeasibilityOuterApproximation(int n, const double * x_bar,const int *ind, OsiCuts &cs);
00828 inline bool cleanNnz(double &value, double colLower, double colUpper,
00829 double rowLower, double rowUpper, double colsol,
00830 double & lb, double &ub, double tiny, double veryTiny);
00832
00833 double getConstraintViolation();
00834
00835
00836 protected:
00837
00839 int initializeJacobianArrays();
00840
00842
00843 virtual std::string appName()
00844 {
00845 return "bonmin";
00846 }
00848
00849
00850
00852 void solveAndCheckErrors(bool doResolve, bool throwOnFailure,
00853 const char * whereFrom);
00854
00855
00858 virtual void applyRowCut( const OsiRowCut & rc )
00859 {
00860 throw SimpleError("Ipopt model does not implement this function.",
00861 "applyRowCut");
00862 }
00865 virtual void applyColCut( const OsiColCut & cc )
00866 {
00867 throw SimpleError("Ipopt model does not implement this function.",
00868 "applyColCut");
00869 }
00870
00872 void readVarNames() const;
00873
00875
00879 Ipopt::SmartPtr<Ipopt::TMINLP> tminlp_;
00881 Ipopt::SmartPtr<Ipopt::TMINLP2TNLP> problem_;
00883 Ipopt::SmartPtr<Ipopt::IpoptApplication> app_;
00885
00889 void freeCachedColRim();
00891 void freeCachedRowRim();
00893 void freeCachedData();
00896 void extractSenseRhsAndRange() const;
00898 mutable char *rowsense_;
00899
00901 mutable double *rhs_;
00902
00904 mutable double *rowrange_;
00907 mutable double *reducedCosts_;
00909 double OsiDualObjectiveLimit_;
00911 Ipopt::ApplicationReturnStatus optimization_status_;
00913 mutable std::string * varNames_;
00915 mutable bool hasVarNamesFile_;
00917
00918 int nCallOptimizeTNLP_;
00920 double totalNlpSolveTime_;
00922 int totalIterations_;
00924 double maxRandomRadius_;
00926 double pushValue_;
00928 int numRetryInitial_;
00930 int numRetryResolve_;
00932 int numRetryUnsolved_;
00934 Messages ipoptIMessages_;
00938 int pretendFailIsInfeasible_;
00940 bool hasContinuedAfterNlpFailure_;
00943 int numIterationSuspect_ ;
00947 bool hasBeenOptimized_;
00955 int warmStartStrategy_;
00957 double * obj_;
00959 static bool hasPrintedOptions;
00960
00962 Ipopt::SmartPtr<Ipopt::TNLP2FPNLP> feasibilityProblem_;
00963
00964
00968 int * jRow_;
00970 int * jCol_;
00972 double * jValues_;
00974 int nnz_jac;
00976
00978 Ipopt::TMINLP::ConstraintType * constTypes_;
00982 int * constTypesNum_;
00984 int nLinear_;
00987 int nNonLinear_;
00989 double tiny_;
00991 double veryTiny_;
00993 bool firstSolve_;
00994
00995
00996 #ifdef COIN_HAS_GAMSLINKS
00997
00998 Ipopt::SmartPtr<CoinMessageHandler2Journal> journal_;
00999 #endif
01000 };
01001
01002 inline
01003 bool IpoptInterface::cleanNnz(double &value, double colLower, double colUpper,
01004 double rowLower, double rowUpper, double colsol,
01005 double & lb, double &ub, double tiny, double veryTiny)
01006 {
01007 if(fabs(value)>= tiny) return 1;
01008
01009 if(fabs(value)<veryTiny) return 0;
01010
01011
01012 double infty = 1e20;
01013 bool colUpBounded = colUpper < 10000;
01014 bool colLoBounded = colLower > -10000;
01015 bool rowNotLoBounded = rowLower <= - infty;
01016 bool rowNotUpBounded = rowUpper >= infty;
01017 bool pos = value > 0;
01018
01019 if(!rowNotLoBounded && ! rowNotUpBounded)
01020 {
01021 messageHandler()->message(WARN_NONCONVEX_OA, ipoptIMessages_)<<CoinMessageEol;
01022 }
01023
01024 if(colLoBounded && pos && rowNotUpBounded) {
01025 lb += value * (colsol - colLower);
01026 value = 0;
01027 return 0;
01028 }
01029 else
01030 if(colLoBounded && !pos && rowNotLoBounded) {
01031 ub += value * (colsol - colLower);
01032 value = 0;
01033 return 0;
01034 }
01035 else
01036 if(colUpBounded && !pos && rowNotUpBounded) {
01037 lb += value * (colsol - colUpper);
01038 value = 0;
01039 return 0;
01040 }
01041 else
01042 if(colUpBounded && pos && rowNotLoBounded) {
01043 ub += value * (colsol - colUpper);
01044 value = 0;
01045 return 0;
01046 }
01047
01048 if(pos) value = tiny;
01049 else
01050 value = - tiny;
01051 return 1;
01052 }
01053
01054 #endif