A family of autocatalytic reaction sets has two distinct requirements: its reactants must be buildable from food, and its catalysts must be available within the selected set. This example turns those two specifications into a literal reaction system and checks that it has exactly the requested RAFs.

Subset truth table shows food generation and catalyst support meeting exactly at empty, a, and a b c.
The paper's three-element worked example, evaluated by literal molecular closure. The last column is the intersection of the first two. Empty is a fixed set of maxRAF; the other two selected rows are the nonempty RAFs.
All-blocker marker counts grow from zero to 769 as chain size reaches eight, while minimal blockers need 28 markers.
Exact marker counts for chain antimatroids. Both constructions use one reaction per element and pass the same food-generation and fixed-family checks. Minimal blockers are the paper's optional reduction, not part of its formal development.

The food-generation specification is an antimatroid: feasible sets can be built by adding elements one at a time and are closed under union. The catalyst specification is a directed graph: every selected reaction needs a catalyst-producing predecessor inside the selected set. The paper shows when both specifications can be realized together using exactly one reaction per element (a same-ground realization).

The worked example orders food generation as aa, then bb, then cc, while catalyst arcs are aaa\to a, aca\to c, and cbc\to b. The set {a,b}\{a,b\} passes food generation but lacks a catalyst for bb. The set {a,c}\{a,c\} has catalyst support but cannot generate a reactant needed by cc. Only {a}\{a\} and {a,b,c}\{a,b,c\} are nonempty RAFs. The maxRAF algorithm returns the largest RAF within any allowed reaction set, or empty if none exists. Empty is included among its unchanged outputs, but is not a RAF.

The construction makes marker molecules for blockers: a blocker for an element intersects every feasible set containing it. The element's reaction requires that marker; reactions in the blocker produce it. Private catalyst products encode the graph separately. The resulting network has actual reactant, product, and catalyst lists, so the checks compute molecular closure independently of the intended family.

One reaction per element can require many auxiliary molecules. For an eight-element chain, the full construction uses 769 marker molecules; retaining only minimal blockers needs 28 and gives the same fixed family. This reduction is described in the paper's remarks and is checked computationally here.

The package also builds the paper's four-element example whose RAFs are exactly the sets of size at least three. The corresponding five-element family cannot be realized on the same ground set by the manuscript theorem. Allowing a producer and a gate per element yields a ten-reaction realization with 16 RAFs, verified across all 1,024 reaction subsets, including incomplete pairs.

Download the package, install requirements.txt, run python example.py --output outputs, and check it with python -m unittest -v. The inputs at the top specify the feasible family and catalyst graph. Import FixedFamily, Antimatroid, Digraph, MarkerRealization, or PairedRealization to synthesize other examples, export their reaction lists, or inspect maxRAF after deletions. Explicit enumeration caps bound the exploratory calculations.

The default run reproduces the paper's 9,845 food-generation comparisons and 143,753 fixed-family comparisons. Separate tests use reaction-order oracles and all 61 union-closed families containing empty on three elements. These are exact finite checks of structural models; they do not simulate concentration dynamics, compile Lean, or computationally prove the general impossibility theorem.

Python source

"""Build literal RAF realizations from feasible families and catalyst graphs.

The paper's marker construction and paired construction; finite exact checks.
Run python example.py --output outputs. Importing this module performs no work.
"""
from __future__ import annotations
import argparse
import csv
from dataclasses import dataclass
import hashlib
from itertools import combinations
import json
from pathlib import Path
import platform
import time

# USER INPUTS ---------------------------------------------------------------
ELEMENTS = ('a', 'b', 'c')
FEASIBLE_SETS = ((), ('a',), ('a','b'), ('a','b','c'))
CATALYST_ARCS = (('a','a'), ('a','c'), ('c','b'))  # producer -> catalysed reaction
USE_MINIMAL_BLOCKERS = False  # True uses the paper's unformalized reduction remark
CHAIN_SIZES = (1,2,3,4,5,6,7,8)
PAIRED_THRESHOLD_SIZE = 5
THRESHOLD = 3
EXHAUSTIVE_ANTIMATROID_SIZE = 4  # all labelled antimatroids through this size
EXHAUSTIVE_GRAPH_SIZE = 3       # all graphs for the antimatroids through this size
MAX_GROUND_SIZE = 8            # explicit construction/enumeration budgets
MAX_REACTION_ENUMERATION = 16
PAPER_SHA256 = '0b534fbc24da9d3482699977e9f464b3fc7a5e5b48e1ae46a720b9ff4f9bcd44'
# Inputs are finite sets and directed incidences, without kinetic/physical units.
# --------------------------------------------------------------------------


