code wiki / _hdl_build / nx_xlate_mt_gate.nx
nx_xlate_mt_gate.nx source
↩ module page · 175 lines · 7886 B
1// nx_xlate_mt_gate.nx -- MEASURES the data-driven RU<->EN engine on a HELD-OUT test set. NO fake green:
2// loads knowledge/xlate/{xlate_lex.tsv, xlate_morph_ru.tsv, xlate_testset.tsv}, builds the engine, translates
3// every held-out sentence, and reports unigram PRECISION + RECALL (clipped, per-mille integer, no float) and
4// EXACT-match count -- then re-scores the SAME set through the OLD 16-word nx_ruen_translate stub to prove the
5// leap. verdict GREEN iff the new engine's unigram precision >= 300 per-mille AND strictly beats the old stub.
6import "nx_syscalls.nx"
7import "nx_xlate_mt.nx"
8import "nx_mt_ruen.nx"
9
10func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
11func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
12func g_num(v: i64) -> i64 {
13 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
14 var m: i64 = v
15 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
16 let d: *u8 = sys_mmap(24)
17 var k: i64 = 0
18 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
19 var j: i64 = k
20 while j > 0 { sys_write(1, d + (j - 1), 1); j = j - 1 }
21 sys_munmap(d, 24)
22 return 0
23}
24func g_norm(src: *u8, n: i64, buf: *u8, cap: i64) -> i64 {
25 let op: *i64 = sys_mmap(8) as *i64
26 *op = 0
27 xl_norm_phrase(src, 0, n, buf, op, cap)
28 let r: i64 = *op
29 sys_munmap(op, 8)
30 return r
31}
32func g_toks(buf: *u8, n: i64, off: *i64, len: *i64, maxt: i64) -> i64 {
33 var nt: i64 = 0
34 var i: i64 = 0
35 while i < n {
36 while i < n { if (buf[i] as i64) == 32 { i = i + 1 } else { break } }
37 if i >= n { break }
38 let s: i64 = i
39 while i < n { if (buf[i] as i64) == 32 { break } i = i + 1 }
40 if nt < maxt { off[nt] = s; len[nt] = i - s }
41 nt = nt + 1
42 }
43 return nt
44}
45func g_teq(b1: *u8, a: i64, la: i64, b2: *u8, bb: i64, lb: i64) -> i64 {
46 if la != lb { return 0 }
47 var k: i64 = 0
48 while k < la { if (b1[a+k] as i64) != (b2[bb+k] as i64) { return 0 } k = k + 1 }
49 return 1
50}
51// field reader (TAB/newline) -- local copy so we don't depend on engine internals
52func g_field(buf: *u8, n: i64, ip: *i64, fs: *i64, fe: *i64, term: *i64) -> i64 {
53 var i: i64 = *ip
54 if i >= n { return 0 }
55 *fs = i
56 while i < n {
57 let c: i64 = buf[i] as i64
58 if c == 9 { break }
59 if c == 10 { break }
60 i = i + 1
61 }
62 *fe = i
63 if i < n { *term = buf[i] as i64; i = i + 1 } else { *term = 0 - 1 }
64 *ip = i
65 return 1
66}
67// score one hyp vs gold; use_old picks translator; accumulate into acc[match,H,G,exact]
68func g_score(eng: *i64, src: *u8, srcn: i64, dir: i64, gold: *u8, goldn: i64, use_old: i64, acc: *i64) -> i64 {
69 let out: *u8 = sys_mmap(2048)
70 var on: i64 = 0
71 if use_old == 1 { on = nx_ruen_translate(src, srcn, dir, out, 2048) } else { on = xl_translate(eng, src, srcn, dir, out, 2048) }
72 let hb: *u8 = sys_mmap(2048)
73 let gb: *u8 = sys_mmap(2048)
74 let hn: i64 = g_norm(out, on, hb, 2048)
75 let gn: i64 = g_norm(gold, goldn, gb, 2048)
76 let hoff: *i64 = sys_mmap(256 * 8) as *i64
77 let hlen: *i64 = sys_mmap(256 * 8) as *i64
78 let goff: *i64 = sys_mmap(256 * 8) as *i64
79 let glen: *i64 = sys_mmap(256 * 8) as *i64
80 let ht: i64 = g_toks(hb, hn, hoff, hlen, 256)
81 let gt: i64 = g_toks(gb, gn, goff, glen, 256)
82 let used: *u8 = sys_mmap(256)
83 var u: i64 = 0
84 while u < gt { used[u] = 0 as u8; u = u + 1 }
85 var nmatch: i64 = 0
86 var hi: i64 = 0
87 while hi < ht {
88 var gi: i64 = 0
89 var found: i64 = 0
90 while gi < gt {
91 if (used[gi] as i64) == 0 {
92 if g_teq(hb, hoff[hi], hlen[hi], gb, goff[gi], glen[gi]) == 1 { used[gi] = 1 as u8; found = 1; break }
93 }
94 gi = gi + 1
95 }
96 if found == 1 { nmatch = nmatch + 1 }
97 hi = hi + 1
98 }
99 var exact: i64 = 0
100 if hn == gn { exact = 1; var z: i64 = 0; while z < hn { if (hb[z] as i64) != (gb[z] as i64) { exact = 0 } z = z + 1 } }
101 acc[0] = acc[0] + nmatch
102 acc[1] = acc[1] + ht
103 acc[2] = acc[2] + gt
104 acc[3] = acc[3] + exact
105 sys_munmap(out, 2048); sys_munmap(hb, 2048); sys_munmap(gb, 2048)
106 sys_munmap(hoff, 256 * 8); sys_munmap(hlen, 256 * 8); sys_munmap(goff, 256 * 8); sys_munmap(glen, 256 * 8); sys_munmap(used, 256)
107 return 0
108}
109func g_report(name: *u8, acc: *i64, ntest: i64) -> i64 {
110 var prec: i64 = 0
111 var rec: i64 = 0
112 if acc[1] > 0 { prec = acc[0] * 1000 / acc[1] }
113 if acc[2] > 0 { rec = acc[0] * 1000 / acc[2] }
114 g_puts(" "); g_puts(name); g_puts(": unigram-precision="); g_num(prec); g_puts("/1000 recall="); g_num(rec)
115 g_puts("/1000 exact="); g_num(acc[3]); g_puts("/"); g_num(ntest); g_puts(" (matched="); g_num(acc[0]); g_puts(" hypTok="); g_num(acc[1]); g_puts(" goldTok="); g_num(acc[2]); g_puts(")\n")
116 return prec
117}
118func main() -> i64 {
119 g_puts("=== nx_xlate_mt_gate: MEASURED RU<->EN on held-out set (new data-driven engine vs old 16-word stub) ===\n")
120 let lnp: *i64 = sys_mmap(8) as *i64
121 let mnp: *i64 = sys_mmap(8) as *i64
122 let tnp: *i64 = sys_mmap(8) as *i64
123 let lex: *u8 = sys_read_file("knowledge/xlate/xlate_lex.tsv" as *u8, lnp)
124 let morph: *u8 = sys_read_file("knowledge/xlate/xlate_morph_ru.tsv" as *u8, mnp)
125 let ts: *u8 = sys_read_file("knowledge/xlate/xlate_testset.tsv" as *u8, tnp)
126 if (lex as i64) == 0 { g_puts("RED: cannot read knowledge/xlate/xlate_lex.tsv\n"); sys_exit(2); return 2 }
127 if (ts as i64) == 0 { g_puts("RED: cannot read knowledge/xlate/xlate_testset.tsv\n"); sys_exit(2); return 2 }
128 var morphn: i64 = 0
129 if (morph as i64) != 0 { morphn = mnp[0] }
130 let eng: *i64 = sys_mmap(256) as *i64
131 let ne: i64 = xl_build(eng, lex, lnp[0], morph, morphn)
132 g_puts("lexicon entries="); g_num(ne); g_puts(" morph-suffixes="); g_num(eng[XLE_NSUF]); g_puts(" testset bytes="); g_num(tnp[0]); g_puts("\n")
133 let accNew: *i64 = sys_mmap(64) as *i64
134 let accOld: *i64 = sys_mmap(64) as *i64
135 var qi: i64 = 0
136 while qi < 8 { accNew[qi] = 0; accOld[qi] = 0; qi = qi + 1 }
137 let ip: *i64 = sys_mmap(8) as *i64
138 let fs: *i64 = sys_mmap(8) as *i64
139 let fe: *i64 = sys_mmap(8) as *i64
140 let term: *i64 = sys_mmap(8) as *i64
141 *ip = 0
142 var ntest: i64 = 0
143 let tsn: i64 = tnp[0]
144 while ntest < 4096 {
145 if g_field(ts, tsn, ip, fs, fe, term) == 0 { break }
146 // field0 = dir
147 let d0s: i64 = *fs
148 let d0e: i64 = *fe
149 if (*term) != 9 { continue }
150 // dir: "ru2en" -> 1 (RU src), else 0
151 var dir: i64 = 0
152 if d0e - d0s >= 2 { if (ts[d0s] as i64) == 114 { dir = 1 } } // 'r' => ru2en
153 if g_field(ts, tsn, ip, fs, fe, term) == 0 { break }
154 let ss: i64 = *fs
155 let se: i64 = *fe
156 if (*term) != 9 { continue }
157 if g_field(ts, tsn, ip, fs, fe, term) == 0 { break }
158 let gs: i64 = *fs
159 let ge: i64 = *fe
160 if (*term) == 9 { g_field(ts, tsn, ip, fs, fe, term) }
161 if se <= ss { continue }
162 if ge <= gs { continue }
163 g_score(eng, ts + ss, se - ss, dir, ts + gs, ge - gs, 0, accNew)
164 g_score(eng, ts + ss, se - ss, dir, ts + gs, ge - gs, 1, accOld)
165 ntest = ntest + 1
166 }
167 g_puts("held-out sentences scored="); g_num(ntest); g_puts("\n")
168 g_puts("-- OLD 16-word nx_ruen_translate stub --\n")
169 let oldp: i64 = g_report("old-stub" as *u8, accOld, ntest)
170 g_puts("-- NEW data-driven nx_xlate_mt --\n")
171 let newp: i64 = g_report("new-engine" as *u8, accNew, ntest)
172 g_puts("XLATE-MT-GATE new-precision="); g_num(newp); g_puts(" old-precision="); g_num(oldp)
173 if newp >= 300 { if newp > oldp { g_puts(" verdict=GREEN -- data-driven engine clears 300/1000 and beats the stub\n"); sys_exit(0); return 0 } }
174 g_puts(" verdict=RED\n"); sys_exit(1); return 1
175}