| … | … | @@ -0,0 +1,147 @@ |
| 1 | /* bridges.c — four candidate BRIDGES past the ribozyme wall, compared head to head. |
| 2 | * |
| 3 | * ribozyme.c bootstrapped fidelity but needed TWO supplied ingredients: (1) decreed structure->catalysis |
| 4 | * map phi->f, (2) compartments + group selection (to privatize the public good). Each bridge removes ONE |
| 5 | * supplied ingredient and asks: does the fidelity/catalysis bootstrap STILL fire (mean phi rises from the |
| 6 | * random-entropy value ~6 toward the max 12)? Shared core so all four are apples-to-apples. |
| 7 | * |
| 8 | * BASELINE well-mixed, shared catalysis (public good, no privatization) -> the thing to beat (falls). |
| 9 | * A SURFACE local catalysis on a 2D grid, local replication. Privatize by SPACE, no compartments. |
| 10 | * B CIS copy fidelity = the strand's OWN phi (cis-acting). Privatize by ATTACHMENT, no compartments. |
| 11 | * C BIND compartments kept, but catalysis is EMERGENT from pairwise binding (no decreed phi->f map). |
| 12 | * D CLAY well-mixed + an environmental fidelity FLOOR f_clay (adsorption assist), sweep f_clay. |
| 13 | * |
| 14 | * Razor: no bridge rewards a specific sequence. phi is an emergent hairpin fold score; catalysis/fidelity |
| 15 | * arise from it (A,B,D) or from binding (C). Whether phi RISES is measured, never encoded. |
| 16 | * |
| 17 | * build: cc -O2 -Wall -std=c11 -o bridges bridges.c -lm |
| 18 | */ |
| 19 | #include <math.h> |
| 20 | #include <stdio.h> |
| 21 | #include <stdint.h> |
| 22 | |
| 23 | #define L 24 |
| 24 | #define PHIMAX (L/2) |
| 25 | #define F0 0.85 |
| 26 | #define F1 0.999 |
| 27 | #define BETA 2.0 |
| 28 | #define EMPTY 0xffffffffu |
| 29 | |
| 30 | static unsigned long long RNG; |
| 31 | static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; } |
| 32 | static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); } |
| 33 | static int phi(uint32_t s){ int c=0; for(int i=0;i<PHIMAX;i++){ int a=(s>>i)&1,b=(s>>(L-1-i))&1; if(a!=b)c++; } return c; } |
| 34 | /* hairpin-style complementarity of a's left half against b's right half (a==b -> phi) */ |
| 35 | static int bind(uint32_t a,uint32_t b){ int c=0; for(int i=0;i<PHIMAX;i++){ int x=(a>>i)&1,y=(b>>(L-1-i))&1; if(x!=y)c++; } return c; } |
| 36 | static uint32_t replicate(uint32_t t,double f){ uint32_t c=0; for(int i=0;i<L;i++){ int b=(t>>i)&1; int nb=(urand()<f)?(1-b):b; if(nb)c|=(1u<<i);} return c; } |
| 37 | static uint32_t randstrand(void){ uint32_t s=0; for(int b=0;b<L;b++) if(urand()<0.5) s|=(1u<<b); return s; } |
| 38 | |
| 39 | /* ---- BASELINE: well-mixed, shared (public-good) catalysis. no privatization. ---- */ |
| 40 | static double baseline(int N,int GEN,double *start){ |
| 41 | static uint32_t pool[8000],nxt[8000]; |
| 42 | for(int i=0;i<N;i++) pool[i]=randstrand(); |
| 43 | { double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); *start=s/N; } |
| 44 | for(int g=0;g<GEN;g++){ |
| 45 | double mphi=0; for(int i=0;i<N;i++) mphi+=phi(pool[i]); mphi/=N; double f=F0+(F1-F0)*(mphi/PHIMAX); |
| 46 | double tot=0; static double cum[8000]; for(int i=0;i<N;i++){ double w=1.0+BETA*(1.0-(double)phi(pool[i])/PHIMAX); tot+=w; cum[i]=tot; } |
| 47 | for(int i=0;i<N;i++){ double r=urand()*tot; int lo=0,hi=N-1; while(lo<hi){int m=(lo+hi)/2; if(cum[m]<r)lo=m+1; else hi=m;} nxt[i]=replicate(pool[lo],f); } |
| 48 | for(int i=0;i<N;i++) pool[i]=nxt[i]; |
| 49 | } |
| 50 | double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); return s/N; |
| 51 | } |
| 52 | |
| 53 | /* ---- B CIS: fidelity = the strand's OWN phi (private by construction). well-mixed. ---- */ |
| 54 | static double cis(int N,int GEN,double *start){ |
| 55 | static uint32_t pool[8000],nxt[8000]; |
| 56 | for(int i=0;i<N;i++) pool[i]=randstrand(); |
| 57 | { double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); *start=s/N; } |
| 58 | for(int g=0;g<GEN;g++){ |
| 59 | double tot=0; static double cum[8000]; for(int i=0;i<N;i++){ double w=1.0+BETA*(1.0-(double)phi(pool[i])/PHIMAX); tot+=w; cum[i]=tot; } |
| 60 | for(int i=0;i<N;i++){ double r=urand()*tot; int lo=0,hi=N-1; while(lo<hi){int m=(lo+hi)/2; if(cum[m]<r)lo=m+1; else hi=m;} int par=lo; |
| 61 | double f=F0+(F1-F0)*((double)phi(pool[par])/PHIMAX); nxt[i]=replicate(pool[par],f); } |
| 62 | for(int i=0;i<N;i++) pool[i]=nxt[i]; |
| 63 | } |
| 64 | double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); return s/N; |
| 65 | } |
| 66 | |
| 67 | /* ---- A SURFACE: local catalysis (neighbours) + local replication on a 2D grid. no compartments. ---- */ |
| 68 | #define G 48 |
| 69 | static uint32_t grd[G*G]; |
| 70 | static double surface(int GEN,double *start){ |
| 71 | int nocc=0; for(int i=0;i<G*G;i++){ if(urand()<0.5){ grd[i]=randstrand(); nocc++; } else grd[i]=EMPTY; } |
| 72 | { double s=0;int c=0; for(int i=0;i<G*G;i++) if(grd[i]!=EMPTY){ s+=phi(grd[i]); c++; } *start=c?s/c:0; } |
| 73 | for(int g=0;g<GEN;g++){ |
| 74 | /* replication attempts */ |
| 75 | for(int t=0;t<G*G;t++){ |
| 76 | int x=(int)(xs()%G), y=(int)(xs()%G), c=y*G+x; if(grd[c]==EMPTY) continue; |
| 77 | double w=1.0+BETA*(1.0-(double)phi(grd[c])/PHIMAX); /* parasites replicate faster */ |
| 78 | if(urand()> w/(1.0+BETA)) continue; |
| 79 | int dx=(int)(xs()%3)-1, dy=(int)(xs()%3)-1; int nx=(x+dx+G)%G, ny=(y+dy+G)%G, nc=ny*G+nx; |
| 80 | if(grd[nc]!=EMPTY) continue; |
| 81 | double sp=0; int cn=0; /* LOCAL catalysis: neighbourhood mean phi */ |
| 82 | for(int ddy=-1;ddy<=1;ddy++)for(int ddx=-1;ddx<=1;ddx++){ int a=((y+ddy+G)%G)*G+((x+ddx+G)%G); if(grd[a]!=EMPTY){ sp+=phi(grd[a]); cn++; } } |
| 83 | double mphi=cn?sp/cn:0; double f=F0+(F1-F0)*(mphi/PHIMAX); |
| 84 | grd[nc]=replicate(grd[c],f); |
| 85 | } |
| 86 | for(int i=0;i<G*G;i++) if(grd[i]!=EMPTY && urand()<0.10) grd[i]=EMPTY; /* degradation */ |
| 87 | } |
| 88 | double s=0;int c=0; for(int i=0;i<G*G;i++) if(grd[i]!=EMPTY){ s+=phi(grd[i]); c++; } return c?s/c:0; |
| 89 | } |
| 90 | |
| 91 | /* ---- C BIND: compartments kept, catalysis EMERGENT from pairwise binding (no decreed phi->f). ---- */ |
| 92 | static double bindbridge(int ncomp,int csz,int GEN,double *start){ |
| 93 | int TOT=ncomp*csz; static uint32_t pool[8000],nxt[8000]; |
| 94 | for(int i=0;i<TOT;i++) pool[i]=randstrand(); |
| 95 | { double s=0; for(int i=0;i<TOT;i++) s+=phi(pool[i]); *start=s/TOT; } |
| 96 | for(int g=0;g<GEN;g++){ |
| 97 | for(int cmp=0;cmp<ncomp;cmp++){ int base=cmp*csz; |
| 98 | double mb=0; for(int a=0;a<csz;a++){ int best=0; for(int b=0;b<csz;b++){ int v=bind(pool[base+a],pool[base+b]); if(v>best)best=v; } mb+=best; } mb/=csz; |
| 99 | double f=F0+(F1-F0)*(mb/PHIMAX); |
| 100 | double tot=0; static double cum[8000]; for(int k=0;k<csz;k++){ double w=1.0+BETA*(1.0-(double)phi(pool[base+k])/PHIMAX); tot+=w; cum[base+k]=tot; } |
| 101 | for(int k=0;k<csz;k++){ double r=urand()*tot; int lo=0,hi=csz-1; while(lo<hi){int m=(lo+hi)/2; if(cum[base+m]<r)lo=m+1; else hi=m;} nxt[base+k]=replicate(pool[base+lo],f); } |
| 102 | } |
| 103 | for(int i=0;i<TOT;i++) pool[i]=nxt[i]; |
| 104 | /* group selection: productivity = mean binding; assort daughters */ |
| 105 | static double cumP[2000]; double tp=0; |
| 106 | for(int cmp=0;cmp<ncomp;cmp++){ int base=cmp*csz; double mb=0; for(int a=0;a<csz;a++){ int best=0; for(int b=0;b<csz;b++){ int v=bind(pool[base+a],pool[base+b]); if(v>best)best=v; } mb+=best; } tp+=mb/csz; cumP[cmp]=tp; } |
| 107 | for(int cmp=0;cmp<ncomp;cmp++){ double r=urand()*tp; int lo=0,hi=ncomp-1; while(lo<hi){int m=(lo+hi)/2; if(cumP[m]<r)lo=m+1; else hi=m;} int par=lo; |
| 108 | for(int k=0;k<csz;k++) nxt[cmp*csz+k]=pool[par*csz+(int)(xs()%csz)]; } |
| 109 | for(int i=0;i<TOT;i++) pool[i]=nxt[i]; |
| 110 | } |
| 111 | double s=0; for(int i=0;i<TOT;i++) s+=phi(pool[i]); return s/TOT; |
| 112 | } |
| 113 | |
| 114 | /* ---- D CLAY: well-mixed + environmental fidelity FLOOR f_clay (adsorption assist). ---- */ |
| 115 | static double clay(int N,int GEN,double fclay,double *start){ |
| 116 | static uint32_t pool[8000],nxt[8000]; |
| 117 | for(int i=0;i<N;i++) pool[i]=randstrand(); |
| 118 | { double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); *start=s/N; } |
| 119 | for(int g=0;g<GEN;g++){ |
| 120 | double mphi=0; for(int i=0;i<N;i++) mphi+=phi(pool[i]); mphi/=N; double fcat=F0+(F1-F0)*(mphi/PHIMAX); double f=fcat>fclay?fcat:fclay; |
| 121 | double tot=0; static double cum[8000]; for(int i=0;i<N;i++){ double w=1.0+BETA*(1.0-(double)phi(pool[i])/PHIMAX); tot+=w; cum[i]=tot; } |
| 122 | for(int i=0;i<N;i++){ double r=urand()*tot; int lo=0,hi=N-1; while(lo<hi){int m=(lo+hi)/2; if(cum[m]<r)lo=m+1; else hi=m;} nxt[i]=replicate(pool[lo],f); } |
| 123 | for(int i=0;i<N;i++) pool[i]=nxt[i]; |
| 124 | } |
| 125 | double s=0; for(int i=0;i<N;i++) s+=phi(pool[i]); return s/N; |
| 126 | } |
| 127 | |
| 128 | static const char* verdict(double st,double en){ if(en>st+2.0)return "IGNITES"; if(en>st+0.5)return "partial"; if(en<st-0.5)return "falls"; return "~flat"; } |
| 129 | |
| 130 | int main(void){ |
| 131 | unsigned long long seed=0x9e3779b97f4a7c15ULL; |
| 132 | double st,en; |
| 133 | printf("=== Four bridges past the ribozyme wall (random start phi~6, max 12; IGNITES = phi climbs) ===\n\n"); |
| 134 | printf(" bridge | removes | phi start->end | verdict\n"); |
| 135 | printf(" --------------+--------------------+----------------+--------\n"); |
| 136 | |
| 137 | RNG=seed; en=baseline(3000,250,&st); printf(" BASELINE | (nothing) | %.2f -> %.2f | %s\n",st,en,verdict(st,en)); |
| 138 | RNG=seed; en=surface(300,&st); printf(" A surface | compartments(->space) | %.2f -> %.2f | %s\n",st,en,verdict(st,en)); |
| 139 | RNG=seed; en=cis(3000,250,&st); printf(" B cis-acting | compartments(->cis) | %.2f -> %.2f | %s\n",st,en,verdict(st,en)); |
| 140 | RNG=seed; en=bindbridge(400,8,180,&st); printf(" C bind (emrg) | decreed phi->f map | %.2f -> %.2f | %s\n",st,en,verdict(st,en)); |
| 141 | printf(" D clay floor | (adds env fidelity assist), sweep f_clay:\n"); |
| 142 | double fcs[]={0.85,0.92,0.97,0.99}; for(int i=0;i<4;i++){ RNG=seed; en=clay(3000,200,fcs[i],&st); printf(" f_clay=%.2f | | %.2f -> %.2f | %s\n",fcs[i],st,en,verdict(st,en)); } |
| 143 | printf("\n"); |
| 144 | printf(" (ribozyme.c reference: supplied compartments size<=8 -> phi ~6->11.6 IGNITES; well-mixed falls.)\n"); |
| 145 | printf(" Compare: which bridges make phi RISE while removing a supplied ingredient? Read verdicts above.\n"); |
| 146 | return 0; |
| 147 | } |