OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent commits / c6920d0

basal-agent: gardphi.c — Phi_r on OUR GARD; real signal, beaten by the paper's own baseline
Third and most direct probe of Pigozzi & Levin (arXiv 2607.28250). ribophi.c and rung34phi.c tested by analogy in non-GARD models; gardenv.c IS the GARD family, so this speaks to their result directly. Matched to their setup: single lineage through fission (not our 200 pockets), selection OFF (they state GARD models events before selection), and MOLECULAR time rather than generations — composition sampled every 10 join/leave events, ~10k points/run. Coordinates = 7 most abundant token types + other, chosen from the FIRST 25% only so nothing leaks from the predicted portion. R4 test-of-the-test: in-replicator fraction mean 0.671, range 0.063-0.997, only 2/30 degenerate. The test is LIVE (unlike ribophi's absent pre-transition phase and partition.c's first non-partitioning attempt). R1 their headline (Phi_r higher during self-replication): 3/28 runs significantly higher, 0 lower, 25 n.s. Directionally consistent — no run went the other way — but far weaker than their 57/100. R2/R3 the predictive claim and its control: early Phi_r vs later self-replication rho = +0.457 (p=0.0066) early compositional drift (CONTROL) rho = -0.872 (p=4.5e-21) FIRST POSITIVE Phi_r RESULT of the three probes — it is genuinely predictive, not noise. But "change in composition" predicts about twice as strongly, and that is EXPLICITLY one of the baselines the paper says Phi_r beat. On the GARD family, against their own declared baseline, the ordering comes out reversed. Four differences remain and none is dismissible: their original-GARD parameters (Ng=100, A=-4, sigma=4) vs gardenv's excess-mutual-catalysis regime; our Gaussian estimator (~50x redundancy-biased) vs their unpublished one; their MLP on the trajectory vs our rank correlation on a scalar; their unspecified similarity threshold vs our 0.90. Standing caveat: gardenv measured heredity ~0 in this chemistry — composomes do not breed true. Compositions can satisfy their similarity criterion while transmitting nothing, which locates what their "self-replication" tracks: residence in a compositional attractor, not transmissible heredity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
c6920d0a1ac6f3698711d5d724593811e0903dd4
by plankatron <fleeky@gmail.com> · 2026-07-31T21:40:48.000Z

Changed files (3) +328 -0

