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 Ipopt::SmartPtr<Ipopt::OptionsList> options();
00163
00164
00167
00168 virtual void initialSolve();
00169
00175 virtual void resolve();
00176
00179 virtual void resolveForCost(int numretry, bool keepWs);
00180
00184 virtual void resolveForRobustness(int numretry);
00185
00187 virtual void branchAndBound()
00188 {
00189 throw SimpleError("Function not implemented for OsiTMINLPInterface","branchAndBound()");
00190 }
00192
00193
00194
00195
00197
00198
00199 virtual bool isAbandoned() const;
00201 virtual bool isProvenOptimal() const;
00203 virtual bool isProvenPrimalInfeasible() const;
00205 virtual bool isProvenDualInfeasible() const;
00207 virtual bool isPrimalObjectiveLimitReached() const;
00209 virtual bool isDualObjectiveLimitReached() const;
00211 virtual bool isIterationLimitReached() const;
00212
00214 void continuingOnAFailure()
00215 {
00216 hasContinuedAfterNlpFailure_ = true;
00217 }
00219 bool hasContinuedOnAFailure()
00220 {
00221 return hasContinuedAfterNlpFailure_;
00222 }
00224 void ignoreFailures()
00225 {
00226 pretendFailIsInfeasible_ = 2;
00227 }
00229 void forceInfeasible()
00230 {
00231 problem_->set_obj_value(1e200);
00232 }
00234 void forceBranchable()
00235 {
00236 problem_->set_obj_value(-1e200);
00237 problem_->force_fractionnal_sol();
00238 }
00240
00241
00242
00258
00259 bool setIntParam(OsiIntParam key, int value);
00260
00261 bool setDblParam(OsiDblParam key, double value);
00262
00263 bool setStrParam(OsiStrParam key, const std::string & value);
00264
00265 bool getIntParam(OsiIntParam key, int& value) const;
00266
00267 bool getDblParam(OsiDblParam key, double& value) const;
00268
00269 bool getStrParam(OsiStrParam key, std::string& value) const;
00270
00271
00272 inline double getPushFact() const
00273 {
00274 return pushValue_;
00275 }
00276
00278
00279
00280
00295
00296 virtual int getNumCols() const;
00297
00299 virtual int getNumRows() const;
00300
00302 const OsiSolverInterface::OsiNameVec& getVarNames() ;
00304 virtual const double * getColLower() const;
00305
00307 virtual const double * getColUpper() const;
00308
00318 virtual const char * getRowSense() const;
00319
00328 virtual const double * getRightHandSide() const;
00329
00338 virtual const double * getRowRange() const;
00339
00341 virtual const double * getRowLower() const;
00342
00344 virtual const double * getRowUpper() const;
00345
00348 virtual double getObjSense() const
00349 {
00350 return 1;
00351 }
00352
00354 virtual bool isContinuous(int colNumber) const;
00355
00357 virtual bool isBinary(int columnNumber) const;
00358
00363 virtual bool isInteger(int columnNumber) const;
00364
00366 virtual bool isIntegerNonBinary(int columnNumber) const;
00367
00369 virtual bool isFreeBinary(int columnNumber) const;
00370
00372 virtual double getInfinity() const;
00373
00375 const int * getPriorities() const
00376 {
00377 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00378 if(branch)
00379 return branch->priorities;
00380 else return NULL;
00381 }
00383 const int * getBranchingDirections() const
00384 {
00385 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00386 if(branch)
00387 return branch->branchingDirections;
00388 else return NULL;
00389 }
00390 const double * getUpPsCosts() const
00391 {
00392 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00393 if(branch)
00394 return branch->upPsCosts;
00395 else return NULL;
00396 }
00397 const double * getDownPsCosts() const
00398 {
00399 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo();
00400 if(branch)
00401 return branch->downPsCosts;
00402 else return NULL;
00403 }
00404
00405
00407
00410
00411 virtual const double * getColSolution() const;
00412
00414 virtual const double * getRowPrice() const;
00415
00417 virtual const double * getReducedCost() const;
00418
00421 virtual const double * getRowActivity() const;
00422
00423
00428 virtual int getIterationCount() const;
00429
00431 int nCallOptimizeTNLP()
00432 {
00433 return nCallOptimizeTNLP_;
00434 }
00436 double totalNlpSolveTime()
00437 {
00438 return totalNlpSolveTime_;
00439 }
00441 int totalIterations()
00442 {
00443 return totalIterations_;
00444 }
00445
00446
00448
00452
00455 virtual void setColLower( int elementIndex, double elementValue );
00456
00459 virtual void setColUpper( int elementIndex, double elementValue );
00460
00464 virtual void setColLower(const double * array);
00465
00469 virtual void setColUpper(const double * array);
00470
00471
00474 virtual void setRowLower( int elementIndex, double elementValue );
00475
00478 virtual void setRowUpper( int elementIndex, double elementValue );
00479
00481 virtual void setRowType(int index, char sense, double rightHandSide,
00482 double range);
00483
00484
00489 virtual void setObjSense(double s);
00490
00495 virtual void setColSolution(const double *colsol);
00496
00501 virtual void setRowPrice(const double * rowprice);
00502
00504
00505
00506
00509
00516 virtual CoinWarmStart *getEmptyWarmStart () const;
00517
00519 virtual CoinWarmStart* getWarmStart() const;
00520
00523 virtual bool setWarmStart(const CoinWarmStart* warmstart);
00524
00525 void setExposeWarmStart(bool value) {
00526 exposeWarmStart_ = value;
00527 }
00528
00529 bool getExposeWarmStart() {
00530 return exposeWarmStart_;
00531 }
00532
00533 void randomStartingPoint();
00534
00535
00536 virtual bool basisIsAvailable() const
00537 {
00538
00539 throw SimpleError("Needs coding for this interface", "basisIsAvailable");
00540 }
00541
00542
00544
00545
00549 virtual void setContinuous(int index);
00551 virtual void setInteger(int index);
00553
00554
00555 void setNumIterationSuspect(int value)
00556 {
00557 numIterationSuspect_ = value;
00558 }
00559
00565
00568 virtual int getNumElements() const
00569 {
00570 return -1;
00571 }
00572
00573
00578 virtual const double * getObjCoefficients() const;
00579
00582 virtual const CoinPackedMatrix * getMatrixByRow() const
00583 {
00584 return NULL;
00585 }
00586
00587
00590 virtual const CoinPackedMatrix * getMatrixByCol() const
00591 {
00592 return NULL;
00593 }
00594
00597 virtual void setObjCoeff( int elementIndex, double elementValue )
00598 {
00599 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00600 "setObjCoeff");
00601 }
00602
00605 virtual void addCol(const CoinPackedVectorBase& vec,
00606 const double collb, const double colub,
00607 const double obj)
00608 {
00609 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00610 "addCol");
00611 }
00614 virtual void deleteCols(const int num, const int * colIndices)
00615 {
00616 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00617 "deleteCols");
00618 }
00619
00622 virtual void addRow(const CoinPackedVectorBase& vec,
00623 const double rowlb, const double rowub)
00624 {
00625 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00626 "addRow");
00627 }
00630 virtual void addRow(const CoinPackedVectorBase& vec,
00631 const char rowsen, const double rowrhs,
00632 const double rowrng)
00633 {
00634 throw SimpleError("OsiTMINLPInterface model does not implement this function.",
00635 "addRow");
00636 }
00639 virtual void deleteRows(const int num, const int * rowIndices)
00640 {
00641 if(num)
00642 freeCachedRowRim();
00643 problem_->removeCuts(num, rowIndices);
00644 }
00645
00646
00649 virtual void loadProblem(const CoinPackedMatrix& matrix,
00650 const double* collb, const double* colub,
00651 const double* obj,
00652 const double* rowlb, const double* rowub)
00653 {
00654 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00655 "loadProblem");
00656 }
00657
00658
00661 virtual void assignProblem(CoinPackedMatrix*& matrix,
00662 double*& collb, double*& colub, double*& obj,
00663 double*& rowlb, double*& rowub)
00664 {
00665 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00666 "assignProblem");
00667 }
00668
00671 virtual void loadProblem(const CoinPackedMatrix& matrix,
00672 const double* collb, const double* colub,
00673 const double* obj,
00674 const char* rowsen, const double* rowrhs,
00675 const double* rowrng)
00676 {
00677 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00678 "loadProblem");
00679 }
00680
00683 virtual void assignProblem(CoinPackedMatrix*& matrix,
00684 double*& collb, double*& colub, double*& obj,
00685 char*& rowsen, double*& rowrhs,
00686 double*& rowrng)
00687 {
00688 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00689 "assignProblem");
00690 }
00691
00692
00695 virtual void loadProblem(const int numcols, const int numrows,
00696 const int* start, const int* index,
00697 const double* value,
00698 const double* collb, const double* colub,
00699 const double* obj,
00700 const double* rowlb, const double* rowub)
00701 {
00702 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00703 "loadProblem");
00704 }
00705
00708 virtual void loadProblem(const int numcols, const int numrows,
00709 const int* start, const int* index,
00710 const double* value,
00711 const double* collb, const double* colub,
00712 const double* obj,
00713 const char* rowsen, const double* rowrhs,
00714 const double* rowrng)
00715 {
00716 throw SimpleError("OsiTMINLPInterface model does not implement this function.",
00717 "loadProblem");
00718 }
00719
00722 virtual int readMps(const char *filename,
00723 const char *extension = "mps")
00724 {
00725 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00726 "readMps");
00727 }
00728
00729
00732 virtual void writeMps(const char *filename,
00733 const char *extension = "mps",
00734 double objSense=0.0) const
00735 {
00736 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00737 "writeMps");
00738 }
00739
00741 virtual std::vector<double*> getDualRays(int maxNumRays) const
00742 {
00743 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00744 "getDualRays");
00745 }
00746
00748 virtual std::vector<double*> getPrimalRays(int maxNumRays) const
00749 {
00750 throw SimpleError("OsiTMINLPInterface does not implement this function.",
00751 "getPrimalRays");
00752 }
00753
00755
00756
00757
00758
00759
00760
00761
00765 void turnOffSolverOutput(){
00766 app_->turnOffOutput();}
00767 void turnOnSolverOutput(){
00768 app_->turnOnOutput();}
00770
00773
00774 virtual double getObjValue() const;
00775
00777
00779 const TMINLP2TNLP * problem() const
00780 {
00781 return GetRawPtr(problem_);
00782 }
00783
00784 TMINLP2TNLP * problem()
00785 {
00786 return GetRawPtr(problem_);
00787 }
00788
00789 const TMINLP * model() const
00790 {
00791 return GetRawPtr(tminlp_);
00792 }
00793
00794 Bonmin::TMINLP * model()
00795 {
00796 return GetRawPtr(tminlp_);
00797 }
00798
00799 const Bonmin::TNLPSolver * solver() const
00800 {
00801 return GetRawPtr(app_);
00802 }
00803
00804 TNLPSolver * solver()
00805 {
00806 return GetRawPtr(app_);
00807 }
00816 virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x,
00817 bool getObj = 1);
00818
00823 virtual void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1,
00824 bool solveNlp = 1){
00825 if(solveNlp)
00826 initialSolve();
00827 extractLinearRelaxation(si, getColSolution(), getObj);
00828 if(solveNlp){
00829 app_->enableWarmStart();
00830 setColSolution(problem()->x_sol());
00831 setRowPrice(problem()->duals_sol());
00832 }
00833 }
00834
00838 void getOuterApproximation(OsiCuts &cs, bool getObj, const double * x2, bool global)
00839 {
00840 getOuterApproximation(cs, getColSolution(), getObj, x2, global);
00841 }
00842
00846 void getOuterApproximation(OsiCuts &cs, const double * x, bool getObj, const double * x2, bool global){
00847 getOuterApproximation(cs, x, getObj, x2, 0., global);}
00848
00852 virtual void getOuterApproximation(OsiCuts &cs, const double * x, bool getObj, const double * x2,
00853 double theta, bool global);
00854
00856 virtual void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
00857 const double * x,
00858 const double * x2, bool global);
00859
00861 void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber,
00862 const double * x2, bool global){
00863 getConstraintOuterApproximation(cs, constraintNumber, getColSolution(),x2,global);
00864 }
00865
00867 void getBendersCut(OsiCuts &cs, const double * x, const double *lambda, bool getObj = 1);
00868
00876 double getFeasibilityOuterApproximation(int n, const double * x_bar,const int *ind, OsiCuts &cs, bool addOnlyViolated, bool global);
00877
00887 double solveFeasibilityProblem(int n, const double * x_bar, const int* ind, double a, double s, int L);
00889
00894 enum OaMessagesTypes {
00895 CUT_NOT_VIOLATED_ENOUGH = 0,
00896 VIOLATED_OA_CUT_GENERATED,
00897 OA_CUT_GENERATED,
00898 OA_MESSAGES_DUMMY_END};
00900 class OaMessages :public CoinMessages{
00901 public:
00903 OaMessages();
00904 };
00906 class OaMessageHandler : public CoinMessageHandler{
00907 public:
00909 OaMessageHandler():CoinMessageHandler(){
00910 }
00912 OaMessageHandler(FILE * fp):CoinMessageHandler(fp){
00913 }
00915 virtual ~OaMessageHandler(){
00916 }
00918 OaMessageHandler(const OaMessageHandler &other):
00919 CoinMessageHandler(other){}
00921 OaMessageHandler(const CoinMessageHandler &other):
00922 CoinMessageHandler(other){}
00924 OaMessageHandler & operator=(const OaMessageHandler &rhs){
00925 CoinMessageHandler::operator=(rhs);
00926 return *this;}
00928 virtual CoinMessageHandler* clone() const{
00929 return new OaMessageHandler(*this);}
00931 void print(OsiRowCut &row);
00932 };
00933 void setOaMessageHandler(const CoinMessageHandler &handler){
00934 delete oaHandler_;
00935 oaHandler_ = new OaMessageHandler(handler);
00936 }
00938
00939
00942 virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs,
00943 double effectivenessLb = 0.0){
00944 freeCachedRowRim();
00945 problem_->addCuts(cs);
00946 ApplyCutsReturnCode rc;
00947 return rc;}
00948
00950 virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts);
00951
00952
00954 virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
00955 {
00956 if(numberCuts)
00957 freeCachedRowRim();
00958 problem_->addCuts(numberCuts, cuts);
00959 }
00960
00963 double getConstraintsViolation(const double * x, double & obj);
00964
00967 double getNonLinearitiesViolation(const double *x, const double obj);
00968
00969
00970
00971 void extractInterfaceParams();
00972
00973
00975 virtual void setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options);
00976
00978 static void registerOptions (Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions);
00979
00980 Ipopt::SmartPtr<Bonmin::RegisteredOptions> regOptions(){
00981 if(IsValid(app_))
00982 return app_->roptions();
00983 else
00984 return NULL;
00985 }
00986
00989
00990 void SetStrongBrachingSolver(Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver);
00993 virtual void markHotStart();
00997 virtual void solveFromHotStart();
01000 virtual void unmarkHotStart();
01002
01003 protected:
01004
01006
01007 enum RandomGenerationType{
01008 uniform =0, perturb=1, perturb_suffix=2};
01010 int initializeJacobianArrays();
01011
01013
01014 virtual std::string appName()
01015 {
01016 return "bonmin";
01017 }
01019
01020
01021
01023 void solveAndCheckErrors(bool doResolve, bool throwOnFailure,
01024 const char * whereFrom);
01025
01026
01029 virtual void applyRowCut( const OsiRowCut & rc )
01030 {
01031 const OsiRowCut * cut = &rc;
01032 problem_->addCuts(1, &cut);
01033 }
01036 virtual void applyColCut( const OsiColCut & cc )
01037 {
01038 throw SimpleError("Ipopt model does not implement this function.",
01039 "applyColCut");
01040 }
01041
01042
01043
01044
01046
01050 Ipopt::SmartPtr<TMINLP> tminlp_;
01052 Ipopt::SmartPtr<TMINLP2TNLP> problem_;
01054 Ipopt::SmartPtr<TNLPSolver> app_;
01056
01058 CoinWarmStart* warmstart_;
01059
01063 void freeCachedColRim();
01065 void freeCachedRowRim();
01067 void freeCachedData();
01070 void extractSenseRhsAndRange() const;
01072 mutable char *rowsense_;
01073
01075 mutable double *rhs_;
01076
01078 mutable double *rowrange_;
01081 mutable double *reducedCosts_;
01083 double OsiDualObjectiveLimit_;
01085 mutable bool hasVarNamesFile_;
01087
01088 int nCallOptimizeTNLP_;
01090 double totalNlpSolveTime_;
01092 int totalIterations_;
01094 double maxRandomRadius_;
01096 int randomGenerationType_;
01098 double max_perturbation_;
01100 double pushValue_;
01102 int numRetryInitial_;
01104 int numRetryResolve_;
01106 int numRetryInfeasibles_;
01108 int numRetryUnsolved_;
01110 Messages messages_;
01114 int pretendFailIsInfeasible_;
01116 bool hasContinuedAfterNlpFailure_;
01119 int numIterationSuspect_ ;
01123 bool hasBeenOptimized_;
01127 mutable double * obj_;
01129 static bool hasPrintedOptions;
01130
01132 Ipopt::SmartPtr<TNLP2FPNLP> feasibilityProblem_;
01133
01134
01138 int * jRow_;
01140 int * jCol_;
01142 double * jValues_;
01144 int nnz_jac;
01146
01148 Ipopt::TNLP::LinearityType * constTypes_;
01151 int nNonLinear_;
01153 double tiny_;
01155 double veryTiny_;
01157 double infty_;
01159 TNLPSolver::ReturnStatus optimizationStatus_;
01161 bool exposeWarmStart_;
01163 bool firstSolve_;
01165 SmartPtr<CutStrengthener> cutStrengthener_;
01166
01171 OaMessages oaMessages_;
01173 OaMessageHandler * oaHandler_;
01175 protected:
01177 void createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
01178 Ipopt::SmartPtr<Ipopt::OptionsList> options,
01179 Ipopt::SmartPtr<Ipopt::Journalist> journalist);
01181 OsiTMINLPInterface(Ipopt::SmartPtr<TNLPSolver> app);
01182
01184 bool internal_setWarmStart(const CoinWarmStart* ws);
01185
01187 CoinWarmStart* internal_getWarmStart() const;
01188 private:
01190 SmartPtr<StrongBranchingSolver> strong_branching_solver_;
01192 TNLPSolver::ReturnStatus optimizationStatusBeforeHotStart_;
01193 };
01194 }
01195 #endif