在Sympy

时间:2016-01-08 09:57:46

标签: python sympy

我在Sympy中有一个表达式(比如

-M - n + x(n)

)我愿意 f表示喜欢创建一个正式的线性函数,并将其应用于我的表达式,以便在简化之后获得:

-f(M) - f(n) + f(x(n))

是否可以告知同意线​​性的属性得到验证?

一种非常黑客的方法是将函数f应用于总和中的每个子表达式。 例如,当给出像我给出的第一个表达式时,简单地访问总和中出现的术语会很好(这里它将是

[-M, -n , x(n)]

然后在列表上映射f并将其求和以获得预期的结果。

有没有一种简单的方法可以这样做,还是我必须通过表达式的句法树?

2 个答案:

答案 0 :(得分:0)

这是一种遍历语法树的hackey方式:

from sympy import *
init_session()
M,n=symbols('M n')
thing=-f(M) - f(n) + f(x(n))
def linerize_element(bro):
    return bro.args[0] if len(bro.args) == 1 else bro.args[0] * bro.args[1].args[0]
print([ linerize_element(tmp) for tmp in thing.args])

答案 1 :(得分:0)

这有效:

>>> x,f = map(Function, 'xf'); n,M = symbols('n,M'); expr = -M - n + x(n)
>>> Add(*[f(a) for a in Add.make_args(expr)])
f(-M) + f(-n) + f(x(n))

如果您有一个像f(n*(M + 1))这样的表达式并将其展开,则会得到f(n*M + n)。您可以告诉SymPy将函数应用于f的arg的arg吗?是的:

>>> expr = f(n*(M + 1))
>>> expr.expand().replace(lambda x: x.func == f,
...         lambda x: Add(*[f(a) for a in Add.make_args(x.args[0])]))
f(n) + f(M*n)

如果调用这样的替换linapp,则可以将其用于所需的任何功能:

def linapp(expr, *f):
    return expr.expand().replace(
      lambda x: x.func in f,
      lambda x: Add(*[x.func(a) for a in Add.make_args(x.args[0])]))

>>> print(linapp(cos(x+y) + sin(x + y), cos, sin))
sin(x) + sin(y) + cos(x) + cos(y)

(不是说这是一个真实的结果,只是您可以做到。而且,如果您将变量替换为其他变量并且想要重新应用线性化,则可以:

>>> linapp(_.subs(y, z + 1), cos)
sin(x) + sin(z + 1) + cos(x) + cos(z) + cos(1)