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