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