我希望SymPy能够评估如下表达式:
我如何定义符号和表达式,以便SymPy可以很好地处理它?我想将N
保留为一个符号,即不要制作x
的实际有限列表。我尝试了IndexedBase
和Sum
/ Product
的各种组合,但没有让它正常工作。
答案 0 :(得分:3)
理想情况下就是这样:
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()
返回
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()
返回
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)
是真的,并且它也犹豫是否简化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(..))
无法再次成为产品。