OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent commits / 4e8fb0d

basal-agent: belief_field_agent.c — the SEED (working base case of the agent design)
A world model that lives as a distributed belief-FIELD over N coupled units, infers by belief- mating, and drives a DECISION toward a setpoint. First model in the arc that closes perception-> belief->decision->action — the actual goal, not origin-of-life. Controllable 3-cause POMDP (action shifts hidden state so its effect depends on WHERE you are -> must infer to act; emission noise 0.60 so reactive control fails). Results (300k ticks): OPTIMAL exact filter 0.634 FIELD (belief-field) 0.626 <- matches optimal NO-MODEL (raw obs) 0.560 <- world model is load-bearing RANDOM 0.334 field inference KL vs exact filter = 0.043 nats (faithful; residual = diffusion lag) coherence (inter-unit agreement) = 0.999 (the field holds together = one individual) Maps to validated arc results: fast loop = belief-mating (mess3.c); boundary = the coherence domain (the supplied unit of selection); goal = the setpoint; learning the operators = mom.c (the valley-crosser) plugs into the slow loop. Field kernel shaped to port to Vulkan later. Operators handed to the agent in this seed to isolate the NEW parts (distributed field + closed loop); learning is the next module. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4e8fb0d69af3ed113460ef8c0d27745861d09b9d
by plankatron <fleeky@gmail.com> · 2026-07-22T02:09:43.000Z

Changed files (2) +143 -0

