[英]Derivative of a parsed SymPy expression is always 0
I am writing a program that requires the user to enter an expression. 我正在编写一个要求用户输入表达式的程序。 This expression is entered as a string and converted to a Sympy expression using
parse_expr
. 该表达式作为字符串输入,并使用
parse_expr
转换为Sympy表达式。 I then need to take the partial derivative of that expression that the user entered. 然后,我需要采用用户输入的表达式的偏导数。 However,
diff
is returning 0 with every expression I am testing. 但是,
diff
正在测试的每个表达式都返回0。
For example if the user enters a*exp(-b*(xc)**(2))
, using the following code, diff
returns 0
when it should (as far as I know about diff
) return 2*a*b*(c - x)*exp(-b*(x - c)**2)
when taking the partial derivative with respect to x
: 例如,如果用户输入
a*exp(-b*(xc)**(2))
,则使用以下代码,当diff
应该返回2*a*b*(c - x)*exp(-b*(x - c)**2)
时(据我所知diff
), diff
返回0
2*a*b*(c - x)*exp(-b*(x - c)**2)
相对于x
取偏导数时2*a*b*(c - x)*exp(-b*(x - c)**2)
:
a, b, c, x = symbols('a b c x', real=True)
str_expr = "a*exp(-b*(x-c)**(2))"
parsed_expr = parse_expr(str_expr)
result = diff(parsed_expr, x)
print(result) # prints 0
What am I doing wrong? 我究竟做错了什么?
Bottom line: use parse_expr(str_expr,locals())
. 底线:使用
parse_expr(str_expr,locals())
。
Add global_dict=<dict of allowed entities to use>
, too, if the expression may use any entities not imported into the local namespace and not accessible with the default from sympy import *
. 如果表达式可以使用未导入到本地名称空间中且无法使用
from sympy import *
的默认值访问的任何实体,则也添加global_dict=<dict of allowed entities to use>
。
According to Calculus — SymPy Tutorial - SymPy 1.0.1.dev documentation , you type the symbolic expression into the diff()
argument as-is. 根据微积分-SymPy教程-SymPy 1.0.1.dev文档 ,您可以按原样在
diff()
参数中键入符号表达式。 Due to the fact that the letters are Symbol
objects (with overridden operators), Python is tricked into constructing the SymPy object corresponding to the expression as it evaluates the argument! 由于字母是
Symbol
对象(带有重写的运算符),因此Python在计算参数时被欺骗构造与表达式相对应的SymPy对象!
Thus, if you have it as a string, you eval
it to trigger the same behaviour: 因此,如果将其作为字符串,则可以
eval
它以触发相同的行为:
<...>
>>> s="a*exp(-b*(x-c)**(2))"
>>> diff(eval(s), x)
−ab(−2c+2x)e−b(−c+x)2
But eval
is a security hazard if used with untrusted input because it accepts arbitrary Python code. 但是,如果
eval
与不受信任的输入一起使用,则会造成安全隐患,因为它接受任意Python代码。
This is where replacements like parse_expr
come into play. 这是诸如
parse_expr
替代品发挥作用的地方。 However, due to the way expressions are parsed, described above, it needs access to the external entities used in the expression - like the Symbol
objects for variables and function objects for the named functions used - through the local_dict
and global_dict
arguments. 但是,由于如上所述解析表达式的方式,它需要通过
local_dict
和global_dict
参数访问表达式中使用的外部实体,例如变量的Symbol
对象和所使用的命名函数的function对象。
Otherwise, it creates the Symbol
objects on the fly. 否则,它将动态创建
Symbol
对象。 Which means, the Symbol
object it has created for x
in the expression is different from the variable x
! 这意味着,它为表达式中的
x
创建的Symbol
对象与变量x
不同! No wonder that the derivative over it is 0! 难怪它的导数是0!
<...>
>>> ps=parse_expr(s)
>>> ps.free_symbols
{a,b,c,x}
>>> x in _
False
>>> diff(ps,x)
0
>>> ps=parse_expr(s,locals())
>>> x in ps.free_symbols
True
>>> diff(ps,x)
-ab(−2c+2x)e−b(−c+x)2
Work is ongoing to make sympify
safer than eval
. 使
sympify
比eval
更安全的工作正在进行中。 Better to use something like the following: 最好使用如下所示的内容:
from sympy import *
var ('a b c x')
str_expr = "a*exp(-b*(x-c)**(2))"
parsed_expr = sympify(str_expr)
result = diff(parsed_expr, x)
print(result)
Result: 结果:
-a*b*(-2*c + 2*x)*exp(-b*(-c + x)**2)
Replace a, b, c, x = symbols('abc x', real=True)
with: 将
a, b, c, x = symbols('abc x', real=True)
替换为:
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
x = Symbol('x')
Symbols with different assumptions compare unequal: 具有不同假设的符号比较不相等:
>>> Symbol('x') == Symbol('x', real=True)
False
When you use sympify
or parse_expr
, it parses unknown variables as symbols without assumptions. 当您使用
sympify
或parse_expr
,它将在不假设的情况下将未知变量解析为符号。 In your case, this creates Symbol('x')
, which is considered distinct from the Symbol('x', real=True)
you already created. 在您的情况下,这将创建
Symbol('x')
,这被认为与您已经创建的Symbol('x', real=True)
。
The solution is to either remove the assumptions, or include the locals()
dictionary when you parse, so that it recognizes the name x
as being the Symbol('x', real=True)
that you already defined, like 解决方案是删除假设,或者在解析时包括
locals()
字典,以便它将名称x
识别为您已经定义的Symbol('x', real=True)
,例如
parse_expr(str_expr,locals())
or 要么
sympify(str_expr, locals())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.