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
00134 double
00135 lower = nlb [i],
00136 upper = nub [i];
00137
00138 if (lower > upper) CoinSwap (lower, upper);
00139 if (p -> Lb (i) > p -> Ub (i)) CoinSwap (p -> Lb (i), p -> Ub (i));
00140
00141 if (lower < p -> Lb (i) - COUENNE_EPS) setColLower (i, CoinMin(nub[i], p -> Lb (i)));
00142 if (upper > p -> Ub (i) + COUENNE_EPS) setColUpper (i, CoinMax(nlb[i], p -> Ub (i)));
00143
00144 } else {
00145
00146 setColLower (i, -COIN_DBL_MAX);
00147 setColUpper (i, COIN_DBL_MAX);
00148 }
00149 }
00150
00151 if (is_feasible) {
00152 try {
00153 options () -> SetNumericValue ("max_cpu_time", CoinMax (0., (p -> getMaxCpuTime () - CoinCpuTime ()) / 2));
00154 initialSolve ();
00155 }
00156 catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00157
00158
00159 }
00160 }
00161
00162 if (!is_feasible) {
00163 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00164 Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00165
00166 if (babInfo)
00167 babInfo -> setInfeasibleNode ();
00168 }
00169
00170 if (is_feasible && isProvenOptimal ()) {
00171
00172 CouNumber obj = getObjValue ();
00173 const CouNumber *solution = getColSolution ();
00174
00175 if (getNumIntegers () > 0) {
00176
00177 int
00178 norig = p -> nOrigVars () - p -> nDefVars (),
00179 nvars = p -> nVars ();
00180
00181 bool fractional = false;
00182
00183
00184
00185
00186 for (int i=0; i<norig; i++)
00187 if ((p -> Var (i) -> Multiplicity () > 0) &&
00188 p -> Var (i) -> isDefinedInteger () &&
00189 (!::isInteger (solution [i]))) {
00190 fractional = true;
00191 break;
00192 }
00193
00194 if (fractional) {
00195
00196 double
00197 *lbSave = new double [norig],
00198 *ubSave = new double [norig],
00199
00200 *lbCur = new double [nvars],
00201 *ubCur = new double [nvars],
00202
00203 *Y = new double [nvars];
00204
00205 CoinCopyN (getColLower (), norig, lbSave);
00206 CoinCopyN (getColUpper (), norig, ubSave);
00207
00208 CoinFillN (Y, nvars, 0.);
00209 CoinFillN (lbCur, nvars, -COUENNE_INFINITY);
00210 CoinFillN (ubCur, nvars, COUENNE_INFINITY);
00211
00212 CoinCopyN (getColLower (), norig, lbCur);
00213 CoinCopyN (getColUpper (), norig, ubCur);
00214
00215 if (p -> getIntegerCandidate (solution, Y, lbCur, ubCur) >= 0) {
00216
00217 for (int i = getNumCols (); i--;) {
00218
00219 if (lbCur [i] > ubCur [i])
00220 CoinSwap (lbCur [i], ubCur [i]);
00221
00222 if (Y [i] < lbCur [i]) Y [i] = lbCur [i];
00223 else if (Y [i] > ubCur [i]) Y [i] = ubCur [i];
00224 }
00225
00226 for (int i=0; i<norig; i++)
00227 if ((p -> Var (i) -> Multiplicity () > 0) &&
00228 p -> Var (i) -> isDefinedInteger ()) {
00229
00230 setColLower (i, lbCur [i]);
00231 setColUpper (i, ubCur [i]);
00232 }
00233
00234 setColSolution (Y);
00235
00236 try {
00237 options () -> SetNumericValue ("max_cpu_time", CoinMax (0., p -> getMaxCpuTime () - CoinCpuTime ()));
00238 resolve ();
00239 }
00240 catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00241 }
00242
00243
00244
00245 obj = getObjValue ();
00246 solution = getColSolution ();
00247
00248
00249 for (int i=0; i<norig; i++)
00250 if ((p -> Var (i) -> Multiplicity () > 0) &&
00251 p -> Var (i) -> isDefinedInteger ()) {
00252
00253 if (lbSave [i] > ubSave [i])
00254 CoinSwap (lbSave [i], ubSave [i]);
00255
00256 setColLower (i, lbSave [i]);
00257 setColUpper (i, ubSave [i]);
00258 }
00259 }
00260
00261 delete [] Y;
00262 delete [] lbSave;
00263 delete [] ubSave;
00264 delete [] lbCur;
00265 delete [] ubCur;
00266 }
00267 }
00268
00269
00270 if (isProvenOptimal () &&
00271 (obj < p -> getCutOff ()) &&
00272
00273 #ifdef FM_CHECKNLP2
00274 (p->checkNLP2(solution, 0, false, true, false, p->getFeasTol())) &&
00275 (p->getRecordBestSol()->getModSolVal() < p->getCutOff())
00276 #else
00277 p -> checkNLP (solution, obj, true) &&
00278 (obj < p -> getCutOff ())
00279 #endif
00280 ) {
00281
00282
00283 have_nlp_solution_ = true;
00284
00285
00286
00287 #ifdef FM_CHECKNLP2
00288 obj = p->getRecordBestSol()->getModSolVal();
00289 #endif
00290
00291 p -> setCutOff (obj, solution);
00292
00293 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00294 Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00295
00296 if (babInfo) {
00297
00298 #ifdef FM_CHECKNLP2
00299 babInfo -> setNlpSolution (p->getRecordBestSol()->modSol,
00300 getNumCols(), obj);
00301 #else
00302 babInfo -> setNlpSolution (solution, getNumCols (), obj);
00303 #endif
00304 babInfo -> setHasNlpSolution (true);
00305 }
00306
00307 #ifdef FM_TRACE_OPTSOL
00308 #ifdef FM_CHECKNLP2
00309 p->getRecordBestSol()->update();
00310 #else
00311 p->getRecordBestSol()->update(solution, getNumCols(),
00312 obj, p->getFeasTol());
00313 #endif
00314 #endif
00315
00316 }
00317 }
00318 }
00319
00320 if (!is_feasible)
00321 return;
00322
00323 int
00324 numcols = p -> nOrigVars (),
00325 numcolsconv = p -> nVars ();
00326
00327 const double
00328 *lb = p -> Lb (),
00329 *ub = p -> Ub ();
00330
00331
00332 for (int i=0; i<numcols; i++)
00333 if (p -> Var (i) -> Multiplicity () > 0) si.addCol (0, NULL,NULL, lb [i], ub [i], 0);
00334 else si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00335 for (int i=numcols; i<numcolsconv; i++) si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00336
00337
00338 OsiCuts cs;
00339 couenneCg.generateCuts (si, cs);
00340
00341
00342 CouNumber * colLower = new CouNumber [numcolsconv];
00343 CouNumber * colUpper = new CouNumber [numcolsconv];
00344
00345 CouNumber *ll = p -> Lb ();
00346 CouNumber *uu = p -> Ub ();
00347
00348
00349 for (int i = numcolsconv; i--;)
00350 if (p -> Var (i) -> Multiplicity () > 0) {
00351 colLower [i] = (ll [i] > - COUENNE_INFINITY) ? ll [i] : -COIN_DBL_MAX;
00352 colUpper [i] = (uu [i] < COUENNE_INFINITY) ? uu [i] : COIN_DBL_MAX;
00353 } else {
00354 colLower [i] = -COIN_DBL_MAX;
00355 colUpper [i] = COIN_DBL_MAX;
00356 }
00357
00358 int numrowsconv = cs.sizeRowCuts ();
00359
00360
00361 CoinBigIndex * start = new CoinBigIndex [numrowsconv + 1];
00362
00363 int * length = new int [numrowsconv];
00364 double * rowLower = new double [numrowsconv];
00365 double * rowUpper = new double [numrowsconv];
00366
00367 start[0] = 0;
00368 int nnz = 0;
00369
00370 for(int i = 0 ; i < numrowsconv ; i++)
00371 {
00372 OsiRowCut * cut = cs.rowCutPtr (i);
00373
00374 const CoinPackedVector &v = cut->row();
00375 start[i+1] = start[i] + v.getNumElements();
00376 nnz += v.getNumElements();
00377 length[i] = v.getNumElements();
00378
00379 rowLower[i] = cut->lb();
00380 rowUpper[i] = cut->ub();
00381 }
00382
00383 assert (nnz == start [numrowsconv]);
00384
00385 int * ind = new int[start[numrowsconv]];
00386 double * elem = new double[start[numrowsconv]];
00387 for(int i = 0 ; i < numrowsconv ; i++) {
00388
00389 OsiRowCut * cut = cs.rowCutPtr (i);
00390
00391 const CoinPackedVector &v = cut->row();
00392
00393 if(v.getNumElements() != length[i])
00394 std::cout<<"Empty row"<<std::endl;
00395
00396 CoinCopyN (v.getIndices(), length[i], ind + start[i]);
00397 CoinCopyN (v.getElements(), length[i], elem + start[i]);
00398 }
00399
00400
00401 CoinPackedMatrix A;
00402 A.assignMatrix(false, numcolsconv, numrowsconv,
00403 start[numrowsconv], elem, ind,
00404 start, length);
00405 if(A.getNumCols() != numcolsconv || A.getNumRows() != numrowsconv){
00406 std::cout<<"Error in row number"<<std::endl;
00407 }
00408 assert(A.getNumElements() == nnz);
00409
00410 double * obj = new double[numcolsconv];
00411 CoinFillN(obj,numcolsconv,0.);
00412
00413
00414 if (p -> nObjs () > 0)
00415 p -> fillObjCoeff (obj);
00416
00417
00418 si.loadProblem (A, colLower, colUpper, obj, rowLower, rowUpper);
00419
00420 delete [] rowLower;
00421 delete [] rowUpper;
00422 delete [] colLower;
00423 delete [] colUpper;
00424 delete [] obj;
00425
00426 for (int i=0; i<numcolsconv; i++)
00427 if ((p -> Var (i) -> Multiplicity () > 0) &&
00428 (p -> Var (i) -> isDefinedInteger ()))
00429 si.setInteger (i);
00430
00431
00432
00433 app_ -> enableWarmStart();
00434
00435
00436 if (problem () -> x_sol ()) {
00437 setColSolution (problem () -> x_sol ());
00438 setRowPrice (problem () -> duals_sol ());
00439 }
00440 }
00441
00442
00444 void CouenneInterface::setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options){
00445 Options->SetStringValue("bonmin.algorithm", "B-Couenne", true, true);
00446 Options->SetIntegerValue("bonmin.filmint_ecp_cuts", 1, true, true);
00447 }
00448