00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "OsiRowCut.hpp"
00012 #include "CouennePrecisions.hpp"
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneCutGenerator.hpp"
00015 #include "CouenneFunTriplets.hpp"
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneExprVar.hpp"
00018 #include "CoinFinite.hpp"
00019
00020 using namespace Couenne;
00021
00022 void CouenneCutGenerator::addEnvelope (OsiCuts &cs, int sign,
00023 unary_function f,
00024 unary_function fprime,
00025 int w_ind, int x_ind,
00026 CouNumber x, CouNumber l, CouNumber u,
00027 t_chg_bounds *chg,
00028 bool is_global) const {
00029
00030 simpletriplet st (f, fprime, fprime);
00031 addEnvelope (cs, sign, &st, w_ind, x_ind, x, l, u, chg, is_global);
00032 }
00033
00034
00035 void CouenneCutGenerator::addEnvelope (OsiCuts &cs, int sign,
00036 funtriplet *ft,
00037 int w_ind, int x_ind,
00038 CouNumber x, CouNumber l, CouNumber u,
00039 t_chg_bounds *chg,
00040 bool is_global) const {
00041 CouNumber opp_slope = - ft -> Fp (x);
00042
00043
00044
00045
00046
00047 bool cLeft = !chg || (chg [x_ind].lower() != t_chg_bounds::UNCHANGED) || firstcall_;
00048 bool cRight = !chg || (chg [x_ind].upper() != t_chg_bounds::UNCHANGED) || firstcall_;
00049
00050 if (fabs (u - l) < COUENNE_EPS) {
00051
00052 CouNumber x0 = 0.5 * (u+l), fp0 = ft -> Fp (x0);
00053 if (cLeft || cRight)
00054 createCut (cs, ft -> F(x0) - fp0 * x0, 0, w_ind, 1., x_ind, - fp0);
00055 return;
00056 }
00057
00058
00059
00060 if (((!firstcall_) || ((x >= l) && (x <= u)))
00061 && !CoinIsnan (opp_slope)
00062 && (fabs (opp_slope) < COUENNE_INFINITY)) {
00063
00064 if (!(problem_ -> Var (x_ind) -> isInteger ()))
00065
00066
00067 createCut (cs, ft -> F (x) + opp_slope * x, sign, w_ind, 1.,
00068 x_ind, opp_slope, -1, 0., is_global);
00069
00070 else {
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 CouNumber x1, x2, y1, y2;
00096
00097 if ((x1 = floor (x)) < l)
00098 x1 = ceil (l - COUENNE_EPS);
00099
00100 y1 = ft -> F (x1);
00101
00102 x2 = ceil (x);
00103
00104 if (fabs (x2-x1) < COUENNE_EPS)
00105 x2 += 1.;
00106
00107 y2 = ft -> F (x2);
00108
00109 if ((x2 > u) ||
00110 CoinIsnan (y1) || CoinIsnan (y2) ||
00111 !CoinFinite (y1) || !CoinFinite (y2))
00112
00113 createCut (cs, ft -> F (x) + opp_slope * x, sign, w_ind, 1.,
00114 x_ind, opp_slope, -1, 0., is_global);
00115
00116 else {
00117
00118 CouNumber
00119 slope = (y1-y2) / (x2-x1),
00120 rhs = y1 + slope * x1;
00121
00122 createCut (cs, rhs, sign, w_ind, 1.,
00123 x_ind, slope, -1, 0., is_global);
00124 }
00125
00126
00127
00128
00129 }
00130 }
00131
00132
00133
00134
00135 if ((convtype_ == UNIFORM_GRID) || firstcall_) {
00136
00137 if (cLeft || cRight) {
00138
00139
00140 CouNumber
00141 sample = l,
00142 step = (u-l) / nSamples_;
00143
00144
00145
00146
00147 for (int i = 0; i <= nSamples_; i++) {
00148
00149 opp_slope = - ft -> Fp (sample);
00150
00151 if ((fabs (opp_slope) < COUENNE_INFINITY) &&
00152 (fabs (sample-x) > COUENNE_EPS)) {
00153
00154
00155
00156
00157 if (!(problem_ -> Var (x_ind) -> isInteger ()))
00158
00159 createCut (cs, ft -> F (sample) + opp_slope * sample, sign,
00160 w_ind, 1.,
00161 x_ind, opp_slope,
00162 -1, 0., is_global);
00163 else {
00164
00165 CouNumber x1, x2, y1, y2;
00166
00167 if ((x1 = floor (sample)) < l)
00168 x1 = ceil (l - COUENNE_EPS);
00169
00170 y1 = ft -> F (x1);
00171
00172 x2 = ceil (sample);
00173
00174 if (fabs (x2-x1) < COUENNE_EPS)
00175 x2 += 1.;
00176
00177 y2 = ft -> F (x2);
00178
00179 if ((x2 > u) ||
00180 CoinIsnan (y1) || CoinIsnan (y2) ||
00181 !CoinFinite (y1) || !CoinFinite (y2))
00182
00183 createCut (cs, ft -> F (sample) + opp_slope * sample, sign, w_ind, 1.,
00184 x_ind, opp_slope, -1, 0., is_global);
00185 }
00186 }
00187
00188
00189
00190 sample += step;
00191 }
00192 }
00193 }
00194 else if (convtype_ != CURRENT_ONLY) {
00195
00196 CouNumber sample = x;
00197
00198 if (fabs (opp_slope) < COUENNE_INFINITY)
00199 createCut (cs, ft -> F (x) + opp_slope * x, sign,
00200 w_ind, 1.,
00201 x_ind, opp_slope,
00202 -1, 0.,
00203 is_global);
00204
00205
00206 for (int i = 0; i <= nSamples_/2; i++) {
00207
00208 sample += (x-l) / nSamples_;
00209 opp_slope = - ft -> Fp (sample);
00210
00211 if (fabs (opp_slope) < COUENNE_INFINITY)
00212 createCut (cs, ft -> F (sample) + opp_slope * sample, sign,
00213 w_ind, 1.,
00214 x_ind, opp_slope,
00215 -1, 0.,
00216 is_global);
00217
00218 }
00219
00220 sample = x;
00221
00222 for (int i = 0; i <= nSamples_/2; i++) {
00223
00224 sample += (u-x) / nSamples_;
00225 opp_slope = - ft -> Fp (sample);
00226
00227 createCut (cs, ft -> F(sample) + opp_slope * sample, sign,
00228 w_ind, 1.,
00229 x_ind, opp_slope,
00230 -1, 0.,
00231 is_global);
00232
00233 }
00234 }
00235 }