/home/coin/SVN-release/OS-2.1.1/Couenne/src/expression/operators/exprMul.cpp

Go to the documentation of this file.
00001 /* $Id: exprMul.cpp 217 2009-07-08 17:02:07Z pbelotti $
00002  *
00003  * Name:    exprMul.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: definition of multiplications
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Common Public License (CPL)
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) { //< non-leaf expression, with argument list
00025 
00026   // commutative operator, sort elements
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     // check for null operands in multiplications
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       // check for nonzero constants in multiplications
00084 
00085       delete arglist_ [i];
00086       arglist_ [i] = NULL;
00087     }
00088   }
00089   /*
00090   if (found_one && shrink_arglist (prod, 1))
00091     return new exprConst (arglist_ [0] -> Value ());
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 // differentiate product of expressions
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 // get a measure of "how linear" the expression is:
00134 //
00135 // ZERO      = 0: constant 0
00136 // CONSTANT  = 1: a constant
00137 // LINEAR    = 2: linear
00138 // QUADRATIC = 3: quadratic
00139 // NONLINER  = 4: nonlinear non-quadratic
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]; // suppose $w = cy$;
00173 
00174   if (varoth -> Index () == varind -> Index ())
00175     varoth = arglist_ [1]; // actually no, it's $w = x*c$
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.;                   // c*d
00207     else          return fabs (x0);            // c*y
00208   else 
00209     if (ind1 < 0) return fabs (x1);            // x*d
00210     else          return sqrt (x0*x0 + x1*x1); // x*y
00211 }
00212 

Generated on Mon May 3 03:05:20 2010 by  doxygen 1.4.7