| … | … | @@ -211,63 +211,93 @@ int main(void) |
| 211 | 211 | printf(" THE TENSION: Test A found assortment VARIANCE purges parasites (+1.14 at matched size).\n"); |
| 212 | 212 | printf(" But a RAF is a property of the SET, so variance should DESTROY closure. Which wins?\n\n"); |
| 213 | 213 | |
| 214 | | printf(" cat.dens | divsz | rand base | FISSION raf | fis ctrl | PROPAGULE raf | prop ctrl | mean sz\n"); |
| 215 | | printf(" ---------+-------+-----------+-------------+----------+---------------+-----------+--------\n"); |
| 214 | /* ---- MATCHED REALIZED SIZE. Test B's reversal was established at matched division |
| 215 | THRESHOLD, but propagule mode also shrinks realized compartment size, and in this model |
| 216 | bigger compartments hold bigger RAFs. So fission > propagule may be a pure size artifact |
| 217 | with no closure destruction at all. Sweep division size finely at one catalysis density, |
| 218 | record each arm's OWN realized size, and interpolate fission onto propagule's sizes. ---- */ |
| 219 | double dens = 0.10; |
| 220 | int sizes[]={4,6,8,10,12,16,20,24}; |
| 221 | int NZ=(int)(sizeof(sizes)/sizeof(sizes[0])); |
| 222 | double fr[16], fsz[16], pr[16], psz[16], cf[16], cp[16], base[16]; |
| 223 | int any_raf=0, ctrl_flat=1; |
| 216 | 224 | |
| 217 | | double dens[]={0.04,0.08,0.12}; |
| 218 | | int sizes[]={8,16}; |
| 219 | | int any_raf=0, coupled_wins=0, ctrl_flat=1, ncmp=0, prop_better=0, fis_better=0; |
| 225 | printf(" catalysis density %.2f, %d seeds\n\n", dens, NS); |
| 226 | printf(" divsz | rand base | FISSION raf / size | PROPAGULE raf / size | fis ctrl | prop ctrl\n"); |
| 227 | printf(" ------+-----------+--------------------+----------------------+----------+----------\n"); |
| 220 | 228 | |
| 221 | | for(int d=0;d<3;d++){ |
| 222 | | for(int z=0;z<2;z++){ |
| 223 | | double bf=0,bc=0,pf=0,pc=0,ms=0,base=0,mc=0,nd=0,nc=0; |
| 224 | | for(int s=0;s<NS;s++){ |
| 225 | | double re,n,m,dv,mm; |
| 226 | | RNG=seeds[s]; build_net(dens[d]); |
| 227 | | base+=random_baseline(sizes[z]/2>2?sizes[z]/2:2, 200); |
| 228 | | RNG=seeds[s]; build_net(dens[d]); bf+=run(1,sizes[z],0,&re,&n,&m,&dv,&mm); ms+=m; mc+=mm; nd+=dv; nc+=n; |
| 229 | | RNG=seeds[s]; build_net(dens[d]); bc+=run(0,sizes[z],0,&re,&n,&m,&dv,&mm); |
| 230 | | RNG=seeds[s]; build_net(dens[d]); pf+=run(1,sizes[z],1,&re,&n,&m,&dv,&mm); |
| 231 | | RNG=seeds[s]; build_net(dens[d]); pc+=run(0,sizes[z],1,&re,&n,&m,&dv,&mm); |
| 232 | | } |
| 233 | | bf/=NS;bc/=NS;pf/=NS;pc/=NS;ms/=NS;base/=NS;mc/=NS;nd/=NS;nc/=NS; |
| 234 | | printf(" %.2f | %2d | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f\n", |
| 235 | | dens[d],sizes[z],base,bf,bc,pf,pc,ms); |
| 236 | | if(bf>0.2||pf>0.2) any_raf=1; |
| 237 | | ncmp++; |
| 238 | | if(bf>base+0.3||pf>base+0.3) coupled_wins++; |
| 239 | | if(bc>base+0.3||pc>base+0.3) ctrl_flat=0; |
| 240 | | if(pf>bf+0.2) prop_better++; |
| 241 | | if(bf>pf+0.2) fis_better++; |
| 229 | for(int z=0;z<NZ;z++){ |
| 230 | double bf=0,bs=0,pf=0,ps=0,c1=0,c2=0,bb=0; |
| 231 | for(int s=0;s<NS;s++){ |
| 232 | double re,n,m,dv,mm; |
| 233 | RNG=seeds[s]; build_net(dens); bb+=random_baseline(sizes[z]/2>2?sizes[z]/2:2,200); |
| 234 | RNG=seeds[s]; build_net(dens); bf+=run(1,sizes[z],0,&re,&n,&m,&dv,&mm); bs+=m; |
| 235 | RNG=seeds[s]; build_net(dens); pf+=run(1,sizes[z],1,&re,&n,&m,&dv,&mm); ps+=m; |
| 236 | RNG=seeds[s]; build_net(dens); c1+=run(0,sizes[z],0,&re,&n,&m,&dv,&mm); |
| 237 | RNG=seeds[s]; build_net(dens); c2+=run(0,sizes[z],1,&re,&n,&m,&dv,&mm); |
| 242 | 238 | } |
| 239 | fr[z]=bf/NS; fsz[z]=bs/NS; pr[z]=pf/NS; psz[z]=ps/NS; cf[z]=c1/NS; cp[z]=c2/NS; base[z]=bb/NS; |
| 240 | printf(" %2d | %5.2f | %5.2f / %5.2f | %5.2f / %5.2f | %5.2f | %5.2f\n", |
| 241 | sizes[z],base[z],fr[z],fsz[z],pr[z],psz[z],cf[z],cp[z]); |
| 242 | if(fr[z]>0.2||pr[z]>0.2) any_raf=1; |
| 243 | if(cf[z]>base[z]+0.3||cp[z]>base[z]+0.3) ctrl_flat=0; |
| 244 | } |
| 245 | |
| 246 | /* fission's realized size is NON-MONOTONIC in division size (it rises then falls as the arm |
| 247 | collapses at large divsz), so the fission points must be SORTED BY SIZE before interpolating. |
| 248 | The first version bounds-checked against fsz[last] and silently dropped almost every point. */ |
| 249 | printf("\n Does RAF track SIZE regardless of reproduction mode? (per-cell, same divsz)\n"); |
| 250 | int tracks=0; |
| 251 | for(int z=0;z<NZ;z++){ |
| 252 | int bigger_f = fsz[z]>psz[z]; |
| 253 | int rafbig_f = fr[z]>pr[z]; |
| 254 | if(bigger_f==rafbig_f) tracks++; |
| 255 | printf(" divsz %2d : larger arm = %s, larger RAF = %s %s\n", sizes[z], |
| 256 | bigger_f?"fission ":"propagule", rafbig_f?"fission ":"propagule", |
| 257 | (bigger_f==rafbig_f)?"tracks":"DIVERGES"); |
| 243 | 258 | } |
| 244 | | printf("\n"); |
| 245 | | printf(" T1 RAFs formed inside compartments at all : %s\n", any_raf?"YES":"NO — test did not run"); |
| 246 | | printf(" T2 coupled beats the random-subset baseline : %d/%d cells\n", coupled_wins,ncmp); |
| 247 | | printf(" T3 CONTROL (uptake blind to closure) flat : %s\n", ctrl_flat?"YES":"NO — CONFOUNDED"); |
| 248 | | printf(" T4 REVERSAL: propagule better %d / fission better %d\n\n", prop_better, fis_better); |
| 259 | printf(" RAF tracks realized size in %d/%d cells\n",tracks,NZ); |
| 260 | |
| 261 | printf("\n MATCHED REALIZED SIZE — propagule vs fission interpolated (fission sorted by size):\n"); |
| 262 | int ord[16]; for(int z=0;z<NZ;z++) ord[z]=z; |
| 263 | for(int a=1;a<NZ;a++){ int k=ord[a],b=a-1; while(b>=0&&fsz[ord[b]]>fsz[k]){ ord[b+1]=ord[b]; b--; } ord[b+1]=k; } |
| 264 | double sumd=0; int nd=0; |
| 265 | for(int z=0;z<NZ;z++){ |
| 266 | double t=psz[z]; |
| 267 | if(t<=fsz[ord[0]]||t>=fsz[ord[NZ-1]]) continue; |
| 268 | int lo=-1; for(int y=0;y+1<NZ;y++) if(fsz[ord[y]]<=t&&fsz[ord[y+1]]>=t){ lo=y; break; } |
| 269 | if(lo<0) continue; |
| 270 | double d0=fsz[ord[lo]], d1=fsz[ord[lo+1]]; |
| 271 | double w=(d1>d0)?(t-d0)/(d1-d0):0.0; |
| 272 | double fi=fr[ord[lo]]+w*(fr[ord[lo+1]]-fr[ord[lo]]); |
| 273 | double d=pr[z]-fi; |
| 274 | printf(" size %5.2f : propagule %5.2f vs fission-interp %5.2f diff %+.2f\n", t, pr[z], fi, d); |
| 275 | sumd+=d; nd++; |
| 276 | } |
| 277 | double mean_adv = nd? sumd/nd : 0.0/0.0; |
| 278 | printf(" mean propagule advantage at MATCHED size: %+.2f over %d points\n\n", mean_adv, nd); |
| 279 | |
| 280 | printf(" T1 RAFs formed : %s\n", any_raf?"YES":"NO — test did not run"); |
| 281 | printf(" T3 CONTROL blind to closure stayed flat : %s\n", ctrl_flat?"YES":"NO — CONFOUNDED"); |
| 282 | printf(" T4 at matched DIVISION THRESHOLD, fission won in the earlier run.\n"); |
| 283 | printf(" T4' at matched REALIZED SIZE, propagule advantage = %+.2f\n\n", mean_adv); |
| 249 | 284 | |
| 250 | | if(!any_raf) |
| 251 | | printf(" => THE TEST DID NOT RUN. No compartment ever closed a RAF, so there was nothing to\n" |
| 252 | | " select on. Invalid experiment, not a null. Raise catalysis density or compartment size.\n"); |
| 253 | | else if(!ctrl_flat) |
| 254 | | printf(" => CONFOUNDED. The closure-blind control also beats baseline, so the rise is not\n" |
| 255 | | " selection on collective function.\n"); |
| 256 | | else if(coupled_wins==0) |
| 257 | | printf(" => HONEST NULL. RAFs form, but compartment selection does NOT raise closure above the\n" |
| 258 | | " random baseline. The ladder does NOT chain: chemoton's success depended on catalytic\n" |
| 259 | | " quality being a PER-UNIT property, and it does not survive the move to collective\n" |
| 260 | | " closure — assortment destroys the very thing selection would act on.\n"); |
| 261 | | else if(fis_better>prop_better) |
| 262 | | printf(" => CHAINS, AND TEST A REVERSES. Compartment selection survives collective quality\n" |
| 263 | | " (%d/%d cells beat baseline), but FISSION now beats the propagule bottleneck\n" |
| 264 | | " (%d vs %d) — the opposite of Test A. A single-unit bottleneck cannot carry a\n" |
| 265 | | " closure, so the variance that purges parasites also destroys collective function.\n" |
| 266 | | " The optimal assortment is a TRADE-OFF, not a maximum.\n", coupled_wins,ncmp,fis_better,prop_better); |
| 285 | if(!any_raf) printf(" => TEST DID NOT RUN.\n"); |
| 286 | else if(!ctrl_flat) printf(" => CONFOUNDED by the control.\n"); |
| 287 | else if(mean_adv < -0.2) |
| 288 | printf(" => THE REVERSAL SURVIVES. Even at matched realized size the propagule bottleneck is\n" |
| 289 | " WORSE for collective closure (%+.2f). So it is not a size artifact: a single-unit\n" |
| 290 | " bottleneck genuinely cannot carry a RAF, and Test A's finding does NOT generalise.\n" |
| 291 | " Optimal assortment is a trade-off set by whether quality is per-unit or collective.\n", mean_adv); |
| 292 | else if(mean_adv > 0.2) |
| 293 | printf(" => THE REVERSAL WAS AN ARTIFACT, AND IT INVERTS. At matched realized size the propagule\n" |
| 294 | " bottleneck is BETTER (%+.2f), same direction as Test A. The earlier fission win was\n" |
| 295 | " entirely propagule mode shrinking compartments, and in this model smaller compartments\n" |
| 296 | " hold smaller RAFs. RETRACT the trade-off claim.\n", mean_adv); |
| 267 | 297 | else |
| 268 | | printf(" => CHAINS, AND TEST A GENERALISES. Compartment selection survives collective quality\n" |
| 269 | | " (%d/%d beat baseline) and the propagule bottleneck still wins (%d vs %d), so RAF\n" |
| 270 | | " closure is more robust to assortment than predicted. Report as-is.\n", |
| 271 | | coupled_wins,ncmp,prop_better,fis_better); |
| 298 | printf(" => THE REVERSAL WAS A SIZE ARTIFACT. At matched realized size the two modes are\n" |
| 299 | " indistinguishable (%+.2f). Fission only looked better because propagule shrinks\n" |
| 300 | " compartments and smaller compartments hold smaller RAFs. There is no evidence here\n" |
| 301 | " that a bottleneck destroys closure — RETRACT the trade-off claim as stated.\n", mean_adv); |
| 272 | 302 | return 0; |
| 273 | 303 | } |