code wiki / _hdl_build / nx_nofloat_grammar_gate.nx
nx_nofloat_grammar_gate.nx source
↩ module page · 150 lines · 9303 B
1// nx_nofloat_grammar_gate.nx -- CAP-NF-GRAMMAR: the AFFORDABLE "landing" step the sovereign researcher
2// identified (knowledge/research/2026-06-23-nofloat-affordable-land-roadmap.md, R1, grounded in TinyStories
3// arXiv 2305.07759 + Textbooks arXiv 2306.11644: a tiny model is COHERENT iff the DOMAIN is constrained).
4// Instead of memorizing one fixed sentence, the model learns a small GRAMMAR and GENERATES coherent NOVEL
5// sentences. Grammar: a stream of [ARTICLE, NOUN, VERB] triples. Vocab 8: articles {the=0,a=1}, nouns
6// {cat=2,dog=3,bird=4}, verbs {ran=5,sat=6,ate=7}. EVERY training stream is fresh-random members -> the model
7// cannot memorize sentences; it must learn the CATEGORY GRAMMAR (article->noun->verb->article ...).
8// T1 GENERATES coherent grammar: from a seed, free argmax-decode produces a stream whose every token is in
9// the grammatically-correct category for its position (>= 90%, vs ~33% chance) = coherent NOVEL generation.
10// T2 learned the grammar on HELD-OUT streams: teacher-forced next-token category accuracy >= 90% (>> chance).
11// Pure integer Q16, attention-only block, 3 clm_fwd sites in separate helpers (nx_cc-lean). Sovereign.
12// HONEST: a CONSTRAINED grammar domain (the affordable landing per the research), not open prose. expect_exit: 0
13import "nx_nofloat_autograd.nx"
14import "nx_syscalls.nx"
15import "nx_gate_emit_lib.nx"
16const Q16: i64 = 65536
17
18
19func dini(a: *i64, n: i64, sd: i64) -> i64 { var i: i64=0; while i<n { a[i]=(((i*7+sd*13+1)%11)-5)*13107; i=i+1 } return 0 }
20func lcg(st: *i64) -> i64 { st[0]=(st[0]*1103515245 + 12345) & 2147483647; return (st[0] >> 15) }
21func cat_of(tok: i64) -> i64 { if tok<2 { return 0 } if tok<5 { return 1 } return 2 }
22// fresh-random grammatical stream: position cat = i%3; article 0..1, noun 2..4, verb 5..7. tgt = next token.
23func make_stream(S: *i64, tgt: *i64, P: i64, st: *i64) -> i64 {
24 var i: i64=0
25 while i<P { let c: i64=i%3; if c==0 { S[i]=lcg(st)%2 } if c==1 { S[i]=2+lcg(st)%3 } if c==2 { S[i]=5+lcg(st)%3 } i=i+1 }
26 i=0; while i<P-1 { tgt[i]=S[i+1]; i=i+1 }
27 tgt[P-1]=S[0]
28 return 0
29}
30
31func clm_fwd(tape: *i64, vals: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, V: i64, scale: i64, leaves: *i64) -> i64 {
32 let E: *i64=W[0] as *i64; let Wq: *i64=W[1] as *i64; let Wk: *i64=W[2] as *i64; let Wv: *i64=W[3] as *i64; let Wo: *i64=W[4] as *i64; let Wlm: *i64=W[5] as *i64
33 st[0]=0; st[1]=0
34 let nE: i64=nfa_leaf(tape,vals,st,V,dm,E,0)
35 let nWq: i64=nfa_leaf(tape,vals,st,dm,dm,Wq,0)
36 let nWk: i64=nfa_leaf(tape,vals,st,dm,dm,Wk,0)
37 let nWv: i64=nfa_leaf(tape,vals,st,dm,dm,Wv,0)
38 let nWo: i64=nfa_leaf(tape,vals,st,dm,dm,Wo,0)
39 let nWlm: i64=nfa_leaf(tape,vals,st,dm,V,Wlm,0)
40 let nX: i64=nfa_embed(tape,vals,st,nE,ids,T)
41 let nXn: i64=nfa_rmsnorm_rows(tape,vals,st,nX)
42 let nQ: i64=nfa_matmul(tape,vals,st,nXn,nWq)
43 let nK: i64=nfa_matmul(tape,vals,st,nXn,nWk)
44 let nV: i64=nfa_matmul(tape,vals,st,nXn,nWv)
45 let nQr: i64=nfa_rope(tape,vals,st,nQ)
46 let nKr: i64=nfa_rope(tape,vals,st,nK)
47 let nS: i64=nfa_matmul_nt(tape,vals,st,nQr,nKr)
48 let nSs: i64=nfa_cmul(tape,vals,st,nS,scale)
49 let nA: i64=nfa_softmax_rows(tape,vals,st,nSs,1)
50 let nO: i64=nfa_matmul(tape,vals,st,nA,nV)
51 let nOp: i64=nfa_matmul(tape,vals,st,nO,nWo)
52 let nH: i64=nfa_vadd(tape,vals,st,nX,nOp)
53 let nHn: i64=nfa_rmsnorm_rows(tape,vals,st,nH)
54 let nLg: i64=nfa_matmul(tape,vals,st,nHn,nWlm)
55 let nLoss: i64=nfa_softce_rows(tape,vals,st,nLg,tgt)
56 leaves[0]=nE; leaves[1]=nWq; leaves[2]=nWk; leaves[3]=nWv; leaves[4]=nWo; leaves[5]=nWlm; leaves[6]=nLg
57 return nLoss
58}
59func step_all(tape: *i64, grads: *i64, W: *i64, WN: *i64, leaves: *i64, nW: i64, lr: i64, clip: i64, gb: *i64) -> i64 {
60 var i: i64=0
61 while i<nW { let ar: *i64=W[i] as *i64; let cn: i64=WN[i]; let nd: i64=leaves[i]; var c: i64=0; while c<cn { var g: i64=nfa_grad(tape,grads,nd,c); if g>clip{g=clip} if g<0-clip{g=0-clip} gb[c]=g; c=c+1 } nfa_sgd(ar,gb,cn,lr); i=i+1 }
62 return 0
63}
64func amx(tape: *i64, vals: *i64, logn: i64, r: i64, V: i64) -> i64 { let o: i64=tape[7*logn+5]; var b: i64=0; var bv: i64=vals[o+r*V]; var j: i64=1; while j<V { if vals[o+r*V+j]>bv { bv=vals[o+r*V+j]; b=j } j=j+1 } return b }
65// site 1: train on fresh-random grammatical streams
66func do_train(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, WN: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, V: i64, scale: i64, leaves: *i64, gb: *i64, steps: i64, sdat: *i64) -> i64 {
67 var ep: i64=0
68 while ep < steps { make_stream(S,tgt,P,sdat); let nl: i64=clm_fwd(tape,vals,st,W,S,tgt,P-1,dm,V,scale,leaves); nfa_backward(tape,vals,grads,st[0],nl); step_all(tape,grads,W,WN,leaves,6,6554,262144,gb); ep=ep+1 }
69 return 0
70}
71// site 2: teacher-forced next-CATEGORY accuracy over N held-out fresh streams (position i predicts cat (i+1)%3)
72func eval_tf(tape: *i64, vals: *i64, st: *i64, W: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, V: i64, scale: i64, leaves: *i64, N: i64, sdat: *i64, totp: *i64) -> i64 {
73 var ok: i64=0; var tp: i64=0; var e: i64=0
74 while e<N {
75 make_stream(S,tgt,P,sdat)
76 let nl: i64=clm_fwd(tape,vals,st,W,S,tgt,P-1,dm,V,scale,leaves)
77 var i: i64=0
78 while i<P-1 { if cat_of(amx(tape,vals,leaves[6],i,V))==((i+1)%3) { ok=ok+1 } tp=tp+1; i=i+1 }
79 e=e+1
80 }
81 totp[0]=tp
82 return ok
83}
84// site 3: free generation coherence -- fixed-T decode from a seed article; count tokens in the grammatically-correct category
85func gen_coherent(tape: *i64, vals: *i64, st: *i64, W: *i64, gen: *i64, P: i64, dm: i64, V: i64, scale: i64, leaves: *i64, outtok: *i64) -> i64 {
86 var z: i64=0; while z<P { gen[z]=0; z=z+1 } // 0 = "the" (valid article seed)
87 let Tf: i64 = P-1
88 var step: i64=1
89 while step <= Tf {
90 let nl: i64=clm_fwd(tape,vals,st,W,gen,gen,Tf,dm,V,scale,leaves)
91 gen[step]=amx(tape,vals,leaves[6],step-1,V)
92 step=step+1
93 }
94 var ok: i64=0; var i: i64=1
95 while i<P { if cat_of(gen[i])==(i%3) { ok=ok+1 } outtok[i]=gen[i]; i=i+1 }
96 outtok[0]=gen[0]
97 return ok
98}
99
100func main() -> i64 {
101 g_puts("nx_nofloat_grammar gate (constrained-grammar -> coherent NOVEL generation; the affordable land)\n" as *u8)
102 var pass: i64=0; var total: i64=0
103 let V: i64=8; let P: i64=12; let dm: i64=24; let scale: i64=13377
104 let tape: *i64 = sys_mmap(512*7*8) as *i64
105 let vals: *i64 = sys_mmap(65536*8) as *i64
106 let grads: *i64 = sys_mmap(65536*8) as *i64
107 let st: *i64 = sys_mmap(2*8) as *i64
108 let nW: i64=6
109 let W: *i64 = sys_mmap(nW*8) as *i64
110 let WN: *i64 = sys_mmap(nW*8) as *i64
111 WN[0]=V*dm; WN[1]=dm*dm; WN[2]=dm*dm; WN[3]=dm*dm; WN[4]=dm*dm; WN[5]=dm*V
112 var wi: i64=0
113 while wi<nW { let a: *i64=sys_mmap(WN[wi]*8) as *i64; dini(a,WN[wi],wi+1); W[wi]=a as i64; wi=wi+1 }
114 let leaves: *i64 = sys_mmap(8*8) as *i64
115 let gbuf: *i64 = sys_mmap(4096*8) as *i64
116 let S: *i64 = sys_mmap(P*8) as *i64; let tgt: *i64 = sys_mmap(P*8) as *i64
117 let totp: *i64 = sys_mmap(8) as *i64; let sdat: *i64 = sys_mmap(8) as *i64
118 let outtok: *i64 = sys_mmap(P*8) as *i64
119
120 sdat[0]=12345
121 do_train(tape,vals,grads,st,W,WN,S,tgt,P,dm,V,scale,leaves,gbuf,30000,sdat)
122
123 // T2: held-out grammar accuracy (teacher-forced next-category)
124 sdat[0]=55554444
125 let ok: i64 = eval_tf(tape,vals,st,W,S,tgt,P,dm,V,scale,leaves,150,sdat,totp)
126 let tp: i64 = totp[0]
127 // T1: free generation coherence (the actual "landing")
128 let gen: *i64 = sys_mmap(P*8) as *i64
129 let gok: i64 = gen_coherent(tape,vals,st,W,gen,P,dm,V,scale,leaves,outtok)
130 g_puts(" [measure] held-out next-category acc=" as *u8); g_pn(ok); g_puts("/" as *u8); g_pn(tp); g_puts(" free-gen coherent tokens=" as *u8); g_pn(gok); g_puts("/" as *u8); g_pn(P-1); g_puts(" (chance~33%)\n" as *u8)
131 // print the generated sentence as category letters (A=article,N=noun,V=verb) + token ids
132 g_puts(" generated grammar: " as *u8)
133 var pi: i64=0
134 while pi<P { let c: i64=cat_of(outtok[pi]); let lab: *u8=sys_mmap(2); if c==0 { lab[0]=65 as u8 } if c==1 { lab[0]=78 as u8 } if c==2 { lab[0]=86 as u8 } sys_write(1,lab,1); pi=pi+1 }
135 g_puts(" (expected A N V A N V ...)\n" as *u8)
136
137 var t1: i64=0; if gok*100 >= (P-1)*90 { t1=1 }
138 pass=pass+g_check("T1: GENERATES coherent grammar -- free-decoded stream is category-valid >= 90% (novel coherent gen)" as *u8, t1); total=total+1
139 var t2: i64=0; if ok*100 >= tp*90 { t2=1 }
140 pass=pass+g_check("T2: learned the grammar on HELD-OUT streams (teacher-forced next-category >= 90% >> 33% chance)" as *u8, t2); total=total+1
141
142 var okall: i64=0; if pass==total { okall=1 }
143 if okall==1 {
144 let logf: i64 = sys_openat_append("knowledge/status/nofloat_grammar.log" as *u8, 420)
145 if logf >= 0 { let w0: i64=sys_write(logf,"NOFLOATGRAMMAR constrained-grammar coherent generation measured\n" as *u8,63); sys_close(logf) }
146 }
147 g_puts("---- grammar gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
148 if okall==1 { g_puts("verdict=GREEN (the affordable landing: a no-float LM learns a grammar and GENERATES coherent novel sentences)\n" as *u8); sys_exit(0); return 0 }
149 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
150}