OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent / bridge.c

81 lines · c ref:
/* bridge.c — bridging the rung 4->5 coordination valley: drift vs duplication.
 *
 * rung45 stalled: CONVERT (generalist->specialist) drops other functions' coverage ->
 * viability falls -> deleterious -> purged. A coordination valley.
 *
 * Two candidate bridges, both ways of NOT hill-climbing straight up:
 *   - DRIFT (temperature): accept the small deleterious step by chance.
 *   - DUPLICATION: ADD a specialist without removing the generalist (size grows) -> other
 *     functions' coverage unchanged -> the step is NEUTRAL; once all F specialists have drifted
 *     in, the weakest function is covered and viability JUMPS. Neutral steps need no drift.
 *
 * Sweep temperature (drift strength) x {CONVERT-only, DUPLICATION}. Prediction: cold (weak
 * drift) -> CONVERT stalls in the displacement valley, DUPLICATION still crosses; warm -> both
 * cross. => drift and duplication are SUBSTITUTE bridges; you need at least one.
 *
 * build:  cc -O2 -Wall -std=c11 -o bridge bridge.c -lm
 */
#include <math.h>
#include <stdio.h>

#define F 3
#define EGEN 0.2
#define LAMBDA 0.02
#define DMIN 3
#define DMAX 30
#define STEPS 400000
#define TRIES 8

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 sizeof_(int G,const int*sp){ int s=G; for(int k=0;k<F;k++) s+=sp[k]; return s; }
static double mincov(int G,const int*sp){ double m=1e9; for(int k=0;k<F;k++){ double c=sp[k]+EGEN*G; if(c<m)m=c; } return m; }
static double fit(int G,const int*sp){ return mincov(G,sp)-LAMBDA*sizeof_(G,sp); }

/* one Metropolis run from all-generalist; returns best min-coverage reached */
static double run(int dup,double TMP,int *Gout,int *spout){
	int G=12, sp[F]={0,0,0};
	double f=fit(G,sp);
	int bG=G,bsp[F]={0,0,0}; double bmc=mincov(G,sp);
	for(int t=0;t<STEPS;t++){
		int G2=G, s2[F]; for(int k=0;k<F;k++) s2[k]=sp[k];
		double r=urand();
		if(dup && r<0.5){                                  /* size-changing (duplication / loss) */
			if(urand()<0.5 && sizeof_(G2,s2)<DMAX){ if(urand()<0.4) G2++; else s2[(int)(xs()%F)]++; }
			else if(sizeof_(G2,s2)>DMIN){ if(urand()<0.4 && G2>0) G2--; else { int k=(int)(xs()%F); if(s2[k]>0) s2[k]--; else if(G2>0) G2--; } }
		} else {                                           /* CONVERT (size fixed = displacement) */
			if(urand()<0.5){ if(G2>0){ G2--; s2[(int)(xs()%F)]++; } }
			else { int k=(int)(xs()%F); if(s2[k]>0){ s2[k]--; G2++; } }
		}
		int sz=sizeof_(G2,s2); if(sz<DMIN||sz>DMAX) continue;
		double f2=fit(G2,s2), df=f2-f;
		if(df>=0 || urand()<exp(df/TMP)){ G=G2; for(int k=0;k<F;k++) sp[k]=s2[k]; f=f2;
			double mc=mincov(G,sp); if(mc>bmc){ bmc=mc; bG=G; for(int k=0;k<F;k++) bsp[k]=sp[k]; } }
	}
	*Gout=bG; for(int k=0;k<F;k++) spout[k]=bsp[k]; return bmc;
}

int main(void){
	printf("=== BRIDGING THE 4->5 VALLEY: drift (temperature) vs duplication ===\n");
	printf("  all-generalist baseline min-coverage = %.2f ; crossing = all 3 specialists present\n\n", EGEN*12);
	double temps[4]={0.005,0.02,0.05,0.12};
	printf("  %-10s %-24s %-24s\n","T (drift)","CONVERT-only","DUPLICATION");
	for(int ti=0;ti<4;ti++){
		int cross[2]={0,0}; double best[2]={0,0};
		for(int mode=0;mode<2;mode++) for(int tr=0;tr<TRIES;tr++){
			RNG=0x9e3779b97f4a7c15ULL + (unsigned long long)(ti*1000+mode*100+tr)*0x2545F4914F6CDD1DULL;
			int G,sp[F]; double mc=run(mode,temps[ti],&G,sp);
			if(sp[0]>0&&sp[1]>0&&sp[2]>0 && mc>EGEN*12+0.3) cross[mode]++;
			if(mc>best[mode]) best[mode]=mc;
		}
		printf("  %-10.3f %d/%d crossed (mincov %-4.1f)  %d/%d crossed (mincov %-4.1f)\n",
		       temps[ti],cross[0],TRIES,best[0],cross[1],TRIES,best[1]);
	}
	printf("\n  Cold (weak drift): CONVERT stalls in the displacement valley; DUPLICATION still crosses\n");
	printf("  (its steps are neutral, needing no drift). Warm: both cross. => drift and duplication\n");
	printf("  are SUBSTITUTE bridges over a coordination valley — you need at least one.\n");
	return 0;
}