generate.py

back to table · edit · history · where entries came from · files · download

3198 bytes, as of the version from 2026-10-28 06:01 (current). Recorded here, not run.

"""Page average entropies of quantum subsystems -- numberdb.org/T573.

Run with SageMath and the numberdb client:
    sage -pip install numberdb
    sage -python generate.py                 # verify every stored entry
    sage -python verify_math.py              # independent checks, no network
    sage -python generate.py --submit        # fill the draft, API key required

Set NUMBERDB_API_KEY for authenticated draft access, or supply a token on stdin
with NUMBERDB_KEY_FROM_STDIN=1. Submitting numbers does not offer, review, or
publish the draft. NUMBERDB_PUBLISH=1 is the runner's alias for --submit.

The complex Haar ensemble and the order N <= K follow Page (1993), equation
(11), and Sen (1996), equation (9). Nats are exact rationals. Bits divide the
rational by an Arb enclosure of log(2). The 64 guard bits are checked across
all 200 dimension pairs in verify_math.py; see numerical-evidence.json.
The finite product bound and both unit conventions are explained in
argument-selection.md. The generator has no source dependencies beyond this
file and the installed numberdb/Sage libraries; the other files are evidence.
"""

import os
import sys
from math import isqrt

import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField

TOTAL_DIMENSION_LIMIT = 128
WORKING_GUARD = 64


def page_nats(N, K):
    """The exact finite Page formula in natural logarithmic units."""
    N, K = int(N), int(K)
    if not 2 <= N <= K:
        raise ValueError('Expected integer dimensions 2 <= N <= K')
    return sum((QQ(1) / QQ(j) for j in range(K + 1, N * K + 1)), QQ(0)) - QQ(N - 1) / QQ(2 * K)


class PageEntropies(numberdb.Generator):
    table = 'T573'
    parameters = ('N', 'K', 'unit')
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'verify_math.py', 'check.py',
             'argument-selection.md', 'sources.md', 'skill-evidence.json',
             'numerical-evidence.json')

    def enumerate(self, total_dimension=TOTAL_DIMENSION_LIMIT):
        """Small dimensions first; nats and bits are adjacent for each pair."""
        for N in range(2, isqrt(total_dimension) + 1):
            for K in range(N, total_dimension // N + 1):
                for unit in ('nats', 'bits'):
                    yield {'N': N, 'K': K, 'unit': unit}

    def value(self, params, digits):
        entropy = page_nats(params['N'], params['K'])
        unit = params['unit']
        if unit == 'nats':
            return entropy
        if unit != 'bits':
            raise ValueError('Expected nats or bits')
        field = RealBallField(numberdb.bits(digits, losing=WORKING_GUARD))
        return field(entropy) / field(2).log()


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
    generator = PageEntropies()
    if '--submit' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='Fill exact Page entropies and certified bit values'))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)