back to table · edit · history · where entries came from · files · download
3019 bytes, as of the version from 2026-10-28 07:03 (current). Recorded here, not run.
"""Trace moments of induced random density matrices -- numberdb.org/T574.
Run with SageMath:
sage -pip install numberdb
sage -python generate.py # verify every stored entry
sage -python generate.py --fill # write entries to this draft
Writing needs NUMBERDB_API_KEY, or NUMBERDB_KEY_FROM_STDIN=1 with a key on
stdin. Filling a draft does not publish or offer it for review.
M_q(N,K) = E Tr(rho^q), for a Haar-uniform pure state on C^N tensor C^K
and rho its N-dimensional reduced density matrix. Complex ensemble only;
ordinary trace, not trace divided by N. Nechita (2007), equations (37)-(38),
give the recurrence used here. All arithmetic is exact over QQ. The suspect
finite sum in that paper's equation (36) is not used. See checks.py for an
independent Wick-permutation computation and eigenvalue-density integration.
Default extent: 2 <= N <= K, N*K <= 64, 2 <= q <= 8. The product bound
controls the underlying Hilbert-space dimension; the moment bound makes
exhaustive permutation validation practical. See argument-selection.md.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from functools import lru_cache
from math import isqrt
import os
import sys
@lru_cache(maxsize=None)
def moment(N, K, q):
"""Exact complex induced trace moment; q=0 and q=1 are controls."""
if N < 1 or K < 1 or q < 0:
raise ValueError('Require positive integer dimensions and q >= 0')
if q == 0:
return QQ(N)
if q == 1:
return QQ(1)
first = QQ((2*q-1)*(N+K)) / QQ((N*K+q-1)*(q+1))
second = QQ((q-2)*((q-1)**2-(K-N)**2)) / QQ((N*K+q-1)*(N*K+q-2)*(q+1))
return first*moment(N, K, q-1) + second*moment(N, K, q-2)
class InducedTraceMoments(numberdb.Generator):
table = 'T574'
parameters = ('N', 'K', 'q')
type = 'Q'
rigour = 'exact'
files = ('generate.py', 'checks.py', 'argument-selection.md', 'source-notes.md')
def enumerate(self, max_dimension=64, max_order=8):
for N in range(2, isqrt(max_dimension)+1):
for K in range(N, max_dimension//N+1):
for q in range(2, max_order+1):
yield {'N': N, 'K': K, 'q': q}
def value(self, params, digits=100):
N, K, q = (int(params[name]) for name in self.parameters)
if not 2 <= N <= K or q < 2:
raise ValueError('Require 2 <= N <= K and q >= 2')
return moment(N, K, q)
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
generator = InducedTraceMoments()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_FILL_DRAFT') == '1':
print(generator.publish(message='Fill exact induced trace moments after independent checks',
assisted_by=os.environ.get('NUMBERDB_ASSISTED_BY', '')))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)