def subsets(elements):
    elements=tuple(elements)
    for size in range(len(elements)+1):
        for selected in combinations(elements,size): yield frozenset(selected)


def ordered(family):
    return sorted(family,key=lambda s:(len(s),sorted(s)))


def label(s):
    return '{'+','.join(sorted(s))+'}' if s else 'empty'


class FixedFamily:
    """Union-closed fixed sets, including empty; owns the interior operator."""
    def __init__(self,elements,members):
        elements=tuple(elements)
        if len(set(elements))!=len(elements) or any(not isinstance(e,str) or not e for e in elements):
            raise ValueError('Elements must be distinct nonempty strings.')
        if len(elements)>MAX_GROUND_SIZE: raise ValueError('Ground-set budget exceeded.')
        self.elements=frozenset(elements);self.members=frozenset(frozenset(s) for s in members)
        if frozenset() not in self.members or any(not s<=self.elements for s in self.members):
            raise ValueError('Members must be subsets of the ground set and include empty.')
        if any(a|b not in self.members for a in self.members for b in self.members):
            raise ValueError('Fixed family must be union-closed.')

    def interior(self,s):
        s=frozenset(s)
        if not s<=self.elements: raise ValueError('Unknown element.')
        return frozenset().union(*(a for a in self.members if a<=s))

    def blockers(self,e,minimal=False):
        if e not in self.elements: raise ValueError('Unknown blocker target.')
        result=tuple(b for b in subsets(sorted(self.elements-{e})) if e not in self.interior(self.elements-b))
        return tuple(b for b in result if not any(a<b for a in result)) if minimal else result

    def accessible(self):
        return all(not s or any(s-{e} in self.members for e in s) for s in self.members)


class Antimatroid(FixedFamily):
    def __init__(self,elements,members):
        super().__init__(elements,members)
        if not self.accessible(): raise ValueError('An antimatroid must be accessible.')


class Digraph:
    """Loops permitted; arc direction is catalyst producer -> consumer."""
    def __init__(self,elements,arcs):
        self.elements=frozenset(elements);self.arcs=frozenset(tuple(a) for a in arcs)
        if any(len(a)!=2 or not set(a)<=self.elements for a in self.arcs):
            raise ValueError('Graph arcs must have two known endpoints.')
        self.predecessors={e:frozenset(u for u,v in self.arcs if v==e) for e in self.elements}

    def supported(self,s):
        s=frozenset(s)
        if not s<=self.elements: raise ValueError('Unknown graph vertex.')
        return all(self.predecessors[e]&s for e in s)


@dataclass(frozen=True)
class Reaction:
    identifier: str
    reactants: frozenset[str]
    products: frozenset[str]
    catalysts: frozenset[str]

    def __post_init__(self):
        for field in ('reactants','products','catalysts'):
            object.__setattr__(self,field,frozenset(getattr(self,field)))


class ReactionSystem:
    """Closure uses reactants alone. Catalysis is checked after closure."""
    def __init__(self,reactions,food=('f',)):
        reactions=tuple(reactions);self.reactions={r.identifier:r for r in reactions}
        if len(reactions)!=len(self.reactions): raise ValueError('Duplicate reaction identifiers.')
        self.food=frozenset(food);self.identifiers=frozenset(self.reactions)

    def selected(self,s):
        s=frozenset(s)
        if not s<=self.identifiers: raise ValueError('Unknown reaction identifier.')
        return s

    def closure_stages(self,s):
        s=self.selected(s);stages=[self.food]
        while True:
            current=stages[-1]
            following=current.union(*(self.reactions[e].products for e in s if self.reactions[e].reactants<=current))
            if following==current: return stages
            stages.append(following)

    def food_generated(self,s):
        s=self.selected(s);closure=self.closure_stages(s)[-1]
        return all(self.reactions[e].reactants<=closure for e in s)

    def is_raf(self,s):
        s=self.selected(s);closure=self.closure_stages(s)[-1]
        return bool(s) and all(self.reactions[e].reactants<=closure and self.reactions[e].catalysts&closure for e in s)

    def maximal_raf(self,s):
        s=self.selected(s)
        while s:
            closure=self.closure_stages(s)[-1]
            kept=frozenset(e for e in s if self.reactions[e].reactants<=closure and self.reactions[e].catalysts&closure)
            if kept==s: return s
            s=kept
        return s

    def fixed_family(self):
        if len(self.identifiers)>MAX_REACTION_ENUMERATION: raise ValueError('Reaction-subset enumeration budget exceeded.')
        return frozenset(s for s in subsets(sorted(self.identifiers)) if not s or self.is_raf(s))

    def product_graph(self):
        arcs={(u,e) for u,r in self.reactions.items() for e,t in self.reactions.items() if r.products&t.catalysts}
        arcs|={(e,e) for e,r in self.reactions.items() if self.food&r.catalysts}
        return Digraph(self.identifiers,arcs)

    def record(self):
        return dict(food=sorted(self.food),reactions=[dict(id=r.identifier,reactants=sorted(r.reactants),
            products=sorted(r.products),catalysts=sorted(r.catalysts)) for r in self.reactions.values()])


