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