00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdlib.h>
00012 #include <assert.h>
00013
00014 #include "CoinHelperFunctions.hpp"
00015 #include "exprMul.hpp"
00016 #include "exprSum.hpp"
00017 #include "exprConst.hpp"
00018 #include "exprClone.hpp"
00019 #include "CouennePrecisions.hpp"
00020
00021
00023 exprMul::exprMul (expression **al, int n):
00024 exprOp (al, n) {
00025
00026
00027 qsort (arglist_, nargs_, sizeof (expression*), compareExpr);
00028 }
00029
00031 exprMul::exprMul (expression *arg0, expression *arg1):
00032 exprOp (arg0, arg1) {
00033
00034 if (compareExpr (arglist_, arglist_ + 1) > 0) {
00035
00036 register expression
00037 *swap = arglist_ [0];
00038 arglist_ [0] = arglist_ [1];
00039 arglist_ [1] = swap;
00040 }
00041 }
00042
00043
00045
00046 expression *exprMul::simplify () {
00047
00048 exprOp:: simplify ();
00049
00050 if (nargs_ == 1) {
00051
00052 expression *ret = arglist_ [0];
00053 arglist_ [0] = NULL;
00054 return ret;
00055 }
00056
00057 CouNumber prod = 1;
00058
00059 bool found_one = false;
00060
00061 for (register int i=0; i<nargs_; i++) {
00062
00063
00064
00065 if (arglist_ [i] -> Type () == CONST) {
00066
00067 found_one = true;
00068
00069 CouNumber c = arglist_ [i] -> Value ();
00070 prod *= c;
00071
00072 if (fabs (c) < COUENNE_EPS_SIMPL) {
00073
00074 for (int j=0; j<nargs_; j++)
00075 if (arglist_ [j]) {
00076 delete arglist_ [j];
00077 arglist_ [j] = NULL;
00078 }
00079
00080 return new exprConst (0.);
00081 }
00082
00083
00084
00085 delete arglist_ [i];
00086 arglist_ [i] = NULL;
00087 }
00088 }
00089
00090
00091
00092
00093 if (found_one && shrink_arglist (prod, 1)) {
00094 expression *ret = arglist_ [0];
00095 arglist_ [0] = NULL;
00096 return ret;
00097 }
00098 else return NULL;
00099 }
00100
00101
00102
00103
00104 expression *exprMul::differentiate (int index) {
00105
00106 expression **als = new expression * [nargs_];
00107 int nonconst = 0;
00108
00109 for (int i = 0; i < nargs_; i++)
00110
00111 if (arglist_ [i] -> dependsOn (index)) {
00112
00113 expression **alm = new expression * [nargs_];
00114
00115 alm [i] = arglist_ [i] -> differentiate (index);
00116
00117 for (int j = 0; j < nargs_; j++)
00118 if (i!=j)
00119 alm [j] = new exprClone (arglist_ [j]);
00120
00121 als [nonconst++] = new exprMul (alm, nargs_);
00122 }
00123
00124 if (nonconst)
00125 return new exprSum (als, nonconst);
00126 else {
00127 delete [] als;
00128 return new exprConst (0.);
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 int exprMul::Linearity () {
00142
00143 int lin0 = arglist_ [0] -> Linearity ();
00144
00145 if (lin0 >= NONLINEAR) return NONLINEAR;
00146 if (lin0 == ZERO) return ZERO;
00147
00148 for (register int i=1; i<nargs_; i++) {
00149
00150 int lin = arglist_ [i] -> Linearity ();
00151
00152 switch (lin) {
00153 case NONLINEAR: return NONLINEAR;
00154 case ZERO: return ZERO;
00155 case LINEAR: lin0++; break;
00156 case QUADRATIC: lin0 += 2; break;
00157 default: break;
00158 }
00159
00160 if (lin0 >= NONLINEAR) return NONLINEAR;
00161 }
00162 return lin0;
00163 }
00164
00165
00167 void exprMul::closestFeasible (expression *varind,
00168 expression *vardep,
00169 CouNumber &left,
00170 CouNumber &right) const {
00171
00172 expression *varoth = arglist_ [0];
00173
00174 if (varoth -> Index () == varind -> Index ())
00175 varoth = arglist_ [1];
00176
00177 assert (varoth -> Index () >= 0);
00178
00179 CouNumber
00180 x = (*varind) (),
00181 y = (*vardep) (),
00182 c = (*varoth) ();
00183
00184 if (c < 0.)
00185 if (y < c*x) {assert (y/c >= right); right = y/c;}
00186 else {assert (y/c <= left); left = y/c;}
00187 else if (c > 0.)
00188 if (y < c*x) {assert (y/c <= left); left = y/c;}
00189 else {assert (y/c >= right); right = y/c;}
00190 else left = - (right = COIN_DBL_MAX);
00191 }
00192
00193
00195 CouNumber exprMul::gradientNorm (const double *x) {
00196
00197 int
00198 ind0 = arglist_ [0] -> Index (),
00199 ind1 = arglist_ [1] -> Index ();
00200
00201 CouNumber
00202 x0 = (ind0 < 0) ? arglist_ [0] -> Value () : x [ind0],
00203 x1 = (ind1 < 0) ? arglist_ [1] -> Value () : x [ind1];
00204
00205 if (ind0 < 0)
00206 if (ind1 < 0) return 0.;
00207 else return fabs (x0);
00208 else
00209 if (ind1 < 0) return fabs (x1);
00210 else return sqrt (x0*x0 + x1*x1);
00211 }
00212