.gitignore +1 -0
……@@ -33,3 +33,4 @@ ribozyme
3333bridges
3434coemerge
3535integrated
36belief_field_agent
belief_field_agent.c +142 -0
……@@ -0,0 +1,142 @@
1/* belief_field_agent.c — the SEED: a world model that lives as a belief-FIELD over coupled units,
2 * infers by belief-mating, and drives a DECISION toward a setpoint. The base case of the design.
3 *
4 * Architecture (each piece traces to a validated result of the arc):
5 * SUBSTRATE : N units on a ring, each holding a belief vector b_i in R^3 (the "cells").
6 * FIELD : the collective belief across units = the world model (pattern memory). Units are
7 * gap-junction-coupled (diffusion) -> a COHERENCE DOMAIN = the individual (the boundary).
8 * INFERENCE : fast loop = BELIEF-MATING (predict via the transition operator, correct via emission),
9 * exactly the mess3 filter (mess3.c) distributed over the field.
10 * DECISION : a setpoint g (goal state); the effector picks the action that its belief predicts will
11 * drive the world toward g. Active-inference flavored: act to reach the setpoint.
12 * LEARNING : (slow loop) the operators are learned by method-of-moments (mom.c, the validated
13 * valley-crosser). This SEED is handed the operators to isolate the NEW parts the arc
14 * never built -- the distributed FIELD and the closed perception->decision->action LOOP.
15 *
16 * Environment: a CONTROLLABLE 3-cause POMDP. Hidden s in {0,1,2}; action a shifts it (next=(s+a)%3
17 * w.p. 1-tn, else uniform) so the effect depends on WHERE you are -> you must INFER s to act well;
18 * emission x is noisy (correct w.p. 1-en). Goal: hold state g. A no-model agent (acts on raw x) must
19 * lose to a belief agent. Validation: FIELD goal-occupancy ~ OPTIMAL filter >> NO-MODEL; and the field's
20 * collective belief tracks the exact filter (inference is correct) while staying coherent (boundary holds).
21 *
22 * build: cc -O2 -Wall -std=c11 -o belief_field_agent belief_field_agent.c -lm
23 */
24#include <math.h>
25#include <stdio.h>
26
27#define K 3 /* causes / symbols / actions */
28#define N 12 /* field units (the coherence domain) */
29#define TICKS 300000
30#define TN 0.15 /* transition noise */
31#define EN 0.60 /* emission noise: raw x is right only 60% -> reactive control fails, inference wins */
32#define DIFF 0.30 /* gap-junction diffusion (keeps the coherence domain together) */
33#define UNITNOISE 0.01 /* per-unit corruption (the field must denoise via coupling) */
34#define GOAL 0
35
36static unsigned long long RNG;
37static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; }
38static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); }
39static int rk(void){ return (int)(xs()%K); }
40
41/* --- environment operators (the agent's model = these; learning them = mom.c) --- */
42static double Ptrans(int j,int i,int a){ return (1.0-TN)*((j==(i+a)%K)?1.0:0.0) + TN/K; } /* P(next=j|s=i,a) */
43static double Pemit (int x,int s){ return (1.0-EN)*((x==s)?1.0:0.0) + EN/K; } /* P(x|s) */
44static int step_env(int s,int a){ return (urand()<1.0-TN)? (s+a)%K : rk(); }
45static int emit_env(int s){ return (urand()<1.0-EN)? s : rk(); }
46
47static void norm(double*b){ double z=0; for(int j=0;j<K;j++) z+=b[j]; if(z<1e-300)z=1e-300; for(int j=0;j<K;j++) b[j]/=z; }
48
49/* belief-mating step (predict via transition op given action a, correct via emission of x) */
50static void mate(double*b,int a,int x){
51 double bp[K]={0,0,0};
52 for(int j=0;j<K;j++){ double s=0; for(int i=0;i<K;i++) s+=b[i]*Ptrans(j,i,a); bp[j]=s; } /* predict */
53 for(int j=0;j<K;j++) bp[j]*=Pemit(x,j); /* correct */
54 norm(bp); for(int j=0;j<K;j++) b[j]=bp[j];
55}
56/* decision: pick the action whose predicted next-belief puts most mass on the goal g */
57static int decide(const double*b){
58 int best=0; double bv=-1;
59 for(int a=0;a<K;a++){ double m=0; for(int i=0;i<K;i++) m+=b[i]*Ptrans(GOAL,i,a); if(m>bv){bv=m;best=a;} }
60 return best;
61}
62
63enum { OPTIMAL, FIELD, NOMODEL, RANDOM };
64
65/* run one controller for TICKS; returns goal-occupancy. For FIELD also writes belief-divergence vs the
66 exact filter and inter-unit coherence. */
67static double run(int type,double*field_kl,double*field_coh){
68 RNG=0x9e3779b97f4a7c15ULL;
69 int s=rk(); long hits=0;
70 double bf[K]={1.0/K,1.0/K,1.0/K}; /* single exact belief (OPTIMAL / shadow for FIELD) */
71 double u[N][K]; for(int n=0;n<N;n++) for(int j=0;j<K;j++) u[n][j]=1.0/K; /* the FIELD */
72 double klsum=0, cohsum=0; long m=0;
73
74 for(long t=0;t<TICKS;t++){
75 /* collective belief of the field */
76 double c[K]={0,0,0}; for(int n=0;n<N;n++) for(int j=0;j<K;j++) c[j]+=u[n][j]/N;
77 /* DECISION */
78 int a;
79 if(type==OPTIMAL) a=decide(bf);
80 else if(type==FIELD) a=decide(c);
81 else a=rk();
82
83 /* world steps */
84 s=step_env(s,a); int x=emit_env(s); if(s==GOAL) hits++;
85
86 /* INFERENCE */
87 if(type==OPTIMAL||type==FIELD) mate(bf,a,x); /* exact filter (also shadow for FIELD) */
88 if(type==FIELD){
89 /* each unit belief-mates, is corrupted, then diffuses toward its neighbours (gap junctions) */
90 double nu[N][K];
91 for(int n=0;n<N;n++){ double b[K]; for(int j=0;j<K;j++) b[j]=u[n][j];
92 mate(b,a,x);
93 for(int j=0;j<K;j++) b[j]*= (1.0 + UNITNOISE*(urand()*2-1));
94 norm(b);
95 int L=(n-1+N)%N,R=(n+1)%N;
96 for(int j=0;j<K;j++) nu[n][j]=(1-DIFF)*b[j]+DIFF*0.5*(u[L][j]+u[R][j]);
97 norm(nu[n]); }
98 for(int n=0;n<N;n++) for(int j=0;j<K;j++) u[n][j]=nu[n][j];
99 /* validation: field collective vs exact filter (KL), and inter-unit coherence */
100 double cc[K]={0,0,0}; for(int n=0;n<N;n++) for(int j=0;j<K;j++) cc[j]+=u[n][j]/N;
101 double kl=0; for(int j=0;j<K;j++){ double p=cc[j]<1e-9?1e-9:cc[j], q=bf[j]<1e-9?1e-9:bf[j]; kl+=p*log(p/q); }
102 double coh=0; for(int n=0;n<N;n++){ double d=0; for(int j=0;j<K;j++) d+=fabs(u[n][j]-cc[j]); coh+=1.0-d/2; }
103 klsum+=kl; cohsum+=coh/N; m++;
104 }
105 }
106 if(type==FIELD){ *field_kl=klsum/m; *field_coh=cohsum/m; }
107 return (double)hits/TICKS;
108}
109
110/* NOMODEL needs to remember last obs; simplest: re-run a dedicated loop */
111static double run_nomodel(void){
112 RNG=0x9e3779b97f4a7c15ULL; int s=rk(),lastx=0; long hits=0;
113 for(long t=0;t<TICKS;t++){ int a=((GOAL-lastx)%K+K)%K; s=step_env(s,a); int x=emit_env(s); if(s==GOAL)hits++; lastx=x; }
114 return (double)hits/TICKS;
115}
116
117int main(void){
118 double kl=0,coh=0,dummy;
119 double opt = run(OPTIMAL,&dummy,&dummy);
120 double fld = run(FIELD,&kl,&coh);
121 double nom = run_nomodel();
122 double rnd = run(RANDOM,&dummy,&dummy);
123
124 printf("=== Belief-field agent (SEED) on a controllable 3-cause POMDP ===\n");
125 printf(" N=%d field units, goal=state %d, emission noise=%.2f, transition noise=%.2f.\n",N,GOAL,EN,TN);
126 printf(" Decision = act toward the setpoint using the field's belief. Chance occupancy = %.3f.\n\n",1.0/K);
127 printf(" controller | goal-occupancy\n");
128 printf(" ----------------------+---------------\n");
129 printf(" OPTIMAL exact filter | %.3f\n", opt);
130 printf(" FIELD (belief-field) | %.3f\n", fld);
131 printf(" NO-MODEL (raw obs) | %.3f\n", nom);
132 printf(" RANDOM | %.3f\n", rnd);
133 printf("\n");
134 printf(" field inference fidelity: KL(field collective || exact filter) = %.4f nats (->0 = correct)\n", kl);
135 printf(" coherence domain: mean inter-unit agreement = %.3f (->1 = the field holds together = one individual)\n", coh);
136 printf("\n");
137 if(fld > nom+0.04 && fld > opt-0.03 && coh > 0.95 && kl < 0.06)
138 printf(" => SEED WORKS. The world model living as a distributed belief-FIELD infers correctly (tracks the\n exact filter) while staying coherent (one individual), and DRIVES DECISIONS that reach the setpoint\n ~as well as the optimal controller and far better than acting on raw observation. Perception->belief\n ->decision->action is closed. Fast loop = belief-mating (mess3); boundary = the coherence domain;\n goal = the setpoint. Learning the operators = mom.c plugs into the slow loop. Base case complete.\n");
139 else
140 printf(" => Not yet: FIELD did not clearly beat NO-MODEL and match OPTIMAL with faithful inference.\n Read the numbers; adjust before claiming the seed works.\n");
141 return 0;
142}