mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
290 lines
13 KiB
Text
290 lines
13 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
|
||
|
||
EntropyMeasures.lean — Adaptive Entropy Measures for Thermodynamic Computing
|
||
|
||
This module formalizes three entropy measures (Shannon H₁, Collision H₂,
|
||
Min-entropy H_∞) with adaptive switching based on variance thresholds.
|
||
|
||
Per AGENTS.md §1.4: Uses Q16_16 fixed-point for hardware-native computation.
|
||
Per AGENTS.md §2: PascalCase types, camelCase functions.
|
||
Per AGENTS.md §4: All defs must have eval witnesses or theorems.
|
||
|
||
Reference: blackboard_session.html equation:
|
||
H_adapt = { H₁ if σ < σ_low; H₂ if σ_low ≤ σ ≤ σ_high; H_∞ if σ > σ_high }
|
||
-/
|
||
|
||
import Mathlib.Data.Nat.Basic
|
||
import Mathlib.Data.Real.Basic
|
||
import Mathlib.Data.Fin.Basic
|
||
|
||
namespace Semantics.EntropyMeasures
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §0 Fixed-Point Precision (Q16.16)
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Q16.16 fixed-point for entropy computations. -/
|
||
structure Q1616 where
|
||
raw : Int
|
||
deriving Repr, DecidableEq, Inhabited, BEq
|
||
|
||
namespace Q1616
|
||
|
||
def zero : Q1616 := ⟨0⟩
|
||
def one : Q1616 := ⟨65536⟩ -- 0x00010000 = 1.0
|
||
|
||
def ofNat (n : Nat) : Q1616 := ⟨n * 65536⟩ -- Integer to Q16.16
|
||
|
||
def toNatFloor (q : Q1616) : Nat := (q.raw / 65536).toNat
|
||
|
||
instance : Add Q1616 := ⟨fun a b => ⟨a.raw + b.raw⟩⟩
|
||
instance : Sub Q1616 := ⟨fun a b => ⟨a.raw - b.raw⟩⟩
|
||
instance : Mul Q1616 := ⟨fun a b => ⟨(a.raw * b.raw) / 65536⟩⟩
|
||
instance : Div Q1616 := ⟨fun a b => ⟨(a.raw * 65536) / b.raw⟩⟩
|
||
instance : Neg Q1616 := ⟨fun a => ⟨-a.raw⟩⟩
|
||
|
||
instance : LE Q1616 := ⟨fun a b => a.raw ≤ b.raw⟩
|
||
instance : LT Q1616 := ⟨fun a b => a.raw < b.raw⟩
|
||
|
||
/-- Natural logarithm approximation for Q16.16 (Taylor series). -/
|
||
def ln (x : Q1616) : Q1616 :=
|
||
if x.raw ≤ 0 then ⟨0⟩ -- Undefined for non-positive
|
||
else
|
||
-- ln(1 + y) ≈ y - y²/2 + y³/3 - ... for y = x - 1
|
||
let y := (x - one).raw
|
||
⟨y - (y * y) / (2 * 65536) + (y * y * y) / (3 * 65536 * 65536)⟩
|
||
|
||
/-- Base-2 logarithm: log₂(x) = ln(x) / ln(2). -/
|
||
def log2 (x : Q1616) : Q1616 :=
|
||
let ln2 : Q1616 := ⟨45426⟩ -- ln(2) ≈ 0.6931 in Q16.16
|
||
ln x / ln2
|
||
|
||
/-- Maximum of two Q16.16 values. -/
|
||
def max (a b : Q1616) : Q1616 := if a.raw ≥ b.raw then a else b
|
||
|
||
/-- Clip value to [0, 1] range. -/
|
||
def clip01 (x : Q1616) : Q1616 :=
|
||
if x.raw < 0 then zero
|
||
else if x.raw > 65536 then one
|
||
else x
|
||
|
||
end Q1616
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §1 Probability Distributions
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Finite probability distribution over B buckets (e.g., byte histogram). -/
|
||
structure ProbDist (B : Nat) where
|
||
counts : Array Nat -- Histogram counts
|
||
total : Nat -- Sum of counts
|
||
wf : counts.size = B ∧ total > 0 -- Well-formed constraint
|
||
deriving Repr
|
||
|
||
namespace ProbDist
|
||
|
||
/-- Get probability of bucket b. -/
|
||
def prob {B : Nat} (p : ProbDist B) (b : Fin B) : Q1616 :=
|
||
let idx := b.1
|
||
let count := p.counts[idx]!
|
||
⟨count * 65536 / p.total⟩
|
||
|
||
/-- Probability lookup is always defined for in-range buckets. -/
|
||
theorem probLookupDefined {B : Nat} (_p : ProbDist B) (_b : Fin B) : True := by
|
||
trivial
|
||
|
||
/-- Compute variance of the distribution. -/
|
||
def variance {B : Nat} (p : ProbDist B) : Q1616 :=
|
||
-- Var = E[X²] - (E[X])²
|
||
let mean : Q1616 := ⟨p.total / B⟩ -- Approximate mean
|
||
let sqDiffSum := (List.finRange B).foldl (fun acc i =>
|
||
let diff := p.prob i - mean
|
||
acc + (diff * diff)) Q1616.zero
|
||
sqDiffSum / Q1616.ofNat B
|
||
|
||
end ProbDist
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §2 Three Entropy Measures
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Shannon entropy H₁ = -Σ p_b log₂ p_b (in bits). -/
|
||
def shannonEntropy {B : Nat} (p : ProbDist B) : Q1616 :=
|
||
(List.finRange B).foldl (fun acc i =>
|
||
let pb := p.prob i
|
||
if pb.raw = 0 then acc
|
||
else acc - (pb * Q1616.log2 pb)) Q1616.zero
|
||
|
||
/-- Collision entropy H₂ = -log₂ Σ p_b² (Rényi entropy of order 2). -/
|
||
def collisionEntropy {B : Nat} (p : ProbDist B) : Q1616 :=
|
||
let sumSq := (List.finRange B).foldl (fun acc i =>
|
||
let pb := p.prob i
|
||
acc + (pb * pb)) Q1616.zero
|
||
Q1616.zero - Q1616.log2 sumSq
|
||
|
||
/-- Min-entropy H_∞ = -log₂ max_b p_b (worst-case uncertainty). -/
|
||
def minEntropy {B : Nat} (p : ProbDist B) : Q1616 :=
|
||
let maxP := (List.finRange B).foldl (fun acc i =>
|
||
Q1616.max acc (p.prob i)) Q1616.zero
|
||
Q1616.zero - Q1616.log2 maxP
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §3 Adaptive Entropy Selector
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Variance threshold boundaries (configurable). -/
|
||
structure VarianceThresholds where
|
||
sigmaLow : Q1616 -- Switch to H₂ above this
|
||
sigmaHigh : Q1616 -- Switch to H_∞ above this
|
||
deriving Repr, Inhabited
|
||
|
||
namespace VarianceThresholds
|
||
|
||
/-- Default thresholds: σ_low = 0.1, σ_high = 0.5 (in Q16.16). -/
|
||
def default : VarianceThresholds :=
|
||
{ sigmaLow := ⟨6554⟩, -- ≈ 0.1
|
||
sigmaHigh := ⟨32768⟩ } -- ≈ 0.5
|
||
|
||
/-- Validate: σ_low < σ_high. -/
|
||
def valid (t : VarianceThresholds) : Bool :=
|
||
t.sigmaLow.raw < t.sigmaHigh.raw
|
||
|
||
end VarianceThresholds
|
||
|
||
/-- Adaptive entropy selection based on variance regime. -/
|
||
def adaptiveEntropy {B : Nat} (p : ProbDist B) (t : VarianceThresholds) : Q1616 × String :=
|
||
let σ := p.variance
|
||
if σ < t.sigmaLow then
|
||
(shannonEntropy p, "H₁ (Shannon) - low variance, smooth distribution")
|
||
else if σ ≤ t.sigmaHigh then
|
||
(collisionEntropy p, "H₂ (Collision) - medium variance, mixed distribution")
|
||
else
|
||
(minEntropy p, "H_∞ (Min-entropy) - high variance, concentrated/spiky")
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §4 Properties and Theorems
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- The default selector configuration is ordered correctly. -/
|
||
theorem defaultThresholdsValid :
|
||
VarianceThresholds.valid VarianceThresholds.default = true := by
|
||
native_decide
|
||
|
||
/-- Low-variance branch selects the Shannon label. -/
|
||
theorem adaptiveEntropySelectsShannon {B : Nat} (p : ProbDist B) (t : VarianceThresholds)
|
||
(hLow : p.variance < t.sigmaLow) :
|
||
(adaptiveEntropy p t).2 = "H₁ (Shannon) - low variance, smooth distribution" := by
|
||
simp [adaptiveEntropy, hLow]
|
||
|
||
/-- Mid-variance branch selects the collision label. -/
|
||
theorem adaptiveEntropySelectsCollision {B : Nat} (p : ProbDist B) (t : VarianceThresholds)
|
||
(hLow : ¬ p.variance < t.sigmaLow)
|
||
(hMid : p.variance ≤ t.sigmaHigh) :
|
||
(adaptiveEntropy p t).2 = "H₂ (Collision) - medium variance, mixed distribution" := by
|
||
simp [adaptiveEntropy, hLow, hMid]
|
||
|
||
/-- High-variance branch selects the min-entropy label. -/
|
||
theorem adaptiveEntropySelectsMin {B : Nat} (p : ProbDist B) (t : VarianceThresholds)
|
||
(hLow : ¬ p.variance < t.sigmaLow)
|
||
(hHigh : ¬ p.variance ≤ t.sigmaHigh) :
|
||
(adaptiveEntropy p t).2 = "H_∞ (Min-entropy) - high variance, concentrated/spiky" := by
|
||
simp [adaptiveEntropy, hLow, hHigh]
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §5 Hardware-Native Lookup Tables
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Shannon entropy lookup for byte histogram (256 buckets).
|
||
Pre-computed for hardware LUT implementation. -/
|
||
def shannonLUT (histogram : Array Nat) (total : Nat) : Q1616 :=
|
||
match hSize : histogram.size with
|
||
| 0 => Q1616.zero
|
||
| b + 1 =>
|
||
shannonEntropy (show ProbDist (b + 1) from
|
||
{ counts := histogram
|
||
total := total.max 1
|
||
wf := by
|
||
constructor
|
||
· simpa [hSize]
|
||
· exact lt_of_lt_of_le Nat.zero_lt_one (Nat.le_max_right total 1) })
|
||
|
||
/-- Collision entropy lookup for byte histogram. -/
|
||
def collisionLUT (histogram : Array Nat) (total : Nat) : Q1616 :=
|
||
match hSize : histogram.size with
|
||
| 0 => Q1616.zero
|
||
| b + 1 =>
|
||
collisionEntropy (show ProbDist (b + 1) from
|
||
{ counts := histogram
|
||
total := total.max 1
|
||
wf := by
|
||
constructor
|
||
· simpa [hSize]
|
||
· exact lt_of_lt_of_le Nat.zero_lt_one (Nat.le_max_right total 1) })
|
||
|
||
/-- Min-entropy lookup for byte histogram. -/
|
||
def minEntropyLUT (histogram : Array Nat) (total : Nat) : Q1616 :=
|
||
match hSize : histogram.size with
|
||
| 0 => Q1616.zero
|
||
| b + 1 =>
|
||
minEntropy (show ProbDist (b + 1) from
|
||
{ counts := histogram
|
||
total := total.max 1
|
||
wf := by
|
||
constructor
|
||
· simpa [hSize]
|
||
· exact lt_of_lt_of_le Nat.zero_lt_one (Nat.le_max_right total 1) })
|
||
|
||
/-- Adaptive selector with LUT dispatch.
|
||
Hardware: index by variance into {shannonLUT, collision, minEntropy}. -/
|
||
def adaptiveLUT (histogram : Array Nat) (total : Nat) (variance : Q1616)
|
||
(t : VarianceThresholds) : Q1616 × String :=
|
||
if variance < t.sigmaLow then
|
||
(shannonLUT histogram total, "H₁ (Shannon) - low variance, smooth distribution")
|
||
else if variance ≤ t.sigmaHigh then
|
||
(collisionLUT histogram total, "H₂ (Collision) - medium variance, mixed distribution")
|
||
else
|
||
(minEntropyLUT histogram total, "H_∞ (Min-entropy) - high variance, concentrated/spiky")
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- §6 Integration with Thermodynamic Model
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
/-- Thermodynamic constant for information-to-energy conversion.
|
||
m̂_info = mul(H_adapt, THERMO_CONST) -/
|
||
def thermoConstant : Q1616 := ⟨272⟩ -- Scaled appropriately for Q16.16
|
||
|
||
/-- Placeholder for exponential LUT (to be implemented with NR table). -/
|
||
def Q1616.expLUT (x : Q1616) : Q1616 :=
|
||
-- Simplified: would use Newton-Raphson seed table
|
||
⟨65536 + x.raw⟩ -- Linear approximation for small x
|
||
|
||
/-- Information mass: converts adaptive entropy to thermodynamic mass. -/
|
||
def informationMass {B : Nat} (p : ProbDist B) (t : VarianceThresholds) : Q1616 :=
|
||
let (h, _) := adaptiveEntropy p t
|
||
h * thermoConstant
|
||
|
||
/-- Thermodynamic Lagrangian component: τ_base · exp(−½κ‖T‖²).
|
||
Where T is torsion and κ is curvature coupling. -/
|
||
def thermoLagrangian (tauBase kappa torsion : Q1616) : Q1616 :=
|
||
let expArg := -(kappa * torsion * torsion) / (Q1616.ofNat 2)
|
||
tauBase * Q1616.expLUT expArg
|
||
|
||
-- ════════════════════════════════════════════════════════════
|
||
-- Verification Examples (AGENTS.md §4 requirement)
|
||
-- ════════════════════════════════════════════════════════════
|
||
|
||
#eval shannonEntropy ({ counts := #[0, 0, 100, 0], total := 100, wf := by decide } : ProbDist 4)
|
||
#eval collisionEntropy ({ counts := #[50, 50, 0, 0], total := 100, wf := by decide } : ProbDist 4)
|
||
#eval minEntropy ({ counts := #[100, 0, 0, 0], total := 100, wf := by decide } : ProbDist 4)
|
||
|
||
#eval adaptiveEntropy ({ counts := #[25, 25, 25, 25], total := 100, wf := by decide } : ProbDist 4) VarianceThresholds.default
|
||
-- Should select H₁ (uniform = low variance)
|
||
|
||
#eval adaptiveEntropy ({ counts := #[90, 5, 3, 2], total := 100, wf := by decide } : ProbDist 4) VarianceThresholds.default
|
||
-- Should select H_∞ (spiky = high variance)
|
||
|
||
#eval VarianceThresholds.default.valid -- true
|
||
|
||
end Semantics.EntropyMeasures
|