简体   繁体   English

将 sympy 中命名表达式的字符串转换为表达式本身

[英]Convert string of a named expression in sympy to the expression itself

Description of the practical problem :实际问题描述
I have defined many expression using sympy , as in我已经使用sympy定义了许多表达式,如

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 (eg, charles , bob ) within categories (eg, X ).所以我使用表达式的名称来描述类别(例如X )中的选项(例如charlesbob )。

Now I want a function that takes two strings (eg, '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.现在我想要一个 function 接受两个字符串(例如, 'Xcharles_YclassA_Zregion1''Xbob_YclassA_Zregion1' )并返回其简化比率(在本例中为1.00000099009999 ),因此我可以快速检查它们在结果方面的“差异”,不是根据它们的书写方式。 Eg, 2*a and a*2 are the same for my objective.例如, 2*aa*2对于我的目标是相同的。

How can I achieve this?我怎样才能做到这一点?

Notes :注意事项

  1. 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.但在我的实际情况中,它们来自许多其他表达式和操作的序列。
  2. Not all combinations of options for all categories would exist.并非所有类别的所有选项组合都会存在。 Eg, Xcharles_YclassA_Zregion2 may not exist.例如, Xcharles_YclassA_Zregion2可能不存在。 Actually, if I were to write a table for existing expression names, it would be sparsely filled.实际上,如果我要为现有的表达式名称编写一个表,它会被稀疏地填充。
  3. I guess rewriting my code using dict to store the table might solve my problem.我想使用dict重写我的代码来存储表可能会解决我的问题。 But I would have to modify a lot of code for that.但是我必须为此修改很多代码。
  4. 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 .除了我的目标的实际方面,我不知道Symbol (这是一个特定的类)和expression之间是否有任何形式上的区别。 From the sources I read (eg, this ) I did not arrive to a conclusion.从我阅读的资料(例如, 这个)我没有得出结论。 This understanding may help in solving the question.这种理解可能有助于解决问题。

TL;DR - What I tried TL;DR - 我试过的

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 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 .我需要一些接受字符串'expr2'并返回表达式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):没有帮助的问题或链接(至少对我而言):

  1. From string to sympy expression 从字符串到 sympy 表达式
  2. https://docs.sympy.org/latest/tutorials/intro-tutorial/basic_operations.html https://docs.sympy.org/latest/tutorials/intro-tutorial/basic_operations.html
  3. https://docs.sympy.org/latest/modules/parsing.html https://docs.sympy.org/latest/modules/parsing.html
  4. https://docs.sympy.org/latest/modules/core.html#sympy.core.sympify.sympify https://docs.sympy.org/latest/modules/core.html#sympy.core.sympify.sympify
  5. https://docs.sympy.org/latest/tutorials/intro-tutorial/manipulation.html https://docs.sympy.org/latest/tutorials/intro-tutorial/manipulation.html

If, when parsing, you want to use the expression that has been mapped to a variable you have to pass the dictionary that python uses to keep track of those mappings, ie locals()如果在解析时要使用已映射到变量的表达式,则必须传递 python 用来跟踪这些映射的字典,即locals()

>>> from sympy.abc import x
>>> from sympy import sympify, parse_expr
>>> y = x + 2
>>> sympify('y')
y
>>> sympify('y', locals=locals())
x + 2
>>> parse_expr('y', local_dict=locals())
x + 2

As suggested by Oscar Benjamin from the Sympy Google group, eval does the job正如 Sympy Google 小组的 Oscar Benjamin 所建议的那样, eval完成了这项工作

def verify_ratio(vstr1, vstr2):
    """Compare the result of two different computations of the same quantity"""
    print(vstr1 + ' / ' + vstr2, '=', eval(vstr1 + ' / ' + vstr2))
    return

What shows this would work is表明这行得通的是

>>> import sys
>>> import sympy as sp
>>> a, b = sp.symbols('a,b', real=True, positive=True)
>>> a is eval('a')
True

In my case, all expressions and symbols I am using in vstr1 and vstr2 are global.就我而言,我在vstr1vstr2中使用的所有表达式和符号都是全局的。 If nesting within other functions, I might need to pass further parameters to verify_ratio , as in the solution by smichr.如果嵌套在其他函数中,我可能需要将更多参数传递给verify_ratio ,就像 smichr 的解决方案一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM