Simplifying by replacing expressions?



[edA-qa mort-ora-y <eda-qa@disemia.com>, Thu, 23 Sep 2004 14:28:51 +0200]:
> I want to achieve the following:
> 	
> 	Given: (x+y+z)*c
> 	Simplify Where: a=x+y
> 	Result: (a+z)*c

subst(a-x, y, (x+y+z)*c) ==> c*(z+a)

Of course this only works when you can solve the "Where" equation for
one of the parameters.

> Ultimately I want to be able to group a lot of terms together in an
> equation (as they are constants which can be precalculated).  That is,
> a larger example:
> 
> 	q:(a+b/c+i)/(a+b)-(d-e-f)*i;
> 	constreplace(q,a,b,c,d,e,f)
> 		c1 = ...
> 		c2 = ...
> 		q = c1 + c2 * i

One way is to walk down the expression, determine for each
subexpression whether it is constant, and generate something of this
kind.  Something to start with:

constWalk(expr,[consts]) :=
  block([found: [], nfound: 0],
    [second(cw(expr)), found]) ;

cw(expr) :=
  if atom(expr)
  then 
    if member(expr, consts)
    then [true, expr]
    else [false, expr]
  else
    block([foo : maplist(cw, args(expr))],
        if apply("and", maplist(first, foo))
        then block([sym : concat(const, nfound: nfound + 1)],
                found: cons([sym, expr], found),
                consts: cons(sym, consts),
                [ true, sym ])
        else [ false, apply(inpart(expr,0), maplist(second, foo)) ]) ;

constWalk((a+b/c+i)/(a+b)-(d-e-f)*i,a,b,c,d,e,f) ==> 
   [const2*(i+const1+a)+const5*i,
       [[const5,-f-e+d],[const4,-e],[const3,-f],[const2,b+a],[const1,b/c]]]

Of course one should use commutativity and associativity of addition
to turn (i+const1+a) into (i + const6), where const6 = const1+a:
Basically you have to recognize those functions and split their
arguments into groups that are constant and those that are not.

Albert.