首页 > 解决方案 > SymPy 中的相同表达式不是 ==

问题描述

我在 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已经有些痛苦了,因为我正在尝试对一个通过独立构造它们来构造一堆符号表达式的例程进行单元测试。

标签: pythonsympy

解决方案


有几种方法可以解决这个问题。

修复 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),所以Function('f')sp.srepr(by_hand)sp.Function(f),或sp.Function(sp.Symbol('f'))

另一方面,Function('f')insp.srepr(from_string)sp.Function('f')
(这导致我们修复 2。)

不同之处在于sp.Function(sp.Symbol('f'))继承了 的默认假设{'commutative': True}。 (这导致我们修复 3。)sp.Symbol('f')

修复 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

这个 hack 演示了{'commutative': True}Fix 1 中确定的继承假设。

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

推荐阅读