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) {
00065 if (nlp_ == NULL) {
00066 CoinError("Error in cut generator for outer approximation no ipopt NLP assigned", "generateCuts", "OaNlpOptim");
00067 }
00068
00069 int numcols = nlp_->getNumCols();
00070
00071
00072
00073
00074 if(!info.inTree || info.pass > 0) return;
00075 #if 1
00076 BabInfo * babInfo = dynamic_cast<BabInfo *> (si.getAuxiliaryInfo());
00077 assert(babInfo);
00078 assert(babInfo->babPtr());
00079 const CbcNode * node = babInfo->babPtr()->model().currentNode();
00080 int level = (node == NULL) ? 0 : babInfo->babPtr()->model().currentNode()->depth();
00081 if (info.level > maxDepth_)
00082 return;
00083 if(solves_per_level_ < 1e10){
00084 double rand = CoinDrand48();
00085 double score = pow(2.,-level)*solves_per_level_;
00086
00087 if (score <= rand)
00088 return;
00089 }
00090 #endif
00091
00092 double * saveColLb = new double[numcols];
00093 double * saveColUb = new double[numcols];
00094 CoinCopyN(nlp_->getColLower(), numcols , saveColLb);
00095 CoinCopyN(nlp_->getColUpper(), numcols , saveColUb);
00096 for (int i = 0; i < numcols ; i++) {
00097 if (nlp_->isInteger(i)) {
00098 nlp_->setColBounds(i,si.getColLower()[i],si.getColUpper()[i]);
00099 }
00100 }
00101
00102
00103
00104
00105 nSolve_++;
00106 nlp_->resolve(txt_id);
00107 const double * violatedPoint = (addOnlyViolated_)? si.getColSolution():
00108 NULL;
00109 nlp_->getOuterApproximation(cs, 1, violatedPoint,global_);
00110 if (nlp_->isProvenOptimal()) {
00111 handler_->message(LP_ERROR,messages_)
00112 <<nlp_->getObjValue()-si.getObjValue()<<CoinMessageEol;
00113 bool feasible = 1;
00114 const double * colsol2 = nlp_->getColSolution();
00115 for (int i = 0 ; i < numcols && feasible; i++) {
00116 if (nlp_->isInteger(i)) {
00117 if (fabs(colsol2[i] - floor(colsol2[i] + 0.5) ) > 1e-07)
00118 feasible = 0;
00119 }
00120 }
00121 if (feasible ) {
00122 #if 1
00123
00124 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo();
00125 OsiBabSolver * auxiliaryInfo = dynamic_cast<OsiBabSolver *> (auxInfo);
00126 if (auxiliaryInfo) {
00127 double * lpSolution = new double[numcols + 1];
00128 CoinCopyN(colsol2, numcols, lpSolution);
00129 lpSolution[numcols] = nlp_->getObjValue();
00130 auxiliaryInfo->setSolution(lpSolution, numcols + 1, lpSolution[numcols]);
00131 delete [] lpSolution;
00132 }
00133 else
00134 fprintf(stderr,"No auxiliary info in nlp solve!\n");
00135 #endif
00136
00137 }
00138 }
00139 else if (nlp_->isAbandoned() || nlp_->isIterationLimitReached()) {
00140 throw CoinError("Unsolved NLP ... exit", "generateCuts", "OaNlpOptim");
00141 }
00142 else {
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 }
00163 for (int i = 0; i < numcols ; i++) {
00164 if (nlp_->isInteger(i)) {
00165 nlp_->setColBounds(i,saveColLb[i],saveColUb[i]);
00166 }
00167 }
00168 #if 0
00169 nlp_->deleteLastRows(numberCuts);
00170 #endif
00171 delete [] saveColLb;
00172 delete [] saveColUb;
00173 }
00174
00175 void
00176 OaNlpOptim::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00177 {
00178 roptions->SetRegisteringCategory("NLP solves in hybrid algorithm (B-Hyb)", RegisteredOptions::BonminCategory);
00179 roptions->AddLowerBoundedIntegerOption("nlp_solve_frequency",
00180 "Specify the frequency (in terms of nodes) at which NLP relaxations are solved in B-Hyb.",
00181 0,10,
00182 "A frequency of 0 amounts to to never solve the NLP relaxation.");
00183 roptions->setOptionExtraInfo("nlp_solve_frequency",1);
00184 roptions->AddLowerBoundedIntegerOption("nlp_solve_max_depth",
00185 "Set maximum depth in the tree at which NLP relaxations are solved in B-Hyb.",
00186 0,10,
00187 "A depth of 0 amounts to to never solve the NLP relaxation.");
00188 roptions->setOptionExtraInfo("nlp_solve_max_depth",1);
00189 roptions->AddLowerBoundedNumberOption("nlp_solves_per_depth",
00190 "Set average number of nodes in the tree at which NLP relaxations are solved in B-Hyb for each depth.",
00191 0.,false,1e100);
00192 roptions->setOptionExtraInfo("nlp_solves_per_depth",1);
00193 }
00194
00195
00196 }