Sympy 简化偏导数的麻烦

Sympy trouble with simplifying partial derivatives

我执行以下操作以在 Sympy 中生成一个表达式:

  1. 创建一些矩阵 Q_{ij},其中包含 x 和 y 的一些函数 \eta、\mu、\nu。
  2. 对指数求和并取一些偏导数。
  3. 用一些简单的表达式代替 \eta、\mu 和 \nu(比如 \sin(x)*\cos(y))。
  4. 尝试简化表达式,使其明确计算简单表达式的偏导数。

当我这样做时,出现以下错误: NotImplementedError: Improve MV Derivative support in collect

我使用的具体代码是:

from sympy import *

# Set up system and generate functions
x, y, z = symbols('x y z')
i, j, k, m, p = symbols('i j k m p')
xi = Matrix([x, y, z])
lims = range(0, 3)

eta = Function('eta', real=True)(x, y)
mu = Function('mu', real=True)(x, y)
nu = Function('nu', real=True)(x, y)

Q = Matrix([[2/sqrt(3)*eta, nu, 0],
            [nu, -1/sqrt(3)*eta + mu, 0],
            [0, 0, -1/sqrt(3)*eta - mu]])

# Create complicated expression of partial derivatives
Phi_L1 = -sum(Eijk(3, p + 1, i + 1)
              *diff(diff(diff(Q[k, l], xi[j]), xi[j]), xi[p])
              *diff(Q[k, l], xi[i])
              for i in lims
              for j in lims
              for k in lims
              for l in lims
              for p in lims
              )

Phi_L1 = simplify(Phi_L1)

# Choose example functions and try to evaluate expression explicitly
eta1 = sin(x)*cos(y)
mu1 = sinh(x)*cosh(y)
nu1 = x**2*y**2
expr1 = Phi_L1.subs(eta, eta1).subs(mu, mu1).subs(nu, nu1)
simplify(expr1)

我找不到给出相同错误的更简单示例。例如,以下按预期工作:

f = Function('f', real=True)(x, y)
expr = diff(diff(f, x), y)
simplify(expr.subs(f, sinh(x)*cosh(y)))

'collect' 和 'simplify' 具有高阶偏导数的已知问题 https://github.com/sympy/sympy/issues/9068 概述了问题

显示的例子是

import sympy as sp
x, y = sp.symbols("x y")
f, g = sp.symbols("f g", cls=sp.Function, args=(x,y))
f, g = f(), g()

expr1 = g.diff(x, 2) + f.diff(x, 2) + 5*f.diff(x, 2) + 2*f.diff(x) + 9*f.diff(x)
expr2 = g.diff(x, 2) + f.diff(x, 2) + 5*f.diff(x, 2) + 2*f.diff(x) + 9*f.diff(x) + g.diff(x).diff(y) + f.diff(x).diff(y) 

它工作正常并显示了 expr1 和 expo2 的预期输出

sp.collect(expr1, f) 效果很好,但 sp.collect(expr2, f) 失败并出现已知错误,因为实施尚未完成...

这并没有解决错误(这显然是一个错误),但是对于明确采用简单函数的导数的情况,一种解决方法是只使用 doit() 函数。在这种情况下,它看起来像(按照问题中发布的代码):

simplify(expr1.doit())