/* byproduct.c — a compartment nobody chooses to build: can a NON-DISCRETIONARY boundary cross 1->2?
*
* WHERE THIS COMES FROM (Law 2, SYNTHESIS Part C). Every boundary the arc tested that had to be
* MAINTAINED was a strategy, and strategies get invaded: signal.c's investment converges to the same
* low value from starts 0.10 / 0.50 / 1.00 -- measured invasion, not a coordination trap. The only
* boundary that emerged, linkage.c, was STRUCTURAL: linked genes cannot replicate at different
* rates, so defection is not an available move. Law 2 says the way past 1->2 is therefore not to
* find a cheaper boundary but a boundary NOBODY CAN DECLINE TO BUILD.
*
* THE IDEA. Chemistry that builds its own container as an unavoidable SIDE EFFECT of catalyzing --
* mineral precipitation, self-templating pores, alkaline-vent chimney walls. Wall-building is not an
* investment anyone elects: you build iff you catalyze. So a catalyst-rich region walls itself in,
* and a region that degenerates to parasites stops producing precipitate, its walls decay, and it is
* mixed back into the open pool. The compartment is maintained by the very activity it protects, and
* no unit ever decides to maintain it.
*
* THE RAZOR (issue #6). Nothing here says "walls exclude parasites" or "only catalysts get walls":
* - deposition is a function of LOCAL ACTIVITY, which parasites simply do not have -- they are not
* forbidden from depositing, they have nothing to deposit;
* - a parasite sitting inside a walled region enjoys the wall AND the catalysis in full. The
* within-region public-goods tragedy is untouched;
* - walls gate MIXING symmetrically -- they keep parasites out and catalysts in, equally.
* Whether catalyst-rich regions persist is therefore left genuinely open.
*
* WHAT IS SUPPLIED vs WHAT MUST EMERGE:
* SUPPLIED: a lattice of sites (space, which bridges.c arm A already had AND FAILED WITH), local
* catalysis, and the physical coupling activity -> precipitate. Deposition rate is SWEPT.
* MUST EMERGE: the compartments. Walls start at ZERO everywhere. If regions become isolated it is
* because their own chemistry isolated them.
* THE ONLY DIFFERENCE from the failed spatial arm is the byproduct wall. That is the variable.
*
* Chemistry identical to ribozyme.c / coupling.c / partition.c / signal.c (phi = hairpin fold,
* parasites 3x faster, F0=0.85, F1=0.999, 4800 units, 200 gens, start phi ~5.99 = the neutral
* expectation 6.0). Reference: ribozyme well-mixed 5.99 -> 5.50; SUPPLIED compartments of size 8
* -> 11.34.
*
* PRE-REGISTERED:
* B1 WALL OFF (free mixing) -> phi FALLS. Reproduces bridges.c arm A, the spatial failure.
* B2 WALL SUPPLIED (always max) -> phi RISES. POSITIVE CONTROL: proves this lattice CAN cross, so
* that a null in B3 is about the byproduct mechanism and not about a model that cannot win.
* B3 WALL BYPRODUCT -> phi RISES. THE TEST.
* B4 WALL SHUFFLED (control) -> the same wall heights reassigned to RANDOM edges each
* generation: identical amount of isolation, decoupled from where the activity is. If phi rises
* here too, the effect is isolation per se and not the activity->wall coupling, and B3 is void.
* B5 TEST OF THE TEST: do walls actually form AND vary AND track local activity? Report mean wall
* height and the correlation between an edge's wall and its neighbouring activity. If walls are
* ~0, saturated everywhere, or uncorrelated with activity, the mechanism never ran and a null
* says nothing -- the mistake partition.c made on its first pass and ribophi.c made with its
* not-actually-early window.
*
* Do not tune to force a positive. A null here, with B2 passing, is a real result about Law 2.
*
* OUTCOME (recorded after the run; the pre-registration above is left exactly as written).
* **B2 FAILED, and its failure is the finding.** Supplied walls at full height -- total isolation --
* reach only 5.65, no better than the spatial arm. Adding modes 4/5 (between-site selection, the
* stochastic-corrector step ribozyme.c actually has) makes supplied walls reach 10.78 and byproduct
* walls 11.39. So the barrier was never what made compartments work: what made them work is that
* compartments DIVIDE and are SELECTED on catalytic content. ISOLATION IS NOT COMPARTMENTALIZATION.
* A byproduct wall buys the isolation half for free and leaves the second-level-selection half
* exactly as supplied as it ever was -- Law 2's non-discretionary fix addresses the wrong half.
* Secondary, and real: GIVEN the second level, byproduct walls BEAT permanently supplied ones
* (11.39 vs 10.78) -- self-sealing high-activity regions while low-activity ones re-mix is a better
* compartment than a permanent box. Byproduct walls are a good compartment; they are not a source
* of the selection level.
*
* build: cc -O2 -Wall -std=c11 -o byproduct byproduct.c -lm
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
/* ---------- identical to the rest of Part C ---------- */
#define L 24
#define PHIMAX (L/2)
#define GEN 200
#define F0 0.85
#define F1 0.999
#define BETA 2.0
/* ---------- lattice ---------- */
#define NSITE 600
#define CAP 8
#define TOTAL (NSITE*CAP) /* 4800, same as every other Part C program */
#define DECAY 0.10 /* wall dissolution per generation */
#define MIGR 0.30 /* base exchange rate across an unwalled edge */
static unsigned long long RNG;
static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; }
static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); }
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; }
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; }
static uint32_t cell[NSITE][CAP], ncell[NSITE][CAP];
static double wall[NSITE], tmpw[NSITE]; /* wall[i] = barrier on the edge between i and i+1 */
static double mphi[NSITE];
static int phic[NSITE][CAP];
/* mode: 0 = wall off, 1 = byproduct wall, 2 = wall supplied at max, 3 = byproduct then SHUFFLED,
4 = supplied wall + BETWEEN-SITE SELECTION, 5 = byproduct wall + between-site selection.
Modes 4/5 add ribozyme.c's group step (sample a parent site proportional to its mean phi, reseed
by random assortment) -- i.e. compartments that DIVIDE and are SELECTED, not merely isolated. */
static double run(int mode,double dep,double *phi_start,double *wall_mean,double *wall_corr)
{
for(int s=0;s<NSITE;s++){
wall[s]=0.0; /* walls start at ZERO: nothing is supplied */
for(int k=0;k<CAP;k++){ uint32_t v=0; for(int b=0;b<L;b++) if(urand()<0.5) v|=(1u<<b); cell[s][k]=v; }
}
{ double sp=0; for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) sp+=phi(cell[s][k]); *phi_start=sp/TOTAL; }
double lastw=0, lastc=0;
for(int g=0;g<GEN;g++){
for(int s=0;s<NSITE;s++){
double a=0; for(int k=0;k<CAP;k++){ phic[s][k]=phi(cell[s][k]); a+=phic[s][k]; }
mphi[s]=a/CAP;
}
/* ---- walls: an unavoidable byproduct of local catalytic activity ---- */
if(mode==2||mode==4){ for(int s=0;s<NSITE;s++) wall[s]=1.0; }
else if(mode==0){ for(int s=0;s<NSITE;s++) wall[s]=0.0; }
else {
for(int s=0;s<NSITE;s++){
int t=(s+1)%NSITE;
double act=0.5*(mphi[s]+mphi[t])/PHIMAX; /* parasites deposit little: nothing to deposit */
double w=wall[s]*(1.0-DECAY)+dep*act;
if(w<0)w=0; if(w>1)w=1;
wall[s]=w;
}
if(mode==3){ /* B4: same heights, random edges */
for(int s=0;s<NSITE;s++) tmpw[s]=wall[s];
for(int s=NSITE-1;s>0;s--){ int j=(int)(xs()%(unsigned long long)(s+1)); double t=tmpw[s]; tmpw[s]=tmpw[j]; tmpw[j]=t; }
for(int s=0;s<NSITE;s++) wall[s]=tmpw[s];
}
}
/* ---- exchange across each edge, gated symmetrically by its wall ---- */
for(int s=0;s<NSITE;s++){
int t=(s+1)%NSITE;
double pm=MIGR*(1.0-wall[s]);
for(int k=0;k<CAP;k++){
if(urand()<pm){
int a=(int)(xs()%CAP), b=(int)(xs()%CAP);
uint32_t tmp=cell[s][a]; cell[s][a]=cell[t][b]; cell[t][b]=tmp;
}
}
}
/* ---- local catalysis -> local fidelity; replication within the site ---- */
for(int s=0;s<NSITE;s++){
double a=0; for(int k=0;k<CAP;k++){ phic[s][k]=phi(cell[s][k]); a+=phic[s][k]; }
mphi[s]=a/CAP;
double f=F0+(F1-F0)*(mphi[s]/PHIMAX);
double tot=0,cum[CAP];
for(int k=0;k<CAP;k++){ tot+=1.0+BETA*(1.0-(double)phic[s][k]/PHIMAX); cum[k]=tot; }
for(int k=0;k<CAP;k++){
double r=urand()*tot; int lo=0,hi=CAP-1;
while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; }
ncell[s][k]=replicate(cell[s][lo],f);
}
}
for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) cell[s][k]=ncell[s][k];
/* ---- between-site selection (modes 4/5): the stochastic-corrector step ribozyme.c has ----
Sites are sampled as parents in proportion to their catalytic content and reseeded by
random assortment. This is the SECOND LEVEL of selection; isolation alone is not it. */
if(mode==4||mode==5){
double tot=0; static double cums[NSITE];
for(int s=0;s<NSITE;s++){
double a=0; for(int k=0;k<CAP;k++) a+=phi(cell[s][k]);
tot+=a/CAP; cums[s]=tot;
}
for(int s=0;s<NSITE;s++){
double r=urand()*tot; int lo=0,hi=NSITE-1;
while(lo<hi){ int mid=(lo+hi)/2; if(cums[mid]<r) lo=mid+1; else hi=mid; }
for(int k=0;k<CAP;k++) ncell[s][k]=cell[lo][(int)(xs()%CAP)];
}
for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) cell[s][k]=ncell[s][k];
}
/* B5 diagnostics: wall height, and whether walls sit where the activity is */
{
double sw=0,sa=0,saw=0,sww=0,saa=0;
for(int s=0;s<NSITE;s++){
int t=(s+1)%NSITE;
double a=0.5*(mphi[s]+mphi[t])/PHIMAX, w=wall[s];
sw+=w; sa+=a; saw+=a*w; sww+=w*w; saa+=a*a;
}
double n=NSITE, cov=saw/n-(sa/n)*(sw/n);
double sdw=sqrt(fmax(1e-12,sww/n-(sw/n)*(sw/n))), sda=sqrt(fmax(1e-12,saa/n-(sa/n)*(sa/n)));
lastw=sw/n; lastc=cov/(sdw*sda);
}
}
double sp=0; for(int s=0;s<NSITE;s++) for(int k=0;k<CAP;k++) sp+=phi(cell[s][k]);
*wall_mean=lastw; *wall_corr=lastc;
return sp/TOTAL;
}
int main(void)
{
unsigned long long seeds[8];
seeds[0]=0x9e3779b97f4a7c15ULL; seeds[1]=0xd1b54a32d192ed03ULL; seeds[2]=0x2545f4914f6cdd1dULL;
for(int i=3;i<8;i++) seeds[i]=0x9e3779b97f4a7c15ULL ^ (0x100000001b3ULL*(unsigned long long)(i+1));
int NS=8;
printf("=== BYPRODUCT COMPARTMENT: a boundary nobody chooses to build ===\n");
printf(" Walls START AT ZERO and accumulate as a side effect of local catalysis; they decay.\n");
printf(" Wall-building is NON-DISCRETIONARY -- parasites are not forbidden from depositing,\n");
printf(" they simply have nothing to deposit. Walls gate mixing SYMMETRICALLY (in and out).\n");
printf(" %d sites x %d units = %d. The ONLY difference from the failed spatial arm is the wall.\n",NSITE,CAP,TOTAL);
printf(" REFERENCE: ribozyme well-mixed 5.99 -> 5.50; SUPPLIED compartments of 8 -> 11.34.\n\n");
printf(" deposition | WALL OFF | BYPRODUCT | SHUFFLED | SUPPLIED | SUP+sel | BYP+sel | wall mean | r\n");
printf(" -----------+----------+-----------+----------+----------+---------+---------+-----------+------\n");
double deps[]={0.00,0.05,0.10,0.20,0.40,0.80};
int ND=(int)(sizeof(deps)/sizeof(deps[0]));
double start=0, bestby=-1e9, bestdep=-1, byp_at_best=0, shf_at_best=0, off_at_best=0, sup_best=-1e9;
double sup_sel_best=-1e9, byp_sel_best=-1e9;
int informative=0;
for(int d=0;d<ND;d++){
double eo=0,eb=0,es=0,ep=0,e4=0,e5=0,wm=0,wc=0,ps=0;
for(int s=0;s<NS;s++){
double p,w,c;
RNG=seeds[s]; eo+=run(0,deps[d],&p,&w,&c);
RNG=seeds[s]; eb+=run(1,deps[d],&p,&w,&c); wm+=w; wc+=c; ps+=p;
RNG=seeds[s]; es+=run(3,deps[d],&p,&w,&c);
RNG=seeds[s]; ep+=run(2,deps[d],&p,&w,&c);
RNG=seeds[s]; e4+=run(4,deps[d],&p,&w,&c);
RNG=seeds[s]; e5+=run(5,deps[d],&p,&w,&c);
}
eo/=NS;eb/=NS;es/=NS;ep/=NS;e4/=NS;e5/=NS;wm/=NS;wc/=NS;ps/=NS;
start=ps;
printf(" %.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %5.2f | %.3f | %+.2f\n",
deps[d],eo,eb,es,ep,e4,e5,wm,wc);
if(e4>sup_sel_best) sup_sel_best=e4;
if(e5>byp_sel_best) byp_sel_best=e5;
if(wm>0.02 && wm<0.98 && wc>0.10) informative=1;
if(eb>bestby){ bestby=eb; bestdep=deps[d]; byp_at_best=eb; shf_at_best=es; off_at_best=eo; }
if(ep>sup_best) sup_best=ep;
}
printf("\n start phi (= neutral expectation) %.2f\n\n",start);
int b1 = off_at_best < start-0.2;
int b2 = sup_best > start+0.5;
int b2b= sup_sel_best > start+0.5;
int b3 = byp_at_best> start+0.5;
int b4 = shf_at_best< byp_at_best-0.2;
printf(" B1 wall OFF falls (spatial arm reproduced) : %s (%.2f)\n", b1?"YES":"no", off_at_best);
printf(" B2 wall SUPPLIED, isolation only : %s (%.2f)\n", b2?"YES":"NO", sup_best);
printf(" B2b SUPPLIED + between-site SELECTION : %s (%.2f) <- real positive control\n", b2b?"YES":"NO", sup_sel_best);
printf(" B2c BYPRODUCT + between-site selection : %.2f\n", byp_sel_best);
printf(" B3 BYPRODUCT rises above start : %s (%.2f at dep %.2f)\n", b3?"YES":"NO", byp_at_best,bestdep);
printf(" B4 SHUFFLED control below byproduct : %s (%.2f vs %.2f)\n", b4?"YES":"NO", shf_at_best,byp_at_best);
printf(" B5 walls formed, varied, and tracked activity: %s\n\n", informative?"YES":"NO");
if(!informative)
printf(" => THE TEST DID NOT RUN. Walls never formed in an informative regime (absent, saturated,\n"
" or uncorrelated with activity). Nothing here speaks to the byproduct mechanism.\n"
" Invalid experiment, NOT a null.\n");
else if(!b2 && !b2b)
printf(" => THE POSITIVE CONTROL FAILED EVEN WITH SELECTION. The lattice cannot cross at all.\n"
" Fix the model before reading anything into any arm.\n");
else if(!b2 && b2b)
printf(" => DIAGNOSIS: ISOLATION IS NOT COMPARTMENTALIZATION. Supplied walls alone do NOT cross\n"
" (%.2f); supplied walls PLUS between-site selection do (%.2f). What made compartments\n"
" work was never the barrier -- it was that compartments DIVIDE and are SELECTED on\n"
" catalytic content. A byproduct wall supplies the isolation half for free, and the\n"
" second-level selection half remains exactly as supplied as it ever was. Law 2's\n"
" non-discretionary fix addresses the WRONG HALF of what a compartment is.\n", sup_best, sup_sel_best);
else if(b3 && b4)
printf(" => A NON-DISCRETIONARY BOUNDARY CROSSES. Compartments formed from nothing but the side\n"
" effects of catalysis, and phi rose above its neutral start with no wall ever supplied\n"
" and no unit ever electing to build one. The shuffled control -- identical isolation,\n"
" wrong places -- did not rise, so the effect is the activity->wall coupling. This is the\n"
" Law 2 prediction confirmed: what fails is not the boundary but its DISCRETION.\n");
else if(b3 && !b4)
printf(" => CONFOUNDED. phi rose but the shuffled control rose too, so the effect is isolation per\n"
" se and not the activity->wall coupling. Claim nothing about byproduct compartments.\n");
else
printf(" => HONEST NULL, with the positive control PASSING. Supplied walls cross and byproduct\n"
" walls do not, so a boundary being non-discretionary is NOT sufficient -- it must also\n"
" arrive before the parasites do. Law 2 is necessary but not sufficient, and rung 1->2\n"
" stands open.\n");
return 0;
}