OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / basal-agent / template.c

141 lines · c ref:
/* template.c — SAMPLED vs TEMPLATED heredity: the affirmative test of digigard's core claim.
 *
 * digigard.c showed DIGITAL modules inherited by POOL-SAMPLING (a random 50% split of the token
 * pool, then regrow) do NOT breed true well and selection FAILED (favored module dropped 0.46->0.27).
 * The session concluded: the real wall is SAMPLED-vs-TEMPLATED, not digital-vs-analog. Pool-sampling
 * is copy-number-limited (Eigen's error threshold in disguise) -> only a FEW units breed true.
 * TEMPLATED copying (each module copied faithfully, INDEPENDENT of copy number, per-unit error mu)
 * should raise that ceiling to ~1/mu units. We never TESTED this. This does.
 *
 * The test is NOT "make copy perfect, watch heredity=1" (tautological). It is the PHASE BOUNDARY:
 * fix the resource budget S, sweep genome size M, run BOTH inheritance modes with everything else
 * identical, and locate where each collapses. Prediction (limited-vs-unlimited heredity, Szathmary):
 *   SAMPLED  collapses at SMALL M   (tokens/module = S/M shrinks -> sampling noise loses modules)
 *   TEMPLATED holds to LARGE M      (until M*mu ~ 1, the fidelity/Eigen limit)
 * The crossover is the measured result. If instead templated ALSO dies at small M, the claim is wrong.
 *
 * HONESTY: the templated-copy primitive copies the PARENT genome (target-blind); it never references
 * the selection target (module 0). Selection is world-supplied (module-0 carriers divide faster) and
 * SEPARATE from copying. Whether selection then HOLDS the favored module, and where the threshold
 * falls, is measured, not encoded. Same discipline as Part A: a directed-read primitive, outcome open.
 *
 * build:  cc -O2 -Wall -std=c11 -o template template.c -lm
 */
#include <math.h>
#include <stdio.h>
#include <string.h>

#define MAXM 24
#define K    4                 /* tokens per module (clique size) */
#define MAXN (MAXM*K)
#define S    200               /* compartment size (FIXED resource budget across the whole sweep) */
#define POCK 150
#define GEN  40
#define MAT  800
#define RHO0 0.10              /* weak basal seeding */
#define MU   0.02              /* per-module templated copy error (predicts ceiling ~1/MU = 50 modules) */

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); }

/* chemistry + growth machinery: identical in spirit to digigard, parameterized by M (N=M*K) */
static int M, N;
static double beta[MAXN][MAXN], rate[MAXN];
static void build_chem(void){ for(int i=0;i<N;i++)for(int j=0;j<N;j++) beta[i][j] = (i!=j && i/K==j/K) ? exp(0.4*randn())*1.2 : 0.0; }
static void recompute(const int*n){ for(int i=0;i<N;i++){ double r=RHO0; for(int j=0;j<N;j++) r+=beta[i][j]*n[j]; rate[i]=r; } }
static int pick_add(void){ double t=0; for(int i=0;i<N;i++)t+=rate[i]; double u=urand()*t,a=0; for(int i=0;i<N;i++){a+=rate[i];if(u<=a)return i;} return N-1; }
static int pick_rem(const int*n,int sz){ double u=urand()*sz,a=0; for(int j=0;j<N;j++){a+=n[j];if(u<=a)return j;} return N-1; }
static void addm(int*n,int i){ n[i]++; for(int k=0;k<N;k++) rate[k]+=beta[k][i]; }
static void remm(int*n,int j){ n[j]--; for(int k=0;k<N;k++) rate[k]-=beta[k][j]; }
static void mature(int*n,int sz){ recompute(n); for(int t=0;t<MAT;t++){ int j=pick_rem(n,sz); remm(n,j); addm(n,pick_add()); } }
static void grow_to(int*n,int*sz,int tgt){ recompute(n); while(*sz<tgt){ addm(n,pick_add()); (*sz)++; } }
static int thresh(void){ return S/(2*M); }
static void genome(const int*n,int*g){ int th=thresh(); for(int m=0;m<M;m++){ int s=0; for(int t=m*K;t<(m+1)*K;t++) s+=n[t]; g[m]=(s>th); } }
static double bitmatch(const int*ga,const int*gb){ int e=0; for(int m=0;m<M;m++) if(ga[m]==gb[m]) e++; return (double)e/M; }

static int pk[POCK][MAXN], nxt[POCK][MAXN];
static double fit[POCK], cum[POCK];

