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