00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneTypes.hpp"
00012
00013 #include "exprInv.hpp"
00014 #include "exprClone.hpp"
00015 #include "exprConst.hpp"
00016 #include "exprMin.hpp"
00017 #include "exprOpp.hpp"
00018 #include "exprDiv.hpp"
00019 #include "exprSum.hpp"
00020 #include "exprMul.hpp"
00021 #include "exprPow.hpp"
00022
00023 #include "CouenneProblem.hpp"
00024 #include "CouenneCutGenerator.hpp"
00025
00026
00027
00028
00029 void exprInv::getBounds (expression *&lb, expression *&ub) {
00030
00031 expression *lba, *uba;
00032 argument_ -> getBounds (lba, uba);
00033
00034 expression **all = new expression * [6];
00035 all [0] = new exprConst (0.); all [1] = new exprConst (- COUENNE_INFINITY);
00036 all [2] = new exprOpp (lba); all [3] = new exprInv (uba);
00037 all [4] = new exprClone (uba); all [5] = new exprInv (new exprClone (uba));
00038
00039 lb = new exprMin (all, 6);
00040
00041 expression **alu = new expression * [6];
00042 alu [0] = new exprConst (0.); alu [1] = new exprConst (COUENNE_INFINITY);
00043 alu [2] = new exprClone (all [2]); alu [3] = new exprInv (new exprClone (lba));
00044 alu [4] = new exprClone (uba); alu [5] = new exprInv (new exprClone (lba));
00045
00046 ub = new exprMin (alu, 6);
00047 }
00048
00049
00050
00051 void exprInv::getBounds (CouNumber &lb, CouNumber &ub) {
00052
00053 register CouNumber lba, uba;
00054
00055 argument_ -> getBounds (lba, uba);
00056
00057 if ((uba < 0) || (lba > 0)) {
00058 lb = 1./uba;
00059 ub = 1./lba;
00060 } else {
00061 lb = -COUENNE_INFINITY;
00062 ub = COUENNE_INFINITY;
00063 }
00064 }
00065
00066
00067 #define MIN_DENOMINATOR 1e-6
00068
00069
00070
00071 void exprInv::generateCuts (expression *aux,
00072 OsiCuts &cs, const CouenneCutGenerator *cg,
00073 t_chg_bounds *chg, int wind,
00074 CouNumber lbw, CouNumber ubw) {
00075 CouNumber l, u;
00076 argument_ -> getBounds (l, u);
00077
00078 if ((l < - COUENNE_EPS) && (u > COUENNE_EPS))
00079 return;
00080
00081 int wi = aux -> Index (),
00082 xi = argument_ -> Index ();
00083
00084 bool cL = !chg || (cg -> isFirst ()) || (chg [xi].lower() != t_chg_bounds::UNCHANGED);
00085 bool cR = !chg || (cg -> isFirst ()) || (chg [xi].upper() != t_chg_bounds::UNCHANGED);
00086
00087
00088
00089
00090 if (fabs (u - l) < COUENNE_EPS) {
00091
00092 CouNumber x0 = 0.5 * (u+l);
00093 if (cL || cR)
00094 cg -> createCut (cs, 2/x0, 0, wi, 1., xi, 1/(x0*x0));
00095 return;
00096 }
00097
00098
00099
00100 if (cL || cR) {
00101
00102 if ((l> COUENNE_EPS) && (u< COU_MAX_COEFF)) cg -> createCut (cs, 1/l+1/u, -1, wi,1., xi,1/(l*u));
00103 if ((u<-COUENNE_EPS) && (l>-COU_MAX_COEFF)) cg -> createCut (cs, 1/l+1/u, +1, wi,1., xi,1/(l*u));
00104
00105 }
00106
00107
00108
00109
00110 int ns = cg -> nSamples ();
00111 if (l < - COUENNE_INFINITY) l = ns * (u-1);
00112 else if (u > COUENNE_INFINITY) u = ns * (l+1);
00113
00114
00115 if (fabs (l) < COUENNE_EPS) l = (l<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
00116 if (fabs (u) < COUENNE_EPS) u = (u<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
00117
00118
00119 cg -> addEnvelope
00120 (cs, (l > 0) ? +1 : -1,
00121 inv, oppInvSqr, wi, xi,
00122 (cg -> isFirst ()) ?
00123
00124 ((l > COUENNE_EPS) ? l : u) :
00125
00126 powNewton ((*argument_) (), (*aux) (), inv, oppInvSqr, inv_dblprime),
00127 l, u, chg);
00128 }