OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent / rung1.c

96 lines · c ref:
/* rung1.c — the autocatalytic set (RAF): self-producing closure ignites at a threshold.
 *
 * Rung 1 of the ladder, built on the corrected principle: GIVEN lawful rules (a random
 * catalytic reaction network) + EMERGENT coherence (the largest self-sustaining subset
 * ignites at a critical catalysis density — a percolation transition, the "laser" of
 * self-production). The structure (reactions) is supplied; the AGENT (the RAF) emerges.
 *
 * A RAF (Reflexively Autocatalytic, Food-generated set; Kauffman; Hordijk & Steel) is a
 * subset of reactions R such that every reaction in R is (a) SUPPORTED — its reactants
 * are producible from the food set F using R, and (b) CATALYZED by a molecule producible
 * from F using R. The maxRAF = prune-to-fixpoint: repeatedly drop reactions that aren't
 * supported+catalyzed given what's currently producible.
 *
 * Sweep the catalysis probability p. Below a critical p the maxRAF is empty (no self-
 * production — dies); above it a system-spanning RAF snaps on. That threshold is the
 * coherence of self-production — the minimal bootstrap, condensing out of GIVEN chemistry.
 *
 * build:  cc -O2 -Wall -std=c11 -o rung1 rung1.c -lm
 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N    60        /* molecule types */
#define NF   8         /* food types (0..NF-1, always available) */
#define M    300       /* reactions (2 reactants -> 1 product) */
#define INST 60        /* random network instances averaged per p */

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 rint_(int n){ return (int)(xs()%(unsigned)n); }

static int r1[M],r2[M],prod[M];
static unsigned char cat[M][N];     /* cat[j][m]=1 : molecule m catalyzes reaction j */
static int active[M];
static unsigned char W[N];

/* build a random catalytic reaction network; each molecule catalyzes each reaction w.p. p */
static void build_net(double p){
	for(int j=0;j<M;j++){
		r1[j]=rint_(N); r2[j]=rint_(N);
		prod[j]=NF+rint_(N-NF);                 /* products are non-food (must be made) */
		for(int m=0;m<N;m++) cat[j][m]=(urand()<p)?1:0;
	}
}

/* maxRAF size (number of reactions) via prune-to-fixpoint */
static int max_raf(void){
	for(int j=0;j<M;j++) active[j]=1;
	for(;;){
		/* closure: producible set W from food, using catalyzed+supported active reactions */
		for(int m=0;m<N;m++) W[m]=(m<NF)?1:0;
		int grew=1;
		while(grew){ grew=0;
			for(int j=0;j<M;j++){ if(!active[j]) continue;
				if(!W[r1[j]]||!W[r2[j]]||W[prod[j]]) continue;
				int cz=0; for(int m=0;m<N;m++) if(cat[j][m]&&W[m]){cz=1;break;}
				if(cz){ W[prod[j]]=1; grew=1; }
			}
		}
		/* prune reactions not supported+catalyzed within W */
		int changed=0;
		for(int j=0;j<M;j++){ if(!active[j]) continue;
			int sup=W[r1[j]]&&W[r2[j]];
			int cz=0; for(int m=0;m<N;m++) if(cat[j][m]&&W[m]){cz=1;break;}
			if(!(sup&&cz)){ active[j]=0; changed=1; }
		}
		if(!changed) break;
	}
	int n=0; for(int j=0;j<M;j++) n+=active[j];
	return n;
}

int main(void){
	printf("=== RUNG 1: AUTOCATALYTIC SET (RAF) — self-production ignites at a threshold ===\n");
	printf("  N=%d molecules, %d food, M=%d reactions; maxRAF size vs catalysis density\n",N,NF,M);
	printf("  %-7s %8s %10s %8s\n","p","f=p*M","maxRAF","P(RAF>0)");
	for(int pi=1;pi<=18;pi++){
		double p=pi*0.003;
		double sz=0; int nz=0;
		for(int inst=0;inst<INST;inst++){
			RNG=0x9e3779b97f4a7c15ULL + (unsigned long long)(pi*10007+inst)*0x2545F4914F6CDD1DULL;
			build_net(p); int s=max_raf(); sz+=s; if(s>0) nz++;
		}
		double meansz=sz/INST, frac=(double)nz/INST, f=p*M;
		int bar=(int)(meansz*0.4+0.5); char b[80]; for(int k=0;k<bar&&k<70;k++)b[k]='#'; b[bar<70?bar:70]=0;
		printf("  %-7.4f %8.2f %10.1f %8.2f  %s\n",p,f,meansz,frac,b);
	}
	printf("\n  Below a critical catalysis density the maxRAF is empty (no self-production).\n");
	printf("  Above it a system-spanning autocatalytic set SNAPS ON — the coherence of\n");
	printf("  self-production condensing out of given chemistry. That is rung 1.\n");
	return 0;
}