Skip to content

Add Kendall (1940) circular-triads consistency test and coefficient of agreement u - #296

Merged
seonghobae merged 1 commit into
seonghobae-top1from
seonghobae-kendall
Jul 31, 2026
Merged

Add Kendall (1940) circular-triads consistency test and coefficient of agreement u#296
seonghobae merged 1 commit into
seonghobae-top1from
seonghobae-kendall

Conversation

@seonghobae

@seonghobae seonghobae commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Iteration 57 of the autonomous paper-implementation loop. Stacked on #295 (seonghobae-top1).

Kendall & Babington Smith (1940): circular triads + coefficient of agreement u

Source governance: CRAN eba 1.10-0 R/circular.R, R/kendall.u.R, man/circular.Rd, man/kendall.u.Rd — READ (implementation source). Kendall & Babington Smith (1940, Biometrika 31, 324-345) and Alway (1962, exact null tables) — NOT READ (acquisition failed); cited as origins as described by the eba source.

What

  • scaling::circular_triads(mat, n, alternative, correct) — number of circular triads T = C(n,3) - sum_j C(d_j,2) (integer form, proves integrality; algebraically equal to eba's n(n-1)(2n-1)/12 - sum(d^2)/2), T_max (parity-split), T_exp = C(n,3)/4, zeta = 1 - T/T_max; EXACT null p-values for n <= 10 from embedded null distributions (p-values are dyadic rationals k/2^C(n,2), pinned with assert_eq!), continuity-corrected chi-square for n >= 11 with tail inversion (less = upper chi-square tail per eba).
  • scaling::kendall_u(mat, n, correct)Sigma, u = 2 Sigma / (C(m,2) C(n,2)) - 1, min_u (-1/m odd, -1/(m-1) even), RAW chi-square (can be negative under the continuity correction — pinned at exactly -1 in a fixture; only the p-value clamps), df = C(n,2) m(m-1)/(m-2)^2.
  • PyO3 bindings + Python wrappers with CircularTriadsResult/KendallUResult dataclasses; validation before casts (complex, object dtype, square 2-D, n cap).

Documented divergences from eba

  • circular(): n = 2 rejected (T_max = 0 makes zeta undefined); incomplete/non-binary tournaments and nonzero diagonals rejected instead of returning garbage.
  • kendall.u(): eba derives m from the FIRST pair only and never checks its equal-observations assumption — here every pair must satisfy M_ij + M_ji = m >= 3; entries capped at 1e6 so all binomials stay exact in u64.

Evidence discipline

  • Exact-Fraction oracle (kendall_oracle.py) EXECUTED all-pass before spec review: 1940 dog example (T=5, zeta=3/8, p_less=1043/2048), transitive n=5 two-sided (9/64), n=12 chi-square path (chi2=121/8, df=165/8 vs scipy), agreement fixtures (Sigma=11, u=2/9, chi2=11, df=9; perfect u=1; negative raw chi2=-1).
  • Adversarial spec-verify BEFORE implementation: APPROVED-WITH-CHANGES, all 8 mandatory changes adopted (incl. proof that the row/colsum mutant is algebraically invisible for complete tournaments — replaced with a drop-the-square mutant; two-sided break-loop = R cumsum equivalence proof).
  • 11 Rust tests + 8 Python tests; every assert reads crate-returned values. Table integrity: sum(freq) = 2^C(n,2) for all n = 2..10.
  • 5 mutants EXECUTED and killed: MU1 drop pairing (9/1 fail), MU2 T_max parity swap (8/2), MU3 drop opposite-tail extra (8/2), MU4 chi-square corr sign flip (9/1), MU5 drop Sigma continuity correction (6/4); baseline restored green.
  • Full suites: cargo 769 pass / pytest 289 pass.

Adversarial impl-review outcome (post-merge-of-review)

Independent adversarial review (background agent, full report in session files kendall_impl_review.md): CLEAN — round 1, no confirmed findings.

Verified by execution: Rust kd_ tests 10 pass + MC-500 ignored pass; Python 8 pass; line-by-line fidelity vs eba circular.R/kendall.u.R (T integer form, T_max parity, exact-table indexing, chi-square + tail directions, kendall.u Sigma/u/min_u/chi2/df); adversarial probes (NaN/inf/complex/object/non-contiguous/Fortran/case-sensitive alternative/huge n) all ValueError or correct; brute-force exact p-values over all tournaments for small n match the crate for all alternatives; scipy chi-square cross-check n=15 all alternatives, correct=True/False; 2 mutation spot-checks re-executed and killed.

Implements the Kendall & Babington Smith (1940) circular-triad
consistency test and coefficient of agreement u, as implemented by the
eba R package 1.10-0 (circular.R / kendall.u.R, source READ; the 1940
paper and Alway's exact tables NOT READ, cited as origins per eba's
manual pages).

- Rust core scaling::circular_triads: T = C(n,3) - sum_j C(d_j,2)
  (integer arithmetic), T_max, T_exp = C(n,3)/4, zeta = 1 - T/T_max;
  EXACT null p-values for n <= 10 from embedded distributions (dyadic
  rationals, assert_eq!-pinned), continuity-corrected chi-square for
  n >= 11 (df = n(n-1)(n-2)/(n-4)^2). Documented divergences from eba:
  n = 2 and malformed/incomplete tournaments are rejected.
- Rust core scaling::kendall_u: Sigma, u = 2*Sigma/(C(m,2)*C(n,2)) - 1,
  min_u, RAW chi-square (can be negative under continuity correction;
  only the p-value clamps), df = C(n,2)m(m-1)/(m-2)^2. Stricter than
  eba: every pair must have the same m >= 3 judges.
- PyO3 bindings + Python wrappers circular_triads / kendall_u with
  CircularTriadsResult / KendallUResult dataclasses; input validation
  before casts.
- 11 Rust tests (exact-Fraction oracle pins: 1940 dog example, n = 12
  chi-square path vs scipy, table integrity sum = 2^C(n,2), negative
  raw chi2, error contracts, MC-500 invariants #[ignore]); 8 Python
  tests. Five mutants (drop pairing, T_max parity swap, drop
  opposite-tail, corr sign flip, drop Sigma correction) all EXECUTED
  and killed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a69db000-ae2f-4d56-a79c-597469037132

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch seonghobae-kendall

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae merged commit 388f29d into seonghobae-top1 Jul 31, 2026
6 checks passed
@seonghobae
seonghobae deleted the seonghobae-kendall branch July 31, 2026 12:37
@seonghobae

Copy link
Copy Markdown
Contributor Author

Note: this PR was squash-merged into a non-main stacked base, so its commits did not land on main via this PR. The feature set reached main via #374 (stack tip integration) after #290.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant