Two autocatalytic cores may each produce a surplus of their species when tested separately, yet fail to do so at the same chemical activities (effective concentrations). This example checks whether their reaction directions, rate magnitudes and shared-species constraints can all be satisfied together. For the paper's two-triangle family, it also constructs a valid realization whenever one exists.

The open response intervals overlap only for the private factor ratio strictly between one half and two.
Gain-two triangles with factors (1,1,1,k,k). The shaded overlap supplies constructive activity witnesses. Boundaries are excluded; the exact interval test, rather than plotting resolution, decides compatibility.
A lower bound on B lies strictly above its required upper bound for every A between zero and one.
The two-species monomial obstruction. Core 1 requires B above the solid curve, while core 2 requires it below the dashed curve. Their analytic difference is 2 A squared times (1 minus A) divided by three, strictly positive throughout the required interval.

The triangles are ABC2AA\rightleftharpoons B\rightleftharpoons C\rightleftharpoons2A and ABD2AA\rightleftharpoons B\rightleftharpoons D\rightleftharpoons2A. They share ABA\rightleftharpoons B. A reaction with factor bb carries the difference of its reactant and product activities (products of species activities raised to their reaction counts), multiplied by bb. The same species activity must be used wherever that species appears.

Writing A, B, C and D also for species activities, each branch constrains the ratio q=(BA2)/(AB)q=(B-A^2)/(A-B). With left factors one and right factors kk, the required intervals are (1,2)(1,2) and (1/k,2/k)(1/k,2/k). They overlap exactly when 1/2<k<21/2<k<2; both endpoints are excluded because production must be strictly positive. For arbitrary positive factors, TriangleInterface constructs the interval and normalized currents, and TrianglePair converts a common response into positive activities and checks the resulting literal currents.

At the default k=1k=1, the code returns A=1/2A=1/2, B=2/5B=2/5, and C=D=207/640C=D=207/640. Each core has production residuals (3/64,3/128,1/320)(3/64,3/128,1/320), all positive. The full network nevertheless has a negative net BB balance: the two core tests each count the shared reaction, while the full network contains it once. This example concerns the paper's static per-core compatibility, not a steady state or whole-network growth guarantee.

The package separately checks three necessary conditions: productive flow, a common direction potential, and independent positive activities for each complex. Linear programs propose witnesses or obstruction vectors, which are then checked with exact rational arithmetic. The filters are independent: the direction-obstructed example still passes the independent-complex relaxation. At k=10k=10, directions pass but the fixed magnitudes prevent any common response.

The second figure shows a different failure. For ABA\rightleftharpoons B, B2AB\rightleftharpoons2A, and B3AB\rightleftharpoons3A with factors (1,1,2)(1,1,2), all three linear filters pass. A species-level realization would require 0<A<10<A<1 and simultaneously B>(A+2A2)/3B>(A+2A^2)/3 and B<(A+2A3)/3B<(A+2A^3)/3. The lower bound exceeds the upper by 2A2(1A)/3>02A^2(1-A)/3>0. Independent complex activities can satisfy the currents, but no common species vector can produce them.

Download the package, install requirements.txt, run python example.py --output outputs, and check it with python -m unittest -v. Edit factors, common gain and construction inputs at the top. Import Reaction, CoreFamily, StrictLinearFeasibility, TriangleInterface, or TrianglePair to explore other networks, inspect exact certificates, and reconstruct activity witnesses. JSON exports the models and CSV files retain the sweeps and filter results.

The tests check endpoints, unequal factors and gains, independent current formulas, both signs of productive currents, and every proper side-incident submotif of the paper's cores. The bounded search reproduces the paper's 441 dominance examples. These are exact finite checks and explicit constructions; the general nonlinear feasibility problem is not solved by the three filters, and no new Lean verification is claimed.

Python source

"""Static thermodynamic compatibility, exact triangle synthesis, and obstructions.

Linear programs propose witnesses/certificates; Fraction arithmetic checks them.
"""
from __future__ import annotations
import argparse
import csv
from dataclasses import dataclass
from fractions import Fraction as F
from itertools import combinations
import hashlib
import json
from math import log
from pathlib import Path
import platform
import time
import numpy as np
from scipy.optimize import linprog

