OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent / rung2.c

73 lines · c ref:
/* rung2.c — the self-templating form: the first HEREDITY, built on rung 1.
 *
 * Rung 1 (RAF) self-PRODUCES but has no heritable form. Rung 2 adds structures that
 * TEMPLATE copies of themselves (prion-/crystal-like): a variant propagates its OWN
 * form, so which form is present is TRANSMITTED — proto-heredity. The forms compete for
 * substrate that rung 1's metabolism supplies (the pool is kept fed).
 *
 * Dynamics = discrete replicator-with-mutation (Eigen, low-dimensional):
 *   x'_i = sum_j Q[i][j] f[j] x[j] / normalization ;  Q[i][j] = (1-eps) if i==j else eps/(Q-1)
 * f = templating rate (fitness, environment-dependent); eps = copying error.
 *
 * Two emergent phenomena that rung 1 lacks:
 *   A. COHERENT TAKEOVER + SELECTION (the "laser"): from a mix, the fittest heritable
 *      form excludes the rest; switch the environment and a DIFFERENT form takes over —
 *      heredity + selection = the system tracks its world (proto-adaptation).
 *   B. FIDELITY requirement: raise the copying error and the winner's dominance erodes
 *      toward a formless mix — heredity needs fidelity. (The SHARP version of this is
 *      rung 3's error catastrophe, once forms become high-dimensional sequences.)
 *
 * build:  cc -O2 -Wall -std=c11 -o rung2 rung2.c -lm
 */
#include <math.h>
#include <stdio.h>

#define Q 4                         /* number of competing self-templating forms */

/* one replicator+mutation step; returns nothing, updates x in place */
static void step(double *x,const double *f,double eps){
	double nx[Q],tot=0;
	for(int i=0;i<Q;i++){
		nx[i]=0;
		for(int j=0;j<Q;j++){
			double Qij=(i==j)?(1.0-eps):(eps/(Q-1));
			nx[i]+=Qij*f[j]*x[j];   /* j templates; copies land on i via the mutation matrix */
		}
		tot+=nx[i];
	}
	if(tot<1e-300)tot=1e-300;
	for(int i=0;i<Q;i++) x[i]=nx[i]/tot;   /* normalize: rung-1 keeps the pool fed */
}
static int argmax(const double *x){ int a=0; for(int i=1;i<Q;i++) if(x[i]>x[a])a=i; return a; }

int main(void){
	printf("=== RUNG 2: SELF-TEMPLATING FORM — heredity + coherent takeover ===\n\n");

	/* --- Demo A: coherent takeover, then environmental switch (adaptation) --- */
	printf("A. Coherent takeover + selection (forms start as an even mix):\n");
	double x[Q]={0.25,0.25,0.25,0.25};
	double fA[Q]={1.00,0.90,0.80,0.70};       /* form 0 templates fastest */
	double eps=0.02;
	printf("   env-1 (form 0 fittest):\n");
	for(int t=0;t<=80;t++){ if(t%20==0) printf("     t=%3d  x=[%.2f %.2f %.2f %.2f]  winner=%d\n",t,x[0],x[1],x[2],x[3],argmax(x)); step(x,fA,eps); }
	double fB[Q]={0.70,0.80,0.90,1.00};       /* ENVIRONMENT SWITCH: now form 3 fittest */
	printf("   env-2 (switch -> form 3 fittest): the population re-coheres onto the new winner\n");
	for(int t=0;t<=80;t++){ if(t%20==0) printf("     t=%3d  x=[%.2f %.2f %.2f %.2f]  winner=%d\n",t,x[0],x[1],x[2],x[3],argmax(x)); step(x,fB,eps); }

	/* --- Demo B: fidelity requirement (error erodes heredity) --- */
	printf("\nB. Fidelity requirement — dominance of the fittest form vs copying error eps:\n");
	printf("   %-7s %12s\n","eps","dominant frac");
	double f[Q]={1.00,0.85,0.70,0.55};
	for(int ei=0;ei<=12;ei++){
		double e=ei*0.05;
		double y[Q]={0.25,0.25,0.25,0.25};
		for(int t=0;t<3000;t++) step(y,f,e);   /* to steady state */
		double dom=y[argmax(y)];
		int bar=(int)(dom*40+0.5); char b[64]; for(int k=0;k<bar&&k<50;k++)b[k]='#'; b[bar<50?bar:50]=0;
		printf("   %-7.2f %12.3f  %s\n",e,dom,b);
	}
	printf("\n   Low error: the fittest form dominates (heredity holds). Rising error erodes it\n");
	printf("   toward 1/Q=%.2f (formless mix) — heredity needs fidelity. rung 3 makes this SHARP.\n",1.0/Q);
	return 0;
}