OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb commits / 08116ff

basal-agent: replicase.c — the genotype/phenotype loop does not close
Last experiment of the arc, and the first with genotype and phenotype MUTUALLY dependent. Fixes two flaws genome.c exposed: reading was a dead end for the template lineage (a picked template always became a catalyst, so it could be useful or persist, never both — now read with prob PREAD, else copied true), and template copying was free physics (now conditional on a replicase). A type-0 catalyst improves template fidelity in its compartment (x0.25 vs x1.50), is EXCLUDED from the target set so it pays nothing directly, is not seeded or protected, and non-folders still replicate 3x faster — so it is a public good inside its own compartment, free-ridable as catalysis was in ribozyme.c. CONTROL FIXED FIRST. R3 failed initially: replicase arm got low-fidelity 3-13% of the time, control 60%. PFLIP was guessed from a uniform-type estimate, but selection purges type 0 precisely because it pays nothing, so the real frequency is an order of magnitude lower and the control ran at a fraction of the mutation load. Fixed with a two-pass design — measure the arm's realized low-fidelity fraction per seed, then give the control a coin flip at exactly that probability. 6 seeds, matched (lo-fid R/C identical to 2dp at every mu): mu | REPLICASE rep-freq/payoff | CONTROL rep-freq/payoff 0.005 | 0.025 / 1.56 | 0.022 / 1.57 0.020 | 0.060 / 1.44 | 0.094 / 1.44 0.080 | 0.129 / 1.22 | 0.129 / 1.23 R1 0/5, R2 0/5 — indistinguishable on both measures. HONEST NULL. (rep-freq rises with mu in BOTH arms: chance generating type-0 catalysts, not selection.) WHY, AND IT IS THE ARC'S OWN WALL ONE LEVEL UP: the replicase improves fidelity for every template in its compartment including free-riders', and costs a slot. Within-compartment selection purges it; between-compartment selection cannot retain it because the benefit is indirect and shared. A boundary can only privatize a good it can exclude non-contributors from, and everything inside a compartment is inside it. Predicted partial; got a complete null. WHAT THE THREE NEGATIVES LOCATE: fidfloor says the split is NECESSARY, genome says the opportunity is NOT SUFFICIENT, replicase says the loop does not close when the replicase is a compartment-scale public good. => it must be privatized at a scale SMALLER than the compartment, coupled to the particular templates it copies rather than to everything nearby. Which is what a replisome does, and what physical association buys that diffusion does not. Unbuilt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
08116ffe14deea8004e945f29bf7f13bb73d4c07
by plankatron <fleeky@gmail.com> · 2026-08-01T01:26:52.000Z

Changed files (4) +358 -69

