乘积在符号数量的变量上的偏导数之和

Sum of partial derivatives of a product over a symbolic number of variables

我希望 SymPy 计算如​​下表达式:

我该如何定义符号和表达式,以便 SymPy 能够很好地处理它?我想将 N 保留为一个符号,即不制作 x 的实际有限列表。我已经尝试了 IndexedBaseSum /Product 的各种组合,但没有让它正常工作。

理想情况下是这样的:

x = IndexedBase("x")
i, j, N = symbols("i j N")
expr = Sum(Product(exp(-x[j]**2), (j, 1, N)).diff(x[i]), (i, 1, N))

到目前为止这是未计算的,expr 是

Sum(Derivative(Product(exp(-x[j]**2), (j, 1, N)), x[i]), (i, 1, N)) 

可以用doit的方法来评价。不幸的是,产品的差异化还不太奏效:expr.doit() returns

N*Derivative(Product(exp(-x[j]**2), (j, 1, N)), x[i])

将乘积重写为微分之前的总和有助于:

expr = Sum(Product(exp(-x[j]**2), (j, 1, N)).rewrite(Sum).diff(x[i]), (i, 1, N))
expr.doit()

returns

Sum(Piecewise((-2*exp(Sum(log(exp(-x[j]**2)), (j, 1, N)))*x[i], (1 <= i) & (i <= N)), (0, True)), (i, 1, N))

这是微分的正确结果。遗憾的是,我们在 Piecewise 中有那个无关的条件,而且 log(exp(...)) 本应被简化。 SymPy 不会从外部总和的上下文中推断出 (1 <= i) & (i <= N) 为 True,并且它还犹豫要简化 log(exp 认为 x[j] 可能很复杂。所以我求助于 Piecewise 的外科手术,用第一块替换它,并强行扩展日志:

e = expr.doit()
p = next(iter(e.atoms(Piecewise)))
e = expand_log(e.xreplace({p: p.args[0][0]}), force=True)

现在 e

Sum(-2*exp(Sum(-x[j]**2, (j, 1, N)))*x[i], (i, 1, N))

很遗憾,无法 exp(Sum(..)) 再次成为产品。