Research-Stack/0-Core-Formalism/lean/Semantics/Semantics/SpatialHashCodec.lean
allaun 2c53cf45ca fix(lean): resolve 4 TODO(lean-port) placeholders
AdjugateMatrix.lean:
- Replace tautological cayley_is_orthogonal with concrete
  cayley_transform_zero theorem (zero matrix case)

LonelyRunner.lean:
- Implement beta0Circular via Rising-edge counting on S1
- Add cyclicPrev, isRisingEdge, Decidable instances, #eval! witnesses
- Replaces placeholder 0 with correct component count

SpatialHashCodec.lean:
- Prove hashToCoord_inj_bounded: injectivity for row_id < 256
- Replace tautological hashCollisionBound with pairwise non-collision
- Add OctreeLevel structure: 5-level octree on 16^3 grid
- Theorems: cubeCount_succ, volume_conservation, level4_eq_grid,
  cube_count_via_depth

SDTA.lean:
- Expand all TODO(lean-port) stubs with spec references, proof
  sketches, and blocker identification (no functional change)
2026-06-18 15:07:39 -05:00

749 lines
31 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
SpatialHashCodec.lean — Formal Specification of Vectorless Spatial Hash Codec
This module formalizes the spatial hash intermediary architecture for H.264-style
database compression. Provides mathematically rigorous definitions of:
- Spatial coordinates (16×16×16 grid)
- Morton code (Z-order curve) for locality-preserving hashing
- Voltage mode classification (2-bit: STORE/COMPUTE/APPROX/MORPHIC)
- Spatial cell structure with Q0_16 density
- Voltage mode classification logic (matching Python semantics)
- Constant-degree graph property (neighbor boundedness)
Corresponds to Python implementation:
4-Infrastructure/shim/vectorless_morton_hash_backend.py
Per AGENTS.md §1.4: Q0_16 for dimensionless scalars (density 0-255).
Per AGENTS.md §2: PascalCase types, camelCase functions.
Per AGENTS.md §4: Every def has eval witness or theorem.
DONE(lean-port): Morton code bijection (mortonRoundtrip, mortonForward_all,
mortonInjective, mortonSurjective — exhaustive in-kernel via native_decide)
DONE(lean-port): Packed-cell roundtrip (packedRoundtrip — bv_decide SAT core
+ explicit 0-255 density-domain hypotheses)
DONE(lean-port): Hash-to-coordinate collision resistance on bounded domain
(hashToCoord_inj_bounded, hashCollisionBound — injectivity on row_id < 256
via omega; replaces the previous `True` tautology placeholder)
DONE(lean-port): Octree-style spatial refinement (OctreeLevel structure
+ volume_conservation, cubeCount_succ — 5-level octree on 16³ grid)
-/
import Mathlib.Data.Nat.Basic
import Mathlib.Data.Fin.Basic
import Std.Tactic.BVDecide
import Semantics.FixedPoint
set_option maxHeartbeats 1000000
-- ============================================================
-- §0 Q0_16 BOUNDARY CONVERSIONS (UInt bit-pattern interface)
-- ============================================================
namespace Semantics.FixedPoint.Q0_16
/-- Boundary read: raw value as Nat (negative raw reads as 0).
Per the FixedPoint design rule, UInt bit-patterns are boundary/hardware
artifacts; this is the hardware-facing read of a Q0_16 density. -/
def toNat (q : Q0_16) : Nat := q.val.toNat
/-- Boundary write: Nat into Q0_16 through the saturating `ofRawInt`. -/
def ofNat (n : Nat) : Q0_16 := ofRawInt (n : Int)
/-- `ofRawInt` is the identity on in-range raw values. -/
theorem val_ofRawInt_of_mem {raw : Int}
(h_lo : q0_16MinRaw ≤ raw) (h_hi : raw ≤ q0_16MaxRaw) :
(ofRawInt raw).val = raw := by
simp only [q0_16MinRaw, q0_16MaxRaw] at h_lo h_hi
unfold ofRawInt
rw [dif_neg (by simp only [q0_16MaxRaw]; omega),
dif_neg (by simp only [q0_16MinRaw]; omega)]
/-- `ofNat ∘ toNat` is the identity on the 0-255 density domain. -/
theorem ofNat_toNat_of_le {q : Q0_16} (h_lo : 0 ≤ q.val) (h_hi : q.val ≤ 255) :
ofNat q.toNat = q := by
apply ext
show (ofRawInt ((q.val.toNat : Nat) : Int)).val = q.val
rw [Int.toNat_of_nonneg h_lo]
exact val_ofRawInt_of_mem (by simp only [q0_16MinRaw]; omega)
(by simp only [q0_16MaxRaw]; omega)
end Semantics.FixedPoint.Q0_16
namespace Semantics.SpatialHashCodec
open Semantics.FixedPoint
open Semantics.Q16_16
open Semantics.Q0_16
-- ============================================================
-- §1 SPATIAL COORDINATE (16×16×16)
-- ============================================================
/-- 16×16×16 spatial coordinate. Each axis is 4 bits (0-15). -/
structure SpatialCoord where
x : Fin 16
y : Fin 16
z : Fin 16
deriving Repr, DecidableEq, BEq
namespace SpatialCoord
/-- Extensionality: coordinates are equal when all three axes agree. -/
theorem ext {a b : SpatialCoord} (hx : a.x = b.x) (hy : a.y = b.y)
(hz : a.z = b.z) : a = b := by
cases a; cases b; simp_all
/-- Convert to linear index using Morton code (Z-order curve). -/
def toMorton (c : SpatialCoord) : Nat :=
-- Interleave bits: z2 y2 x2 z1 y1 x1 z0 y0 x0 (9 bits for 3D Morton)
let morton : Nat := 0
let morton := morton ||| ((c.x.val >>> 0 &&& 1) <<< 0) ||| ((c.y.val >>> 0 &&& 1) <<< 1) ||| ((c.z.val >>> 0 &&& 1) <<< 2)
let morton := morton ||| ((c.x.val >>> 1 &&& 1) <<< 3) ||| ((c.y.val >>> 1 &&& 1) <<< 4) ||| ((c.z.val >>> 1 &&& 1) <<< 5)
let morton := morton ||| ((c.x.val >>> 2 &&& 1) <<< 6) ||| ((c.y.val >>> 2 &&& 1) <<< 7) ||| ((c.z.val >>> 2 &&& 1) <<< 8)
let morton := morton ||| ((c.x.val >>> 3 &&& 1) <<< 9) ||| ((c.y.val >>> 3 &&& 1) <<< 10) ||| ((c.z.val >>> 3 &&& 1) <<< 11)
morton
-- 4-bit extraction of any 12-bit value (0-4095) always yields < 16.
-- Previously DSP-shim axioms; now verified in-kernel by exhaustive
-- evaluation over the 4096-case domain (native_decide).
theorem decodeBitX_lt_16 (v : Nat) (h : v < 4096) : ((v >>> 0) &&& 1) ||| (((v >>> 3) &&& 1) <<< 1) ||| (((v >>> 6) &&& 1) <<< 2) ||| (((v >>> 9) &&& 1) <<< 3) < 16 := by
revert h
revert v
native_decide
theorem decodeBitY_lt_16 (v : Nat) (h : v < 4096) : ((v >>> 1) &&& 1) ||| (((v >>> 4) &&& 1) <<< 1) ||| (((v >>> 7) &&& 1) <<< 2) ||| (((v >>> 10) &&& 1) <<< 3) < 16 := by
revert h
revert v
native_decide
theorem decodeBitZ_lt_16 (v : Nat) (h : v < 4096) : ((v >>> 2) &&& 1) ||| (((v >>> 5) &&& 1) <<< 1) ||| (((v >>> 8) &&& 1) <<< 2) ||| (((v >>> 11) &&& 1) <<< 3) < 16 := by
revert h
revert v
native_decide
/-- Convert from linear index using Morton code decoding. -/
def fromMorton (morton : Nat) (h_bound : morton < 4096) : SpatialCoord :=
let x : Nat := ((morton >>> 0) &&& 1) ||| (((morton >>> 3) &&& 1) <<< 1) ||| (((morton >>> 6) &&& 1) <<< 2) ||| (((morton >>> 9) &&& 1) <<< 3)
let y : Nat := ((morton >>> 1) &&& 1) ||| (((morton >>> 4) &&& 1) <<< 1) ||| (((morton >>> 7) &&& 1) <<< 2) ||| (((morton >>> 10) &&& 1) <<< 3)
let z : Nat := ((morton >>> 2) &&& 1) ||| (((morton >>> 5) &&& 1) <<< 1) ||| (((morton >>> 8) &&& 1) <<< 2) ||| (((morton >>> 11) &&& 1) <<< 3)
have h_x' : x < 16 := decodeBitX_lt_16 morton h_bound
have h_y' : y < 16 := decodeBitY_lt_16 morton h_bound
have h_z' : z < 16 := decodeBitZ_lt_16 morton h_bound
{ x := ⟨x, h_x'⟩, y := ⟨y, h_y'⟩, z := ⟨z, h_z'⟩ }
/-- All 4096 coordinates produce Morton < 4096.
Previously a Python-DSP-shim axiom; now verified in-kernel by
exhaustive evaluation over Fin 16 × Fin 16 × Fin 16 (native_decide). -/
theorem mortonBounded_all : ∀ (x y z : Fin 16),
toMorton { x := x, y := y, z := z } < 4096 := by
native_decide
/-- Linear index is bounded (0-4095). -/
theorem mortonBounded (c : SpatialCoord) :
toMorton c < 4096 :=
mortonBounded_all c.x c.y c.z
/-- fromMorton (toMorton c) = c for all 4096 coordinates.
Previously a Python-DSP-shim axiom; now verified in-kernel by
exhaustive evaluation of the bit-interleaving map (native_decide). -/
theorem mortonRoundtrip_all : ∀ (x y z : Fin 16),
fromMorton (toMorton { x := x, y := y, z := z })
(mortonBounded_all x y z) = { x := x, y := y, z := z } := by
native_decide
/-- Roundtrip: fromMorton (toMorton c) = c. -/
theorem mortonRoundtrip (c : SpatialCoord) :
fromMorton (toMorton c) (mortonBounded c) = c := by
have this := mortonRoundtrip_all c.x c.y c.z
simpa using this
/-- toMorton (fromMorton idx) = idx for all idx < 4096.
Previously a Python-DSP-shim axiom; now verified in-kernel by
exhaustive evaluation over the 4096-index domain (native_decide). -/
theorem mortonForward_all (idx : Nat) (h : idx < 4096) :
toMorton (fromMorton idx h) = idx := by
revert h
revert idx
native_decide
/-- Morton code is injective (no collisions).
Proof: if toMorton c1 = toMorton c2, then applying fromMorton to both
sides (using the roundtrip property) gives c1 = c2. -/
theorem mortonInjective (c1 c2 : SpatialCoord) :
toMorton c1 = toMorton c2 → c1 = c2 := by
intro h
-- NOTE: `rw [h] at h1` here diverges at whnf (it rewrites under
-- fromMorton's dependent proof argument, forcing reduction of the Morton
-- bit arithmetic on opaque variables). Substituting at the Nat level
-- first keeps everything proof-irrelevant and cheap.
have key : ∀ (m1 m2 : Nat) (e : m1 = m2) (p1 : m1 < 4096) (p2 : m2 < 4096),
fromMorton m1 p1 = fromMorton m2 p2 := by
intro m1 m2 e p1 p2
subst e
rfl
have h12 := key _ _ h (mortonBounded c1) (mortonBounded c2)
rw [mortonRoundtrip c1, mortonRoundtrip c2] at h12
exact h12
/-- Morton code covers all values 0-4095.
Proof: for any idx < 4096, construct fromMorton idx h. By mortonForward_all,
toMorton of that coordinate equals idx. -/
theorem mortonSurjective (idx : Nat) (h : idx < 4096) :
∃ c : SpatialCoord, toMorton c = idx := by
exact ⟨fromMorton idx h, mortonForward_all idx h⟩
/-- Octant locality (exhaustive core): coordinates lying in the same aligned
2×2×2 octant have Morton codes at distance ≤ 7 (same aligned block of 8).
Verified in-kernel over the full 16M-case product space (native_decide).
REMOVED (false axiom): the previous `localityPreservation` axiom claimed
|toMorton c1 toMorton c2| ≤ 7 for *all* Chebyshev-adjacent cells. That
is false — Z-order codes jump at power-of-2 boundaries. Counterexample:
(7,0,0) and (8,0,0) are adjacent, but toMorton = 73 and 512 respectively
(|diff| = 439). Asserting it as an axiom made the environment
inconsistent. The true classical property of the Z-order curve is the
*prefix property* (Morton 1966; Gargantini 1982): coordinates sharing
their high bits share the corresponding Morton-code prefix, stated here
for the lowest level (shared bits 1-3 of each axis ⇒ same block of 8). -/
theorem octantLocality_all : ∀ (x1 y1 z1 x2 y2 z2 : Fin 16),
x1.val / 2 = x2.val / 2 → y1.val / 2 = y2.val / 2 → z1.val / 2 = z2.val / 2 →
toMorton { x := x1, y := y1, z := z1 } - toMorton { x := x2, y := y2, z := z2 } ≤ 7 ∧
toMorton { x := x2, y := y2, z := z2 } - toMorton { x := x1, y := y1, z := z1 } ≤ 7 := by
native_decide
/-- Octant locality on SpatialCoord with the Int-valued distance form. -/
theorem octantLocality (c1 c2 : SpatialCoord)
(hx : c1.x.val / 2 = c2.x.val / 2)
(hy : c1.y.val / 2 = c2.y.val / 2)
(hz : c1.z.val / 2 = c2.z.val / 2) :
|(toMorton c1 : Int) - toMorton c2| ≤ 7 := by
-- structure eta: c = ⟨c.x, c.y, c.z⟩ definitionally
have h : toMorton c1 - toMorton c2 ≤ 7 ∧ toMorton c2 - toMorton c1 ≤ 7 :=
octantLocality_all c1.x c1.y c1.z c2.x c2.y c2.z hx hy hz
rw [abs_sub_le_iff]
omega
end SpatialCoord
-- ============================================================
-- §2 VOLTAGE MODE (2-bit classification)
-- ============================================================
/-- Voltage mode: 2-bit classification (4 states). -/
inductive VoltageMode where
| store -- 00: I-frame (exact storage)
| compute -- 01: P-frame (motion vectors + residuals)
| approx -- 10: Quantized (lossy approximation)
| morphic -- 11: B-frame (bidirectional prediction)
deriving Repr, DecidableEq, BEq
namespace VoltageMode
/-- Convert to 2-bit value. -/
def toBits (m : VoltageMode) : Fin 4 :=
match m with
| store => ⟨0, by decide⟩
| compute => ⟨1, by decide⟩
| approx => ⟨2, by decide⟩
| morphic => ⟨3, by decide⟩
/-- Convert from 2-bit value. -/
def fromBits (b : Fin 4) : VoltageMode :=
match b.val with
| 0 => store
| 1 => compute
| 2 => approx
| _ => morphic
/-- Roundtrip: fromBits (toBits m) = m. -/
theorem bitsRoundtrip (m : VoltageMode) :
fromBits (toBits m) = m := by
cases m <;> simp [toBits, fromBits]
/-- toBits is injective. -/
theorem bitsInjective (m1 m2 : VoltageMode) :
toBits m1 = toBits m2 → m1 = m2 := by
intro h_eq
cases m1 <;> cases m2 <;> simp [toBits] at h_eq <;> rfl
end VoltageMode
-- ============================================================
-- §3 SPATIAL CELL
-- ============================================================
/-- Single cell in 16×16×16 spatial hash grid. -/
structure SpatialCell where
coord : SpatialCoord
voltage_mode : VoltageMode
density : Q0_16 -- 0-255 as Q0_16
row_ids : List Nat
table_name : String
write_count : Nat
read_count : Nat
delta_variance : Q16_16
last_access_ts : Q16_16 -- UInt64 timestamp as Q16_16
deriving Repr
namespace SpatialCell
/-- Empty cell at given coordinate. -/
def empty (coord : SpatialCoord) : SpatialCell :=
{
coord := coord,
voltage_mode := .store,
density := Q0_16.zero,
row_ids := [],
table_name := "",
write_count := 0,
read_count := 0,
delta_variance := Q16_16.zero,
last_access_ts := Q16_16.zero
}
/-- Pack to 64-bit integer for hardware transmission.
The density field is masked to 8 bits (`&&& 0xFF`), matching the Python
reference `to_packed` exactly; coordinates and mode are bounded by their
types (Fin 16 / Fin 4) so no mask is needed for them. -/
def toPacked (c : SpatialCell) : UInt64 :=
let packed : UInt64 := 0
let packed := packed ||| (UInt64.ofNat c.coord.x.val)
let packed := packed ||| (UInt64.ofNat c.coord.y.val <<< 4)
let packed := packed ||| (UInt64.ofNat c.coord.z.val <<< 8)
let packed := packed ||| (UInt64.ofNat (VoltageMode.toBits c.voltage_mode).val <<< 12)
let packed := packed ||| ((UInt64.ofNat c.density.toNat &&& 0xFF) <<< 16)
packed
/-- Unpack from 64-bit integer. -/
def fromPacked (packed : UInt64) : SpatialCell :=
let x := (packed &&& 0xF).toNat
let y := ((packed >>> 4) &&& 0xF).toNat
let z := ((packed >>> 8) &&& 0xF).toNat
let mode := ((packed >>> 12) &&& 0x3).toNat
let density := ((packed >>> 16) &&& 0xFF).toNat
{
coord := {
x := ⟨x % 16, Nat.mod_lt x (by decide)⟩,
y := ⟨y % 16, Nat.mod_lt y (by decide)⟩,
z := ⟨z % 16, Nat.mod_lt z (by decide)⟩
},
voltage_mode := VoltageMode.fromBits ⟨mode % 4, Nat.mod_lt mode (by decide)⟩,
density := Q0_16.ofNat density,
row_ids := [],
table_name := "",
write_count := 0,
read_count := 0,
delta_variance := Q16_16.zero,
last_access_ts := Q16_16.zero
}
/-- Definitional projections of `fromPacked` (proof components are
irrelevant, so `rfl` closes each). -/
theorem fromPacked_coord_x (p : UInt64) :
(fromPacked p).coord.x = ⟨(p &&& 0xF).toNat % 16, by omega⟩ := rfl
theorem fromPacked_coord_y (p : UInt64) :
(fromPacked p).coord.y = ⟨((p >>> 4) &&& 0xF).toNat % 16, by omega⟩ := rfl
theorem fromPacked_coord_z (p : UInt64) :
(fromPacked p).coord.z = ⟨((p >>> 8) &&& 0xF).toNat % 16, by omega⟩ := rfl
theorem fromPacked_voltage_mode (p : UInt64) :
(fromPacked p).voltage_mode =
VoltageMode.fromBits ⟨((p >>> 12) &&& 0x3).toNat % 4, by omega⟩ := rfl
theorem fromPacked_density (p : UInt64) :
(fromPacked p).density = Q0_16.ofNat ((p >>> 16) &&& 0xFF).toNat := rfl
/-- Field extraction from the packed 64-bit layout: the five fields occupy
disjoint bit ranges, so masking recovers each exactly. Verified by SAT
over the 64-bit vector semantics (bv_decide). -/
theorem packed_extract (x y z m d : UInt64)
(hx : x < 16) (hy : y < 16) (hz : z < 16) (hm : m < 4) (hd : d < 256) :
(((0 : UInt64) ||| x ||| (y <<< 4) ||| (z <<< 8) ||| (m <<< 12) ||| ((d &&& 0xFF) <<< 16)) &&& 0xF = x) ∧
((((0 : UInt64) ||| x ||| (y <<< 4) ||| (z <<< 8) ||| (m <<< 12) ||| ((d &&& 0xFF) <<< 16)) >>> 4) &&& 0xF = y) ∧
((((0 : UInt64) ||| x ||| (y <<< 4) ||| (z <<< 8) ||| (m <<< 12) ||| ((d &&& 0xFF) <<< 16)) >>> 8) &&& 0xF = z) ∧
((((0 : UInt64) ||| x ||| (y <<< 4) ||| (z <<< 8) ||| (m <<< 12) ||| ((d &&& 0xFF) <<< 16)) >>> 12) &&& 0x3 = m) ∧
((((0 : UInt64) ||| x ||| (y <<< 4) ||| (z <<< 8) ||| (m <<< 12) ||| ((d &&& 0xFF) <<< 16)) >>> 16) &&& 0xFF = d) := by
refine ⟨?_, ?_, ?_, ?_, ?_⟩ <;> bv_decide
/-- Roundtrip: fromPacked (toPacked c) = c (excluding volatile fields).
The density hypotheses are required and explicit (per the provability
doctrine): the packed layout allocates 8 bits to density (the documented
0-255 domain), so only raw values in [0, 255] survive the boundary trip.
Coordinate and voltage-mode fields roundtrip unconditionally — their
types (Fin 16, Fin 4) bound them. -/
theorem packedRoundtrip (c : SpatialCell)
(h_lo : 0 ≤ c.density.val) (h_hi : c.density.val ≤ 255) :
(fromPacked (toPacked c)).coord = c.coord ∧
(fromPacked (toPacked c)).voltage_mode = c.voltage_mode ∧
(fromPacked (toPacked c)).density = c.density := by
-- Nat-level bounds for the five packed fields
have hxlt : c.coord.x.val < 16 := c.coord.x.isLt
have hylt : c.coord.y.val < 16 := c.coord.y.isLt
have hzlt : c.coord.z.val < 16 := c.coord.z.isLt
have hmlt : (VoltageMode.toBits c.voltage_mode).val < 4 :=
(VoltageMode.toBits c.voltage_mode).isLt
have hdlt : c.density.toNat < 256 := by
show c.density.val.toNat < 256
omega
-- UInt64-level bounds
have toNat_ofNat_eq : ∀ (n b : Nat), n < b → b ≤ 2 ^ 64 →
(UInt64.ofNat n).toNat = n := by
intro n b hn hb
simp
omega
have hX : UInt64.ofNat c.coord.x.val < 16 := by
rw [UInt64.lt_iff_toNat_lt, toNat_ofNat_eq _ 16 hxlt (by norm_num)]
simp
have hY : UInt64.ofNat c.coord.y.val < 16 := by
rw [UInt64.lt_iff_toNat_lt, toNat_ofNat_eq _ 16 hylt (by norm_num)]
simp
have hZ : UInt64.ofNat c.coord.z.val < 16 := by
rw [UInt64.lt_iff_toNat_lt, toNat_ofNat_eq _ 16 hzlt (by norm_num)]
simp
have hM : UInt64.ofNat (VoltageMode.toBits c.voltage_mode).val < 4 := by
rw [UInt64.lt_iff_toNat_lt, toNat_ofNat_eq _ 4 hmlt (by norm_num)]
simp
have hD : UInt64.ofNat c.density.toNat < 256 := by
rw [UInt64.lt_iff_toNat_lt, toNat_ofNat_eq _ 256 hdlt (by norm_num)]
simpa using hdlt
-- the packed word in explicit form (definitional)
have hp : toPacked c =
(0 : UInt64) ||| UInt64.ofNat c.coord.x.val
||| (UInt64.ofNat c.coord.y.val <<< 4)
||| (UInt64.ofNat c.coord.z.val <<< 8)
||| (UInt64.ofNat (VoltageMode.toBits c.voltage_mode).val <<< 12)
||| ((UInt64.ofNat c.density.toNat &&& 0xFF) <<< 16) := rfl
obtain ⟨e1, e2, e3, e4, e5⟩ := packed_extract _ _ _ _ _ hX hY hZ hM hD
-- Nat-level extraction equalities
have tx : ((toPacked c) &&& 0xF).toNat = c.coord.x.val := by
rw [hp, e1, toNat_ofNat_eq _ 16 hxlt (by norm_num)]
have ty : (((toPacked c) >>> 4) &&& 0xF).toNat = c.coord.y.val := by
rw [hp, e2, toNat_ofNat_eq _ 16 hylt (by norm_num)]
have tz : (((toPacked c) >>> 8) &&& 0xF).toNat = c.coord.z.val := by
rw [hp, e3, toNat_ofNat_eq _ 16 hzlt (by norm_num)]
have tm : (((toPacked c) >>> 12) &&& 0x3).toNat =
(VoltageMode.toBits c.voltage_mode).val := by
rw [hp, e4, toNat_ofNat_eq _ 4 hmlt (by norm_num)]
have td : (((toPacked c) >>> 16) &&& 0xFF).toNat = c.density.toNat := by
rw [hp, e5, toNat_ofNat_eq _ 256 hdlt (by norm_num)]
refine ⟨?_, ?_, ?_⟩
· -- coordinate roundtrip
apply SpatialCoord.ext
· rw [fromPacked_coord_x]
apply Fin.ext
show ((toPacked c) &&& 0xF).toNat % 16 = c.coord.x.val
rw [tx]
omega
· rw [fromPacked_coord_y]
apply Fin.ext
show (((toPacked c) >>> 4) &&& 0xF).toNat % 16 = c.coord.y.val
rw [ty]
omega
· rw [fromPacked_coord_z]
apply Fin.ext
show (((toPacked c) >>> 8) &&& 0xF).toNat % 16 = c.coord.z.val
rw [tz]
omega
· -- voltage mode roundtrip
rw [fromPacked_voltage_mode]
have hfin : (⟨(((toPacked c) >>> 12) &&& 0x3).toNat % 4, by omega⟩ : Fin 4)
= VoltageMode.toBits c.voltage_mode := by
apply Fin.ext
show (((toPacked c) >>> 12) &&& 0x3).toNat % 4 =
(VoltageMode.toBits c.voltage_mode).val
rw [tm]
omega
rw [hfin, VoltageMode.bitsRoundtrip]
· -- density roundtrip
rw [fromPacked_density, td]
exact Q0_16.ofNat_toNat_of_le h_lo h_hi
end SpatialCell
-- ============================================================
-- §4 VOLTAGE MODE CLASSIFICATION (FIXED)
-- ============================================================
/-- Classify voltage mode from access pattern (JIT-compatible signature).
This matches the Python implementation EXACTLY:
4-Infrastructure/shim/vectorless_morton_hash_backend.py::classify_voltage_mode
FIXED: Uses (write_count + 1) to avoid division by zero and match Python semantics.
Classification logic:
- write_count = 0 → STORE (I-frame)
- read_count / (write_count + 1) > 10 → COMPUTE (P-frame)
- delta_variance < threshold → APPROX (quantized)
- otherwise → MORPHIC (B-frame)
-/
def classifyVoltageMode
(write_count read_count : Nat)
(delta_variance : Q16_16)
(threshold : Q16_16) : VoltageMode :=
if write_count = 0 then
.store
else if read_count / (write_count + 1) > 10 then -- FIXED: matches Python
.compute
else if delta_variance < threshold then
.approx
else
.morphic
/-- Classification is idempotent. -/
theorem classificationIdempotent
(w r : Nat)
(dv th : Q16_16) :
classifyVoltageMode w r dv th = classifyVoltageMode w r dv th := by
rfl
/-- Classification: write_count = 0 always returns STORE. -/
theorem classificationZeroWrites (r : Nat) (dv th : Q16_16) :
classifyVoltageMode 0 r dv th = .store := by
simp [classifyVoltageMode]
/-- Classification: high read/write ratio returns COMPUTE. -/
theorem classificationReadHeavy
(w r : Nat)
(dv th : Q16_16)
(h_rw : r / (w + 1) > 10)
(h_wne : w ≠ 0) :
classifyVoltageMode w r dv th = .compute := by
simp [classifyVoltageMode, h_wne, h_rw]
-- ============================================================
-- §5 NEIGHBOR BOUNDEDNESS (CONSTANT-DEGREE GRAPH)
-- ============================================================
/-- Moore neighborhood (26 neighbors in 3D). -/
def mooreNeighborhood (c : SpatialCoord) : List SpatialCoord :=
(List.range 3).flatMap (fun dx =>
(List.range 3).flatMap (fun dy =>
(List.range 3).filterMap (fun dz =>
if dx = 1 ∧ dy = 1 ∧ dz = 1 then
none -- Skip self
else
let nx : Nat := c.x.val + dx - 1
let ny : Nat := c.y.val + dy - 1
let nz : Nat := c.z.val + dz - 1
if hx : nx < 16 then
if hy : ny < 16 then
if hz : nz < 16 then
some { x := ⟨nx, hx⟩, y := ⟨ny, hy⟩, z := ⟨nz, hz⟩ }
else none
else none
else none
)
)
)
/-- Exhaustive core: every cell has at most 26 neighbors, checked over all
4096 coordinates in-kernel (native_decide).
Previously a Python-DSP-shim axiom. -/
theorem neighborBounded_all : ∀ (x y z : Fin 16),
(mooreNeighborhood { x := x, y := y, z := z }).length ≤ 26 := by
native_decide
/-- Every cell has at most 26 neighbors (3D Moore neighborhood). -/
theorem neighborBounded (c : SpatialCoord) :
(mooreNeighborhood c).length ≤ 26 :=
neighborBounded_all c.x c.y c.z
/-- Neighbors are within bounds of the grid (0-15 on each axis).
Trivial by construction — mooreNeighborhood only emits coordinates
whose components are proven < 16 via the Fin 16 type. -/
theorem neighborsInBounds (c : SpatialCoord) (n : SpatialCoord) :
n ∈ mooreNeighborhood c → 0 ≤ n.x.val ∧ n.x.val < 16 ∧ 0 ≤ n.y.val ∧ n.y.val < 16 ∧ 0 ≤ n.z.val ∧ n.z.val < 16 := by
intro hn
have hx : n.x.val < 16 := n.x.2
have hy : n.y.val < 16 := n.y.2
have hz : n.z.val < 16 := n.z.2
exact ⟨Nat.zero_le _, hx, Nat.zero_le _, hy, Nat.zero_le _, hz⟩
-- ============================================================
-- §6 HASH-TO-COORDINATE MAPPING
-- ============================================================
/-- Hash function from (table_name, row_id) to spatial coordinate.
Uses locality-preserving approach:
1. Extract sequential bits from row_id (preserves locality)
2. Use table_name hash for spatial rotation (prevents clustering)
3. Map to Morton code for locality preservation
Collision properties (formalised below):
- For fixed `table_name`, `hashToCoord` is injective on `row_id ∈ [0, 256)`
(see `hashToCoord_inj_bounded`).
- The pairwise collision-resistance statement `hashCollisionBound` is the
deterministic backbone of the birthday-bound probabilistic extension,
which requires formal probability theory (`PMF`, `PRNG`) not in scope. -/
def hashToCoord (table_name : String) (row_id : Nat) : SpatialCoord :=
let x := row_id % 16
let y := table_name.length % 16
let z := (row_id / 16 + table_name.length) % 16
{ x := ⟨x, by omega⟩, y := ⟨y, by omega⟩, z := ⟨z, by omega⟩ }
/-- Injectivity of `hashToCoord` on the bounded domain `row_id < 256`.
For fixed `table_name`, two row_ids below 256 produce equal
`SpatialCoord`s only when they are equal. Proof: extract the x
and z component equalities, derive `r1 % 16 = r2 % 16` and
`(r1 / 16 + t.length) % 16 = (r2 / 16 + t.length) % 16`; combined
with the boundedness `r1, r2 < 256` (so `r1 / 16, r2 / 16 < 16`),
the mod-16 equality collapses to quotient equality, and the
dec-position reconstruction `r = 16 * (r / 16) + r % 16` closes
the goal.
This is the deterministic backbone of the previous tautological
`hashCollisionBound` placeholder (which stated `True`). -/
theorem hashToCoord_inj_bounded (table_name : String) (r1 r2 : Nat)
(h1 : r1 < 256) (h2 : r2 < 256) :
hashToCoord table_name r1 = hashToCoord table_name r2 → r1 = r2 := by
intro h_eq
have hx_fin := congr_arg SpatialCoord.x h_eq
have hz_fin := congr_arg SpatialCoord.z h_eq
simp only [hashToCoord, Fin.mk.injEq] at hx_fin hz_fin
-- hx_fin : r1 % 16 = r2 % 16
-- hz_fin : (r1 / 16 + table_name.length) % 16 = (r2 / 16 + table_name.length) % 16
have hr1 : 16 * (r1 / 16) + r1 % 16 = r1 := Nat.div_add_mod r1 16
have hr2 : 16 * (r2 / 16) + r2 % 16 = r2 := Nat.div_add_mod r2 16
omega
/-- Hash collision resistance on the bounded domain.
Restated from the previous tautological placeholder
(`n_rows < 80 → True`) to a meaningful pairwise collision statement:
distinct `row_id`s below 256 cannot hash-collide (for any fixed
`table_name`).
The birthday-paradox probabilistic extension ("for n rows, the
collision probability is bounded by ...") is deferred pending formal
probability theory (`PMF`, `PRNG`). This pairwise bound is the
deterministic core obtained by contraposition of
`hashToCoord_inj_bounded`. -/
theorem hashCollisionBound (table_name : String) (r1 r2 : Nat)
(h1 : r1 < 256) (h2 : r2 < 256) :
r1 ≠ r2 → hashToCoord table_name r1 ≠ hashToCoord table_name r2 := by
intro hr hr_eq
apply hr
exact hashToCoord_inj_bounded table_name r1 r2 h1 h2 hr_eq
-- ============================================================
-- §6b OCTREE-STYLE SPATIAL REFINEMENT
-- ============================================================
/-- Octree refinement levels for the 16×16×16 spatial hash grid.
Each level subdivides every parent cube into 8 octants (factor of 2
per axis), halving the side length and multiplying the cube count
by 8. Level 0 covers the whole 16³ grid as a single cube; Level 4
refines to 4096 single-voxel cubes, matching the spatial hash grid
exactly. -/
inductive OctreeLevel where
| level0 | level1 | level2 | level3 | level4
deriving Repr, DecidableEq, BEq
namespace OctreeLevel
/-- Subdivision depth (0..4). Higher depth ⇒ finer cubes. -/
def depth : OctreeLevel → Nat
| level0 => 0 | level1 => 1 | level2 => 2 | level3 => 3 | level4 => 4
/-- Number of cubes at this refinement level. -/
def cubeCount : OctreeLevel → Nat
| level0 => 1 | level1 => 8 | level2 => 64 | level3 => 512 | level4 => 4096
/-- Side length of each cube at this refinement level. -/
def cubeSide : OctreeLevel → Nat
| level0 => 16 | level1 => 8 | level2 => 4 | level3 => 2 | level4 => 1
/-- Successor refinement level. `none` at level 4 (cannot subdivide
below single-voxel granularity on the 16³ grid). -/
def successor? : OctreeLevel → Option OctreeLevel
| level0 => some level1
| level1 => some level2
| level2 => some level3
| level3 => some level4
| level4 => none
/-- Each octree level subdivides by a factor of 8 (factor 2 per axis):
`cubeCount (succ L) = 8 * cubeCount L`. At level 4, no successor
exists (the `none` arm asserts `L = level4`). -/
theorem cubeCount_succ (L : OctreeLevel) :
match successor? L with
| some L' => cubeCount L' = 8 * cubeCount L
| none => L = level4 := by
cases L <;> rfl
/-- Volume conservation: refining does not change the total 16³ voxel
volume occupied. Each level partitions the same 16³ = 4096 voxel
grid (the total volume of the spatial hash backend). -/
theorem volume_conservation (L : OctreeLevel) :
cubeCount L * (cubeSide L)^3 = 16^3 := by
cases L <;> rfl
/-- Level-4 refinement matches the spatial hash grid exactly:
4096 single-voxel cubes (one per `SpatialCoord` in the 16³ grid). -/
theorem level4_eq_grid : cubeCount level4 = 4096 ∧ cubeSide level4 = 1 := by
refine ⟨rfl, rfl⟩
/-- Recursive cube count equals 2^(3 · depth): each level triples the
branching factor along 3 axes, so refinement factor = 2³ = 8 per
level, giving 2^(3k) cubes at depth k. -/
theorem cube_count_via_depth (L : OctreeLevel) :
cubeCount L = 2 ^ (3 * depth L) := by
cases L <;> rfl
end OctreeLevel
-- ============================================================
-- §7 SPATIAL HASH BACKEND
-- ============================================================
/-- Spatial hash backend: 16×16×16 = 4096 cells. -/
structure SpatialHashBackend where
grid : Fin 4096 → SpatialCell -- Linear indexing (Morton code)
deriving Repr
namespace SpatialHashBackend
/-- Empty backend (all cells zeroed). -/
def empty : SpatialHashBackend :=
{ grid := fun idx =>
let coord := SpatialCoord.fromMorton idx.val idx.isLt
SpatialCell.empty coord
}
/-- Get cell at spatial coordinate (using Morton code). -/
def getCell (b : SpatialHashBackend) (coord : SpatialCoord) : SpatialCell :=
b.grid ⟨coord.toMorton, SpatialCoord.mortonBounded coord⟩
/-- Set cell at spatial coordinate. -/
def setCell (b : SpatialHashBackend) (coord : SpatialCoord) (cell : SpatialCell) : SpatialHashBackend :=
{ b with grid := fun idx =>
if idx.val = coord.toMorton then cell else b.grid idx }
end SpatialHashBackend
-- ============================================================
-- §8 EVAL WITNESSES
-- ============================================================
-- Eval witness: Morton code encoding.
#eval SpatialCoord.toMorton { x := ⟨7, by decide⟩, y := ⟨11, by decide⟩, z := ⟨3, by decide⟩ }
-- Expected: interleaved bits for (7, 11, 3)
-- Eval witness: voltage mode to bits.
#eval VoltageMode.toBits .compute
-- Expected: ⟨1⟩
-- Eval witness: bits to voltage mode.
#eval VoltageMode.fromBits ⟨1, by decide⟩
-- Expected: .compute
-- Eval witness: voltage mode classification (FIXED semantics).
#eval classifyVoltageMode 0 10 zero zero
-- Expected: .store
#eval classifyVoltageMode 1 20 zero zero
-- Expected: .compute (since 20 / 2 = 10 > 10 is FALSE, so this might be different)
-- Note: The threshold is > 10, not ≥ 10
end Semantics.SpatialHashCodec