Skip to content

P3: prove partition correctness generally (all n, k), not hand-picked vectors#40

Merged
hyperpolymath merged 4 commits into
mainfrom
claude/new-session-1fphit
Jun 27, 2026
Merged

P3: prove partition correctness generally (all n, k), not hand-picked vectors#40
hyperpolymath merged 4 commits into
mainfrom
claude/new-session-1fphit

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

What & why

Proofs.idr verified partition completeness/disjointness only on a few explicit slice vectors (tenAcrossTwo, tenAcrossThree). The §5.6 frontier is partition correctness over perItemSlices for all inputs — which is hard because perItemSlices uses div/mod, and those don't reduce at the type level.

Insight

Contiguity is structural: perItemSlices' inner go offset (S r) = MkSlice offset cnt :: go (offset+cnt) r places each slice exactly where the previous ended, independent of the cnt values. So the non-overlap guarantee can be proven for all n, k without ever reducing div/mod.

Change — new module Chapeliser.ABI.Partition

  • contiguousComplete — for any start and any count vector, sliceSum (contiguousFrom start counts) = sumNat counts (general completeness, by induction).
  • Tiling + contiguousTiles — a gapless, overlap-free cover, proven for any counts. Strictly stronger than the pairwise disjoint Bool check.
  • tilingStartsGE / tilingHeadNoOverlap — derive genuine propositional pairwise non-overlap (LTE) from a tiling, generically (the compare-based Bool <= and foldl-based all don't reduce symbolically, so the proof uses propositional LTE).
  • blockPartitionTiles — the headline: the real block partition is a non-overlapping tiling for ALL n, k. blockPartitionComplete isolates the sole residual — the div/mod identity sumNat (perItemCounts n k) = n — flagged as future work.
  • shortPartitionNotComplete — negative control (a 3-locale layout summing to 9 is provably not a complete partition of 10).

Verification (Idris2 0.7.0)

  • Full ABI builds clean (all 5 modules, zero warnings); no believe_me/postulate/holes.
  • Adversarial: a Tiling for deliberately overlapping slices [0,5)/[3,8) is rejected by the type checker (Mismatch between 2 and 0) — the non-overlap certificate is non-vacuous; and the general theorem instantiates at concrete n,k.

Second of the priority-repo P3 deepenings (chapeliser #2).

Note: this branch also carries the ABI↔FFI gate (scripts/abi-ffi-gate.py + workflow), which had not yet merged into main for this repo — it rides along here. The ABI-FFI Gate check is green.

CI note

rust-ci / Hypatia / governance reds are pre-existing estate-infra unrelated to this change.

🤖 Generated with Claude Code

https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH


Generated by Claude Code

claude and others added 4 commits June 26, 2026 22:03
The Idris2 ABI in src/interface/abi/Chapeliser/ABI/Foreign.idr is the
source of truth for the C-ABI contract. It declares 12 foreign symbols
via `%foreign "C:c_*, libchapeliser_ffi"`:

  c_init, c_shutdown, c_get_total_items, c_load_item, c_store_result,
  c_process_item, c_process_chunk, c_reduce, c_is_match, c_key_hash,
  c_checkpoint_save, c_checkpoint_load

The Zig FFI reference implementation exported these as
`chapeliser_ref_<stem>` instead. The functions correspond 1:1 by stem
and the Result codes already match, but the symbol names diverged, so
the ABI and FFI would not link (every `c_*` import would be undefined).

Fix (Zig-only, ABI unchanged because it is the source of truth):
  - Rename the 12 ABI-declared exports from `chapeliser_ref_<stem>` to
    exactly `c_<stem>` in src/interface/ffi/src/main.zig.
  - The two extra utility functions (`version`, `build_info`) are NOT
    part of the ABI, so they are namespaced as `chapeliser_version` and
    `chapeliser_build_info` rather than given `c_` names.
  - Update all internal call sites in main.zig tests and the
    `extern fn` declarations in test/integration_test.zig accordingly.

No behaviour or result-code values changed.

Verification:
  - `zig build test` (main.zig unit tests): pass
  - `zig build test-integration` (links the lib, resolves externs): pass
  - `idris2 --build chapeliser-abi.ipkg`: exit 0
  - Every `C:c_<name>` in Foreign.idr now has a matching
    `export fn c_<name>` in main.zig.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH
Adds scripts/abi-ffi-gate.py + .github/workflows/abi-ffi-gate.yml enforcing
that the Zig FFI matches the Idris2 ABI (source of truth), on top of this
branch's FFI fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH
… vectors

Proofs.idr verified completeness/disjointness only on explicit slice vectors
(tenAcrossTwo, tenAcrossThree). This module, Chapeliser.ABI.Partition, lifts
those invariants to the whole contiguous-partition family — quantified over an
arbitrary vector of per-locale counts — and applies them to the actual block
strategy (the div/mod counts of perItemSlices) for ALL n items and k locales.

Key idea: contiguity is structural — a contiguous layout places each slice
exactly where the previous one ended, independent of the count values — so the
non-overlap guarantee needs no reasoning about div/mod (which do not reduce at
the type level).

- contiguousComplete: for any start and any counts, sliceSum (contiguousFrom
  start counts) = sumNat counts (general completeness, by induction).
- Tiling + contiguousTiles: a gapless, overlap-free cover proven for any start
  and any counts; strictly stronger than the pairwise `disjoint` Bool check.
- tilingStartsGE / tilingHeadNoOverlap: derive genuine propositional pairwise
  non-overlap (LTE) from a tiling, generically.
- blockPartitionTiles: THE result — the real block partition is a tiling for
  ALL n, k. blockPartitionComplete isolates the sole residual, the div/mod
  identity sumNat (perItemCounts n k) = n.
- shortPartitionNotComplete: negative control (a 3-locale layout summing to 9
  is provably not a complete partition of 10).

Adversarially verified under Idris2 0.7.0: full ABI builds clean (zero
warnings, no believe_me/postulate/holes); a Tiling for deliberately
overlapping slices is rejected by the type checker (start mismatch), so the
non-overlap certificate is non-vacuous.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH
@hyperpolymath hyperpolymath marked this pull request as ready for review June 27, 2026 10:06
@hyperpolymath hyperpolymath merged commit 1eae83d into main Jun 27, 2026
15 of 25 checks passed
@hyperpolymath hyperpolymath deleted the claude/new-session-1fphit branch June 27, 2026 10:06
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.

2 participants