00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BonOaNlpOptim.hpp"
00011 #include "OsiAuxInfo.hpp"
00012 #include "CbcModel.hpp"
00013 #include "BonBabInfos.hpp"
00014 #include "BonCbc.hpp"
00015
00016 namespace Bonmin
00017 {
00018 static const char * txt_id = "NLP relax. for OA";
00019
00021 OaNlpOptim::OaNlpOptim(OsiTMINLPInterface * si,
00022 int maxDepth, bool addOnlyViolated, bool global)
00023 :
00024 CglCutGenerator(),
00025 nlp_(si),
00026 maxDepth_(maxDepth),
00027 nSolve_(0),
00028 addOnlyViolated_(addOnlyViolated),
00029 global_(global)
00030 {
00031 handler_ = new CoinMessageHandler();
00032 handler_ -> setLogLevel(1);
00033 messages_ = OaMessages();
00034 }
00035
00036 OaNlpOptim::OaNlpOptim(BabSetupBase &b):
00037 CglCutGenerator(),
00038 nlp_(b.nonlinearSolver()),
00039 maxDepth_(1000),
00040 nSolve_(0)
00041 {
00042 int ivalue;
00043 b.options()->GetEnumValue("add_only_violated_oa", ivalue,b.prefix());
00044 addOnlyViolated_ = ivalue;
00045 b.options()->GetEnumValue("oa_cuts_scope", ivalue,b.prefix());
00046 global_ = ivalue;
00047
00048 b.options()->GetIntegerValue("nlp_solve_max_depth", maxDepth_,b.prefix());
00049 b.options()->GetNumericValue("nlp_solves_per_depth", solves_per_level_,b.prefix());
00050 handler_ = new CoinMessageHandler();
00051 handler_ -> setLogLevel(1);
00052 messages_ = OaMessages();
00053 }
00055 void
00056 OaNlpOptim::assignInterface(OsiTMINLPInterface * si)
00057
00058 {
00059 nlp_ = si;
00060 }
00062 void
00063 OaNlpOptim::generateCuts( const OsiSolverInterface & si, OsiCuts & cs,
00064 const CglTreeInfo info) const
00065 {
00066 if (nlp_ == NULL) {
00067 CoinError("Error in cut generator for outer approximation no ipopt NLP assigned", "generateCuts", "OaNlpOptim");
00068 }
00069
00070 int numcols = nlp_->getNumCols();
00071
00072
00073
00074
00075 if(!info.inTree || info.pass > 0) return;
00076 #if 1
00077 BabInfo * babInfo = dynamic_cast<BabInfo *> (si.getAuxiliaryInfo());
00078 assert(babInfo);
00079 assert(babInfo->babPtr());
00080 const CbcNode * node = babInfo->babPtr()->model().currentNode();
00081 int level = (node == NULL) ? 0 : babInfo->babPtr()->model().currentNode()->depth();
00082 if (info.level > maxDepth_)
00083 return;
00084 if(solves_per_level_ < 1e10){
00085 double rand = CoinDrand48();
00086 double score = pow(2.,-level)*solves_per_level_;
00087
00088 if (score <= rand)
00089 return;
00090 }
00091 #endif
00092
00093 double * saveColLb = new double[numcols];
00094 double * saveColUb = new double[numcols];
00095 CoinCopyN(nlp_->getColLower(), numcols , saveColLb);
00096 CoinCopyN(nlp_->getColUpper(), numcols , saveColUb);
00097 for (int i = 0; i < numcols ; i++) {
00098 if (nlp_->isInteger(i)) {
00099 nlp_->setColBounds(i,si.getColLower()[i],si.getColUpper()[i]);
00100 }
00101 }
00102
00103
00104
00105
00106 nSolve_++;
00107 nlp_->resolve(txt_id);
00108 const double * violatedPoint = (addOnlyViolated_)? si.getColSolution():
00109 NULL;
00110 nlp_->getOuterApproximation(cs, 1, violatedPoint,global_);
00111 if (nlp_->isProvenOptimal()) {
00112 handler_->message(LP_ERROR,messages_)
00113 <<nlp_->getObjValue()-si.getObjValue()<<CoinMessageEol;
00114 bool feasible = 1;
00115 const double * colsol2 = nlp_->getColSolution();
00116 for (int i = 0 ; i < numcols && feasible; i++) {
00117 if (nlp_->isInteger(i)) {
00118 if (fabs(colsol2[i] - floor(colsol2[i] + 0.5) ) > 1e-07)
00119 feasible = 0;
00120 }
00121 }
00122 if (feasible ) {
00123 #if 1
00124
00125 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo();
00126 OsiBabSolver * auxiliaryInfo = dynamic_cast<OsiBabSolver *> (auxInfo);
00127 if (auxiliaryInfo) {
00128 double * lpSolution = new double[numcols + 1];
00129 CoinCopyN(colsol2, numcols, lpSolution);
00130 lpSolution[numcols] = nlp_->getObjValue();
00131 auxiliaryInfo->setSolution(lpSolution, numcols + 1, lpSolution[numcols]);
00132 delete [] lpSolution;
00133 }
00134 else
00135 fprintf(stderr,"No auxiliary info in nlp solve!\n");
00136 #endif
00137
00138 }
00139 }
00140 else if (nlp_->isAbandoned() || nlp_->isIterationLimitReached()) {
00141 throw CoinError("Unsolved NLP ... exit", "generateCuts", "OaNlpOptim");
00142 }
00143 else {
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 }
00164 for (int i = 0; i < numcols ; i++) {
00165 if (nlp_->isInteger(i)) {
00166 nlp_->setColBounds(i,saveColLb[i],saveColUb[i]);
00167 }
00168 }
00169 #if 0
00170 nlp_->deleteLastRows(numberCuts);
00171 #endif
00172 delete [] saveColLb;
00173 delete [] saveColUb;
00174 }
00175
00176 void
00177 OaNlpOptim::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00178 {
00179 roptions->SetRegisteringCategory("Nlp solve options in B-Hyb", RegisteredOptions::BonminCategory);
00180 roptions->AddLowerBoundedIntegerOption("nlp_solve_frequency",
00181 "Specify the frequency (in terms of nodes) at which NLP relaxations are solved in B-Hyb.",
00182 0,10,
00183 "A frequency of 0 amounts to to never solve the NLP relaxation.");
00184 roptions->setOptionExtraInfo("nlp_solve_frequency",1);
00185 roptions->AddLowerBoundedIntegerOption("nlp_solve_max_depth",
00186 "Set maximum depth in the tree at which NLP relaxations are solved in B-Hyb.",
00187 0,10,
00188 "A depth of 0 amounts to to never solve the NLP relaxation.");
00189 roptions->setOptionExtraInfo("nlp_solve_max_depth",1);
00190 roptions->AddLowerBoundedNumberOption("nlp_solves_per_depth",
00191 "Set average number of nodes in the tree at which NLP relaxations are solved in B-Hyb for each depth.",
00192 0.,false,1e100);
00193 roptions->setOptionExtraInfo("nlp_solves_per_depth",1);
00194 }
00195
00196
00197 }