| … | … | @@ -91,7 +91,7 @@ static double pool; |
| 91 | 91 | static double demand[MAXCOMP]; |
| 92 | 92 | |
| 93 | 93 | /* coupled=1: uptake tracks catalytic output. coupled=0: uptake is constant per unit (C4 control). */ |
| 94 | | static double run(int coupled,int divsz,double *phi_start,double *ndiv,double *ndeath, |
| 94 | static double run(int coupled,int divsz,int propagule,double *phi_start,double *ndiv,double *ndeath, |
| 95 | 95 | double *ncomp_end,double *msize,double *matcheck) |
| 96 | 96 | { |
| 97 | 97 | int seed_n = divsz/2 > 2 ? divsz/2 : 2; |
| … | … | @@ -144,13 +144,25 @@ static double run(int coupled,int divsz,double *phi_start,double *ndiv,double *n |
| 144 | 144 | for(int c=0;c<base;c++){ |
| 145 | 145 | if(C[c].n>=divsz && ncomp<MAXCOMP){ |
| 146 | 146 | Comp *p=&C[c], *q=&C[ncomp]; |
| 147 | | q->n=0; q->mat=p->mat*0.5; p->mat*=0.5; |
| 148 | | int w=0; |
| 149 | | for(int k=0;k<p->n;k++){ |
| 150 | | if(urand()<0.5) q->u[q->n++]=p->u[k]; |
| 151 | | else p->u[w++]=p->u[k]; |
| 147 | if(propagule){ |
| 148 | /* BOTTLENECK: the offspring is ONE randomly chosen unit -- it may equally be a |
| 149 | parasite. Nothing selects which unit buds; only the VARIANCE among offspring |
| 150 | compartments changes, which is the quantity the relatedness literature says |
| 151 | does the work (a zygote is the n=1 limit of a small compartment). */ |
| 152 | int pick=(int)(xs()%(unsigned long long)p->n); |
| 153 | double share=p->mat/(double)p->n; |
| 154 | q->n=0; q->u[q->n++]=p->u[pick]; q->mat=share; p->mat-=share; |
| 155 | p->u[pick]=p->u[p->n-1]; p->n--; |
| 156 | } else { |
| 157 | q->n=0; q->mat=p->mat*0.5; p->mat*=0.5; |
| 158 | int w=0; |
| 159 | for(int k=0;k<p->n;k++){ |
| 160 | if(urand()<0.5) q->u[q->n++]=p->u[k]; |
| 161 | else p->u[w++]=p->u[k]; |
| 162 | } |
| 163 | p->n=w; |
| 152 | 164 | } |
| 153 | | p->n=w; ncomp++; totdiv++; |
| 165 | ncomp++; totdiv++; |
| 154 | 166 | } |
| 155 | 167 | } |
| 156 | 168 | |
| … | … | @@ -186,25 +198,28 @@ int main(void) |
| 186 | 198 | printf(" at size >= 16. If growth-coupling is the mechanism behind that decree, the SIZE THRESHOLD\n"); |
| 187 | 199 | printf(" must reappear here on its own.\n\n"); |
| 188 | 200 | |
| 189 | | printf(" div size | COUPLED phi | CONTROL phi | comps | mean sz | div/gen | death/gen | material\n"); |
| 190 | | printf(" ---------+-------------+-------------+-------+---------+---------+-----------+---------\n"); |
| 201 | printf(" div size | FISSION phi | fis CONTROL | PROPAGULE phi | prop CONTROL | fis mean sz | prop mean sz\n"); |
| 202 | printf(" ---------+-------------+-------------+---------------+--------------+-------------+-------------\n"); |
| 191 | 203 | |
| 192 | | int sizes[]={4,8,16,32}; |
| 204 | int sizes[]={4,6,8,10,12,16,20,24,32}; |
| 193 | 205 | int NZ=(int)(sizeof(sizes)/sizeof(sizes[0])); |
| 194 | 206 | double start=0; int turned_over=0; |
| 195 | | double co[8], ct[8]; |
| 207 | double co[16], ct[16], cb[16], cz[16], fs[16], bsz[16]; |
| 196 | 208 | |
| 197 | 209 | for(int z=0;z<NZ;z++){ |
| 198 | | double ec=0,ek=0,nd=0,nx=0,nc=0,ms=0,mc=0,ps=0; |
| 210 | double ec=0,ek=0,eb=0,ez=0,bd=0,bs=0,nd=0,nx=0,nc=0,ms=0,mc=0,ps=0; |
| 199 | 211 | for(int s=0;s<NS;s++){ |
| 200 | 212 | double p,d,x,n,m,mm; |
| 201 | | RNG=seeds[s]; ec+=run(1,sizes[z],&p,&d,&x,&n,&m,&mm); nd+=d; nx+=x; nc+=n; ms+=m; mc+=mm; ps+=p; |
| 202 | | RNG=seeds[s]; ek+=run(0,sizes[z],&p,&d,&x,&n,&m,&mm); |
| 213 | RNG=seeds[s]; ec+=run(1,sizes[z],0,&p,&d,&x,&n,&m,&mm); nd+=d; nx+=x; nc+=n; ms+=m; mc+=mm; ps+=p; |
| 214 | RNG=seeds[s]; ek+=run(0,sizes[z],0,&p,&d,&x,&n,&m,&mm); |
| 215 | RNG=seeds[s]; eb+=run(1,sizes[z],1,&p,&d,&x,&n,&m,&mm); bd+=d; bs+=m; |
| 216 | RNG=seeds[s]; ez+=run(0,sizes[z],1,&p,&d,&x,&n,&m,&mm); |
| 203 | 217 | } |
| 204 | | ec/=NS;ek/=NS;nd/=NS;nx/=NS;nc/=NS;ms/=NS;mc/=NS;ps/=NS; |
| 218 | ec/=NS;ek/=NS;eb/=NS;ez/=NS;bd/=NS;bs/=NS;nd/=NS;nx/=NS;nc/=NS;ms/=NS;mc/=NS;ps/=NS; |
| 205 | 219 | start=ps; co[z]=ec; ct[z]=ek; |
| 206 | | printf(" %2d | %5.2f | %5.2f | %5.0f | %5.2f | %6.1f | %6.1f | %.0f\n", |
| 207 | | sizes[z],ec,ek,nc,ms,nd,nx,mc); |
| 220 | printf(" %2d | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f\n", |
| 221 | sizes[z],ec,ek,eb,ez,ms,bs); |
| 222 | cb[z]=eb; cz[z]=ez; fs[z]=ms; bsz[z]=bs; |
| 208 | 223 | if(nd>1.0 && nx>1.0) turned_over=1; |
| 209 | 224 | } |
| 210 | 225 | printf("\n start phi (= neutral expectation) %.2f [material must stay ~%.0f]\n\n",start,TOTALMAT); |
| … | … | @@ -216,34 +231,66 @@ int main(void) |
| 216 | 231 | if(ct[z]>start+0.5) ctrl_flat=0; |
| 217 | 232 | } |
| 218 | 233 | |
| 219 | | printf(" C5 compartments divided AND died (turnover) : %s\n", turned_over?"YES":"NO — test did not run"); |
| 220 | | printf(" C2 phi rose above neutral somewhere : %s\n", (co[0]>start+0.5||co[1]>start+0.5||co[2]>start+0.5||co[3]>start+0.5)?"YES":"NO"); |
| 221 | | printf(" C3 SIZE THRESHOLD reappeared (small yes/large no): small %d/2, large %d/2\n", small_wins, large_fails); |
| 222 | | printf(" C4 control (uptake blind to phi) stayed flat : %s\n\n", ctrl_flat?"YES":"NO — CONFOUNDED"); |
| 234 | /* ---- THE CONFOUND CHECK: propagule mode also SHRINKS realized compartment size, so a rescue |
| 235 | at matched DIVISION THRESHOLD may simply be smaller compartments by another route. Plot phi |
| 236 | against MEAN REALIZED SIZE for both modes: if they trace one curve, size is the variable and |
| 237 | variance adds nothing. If propagule sits above fission at matched size, variance is real. ---- */ |
| 238 | printf(" phi vs MEAN REALIZED SIZE (the confound check)\n"); |
| 239 | printf(" fission :"); |
| 240 | for(int z=0;z<NZ;z++) printf(" %.2f/%.1f", co[z], fs[z]); |
| 241 | printf("\n propagule:"); |
| 242 | for(int z=0;z<NZ;z++) printf(" %.2f/%.1f", cb[z], bsz[z]); |
| 243 | printf("\n (read as phi/size pairs)\n"); |
| 244 | { |
| 245 | double worst=1e9, sumd=0; int nd2=0; |
| 246 | for(int z=0;z<NZ;z++){ |
| 247 | double tsz=bsz[z]; if(tsz<=fs[0]||tsz>=fs[NZ-1]) continue; |
| 248 | int lo=-1; |
| 249 | for(int y=0;y+1<NZ;y++) if(fs[y]<=tsz && fs[y+1]>=tsz){ lo=y; break; } |
| 250 | if(lo<0) continue; |
| 251 | double t=(tsz-fs[lo])/(fs[lo+1]-fs[lo]); |
| 252 | double fis_interp=co[lo]+t*(co[lo+1]-co[lo]); |
| 253 | double d=cb[z]-fis_interp; |
| 254 | printf(" at size %.1f : propagule %.2f vs fission-interpolated %.2f (diff %+.2f)\n", tsz, cb[z], fis_interp, d); |
| 255 | sumd+=d; nd2++; if(d<worst) worst=d; |
| 256 | } |
| 257 | if(nd2) printf(" mean advantage of propagule at MATCHED size: %+.2f over %d points\n\n", sumd/nd2, nd2); |
| 258 | else printf(" (no overlapping sizes to compare)\n\n"); |
| 259 | } |
| 260 | |
| 261 | int fis_small=0, fis_large=0, prop_small=0, prop_large=0, prop_ctrl_flat=1; |
| 262 | for(int z=0;z<NZ;z++){ |
| 263 | if(sizes[z]<=8 && co[z]>start+0.5) fis_small++; |
| 264 | if(sizes[z]>=16 && co[z]>start+0.5) fis_large++; |
| 265 | if(sizes[z]<=8 && cb[z]>start+0.5) prop_small++; |
| 266 | if(sizes[z]>=16 && cb[z]>start+0.5) prop_large++; |
| 267 | if(cz[z]>start+0.5) prop_ctrl_flat=0; |
| 268 | } |
| 269 | printf(" C5 turnover : %s\n", turned_over?"YES":"NO — test did not run"); |
| 270 | printf(" FISSION crosses at small / large div size : %d/2 %d/2\n", fis_small, fis_large); |
| 271 | printf(" PROPAGULE crosses at small / large div size : %d/2 %d/2\n", prop_small, prop_large); |
| 272 | printf(" A3 CONTROL propagule + uptake blind to phi : %s\n\n", prop_ctrl_flat?"flat (good)":"ROSE — CONFOUNDED"); |
| 223 | 273 | |
| 224 | 274 | if(!turned_over) |
| 225 | | printf(" => THE TEST DID NOT RUN. Compartments did not divide and die, so no compartment-level\n" |
| 226 | | " reproduction existed to select on. Invalid experiment, not a null.\n"); |
| 227 | | else if(!ctrl_flat) |
| 228 | | printf(" => CONFOUNDED. The control rose too, so division-plus-assortment alone produces the\n" |
| 229 | | " effect and the growth->catalysis coupling is not doing the work.\n"); |
| 230 | | else if(small_wins==2 && large_fails==2) |
| 231 | | printf(" => THE CORRECTOR EMERGED, THRESHOLD AND ALL. Compartment-level differential reproduction\n" |
| 232 | | " arose with no group-selection step anywhere: compartments divided because they grew,\n" |
| 233 | | " grew because they took up material, took up material because their contents catalyzed.\n" |
| 234 | | " And it reproduces the DECREE'S SIGNATURE -- crossing at small division sizes, failing\n" |
| 235 | | " at large -- which is what makes this the mechanism behind ribozyme.c's rule rather\n" |
| 236 | | " than merely another way to get a rise.\n"); |
| 237 | | else if(small_wins>0) |
| 238 | | printf(" => PARTIAL. phi rises with the coupling and the control stays flat, so growth-coupling is\n" |
| 239 | | " doing real work -- but the size threshold does not cleanly match the decreed version\n" |
| 240 | | " (small %d/2, large %d/2). Report the shape as-is; do not claim the corrector.\n", |
| 241 | | small_wins,large_fails); |
| 275 | printf(" => THE TEST DID NOT RUN.\n"); |
| 276 | else if(!prop_ctrl_flat) |
| 277 | printf(" => CONFOUNDED. The phi-blind control rises under propagule reproduction, so the change is\n" |
| 278 | " a demographic artifact of the reproduction mode, not selection. Claim nothing.\n"); |
| 279 | else if(prop_large>fis_large) |
| 280 | printf(" => The bottleneck rescues large DIVISION THRESHOLDS (fission %d, propagule %d of the\n" |
| 281 | " large sizes). But propagule mode ALSO shrinks realized compartment size, so read the\n" |
| 282 | " matched-size comparison above before concluding anything: if the advantage at matched\n" |
| 283 | " size is ~0, size is the operative variable and the bottleneck merely produces smaller\n" |
| 284 | " compartments by another route. Only a clear positive there licenses the claim that\n" |
| 285 | " ASSORTMENT VARIANCE is what does the work.\n", fis_large, prop_large); |
| 286 | else if(prop_large==fis_large && prop_small>=fis_small) |
| 287 | printf(" => NO RESCUE. A single-unit bottleneck does NOT save large compartments (%d/2 vs %d/2),\n" |
| 288 | " so the size threshold is NOT about assortment variance. The remaining candidate is\n" |
| 289 | " within-compartment competition TIME: a large compartment gives parasites more\n" |
| 290 | " generations to take over before it ever divides, and no amount of offspring variance\n" |
| 291 | " fixes that. Informative negative -- it rules out the relatedness reading.\n", |
| 292 | fis_large, prop_large); |
| 242 | 293 | else |
| 243 | | printf(" => HONEST NULL, with turnover confirmed. Coupling growth to catalysis does NOT generate\n" |
| 244 | | " usable compartment-level selection here: the within-compartment tragedy outruns the\n" |
| 245 | | " between-compartment advantage at every division size. Ganti's coupling is necessary\n" |
| 246 | | " but not sufficient, and the first unit of selection may have had to be supplied by\n" |
| 247 | | " the world rather than built by the chemistry.\n"); |
| 294 | printf(" => Mixed. Report the numbers as-is.\n"); |
| 248 | 295 | return 0; |
| 249 | 296 | } |