code wiki / _hdl_build / nx_mt_r0_gate.nx
nx_mt_r0_gate.nx source
↩ module page · 279 lines · 12043 B
1// nx_mt_r0_gate.nx -- GATE for MT-R0: the first rung of the SOVEREIGN NEURAL MACHINE TRANSLATION
2// arc (GEN-WL-WL-NN-TRANSLATION). Proves, by RUNNING, that a sovereign neural net LEARNS to
3// translate -- from random/zero init via the team's own scalar-tape autograd, NOT a hardcoded
4// table. The trainable atom of neural MT = a learned bilingual map: one-hot source word ->
5// linear layer W (the learned parameters) -> output vector -> argmax -> target word. Composes
6// ONLY shipped+gated organs (nx_autograd TRAIN-R1 GREEN + nx_f32 tower). No attention/weights
7// loaded; this is the BACKWARD/learning half proven on a translation task in miniature, the
8// foundation the rest of the arc (sequences -> FNet-mix context -> BPE vocab -> corpus -> the
9// /video /translate endpoint) climbs on.
10//
11// Demo dictionary (English -> Spanish), TARGET INDICES ARE A PERMUTATION (not identity) so a
12// pass cannot come from a trivial copy:
13// src EN: 0 hello 1 family 2 love 3 good 4 day 5 water
14// tgt ES: 0 familia 1 bueno 2 hola 3 dia 4 agua 5 amor (vocab in a DIFFERENT order)
15// map: hello->hola(2) family->familia(0) love->amor(5) good->bueno(1) day->dia(3) water->agua(4)
16// => tgt = [2,0,5,1,3,4] (a real permutation the net must LEARN)
17//
18// FOUR GATES:
19// A LEARNS: after training, argmax == tgt for ALL 6 pairs (acc 6/6) AND mean loss < 1/1000
20// AND loss decreased. The exact statement of "the net learned to translate".
21// B UNTRAINED FAILS (liar-kill): the zero-epoch (W=0) model scores < 6/6 -> the LEARNING did
22// it, not the harness/architecture.
23// C BIT-EXACT REPRODUCIBLE: train twice from zero-init; final W bits identical (determinism
24// exceed-axis carried into ML, like TRAIN-R1 gate C).
25// D DATA-DRIVEN (anti-hardcode liar-kill): train against a DIFFERENT permutation tgt2; the net
26// learns tgt2 (acc_vs_tgt2 == 6/6) AND no longer matches the original (acc_vs_tgt < 6/6).
27// Kills any "the answer was baked in" cheat -- it learns whatever data it is given.
28//
29// genealogy_id: linnainmaa_1970_reverse_mode_ad + rumelhart_1986_backprop (realized_in nx_autograd)
30// lineage_id: sovereign_neural_mt_r0_learned_wordmap_v1
31// license_tier: ORIGINAL
32import "nx_autograd.nx" // ag_* tape + transitively nx_f32 / nx_f32_div / nx_f32_cvt / nx_syscalls
33import "nx_syscalls.nx"
34import "nx_gate_verdict.nx"
35
36const MT_LOG: *u8 = "knowledge/status/mt_r0.log"
37const MT_S: i64 = 6 // source vocab size
38const MT_T: i64 = 6 // target vocab size
39
40// demo words (file-scope consts; long/literal strings must not live inline -> empty .s)
41const EN0: *u8 = "hello" as *u8
42const EN1: *u8 = "family" as *u8
43const EN2: *u8 = "love" as *u8
44const EN3: *u8 = "good" as *u8
45const EN4: *u8 = "day" as *u8
46const EN5: *u8 = "water" as *u8
47const ES0: *u8 = "familia" as *u8
48const ES1: *u8 = "bueno" as *u8
49const ES2: *u8 = "hola" as *u8
50const ES3: *u8 = "dia" as *u8
51const ES4: *u8 = "agua" as *u8
52const ES5: *u8 = "amor" as *u8
53const ESQ: *u8 = "?" as *u8
54
55func mt_en(i: i64) -> *u8 {
56 if i == 0 { return EN0 }
57 if i == 1 { return EN1 }
58 if i == 2 { return EN2 }
59 if i == 3 { return EN3 }
60 if i == 4 { return EN4 }
61 if i == 5 { return EN5 }
62 return ESQ
63}
64func mt_es(j: i64) -> *u8 {
65 if j == 0 { return ES0 }
66 if j == 1 { return ES1 }
67 if j == 2 { return ES2 }
68 if j == 3 { return ES3 }
69 if j == 4 { return ES4 }
70 if j == 5 { return ES5 }
71 return ESQ
72}
73
74// ---- logging (mirrors nx_train_r1_gate idioms) ----
75func mt_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
76func mt_wn(fd: i64, v: i64) -> i64 {
77 let bb: *u8 = sys_mmap(28); var m: i64 = v
78 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
79 let t: *u8 = sys_mmap(28); var k: i64 = 0
80 if m == 0 { t[0] = 48; k = 1 }
81 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
82 var i: i64 = 0
83 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
84 sys_write(fd, bb, k); return 0
85}
86// f32 -> round(v*1000) as signed int (no f32->int converter; nearest by linear advance, values O(1))
87func mt_f32_to_milli(v: i64) -> i64 {
88 var s: i64 = nx_f32_mul(v, nx_i32_to_f32(1000))
89 var neg: i64 = 0
90 if nx_f32_lt(s, AG_F32_ZERO) == 1 { neg = 1; s = nx_f32_neg(s) }
91 let half: i64 = ag_constf(1, 2)
92 var m: i64 = 0
93 var go: i64 = 1
94 while go == 1 {
95 let mid: i64 = nx_f32_add(nx_i32_to_f32(m), half)
96 if nx_f32_lt(mid, s) == 1 {
97 m = m + 1
98 if m >= 100000 { go = 0 }
99 } else { go = 0 }
100 }
101 if neg == 1 { return 0 - m }
102 return m
103}
104
105// argmax over the output vector for source token i: o_j = W[j*MT_S + i] (one-hot input picks
106// column i). First-max on ties (so the W=0 untrained model predicts token 0 for every source).
107func mt_argmax(W: *i64, i: i64) -> i64 {
108 var bestj: i64 = 0
109 var best: i64 = W[0 * MT_S + i]
110 var j: i64 = 1
111 while j < MT_T {
112 let o: i64 = W[j * MT_S + i]
113 if nx_f32_gt(o, best) == 1 { best = o; bestj = j }
114 j = j + 1
115 }
116 return bestj
117}
118
119// accuracy: how many of the MT_S sources the model maps to the given target indices.
120func mt_accuracy(W: *i64, tgt: *i64) -> i64 {
121 var c: i64 = 0
122 var i: i64 = 0
123 while i < MT_S {
124 if mt_argmax(W, i) == tgt[i] { c = c + 1 }
125 i = i + 1
126 }
127 return c
128}
129
130// full-batch GD training of the learned word-map W (MT_T x MT_S) on the given targets, MSE to the
131// one-hot target vector, zero-init, lr=1/20. Writes final W (MT_T*MT_S f32) + first/last mean loss.
132func mt_train(epochs: i64, tgt: *i64, Wout: *i64, lfirst: *i64, llast: *i64) -> i64 {
133 let NW: i64 = MT_T * MT_S
134 let W: *i64 = (sys_mmap(NW * 8)) as *i64
135 var z: i64 = 0
136 while z < NW { W[z] = AG_F32_ZERO; z = z + 1 }
137 let lr: i64 = ag_constf(1, 4) // factor |1-2lr|=0.5/epoch -> full f32 convergence
138 let wn: *i64 = (sys_mmap(NW * 8)) as *i64 // tape node index for each W param
139 let tape: *i64 = (sys_mmap(4096 * 5 * 8)) as *i64
140 let np: *i64 = (sys_mmap(8)) as *i64
141 var ep: i64 = 0
142 while ep < epochs {
143 *np = 0
144 // W params as leaves
145 var p: i64 = 0
146 while p < NW { wn[p] = ag_leaf(tape, np, W[p]); p = p + 1 }
147 // one-hot target constants as leaves (reused)
148 let one: i64 = ag_leaf(tape, np, AG_F32_ONE)
149 let zero: i64 = ag_leaf(tape, np, AG_F32_ZERO)
150 var nsum: i64 = ag_leaf(tape, np, AG_F32_ZERO)
151 var i: i64 = 0
152 while i < MT_S {
153 var j: i64 = 0
154 while j < MT_T {
155 var tn: i64 = zero
156 if tgt[i] == j { tn = one }
157 let res: i64 = ag_sub(tape, np, wn[j * MT_S + i], tn)
158 let sq: i64 = ag_mul(tape, np, res, res)
159 nsum = ag_add(tape, np, nsum, sq)
160 j = j + 1
161 }
162 i = i + 1
163 }
164 ag_backward(tape, *np, nsum) // nsum = sum-of-squared-errors over all terms
165 if ep == 0 { *lfirst = ag_val(tape, nsum) }
166 *llast = ag_val(tape, nsum)
167 p = 0
168 while p < NW {
169 W[p] = nx_f32_sub(W[p], nx_f32_mul(lr, ag_grad(tape, wn[p])))
170 p = p + 1
171 }
172 ep = ep + 1
173 }
174 var q: i64 = 0
175 while q < NW { Wout[q] = W[q]; q = q + 1 }
176 return 0
177}
178
179// emit the live translations the trained model produces (honest demo + operator-visible proof).
180func mt_demo(fd: i64, W: *i64) -> i64 {
181 mt_w(fd, "MT-R0 translations:" as *u8)
182 var i: i64 = 0
183 while i < MT_S {
184 let pj: i64 = mt_argmax(W, i)
185 mt_w(fd, " " as *u8); mt_w(fd, mt_en(i)); mt_w(fd, "->" as *u8); mt_w(fd, mt_es(pj))
186 i = i + 1
187 }
188 mt_w(fd, "\n" as *u8)
189 return 0
190}
191
192func mt_emit(fd: i64, r: *i64) -> i64 {
193 mt_w(fd, "MTR0GATE authored=organ engine=scalar-tape-autograd-f32 task=learned-bilingual-wordmap" as *u8)
194 mt_w(fd, " | A_learns_pass=" as *u8); mt_wn(fd, r[0])
195 mt_w(fd, " acc=" as *u8); mt_wn(fd, r[1]); mt_w(fd, "/" as *u8); mt_wn(fd, MT_S)
196 mt_w(fd, " loss_first_milli=" as *u8); mt_wn(fd, r[2]); mt_w(fd, " loss_last_milli=" as *u8); mt_wn(fd, r[3])
197 mt_w(fd, " | B_untrained_fails_pass=" as *u8); mt_wn(fd, r[4]); mt_w(fd, " untrained_acc=" as *u8); mt_wn(fd, r[5])
198 mt_w(fd, " | C_bitexact_pass=" as *u8); mt_wn(fd, r[6])
199 mt_w(fd, " | D_datadriven_pass=" as *u8); mt_wn(fd, r[7])
200 mt_w(fd, " acc_vs_new=" as *u8); mt_wn(fd, r[8]); mt_w(fd, " acc_vs_old=" as *u8); mt_wn(fd, r[9])
201 if r[10] == 1 { mt_w(fd, " verdict=GREEN\n" as *u8) } else { mt_w(fd, " verdict=RED\n" as *u8) }
202 return 0
203}
204
205func main() -> i64 {
206 var ok: i64 = 1
207 let NW: i64 = MT_T * MT_S
208
209 // demo dictionary targets (a permutation) and a DIFFERENT permutation for gate D
210 let tgt: *i64 = (sys_mmap(MT_S * 8)) as *i64
211 tgt[0] = 2; tgt[1] = 0; tgt[2] = 5; tgt[3] = 1; tgt[4] = 3; tgt[5] = 4
212 let tgt2: *i64 = (sys_mmap(MT_S * 8)) as *i64
213 tgt2[0] = 1; tgt2[1] = 4; tgt2[2] = 0; tgt2[3] = 5; tgt2[4] = 2; tgt2[5] = 3
214
215 // ---------- Gate A: the net LEARNS to translate ----------
216 let W: *i64 = (sys_mmap(NW * 8)) as *i64
217 let lf: *i64 = (sys_mmap(8)) as *i64
218 let ll: *i64 = (sys_mmap(8)) as *i64
219 mt_train(300, tgt, W, lf, ll)
220 let acc: i64 = mt_accuracy(W, tgt)
221 var learns_pass: i64 = 1
222 if acc != MT_S { learns_pass = 0 }
223 if nx_f32_lt(*ll, ag_constf(1, 1000)) != 1 { learns_pass = 0 } // mean loss < 1/1000
224 if nx_f32_lt(*ll, *lf) != 1 { learns_pass = 0 } // loss decreased
225 if learns_pass != 1 { ok = 0 }
226
227 // ---------- Gate B: untrained (zero-epoch) model FAILS ----------
228 let W0: *i64 = (sys_mmap(NW * 8)) as *i64
229 let lf0: *i64 = (sys_mmap(8)) as *i64
230 let ll0: *i64 = (sys_mmap(8)) as *i64
231 mt_train(0, tgt, W0, lf0, ll0) // 0 epochs -> stays zero-init
232 let acc0: i64 = mt_accuracy(W0, tgt)
233 var untrained_fails_pass: i64 = 1
234 if acc0 >= MT_S { untrained_fails_pass = 0 }
235 if untrained_fails_pass != 1 { ok = 0 }
236
237 // ---------- Gate C: bit-exact reproducible ----------
238 let Wr: *i64 = (sys_mmap(NW * 8)) as *i64
239 let lfr: *i64 = (sys_mmap(8)) as *i64
240 let llr: *i64 = (sys_mmap(8)) as *i64
241 mt_train(300, tgt, Wr, lfr, llr)
242 var bitexact_pass: i64 = 1
243 var c: i64 = 0
244 while c < NW { if Wr[c] != W[c] { bitexact_pass = 0 } c = c + 1 }
245 if bitexact_pass != 1 { ok = 0 }
246
247 // ---------- Gate D: data-driven (anti-hardcode liar-kill) ----------
248 let Wd: *i64 = (sys_mmap(NW * 8)) as *i64
249 let lfd: *i64 = (sys_mmap(8)) as *i64
250 let lld: *i64 = (sys_mmap(8)) as *i64
251 mt_train(300, tgt2, Wd, lfd, lld)
252 let acc_new: i64 = mt_accuracy(Wd, tgt2)
253 let acc_old: i64 = mt_accuracy(Wd, tgt)
254 var datadriven_pass: i64 = 1
255 if acc_new != MT_S { datadriven_pass = 0 }
256 if acc_old >= MT_S { datadriven_pass = 0 }
257 if datadriven_pass != 1 { ok = 0 }
258
259 // ---------- emit ----------
260 let r: *i64 = (sys_mmap(11 * 8)) as *i64
261 r[0] = learns_pass; r[1] = acc; r[2] = mt_f32_to_milli(*lf); r[3] = mt_f32_to_milli(*ll)
262 r[4] = untrained_fails_pass; r[5] = acc0
263 r[6] = bitexact_pass; r[7] = datadriven_pass; r[8] = acc_new; r[9] = acc_old
264 r[10] = ok
265 mt_emit(1, r)
266 mt_demo(1, W)
267 let logf: i64 = sys_openat_append(MT_LOG, 420)
268 if logf >= 0 { mt_emit(logf, r); mt_demo(logf, W); sys_close(logf) }
269
270 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
271 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
272 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
273 let ctr__dry: *i64 = gv_ctr()
274 ctr__dry[0] = ok
275 ctr__dry[1] = 1
276 let rc__dry: i64 = gv_verdict("MT-R0-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
277 sys_exit(rc__dry)
278 return rc__dry
279}