00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CoinHelperFunctions.hpp"
00013
00014 #include "OsiRowCut.hpp"
00015
00016 #include "CouenneCutGenerator.hpp"
00017
00018 #include "CouenneProblem.hpp"
00019 #include "CouenneProblemElem.hpp"
00020 #include "CouenneObject.hpp"
00021 #include "CouenneBranchingObject.hpp"
00022
00023 using namespace Ipopt;
00024 using namespace Couenne;
00025
00026
00027 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
00028
00035 CouenneBranchingObject::CouenneBranchingObject (OsiSolverInterface *solver,
00036 const OsiObject * originalObject,
00037 JnlstPtr jnlst,
00038 CouenneCutGenerator *cutGen,
00039 CouenneProblem *problem,
00040 expression *var,
00041 int way,
00042 CouNumber brpoint,
00043 bool doFBBT, bool doConvCuts):
00044
00045 OsiTwoWayBranchingObject (solver, originalObject, way, brpoint),
00046
00047 cutGen_ (cutGen),
00048 problem_ (problem),
00049 variable_ (var),
00050 jnlst_ (jnlst),
00051 doFBBT_ (doFBBT),
00052 doConvCuts_ (doConvCuts),
00053 downEstimate_ (0.),
00054 upEstimate_ (0.),
00055 simulate_ (false) {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 CouNumber lb, ub;
00074
00075 variable_ -> getBounds (lb, ub);
00076
00077
00078
00079 value_ = (fabs (brpoint) < large_bound) ? brpoint : (*variable_) ();
00080
00081 if (lb < -large_bound)
00082 if (ub > large_bound) value_ = 0.;
00083 else value_ = ((value_ < -COUENNE_EPS) ? (AGGR_MUL * (-1+value_)) :
00084 (value_ > COUENNE_EPS) ? 0. : -AGGR_MUL);
00085 else
00086 if (ub > large_bound) value_ = ((value_ > COUENNE_EPS) ? (AGGR_MUL * (1+value_)) :
00087 (value_ < -COUENNE_EPS) ? 0. : AGGR_MUL);
00088 else {
00089 double margin = fabs (ub-lb) * closeToBounds;
00090 if (value_ < lb + margin) value_ = lb + margin;
00091 else if (value_ > ub - margin) value_ = ub - margin;
00092 }
00093
00094 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00095 "Branch: x%-3d will branch on %g (cur. %g) [%g,%g]; firstBranch_ = %d\n",
00096 variable_ -> Index (), value_, (*variable_) (), lb, ub, firstBranch_);
00097 }
00098
00099
00107 double CouenneBranchingObject::branch (OsiSolverInterface * solver) {
00108
00109 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00110 "::branch: at %.20e\n", value_);
00111
00112
00113
00114
00115 int
00116 way = (!branchIndex_) ? firstBranch_ : !firstBranch_,
00117 index = variable_ -> Index ();
00118
00119 bool
00120 integer = variable_ -> isInteger (),
00121 infeasible = false;
00122
00123 CouNumber
00124 l = solver -> getColLower () [index],
00125 u = solver -> getColUpper () [index],
00126 brpt = value_;
00127
00128 if (brpt < l) brpt = l;
00129 else if (brpt > u) brpt = u;
00130
00131
00132
00133 if (l < -large_bound) {
00134 if (u <= large_bound)
00135 brpt = ((u < -COUENNE_EPS) ? CoinMax (CoinMax (brpt, .5 * (l+u)), AGGR_MUL * (-1. + brpt)) :
00136 (u > COUENNE_EPS) ? 0. : -AGGR_MUL);
00137 else brpt = 0.;
00138 } else
00139 if (u > large_bound)
00140 brpt = ((l > COUENNE_EPS) ? CoinMin (CoinMin (brpt, .5 * (l+u)), AGGR_MUL * ( 1. + brpt)) :
00141 (l < -COUENNE_EPS) ? 0. : AGGR_MUL);
00142 else {
00143
00144 CouNumber point = default_alpha * brpt + (1. - default_alpha) * (l + u) / 2.;
00145
00146 if ((point-l) / (u-l) < closeToBounds) brpt = l + (u-l) * closeToBounds;
00147 else if ((u-point) / (u-l) < closeToBounds) brpt = u + (l-u) * closeToBounds;
00148 else brpt = point;
00149 }
00150
00151
00152
00153
00154
00155
00156 if (integer &&
00157 ::isInteger (brpt)) {
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 if ((brpt - l > .5) &&
00173 (u - brpt > .5)) {
00174
00175 if (!branchIndex_) {
00176 if (!way) brpt -= (1. - COUENNE_EPS);
00177 else brpt += (1. - COUENNE_EPS);
00178 }
00179 else {
00180
00181 if (!way) brpt += COUENNE_EPS;
00182 else brpt -= COUENNE_EPS;
00183 }
00184 }
00185 else {
00186 if (u - brpt > .5) {
00187 if (way) {
00188 brpt += (1. - COUENNE_EPS);
00189 }
00190 else {
00191 brpt += COUENNE_EPS;
00192 }
00193 }
00194 else {
00195 if (brpt - l > .5) {
00196 if (!way) {
00197 brpt -= (1. - COUENNE_EPS);
00198 }
00199 else {
00200 brpt -= COUENNE_EPS;
00201 }
00202 }
00203 else {
00204
00205 if(way) {
00206 solver->setColLower(index, u+1);
00207 }
00208 }
00209 }
00210 }
00211 }
00212
00213 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "Branching: x%-3d %c= %.20e\n",
00214 index, way ? '>' : '<', integer ? (way ? ceil (brpt) : floor (brpt)) : brpt);
00215
00216 if (way) {
00217 if (brpt < l) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "Nonsense up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00218 else if (brpt < l+COUENNE_EPS) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "## WEAK up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00219 } else {
00220 if (brpt > u) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "Nonsense dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00221 else if (brpt > u-COUENNE_EPS) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "## WEAK dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 t_chg_bounds *chg_bds = NULL;
00237
00238
00239
00240 branchCore (solver, index, way, integer, brpt, chg_bds);
00241
00242
00243
00244
00245
00246 int
00247 nvars = problem_ -> nVars (),
00248 objind = problem_ -> Obj (0) -> Body () -> Index ();
00249
00250
00251 CouNumber estimate = 0.;
00252
00253 if ((doFBBT_ && problem_ -> doFBBT ()) ||
00254 (doConvCuts_ && simulate_ && cutGen_)) {
00255
00256 problem_ -> domain () -> push (solver);
00257
00258 if ( doFBBT_ &&
00259 problem_ -> doFBBT ()) {
00260
00261 problem_ -> installCutOff ();
00262
00263 if (!problem_ -> btCore (chg_bds))
00264 infeasible = true;
00265
00266 else {
00267
00268 const double
00269 *lb = solver -> getColLower (),
00270 *ub = solver -> getColUpper ();
00271
00272
00273 estimate = CoinMax (0., problem_ -> Lb (objind) - lb [objind]);
00274
00275 for (int i=0; i<nvars; i++) {
00276 if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00277 if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00278 }
00279 }
00280 }
00281
00282 if (!infeasible && doConvCuts_ && simulate_ && cutGen_) {
00283
00284
00285 int nchanged, *changed = NULL;
00286 OsiCuts cs;
00287
00288
00289 sparse2dense (nvars, chg_bds, changed, nchanged);
00290 cutGen_ -> genRowCuts (*solver, cs, nchanged, changed, chg_bds);
00291 free (changed);
00292
00293 solver -> applyCuts (cs);
00294 }
00295
00296
00297
00298 problem_ -> domain () -> pop ();
00299 }
00300
00301 if (chg_bds) delete [] chg_bds;
00302
00303
00304 branchIndex_++;
00305
00306 return (infeasible ? COIN_DBL_MAX : estimate);
00307 }