长表达式崩溃SymPy [英] Long expression crashes SymPy
问题描述
def sqrt2扩展(限制):
x =符号('x')
term =
term = term.subs({x:(2 + 1 / x)})
返回term.subs({x :2})
生成这种表达式: 1 + 1 /( 2 + 1 /(2 + 1 /(2 + 1 /(2 + 1 /(2 + 1 /(...)))))
。
当调用as: sqrt2Expansion(100)
返回有效结果,但 sqrt2Expansion(200)
生成 RuntimeError
与许多页面的追溯和挂起pylab / IPython解释器与大量的系统内存未使用。任何想法如何更有效地实施?我想调用 sqrt2Expansion(1000)
,并得到结果。
我将尝试详细阐述我在上面发布的评论。
Sympy表达式是树。每个操作是一个具有分支操作数的节点。例如 x + y
看起来像 Add(x,y)
和 x *(y + z)
像 Mul(x,Add(y,z))
。
通常这些表达式会像 Add(x,Add(y,z))
中的添加(x,y,z)
,但是对于更复杂的情况,可以得到非常深的树。
深树可能会造成问题,特别是当解释器或库本身限制允许递归的深度(作为防止无限递归和爆炸内存使用的保护)。很可能这是您的 RuntimeError
的原因:每个 subs
使树更深,随着树更深入的递归 subs
必须调用自己更多次,直到它到达最深的节点。
您可以将树简化为多项式/多项式
,它通过使用因子
方法具有恒定的深度。只需将 term = term.subs({x:(2 + 1 / x)})
更改为 term = term.subs({x: 2 + 1 / x)})。factor()
。
I'm using 64-bit Python 3.3.1, pylab and 32GB system RAM. This function:
def sqrt2Expansion(limit):
x = Symbol('x')
term = 1+1/x
for _ in range(limit):
term = term.subs({x: (2+1/x)})
return term.subs({x: 2})
Produces expressions of this kind: 1 + 1/(2 + 1/(2 + 1/(2 + 1/(2 + 1/(2 + 1/(...))))))
.
When called as: sqrt2Expansion(100)
returns valid result, but sqrt2Expansion(200)
produces RuntimeError
with many pages of traceback and hangs up pylab/IPython interpreter with plenty of system memory left unused. Any ideas how to implement it more efficiently? I would like to call sqrt2Expansion(1000)
and still get a result.
I will try to elaborate on the comment that I have posted above.
Sympy expressions are trees. Each operation is a node which has as branches its operands. For instance x+y
looks like Add(x, y)
and x*(y+z)
like Mul(x, Add(y, z))
.
Usually these expressions get automatically flattened like in Add(x, Add(y, z))
becoming Add(x, y, z)
, but for more complicated cases one can get very deep trees.
And deep trees can pose problems especially when either the interpreter or the library itself limits the depth of permitted recursion (as a protection against infinite recursion and exploding memory usage). Most probably this is the cause of your RuntimeError
: each subs
makes the tree deeper and as the tree gets deeper the recursive subs
must call itself more times till it gets to the deepest node.
You can simplify the tree to something of the form polynomial/polynomial
which has constant depth by using the factor
method. Just change term = term.subs({x: (2+1/x)})
to term = term.subs({x: (2+1/x)}).factor()
.
这篇关于长表达式崩溃SymPy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!