| … | … | @@ -0,0 +1,289 @@ |
| 1 | /* byproduct.c — a compartment nobody chooses to build: can a NON-DISCRETIONARY boundary cross 1->2? |
| 2 | * |
| 3 | * WHERE THIS COMES FROM (Law 2, SYNTHESIS Part C). Every boundary the arc tested that had to be |
| 4 | * MAINTAINED was a strategy, and strategies get invaded: signal.c's investment converges to the same |
| 5 | * low value from starts 0.10 / 0.50 / 1.00 -- measured invasion, not a coordination trap. The only |
| 6 | * boundary that emerged, linkage.c, was STRUCTURAL: linked genes cannot replicate at different |
| 7 | * rates, so defection is not an available move. Law 2 says the way past 1->2 is therefore not to |
| 8 | * find a cheaper boundary but a boundary NOBODY CAN DECLINE TO BUILD. |
| 9 | * |
| 10 | * THE IDEA. Chemistry that builds its own container as an unavoidable SIDE EFFECT of catalyzing -- |
| 11 | * mineral precipitation, self-templating pores, alkaline-vent chimney walls. Wall-building is not an |
| 12 | * investment anyone elects: you build iff you catalyze. So a catalyst-rich region walls itself in, |
| 13 | * and a region that degenerates to parasites stops producing precipitate, its walls decay, and it is |
| 14 | * mixed back into the open pool. The compartment is maintained by the very activity it protects, and |
| 15 | * no unit ever decides to maintain it. |
| 16 | * |
| 17 | * THE RAZOR (issue #6). Nothing here says "walls exclude parasites" or "only catalysts get walls": |
| 18 | * - deposition is a function of LOCAL ACTIVITY, which parasites simply do not have -- they are not |
| 19 | * forbidden from depositing, they have nothing to deposit; |
| 20 | * - a parasite sitting inside a walled region enjoys the wall AND the catalysis in full. The |
| 21 | * within-region public-goods tragedy is untouched; |
| 22 | * - walls gate MIXING symmetrically -- they keep parasites out and catalysts in, equally. |
| 23 | * Whether catalyst-rich regions persist is therefore left genuinely open. |
| 24 | * |
| 25 | * WHAT IS SUPPLIED vs WHAT MUST EMERGE: |
| 26 | * SUPPLIED: a lattice of sites (space, which bridges.c arm A already had AND FAILED WITH), local |
| 27 | * catalysis, and the physical coupling activity -> precipitate. Deposition rate is SWEPT. |
| 28 | * MUST EMERGE: the compartments. Walls start at ZERO everywhere. If regions become isolated it is |
| 29 | * because their own chemistry isolated them. |
| 30 | * THE ONLY DIFFERENCE from the failed spatial arm is the byproduct wall. That is the variable. |
| 31 | * |
| 32 | * Chemistry identical to ribozyme.c / coupling.c / partition.c / signal.c (phi = hairpin fold, |
| 33 | * parasites 3x faster, F0=0.85, F1=0.999, 4800 units, 200 gens, start phi ~5.99 = the neutral |
| 34 | * expectation 6.0). Reference: ribozyme well-mixed 5.99 -> 5.50; SUPPLIED compartments of size 8 |
| 35 | * -> 11.34. |
| 36 | * |
| 37 | * PRE-REGISTERED: |
| 38 | * B1 WALL OFF (free mixing) -> phi FALLS. Reproduces bridges.c arm A, the spatial failure. |
| 39 | * B2 WALL SUPPLIED (always max) -> phi RISES. POSITIVE CONTROL: proves this lattice CAN cross, so |
| 40 | * that a null in B3 is about the byproduct mechanism and not about a model that cannot win. |
| 41 | * B3 WALL BYPRODUCT -> phi RISES. THE TEST. |
| 42 | * B4 WALL SHUFFLED (control) -> the same wall heights reassigned to RANDOM edges each |
| 43 | * generation: identical amount of isolation, decoupled from where the activity is. If phi rises |
| 44 | * here too, the effect is isolation per se and not the activity->wall coupling, and B3 is void. |
| 45 | * B5 TEST OF THE TEST: do walls actually form AND vary AND track local activity? Report mean wall |
| 46 | * height and the correlation between an edge's wall and its neighbouring activity. If walls are |
| 47 | * ~0, saturated everywhere, or uncorrelated with activity, the mechanism never ran and a null |
| 48 | * says nothing -- the mistake partition.c made on its first pass and ribophi.c made with its |
| 49 | * not-actually-early window. |
| 50 | * |
| 51 | * Do not tune to force a positive. A null here, with B2 passing, is a real result about Law 2. |
| 52 | * |
| 53 | * OUTCOME (recorded after the run; the pre-registration above is left exactly as written). |
| 54 | * **B2 FAILED, and its failure is the finding.** Supplied walls at full height -- total isolation -- |
| 55 | * reach only 5.65, no better than the spatial arm. Adding modes 4/5 (between-site selection, the |
| 56 | * stochastic-corrector step ribozyme.c actually has) makes supplied walls reach 10.78 and byproduct |
| 57 | * walls 11.39. So the barrier was never what made compartments work: what made them work is that |
| 58 | * compartments DIVIDE and are SELECTED on catalytic content. ISOLATION IS NOT COMPARTMENTALIZATION. |
| 59 | * A byproduct wall buys the isolation half for free and leaves the second-level-selection half |
| 60 | * exactly as supplied as it ever was -- Law 2's non-discretionary fix addresses the wrong half. |
| 61 | * Secondary, and real: GIVEN the second level, byproduct walls BEAT permanently supplied ones |
| 62 | * (11.39 vs 10.78) -- self-sealing high-activity regions while low-activity ones re-mix is a better |
| 63 | * compartment than a permanent box. Byproduct walls are a good compartment; they are not a source |
| 64 | * of the selection level. |
| 65 | * |
| 66 | * build: cc -O2 -Wall -std=c11 -o byproduct byproduct.c -lm |
| 67 | */ |
| 68 | #include <math.h> |
| 69 | #include <stdio.h> |
| 70 | #include <stdint.h> |
| 71 | |
| 72 | /* ---------- identical to the rest of Part C ---------- */ |
| 73 | #define L 24 |
| 74 | #define PHIMAX (L/2) |
| 75 | #define GEN 200 |
| 76 | #define F0 0.85 |
| 77 | #define F1 0.999 |
| 78 | #define BETA 2.0 |
| 79 | |
| 80 | /* ---------- lattice ---------- */ |
| 81 | #define NSITE 600 |
| 82 | #define CAP 8 |
| 83 | #define TOTAL (NSITE*CAP) /* 4800, same as every other Part C program */ |
| 84 | #define DECAY 0.10 /* wall dissolution per generation */ |
| 85 | #define MIGR 0.30 /* base exchange rate across an unwalled edge */ |
| 86 | |
| 87 | static unsigned long long RNG; |
| 88 | static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; } |
| 89 | static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); } |
| 90 | |
| 91 | static int phi(uint32_t s){ int c=0; for(int i=0;i<PHIMAX;i++){ int a=(s>>i)&1, b=(s>>(L-1-i))&1; if(a!=b) c++; } return c; } |
| 92 | static uint32_t replicate(uint32_t t,double f){ uint32_t c=0; for(int i=0;i<L;i++){ int b=(t>>i)&1; int nb=(urand()<f)?(1-b):b; if(nb) c|=(1u<<i);} return c; } |
| 93 | |
| 94 | static uint32_t cell[NSITE][CAP], ncell[NSITE][CAP]; |
| 95 | static double wall[NSITE], tmpw[NSITE]; /* wall[i] = barrier on the edge between i and i+1 */ |
| 96 | static double mphi[NSITE]; |
| 97 | static int phic[NSITE][CAP]; |
| 98 | |
| 99 | /* mode: 0 = wall off, 1 = byproduct wall, 2 = wall supplied at max, 3 = byproduct then SHUFFLED, |
| 100 | 4 = supplied wall + BETWEEN-SITE SELECTION, 5 = byproduct wall + between-site selection. |
| 101 | Modes 4/5 add ribozyme.c's group step (sample a parent site proportional to its mean phi, reseed |
| 102 | by random assortment) -- i.e. compartments that DIVIDE and are SELECTED, not merely isolated. */ |
| 103 | static double run(int mode,double dep,double *phi_start,double *wall_mean,double *wall_corr) |
| 104 | { |
| 105 | for(int s=0;s<NSITE;s++){ |
| 106 | wall[s]=0.0; /* walls start at ZERO: nothing is supplied */ |
| 107 | for(int k=0;k<CAP;k++){ uint32_t v=0; for(int b=0;b<L;b++) if(urand()<0.5) v|=(1u<<b); cell[s][k]=v; } |
| 108 | } |
| 109 | { double sp=0; for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) sp+=phi(cell[s][k]); *phi_start=sp/TOTAL; } |
| 110 | |
| 111 | double lastw=0, lastc=0; |
| 112 | |
| 113 | for(int g=0;g<GEN;g++){ |
| 114 | for(int s=0;s<NSITE;s++){ |
| 115 | double a=0; for(int k=0;k<CAP;k++){ phic[s][k]=phi(cell[s][k]); a+=phic[s][k]; } |
| 116 | mphi[s]=a/CAP; |
| 117 | } |
| 118 | |
| 119 | /* ---- walls: an unavoidable byproduct of local catalytic activity ---- */ |
| 120 | if(mode==2||mode==4){ for(int s=0;s<NSITE;s++) wall[s]=1.0; } |
| 121 | else if(mode==0){ for(int s=0;s<NSITE;s++) wall[s]=0.0; } |
| 122 | else { |
| 123 | for(int s=0;s<NSITE;s++){ |
| 124 | int t=(s+1)%NSITE; |
| 125 | double act=0.5*(mphi[s]+mphi[t])/PHIMAX; /* parasites deposit little: nothing to deposit */ |
| 126 | double w=wall[s]*(1.0-DECAY)+dep*act; |
| 127 | if(w<0)w=0; if(w>1)w=1; |
| 128 | wall[s]=w; |
| 129 | } |
| 130 | if(mode==3){ /* B4: same heights, random edges */ |
| 131 | for(int s=0;s<NSITE;s++) tmpw[s]=wall[s]; |
| 132 | for(int s=NSITE-1;s>0;s--){ int j=(int)(xs()%(unsigned long long)(s+1)); double t=tmpw[s]; tmpw[s]=tmpw[j]; tmpw[j]=t; } |
| 133 | for(int s=0;s<NSITE;s++) wall[s]=tmpw[s]; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | /* ---- exchange across each edge, gated symmetrically by its wall ---- */ |
| 138 | for(int s=0;s<NSITE;s++){ |
| 139 | int t=(s+1)%NSITE; |
| 140 | double pm=MIGR*(1.0-wall[s]); |
| 141 | for(int k=0;k<CAP;k++){ |
| 142 | if(urand()<pm){ |
| 143 | int a=(int)(xs()%CAP), b=(int)(xs()%CAP); |
| 144 | uint32_t tmp=cell[s][a]; cell[s][a]=cell[t][b]; cell[t][b]=tmp; |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | /* ---- local catalysis -> local fidelity; replication within the site ---- */ |
| 150 | for(int s=0;s<NSITE;s++){ |
| 151 | double a=0; for(int k=0;k<CAP;k++){ phic[s][k]=phi(cell[s][k]); a+=phic[s][k]; } |
| 152 | mphi[s]=a/CAP; |
| 153 | double f=F0+(F1-F0)*(mphi[s]/PHIMAX); |
| 154 | double tot=0,cum[CAP]; |
| 155 | for(int k=0;k<CAP;k++){ tot+=1.0+BETA*(1.0-(double)phic[s][k]/PHIMAX); cum[k]=tot; } |
| 156 | for(int k=0;k<CAP;k++){ |
| 157 | double r=urand()*tot; int lo=0,hi=CAP-1; |
| 158 | while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; } |
| 159 | ncell[s][k]=replicate(cell[s][lo],f); |
| 160 | } |
| 161 | } |
| 162 | for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) cell[s][k]=ncell[s][k]; |
| 163 | |
| 164 | /* ---- between-site selection (modes 4/5): the stochastic-corrector step ribozyme.c has ---- |
| 165 | Sites are sampled as parents in proportion to their catalytic content and reseeded by |
| 166 | random assortment. This is the SECOND LEVEL of selection; isolation alone is not it. */ |
| 167 | if(mode==4||mode==5){ |
| 168 | double tot=0; static double cums[NSITE]; |
| 169 | for(int s=0;s<NSITE;s++){ |
| 170 | double a=0; for(int k=0;k<CAP;k++) a+=phi(cell[s][k]); |
| 171 | tot+=a/CAP; cums[s]=tot; |
| 172 | } |
| 173 | for(int s=0;s<NSITE;s++){ |
| 174 | double r=urand()*tot; int lo=0,hi=NSITE-1; |
| 175 | while(lo<hi){ int mid=(lo+hi)/2; if(cums[mid]<r) lo=mid+1; else hi=mid; } |
| 176 | for(int k=0;k<CAP;k++) ncell[s][k]=cell[lo][(int)(xs()%CAP)]; |
| 177 | } |
| 178 | for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) cell[s][k]=ncell[s][k]; |
| 179 | } |
| 180 | |
| 181 | /* B5 diagnostics: wall height, and whether walls sit where the activity is */ |
| 182 | { |
| 183 | double sw=0,sa=0,saw=0,sww=0,saa=0; |
| 184 | for(int s=0;s<NSITE;s++){ |
| 185 | int t=(s+1)%NSITE; |
| 186 | double a=0.5*(mphi[s]+mphi[t])/PHIMAX, w=wall[s]; |
| 187 | sw+=w; sa+=a; saw+=a*w; sww+=w*w; saa+=a*a; |
| 188 | } |
| 189 | double n=NSITE, cov=saw/n-(sa/n)*(sw/n); |
| 190 | double sdw=sqrt(fmax(1e-12,sww/n-(sw/n)*(sw/n))), sda=sqrt(fmax(1e-12,saa/n-(sa/n)*(sa/n))); |
| 191 | lastw=sw/n; lastc=cov/(sdw*sda); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | double sp=0; for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) sp+=phi(cell[s][k]); |
| 196 | *wall_mean=lastw; *wall_corr=lastc; |
| 197 | return sp/TOTAL; |
| 198 | } |
| 199 | |
| 200 | int main(void) |
| 201 | { |
| 202 | unsigned long long seeds[8]; |
| 203 | seeds[0]=0x9e3779b97f4a7c15ULL; seeds[1]=0xd1b54a32d192ed03ULL; seeds[2]=0x2545f4914f6cdd1dULL; |
| 204 | for(int i=3;i<8;i++) seeds[i]=0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(i+1)); |
| 205 | int NS=8; |
| 206 | |
| 207 | printf("=== BYPRODUCT COMPARTMENT: a boundary nobody chooses to build ===\n"); |
| 208 | printf(" Walls START AT ZERO and accumulate as a side effect of local catalysis; they decay.\n"); |
| 209 | printf(" Wall-building is NON-DISCRETIONARY -- parasites are not forbidden from depositing,\n"); |
| 210 | printf(" they simply have nothing to deposit. Walls gate mixing SYMMETRICALLY (in and out).\n"); |
| 211 | printf(" %d sites x %d units = %d. The ONLY difference from the failed spatial arm is the wall.\n",NSITE,CAP,TOTAL); |
| 212 | printf(" REFERENCE: ribozyme well-mixed 5.99 -> 5.50; SUPPLIED compartments of 8 -> 11.34.\n\n"); |
| 213 | |
| 214 | printf(" deposition | WALL OFF | BYPRODUCT | SHUFFLED | SUPPLIED | SUP+sel | BYP+sel | wall mean | r\n"); |
| 215 | printf(" -----------+----------+-----------+----------+----------+---------+---------+-----------+------\n"); |
| 216 | |
| 217 | double deps[]={0.00,0.05,0.10,0.20,0.40,0.80}; |
| 218 | int ND=(int)(sizeof(deps)/sizeof(deps[0])); |
| 219 | double start=0, bestby=-1e9, bestdep=-1, byp_at_best=0, shf_at_best=0, off_at_best=0, sup_best=-1e9; |
| 220 | double sup_sel_best=-1e9, byp_sel_best=-1e9; |
| 221 | int informative=0; |
| 222 | |
| 223 | for(int d=0;d<ND;d++){ |
| 224 | double eo=0,eb=0,es=0,ep=0,e4=0,e5=0,wm=0,wc=0,ps=0; |
| 225 | for(int s=0;s<NS;s++){ |
| 226 | double p,w,c; |
| 227 | RNG=seeds[s]; eo+=run(0,deps[d],&p,&w,&c); |
| 228 | RNG=seeds[s]; eb+=run(1,deps[d],&p,&w,&c); wm+=w; wc+=c; ps+=p; |
| 229 | RNG=seeds[s]; es+=run(3,deps[d],&p,&w,&c); |
| 230 | RNG=seeds[s]; ep+=run(2,deps[d],&p,&w,&c); |
| 231 | RNG=seeds[s]; e4+=run(4,deps[d],&p,&w,&c); |
| 232 | RNG=seeds[s]; e5+=run(5,deps[d],&p,&w,&c); |
| 233 | } |
| 234 | eo/=NS;eb/=NS;es/=NS;ep/=NS;e4/=NS;e5/=NS;wm/=NS;wc/=NS;ps/=NS; |
| 235 | start=ps; |
| 236 | printf(" %.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %.3f | %+.2f\n", |
| 237 | deps[d],eo,eb,es,ep,e4,e5,wm,wc); |
| 238 | if(e4>sup_sel_best) sup_sel_best=e4; |
| 239 | if(e5>byp_sel_best) byp_sel_best=e5; |
| 240 | if(wm>0.02 && wm<0.98 && wc>0.10) informative=1; |
| 241 | if(eb>bestby){ bestby=eb; bestdep=deps[d]; byp_at_best=eb; shf_at_best=es; off_at_best=eo; } |
| 242 | if(ep>sup_best) sup_best=ep; |
| 243 | } |
| 244 | printf("\n start phi (= neutral expectation) %.2f\n\n",start); |
| 245 | |
| 246 | int b1 = off_at_best < start-0.2; |
| 247 | int b2 = sup_best > start+0.5; |
| 248 | int b2b= sup_sel_best > start+0.5; |
| 249 | int b3 = byp_at_best> start+0.5; |
| 250 | int b4 = shf_at_best< byp_at_best-0.2; |
| 251 | |
| 252 | printf(" B1 wall OFF falls (spatial arm reproduced) : %s (%.2f)\n", b1?"YES":"no", off_at_best); |
| 253 | printf(" B2 wall SUPPLIED, isolation only : %s (%.2f)\n", b2?"YES":"NO", sup_best); |
| 254 | printf(" B2b SUPPLIED + between-site SELECTION : %s (%.2f) <- real positive control\n", b2b?"YES":"NO", sup_sel_best); |
| 255 | printf(" B2c BYPRODUCT + between-site selection : %.2f\n", byp_sel_best); |
| 256 | printf(" B3 BYPRODUCT rises above start : %s (%.2f at dep %.2f)\n", b3?"YES":"NO", byp_at_best,bestdep); |
| 257 | printf(" B4 SHUFFLED control below byproduct : %s (%.2f vs %.2f)\n", b4?"YES":"NO", shf_at_best,byp_at_best); |
| 258 | printf(" B5 walls formed, varied, and tracked activity: %s\n\n", informative?"YES":"NO"); |
| 259 | |
| 260 | if(!informative) |
| 261 | printf(" => THE TEST DID NOT RUN. Walls never formed in an informative regime (absent, saturated,\n" |
| 262 | " or uncorrelated with activity). Nothing here speaks to the byproduct mechanism.\n" |
| 263 | " Invalid experiment, NOT a null.\n"); |
| 264 | else if(!b2 && !b2b) |
| 265 | printf(" => THE POSITIVE CONTROL FAILED EVEN WITH SELECTION. The lattice cannot cross at all.\n" |
| 266 | " Fix the model before reading anything into any arm.\n"); |
| 267 | else if(!b2 && b2b) |
| 268 | printf(" => DIAGNOSIS: ISOLATION IS NOT COMPARTMENTALIZATION. Supplied walls alone do NOT cross\n" |
| 269 | " (%.2f); supplied walls PLUS between-site selection do (%.2f). What made compartments\n" |
| 270 | " work was never the barrier -- it was that compartments DIVIDE and are SELECTED on\n" |
| 271 | " catalytic content. A byproduct wall supplies the isolation half for free, and the\n" |
| 272 | " second-level selection half remains exactly as supplied as it ever was. Law 2's\n" |
| 273 | " non-discretionary fix addresses the WRONG HALF of what a compartment is.\n", sup_best, sup_sel_best); |
| 274 | else if(b3 && b4) |
| 275 | printf(" => A NON-DISCRETIONARY BOUNDARY CROSSES. Compartments formed from nothing but the side\n" |
| 276 | " effects of catalysis, and phi rose above its neutral start with no wall ever supplied\n" |
| 277 | " and no unit ever electing to build one. The shuffled control -- identical isolation,\n" |
| 278 | " wrong places -- did not rise, so the effect is the activity->wall coupling. This is the\n" |
| 279 | " Law 2 prediction confirmed: what fails is not the boundary but its DISCRETION.\n"); |
| 280 | else if(b3 && !b4) |
| 281 | printf(" => CONFOUNDED. phi rose but the shuffled control rose too, so the effect is isolation per\n" |
| 282 | " se and not the activity->wall coupling. Claim nothing about byproduct compartments.\n"); |
| 283 | else |
| 284 | printf(" => HONEST NULL, with the positive control PASSING. Supplied walls cross and byproduct\n" |
| 285 | " walls do not, so a boundary being non-discretionary is NOT sufficient -- it must also\n" |
| 286 | " arrive before the parasites do. Law 2 is necessary but not sufficient, and rung 1->2\n" |
| 287 | " stands open.\n"); |
| 288 | return 0; |
| 289 | } |