code wiki / _hdl_build / nx_pagerank_build_gate.nx
nx_pagerank_build_gate.nx source
↩ module page · 93 lines · 5209 B
1// nx_pagerank_build_gate.nx -- P1 STEP 2 gate: writes a synthetic out:<cid> link graph (a hub: A,B,C -> H)
2// to a /tmp shard, runs pb_run (collect edges -> pr_compute -> store pr:<cid>), and proves the SINK H is the
3// highest-authority node + rank conservation (~PR_SCALE). Distinguishing: PageRank is the ONLY signal that
4// makes H (3 in-links, no out-links) outrank the leaves. license_tier: ORIGINAL
5import "nx_pagerank_build.nx"
6
7func gp_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
8func gp_num(v: i64) -> i64 {
9 let bb: *u8 = sys_mmap(28); var m: i64 = v
10 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
11 let t: *u8 = sys_mmap(28); var k: i64 = 0
12 if m == 0 { t[0] = 48 as u8; k = 1 }
13 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
14 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
15 sys_write(1, bb, k); return 0
16}
17func gp_check(name: *u8, cond: i64, pass: *i64, total: *i64) -> i64 {
18 total[0] = total[0] + 1
19 gp_puts(name)
20 if cond == 1 { pass[0] = pass[0] + 1; gp_puts(" PASS\n" as *u8) } else { gp_puts(" FAIL\n" as *u8) }
21 return 0
22}
23// "out:<cid>" key (the gate writes edges; the builder reads them)
24func gp_outkey(cid: i64, out: *u8) -> i64 {
25 out[0] = 111 as u8; out[1] = 117 as u8; out[2] = 116 as u8; out[3] = 58 as u8
26 var m: i64 = cid; let t: *u8 = sys_mmap(28); var k: i64 = 0
27 if m == 0 { t[0] = 48 as u8; k = 1 }
28 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
29 var i: i64 = 0; while i < k { out[4 + i] = t[k - 1 - i]; i = i + 1 }
30 out[4 + k] = 0 as u8; return 4 + k
31}
32// read pr:<cid> -> rank (0 if absent)
33func gp_pr(h: *i64, cid: i64) -> i64 {
34 let key: *u8 = sys_mmap(32); pb_prkey(cid, key)
35 let pp: *i64 = sys_mmap(16) as *i64
36 let pl: *i64 = sys_mmap(16) as *i64
37 if ss_hget(h, key, pp, pl) == 1 { if pl[0] == 8 {
38 let vp: *i64 = pp[0] as *i64 // temp, NOT inline (pp[0] as *i64)[0] -- inline cast-index miscompiles
39 return vp[0]
40 } }
41 return 0
42}
43func main() -> i64 {
44 gp_puts("=== nx_pagerank_build gate (link graph -> PageRank -> pr:<cid>) ===\n" as *u8)
45 let pass: *i64 = sys_mmap(16) as *i64; pass[0] = 0
46 let total: *i64 = sys_mmap(16) as *i64; total[0] = 0
47
48 // hub graph (bidirectional so H is a CRAWLED page, not a bare link target): leaves A(1001) B(1002)
49 // C(1003) each link ONLY to H(9999); H links back to all three EQUALLY. This matches the real corpus
50 // where every served doc was crawled and therefore has outlinks (is an out: source) -- the persist
51 // filter (2026-07-23 seq631 fix) only stores pr: for source docs, so a pure-sink H would (correctly)
52 // get no prior. H links to A,B,C equally -> leaves stay equal; H keeps 3 in-links -> H stays top.
53 let prefix: *u8 = "/tmp/prgate-" as *u8
54 let w: *i64 = ss_begin()
55 let okey: *u8 = sys_mmap(64)
56 let tv: *i64 = sys_mmap(16) as *i64
57 tv[0] = 9999
58 gp_outkey(1001, okey); ss_add(w, 1, okey, tv as *u8, 8)
59 gp_outkey(1002, okey); ss_add(w, 1, okey, tv as *u8, 8)
60 gp_outkey(1003, okey); ss_add(w, 1, okey, tv as *u8, 8)
61 let tvh: *i64 = sys_mmap(32) as *i64 // H -> [A, B, C] (3 packed target cids)
62 tvh[0] = 1001; tvh[1] = 1002; tvh[2] = 1003
63 gp_outkey(9999, okey); ss_add(w, 1, okey, tvh as *u8, 24)
64 ss_commit(prefix, w, 1)
65
66 // build: collect edges -> pr_compute -> store pr:<cid>
67 let N: i64 = pb_run(prefix, 100, 900000)
68 gp_check("T1 graph has 4 nodes (A,B,C,H)" as *u8, (N == 4) as i64, pass, total)
69
70 let h2: *i64 = ss_open(prefix)
71 let prH: i64 = gp_pr(h2, 9999)
72 let prA: i64 = gp_pr(h2, 1001)
73 let prB: i64 = gp_pr(h2, 1002)
74 let prC: i64 = gp_pr(h2, 1003)
75 // T2 pr rows stored for every SOURCE doc (all four are sources now -> all present, positive)
76 var t2: i64 = 0
77 if prH > 0 { if prA > 0 { if prB > 0 { if prC > 0 { t2 = 1 } } } }
78 gp_check("T2 pr:<cid> stored for every source doc (>0)" as *u8, t2, pass, total)
79 // T3 THE PAGERANK PROPERTY: the hub H (3 in-links) outranks a leaf A (1 in-link)
80 gp_check("T3 authority: pr(H) > pr(A) [hub outranks leaf]" as *u8, (prH > prA) as i64, pass, total)
81 // T3b symmetry: the three leaves are equal-authority (identical role)
82 gp_check("T3b leaves equal (pr(A)==pr(B)==pr(C))" as *u8, ((prA == prB) as i64) * ((prB == prC) as i64), pass, total)
83 // T4 conservation liar-killer: total rank ~ PR_SCALE (0.8..1.2x) -> the iteration really ran, no garbage
84 let sum: i64 = prH + prA + prB + prC
85 var t4: i64 = 0
86 if sum > (PR_SCALE - PR_SCALE / 5) { if sum < (PR_SCALE + PR_SCALE / 5) { t4 = 1 } }
87 gp_puts(" (sum="); gp_num(sum); gp_puts(" PR_SCALE="); gp_num(PR_SCALE); gp_puts(" prH="); gp_num(prH); gp_puts(" prA="); gp_num(prA); gp_puts(")\n" as *u8)
88 gp_check("T4 rank conservation ~PR_SCALE (real iteration, not garbage)" as *u8, t4, pass, total)
89
90 gp_puts("=== pagerank-build gate: " as *u8); gp_num(pass[0]); gp_puts("/" as *u8); gp_num(total[0]); gp_puts(" " as *u8)
91 if pass[0] == total[0] { gp_puts("verdict=GREEN\n" as *u8); return 0 }
92 gp_puts("verdict=RED\n" as *u8); return 1
93}