OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent / window.c

88 lines · c ref:
/* window.c — the evolutionary WINDOW: adaptation is maximized at an INTERIOR copy-error rate,
 * failing toward BOTH mu=0 (no variation for selection to act on) and mu past the error threshold
 * (catastrophe — the assembled target can't be held). This answers "faithful copying is never
 * perfect in nature": the target was never mu=0. Life sits in the window between MEMORY and
 * EXPLORATION, and what a templated (tunable) error rate buys is the ability to sit there.
 *
 * Genome-level model (the module abstraction template.c earned): M binary modules, templated copy
 * with per-module error mu, population P, fitness = # of TARGET modules present. The population starts
 * SPARSE and FAR from a multi-module target it must ASSEMBLE by mutation+selection. Measured as the
 * ABSOLUTE final adaptation (mean target modules present), NOT a start->end delta -> no headroom
 * confound; sparse start -> mu=0 genuinely cannot reach the target (no "already solved at init").
 *
 * Nothing encodes WHERE the optimum is; the window emerges from the mutation-selection balance. This
 * REPRODUCES the known error-threshold / optimal-mutation-rate result (Eigen) in our own terms --
 * confirmation that our model contains the window, not a novel claim.
 *
 * build:  cc -O2 -Wall -std=c11 -o window window.c -lm
 */
#include <math.h>
#include <stdio.h>

#define M     20        /* modules (genome length) */
#define T     10        /* target modules that should be PRESENT (indices 0..T-1) */
#define P     300       /* population */
#define G     80        /* generations */
#define INITP 0.20      /* sparse start: each module present w.p. 0.20 -> target far, mostly absent */
#define SS    0.70      /* selection strength: fitness = exp(SS * #target-present) */

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 pop[P][M], nxt[P][M];
static double fit[P], cum[P];

static int ntarget(const int*g){ int s=0; for(int m=0;m<T;m++) s+=g[m]; return s; }
static int nnon(const int*g){ int s=0; for(int m=T;m<M;m++) s+=g[m]; return s; }

/* one run at error rate mu. returns final mean target-present; writes final mean nontarget-present. */
static double run(double mu, double *mean_non){
	for(int p=0;p<P;p++) for(int m=0;m<M;m++) pop[p][m]=(urand()<INITP);
	for(int g=0;g<G;g++){
		double tot=0; for(int p=0;p<P;p++){ fit[p]=exp(SS*ntarget(pop[p])); tot+=fit[p]; cum[p]=tot; }
		for(int p=0;p<P;p++){
			double r=urand()*tot; int lo=0,hi=P-1; while(lo<hi){int mid=(lo+hi)/2; if(cum[mid]<r)lo=mid+1; else hi=mid;} int par=lo;
			for(int m=0;m<M;m++){ int b=pop[par][m]; if(urand()<mu) b^=1; nxt[p][m]=b; }   /* templated copy, per-module flip */
		}
		for(int p=0;p<P;p++) for(int m=0;m<M;m++) pop[p][m]=nxt[p][m];
	}
	double st=0,sn=0; for(int p=0;p<P;p++){ st+=ntarget(pop[p]); sn+=nnon(pop[p]); }
	*mean_non = sn/P; return st/P;
}

int main(void){
	double mus[]={0.0,0.005,0.01,0.02,0.05,0.10,0.20,0.35,0.50}; int nMU=sizeof(mus)/sizeof(double);
	unsigned long long seeds[]={0x9e3779b97f4a7c15ULL,0xd1b54a32d192ed03ULL,0x2545f4914f6cdd1dULL,0x123456789abcdefULL,
	                            0xfeedface12345678ULL,0xa5a5a5a5a5a5a5a5ULL,0x0f0f0f0f0f0f0f0fULL,0xcafebabedeadbeefULL};
	int NS=sizeof(seeds)/sizeof(seeds[0]);

	printf("=== The evolutionary WINDOW: adaptation vs per-module copy error mu ===\n");
	printf("  M=%d modules, target=%d must be assembled, sparse start (p=%.2f), pop=%d, %d gens, %d seeds.\n",M,T,INITP,P,G,NS);
	printf("  Fitness = exp(%.2f * #target-present). Measured: ABSOLUTE final mean target-present (max %d).\n\n",SS,T);
	printf("    mu    | target-present (of %2d) | nontarget (of %2d, unselected)\n",T,M-T);
	printf("    ------+------------------------+------------------------------\n");

	double best=-1; double best_mu=-1; double tvals[16];
	for(int i=0;i<nMU;i++){
		double st=0,sn=0;
		for(int s=0;s<NS;s++){ double mn; RNG=seeds[s]; st+=run(mus[i],&mn); sn+=mn; }
		st/=NS; sn/=NS; tvals[i]=st;
		int bar=(int)(st*2.0+0.5); char b[64]; int k; for(k=0;k<bar&&k<40;k++) b[k]='#'; b[k]=0;
		printf("    %.3f |   %5.2f  %-14s|   %4.2f\n", mus[i], st, b, sn);
		if(st>best){ best=st; best_mu=mus[i]; }
	}
	printf("\n");

	int interior = (best_mu>0.0 && best_mu<mus[nMU-1]);
	double at_zero=tvals[0], at_top=tvals[nMU-1];
	printf("  peak adaptation at mu* = %.3f  (target-present %.2f of %d)\n", best_mu, best, T);
	printf("  ends: mu=0 -> %.2f (no variation: frozen at best initial), mu=%.2f -> %.2f (catastrophe)\n", at_zero, mus[nMU-1], at_top);
	printf("\n");
	if(interior && best > at_zero+0.5 && best > at_top+0.5)
		printf("  => WINDOW CONFIRMED. Adaptation peaks at an INTERIOR error rate and falls off toward BOTH\n     ends: mu=0 has no variation for selection to assemble the target (frozen at the best it started\n     with); high mu is past the error threshold (the assembled target randomizes away, -> ~%.0f/%d like\n     the unselected bits). Faithful copying was never the goal -- the goal is the window between memory\n     and exploration, and a TUNABLE (templated) error rate is what makes sitting in it possible. This\n     reproduces Eigen's error-threshold / optimal-mutation-rate result in our own model.\n", at_top, T);
	else
		printf("  => No clean interior optimum in this range (peak mu*=%.3f). Report as-is; do not tune to force it.\n",best_mu);
	return 0;
}