2

有没有办法为具有任意数量参数的函数 f 编写替换规则,使其在所有参数中都是线性的?当 f 具有三个参数时的示例:

  1. f( x1+x4 , x2 , x3 ) = f(x4,x2,x3) + f(x1,x2,x3)
  2. f( x1 , x2+x4 , x3 ) = f(x1,x2,x3) + f(x1,x4,x3)
  3. f( x1 , x2 , x3+x4 ) = f(x1,x2,x3) + f(x1,x2,x4)

使用“Wild”部分工作:

from sympy import *
f=Function('f')
var("x1:5")
a=Wild("a")
b=Wild("b")
A=Wild('A', exclude=[0])
B=Wild('B', exclude=[0])
expr=f(x1,x2+x4,x3);
print("This one works")
print expr , '->' , expr.replace(f(a,Add(A,B),b),f(a,A,b)+f(a,B,b))
# f(x1, x2 + x4, x3) -> f(x1, x2, x3) + f(x1, x4, x3)
print("This one doesn't on the last entry")
expr=f(x1,x2,x3+x4);
print f(x1,x2,x3+x4) , '->' , expr.replace(f(a,Add(A,B),b),f(a,A,b)+f(a,B,b))
# f(x1, x2, x3 + x4) -> f(x1, x2, x3 + x4)

我知道我可以在更改替换时以多种方式迭代函数的参数,但我希望该功能已经内置到“Wild”或“替换”中。例如,Mathematica 有“a___,b___,A___,B___”之类的“通配符”,这意味着“a___”可以是一个空序列,也可以是单个参数,也可以是多个参数的序列。例如,在 Mathematica 中,

expr /. f[a__,A_Plus,b__] :> f[a,A[[1]],b]+f[a,A[[2;;]],b]

将正确地简化两个测试用例,以及f带有任意数量参数的 for 。

是否有类似的东西,或者这是否与 sympy 一样接近?

或者,这可能与从类似的递归定义上的参数解包有关def f(*args):吗?

4

1 回答 1

0

而不是 Wild 匹配,我会检测 f 的哪些参数是 Add 并使用扩展这些参数itertools.product

import itertools
term_groups = [term.args if term.func is Add else (term,) for term in expr.args]
expanded = Add(*[expr.func(*args) for args in itertools.product(*term_groups)])

例如, if expris f(x1+x2+x4, x2+x4, x3*x1), thenterm_groups[(x1, x2, x4), (x2, x4), (x1*x3,)]最后一个参数产生 1 元素元组的地方,因为它不是 Add。并且expanded

f(x1, x2, x1*x3) + f(x1, x4, x1*x3) + f(x2, x2, x1*x3) + f(x2, x4, x1*x3) + f(x4, x2, x1*x3) + f(x4, x4, x1*x3)
于 2018-05-16T03:59:39.950 回答