mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
181 lines
7.9 KiB
Text
181 lines
7.9 KiB
Text
/- Copyright (c) 2026 Sovereign Research Stack. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Research Stack Team
|
||
|
||
ShellModel.lean — Shell State Geometry and Event Classification
|
||
|
||
This module implements the Erdős #1196 piecewise eigenvector construction
|
||
for shell-based event classification. It provides:
|
||
• Shell state geometry (n, k, a, b parameters)
|
||
• Integer square root for shell boundary calculation
|
||
• Event classification at shell boundaries
|
||
• Tip coordinates (mass, polarity) for event positioning
|
||
• Spectral signatures for each event type
|
||
|
||
The shell model organizes events in concentric square shells, with each
|
||
shell containing events at specific geometric positions.
|
||
|
||
Per AGENTS.md §0: Lean is the source of truth.
|
||
Per AGENTS.md §1.4: Uses Q16.16 for hot-path arithmetic.
|
||
-/
|
||
|
||
import Semantics.FixedPoint
|
||
import Semantics.GeneticCode
|
||
import Semantics.Spectrum
|
||
import Mathlib.Data.Nat.Sqrt
|
||
|
||
namespace Semantics.ShellModel
|
||
|
||
open Semantics
|
||
open Semantics.GeneticCode
|
||
open Semantics.Spectrum
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §1 Core Structures
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Shell state parametrization.
|
||
The Erdős shell model uses four parameters:
|
||
• n: Global event index
|
||
• k: Shell index (k = floor(sqrt(n)))
|
||
• a: Distance from previous perfect square (n - k²)
|
||
• b: Distance to next perfect square ((k+1)² - n)
|
||
|
||
Invariants: n = k² + a = (k+1)² - b, with a + b = 2k + 1 -/
|
||
structure ShellState where
|
||
n : Nat
|
||
k : Nat
|
||
a : Nat
|
||
b : Nat
|
||
deriving Repr, DecidableEq
|
||
|
||
/-- Tip coordinate representation.
|
||
Each event has a "tip" with:
|
||
• mass: ab (product of distances, measures event magnitude)
|
||
• polarity: a - b (difference, measures event asymmetry) -/
|
||
structure TipCoord where
|
||
mass : Int -- ab
|
||
polarity : Int -- a - b
|
||
deriving Repr, DecidableEq
|
||
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §2 Shell State Calculation
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Integer square root (floor of sqrt) via Mathlib's proven `Nat.sqrt`. -/
|
||
def isqrt (n : Nat) : Nat :=
|
||
Nat.sqrt n
|
||
|
||
/-- Construct shell state from event index.
|
||
k = floor(sqrt(n))
|
||
a = n - k² (distance from lower perfect square)
|
||
b = (k+1)² - n (distance to upper perfect square) -/
|
||
def shellState (n : Nat) : ShellState :=
|
||
let k := isqrt n
|
||
let a := n - k*k
|
||
let b := (k+1)*(k+1) - n
|
||
{ n := n, k := k, a := a, b := b }
|
||
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §3 Event Classification
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Classify event type based on position within shell.
|
||
Event positions in shell (reading clockwise from lower-right):
|
||
• a: At k² (perfect square corner)
|
||
• g: At k² + k (midpoint of right edge)
|
||
• c: At k² + k + 1 (corner after midpoint)
|
||
• t: At (k+1)² - 1 (last position before next square) -/
|
||
def classifyEvent (s : ShellState) : Option EventType :=
|
||
let k := s.k
|
||
let n := s.n
|
||
if n = k*k then some .a
|
||
else if n = k*k + k then some .g
|
||
else if n = k*k + k + 1 then some .c
|
||
else if n = (k+1)*(k+1) - 1 then some .t
|
||
else none
|
||
|
||
/-- Compute tip coordinates from shell state.
|
||
mass = a·b (product measures event "size")
|
||
polarity = a - b (difference measures event "tilt") -/
|
||
def tipCoord (s : ShellState) : TipCoord :=
|
||
{ mass := Int.ofNat (s.a * s.b)
|
||
, polarity := Int.ofNat s.a - Int.ofNat s.b
|
||
}
|
||
|
||
/-- Full event information at index n.
|
||
Returns: (ShellState, EventType, TipCoord) or none if not at special position. -/
|
||
def eventAt (n : Nat) : Option (ShellState × EventType × TipCoord × SpectralSignature) := do
|
||
let s := shellState n
|
||
let e ← classifyEvent s
|
||
let t := tipCoord s
|
||
let col := SpectralSignature.eventSpectrum e
|
||
pure (s, e, t, col)
|
||
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §4 Spectral Encoding
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
-- Map event to spectrum moved to Spectrum.lean
|
||
|
||
/-- Merge two spectral signatures (piecewise max). -/
|
||
def SpectralSignature.piecewiseMerge (x y : SpectralSignature) : SpectralSignature :=
|
||
{ bins := List.zipWith (λ a b => if a.val.toNat > b.val.toNat then a else b) x.bins y.bins }
|
||
|
||
/-- Compute resonance degeneracy between two spectra.
|
||
Counts overlapping spectral peaks (both non-zero at same position). -/
|
||
def SpectralSignature.resonanceDegeneracy (x y : SpectralSignature) : Nat :=
|
||
List.zipWith (λ a b => if a.val.toNat > 0 && b.val.toNat > 0 then 1 else 0) x.bins y.bins
|
||
|>.foldl (· + ·) 0
|
||
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §5 Tail Weight System
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Tail weight for backward residue as Q16_16.
|
||
Used in field accumulation to weight backward-looking contributions.
|
||
Weights decrease with distance: d=1 → -1, d=2 → -0.5, d=3 → -0.25 -/
|
||
def tailWeight : Nat → Q16_16
|
||
| 1 => Q16_16.sub Q16_16.zero Q16_16.one
|
||
| 2 => Q16_16.div (Q16_16.ofInt (-1)) (Q16_16.ofInt 2)
|
||
| 3 => Q16_16.div (Q16_16.ofInt (-1)) (Q16_16.ofInt 4)
|
||
| _ => Q16_16.zero
|
||
|
||
/-- Integer clamping utility.
|
||
Restricts value to [lo, hi] range. -/
|
||
def clampInt (lo hi x : Int) : Int :=
|
||
if x < lo then lo else if x > hi then hi else x
|
||
|
||
/-- Phase calculation from tip coordinates and interaction strength.
|
||
Combines polarity and mass terms to produce phase index (-3 to 3). -/
|
||
def phaseFromTipAndInteraction (s : ShellState) (tip : TipCoord) (j : Q16_16) : Int :=
|
||
let shellWidth : Int := Int.ofNat (2 * s.k + 1)
|
||
let polTerm : Int :=
|
||
if shellWidth = 0 then 0 else (3 * tip.polarity) / shellWidth
|
||
let intTerm : Int :=
|
||
if Q16_16.gt j Q16_16.zero then
|
||
if tip.mass > 0 then 1 else -1
|
||
else 0
|
||
clampInt (-3) 3 (polTerm + intTerm)
|
||
|
||
/-- Boolean index from interaction sign.
|
||
True if interaction is positive (attractive). -/
|
||
def indexBitFromInteraction (j : Q16_16) : Bool :=
|
||
Q16_16.gt j Q16_16.zero
|
||
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §6 Verification Examples
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
#eval shellState 1 -- k=1, a=0, b=3 (perfect square 1²)
|
||
#eval shellState 5 -- k=2, a=1, b=4 (between 2²=4 and 3²=9)
|
||
#eval classifyEvent (shellState 4) -- Some EventType.a (4 = 2²)
|
||
#eval classifyEvent (shellState 6) -- Some EventType.g (6 = 2² + 2)
|
||
#eval tipCoord (shellState 5) -- mass=4, polarity=-3
|
||
|
||
end Semantics.ShellModel
|