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}