【发布时间】:2016-06-15 12:55:33
【问题描述】:
考虑python/sympy中的以下表达式:
from sympy.abc import x, y
expression = 3*x**2*y**1 + x**2*y**3
现在我想通过使用模式匹配将x**n*y**m 替换为max(n,m):
from sympy import Wild
n = Wild('n')
m = Wild('m')
expression = expression.replace(x**n*y**m,max(n,m))
但是,我收到了TypeError:
Traceback (most recent call last):
File "wild.py", line 15, in <module>
expression = expression.replace(x**n*y**m,max(n,m))
File "/usr/lib/python3/dist-packages/sympy/core/relational.py", line 103, in __nonzero__
raise TypeError("cannot determine truth value of\n%s" % self)
TypeError: cannot determine truth value of
m_ > n_
问题显然是在匹配表达式时,sympy 不会在将 Wild 符号的值转发到 max-函数之前将其转换为匹配的值。有什么办法可以做到吗?
请注意,这是我遇到的更普遍问题的一个简单示例,因此不能很好地概括的解决方法不是很有帮助。特别希望有使用表达式匹配的解决方案。
更新:按照 Sandwich 的建议,将 max(n,m) 替换为 (m+n+abs(m-n))/2 是可行的,但是,我在实际程序中使用的函数要复杂得多。
关于三明治提到的问题,replace 从表达式树的底部开始执行替换:如果我使用exact=True 并定义f = sympy.Function('f'),则以下工作(除了我将不得不单独处理某些情况):
expression = expression.replace(x**n*y**m,f(n,m),exact=True)
但是,它仍然不适用于max(n,m)。
【问题讨论】:
-
用数学上等效的
(m+n+abs(m-n))/2替换max(m,n)有助于解决您遇到的错误。但是还有一个更大的问题,replace从表达式树的底部开始执行替换。因此,x**2*y**3将替换为 1,因为它是x*x*y*y*y,其中五个术语中的每一个都替换为 1。 -
@soup
x**2*y**3表示为Mul(Pow(x, 2), Pow(y, 3)),而不是Mul(x, x, y, y, y)。实际上,表示后者的唯一方法是使用evaluate=False显式创建它。
标签: python python-3.x sympy