Mova0.6 pre-release⌕
☰
home / docs / repo-docs / Correspondences

Correspondences

This page describes typed mathematical correspondences between algorithm groupants and ordinary Mova sources: what a correspondence is, how the mova-correspondence scanner checks the catalogue, how to repeat a review, the relation algebra and evidence model, short worked cases (gcd, digits and Horner, LCS, edit-distance continuation, penalty tuning), and how algorithm ideas are transferred into Mova through explicit adapters. Groupants themselves are described in groupants; vidtvorants and typed obernants in mathematical modeling.

What a correspondence is

The ownership registry is a tree: every Rust file has one owner. Correspondences form a separate graph across that tree. They live in models/correspondences.json as typed, source- and model-bound finite formulas — explicit relation instances, never equations inferred from prose or matching names.

Source coverage, typed-formula coverage, finite equality and proved abstract laws are different measurements. Prose, registration and matching names never fill a missing formalization.

The scanner

cargo build --offline --locked --release -p mova-correspondence -p mova-modelcheck
target/release/mova-correspondence scan "$REPO" "$REGISTRY" "$REPO/models/correspondences.json" "$RUN/scan-1.json"
target/release/mova-correspondence scan "$REPO" "$REGISTRY" "$REPO/models/correspondences.json" "$RUN/scan-2.json"
cmp "$RUN/scan-1.json" "$RUN/scan-2.json"

REPO is the reviewed checkout, REGISTRY its public registry or a freshly composed one (mova-modelcheck compose-registry BASE OVERLAY NEW_JSON; keep overlay reports out of public exports), RUN a new external run directory. Catalogue and bindings must describe the same checkout. The output must be new; missing or stale bindings stop the scan instead of refreshing claims. Two scans of the same inputs must be byte-identical.

The report lists missing roles, typed formula comparisons, finite coincidences, counterexamples, incompatible contracts and admitted compositions. Pure algorithm, pure non-algorithm and mixed ancestors have separate meanings; keep the report's classification. The normalizer is deliberately incomplete: it builds a deterministic order-preserving minimum-height composition tree, commutes converse with complement, keeps a bounded fallback when pushing converse would exceed the node budget, and must stay idempotent. Composition summaries distinguish total and surjective from functional (at most one output) and injective (univalent converse), including empty endpoint sets. The finite relation AST does not parse Markdown, arithmetic recurrences, Rust macros or program semantics. See the tool README.

Native bridges in tools/correspondence/tests/ (bridges.rs, lcs_bridges.rs) call the actual public APIs and bind each catalogue row to declared input labels and computed output labels.

Relation algebra

For R:X→Y, S:Y→Z and a forbidden relation T:X→Z,

(R;S) ∩ T = ∅  ⇔  (Rᵒ;T) ∩ S = ∅  ⇔  (T;Sᵒ) ∩ R = ∅

connects forward computation, converse and exclusions. The residual

R;S ⊆ T  ⇔  S ⊆ ¬(Rᵒ;¬T)

constrains a following stage. The abstract laws are proved in Lean (composition, residual); that proof is separate evidence from a finite interpretation and from source correspondence.

Repeating a review

  1. Read the working rules and prior epoch evidence. Check the source revision, worktree changes and catalogue hashes. Edit in an isolated worktree.
  2. Scan the current registry and inspect missing roles, comparisons, counterexamples and admitted compositions.
  3. Pick one bounded candidate from real source/model mechanisms: a shared recurrence, a projected observation, a conservation law or invariant, a monotone bound, a converse fiber, the conditioning of an approximate inverse. A matching word is only a lead.
  4. Before implementing, state input and output types, domain, observation, assumptions, effects and the expected relation. Add a manually reviewed formula only for what can be represented faithfully.
  5. Check an independent witness against the actual Rust APIs. Include a plausible false candidate: lost state, a different scalar field, changed error behavior, non-injectivity, undefined arithmetic. Keep successful and rejected outcomes. Never certify a program by copying its desired result into both sides of a test.
  6. Only after a useful mathematical result, consider a production change. Preserve reference behavior and measure the affected path before claiming speed or accuracy. Error composition needs compatible metrics, image/domain containment and a downstream sensitivity bound.
  7. Update source-bound groupants, syntax artifacts and parent composition models; run focused tests and the modelcheck gates (groupants).

Rescanning an unchanged catalogue rediscovers the same relations. Progress is a justified new formalization, a better adapter or a useful rejected lead — not more identical reports. The loop needs no teacher, training, corpus or held-out assessment.

Worked cases

Gcd and modular arithmetic

The algorithm gcd equals public arbitrary-integer math::nt::gcd after lossless unsigned conversion on the declared domain. Both return zero at (0,0). The converse keeps all compatible input pairs: output two has several antecedents, so no unique inverse follows. For modular multiplication with m≠0, an output y has gcd(a,m) preimages when the gcd divides y and none otherwise; units give unique reconstruction. Algorithm CRT and math::nt::crt agree on nonempty valid inputs whose lcm fits u64; their empty, zero-modulus and overflow contracts differ.

Elimination: small unit-diagonal integer systems satisfy both rational equations and modular reductions, but direct solver equivalence is rejected. 998244353*x=1 is uniquely solvable over Q and inconsistent over F_998244353.

Digits and Horner

math::nt::from_digits folds most-significant-first integer coefficients; the algorithm Horner API takes ascending coefficients and returns a value and a derivative behind a Result. Reversing coefficients connects their values on an exact domain. Write H_b(d)=Σ d_i b^(k-1-i) and D_b(n) for digits(n,b) (u32 b≥2, canonical word of |n|, zero as [0]).