class MarkerInventory:
    """Shared mechanical encoding; names use indices to avoid label collisions."""
    def __init__(self,family,minimal=False):
        self.elements=sorted(family.elements);self.index={e:i for i,e in enumerate(self.elements)}
        self.blockers={e:family.blockers(e,minimal) for e in self.elements}
        self.records=[(e,b,f'm:{self.index[e]}:{k}') for e in self.elements for k,b in enumerate(self.blockers[e])]

    def required(self,e): return frozenset(m for t,b,m in self.records if t==e)
    def produced(self,e): return frozenset(m for t,b,m in self.records if e in b)


class MarkerRealization:
    def __init__(self,feasible:Antimatroid,graph:Digraph,minimal=False):
        if not isinstance(feasible,Antimatroid): raise ValueError('Same-ground construction requires an Antimatroid.')
        if feasible.elements!=graph.elements: raise ValueError('Family and graph must use the same ground set.')
        self.feasible,self.graph=feasible,graph;self.markers=MarkerInventory(feasible,minimal)
        private={e:f'c:{i}' for e,i in self.markers.index.items()}
        self.system=ReactionSystem(Reaction(e,{'f'}|self.markers.required(e),{private[e]}|self.markers.produced(e),
                    {private[u] for u in graph.predecessors[e]}) for e in self.markers.elements)

    def audit(self):
        expected=FixedFamily(self.feasible.elements,(s for s in self.feasible.members if self.graph.supported(s)))
        rows=[]
        for s in subsets(sorted(self.feasible.elements)):
            fg=self.system.food_generated(s);support=self.graph.supported(s);raf=self.system.is_raf(s)
            maximum=self.system.maximal_raf(s)
            if fg!=(s in self.feasible.members) or (not s or raf)!=(s in expected.members) or maximum!=expected.interior(s):
                raise ArithmeticError('Literal realization differs from the two-layer specification.')
            rows.append(dict(selected=label(s),food_generated=fg,catalyst_supported=support,is_raf=raf,
                fixed_set=(not s or raf),maximal_raf=label(maximum),closure_stages=len(self.system.closure_stages(s))-1))
        if self.system.product_graph().arcs!=self.graph.arcs: raise ArithmeticError('Product catalyst graph mismatch.')
        return rows


class PairedRealization:
    def __init__(self,family:FixedFamily,minimal=False):
        self.family=family;self.markers=MarkerInventory(family,minimal)
        self.pairs={e:(f'p:{i}',f'g:{i}') for e,i in self.markers.index.items()};reactions=[]
        for e,i in self.markers.index.items():
            p,g=self.pairs[e];alpha,beta=f'alpha:{i}',f'beta:{i}'
            reactions.extend([Reaction(p,{'f'},{alpha}|self.markers.produced(e),{beta}),
                Reaction(g,{'f'}|self.markers.required(e),{beta},{alpha})])
        self.system=ReactionSystem(reactions)

    def encode(self,s):
        s=frozenset(s)
        if not s<=self.family.elements: raise ValueError('Unknown element.')
        return frozenset(r for e in s for r in self.pairs[e])

    def audit(self):
        actual=self.system.fixed_family();expected=frozenset(self.encode(s) for s in self.family.members)
        if actual!=expected: raise ArithmeticError('Paired construction has missing or spurious fixed sets.')
        # Includes incomplete pairs: projection means both partner reactions available.
        for t in subsets(sorted(self.system.identifiers)):
            available={e for e,pair in self.pairs.items() if set(pair)<=t}
            if self.system.maximal_raf(t)!=self.encode(self.family.interior(available)):
                raise ArithmeticError('Paired maxRAF differs on a restricted reaction set.')
        return dict(elements=len(self.family.elements),reactions=len(self.system.identifiers),
            reaction_subsets_checked=2**len(self.system.identifiers),nonempty_rafs=len(actual)-1,
            marker_molecules=len(self.markers.records))