.gitignore +1 -0
……@@ -39,3 +39,4 @@ ribophi
3939rung34phi
4040coupling
4141partition
42gardphi
gardphi.c +237 -0
……@@ -0,0 +1,237 @@
1/* gardphi.c — Phi_r probe on OUR GARD (gardenv.c). The only model of ours that is actually GARD.
2 *
3 * WHY THIS ONE MATTERS. ribophi.c and rung34phi.c tested Pigozzi & Levin's causal-emergence claim
4 * (arXiv 2607.28250) by ANALOGY, in models that are not GARD. Both returned nulls, and the honest
5 * caveat in both was the same: different model, so the disagreement could sit anywhere. gardenv.c
6 * IS the GARD family -- token types, a catalysis matrix beta, accretion, split-and-regrow,
7 * compositional (not sequence) inheritance. So this probe can speak to their result directly.
8 *
9 * MATCHING THEIR SETUP, not ours:
10 * - SINGLE LINEAGE. The paper traces one assembly, fissioning and continuing from one daughter.
11 * gardenv.c normally runs 200 pockets with between-pocket selection; here selection is OFF and
12 * one lineage is followed, because the paper is explicit that GARD "is essentially a stochastic
13 * model of events before natural selection takes place".
14 * - MOLECULAR TIME, not generations. They compute Phi_r over molecular steps. ribophi.c sampled
15 * once per generation and that coarseness was part of why it could not host the test. Here the
16 * composition is sampled every SAMPLE join/leave events, giving ~9000 points per run.
17 * - THEIR SELF-REPLICATOR CRITERION. "Recurring compositions inherited across generations": find
18 * the most recurring composition, then a timestep is in-self-replicator if its cosine to that
19 * composition exceeds a threshold. A run enters and leaves self-replication over its lifetime.
20 *
21 * DIMENSION REDUCTION (declared, because it is a real deviation). They use Ng=100 parts and an
22 * unspecified minimum-information-bipartition search; exhaustive search over 100 parts is
23 * impossible, so they must use a heuristic they do not describe. We reduce N=40 token types to 8
24 * coordinates -- the 7 most abundant types plus an "other" bin -- chosen from the FIRST 25% of each
25 * run only, so no information from the predicted portion leaks into the coordinate choice. Then
26 * CLR, drop one, 7 parts, exhaustive bipartition (63) as in the other probes.
27 *
28 * PRE-REGISTERED:
29 * R1 (their Fig 3/4, the headline): Phi_r is HIGHER during timesteps in self-replication than
30 * outside it. Per run by Mann-Whitney; report how many runs are significantly positive.
31 * R2 (their Fig 5): mean Phi_r over the FIRST 25% of a run predicts the fraction of the REMAINING
32 * 75% spent in self-replication, across runs (Spearman).
33 * R3 CONTROL for R2, the one that can kill it: the same prediction from a raw compositional
34 * statistic over the same first 25% (mean drift = 1 - cosine between consecutive samples).
35 * Phi_r earns its keep only if it beats this. NOTE R1 is not circular -- Phi_r is not derived
36 * from the label -- but R2's control must be, since the label itself is compositional.
37 * R4 TEST OF THE TEST: does self-replication actually occur and fluctuate? If a run is in-replicator
38 * ~always or ~never, there is nothing to predict and that run is uninformative. Report the
39 * distribution of in-replicator fraction before reading anything else.
40 *
41 * Prior from our own arc: gardenv.c measured heredity ~0 in this chemistry -- composomes do not
42 * breed true. So compositions may satisfy the paper's similarity criterion while transmitting
43 * nothing. If R1 holds while heredity is ~0, that is not a contradiction of the paper; it locates
44 * precisely what their "self-replication" is tracking.
45 *
46 * build: cc -O2 -Wall -std=c11 -o gardphi gardphi.c -lm
47 */
48#include <math.h>
49#include <stdio.h>
50#include <string.h>
51#include "phir.h"
52
53/* ---------- verbatim from gardenv.c ---------- */
54#define N 40
55#define S 150
56#define GEN 60
57#define MAT 1500
58#define PCAT 0.15
59#define RHO0 0.4
60
61/* ---------- probe ---------- */
62#define SAMPLE 10 /* sample the composition every SAMPLE molecular events */
63#define MAXT 12000
64#define NB 8
65#define P (NB-1)
66#define WINL 200 /* Phi_r window, in samples */
67#define STRIDE 50
68#define NRUN 30
69#define SIMTHR 0.90 /* cosine to the most recurring composition = "in self-replicator" */
70
71static unsigned long long RNG;
72static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; }
73static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); }
74static double randnv(void){ double u=urand(),v=urand(); if(u<1e-300)u=1e-300; return sqrt(-2*log(u))*cos(6.283185307*v); }
75
76static double bta[N][N], rate[N];
77static void build_chem(void){ for(int i=0;i<N;i++)for(int j=0;j<N;j++) bta[i][j]=(i!=j&&urand()<PCAT)? exp(1.8*randnv())*0.30 : 0.0; }
78static void recompute(const int*n){ for(int i=0;i<N;i++){ double r=RHO0; for(int j=0;j<N;j++) r+=bta[i][j]*n[j]; rate[i]=r; } }
79static int pick_add(void){ double t=0; for(int i=0;i<N;i++)t+=rate[i]; double u=urand()*t,a=0; for(int i=0;i<N;i++){a+=rate[i];if(u<=a)return i;} return N-1; }
80static int pick_rem(const int*n,int sz){ double u=urand()*sz,a=0; for(int j=0;j<N;j++){a+=n[j];if(u<=a)return j;} return N-1; }
81static void addm(int*n,int i){ n[i]++; for(int k=0;k<N;k++) rate[k]+=bta[k][i]; }
82static void remm(int*n,int j){ n[j]--; for(int k=0;k<N;k++) rate[k]-=bta[k][j]; }
83static double cosv(const double*a,const double*b){ double d=0,na=0,nb=0; for(int i=0;i<N;i++){ d+=a[i]*b[i]; na+=a[i]*a[i]; nb+=b[i]*b[i]; } if(na<=0||nb<=0)return 0; return d/(sqrt(na)*sqrt(nb)); }
84
85static double traj[MAXT][N];
86static int ntraj;
87
88static void snap(const int*n){ if(ntraj>=MAXT) return; for(int i=0;i<N;i++) traj[ntraj][i]=n[i]; ntraj++; }
89
90/* mature + grow, sampling composition in MOLECULAR time (the paper's substrate) */
91static void mature_s(int*n,int sz){ recompute(n); for(int t=0;t<MAT;t++){ int j=pick_rem(n,sz); remm(n,j); addm(n,pick_add()); if(t%SAMPLE==0) snap(n); } }
92static void grow_to_s(int*n,int*sz,int tgt){ recompute(n); int c=0; while(*sz<tgt){ addm(n,pick_add()); (*sz)++; if((c++)%SAMPLE==0) snap(n); } }
93
94/* one lineage: accrete, mature, fission, continue from a daughter. NO selection. */
95static void run_lineage(void)
96{
97 int n[N]; memset(n,0,sizeof n);
98 for(int s=0;s<S;s++) n[(int)(xs()%N)]++;
99 ntraj=0;
100 mature_s(n,S);
101 for(int g=0;g<GEN;g++){
102 int D[N]; memset(D,0,sizeof D); int ds=0;
103 for(int i=0;i<N;i++) for(int c=0;c<n[i];c++) if(urand()<0.5){ D[i]++; ds++; }
104 if(ds<1){ D[0]=1; ds=1; }
105 grow_to_s(D,&ds,S);
106 mature_s(D,S);
107 memcpy(n,D,sizeof D);
108 }
109}
110
111int main(void)
112{
113 phir_seed(0x9e3779b97f4a7c15ULL);
114 printf("=== Phi_r on OUR GARD (gardenv.c chemistry): single lineage, no selection ===\n");
115 printf(" %d runs, %d tokens, %d generations, composition sampled every %d molecular events.\n",NRUN,N,GEN,SAMPLE);
116 printf(" Self-replicator = cosine to the most recurring composition > %.2f (their criterion).\n",SIMTHR);
117 printf(" Coordinates: 7 most abundant token types + other, chosen from the FIRST 25%% only.\n\n");
118
119 double earlyPhi[NRUN], lateFrac[NRUN], earlyDrift[NRUN], inFrac[NRUN];
120 int nrun=0, nsig_pos=0, nsig_neg=0, ntested=0;
121
122 for(int r=0;r<NRUN;r++){
123 RNG = 0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(r+1));
124 for(int k=0;k<5;k++) xs();
125 build_chem();
126 run_lineage();
127 if(ntraj < 4*WINL) continue;
128
129 int q1 = ntraj/4; /* first 25% */
130
131 /* --- coordinates from the first 25% only: 7 most abundant types + other --- */
132 double ab[N]; for(int i=0;i<N;i++) ab[i]=0;
133 for(int t=0;t<q1;t++) for(int i=0;i<N;i++) ab[i]+=traj[t][i];
134 int top[NB-1];
135 { int used[N]; for(int i=0;i<N;i++) used[i]=0;
136 for(int s=0;s<NB-1;s++){ int bi=-1; double bv=-1;
137 for(int i=0;i<N;i++) if(!used[i] && ab[i]>bv){ bv=ab[i]; bi=i; }
138 top[s]=bi; used[bi]=1; } }
139
140 static double clr[MAXT][P];
141 for(int t=0;t<ntraj;t++){
142 double bins[NB]; for(int b=0;b<NB;b++) bins[b]=0;
143 double tot=0; for(int i=0;i<N;i++) tot+=traj[t][i];
144 for(int s=0;s<NB-1;s++) bins[s]=traj[t][top[s]];
145 double used=0; for(int s=0;s<NB-1;s++) used+=bins[s];
146 bins[NB-1]=tot-used;
147 phir_clr(bins,NB,clr[t]);
148 }
149
150 /* --- most recurring composition: biggest cosine>0.85 cluster over the whole run --- */
151 double cent[N]; int bestcount=-1;
152 {
153 int NPROBE=60;
154 for(int a=0;a<NPROBE;a++){
155 int idx=(int)((double)a/NPROBE*ntraj);
156 int cnt=0; for(int t=0;t<ntraj;t+=5) if(cosv(traj[idx],traj[t])>0.85) cnt++;
157 if(cnt>bestcount){ bestcount=cnt; memcpy(cent,traj[idx],sizeof cent); }
158 }
159 }
160 static int lab[MAXT];
161 int nin=0;
162 for(int t=0;t<ntraj;t++){ lab[t] = (cosv(traj[t],cent)>SIMTHR); nin+=lab[t]; }
163 inFrac[nrun]=(double)nin/ntraj;
164
165 /* --- Phi_r trajectory in molecular time --- */
166 static double pairs[MAXT][2*P];
167 static double pv[MAXT]; static int pc[MAXT]; int nw=0;
168 for(int st=0; st+WINL<=ntraj; st+=STRIDE){
169 int n2=WINL-1;
170 for(int t=0;t<n2;t++) for(int i=0;i<P;i++){ pairs[t][i]=clr[st+t][i]; pairs[t][P+i]=clr[st+t+1][i]; }
171 int ok; double v=phi_r(&pairs[0][0],n2,P,&ok);
172 if(ok){ pv[nw]=v; pc[nw]=st+WINL/2; nw++; }
173 }
174 if(nw<8) continue;
175
176 /* --- R1: Phi_r inside vs outside self-replication (per run) --- */
177 double insv[MAXT], outv[MAXT]; int ni=0,no=0;
178 for(int i=0;i<nw;i++){ if(lab[pc[i]]) insv[ni++]=pv[i]; else outv[no++]=pv[i]; }
179 if(ni>=4 && no>=4){
180 ntested++;
181 double p=mannwhitney_p(insv,ni,outv,no);
182 double mi=meanv(insv,ni), mo=meanv(outv,no);
183 if(p<0.05){ if(mi>mo) nsig_pos++; else nsig_neg++; }
184 }
185
186 /* --- R2/R3: early Phi_r and early drift vs later self-replication --- */
187 {
188 double sPhi=0; int cPhi=0;
189 for(int i=0;i<nw;i++) if(pc[i]<q1){ sPhi+=pv[i]; cPhi++; }
190 earlyPhi[nrun] = cPhi? sPhi/cPhi : NAN;
191 double d=0; int cd=0;
192 for(int t=1;t<q1;t++){ d += 1.0-cosv(traj[t-1],traj[t]); cd++; }
193 earlyDrift[nrun] = cd? d/cd : NAN;
194 int late=0,lc=0;
195 for(int t=q1;t<ntraj;t++){ late+=lab[t]; lc++; }
196 lateFrac[nrun] = lc? (double)late/lc : NAN;
197 }
198 nrun++;
199 }
200
201 /* ---------- R4 first: did self-replication happen and fluctuate? ---------- */
202 printf(" R4 TEST OF THE TEST — in-self-replicator fraction across %d runs:\n",nrun);
203 {
204 double f[NRUN]; int nf=0, degenerate=0;
205 for(int i=0;i<nrun;i++){ f[nf++]=inFrac[i]; if(inFrac[i]<0.02||inFrac[i]>0.98) degenerate++; }
206 printf(" mean %.3f, median %.3f, min %.3f, max %.3f | degenerate runs (always/never): %d/%d\n",
207 meanv(f,nf), median(f,nf), f[0], f[nf-1], degenerate, nrun);
208 double mn=1,mx=0; for(int i=0;i<nf;i++){ if(f[i]<mn)mn=f[i]; if(f[i]>mx)mx=f[i]; }
209 printf(" range %.3f .. %.3f\n",mn,mx);
210 if(degenerate>nrun/2)
211 printf(" => MOSTLY DEGENERATE: little to predict. Treat everything below as uninformative.\n");
212 else
213 printf(" => self-replication occurs and fluctuates; the test is live.\n");
214 }
215
216 /* ---------- R1 ---------- */
217 printf("\n R1 (their headline): Phi_r higher DURING self-replication than outside?\n");
218 printf(" runs tested %d | significantly HIGHER %d | significantly LOWER %d | n.s. %d\n",
219 ntested,nsig_pos,nsig_neg,ntested-nsig_pos-nsig_neg);
220
221 /* ---------- R2 / R3 ---------- */
222 printf("\n R2/R3: early (first 25%%) predictor vs later self-replication fraction, across runs\n");
223 {
224 double a[NRUN],b[NRUN],c[NRUN]; int m=0;
225 for(int i=0;i<nrun;i++){
226 if(isnan(earlyPhi[i])||isnan(lateFrac[i])||isnan(earlyDrift[i])) continue;
227 a[m]=earlyPhi[i]; b[m]=lateFrac[i]; c[m]=earlyDrift[i]; m++;
228 }
229 double r1=spearman(a,b,m), r2=spearman(c,b,m);
230 printf(" n=%d runs\n",m);
231 printf(" R2 early Phi_r vs later self-replication : rho = %+.3f (p=%.3g)\n",r1,spearman_p(r1,m));
232 printf(" R3 early drift vs later self-replication : rho = %+.3f (p=%.3g) <- CONTROL\n",r2,spearman_p(r2,m));
233 printf(" => Phi_r earns its keep only if |rho| exceeds the control's.\n");
234 }
235 printf("\n=== verdict read off R1-R4 ===\n");
236 return 0;
237}
gardphi.md +90 -0
……@@ -0,0 +1,90 @@
1# `gardphi.c` — Φ_r on our GARD: real signal, decisively beaten by one of the paper's own baselines
2
3The third and most direct probe of Pigozzi & Levin (arXiv 2607.28250). `ribophi.c` and
4`rung34phi.c` tested by analogy in models that are not GARD, and both nulls carried the same
5caveat — different model, so the disagreement could sit anywhere. `gardenv.c` **is** the GARD
6family, so this one speaks to their result directly.
7
8Setup matched to theirs, not ours: **single lineage** (they trace one assembly through fission,
9continuing from one daughter), **selection off** (they state GARD models events "before natural
10selection takes place"), and **molecular time** rather than generations — composition sampled every
1110 join/leave events, ~10,000 points per run. Coordinates: 7 most abundant token types + "other",
12chosen from the **first 25% only** so nothing leaks from the predicted portion.
13
14## R4 — the test of the test, read first
15
16| | |
17|---|---|
18| in-self-replicator fraction | mean 0.671, median 0.733, range 0.063–0.997 |
19| degenerate runs (always/never) | **2 / 30** |
20
21Self-replication occurs and fluctuates. **The test is live** — unlike `ribophi.c` (no pre-transition
22phase) and `partition.c`'s first attempt (graph never partitioned).
23
24## R1 — their headline claim
25
26> Φ_r higher during self-replication than outside it.
27
28| | our GARD | paper |
29|---|---|---|
30| runs significantly higher | **3 / 28** | 57 / 100 |
31| runs significantly lower | **0 / 28** | — |
32| not significant | 25 / 28 | — |
33
34Directionally consistent — no run went the other way, where chance alone would give ~1.4 each way —
35but far weaker than reported.
36
37## R2 / R3 — the predictive claim, and the control
38
39> Early Φ_r predicts later self-replication.
40
41| predictor (first 25%) | ρ vs later self-replication fraction | p |
42|---|---|---|
43| **mean Φ_r** | **+0.457** | **0.0066** |
44| mean compositional drift (control) | **−0.872** | 4.5e-21 |
45
46**Φ_r is genuinely predictive here — the first positive Φ_r result across all three probes.** It is
47not noise. But a one-line statistic — mean `1 − cosine` between consecutive samples — predicts
48roughly twice as strongly.
49
50The sign makes mechanistic sense: a lineage that drifts little early has already settled into an
51attractor, and spends more of the rest of the run inside it.
52
53## Why this probe is the one that matters
54
55The control here, **change in composition**, is *explicitly one of the baselines the paper says
56Φ_r beat* ("we trained the same model using other soup statistics as input — change in composition,
57raw composition counts, and fluxes"). So this is not an analogy result any more: on the GARD family,
58against one of their own declared baselines, the ordering comes out reversed.
59
60## What still separates us from them
61
62Four differences remain, and any could account for it. None is dismissible:
63
641. **Parameters.** They use original GARD (Ng=100, nmin=40, A=−4, σ=4, nmax=80). `gardenv.c` uses
65 N=40, S=150, and deliberately **excess mutual catalysis** (β\[i]\[i]=0) to get *multiple*
66 attractors, which original GARD does not. Same family, different regime.
672. **Estimator.** Ours is Gaussian log-determinant ΦID with a measured ~50× bias toward redundancy
68 over synergy. Theirs is unpublished ("code available upon publication").
693. **Statistics.** They fit an MLP on the Φ_r trajectory; we use rank correlation on a scalar
70 summary. Ours is the *harder* baseline to beat — a single mean beating Φ_r is informative — but
71 it is not the same test, and an MLP could extract more from Φ_r than its mean does.
724. **Threshold.** Their self-replicator similarity threshold is unspecified; we used 0.90.
73
74## Combined across all three probes
75
76| | `ribozyme.c` | `rung34.c` | **`gardenv.c` (is GARD)** |
77|---|---|---|---|
78| test actually hosted | **no** (ignites gen 6–10) | yes | **yes** |
79| Φ_r carries real signal | — | no | **yes, ρ=+0.457, p=0.007** |
80| trivial baseline beats it | p=3.1e-17 vs 1.1e-6 | ρ=−0.641 vs +0.161 | **ρ=−0.872 vs +0.457** |
81
82Consistent picture: Φ_r is not nothing — in the right model it is genuinely predictive — but in every
83model we can test, a simple compositional statistic predicts the transition better.
84
85## Standing caveat
86
87Our own `gardenv.c` result is that heredity in this chemistry is ≈0 — composomes do **not** breed
88true. So compositions can satisfy the paper's similarity criterion while transmitting nothing. That
89is not a contradiction of their result; it locates what their "self-replication" measures:
90**residence in a compositional attractor, not transmissible heredity.**