| … | … | @@ -7,6 +7,27 @@ |
| 7 | 7 | * 0 PARASITES, which is death, not collapse-to-parasites. Units now persist, production adds, and a |
| 8 | 8 | * per-unit death rate removes. |
| 9 | 9 | * |
| 10 | * SECOND ATTEMPT, ALSO VOID — and the diagnosis was already on record before it was built. |
| 11 | * K1 was fixed (growth now tracks TOTAL SIZE, so a parasite-filled compartment grows as well as a |
| 12 | * catalyst-filled one, and the knockout receives MORE material than FULL) and the metrics were |
| 13 | * separated (integrity = function >= 2; template retention reported on its own). A T0 guard was |
| 14 | * added: do the arms differ at all? |
| 15 | * |
| 16 | * They do not. FULL 0.940 / K1 0.954 / K2 0.944 / K3 0.952, function 2.45-2.52 throughout. The |
| 17 | * reason is in the template column: 0.007-0.012 IN EVERY ARM. Templates are absent, so there is no |
| 18 | * third carrier and the two couplings that involve one cannot possibly matter — K2 has nothing to |
| 19 | * read, K3 nothing whose fidelity counts. The system persists on boundary + metabolism alone. |
| 20 | * |
| 21 | * WHY TEMPLATES COLLAPSE, AND IT IS A REPEAT: func_of() counts only catalysts, so selection on |
| 22 | * function selects AGAINST templates — they are pure cost. That is exactly genome.c's finding |
| 23 | * ("nothing is expensive enough to be worth remembering; payoff is scored on the present |
| 24 | * configuration so rediscovery always beats storage"), identified hours earlier and then rebuilt. |
| 25 | * |
| 26 | * THE FIX IS THEREFORE KNOWN AND NOT A GUESS: the payoff must reward something that is EXPENSIVE TO |
| 27 | * REDISCOVER, so that holding a template beats re-finding a catalyst type. Until the fitness function |
| 28 | * has that property, no three-carrier model can show the third carrier doing anything. |
| 29 | * |
| 30 | * ---- first attempt's fault, kept for the record ---- |
| 10 | 31 | * FATAL, AND WHY THE RESULT IS VOID: after that fix all four arms land within noise of each other |
| 11 | 32 | * (intact 0.052 / 0.055 / 0.037 / 0.049; function 2.47 / 2.46 / 2.45 / 2.52). That reads as "no |
| 12 | 33 | * coupling is load-bearing", but at least one arm is not a knockout at all: |
| … | … | @@ -96,6 +117,7 @@ static Unit cell[NCOMP][CAP], nxt[NCOMP][CAP]; |
| 96 | 117 | static int sz[NCOMP], nsz[NCOMP]; |
| 97 | 118 | static double mat[NCOMP], nmat[NCOMP]; |
| 98 | 119 | static int ncomp; |
| 120 | static double TFRAC; |
| 99 | 121 | |
| 100 | 122 | static void counts(int c,int *nc,int *nt,int *np){ |
| 101 | 123 | *nc=*nt=*np=0; |
| … | … | @@ -128,7 +150,12 @@ static void run(int ko,double *alive,double *funcavg,double *parfrac) |
| 128 | 150 | for(int c=0;c<ncomp;c++){ |
| 129 | 151 | int nc,nt,np; counts(c,&nc,&nt,&np); |
| 130 | 152 | /* coupling 1: metabolism -> boundary. K1 decouples it. */ |
| 131 | | mat[c] += (ko==1)? GROW*CAP*0.5 : GROW*nc; |
| 153 | /* K1 FIXED. The old ablation used GROW*CAP*0.5 = 4.4, identical by construction to the |
| 154 | coupled GROW*nc at nc~8 — not a knockout at all. Now growth tracks TOTAL SIZE, so a |
| 155 | parasite-filled compartment grows exactly as well as a catalyst-filled one. That is the |
| 156 | real decoupling, and it gives the knockout the BENEFIT OF THE DOUBT: sz >= nc always, so |
| 157 | K1 receives MORE material than FULL. If it still loses, the coupling is load-bearing. */ |
| 158 | mat[c] += (ko==1)? GROW*sz[c] : GROW*nc; |
| 132 | 159 | /* coupling 3: catalyst -> template fidelity. K3 decouples it. */ |
| 133 | 160 | double f = (ko==3)? FLO : ((nc>0)? FHI : FLO); |
| 134 | 161 | /* replication within the compartment; parasites are faster */ |
| … | … | @@ -169,13 +196,18 @@ static void run(int ko,double *alive,double *funcavg,double *parfrac) |
| 169 | 196 | for(int c=0;c<ncomp;c++){ sz[c]=nsz[c]; mat[c]=nmat[c]; for(int k=0;k<sz[c];k++) cell[c][k]=nxt[c][k]; } |
| 170 | 197 | } |
| 171 | 198 | } |
| 172 | | int ok=0,tp=0,tu=0; double fs=0; |
| 199 | /* METRICS SEPARATED. "intact" previously required catalysts AND templates, which conflated |
| 200 | template retention with system integrity. Now: integrity = the compartment still does work |
| 201 | (function >= 2 of NTYPE); template retention is reported on its own. */ |
| 202 | int ok=0,tp=0,tt=0,tu=0; double fs=0; |
| 173 | 203 | for(int c=0;c<ncomp;c++){ |
| 174 | 204 | int nc,nt,np; counts(c,&nc,&nt,&np); |
| 175 | | if(nc>0 && nt>0) ok++; |
| 176 | | fs += func_of(c); tp+=np; tu+=sz[c]; |
| 205 | if(func_of(c)>=2) ok++; |
| 206 | fs += func_of(c); tp+=np; tt+=nt; tu+=sz[c]; |
| 177 | 207 | } |
| 178 | | *alive=(double)ok/ncomp; *funcavg=fs/ncomp; *parfrac= tu? (double)tp/tu : 0; |
| 208 | *alive=(double)ok/ncomp; *funcavg=fs/ncomp; |
| 209 | *parfrac= tu? (double)tp/tu : 0; |
| 210 | TFRAC = tu? (double)tt/tu : 0; |
| 179 | 211 | } |
| 180 | 212 | |
| 181 | 213 | int main(void) |
| … | … | @@ -188,26 +220,31 @@ int main(void) |
| 188 | 220 | printf(" three couplings, none defectable: metabolism->boundary, template->function,\n"); |
| 189 | 221 | printf(" catalyst->template fidelity. Seeded COMPLETE; parasites are NOT seeded, they arise by\n"); |
| 190 | 222 | printf(" mutation, replicate %.0fx faster and contribute nothing. %d compartments x %d, %d gens.\n\n",1+BETA,NCOMP,CAP,GEN); |
| 191 | | printf(" arm | compartments intact | mean function (max %d) | parasites\n",NTYPE); |
| 192 | | printf(" ------------------------+---------------------+------------------------+----------\n"); |
| 223 | printf(" arm | working (func>=2) | mean function (max %d) | templates | parasites\n",NTYPE); |
| 224 | printf(" ------------------------+-------------------+------------------------+-----------+----------\n"); |
| 193 | 225 | const char *nm[4]={"FULL (all three) ","K1 boundary decoupled ","K2 reading off ","K3 replicase off "}; |
| 194 | | double A[4],F[4],P[4]; |
| 226 | double A[4],F[4],P[4],T[4]; |
| 195 | 227 | for(int k=0;k<4;k++){ |
| 196 | | double a=0,f=0,p=0; |
| 197 | | for(int s=0;s<NS;s++){ double x,y,z; RNG=seeds[s]; run(k,&x,&y,&z); a+=x; f+=y; p+=z; } |
| 198 | | A[k]=a/NS; F[k]=f/NS; P[k]=p/NS; |
| 199 | | printf(" %s | %.3f | %.2f | %.3f\n",nm[k],A[k],F[k],P[k]); |
| 228 | double a=0,f=0,p=0,tf=0; |
| 229 | for(int s=0;s<NS;s++){ double x,y,z; RNG=seeds[s]; run(k,&x,&y,&z); a+=x; f+=y; p+=z; tf+=TFRAC; } |
| 230 | A[k]=a/NS; F[k]=f/NS; P[k]=p/NS; T[k]=tf/NS; |
| 231 | printf(" %s | %.3f | %.2f | %.3f | %.3f\n",nm[k],A[k],F[k],T[k],P[k]); |
| 200 | 232 | } |
| 201 | 233 | printf("\n"); |
| 202 | 234 | int t3 = P[0]>0.01 || P[1]>0.01 || P[2]>0.01 || P[3]>0.01; |
| 203 | 235 | int t1 = A[0]>0.5; |
| 204 | 236 | int ko_collapse=0; for(int k=1;k<4;k++) if(A[k] < A[0]-0.15) ko_collapse++; |
| 237 | int arms_differ=0; for(int k=1;k<4;k++) if(fabs(A[k]-A[0])>0.03||fabs(F[k]-F[0])>0.10) arms_differ=1; |
| 205 | 238 | printf(" T3 parasites arose and could win : %s (max frac %.3f)\n", t3?"YES":"NO — nothing was resisted", |
| 206 | 239 | fmax(fmax(P[0],P[1]),fmax(P[2],P[3]))); |
| 207 | 240 | printf(" T1 FULL persists : %s (%.3f intact)\n", t1?"YES":"NO",A[0]); |
| 208 | | printf(" T2 knockouts collapse : %d of 3\n\n",ko_collapse); |
| 241 | printf(" T2 knockouts collapse : %d of 3\n",ko_collapse); |
| 242 | printf(" T0 arms actually differ at all : %s\n\n", arms_differ?"YES":"NO — the ablations are not ablating, result void"); |
| 209 | 243 | |
| 210 | | if(!t3) |
| 244 | if(!arms_differ) |
| 245 | printf(" => VOID. The arms are indistinguishable, so at least one ablation is not ablating.\n" |
| 246 | " Nothing here bears on stability. Fix the knockouts before reading anything.\n"); |
| 247 | else if(!t3) |
| 211 | 248 | printf(" => TEST DID NOT RUN. Parasites never appeared, so nothing was being resisted and\n" |
| 212 | 249 | " persistence means nothing. Invalid, not a result.\n"); |
| 213 | 250 | else if(t1 && ko_collapse==3) |