Python 在Sympy中创建一个形式线性函数

Python 在Sympy中创建一个形式线性函数,python,sympy,Python,Sympy,我有一个同情心的表达 )我会的 我想创建一个正式的线性函数,f说,并将其应用于我的表达式,以便在简化后得到: -f(M) - f(n) + f(x(n)) 是否有可能告诉sympy诸如线性之类的特性已被验证 一种非常简单的方法是将函数f应用于求和中的每个子表达式。 例如,当给出一个类似于我给出的第一个表达式时,只需访问总和中出现的术语就好了(这里是 [-M, -n , x(n)] 然后将f映射到列表上并求和以得到期望值 有没有一种简单的方法可以做到这一点,或者我必须遍历表达式的语法树吗?下面

我有一个同情心的表达

)我会的 我想创建一个正式的线性函数,f说,并将其应用于我的表达式,以便在简化后得到:

-f(M) - f(n) + f(x(n))
是否有可能告诉sympy诸如线性之类的特性已被验证

一种非常简单的方法是将函数f应用于求和中的每个子表达式。 例如,当给出一个类似于我给出的第一个表达式时,只需访问总和中出现的术语就好了(这里是

[-M, -n , x(n)]
然后将f映射到列表上并求和以得到期望值


有没有一种简单的方法可以做到这一点,或者我必须遍历表达式的语法树吗?

下面是一种遍历语法树的哈奇方法:

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])
这项工作:

>>> 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
的参数吗?是:

>>> 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)

你可以把f看作一个操作符,然后写
f*(-M-n+x(n))
。与此同时,我发现如果S是一个表示和的表达式,那么S.args返回组成元素的列表。然后,我给出的策略很好(即使很粗糙),你可以使用
Add.make_args(S)
即使S不是一个总和,它仍然有效。@user70925如果您找到了问题的解决方案,您可以将其作为问题的答案发布。
>>> linapp(_.subs(y, z + 1), cos)
sin(x) + sin(z + 1) + cos(x) + cos(z) + cos(1)