Example code
Finding a minimal autocatalytic core requires knowing which molecules enter and leave each reaction, as well as their net change. Reactants and products tell us which species participate; their difference tells us what a flow produces. Cancelling molecules that appear on both sides too early can erase an autocatalytic witness. Reversible reaction identities also need signed flows, because a productive pathway may run a reaction backwards.
The example provides an exact network-screening tool and an independent certificate verifier. It finds a minimal productive core in a three-reaction cycle, distinguishes exhaustive absence from an unfinished search, and shows how an external resource changes the answer.


The paper's complexity result becomes a runnable construction: compile a Boolean formula into a directed-path problem and then a reaction network. The desired path pairing yields a nonsingular boundary matrix; the crossed pairing does not. The complete fixed switch is checked afresh, and a satisfying assignment produces explicit paths and an integer productivity certificate.
The components are reusable for candidate generators and network-screening experiments. Certificates establish structural production, not a kinetic trajectory or a finite-resource operating guarantee. The transparent search is exponential, and the formal machine-time and Lean proofs are not rerun.
Python source
"""Find productive autocatalytic cores and independently verify their certificates."""
# EDIT THESE INPUTS. Rows are species; columns are reversible reaction identities.
SPECIES=('A','B','C')
REACTIONS=('A_to_2B','B_to_2C','C_to_2A')
LEFT=((1,0,0),(0,1,0),(0,0,1))
RIGHT=((0,0,2),(2,0,0),(0,2,0))
SEARCH_CANDIDATE_BUDGET=100000
CNF_CLAUSES=((1,),(-1,2)) # signed one-based literals; repeated occurrences retained
CNF_VARIABLES=2
ASSIGNMENT_BUDGET=65536
import argparse,hashlib,json,platform,csv
from pathlib import Path
from itertools import combinations
import numpy as np
import sympy as sp
from network import LiteralSource,SquareSearch,BinarySourceCodec
from linkage import CNF,DirectedLinkage,switch_check
from check_certificate import check
MANUSCRIPT_SHA256='a3ac0ec8661bb0553397f5bc881993d054eeb3b6917f2dcdec4569b0d87bf590'
def examples():
return {
'literal_self_amplification':LiteralSource(('A',),('A_to_2A',),((1,),),((2,),)),
'reverse_flow_needed':LiteralSource(('A',),('2A_to_A',),((2,),),((1,),)),
'balanced_conversion':LiteralSource(('A','B'),('A_to_B',),((1,),(0,)),((0,),(1,))),
'external_resource':LiteralSource(('A','F'),('A_plus_F_to_2A',),((1,),(1,)),((2,),(0,))),
'net_only_cancellation_error':LiteralSource(('A',),('cancelled',),((0,),),((1,),)),
'closed_conservative_cycle':LiteralSource(('A','B','C'),('A_B','B_C','C_A'),((1,0,0),(0,1,0),(0,0,1)),((0,0,1),(1,0,0),(0,1,0)))
}
def main():
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--output',type=Path,default=Path('outputs'));out=parser.parse_args().output;out.mkdir(parents=True,exist_ok=True)
def dump(name,x):(out/name).write_text(json.dumps(x,indent=2,default=str)+'\n')
source=LiteralSource(SPECIES,REACTIONS,LEFT,RIGHT);result=SquareSearch(SEARCH_CANDIDATE_BUDGET).search(source);dump('configured_search.json',result)
if result['status']=='yes':dump('configured_certificate.json',result['witness']['certificate'])
encoded=BinarySourceCodec.encode(source);(out/'configured_source.bits.txt').write_text(encoded+'\n');decoded=BinarySourceCodec.decode(encoded)
if decoded.left!=source.left or decoded.right!=source.right:raise ArithmeticError('Literal binary round trip failed.')
rows=[];details={}
for name,s in examples().items():
answer=SquareSearch(SEARCH_CANDIDATE_BUDGET).search(s);details[name]=answer;rows.append(dict(example=name,status=answer['status'],candidates=answer['attempted'],selected_entities=answer.get('witness',{}).get('certificate',{}).get('entities'),signed_flow=answer.get('witness',{}).get('certificate',{}).get('flow')))
dump('literal_and_signed_flow_examples.json',details)
dump('explicit_budget_exhaustion.json',SquareSearch(0).search(source))
fresh_switch=switch_check();dump('complete_switch_check.json',fresh_switch)
pairing={}
for label,arcs in [('desired',(('a0','b0'),('a1','b1'))),('crossed',(('a0','b1'),('a1','b0')))]:
g=DirectedLinkage(('a0','a1','b0','b1'),arcs,('a0','a1','b0','b1'));s=g.source();answer=SquareSearch(SEARCH_CANDIDATE_BUDGET).search(s);pairing[label]=dict(net=s.net,boundary_determinant=int(sp.Matrix(s.net).det()),search=answer)
dump('desired_versus_crossed.json',pairing)
census=[];arcs=(('a0','b0'),('a0','b1'),('a1','b0'),('a1','b1'))
for mask in range(16):
selected=tuple(e for i,e in enumerate(arcs) if mask&(1<<i));g=DirectedLinkage(('a0','a1','b0','b1'),selected,('a0','a1','b0','b1'));answer=SquareSearch(1000).search(g.source());expected=bool(mask&1 and mask&8)
if (answer['status']=='yes')!=expected:raise ArithmeticError('Small complete linkage/PAC equivalence check failed.')
census.append(dict(mask=mask,desired_paths=expected,pac_status=answer['status']))
dump('all_direct_linkage_graphs.json',census)
cnf=CNF(CNF_CLAUSES,CNF_VARIABLES);graph=cnf.compile();converted=graph.source();sat=cnf.assignments(ASSIGNMENT_BUDGET)
formula=dict(clauses=cnf.clauses,variables=cnf.variable_count,occurrences=sum(map(len,cnf.clauses)),vertices=len(graph.vertices),arcs=len(graph.arcs),source_entities=len(converted.entities),source_reactions=len(converted.reactions),max_stoichiometry=max([0]+[v for matrix in (converted.left,converted.right) for row in matrix for v in row]),assignment_search=sat)
dump('formula_source.json',dict(entities=converted.entities,reactions=converted.reactions,left=converted.left,right=converted.right))
if sat['status']=='sat':
paths=cnf.satisfying_paths(sat['assignment']);certificate=graph.path_certificate(paths);dump('formula_productivity_certificate.json',certificate);dump('formula_paths.json',dict(P=paths[0],Q=paths[1]));formula['certificate_verified']=certificate['verification']['accepted'];formula['square_size']=len(certificate['certificate']['entities']);formula['integer_flow_bits']=certificate['max_flow_bits']
else:formula['scope']='No direct PAC search on the large compiled network. UNSAT implies no PAC by the paper reduction theorem; budget exhaustion implies neither.'
dump('sat_to_network_summary.json',formula)
boundary=[]
for clauses,V in [((),0),(((),),0),(((1,),(-1,)),1),(((1,1),),1)]:
f=CNF(clauses,V);g=f.compile();answer=f.assignments();record=dict(clauses=clauses,variables=V,status=answer['status'],terminals=g.terminals,distinct_terminals=len(set(g.terminals))==4)
if answer['status']=='sat':record['certificate_verified']=g.path_certificate(f.satisfying_paths(answer['assignment']))['verification']['accepted']
else:record['no_pac_scope']='Inference from the published reduction, not exhaustive support enumeration of this large instance.'
boundary.append(record)
dump('formula_boundary_cases.json',boundary)
damaged=None
if result['status']=='yes':
c=json.loads(json.dumps(result['witness']['certificate']));c['flow']=[-v for v in c['flow']];damaged=check(c)
dump('rejected_reversed_certificate.json',damaged)
plot(out,source,result,pairing,rows)
print('Configured network:',result['status'],'after',result['attempted'],'square candidates.',flush=True)
print('Desired/crossed boundary determinants:',pairing['desired']['boundary_determinant'],pairing['crossed']['boundary_determinant'],flush=True)
print('Complete 20-vertex switch replay:',fresh_switch,flush=True)
print('Compiled formula:',formula,flush=True)
print('Certificates establish literal structural productivity and PAC existence. They do not prescribe concentrations, kinetics or conserved elemental chemistry. Exhaustive NO and budget-limited UNKNOWN are distinct. Lean and machine-time proofs are not rerun.',flush=True)
here=Path(__file__).parent;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(),sympy=sp.__version__,numpy=np.__version__,module_sha256={p.name:digest(p) for p in sorted(here.glob('*.py')) if p.name not in ['example.py','test_example.py']},output_sha256={p.name:digest(p) for p in sorted(out.iterdir()) if p.is_file() and p.name!='run_metadata.json'}))
def plot(out,source,result,pairing,rows):
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig,axs=plt.subplots(1,3,figsize=(11,4),layout='constrained')
for ax,matrix,title in zip(axs,[source.left,source.right,source.net],['Literal reactants L','Literal products P','Net change N = P - L']):
a=np.array(matrix);ax.imshow(a,cmap='coolwarm',vmin=-max(1,np.max(abs(a))),vmax=max(1,np.max(abs(a))))
for (i,j),v in np.ndenumerate(a):ax.text(j,i,str(v),ha='center',va='center',color='black')
ax.set(xticks=range(len(source.reactions)),xticklabels=[f'r{i}' for i in range(len(source.reactions))],yticks=range(len(source.entities)),yticklabels=source.entities,title=title,xlabel='Reversible reaction identity')
fig.savefig(out/'literal_network.png',dpi=180);fig.savefig(out/'literal_network.svg');plt.close(fig)
fig,axs=plt.subplots(1,2,figsize=(10,4),layout='constrained')
for ax,(name,d) in zip(axs,pairing.items()):
matrix=np.array(d['net']).T;ax.imshow(matrix,cmap='coolwarm',vmin=-4,vmax=4)
for (i,j),v in np.ndenumerate(matrix):ax.text(j,i,str(v),ha='center',va='center',fontsize=20)
ax.set(xticks=[0,1],xticklabels=['Path from a0','Path from a1'],yticks=[0,1],yticklabels=['Source boundary','Sink boundary'],title=f'{name.capitalize()} pairing: determinant {d["boundary_determinant"]}')
fig.savefig(out/'pairing_obstruction.png',dpi=180);fig.savefig(out/'pairing_obstruction.svg');plt.close(fig)
if __name__=='__main__':main()
Run output
Configured network: yes after 19 square candidates.
Desired/crossed boundary determinants: -3 0
Complete 20-vertex switch replay: {'vertices': 20, 'arcs': 29, 'simple_port_paths': 77, 'control_pairs': 3, 'control_pair_checks': 3, 'residual_mode_counts': {'(2, 6)': 2, '(3, 7)': 1}, 'all_three_properties': True, 'scope': 'Complete Python simple-path enumeration on the fixed 20-vertex gadget; independent finite replay, not a Lean kernel run.'}
Compiled formula: {'clauses': ((1,), (-1, 2)), 'variables': 2, 'occurrences': 3, 'vertices': 106, 'arcs': 157, 'source_entities': 157, 'source_reactions': 104, 'max_stoichiometry': 2, 'assignment_search': {'status': 'sat', 'assignment': (True, True)}, 'certificate_verified': True, 'square_size': 80, 'integer_flow_bits': 9}
Certificates establish literal structural productivity and PAC existence. They do not prescribe concentrations, kinetics or conserved elemental chemistry. Exhaustive NO and budget-limited UNKNOWN are distinct. Lean and machine-time proofs are not rerun.