OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / basal-agent / stress.c

325 lines · c ref:
/* stress.c — does an error-sourced, LEAKED temperature field cross the Mess3 valley?
 *
 * PRE-REGISTERED in TRAJECTORY.md (2026-09-11). Read that first.
 *
 * THE CLAIM UNDER TEST. Part A concluded: nothing local/online/greedy/self-organized
 * crosses the Mess3 structure-learning valley (nine mechanisms, learn.c..wakesleep2.c).
 * Every annealing attempt used a GLOBAL SCALAR SCHEDULE: da-em.c broke onto a wrong
 * branch or re-symmetrized at beta_c; soc.c found beta_c but online averaging washed it
 * out; critical.c's homeostat was BLIND because washout IS max usage-entropy.
 *
 * Shreesha & Levin, BBRC 731 (2024) 150396, Fig 1 A1/A2 is a fitness valley crossed by a
 * LOCAL mechanism: a stuck cell leaks stress to neighbours already at their setpoints,
 * raising their plasticity ("temperature", their word) until they accept a temporarily
 * worse configuration and open a channel. The temperature is a FIELD sourced from local
 * error, and the receiving unit CANNOT TELL whose error it is.
 *
 * This does not share critical.c's failure mode: it is driven by distance-from-setpoint,
 * and washout has HIGH error, so the field holds temperature UP instead of declaring
 * victory.
 *
 * !!! PRE-REGISTERED MOST-LIKELY NULL — WRITTEN BEFORE THE RUN !!!
 * Levin's valley is a SPATIAL REARRANGEMENT barrier (cells physically blocking each
 * other). Ours is a PARAMETER-SPACE barrier (an HMM local optimum). These may not be the
 * same kind of wall. If this nulls, that is the first explanation to reach for -- NOT a
 * tuning problem. Recorded here and not only in a .md because the template-abundance
 * error was diagnosed in genome.md in plain language and then rebuilt twice.
 *
 * ARMS (differ ONLY in where each unit's temperature comes from):
 *   A  shared   : diffused field, own + neighbours indistinguishable at the read
 *   B  private  : own excess only (Levin's own control arm)
 *   B2 matched  : uncoupled, T rescaled to match A's REALIZED mean T
 *                 -> postmortem lesson (a): coupling moves mean temperature AND targets
 *                    it. B2 holds the mean fixed so the survivor is TARGETING, not amount.
 *                    3 of 4 prior one-knob-two-variable claims failed. This is the fix.
 *   C  global   : one shared annealing schedule (prior art: da-em.c, soc.c)
 *
 * PRIMARY ENDPOINT = distinct-belief-state count vs resolution (box-dim growth).
 * NOT log-loss: README.md records that prediction barely distinguishes finite/infinite/
 * fractal structure. Scoring on log-loss alone would repeat a documented error.
 * Reference (critical.c, G=30/100/300/1000/3000):
 *   true Mess3   396 / 2399 / 8924 / 26394 / 54821
 *   learn.c collapse 5 / 9 / 14 / 20 / 36      optimal log-loss ~0.794 nats
 *
 * STATISTIC: two-arm question -> report the SEPARATION across seeds, never an absolute
 * bar (postmortem lesson (b): linkage.c used an absolute bar on a control in a two-arm
 * experiment).
 *
 * The setpoint is the field's own best-achieved loss -- observable, collective, and it
 * does NOT encode the Mess3 answer. A unit sitting at the best has zero OWN stress, so
 * only the leak can move it. That is exactly Fig 1 A1 vs A2.
 *
 * build:  cc -O2 -Wall -std=c11 -o stress stress.c -lm && ./stress
 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define K      3
#define M      16        /* units in the ring */
#define SWEEPS 4000
#define WIN    10000     /* scoring window per sweep */
#define NSEED  5

#define T_FLOOR 5e-6     /* baseline exploration, IDENTICAL in A, B, B2 -- so B is not
                          * trivially frozen at its own setpoint.
                          * CALIBRATED (dscale.c): |delta| per single-entry STEP is 2e-5.
                          * Run 1 used 3.5e-3 = 175x too hot -> pure diffusion. See VOID note. */
#define T_GAIN  6e-4     /* stress -> temperature */
#define LEAK    0.60     /* fraction of a unit's deposit that leaves it (arm A) */
#define STEP    0.06     /* proposal size */