def threshold_family(n,k):
    if not isinstance(n,int) or not 0<=n<=MAX_GROUND_SIZE or not isinstance(k,int) or k<1:
        raise ValueError('Threshold family requires a bounded nonnegative size and positive threshold.')
    elements=tuple(str(i) for i in range(n))
    return FixedFamily(elements,(s for s in subsets(elements) if not s or len(s)>=k))


def four_element_certificate():
    elements=('a','b','c','d')
    small=((),('a',),('b',),('a','b'),('a','c'),('b','c'))
    feasible=Antimatroid(elements,(*small,*(s for s in subsets(elements) if len(s)>=3)))
    graph=Digraph(elements,(('b','a'),('d','a'),('c','b'),('d','b'),('a','c'),('d','c'),('a','d'),('b','d')))
    return MarkerRealization(feasible,graph)


def all_antimatroids(n):
    if not isinstance(n,int) or not 0<=n<=4: raise ValueError('All-family enumeration is capped at four elements.')
    elements=tuple(str(i) for i in range(n));universe=tuple(subsets(elements))
    for mask in range(1<<(len(universe)-1)):
        family=frozenset([frozenset(),*(s for i,s in enumerate(universe[1:]) if mask>>i&1)])
        if any(s and not any(s-{e} in family for e in s) for s in family): continue
        if any(a|b not in family for a in family for b in family): continue
        yield Antimatroid(elements,family)


def exhaustive_checks(max_antimatroid=4,max_graph=3):
    if not 0<=max_graph<=min(3,max_antimatroid) or not 0<=max_antimatroid<=4:
        raise ValueError('Exhaustive checks permit antimatroids through 4 and graphs through 3.')
    rows=[]
    for n in range(max_antimatroid+1):
        count=fg_checks=raf_checks=0
        for feasible in all_antimatroids(n):
            count+=1;elements=sorted(feasible.elements)
            base=MarkerRealization(feasible,Digraph(elements,()))
            selections=tuple(subsets(elements))
            for s in selections:
                if base.system.food_generated(s)!=(s in feasible.members): raise ArithmeticError('Food family mismatch.')
                fg_checks+=1
            if n<=max_graph:
                arcs=tuple((u,v) for u in elements for v in elements)
                for mask in range(1<<len(arcs)):
                    graph=Digraph(elements,(a for i,a in enumerate(arcs) if mask>>i&1))
                    model=MarkerRealization(feasible,graph)
                    for s in selections:
                        if (not s or model.system.is_raf(s))!=((s in feasible.members) and graph.supported(s)):
                            raise ArithmeticError('Literal RAF factorization mismatch.')
                        raf_checks+=1
        rows.append(dict(elements=n,antimatroids=count,food_comparisons=fg_checks,raf_comparisons=raf_checks))
    return rows


def write_csv(path,rows):
    with path.open('w',newline='',encoding='utf-8') as f:
        writer=csv.DictWriter(f,fieldnames=list(rows[0]));writer.writeheader();writer.writerows(rows)


def plot(truth,scaling,output):
    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    from matplotlib.colors import ListedColormap
    with plt.rc_context({'font.size':11,'figure.facecolor':'white','savefig.facecolor':'white','svg.fonttype':'none'}):
        fig,ax=plt.subplots(figsize=(7.2,4.5),layout='constrained')
        data=[[int(r[c]) for c in ('food_generated','catalyst_supported','fixed_set')] for r in truth]
        ax.imshow(data,cmap=ListedColormap(['#e8edf0','#0072B2']),vmin=0,vmax=1,aspect='auto')
        ax.set_xticks(range(3),['Food generated','Catalyst supported','Fixed set (intersection)'])
        ax.set_yticks(range(len(truth)),[r['selected'] for r in truth])
        for i,row in enumerate(data):
            for j,v in enumerate(row): ax.text(j,i,'yes' if v else 'no',ha='center',va='center',color='white' if v else '#30363a')
        ax.tick_params(length=0);fig.savefig(output/'layers.png',dpi=220);fig.savefig(output/'layers.svg');plt.close(fig)
        fig,ax=plt.subplots(figsize=(7.2,4.5),layout='constrained')
        ax.plot([r['elements'] for r in scaling],[r['all_blockers'] for r in scaling],'o-',label='All blockers (main construction)',color='#0072B2')
        ax.plot([r['elements'] for r in scaling],[r['minimal_blockers'] for r in scaling],'s--',label='Minimal blockers (paper remark)',color='#D55E00')
        ax.set(xlabel='Length of the chain antimatroid',ylabel='Auxiliary marker molecules')
        ax.spines[['top','right']].set_visible(False);ax.grid(axis='y',color='#e3e6e8');ax.legend(fontsize=9)
        fig.savefig(output/'markers.png',dpi=220);fig.savefig(output/'markers.svg');plt.close(fig)


