00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "OsiRowCut.hpp"
00012
00013 #include "CouenneTypes.hpp"
00014 #include "CouennePrecisions.hpp"
00015 #include "CouenneCutGenerator.hpp"
00016 #include "CouenneProblem.hpp"
00017
00018 using namespace Ipopt;
00019 using namespace Couenne;
00020
00022 bool badCoeff (CouNumber coe) {
00023
00024 coe = fabs (coe);
00025 return ((coe > COU_MAX_COEFF) || ((coe < COU_MIN_COEFF) && (coe > 0.)));
00026 }
00027
00028
00031
00032 int CouenneCutGenerator::createCut (OsiCuts &cs,
00033 CouNumber lb, CouNumber ub,
00034 int i1, CouNumber c1,
00035 int i2, CouNumber c2,
00036 int i3, CouNumber c3,
00037 bool is_global) const {
00038 bool numerics = false;
00039
00040
00041
00042
00043 int nterms = 0;
00044
00045
00046
00047 if ((i1 != -1) && (i1 == i3)) {i3 = -1; c1 += c3; c3 = 0;}
00048 if ((i2 != -1) && (i2 == i3)) {i3 = -1; c2 += c3; c3 = 0;}
00049 if ((i1 != -1) && (i1 == i2)) {i2 = -1; c1 += c2; c2 = 0;}
00050
00051
00052 if (fabs (c3) <= 1.e-21) { i3 = -1;}
00053 if (fabs (c2) <= 1.e-21) { c2 = c3; i2 = i3; i3 = -1;}
00054 if (fabs (c1) <= 1.e-21) {c1 = c2; i1 = i2; c2 = c3; i2 = i3; i3 = -1;}
00055
00056
00057 #if 0
00058 if (i1 >= 0) {if (fabs (c1) > COU_MAX_COEFF) numerics = true; nterms++;} else c1 = 0;
00059 if (i2 >= 0) {if (fabs (c2) > COU_MAX_COEFF) numerics = true; nterms++;} else c2 = 0;
00060 if (i3 >= 0) {if (fabs (c3) > COU_MAX_COEFF) numerics = true; nterms++;} else c3 = 0;
00061 #else
00062 if (i1 >= 0) {if (badCoeff (c1)) numerics = true; nterms++;} else c1 = 0;
00063 if (i2 >= 0) {if (badCoeff (c2)) numerics = true; nterms++;} else c2 = 0;
00064 if (i3 >= 0) {if (badCoeff (c3)) numerics = true; nterms++;} else c3 = 0;
00065 #endif
00066
00067 if (!nterms)
00068 return 0;
00069
00070
00071 if (numerics
00072
00073
00074 || ((fabs (lb) > COU_MAX_COEFF) &&
00075 (fabs (ub) > COU_MAX_COEFF))) {
00076
00077 jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00078 "### Discarding cut, large coeff/rhs: %g (%d), %g (%d), %g (%d); [%g,%g]\n",
00079 c1, i1, c2, i2, c3, i3, lb, ub);
00080 return 0;
00081 }
00082
00083 if (!firstcall_ && addviolated_) {
00084
00085 const CouNumber *x = problem_ -> X ();
00086
00087
00088 CouNumber violation = 0.;
00089
00090 if (i1 >= 0) violation += c1 * x [i1];
00091 if (i2 >= 0) violation += c2 * x [i2];
00092 if (i3 >= 0) violation += c3 * x [i3];
00093
00094
00095
00096 if ((violation < ub + 0 * COUENNE_EPS) &&
00097 (violation > lb - 0 * COUENNE_EPS))
00098 return 0;
00099 }
00100
00101
00102
00103
00104 CouNumber *best = problem_ -> bestSol ();
00105
00106 if (best &&
00107 ((i1 < 0) || ((best [i1] >= problem_ -> Lb (i1)) && (best [i1] <= problem_ -> Ub (i1)))) &&
00108 ((i2 < 0) || ((best [i2] >= problem_ -> Lb (i2)) && (best [i2] <= problem_ -> Ub (i2)))) &&
00109 ((i3 < 0) || ((best [i3] >= problem_ -> Lb (i3)) && (best [i3] <= problem_ -> Ub (i3))))) {
00110
00111 CouNumber lhs = 0.;
00112
00113 if (i1 >= 0) lhs += c1 * best [i1];
00114 if (i2 >= 0) lhs += c2 * best [i2];
00115 if (i3 >= 0) lhs += c3 * best [i3];
00116
00117 if (lhs > ub + COUENNE_EPS)
00118 jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00119 "### cut (%d,%d,%d) (%g,%g,%g) cuts optimum: %g >= %g [%g]\n",
00120 i1,i2,i3, c1,c2,c3, lhs, ub, lhs - ub);
00121
00122 if (lhs < lb - COUENNE_EPS)
00123 jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00124 "### cut (%d,%d,%d) (%g,%g,%g) cuts optimum: %g <= %g [%g]\n",
00125 i1,i2,i3, c1,c2,c3, lhs, lb, lb - lhs);
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 if ((i2 < 0) && (i3 < 0)) {
00139
00140 if ( (fabs (c1) < COUENNE_EPS)
00141 && (fabs (lb) > COU_MAX_COEFF * COUENNE_EPS)
00142 && (fabs (ub) > COU_MAX_COEFF * COUENNE_EPS)) {
00143
00144 jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00145 "#### nonsense column cut: %e <= %e w_%d <= %e\n",
00146 lb, c1, i1, ub);
00147 return 0;
00148 }
00149
00150 OsiColCut *cut = new OsiColCut;
00151
00152 CouNumber
00153 ll = lb / c1,
00154 uu = ub / c1;
00155
00156 if (c1 < 0) {
00157 CouNumber tmp = ll;
00158 ll = uu;
00159 uu = tmp;
00160 }
00161
00162 CouNumber &curL = problem_ -> Lb (i1),
00163 &curU = problem_ -> Ub (i1);
00164
00165 if ((uu < COUENNE_INFINITY) &&
00166 (uu < curU - COUENNE_EPS)) {
00167
00168 cut -> setUbs (1, &i1, &uu);
00169 curU = uu;
00170 }
00171
00172 if ((ll > -COUENNE_INFINITY) &&
00173 (ll > curL + COUENNE_EPS)) {
00174 cut -> setLbs (1, &i1, &ll);
00175 curL = ll;
00176 }
00177
00178 cut -> setGloballyValid (is_global);
00179
00180 cs.insert (cut);
00181 delete cut;
00182
00183 } else {
00184
00185
00186
00187 CouNumber *coeff = new CouNumber [nterms];
00188 int *index = new int [nterms];
00189 OsiRowCut *cut = new OsiRowCut;
00190
00191 int nt = 0;
00192
00193 if (i1 >= 0) {coeff [nt] = c1; index [nt++] = i1;}
00194 if (i2 >= 0) {coeff [nt] = c2; index [nt++] = i2;}
00195 if (i3 >= 0) {coeff [nt] = c3; index [nt++] = i3;}
00196
00197 if (lb > -COUENNE_INFINITY) cut -> setLb (lb);
00198 if (ub < COUENNE_INFINITY) cut -> setUb (ub);
00199
00200 cut -> setRow (nterms, index, coeff);
00201
00202 delete [] coeff;
00203 delete [] index;
00204
00205 cut -> setGloballyValid (is_global);
00206
00207 cs.insert (cut);
00208 delete cut;
00209 }
00210
00211 return 1;
00212 }
00213
00214
00217
00218 int CouenneCutGenerator::createCut (OsiCuts &cs,
00219 CouNumber rhs, int sign,
00220 int i1, CouNumber c1,
00221 int i2, CouNumber c2,
00222 int i3, CouNumber c3,
00223 bool is_global) const {
00224
00225 return createCut (cs, (sign >= 0) ? rhs : - COIN_DBL_MAX,
00226 (sign <= 0) ? rhs : COIN_DBL_MAX,
00227 i1, c1, i2, c2, i3, c3, is_global);
00228 }