static const double TT[K][K][K] = {
 {{0.765,0.00375,0.00375},{0.0425,0.0675,0.00375},{0.0425,0.00375,0.0675}},
 {{0.0675,0.0425,0.00375},{0.00375,0.765,0.00375},{0.00375,0.0425,0.0675}},
 {{0.0675,0.00375,0.0425},{0.00375,0.0675,0.0425},{0.00375,0.00375,0.765}},
};

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 void gen_mess3(unsigned char *out,int n){
	int s=0;
	for(int i=0;i<n;i++){ double u=urand(),acc=0; int es=0,nj=0,d=0;
		for(int sym=0;sym<K&&!d;sym++)for(int j=0;j<K&&!d;j++){acc+=TT[sym][s][j];if(u<acc){es=sym;nj=j;d=1;}}
		out[i]=(unsigned char)es; s=nj; }
}

/* mean negative log-likelihood of the exact belief filter under tensor T, over s[off..off+n) */
static double filter_ll(const double T[K][K][K],const unsigned char *s,long off,int n){
	double b[K]={1.0/3,1.0/3,1.0/3},ll=0;
	for(int t=0;t<n;t++){ int x=s[off+t]; double px=0,nb[K]={0,0,0};
		for(int i=0;i<K;i++)for(int j=0;j<K;j++){double m=b[i]*T[x][i][j];nb[j]+=m;px+=m;}
		if(px<1e-300)px=1e-300; ll+=-log(px); for(int j=0;j<K;j++)b[j]=nb[j]/px; }
	return ll/(double)n;
}
static long filter_distinct(const double T[K][K][K],const unsigned char *s,int n,int G){
	double b[K]={1.0/3,1.0/3,1.0/3}; char *seen=calloc((size_t)(G+1)*(G+1),1); long d=0;
	for(int t=0;t<n;t++){ int q0=(int)(b[0]*G+0.5),q1=(int)(b[1]*G+0.5);
		if(q0<0)q0=0; if(q0>G)q0=G; if(q1<0)q1=0; if(q1>G)q1=G;
		size_t key=(size_t)q0*(G+1)+q1; if(!seen[key]){seen[key]=1;d++;}
		int x=s[t]; double px=0,nb[K]={0,0,0};
		for(int i=0;i<K;i++)for(int j=0;j<K;j++){double m=b[i]*T[x][i][j];nb[j]+=m;px+=m;}
		if(px<1e-300)px=1e-300; for(int j=0;j<K;j++)b[j]=nb[j]/px; }
	free(seen); return d;
}
static void renorm(double T[K][K][K]){
	for(int i=0;i<K;i++){ double z=0;
		for(int s=0;s<K;s++)for(int j=0;j<K;j++){ if(T[s][i][j]<1e-6)T[s][i][j]=1e-6; z+=T[s][i][j]; }
		for(int s=0;s<K;s++)for(int j=0;j<K;j++) T[s][i][j]/=z; }
}

typedef struct {
	double ll_best;                 /* best full-test log-loss found by any unit */
	long   ladder[5];               /* box-count ladder of the best unit's tensor */
	double meanT;                   /* realized mean temperature (for B2 matching) */
	long   uphill;                  /* accepted-worse moves  (guard 2) */
	double fieldcorr;               /* cross-unit stress correlation (guard 1) */
	double beta_span;               /* arm C only (guard 3) */
} Res;

