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