| … | … | @@ -0,0 +1,417 @@ |
| 1 | /* fluctuate.c — does MEMORY pay when the world CHANGES? Scored on FUNCTION, against a SCRAMBLED |
| 2 | * control, with the reading knockout reduced to ONE variable. |
| 3 | * |
| 4 | * WHERE THIS COMES FROM. threecarrier.c's fourth attempt reported that under a fluctuating target |
| 5 | * set, turning reading ON raised the working fraction 0.294 -> 0.478 and function 1.27 -> 1.47. |
| 6 | * That number is NOT usable as it stands, for two reasons found by reading its source: |
| 7 | * |
| 8 | * (1) WRONG METRIC. Its pre-registered M1/M2 scored TEMPLATE ABUNDANCE. Reading converts a template |
| 9 | * replication event into a catalyst, so the reading-OFF arm holds MORE templates (0.023 vs |
| 10 | * 0.012) precisely because they are useless there. Template count measures templates NOT BEING |
| 11 | * USED. genome.md records this identical mistake; it has now been made three times. |
| 12 | * |
| 13 | * (2) THE KNOCKOUT MOVED TWO VARIABLES. threecarrier.c:238-239 reads |
| 14 | * if(ko!=2 && nc>0 && urand()<0.5){ ch.role=CAT; ch.type=p.type; } |
| 15 | * else if(urand()>f) ch.type=rint_(NTYPE); // copy error |
| 16 | * An if/else. With reading ON a read child SKIPS the copy-error branch; with reading OFF every |
| 17 | * template replication takes it. So "reading off" also raises template mutation load. That is |
| 18 | * the one-knob-two-variables fault the 2026-07-31 post-mortem counted four separate times. |
| 19 | * |
| 20 | * WHAT THIS FILE CHANGES, AND NOTHING ELSE. Chemistry, sizes, rates, seeding and between-compartment |
| 21 | * selection are IDENTICAL to threecarrier.c so the numbers stay comparable: |
| 22 | * - copy error now applies to EVERY template replication, independent of reading. Reading is a |
| 23 | * separate, subsequent event. The knockout is one variable. |
| 24 | * - scored on FUNCTION and WORKING FRACTION, time-averaged over the second half of the run |
| 25 | * (many switch cycles, not one phase-dependent snapshot). Template fraction is still reported, |
| 26 | * and is explicitly NOT a criterion. |
| 27 | * - 24 seeds, not 5, with the paired per-seed difference and its spread reported. |
| 28 | * |
| 29 | * THE CONTROL, WHICH IS THE POINT. genome.c ran this same question and looked positive until the |
| 30 | * SCRAMBLED control inverted it: reading that produces a catalyst of a RANDOM type BEAT faithful |
| 31 | * reading at every mutation rate, because the gain was the mechanism turning non-folders into |
| 32 | * folders, and the information contributed nothing. threecarrier.c never ran that control. Comparing |
| 33 | * read-ON against read-OFF cannot separate the information from the conversion, because reading also |
| 34 | * adds a catalyst, which raises nc, which raises both growth (GROW*nc) and fidelity (nc>0 => FHI). |
| 35 | * So the headline comparison here is FAITHFUL vs SCRAMBLED, not ON vs OFF. |
| 36 | * |
| 37 | * genome.md also named the missing ingredient and designed the fix deliberately left unrun: "a |
| 38 | * genome is only worth having when a SPECIFIC configuration beats a random one". threecarrier.c |
| 39 | * supplied that (NTARG specific types out of NTYPE) but never ran the control it was designed for. |
| 40 | * This does. |
| 41 | * |
| 42 | * AND THE PREDICTION THAT MAKES A NULL INFORMATIVE. Under a FRESH random redraw, a stored type is a |
| 43 | * target again with probability NTARG/NTYPE = 0.25 -- exactly the odds a scrambled read gets by |
| 44 | * dice. So a fresh-redraw world offers memory no edge in principle, and worse: right after a switch |
| 45 | * the template pool is enriched for the OLD targets, which is worse than random. If memory pays |
| 46 | * anywhere it is in a world that REPEATS. So the fluctuating condition is run twice: |
| 47 | * FRESH -- targets redrawn at random every switch (threecarrier.c's condition) |
| 48 | * RECUR -- cycled among NENV fixed target sets, so a type not needed now IS needed again |
| 49 | * Both are pre-registered before running, so a null on FRESH plus a positive on RECUR is a stated |
| 50 | * prediction confirmed, not a story told afterwards. |
| 51 | * |
| 52 | * SUPPLIED vs MUST EMERGE: |
| 53 | * SUPPLIED: the three carriers seeded complete and correct, the reading physics, between-compartment |
| 54 | * selection on current function, and the environment's switching schedule. |
| 55 | * MUST EMERGE: any advantage of holding information. NOTHING rewards templates directly -- they |
| 56 | * fold nothing and cost a slot. Parasites are not seeded; they arise by mutation and replicate |
| 57 | * BETA faster, so the tragedy is live in every arm. |
| 58 | * |
| 59 | * PRE-REGISTERED: |
| 60 | * P1 THE PRIMARY TEST: under fluctuation, FAITHFUL reading beats SCRAMBLED reading on function. |
| 61 | * One variable: the type the read catalyst gets. If this fails, the information is doing |
| 62 | * nothing and any ON-vs-OFF gain is the conversion, exactly as in genome.c. |
| 63 | * P2 reading of any kind beats no reading. REPORTED BUT CONFOUNDED by construction (conversion + |
| 64 | * information + the nc it feeds). It is not evidence for memory and is not read as such. |
| 65 | * P3 fluctuation actually costs function relative to static. If it does not, nothing was survived. |
| 66 | * P4 THE STATED ALTERNATIVE: if P1 is null under FRESH but holds under RECUR, then memory pays only |
| 67 | * when the world repeats itself -- a condition on the ENVIRONMENT, not on the chemistry. |
| 68 | * |
| 69 | * TESTS OF THE TEST (any failure voids the arm it belongs to; a void result is reported as void): |
| 70 | * G1 reads actually happen -- nonzero in every reading arm, exactly zero in every OFF arm. |
| 71 | * G2 templates actually exist. If the template fraction is ~0 there is no third carrier and nothing |
| 72 | * was tested. This is what voided threecarrier.c's second and third attempts. |
| 73 | * G3 the environment actually changes -- switches occur and consecutive target sets differ. |
| 74 | * G4 the arms differ at all. |
| 75 | * |
| 76 | * Do not tune to force a positive. A null with G1-G4 passing is a real result: it says memory cannot |
| 77 | * pay under instantaneous selection even when the world moves, which is the fifth 1->2 constraint |
| 78 | * stated more strongly than the post-mortem could state it. |
| 79 | * |
| 80 | * build: cc -O2 -Wall -Wextra -std=c11 -o fluctuate fluctuate.c -lm |
| 81 | */ |
| 82 | #include <math.h> |
| 83 | #include <stdio.h> |
| 84 | #include <string.h> |
| 85 | |
| 86 | #define NCOMP 600 |
| 87 | #define CAP 16 |
| 88 | #define GEN 400 |
| 89 | #define BURN 200 /* measurement window is generations BURN..GEN-1 */ |
| 90 | #define NTYPE 16 |
| 91 | #define NTARG 4 |
| 92 | #define NENV 3 /* RECUR: this many fixed target sets, cycled */ |
| 93 | #define SWEVERY 15 |
| 94 | #define BETA 2.0 /* parasite replication advantage */ |
| 95 | #define MUT 0.02 |
| 96 | #define FLO 0.85 /* template copy fidelity with no catalyst present */ |
| 97 | #define FHI 0.995 /* ... with one (the replicase coupling) */ |
| 98 | #define GROW 0.55 |
| 99 | #define DEATH 0.15 |
| 100 | #define PREAD 0.5 /* per-replication chance a template is read */ |
| 101 | #define NSEED 24 |
| 102 | |
| 103 | enum { CAT=0, TEM=1, PAR=2 }; |
| 104 | enum { ENV_STATIC=0, ENV_FRESH=1, ENV_RECUR=2 }; |
| 105 | enum { READ_OFF=0, READ_FAITHFUL=1, READ_SCRAMBLED=2 }; |
| 106 | |
| 107 | static unsigned long long RNG; |
| 108 | static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; } |
| 109 | static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); } |
| 110 | static int rint_(int n){ return (int)(xs()%(unsigned)n); } |
| 111 | |
| 112 | typedef struct { unsigned char role, type; } Unit; |
| 113 | static Unit cell[NCOMP][CAP], nxt[NCOMP][CAP]; |
| 114 | static int sz[NCOMP], nsz[NCOMP]; |
| 115 | static double mat[NCOMP], nmat[NCOMP]; |
| 116 | |
| 117 | static int TARGET[NTYPE]; |
| 118 | static int ENVSET[NENV][NTYPE]; |
| 119 | |
| 120 | typedef struct { |
| 121 | double func, work, tfrac, parfrac; /* time-averaged over the measurement window */ |
| 122 | double early, late; /* function just after / just before a switch */ |
| 123 | double reads; /* read events per compartment per generation */ |
| 124 | double redund, gapfill; /* fraction of reads that were redundant / filled a gap */ |
| 125 | double switches, overlap; /* did the environment actually change? */ |
| 126 | } Res; |
| 127 | |
| 128 | static void counts(int c,int *nc,int *nt,int *np){ |
| 129 | *nc=*nt=*np=0; |
| 130 | for(int k=0;k<sz[c];k++){ |
| 131 | if(cell[c][k].role==CAT) (*nc)++; |
| 132 | else if(cell[c][k].role==TEM) (*nt)++; |
| 133 | else (*np)++; |
| 134 | } |
| 135 | } |
| 136 | /* function = how many of the SPECIFIC target types are present among catalysts. Identical to |
| 137 | threecarrier.c. Nothing rewards templates; they fold nothing and still cost a slot. */ |
| 138 | static int func_of(int c){ |
| 139 | int seen[NTYPE]; memset(seen,0,sizeof seen); |
| 140 | for(int k=0;k<sz[c];k++) if(cell[c][k].role==CAT) seen[cell[c][k].type]=1; |
| 141 | int f=0; for(int t=0;t<NTYPE;t++) if(seen[t]&&TARGET[t]) f++; |
| 142 | return f; |
| 143 | } |
| 144 | static void drawset(int *set){ |
| 145 | for(int t=0;t<NTYPE;t++) set[t]=0; |
| 146 | for(int got=0;got<NTARG;){ int t=rint_(NTYPE); if(!set[t]){ set[t]=1; got++; } } |
| 147 | } |
| 148 | static int overlap_of(const int *a,const int *b){ |
| 149 | int o=0; for(int t=0;t<NTYPE;t++) if(a[t]&&b[t]) o++; return o; |
| 150 | } |
| 151 | |
| 152 | static void run(int envmode,int readmode,Res *R) |
| 153 | { |
| 154 | int prev[NTYPE]; int envi=0; |
| 155 | double nsw=0, novl=0, reads=0, redund=0, gapfill=0; |
| 156 | double fsum=0, wsum=0, tsum=0, psum=0; long nmeas=0; |
| 157 | double phase_f[SWEVERY]; long phase_n[SWEVERY]; |
| 158 | memset(phase_f,0,sizeof phase_f); memset(phase_n,0,sizeof phase_n); |
| 159 | |
| 160 | if(envmode==ENV_RECUR){ |
| 161 | for(int e=0;e<NENV;e++) drawset(ENVSET[e]); |
| 162 | memcpy(TARGET,ENVSET[0],sizeof TARGET); |
| 163 | } else drawset(TARGET); |
| 164 | |
| 165 | /* SEEDED COMPLETE AND CORRECT: catalysts and templates covering the target set. Identical to |
| 166 | threecarrier.c -- nothing here has to bootstrap; the question is only whether it holds. */ |
| 167 | for(int c=0;c<NCOMP;c++){ |
| 168 | sz[c]=CAP; mat[c]=0; |
| 169 | for(int k=0;k<CAP;k++){ |
| 170 | int tg=-1,seen=0; |
| 171 | for(int t=0;t<NTYPE&&tg<0;t++) if(TARGET[t]){ if(seen==(k/2)%NTARG) tg=t; seen++; } |
| 172 | cell[c][k].role = (k%2)?TEM:CAT; |
| 173 | cell[c][k].type = (unsigned char)(tg<0?0:tg); |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | int lastsw=0; |
| 178 | for(int g=0;g<GEN;g++){ |
| 179 | if(envmode!=ENV_STATIC && g>0 && g%SWEVERY==0){ |
| 180 | memcpy(prev,TARGET,sizeof prev); |
| 181 | if(envmode==ENV_FRESH) drawset(TARGET); |
| 182 | else { envi=(envi+1)%NENV; memcpy(TARGET,ENVSET[envi],sizeof TARGET); } |
| 183 | nsw++; novl += overlap_of(prev,TARGET); lastsw=g; |
| 184 | } |
| 185 | for(int c=0;c<NCOMP;c++){ |
| 186 | int nc,nt,np; counts(c,&nc,&nt,&np); |
| 187 | mat[c] += GROW*nc; /* metabolism -> boundary */ |
| 188 | double f = (nc>0)? FHI : FLO; /* catalyst -> template fidelity */ |
| 189 | double tot=0,cum[CAP]; |
| 190 | for(int k=0;k<sz[c];k++){ tot += (cell[c][k].role==PAR)? 1.0+BETA : 1.0; cum[k]=tot; } |
| 191 | /* which catalyst types this compartment ALREADY has, fixed at the start of the generation |
| 192 | so both arms are scored against the same reference. Used only to characterize WHY an |
| 193 | arm wins -- it feeds no dynamics. */ |
| 194 | int present[NTYPE]; memset(present,0,sizeof present); |
| 195 | for(int k=0;k<sz[c];k++) if(cell[c][k].role==CAT) present[cell[c][k].type]=1; |
| 196 | int newn=0; |
| 197 | for(int k=0;k<sz[c];k++) if(urand()>=DEATH) nxt[c][newn++]=cell[c][k]; |
| 198 | while(mat[c]>=1.0 && newn<CAP && sz[c]>0){ |
| 199 | double r=urand()*tot; int lo=0,hi=sz[c]-1; |
| 200 | while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; } |
| 201 | Unit p=cell[c][lo], ch=p; |
| 202 | if(p.role==TEM){ |
| 203 | /* THE FIX. Copy error applies to EVERY template replication, independent of |
| 204 | reading; reading is a separate, subsequent event. In threecarrier.c these were |
| 205 | an if/else, so the reading knockout also changed mutation load. Both RNG draws |
| 206 | are taken unconditionally so the arms stay on the same stream as long as |
| 207 | possible -- the read modes then differ in exactly one thing: the type the |
| 208 | produced catalyst gets. */ |
| 209 | if(urand()>f) ch.type=(unsigned char)rint_(NTYPE); /* copy error */ |
| 210 | double rread = urand(); |
| 211 | unsigned char rtype = (unsigned char)rint_(NTYPE); |
| 212 | if(readmode!=READ_OFF && nc>0 && rread<PREAD){ |
| 213 | ch.role=CAT; /* template -> function */ |
| 214 | if(readmode==READ_SCRAMBLED) ch.type=rtype; /* the control: no information */ |
| 215 | reads++; |
| 216 | /* did this read add anything? A read that reproduces a type the compartment |
| 217 | already has changes no function; one that supplies a MISSING target type |
| 218 | raises it by one. This is the measurement that decides whether a scrambled |
| 219 | win is the diversity effect genome.md named. */ |
| 220 | if(present[ch.type]) redund++; |
| 221 | else if(TARGET[ch.type]) gapfill++; |
| 222 | } |
| 223 | } |
| 224 | if(urand()<MUT){ ch.role=(unsigned char)rint_(3); ch.type=(unsigned char)rint_(NTYPE); } |
| 225 | nxt[c][newn++]=ch; mat[c]-=1.0; |
| 226 | } |
| 227 | nsz[c]=newn; nmat[c]=mat[c]; |
| 228 | } |
| 229 | 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]; } |
| 230 | /* between-compartment: reproduce in proportion to CURRENT function. Identical to |
| 231 | threecarrier.c, and it is the instantaneous selection the deferred-benefit obstacle is |
| 232 | about -- deliberately left in place, since removing it would answer a different question. */ |
| 233 | { |
| 234 | double tot=0,cum[NCOMP]; |
| 235 | for(int c=0;c<NCOMP;c++){ tot += 0.02 + func_of(c); cum[c]=tot; } |
| 236 | for(int c=0;c<NCOMP;c++){ |
| 237 | double r=urand()*tot; int lo=0,hi=NCOMP-1; |
| 238 | while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; } |
| 239 | int m = sz[lo]<CAP? sz[lo] : CAP; |
| 240 | nsz[c]=m; nmat[c]=mat[lo]*0.5; |
| 241 | for(int k=0;k<m;k++) nxt[c][k]=cell[lo][rint_(sz[lo]>0?sz[lo]:1)]; |
| 242 | } |
| 243 | 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]; } |
| 244 | } |
| 245 | if(g>=BURN){ |
| 246 | int ok=0,tp=0,tt=0,tu=0; double fs=0; |
| 247 | for(int c=0;c<NCOMP;c++){ |
| 248 | int nc,nt,np; counts(c,&nc,&nt,&np); |
| 249 | int fc=func_of(c); |
| 250 | if(fc>=2) ok++; |
| 251 | fs+=fc; tp+=np; tt+=nt; tu+=sz[c]; |
| 252 | } |
| 253 | double mf=fs/NCOMP; |
| 254 | fsum+=mf; wsum+=(double)ok/NCOMP; |
| 255 | tsum += tu? (double)tt/tu : 0; psum += tu? (double)tp/tu : 0; |
| 256 | nmeas++; |
| 257 | if(envmode!=ENV_STATIC){ int ph=g-lastsw; if(ph<SWEVERY){ phase_f[ph]+=mf; phase_n[ph]++; } } |
| 258 | } |
| 259 | } |
| 260 | R->func=fsum/nmeas; R->work=wsum/nmeas; R->tfrac=tsum/nmeas; R->parfrac=psum/nmeas; |
| 261 | R->reads = reads/((double)NCOMP*GEN); |
| 262 | R->redund = reads? redund/reads : 0; |
| 263 | R->gapfill = reads? gapfill/reads : 0; |
| 264 | R->switches=nsw; R->overlap = nsw? novl/nsw : 0; |
| 265 | /* where memory should pay if it pays anywhere: the generations right after a switch, versus |
| 266 | right before the next one. */ |
| 267 | double e=0,l=0; long en=0,ln=0; |
| 268 | for(int ph=0;ph<5;ph++){ e+=phase_f[ph]; en+=phase_n[ph]; } |
| 269 | for(int ph=SWEVERY-5;ph<SWEVERY;ph++){ l+=phase_f[ph]; ln+=phase_n[ph]; } |
| 270 | R->early = en? e/en : 0; R->late = ln? l/ln : 0; |
| 271 | } |
| 272 | |
| 273 | typedef struct { const char *nm; int env, rd; } Arm; |
| 274 | |
| 275 | static void stats(const double *v,int n,double *mu,double *sd){ |
| 276 | double s=0; for(int i=0;i<n;i++) s+=v[i]; *mu=s/n; |
| 277 | double q=0; for(int i=0;i<n;i++){ double d=v[i]-*mu; q+=d*d; } |
| 278 | *sd = n>1? sqrt(q/(n-1)) : 0; |
| 279 | } |
| 280 | /* paired difference a-b across seeds: mean, standard error, and how many seeds favour a */ |
| 281 | static void paired(const double *a,const double *b,int n,double *mu,double *sem,int *win){ |
| 282 | double d[NSEED]; *win=0; |
| 283 | for(int i=0;i<n;i++){ d[i]=a[i]-b[i]; if(d[i]>0) (*win)++; } |
| 284 | double sd; stats(d,n,mu,&sd); *sem = n>1? sd/sqrt((double)n) : 0; |
| 285 | } |
| 286 | |
| 287 | int main(void) |
| 288 | { |
| 289 | Arm arms[7]={ |
| 290 | {"STATIC faithful",ENV_STATIC, READ_FAITHFUL }, |
| 291 | {"FRESH faithful",ENV_FRESH, READ_FAITHFUL }, |
| 292 | {"FRESH scrambled",ENV_FRESH, READ_SCRAMBLED}, |
| 293 | {"FRESH off",ENV_FRESH, READ_OFF }, |
| 294 | {"RECUR faithful",ENV_RECUR, READ_FAITHFUL }, |
| 295 | {"RECUR scrambled",ENV_RECUR, READ_SCRAMBLED}, |
| 296 | {"RECUR off",ENV_RECUR, READ_OFF }}; |
| 297 | enum { A_STAT=0, A_FF, A_FS, A_FO, A_RF, A_RS, A_RO }; |
| 298 | |
| 299 | static double F[7][NSEED], W[7][NSEED], T[7][NSEED], P[7][NSEED]; |
| 300 | static double EA[7][NSEED], LA[7][NSEED], RD[7][NSEED], OV[7][NSEED]; |
| 301 | |
| 302 | printf("=== fluctuate.c — does memory pay when the world changes? ===\n"); |
| 303 | printf(" Scored on FUNCTION, not template abundance (the metric that voided threecarrier.c's\n"); |
| 304 | printf(" fourth attempt). Reading knockout reduced to ONE variable. %d seeds.\n", NSEED); |
| 305 | printf(" THE HEADLINE IS FAITHFUL vs SCRAMBLED: reading also converts a template into a catalyst,\n"); |
| 306 | printf(" which raises nc and so raises growth AND fidelity. Only the scrambled control holds that\n"); |
| 307 | printf(" constant and isolates the information. genome.c's positive died to this control.\n\n"); |
| 308 | printf(" %d of %d types needed at a time; environment switches every %d generations;\n", NTARG,NTYPE,SWEVERY); |
| 309 | printf(" FRESH redraws at random, RECUR cycles %d fixed sets. Measured over generations %d-%d.\n\n", |
| 310 | NENV,BURN,GEN-1); |
| 311 | |
| 312 | for(int k=0;k<7;k++){ |
| 313 | for(int s=0;s<NSEED;s++){ |
| 314 | Res R; |
| 315 | RNG = 0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(s+1)); |
| 316 | for(int w=0;w<8;w++) xs(); /* warm the stream */ |
| 317 | run(arms[k].env,arms[k].rd,&R); |
| 318 | F[k][s]=R.func; W[k][s]=R.work; T[k][s]=R.tfrac; P[k][s]=R.parfrac; |
| 319 | EA[k][s]=R.early; LA[k][s]=R.late; RD[k][s]=R.reads; OV[k][s]=R.overlap; |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | printf(" arm | function (max %d) | working | reads/c/g | templates | parasites\n",NTARG); |
| 324 | printf(" -------------------+-------------------+-----------+-----------+-----------+----------\n"); |
| 325 | double fmu[7],fsd[7],wmu[7],wsd[7],tmu[7],tsd[7],pmu[7],psd[7],rmu[7],rsd[7]; |
| 326 | for(int k=0;k<7;k++){ |
| 327 | stats(F[k],NSEED,&fmu[k],&fsd[k]); stats(W[k],NSEED,&wmu[k],&wsd[k]); |
| 328 | stats(T[k],NSEED,&tmu[k],&tsd[k]); stats(P[k],NSEED,&pmu[k],&psd[k]); |
| 329 | stats(RD[k],NSEED,&rmu[k],&rsd[k]); |
| 330 | printf(" %s | %.3f +- %.3f | %.3f | %.3f | %.3f | %.3f\n", |
| 331 | arms[k].nm,fmu[k],fsd[k],wmu[k],rmu[k],tmu[k],pmu[k]); |
| 332 | } |
| 333 | printf(" (template fraction is REPORTED, and is deliberately NOT a criterion — see header)\n\n"); |
| 334 | |
| 335 | /* ---- tests of the test ---- */ |
| 336 | double omu,osd; stats(OV[A_FF],NSEED,&omu,&osd); |
| 337 | double omu2,osd2; stats(OV[A_RF],NSEED,&omu2,&osd2); |
| 338 | int g1 = (rmu[A_FF]>0 && rmu[A_FS]>0 && rmu[A_RF]>0 && rmu[A_RS]>0 |
| 339 | && rmu[A_FO]==0 && rmu[A_RO]==0); |
| 340 | int g2 = (tmu[A_FF]>0.002 && tmu[A_RF]>0.002); |
| 341 | int g3 = (omu < NTARG - 0.05) && (omu2 < NTARG - 0.05); |
| 342 | printf(" G1 reads happen in reading arms, never in OFF arms : %s (%.3f/%.3f on, %.3f/%.3f off)\n", |
| 343 | g1?"PASS":"FAIL", rmu[A_FF],rmu[A_RF],rmu[A_FO],rmu[A_RO]); |
| 344 | printf(" G2 templates actually exist (else no third carrier): %s (%.4f fresh, %.4f recur)\n", |
| 345 | g2?"PASS":"FAIL", tmu[A_FF],tmu[A_RF]); |
| 346 | printf(" G3 the environment actually changes : %s (overlap %.2f fresh, %.2f recur, of %d)\n", |
| 347 | g3?"PASS":"FAIL", omu,omu2,NTARG); |
| 348 | |
| 349 | double d,se; int win; |
| 350 | paired(F[A_FF],F[A_FS],NSEED,&d,&se,&win); |
| 351 | double d_p1f=d, se_p1f=se; int w_p1f=win; |
| 352 | paired(F[A_RF],F[A_RS],NSEED,&d,&se,&win); |
| 353 | double d_p1r=d, se_p1r=se; int w_p1r=win; |
| 354 | paired(F[A_FF],F[A_FO],NSEED,&d,&se,&win); |
| 355 | double d_p2f=d, se_p2f=se; |
| 356 | paired(F[A_RF],F[A_RO],NSEED,&d,&se,&win); |
| 357 | double d_p2r=d, se_p2r=se; |
| 358 | paired(F[A_STAT],F[A_FF],NSEED,&d,&se,&win); |
| 359 | double d_p3=d, se_p3=se; |
| 360 | |
| 361 | int g4 = fabs(d_p1f)>2*se_p1f || fabs(d_p1r)>2*se_p1r || fabs(d_p2f)>2*se_p2f || fabs(d_p3)>2*se_p3; |
| 362 | printf(" G4 the arms differ at all : %s\n\n", g4?"PASS":"FAIL"); |
| 363 | |
| 364 | if(!(g1&&g2&&g3&&g4)){ |
| 365 | printf(" => VOID. A test of the test failed, so nothing below is a result. Fix the test, not\n" |
| 366 | " the hypothesis.\n"); |
| 367 | return 0; |
| 368 | } |
| 369 | |
| 370 | int p1f = d_p1f > 2*se_p1f; |
| 371 | int p1r = d_p1r > 2*se_p1r; |
| 372 | printf(" P1 FRESH: faithful beats scrambled : %s %+.3f +- %.3f (%d/%d seeds)\n", |
| 373 | p1f?"YES":"no", d_p1f, se_p1f, w_p1f, NSEED); |
| 374 | printf(" P1 RECUR: faithful beats scrambled : %s %+.3f +- %.3f (%d/%d seeds)\n", |
| 375 | p1r?"YES":"no", d_p1r, se_p1r, w_p1r, NSEED); |
| 376 | printf(" P2 reading beats no reading (CONFOUNDED — conversion, not memory):\n"); |
| 377 | printf(" FRESH %+.3f +- %.3f RECUR %+.3f +- %.3f\n", d_p2f,se_p2f,d_p2r,se_p2r); |
| 378 | printf(" P3 fluctuation costs function : %s static-minus-fresh %+.3f +- %.3f\n", |
| 379 | (d_p3>2*se_p3)?"YES":"no", d_p3, se_p3); |
| 380 | printf(" post-switch -> pre-switch function (where memory should pay if anywhere):\n"); |
| 381 | { |
| 382 | double ea,es,la,ls; |
| 383 | stats(EA[A_FF],NSEED,&ea,&es); stats(LA[A_FF],NSEED,&la,&ls); |
| 384 | double ea2,es2,la2,ls2; |
| 385 | stats(EA[A_FS],NSEED,&ea2,&es2); stats(LA[A_FS],NSEED,&la2,&ls2); |
| 386 | double ea3,es3,la3,ls3; |
| 387 | stats(EA[A_RF],NSEED,&ea3,&es3); stats(LA[A_RF],NSEED,&la3,&ls3); |
| 388 | double ea4,es4,la4,ls4; |
| 389 | stats(EA[A_RS],NSEED,&ea4,&es4); stats(LA[A_RS],NSEED,&la4,&ls4); |
| 390 | printf(" FRESH faithful %.3f -> %.3f | scrambled %.3f -> %.3f\n", ea,la,ea2,la2); |
| 391 | printf(" RECUR faithful %.3f -> %.3f | scrambled %.3f -> %.3f\n", ea3,la3,ea4,la4); |
| 392 | } |
| 393 | printf("\n"); |
| 394 | |
| 395 | if(p1f && p1r) |
| 396 | printf(" => THE INFORMATION IS DOING WORK, IN BOTH WORLDS. Faithful reading beats a scrambled\n" |
| 397 | " read that converts identically, so it is the type carried by the template and not\n" |
| 398 | " the conversion. This is the control genome.c died to, passed.\n"); |
| 399 | else if(!p1f && p1r) |
| 400 | printf(" => MEMORY PAYS ONLY WHEN THE WORLD REPEATS. P4 as pre-registered: a fresh random\n" |
| 401 | " redraw gives a stored type the same %.2f odds a dice roll gets, so there is nothing\n" |
| 402 | " to be faithful to; a recurring world makes a specific past configuration worth more\n" |
| 403 | " than a random one, and faithful reading separates from its control. The condition is\n" |
| 404 | " on the ENVIRONMENT, not the chemistry.\n", (double)NTARG/NTYPE); |
| 405 | else if(p1f && !p1r) |
| 406 | printf(" => BACKWARDS AND UNEXPLAINED. Faithful wins under a random redraw but not under a\n" |
| 407 | " repeating world, which inverts the stated prediction. Do not narrate this;\n" |
| 408 | " characterize it before claiming anything.\n"); |
| 409 | else |
| 410 | printf(" => HONEST NULL, AND IT IS genome.c's RESULT AGAIN. Faithful reading does not beat a\n" |
| 411 | " scrambled read in either world (%+.3f fresh, %+.3f recur), so whatever ON-vs-OFF\n" |
| 412 | " gain exists is the CONVERSION of a template into a catalyst, not the information it\n" |
| 413 | " carries. threecarrier.c's 0.294 -> 0.478 is therefore not evidence for memory.\n" |
| 414 | " Memory still cannot pay under instantaneous selection, and a moving world does not\n" |
| 415 | " rescue it.\n", d_p1f, d_p1r); |
| 416 | return 0; |
| 417 | } |