/* arm: 0=A shared  1=B private  2=B2 matched  3=C global schedule */
static Res run_arm(int arm,const unsigned char *tr,long ntr,const unsigned char *te,int nte,
                   unsigned long long seed,double meanT_target)
{
	static double T[M][K][K][K], Tp[K][K][K];
	double ll[M], stress[M], field[M], Temp[M];
	Res R; memset(&R,0,sizeof R);

	RNG=seed;
	for(int u=0;u<M;u++){
		for(int i=0;i<K;i++){ double z=0;
			for(int s=0;s<K;s++)for(int j=0;j<K;j++){ T[u][s][i][j]=0.1+urand(); z+=T[u][s][i][j]; }
			for(int s=0;s<K;s++)for(int j=0;j<K;j++) T[u][s][i][j]/=z; }
		ll[u]=1e9; stress[u]=0; Temp[u]=T_FLOOR;
	}

	double Tsum=0; long Tn=0, corr_n=0; double corr_acc=0;
	double beta_lo=1e9, beta_hi=-1e9;

	for(int sw=0; sw<SWEEPS; sw++){
		long off = (long)(urand()*(double)(ntr-WIN-1));   /* same window for every unit */

		/* COMMON RANDOM NUMBERS (mandatory, not a refinement). dscale.c measured
		 * window-to-window noise at 380x the per-step signal, and only 114x even at a
		 * 20x larger window -- so delta MUST be taken on one shared window. Run 1
		 * compared llp(window_t) against ll[u](window_{t-1}) and was a coin flip on
		 * noise in every arm, which is why all four arms landed on the same number. */
		for(int u=0;u<M;u++) ll[u]=filter_ll((const double(*)[K][K])T[u],tr,off,WIN);

		/* ---- setpoint: the best loss anyone in the field has achieved this sweep ---- */
		double best=1e9; for(int u=0;u<M;u++) if(ll[u]<best) best=ll[u];
		for(int u=0;u<M;u++){ double e=ll[u]-best; stress[u]= e>0? e:0; }

		/* ---- the field ---- */
		if(arm==0){
			/* deposit, then diffuse around the ring. The read is a SINGLE number: the unit
			 * cannot decompose field[u] into own vs neighbour. That is the anonymization. */
			for(int u=0;u<M;u++){
				int l=(u+M-1)%M, r=(u+1)%M;
				field[u] = (1.0-LEAK)*stress[u] + 0.5*LEAK*(stress[l]+stress[r]);
			}
			/* guard 1: did the field actually mix? correlate field against own stress */
			double ms=0,mf=0; for(int u=0;u<M;u++){ms+=stress[u];mf+=field[u];} ms/=M; mf/=M;
			double sn=0,ss=0,ff=0;
			for(int u=0;u<M;u++){ double a=stress[u]-ms,b=field[u]-mf; sn+=a*b; ss+=a*a; ff+=b*b; }
			if(ss>1e-18&&ff>1e-18){ corr_acc+=sn/sqrt(ss*ff); corr_n++; }
		} else {
			for(int u=0;u<M;u++) field[u]=stress[u];
			if(arm!=3){ corr_acc+=1.0; corr_n++; }   /* private: field IS own stress, corr=1 */
		}

		double gsched = 0.0;
		if(arm==3){ /* one global schedule shared by all units */
			double frac=(double)sw/(double)SWEEPS;
			gsched = T_FLOOR + T_GAIN*0.5*(1.0-frac);
			if(gsched<beta_lo)beta_lo=gsched; if(gsched>beta_hi)beta_hi=gsched;
		}

		for(int u=0;u<M;u++){
			if(arm==3)      Temp[u]=gsched;
			else if(arm==2) Temp[u]=meanT_target;             /* mean-matched, untargeted */
			else            Temp[u]=T_FLOOR + T_GAIN*field[u];
			Tsum+=Temp[u]; Tn++;

			memcpy(Tp,T[u],sizeof Tp);
			int si=(int)(urand()*K), ii=(int)(urand()*K), jj=(int)(urand()*K);
			if(si>=K)si=K-1; if(ii>=K)ii=K-1; if(jj>=K)jj=K-1;
			Tp[si][ii][jj] *= exp(STEP*(2.0*urand()-1.0));
			renorm(Tp);

			double llp=filter_ll((const double(*)[K][K])Tp,tr,off,WIN);
			double d=llp-ll[u];
			int accept;
			if(d<=0) accept=1;
			else { accept = (urand() < exp(-d/(Temp[u]>1e-12?Temp[u]:1e-12))); if(accept) R.uphill++; }
			if(accept){ memcpy(T[u],Tp,sizeof Tp); ll[u]=llp; }
		}
	}

	R.meanT     = Tn? Tsum/(double)Tn : 0.0;
	R.fieldcorr = corr_n? corr_acc/(double)corr_n : -2.0;
	R.beta_span = (arm==3)? beta_hi-beta_lo : 0.0;

	int ubest=0; double bb=1e9;
	for(int u=0;u<M;u++){ double v=filter_ll((const double(*)[K][K])T[u],te,0,nte);
		if(v<bb){bb=v;ubest=u;} }
	R.ll_best=bb;
	int Gs[5]={30,100,300,1000,3000};
	for(int g=0;g<5;g++) R.ladder[g]=filter_distinct((const double(*)[K][K])T[ubest],te,nte,Gs[g]);
	return R;
}

