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}