# USER INPUTS ---------------------------------------------------------------
FACTORS = ('1','1','1','1','1') # shared, left1, left2, right1, right2
GAIN = 2                     # same product complex on both branches
A_ACTIVITY = '1/2'            # free construction choice, dimensionless, 0 < A < 1
K_SWEEP = tuple(F(i,100) for i in range(20,301,2))
TEMPERATURE_K = 298.0         # optional symmetric equal-prefactor energy reading
GAS_CONSTANT_J_MOL_K = 8.314462618
RATIONAL_DENOMINATOR_LIMIT = 1_000_000
MAX_PAC_ENUMERATION_BITS = 16 # species + reactions of a motif
PAPER_SHA256 = 'fcd130caf5eb188887d31e607de61c6ad6a65053acf1c6ed3a62de7b2e9006d0'
# Activities and factors use the paper's normalized current convention.
# These are static productive-current witnesses, not steady operating states.
# --------------------------------------------------------------------------


def matrix(rows): return np.array([[F(v) for v in row] for row in rows],dtype=object)
def subsets(values):
    values=tuple(values)
    for size in range(len(values)+1):
        for s in combinations(values,size): yield tuple(s)


@dataclass(frozen=True)
class LinearDecision:
    status: str
    vector: tuple[F,...]
    residuals: tuple[F,...]

    def record(self):
        return dict(status=self.status,vector=list(map(str,self.vector)),residuals=list(map(str,self.residuals)))


class StrictLinearFeasibility:
    """Solve A x > 0 over free x; return only exactly verified conclusions.

    Homogeneity allows A x >= 1. Infeasibility uses w>=0, sum(w)=1, A.T w=0.
    """
    @staticmethod
    def solve(rows):
        a=matrix(rows)
        if a.ndim!=2 or min(a.shape)<1: raise ValueError('A nonempty inequality matrix is required.')
        numeric=np.array(a,dtype=float);nr,nv=a.shape
        result=linprog(np.zeros(nv),A_ub=-numeric,b_ub=-np.ones(nr),bounds=[(None,None)]*nv,method='highs')
        if result.success:
            witness=tuple(F(float(v)).limit_denominator(RATIONAL_DENOMINATOR_LIMIT) for v in result.x)
            residuals=tuple(a@witness)
            if all(v>0 for v in residuals): return LinearDecision('feasible',witness,residuals)
        dual=linprog(np.zeros(nr),A_eq=np.vstack([numeric.T,np.ones(nr)]),b_eq=np.r_[np.zeros(nv),1],bounds=[(0,None)]*nr,method='highs')
        if dual.success:
            certificate=tuple(F(float(v)).limit_denominator(RATIONAL_DENOMINATOR_LIMIT) for v in dual.x)
            residuals=tuple(a.T@certificate)
            if all(w>=0 for w in certificate) and sum(certificate)>0 and all(v==0 for v in residuals):
                return LinearDecision('infeasible',certificate,residuals)
        return LinearDecision('unresolved',(),())


@dataclass(frozen=True)
class Reaction:
    reactants: tuple[int,...]
    products: tuple[int,...]
    factor: F

    def __post_init__(self):
        object.__setattr__(self,'reactants',tuple(self.reactants));object.__setattr__(self,'products',tuple(self.products))
        object.__setattr__(self,'factor',F(self.factor))
        if len(self.reactants)!=len(self.products) or not self.reactants or any(not isinstance(v,int) or v<0 for v in self.reactants+self.products):
            raise ValueError('Complexes require equally sized nonnegative integer vectors.')
        if self.factor<=0: raise ValueError('Factors must be strictly positive.')


@dataclass(frozen=True)
class Motif:
    species: tuple[int,...]
    reactions: tuple[int,...]


class CoreFamily:
    """Literal network and motif balances; PAC status can be audited separately."""
    def __init__(self,species,reactions,motifs,orientation=None):
        self.species=tuple(species);self.reactions=tuple(reactions);self.motifs=tuple(motifs)
        n,m=len(self.species),len(self.reactions)
        if n==0 or m==0 or len(set(self.species))!=n or not self.motifs: raise ValueError('Nonempty network and distinct species required.')
        if any(len(r.reactants)!=n for r in self.reactions): raise ValueError('Complex dimension mismatch.')
        self.orientation=tuple(orientation if orientation is not None else [1]*m)
        if len(self.orientation)!=m or any(e not in (-1,1) for e in self.orientation): raise ValueError('Orientation entries must be +1 or -1.')
        if any(not c.species or not c.reactions or len(set(c.species))!=len(c.species) or len(set(c.reactions))!=len(c.reactions)
               or not set(c.species)<=set(range(n)) or not set(c.reactions)<=set(range(m)) for c in self.motifs):
            raise ValueError('Invalid motif indices.')
        if set().union(*(set(c.reactions) for c in self.motifs))!=set(range(m)): raise ValueError('Every reaction must belong to a motif.')
        self.stoichiometry=matrix([[r.products[i]-r.reactants[i] for r in self.reactions] for i in range(n)])
        self.complexes=tuple(sorted({c for r in self.reactions for c in (r.reactants,r.products)}))
        self.incidence=matrix([[r.factor*(int(c==r.reactants)-int(c==r.products)) for c in self.complexes] for r in self.reactions])

    def balance_rows(self,motifs=None):
        return matrix([[self.stoichiometry[i,j] if j in c.reactions else 0 for j in range(len(self.reactions))]
                       for c in (self.motifs if motifs is None else motifs) for i in c.species])

    def flow_rows(self): return np.vstack([np.diag(self.orientation),self.balance_rows()])
    def direction_rows(self): return -np.diag(self.orientation)@self.stoichiometry.T
    def linear_complex_rows(self): return np.vstack([self.flow_rows()@self.incidence,np.eye(len(self.complexes),dtype=int)])
    def filters(self):
        return {name:StrictLinearFeasibility.solve(a) for name,a in [('productive_flow',self.flow_rows()),('direction',self.direction_rows()),('independent_complex',self.linear_complex_rows())]}

    def currents(self,activities):
        z=tuple(F(v) for v in activities)
        if len(z)!=len(self.species) or any(v<=0 for v in z): raise ValueError('A positive activity per species is required.')
        monomials=[]
        for c in self.complexes:
            value=F(1)
            for activity,power in zip(z,c): value*=activity**power
            monomials.append(value)
        return self.incidence@monomials

    def evaluate(self,activities):
        currents=self.currents(activities);residuals=self.balance_rows()@currents;directions=np.array(self.orientation)*currents
        return dict(activities=list(map(str,activities)),currents=list(map(str,currents)),
            motif_production=list(map(str,residuals)),whole_network_production=list(map(str,self.stoichiometry@currents)),
            strictly_productive=bool(all(v>0 for v in (*residuals,*directions))))

    def side_incident(self,motif):
        return bool(motif.species and motif.reactions) and all(any(self.reactions[j].reactants[i]>0 for i in motif.species)
            and any(self.reactions[j].products[i]>0 for i in motif.species) for j in motif.reactions)

    def audit_pac(self,motif):
        """Finite submotif check; currents can have either sign, as in the paper."""
        if len(motif.species)+len(motif.reactions)>MAX_PAC_ENUMERATION_BITS:
            raise ValueError('PAC submotif enumeration exceeds declared budget.')
        if not self.side_incident(motif): return dict(is_pac=False,reason='not side-incident')
        own=StrictLinearFeasibility.solve(self.balance_rows([motif])[:,motif.reactions])
        if own.status!='feasible': return dict(is_pac=False if own.status=='infeasible' else None,reason=own.status)
        checked=0
        for species in subsets(motif.species):
            for reactions in subsets(motif.reactions):
                sub=Motif(species,reactions)
                if sub==motif or not self.side_incident(sub): continue
                checked+=1;decision=StrictLinearFeasibility.solve(self.balance_rows([sub])[:,reactions])
                if decision.status!='infeasible': return dict(is_pac=False if decision.status=='feasible' else None,reason='proper submotif '+decision.status)
        return dict(is_pac=True,proper_side_incident_submotifs_checked=checked)

    def record(self):
        return dict(species=self.species,orientation=self.orientation,reactions=[dict(reactants=r.reactants,products=r.products,factor=str(r.factor)) for r in self.reactions],
            motifs=[dict(species=c.species,reactions=c.reactions) for c in self.motifs],complexes=self.complexes)


