00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CoinHelperFunctions.hpp"
00013
00014 #include "OsiRowCut.hpp"
00015
00016
00017 #include "CouenneProblem.hpp"
00018 #include "CouenneObject.hpp"
00019 #include "CouenneBranchingObject.hpp"
00020 #include "CouenneCutGenerator.hpp"
00021
00022 class CouenneCutGenerator;
00023
00024
00025 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
00026
00027
00034 CouenneBranchingObject::CouenneBranchingObject (OsiSolverInterface *solver,
00035 const OsiObject * originalObject,
00036 JnlstPtr jnlst,
00037 CouenneCutGenerator *cutGen,
00038 CouenneProblem *problem,
00039 expression *var,
00040 int way,
00041 CouNumber brpoint,
00042 bool doFBBT, bool doConvCuts):
00043
00044 OsiTwoWayBranchingObject (solver, originalObject, way, brpoint),
00045 cutGen_ (cutGen),
00046 problem_ (problem),
00047 variable_ (var),
00048 jnlst_ (jnlst),
00049 doFBBT_ (doFBBT),
00050 doConvCuts_ (doConvCuts),
00051 downEstimate_ (0.),
00052 upEstimate_ (0.),
00053 simulate_ (false) {
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 value_ = (*variable_) ();
00072
00073 if (fabs (brpoint) < COUENNE_INFINITY)
00074 value_ = brpoint;
00075
00076 CouNumber lb, ub;
00077 var -> getBounds (lb, ub);
00078
00079
00080 if ((lb > -COUENNE_INFINITY) && (ub < COUENNE_INFINITY)) {
00081 if ((value_ - lb) / (ub-lb) < closeToBounds) value_ = lb + (ub-lb) * closeToBounds;
00082 else if ((ub - value_) / (ub-lb) < closeToBounds) value_ = ub + (lb-ub) * closeToBounds;
00083 }
00084
00085 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00086 "Branch: x%-3d will branch on %g (cur. %g) [%g,%g]; firstBranch_ = %d\n",
00087 variable_ -> Index (), value_, (*variable_) (), lb, ub, firstBranch_);
00088 }
00089
00090
00098 double CouenneBranchingObject::branch (OsiSolverInterface * solver) {
00099
00100
00101
00102
00103 int
00104 way = (!branchIndex_) ? firstBranch_ : !firstBranch_,
00105 index = variable_ -> Index ();
00106
00107 bool
00108 integer = variable_ -> isInteger (),
00109 infeasible = false;
00110
00111 CouNumber
00112 l = solver -> getColLower () [index],
00113 u = solver -> getColUpper () [index],
00114 brpt = value_;
00115
00116 if (way) {
00117 if (value_ < l)
00118 jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "Nonsense up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00119 else if (value_ < l+COUENNE_EPS)
00120 jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "## WEAK up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00121 } else {
00122 if (value_ > u)
00123 jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "Nonsense dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00124 else if (value_ > u+COUENNE_EPS)
00125 jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "## WEAK dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00126 }
00127
00128 if ((brpt < l) || (brpt > u))
00129 brpt = 0.5 * (l+u);
00130
00131 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "Branching: x%-3d %c= %g\n",
00132
00133 index, way ? '>' : '<', integer ? (way ? ceil (brpt) : floor (brpt)) : brpt);
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 if (!way) solver -> setColUpper (index, integer ? floor (brpt) : brpt);
00148 else solver -> setColLower (index, integer ? ceil (brpt) : brpt);
00149
00150
00151
00152
00153
00154 int
00155 nvars = problem_ -> nVars (),
00156 objind = problem_ -> Obj (0) -> Body () -> Index ();
00157
00158
00159 CouNumber estimate = 0.;
00160
00161 if ((doFBBT_ && problem_ -> doFBBT ()) ||
00162 (doConvCuts_ && simulate_ && cutGen_)) {
00163
00164 problem_ -> domain () -> push (nvars,
00165 solver -> getColSolution (),
00166 solver -> getColLower (),
00167 solver -> getColUpper ());
00168
00169 t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00170
00171 if (!way) chg_bds [index].setUpper (t_chg_bounds::CHANGED);
00172 else chg_bds [index].setLower (t_chg_bounds::CHANGED);
00173
00174 if ( doFBBT_ &&
00175 problem_ -> doFBBT ()) {
00176
00177 problem_ -> installCutOff ();
00178
00179 if (!problem_ -> btCore (chg_bds))
00180 infeasible = true;
00181 else {
00182
00183 const double
00184 *lb = solver -> getColLower (),
00185 *ub = solver -> getColUpper ();
00186
00187
00188 estimate = CoinMax (0., problem_ -> Lb (objind) - lb [objind]);
00189
00190
00191
00192
00193 for (int i=0; i<nvars; i++) {
00194 if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00195 if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00196 }
00197 }
00198 }
00199
00200 if (!infeasible && doConvCuts_ && simulate_ && cutGen_) {
00201
00202
00203 int nchanged, *changed = NULL;
00204 OsiCuts cs;
00205
00206
00207 sparse2dense (nvars, chg_bds, changed, nchanged);
00208 cutGen_ -> genRowCuts (*solver, cs, nchanged, changed, chg_bds);
00209 free (changed);
00210
00211 solver -> applyCuts (cs);
00212 }
00213
00214 delete [] chg_bds;
00215
00216 problem_ -> domain () -> pop ();
00217 }
00218
00219
00220 branchIndex_++;
00221
00222 return (infeasible ? COIN_DBL_MAX : estimate);
00223 }