wordgraph-compile
The groupant beside wordgraph/src/compile.rs in the Mova repository: what the code computes, what it never does, how to go back from its outputs, its invariants, cost and checks.
Facts
Implementation material. A Mova code model describes this code at one source revision: partial models, finite checks and their stated scope. It is not a reviewed general exposition, and its labels are shown as written, never raised.
Components
| component | label | where |
|---|---|---|
| Approximant | partial | Approximant |
| Ast | partial | syntax.json |
| Composition | partial | Composition |
| Cost | partial | Cost |
| Descriptant | present | Descriptant |
| Invariant | partial | Invariant |
| Tests | executed bounded checks | Tests |
Obernants
The typed relations around the forward model: the behaviour complement (what the code never does), the reverse reconstruction (every input compatible with an output) and specialised views.
| relation | type | label | where |
|---|---|---|---|
| Behavior complement | behavior complement | partial source derived model | Behavior complement |
| Reverse reconstruction | reverse reconstruction | partial source derived model | Reverse reconstruction |
Model text
Descriptant
The build: passes → one graph file. Unites the parts' OOV tables, merges all parts twice with a k-way heap merge
(marginals, then candidates), scores pairs with PMI and LMI, keeps the top k (or k_core for core argument
relations) per (head, relation) and per (dependent, relation), assigns registry ids to kept OOV words, writes the file
through graph::Writer. Epoch 2026-11-06: LMI chosen for selection as the observed-cell term of G²; k_core = 128
chosen after a k = 32 probe on the absurdity matrix (recorded in the README).
Approximant
With merged counts c(h,r,d), marginals c(h,r,·), c(·,r,d), N_r: candidates C = {(h,r,d) : c ≥ m, keep(h), keep(d), PMI > 0}, PMI = log2(c·N_r / (c(h,r,·)·c(·,r,d))), LMI = c·PMI, keep(n) ⇔ n is a dictionary word or freq(n) ≥ min_oov. F = ⋃{(h,r)} top{bound(r)} by (LMI desc, d asc); R = ⋃{(d,r)} top{bound(r)} by (LMI desc, h asc). Nodes = ends of F ∪ R, sorted by (final word id, UPOS); edges stored in ranking order.
Invariant
Output bytes are a function of (set of parts, parameters, registry contents): parts are sorted by path, merge sums are
commutative, every sort has a total tie-break, f32 values come from deterministic f64 arithmetic (two builds of
the 50 k pass byte-identical, 2026-11-06; reversed pass order identical in tests/build.rs). Each group holds at
most bound(r) edges. The OOV rank map is monotone, so merged streams stay sorted; a non-increasing record aborts
the build. The registry is only appended, in byte order of new strings.
Cost
Time O(M log P) for each of two merges (M records, P parts) + O(K log K) for the candidate sorts; memory: marginal hash maps (distinct (h,r) and (r,d)) + 32 B per candidate + the OOV union. Measured 2026-11-06, 50 k pass: 74 M records, 35 M merged triples, 4.4 M candidates, 58 s, 1.25 GB peak.
Composition
Reads pass parts and metas; writes through graph::Writer; parameters from the CLI.
Tests
tests/build.rs: byte-identical rebuild, order independence, bound, registry content, the shuffled control losing
the signal (red side asserted).
Behavior complement
Does not smooth PMI, does not weigh sources, does not prune by PMI threshold other than > 0, does not compress the file, does not remove registry lines, does not verify part SHA-256 against sidecars, does not detect overlapping passes, does not keep counts exactly (log-quantized in the file).
Reverse reconstruction
From the file: the kept pairs, quantized PMI and approximate counts, node frequencies and pass provenance. Not recoverable: pruned pairs, exact counts, marginals, the source sentences. A missing edge admits an unseen pair, a pair with c < min_count, PMI ≤ 0, or one ranked below the bound in both directions.
Provenance
This page in Markdown → https://md.groupants.elamur.ai/free/en/mova/wordgraph/src/compile.rs.groupant/