Skip to content

Commit d9ac5af

Browse files
authored
Merge pull request #548 from AdaWorldAPI/claude/value-tier-replant
feat(graph): re-land Hamming-plane DistanceMeans on main (stranded by #545 stacked-merge order)
2 parents 5ad6871 + b8ea988 commit d9ac5af

3 files changed

Lines changed: 137 additions & 9 deletions

File tree

crates/cognitive-shader-driver/src/mailbox_soa.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use lance_graph_contract::cognitive_shader::MetaWord;
3131
use lance_graph_contract::collapse_gate::MailboxId;
3232
use lance_graph_contract::kanban::{ExecTarget, KanbanColumn, KanbanMove};
3333
use lance_graph_contract::qualia::QualiaI4_16D;
34-
use lance_graph_contract::soa_view::{MailboxSoaOwner, MailboxSoaView};
34+
use lance_graph_contract::soa_view::{IdentityPlane, MailboxSoaOwner, MailboxSoaView};
3535

3636
/// Canonical named-fingerprint plane width: 256 × u64 = 16,384 bits
3737
/// (mirrors `bindspace::WORDS_PER_FP`; defined locally so the mailbox does NOT
@@ -729,6 +729,23 @@ impl<const N: usize> MailboxSoaView for MailboxSoA<N> {
729729
fn phase(&self) -> KanbanColumn {
730730
self.phase
731731
}
732+
/// Override the deferred-binding default: the in-RAM owner DOES carry the
733+
/// content/topic/angle identity planes (W1b), so the value-side Hamming
734+
/// distance (`graph::mailbox_scan::DistanceMeans::Hamming`) can compute over
735+
/// the real view, not just the unit-test fake. Guarded by `populated` — never
736+
/// reads a zero-padded capacity row (same logical-row discipline as
737+
/// `n_rows()`); a query into `populated..N` returns `None`.
738+
#[inline]
739+
fn identity_plane_at(&self, row: usize, plane: IdentityPlane) -> Option<&[u64]> {
740+
if row >= self.populated {
741+
return None;
742+
}
743+
Some(match plane {
744+
IdentityPlane::Content => self.content_row(row),
745+
IdentityPlane::Topic => self.topic_row(row),
746+
IdentityPlane::Angle => self.angle_row(row),
747+
})
748+
}
732749
#[inline]
733750
fn energy(&self) -> &[f32] {
734751
&self.energy
@@ -1208,6 +1225,32 @@ mod tests {
12081225
assert_eq!(mb.sigma_at(2), 0, "sigma[2] must reset to 0");
12091226
}
12101227

1228+
/// `identity_plane_at` (the `MailboxSoaView` override, #545 codex P2): the real
1229+
/// owner DOES carry the W1b planes, so the value-side Hamming distance can read
1230+
/// them on the live view (not just the unit-test fake). Guarded by `populated`:
1231+
/// a row beyond the logical size returns `None`, never a zero-padded capacity row.
1232+
#[test]
1233+
fn identity_plane_at_returns_planes_and_guards_padding() {
1234+
let mut mb: MailboxSoA<4> = MailboxSoA::new(1, 0, 1.0);
1235+
mb.set_populated(2);
1236+
let mut c0 = vec![0u64; WORDS_PER_FP];
1237+
c0[0] = 0b1011;
1238+
mb.set_content(0, &c0);
1239+
// populated row → Some, byte-identical to content_row.
1240+
assert_eq!(
1241+
mb.identity_plane_at(0, IdentityPlane::Content),
1242+
Some(mb.content_row(0))
1243+
);
1244+
// topic/angle planes default zero but are still materialized (Some).
1245+
assert_eq!(
1246+
mb.identity_plane_at(0, IdentityPlane::Topic),
1247+
Some(mb.topic_row(0))
1248+
);
1249+
// row beyond `populated` (2) → None: never a zero-padded capacity row.
1250+
assert_eq!(mb.identity_plane_at(2, IdentityPlane::Content), None);
1251+
assert_eq!(mb.identity_plane_at(3, IdentityPlane::Angle), None);
1252+
}
1253+
12111254
// ── test 15: W1b dense identity planes — parity with BindSpace ───────────
12121255

12131256
/// **The W1b "test the new" proof.** The content/topic/angle Hamming identity

crates/lance-graph-contract/src/soa_view.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@
1919
use crate::collapse_gate::MailboxId;
2020
use crate::kanban::{KanbanColumn, KanbanMove, RubiconTransitionError};
2121

22+
/// Which dense identity plane a value-side read selects — the orthogonal
23+
/// perspective axes of a node's content (`E-TENANT-ANGLE-RANK-IS-CAM-PQ-ADC`).
24+
/// Each is a `WORDS_PER_FP`-u64 fingerprint in the value slab; reading one is a
25+
/// **value decode** (the costed tier), never the zero-decode key path.
26+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27+
pub enum IdentityPlane {
28+
/// The content identity fingerprint plane.
29+
Content,
30+
/// The topic identity fingerprint plane.
31+
Topic,
32+
/// The angle (perspective) identity fingerprint plane.
33+
Angle,
34+
}
35+
2236
/// A transparent, read-only view over one mailbox's SoA columns.
2337
///
2438
/// Implementors return **borrows** (`&[T]`) or `Copy` scalars — never clones of the
@@ -125,6 +139,20 @@ pub trait MailboxSoaView {
125139
None
126140
}
127141

142+
/// `row`'s dense identity-plane fingerprint (`WORDS_PER_FP` u64) for the
143+
/// selected [`IdentityPlane`] — content / topic / angle. This is the
144+
/// **value-side** read behind the costed distance/sweep tier
145+
/// (`E-TENANT-ANGLE-RANK-IS-CAM-PQ-ADC`): a Hamming/CAM rank "from an angle"
146+
/// reads this plane, so unlike the key facets it is **NOT zero value decode**.
147+
///
148+
/// **Default = `None` (zero-fallback, deferred binding)** — a view that has not
149+
/// materialized the planes returns `None`; the in-RAM `MailboxSoA` owner
150+
/// (which carries content/topic/angle planes, W1b) overrides this.
151+
#[inline]
152+
fn identity_plane_at(&self, _row: usize, _plane: IdentityPlane) -> Option<&[u64]> {
153+
None
154+
}
155+
128156
// NOTE (follow-up): the qualia column (`QualiaI4_16D`) accessor is intentionally omitted —
129157
// add `fn qualia(&self) -> &[crate::qualia::QualiaI4_16D]` when the first consumer
130158
// (planner strategy selection) needs it; keep the read surface minimal until then.

crates/lance-graph/src/graph/mailbox_scan.rs

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
4646
use lance_graph_contract::canonical_node::EdgeCodecFlavor;
4747
use lance_graph_contract::hhtl::NiblePath;
48-
use lance_graph_contract::soa_view::MailboxSoaView;
48+
use lance_graph_contract::soa_view::{IdentityPlane, MailboxSoaView};
4949

5050
use crate::graph::graph_router::Backend;
5151

@@ -226,13 +226,18 @@ pub enum DistanceMeans {
226226
/// triangle inequality). Key-only, zero value decode
227227
/// (`E-PANCAKES-IS-RADIX-IS-HHTL`).
228228
PrefixDepth,
229-
// ── value-decode means (the costed tier — named here as the dispatch
230-
// surface; wired on their own branch with their own cost gate, never
231-
// mixed into the zero-decode facets; `E-TENANT-ANGLE-RANK-IS-CAM-PQ-ADC`,
232-
// `E-HELIX-IS-EXACT-LOCATION`): ──
233-
// Hamming(plane) — fingerprint popcount over a content/topic/angle plane;
234-
// HelixAngular — Signed360 exact-orthogonal-location distance;
235-
// PqAdc — CAM-PQ asymmetric distance (IVF probe + tables).
229+
/// **Hamming over an identity plane** (`IdentityPlane`: content / topic /
230+
/// angle) — the popcount of the XOR of the two nodes' fingerprint planes.
231+
/// This is the **costed tier**: it reads the value-side plane
232+
/// (`MailboxSoaView::identity_plane_at`), so — unlike `PrefixDepth` — it is
233+
/// **NOT zero value decode** (`E-TENANT-ANGLE-RANK-IS-CAM-PQ-ADC`). The right
234+
/// use of popcount: homogeneous 16K-bit fingerprint bits, not the
235+
/// heterogeneous GUID key.
236+
Hamming(IdentityPlane),
237+
// ── further value means (named; wired as they land, same costed tier):
238+
// HelixAngular — Signed360 exact-orthogonal-location distance
239+
// (`E-HELIX-IS-EXACT-LOCATION`);
240+
// PqAdc — CAM-PQ asymmetric distance (IVF probe + tables).
236241
}
237242

238243
/// Distance between two nodes (rows, each a GUID) under the chosen `means`.
@@ -258,6 +263,12 @@ pub fn node_distance<V: MailboxSoaView>(
258263
let cpd = pa.common_prefix_depth(pb);
259264
Some(u32::from((pa.depth() - cpd) + (pb.depth() - cpd)))
260265
}
266+
// COSTED tier: reads the value-side plane (NOT zero value decode).
267+
DistanceMeans::Hamming(plane) => {
268+
let fa = view.identity_plane_at(a, plane)?;
269+
let fb = view.identity_plane_at(b, plane)?;
270+
Some(fa.iter().zip(fb).map(|(x, y)| (x ^ y).count_ones()).sum())
271+
}
261272
}
262273
}
263274

@@ -277,6 +288,7 @@ mod tests {
277288
keyed_rows: Vec<(u64, usize)>,
278289
paths: Vec<Option<NiblePath>>,
279290
blocks: Vec<Option<EdgeBlock>>,
291+
content_planes: Vec<Option<Vec<u64>>>,
280292
/// Logical populated rows; `None` ⇒ the full `class_ids` length. Set
281293
/// smaller to model the real `MailboxSoA<N>` (zero-padded capacity with
282294
/// `n_rows() == populated < entity_type().len()`).
@@ -328,6 +340,13 @@ mod tests {
328340
fn edge_block_at(&self, row: usize) -> Option<EdgeBlock> {
329341
self.blocks.get(row).copied().flatten()
330342
}
343+
fn identity_plane_at(&self, row: usize, plane: IdentityPlane) -> Option<&[u64]> {
344+
// Only the Content plane is materialized in this fake.
345+
match plane {
346+
IdentityPlane::Content => self.content_planes.get(row).and_then(|p| p.as_deref()),
347+
IdentityPlane::Topic | IdentityPlane::Angle => None,
348+
}
349+
}
331350
}
332351

333352
fn sample() -> GuardedSoa {
@@ -356,6 +375,14 @@ mod tests {
356375
None,
357376
None,
358377
],
378+
// content planes (2 u64 each) for the Hamming means; row2 unmaterialized.
379+
content_planes: vec![
380+
Some(vec![0b1011, 0]),
381+
Some(vec![0b1101, 0]),
382+
None,
383+
Some(vec![0, 0]),
384+
Some(vec![u64::MAX, u64::MAX]),
385+
],
359386
logical_n: None,
360387
}
361388
}
@@ -511,6 +538,36 @@ mod tests {
511538
assert!(d(0, 1).unwrap() < d(0, 4).unwrap());
512539
}
513540

541+
#[test]
542+
fn node_distance_hamming_plane_is_popcount_xor_over_the_value_plane() {
543+
let soa = sample();
544+
// row0 0b1011, row1 0b1101 → XOR 0b0110 → popcount 2.
545+
assert_eq!(
546+
node_distance(&soa, 0, 1, DistanceMeans::Hamming(IdentityPlane::Content)),
547+
Some(2)
548+
);
549+
// self-distance = 0 (metric).
550+
assert_eq!(
551+
node_distance(&soa, 0, 0, DistanceMeans::Hamming(IdentityPlane::Content)),
552+
Some(0)
553+
);
554+
// all-zero vs all-ones over 2×u64 = 128 bits.
555+
assert_eq!(
556+
node_distance(&soa, 3, 4, DistanceMeans::Hamming(IdentityPlane::Content)),
557+
Some(128)
558+
);
559+
// unmaterialized plane (row2) ⇒ None (costed-tier fallback).
560+
assert_eq!(
561+
node_distance(&soa, 0, 2, DistanceMeans::Hamming(IdentityPlane::Content)),
562+
None
563+
);
564+
// a plane this fake doesn't carry ⇒ None (Topic/Angle not materialized).
565+
assert_eq!(
566+
node_distance(&soa, 0, 1, DistanceMeans::Hamming(IdentityPlane::Angle)),
567+
None
568+
);
569+
}
570+
514571
#[test]
515572
fn node_distance_none_without_materialized_path() {
516573
let mut soa = sample();

0 commit comments

Comments
 (0)