如何解决SymPy:如何实现对几个“相似”术语的一般替换?
我搜索了很多问题,老实说,找不到适合我的情况的内容。
我正在使用 SymPy 库来执行大型计算,并且它运行得非常好。然而,我最近的结果变得太复杂了。所以,我开始实现更多的定义和符号,以执行多次替换并将表达式缩小到更可行的形式。对于很多术语,我已经能够“手动”执行此操作,这些术语太过特殊,无法进行任何类型的自动化。但是,如果我可以运行这个简单的替换规则,我的表达式中有一系列特定的贡献可以大大简化。
让 A 成为我的完整表达。在 this image 中,点代表已经简化的术语,总和代表我的查询背后的一般设置。我的目标是像 this 一样重写它。
T_k 只是表示通用术语;实际上,它们是由几个字面量 Symbols
组成的。在我的代码中,rho 字母与单个变量 Symbol
类型相关联。因此,话虽如此,我的问题可以举例如下:
# sympy symbols: rho,a,b,c,d
# sympy functions: f,g,h
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
# apply some clever substitution method ???
A.subs(???)
>>> f(a * b) * rho + g(c * d) * rho + h(a * c * d * b) * rho
当然,在上面的例子中,我可以“手工”完成。当有很多这样的术语时,问题就出现了。我尝试使用 lambda
表达式实现我的目标,但无法实现。这个想法是:对于任何泛型 lambda t
,我可以尝试为每个符号函数 ({t * f(rho) : f(t) * rho}
) 输入映射 # f,h
,但不关心特定的伴随术语。
我尝试定义,例如,genSub_f = lambda t: A.subs(t * f(rho),f(t) * rho)
。但是,为了进行替换,我必须调用 genSub_f(a * b)
,这可行,但这是不切实际的,因为必须保留有关与 {{1} 一起出现的符号组合的先验知识}.如何进行?
解决方法
您可以为此使用 Wild
符号,但有几种方法可以获得所需的输出。
一个复杂的问题是您似乎不想应用替换
f(a*b)*rho -> f(a*b*rho)
。有几种方法可以实现这一点,但首先我会给出一个确实会导致这种替换的答案:
from sympy import *
rho,a,b,c,d = symbols("rho,d")
f,g,h = symbols("f,h",cls=Function)
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1,w2 = symbols("w1,w2",cls=Wild)
for ff in [f,h]:
A = A.replace(w1*ff(w2),w2*ff(w1))
print(A) # f(a*b*rho) + g(c*d*rho) + h(a*b*c*d*rho)
那么排除替换 rho*f(a*b) -> f(a*b*rho)
怎么样?
一种方法是通过像这样定义您的 rho
符号 Wild
从 Wild
匹配中排除 w1
(我们还必须排除替换 1*f(...) -> ...*f(1)
)。这会产生您想要的输出:
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1 = Wild("w1",exclude=[rho,1]) # exclude unwanted substitutions
w2 = Wild("w2")
for ff in [f,w2*ff(w1))
print(A) # rho*f(a*b) + rho*g(c*d) + rho*h(a*b*c*d)
然而,实现您想要的输出的另一种方法是使用 match
而不是 replace
。这样您就不必明确排除 rho
(使用这种方法替换是手动完成的,因此无需担心避免替换规则的“双重”应用):
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1,w2,w3 = symbols("w1,w3",h]:
m = A.match(w1*ff(w2) + w3)
if m:
A = m[w2]*ff(m[w1]) + m[w3] # manual replacement
print(A) # rho*f(a*b) + rho*g(c*d) + rho*h(a*b*c*d)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。