00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CoinHelperFunctions.hpp"
00012
00013 #include "BonBabSetupBase.hpp"
00014
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneVarObject.hpp"
00017 #include "CouenneBranchingObject.hpp"
00018 #include "CouenneComplObject.hpp"
00019 #include "CouenneProblemElem.hpp"
00020
00021 using namespace Ipopt;
00022 using namespace Couenne;
00023
00025 CouenneVarObject::CouenneVarObject (CouenneCutGenerator *c,
00026 CouenneProblem *p,
00027 exprVar *ref,
00028 Bonmin::BabSetupBase *base,
00029 JnlstPtr jnlst,
00030 int varSelection):
00031
00032
00033
00034 CouenneObject (c, p, ref, base, jnlst),
00035 varSelection_ (varSelection) {
00036
00037 if (jnlst_ -> ProduceOutput (J_SUMMARY, J_BRANCHING)) {
00038 printf ("created Variable Object: ");
00039 reference_ -> print ();
00040 printf (" with %s strategy [clamp=%g, alpha=%g]\n",
00041 (strategy_ == LP_CLAMPED) ? "lp-clamped" :
00042 (strategy_ == LP_CENTRAL) ? "lp-central" :
00043 (strategy_ == BALANCED) ? "balanced" :
00044 (strategy_ == MIN_AREA) ? "min-area" :
00045 (strategy_ == MID_INTERVAL) ? "mid-point" :
00046 (strategy_ == NO_BRANCH) ? "no-branching (null infeasibility)" :
00047 "no strategy",
00048 lp_clamp_, alpha_);
00049 }
00050 }
00051
00052
00054 OsiBranchingObject *CouenneVarObject::createBranch (OsiSolverInterface *si,
00055 const OsiBranchingInformation *info,
00056 int way) const {
00057
00058
00059
00060 problem_ -> domain () -> push
00061 (problem_ -> nVars (),
00062 info -> solution_,
00063 info -> lower_,
00064 info -> upper_, false);
00065
00066 OsiBranchingObject *obj = NULL;
00067
00068
00069
00070
00071
00072
00073 if ((varSelection_ == Bonmin::BabSetupBase::OSI_SIMPLE) &&
00074 ((strategy_ == CouenneObject::LP_CLAMPED) ||
00075 (strategy_ == CouenneObject::LP_CENTRAL) ||
00076 (strategy_ == CouenneObject::MID_INTERVAL))) {
00077
00078 int indVar = reference_ -> Index ();
00079
00080 CouNumber
00081 brpt = info -> solution_ [indVar],
00082 l = info -> lower_ [indVar],
00083 u = info -> upper_ [indVar];
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 #define LARGE_VALUE 1e8
00094
00095 if ((l < - LARGE_VALUE) &&
00096 (u > LARGE_VALUE) &&
00097 (fabs (brpt) > LARGE_VALUE / 10))
00098 brpt = 0.;
00099
00100 if (l < - COUENNE_INFINITY) l = -1. - 2 * fabs (brpt);
00101 if (u > COUENNE_INFINITY) u = +1. + 2 * fabs (brpt);
00102
00103 CouNumber width = lp_clamp_ * (u-l);
00104
00105 switch (strategy_) {
00106
00107 case CouenneObject::LP_CLAMPED: brpt = CoinMax (l + width, CoinMin (brpt, u - width)); break;
00108 case CouenneObject::LP_CENTRAL: if ((brpt < l + width) ||
00109 (brpt > u - width)) brpt = .5 * (l+u); break;
00110 case CouenneObject::MID_INTERVAL: brpt = midInterval (brpt,
00111 info -> lower_ [indVar],
00112 info -> upper_ [indVar], info); break;
00113 default: assert (false);
00114 }
00115
00116 obj = new CouenneBranchingObject (si, this, jnlst_, cutGen_, problem_, reference_,
00117 TWO_LEFT, brpt, doFBBT_, doConvCuts_);
00118 } else {
00119
00120
00121
00122
00123
00124
00125
00126 int bestWay;
00127 const CouenneObject *criticalObject = NULL;
00128
00129 CouNumber bestPt = computeBranchingPoint (info, bestWay, criticalObject);
00130
00132
00133 int indVar = reference_ -> Index ();
00134
00135 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, ":::: creating branching on x_%d @%g [%g,%g]\n",
00136 indVar,
00137 info -> solution_ [indVar],
00138 info -> lower_ [indVar],
00139 info -> upper_ [indVar]);
00140
00141 obj = criticalObject ?
00142 criticalObject -> createBranch (si, info, way) :
00143 new CouenneBranchingObject (si, this, jnlst_, cutGen_, problem_, reference_,
00144 way, bestPt, doFBBT_, doConvCuts_);
00145 }
00146
00147 problem_ -> domain () -> pop ();
00148
00149 return obj;
00150 }
00151
00152
00154 CouNumber CouenneVarObject::computeBranchingPoint (const OsiBranchingInformation *info,
00155 int& bestWay,
00156 const CouenneObject *&criticalObject) const {
00157 criticalObject = NULL;
00158
00159 if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00160 printf ( "---------- computeBRPT for ");
00161 reference_ -> print ();
00162 printf (" [%g,%g]\n",
00163 info -> lower_ [reference_ -> Index ()],
00164 info -> upper_ [reference_ -> Index ()]);
00165 }
00166
00167 expression *brVar = NULL;
00168
00169 CouNumber
00170 brdistDn = 0.,
00171 brdistUp = 0.,
00172 bestPt = 0.,
00173 *brPts = NULL,
00174 *brDist = NULL,
00175 maxdist = - COIN_DBL_MAX;
00176
00177 bool chosen = false;
00178
00179 bestWay = TWO_LEFT;
00180
00181 int
00182 whichWay = TWO_LEFT,
00183 index = reference_ -> Index ();
00184
00185 std::set <int> deplist = problem_ -> Dependence () [index];
00186
00187 for (std::set <int>::iterator i = deplist.begin (); i != deplist.end (); ++i) {
00188
00189 const CouenneObject *obj = problem_ -> Objects () [*i];
00190
00191 CouNumber improv = 0.;
00192
00193 assert (obj -> Reference ());
00194
00195 if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00196 printf (" dependence: ");
00197 obj -> Reference () -> print ();
00198 if (reference_ -> Image ()) {printf (" := "); obj -> Reference () -> Image () -> print ();}
00199 printf ("\n");
00200 }
00201
00202 if (obj -> Reference ()) {
00203 if (obj -> Reference () -> Image ())
00204
00205 improv = obj -> Reference () -> Image ()
00206 -> selectBranch (obj, info,
00207 brVar, brPts, brDist, whichWay);
00208 else {
00209
00210 brVar = obj -> Reference ();
00211 brPts = (double *) realloc (brPts, sizeof (double));
00212 brDist = (double *) realloc (brDist, 2 * sizeof (double));
00213
00214 double point = info -> solution_ [obj -> Reference () -> Index ()];
00215
00216 *brPts = point;
00217 improv = 0.;
00218
00219 if (point > floor (point)) {improv = brDist [0] = point - floor (point);}
00220 if (point < ceil (point)) {improv = CoinMin (improv, brDist [1] = ceil (point) - point);}
00221
00222 point -= floor (point);
00223 whichWay = (point < 0.45) ? TWO_LEFT : (point > 0.55) ? TWO_RIGHT : TWO_RAND;
00224 }
00225 }
00226
00227 if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00228 printf (" --> Branching on ");
00229 if (brVar) {
00230 brVar -> print ();
00231 if (brPts)
00232 printf (" at %g, improv %g <%g>, indices = %d,%d\n",
00233 *brPts, improv, maxdist, index, brVar -> Index ());
00234 }
00235 }
00236
00237 if (brVar &&
00238 (brVar -> Index () == index) &&
00239 (fabs (improv) > maxdist) &&
00240 (fabs (*brPts) < COU_MAX_COEFF)) {
00241
00242 criticalObject = (problem_ -> Objects () [*i]);
00243
00244 brdistDn = brDist [0];
00245 brdistUp = brDist [1];
00246 chosen = true;
00247 bestPt = *brPts;
00248 maxdist = improv;
00249 bestWay = whichWay;
00250 }
00251 }
00252
00253
00254
00255
00256 if (!chosen) {
00257
00258 bestPt = info -> solution_ [index];
00259 brVar = reference_;
00260
00261 CouNumber
00262 l = info -> lower_ [index],
00263 u = info -> upper_ [index],
00264 width = lp_clamp_ * (u-l);
00265
00266 switch (strategy_) {
00267
00268 case CouenneObject::LP_CLAMPED:
00269 bestPt = CoinMax (l + width, CoinMin (bestPt, u - width));
00270 break;
00271
00272 case CouenneObject::LP_CENTRAL:
00273 if ((bestPt < l + width) || (bestPt > u - width))
00274 bestPt = (l+u)/2;
00275 break;
00276
00277 case CouenneObject::MID_INTERVAL:
00278
00279 default:
00280
00281 bestPt = midInterval (bestPt, l, u, info);
00282
00283 if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00284 if (CoinMin (fabs (bestPt - l), fabs (bestPt - u)) < 1e-3) {
00285 printf ("computed failsafe %g [%g,%g] for ", bestPt, l,u);
00286 reference_ -> print (); printf ("\n");
00287 }
00288 }
00289
00290 break;
00291 }
00292
00293 if ((l < - large_bound) &&
00294 (u > large_bound) &&
00295 (fabs (bestPt) > large_bound))
00296 bestPt = 0.;
00297
00298 brPts = (double *) realloc (brPts, sizeof (double));
00299 *brPts = bestPt;
00300
00301 if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00302 printf (" ::: failsafe: %g [%g,%g] for ",
00303 bestPt, info -> lower_ [index], info -> upper_ [index]);
00304 reference_ -> print ();
00305 printf ("\n");
00306 }
00307
00308 } else {
00309
00310 if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00311 if (CoinMin (fabs (bestPt - info -> lower_ [index]),
00312 fabs (bestPt - info -> upper_ [index])) < 1e-3) {
00313 printf (" computed %g [%g,%g] for ",
00314 bestPt, info -> lower_ [index], info -> upper_ [index]);
00315 reference_ -> print ();
00316 printf ("\n");
00317 }
00318 }
00319 }
00320
00321 if (pseudoMultType_ == PROJECTDIST) {
00322
00323 if (chosen) {
00324 downEstimate_ = brdistDn;
00325 upEstimate_ = brdistUp;
00326 }
00327 else downEstimate_ = upEstimate_ = 1.;
00328 }
00329
00330 if (brPts) free (brPts);
00331 if (brDist) free (brDist);
00332
00333 return bestPt;
00334 }
00335
00336
00337 #define TOL 0.
00338
00340 double CouenneVarObject::feasibleRegion (OsiSolverInterface *solver,
00341 const OsiBranchingInformation *info) const {
00342 int index = reference_ -> Index ();
00343
00344 assert (index >= 0);
00345
00346 double val = info -> solution_ [index];
00347
00348
00349 solver -> setColLower (index, val-TOL);
00350 solver -> setColUpper (index, val+TOL);
00351
00352 return 0.;
00353 }
00354
00355
00357 bool CouenneVarObject::isCuttable () const {
00358
00359 const std::set <int> &deplist = problem_ -> Dependence () [reference_ -> Index ()];
00360 const std::vector <CouenneObject *> &objects = problem_ -> Objects ();
00361
00362 for (std::set <int>::const_iterator depvar = deplist. begin ();
00363 depvar != deplist. end (); ++depvar)
00364 if (!(objects [*depvar] -> isCuttable ()))
00365 return false;
00366
00367 return (!(reference_ -> isInteger ()));
00368 }
00369