长表达式崩溃SymPy [英] Long expression crashes SymPy

查看:162
本文介绍了长表达式崩溃SymPy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用64位Python 3.3.1,pylab和32GB系统RAM。此功能:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