我发现在编写
sympy
代码时很难以可重用的方式真正封装大量逻辑
我想用以下方式编写一个函数:
def compute_integral(fn):
s = symbols_new() # do not apply lexicographic identity, this symbol identity is unique
return integrate( fn(s), (s, 0, 1))
如果我只是使用通常的
symbols()
来实例化 s
,我就有可能在定义表达式中的某处使用 fn
相同的符号,例如可能会发生以下情况:
def compute_integral(fn):
s = symbols("s")
return integrate(fn(s), (s, 0, 1))
...
import sympy as sp
from sympy.abc import *
t = sp.sin(3 + s)
f = sp.lambdify([x], x**2 + t * s * x)
compute_integral(f) #< ---- symbol s is already present in the function, now the integral will produce the wrong result
我现在为尽量减少这个问题所做的事情并不理想:
compute_integral_local_var = 0
def compute_integral(fn):
global compute_integral_local_var
compute_integral_local_var += 1
s = symbols("local_{}".format(compute_integral_local_var))
return integrate(fn(s), (s, 0, 1))
我想避免此类冲突,而不必添加特殊的全局变量。有没有更好的方法可以在
sympy
API 中实现这种类型的封装?
我正在使用最新的 sympy,版本 1.13.2,并且您提供的代码块无法运行:它会引发错误。
似乎有一些误解,我想澄清一下。考虑这个代码块:
import sympy as sp
from sympy.abc import s, x
t = sp.sin(3 + s)
print("t:", t)
e = x**2 + t * s * x
print("e:", e)
# t: sin(s + 3)
# e: s*x*sin(s + 3) + x**2
在这里,我创建了两个符号表达式,
t
和e
。 t
包含符号函数sin
,e
由t
组成。您可以将 e
视为一个函数,但在 sympy 术语中,e
是一个符号表达式。
接下来,在您的示例中,您执行了如下操作:
f = sp.lambdify([x], e)
创建一个由 NumPy 计算的数值函数。然后,您尝试对这个数值函数进行符号积分,这是绝对错误的。使用 SymPy,您只能执行符号表达式的符号积分。
如果您尝试执行的只是符号积分,那么此命令就足够了:
sp.integrate(e, (x, 0, 1))
# s*sin(s + 3)/2 + 1/3
如果您想集成同一范围内的多个符号表达式,那么您可以创建自定义函数:
def compute_integral(expr, sym):
return sp.integrate(expr, (sym, 0, 1))
print(compute_integral(e, x))
# s*sin(s + 3)/2 + 1/3
print(compute_integral(t, x))
# sin(s + 3)