OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / basal-agent / rung34.c

93 lines · c ref:
/* rung34.c — does rung 4 (compartmentalization) EMERGE from rung 3, un-forced?
 *
 * The honest test (not hand-coding rung 4): compartmentalization is a HERITABLE trait
 * c in [0,1] that can mutate UP OR DOWN. It sets a lineage's compartment size
 * D(c) = Dmax at c=0 (big ~ well-mixed) -> Dmin at c=1 (tiny, strong compartmentalization).
 * Cooperators keep a compartment viable; parasites replicate faster within it (free-ride).
 * Survival is weighted by cooperator FRACTION (quality, size-neutral) — so nothing rewards
 * small compartments for being small. We only watch which way selection drives c.
 *
 * Mechanism (Szathmary-Demeter stochastic corrector): small compartments have HIGH variance
 * in cooperator fraction among daughters -> selection finds cooperator-rich ones -> maintains
 * cooperation AND (since only small D produces those) drives c UP. Large compartments: within-
 * level parasite growth wins, low variance, all daughters low-quality -> die. If c climbs on
 * its own, rung 4 EMERGED — selection discovered compartmentalization, we didn't impose it.
 * (We supply the OPTION — the law-space; evolution supplies the selection.)
 *
 * Control: freeze c (no mutation) at its low start -> cooperation should COLLAPSE.
 *
 * build:  cc -O2 -Wall -std=c11 -o rung34 rung34.c -lm
 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define NCOMP 600
#define GEN   500
#define SADV  0.6          /* parasite replication advantage */
#define DMIN  2
#define DMAX  40
#define MUTC  0.03
#define MUP   0.10        /* cooperator->parasite mutation: sustained parasite pressure */

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 double randn(void){ double u=urand(),v=urand(); if(u<1e-300)u=1e-300; return sqrt(-2*log(u))*cos(6.283185307*v); }
static int Dof(double c){ int D=(int)(DMIN+(1.0-c)*(DMAX-DMIN)+0.5); return D<DMIN?DMIN:(D>DMAX?DMAX:D); }
static int binom(int n,double p){ int k=0; for(int i=0;i<n;i++) if(urand()<p) k++; return k; }

static double cc[NCOMP]; static int nC[NCOMP];
static double dcc[2*NCOMP]; static int dnC[2*NCOMP], dD[2*NCOMP]; static double cum[2*NCOMP];

/* returns final mean c; writes final coop fraction to *coopf. evolve_c toggles c mutation. */
static double run(int evolve_c,double *coopf,int verbose){
	for(int i=0;i<NCOMP;i++){ cc[i]=0.10; nC[i]=Dof(0.10)/2; }   /* weak compartmentalization start */
	for(int g=0;g<GEN;g++){
		for(int i=0;i<NCOMP;i++){
			int D=Dof(cc[i]); int nc=nC[i]; if(nc>D)nc=D; int np=D-nc;
			double wc=nc, wp=np*(1.0+SADV); double p=(wc+wp>0)?wc/(wc+wp):0;
			int g2=binom(2*D,p); g2=binom(g2,1.0-MUP); double frac=(double)g2/(2*D);
			for(int d=0;d<2;d++){
				double c2 = evolve_c ? cc[i]+MUTC*randn() : cc[i];
				if(c2<0)c2=0; if(c2>1)c2=1;
				int D2=Dof(c2);
				dcc[2*i+d]=c2; dD[2*i+d]=D2; dnC[2*i+d]=binom(D2,frac);
			}
		}
		/* select NCOMP survivors weighted by cooperator FRACTION (size-neutral quality) */
		double tot=0; for(int i=0;i<2*NCOMP;i++){ tot+=(double)dnC[i]/dD[i]; cum[i]=tot; }
		if(tot<=0){ for(int i=0;i<NCOMP;i++){ nC[i]=0; } }
		else for(int i=0;i<NCOMP;i++){
			double r=urand()*tot; int lo=0,hi=2*NCOMP-1;
			while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; }
			cc[i]=dcc[lo]; nC[i]=dnC[lo];
		}
		if(verbose && (g%50==0||g==GEN-1)){
			double mc=0; long sc=0,sd=0; for(int i=0;i<NCOMP;i++){ mc+=cc[i]; int D=Dof(cc[i]); sc+=nC[i]; sd+=D; }
			fprintf(stderr,"    gen %3d  mean c=%.3f  D=%d  coop frac=%.3f\n",g,mc/NCOMP,Dof(mc/NCOMP),(double)sc/sd);
		}
	}
	double mc=0; long sc=0,sd=0; for(int i=0;i<NCOMP;i++){ mc+=cc[i]; sc+=nC[i]; sd+=Dof(cc[i]); }
	*coopf=(double)sc/sd; return mc/NCOMP;
}

int main(void){
	printf("=== RUNG 3 -> 4 EMERGENCE: does compartmentalization evolve un-forced? ===\n");
	printf("  trait c free to mutate up/down; D(c): c=0 -> D=%d (well-mixed), c=1 -> D=%d (compartmentalized)\n",DMAX,DMIN);
	printf("  start c=0.10 (weak); parasite advantage %.0f%%\n\n",SADV*100);

	fprintf(stderr,"  [c EVOLVABLE]\n");
	RNG=0x9e3779b97f4a7c15ULL; double cf1; double c1=run(1,&cf1,1);
	fprintf(stderr,"  [c FROZEN — control]\n");
	RNG=0x9e3779b97f4a7c15ULL; double cf0; double c0=run(0,&cf0,1);

	printf("  c EVOLVABLE : final mean c = %.3f (D=%d)   cooperation frac = %.3f\n",c1,Dof(c1),cf1);
	printf("  c FROZEN    : final mean c = %.3f (D=%d)   cooperation frac = %.3f\n",c0,Dof(c0),cf0);
	printf("\n  %s\n", (c1>0.4 && cf1>0.3)
	   ? "=> compartmentalization EVOLVED UP on its own and rescued cooperation. Rung 4 EMERGED."
	   : "=> compartmentalization did not clearly emerge here — see trajectory / tune the world.");
	printf("     (We supplied the option to compartmentalize; the world's parasite pressure selected it.)\n");
	return 0;
}