# Thermodynamic compatibility of overlapping autocatalytic cores

This example implements the literal networks, triangle interfaces, and three
obstruction mechanisms in *Thermodynamic compatibility of interacting
autocatalytic cores: an exact phase diagram and a layered obstruction theory*
(7 September 2026). It reconstructs productive species activities when possible
and returns checkable linear witnesses or obstruction certificates for the
preliminary tests. The manuscript hash is in the source. This is original Python
from the paper, not extracted or compiled Lean code.

## What the model means

A reversible reaction has reactant complex alpha, product complex beta, and
positive fixed transition-state factor b. For positive species activities z,
its oriented current is b*(z**alpha-z**beta), with monomials over the species.
Factors scale both reaction directions together. Activities are dimensionless;
currents use the paper's normalized convention, without an experimental time
calibration. The default factors are all one.

Each motif specifies its own species and reactions. Its production residuals
include only its reactions. Compatibility asks for one species-activity vector
that gives correctly directed currents and strictly positive production in each
core. This is a static condition, not an equilibrium, persistence, or total
network growth claim. Shared reactions are counted in each core's test but only
once in the full network balance. The output reports both balances explicitly.

Top-level inputs select the five triangle factors, common integer gain, the
free A-activity used for construction, the symmetric factor sweep and temperature
for an optional energy interpretation. The selected triangle factors may be
arbitrary positive rationals. Both branches have the same product complex mA;
the code does not apply the common-response rule to different product complexes.

## Components and reuse

`Reaction` stores literal complexes and a factor. `CoreFamily` owns stoichiometry,
motif balances, currents, the three linear filters, and an optional PAC audit.
`StrictLinearFeasibility` handles homogeneous strict inequalities A x > 0.
SciPy proposes a solution of A x >= 1 or a nonnegative alternative certificate;
Fraction arithmetic then checks every positive residual or the identity A.T w=0
with w>=0 and sum(w)>0. If rational reconstruction fails, the result is
`unresolved`, never a claim based solely on solver tolerance.

The three filters are:

* **Productive flow:** arbitrary reaction currents with the required directions
  and every motif's balances positive.
* **Direction:** species potentials whose oriented reaction affinities are
  positive. Failure has a nonnegative signed-circuit certificate.
* **Independent complexes:** a separate positive activity for every distinct
  complex, retaining factor-weighted currents and productivity but dropping
  the requirement that all activities come from one species vector.

These filters are not a hierarchy: the direction-obstructed paper network still
passes the independent-complex test. Passing all three is necessary but not
sufficient for a species-activity realization. The generic model does not claim
to solve the nonlinear realization problem for arbitrary networks.

`TriangleInterface` projects a gain-m triangle onto the exact open response
interval (R/m,R), where R=b0*(1/b1+1/b2), and reconstructs normalized currents
with 1/m < v < u < 1. `TrianglePair` intersects the intervals of two same-gain
branches and reconstructs actual positive species activities, then replays them
against the literal network.

```python
from fractions import Fraction
from example import TrianglePair

pair = TrianglePair((1, 2, 3, 3, 4), gain=2)
witness = pair.witness(a=Fraction(2, 3))
if witness is not None:
    print(witness['activities'])
    print(witness['motif_production'])
    print(witness['whole_network_production'])
print(pair.family.filters()['independent_complex'].record())
```

For a different topology, construct `Reaction` and `Motif` objects and pass them
to `CoreFamily`. Reaction and species indices start at zero. Motifs need not
already be certified PACs; `audit_pac()` checks side incidence, productive flow
with unrestricted current signs, and every proper side-incident submotif. It
uses a declared species-plus-reactions enumeration budget of sixteen. The audit
has exponential cost and is intended for small cores, not large-network discovery.

## Run

Python 3.11 or newer. Direct dependencies are pinned, not the entire transitive
environment.

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
```

Edit FACTORS and GAIN for the selected model. K_SWEEP separately controls the
paper's symmetric gain-two family (1,1,1,k,k). It does not inherit another gain
chosen for the selected model. Standard free energies are absorbed into the
activities. The energy window RT ln(2), approximately 1.7174 kJ/mol at 298 K,
applies only to the symmetric family with equal nonexponential prefactors.

## Default results

At k=1 the construction returns A=1/2, B=2/5 and C=D=207/640. Currents are
(1/10,49/640,47/640,49/640,47/640); each core has production residuals
(3/64,3/128,1/320). The whole-network B residual is -17/320: this is a direct
illustration of the distinction between the paper's per-core predicate and
total-network growth.

The symmetric triangle family is compatible exactly for 1/2 < k < 2; endpoints
are rejected using strict rational comparisons. The first figure displays the
common response interval. Arbitrary factors are handled by the reciprocal-sum
condition and constructive witness, not by a numerical nonlinear search.

The three obstruction fixtures reproduce:

* The eight-species paper pair: productive flow is feasible, direction is not,
  and the all-ones signed circuit is checked exactly. Independent complexes are
  feasible, emphasizing that this relaxation can forget directional constraints.
* The triangles at k=10: productive flow and direction pass, but independent
  complexes fail. Their required response intervals do not overlap.
* A<->B, B<->2A, B<->3A with factors (1,1,2): all three filters pass. Independent
  activities (yA,yB,y2A,y3A)=(4,3,9/4,11/4) give currents (1,3/4,1/2).
  A species vector would require 0<A<1, B>(A+2A^2)/3 and
  B<(A+2A^3)/3. The lower bound exceeds the upper by 2A^2(1-A)/3>0, so there
  is no lift. The second figure displays this gap; the analytic inequality,
  not the plotted samples, supplies the obstruction.

The bounded dominance enumeration also reproduces the paper's count of 441.
It is a discovery family, not a global minimality assertion.

## Outputs, checks, and scope

`models_and_certificates.json` exports every literal network, ordered complexes,
motifs, rational linear witness or dual vector, and PAC audit. Rows of each
matrix can be reconstructed with the model methods; dual entries follow that
row order. CSV files record filter outcomes, the factor sweep, monomial bounds,
and the dominance family. Figures, console output, summary and metadata record
source/manuscript hashes, dependency versions, elapsed time and output hashes.
No random sampling is used. LP solvers may choose different valid rational
witnesses across versions; every returned certificate is checked exactly.

Six test groups replay independent literal currents, test strict endpoints and
near-endpoint witnesses, sweep unequal factors and gains, check scale invariance,
reconstruct interface currents, verify all three obstruction fixtures and the
441 count, audit source-minimality with currents of either sign, and check exact
linear alternatives and invalid inputs. General same-product gain extensions
are derived from the interface construction and tested; formal coverage remains
as stated in the manuscript. No Lean compilation is performed.

## 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.
