00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef OsiTMINLPInterface_H
00014 #define OsiTMINLPInterface_H
00015
00016 #define INT_BIAS 0e-8
00017
00018 #include <string>
00019 #include <iostream>
00020
00021 #include "OsiSolverInterface.hpp"
00022 #include "CoinWarmStartBasis.hpp"
00023
00024 #include "BonTMINLP.hpp"
00025 #include "BonTMINLP2TNLP.hpp"
00026 #include "BonTNLP2FPNLP.hpp"
00027 #include "BonTNLPSolver.hpp"
00028 #include "BonCutStrengthener.hpp"
00029 #include "BonRegisteredOptions.hpp"
00030
00031 namespace Bonmin {
00032
00033 class StrongBranchingSolver;
00034
00036 enum Solver{
00037 EIpopt=0 ,
00038 EFilterSQP
00039 };
00046 class OsiTMINLPInterface : public OsiSolverInterface
00047 {
00048 friend class BonminParam;
00049
00050 public:
00051
00052
00053
00058 class SimpleError : public CoinError
00059 {
00060 private:
00061 SimpleError();
00062
00063 public:
00065 SimpleError(std::string message,
00066 std::string methodName,
00067 std::string f = std::string(),
00068 int l = -1)
00069 :
00070 CoinError(message,methodName,std::string("OsiTMINLPInterface"), f, l)
00071 {}
00072 }
00073 ;
00074
00075 #ifdef __LINE__
00076 #define SimpleError(x, y) SimpleError((x), (y), __FILE__, __LINE__)
00077 #endif
00078
00079
00080 TNLPSolver::UnsolvedError * newUnsolvedError(int num, Ipopt::SmartPtr<TMINLP2TNLP> problem, std::string name){
00081 return app_->newUnsolvedError(num, problem, name);
00082 }
00083
00084
00085
00087 enum MessagesTypes{
00088 SOLUTION_FOUND,
00089 INFEASIBLE_SOLUTION_FOUND,
00090 UNSOLVED_PROBLEM_FOUND,
00091 WARNING_RESOLVING ,
00092 WARN_SUCCESS_WS,
00093 WARN_SUCCESS_RANDOM,
00094 WARN_CONTINUING_ON_FAILURE,
00095 SUSPECT_PROBLEM,
00096 SUSPECT_PROBLEM2,
00097 IPOPT_SUMMARY ,
00098 BETTER_SOL ,
00099 LOG_HEAD,
00100 LOG_FIRST_LINE,
00101 LOG_LINE,
00102 ALTERNATE_OBJECTIVE,
00103 WARN_RESOLVE_BEFORE_INITIAL_SOLVE ,
00106 ERROR_NO_TNLPSOLVER ,
00107 WARNING_NON_CONVEX_OA ,
00108 OSITMINLPINTERFACE_DUMMY_END
00109 };
00110
00111
00112
00113
00115 class Messages : public CoinMessages
00116 {
00117 public:
00119 Messages();
00120 };
00121
00122
00123
00124
00125
00128
00129 OsiTMINLPInterface();
00130
00132 void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00133 Ipopt::SmartPtr<Ipopt::OptionsList> options,
00134 Ipopt::SmartPtr<Ipopt::Journalist> journalist_,
00135 Ipopt::SmartPtr<TMINLP> tminlp);
00136
00138 void setModel(Ipopt::SmartPtr<TMINLP> tminlp);
00140 void setSolver(Ipopt::SmartPtr<TNLPSolver> app);
00142 void use(Ipopt::SmartPtr<TMINLP2TNLP> tminlp2tnlp){
00143 problem_ = tminlp2tnlp;}
00146 OsiTMINLPInterface (const OsiTMINLPInterface &);
00147
00149 OsiSolverInterface * clone(bool copyData = true) const;
00150
00152 OsiTMINLPInterface & operator=(const OsiTMINLPInterface& rhs);
00153
00155 virtual ~OsiTMINLPInterface ();
00156
00157
00159 void readOptionFile(const std::string & fileName);
00160
00162 const Ipopt::SmartPtr<Ipopt::OptionsList> options() const;
00164 Ipopt::SmartPtr<Ipopt::OptionsList> options();
00165
00166
00169
00170 virtual void initialSolve();
00171
00177 virtual void resolve();
00178
00181 virtual void resolveForCost(int numretry, bool keepWs);
00182
00186 virtual void resolveForRobustness(int numretry);
00187
00189 virtual void branchAndBound()
00190 {
00191 throw SimpleError("Function not implemented for OsiTMINLPInterface","branchAndBound()");
00192 }
00194
00195
00196
00197
00199
00200
00201 virtual bool isAbandoned() const;
00203 virtual bool isProvenOptimal() const;
00205 virtual bool isProvenPrimalInfeasible() const;
00207 virtual bool isProvenDualInfeasible() const;
00209 virtual bool isPrimalObjectiveLimitReached() const;
00211 virtual bool isDualObjectiveLimitReached() const;
00213 virtual bool isIterationLimitReached() const;
00214
00216 void continuingOnAFailure()
00217 {
00218 hasContinuedAfterNlpFailure_ = true;
00219 }
00221 bool hasContinuedOnAFailure()
00222 {
00223 return hasContinuedAfterNlpFailure_;
00224 }
00226 void ignoreFailures()
00227 {
00228 pretendFailIsInfeasible_ = 2;
00229 }
00231 void forceInfeasible()
00232 {
00233 problem_->set_obj_value(1e200);
00234 }
00236 void forceBranchable()
00237 {
00238 problem_->set_obj_value(-1e200);
00239 problem_->force_fractionnal_sol();
00240 }
00242
00243
00244
00260
00261 bool setIntParam(OsiIntParam key, int value);
00262
00263 bool setDblParam(OsiDblParam key, double value);
00264
00265 bool setStrParam(OsiStrParam key, const std::string & value);
00266
00267 bool getIntParam(OsiIntParam key, int& value) const;
00268
00269 bool getDblParam(OsiDblParam key, double& value) const;
00270
00271 bool getStrParam(OsiStrParam key, std::string& value) const;
00272
00273
00274 inline double getPushFact() const
00275 {
00276 return pushValue_;
00277 }
00278
00280
00281
00282
00297
00298 virtual int getNumCols() const;
00299
00301 virtual int getNumRows() const;
00302
00304 const OsiSolverInterface::OsiNameVec& getVarNames() ;
00306 virtual const double * getColLower() const;
00307
00309 virtual const double * getColUpper() const;
00310
00320 virtual const char * getRowSense() const;
00321
00330 virtual const double * getRightHandSide() const;
00331
00340 virtual const double * getRowRange() const;
00341
00343 virtual const double * getRowLower() const;
00344
00346 virtual const double * getRowUpper() const;
00347
00350 virtual double getObjSense() const
00351 {
00352 return 1;
00353 }
00354
00356 virtual bool isContinuous(int colNumber) const;
00357
00359 virtual bool isBinary(int columnNumber) const;
00360
00365 virtual bool isInteger(int columnNumber) const;
00366
00368 virtual bool isIntegerNonBinary(int columnNumber) const;
00369
00371 virtual bool isFreeBinary(int columnNumber) const;
00372
00374 virtual double getInfinity() const;
00375
00377 const int * getPriorities() const
00378 {
00379 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00380 if(branch)
00381 return branch->priorities;
00382 else return NULL;
00383 }
00385 const int * getBranchingDirections() const
00386 {
00387 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00388 if(branch)
00389 return branch->branchingDirections;
00390 else return NULL;
00391 }
00392 const double * getUpPsCosts() const
00393 {
00394 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00395 if(branch)
00396 return branch->upPsCosts;
00397 else return NULL;
00398 }
00399 const double * getDownPsCosts() const
00400 {
00401 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00402 if(branch)
00403 return branch->downPsCosts;
00404 else return NULL;
00405 }
00406
00407
00409
00412
00413 virtual const double * getColSolution() const;
00414
00416 virtual const double * getRowPrice() const;
00417
00419 virtual const double * getReducedCost() const;
00420
00423 virtual const double * getRowActivity() const;
00424
00425
00430 virtual int getIterationCount() const;
00431
00433 int nCallOptimizeTNLP()
00434 {
00435 return nCallOptimizeTNLP_;
00436 }
00438 double totalNlpSolveTime()
00439 {
00440 return totalNlpSolveTime_;
00441 }
00443 int totalIterations()
00444 {
00445 return totalIterations_;
00446 }
00447
00448
00450
00454
00457 virtual void setColLower( int elementIndex, double elementValue );
00458
00461 virtual void setColUpper( int elementIndex, double elementValue );
00462
00466 virtual void setColLower(const double * array);
00467
00471 virtual void setColUpper(const double * array);
00472
00473
00476 virtual void setRowLower( int elementIndex, double elementValue );
00477
00480 virtual void setRowUpper( int elementIndex, double elementValue );
00481
00483 virtual void setRowType(int index, char sense, double rightHandSide,
00484 double range);
00485
00486
00491 virtual void setObjSense(double s);
00492
00497 virtual void setColSolution(const double *colsol);
00498
00503 virtual void setRowPrice(const double * rowprice);
00504
00506
00507
00508
00511
00518 virtual CoinWarmStart *getEmptyWarmStart () const;
00519
00521 virtual CoinWarmStart* getWarmStart() const;
00522
00525 virtual bool setWarmStart(const CoinWarmStart* warmstart);
00526
00527 void setExposeWarmStart(bool value) {
00528 exposeWarmStart_ = value;
00529 }
00530
00531 bool getExposeWarmStart() {
00532 return exposeWarmStart_;
00533 }
00534
00535 void randomStartingPoint();
00536
00537
00538 virtual bool basisIsAvailable() const
00539 {
00540
00541 throw SimpleError("Needs coding for this interface", "basisIsAvailable");
00542 }
00543
00544
00546
00547
00551 virtual void setContinuous(int index);
00553 virtual void setInteger(int index);
00555
00556
00557 void setNumIterationSuspect(int value)
00558 {
00559 numIterationSuspect_ = value;
00560 }
00561
00567
00570 virtual int getNumElements() const
00571 {
00572 return -1;
00573 }
00574
00575
00580 virtual const double * getObjCoefficients() const;
00581
00584 virtual const CoinPackedMatrix * getMatrixByRow() const
00585 {
00586 return NULL;
00587 }
00588
00589
00592 virtual const CoinPackedMatrix * getMatrixByCol() const
00593 {
00594 return NULL;
00595 }
00596
00599 virtual void setObjCoeff( int elementIndex, double elementValue )
00600 {
00601 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00602 "setObjCoeff");
00603 }
00604
00607 virtual void addCol(const CoinPackedVectorBase& vec,
00608 const double collb, const double colub,
00609 const double obj)
00610 {
00611 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00612 "addCol");
00613 }
00616 virtual void deleteCols(const int num, const int * colIndices)
00617 {
00618 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00619 "deleteCols");
00620 }
00621
00624 virtual void addRow(const CoinPackedVectorBase& vec,
00625 const double rowlb, const double rowub)
00626 {
00627 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00628 "addRow");
00629 }
00632 virtual void addRow(const CoinPackedVectorBase& vec,
00633 const char rowsen, const double rowrhs,
00634 const double rowrng)
00635 {
00636 throw SimpleError("OsiTMINLPInterface model does not implement this function.",
00637 "addRow");
00638 }
00641 virtual void deleteRows(const int num, const int * rowIndices)
00642 {
00643 if(num)
00644 freeCachedRowRim();
00645 problem_->removeCuts(num, rowIndices);
00646 }
00647
00648
00651 virtual void loadProblem(const CoinPackedMatrix& matrix,
00652 const double* collb, const double* colub,
00653 const double* obj,
00654 const double* rowlb, const double* rowub)
00655 {
00656 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00657 "loadProblem");
00658 }
00659
00660
00663 virtual void assignProblem(CoinPackedMatrix*& matrix,
00664 double*& collb, double*& colub, double*& obj,
00665 double*& rowlb, double*& rowub)
00666 {
00667 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00668 "assignProblem");
00669 }
00670
00673 virtual void loadProblem(const CoinPackedMatrix& matrix,
00674 const double* collb, const double* colub,
00675 const double* obj,
00676 const char* rowsen, const double* rowrhs,
00677 const double* rowrng)
00678 {
00679 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00680 "loadProblem");
00681 }
00682
00685 virtual void assignProblem(CoinPackedMatrix*& matrix,
00686 double*& collb, double*& colub, double*& obj,
00687 char*& rowsen, double*& rowrhs,
00688 double*& rowrng)
00689 {
00690 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00691 "assignProblem");
00692 }
00693
00694
00697 virtual void loadProblem(const int numcols, const int numrows,
00698 const int* start, const int* index,
00699 const double* value,
00700 const double* collb, const double* colub,
00701 const double* obj,
00702 const double* rowlb, const double* rowub)
00703 {
00704 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00705 "loadProblem");
00706 }
00707
00710 virtual void loadProblem(const int numcols, const int numrows,
00711 const int* start, const int* index,
00712 const double* value,
00713 const double* collb, const double* colub,
00714 const double* obj,
00715 const char* rowsen, const double* rowrhs,
00716 const double* rowrng)
00717 {
00718 throw SimpleError("OsiTMINLPInterface model does not implement this function.",
00719 "loadProblem");
00720 }
00721
00724 virtual int readMps(const char *filename,
00725 const char *extension = "mps")
00726 {
00727 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00728 "readMps");
00729 }
00730
00731
00734 virtual void writeMps(const char *filename,
00735 const char *extension = "mps",
00736 double objSense=0.0) const
00737 {
00738 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00739 "writeMps");
00740 }
00741
00743 virtual std::vector<double*> getDualRays(int maxNumRays) const
00744 {
00745 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00746 "getDualRays");
00747 }
00748
00750 virtual std::vector<double*> getPrimalRays(int maxNumRays) const
00751 {
00752 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00753 "getPrimalRays");
00754 }
00755
00757
00758
00759
00760
00761
00762
00763
00767 void turnOffSolverOutput(){
00768 app_->turnOffOutput();}
00769 void turnOnSolverOutput(){
00770 app_->turnOnOutput();}
00772
00775
00776 virtual double getObjValue() const;
00777
00779
00781 const TMINLP2TNLP * problem() const
00782 {
00783 return GetRawPtr(problem_);
00784 }
00785
00786 TMINLP2TNLP * problem()
00787 {
00788 return GetRawPtr(problem_);
00789 }
00790
00791 const TMINLP * model() const
00792 {
00793 return GetRawPtr(tminlp_);
00794 }
00795
00796 Bonmin::TMINLP * model()
00797 {
00798 return GetRawPtr(tminlp_);
00799 }
00800
00801 const Bonmin::TNLPSolver * solver() const
00802 {
00803 return GetRawPtr(app_);
00804 }
00805
00806 TNLPSolver * solver()
00807 {
00808 return GetRawPtr(app_);
00809 }
00818 virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x,
00819 bool getObj = 1);
00820
00825 virtual void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1,
00826 bool solveNlp = 1){
00827 if(solveNlp)
00828 initialSolve();
00829 extractLinearRelaxation(si, getColSolution(), getObj);
00830 if(solveNlp){
00831 app_->enableWarmStart();
00832 setColSolution(problem()->x_sol());
00833 setRowPrice(problem()->duals_sol());
00834 }
00835 }
00836
00840 void getOuterApproximation(OsiCuts &cs, bool getObj, const double * x2, bool global)
00841 {
00842 getOuterApproximation(cs, getColSolution(), getObj, x2, global);
00843 }
00844
00848 void getOuterApproximation(OsiCuts &cs, const double * x, bool getObj, const double * x2, bool global){
00849 getOuterApproximation(cs, x, getObj, x2, 0., global);}
00850
00854 virtual void getOuterApproximation(OsiCuts &cs, const double * x, bool getObj, const double * x2,
00855 double theta, bool global);
00856
00858 virtual void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
00859 const double * x,
00860 const double * x2, bool global);
00861
00863 void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
00864 const double * x2, bool global){
00865 getConstraintOuterApproximation(cs, constraintNumber, getColSolution(),x2,global);
00866 }
00867
00869 void getBendersCut(OsiCuts &cs, const double * x, const double *lambda, bool getObj = 1);
00870
00878 double getFeasibilityOuterApproximation(int n, const double * x_bar,const int *ind, OsiCuts &cs, bool addOnlyViolated, bool global);
00879
00889 double solveFeasibilityProblem(int n, const double * x_bar, const int* ind, double a, double s, int L);
00891
00896 enum OaMessagesTypes {
00897 CUT_NOT_VIOLATED_ENOUGH = 0,
00898 VIOLATED_OA_CUT_GENERATED,
00899 OA_CUT_GENERATED,
00900 OA_MESSAGES_DUMMY_END};
00902 class OaMessages :public CoinMessages{
00903 public:
00905 OaMessages();
00906 };
00908 class OaMessageHandler : public CoinMessageHandler{
00909 public:
00911 OaMessageHandler():CoinMessageHandler(){
00912 }
00914 OaMessageHandler(FILE * fp):CoinMessageHandler(fp){
00915 }
00917 virtual ~OaMessageHandler(){
00918 }
00920 OaMessageHandler(const OaMessageHandler &other):
00921 CoinMessageHandler(other){}
00923 OaMessageHandler(const CoinMessageHandler &other):
00924 CoinMessageHandler(other){}
00926 OaMessageHandler & operator=(const OaMessageHandler &rhs){
00927 CoinMessageHandler::operator=(rhs);
00928 return *this;}
00930 virtual CoinMessageHandler* clone() const{
00931 return new OaMessageHandler(*this);}
00933 void print(OsiRowCut &row);
00934 };
00935 void setOaMessageHandler(const CoinMessageHandler &handler){
00936 delete oaHandler_;
00937 oaHandler_ = new OaMessageHandler(handler);
00938 }
00940
00941
00944 virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs,
00945 double effectivenessLb = 0.0){
00946 freeCachedRowRim();
00947 problem_->addCuts(cs);
00948 ApplyCutsReturnCode rc;
00949 return rc;}
00950
00952 virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts);
00953
00954
00956 virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
00957 {
00958 if(numberCuts)
00959 freeCachedRowRim();
00960 problem_->addCuts(numberCuts, cuts);
00961 }
00962
00965 double getConstraintsViolation(const double * x, double & obj);
00966
00969 double getNonLinearitiesViolation(const double *x, const double obj);
00970
00971
00972
00973 void extractInterfaceParams();
00974
00975
00977 virtual void setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options);
00978
00980 static void registerOptions (Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions);
00981
00982 Ipopt::SmartPtr<Bonmin::RegisteredOptions> regOptions(){
00983 if(IsValid(app_))
00984 return app_->roptions();
00985 else
00986 return NULL;
00987 }
00988
00991
00992 void SetStrongBrachingSolver(Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver);
00995 virtual void markHotStart();
00999 virtual void solveFromHotStart();
01002 virtual void unmarkHotStart();
01004
01005 protected:
01006
01008
01009 enum RandomGenerationType{
01010 uniform =0, perturb=1, perturb_suffix=2};
01012 int initializeJacobianArrays();
01013
01015
01016 virtual std::string appName()
01017 {
01018 return "bonmin";
01019 }
01021
01022
01023
01025 void solveAndCheckErrors(bool doResolve, bool throwOnFailure,
01026 const char * whereFrom);
01027
01028
01031 virtual void applyRowCut( const OsiRowCut & rc )
01032 {
01033 const OsiRowCut * cut = &rc;
01034 problem_->addCuts(1, &cut);
01035 }
01038 virtual void applyColCut( const OsiColCut & cc )
01039 {
01040 throw SimpleError("Ipopt model does not implement this function.",
01041 "applyColCut");
01042 }
01043
01044
01045
01046
01048
01052 Ipopt::SmartPtr<TMINLP> tminlp_;
01054 Ipopt::SmartPtr<TMINLP2TNLP> problem_;
01056 Ipopt::SmartPtr<TNLPSolver> app_;
01058
01060 CoinWarmStart* warmstart_;
01061
01065 void freeCachedColRim();
01067 void freeCachedRowRim();
01069 void freeCachedData();
01072 void extractSenseRhsAndRange() const;
01074 mutable char *rowsense_;
01075
01077 mutable double *rhs_;
01078
01080 mutable double *rowrange_;
01083 mutable double *reducedCosts_;
01085 double OsiDualObjectiveLimit_;
01087 mutable bool hasVarNamesFile_;
01089
01090 int nCallOptimizeTNLP_;
01092 double totalNlpSolveTime_;
01094 int totalIterations_;
01096 double maxRandomRadius_;
01098 int randomGenerationType_;
01100 double max_perturbation_;
01102 double pushValue_;
01104 int numRetryInitial_;
01106 int numRetryResolve_;
01108 int numRetryInfeasibles_;
01110 int numRetryUnsolved_;
01112 Messages messages_;
01116 int pretendFailIsInfeasible_;
01118 bool hasContinuedAfterNlpFailure_;
01121 int numIterationSuspect_ ;
01125 bool hasBeenOptimized_;
01129 mutable double * obj_;
01131 static bool hasPrintedOptions;
01132
01134 Ipopt::SmartPtr<TNLP2FPNLP> feasibilityProblem_;
01135
01136
01140 int * jRow_;
01142 int * jCol_;
01144 double * jValues_;
01146 int nnz_jac;
01148
01150 Ipopt::TNLP::LinearityType * constTypes_;
01153 int nNonLinear_;
01155 double tiny_;
01157 double veryTiny_;
01159 double infty_;
01161 TNLPSolver::ReturnStatus optimizationStatus_;
01163 bool exposeWarmStart_;
01165 bool firstSolve_;
01167 SmartPtr<CutStrengthener> cutStrengthener_;
01168
01173 OaMessages oaMessages_;
01175 OaMessageHandler * oaHandler_;
01177 protected:
01179 void createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
01180 Ipopt::SmartPtr<Ipopt::OptionsList> options,
01181 Ipopt::SmartPtr<Ipopt::Journalist> journalist);
01183 OsiTMINLPInterface(Ipopt::SmartPtr<TNLPSolver> app);
01184
01186 bool internal_setWarmStart(const CoinWarmStart* ws);
01187
01189 CoinWarmStart* internal_getWarmStart() const;
01190 private:
01192 SmartPtr<StrongBranchingSolver> strong_branching_solver_;
01194 TNLPSolver::ReturnStatus optimizationStatusBeforeHotStart_;
01195 };
01196 }
01197 #endif