Create a formal linear function in Sympy

帅比萌擦擦* 提交于 2019-12-10 03:05:28

问题


I have an expression in Sympy (like

-M - n + x(n)

) and I would like to create a formal linear function, says f, and apply it to my expression, in order to get, after simplification:

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

Is it possible to tell sympy that a property such as linearity is verified?

A very hacky way to do it would be to apply the function f to every subexpression which is in a sum. For instance when given an expressions like the first one I gave, it would be nice to simply access the terms appearing in the sum (here it would be

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

Then mapping f on the list and sum it to get what is expected.

Is there an easy way to do so, or have I necessarily to go trough the syntactic tree of the expression ?


回答1:


This works:

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

If you have an expression like f(n*(M + 1)) and you expand it you will get f(n*M + n). Can you tell SymPy to apply the function to the args of f's args? Yes:

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

If you call such a replacement linapp you can use it for any function that you want:

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)

(Not saying that it's a true result, just that you can do it. And if you replace a variable with something else and you want to reapply the linearization, you can:

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



回答2:


Here's a hackey way that goes through the syntactic tree:

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


来源:https://stackoverflow.com/questions/34674133/create-a-formal-linear-function-in-sympy

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!