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