def main():
    parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--output',type=Path,default=Path('outputs'))
    args=parser.parse_args();args.output.mkdir(parents=True,exist_ok=True);start=time.perf_counter()
    inputs=dict(elements=ELEMENTS,feasible_sets=FEASIBLE_SETS,catalyst_arcs=CATALYST_ARCS,minimal_blockers=USE_MINIMAL_BLOCKERS,
        chain_sizes=CHAIN_SIZES,paired_threshold_size=PAIRED_THRESHOLD_SIZE,threshold=THRESHOLD,
        exhaustive_antimatroid_size=EXHAUSTIVE_ANTIMATROID_SIZE,exhaustive_graph_size=EXHAUSTIVE_GRAPH_SIZE,
        max_ground_size=MAX_GROUND_SIZE,max_reaction_enumeration=MAX_REACTION_ENUMERATION)
    intro='Resolved inputs: '+json.dumps(inputs);print(intro,flush=True)
    model=MarkerRealization(Antimatroid(ELEMENTS,FEASIBLE_SETS),Digraph(ELEMENTS,CATALYST_ARCS),USE_MINIMAL_BLOCKERS)
    truth=model.audit();write_csv(args.output/'layers.csv',truth)
    blockers=[dict(target=e,blocker=label(b),marker=m) for e,b,m in model.markers.records]
    (args.output/'blockers.json').write_text(json.dumps(blockers,indent=2)+'\n',encoding='utf-8')
    (args.output/'network.json').write_text(json.dumps(model.system.record(),indent=2)+'\n',encoding='utf-8')
    write_csv(args.output/'closure.csv',[dict(stage=i,molecules=' '.join(sorted(s))) for i,s in enumerate(model.system.closure_stages(ELEMENTS))])
    certificate=four_element_certificate();certificate.audit()
    if any(bool(s) and (certificate.system.is_raf(s)!=(len(s)>=3)) for s in subsets(sorted(certificate.feasible.elements))):
        raise ArithmeticError('Four-element threshold certificate failed.')
    paired=PairedRealization(threshold_family(PAIRED_THRESHOLD_SIZE,THRESHOLD),USE_MINIMAL_BLOCKERS);paired_audit=paired.audit()
    (args.output/'paired_network.json').write_text(json.dumps(paired.system.record(),indent=2)+'\n',encoding='utf-8')
    scaling=[]
    for n in CHAIN_SIZES:
        elements=tuple(str(i) for i in range(n));family=Antimatroid(elements,(elements[:i] for i in range(n+1)))
        all_model=MarkerRealization(family,Digraph(elements,((e,e) for e in elements)))
        minimal_model=MarkerRealization(family,all_model.graph,True)
        all_model.audit();minimal_model.audit()
        scaling.append(dict(elements=n,reactions=n,all_blockers=len(all_model.markers.records),minimal_blockers=len(minimal_model.markers.records)))
    write_csv(args.output/'marker_scaling.csv',scaling)
    checks=exhaustive_checks(EXHAUSTIVE_ANTIMATROID_SIZE,EXHAUSTIVE_GRAPH_SIZE);write_csv(args.output/'exhaustive_checks.csv',checks)
    plot(truth,scaling,args.output)
    summary=dict(inputs=inputs,worked_fixed_sets=[label(s) for s in ordered(model.system.fixed_family())],
        worked_markers=len(model.markers.records),four_element_threshold_rafs=len(certificate.system.fixed_family())-1,
        paired_threshold=paired_audit,marker_scaling=scaling,exhaustive_checks=checks,
        total_food_comparisons=sum(r['food_comparisons'] for r in checks),total_raf_comparisons=sum(r['raf_comparisons'] for r in checks),
        evidence='Exact finite constructions and exhaustive subset checks. Five-element same-ground impossibility is the manuscript theorem, not searched here. No Lean compilation.')
    transcript=json.dumps(summary,indent=2)
    (args.output/'summary.json').write_text(transcript+'\n',encoding='utf-8')
    (args.output/'console.txt').write_text(intro+'\n'+transcript+'\n',encoding='utf-8')
    import matplotlib
    metadata=dict(paper_sha256=PAPER_SHA256,source_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
        python=platform.python_version(),matplotlib=matplotlib.__version__,platform=platform.platform(),processor=platform.processor(),
        elapsed_seconds=time.perf_counter()-start,command='python example.py --output outputs',seed_policy='No random sampling.',
        output_sha256={p.name:hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(args.output.iterdir()) if p.is_file() and p.name!='run_metadata.json'})
    (args.output/'run_metadata.json').write_text(json.dumps(metadata,indent=2)+'\n',encoding='utf-8');print(transcript)


