code wiki / (root) / sketch_markov_test.nx

sketch_markov_test.nx source

↩ module page · 126 lines · 4818 B

1// sketch_markov_test.nx -- Markov chain transition tracker verification. 2 3import "syscalls.nx" 4import "sketch_markov.nx" 5import "sketch_types.nx" 6 7func iabs(x: i64) -> i64 { 8 if x < 0 { return -x } 9 return x 10} 11 12func main() -> i64 { 13 // ---- alloc ---- 14 let m: *Markov = nx_markov_alloc(4) 15 if m == (0 as *Markov) { return __syscall(93, 5, 0, 0, 0, 0, 0) } 16 if nx_markov_total(m) != 0 { return __syscall(93, 6, 0, 0, 0, 0, 0) } 17 // Reject N<2. 18 if nx_markov_alloc(1) != (0 as *Markov) { 19 return __syscall(93, 7, 0, 0, 0, 0, 0) 20 } 21 // Reject N>MAX. 22 if nx_markov_alloc(5000) != (0 as *Markov) { 23 return __syscall(93, 8, 0, 0, 0, 0, 0) 24 } 25 26 // ---- observe explicit transitions ---- 27 nx_markov_observe(m, 0, 1) 28 nx_markov_observe(m, 0, 1) 29 nx_markov_observe(m, 0, 2) 30 nx_markov_observe(m, 1, 0) 31 // counts: t[0][1]=2, t[0][2]=1, t[1][0]=1. 32 if nx_markov_count(m, 0, 1) != 2 { return __syscall(93, 10, 0, 0, 0, 0, 0) } 33 if nx_markov_count(m, 0, 2) != 1 { return __syscall(93, 11, 0, 0, 0, 0, 0) } 34 if nx_markov_count(m, 1, 0) != 1 { return __syscall(93, 12, 0, 0, 0, 0, 0) } 35 if nx_markov_count(m, 2, 3) != 0 { return __syscall(93, 13, 0, 0, 0, 0, 0) } 36 // row_sums: [3, 1, 0, 0] 37 if nx_markov_row_sum(m, 0) != 3 { return __syscall(93, 14, 0, 0, 0, 0, 0) } 38 if nx_markov_row_sum(m, 1) != 1 { return __syscall(93, 15, 0, 0, 0, 0, 0) } 39 if nx_markov_total(m) != 4 { return __syscall(93, 16, 0, 0, 0, 0, 0) } 40 41 // ---- probability query (PPM) ---- 42 // P[0][1] = 2/3 = 666_666 PPM (integer truncation -> 666_666) 43 let p01: i64 = nx_markov_probability_ppm(m, 0, 1) 44 if iabs(p01 - 666666) > 1 { 45 return __syscall(93, 20, 0, 0, 0, 0, 0) 46 } 47 // P[0][2] = 1/3 = 333_333 PPM 48 let p02: i64 = nx_markov_probability_ppm(m, 0, 2) 49 if iabs(p02 - 333333) > 1 { 50 return __syscall(93, 21, 0, 0, 0, 0, 0) 51 } 52 // P[1][0] = 1/1 = 1_000_000 PPM 53 let p10: i64 = nx_markov_probability_ppm(m, 1, 0) 54 if p10 != 1000000 { 55 return __syscall(93, 22, 0, 0, 0, 0, 0) 56 } 57 // P[2][anything] = 0 (unobserved row). 58 if nx_markov_probability_ppm(m, 2, 0) != 0 { 59 return __syscall(93, 23, 0, 0, 0, 0, 0) 60 } 61 62 // ---- predict: most likely next state ---- 63 // From 0: best is 1 (count 2 > count 1 for state 2). 64 if nx_markov_predict(m, 0) != 1 { 65 return __syscall(93, 30, 0, 0, 0, 0, 0) 66 } 67 // From 1: best is 0 (only observed). 68 if nx_markov_predict(m, 1) != 0 { 69 return __syscall(93, 31, 0, 0, 0, 0, 0) 70 } 71 // From 2 (unobserved): -1. 72 if nx_markov_predict(m, 2) != -1 { 73 return __syscall(93, 32, 0, 0, 0, 0, 0) 74 } 75 76 // ---- step API (sequential streaming) ---- 77 let m2: *Markov = nx_markov_alloc(3) 78 // Sequence: 0 -> 1 -> 2 -> 0 -> 1 -> 2 -> 0 79 nx_markov_step(m2, 0) // seed (no transition yet) 80 nx_markov_step(m2, 1) // 0->1 81 nx_markov_step(m2, 2) // 1->2 82 nx_markov_step(m2, 0) // 2->0 83 nx_markov_step(m2, 1) // 0->1 84 nx_markov_step(m2, 2) // 1->2 85 nx_markov_step(m2, 0) // 2->0 86 // Transitions: 0->1 twice, 1->2 twice, 2->0 twice. 87 if nx_markov_count(m2, 0, 1) != 2 { return __syscall(93, 40, 0, 0, 0, 0, 0) } 88 if nx_markov_count(m2, 1, 2) != 2 { return __syscall(93, 41, 0, 0, 0, 0, 0) } 89 if nx_markov_count(m2, 2, 0) != 2 { return __syscall(93, 42, 0, 0, 0, 0, 0) } 90 if nx_markov_total(m2) != 6 { return __syscall(93, 43, 0, 0, 0, 0, 0) } 91 // Deterministic cycle: P[0][1]=1.0, P[1][2]=1.0, P[2][0]=1.0. 92 if nx_markov_probability_ppm(m2, 0, 1) != 1000000 { 93 return __syscall(93, 44, 0, 0, 0, 0, 0) 94 } 95 96 // ---- input validation ---- 97 if nx_markov_observe(m, -1, 1) != -1 { 98 return __syscall(93, 50, 0, 0, 0, 0, 0) 99 } 100 if nx_markov_observe(m, 0, 99) != -1 { 101 return __syscall(93, 51, 0, 0, 0, 0, 0) 102 } 103 if nx_markov_step(m2, 99) != -1 { 104 return __syscall(93, 52, 0, 0, 0, 0, 0) 105 } 106 107 // ---- typed envelope ---- 108 let q: *ApproxI64 = nx_markov_query_probability(m, 0, 1) 109 if q.envelope_kind != NX_ENV_ABS { 110 return __syscall(93, 60, 0, 0, 0, 0, 0) 111 } 112 if q.param_a != 1 { 113 return __syscall(93, 61, 0, 0, 0, 0, 0) 114 } 115 if q.maturity != NX_MATURITY_PRODUCTION { 116 return __syscall(93, 62, 0, 0, 0, 0, 0) 117 } 118 119 // ---- reset ---- 120 nx_markov_reset(m) 121 if nx_markov_total(m) != 0 { return __syscall(93, 70, 0, 0, 0, 0, 0) } 122 if nx_markov_count(m, 0, 1) != 0 { return __syscall(93, 71, 0, 0, 0, 0, 0) } 123 if nx_markov_probability_ppm(m, 0, 1) != 0 { return __syscall(93, 72, 0, 0, 0, 0, 0) } 124 125 return 0 126}