int main(void){
	const long NTR=600000; const int NTE=200000;
	unsigned char *tr=malloc(NTR),*te=malloc(NTE);
	RNG=0x9e3779b97f4a7c15ULL; gen_mess3(tr,(int)NTR);
	RNG=0xd1b54a32d192ed03ULL; gen_mess3(te,NTE);

	/* guard 4: generator sane? */
	long cnt[K]={0,0,0}; for(long i=0;i<NTR;i++) cnt[tr[i]]++;
	int gen_ok = 1;
	for(int s=0;s<K;s++){ double f=(double)cnt[s]/(double)NTR; if(f<0.25||f>0.42) gen_ok=0; }

	double ll_opt=filter_ll(TT,te,0,NTE);

	printf("=== stress.c — LEAKED error-sourced temperature vs Mess3 valley ===\n");
	printf("  M=%d units, %d sweeps, window %d, %d seeds\n",M,SWEEPS,WIN,NSEED);
	printf("  optimal log-loss %.4f nats | symbol marginals %.3f %.3f %.3f\n\n",
	       ll_opt,(double)cnt[0]/NTR,(double)cnt[1]/NTR,(double)cnt[2]/NTR);

	const char *nm[4]={"A  shared ","B  private","B2 matched","C  global "};
	double gap[4][NSEED]; long lad[4][5]; double mT[4]={0,0,0,0};
	long uph[4]={0,0,0,0}; double fcorr[4]={0,0,0,0}, bspan=0;
	memset(lad,0,sizeof lad);

	for(int sd=0; sd<NSEED; sd++){
		unsigned long long seed=0x243f6a8885a308d3ULL + 0x1234567ULL*(unsigned long long)sd;
		Res rA=run_arm(0,tr,NTR,te,NTE,seed,0.0);
		Res rB=run_arm(1,tr,NTR,te,NTE,seed,0.0);
		Res rM=run_arm(2,tr,NTR,te,NTE,seed,rA.meanT);   /* matched to A's REALIZED mean T */
		Res rC=run_arm(3,tr,NTR,te,NTE,seed,0.0);
		Res all[4]={rA,rB,rM,rC};
		for(int a=0;a<4;a++){
			gap[a][sd]=all[a].ll_best-ll_opt;
			mT[a]+=all[a].meanT; uph[a]+=all[a].uphill; fcorr[a]+=all[a].fieldcorr;
			if(sd==0) for(int g=0;g<5;g++) lad[a][g]=all[a].ladder[g];
		}
		bspan+=rC.beta_span;
		fprintf(stderr,"  seed %d: A %+.4f  B %+.4f  B2 %+.4f  C %+.4f\n",
		        sd,gap[0][sd],gap[1][sd],gap[2][sd],gap[3][sd]);
	}
	for(int a=0;a<4;a++){ mT[a]/=NSEED; fcorr[a]/=NSEED; }
	bspan/=NSEED;

	/* ---------- guard: did the test actually run? ---------- */
	int void_run=0;
	printf("  --- guard: did the test actually run? ---\n");
	printf("  [1] field mixed?   A stress~field corr %.3f (want <0.99)  B corr %.3f (want 1.00)\n",
	       fcorr[0],fcorr[1]);
	if(!(fcorr[0]<0.99)) { printf("      FAIL: arm A's field did not mix.\n"); void_run=1; }
	printf("  [2] uphill moves?  A %ld  B %ld  B2 %ld  (all must be >0)\n",uph[0],uph[1],uph[2]);
	if(uph[0]==0||uph[1]==0||uph[2]==0){ printf("      FAIL: no annealing happened.\n"); void_run=1; }
	printf("  [3] C schedule span %.4f (must be >0)\n",bspan);
	if(!(bspan>0)){ printf("      FAIL: global schedule was flat.\n"); void_run=1; }
	printf("  [4] generator marginals sane? %s\n", gen_ok?"yes":"NO");
	if(!gen_ok) void_run=1;
	printf("  [5] mean T: A %.2e vs B2 %.2e  (B2 must match A; that is the point)\n",mT[0],mT[2]);
	if(fabs(mT[0]-mT[2])>1e-12){ printf("      FAIL: B2 not matched.\n"); void_run=1; }
	/* [6] POSITIVE CONTROL -- the guard run 1 did not have, and the reason run 1 was VOID.
	 * Seed a unit at the TRUE tensor and anneal it with this harness at T_FLOOR. If it
	 * cannot HOLD an answer it is handed, no arm result means anything. */
	{
		double Tc[K][K][K],Tp2[K][K][K]; memcpy(Tc,TT,sizeof Tc);
		RNG=0x51ee7c0deULL; long ofc=0; double cur=filter_ll((const double(*)[K][K])Tc,tr,ofc,WIN);
		for(int sw=0;sw<SWEEPS;sw++){
			long off=(long)(urand()*(double)(NTR-WIN-1));
			cur=filter_ll((const double(*)[K][K])Tc,tr,off,WIN);
			memcpy(Tp2,Tc,sizeof Tp2);
			int si=(int)(urand()*K),ii=(int)(urand()*K),jj=(int)(urand()*K);
			if(si>=K)si=K-1;
			if(ii>=K)ii=K-1;
			if(jj>=K)jj=K-1;
			Tp2[si][ii][jj]*=exp(STEP*(2.0*urand()-1.0)); renorm(Tp2);
			double p=filter_ll((const double(*)[K][K])Tp2,tr,off,WIN),d=p-cur;
			if(d<=0||urand()<exp(-d/T_FLOOR)) memcpy(Tc,Tp2,sizeof Tc);
		}
		double held=filter_ll((const double(*)[K][K])Tc,te,0,NTE)-ll_opt;
		printf("  [6] positive control: TRUE-seeded unit ends at gap %+.4f (must stay <+0.01)\n",held);
		if(!(held<0.01)){ printf("      FAIL: harness cannot hold the optimum it is handed.\n"); void_run=1; }
	}
	if(void_run){ printf("\n  *** VOID — invalid experiment, NOT a null. ***\n"); free(tr);free(te); return 1; }
	printf("  guard PASSED.\n\n");

	/* ---------- PRIMARY endpoint: structure, not prediction ---------- */
	printf("  PRIMARY — distinct belief states vs resolution (seed 0 best unit):\n");
	printf("    %-11s %8s %8s %8s %8s %8s\n","arm","G=30","100","300","1000","3000");
	for(int a=0;a<4;a++){
		printf("    %-11s",nm[a]);
		for(int g=0;g<5;g++) printf(" %8ld",lad[a][g]);
		printf("\n");
	}
	printf("    %-11s %8d %8d %8d %8d %8d\n","TRUE Mess3",396,2399,8924,26394,54821);
	printf("    %-11s %8d %8d %8d %8d %8d\n","learn.c coll",5,9,14,20,36);

	/* ---------- SECONDARY: log-loss, reported as a SEPARATION ---------- */
	printf("\n  SECONDARY — log-loss gap vs optimal (mean +- sd over %d seeds):\n",NSEED);
	double mu[4],sd_[4];
	for(int a=0;a<4;a++){
		double s=0; for(int i=0;i<NSEED;i++) s+=gap[a][i]; mu[a]=s/NSEED;
		double v=0; for(int i=0;i<NSEED;i++){double d=gap[a][i]-mu[a]; v+=d*d;}
		sd_[a]=NSEED>1?sqrt(v/(NSEED-1)):0.0;
		printf("    %-11s %+.4f +- %.4f   (mean T %.4f)\n",nm[a],mu[a],sd_[a],mT[a]);
	}
	double sep=0,sv=0;
	for(int i=0;i<NSEED;i++) sep+=gap[2][i]-gap[0][i];  sep/=NSEED;
	for(int i=0;i<NSEED;i++){double d=(gap[2][i]-gap[0][i])-sep; sv+=d*d;}
	printf("\n  SEPARATION  B2 - A  = %+.4f +- %.4f nats  (>0 means TARGETING beat amount)\n",
	       sep,NSEED>1?sqrt(sv/(NSEED-1)):0.0);
	printf("  NOTE: log-loss is SECONDARY by pre-registration — README records that it barely\n");
	printf("        distinguishes finite/infinite/fractal structure. Judge on the ladder above.\n");
	free(tr); free(te); return 0;
}