[GiNaC-list] Re: Disabling flattening of sums and products?

Martin Sandve Alnæs martinal at simula.no
Thu Nov 15 10:03:47 CET 2007


2007/11/14, Alexei Sheplyakov <varg at theor.jinr.ru>:
> Hello!
>
> On Wed, Nov 14, 2007 at 02:38:44PM +0100, Martin Sandve Alnæs wrote:
> > Is it possible to disable the automatic flattening of expressions like
> > f = (x+y) + (x+y)
> > into
> > g = 2*y+2*x
> > ?
>
> No.
>
> > In other words, I want to be able to retain the additions in
> > expression f as binary operators.
>
> And GiNaC wants to 1) canonicalize the tree (expression), 2) make
> the tree as flat as possible, so large expressions can be stored
> reasonably well.

Ok. (I think SymPy has a flag to switch behaviour on this one.)

> > The reason for this is that I want
> > to examine some expression to detect subtrees that occur multiple
> > times,
>
> ex::to_polynomial() does somethings similar, so you might want to look
> how different classes implement this method (see the ginac/normal.cpp file).

Good idea, will do.

> N.B.: the concept is a bit ill-defined: it depends not on the mathematical
> properties of the expression in question, but on its internal representation.
> E.g. is x*y a subtree of x^2*y?

I'm aware of that, I've already experimented with things like this a bit.

> > and this automatic flattening destroys some opportunities for
> > this.
>
> Not flattening the tree destroys some opportunities for this. Example:

Sure, it depends very much on the structure of the expressions, like
you said above. But with some experience with the particular
application in question, I know that some large expressions often
occur multiple times, but the flattening hides their equality.

> a = c*x^2*y
> b = (c*x)*(x*y)
>
> > Example:
> >
> > a = x*y
> > b = (x*y) * (x*y)
>
> #include <ginac/ginac.h>
> #include <iostream>
> using namespace std;
> using namespace GiNaC;
>
> int main(int argc, char** argv) {
>         symbol x("x"), y("y"), t("t");
>         ex a = x*y;
>         ex b = (x*y)*(x*y);
>         cout << "b = " << b << endl;
>         // b = y^2*x^2
>         symbol foo;
>         b = b.subs(a == foo, subs_options::algebraic);
>         cout << "b = " << b << " with: " << foo << " = " << a << endl;
>         // b = symbol4^2 with: symbol4 = y*x
>         return 0;
> }

That's useful. Thanks, I didn't know that.

-- 
Martin


More information about the GiNaC-list mailing list