back to table · edit · history · where entries came from · files · download
5065 bytes, as of the version from 2026-10-24 21:41 (current). Recorded here, not run.
"""Convex-position probabilities -- numberdb.org/T468.
Run with SageMath (or passagemath):
sage -pip install numberdb
sage -python generate.py # verify the stored draft/table
sage -python generate.py --fill # write entries with an authorized key
Set NUMBERDB_API_KEY for an authenticated draft read or fill. Filling entries
never publishes the draft. The campaign wrapper can instead supply the key on
stdin with NUMBERDB_KEY_FROM_STDIN=1 and select filling with NUMBERDB_PUBLISH=1.
The table covers n=3,...,8 for triangles, parallelograms and ellipses, using
uniform area measure, not boundary measure. The exact rational polygon values
use recurrences derived from Valtr's factorial formulas. The disk values use
Marckert, arXiv:1402.3512v1, equation (7), which tabulates 1-p, not p.
An ellipse has the disk's probability by invertible affine invariance.
An 80-bit guard beyond the requested precision is checked in checks.py, along
with exact factorial formulas, Dyck-path enumeration, a geometric area integral,
independent evaluation, and uniform-point simulations. The attached evidence
records the measured accuracy. No digits are inferred from a simulation.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
GUARD_BITS = 80
REGIONS = ('equilateral-triangle', 'unit-square', 'unit-disk')
N_MIN, N_MAX = 3, 8
DISK_COMMENTS = {
4: "This is Sylvester's four-point probability, $1-35/(12\\pi^2)$ CITE{Marckert}.",
5: r'The exact value is $1-305/(48\pi^2)$ CITE{Marckert}.',
6: r'The exact value is $1-(146400\pi^2-473473)/(11520\pi^4)$ CITE{Marckert}.',
7: r'The exact value is $1-(512400\pi^2-2900611)/(23040\pi^4)$ CITE{Marckert}.',
8: r'The exact value is $1-(62664108221+1721664000\pi^4-18670881600\pi^2)/(48384000\pi^6)$ CITE{Marckert}.',
}
def polygon_probability(region, n):
"""Exact recurrence from p(3)=1; all quotients are Sage rationals."""
result = QQ(1)
for j in range(3, n):
if region == 'equilateral-triangle':
result *= QQ(2*(3*j)*(3*j-1)*(3*j-2)) / QQ(j**3*(2*j+2)*(2*j+1))
elif region == 'unit-square':
result *= (QQ(2*(2*j-1)) / QQ(j*(j+1)))**2
else:
raise ValueError('not a polygon class in this table')
return result
def disk_probability(n, digits):
"""Evaluate a polynomial in 1/pi^2 using ball arithmetic throughout."""
if n == 3:
return QQ(1)
field = RealBallField(numberdb.bits(digits, losing=GUARD_BITS))
q = field(1) / field.pi()**2
if n == 4:
result = 1 - field(QQ(35)/12)*q
elif n == 5:
result = 1 - field(QQ(305)/48)*q
elif n == 6:
result = 1 + q*(-field(QQ(146400)/11520) + q*field(QQ(473473)/11520))
elif n == 7:
result = 1 + q*(-field(QQ(512400)/23040) + q*field(QQ(2900611)/23040))
elif n == 8:
result = 1 + q*(-field(QQ(1721664000)/48384000)
+ q*(field(QQ(18670881600)/48384000)
- q*field(QQ(62664108221)/48384000)))
else:
raise ValueError('the cited explicit disk formulas cover n=3,...,8')
assert result.is_finite() and result > 0 and result < 1
assert field(result.rad()) < abs(result) * field(10)**(-digits-10)
return result
class ConvexPosition(numberdb.Generator):
table = 'T468'
parameters = ('region', 'n')
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py', 'checks.py', 'check.py', 'evidence-before-fill.json')
def enumerate(self):
for region in REGIONS:
for n in range(N_MIN, N_MAX+1):
yield {'region': region, 'n': n}
def value(self, params, digits):
n = int(params['n'])
if not N_MIN <= n <= N_MAX:
raise ValueError('n must be in the documented range 3,...,8')
region = params['region']
if region == 'unit-disk':
result = {'number': disk_probability(n, digits)}
if n in DISK_COMMENTS:
result['comment'] = DISK_COMMENTS[n]
elif region in REGIONS[:2]:
result = {'number': polygon_probability(region, n)}
if n == 4:
result['comment'] = "This is Sylvester's four-point probability."
else:
raise ValueError('unknown region')
if n == 3:
result['comment'] = 'Three independent uniform area points are noncollinear with probability $1$.'
return result
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
numberdb.configure(api_key=sys.stdin.read().strip())
generator = ConvexPosition()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill 18 convex-position probabilities with exact rationals and certified disk enclosures'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)