# Build reaction systems from feasible families and catalyst graphs

This example implements the constructions in *Interior operators realizable by
autocatalytic networks: an antimatroid characterization* (7 September 2026).
It builds literal molecules, reactions, and catalyst incidences, then checks food
closure rather than assuming the target family. The manuscript hash is in the
source. This is original Python, not code extracted from the Lean development.

## Editable inputs and meaning

The inputs at the top of `example.py` are finite element names, feasible subsets,
and directed catalyst arcs. The default chain family is empty, {a}, {a,b},
{a,b,c}; arcs a->a, a->c, c->b reproduce the paper's worked example. There are
no concentrations, physical units, kinetic rates, or thermodynamic assumptions.

An antimatroid is a union-closed family containing empty, where each nonempty
member can lose some element and remain feasible. It records which reaction
sets can be generated from food. A digraph records which selected reactions
supply catalysts for others. Every selected vertex must have an incoming arc
from a selected vertex. Their intersection is the fixed family of maxRAF,
including empty; its nonempty members are RAFs.

A blocker B for element e is a set avoiding e that intersects every feasible
set containing e. A marker for (e,B) is required by reaction e and produced by
every reaction in B. Each reaction also consumes food and produces a private
catalyst. Catalyst arcs select which private products catalyse which reactions.
An empty blocker has no producer, correctly making an absent element unreachable.
Closure ignores catalysis, as required by structural RAF semantics; this does
not assert that a self-catalytic reaction can fire from zero concentration.

`USE_MINIMAL_BLOCKERS=True` retains only inclusion-minimal blockers. This is the
paper's reduction remark, explicitly outside its formal development. The script
checks both versions in a controlled chain-size sweep. It also constructs the
paper's four-element threshold certificate and a paired realization of the
family consisting of empty and sets of size at least `THRESHOLD` on
`PAIRED_THRESHOLD_SIZE` elements (default five).

## Run

Python 3.11 or newer; the model and tests use only the standard library.
Matplotlib is imported only for the figure-producing entry command. The direct
dependency is pinned; transitive dependencies are not fully locked.

Windows PowerShell:

```powershell
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe example.py --output outputs
.\.venv\Scripts\python.exe -m unittest -v
```

POSIX:

```sh
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python example.py --output outputs
.venv/bin/python -m unittest -v
```

## Reuse

`FixedFamily` validates union closure and computes the interior operator and
blockers. `Antimatroid` adds accessibility validation. `Digraph` handles catalyst
support. `ReactionSystem` provides synchronous closure, the RAF predicate,
maxRAF pruning, and recovery of the product-catalysis graph. The two realization
classes own the distinct one-reaction and two-reaction constructions.

```python
from example import Antimatroid, Digraph, MarkerRealization

feasible = Antimatroid(('prepare', 'finish'),
                      ((), ('prepare',), ('prepare', 'finish')))
graph = Digraph(feasible.elements,
                (('prepare', 'prepare'), ('finish', 'finish')))
model = MarkerRealization(feasible, graph, minimal=True)
print(model.system.maximal_raf({'finish'}))  # empty: missing reactant markers
print(model.system.maximal_raf({'prepare', 'finish'}))  # both reactions
model.audit()                               # compare every input subset
```

For an arbitrary union-closed family use `PairedRealization(FixedFamily(...))`.
`encode(S)` returns both the producer and gate reaction for each element of S.
Each partner produces the other's catalyst, forcing RAFs to contain complete
pairs. Producers generate markers before gates need them. `audit()` checks all
reaction subsets, including incomplete pairs and maxRAF after arbitrary deletions.
`record()` returns a serializable literal network. Use `ReactionSystem` directly
to experiment with alternative construction molecules or a different CRS.

Construction enumerates blockers and can use exponentially many molecules.
Ground sets are capped at eight; reaction-subset enumeration at sixteen;
all-antimatroid enumeration at four; exhaustive graphs at three. These limits
raise errors rather than report partial results. The limits can be deliberately
changed for research, but this is not a polynomial-time synthesis algorithm.

## Results and checks

The default network has three reactions and five marker molecules. Its only
nonempty RAFs are {a} and {a,b,c}. {a,b} is food-generated but lacks a catalyst;
{a,c} has graph support but lacks the marker produced by b. `layers.csv` and its
figure show the two independent requirements for every subset. `closure.csv`
records the three successive food-generation stages of the full set.

The four-element certificate has exactly five nonempty RAFs: all four triples
and the full set. The five-element threshold family has no same-ground
realization by the manuscript theorem; the script does not re-prove or search
that impossibility. Its paired construction has ten reactions, 25 markers, and
16 nonempty RAFs, verified over all 1,024 reaction subsets.

For a chain of eight elements, all blockers require 769 markers, while minimal
blockers need 28. Both realize the same food family and fixed family. The second
figure reports this exact construction cost, not a runtime benchmark.

The entry run independently reproduces the paper's complete finite counts:
1, 2, 6, 35, and 596 labelled antimatroids for ground sizes zero through four;
9,845 food-generation comparisons; and 143,753 fixed-family comparisons over
all catalyst digraphs through three vertices. The separate six test groups
include a permutation-of-reactions oracle for food generation, all 61 union-closed
families containing empty on three elements, incomplete pairs, absent elements,
unseeded cycles, food catalysis loops, and input/budget failures.

Outputs include literal network JSON for both constructions, blocker definitions,
CSV truth tables and counts, PNG/SVG figures, a summary, console output, and
run metadata with environment, source/manuscript hashes, elapsed time and output
hashes. No random sampling is used. SVG metadata may change across replays;
scientific counts and network content are deterministic.

All claims from the program are finite exact computations. The general
characterization and impossibility theorem remain mathematical results of the
paper. The script does not compile Lean, and does not extend the manuscript's
formal-verification claim to its unformalized corollaries or minimal-blocker remark.

## License

MIT is proposed for this original example code, pending the owner's license
choice. No license grant is asserted here. This does not change the license of
the manuscript or any third-party dependency.