relationdomain and observation
H_b(D_b(n)) = |n|integer n, b≥2; the sign is lost
D_b⁻¹(c) = {H_b(c), −H_b(c)}canonical nonempty words; the zero fiber is a singleton
N_b = D_b∘H_b, N_b² = N_bmagnitude normalization, not signed-value preservation
H_b⁻¹(n) = {(p, n − b·H_b(p))}fixed length k≥1, p ∈ Z^(k−1); infinitely many antecedents for k≥2

Adjacent carries (u,v)→(u+t, v−b·t) preserve H. A successful Horner value equals H when every conversion and value operation is exact; bounding base, coefficients and intermediates by 2^53 is a sufficient premise. Real counterexamples reject wider transfers: an intermediate rounding at b=2^53, a base that aliases on conversion at b=2^53+1, and a derivative overflow that makes the algorithm reject an input whose value is exactly zero. Without reversal, [1,2] at base 10 gives 21 instead of 12.

Unrestricted Horner versus Poly::eval_f64 also fails: [0,0,10^308] at one overflows the derivative, so the algorithm rejects while the ordinary value is finite.

Longest common subsequence

en::text::lcs (en/src/text.rs) computes LCS length for tokenizer evaluation and text metrics. It keeps two rolling rows and returns zero before allocating when either side is empty; the comparison schedule is unchanged. The catalogue holds three forward rows with one contract — lcs.ordinary, lcs.algorithm, lcs.bitparallel — observing length only on listed byte fixtures (shorter side at most 64, successful returns). The scanner reports finite coincidences between the ordinary row and each algorithm row; same-direction LCS relations do not compose with one another.

The histogram bound Σ_t min(count_a(t), count_b(t)) ≤ min(len a, len b) is an upper bound only: [1,2] versus [2,1] has bound 2 and LCS 1. It is an interval/filter idea, not a substitute value and not a percentage-error certificate. Callers pass tokens or characters; raw UTF-8 byte LCS cannot replace character LCS.

cargo test --offline --locked -p mova-correspondence --test lcs_bridges

Edit-distance continuation

For a fixed pattern p, let F_p(t) be unit-cost Levenshtein distance. A cache that keeps only Q_p(t)=(F_p(t), |t|) cannot update the distance when a byte arrives:

patternhistoryscorelengthnext bytenew score
aba11b0
abb11b1

The same arguments would need two different results. The converse of Q_p followed by append and distance is a many-valued relation (T_ab(1,1,b)={0,1}); picking one representative history does not preserve future observations. A parent model must keep the ambiguity or retain a stronger state (a row or bit vector). Empty and singleton patterns, and an Eq type with one class, do admit scalar updates. The metric still gives the partial exclusion max(0,d−1) ≤ F_p(tc) ≤ d+1.

The Myers implementation checks pattern length ≤64 before text length ≤65536. The metric is symmetric but the full Result is not: a 65-byte pattern against empty text errors, while the exchanged call succeeds. Orienting the shorter input as pattern would admit more calls but change error observations, so it is not an equivalent replacement. Reproduce the check:

rustc --edition=2024 -O --crate-name continuation_check \
  algorithms/src/myers_bitvector/mod.rs.groupant/continuation-check.rs.txt \
  -o "$RUN/continuation-check"
"$RUN/continuation-check"

Models: Myers, generic, parent composition.

Penalty model for segmentation

General Viterbi and the segmentation shortcut agree in objective for finite nonnegative switch costs; paths may differ on ties, so this is not a substitution. For fixed emissions, V(λ)=max_p(E(p) − λ·switches(p)) is a maximum of affine functions: convex, nonincreasing and piecewise linear for λ≥0. At a unique optimum its derivative is minus the switch count; at ties the subgradients span the competing slopes. This gives cheap consistency checks and penalty tuning. A penalty that forces a constant path must be derived from emission-score ranges, not chosen as an arbitrary large constant.

Algorithm transfers

An algorithm model helps an application only through an explicit adapter that preserves the application's observation. For reference M, algorithm A, input adapter α and output projection β:

Obs(M(x)) = β(x, A(α(x)))   on a declared domain.

Surrounding validation and effects stay part of the application contract. Transfers add edges to the correspondence graph; they do not change algorithm ownership or invent production calls. The catalogue records reviewed transfers; it is not an automatic semantic matcher, and nothing is substituted automatically.

transferadapter and retained observationresource policy
BFS → annotation gatereverse each validated token→head arc; from root reachability pick the first unreachable token; keep Count/Form/Head/Registry/Roots precedenceoriginal walks for ≤64 tokens; larger calls spend ≤4n head steps before whole-input BFS
root reachability → conversion gatekeep parsing, range, root-label and first-failed-start policies; coloring realizes the graph property without BFSoriginal walks for n≤64; otherwise n+1 colors and ≤2n head transitions
heap order → coreference mention matchingexact spans first; residual edges by descending overlap, prediction ordinal, gold ordinal; accept only free endpoints; keep greedy identitiessort only when both sides have ≥128 mentions and the checked product is ≤262144; otherwise scan
Hungarian storage schedule → assignment scorereuse slack/visited buffers, reset every augmentation; keep floating-point arithmetic and selection ordertwo scratch allocations instead of two per row
BFS adjacency → spatial inferenceproject directional facts and lawful inverse edges into ordered rows; keep vertex, far, capped steps and all-qualified flagsscan for E≤64; larger queries reject absent outgoing starts before building rows

The root-reachability gate in closed form: after preflight, set successor[0]=0, successor[i]=head[i]; a tree is accepted iff every token shares token 0's cycle ID, and the first error is the least token outside that basin. A parse success alone does not imply a tree.

Models: syntax validation, coreference observation, spatial inference.

Rejected combinations

Failed combinations show what an adapter must retain:

Limits

This page in Markdown → https://md.mova.elamur.ai/free/en/docs/repo-docs/correspondences/