nx_lbp_cluster.nx source
↩ module page · 58 lines · 2982 B
1// nx_lbp_cluster.nx -- SOVEREIGN face-descriptor RUNG 4 GATE: greedy chi-square clustering of descriptors
2// into person groups (cluster_greedy in nx_lbp_core.nx). Pure NishiLang, no benchmark. KAT on synthetic
3// descriptors with 3 clearly-separated groups -> exactly 3 clusters with correct membership; plus threshold
4// neg-controls (huge thresh -> 1 cluster, zero thresh -> every item its own). This is the engine that will
5// turn the corpus descriptor store into galx_face_index (cid->person). Build/run:
6// ./_offc/nx_sov_build_run.elf nx_lbp_cluster license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_lbp_core.nx"
9const K_MAGIC_50000: i64 = 50000
10const K_MAGIC_1000000000: i64 = 1000000000
11
12func setrow(buf: *i64, i: i64, d: i64, b0: i64, b1: i64, b2: i64, b3: i64) -> i64 {
13 buf[i*d+0]=b0; buf[i*d+1]=b1; buf[i*d+2]=b2; buf[i*d+3]=b3; return 0
14}
15
16func main() -> i64 {
17 var fail: i64 = 0
18 let D: i64 = 4
19 let M: i64 = 6
20 let buf: *i64 = sys_mmap(8*M*D) as *i64
21 // group A (mass bin0): A1,A2 ; group B (mass bin2): B1,B2 ; group C (mass bin1): C1,C2
22 setrow(buf, 0, D, 100, 0, 0, 0) // A1
23 setrow(buf, 1, D, 90, 10, 0, 0) // A2 (near A1)
24 setrow(buf, 2, D, 0, 0, 100, 0) // B1
25 setrow(buf, 3, D, 0, 0, 90, 10) // B2 (near B1)
26 setrow(buf, 4, D, 0, 100, 0, 0) // C1
27 setrow(buf, 5, D, 10, 90, 0, 0) // C2 (near C1)
28
29 let assign: *i64 = sys_mmap(8*M) as *i64
30 let reps: *i64 = sys_mmap(8*M) as *i64
31
32 // within-group chi2 ~10526, across-group ~>120000 -> thresh 50000 separates cleanly
33 let nc: i64 = cluster_greedy(buf, M, D, K_MAGIC_50000, 1000, assign, reps)
34 lp("clusters="); ln(nc); lp(" assign=[")
35 var i: i64=0; while i<M { ln(assign[i]); if i<M-1 { lp(" " as *u8) } i=i+1 } lp("] expect 3 [0 0 1 1 2 2] -> ")
36 var ok: i64 = 1
37 if nc != 3 { ok = 0 }
38 if assign[0] != assign[1] { ok = 0 }
39 if assign[2] != assign[3] { ok = 0 }
40 if assign[4] != assign[5] { ok = 0 }
41 if assign[0] == assign[2] { ok = 0 }
42 if assign[0] == assign[4] { ok = 0 }
43 if assign[2] == assign[4] { ok = 0 }
44 if ok == 1 { lp("PASS\n" as *u8) } else { lp("FAIL\n" as *u8); fail = 1 }
45
46 // neg-control 1: huge threshold -> everything merges into 1 cluster
47 let nc1: i64 = cluster_greedy(buf, M, D, K_MAGIC_1000000000, 1000, assign, reps)
48 lp("thresh=BIG clusters="); ln(nc1); lp(" expect 1 -> ")
49 if nc1 == 1 { lp("PASS\n" as *u8) } else { lp("FAIL\n" as *u8); fail = 1 }
50
51 // neg-control 2: zero threshold -> nothing merges, M clusters
52 let nc2: i64 = cluster_greedy(buf, M, D, 0, 1000, assign, reps)
53 lp("thresh=0 clusters="); ln(nc2); lp(" expect 6 -> ")
54 if nc2 == M { lp("PASS\n" as *u8) } else { lp("FAIL\n" as *u8); fail = 1 }
55
56 if fail == 0 { lp("nx_lbp_cluster RUNG4 GREEN (3 groups -> 3 clusters; threshold controls granularity)\n" as *u8); sys_exit(0); return 0 }
57 lp("nx_lbp_cluster RUNG4 RED\n" as *u8); sys_exit(1); return 1
58}