00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CouenneCutGenerator.hpp"
00014
00015 #include "BonTNLPSolver.hpp"
00016 #include "BonNlpHeuristic.hpp"
00017 #include "CoinHelperFunctions.hpp"
00018 #include "BonCouenneInfo.hpp"
00019
00020 #include "CouenneProblem.hpp"
00021 #include "CouenneExprVar.hpp"
00022 #include "CouenneProblemElem.hpp"
00023
00024 using namespace Ipopt;
00025 using namespace Couenne;
00026
00027 namespace Bonmin {
00028 class OsiTMINLPInterface;
00029 class BabInfo;
00030 class TNLPSolver;
00031 }
00032
00033 #define MAX_ABT_ITER 4 // max # aggressive BT iterations
00034 #define THRES_ABT_IMPROVED 0 // only continue ABT if at least these bounds have improved
00035 #define THRES_ABT_ORIG 100 // only do ABT on auxiliaries if they are less originals than this
00036
00037 static double distanceToBound (register int n,
00038 register const double* xOrig,
00039 register const double* lower,
00040 register const double* upper,
00041 register double cutoff_distance) {
00042
00043 register double Xdist = 0.;
00044
00045 for (; n--; ++upper, ++xOrig) {
00046
00047 register CouNumber diff = *lower++ - *xOrig;
00048
00049 if ( diff > 0.) {if ((Xdist += diff) > cutoff_distance) break;}
00050 else if ((diff = *xOrig - *upper) > 0.) {if ((Xdist += diff) > cutoff_distance) break;}
00051 }
00052
00053 return Xdist;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 bool CouenneProblem::aggressiveBT (Bonmin::OsiTMINLPInterface *nlp,
00063 t_chg_bounds *chg_bds,
00064 const CglTreeInfo &info,
00065 Bonmin::BabInfo * babInfo) const {
00066
00067 if (info.level <= 0 && !(info.inTree)) {
00068 jnlst_ -> Printf (J_ERROR, J_COUENNE, "Probing: ");
00069 fflush (stdout);
00070 }
00071
00072 CouenneInfo* couInfo =
00073 dynamic_cast <CouenneInfo *> (babInfo);
00074
00075 int ncols = nVars ();
00076 bool retval = false;
00077
00078 CouNumber
00079 *olb = CoinCopyOfArray (Lb (), ncols),
00080 *oub = CoinCopyOfArray (Ub (), ncols);
00081
00082
00083
00084 SmartPtr<const CouenneInfo::NlpSolution> closestSol;
00085 double dist = 1.e50;
00086
00087 if (couInfo) {
00088
00089 const std::list<SmartPtr<const CouenneInfo::NlpSolution> >& solList =
00090 couInfo->NlpSolutions();
00091
00092 for (std::list<SmartPtr<const CouenneInfo::NlpSolution> >::const_iterator
00093 i = solList.begin();
00094 i != solList.end(); ++i) {
00095
00096 assert (nOrigVars_ - ndefined_ == (*i)->nVars());
00097
00098 const double thisDist = distanceToBound (nOrigVars_ - ndefined_, (*i)->solution(), olb, oub, dist);
00099
00100 if (thisDist < dist) {
00101 closestSol = *i;
00102 dist = thisDist;
00103 }
00104 }
00105 }
00106
00107 jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, "best dist = %e\n", dist);
00108
00109 bool haveNLPsol = false;
00110
00111
00112 if (dist > 0.1) {
00113
00114
00115
00116 int nvars = nVars ();
00117
00118 double *lower = new double [nvars];
00119 double *upper = new double [nvars];
00120
00121 CoinFillN (lower, nvars, -COUENNE_INFINITY);
00122 CoinFillN (upper, nvars, COUENNE_INFINITY);
00123
00124 CoinCopyN (nlp -> getColLower (), nOrigVars_ - ndefined_, lower);
00125 CoinCopyN (nlp -> getColUpper (), nOrigVars_ - ndefined_, upper);
00126
00127 double *Y = new double [nvars];
00128
00129 CoinZeroN (Y, nvars);
00130 CoinCopyN (X (), nOrigVars_ - ndefined_, Y);
00131
00132 if (getIntegerCandidate (nlp -> getColSolution (), Y, lower, upper) < 0) {
00133
00134 jnlst_ -> Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING, "TODO: find NLP point in ABT failed\n");
00135 retval = true;
00136
00137 } else {
00138
00140
00141 nlp -> setColLower (lower);
00142 nlp -> setColUpper (upper);
00143 nlp -> setColSolution (Y);
00144
00145 try {
00146
00147 nlp -> options () -> SetNumericValue ("max_cpu_time", CoinMax (0., getMaxCpuTime () - CoinCpuTime ()));
00148 nlp -> initialSolve ();
00149 }
00150
00151 catch (Bonmin::TNLPSolver::UnsolvedError *E) {}
00152
00153 delete [] Y;
00154 delete [] lower;
00155 delete [] upper;
00156
00157 if (nlp -> isProvenOptimal ()) {
00158
00159 if (couInfo) {
00160 closestSol = new CouenneInfo::NlpSolution
00161 (nOrigVars_ - ndefined_, nlp->getColSolution(), nlp->getObjValue());
00162 couInfo->addSolution(closestSol);
00163 dist = 0.;
00164 haveNLPsol = true;
00165 }
00166 }
00167 else {
00168 jnlst_ -> Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING, "TODO: NLP solve in ABT failed\n");
00169 retval = true;
00170 }
00171 }
00172 }
00173
00174 int nTotImproved = 0;
00175
00176
00177
00178
00179
00180 {
00181 retval = true;
00182
00183
00184
00185
00186
00187 double *X = NULL;
00188
00189 if (haveNLPsol) {
00190
00191 X = new double [ncols];
00192 CoinZeroN (X, nVars ());
00193 CoinCopyN (closestSol -> solution(), nOrigVars_ - ndefined_, X);
00194 getAuxs (X);
00195 } else X = domain () -> x ();
00196
00197
00198 t_chg_bounds *f_chg = new t_chg_bounds [ncols];
00199
00200 if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
00201
00202 int objind = Obj (0) -> Body () -> Index ();
00203 for (int i=0; i<nOrigVars_ - ndefined_; i++)
00204 Jnlst()->Printf(J_MOREVECTOR, J_BOUNDTIGHTENING,
00205 " %2d %+20g [%+20g %+20g]\n",
00206 i, X [i], Lb (i), Ub (i));
00207 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00208 "-------------\nAggressive BT. Current bound = %g, cutoff = %g, %d vars\n",
00209 Lb (objind), getCutOff (), ncols);
00210 }
00211
00212 int improved, second, iter = 0;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 bool maxTimeReached = false;
00223
00224 do {
00225
00226 improved = 0;
00227
00228
00229 for (int i=0; i<ncols; i++) {
00230
00231 if (CoinCpuTime () > maxCpuTime_) {
00232 maxTimeReached = true;
00233 break;
00234 }
00235
00236 int index = evalOrder (i);
00237
00238 if ((Var (index) -> Multiplicity () <= 0) ||
00239 (fabs (Lb (index) - Ub (index)) < COUENNE_EPS) ||
00240 ((nOrigVars_ >= THRES_ABT_ORIG) &&
00241 (index >= nOrigVars_)))
00242 continue;
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 {
00255
00256
00257
00258 improved = 0;
00259
00260 if ((variables_ [index] -> sign () != expression::AUX_GEQ) &&
00261 (X [index] >= Lb (index) + COUENNE_EPS)) {
00262
00263 Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00264 "------------- tighten left %d-th = x%d @%g [%g,%g]\n",
00265 i, index, X [index], olb [index], oub [index]);
00266
00267
00268 if ((improved = fake_tighten (0, index, X, olb, oub, chg_bds, f_chg)) < 0) {
00269
00270 retval = false;
00271 break;
00272 }
00273 }
00274
00275 second = 0;
00276
00277 if (retval && (variables_ [index] -> sign () != expression::AUX_LEQ) &&
00278 (X [index] <= Ub (index) - COUENNE_EPS)) {
00279
00280 Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00281 "------------- tighten right %d-th = x%d @%g [%g,%g]\n",
00282 i, index, X [index], olb [index], oub [index]);
00283
00284
00285 if ((second = fake_tighten (1, index, X, olb, oub, chg_bds, f_chg) < 0)) {
00286 retval = false;
00287 break;
00288 }
00289 }
00290
00291 improved += second;
00292 nTotImproved += improved;
00293 }
00294 }
00295
00296 } while (!maxTimeReached && retval && (improved > THRES_ABT_IMPROVED) && (iter++ < MAX_ABT_ITER));
00297
00298
00299 CoinCopyN (olb, ncols, Lb ());
00300 CoinCopyN (oub, ncols, Ub ());
00301
00302 if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
00303
00304 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,"------------------\n");
00305
00306 if (!retval) Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00307 "Couenne infeasible node from aggressive BT\n");
00308
00309 int objind = Obj (0) -> Body () -> Index ();
00310
00311 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00312 "-------------\ndone Aggressive BT. Current bound = %g, cutoff = %g, %d vars\n",
00313 Lb (objind), getCutOff (), ncols);
00314
00315 if (Jnlst()->ProduceOutput(J_DETAILED, J_BOUNDTIGHTENING))
00316 for (int i=0; i<nOrigVars_; i++)
00317 printf(" x%02d [%+20g %+20g] | %+20g\n",
00318 i, Lb (i), Ub (i), X [i]);
00319
00320 if (Jnlst()->ProduceOutput(J_MOREDETAILED, J_BOUNDTIGHTENING))
00321 for (int i=nOrigVars_; i<ncols; i++)
00322 printf (" w%02d [%+20g %+20g] | %+20g\n", i, Lb (i), Ub (i), X [i]);
00323 }
00324
00325 if (haveNLPsol)
00326 delete [] X;
00327 delete [] f_chg;
00328 }
00329
00330
00331
00332
00333 delete [] olb;
00334 delete [] oub;
00335
00336 if (info.level <= 0 && !(info.inTree)) {
00337 if (!retval) jnlst_ -> Printf (J_ERROR, J_COUENNE, "infeasible\n");
00338 else jnlst_ -> Printf (J_ERROR, J_COUENNE, "%d improved bounds\n", nTotImproved);
00339 }
00340
00341 return retval;
00342
00343 }