Description of the practical problem:
I have defined many expression using sympy
, as in
import sympy as sp
a, b = sp.symbols('a,b', real=True, positive=True)
Xcharles_YclassA_Zregion1 = 1.01 * a**1.01 * b**0.99
Xbob_YclassA_Zregion1 = 1.009999 * a**1.01 * b**0.99
Xbob_YclassA_Zregion2 = 1.009999 * a**1.01 * b**0.99000000001
...
So I have used the names of the expressions to describe options (e.g., charles
, bob
) within categories (e.g., X
).
Now I want a function that takes two strings (e.g., 'Xcharles_YclassA_Zregion1'
and 'Xbob_YclassA_Zregion1'
) and returns its simplified ratio (in this example, 1.00000099009999
), so I can quickly check "how different" they are, in terms of result, not in terms of how they are written.
E.g., 2*a
and a*2
are the same for my objective.
How can I achieve this?
Notes:
- The expressions in the example are hardcoded for the sake of simplicity. But in my actual case they come from a sequence of many other expressions and operations.
- Not all combinations of options for all categories would exist. E.g.,
Xcharles_YclassA_Zregion2
may not exist. Actually, if I were to write a table for existing expression names, it would be sparsely filled. - I guess rewriting my code using
dict
to store the table might solve my problem. But I would have to modify a lot of code for that. - Besides the practical aspects of my objective, I don't know if there is any formal difference between
Symbol
(which is a specific class) and expression. From the sources I read (e.g., this) I did not arrive to a conclusion. This understanding may help in solving the question.
TL;DR - What I tried
I aimed at something like
def verify_ratio(vstr1, vstr2):
"""Compare the result of two different computations of the same quantity"""
ratio = sp.N(sp.parsing.sympy_parser.parse_expr(vstr1)) / sp.parsing.sympy_parser.parse_expr(vstr2)
print(vstr1 + ' / ' + vstr2, '=', sp.N(ratio))
return
This did not work. Code below shows why
import sympy as sp
a, b = sp.symbols('a,b', real=True, positive=True)
expr2 = 1.01 * a**1.01 * b**0.99
print(type(expr2), '->', expr2)
expr2b = sp.parsing.sympy_parser.parse_expr('expr2')
print(type(expr2b), '->', expr2b)
expr2c = sp.N(sp.parsing.sympy_parser.parse_expr('expr2'))
print(type(expr2c), '->', expr2c)
#print(sp.N(sp.parsing.sympy_parser.parse_expr('expr2')))
expr2d = sp.sympify('expr2')
print(type(expr2d), '->', expr2d)
with output
<class 'sympy.core.mul.Mul'> -> 1.01*a**1.01*b**0.99
<class 'sympy.core.symbol.Symbol'> -> expr2
<class 'sympy.core.symbol.Symbol'> -> expr2
<class 'sympy.core.symbol.Symbol'> -> expr2
I need something that takes the string 'expr2'
and returns the expression 1.01 * a**1.01 * b**0.99
.
None of my attempts achieved the objective. Questions or links which did not help (at least for me):
- From string to sympy expression
- https://docs.sympy.org/latest/tutorials/intro-tutorial/basic_operations.html
- https://docs.sympy.org/latest/modules/parsing.html
- https://docs.sympy.org/latest/modules/core.html#sympy.core.sympify.sympify
- https://docs.sympy.org/latest/tutorials/intro-tutorial/manipulation.html