/* one full run for a given M and inheritance mode. returns heredity signal; writes selection start/end. */
static double run(int mode /*0=sampled 1=templated*/, double *f_start, double *f_end)
{
	/* init: each pocket seeds a RANDOM SUBSET of modules -> combinatorial variation */
	for(int p=0;p<POCK;p++){ memset(pk[p],0,sizeof pk[p]); int present[MAXM],np=0;
		for(int m=0;m<M;m++){present[m]=(urand()<0.5); if(present[m])np++;} if(np==0){present[0]=1;np=1;}
		for(int s=0;s<S;s++){ int m; do{ m=(int)(xs()%M); }while(!present[m]); pk[p][m*K+(int)(xs()%K)]++; }
		mature(pk[p],S); }

	double dig=0; int hc=0; double tgt_start=0,tgt_end=0;
	for(int g=0;g<GEN;g++){
		double tot=0; for(int p=0;p<POCK;p++){ int gp[MAXM]; genome(pk[p],gp); fit[p]=0.3+(gp[0]?1.0:0.0); tot+=fit[p]; cum[p]=tot; }
		if(g==1){ double f=0; for(int p=0;p<POCK;p++){int gp[MAXM];genome(pk[p],gp);f+=gp[0];} tgt_start=f/POCK; }
		for(int p=0;p<POCK;p++){
			double r=urand()*tot; int lo=0,hi=POCK-1; while(lo<hi){int mid=(lo+hi)/2; if(cum[mid]<r)lo=mid+1; else hi=mid;} int par=lo;
			int D[MAXN]; memset(D,0,sizeof D); int ds=0;
			if(mode==0){
				/* SAMPLED (digigard): daughter = random 50% subsample of the parent token pool */
				for(int i=0;i<N;i++) for(int c=0;c<pk[par][i];c++) if(urand()<0.5){ D[i]++; ds++; }
				if(ds<1){D[0]=1;ds=1;}
			} else {
				/* TEMPLATED: read parent genome, copy each MODULE faithfully (per-unit error MU,
				   independent of copy number). Seed present modules with a clique starter. */
				int gpar[MAXM]; genome(pk[par],gpar);
				for(int m=0;m<M;m++){ int bit=gpar[m]; if(urand()<MU) bit^=1;   /* faithful copy, per-unit flip */
					if(bit){ for(int t=m*K;t<(m+1)*K;t++){ D[t]++; ds++; } } }
				if(ds<1){ for(int t=0;t<K;t++){D[t]++;ds++;} }
			}
			grow_to(D,&ds,S); mature(D,S);
			memcpy(nxt[p],D,sizeof D);
			if(g>GEN/2){ int rp=(int)(xs()%POCK); int gd[MAXM],gpar[MAXM],grn[MAXM]; genome(D,gd); genome(pk[par],gpar); genome(pk[rp],grn);
				dig += bitmatch(gd,gpar)-bitmatch(gd,grn); hc++; }
		}
		memcpy(pk,nxt,sizeof pk);
	}
	{ double f=0; for(int p=0;p<POCK;p++){int gp[MAXM];genome(pk[p],gp);f+=gp[0];} tgt_end=f/POCK; }
	*f_start = tgt_start; *f_end = tgt_end;
	return hc?dig/hc:0;
}

int main(void){
	printf("=== SAMPLED vs TEMPLATED heredity (the phase boundary) ===\n");
	printf("  Fixed budget S=%d, per-module templated error MU=%.2f (predicted ceiling ~1/MU=%.0f modules).\n",S,MU,1.0/MU);
	printf("  Heredity = bit-match(daughter,parent) - bit-match(daughter,random). Selection favors module 0.\n\n");
	printf("   M  tok/mod |  SAMPLED   her   sel(start->end) |  TEMPLATED her   sel(start->end)\n");
	printf("  ------------+----------------------------------+---------------------------------\n");

	int Msweep[]={3,6,10,14,20}; int nM=sizeof(Msweep)/sizeof(int);
	double hSamp[8], hTempl[8], selS[8], selT[8];
	for(int mi=0;mi<nM;mi++){
		M=Msweep[mi]; N=M*K;
		RNG=0x9e3779b97f4a7c15ULL; build_chem();   /* same seed+chem per M so the two modes are comparable */
		double s0,s1,t0,t1;
		double hS=run(0,&s0,&s1);
		RNG=0x9e3779b97f4a7c15ULL; build_chem();
		double hT=run(1,&t0,&t1);
		hSamp[mi]=hS; hTempl[mi]=hT; selS[mi]=s1-s0; selT[mi]=t1-t0;
		printf("  %3d   %4d   |   %+.3f   %.2f->%.2f (%+.3f) |    %+.3f   %.2f->%.2f (%+.3f)\n",
		       M,S/M, hS, s0,s1, s1-s0,  hT, t0,t1, t1-t0);
	}
	printf("\n");

	/* The claim's actual predictions, tested directly (no single hand-set pass/fail bar):
	   P1 heredity: sampled DECAYS with genome size, templated does NOT -> the gap WIDENS.
	   P2 selection: sampled INVERTS to negative at large M (favored trait lost), templated stays positive. */
	double gap_small = hTempl[0]-hSamp[0], gap_big = hTempl[nM-1]-hSamp[nM-1];
	int samp_neg=0; for(int i=0;i<nM;i++) if(selS[i] < -0.01) samp_neg=1;
	int templ_pos_all=1; for(int i=0;i<nM;i++) if(selT[i] < -0.01) templ_pos_all=0;
	printf("  P1 heredity gap (templated-sampled): M=%d -> %+.3f,  M=%d -> %+.3f  [%s]\n",
	       Msweep[0],gap_small,Msweep[nM-1],gap_big, gap_big>gap_small?"WIDENS with genome size":"does not widen");
	printf("  P2 selection at largest M: sampled %+.3f%s, templated %+.3f%s\n",
	       selS[nM-1], selS[nM-1]<-0.01?" (INVERTED: favored trait lost)":"", selT[nM-1], selT[nM-1]>0?" (held)":"");
	printf("\n");

	if(gap_big>gap_small && samp_neg && templ_pos_all)
		printf("  => The wall is SAMPLED vs TEMPLATED, confirmed. Pool-sampling is copy-number-limited: as the\n     genome outgrows the fixed token budget (tokens/module = S/M shrinks), heredity decays and\n     SELECTION INVERTS -- the favored module is actively lost. Templated copying is fidelity-limited,\n     not copy-number-limited: heredity stays high and selection stays positive across the whole sweep.\n     This is Szathmary's limited-vs-unlimited heredity, measured as a phase boundary in our own\n     chemistry -- the affirmative half of digigard's null, and why life needed a TEMPLATE, not a\n     bag of sampled metabolic modules. (Templated small-M selDelta is a headroom ceiling: strong\n     selection near-fixes module-0 before the g=1 baseline, not a failure -- see start->end columns.)\n");
	else
		printf("  => Predictions not jointly met -- report the table as-is; do NOT tune to force the claim.\n");
	return 0;
}