我在SymPy中有两个结构相同的表达式,它们以不同的方式创建:
import sympy as sp
f = sp.Symbol('f')
x = sp.Symbol('x')
by_hand = sp.Function(f)(x)
from_string = sp.sympify('f(x)')
尽管两者在结构上是相同的表达式,但它们不是==
:
by_hand == from_string
# False
事实上,SymPy甚至不知道它们在符号上是相等的:
sp.simplify(by_hand - from_string)
# ( )− ( )
两者具有相同的srepr
s:
(sp.srepr(by_hand), sp.srepr(from_string))
# ("Function('f')(Symbol('x'))", "Function('f')(Symbol('x'))")
sp.srepr(by_hand) == sp.srepr(from_string)
# True
我知道在SymPy中维护身份不需要可靠的字符串往返,但即使使用locals
参数作为修复也不能解决这个问题:
by_hand == sp.sympify('f(x)', locals={'f': f}) == by_hand
# False
必须使用locals
已经有些痛苦了,因为我正在尝试对一个例程进行单元测试,该例程通过独立构建符号表达式来构建一堆符号表达式。
有几种方法可以解决这个问题。
修复1
传递locals={'f': sp.Function(f)}
而不是locals={'f': f}
。
by_hand = sp.Function(f)(x)
from_string = sp.sympify('f(x)')
# by_hand == sp.sympify('f(x)', locals={'f': f}) # Change this
by_hand == sp.sympify('f(x)', locals={'f': sp.Function(f)}) # True # to this
您定义了by_hand = sp.Function(f)(x)
,因此sp.srepr(by_hand)
中的Function('f')
是sp.Function(f)
或sp.Function(sp.Symbol('f'))
。
另一方面,sp.srepr(from_string)
中的Function('f')
是sp.Function('f')
(这导致我们修复2。)
不同之处在于sp.Function(sp.Symbol('f'))
继承了sp.Symbol('f')
的默认假设{'commutative': True}
(这导致我们修复3.)
修复2
这是一个干净的解决方案,可能是你想要的。
# f = sp.Symbol('f') # Change this
f = sp.Function('f') # to this
x = sp.Symbol('x')
# by_hand = sp.Function(f)(x) # Change this
by_hand = f(x) # to this
from_string = sp.sympify('f(x)')
by_hand == from_string # True
修复3
该破解演示了Fix 1中确定的继承假设{'commutative': True}
。
by_hand = sp.Function(f)(x)
del by_hand._kwargs['commutative'] # Add this
# del by_hand._assumptions['commutative'] # Add this, optional
from_string = sp.sympify('f(x)')
by_hand == from_string # True