在处理复杂的决定因素时,Sympy永远不会返回

时间:2016-06-30 14:24:46

标签: python sympy

至少它是如何出现的。以下代码对3x3和6x6矩阵的行为正确。

    deter = mat.det('method':'berkowitz')
    #self.resultFileHandler.writeLogStr(str(deter))
    a = sy_polys.Poly(deter, k)

对于3x3,执行此代码需要~0.8s,对于6x6需要~288s(det函数只有650ms,其余为Poly)。对于10x10,要么复杂性以巨大的速度增加,要么其他一些原因阻止它从Poly呼叫返回(我等了一周)。没有例外被抛出。

决定因素的元素由大符号多项式组成。

我在0.7.1,刚升级到1.0(两个版本都有问题)。

我添加了日志以尝试获取文件的行列式,但它再次粘在str(deter)函数调用中。如果我打破我的调试器无法显示阻止(对调试器来说太大了)。

这是一个堆栈:

MainThread - pid_135368_id_42197520 
  _print [printer.py:262]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  parenthesize [str.py:29]  
  _print_Mul [str.py:290]   
  _print [printer.py:257]   
  _print_Add [str.py:56]    
  _print [printer.py:257]   
  doprint [printer.py:233]  
  sstr [str.py:748] 
  __str__ [basic.py:396]    
  _getRoots_sympy_Poly_nroots [__init__.py:91]  
  getRoots [__init__.py:68] 
  findPolyRoots [__init__.py:697]   
  _getNroots [polefinder.py:97] 
  _doForN [polefinder.py:60]    
  _incN [polefinder.py:52]  
  __init__ [polefinder.py:39]   
  _doPoleFind [polefinderwrap.py:33]    
  _polesForPos [polefinderwrap.py:47]   
  <module> [polefinderwrap.py:60]   
  run [pydevd.py:937]   
  <module> [pydevd.py:1530] 

好的,我的str函数有一个例外。似乎多项式可能变得太大了。

Traceback (most recent call last):
  File "E:\Peter's Documents\PhD\Code\Git\ProtoQScat\multichannel\qscat\ratsmat.\polefinder.py", line 60, in _doForN
    roots = self._getNroots(N)
  File "E:\Peter's Documents\PhD\Code\Git\ProtoQScat\multichannel\qscat\ratsmat.\polefinder.py", line 97, in _getNroots
    roots = ratSmat.findPolyRoots(False)
  File "E:\Peter's Documents\PhD\Code\Git\ProtoQScat\multichannel\qscat\numerical/..\ratsmat\__init__.py", line 697, in findPolyRoots
    roots = self.polyRootSolve.getRoots(mat, k)
  File "E:\Peter's Documents\PhD\Code\Git\ProtoQScat\multichannel\qscat\numerical/..\ratsmat\__init__.py", line 68, in getRoots
    ret = self._getRoots_sympy_Poly_nroots(mat, k)
  File "E:\Peter's Documents\PhD\Code\Git\ProtoQScat\multichannel\qscat\numerical/..\ratsmat\__init__.py", line 91, in _getRoots_sympy_Poly_nroots
    self.resultFileHandler.writeLogStr(str(deter))
  File "C:\Python27\lib\site-packages\sympy\core\basic.py", line 396, in __str__
    return sstr(self, order=None)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 748, in sstr
    s = p.doprint(expr)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 233, in doprint
    return self._str(self._print(expr))
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 56, in _print_Add
    t = self._print(term)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 290, in _print_Mul
    a_str = [self.parenthesize(x, prec) for x in a]
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 29, in parenthesize
    return "(%s)" % self._print(item)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 56, in _print_Add
    t = self._print(term)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 290, in _print_Mul
    a_str = [self.parenthesize(x, prec) for x in a]
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 29, in parenthesize
    return "(%s)" % self._print(item)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 56, in _print_Add
    t = self._print(term)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 290, in _print_Mul
    a_str = [self.parenthesize(x, prec) for x in a]
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 29, in parenthesize
    return "(%s)" % self._print(item)
  File "C:\Python27\lib\site-packages\sympy\printing\printer.py", line 257, in _print
    return getattr(self, printmethod)(expr, *args, **kwargs)
  File "C:\Python27\lib\site-packages\sympy\printing\str.py", line 69, in _print_Add
    return sign + ' '.join(l)
MemoryError

编辑: 以下答案如下所示是具有行列式大小(通道)的剖面图。忽略N(在y轴上)它是计算的另一个参数(控制元素中多边形的大小)。 enter image description here

2 个答案:

答案 0 :(得分:1)

算法很慢。

Sympy解释the Berkowitz method in its documentation,并引用"On computing the determinant in small parallel time using a small number of processors";为了实施,look at the open-source sympy code

Berkowitz的复杂性很难理解,看起来如果你不想强行证明其正确性then you need to get involved in some pretty hairy combinatorics

该算法适用于高度并行的体系结构;这主要是因为高斯椭球不能很好地进行分裂。正式地,它在class NC^2。我猜可能你的测试没有在这样的架构上运行。一些研究人员使用算法seem to be contributors on CS.SE,如果您对该主题有更多疑问。

多项式通话很慢

From the docs,有多种构造多项式的方法,取决于传递给构造函数的集合类型(列表[1],元组[2]或字典{{1} });它们导致不同的验证并且具有非常不同的性能。我会在文档中指出你的这个注释(强调我的,大写他们的):

  

对于交互式使用,请选择[3],因为它安全且相对较快。

     

注意:在内部使用[1][2]时间关键算法   你知道系数和单项式将是有效的同情   表达式。谨慎使用它们!如果系数是整数   而不是同情整数(例如1而不是S(1))多项式将   如果您尝试打印,可能会遇到问题   多项式即可。如果单项式不是作为整数元组给出的   会有问题。

Sympy还保留在需要输出之前懒惰地评估表达式的权利。这是符号计算的一个重要部分 - 数学简化可以带来精确增益和性能提升,但也可能意味着复杂表达式的实际评估可能会延迟到意外时间。

答案 1 :(得分:0)

好的,所以我在阅读了文献和感觉(强调这里)之后回到了这里,Berkowitz应该在O(n ^ 2)和O(n ^ 3)之间执行。

我发现det和Poly的输入类型对性能有很大影响(我承认输入类型没有显示在我的问题中)。将多维数据集中的原始表达式包装可以显着提高性能。

考虑以下三个代码

1:使用MatrixSymbol。 det需要1.1s然后在30分钟后仍然停留在str上

tabLayout.setupWithViewPager(viewPager)

2:代表我原来的问题代码。 det需要1.8秒,然后在30分钟后仍然停留在Poly。

from sympy import MatrixSymbol, Matrix

X = MatrixSymbol('X', 10, 10)
Xmat = Matrix(X)

deter = Xmat.det(method='berkowitz')
str(deter)

3:高于import sympy from sympy import Matrix, I from sympy.polys import Poly matSz = 10 m = Matrix([[0.0]*matSz]*matSz) x = sympy.symbols('x') for i in range(matSz): for j in range(matSz): m[i,j] = 2.0*float(i+1)*x**2 + 2.0*float(j+1)*x - 5.0*float(i+1) deter = m.det(method='berkowitz') deter_poly = Poly(deter, x) #Required or exception roots = deter_poly.nroots() 。 det需要3.0s,Poly 0.04和nroots 0.27

m[i,j] = poly(