@dataclass(frozen=True)
class TriangleInterface:
    gain: F
    shared: F
    first: F
    second: F

    def __post_init__(self):
        for name in ('gain','shared','first','second'): object.__setattr__(self,name,F(getattr(self,name)))
        if self.gain<=1 or min(self.shared,self.first,self.second)<=0: raise ValueError('Gain > 1 and positive factors required.')

    @property
    def resistance(self): return self.shared*(1/self.first+1/self.second)
    @property
    def interval(self): return self.resistance/self.gain,self.resistance

    def currents(self,q):
        q=F(q);lower,upper=self.interval
        if not lower<q<upper: raise ValueError('Response is outside the strict open interval.')
        x,y=self.shared/self.first,self.shared/self.second;t=q/(x+y);ell=1/self.gain
        e=(t-ell)*(1-t)/(2*(x+y));u=t+e*y;v=t-e*x
        if not ell<v<u<1 or x*u+y*v!=q: raise ArithmeticError('Interface reconstruction failed.')
        return F(1),u,v

    def overlap(self,other):
        lower=max(self.interval[0],other.interval[0]);upper=min(self.interval[1],other.interval[1])
        return (lower,upper) if lower<upper else None


class TrianglePair:
    def __init__(self,factors,gain=2):
        factors=tuple(F(v) for v in factors)
        if len(factors)!=5 or not isinstance(gain,int) or gain<=1: raise ValueError('Five factors and one integer gain > 1 required.')
        self.gain=gain;self.factors=factors;b0,b1,b2,b3,b4=factors
        self.left=TriangleInterface(gain,b0,b1,b2);self.right=TriangleInterface(gain,b0,b3,b4)
        A=(1,0,0,0);B=(0,1,0,0);C=(0,0,1,0);D=(0,0,0,1);mA=(gain,0,0,0)
        self.family=CoreFamily(('A','B','C','D'),[Reaction(a,b,k) for (a,b),k in zip(((A,B),(B,C),(C,mA),(B,D),(D,mA)),factors)],
            [Motif((0,1,2),(0,1,2)),Motif((0,1,3),(0,3,4))])

    def witness(self,a=F(1,2)):
        a=F(a)
        if not 0<a<1: raise ValueError('A activity must lie strictly between zero and one.')
        overlap=self.left.overlap(self.right)
        if overlap is None: return None
        q=sum(overlap)/2;_,ul,vl=self.left.currents(q);_,ur,vr=self.right.currents(q)
        b=(a**self.gain+q*a)/(1+q);j=self.factors[0]*(a-b)
        c=b-ul*j/self.factors[1];d=b-ur*j/self.factors[3]
        result=self.family.evaluate((a,b,c,d))
        if not result['strictly_productive']: raise ArithmeticError('Species reconstruction failed literal network replay.')
        result.update(q=str(q),overlap=list(map(str,overlap)))
        return result


def toric_family():
    return CoreFamily(('A','B'),[Reaction((1,0),(0,1),1),Reaction((0,1),(2,0),1),Reaction((0,1),(3,0),2)],
        [Motif((0,1),(0,1)),Motif((0,1),(0,2))])


def direction_family():
    species=('e1','e2','e3','e4','e1p','e2p','eA','eB')
    def c(**kwargs): return tuple(kwargs.get(s,0) for s in species)
    pairs=[(c(e1=1),c(eB=1,e2=1)),(c(e2=1,e2p=1),c(e3=1)),(c(e3=1),c(e4=2)),
           (c(eA=1,e4=1),c(e1=1)),(c(e1p=1),c(eA=1,e2p=1)),(c(eB=1,e4=1),c(e1p=1))]
    return CoreFamily(species,[Reaction(a,b,1) for a,b in pairs],[Motif((0,1,2,3),(0,1,2,3)),Motif((4,5,2,3),(4,1,2,5))])