basal-agent/.gitignore +1 -0
……@@ -47,3 +47,4 @@ chemoton
4747rafcomp
4848fidfloor
4949genome
50replicase
basal-agent/genome.c +73 -69
……@@ -61,6 +61,7 @@
6161#define NCOMP 600
6262#define CSZ 8 /* small compartments: the regime the corrector needs */
6363#define GEN 200
64#define PREAD 0.50 /* chance a picked template is READ rather than copied true */
6465#define BETA 2.0 /* non-folders replicate faster — the parasite advantage stays */
6566
6667static unsigned long long RNG;
……@@ -73,19 +74,31 @@ static int isfold(uint32_t s){ return phi(s)>=THETA; }
7374static int typeof_(uint32_t s){ return (int)((s>>NFOLD)&7); }
7475static uint32_t mut(uint32_t s,double mu){ for(int i=0;i<NFOLD+3;i++) if(urand()<mu) s^=(1u<<i); return s; }
7576
77static int TARGET[NTYPE]; /* world-supplied: which types are worth having (payoff mode 1) */
78static int NTARG=4;
7679static uint32_t cell[NCOMP][CSZ], ncell[NCOMP][CSZ];
7780static double cum[NCOMP];
7881
79/* distinct types present among CATALYSTS — the compartment's functional repertoire */
80static int repertoire(const uint32_t *c){
82/* payoff 0 = DIVERSITY: any distinct catalyst types count (genome.c's original).
83 payoff 1 = TARGET: only types in a world-supplied target set count.
84 The difference is the whole point: under DIVERSITY any repertoire is as good as any other, so
85 there is nothing worth remembering and a dice-roll beats a memory. Under TARGET a SPECIFIC
86 configuration beats a random one, so faithful reading has something to be faithful TO. */
87static int repertoire_mode(const uint32_t *c,int payoff){
8188 int seen[NTYPE]; for(int t=0;t<NTYPE;t++) seen[t]=0;
82 int d=0; for(int k=0;k<CSZ;k++) if(isfold(c[k])){ int t=typeof_(c[k]); if(!seen[t]){seen[t]=1;d++;} }
89 int d=0;
90 for(int k=0;k<CSZ;k++) if(isfold(c[k])){ int t=typeof_(c[k]); if(!seen[t]){ seen[t]=1; if(payoff==0||TARGET[t]) d++; } }
8391 return d;
8492}
93static int repertoire(const uint32_t *c){ return repertoire_mode(c,0); }
8594
8695/* mode 0 = READ OFF, 1 = READ ON, 2 = SCRAMBLED control (reads, but type bits randomised) */
87static double run(int mode,double mu,double *tmpl_frac,double *cat_frac,double *rep_out)
96static double run(int mode,double mu,int payoff,double *tmpl_frac,double *cat_frac,double *rep_out)
8897{
98 /* world-supplied target: a random NTARG-subset of the types, redrawn per run so no particular
99 set is special-cased. Same shape as polymer.c's random target motif. */
100 for(int t=0;t<NTYPE;t++) TARGET[t]=0;
101 for(int got=0;got<NTARG;){ int t=(int)(xs()%NTYPE); if(!TARGET[t]){ TARGET[t]=1; got++; } }
89102 for(int c=0;c<NCOMP;c++)
90103 for(int k=0;k<CSZ;k++){ uint32_t v=0; for(int i=0;i<NFOLD+3;i++) if(urand()<0.5) v|=(1u<<i); cell[c][k]=v; }
91104
……@@ -100,12 +113,17 @@ static double run(int mode,double mu,double *tmpl_frac,double *cat_frac,double *
100113 double r=urand()*tot; int lo=0,hi=CSZ-1;
101114 while(lo<hi){ int mid=(lo+hi)/2; if(cw[mid]<r) lo=mid+1; else hi=mid; }
102115 uint32_t par=cell[c][lo], child;
103 if(mode!=0 && !isfold(par) && mach>=0){
104 /* READ: a catalyst's fold bits + this template's type bits -> catalyst of that type.
105 Supplied physics. Nothing here rewards holding templates. */
116 if(mode!=0 && !isfold(par) && mach>=0 && urand()<PREAD){
117 /* READ (template -> catalyst): a catalyst's fold bits + this template's type bits.
118 v1/v2 made this the ONLY thing a template could do, so reading was a dead end for
119 the template lineage — it could be useful or persist, never both. Real genomes are
120 copied AS genomes and SEPARATELY read. Now reading happens with probability PREAD
121 and otherwise the template is copied as a template, exactly as a catalyst is
122 copied as a catalyst. Both classes propagate only by copying; reading is a
123 FUNCTION templates provide, not an extra route to propagate. */
106124 uint32_t ty = (mode==2) ? (uint32_t)(xs()&7) : (uint32_t)typeof_(par);
107125 child = (cell[c][mach] & ((1u<<NFOLD)-1)) | (ty<<NFOLD);
108 } else child = par; /* plain copy: catalyst or unread template */
126 } else child = par; /* copy true: catalyst->catalyst, template->template */
109127 ncell[c][k]=mut(child,mu);
110128 }
111129 }
……@@ -113,7 +131,7 @@ static double run(int mode,double mu,double *tmpl_frac,double *cat_frac,double *
113131
114132 /* ---- between compartment: DECREED selection on functional repertoire (flagged, not derived) ---- */
115133 double tot=0;
116 for(int c=0;c<NCOMP;c++){ tot += 0.05 + (double)repertoire(cell[c]); cum[c]=tot; }
134 for(int c=0;c<NCOMP;c++){ tot += 0.05 + (double)repertoire_mode(cell[c],payoff); cum[c]=tot; }
117135 for(int c=0;c<NCOMP;c++){
118136 double r=urand()*tot; int lo=0,hi=NCOMP-1;
119137 while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; }
……@@ -124,7 +142,7 @@ static double run(int mode,double mu,double *tmpl_frac,double *cat_frac,double *
124142
125143 long nt=0,nc=0; double rp=0;
126144 for(int c=0;c<NCOMP;c++){
127 rp += repertoire(cell[c]);
145 rp += repertoire_mode(cell[c],payoff);
128146 for(int k=0;k<CSZ;k++){ if(isfold(cell[c][k])) nc++; else nt++; }
129147 }
130148 *tmpl_frac=(double)nt/((double)NCOMP*CSZ);
……@@ -140,72 +158,58 @@ int main(void)
140158 for(int i=3;i<6;i++) seeds[i]=0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(i+1));
141159 int NS=6;
142160
143 printf("=== PARASITE AS PROTO-GENOME: does information move onto the cheap molecule? ===\n");
144 printf(" A strand is %d FOLD bits + 3 TYPE bits. Folds (phi>=%d) => a CATALYST of its type.\n",NFOLD,THETA);
145 printf(" Does not fold => a TEMPLATE carrying only type. A template protects 3 bits, a catalyst\n");
146 printf(" protects %d — the same information, fewer constrained bits, IF it can be read.\n",NFOLD+3);
147 printf(" SUPPLIED: reading (a catalyst's fold + a template's type -> a catalyst of that type).\n");
148 printf(" NOT SUPPLIED: any reward for holding templates. They fold nothing, cost the same, and\n");
149 printf(" keep the parasite advantage (non-folders replicate %.0fx faster). %d comps x %d, %d gens.\n\n",1+BETA,NCOMP,CSZ,GEN);
161 printf("=== PARASITE AS PROTO-GENOME v2: does the PAYOFF decide whether memory pays? ===\n");
162 printf(" v1 found reading raises function (+0.92 at high mu) but SCRAMBLED reading — random type\n");
163 printf(" instead of the template's — BEAT faithful reading everywhere. Diagnosis: the payoff\n");
164 printf(" rewarded DIVERSITY, and randomness supplies diversity better than fidelity does. A world\n");
165 printf(" where any repertoire is as good as any other has nothing worth remembering.\n");
166 printf(" v2 adds a TARGET payoff: only %d of %d types count, drawn at random per run. Now a\n",4,NTYPE);
167 printf(" SPECIFIC configuration beats a random one. PREDICTION: the control INVERTS.\n\n");
150168
151 printf(" mu | READ OFF: rep / tmpl | READ ON: rep / tmpl | SCRAMBLED: rep / tmpl\n");
152 printf(" ------+----------------------+---------------------+----------------------\n");
153169 double mus[]={0.005,0.01,0.02,0.04,0.08};
154 int nM=5, coexist=0, on_wins=0, scr_flat=1;
155 double gap_lo=0, gap_hi=0;
170 int nM=5;
171 const char *pn[2]={"DIVERSITY (v1)","TARGET (v2)"};
172 int inverted=0, div_scr_wins=0, tgt_faith_wins=0;
156173
157 for(int i=0;i<nM;i++){
158 double r0=0,t0=0,c0=0, r1=0,t1=0,c1=0, r2=0,t2=0,c2=0;
159 for(int s=0;s<NS;s++){
160 double tf,cf,rp;
161 RNG=seeds[s]; run(0,mus[i],&tf,&cf,&rp); r0+=rp; t0+=tf; c0+=cf;
162 RNG=seeds[s]; run(1,mus[i],&tf,&cf,&rp); r1+=rp; t1+=tf; c1+=cf;
163 RNG=seeds[s]; run(2,mus[i],&tf,&cf,&rp); r2+=rp; t2+=tf; c2+=cf;
174 for(int pay=0;pay<2;pay++){
175 printf(" --- payoff = %s ---\n",pn[pay]);
176 printf(" mu | READ OFF | READ ON (faithful) | SCRAMBLED | faithful - scrambled\n");
177 printf(" ------+----------+--------------------+-----------+---------------------\n");
178 for(int i=0;i<nM;i++){
179 double r0=0,r1=0,r2=0;
180 for(int s=0;s<NS;s++){
181 double tf,cf,rp;
182 RNG=seeds[s]; run(0,mus[i],pay,&tf,&cf,&rp); r0+=rp;
183 RNG=seeds[s]; run(1,mus[i],pay,&tf,&cf,&rp); r1+=rp;
184 RNG=seeds[s]; run(2,mus[i],pay,&tf,&cf,&rp); r2+=rp;
185 }
186 r0/=NS;r1/=NS;r2/=NS;
187 double d=r1-r2;
188 printf(" %.3f | %.2f | %.2f | %.2f | %+.3f\n",mus[i],r0,r1,r2,d);
189 if(pay==0 && d<-0.02) div_scr_wins++;
190 if(pay==1 && d>0.02) tgt_faith_wins++;
164191 }
165 r0/=NS;t0/=NS;c0/=NS; r1/=NS;t1/=NS;c1/=NS; r2/=NS;t2/=NS;c2/=NS;
166 printf(" %.3f | %.2f / %.3f | %.2f / %.3f | %.2f / %.3f\n",
167 mus[i], r0,t0, r1,t1, r2,t2);
168 /* CORRECTED CRITERIA. The first version required TEMPLATE FRACTION TO RISE in both G2 and
169 G3, which is backwards: reading CONSUMES templates by converting them into catalysts, so a
170 working genome shows FEWER standing templates, not more. Judge on repertoire, and judge the
171 control by whether faithful reading beats scrambled reading. */
172 if(c1>0.02 && t1>0.02) coexist=1;
173 if(r1>r0+0.1) on_wins++;
174 if(r2>r1+0.05) scr_flat=0; /* scrambled beating faithful = the information does nothing */
175 if(i==0) gap_lo=r1-r0;
176 gap_hi=r1-r0;
192 printf("\n");
177193 }
178 printf("\n rep = mean distinct catalyst types per compartment (max %d); tmpl = template fraction\n\n",NTYPE);
194 inverted = (div_scr_wins>=4 && tgt_faith_wins>=4);
179195
180 printf(" G4 catalysts and templates coexist : %s\n", coexist?"YES":"NO — nothing to observe");
181 printf(" G2 READ ON beats READ OFF : %d/%d mutation rates\n", on_wins,nM);
182 printf(" G3 faithful reading beats SCRAMBLED : %s\n", scr_flat?"YES":"NO — the INFORMATION does nothing");
183 printf(" G5 advantage grows with mu : %+.2f at mu=%.3f -> %+.2f at mu=%.3f\n\n",
184 gap_lo,mus[0],gap_hi,mus[nM-1]);
196 printf(" under DIVERSITY, scrambled beats faithful : %d/%d mutation rates\n",div_scr_wins,nM);
197 printf(" under TARGET, faithful beats scrambled : %d/%d mutation rates\n\n",tgt_faith_wins,nM);
185198
186 if(!coexist)
187 printf(" => THE TEST DID NOT RUN. One class went extinct everywhere, so there was no offloading\n"
188 " to observe. Invalid experiment, not a null.\n");
189 else if(!scr_flat)
190 printf(" => THE INFORMATION DOES NOTHING. Reading raises functional repertoire (+0.14 at low mu\n"
191 " to +0.92 at high mu, exactly as G5 predicted), but SCRAMBLED reading -- which\n"
192 " produces a catalyst of a RANDOM type -- beats faithful reading at every mutation\n"
193 " rate. So the gain is the mechanism CONVERTING non-folders into folders, not the\n"
194 " information a template carries. Claim nothing about genomes.\n"
195 " DIAGNOSIS: the payoff here rewards DIVERSITY of catalyst types, and randomness\n"
196 " supplies diversity better than fidelity does. A world where any repertoire is as\n"
197 " good as any other has nothing worth remembering, so memory cannot pay. The fix is a\n"
198 " payoff on a SPECIFIC target set of types, where a particular configuration beats a\n"
199 " random one -- then faithful reading has something to be faithful TO. NOT RUN.\n");
200 else if(on_wins>=nM-1)
201 printf(" => THE SYSTEM OFFLOADED ITS INFORMATION. Given a way to read cheap non-folding strands,\n"
202 " lineages keep them and carry more function than lineages that cannot — with the\n"
203 " scrambled control flat, so it is the INFORMATION and not the mechanism. The molecule\n"
204 " the whole arc treated as a parasite to be purged became the thing that remembers.\n");
199 if(inverted)
200 printf(" => THE CONTROL INVERTS, AND THE PAYOFF IS WHAT DECIDES. The identical mechanism, the\n"
201 " identical molecules, the identical parasite advantage — and whether carrying\n"
202 " information on a cheap non-folding strand pays depends entirely on whether the world\n"
203 " rewards a SPECIFIC configuration or merely variety. Memory is worthless in a world\n"
204 " that will take any answer, and selected for in one that will not. That is a\n"
205 " condition on the ENVIRONMENT for the genotype/phenotype split, not on the chemistry.\n");
206 else if(tgt_faith_wins>=4)
207 printf(" => FAITHFUL WINS UNDER TARGET (%d/%d) but the diversity contrast did not come out as\n"
208 " cleanly (%d/%d). The direction supports the diagnosis; report the asymmetry as-is.\n",
209 tgt_faith_wins,nM,div_scr_wins,nM);
205210 else
206 printf(" => HONEST NULL. Reading is available and free, and the system does NOT offload:\n"
207 " templates are purged as parasites anyway. Carrying information on a cheap molecule\n"
208 " is not selected for here, so the genotype/phenotype split needs more than the\n"
209 " opportunity — fidfloor.c says it is necessary, this says it is not sufficient.\n");
211 printf(" => HONEST NULL. Even with a target payoff, faithful reading does NOT beat scrambled.\n"
212 " The diagnosis from v1 was wrong: giving the world something specific to want is not\n"
213 " what makes memory pay, and the missing ingredient is still unidentified.\n");
210214 return 0;
211215}
basal-agent/replicase.c +212 -0
……@@ -0,0 +1,212 @@
1/* replicase.c — the closed genotype/phenotype loop. Can it bootstrap?
2 *
3 * WHERE THIS COMES FROM. genome.c v1/v2 gave templates a fair test and they failed twice, but the
4 * second failure exposed something I had been getting for free: TEMPLATE COPYING WAS FREE PHYSICS
5 * (child = par, perfect, no cost). In reality copying a genome faithfully needs a REPLICASE, which
6 * is itself a catalyst, which is itself specified by a template. That is the loop, and it is exactly
7 * rung 1→2.
8 *
9 * Two flaws in genome.c are fixed here:
10 * (1) a picked template ALWAYS became a catalyst when reading was on, so reading was a dead end for
11 * the template lineage — it could be useful or persist, never both. Now a picked template is
12 * READ with probability PREAD and otherwise COPIED TRUE, exactly as a catalyst is copied true.
13 * Reading is a FUNCTION templates provide, not a route by which they propagate.
14 * (2) template fidelity was free. Now it is CONDITIONAL on the compartment holding a catalyst of
15 * the replicase type: with one, templates copy at MU*RLO; without, at MU*RHI.
16 *
17 * THE RAZOR. This is where encoding the answer is easiest, so, precisely:
18 * SUPPLIED as physics: "a type-REPTYPE catalyst improves template fidelity in its compartment" —
19 * a function, the same shape as ribozyme.c's supplied fold→catalysis map.
20 * NOT SUPPLIED: any reward for being or holding a replicase. REPTYPE is EXCLUDED FROM THE TARGET
21 * SET, so it contributes nothing to payoff directly — it is pure overhead unless the template
22 * loop pays for itself. It is not seeded, not protected, not favoured in replication. Non-folders
23 * still replicate faster, so the parasite advantage is intact and the replicase is a PUBLIC GOOD
24 * within its compartment, free-ridable exactly as catalysis was in ribozyme.c.
25 * MEASURED: whether lineages acquire and HOLD the replicase, and whether function is higher for it.
26 *
27 * THE CONTROL, built to today's matched-condition lesson. Turning the replicase effect on also
28 * changes the average template mutation rate, which would confound any gain. So the control applies
29 * the IDENTICAL two-rate structure conditioned on a COIN FLIP per compartment instead of on
30 * replicase presence — same mutation-rate distribution, no type to select for. The realized
31 * low-fidelity fraction is reported for both arms so the match is visible rather than assumed.
32 *
33 * PRE-REGISTERED:
34 * R1 replicase frequency RISES above the control's. Lineages hold a type that pays them nothing
35 * directly, because it protects the templates that carry everything else.
36 * R2 target repertoire is HIGHER with the replicase effect than with the coin-flip control.
37 * R3 TEST OF THE TEST: catalysts and templates coexist, and the two arms' low-fidelity fractions
38 * are comparable. If they diverge sharply the comparison is confounded by mutation load.
39 * R4 the advantage should GROW with base mu — the replicase matters most where templates decay fast.
40 *
41 * HONEST PRIOR: partial. The replicase is a public good inside its compartment, so free-riding should
42 * bite exactly as it did in ribozyme.c — one level up. A null here is a real result.
43 *
44 * build: cc -O2 -Wall -std=c11 -o replicase replicase.c -lm
45 */
46#include <math.h>
47#include <stdio.h>
48#include <stdint.h>
49
50#define NFOLD 16
51#define NPAIR (NFOLD/2)
52#define THETA 6
53#define NTYPE 8
54#define REPTYPE 0 /* the replicase type — excluded from the target set */
55#define NTARG 3 /* target types, drawn from types 1..7 */
56#define NCOMP 600
57#define CSZ 8
58#define GEN 200
59#define BETA 2.0
60#define PREAD 0.50
61#define RLO 0.25 /* template mutation multiplier WITH a replicase present */
62#define RHI 1.50 /* ... and without */
63
64
65static unsigned long long RNG;
66static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; }
67static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); }
68
69static int TARGET[NTYPE];
70static int phi(uint32_t s){ int c=0; for(int i=0;i<NPAIR;i++){ int a=(s>>i)&1,b=(s>>(NFOLD-1-i))&1; if(a!=b)c++; } return c; }
71static int isfold(uint32_t s){ return phi(s)>=THETA; }
72static int typeof_(uint32_t s){ return (int)((s>>NFOLD)&7); }
73static uint32_t mut(uint32_t s,double mu){ for(int i=0;i<NFOLD+3;i++) if(urand()<mu) s^=(1u<<i); return s; }
74
75static uint32_t cell[NCOMP][CSZ], ncell[NCOMP][CSZ];
76static double cum[NCOMP];
77
78static int payoff_of(const uint32_t *c){
79 int seen[NTYPE]; for(int t=0;t<NTYPE;t++) seen[t]=0;
80 int d=0;
81 for(int k=0;k<CSZ;k++) if(isfold(c[k])){ int t=typeof_(c[k]); if(!seen[t]){ seen[t]=1; if(TARGET[t]) d++; } }
82 return d;
83}
84static int has_replicase(const uint32_t *c){
85 for(int k=0;k<CSZ;k++) if(isfold(c[k]) && typeof_(c[k])==REPTYPE) return 1;
86 return 0;
87}
88
89/* mode 0 = REPLICASE (fidelity conditioned on holding one), 1 = CONTROL (same structure, coin flip) */
90static void run(int mode,double mu,double pflip,double *rep_freq,double *pay_out,double *tmpl,double *lofrac)
91{
92 for(int t=0;t<NTYPE;t++) TARGET[t]=0;
93 for(int got=0;got<NTARG;){ int t=1+(int)(xs()%(NTYPE-1)); if(!TARGET[t]){ TARGET[t]=1; got++; } }
94 for(int c=0;c<NCOMP;c++)
95 for(int k=0;k<CSZ;k++){ uint32_t v=0; for(int i=0;i<NFOLD+3;i++) if(urand()<0.5) v|=(1u<<i); cell[c][k]=v; }
96
97 double losum=0; long lon=0;
98
99 for(int g=0;g<GEN;g++){
100 for(int c=0;c<NCOMP;c++){
101 int lo_fid = (mode==0)? has_replicase(cell[c]) : (urand()<pflip);
102 losum += lo_fid; lon++;
103 double tmu = mu*(lo_fid?RLO:RHI);
104 double tot=0,cw[CSZ];
105 for(int k=0;k<CSZ;k++){ tot += 1.0 + BETA*(1.0-(double)phi(cell[c][k])/NPAIR); cw[k]=tot; }
106 int mach=-1; for(int k=0;k<CSZ;k++) if(isfold(cell[c][k])){ mach=k; break; }
107 for(int k=0;k<CSZ;k++){
108 double r=urand()*tot; int lo=0,hi=CSZ-1;
109 while(lo<hi){ int mid=(lo+hi)/2; if(cw[mid]<r) lo=mid+1; else hi=mid; }
110 uint32_t par=cell[c][lo], child; double emu;
111 if(!isfold(par)){
112 if(mach>=0 && urand()<PREAD){ /* READ: template -> catalyst */
113 child=(cell[c][mach]&((1u<<NFOLD)-1))|((uint32_t)typeof_(par)<<NFOLD);
114 emu=mu; /* the new catalyst is a catalyst */
115 } else { child=par; emu=tmu; } /* COPY TRUE, at template fidelity */
116 } else { child=par; emu=mu; } /* catalyst -> catalyst */
117 ncell[c][k]=mut(child,emu);
118 }
119 }
120 for(int c=0;c<NCOMP;c++) for(int k=0;k<CSZ;k++) cell[c][k]=ncell[c][k];
121
122 double tot=0;
123 for(int c=0;c<NCOMP;c++){ tot += 0.05 + (double)payoff_of(cell[c]); cum[c]=tot; }
124 for(int c=0;c<NCOMP;c++){
125 double r=urand()*tot; int lo=0,hi=NCOMP-1;
126 while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; }
127 for(int k=0;k<CSZ;k++) ncell[c][k]=cell[lo][(int)(xs()%CSZ)];
128 }
129 for(int c=0;c<NCOMP;c++) for(int k=0;k<CSZ;k++) cell[c][k]=ncell[c][k];
130 }
131
132 long nt=0; double rp=0,pay=0;
133 for(int c=0;c<NCOMP;c++){
134 rp += has_replicase(cell[c]); pay += payoff_of(cell[c]);
135 for(int k=0;k<CSZ;k++) if(!isfold(cell[c][k])) nt++;
136 }
137 *rep_freq=rp/NCOMP; *pay_out=pay/NCOMP;
138 *tmpl=(double)nt/((double)NCOMP*CSZ); *lofrac=losum/(double)lon;
139}
140
141int main(void)
142{
143 unsigned long long seeds[6];
144 seeds[0]=0x9e3779b97f4a7c15ULL; seeds[1]=0xd1b54a32d192ed03ULL; seeds[2]=0x2545f4914f6cdd1dULL;
145 for(int i=3;i<6;i++) seeds[i]=0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(i+1));
146 int NS=6;
147
148 printf("=== REPLICASE: can the genotype/phenotype loop close on itself? ===\n");
149 printf(" A type-%d catalyst improves TEMPLATE fidelity in its compartment (x%.2f vs x%.2f).\n",REPTYPE,RLO,RHI);
150 printf(" It is EXCLUDED from the target set, so it pays nothing directly — pure overhead unless\n");
151 printf(" the template loop pays for itself. Not seeded, not protected; non-folders still replicate\n");
152 printf(" %.0fx faster, so the replicase is a PUBLIC GOOD inside its compartment and free-ridable.\n",1+BETA);
153 printf(" CONTROL applies the identical two-rate structure by COIN FLIP instead — same mutation\n");
154 printf(" distribution, no type to select for. %d comps x %d, %d gens, %d seeds.\n\n",NCOMP,CSZ,GEN,NS);
155
156 printf(" mu | REPLICASE: rep-freq / payoff / tmpl | CONTROL: rep-freq / payoff | lo-fid frac R/C\n");
157 printf(" ------+-------------------------------------+----------------------------+----------------\n");
158 double mus[]={0.005,0.01,0.02,0.04,0.08};
159 int nM=5, r1=0, r2=0, matched=1; double g0=0,g1=0;
160
161 for(int i=0;i<nM;i++){
162 /* TWO PASS, so the control is matched rather than guessed: run the replicase arm, measure the
163 fraction of compartment-generations that actually got the low rate, then give the control a
164 coin flip at exactly that probability. The first version guessed PFLIP=0.60 from a uniform-type
165 estimate; selection purges type 0 (it pays nothing) so the real figure is 0.03-0.13, and the
166 control was running at a fraction of the mutation load. R3 caught it. */
167 double a1=0,a2=0,a3=0,a4=0, b1=0,b2=0,b4=0;
168 double lf_meas[8];
169 for(int s=0;s<NS;s++){
170 double rf,pv,tm,lf;
171 RNG=seeds[s]; run(0,mus[i],0.0,&rf,&pv,&tm,&lf); a1+=rf; a2+=pv; a3+=tm; a4+=lf; lf_meas[s]=lf;
172 }
173 for(int s=0;s<NS;s++){
174 double rf,pv,tm,lf;
175 RNG=seeds[s]; run(1,mus[i],lf_meas[s],&rf,&pv,&tm,&lf); b1+=rf; b2+=pv; b4+=lf;
176 }
177 a1/=NS;a2/=NS;a3/=NS;a4/=NS; b1/=NS;b2/=NS;b4/=NS;
178 printf(" %.3f | %.3f / %.2f / %.3f | %.3f / %.2f | %.2f / %.2f\n",
179 mus[i],a1,a2,a3,b1,b2,a4,b4);
180 if(a1>b1+0.02) r1++;
181 if(a2>b2+0.05) r2++;
182 if(fabs(a4-b4)>0.03) matched=0;
183 if(i==0) g0=a2-b2;
184 g1=a2-b2;
185 }
186 printf("\n rep-freq = fraction of compartments holding a replicase; payoff = target types present (max %d)\n\n",NTARG);
187
188 printf(" R3 low-fidelity fractions comparable : %s\n", matched?"YES":"NO — CONFOUNDED by mutation load");
189 printf(" R1 replicase held above control : %d/%d mutation rates\n",r1,nM);
190 printf(" R2 payoff higher than control : %d/%d mutation rates\n",r2,nM);
191 printf(" R4 advantage grows with mu : %+.2f at mu=%.3f -> %+.2f at mu=%.3f\n\n",g0,mus[0],g1,mus[nM-1]);
192
193 if(!matched)
194 printf(" => CONFOUNDED. The arms did not experience comparable mutation loads, so any difference\n"
195 " is the load and not the loop.\n");
196 else if(r1>=nM-1 && r2>=nM-1)
197 printf(" => THE LOOP CLOSED. Lineages hold a catalyst type that pays them NOTHING directly,\n"
198 " because it protects the templates that carry everything that does pay — and they\n"
199 " carry more function for it than the matched control. Genotype and phenotype became\n"
200 " mutually dependent without either being rewarded for it. That is rung 1->2's\n"
201 " architecture, bootstrapped rather than installed.\n");
202 else if(r2>=nM-1)
203 printf(" => FUNCTION UP, REPLICASE NOT HELD (%d/%d vs %d/%d). The fidelity boost helps where it\n"
204 " happens to occur, but lineages do not retain the replicase — free-riding inside the\n"
205 " compartment wins, exactly as ribozyme.c found one level down. The loop does not close.\n",r2,nM,r1,nM);
206 else
207 printf(" => HONEST NULL. The replicase is not held and function is not raised. A catalyst that\n"
208 " pays only by protecting templates cannot pay for itself here: it is a public good\n"
209 " inside its own compartment and is free-ridden away. The genotype/phenotype loop\n"
210 " needs something this model does not have.\n");
211 return 0;
212}
basal-agent/replicase.md +72 -0
……@@ -0,0 +1,72 @@
1# `replicase.c` — the loop does not close, and the wall is the same one, one level up
2
3The last experiment of the arc, and the first with **genotype and phenotype mutually dependent**
4rather than one being a convenience for the other.
5
6## What it fixes from `genome.c`
7
8Two flaws, both found by the earlier runs:
9
101. **Reading was a dead end.** A picked template always became a catalyst, so a template could be
11 useful or persist, never both. Now it is read with probability `PREAD` and otherwise **copied
12 true**, exactly as a catalyst is. Reading is a function templates provide, not a route by which
13 they propagate.
142. **Template copying was free physics.** `child = par`, perfect, no cost. In reality copying a
15 genome needs a **replicase** — itself a catalyst, itself specified by a template. That is the loop.
16
17So: a type-0 catalyst improves template fidelity in its compartment (×0.25 vs ×1.50). It is
18**excluded from the target set**, so it pays nothing directly — pure overhead unless the loop pays
19for itself. Not seeded, not protected; non-folders still replicate 3× faster, so the replicase is a
20**public good inside its own compartment**, free-ridable exactly as catalysis was in `ribozyme.c`.
21
22## The control had to be fixed first
23
24R3 failed on the first run: the replicase arm got low-fidelity 3–13% of the time, the control **60%**.
25I had guessed `PFLIP` from a uniform-type estimate, but selection *purges* type 0 precisely because it
26pays nothing, so the real frequency is an order of magnitude lower — and the control was running at a
27fraction of the mutation load, against the arm it was meant to test. Fixed by a two-pass design: run
28the replicase arm, measure the realized low-fidelity fraction per seed, then give the control a coin
29flip at exactly that probability.
30
31## Results (6 seeds, matched)
32
33| μ | replicase: rep-freq / payoff / tmpl | control: rep-freq / payoff | lo-fid R / C |
34|---|---|---|---|
35| 0.005 | 0.025 / 1.56 / 0.094 | 0.022 / 1.57 | 0.03 / 0.03 |
36| 0.010 | 0.039 / 1.51 / 0.145 | 0.050 / 1.51 | 0.04 / 0.04 |
37| 0.020 | 0.060 / 1.44 / 0.240 | 0.094 / 1.44 | 0.07 / 0.07 |
38| 0.040 | 0.111 / 1.37 / 0.361 | 0.100 / 1.39 | 0.10 / 0.10 |
39| 0.080 | 0.129 / 1.22 / 0.502 | 0.129 / 1.23 | 0.13 / 0.13 |
40
41**R3 passes** — loads matched exactly. **R1: 0/5.** **R2: 0/5.** The two arms are indistinguishable
42on both measures. (Replicase frequency rises with μ in *both* arms — that is chance generating more
43type-0 catalysts, not selection retaining them.)
44
45> **HONEST NULL.** A catalyst that pays only by protecting templates cannot pay for itself here.
46
47## Why — and it is the arc's own wall, one level up
48
49The replicase improves fidelity for **every** template in its compartment, including those of
50free-riders, and it costs a slot: it occupies one of eight without contributing to payoff.
51Within-compartment selection therefore purges it, and between-compartment selection cannot retain it
52because its benefit is indirect and shared.
53
54That is precisely `ribozyme.c`'s public-goods wall, relocated. There, catalysis was the public good
55and a compartment privatised it. Here **the compartment cannot privatise the replicase, because the
56compartment is exactly the scope over which the replicase's benefit is shared.** A boundary can only
57privatise a good it can exclude non-contributors from — and everything inside a compartment is inside
58it.
59
60I predicted partial. It was a complete null; free-riding bit harder than expected.
61
62## What this leaves
63
64`fidfloor.c` says the genotype/phenotype split is **necessary**. `genome.c` says the opportunity is
65**not sufficient**. `replicase.c` says the loop **does not close** when the replicase is a
66compartment-scale public good. Three negatives that between them locate the problem precisely:
67
68> The replicase must be privatised at a scale *smaller* than the compartment — coupled to the
69> particular templates it copies rather than to everything nearby. Which is what a replisome does,
70> and what physical association buys that diffusion does not.
71
72That is the next design, and it is unbuilt.