Disabling flattening of sums and products?
Is it possible to disable the automatic flattening of expressions like f = (x+y) + (x+y) into g = 2*y+2*x ? In other words, I want to be able to retain the additions in expression f as binary operators. The reason for this is that I want to examine some expression to detect subtrees that occur multiple times, and this automatic flattening destroys some opportunities for this. Example: a = x*y b = (x*y) * (x*y) Examining a I will see a mul with ops x,y, while examining b I will see a mul with ops power(y,2), power(x,2), requiring some kind of factorization to recognize the similarities. -- Martin
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.
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). 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?
and this automatic flattening destroys some opportunities for this.
Not flattening the tree destroys some opportunities for this. Example: 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; } Best regards, Alexei -- All science is either physics or stamp collecting.
2007/11/14, Alexei Sheplyakov <varg@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
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.)
SymPy works the same way as GiNaC, so it doesn't. Sympycore tries to implement it, but it's a lot of work and I personally don't think it's worth the pain. Ondrej
participants (3)
-
Alexei Sheplyakov
-
Martin Sandve Alnæs
-
Ondrej Certik