Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/board/STATUS_BOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Plan: `.claude/plans/d-relalg-unified-v1.md`. Decisions recorded there: ADMISSIO
| **D-RU-1** | U1: JC statistical batch, distinct (selection, key, lane pair) triples over shared power-sum terminals | MEASURED (`crates/jc-batch-probe`; `entries/2026-10-20-u1-jc-batch.md`): 252 requests → 2 selection + 42 cross passes; at 1M rows 6.4× faster, 11.5× fewer rows traversed, 8.5× fewer values read, 126× fewer mask bytes; bit-identical to per-request; no R reference (R absent) | rows traversed and terminal passes below the per-request baseline; results bit-exact on integer lanes; overflow refused, not wrapped; R references |
| **D-RU-2** | U2: `let`-bound planes on the contract IR, immutable `Plane(i)`, versioned coordinates, no DAG inside a fold | MEASURED (`contract::set_program`, `relalg::program`; `entries/2026-10-21-u2-let-planes.md`): 16 queries sharing one conjunction at 1M rows: 3.1× faster, 14 vs 59 lane reads, 2 planes (250 kB) materialized, ≤ 2 scratch slots; answers equal recompute and a row oracle; other versions refused | rows traversed and planes materialized against recompute; width test ≤ 3 slots; answers and versions unchanged |
| **D-RU-3** | cross-rule CSE in crepe-plan-probe (256-rule benchmark, separate from the hop benchmark) | MEASURED (`crepe-plan-probe/src/cse.rs`, `examples/rule_cse.rs`; `entries/2026-10-21-u3-cross-rule-cse.md`): 256 rules, 90 % shared core, 200k centers: rows laid out 15.3 M → 6.2 M, prepare 1.78 s → 1.22 s; lets cut ops 512 → 283 but folds are ≤ 2.4 ms and `share` costs 7 ms; one table for all rules is slower than per-rule when nothing is shared, so tables are per group of rules sharing a side; answers equal crepe, ascent and the reference | answers == crepe and ascent; traversals and materializations measured |
| **D-RU-4** | co-addressed join operator over `JoinDomain` | Queued (after D-RU-2) | parity with the star path; no position taken from another table's values |
| **D-RU-4** | co-addressed join operator over `JoinDomain` | FAILED GATE — speed (no-ms rule, `CLAUDE.md` P0); correctness MEASURED (`crepe-plan-probe/src/coaddressed.rs`, `examples/coaddressed.rs`; `entries/2026-10-21-u4-coaddressed-join.md`): per-side `Rel`s at query time over one unrestricted table, `GroupReduce Count` on each side's own slot lane, `And` of slot planes; answers equal the star path, the nested-loop reference and every arm; no program has a foreign hop (disable-verified). Every arm of the benchmark, the star path's included, ran in milliseconds; open: fold the per-side `Rel` into the projection terminal | parity with the star path; no position taken from another table's values |
| **D-RU-5** | Quack physical pins (dense vs sorted, materialize vs recompute) | Queued (after D-RU-3/4) | can-fire and can-stay-silent per pin |
| **D-RU-6** | recursion driver over BIND tiles (256-hop benchmark) | Queued/Lab (slot assignment must be argued as an attested frozen-codebook lookup under ADMISSION = B). Lab probe MEASURED (`crepe-plan-probe/examples/walk_tile.rs`, `entries/2026-10-21-d-ru-6-tile-walk-probe.md`): tuple sets equal ascent, crepe and walk_mask; execution gather-free; binding witness probe-local, so ADMISSION B is NOT demonstrated; count-only 1.0–9.3× slower than walk_mask, end to end 1.1–2.0× slower. Block-sparse arm C MEASURED (`examples/walk_sparse.rs`, `entries/2026-10-21-d-ru-6-sparse-compute.md`): faster than the dense tile path on every fixture (0.11–0.96× count-only); against walk_mask end to end it wins only on deep low-fan-out recursion (chain(230) 0.82×, chain(700) 0.59× UNCHECKED), is near parity on sparse graphs (1.03–1.07×) and loses on dense, cyclic, clustered and mixed-length graphs (1.20–2.43×). Arm A′ (walk_mask with a dirty-frontier skip, `examples/walk_dirty.rs`, `entries/2026-10-21-d-ru-6-dirty-frontier.md`) does not remove C's chain lead; the chain sweep (two runs, distinct fan-out, like-for-like timing) confines C's end-to-end win over A′ to unbranched chains of about 192 nodes or more (3–30 %); with fan-out 2 or 4 C loses end to end at most points. Recommendation: defer the codebook attestation | least fixpoint == datafrog; ≥ 200 iterations asserted; cycles terminate. Benchmark requirement (operator, 2026-10-21; refs D-RMAP-2 §5b, #1642): tuple materialization, count-only evaluation, memory growth, address binding and value-derived reads by origin reported separately; tuple-set equality with crepe and ascent wherever they run |
| **D-RU-7** | prefetch and staging of Arm B ranges | Queued (after D-RU-6 or a non-recursive multi-stage plan) | critical-path overlap measured; bytes read unchanged |
Expand Down
52 changes: 52 additions & 0 deletions .claude/board/entries/2026-10-21-u4-coaddressed-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 2026-10-21 — D-RU-4 (U4): the co-addressed join as a named operator

**Status:** FAILED GATE (no-ms rule, `CLAUDE.md` P0, 2026-10-21) — correctness MEASURED, speed not (lab; `crates/crepe-plan-probe/src/coaddressed.rs`, `examples/coaddressed.rs`). Plan: `.claude/plans/d-relalg-unified-v1.md` §5.3, §6, stage table (U4). Builds on U2 (`relalg::run_with_program`) and the D-MPS-8 table (`mork_pathmap_probe::join`).

## What landed

- `coaddressed::eval(table, plan, rels, current)`: a conjunction of per-table `Rel`s over one `JoinDomain`. For each side `i`:
- `rel_i` runs as a relalg fold over side `i`'s own rows (lane 0 = the side's other column);
- one mask-risc `GroupReduce Count` keyed by the side's slot lane turns the selected rows into per-slot counts;
- a side whose `Rel` normalizes to `All` reads its presence plane and offsets as prepared, with no row read.
- The joint is relalg `And(Plane(i))` over the per-side slot planes. Answers:
- `distinct_centers`, the popcount of the joint;
- `bag_count`, a co-addressed dot product of the per-side counts (`Σ_slot Π_i count_i[slot]`) that enumerates no row;
- `matching(pattern)`, the derivations whose head reads as a pattern: a fold over the joint, no row built. (This replaced the first version's `bindings`, a tuple builder, in `1d1c0b77` after #1657 removed `native::bindings`.)
- `CoTable::prepare` lays out every side without its restriction. `plan_rels` turns a `StarPlan`'s restrictions into `value == k` (or `Empty` for a constant above `u32::MAX`). A restriction is therefore a query-time `Rel` and no longer part of the layout. The `Rel` can be anything relalg lowers on a `U32` lane (`==`, `!=`, `Or`, `Not`), which the star path cannot express.
- The slot lane is built from the side's own offsets, so it is non-decreasing. A row is counted in the run it already sits in, and no operand is read at a position taken from another operand's values. `CoEval::programs` keeps every program run so a caller can check that with `native::has_foreign_hop`.
- Refusals: a table holding other sides than the plan reads, the wrong number of `Rel`s or generations, a stale side.
- `mork_pathmap_probe::join::Side` gains two read-only accessors, `values()` and `offsets()`.

## Measured — failed gate

The benchmark (`examples/coaddressed.rs`: 64 queries `Out(x, c, z) <- R(x, c), S(c, z), T(c, q)`, 200,000 rows per relation, 20,000 centers) produced results in milliseconds for every arm: the per-query layout of the star path (`native::prepare`, with and without semijoin) and this operator alike. Under the `CLAUDE.md` P0 rule (2026-10-21) a millisecond result is a failed gate, not a measurement, so no timing is reported here. The first version of this entry and of #1658's body reported them; they are withdrawn.

What stays true and is not a timing: the operator lays the table out once and reads only the rows of sides whose `Rel` is not `All` (here T's value and slot lanes, 200k rows per query); the star path lays out all sides again per query.

**Where the operator leaves the mask-risc terminals** (from the code; not attributed by measurement):
- each filtered side keeps a full row mask (`Measure::Keep`) instead of folding into the terminal;
- the projection's `GroupReduce Count` sinks into an `i64` buffer of domain size (`8 × domain` bytes);
- the slot plane is built from those counts by a scalar Rust loop over the domain;
- `bag_count` / `matching` walk the joint bit by bit and multiply side counts in scalar code per slot;
- each filtered side runs two programs (fold, then projection).

**Correctness.**
- `parity_with_the_star_path`: for five restriction combinations (none; one; two; three; a constant above `u32::MAX`), the bag count, distinct centers and pinned per-derivation counts equal the star path (`native::matching` / `distinct_centers`). At least four of the five cases have answers.
- `disjunctive_restrictions_match_the_reference`: `Or`, `Not` and `!=` restrictions equal a nested-loop reference, bag and set.
- The benchmark asserts that the answers of every arm are equal on every rep, and `cargo test --example coaddressed` runs the same comparison on a small fixture in CI.
- **Disables:** five, each red on the test it targets:
- a projection that scatters by the slot lane (`ScatterOrU32`, answer-correct) fails only `no_gather`, at the gather assertion;
- row bits ignored in tuple enumeration;
- per-slot counts replaced by run lengths;
- witness check removed;
- stale-generation check removed.
- The first scatter disable used `ScatterCountU32` with an `Out::I64`. It failed on an `ExecError` before the gather assertion ran, so it proved nothing about that assertion. It was replaced with the answer-correct `ScatterOrU32` version above.

## Open

- **The speed gate.** Bring the per-query path to the mask-risc terminals: fold each side's `Rel` straight into the slot projection, sink into a plane rather than an `i64` buffer, and answer counts through a terminal over the kept joint. Until that runs in nanoseconds per operation (microseconds per batch), D-RU-4 is not shipped.

- The projection writes per-slot counts as `i64` for every filtered side (`8 × domain` bytes), and builds the slot plane from them in a Rust loop over the domain. A fused "count into plane" terminal would remove both; not built, not measured.
- Each filtered side runs two programs (fold, then projection) and keeps the row mask for tuple enumeration. When only counts are asked, the fold and the projection could be one program; not measured.
- No restriction on the center itself (a `Rel` over the domain) yet.
- §6 factorization beyond the star (a chain through two domains) is not built.
3 changes: 2 additions & 1 deletion .claude/board/entries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately
opposite directions; the stranding this convention prevents shows up in
exactly one of them, never both.

409 entries, 2026-08-06 .. 2026-10-21.
410 entries, 2026-08-06 .. 2026-10-21.

| date | entry id | finding | file |
|---|---|---|---|
| 2026-10-21 | `D-RU-4` | | [2026-10-21-u4-coaddressed-join.md](2026-10-21-u4-coaddressed-join.md) |
| 2026-10-21 | `D-RU-3` | | [2026-10-21-u3-cross-rule-cse.md](2026-10-21-u3-cross-rule-cse.md) |
| 2026-10-21 | `D-RU-2` | | [2026-10-21-u2-let-planes.md](2026-10-21-u2-let-planes.md) |
| 2026-10-21 | `tuple-zero-copy-council` | | [2026-10-21-tuple-zero-copy-council.md](2026-10-21-tuple-zero-copy-council.md) |
Expand Down
2 changes: 1 addition & 1 deletion .claude/plans/d-relalg-unified-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,4 @@ One workload, run under three toggles. Each toggle changes one mechanism only.
| U7 | prefetch and staging of Arm B ranges | U6 or a non-recursive multi-stage plan | critical-path overlap measured; bytes read unchanged |
| U8 | Wikidata and SAP-shaped fixtures; completeness refusals | U6, U7 | refusal tests; witness carried end to end |

U1 needs nothing new and comes first. **U1 MEASURED (2026-10-20, `crates/jc-batch-probe`, `entries/2026-10-20-u1-jc-batch.md`):** 252 requests reduce to 2 selection and 42 cross passes; at 1M rows the batch is 6.4× faster with 11.5× fewer rows traversed, 8.5× fewer values read and 126× fewer mask bytes, and its answers equal the per-request answers bit for bit. The R reference is replaced by JC's slice functions because R is not installed. **U2 MEASURED (2026-10-21, `contract::set_program` + `relalg::program`, `entries/2026-10-21-u2-let-planes.md`):** each shared junction subset is evaluated once into a scratch plane; for 16 queries sharing one conjunction at 1M rows the program is 3.1× faster than recompute and reads 14 lanes instead of 59, at the cost of 2 materialized planes (250 kB). Answers equal recompute and a row oracle, and a program for another version is refused. **U3 MEASURED (2026-10-21, `crepe-plan-probe/src/cse.rs` + `examples/rule_cse.rs`, `entries/2026-10-21-u3-cross-rule-cse.md`):** the §7 claim "one core join plus 256 ANDs" holds for the layout, not for the folds. At 90 % shared core the core is laid out once (15.3 M → 6.2 M rows, prepare 1.78 s → 1.22 s); the lets cut ops 512 → 283, but the folds cost ≤ 2.4 ms and the subset search 7 ms. One table for all rules is slower than per-rule tables when nothing is shared, so tables are formed per group of rules that share a side. Both are accepted only on measured row traversals, materializations and total cost (§ Decisions), not on operator counts.
U1 needs nothing new and comes first. **U1 MEASURED (2026-10-20, `crates/jc-batch-probe`, `entries/2026-10-20-u1-jc-batch.md`):** 252 requests reduce to 2 selection and 42 cross passes; at 1M rows the batch is 6.4× faster with 11.5× fewer rows traversed, 8.5× fewer values read and 126× fewer mask bytes, and its answers equal the per-request answers bit for bit. The R reference is replaced by JC's slice functions because R is not installed. **U2 MEASURED (2026-10-21, `contract::set_program` + `relalg::program`, `entries/2026-10-21-u2-let-planes.md`):** each shared junction subset is evaluated once into a scratch plane; for 16 queries sharing one conjunction at 1M rows the program is 3.1× faster than recompute and reads 14 lanes instead of 59, at the cost of 2 materialized planes (250 kB). Answers equal recompute and a row oracle, and a program for another version is refused. **U3 MEASURED (2026-10-21, `crepe-plan-probe/src/cse.rs` + `examples/rule_cse.rs`, `entries/2026-10-21-u3-cross-rule-cse.md`):** the §7 claim "one core join plus 256 ANDs" holds for the layout, not for the folds. At 90 % shared core the core is laid out once (15.3 M → 6.2 M rows, prepare 1.78 s → 1.22 s); the lets cut ops 512 → 283, but the folds cost ≤ 2.4 ms and the subset search 7 ms. One table for all rules is slower than per-rule tables when nothing is shared, so tables are formed per group of rules that share a side. **U4 FAILED GATE on speed (2026-10-21, `crepe-plan-probe/src/coaddressed.rs` + `examples/coaddressed.rs`, `entries/2026-10-21-u4-coaddressed-join.md`):** the co-addressed join is a named operator, a conjunction of per-table `Rel`s over one `JoinDomain`, and a side's restriction runs at query time over one table laid out without it. Answers equal the star path and no program reads at a position taken from another operand's values, but every arm of its benchmark ran in milliseconds, which the no-ms rule makes a failed gate; the per-side `Rel` must fold into the projection terminal. Both are accepted only on measured row traversals, materializations and total cost (§ Decisions), not on operator counts.
4 changes: 4 additions & 0 deletions .github/workflows/crepe-plan-probe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ jobs:
# The benchmark (`cargo run --release --example rule_cse`) is not run
# in CI.
- run: cargo test --example rule_cse
# D-RU-4 (U4): the co-addressed join operator against the star path.
# The benchmark (`cargo run --release --example coaddressed`) is not
# run in CI.
- run: cargo test --example coaddressed
# D-RU-6 arm C: the block-sparse product, against arms A and B and the
# oracles, its refusals and the semi-naive bound.
- run: cargo test --example walk_sparse
Expand Down
Loading
Loading