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