back to table · edit · history · where entries came from · files · download
4150 bytes, as of the version from 2026-10-27 14:23 (current). Recorded here, not run.
"""Symplectic Weingarten functions -- numberdb.org/T551.
Run with SageMath (or a compatible passagemath installation):
sage -pip install numberdb
sage -python generate.py # verify every stored coefficient
sage -python generate.py --fill # write entries with NUMBERDB_API_KEY
The --fill operation fills this table; it does not make a draft public.
The default enumeration is N=1..6 and all partitions 1<=|mu|<=N.
N is rank; matrices have complex dimension 2N. Values are exact rationals.
Matsumoto arXiv:1301.5401v3, (2.8), gives the twisted spherical expansion.
At his even representatives (2.3), pi^lambda = omega^(lambda transpose).
Collins--Matsumoto arXiv:0903.5143, (3.5), expresses omega in the power-sum
coefficients of the integral Jack J polynomial with parameter 2.
All divisions take place in QQ. No numerical precision is used.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.symbolic.ring import SR # initialize symbolic conversion used by Jack
import sage.rings.polynomial.laurent_polynomial_ring
from sage.combinat.partition import Partitions
from sage.combinat.sf.sf import SymmetricFunctions
from collections import Counter
from functools import lru_cache
from math import factorial, prod
import os
import sys
@lru_cache(maxsize=None)
def partitions(k):
return tuple(sorted((tuple(int(v) for v in lam) for lam in Partitions(k)),
reverse=True))
def transpose(lam):
return tuple(sum(row > j for row in lam) for j in range(lam[0]))
def representation_dimension(lam):
"""Hook-length formula, evaluated in the rational field."""
hooks = prod(row-j + sum(other > j for other in lam[i+1:])
for i, row in enumerate(lam) for j in range(row))
result = QQ(factorial(sum(lam))) / QQ(hooks)
assert result.denominator() == 1
return result
@lru_cache(maxsize=None)
def spherical_data(k):
sf = SymmetricFunctions(QQ)
p = sf.power()
jack = sf.jack(t=QQ(2)).J()
return tuple((lam, representation_dimension(tuple(r for r in lam for _ in (0, 1))),
{tuple(mu): QQ(c) for mu, c in p(jack[transpose(lam)])})
for lam in partitions(k))
def symplectic_weingarten(N, mu):
N = int(N)
mu = tuple(int(x) for x in mu)
if N < 1 or not mu or min(mu) < 1 or mu != tuple(sorted(mu, reverse=True)):
raise ValueError('N must be positive and mu a nonempty decreasing partition')
k = sum(mu)
z_mu = prod(r**m * factorial(m) for r, m in Counter(mu).items())
total = QQ(0)
for lam, dimension, coefficients in spherical_data(k):
if len(lam) > N:
continue
denominator = prod(2*N-2*i+j for i, row in enumerate(lam) for j in range(row))
assert denominator != 0
total += dimension * coefficients.get(mu, QQ(0)) / QQ(denominator)
return QQ(2**len(mu)*z_mu) * total / QQ(factorial(2*k))
class SymplecticWeingarten(numberdb.Generator):
table = 'T551'
parameters = ('N', 'mu')
type = 'Q'
rigour = 'exact'
digits = 100
def enumerate(self, rank_bound=6, degree_bound=6):
for N in range(1, rank_bound+1):
for k in range(1, min(N, degree_bound)+1):
for mu in partitions(k):
yield {'N': str(N), 'mu': ','.join(map(str, mu))}
def value(self, params, digits):
return symplectic_weingarten(int(params['N']),
tuple(map(int, str(params['mu']).split(','))))
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
key = sys.stdin.read().strip()
if '=' in key:
key = key.split('=', 1)[1].strip().strip('\"\'')
numberdb.configure(api_key=key)
generator = SymplecticWeingarten()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill exact symplectic Weingarten coefficients after independent Gram and Haar-moment checks'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)