00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "OsiRowCut.hpp"
00012 #include "OsiCuts.hpp"
00013
00014 #include "exprGroup.hpp"
00015 #include "exprBound.hpp"
00016 #include "exprMul.hpp"
00017
00018 #include "CouenneProblem.hpp"
00019 #include "CouenneCutGenerator.hpp"
00020
00022 void exprGroup::getBounds (expression *&lb, expression *&ub) {
00023
00024 expression
00025 **lbnl = new expression * [1],
00026 **ubnl = new expression * [1];
00027
00028
00029
00030
00031 exprSum::getBounds (*lbnl, *ubnl);
00032
00033 lincoeff
00034 *coeL = new lincoeff,
00035 *coeU = new lincoeff;
00036
00037
00038 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00039
00040 std::pair <exprVar *, CouNumber> pairL, pairU;
00041
00042 CouNumber coeff = el -> second;
00043 int ind = el -> first -> Index ();
00044
00045 pairL .second = pairU .second = coeff;
00046
00047 if (coeff < 0.) {
00048 pairL.first = new exprUpperBound (ind, el -> first -> domain ());
00049 pairU.first = new exprLowerBound (ind, el -> first -> domain ());
00050 } else {
00051 pairL.first = new exprLowerBound (ind, el -> first -> domain ());
00052 pairU.first = new exprUpperBound (ind, el -> first -> domain ());
00053 }
00054
00055 coeL -> push_back (pairL);
00056 coeU -> push_back (pairU);
00057 }
00058
00059 lb = new exprGroup (c0_, *coeL, lbnl, 1);
00060 ub = new exprGroup (c0_, *coeU, ubnl, 1);
00061
00062 delete coeL;
00063 delete coeU;
00064 }
00065
00066
00067
00068
00069
00070
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
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00133 void exprGroup::getBounds (CouNumber &lb, CouNumber &ub) {
00134
00135
00136
00137 exprSum::getBounds (lb, ub);
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 lb += c0_;
00150 ub += c0_;
00151
00152
00153 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00154
00155 exprVar *var = el -> first;
00156 CouNumber coeff = el -> second, vlb, vub;
00157
00158 bool
00159 inf_lb = false,
00160 inf_ub = false;
00161
00162 if ((vlb = var -> lb ()) < -COUENNE_INFINITY) {
00163 if (coeff > 0) inf_lb = true;
00164 else inf_ub = true;
00165 } else {
00166 if (coeff > 0) lb += vlb * coeff;
00167 else ub += vlb * coeff;
00168 }
00169
00170 if ((vub = var -> ub ()) > COUENNE_INFINITY) {
00171 if (coeff > 0) inf_ub = true;
00172 else inf_lb = true;
00173 } else {
00174 if (coeff > 0) ub += vub * coeff;
00175 else lb += vub * coeff;
00176 }
00177
00178 if (inf_lb)
00179 lb = -COUENNE_INFINITY;
00180
00181 if (inf_ub) {
00182 ub = COUENNE_INFINITY;
00183 if (inf_lb)
00184 break;
00185 }
00186
00187
00188 }
00189 }
00190
00191
00192
00193 void exprGroup::generateCuts (expression *w, const OsiSolverInterface &si,
00194 OsiCuts &cs, const CouenneCutGenerator *cg,
00195 t_chg_bounds *chg,
00196 int wind, CouNumber lb, CouNumber ub) {
00197
00198
00199
00200
00201 if (!(cg -> isFirst ()))
00202 return;
00203
00204
00205 int nterms = lcoeff_.size ();
00206
00207 OsiRowCut *cut = new OsiRowCut;
00208
00209 int displacement = (wind < 0) ? 1: 0;
00210
00211 CouNumber *coeff = new CouNumber [nargs_ + nterms + displacement];
00212 int *index = new int [nargs_ + nterms + displacement];
00213
00214 if (wind < 0) {
00215
00216 coeff [0] = -1.;
00217 index [0] = w -> Index ();
00218 lb = ub = 0;
00219 }
00220
00221 lb -= c0_;
00222 ub -= c0_;
00223
00224
00225 lincoeff::iterator el = lcoeff_.begin ();
00226
00227 for (int i=0; el != lcoeff_.end (); ++el)
00228
00229 if (fabs (el -> second) > 1.0e-21) {
00230
00231
00232 coeff [i + displacement] = el -> second;
00233 index [i++ + displacement] = el -> first -> Index ();
00234 }
00235
00236
00237 for (int i=0; i<nargs_; i++) {
00238
00239 expression *curr = arglist_ [i];
00240
00241 if (curr -> Type () == CONST) {
00242 lb -= curr -> Value ();
00243 ub -= curr -> Value ();
00244 }
00245 else {
00246 coeff [++nterms] = 1.;
00247 index [nterms] = curr -> Index ();
00248 }
00249 }
00250
00251 cut -> setRow (nterms + displacement, index, coeff);
00252
00253 delete [] index;
00254 delete [] coeff;
00255
00256 if (lb > -COUENNE_INFINITY) cut -> setLb (lb);
00257 if (ub < COUENNE_INFINITY) cut -> setUb (ub);
00258
00259 cut -> setGloballyValid ();
00260 cs.insert (cut);
00261 delete cut;
00262 }