Я хотел бы, чтобы непрерывные дроби с целыми числами отображались в этой форме с помощью SymPy
, но я не могу заставить SymPy
соответствовать. Я нашел этот вопрос и ответ Stack Overflow очень полезным (см. Ниже), но не могу достичь своей цели здесь:
Это разложение $\frac{13}{5}$ на непрерывные дроби. Обычное обозначение для этого расширения состоит в том, чтобы давать только термины в рамке, как SymPy
ниже, то есть $[2,1,1,2]$ из SymPy
continued_fraction_iterator
:
Rat_13_5 = list(continued_fraction_iterator(Rational(13, 5)))
print( Rat_13_5 )
Rat_13_5 = list(continued_fraction_iterator(Rational(13, 5)))
( Rat_13_5 )
print( Rat_13_5 )
С выходом [2, 1, 1, 2]
.
На стр. 37 руководства Sympy версии 1.5 от 9 декабря 2019 г. приведен фрагмент кода для печати такого расширенного списка фракций:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr += i
expr = 1/expr
return l[0] + expr
Если вы вызываете list_to_frac
с расширенным списком Rat_13_5
непрерывных дробей, SymPy
взлетает и оценивает его:
print( list_to_frac( Rat_13_5 ) )
с выходом 13/5
Если вместо этого вы используете список символов, то list_to_frac
напечатает нужную непрерывную дробь, например,
n1, n2, n3, n4, n5, n6, n7, n8, n9 = symbols('n1:10')
cont_frac_list = [n2, n1, n1, n2]
contfrac12201015 = list_to_frac( [n2,n1,n1,n2] )
contfrac122010154
Что дает желаемое (я работаю в среде JupyterLab, поэтому фактически получаю вывод LaTeX с набором):
n2 + 1/(n1 + 1/(n1 + 1/n2))
Я переписал list_to_frac
, чтобы использовать средство UnevaluatedExpr
, представленное Франческо в вопросе StackOverflow, который я цитировал ранее:
def list_to_frac_noEval(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = UnevaluatedExpr(expr + i)
expr = UnevaluatedExpr( 1/expr )
return l[0] + expr
Вызов list_to_frac_noEval
в списке расширения $\frac{13}{5}$:
list_to_frac_noEval( [2,1,1,2] )
я получаю вывод
2 + (1 + (1 + 2**(-1))**(-1))**(-1)
Некоторые люди используют эту нотацию (поэтому я хотел поделиться list_to_frac_noEval
в любом случае, это лучше, чем получить оцененное единственное рациональное число, если вы хотите увидеть непрерывную дробь), например Роджер Пенроуз в разделе $\unicode{x00A7}3.2 $ из «Дороги к реальности» (2004), но меня все еще раздражает, что я не могу получить явный формат непрерывной дроби при использовании целых чисел вместо символов.
Я экспериментировал с заменой целых чисел на символы с evaluate=False
, используя как метод subs
, так и функцию Subs
, просмотрел различные комбинации sympify
и srepr
и parse_expr
с evaluate=False
, , но не смог убедить SymPy 1.4
напечатать явную форму дроби, которую я получаю с list_to_frac
работа с символьными аргументами. Есть ли способ выполнить это, за исключением изменения кода SymPy
или специального оформления определенного набора чисел?
Вы можете создать выражение, явно передавая evaluate=False
каждой части дерева выражений:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = Add(i, expr, evaluate=False)
expr = Pow(expr, -1, evaluate=False)
return Add(l[0], expr, evaluate=False)
Это дает:
In [2]: nums = list(continued_fraction_iterator(Rational(13, 5)))
In [3]: nums
Out[3]: [2, 1, 1, 2]
In [4]: list_to_frac(nums)
Out[4]:
1
───────────── + 2
1
───────── + 1
1
───── + 1
0 + 2
Похоже, что это не так, но именно так печать работает с настройками по умолчанию:
In [5]: init_printing(order='old')
In [6]: list_to_frac(nums)
Out[6]:
1
2 + ─────────────
1
1 + ─────────
1
1 + ─────
0 + 2
Вы можете активировать оценку с помощью doit
:
In [7]: _.doit()
Out[7]: 13/5
Вывод, который я показал выше, относится к мастеру sympy, который близок к недавно выпущенному sympy 1.7.1.
Полезно знать (разница в поведении init_printing связана с изменением в новой версии, т. е. улучшением). Я буду "стоять при себе" (не брать больше карт и играть с той рукой, которая у меня есть).
Хорошее решение. Мой SymPy 1.4 в Jupyter Lab не меняет отображение с иврита на обычное с помощью init_printing(order='old'), но это незначительно. Кроме того, моя версия печатает не 0 + 2, а правильную дробь 1/2, поэтому я не буду жаловаться. Интересно посмотреть на дерево операций в действии. Спасибо.