/* digigard.c — DIGITAL module inheritance vs ANALOG composition (rung 1->2, the decisive test).
*
* gardenv showed: analog composition (composomes) does NOT breed true across splits (fidelity wall),
* even with environmental compartments + multiple attractors. The session's core claim is that the
* escape is to make the inherited unit DIGITAL (discrete modules on/off), not analog. Hordijk-Steel's
* "network-level heredity" (which subRAFs are present) is exactly that. This tests it directly.
*
* Digital, not organic: N tokens partitioned into M non-interfering self-sustaining cliques (modules).
* A compartment = token composition; its DIGITAL GENOME = which modules are present (bit vector,
* READ from the composition, not stored separately). Environmental pockets + split/regrow + selection,
* identical to gardenv. Measured (not encoded): does the DIGITAL module-set breed true across splits
* (Hamming match daughter~parent >> random), and does the ANALOG composition, in the SAME run? Plus
* selectability of a target module.
*
* HONEST BOUNDARY: I supply the MODULAR substrate (cliques). Whether such modular/subRAF structure
* arises on its own from random chemistry is the deeper open problem gardenv couldn't solve. This
* tests only: IF the substrate is modular/digital, does heredity work where analog failed?
*
* build: cc -O2 -Wall -std=c11 -o digigard digigard.c -lm
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#define M 12 /* modules (the digital genome has M bits) */
#define K 4 /* tokens per module */
#define N (M*K) /* 48 tokens */
#define S 180 /* compartment size */
#define POCK 200
#define GEN 60
#define MAT 1200
#define RHO0 0.10 /* weak basal: a whole clique rarely self-seeds -> low mutation */
#define THRESH (S/(2*M)) /* module 'present' if its tokens exceed this */
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); }
static double beta[N][N], rate[N];
static void build_chem(void){ /* MODULAR: strong mutual catalysis WITHIN a clique, none between */
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 double cosv(const int*a,const int*b){ double d=0,na=0,nb=0; for(int i=0;i<N;i++){ d+=(double)a[i]*b[i]; na+=(double)a[i]*a[i]; nb+=(double)b[i]*b[i]; } if(na<=0||nb<=0)return 0; return d/(sqrt(na)*sqrt(nb)); }
static void genome(const int*n,int*g){ 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>THRESH); } }
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][N], nxt[POCK][N];
static double fit[POCK], cum[POCK];
int main(void){
RNG=0x9e3779b97f4a7c15ULL; build_chem();
printf("=== DIGITAL module inheritance vs ANALOG composition (rung 1->2) ===\n");
printf(" %d modules (M-bit genome), %d environmental pockets. gardenv (analog) gave heredity ~0.\n\n",M,POCK);
/* 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[M],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, ana=0; int hc=0; int SEL=1; /* selection favors module 0 present */
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[M]; genome(pk[p],gp); fit[p]= SEL? (0.3+(gp[0]?1.0:0.0)) : 1.0; tot+=fit[p]; cum[p]=tot; }
if(g==1){ double f=0; for(int p=0;p<POCK;p++){int gp[M];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[N]; memset(D,0,sizeof D); int ds=0;
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;}
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[M],gpar[M],grn[M]; genome(D,gd); genome(pk[par],gpar); genome(pk[rp],grn);
dig += bitmatch(gd,gpar)-bitmatch(gd,grn); ana += cosv(D,pk[par])-cosv(D,pk[rp]); hc++; }
}
memcpy(pk,nxt,sizeof pk);
}
{ double f=0; for(int p=0;p<POCK;p++){int gp[M];genome(pk[p],gp);f+=gp[0];} tgt_end=f/POCK; }
int ng=0; static int seen[POCK][M]; for(int p=0;p<POCK;p++){ int gp[M];genome(pk[p],gp); int f=0; for(int c=0;c<ng;c++){int e=1;for(int m=0;m<M;m++)if(seen[c][m]!=gp[m]){e=0;break;} if(e){f=1;break;}} if(!f){memcpy(seen[ng],gp,sizeof gp);ng++;} }
printf(" DIGITAL module-set heredity signal : %+.3f (bit-match daughter~parent minus ~random)\n",hc?dig/hc:0);
printf(" ANALOG composition heredity signal : %+.3f (cosine daughter~parent minus ~random, same run)\n",hc?ana/hc:0);
printf(" distinct digital genomes in population: %d / %d (of 2^%d possible)\n",ng,POCK,M);
printf(" selection on module-0 present: frequency %.3f -> %.3f (%+.3f)\n",tgt_start,tgt_end,tgt_end-tgt_start);
printf("\n");
if((hc?dig/hc:0) > 0.15)
printf(" => DIGITAL module inheritance BREEDS TRUE where analog composition did not. Making the\n inherited unit discrete/modular restores the fidelity gardenv lacked — the session's core\n claim, shown in chemistry. CAVEAT: modular substrate was supplied; its spontaneous origin is open.\n");
else
printf(" => digital inheritance did NOT breed true here either — the wall is deeper than digitization.\n");
return 0;
}