使用 sympy 解析字符串时的意外行为
Unexpected behaviour when parsing string with sympy
我正在尝试使用 sympy 执行方程式的导数,但是,如果我手写方程式,则导数是正确的;当我将等式作为字符串传递时,输出是错误的。谁能解释我如何解决这个问题?我正在使用 python 3.6 和 sympy 1.5.1.
>>>from sympy import *
>>>from operator import *
>>> x1 = symbols('x1')
>>> f = add(sin(x1), mul(x1, x1))
>>> diff(f, x1)
2*x1 + cos(x1) ## Correct output
>>>> f = 'add(sin(x1), mul(x1, x1))' ## Equation provided as string
>>>> diff(f, x1)
(Subs(Derivative(mul(_xi_1, x1), _xi_1), _xi_1, x1) + Subs(Derivative(mul(x1, _xi_2), _xi_2), _xi_2, x1))*Subs(Derivative(add(sin(x1), _xi_2), _xi_2), _xi_2, mul(x1, x1)) + cos(x1)*Subs(Derivative(add(_xi_1, mul(x1, x1)), _xi_1), _xi_1, sin(x1)) ## Wrong output
发生这种情况是因为 f = 'add(sin(x1), mul(x1, x1))'
不是 parse_expr
可以解析的有效数学方程式。此函数旨在解析以数学语法编写的方程式,而不是 Sympy 函数。要特别正确地解析此函数,您需要使用,例如:
>>> f = 'sin(x1) + x1^2'
>>> diff(f, x1)
2*x1 + cos(x1)
如果你真的需要使用那个特定的字符串,你可以使用 eval()
:
>>> f = 'add(sin(x1), mul(x1, x1))'
>>> diff(eval(f), x1)
2*x1 + cos(x1)
如果您想以这种方式编写它,请务必使用实际的 SymPy 对象名称(大写)。我使用 S(...)
来解释表达式,这与任何函数都会做的事情一样:
>>> S('Add(sin(x1), Mul(x1, x1))')
x1**2 + sin(x1)
但您也可以使用数学运算符 +
和 *
:
>>> S('sin(x1) + x1*x1')
x1**2 + sin(x1)
您不应将字符串直接传递给 SymPy 函数。相反,首先用 sympify
解析它们(与 S
相同)。如果您希望 add
等非标准名称映射到现有的 SymPy 名称,例如
,则可以将名称字典作为第二个参数传递给 sympify
sympify('add(x, y)', {'add': Add}) # Gives x + y
否则 sympify 将假设任何未知函数都是未定义的函数,如 f(x)。
Sympy 提供了将字符串转换为 sympy 对象的解析器函数,请参阅文档 parse_expr。
对于自定义函数翻译,您可以使用 sympy 提供的映射映射,并将其作为参数 local_dict
传递给解析器。
from sympy import Add, Mul, sin
from sympy.parsing.sympy_parser import parse_expr
f = parse_expr('add(sin(x1), mul(x1, x1))', local_dict={'add': Add, 'mul': Mul})
f.diff('x1')
输出
2x1 + cos(x1)
我正在尝试使用 sympy 执行方程式的导数,但是,如果我手写方程式,则导数是正确的;当我将等式作为字符串传递时,输出是错误的。谁能解释我如何解决这个问题?我正在使用 python 3.6 和 sympy 1.5.1.
>>>from sympy import *
>>>from operator import *
>>> x1 = symbols('x1')
>>> f = add(sin(x1), mul(x1, x1))
>>> diff(f, x1)
2*x1 + cos(x1) ## Correct output
>>>> f = 'add(sin(x1), mul(x1, x1))' ## Equation provided as string
>>>> diff(f, x1)
(Subs(Derivative(mul(_xi_1, x1), _xi_1), _xi_1, x1) + Subs(Derivative(mul(x1, _xi_2), _xi_2), _xi_2, x1))*Subs(Derivative(add(sin(x1), _xi_2), _xi_2), _xi_2, mul(x1, x1)) + cos(x1)*Subs(Derivative(add(_xi_1, mul(x1, x1)), _xi_1), _xi_1, sin(x1)) ## Wrong output
发生这种情况是因为 f = 'add(sin(x1), mul(x1, x1))'
不是 parse_expr
可以解析的有效数学方程式。此函数旨在解析以数学语法编写的方程式,而不是 Sympy 函数。要特别正确地解析此函数,您需要使用,例如:
>>> f = 'sin(x1) + x1^2'
>>> diff(f, x1)
2*x1 + cos(x1)
如果你真的需要使用那个特定的字符串,你可以使用 eval()
:
>>> f = 'add(sin(x1), mul(x1, x1))'
>>> diff(eval(f), x1)
2*x1 + cos(x1)
如果您想以这种方式编写它,请务必使用实际的 SymPy 对象名称(大写)。我使用 S(...)
来解释表达式,这与任何函数都会做的事情一样:
>>> S('Add(sin(x1), Mul(x1, x1))')
x1**2 + sin(x1)
但您也可以使用数学运算符 +
和 *
:
>>> S('sin(x1) + x1*x1')
x1**2 + sin(x1)
您不应将字符串直接传递给 SymPy 函数。相反,首先用 sympify
解析它们(与 S
相同)。如果您希望 add
等非标准名称映射到现有的 SymPy 名称,例如
sympify
sympify('add(x, y)', {'add': Add}) # Gives x + y
否则 sympify 将假设任何未知函数都是未定义的函数,如 f(x)。
Sympy 提供了将字符串转换为 sympy 对象的解析器函数,请参阅文档 parse_expr。
对于自定义函数翻译,您可以使用 sympy 提供的映射映射,并将其作为参数 local_dict
传递给解析器。
from sympy import Add, Mul, sin
from sympy.parsing.sympy_parser import parse_expr
f = parse_expr('add(sin(x1), mul(x1, x1))', local_dict={'add': Add, 'mul': Mul})
f.diff('x1')
输出
2x1 + cos(x1)