if __name__=='__main__': main()
Run output
Resolved inputs: {"elements": ["a", "b", "c"], "feasible_sets": [[], ["a"], ["a", "b"], ["a", "b", "c"]], "catalyst_arcs": [["a", "a"], ["a", "c"], ["c", "b"]], "minimal_blockers": false, "chain_sizes": [1, 2, 3, 4, 5, 6, 7, 8], "paired_threshold_size": 5, "threshold": 3, "exhaustive_antimatroid_size": 4, "exhaustive_graph_size": 3, "max_ground_size": 8, "max_reaction_enumeration": 16}
{
  "inputs": {
    "elements": [
      "a",
      "b",
      "c"
    ],
    "feasible_sets": [
      [],
      [
        "a"
      ],
      [
        "a",
        "b"
      ],
      [
        "a",
        "b",
        "c"
      ]
    ],
    "catalyst_arcs": [
      [
        "a",
        "a"
      ],
      [
        "a",
        "c"
      ],
      [
        "c",
        "b"
      ]
    ],
    "minimal_blockers": false,
    "chain_sizes": [
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8
    ],
    "paired_threshold_size": 5,
    "threshold": 3,
    "exhaustive_antimatroid_size": 4,
    "exhaustive_graph_size": 3,
    "max_ground_size": 8,
    "max_reaction_enumeration": 16
  },
  "worked_fixed_sets": [
    "empty",
    "{a}",
    "{a,b,c}"
  ],
  "worked_markers": 5,
  "four_element_threshold_rafs": 5,
  "paired_threshold": {
    "elements": 5,
    "reactions": 10,
    "reaction_subsets_checked": 1024,
    "nonempty_rafs": 16,
    "marker_molecules": 25
  },
  "marker_scaling": [
    {
      "elements": 1,
      "reactions": 1,
      "all_blockers": 0,
      "minimal_blockers": 0
    },
    {
      "elements": 2,
      "reactions": 2,
      "all_blockers": 1,
      "minimal_blockers": 1
    },
    {
      "elements": 3,
      "reactions": 3,
      "all_blockers": 5,
      "minimal_blockers": 3
    },
    {
      "elements": 4,
      "reactions": 4,
      "all_blockers": 17,
      "minimal_blockers": 6
    },
    {
      "elements": 5,
      "reactions": 5,
      "all_blockers": 49,
      "minimal_blockers": 10
    },
    {
      "elements": 6,
      "reactions": 6,
      "all_blockers": 129,
      "minimal_blockers": 15
    },
    {
      "elements": 7,
      "reactions": 7,
      "all_blockers": 321,
      "minimal_blockers": 21
    },
    {
      "elements": 8,
      "reactions": 8,
      "all_blockers": 769,
      "minimal_blockers": 28
    }
  ],
  "exhaustive_checks": [
    {
      "elements": 0,
      "antimatroids": 1,
      "food_comparisons": 1,
      "raf_comparisons": 1
    },
    {
      "elements": 1,
      "antimatroids": 2,
      "food_comparisons": 4,
      "raf_comparisons": 8
    },
    {
      "elements": 2,
      "antimatroids": 6,
      "food_comparisons": 24,
      "raf_comparisons": 384
    },
    {
      "elements": 3,
      "antimatroids": 35,
      "food_comparisons": 280,
      "raf_comparisons": 143360
    },
    {
      "elements": 4,
      "antimatroids": 596,
      "food_comparisons": 9536,
      "raf_comparisons": 0
    }
  ],
  "total_food_comparisons": 9845,
  "total_raf_comparisons": 143753,
  "evidence": "Exact finite constructions and exhaustive subset checks. Five-element same-ground impossibility is the manuscript theorem, not searched here. No Lean compilation."
}