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 if (objind >= 0)
00208 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00209 "-------------\nAggressive BT. Current bound = %g, cutoff = %g, %d vars\n",
00210 Lb (objind), getCutOff (), ncols);
00211 }
00212
00213 int improved, second, iter = 0;
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 bool maxTimeReached = false;
00224
00225 do {
00226
00227 improved = 0;
00228
00229
00230 for (int i=0; i<ncols; i++) {
00231
00232 if (CoinCpuTime () > maxCpuTime_) {
00233 maxTimeReached = true;
00234 break;
00235 }
00236
00237 int index = evalOrder (i);
00238
00239 if ((Var (index) -> Multiplicity () <= 0) ||
00240 (fabs (Lb (index) - Ub (index)) < COUENNE_EPS) ||
00241 ((nOrigVars_ >= THRES_ABT_ORIG) &&
00242 (index >= nOrigVars_)))
00243 continue;
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 {
00256
00257
00258
00259 improved = 0;
00260
00261 if ((variables_ [index] -> sign () != expression::AUX_GEQ) &&
00262 (X [index] >= Lb (index) + COUENNE_EPS)) {
00263
00264 Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00265 "------------- tighten left %d-th = x%d @%g [%g,%g]\n",
00266 i, index, X [index], olb [index], oub [index]);
00267
00268
00269 if ((improved = fake_tighten (0, index, X, olb, oub, chg_bds, f_chg)) < 0) {
00270
00271 retval = false;
00272 break;
00273 }
00274 }
00275
00276 second = 0;
00277
00278 if (retval && (variables_ [index] -> sign () != expression::AUX_LEQ) &&
00279 (X [index] <= Ub (index) - COUENNE_EPS)) {
00280
00281 Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00282 "------------- tighten right %d-th = x%d @%g [%g,%g]\n",
00283 i, index, X [index], olb [index], oub [index]);
00284
00285
00286 if ((second = fake_tighten (1, index, X, olb, oub, chg_bds, f_chg) < 0)) {
00287 retval = false;
00288 break;
00289 }
00290 }
00291
00292 improved += second;
00293 nTotImproved += improved;
00294 }
00295 }
00296
00297 } while (!maxTimeReached && retval && (improved > THRES_ABT_IMPROVED) && (iter++ < MAX_ABT_ITER));
00298
00299
00300 CoinCopyN (olb, ncols, Lb ());
00301 CoinCopyN (oub, ncols, Ub ());
00302
00303 if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
00304
00305 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,"------------------\n");
00306
00307 if (!retval) Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00308 "Couenne infeasible node from aggressive BT\n");
00309
00310 int objind = Obj (0) -> Body () -> Index ();
00311
00312 if (objind >= 0)
00313 Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00314 "-------------\ndone Aggressive BT. Current bound = %g, cutoff = %g, %d vars\n",
00315 Lb (objind), getCutOff (), ncols);
00316
00317 if (Jnlst()->ProduceOutput(J_DETAILED, J_BOUNDTIGHTENING))
00318 for (int i=0; i<nOrigVars_; i++)
00319 printf(" x%02d [%+20g %+20g] | %+20g\n",
00320 i, Lb (i), Ub (i), X [i]);
00321
00322 if (Jnlst()->ProduceOutput(J_MOREDETAILED, J_BOUNDTIGHTENING))
00323 for (int i=nOrigVars_; i<ncols; i++)
00324 printf (" w%02d [%+20g %+20g] | %+20g\n", i, Lb (i), Ub (i), X [i]);
00325 }
00326
00327 if (haveNLPsol)
00328 delete [] X;
00329 delete [] f_chg;
00330 }
00331
00332
00333
00334
00335 delete [] olb;
00336 delete [] oub;
00337
00338 if (info.level <= 0 && !(info.inTree)) {
00339 if (!retval) jnlst_ -> Printf (J_ERROR, J_COUENNE, "infeasible\n");
00340 else jnlst_ -> Printf (J_ERROR, J_COUENNE, "%d improved bounds\n", nTotImproved);
00341 }
00342
00343 return retval;
00344
00345 }