def dominance_family():
    return [dict(m=m,n=n,bm=bm,bn=bn) for m in range(2,9) for n in range(m+1,9) for bm in range(1,13) for bn in range(1,13) if F(1,m*bm)>=F(1,bn)]


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(sweep,toric,output):
    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    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');k=np.array([float(F(r['k'])) for r in sweep])
        ax.axhspan(1,2,color='#0072B2',alpha=.12,label='Left interval: 1 < q < 2')
        ax.plot(k,1/k,'--',color='#D55E00',label='Right boundaries: 1/k and 2/k');ax.plot(k,2/k,'--',color='#D55E00')
        lower=np.maximum(1,1/k);upper=np.minimum(2,2/k)
        ax.fill_between(k,lower,upper,where=lower<upper,color='#009E73',alpha=.4,label='Common open response interval')
        ax.axvline(.5,color='#666666',linewidth=.8);ax.axvline(2,color='#666666',linewidth=.8)
        ax.set(xlabel='Private-factor ratio k',ylabel='Response q = (B - A squared) / (A - B)',ylim=(0,3.3),xlim=(min(k),max(k)))
        ax.legend(fontsize=8,loc='upper right');ax.spines[['top','right']].set_visible(False)
        fig.savefig(output/'phase.png',dpi=220);fig.savefig(output/'phase.svg');plt.close(fig)
        fig,ax=plt.subplots(figsize=(7.2,4.5),layout='constrained')
        x=np.array([float(F(r['A'])) for r in toric]);lower=np.array([float(F(r['B_lower'])) for r in toric]);upper=np.array([float(F(r['B_upper'])) for r in toric])
        ax.plot(x,lower,color='#0072B2',label='B must be above this: core 1 produces A')
        ax.plot(x,upper,'--',color='#D55E00',label='B must be below this: core 2 produces B')
        ax.fill_between(x,upper,lower,color='#888888',alpha=.18,label='Incompatible gap for 0 < A < 1')
        ax.set(xlabel='Species activity A',ylabel='Required bounds on species activity B',xlim=(0,1),ylim=(0,1))
        ax.legend(fontsize=8);ax.spines[['top','right']].set_visible(False)
        fig.savefig(output/'monomial.png',dpi=220);fig.savefig(output/'monomial.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(factors=FACTORS,gain=GAIN,A_activity=A_ACTIVITY,k_sweep=list(map(str,K_SWEEP)),temperature_K=TEMPERATURE_K,
        gas_constant_J_mol_K=GAS_CONSTANT_J_MOL_K,rational_denominator_limit=RATIONAL_DENOMINATOR_LIMIT,max_pac_enumeration_bits=MAX_PAC_ENUMERATION_BITS)
    intro='Resolved inputs: '+json.dumps(inputs);print(intro,flush=True)
    chosen=TrianglePair(FACTORS,GAIN);witness=chosen.witness(F(A_ACTIVITY));sweep=[]
    for k in K_SWEEP:
        pair=TrianglePair((1,1,1,k,k));w=pair.witness(F(A_ACTIVITY));overlap=pair.left.overlap(pair.right)
        sweep.append(dict(k=str(k),compatible=w is not None,overlap_lower=str(overlap[0]) if overlap else '',overlap_upper=str(overlap[1]) if overlap else '',
            minimum_motif_production=str(min(map(F,w['motif_production']))) if w else '',activities=' '.join(w['activities']) if w else ''))
    write_csv(args.output/'phase_sweep.csv',sweep)
    families={'direction_obstruction':direction_family(),'magnitude_obstruction':TrianglePair((1,1,1,10,10)).family,'monomial_obstruction':toric_family(),'selected_triangles':chosen.family}
    records={};layer_rows=[]
    for name,family in families.items():
        filters=family.filters();audits=[family.audit_pac(c) for c in family.motifs]
        if any(d.status=='unresolved' for d in filters.values()) or any(a['is_pac'] is not True for a in audits):
            raise ArithmeticError('Numerical candidate could not be certified by rational arithmetic.')
        records[name]=dict(network=family.record(),filters={name:d.record() for name,d in filters.items()},pac_audits=audits)
        layer_rows.append(dict(example=name,**{key:d.status for key,d in filters.items()},species_activity='infeasible by manuscript analytic obstruction' if name!='selected_triangles' else 'feasible exact witness' if witness else 'infeasible exact interval separation'))
    write_csv(args.output/'layers.csv',layer_rows)
    direction=direction_family()
    if any(v!=0 for v in direction.direction_rows().sum(axis=0)): raise ArithmeticError('All-ones signed circuit failed.')
    toric=toric_family();complex_witness={(1,0):F(4),(0,1):F(3),(2,0):F(9,4),(3,0):F(11,4)}
    toric_linear=toric.incidence@[complex_witness[c] for c in toric.complexes]
    if tuple(toric_linear)!=(F(1),F(3,4),F(1,2)) or not all(v>0 for v in toric.flow_rows()@toric_linear):
        raise ArithmeticError('Paper linear-complex witness failed.')
    toric_rows=[]
    for i in range(1,100):
        a=F(i,100);lower=(a+2*a*a)/3;upper=(a+2*a**3)/3
        if lower-upper!=2*a*a*(1-a)/3 or not lower>upper: raise ArithmeticError('Monomial bound identity failed.')
        toric_rows.append(dict(A=str(a),B_lower=str(lower),B_upper=str(upper),gap=str(lower-upper)))
    write_csv(args.output/'monomial_bounds.csv',toric_rows);dominance=dominance_family();write_csv(args.output/'dominance_family.csv',dominance)
    (args.output/'models_and_certificates.json').write_text(json.dumps(records,indent=2)+'\n',encoding='utf-8')
    plot(sweep,toric_rows,args.output)
    if TEMPERATURE_K<=0: raise ValueError('Temperature must be positive.')
    summary=dict(inputs=inputs,selected_witness=witness,layers=layer_rows,dominance_count=len(dominance),
        barrier_window_J_per_mol=GAS_CONSTANT_J_MOL_K*TEMPERATURE_K*log(2),
        monomial_contradiction='Directions force 0<A<1; required B lower minus required B upper = 2 A^2 (1-A) / 3 > 0.',
        evidence='Exact rational witnesses and linear alternative certificates. Analytical species-level obstruction is from the manuscript. Static per-core productivity is not a steady state, stability, or whole-network-growth guarantee. 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 scipy,matplotlib
    metadata=dict(paper_sha256=PAPER_SHA256,source_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),python=platform.python_version(),
        numpy=np.__version__,scipy=scipy.__version__,matplotlib=matplotlib.__version__,platform=platform.platform(),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: {"factors": ["1", "1", "1", "1", "1"], "gain": 2, "A_activity": "1/2", "k_sweep": ["1/5", "11/50", "6/25", "13/50", "7/25", "3/10", "8/25", "17/50", "9/25", "19/50", "2/5", "21/50", "11/25", "23/50", "12/25", "1/2", "13/25", "27/50", "14/25", "29/50", "3/5", "31/50", "16/25", "33/50", "17/25", "7/10", "18/25", "37/50", "19/25", "39/50", "4/5", "41/50", "21/25", "43/50", "22/25", "9/10", "23/25", "47/50", "24/25", "49/50", "1", "51/50", "26/25", "53/50", "27/25", "11/10", "28/25", "57/50", "29/25", "59/50", "6/5", "61/50", "31/25", "63/50", "32/25", "13/10", "33/25", "67/50", "34/25", "69/50", "7/5", "71/50", "36/25", "73/50", "37/25", "3/2", "38/25", "77/50", "39/25", "79/50", "8/5", "81/50", "41/25", "83/50", "42/25", "17/10", "43/25", "87/50", "44/25", "89/50", "9/5", "91/50", "46/25", "93/50", "47/25", "19/10", "48/25", "97/50", "49/25", "99/50", "2", "101/50", "51/25", "103/50", "52/25", "21/10", "53/25", "107/50", "54/25", "109/50", "11/5", "111/50", "56/25", "113/50", "57/25", "23/10", "58/25", "117/50", "59/25", "119/50", "12/5", "121/50", "61/25", "123/50", "62/25", "5/2", "63/25", "127/50", "64/25", "129/50", "13/5", "131/50", "66/25", "133/50", "67/25", "27/10", "68/25", "137/50", "69/25", "139/50", "14/5", "141/50", "71/25", "143/50", "72/25", "29/10", "73/25", "147/50", "74/25", "149/50", "3"], "temperature_K": 298.0, "gas_constant_J_mol_K": 8.314462618, "rational_denominator_limit": 1000000, "max_pac_enumeration_bits": 16}
{
  "inputs": {
    "factors": [
      "1",
      "1",
      "1",
      "1",
      "1"
    ],
    "gain": 2,
    "A_activity": "1/2",
    "k_sweep": [
      "1/5",
      "11/50",
      "6/25",
      "13/50",
      "7/25",
      "3/10",
      "8/25",
      "17/50",
      "9/25",
      "19/50",
      "2/5",
      "21/50",
      "11/25",
      "23/50",
      "12/25",
      "1/2",
      "13/25",
      "27/50",
      "14/25",
      "29/50",
      "3/5",
      "31/50",
      "16/25",
      "33/50",
      "17/25",
      "7/10",
      "18/25",
      "37/50",
      "19/25",
      "39/50",
      "4/5",
      "41/50",
      "21/25",
      "43/50",
      "22/25",
      "9/10",
      "23/25",
      "47/50",
      "24/25",
      "49/50",
      "1",
      "51/50",
      "26/25",
      "53/50",
      "27/25",
      "11/10",
      "28/25",
      "57/50",
      "29/25",
      "59/50",
      "6/5",
      "61/50",
      "31/25",
      "63/50",
      "32/25",
      "13/10",
      "33/25",
      "67/50",
      "34/25",
      "69/50",
      "7/5",
      "71/50",
      "36/25",
      "73/50",
      "37/25",
      "3/2",
      "38/25",
      "77/50",
      "39/25",
      "79/50",
      "8/5",
      "81/50",
      "41/25",
      "83/50",
      "42/25",
      "17/10",
      "43/25",
      "87/50",
      "44/25",
      "89/50",
      "9/5",
      "91/50",
      "46/25",
      "93/50",
      "47/25",
      "19/10",
      "48/25",
      "97/50",
      "49/25",
      "99/50",
      "2",
      "101/50",
      "51/25",
      "103/50",
      "52/25",
      "21/10",
      "53/25",
      "107/50",
      "54/25",
      "109/50",
      "11/5",
      "111/50",
      "56/25",
      "113/50",
      "57/25",
      "23/10",
      "58/25",
      "117/50",
      "59/25",
      "119/50",
      "12/5",
      "121/50",
      "61/25",
      "123/50",
      "62/25",
      "5/2",
      "63/25",
      "127/50",
      "64/25",
      "129/50",
      "13/5",
      "131/50",
      "66/25",
      "133/50",
      "67/25",
      "27/10",
      "68/25",
      "137/50",
      "69/25",
      "139/50",
      "14/5",
      "141/50",
      "71/25",
      "143/50",
      "72/25",
      "29/10",
      "73/25",
      "147/50",
      "74/25",
      "149/50",
      "3"
    ],
    "temperature_K": 298.0,
    "gas_constant_J_mol_K": 8.314462618,
    "rational_denominator_limit": 1000000,
    "max_pac_enumeration_bits": 16
  },
  "selected_witness": {
    "activities": [
      "1/2",
      "2/5",
      "207/640",
      "207/640"
    ],
    "currents": [
      "1/10",
      "49/640",
      "47/640",
      "49/640",
      "47/640"
    ],
    "motif_production": [
      "3/64",
      "3/128",
      "1/320",
      "3/64",
      "3/128",
      "1/320"
    ],
    "whole_network_production": [
      "31/160",
      "-17/320",
      "1/320",
      "1/320"
    ],
    "strictly_productive": true,
    "q": "3/2",
    "overlap": [
      "1",
      "2"
    ]
  },
  "layers": [
    {
      "example": "direction_obstruction",
      "productive_flow": "feasible",
      "direction": "infeasible",
      "independent_complex": "feasible",
      "species_activity": "infeasible by manuscript analytic obstruction"
    },
    {
      "example": "magnitude_obstruction",
      "productive_flow": "feasible",
      "direction": "feasible",
      "independent_complex": "infeasible",
      "species_activity": "infeasible by manuscript analytic obstruction"
    },
    {
      "example": "monomial_obstruction",
      "productive_flow": "feasible",
      "direction": "feasible",
      "independent_complex": "feasible",
      "species_activity": "infeasible by manuscript analytic obstruction"
    },
    {
      "example": "selected_triangles",
      "productive_flow": "feasible",
      "direction": "feasible",
      "independent_complex": "feasible",
      "species_activity": "feasible exact witness"
    }
  ],
  "dominance_count": 441,
  "barrier_window_J_per_mol": 1717.417603818253,
  "monomial_contradiction": "Directions force 0<A<1; required B lower minus required B upper = 2 A^2 (1-A) / 3 > 0.",
  "evidence": "Exact rational witnesses and linear alternative certificates. Analytical species-level obstruction is from the manuscript. Static per-core productivity is not a steady state, stability, or whole-network-growth guarantee. No Lean compilation."
}