back to table · edit · history · where entries came from · files · download
6019 bytes, as of the version from 2026-10-30 13:35 (current). Recorded here, not run.
"""Resistance of infinite triangular and honeycomb lattices -- numberdb.org/T626.
Run with SageMath (install numberdb with sage -pip install numberdb):
sage -python generate.py # verify every stored entry
sage -python generate.py --fill # write entries to this draft, key required
sage -python checks.py # independent quadrature and graph checks
The exact coefficient polynomial a+b*z represents a+b*sqrt(3)/pi. Axis seeds
come from integrating (1-T_{2m}(u))/(1-u^2) against 1/sqrt(4-u^2), using exact
moment recurrence 2k M_k=4(2k-1)M_{k-1}-sqrt(3), M_0=pi/6. Harmonicity then
fills the triangular wedge; honeycomb values use Cserti (2000), (77)-(78).
No conjectured recurrence in Mathar (2022) is used. See derivation.md.
The default selection is all noncoincident endpoint orbits through graph
distance 12, justified in argument-selection.md. Arithmetic is exact until
one final Arb evaluation. The 128-bit guard covers measured cancellation;
checks.py records the minimum retained accuracy and verifies serialization.
The --fill action submits numbers and attachments; it never offers or publishes
the draft. NUMBERDB_KEY_FROM_STDIN=1 supports the campaign's protected key pipe.
"""
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.rings.real_arb import RealBallField
P = PolynomialRing(QQ, 'z')
z = P.gen()
U = PolynomialRing(QQ, 'u')
u = U.gen()
WORKING_GUARD = 128
RADIUS = 12
STEPS = ((1,0),(-1,0),(0,1),(0,-1),(1,1),(-1,-1))
def distance(m, n):
return max(abs(m), abs(n), abs(m-n))
def triangular_orbit(m, n):
orbit = set()
for j in range(6):
orbit.add((m,n))
orbit.add((n,m))
m,n = m-n,m
return orbit
def canonical(m, n):
return next((a,b) for a,b in triangular_orbit(m,n) if a >= 2*b >= 0)
def b_orbit(m,n):
orbit = set()
for j in range(3):
orbit.add((m,n))
orbit.add((m,m-n))
m,n = -n-1,m-n
return orbit
def honey_distance(s,m,n):
return 2*distance(m,n) if s == 'A' else 1+2*min(distance(m,n),distance(m+1,n),distance(m+1,n+1))
@lru_cache(None)
def chebyshev(k):
if k == 0: return U(1)
if k == 1: return u
return 2*u*chebyshev(k-1)-chebyshev(k-2)
@lru_cache(None)
def moment_over_pi(k):
if k == 0: return P(QQ(1)/6)
return (4*(2*k-1)*moment_over_pi(k-1)-z)/QQ(2*k)
@lru_cache(None)
def axis(m):
poly, remainder = (1-chebyshev(2*m)).quo_rem(1-u*u)
assert remainder == 0
assert all(poly[k] == 0 for k in range(1,poly.degree()+1,2))
return sum((poly[2*k]*moment_over_pi(k) for k in range(m)), P(0))
@lru_cache(None)
def triangular(m,n):
m,n = canonical(int(m),int(n))
if n == 0: return axis(m)
if n == 1:
return 3*triangular(m-1,0)-triangular(m-1,1)-(triangular(m,0)+triangular(m-2,0))/QQ(2)
return (6*triangular(m-1,n-1)-triangular(m-1,n)-triangular(m,n-1)
-triangular(m-2,n-1)-triangular(m-1,n-2)-triangular(m-2,n-2))
def coefficients(params):
m,n = int(params['m']),int(params['n'])
if params['lattice'] == 'triangular':
assert params['sublattice'] == 'A'
return triangular(m,n)
assert params['lattice'] == 'honeycomb'
if params['sublattice'] == 'A': return 3*triangular(m,n)
assert params['sublattice'] == 'B'
return triangular(m,n)+triangular(m+1,n)+triangular(m+1,n+1)
class Resistance(numberdb.Generator):
table = 'T626'
parameters = ('lattice','sublattice','m','n')
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py','checks.py','argument-selection.md','derivation.md',
'numerical-evidence.json','skill-manifest.json','stored_checks.py')
def enumerate(self, radius=RADIUS):
rows = []
for lattice,bound in [('triangular',radius),('honeycomb',radius//2)]:
for m in range(1,bound+1):
for n in range(m//2+1):
rows.append((m if lattice == 'triangular' else 2*m,lattice,'A',m,n))
for m in range(-radius,radius+1):
for n in range(-radius,radius+1):
d = honey_distance('B',m,n)
if d <= radius and (m,n) == max(b_orbit(m,n)):
rows.append((d,'honeycomb','B',m,n))
rows.sort(key=lambda row:(row[0], row[1] != 'triangular', row[2],row[3],row[4]))
for d,lattice,s,m,n in rows:
yield dict(lattice=lattice,sublattice=s,m=str(m),n=str(n))
def value(self,params,digits):
poly = coefficients(params)
assert poly.degree() <= 1
if poly[1] == 0:
value = poly[0]
else:
ball = RealBallField(numberdb.bits(digits,losing=WORKING_GUARD))
value = ball(poly[0])+ball(poly[1])*ball(3).sqrt()/ball.pi()
assert value.is_finite() and value > 0
special = {
('triangular','A',1,0): r'Adjacent vertices: $t(1,0)=1/3$.',
('honeycomb','B',0,0): r'Adjacent vertices: $h_B(0,0)=2/3$.',
('honeycomb','A',1,0): r'Second-neighbor vertices: $h_A(1,0)=1$.'}
key=(params['lattice'],params['sublattice'],int(params['m']),int(params['n']))
return {'number':value, 'comment':special[key]} if key in special else value
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
key = sys.stdin.read().strip()
if '=' in key and key.split('=',1)[0].replace('_','').isalnum():
key = key.split('=',1)[1].strip().strip('\"\'')
numberdb.configure(api_key=key)
generator=Resistance()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill all 84 graph-distance orbits with exact recurrence and certified bounds'))
else:
report=generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)