Example code
How likely is a randomly catalysed polymer network to support itself as the allowed polymer length grows? This example compares finite-network RAF probabilities with bounds on the infinite model's probability of generating arbitrarily long polymers.
The molecules are binary words; a reaction joins two words or splits their product. Food contains all words of length one or two. The split catalogue retains ordered split identities; the quotient catalogue merges opposite factor orders only when they produce the same word. Those conventions change both the random experiment and its exact counts.


The central counting idea is to follow productive histories: each chosen channel adds at least one new word type. Earlier channels are already settled, with all their endpoints available. Tracking total word length and cleavage positions therefore bounds the number of possible next steps without enumerating a vast ambient network. The code checks small histories and uses exact integer products to bound that infinite-survival probability by for both catalogues. This is an upper bound, not an evaluation of the true profile.
Finite networks behave differently near zero. A reaction's product may catalyze that same reaction under the structural RAF definition. The example enumerates 248 split and 234 quotient catalytic assignments that each support a one-reaction RAF, giving the exact contribution . These witnesses make the finite RAF probability linear near zero, even though the infinite-size probability approaches zero faster than any fixed power of the intensity.
At word cap 16 and intensity , exact calculations put the split RAF probability between and , with a similar quotient interval. The limiting probability at that intensity is below . This is an order-of-limits distinction, not sampling error or evidence that cap 16 already approximates infinity.
The package includes catalogue and closure classes, maximal-RAF detection, exact finite-field recursion, productive-history counts, finite probability bounds, fresh-record repair supports and rational parameter conversion. Inputs at the top support new caps and parameter sweeps. Seven scientific test groups check the semantics and arithmetic independently on small cases.
The general profile evaluator also exposes its cost. Even at openness one half, the paper's seed construction needs words of length 4,830 or 21,520 before the much larger escape cap is formed. The implementation returns useful narrow intervals at low openness and reports a resource limit rather than inventing an interior estimate. Universal results are imported at the paper's stated scope; Lean is not rerun. These structural probabilities describe neither reactor flux nor finite-molecule viability.
Python source
"""Exact finite RAF bounds, productive histories, and a budgeted profile evaluator.
Three distinct observables: finite catalytic RAF probability, static escape,
and infinite survival. No Monte Carlo curve is presented as the limiting profile.
"""
from __future__ import annotations
import argparse
from collections import Counter
import csv
from dataclasses import dataclass
from fractions import Fraction as Q
from functools import lru_cache
from itertools import product
import hashlib
import json
import math
from pathlib import Path
import platform
# EDITABLE INPUTS -----------------------------------------------------------
WORD_CAP = 16
INTENSITY = Q(1,10000) # lambda; catalytic p=lambda*n/R_n
STATIC_OPENNESS = Q(1,10000) # a; distinct from catalytic p and 1-exp(-lambda)
PROFILE_TOLERANCE = Q(1,10**12)
HISTORY_DEPTH = 2 # exhaustive tiny census, not full cap-16 fields
MAX_HISTORY_BOUND = 80
MAX_STATIC_DECISIONS = 20000 # resource exhaustion raises; never means zero
MAX_SEED_INDEX = 10000
MAX_EXACT_BITS = 1000000
SEED_COST_OPENNESS = Q(1,2)
SEED_COST_M = 100
MANUSCRIPT_SHA256 = '1d561295f36a0415f2aa64ea12e4a310e078a3fbbc3be17eb3b8122d5e388c45'
# --------------------------------------------------------------------------
FOOD=frozenset(''.join(v) for k in (1,2) for v in product('01',repeat=k))
C_STAR=2*7**64*81
class ResourceLimit(RuntimeError):
"""Incomplete computation; carries no probability verdict."""
@dataclass(frozen=True)
class Interval:
lower: Q
upper: Q
def __post_init__(self):
if self.lower>self.upper:raise ValueError('Reversed interval.')
@property
def width(self):return self.upper-self.lower
def json(self):return dict(lower=str(self.lower),upper=str(self.upper),width=str(self.width))
@dataclass(frozen=True,order=True)
class Channel:
left: str
right: str
product: str
@property
def endpoints(self):return frozenset((self.left,self.right,self.product))
def enabled(self,available):return self.product in available or self.left in available and self.right in available
def productive(self,available):return self.enabled(available) and not self.endpoints<=available
class PolymerCatalogue:
"""Ordered split identity or commuting-factor quotient; product never changes."""
def __init__(self,mode):
if mode not in ('sp','qt'):raise ValueError('Use sp (split) or qt (quotient).')
self.mode=mode
def channel(self,u,v):
if not u or not v or set(u+v)-set('01'):raise ValueError('Nonempty binary factors required.')
if self.mode=='qt' and u+v==v+u and (len(u),u)>(len(v),v):u,v=v,u
return Channel(u,v,u+v)
@staticmethod
def words(n):
return [''.join(v) for k in range(1,n+1) for v in product('01',repeat=k)]
def channels(self,n):
return tuple(sorted({self.channel(w[:j],w[j:]) for w in self.words(n) for j in range(1,len(w))}))
@staticmethod
def molecule_count(n):return 2**(n+1)-2
@staticmethod
@lru_cache(None)
def primitive_count(n):return 2**n-sum(PolymerCatalogue.primitive_count(d) for d in range(1,n) if n%d==0)
def channel_count(self,n):
if not isinstance(n,int) or n<2:raise ValueError('Integer cap at least two required.')
split=(n-2)*2**(n+1)+4
if self.mode=='sp':return split
loss=0
for d in range(1,n//3+1):
limit=n//d
pairs=sum(max(0,limit-2*i) for i in range(1,limit//2+1))
loss+=self.primitive_count(d)*pairs
return split-loss
@property
def growth_count(self):return 32 if self.mode=='sp' else 30
@property
def gateway_count(self):return self.growth_count+4
@property
def singleton_count(self):return 24+7*self.growth_count
def productive(self,available):
candidates={self.channel(u,v) for u in available for v in available if u+v not in available}
candidates.update(self.channel(w[:j],w[j:]) for w in available for j in range(1,len(w))
if w[:j] not in available or w[j:] not in available)
return tuple(sorted(candidates))
class ReversibleClosure:
@staticmethod
def compute(channels,food=FOOD):
available=set(food)
while True:
before=len(available)
for ch in channels:
if ch.enabled(available):available.update(ch.endpoints)
if len(available)==before:return frozenset(available)
@staticmethod
def maximal_raf(channels,catalysis):
"""Deletion algorithm with one catalyst mark serving both directions.
Product self-catalysis is allowed; no catalyzed startup order is imposed.
catalysis maps a Channel to its set of catalyst word types.
"""
remaining=set(channels)
while remaining:
available=ReversibleClosure.compute(remaining)
good={ch for ch in remaining if ch.endpoints<=available and set(catalysis.get(ch,()))&available}
if good==remaining:return frozenset(good)
remaining=good
return frozenset()
class ProductiveHistories:
def __init__(self,catalogue):self.catalogue=catalogue
@staticmethod
def budget(j):return (6+2*j)**2+4*2**j-j
@lru_cache(None)
def coefficient(self,r):
if not isinstance(r,int) or r<0:raise ValueError('Nonnegative integer depth required.')
return 1 if r==0 else self.catalogue.growth_count*math.prod(self.budget(j) for j in range(1,r))
def bound(self,a,max_r=MAX_HISTORY_BOUND):
a=probability(a)
if max_r<0:raise ValueError('Nonnegative maximum depth required.')
values=[Q(self.coefficient(r))*a**r for r in range(max_r+1)]
r=min(range(len(values)),key=values.__getitem__)
return r,values[r]
def census(self,depth=HISTORY_DEPTH):
"""Deduplicate states, but retain ordered-path multiplicities and witness support."""
states={FOOD:(1,frozenset())};rows=[]
for j in range(depth+1):
nxt={};transitions=0;maxchoices=maxT=maxQ=0
for available,(count,used) in sorted(states.items(),key=lambda v:tuple(sorted(v[0]))):
assert ReversibleClosure.compute(used)==available and all(ch.endpoints<=available for ch in used)
T=sum(map(len,available));slots=T-len(available)
assert len(available)<=6+2*j and max(map(len,available))<=2**(j+1)
assert T<=2**(j+2)+6 and slots<=4*2**j-j
choices=self.catalogue.productive(available);maxchoices=max(maxchoices,len(choices));maxT=max(maxT,T);maxQ=max(maxQ,slots)
assert len(choices)<=(self.catalogue.growth_count if j==0 else self.budget(j))
for ch in choices:
target=available|ch.endpoints;support=used|{ch}
assert ch not in used and ReversibleClosure.compute(support)==target
transitions+=count
if j<depth:
old=nxt.get(target,(0,support));nxt[target]=(old[0]+count,old[1])
rows.append(dict(depth=j,states=len(states),ordered_histories=sum(v[0] for v in states.values()),
next_histories=transitions,max_choices=maxchoices,max_total_length=maxT,max_cleavage_slots=maxQ))
assert transitions<=self.coefficient(j+1)
states=nxt
return rows
def probability(v):
v=Q(v)
if not 0<=v<=1:raise ValueError('Probability outside [0,1].')
return v
class FinitePrediction:
def __init__(self,catalogue,n):
if not isinstance(n,int) or n<4:raise ValueError('Finite prediction requires n>=4.')
self.catalogue=catalogue;self.n=n;self.M=catalogue.molecule_count(n);self.R=catalogue.channel_count(n)
def canonical_probability(self,intensity):return probability(Q(intensity)*self.n/self.R)
def singleton(self,p):return 1-(1-probability(p))**self.catalogue.singleton_count
def bounds(self,p):
p=probability(p);a=self.catalogue.singleton_count;g=self.catalogue.gateway_count
lower=self.singleton(p);bonf=max(Q(0),a*p-math.comb(a,2)*p*p)
# All RAFs require a gateway. This exact bound covers caps too small for r>=1.
candidates=[dict(kind='singleton_remainder',r=None,upper=min(Q(1),lower+math.comb(self.M*self.R,2)*p*p))]
# Bernoulli union bound avoids raising a huge denominator to M*G.
candidates.append(dict(kind='gateway_union',r=None,upper=min(Q(1),g*self.M*p)))
r=1;history=ProductiveHistories(self.catalogue)
while 2**(r+2)<=self.n:
B=2**(r+1);hist=history.coefficient(r)*(self.M*p)**r;short=g*self.catalogue.molecule_count(B)*p
candidates.append(dict(kind='history_plus_short_gateway',r=r,B=B,history=hist,short=short,upper=min(Q(1),hist+short)))
r+=1
best=min(candidates,key=lambda v:v['upper'])
assert lower<=best['upper']
return dict(n=self.n,molecules=self.M,channels=self.R,p=p,singleton=lower,bonferroni_lower=bonf,
interval=Interval(lower,best['upper']).json(),best=best,candidates=candidates)
class StaticField:
"""Exact independent-open finite field. Adaptive queries reveal only fresh marks.
Every previously open channel is settled, so current closure and closed marks
suffice for recursion. Memoization shares subproblems; budget exhaustion raises.
"""
def __init__(self,channels):self.channels=tuple(sorted(set(channels)))
def escape(self,a,B,max_decisions=MAX_STATIC_DECISIONS):
a=probability(a)
if B<2:raise ValueError('Escape threshold must be at least food length two.')
if a==0:return Q(0)
if a==1:return Q(int(max(map(len,ReversibleClosure.compute(self.channels)))>B))
decisions=0
@lru_cache(None)
def visit(available,closed):
nonlocal decisions
if max(map(len,available))>B:return Q(1)
enabled=next((i for i,ch in enumerate(self.channels) if i not in closed and ch.productive(available)),None)
if enabled is None:return Q(0)
decisions+=1
if decisions>max_decisions:raise ResourceLimit('Static decision budget exhausted; escape probability not computed.')
ch=self.channels[enabled]
return a*visit(available|ch.endpoints,closed)+(1-a)*visit(available,closed|{enabled})
return visit(FOOD,frozenset())
@classmethod
def full_escape(cls,catalogue,a,B,max_decisions=MAX_STATIC_DECISIONS,max_channels=200):
a=probability(a)
if B==2:return 1-(1-a)**catalogue.growth_count
if catalogue.channel_count(2*B)>max_channels:
raise ResourceLimit('Full witness-cap catalogue exceeds channel budget; no escape verdict.')
return cls(catalogue.channels(2*B)).escape(a,B,max_decisions)
class RepairConstruction:
def __init__(self,catalogue):self.catalogue=catalogue
def support(self,carrier,target):
# Append letters, then split off the whole target. Repeated identities merge.
support=set();word=carrier
for letter in target:
ch=self.catalogue.channel(word,letter);support.add(ch);word+=letter
support.add(self.catalogue.channel(carrier,target))
assert len(support)<=len(target)+1 and all(len(ch.product)>len(carrier) for ch in support)
assert target in ReversibleClosure.compute(support,FOOD|{carrier})
return tuple(sorted(support))
class RationalConversion:
@staticmethod
def openness(z,tolerance):
z=Q(z);tol=Q(tolerance)
if z<0 or tol<=0:raise ValueError('Nonnegative intensity and positive tolerance required.')
if z==0:return Interval(Q(0),Q(0))
total=Q(1);term=Q(1);n=0
while True:
if n+2>=2*z:
tail=2*term*z/(n+1);answer=Interval(1-1/total,1-1/(total+tail))
if answer.width<=tol:return answer
n+=1;term*=z/n;total+=term
@staticmethod
def intensity(a,tolerance):
a=probability(a);tol=Q(tolerance)
if a==1 or tol<=0:raise ValueError('a<1 and positive tolerance required.')
total=Q(0);power=a;n=1
while True:
total+=power/n;remainder=power*a/((n+1)*(1-a))
if remainder<=tol:return Interval(total,total+remainder)
n+=1;power*=a
class EffectiveApproximation:
"""Resource-bounded implementation of the proof, with useful bound shortcuts.
Failure to fit the resource budget is explicit. It is not a numerical estimate
of the survival profile and does not contradict mathematical computability.
"""
def __init__(self,catalogue):self.catalogue=catalogue
def seed(self,q,m,max_index=MAX_SEED_INDEX,max_bits=MAX_EXACT_BITS):
q=probability(q)
if not q or not isinstance(m,int) or m<2:raise ValueError('q>0, integer m>=2 required.')
b=q if self.catalogue.mode=='sp' else q/2;base=1-b*b;factor=C_STAR*(m*(m+1)+1)
def passes(k):
if k>max_index or k*max(base.numerator.bit_length(),base.denominator.bit_length())>max_bits:
raise ResourceLimit('Exact seed search exceeds index/bit budget; seed not computed.')
return factor*base**k<=1
hi=1
while not passes(hi):hi*=2
lo=0
while hi-lo>1:
mid=(lo+hi)//2
if passes(mid):hi=mid
else:lo=mid
return 10*hi
def record_upper(self,q,L,tolerance):
q=probability(q);tol=Q(tolerance)
if not q or L<1 or tol<=0:raise ValueError('q>0, L>=1 and positive tolerance required.')
if (L+1)*max(q.numerator.bit_length(),q.denominator.bit_length())>MAX_EXACT_BITS:raise ResourceLimit('Record construction exceeds rational bit budget.')
# (1-t)^r <= 1/(1+r*t) by Bernoulli, with t=q^(L+1).
# This computable index is conservative, not the paper's least index.
return max(1,math.ceil((Q(2**(L+1))/tol-1)/q**(L+1)))
def evaluate(self,a,tolerance,max_cap_bits=20):
a=probability(a);tol=Q(tolerance)
if tol<=0:raise ValueError('Positive tolerance required.')
if a in (0,1):return dict(method='exact_endpoint',interval=Interval(a,a).json())
r,upper=ProductiveHistories(self.catalogue).bound(a)
if upper<tol:return dict(method='history_upper_bound',history_depth=r,interval=Interval(Q(0),upper).json())
m=math.ceil(4/tol)+2;L=self.seed(a,m);record=self.record_upper(a,L,tol/4)
if record>max_cap_bits:raise ResourceLimit(f'Profile cap cannot be materialized: seed L={L}, conservative record-index bit length={record.bit_length()}; no interior evaluation.')
B=2**record*(L+2)-L
e=StaticField.full_escape(self.catalogue,a,B)
return dict(method='finite_escape_with_uniform_error',seed=L,record=record,
interval=Interval(max(Q(0),e-tol/2),min(Q(1),e)).json())
def main():
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--output',type=Path,default=Path('outputs'));args=parser.parse_args();out=args.output;out.mkdir(parents=True,exist_ok=True)
models={};bounds_rows=[];finite_rows=[];history_rows=[]
for mode in ('sp','qt'):
cat=PolymerCatalogue(mode);hist=ProductiveHistories(cat);pred=FinitePrediction(cat,WORD_CAP)
gateways=[ch for ch in cat.channels(4) if ch.enabled(FOOD)]
witnesses=[(x,ch) for ch in gateways for x in ReversibleClosure.compute([ch])]
assert len(witnesses)==cat.singleton_count and len(gateways)==cat.gateway_count
for n in range(2,10):assert len(cat.channels(n))==cat.channel_count(n)
census=hist.census();history_rows.extend((mode,*row.values()) for row in census)
finite=pred.bounds(pred.canonical_probability(INTENSITY));certificates=[]
for power,r,target in [(3,8,5),(4,12,15),(6,18,45),(20,65,629)]:
bound=Q(hist.coefficient(r),10**(power*r));assert bound<Q(1,10**target)
certificates.append(dict(a=f'1e-{power}',r=r,bound=str(bound),strictly_below=f'1e-{target}'))
evaluator=EffectiveApproximation(cat);L=evaluator.seed(SEED_COST_OPENNESS,SEED_COST_M)
record=evaluator.record_upper(SEED_COST_OPENNESS,L,Q(1,100))
# This estimate describes the LEAST record scale; the exact conservative index above is larger.
least_log2=(L+1)+math.log2((L+1)*math.log(2)+math.log(100))
try:interior=evaluator.evaluate(Q(1,2),Q(1,100))
except ResourceLimit as exc:interior=dict(status='resource_limit',reason=str(exc))
repair=RepairConstruction(cat).support('000','101')
toy=tuple(sorted(set(repair)|{cat.channel('0','00'),cat.channel('00','0')}))
toy_escape=StaticField(toy).escape(Q(1,2),4)
models[mode]=dict(finite=finite,gateway_count=len(gateways),singleton_coordinates=len(witnesses),history_census=census,
low_openness_certificates=certificates,configured_profile=evaluator.evaluate(STATIC_OPENNESS,PROFILE_TOLERANCE),
seed_cost=dict(q=str(SEED_COST_OPENNESS),m=SEED_COST_M,L=L,conservative_record_index_bit_length=record.bit_length(),
least_record_log2_approx=least_log2,note='Cost of the proof, not an estimate of the profile. Conservative index uses a rational Bernoulli bound.'),
interior_attempt=interior,repair=[(c.left,c.right,c.product) for c in repair],restricted_field_escape=dict(a='1/2',B=4,value=str(toy_escape),
channels=[(c.left,c.right,c.product) for c in toy],scope='Only this explicit small subnetwork is random; omitted channels closed. Not full polymer escape or survival.'),
full_escape_B2_at_half=str(StaticField.full_escape(cat,Q(1,2),2)))
for exponent in range(2,21):
a=Q(1,10**exponent);r,v=hist.bound(a);bounds_rows.append((mode,exponent,r,str(v),math.log10(v.numerator)-math.log10(v.denominator)))
for exponent in range(2,10):
lam=Q(1,10**exponent);f=pred.bounds(pred.canonical_probability(lam));_,limit=hist.bound(lam)
finite_rows.append((mode,exponent,str(f['singleton']),f['interval']['upper'],str(limit),float(f['singleton']),float(Q(f['interval']['upper'])),float(limit)))
conversion=RationalConversion.openness(INTENSITY,Q(1,10**16));inverse=RationalConversion.intensity(Q(1,2),Q(1,10**10))
assert conversion.upper<INTENSITY
result=dict(manuscript_sha256=MANUSCRIPT_SHA256,models=models,intensity_to_openness=conversion.json(),half_openness_to_intensity=inverse.json(),
dependence_counterexample=dict(model='One shared Bernoulli(a) mark opens all channels or none.',survival='a exactly',scope='Same marginals as the independent model, different survival. History powers require independence.'),
scope='Exact finite algebra and enumeration plus imported universal theorems. No Lean replay; no interior survival plot or kinetic interpretation.')
def dump(name,data):(out/name).write_text(json.dumps(data,indent=2,default=str)+'\n')
def table(name,header,rows):
with (out/name).open('w',newline='') as f:w=csv.writer(f);w.writerow(header);w.writerows(rows)
dump('results.json',result);table('history_bounds.csv',['mode','log10_inverse_a','r','upper_exact','log10_upper_display'],bounds_rows)
table('finite_vs_limit.csv',['mode','log10_inverse_lambda','finite_lower_exact','finite_upper_exact','limit_upper_exact','finite_lower_display','finite_upper_display','limit_upper_display'],finite_rows)
table('history_census.csv',['mode',*models['sp']['history_census'][0].keys()],history_rows)
lines=['Split/quotient catalogues, gateway and singleton coordinates checked by literal enumeration.',
f'Configured n={WORD_CAP}, lambda={INTENSITY}:']
for mode,data in models.items():
f=data['finite'];lines.append(f' {mode}: singleton lower {float(f["singleton"]):.9g}; RAF upper {float(Q(f["interval"]["upper"])):.9g}; p={f["p"]}.')
lines+=['Both profiles: exact S(1e-20) < 1e-629. These are upper bounds, not the profile values.',
'Interior evaluation at a=1/2 stops at an explicit resource limit; it returns no probability estimate.',
'One shared channel mark gives survival a, showing why marginal probabilities alone do not justify history powers.']
(out/'console.txt').write_text('\n'.join(lines)+'\n');print('\n'.join(lines))
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig,axs=plt.subplots(1,2,figsize=(10,4),layout='constrained')
for mode,label in [('sp','Split'),('qt','Quotient')]:
data=[r for r in bounds_rows if r[0]==mode];axs[0].plot([r[1] for r in data],[r[4] for r in data],'.-',label=label)
# Earlier sparse-support envelope: exact integer binomials, float only at rendering.
old=[math.log10(math.comb(PolymerCatalogue('sp').channel_count(2*(2**(r+1)+2)),r)) for r in range(1,8)]
xs=range(2,21);axs[0].plot(xs,[min([0]+[v-r*x for r,v in enumerate(old,1)]) for x in xs],'--',color='gray',label='Earlier sparse-support bound')
axs[0].set(xlabel='log10(1 / static openness a)',ylabel='log10 upper bound on survival',title='Upper bounds on infinite polymer survival');axs[0].legend(fontsize=8)
for mode,color in [('sp','#246d91'),('qt','#bd5a24')]:
d=[r for r in finite_rows if r[0]==mode];x=[r[1] for r in d]
axs[1].fill_between(x,[math.log10(r[5]) for r in d],[math.log10(r[6]) for r in d],color=color,alpha=.2,label=f'{mode}: finite RAF interval')
axs[1].plot(x,[math.log10(r[7]) for r in d],'--',color=color,label=f'{mode}: limit upper bound')
axs[1].set(xlabel='log10(1 / intensity lambda)',ylabel='log10 probability / bound',title=f'Finite cap {WORD_CAP} and infinite-survival\nbounds');axs[1].legend(fontsize=7)
for ax in axs:ax.grid(alpha=.2)
fig.savefig(out/'bounds.png',dpi=180);fig.savefig(out/'bounds.svg');plt.close(fig)
fig,axs=plt.subplots(1,2,figsize=(10,3.6),layout='constrained')
for mode,label in [('sp','Split'),('qt','Quotient')]:
rows=models[mode]['history_census'];axs[0].plot([r['depth']+1 for r in rows],[r['next_histories'] for r in rows],'.-',label=f'{label}: counted')
h=ProductiveHistories(PolymerCatalogue(mode));axs[0].plot([r['depth']+1 for r in rows],[h.coefficient(r['depth']+1) for r in rows],':',label=f'{label}: bound')
axs[0].set(yscale='log',xlabel='Productive steps',ylabel='Ordered histories',title='Counts and upper bounds for productive\nhistories');axs[0].legend(fontsize=7)
x=[0,1];axs[1].bar(x,[models[m]['seed_cost']['L'] for m in ('sp','qt')],color=['#246d91','#bd5a24']);axs[1].set_xticks(x,['Split','Quotient']);axs[1].set(ylabel='Required seed length L',title=f'Proof cost at q={SEED_COST_OPENNESS}, m={SEED_COST_M}')
for i,m in enumerate(('sp','qt')):axs[1].text(i,models[m]['seed_cost']['L'],str(models[m]['seed_cost']['L']),ha='center',va='bottom')
axs[1].margins(y=.15)
for ax in axs:ax.grid(axis='y',alpha=.2)
fig.savefig(out/'construction.png',dpi=180);fig.savefig(out/'construction.svg');plt.close(fig)
digest=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
dump('run_metadata.json',dict(manuscript_sha256=MANUSCRIPT_SHA256,source_sha256=digest(Path(__file__)),python=platform.python_version(),output_sha256={p.name:digest(p) for p in sorted(out.iterdir()) if p.is_file() and p.name!='run_metadata.json'}))
if __name__=='__main__':main()
Run output
Split/quotient catalogues, gateway and singleton coordinates checked by literal enumeration. Configured n=16, lambda=1/10000: sp: singleton lower 2.16238345e-07; RAF upper 4.56826817e-05; p=1/1146882500. qt: singleton lower 2.0405514e-07; RAF upper 4.29469382e-05; p=1/1146748750. Both profiles: exact S(1e-20) < 1e-629. These are upper bounds, not the profile values. Interior evaluation at a=1/2 stops at an explicit resource limit; it returns no probability estimate. One shared channel mark gives survival a, showing why marginal probabilities alone do not justify history powers.