| … | … | @@ -0,0 +1,232 @@ |
| 1 | /* threecarrier.c — INVALID AS RUN. DO NOT READ ITS NUMBERS AS A RESULT. |
| 2 | * |
| 3 | * Two faults, one fixed and one fatal, both recorded so the next attempt starts from them. |
| 4 | * |
| 5 | * FIXED: the first version set nsz[c]=newn, REPLACING each compartment with only what production |
| 6 | * could afford, so nothing persisted and every arm starved to extinction — FULL ended at 0 units and |
| 7 | * 0 PARASITES, which is death, not collapse-to-parasites. Units now persist, production adds, and a |
| 8 | * per-unit death rate removes. |
| 9 | * |
| 10 | * FATAL, AND WHY THE RESULT IS VOID: after that fix all four arms land within noise of each other |
| 11 | * (intact 0.052 / 0.055 / 0.037 / 0.049; function 2.47 / 2.46 / 2.45 / 2.52). That reads as "no |
| 12 | * coupling is load-bearing", but at least one arm is not a knockout at all: |
| 13 | * K1 gives growth GROW*CAP*0.5 = 4.4, and the coupled case gives GROW*nc with nc~8 = 4.4. |
| 14 | * IDENTICAL BY CONSTRUCTION. The "decoupled" control was calibrated to the coupled value. |
| 15 | * A second problem sits underneath: the "intact" metric requires catalysts AND templates, but |
| 16 | * reading CONSUMES templates (the same mistake genome.c made), so intact is measuring template |
| 17 | * retention rather than system integrity while function stays high at ~2.5/4. |
| 18 | * |
| 19 | * So nothing here bears on whether the complete system is stable. The verdict text below is left |
| 20 | * exactly as the program printed it, and it is WRONG. |
| 21 | * |
| 22 | * FOR THE NEXT ATTEMPT: make each knockout a real ablation (K1 must give growth genuinely unrelated |
| 23 | * to catalytic content, e.g. a rate that does not track nc), separate template retention from system |
| 24 | * integrity in the metrics, and confirm the arms differ before reading anything into them. |
| 25 | * |
| 26 | * ---- original design notes follow ---- |
| 27 | * |
| 28 | * threecarrier.c — is the COMPLETE system stable? (not: can it bootstrap) |
| 29 | * |
| 30 | * The arc has only ever tested REACHABILITY of parts. It has never tested STABILITY of the whole. |
| 31 | * Every failure had one shape — one object asked to do two jobs: catalyst = function AND information |
| 32 | * (fidfloor.c: no compartment size both corrects and remembers); compartment = isolation AND |
| 33 | * selection (byproduct.c); replicase = catalyst AND its own specification (replicase.c); role = |
| 34 | * elective AND stable (rung45.c). The two things that WORKED — linkage.c, rung45irr.c — worked by |
| 35 | * making a coupling STRUCTURAL rather than elective. |
| 36 | * |
| 37 | * So: three carriers, not one. A BOUNDARY nobody maintains, a METABOLISM that produces, and a |
| 38 | * TEMPLATE that only remembers, with couplings that cannot be defected on. That is Ganti's chemoton, |
| 39 | * and his claim was always that all three are needed SIMULTANEOUSLY. Every failure above was an |
| 40 | * attempt to get two and derive the third. |
| 41 | * |
| 42 | * THE TEST IS STABILITY, WHICH IS A DIFFERENT QUESTION. Start the system COMPLETE and correct, then |
| 43 | * ask whether it persists against parasite invasion, mutation and competition. Nothing here has to |
| 44 | * bootstrap; the question is only whether the finished thing holds together. |
| 45 | * |
| 46 | * THE THREE COUPLINGS, each non-discretionary: |
| 47 | * metabolism -> boundary : catalysts produce the material the compartment grows from. You build |
| 48 | * iff you catalyse; wall-building is not an investment anyone elects. |
| 49 | * template -> function : a template is read to make a catalyst of its type. |
| 50 | * catalyst -> template : catalysts copy templates at high fidelity (the replicase role). |
| 51 | * |
| 52 | * ARMS. FULL, then each coupling KNOCKED OUT in turn. If breaking any one collapses the system, all |
| 53 | * three are load-bearing and the complete system is stable only when complete — which is the |
| 54 | * simultaneous-origin claim, tested rather than asserted. |
| 55 | * K1 boundary decoupled : compartments grow at a fixed rate regardless of catalytic content |
| 56 | * K2 reading off : templates cannot be read |
| 57 | * K3 replicase off : templates copy at base fidelity regardless of catalysts present |
| 58 | * |
| 59 | * PARASITES ARE NOT SEEDED. They arise by mutation from catalysts and templates, replicate faster, |
| 60 | * and contribute nothing — so the tragedy is live in every arm. |
| 61 | * |
| 62 | * PRE-REGISTERED: |
| 63 | * T1 FULL persists — most compartments still hold catalysts AND templates after GEN generations. |
| 64 | * T2 every knockout collapses. If a knockout persists, that coupling is not load-bearing. |
| 65 | * T3 TEST OF THE TEST: parasites must actually appear and be able to win, or nothing was resisted. |
| 66 | * |
| 67 | * If FULL also collapses, the complete system is not even stable, which is a stronger negative than |
| 68 | * anything the arc has produced. |
| 69 | * |
| 70 | * build: cc -O2 -Wall -std=c11 -o threecarrier threecarrier.c -lm |
| 71 | */ |
| 72 | #include <math.h> |
| 73 | #include <stdio.h> |
| 74 | #include <string.h> |
| 75 | |
| 76 | #define NCOMP 600 |
| 77 | #define CAP 16 |
| 78 | #define GEN 400 |
| 79 | #define NTYPE 4 |
| 80 | #define BETA 2.0 /* parasite replication advantage */ |
| 81 | #define MUT 0.02 /* role/type mutation */ |
| 82 | #define FLO 0.85 /* template copy fidelity without a catalyst present */ |
| 83 | #define FHI 0.995 /* ... with one (the replicase coupling) */ |
| 84 | #define GROW 0.55 |
| 85 | #define DEATH 0.15 /* per-unit death per generation; production must exceed it */ /* material per catalyst per generation */ |
| 86 | |
| 87 | enum { CAT=0, TEM=1, PAR=2 }; |
| 88 | |
| 89 | static unsigned long long RNG; |
| 90 | static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; } |
| 91 | static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); } |
| 92 | static int rint_(int n){ return (int)(xs()%(unsigned)n); } |
| 93 | |
| 94 | typedef struct { unsigned char role, type; } Unit; |
| 95 | static Unit cell[NCOMP][CAP], nxt[NCOMP][CAP]; |
| 96 | static int sz[NCOMP], nsz[NCOMP]; |
| 97 | static double mat[NCOMP], nmat[NCOMP]; |
| 98 | static int ncomp; |
| 99 | |
| 100 | static void counts(int c,int *nc,int *nt,int *np){ |
| 101 | *nc=*nt=*np=0; |
| 102 | for(int k=0;k<sz[c];k++){ |
| 103 | if(cell[c][k].role==CAT) (*nc)++; |
| 104 | else if(cell[c][k].role==TEM) (*nt)++; |
| 105 | else (*np)++; |
| 106 | } |
| 107 | } |
| 108 | /* function = distinct catalyst types present. What the compartment can actually do. */ |
| 109 | static int func_of(int c){ |
| 110 | int seen[NTYPE]; memset(seen,0,sizeof seen); |
| 111 | for(int k=0;k<sz[c];k++) if(cell[c][k].role==CAT) seen[cell[c][k].type]=1; |
| 112 | int f=0; for(int t=0;t<NTYPE;t++) f+=seen[t]; |
| 113 | return f; |
| 114 | } |
| 115 | |
| 116 | /* ko: 0 = FULL, 1 = boundary decoupled, 2 = reading off, 3 = replicase off */ |
| 117 | static void run(int ko,double *alive,double *funcavg,double *parfrac) |
| 118 | { |
| 119 | ncomp=NCOMP; |
| 120 | for(int c=0;c<ncomp;c++){ |
| 121 | sz[c]=CAP; mat[c]=0; |
| 122 | for(int k=0;k<CAP;k++){ /* SEEDED COMPLETE: catalysts + templates */ |
| 123 | cell[c][k].role = (k%2)?TEM:CAT; |
| 124 | cell[c][k].type = k%NTYPE; |
| 125 | } |
| 126 | } |
| 127 | for(int g=0;g<GEN;g++){ |
| 128 | for(int c=0;c<ncomp;c++){ |
| 129 | int nc,nt,np; counts(c,&nc,&nt,&np); |
| 130 | /* coupling 1: metabolism -> boundary. K1 decouples it. */ |
| 131 | mat[c] += (ko==1)? GROW*CAP*0.5 : GROW*nc; |
| 132 | /* coupling 3: catalyst -> template fidelity. K3 decouples it. */ |
| 133 | double f = (ko==3)? FLO : ((nc>0)? FHI : FLO); |
| 134 | /* replication within the compartment; parasites are faster */ |
| 135 | double tot=0,cum[CAP]; |
| 136 | for(int k=0;k<sz[c];k++){ tot += (cell[c][k].role==PAR)? 1.0+BETA : 1.0; cum[k]=tot; } |
| 137 | /* BUG FIXED: the first version set nsz[c]=newn, REPLACING the compartment with only what |
| 138 | production could afford — so nothing persisted and every arm starved to extinction |
| 139 | (FULL ended at 0 units, 0 parasites, which is death, not collapse-to-parasites). |
| 140 | Existing units now PERSIST; production ADDS to them; a per-unit death rate removes. */ |
| 141 | int newn=0; |
| 142 | for(int k=0;k<sz[c];k++) if(urand()>=DEATH) nxt[c][newn++]=cell[c][k]; |
| 143 | while(mat[c]>=1.0 && newn<CAP && sz[c]>0){ |
| 144 | double r=urand()*tot; int lo=0,hi=sz[c]-1; |
| 145 | while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; } |
| 146 | Unit p=cell[c][lo], ch=p; |
| 147 | if(p.role==TEM){ |
| 148 | /* coupling 2: template -> function. K2 turns reading off. */ |
| 149 | if(ko!=2 && nc>0 && urand()<0.5){ ch.role=CAT; ch.type=p.type; } |
| 150 | else if(urand()>f) ch.type=(unsigned char)rint_(NTYPE); /* copy error */ |
| 151 | } |
| 152 | if(urand()<MUT){ ch.role=(unsigned char)rint_(3); ch.type=(unsigned char)rint_(NTYPE); } |
| 153 | nxt[c][newn++]=ch; mat[c]-=1.0; |
| 154 | } |
| 155 | nsz[c]=newn; nmat[c]=mat[c]; |
| 156 | } |
| 157 | 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]; } |
| 158 | /* between-compartment: reproduce in proportion to function; empty ones are replaced */ |
| 159 | { |
| 160 | double tot=0,cum[NCOMP]; |
| 161 | for(int c=0;c<ncomp;c++){ tot += 0.02 + func_of(c); cum[c]=tot; } |
| 162 | for(int c=0;c<ncomp;c++){ |
| 163 | double r=urand()*tot; int lo=0,hi=ncomp-1; |
| 164 | while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; } |
| 165 | int m = sz[lo]<CAP? sz[lo] : CAP; |
| 166 | nsz[c]=m; nmat[c]=mat[lo]*0.5; |
| 167 | for(int k=0;k<m;k++) nxt[c][k]=cell[lo][rint_(sz[lo]>0?sz[lo]:1)]; |
| 168 | } |
| 169 | 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 | } |
| 171 | } |
| 172 | int ok=0,tp=0,tu=0; double fs=0; |
| 173 | for(int c=0;c<ncomp;c++){ |
| 174 | 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]; |
| 177 | } |
| 178 | *alive=(double)ok/ncomp; *funcavg=fs/ncomp; *parfrac= tu? (double)tp/tu : 0; |
| 179 | } |
| 180 | |
| 181 | int main(void) |
| 182 | { |
| 183 | unsigned long long seeds[5]={0x9e3779b97f4a7c15ULL,0xd1b54a32d192ed03ULL,0x2545f4914f6cdd1dULL, |
| 184 | 0x123456789abcdefULL,0xfeedface12345678ULL}; |
| 185 | int NS=5; |
| 186 | printf("=== THREE CARRIERS: is the COMPLETE system STABLE? (not: can it bootstrap) ===\n"); |
| 187 | printf(" BOUNDARY nobody maintains, METABOLISM that produces, TEMPLATE that only remembers —\n"); |
| 188 | printf(" three couplings, none defectable: metabolism->boundary, template->function,\n"); |
| 189 | printf(" catalyst->template fidelity. Seeded COMPLETE; parasites are NOT seeded, they arise by\n"); |
| 190 | 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"); |
| 193 | const char *nm[4]={"FULL (all three) ","K1 boundary decoupled ","K2 reading off ","K3 replicase off "}; |
| 194 | double A[4],F[4],P[4]; |
| 195 | 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]); |
| 200 | } |
| 201 | printf("\n"); |
| 202 | int t3 = P[0]>0.01 || P[1]>0.01 || P[2]>0.01 || P[3]>0.01; |
| 203 | int t1 = A[0]>0.5; |
| 204 | int ko_collapse=0; for(int k=1;k<4;k++) if(A[k] < A[0]-0.15) ko_collapse++; |
| 205 | printf(" T3 parasites arose and could win : %s (max frac %.3f)\n", t3?"YES":"NO — nothing was resisted", |
| 206 | fmax(fmax(P[0],P[1]),fmax(P[2],P[3]))); |
| 207 | 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); |
| 209 | |
| 210 | if(!t3) |
| 211 | printf(" => TEST DID NOT RUN. Parasites never appeared, so nothing was being resisted and\n" |
| 212 | " persistence means nothing. Invalid, not a result.\n"); |
| 213 | else if(t1 && ko_collapse==3) |
| 214 | printf(" => THE COMPLETE SYSTEM IS STABLE, AND ALL THREE COUPLINGS ARE LOAD-BEARING. It holds\n" |
| 215 | " against parasites when whole and collapses when ANY single coupling is cut. That is\n" |
| 216 | " the simultaneous-origin claim measured rather than asserted: the arc's failures were\n" |
| 217 | " all attempts to get two carriers and derive the third, and this says the third\n" |
| 218 | " cannot be derived because the system is only stable complete.\n"); |
| 219 | else if(t1 && ko_collapse>0) |
| 220 | printf(" => STABLE, BUT ONLY %d OF 3 COUPLINGS ARE LOAD-BEARING. The others can be cut without\n" |
| 221 | " collapse, so the system is over-specified — report which, it narrows what a\n" |
| 222 | " minimal origin actually needs.\n",ko_collapse); |
| 223 | else if(t1) |
| 224 | printf(" => STABLE, AND NO COUPLING IS LOAD-BEARING. Persistence does not depend on any of the\n" |
| 225 | " three, so something else is holding it up. Find that before claiming anything.\n"); |
| 226 | else |
| 227 | printf(" => THE COMPLETE SYSTEM IS NOT STABLE. Even seeded whole, with all three couplings\n" |
| 228 | " intact, it collapses to parasites. That is a stronger negative than anything the arc\n" |
| 229 | " has produced: it is not that 1->2 cannot be REACHED, it is that the destination does\n" |
| 230 | " not hold together under its own tragedy.\n"); |
| 231 | return 0; |
| 232 | } |