back to table · edit · history · where entries came from · files · download
3163 bytes, as of the version from 2026-10-28 08:16 (current). Recorded here, not run.
"""Yablonskii–Vorob’ev polynomials -- numberdb.org/T556.
Run with SageMath:
sage -pip install numberdb # once
sage -python generate.py # verify every stored entry
sage -python generate.py --fill-draft # write entries to this draft
The fill operation requires NUMBERDB_API_KEY. For a private draft, verification
also requires its author's key. NUMBERDB_KEY_FROM_STDIN=1 reads the key from
standard input; NUMBERDB_PUBLISH=1 is the campaign wrapper's fill switch.
Neither operation offers or publishes the table.
Q_0=1, Q_1=x and Q_(n+1) Q_(n-1)=x Q_n^2-4(Q_n Q_n''-(Q_n')^2).
Reference: DLMF 32.8.6; the variable is x with no scaling. All arithmetic is
in ZZ[x], and each quotient is checked for a zero remainder. The finite
selection is documented in argument-selection.md. checks.py independently
reconstructs the polynomials by a determinant and verifies the Painleve II
rational-solution identity.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
R = PolynomialRing(ZZ, 'x')
x = R.gen()
MAX_N = 12 # Q_12 has 1076 characters; Q_13 has 1358.
def polynomials(max_n):
"""Compute all Q_n through max_n by exact differential recurrence."""
if max_n < 0:
raise ValueError('n must be nonnegative')
values = [R.one(), x]
for n in range(1, max_n):
q = values[n]
numerator = x*q*q - 4*(q*q.derivative(2)-q.derivative()**2)
quotient, remainder = numerator.quo_rem(values[n-1])
if remainder:
raise ArithmeticError('Nonzero remainder at index %d' % (n+1))
values.append(R(quotient))
return values[:max_n+1]
class YablonskiiVorobev(numberdb.Generator):
table = 'T556'
parameters = ('n',)
type = 'Z[]'
rigour = 'exact'
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
'source-notes.md', 'skill-manifest.json', 'skill-evidence.json')
def enumerate(self, max_n=MAX_N):
for n in range(max_n+1):
yield {'n': n}
def value(self, params, digits=100):
n = int(params['n'])
if n < 0:
raise ValueError('n must be nonnegative')
if not hasattr(self, '_values') or n >= len(self._values):
self._values = polynomials(max(n, MAX_N))
return self._values[n]
def configure_key_from_stdin():
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
key = sys.stdin.read().strip()
if '=' in key and key.split('=', 1)[0].strip().isidentifier():
key = key.split('=', 1)[1].strip().strip('\"\'')
numberdb.configure(api_key=key)
if __name__ == '__main__':
configure_key_from_stdin()
generator = YablonskiiVorobev()
if '--fill-draft' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill exact polynomials after independent determinant and differential-equation checks.'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)