Reza
Reza

Reputation: 43

Abstract representation of expressions in SymPy

Consider these two equations:

x^y + xy

a^b + ab

I want to be able to recognize these as identical symbolic expressions. "Simplify" won't work. "Subs" (substituting a for x, etc.) won't always work either because the order of the variables may change, etc.

So, is there a way to get an abstract representation for a SymPy expression that is independent of the symbols used?

Upvotes: 3

Views: 175

Answers (2)

Reza
Reza

Reputation: 43

Just to elaborate a bit:

I wasn't too happy with the permutation approach. So, I kept digging and I noticed that SymPy generates a tree graph to represent the symbolic expressions. The structure of the tree is the structure of the expression, and it is independent of the symbols. However, once you have the corresponding graphs, you will need to decide whether they are isomorphic (i.e. if the two expressions are identical), which is a very non-trivial problem.

Upvotes: 1

user6655984
user6655984

Reputation:

A representation that is not tied to the symbols used is a function. For example,

f1 = lambda x, y: (2*x+y)**2 

defines a function that is not tied to x and y, they don't exist other than as placeholders inside of this function. (This is a Python function; one can also define a SymPy Function object but the distinction is not material here.)

If someone asked you whether (2*x+y)**2 is "identical" to a**2 + 4*b*(a+b), what would you do? The only way I know is to simplify both and try to match variables under all possible permutations. Which is what the following code does.

from sympy import *
from itertools import permutations
f1 = lambda x, y: (2*x+y)**2
f2 = lambda a, b: a**2 + 4*b*(a+b)
vars = symbols("v0:2")    # auxiliary variables to plug in f1 and f2
identical = any([simplify(f1(*vars) - f2(*p)) == 0 for p in permutations(vars)])

Now identical is True, since the expressions are the same in the sense you described.

If you have expressions, rather than functions, to start with, then subs can be used instead:

x, y, a, b = symbols("x y a b")
expr1 = (2*x+y)**2
expr2 = a**2 + 4*b*(a+b)
vars = symbols("v0:2")
identical = any([simplify(expr1.subs(zip((x, y), vars)) - expr2.subs(zip((a, b), p))) for p in permutations(vars)]) 

Upvotes: 4

Related Questions