Ошибка памяти Python в sympy.simplify

Использование 64-битного Python 3.3.1 и 32 ГБ ОЗУ и этой функции для создания целевого выражения 1+1/(2+1/(2+1/...)):

def sqrt2Expansion(limit):
    term = "1+1/2"
    for _ in range(limit):
        i    = term.rfind('2')
        term = term[:i] + '(2+1/2)' + term[i+1:]
    return term

Я получаю MemoryError при звонке:

simplify(sqrt2Expansion(100))

Более короткие выражения работают нормально, например:

simplify(sqrt2Expansion(50))

Есть ли способ настроить SymPy для завершения этого расчета? Ниже приведено сообщение об ошибке:

    MemoryError                               Traceback (most recent call last)
<ipython-input-90-07c1e2de29d1> in <module>()
----> 1 simplify(sqrt2Expansion(100))

C:\Python33\lib\site-packages\sympy\simplify\simplify.py in simplify(expr, ratio, measure)
   2878     from sympy.functions.special.bessel import BesselBase
   2879 
-> 2880     original_expr = expr = sympify(expr)
   2881 
   2882     expr = signsimp(expr)

C:\Python33\lib\site-packages\sympy\core\sympify.py in sympify(a, locals, convert_xor, strict, rational)
    176     try:
    177         a = a.replace('\n', '')
--> 178         expr = parse_expr(a, locals or {}, rational, convert_xor)
    179     except (TokenError, SyntaxError):
    180         raise SympifyError('could not parse %r' % a)

C:\Python33\lib\site-packages\sympy\parsing\sympy_parser.py in parse_expr(s, local_dict, rationalize, convert_xor)
    161 
    162     code = _transform(s.strip(), local_dict, global_dict, rationalize, convert_xor)
--> 163     expr = eval(code, global_dict, local_dict) # take local objects in preference
    164 
    165     if not hit:

MemoryError: 

ИЗМЕНИТЬ:

Я написал версию, используя sympy-выражения вместо строк:

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})

Он работает лучше: sqrt2Expansion(100) возвращает действительный результат, но sqrt2Expansion(200) выдает RuntimeError с большим количеством страниц трассировки и зависает интерпретатор IPython с большим количеством неиспользуемой системной памяти. Я создал новый вопрос Длинное выражение приводит к сбою SymPy с этой проблемой.


person Paul Jurczak    schedule 05.05.2013    source источник
comment
Вы можете вставить вывод ошибки?   -  person donfede    schedule 05.05.2013
comment
Вам на самом деле не следует использовать строки, если вы можете написать это непосредственно с помощью математических выражений.   -  person Krastanov    schedule 05.05.2013
comment
@Krastanov Я попробую, спасибо.   -  person Paul Jurczak    schedule 05.05.2013
comment
@Krastanov Я создал новый вопрос: Длинное выражение приводит к сбою SymPy   -  person Paul Jurczak    schedule 06.05.2013
comment
См. мой ответ на другой вопрос о том, как, по моему мнению, вы действительно должны это делать.   -  person asmeurer    schedule 13.05.2013


Ответы (1)


SymPy использует eval вдоль пути, чтобы превратить вашу строку в объект SymPy, а eval использует встроенный анализатор Python, который имеет максимальное ограничение. На самом деле это не проблема SymPy.

Например, для меня:

>>> eval("("*100+'3'+")"*100)
s_push: parser stack overflow
Traceback (most recent call last):
  File "<ipython-input-46-1ce3bf24ce9d>", line 1, in <module>
    eval("("*100+'3'+")"*100)
MemoryError

Если не считать изменения MAXSTACK в Parser.h и перекомпиляции Python с другой предел, возможно, лучший способ добиться того, к чему вы стремитесь, — это вообще избегать использования строк. [Я должен упомянуть, что интерпретатор PyPy может сделать это до ~ 1100 для меня.]

person DSM    schedule 05.05.2013
comment
Хорошо, я собираюсь научиться использовать выражение вместо строки. - person Paul Jurczak; 05.05.2013
comment
Я создал новый вопрос: Длинное выражение приводит к сбою SymPy - person Paul Jurczak; 06.05.2013