有没有可能 `sympy` 比 Mathematica 慢得多得多?

6
我正在使用Sympy重现Mathematica的结果,对于Sympy我还是新手,所以我的操作可能存在问题。然而,我注意到在Sympy中有些内容需要很长时间才能完成(即使在Mathematica中最多只需一分钟),例如Simplify()和solve()函数。我是否存在错误操作或者这就是事实呢?
以下是我使用solve()函数的例子:
import sympy as sp
from sympy import init_printing
init_printing()

p, r, c, p, y, Lambda = sp.symbols('p r c p y Lambda')

F = sp.Symbol('F')
eta1 = lambda p: 1/(1-sp.exp(-Lambda) * sp.exp(-Lambda)*(sp.exp(Lambda) - 1 - Lambda))
eta2 = lambda p: 1/(1-sp.exp(-Lambda)) * sp.exp(-Lambda)/(1-F) * (sp.exp(Lambda*(1- F)) - 1 - Lambda*(1-F))

eta = lambda p: 1 - eta1(p) + eta2(p)
etaOfR = sp.limit(eta(p), F,  1)

S = lambda p: eta(p)*y/p*(p-c)
SOfR = etaOfR*y/r*(r-c)
sp.solve(S(p)-SOfR, F)

相应的Mathematica代码:

ClearAll[r, p, lambda, a, A, c, eta, f, y, constant1, constant2, eta, \
etaOfR]
constant1[lambda_] := Exp[-lambda]/(1 - Exp[-lambda]);
constant2[lambda_] := constant1[lambda]*(Exp[lambda] - 1 - lambda);
eta[lambda_, f_] := 
  1 - constant2[lambda] + 
   constant1[lambda]*(Exp[lambda*(1 - f)] - 1 - lambda*(1 - f)) ;
etaOfR[lambda_] := Limit[eta[lambda, f], f -> 1];
expression1[lambda_, f_] := 
  y/p (p - c) eta[lambda, f] == y/r (r - c) etaOfR[lambda];

Solve[expression1[lambda, f], f] // FullSimplify

输出:

{{f -> (-(1 + lambda) p r + 
    c (lambda p + r) + (c - 
       p) r ProductLog[-E^(((-c lambda p + (c (-1 + lambda) + 
           p) r)/((c - p) r)))])/(lambda (c - p) r)}}

为什么要使用lambda来定义函数? - MaxNoe
我也分享chthonicdaemon的感受。最终关键在于底层算法(以及它们的优化程度)来执行分配的任务。我曾经不得不转向Maple,因为sympy无法积分一些复杂函数,而对于它可以处理的问题,速度非常缓慢。 - Reti43
1
据我理解,sympy不需要这些成为函数。只需使用您的符号即可。 - MaxNoe
以上的代码没有太多意义。 我尝试解决问题,但它看起来在数学上是错误的。请参见此处:http://nbviewer.ipython.org/gist/jankoslavic/0ad7d5c2731d425dabb3请发布Mathematica代码,我将尽力帮助您。 - jankos
1
关于"Simplify":简化并不是一个明确定义的概念,因此可以完全预期到巨大的性能差异和结果上的巨大差异。只需考虑“FullSimplify”和“Simplify”之间的差异即可。即使在给出相同结果的情况下,前者可能会慢得多。(这种情况不适用于解方程。) - Szabolcs
显示剩余4条评论
1个回答

6

正确的方法是:

from sympy import *
init_printing()
p, r, c, p, y, lam, f = symbols('p r c p y lambda f')
constant1 = exp(-lam) / (1 - exp(-lam))
constant2 = constant1 * (exp(lam) -  1 - lam)
eta = 1 - constant2 + constant1 * (exp(lam * (1-f)) - 1 - lam * (1 - f))
etaOfR = limit(eta, f,  1)
expression1 = Eq(y / p * (p - c) * eta, 
             y / r * (r - c) * etaOfR)
solve(expression1, f)

您可以在此处查看笔记本: http://nbviewer.ipython.org/gist/jankoslavic/0ad7d5c2731d425dabb3 结果与Mathematica相等(见最后一行),Sympy的性能也相当。

2
在sympy中需要30秒,在Mathematica中只需要1秒,这并不是我所说的可比较的。Certik正在将sympy移植到C++,这是有原因的。 - Connor Behan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接