code wiki / _hdl_build / nx_dr_fuse_cli.nx
nx_dr_fuse_cli.nx source
↩ module page · 95 lines · 5097 B
1// nx_dr_fuse_cli.nx -- fit the learned combiner on REAL DRBench labels and report HELD-OUT
2// performance against every individual signal (DR-12).
3// nx_dr_fuse <feats.csv> [train_percent]
4// feats.csv = flat comma-separated ints, 5 per candidate: task,label,lexical,semantic,semantic_idf
5// Weights are fitted ONLY on the first train_percent of tasks and every reported number is
6// computed ONLY on the DISJOINT remainder -- fitting and scoring on the same tasks would be
7// rigged, so the split is explicit and reported.
8// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
9import "nx_dr_fuse.nx"
10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
11import "nx_syscalls.nx"
12const K_MAGIC_1000000: i64 = 1000000
13const K_MAGIC_262144: i64 = 262144
14
15func fc_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
16func fc_q() -> i64 { let b: *u8 = sys_mmap(1); b[0] = 34 as u8; sys_write(1, b, 1); return 0 }
17func fc_key(name: *u8) -> i64 { fc_q(); fc_puts(name); fc_q(); fc_puts(":" as *u8); return 0 }
18// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
19// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
20// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
21// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
22func fc_num(v: i64) -> i64 { nxi_out(v); return 0 }
23// parse every non-negative integer in the buffer, in order
24func fc_parse(buf: *u8, len: i64, out: *i64, maxn: i64) -> i64 {
25 var cnt: i64 = 0; var cur: i64 = 0; var have: i64 = 0; var i: i64 = 0
26 while i < len {
27 let c: i64 = buf[i] as i64
28 if c >= 48 { if c <= 57 { cur = cur * 10 + (c - 48); have = 1 } }
29 else { if have == 1 { if cnt < maxn { out[cnt] = cur; cnt = cnt + 1 } cur = 0; have = 0 } }
30 i = i + 1
31 }
32 if have == 1 { if cnt < maxn { out[cnt] = cur; cnt = cnt + 1 } }
33 return cnt
34}
35// emit one held-out score line for a fixed weight vector
36func fc_row(name: *u8, r: *i64, n: i64, w: *i64, lo: i64) -> i64 {
37 fc_puts("," as *u8); fc_key(name); fc_num(fu_recall(r, n, w, lo, K_MAGIC_1000000))
38 return 0
39}
40
41func main(argc: i64, argv: *i64) -> i64 {
42 if argc < 2 { fc_puts("{" as *u8); fc_key("error" as *u8); fc_q(); fc_puts("usage: nx_dr_fuse <feats.csv> [train_percent]" as *u8); fc_q(); fc_puts("}\n" as *u8); sys_exit(2); return 2 }
43 var trainpct: i64 = 70
44 if argc > 2 {
45 let ap: *u8 = argv[2] as *u8
46 let tb: *i64 = sys_mmap(8) as *i64
47 var al: i64 = 0
48 while ap[al] != (0 as u8) { al = al + 1 }
49 if fc_parse(ap, al, tb, 1) > 0 { trainpct = tb[0] }
50 }
51
52 let lenp: *i64 = sys_mmap(8) as *i64
53 lenp[0] = 0
54 let buf: *u8 = sys_read_file(argv[1] as *u8, lenp)
55 if lenp[0] <= 0 { fc_puts("{" as *u8); fc_key("error" as *u8); fc_q(); fc_puts("feature file unreadable or empty" as *u8); fc_q(); fc_puts("}\n" as *u8); sys_exit(1); return 1 }
56
57 let r: *i64 = sys_mmap(K_MAGIC_262144 * 8) as *i64
58 let nints: i64 = fc_parse(buf, lenp[0], r, K_MAGIC_262144)
59 let n: i64 = nints / 5
60 if n < 10 { fc_puts("{" as *u8); fc_key("error" as *u8); fc_q(); fc_puts("too few records" as *u8); fc_q(); fc_puts("}\n" as *u8); sys_exit(1); return 1 }
61
62 // task count = max task id + 1
63 var ntasks: i64 = 0
64 var i: i64 = 0
65 while i < n { let t: i64 = fu_task(r, i); if t + 1 > ntasks { ntasks = t + 1 } i = i + 1 }
66 let split: i64 = (ntasks * trainpct) / 100
67
68 let w: *i64 = sys_mmap(3 * 8) as *i64
69 let trainacc: i64 = fu_fit(r, n, w, 0, split)
70
71 let wl: *i64 = sys_mmap(3 * 8) as *i64
72 wl[0] = 1; wl[1] = 0; wl[2] = 0
73 let ws: *i64 = sys_mmap(3 * 8) as *i64
74 ws[0] = 0; ws[1] = 1; ws[2] = 0
75 let wi: *i64 = sys_mmap(3 * 8) as *i64
76 wi[0] = 0; wi[1] = 0; wi[2] = 1
77
78 fc_puts("{" as *u8)
79 fc_key("tool" as *u8); fc_q(); fc_puts("nx_dr_fuse" as *u8); fc_q(); fc_puts("," as *u8)
80 fc_key("candidates" as *u8); fc_num(n); fc_puts("," as *u8)
81 fc_key("tasks" as *u8); fc_num(ntasks); fc_puts("," as *u8)
82 fc_key("train_tasks" as *u8); fc_num(split); fc_puts("," as *u8)
83 fc_key("heldout_tasks" as *u8); fc_num(ntasks - split); fc_puts("," as *u8)
84 fc_key("train_pairwise_acc_permil" as *u8); fc_num(trainacc); fc_puts("," as *u8)
85 fc_key("weights" as *u8); fc_puts("[" as *u8); fc_num(w[0]); fc_puts("," as *u8); fc_num(w[1]); fc_puts("," as *u8); fc_num(w[2]); fc_puts("]" as *u8)
86 fc_puts(",\"heldout_recall_permil\":{" as *u8)
87 fc_key("learned" as *u8); fc_num(fu_recall(r, n, w, split, K_MAGIC_1000000))
88 fc_row("lexical_only" as *u8, r, n, wl, split)
89 fc_row("semantic_only" as *u8, r, n, ws, split)
90 fc_row("semantic_idf_only" as *u8, r, n, wi, split)
91 fc_puts("}," as *u8)
92 fc_key("note" as *u8); fc_q(); fc_puts("weights fitted ONLY on train tasks; every recall above is on the DISJOINT held-out range at 100% distractor-avoidance" as *u8); fc_q()
93 fc_puts("}\n" as *u8)
94 sys_exit(0); return 0
95}