OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent / byproduct.c

290 lines · c ref:
/* 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;
}