【问题标题】:Create a formal linear function in Sympy在 Sympy 中创建正式的线性函数
【发布时间】:2016-01-08 09:57:46
【问题描述】:

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

-M - n + x(n)

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

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

是否可以告诉 sympy 已验证线性等属性?

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

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

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

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

【问题讨论】:

  • 你可以把 f 想象成一个运算符,写成f*(-M - n + x(n))
  • 同时我发现如果 S 是一个表示 sum 的表达式,S.args 返回构成元素的列表。然后我给出的策略效果很好(即使它很老套)
  • 您可以使用Add.make_args(S),即使 S 不是总和也可以使用。
  • @user70925 如果您找到了问题的解决方案,您可以发布它作为您问题的答案。

标签: python sympy


【解决方案1】:

这行得通:

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

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

【讨论】:

    【解决方案2】:

    这是一个遍历句法树的 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])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多