00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012 #include "CouenneProblem.hpp"
00013 #include "CouenneExprVar.hpp"
00014 #include "CouenneProblemElem.hpp"
00015 #include "CouenneBTPerfIndicator.hpp"
00016 #include "BonBabInfos.hpp"
00017 #include "BonCbc.hpp"
00018
00019
00020 #define THRES_IMPROVED 0
00021
00022 using namespace Couenne;
00023
00024
00025
00026 bool CouenneProblem::btCore (t_chg_bounds *chg_bds) const {
00027
00028 fbbtReachedIterLimit_ = false;
00029
00030 bool null_chg_bds = (NULL == chg_bds);
00031
00032 if (!chg_bds) {
00033
00034 chg_bds = new t_chg_bounds [nVars ()];
00035
00036 for (int i=0; i < nVars (); i++)
00037
00038 if (Var (i) -> Multiplicity () > 0) {
00039
00040 chg_bds [i].setLower (t_chg_bounds::CHANGED);
00041 chg_bds [i].setUpper (t_chg_bounds::CHANGED);
00042 }
00043 }
00044
00045
00046
00047 int ntightened = 0,
00048 nbwtightened = 0,
00049 niter = 0;
00050
00051 bool first = true;
00052
00053 installCutOff ();
00054
00055
00056 bool contains_optimum = false;
00057
00058 if (optimum_ != NULL) {
00059 contains_optimum = true;
00060 for (int i=0; i < nVars (); i++)
00061 if ((optimum_ [i] < Lb (i) * (1 - COUENNE_EPS) - COUENNE_EPS) ||
00062 (optimum_ [i] > Ub (i) * (1 + COUENNE_EPS) + COUENNE_EPS)) {
00063
00064
00065
00066
00067 contains_optimum = false;
00068 break;
00069 }
00070 }
00071
00072 if (max_fbbt_iter_)
00073
00074 do {
00075
00076 if (CoinCpuTime () > maxCpuTime_)
00077 break;
00078
00079
00080
00081
00082 ntightened = ((nbwtightened > 0) || first) ?
00083 tightenBounds (chg_bds) : 0;
00084
00085
00086
00087
00088
00089 nbwtightened = ((ntightened > 0) || ((ntightened==0) && first)) ? impliedBounds (chg_bds) : 0;
00090
00091 if (first)
00092 first = false;
00093
00094 if ((ntightened < 0) || (nbwtightened < 0)) {
00095 Jnlst () -> Printf (Ipopt::J_ITERSUMMARY, J_BOUNDTIGHTENING, "infeasible BT\n");
00096 if (null_chg_bds)
00097 delete [] chg_bds;
00098 return false;
00099 }
00100
00101
00102
00103
00104 if (contains_optimum) {
00105 for (int i=0; i<nVars (); i++)
00106 if ((optimum_[i] < Lb(i) - COUENNE_EPS * (1. + CoinMin (fabs(optimum_ [i]), fabs (Lb(i))))) ||
00107 (optimum_[i] > Ub(i) + COUENNE_EPS * (1. + CoinMin (fabs(optimum_ [i]), fabs (Ub(i)))))) {
00108 printf ("bound tightening CUTS optimum: x%d [%e,%e] val = %e, violation = %e\n",
00109 i, Lb (i), Ub (i), optimum_ [i],
00110 CoinMax (- optimum_ [i] + Lb (i),
00111 optimum_ [i] - Ub (i)));
00112 contains_optimum = false;
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 } while (((ntightened > 0) || (nbwtightened > 0)) &&
00134 (ntightened + nbwtightened > THRES_IMPROVED) &&
00135 ((max_fbbt_iter_ < 0) || (niter++ < max_fbbt_iter_)));
00136
00137 if (null_chg_bds)
00138 delete [] chg_bds;
00139
00140 fbbtReachedIterLimit_ = ((max_fbbt_iter_ > 0) && (niter >= max_fbbt_iter_));
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 for (int i = 0, j = nVars (); j--; i++)
00154 if (Var (i) -> Multiplicity () > 0) {
00155
00156
00157 if ((Lb (i) > Ub (i) + COUENNE_BOUND_PREC * (1 + CoinMin (fabs (Lb (i)), fabs (Ub (i))))) ||
00158 (Ub (i) < - MAX_BOUND) ||
00159 (Lb (i) > MAX_BOUND)) {
00160
00161 Jnlst () -> Printf (Ipopt::J_ITERSUMMARY, J_BOUNDTIGHTENING, "final test: infeasible BT\n");
00162 return false;
00163 }
00164
00165
00166 if (Lb (i) > Ub (i)) {
00167 CouNumber swap = Lb (i);
00168 Lb (i) = Ub (i);
00169 Ub (i) = swap;
00170 }
00171 }
00172
00173 return true;
00174 }
00175
00176
00179
00180 bool CouenneProblem::boundTightening (t_chg_bounds *chg_bds,
00181 const CglTreeInfo info,
00182 Bonmin::BabInfo * babInfo) const {
00183
00184 double startTime = CoinCpuTime ();
00185
00186 perfIndicator_ -> setOldBounds (Lb (), Ub ());
00187
00188
00189
00190
00191
00192
00193
00194
00195 Jnlst () -> Printf (Ipopt::J_ITERSUMMARY, J_BOUNDTIGHTENING,
00196 "Feasibility-based Bound Tightening\n");
00197
00198 int objInd = Obj (0) -> Body () -> Index ();
00199
00201
00202 if ((objInd >= 0) && babInfo && (babInfo -> babPtr ())) {
00203
00204 CouNumber UB = babInfo -> babPtr () -> model (). getObjValue(),
00205 LB = babInfo -> babPtr () -> model (). getBestPossibleObjValue (),
00206 primal0 = Ub (objInd),
00207 dual0 = Lb (objInd);
00208
00209
00210
00211
00212 if ((UB < COUENNE_INFINITY) &&
00213 (UB < primal0 - COUENNE_EPS)) {
00214
00215 Ub (objInd) = UB;
00216 chg_bds [objInd].setUpper(t_chg_bounds::CHANGED);
00217 }
00218
00219 if ((LB > - COUENNE_INFINITY) &&
00220 (LB > dual0 + COUENNE_EPS)) {
00221 Lb (objInd) = LB;
00222 chg_bds [objInd].setLower(t_chg_bounds::CHANGED);
00223 }
00224 }
00225
00226 bool retval = btCore (chg_bds);
00227
00228 perfIndicator_ -> update (Lb (), Ub (), info.level);
00229 perfIndicator_ -> addToTimer (CoinCpuTime () - startTime);
00230
00231 return retval;
00232
00233
00234
00235
00236 }
00237
00238
00240 int CouenneProblem::redCostBT (const OsiSolverInterface *psi,
00241 t_chg_bounds *chg_bds) const {
00242
00243 int
00244 nchanges = 0,
00245 objind = Obj (0) -> Body () -> Index ();
00246
00247 if (objind < 0)
00248 return 0;
00249
00250 CouNumber
00251 UB = getCutOff (),
00252 LB = Lb (objind);
00253
00255
00256 if ((LB > -COUENNE_INFINITY) &&
00257 (UB < COUENNE_INFINITY)) {
00258
00259 const double
00260 *X = psi -> getColSolution (),
00261 *L = psi -> getColLower (),
00262 *U = psi -> getColUpper (),
00263 *RC = psi -> getReducedCost ();
00264
00265 if (jnlst_ -> ProduceOutput (Ipopt::J_MATRIX, J_BOUNDTIGHTENING)) {
00266 printf ("REDUCED COST BT (LB=%g, UB=%g):\n", LB, UB);
00267 for (int i=0, j=0; i < nVars (); i++) {
00268 if (Var (i) -> Multiplicity () <= 0)
00269 continue;
00270 printf ("%3d %7e [%7e %7e] c %7e ", i, X [i], L [i], U [i], RC [i]);
00271 if (!(++j % 3))
00272 printf ("\n");
00273 }
00274 printf ("-----------\n");
00275 }
00276
00277 int ncols = psi -> getNumCols ();
00278
00279 for (int i=0; i<ncols; i++)
00280 if ((i != objind) &&
00281 (Var (i) -> Multiplicity () > 0)) {
00282
00283 CouNumber
00284 x = X [i],
00285 l = L [i],
00286 u = U [i],
00287 rc = RC [i];
00288
00289 #define CLOSE_TO_BOUNDS 1.e-15
00290
00291 if ((fabs (rc) < CLOSE_TO_BOUNDS) ||
00292 (fabs (l-u) < CLOSE_TO_BOUNDS))
00293 continue;
00294
00295 bool isInt = Var (i) -> isInteger ();
00296
00297 if ((rc >= 0.) &&
00298 (fabs (x-l) <= CLOSE_TO_BOUNDS)) {
00299
00300 if (LB + (u-l)*rc > UB) {
00301
00302 CouNumber newUb = l + (UB-LB) / rc;
00303 newUb = !isInt ? newUb : floor (newUb + COUENNE_EPS);
00304
00305 if (newUb < Ub (i)) {
00306
00307 Ub (i) = newUb;
00308
00309 nchanges++;
00310 chg_bds [i].setLower (t_chg_bounds::CHANGED);
00311 }
00312 }
00313
00314 } else if ((rc <= 0.) &&
00315 (fabs (x-u) <= CLOSE_TO_BOUNDS)) {
00316
00317 if (LB - (u-l) * rc > UB) {
00318
00319 CouNumber newLb = u + (UB-LB) / rc;
00320
00321 newLb = !isInt ? newLb : ceil (newLb - COUENNE_EPS);
00322
00323 if (newLb > Lb (i)) {
00324
00325 Lb (i) = newLb;
00326
00327 nchanges++;
00328 chg_bds [i].setUpper (t_chg_bounds::CHANGED);
00329 }
00330 }
00331 }
00332 }
00333
00334 if (jnlst_ -> ProduceOutput (Ipopt::J_MATRIX, J_BOUNDTIGHTENING)) {
00335 printf ("AFTER reduced cost bt:\n");
00336 for (int i=0, j=0; i < nVars (); ++i) {
00337 if (Var (i) -> Multiplicity () <= 0)
00338 continue;
00339 printf ("%3d [%7e %7e] ", i, Lb (i), Ub (i));
00340 if (!(++j % 4))
00341 printf ("\n");
00342 }
00343 printf ("-----------\n");
00344 }
00345 }
00346
00347 return nchanges;
00348 }