00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "BonCouenneInterface.hpp"
00014 #include "CoinHelperFunctions.hpp"
00015
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneProblemElem.hpp"
00018 #include "CouenneExprVar.hpp"
00019 #include "CouenneRecordBestSol.hpp"
00020
00021 using namespace Couenne;
00022
00024 CouenneInterface::CouenneInterface():
00025 AmplInterface(),
00026 have_nlp_solution_ (false)
00027 {}
00028
00030 CouenneInterface::CouenneInterface(const CouenneInterface &other):
00031 AmplInterface(other),
00032 have_nlp_solution_ (false)
00033 {}
00034
00036 CouenneInterface * CouenneInterface::clone(bool CopyData){
00037 return new CouenneInterface(*this);
00038 }
00039
00041 CouenneInterface::~CouenneInterface(){
00042 }
00043
00044 #ifdef COUENNEINTERFACE_FROM_ASL
00045 void
00046 CouenneInterface::readAmplNlFile(char **& argv, Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00047 Ipopt::SmartPtr<Ipopt::OptionsList> options,
00048 Ipopt::SmartPtr<Ipopt::Journalist> journalist){
00049
00050
00051 AmplInterface::readAmplNlFile(argv, roptions, options, journalist);
00052 }
00053 #endif
00054
00067 void
00068 CouenneInterface::extractLinearRelaxation
00069 (OsiSolverInterface &si, CouenneCutGenerator & couenneCg, bool getObj, bool solveNlp) {
00070
00071 {
00072 int nlpLogLevel;
00073 options () -> GetIntegerValue ("nlp_log_level", nlpLogLevel, "couenne.");
00074 messageHandler () -> setLogLevel (nlpLogLevel);
00075 }
00076
00077 CouenneProblem *p = couenneCg.Problem ();
00078 bool is_feasible = true;
00079
00080 if (solveNlp) {
00081
00082 int nvars = p -> nVars();
00083
00084 if (p -> doFBBT ()) {
00085
00086
00087
00088
00089 for (int i=0; i < p -> nCons (); i++) {
00090
00091
00092 CouenneConstraint *con = p -> Con (i);
00093
00094
00095 int index = con -> Body () -> Index ();
00096
00097 if ((index >= 0) && (con -> Body () -> Type () == AUX)) {
00098
00099
00100 CouNumber
00101 l = con -> Lb () -> Value (),
00102 u = con -> Ub () -> Value ();
00103
00104
00105 p -> Lb (index) = CoinMax (l, p -> Lb (index));
00106 p -> Ub (index) = CoinMin (u, p -> Ub (index));
00107 }
00108 }
00109
00110 t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00111
00112 for (int i=0; i<nvars; i++) {
00113 chg_bds [i].setLower(t_chg_bounds::CHANGED);
00114 chg_bds [i].setUpper(t_chg_bounds::CHANGED);
00115 }
00116
00117 if (!(p -> boundTightening (chg_bds, NULL))) {
00118 is_feasible = false;
00119 *messageHandler() << "Couenne: Warning, tightened NLP is infeasible" << CoinMessageEol;
00120 }
00121
00122 delete [] chg_bds;
00123
00124 const double
00125 *nlb = getColLower (),
00126 *nub = getColUpper ();
00127
00128 for (int i=0; i < p -> nOrigVars () - p -> nDefVars (); i++)
00129 if (p -> Var (i) -> Multiplicity () > 0) {
00130
00131
00132
00133 if (nlb [i] < p -> Lb (i) - COUENNE_EPS) setColLower (i, p -> Lb (i));
00134 if (nub [i] > p -> Ub (i) + COUENNE_EPS) setColUpper (i, p -> Ub (i));
00135 } else {
00136
00137 setColLower (i, -COIN_DBL_MAX);
00138 setColUpper (i, COIN_DBL_MAX);
00139 }
00140 }
00141
00142 if (is_feasible) {
00143 try {
00144 options () -> SetNumericValue ("max_cpu_time", CoinMax (0., (p -> getMaxCpuTime () - CoinCpuTime ()) / 2));
00145 initialSolve ();
00146 }
00147 catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00148
00149
00150 }
00151 }
00152
00153 if (!is_feasible) {
00154 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00155 Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00156
00157 if (babInfo)
00158 babInfo -> setInfeasibleNode ();
00159 }
00160
00161 if (is_feasible && isProvenOptimal ()) {
00162
00163 CouNumber obj = getObjValue ();
00164 const CouNumber *solution = getColSolution ();
00165
00166 if (getNumIntegers () > 0) {
00167
00168 int
00169 norig = p -> nOrigVars () - p -> nDefVars (),
00170 nvars = p -> nVars ();
00171
00172 bool fractional = false;
00173
00174
00175
00176
00177 for (int i=0; i<norig; i++)
00178 if ((p -> Var (i) -> Multiplicity () > 0) &&
00179 p -> Var (i) -> isDefinedInteger () &&
00180 (!::isInteger (solution [i]))) {
00181 fractional = true;
00182 break;
00183 }
00184
00185 if (fractional) {
00186
00187 double
00188 *lbSave = new double [norig],
00189 *ubSave = new double [norig],
00190
00191 *lbCur = new double [nvars],
00192 *ubCur = new double [nvars],
00193
00194 *Y = new double [nvars];
00195
00196 CoinCopyN (getColLower (), norig, lbSave);
00197 CoinCopyN (getColUpper (), norig, ubSave);
00198
00199 CoinFillN (Y, nvars, 0.);
00200 CoinFillN (lbCur, nvars, -COUENNE_INFINITY);
00201 CoinFillN (ubCur, nvars, COUENNE_INFINITY);
00202
00203 CoinCopyN (getColLower (), norig, lbCur);
00204 CoinCopyN (getColUpper (), norig, ubCur);
00205
00206 if (p -> getIntegerCandidate (solution, Y, lbCur, ubCur) >= 0) {
00207
00208 for (int i = getNumCols (); i--;) {
00209
00210 if (lbCur [i] > ubCur [i]) {
00211 double swap = lbCur [i];
00212 lbCur [i] = ubCur [i];
00213 ubCur [i] = swap;
00214 }
00215
00216 if (Y [i] < lbCur [i]) Y [i] = lbCur [i];
00217 else if (Y [i] > ubCur [i]) Y [i] = ubCur [i];
00218 }
00219
00220 for (int i=0; i<norig; i++)
00221 if ((p -> Var (i) -> Multiplicity () > 0) &&
00222 p -> Var (i) -> isDefinedInteger ()) {
00223 setColLower (i, lbCur [i]);
00224 setColUpper (i, ubCur [i]);
00225 }
00226
00227 setColSolution (Y);
00228
00229 try {
00230 options () -> SetNumericValue ("max_cpu_time", CoinMax (0., p -> getMaxCpuTime () - CoinCpuTime ()));
00231 resolve ();
00232 }
00233 catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00234 }
00235
00236
00237
00238 obj = getObjValue ();
00239 solution = getColSolution ();
00240
00241
00242 for (int i=0; i<norig; i++)
00243 if ((p -> Var (i) -> Multiplicity () > 0) &&
00244 p -> Var (i) -> isDefinedInteger ()) {
00245 setColLower (i, lbSave [i]);
00246 setColUpper (i, ubSave [i]);
00247 }
00248 }
00249
00250 delete [] Y;
00251 delete [] lbSave;
00252 delete [] ubSave;
00253 delete [] lbCur;
00254 delete [] ubCur;
00255 }
00256 }
00257
00258
00259 if (isProvenOptimal () &&
00260 (obj < p -> getCutOff ()) &&
00261
00262 #ifdef FM_CHECKNLP2
00263 (p->checkNLP2(solution, 0, false, true, false, p->getFeasTol())) &&
00264 (p->getRecordBestSol()->getModSolVal() < p->getCutOff())
00265 #else
00266 p -> checkNLP (solution, obj, true) &&
00267 (obj < p -> getCutOff ())
00268 #endif
00269 ) {
00270
00271
00272 have_nlp_solution_ = true;
00273
00274
00275
00276 #ifdef FM_CHECKNLP2
00277 obj = p->getRecordBestSol()->getModSolVal();
00278 #endif
00279
00280 p -> setCutOff (obj, solution);
00281
00282 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00283 Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00284
00285 if (babInfo) {
00286
00287 #ifdef FM_CHECKNLP2
00288 babInfo -> setNlpSolution (p->getRecordBestSol()->modSol,
00289 getNumCols(), obj);
00290 #else
00291 babInfo -> setNlpSolution (solution, getNumCols (), obj);
00292 #endif
00293 babInfo -> setHasNlpSolution (true);
00294 }
00295
00296 #ifdef FM_TRACE_OPTSOL
00297 #ifdef FM_CHECKNLP2
00298 p->getRecordBestSol()->update();
00299 #else
00300 p->getRecordBestSol()->update(solution, getNumCols(),
00301 obj, p->getFeasTol());
00302 #endif
00303 #endif
00304
00305 }
00306 }
00307 }
00308
00309 if (!is_feasible)
00310 return;
00311
00312 int
00313 numcols = p -> nOrigVars (),
00314 numcolsconv = p -> nVars ();
00315
00316 const double
00317 *lb = p -> Lb (),
00318 *ub = p -> Ub ();
00319
00320
00321 for (int i=0; i<numcols; i++)
00322 if (p -> Var (i) -> Multiplicity () > 0) si.addCol (0, NULL,NULL, lb [i], ub [i], 0);
00323 else si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00324 for (int i=numcols; i<numcolsconv; i++) si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00325
00326
00327 OsiCuts cs;
00328 couenneCg.generateCuts (si, cs);
00329
00330
00331 CouNumber * colLower = new CouNumber [numcolsconv];
00332 CouNumber * colUpper = new CouNumber [numcolsconv];
00333
00334 CouNumber *ll = p -> Lb ();
00335 CouNumber *uu = p -> Ub ();
00336
00337
00338 for (int i = numcolsconv; i--;)
00339 if (p -> Var (i) -> Multiplicity () > 0) {
00340 colLower [i] = (ll [i] > - COUENNE_INFINITY) ? ll [i] : -COIN_DBL_MAX;
00341 colUpper [i] = (uu [i] < COUENNE_INFINITY) ? uu [i] : COIN_DBL_MAX;
00342 } else {
00343 colLower [i] = -COIN_DBL_MAX;
00344 colUpper [i] = COIN_DBL_MAX;
00345 }
00346
00347 int numrowsconv = cs.sizeRowCuts ();
00348
00349
00350 CoinBigIndex * start = new CoinBigIndex [numrowsconv + 1];
00351
00352 int * length = new int [numrowsconv];
00353 double * rowLower = new double [numrowsconv];
00354 double * rowUpper = new double [numrowsconv];
00355
00356 start[0] = 0;
00357 int nnz = 0;
00358
00359 for(int i = 0 ; i < numrowsconv ; i++)
00360 {
00361 OsiRowCut * cut = cs.rowCutPtr (i);
00362
00363 const CoinPackedVector &v = cut->row();
00364 start[i+1] = start[i] + v.getNumElements();
00365 nnz += v.getNumElements();
00366 length[i] = v.getNumElements();
00367
00368 rowLower[i] = cut->lb();
00369 rowUpper[i] = cut->ub();
00370 }
00371
00372 assert (nnz == start [numrowsconv]);
00373
00374 int * ind = new int[start[numrowsconv]];
00375 double * elem = new double[start[numrowsconv]];
00376 for(int i = 0 ; i < numrowsconv ; i++) {
00377
00378 OsiRowCut * cut = cs.rowCutPtr (i);
00379
00380 const CoinPackedVector &v = cut->row();
00381
00382 if(v.getNumElements() != length[i])
00383 std::cout<<"Empty row"<<std::endl;
00384
00385 CoinCopyN (v.getIndices(), length[i], ind + start[i]);
00386 CoinCopyN (v.getElements(), length[i], elem + start[i]);
00387 }
00388
00389
00390 CoinPackedMatrix A;
00391 A.assignMatrix(false, numcolsconv, numrowsconv,
00392 start[numrowsconv], elem, ind,
00393 start, length);
00394 if(A.getNumCols() != numcolsconv || A.getNumRows() != numrowsconv){
00395 std::cout<<"Error in row number"<<std::endl;
00396 }
00397 assert(A.getNumElements() == nnz);
00398
00399 double * obj = new double[numcolsconv];
00400 CoinFillN(obj,numcolsconv,0.);
00401
00402
00403 if (p -> nObjs () > 0)
00404 p -> fillObjCoeff (obj);
00405
00406
00407 si.loadProblem (A, colLower, colUpper, obj, rowLower, rowUpper);
00408
00409 delete [] rowLower;
00410 delete [] rowUpper;
00411 delete [] colLower;
00412 delete [] colUpper;
00413 delete [] obj;
00414
00415 for (int i=0; i<numcolsconv; i++)
00416 if ((p -> Var (i) -> Multiplicity () > 0) &&
00417 (p -> Var (i) -> isDefinedInteger ()))
00418 si.setInteger (i);
00419
00420
00421
00422 app_ -> enableWarmStart();
00423
00424
00425 if (problem () -> x_sol ()) {
00426 setColSolution (problem () -> x_sol ());
00427 setRowPrice (problem () -> duals_sol ());
00428 }
00429 }
00430
00431
00433 void CouenneInterface::setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options){
00434 Options->SetStringValue("bonmin.algorithm", "B-Couenne", true, true);
00435 Options->SetIntegerValue("bonmin.filmint_ecp_cuts", 1, true, true);
00436 }
00437