code wiki / _hdl_build / nx_analyst_multi_gate.nx
nx_analyst_multi_gate.nx source
↩ module page · 129 lines · 6836 B
1// nx_analyst_multi_gate.nx -- GATE for multi-column correlation (nx_analyst_multi). Known-answer: exact
2// linear relations must yield r=+/-1000; independent columns ~0; a constant column -> DEGENERATE; the
3// key-driver finder picks the truly-most-correlated candidate. Classification words asserted. Anti-false-
4// green: perfect + anti + null are DISTINCT verdicts. expect_exit: 0 license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "_hdl_build/nx_analyst_multi.nx"
7import "nx_gate_verdict.nx"
8
9func mp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func mn(v: i64) -> i64 { var m: i64=v; if m<0{mp("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o:*u8=sys_mmap(24); var i:i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
11func mhas(hay: *u8, n: i64, needle: *u8) -> i64 {
12 var nl: i64 = 0
13 while needle[nl] != (0 as u8) { nl = nl + 1 }
14 var i: i64 = 0
15 while i + nl <= n { var j: i64 = 0; var eq: i64 = 1; while j < nl { if hay[i+j] != needle[j] { eq = 0; break } j = j + 1 } if eq == 1 { return 1 } i = i + 1 }
16 return 0
17}
18func mslen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
19func lcg(s: i64) -> i64 { return (s * 1103515245 + 12345) & 0x7fffffff }
20
21func main() -> i64 {
22 mp("=== nx_analyst_multi_gate ===\n" as *u8)
23 var pass: i64 = 0
24 var fail: i64 = 0
25 let n: i64 = 200
26 let x: *i64 = sys_mmap(n * 8) as *i64
27 let y_perfect: *i64 = sys_mmap(n * 8) as *i64
28 let y_anti: *i64 = sys_mmap(n * 8) as *i64
29 let y_indep: *i64 = sys_mmap(n * 8) as *i64
30 let y_const: *i64 = sys_mmap(n * 8) as *i64
31 let y_noisy: *i64 = sys_mmap(n * 8) as *i64
32 var s: i64 = 7
33 var i: i64 = 0
34 while i < n {
35 s = lcg(s)
36 x[i] = s % 100
37 y_perfect[i] = 2 * x[i] + 3 // exact positive linear -> r=+1000
38 y_anti[i] = 500 - 3 * x[i] // exact negative linear -> r=-1000
39 s = lcg(s)
40 y_indep[i] = s % 100 // independent -> r~0
41 y_const[i] = 42 // constant -> DEGENERATE
42 s = lcg(s)
43 y_noisy[i] = 2 * x[i] + (s % 30) // strong positive + noise -> r moderate/strong positive
44 i = i + 1
45 }
46
47 // T1 perfect positive (exact linear -> r=1000 within 1 permil integer precision; isqrt/mean rounding)
48 let r1: i64 = am_pearson_milli(x, y_perfect, n)
49 mp("perfect+ r=" as *u8); mn(r1); mp("\n" as *u8)
50 if r1 >= 999 { pass = pass + 1 } else { fail = fail + 1; mp("T1 FAIL perfect+ (want >=999)\n" as *u8) }
51
52 // T2 perfect negative (integer arithmetic yields -999 on this data -- exact relation, 1-permil rounding)
53 let r2: i64 = am_pearson_milli(x, y_anti, n)
54 mp("perfect- r=" as *u8); mn(r2); mp("\n" as *u8)
55 if r2 <= (0 - 999) { pass = pass + 1 } else { fail = fail + 1; mp("T2 FAIL perfect- (want <=-999)\n" as *u8) }
56
57 // T3 independent ~0 (|r| < 200)
58 let r3: i64 = am_pearson_milli(x, y_indep, n)
59 mp("independent r=" as *u8); mn(r3); mp("\n" as *u8)
60 var a3: i64 = r3
61 if a3 < 0 { a3 = 0 - a3 }
62 if a3 < 200 { pass = pass + 1 } else { fail = fail + 1; mp("T3 FAIL independent |r| >= 200\n" as *u8) }
63
64 // T4 constant -> DEGENERATE
65 let r4: i64 = am_pearson_milli(x, y_const, n)
66 if r4 == AM_R_DEGENERATE { pass = pass + 1 } else { fail = fail + 1; mp("T4 FAIL const not degenerate\n" as *u8) }
67
68 // T5 classification words
69 let cb: *u8 = sys_mmap(128)
70 am_class(0 as *u8, r1, cb)
71 var t5: i64 = 1
72 if mhas(cb, mslen(cb), "positive very strong" as *u8) == 0 { t5 = 0 }
73 am_class(0 as *u8, r2, cb)
74 if mhas(cb, mslen(cb), "negative very strong" as *u8) == 0 { t5 = 0 }
75 am_class(0 as *u8, r4, cb)
76 if mhas(cb, mslen(cb), "undefined" as *u8) == 0 { t5 = 0 }
77 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; mp("T5 FAIL classification words\n" as *u8) }
78
79 // T6 noisy strong positive -> class contains "positive" and band strong/moderate (not negligible)
80 let r6: i64 = am_pearson_milli(x, y_noisy, n)
81 mp("noisy+ r=" as *u8); mn(r6); mp("\n" as *u8)
82 am_class(0 as *u8, r6, cb)
83 var t6: i64 = 1
84 if mhas(cb, mslen(cb), "positive" as *u8) == 0 { t6 = 0 }
85 if mhas(cb, mslen(cb), "negligible" as *u8) == 1 { t6 = 0 }
86 if r6 <= 500 { t6 = 0 } // strong positive despite noise
87 if t6 == 1 { pass = pass + 1 } else { fail = fail + 1; mp("T6 FAIL noisy positive\n" as *u8) }
88
89 // T7 KEY-DRIVER: target=x; candidates=[y_indep, y_noisy, y_perfect] -> winner index 2 (y_perfect, r=1000)
90 let cols: *i64 = sys_mmap(3 * 8) as *i64
91 cols[0] = y_indep as i64
92 cols[1] = y_noisy as i64
93 cols[2] = y_perfect as i64
94 let oi: *i64 = sys_mmap(8) as *i64
95 let orr: *i64 = sys_mmap(8) as *i64
96 let found: i64 = am_key_driver(x, cols, 3, n, oi, orr)
97 mp("key-driver idx=" as *u8); mn(oi[0]); mp(" r=" as *u8); mn(orr[0]); mp("\n" as *u8)
98 var t7: i64 = 1
99 if found != 1 { t7 = 0 }
100 if oi[0] != 2 { t7 = 0 } // y_perfect is the strongest driver
101 if orr[0] != 1000 { t7 = 0 }
102 if t7 == 1 { pass = pass + 1 } else { fail = fail + 1; mp("T7 FAIL key-driver\n" as *u8) }
103
104 // T8 covariance sign (perfect+ positive cov, anti negative cov)
105 var t8: i64 = 1
106 if am_covariance(x, y_perfect, n) <= 0 { t8 = 0 }
107 if am_covariance(x, y_anti, n) >= 0 { t8 = 0 }
108 if t8 == 1 { pass = pass + 1 } else { fail = fail + 1; mp("T8 FAIL covariance sign\n" as *u8) }
109
110 mp("pass=" as *u8); mn(pass); mp(" fail=" as *u8); mn(fail); mp("\n" as *u8)
111 let log: *u8 = sys_mmap(128)
112 var lo: i64 = 0
113 let pre: *u8 = "ANALYSTMULTI authored=organ verdict=" as *u8
114 var pi: i64 = 0
115 while pre[pi] != (0 as u8) { log[lo] = pre[pi]; lo = lo + 1; pi = pi + 1 }
116 if fail == 0 { let g: *u8 = "GREEN\n" as *u8; var gi: i64 = 0; while g[gi] != (0 as u8) { log[lo] = g[gi]; lo = lo + 1; gi = gi + 1 } } else { let r: *u8 = "RED\n" as *u8; var ri: i64 = 0; while r[ri] != (0 as u8) { log[lo] = r[ri]; lo = lo + 1; ri = ri + 1 } }
117 let fd: i64 = sys_openat_wr("knowledge/status/analyst_multi.log" as *u8, 0x1A4)
118 if fd >= 0 { sys_write(fd, log, lo); sys_close(fd) }
119
120 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
121 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
122 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
123 let ctr__dry: *i64 = gv_ctr()
124 ctr__dry[0] = pass
125 ctr__dry[1] = pass + fail
126 let rc__dry: i64 = gv_verdict("ANALYST-MULTI-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
127 sys_exit(rc__dry)
128 return rc__dry
129}