mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
93 lines
3.5 KiB
Text
93 lines
3.5 KiB
Text
/-
|
||
MISignal.lean - Mutual Information Signal Processing Bindings
|
||
Ports rows 72-76 from MATH_MODEL_MAP.tsv (Python → Lean).
|
||
|
||
All values are Q16.16. Bits-per-byte range [0, 8] maps to [0, 8·65536].
|
||
-/
|
||
import Semantics.Bind
|
||
import Semantics.FixedPoint
|
||
|
||
namespace Semantics.MISignal
|
||
|
||
open Q16_16
|
||
|
||
def epsilon : Q16_16 := ⟨1⟩
|
||
|
||
-- Scale constant: 8.0 in Q16.16 = 8 * 65536
|
||
def bitsPerByteMax : Q16_16 := ⟨8 * 65536⟩
|
||
|
||
structure MIRecord where
|
||
baselineBpb : Q16_16 -- baseline bits-per-byte (uncompressed context)
|
||
actualBpb : Q16_16 -- actual bits-per-byte achieved
|
||
miPredicted : Q16_16 -- kNN-predicted MI value
|
||
deriving Repr, Inhabited, DecidableEq
|
||
|
||
-- Row 72: MI(x) = baseline_bpb - actual_bpb
|
||
-- Mutual information extracted through compression improvement
|
||
def mutualInformationSignal (r : MIRecord) : Q16_16 :=
|
||
if r.baselineBpb.val ≥ r.actualBpb.val
|
||
then sub r.baselineBpb r.actualBpb
|
||
else zero
|
||
|
||
-- Row 73: MI_pred = Σ(w_i · MI_i · S_i) / Σ(w_i · S_i)
|
||
-- kNN weighted MI prediction; w_i = 1/(d_i + ε)
|
||
-- distances, mis, similarities are parallel arrays
|
||
def knnMIPrediction (distances mis similarities : Array Q16_16) : Q16_16 :=
|
||
let n := distances.size
|
||
if n == 0 || mis.size != n || similarities.size != n then zero
|
||
else
|
||
let num := Array.foldl (fun acc i =>
|
||
let w := div one (add distances[i]! epsilon)
|
||
add acc (mul (mul w mis[i]!) similarities[i]!)
|
||
) zero (Array.range n)
|
||
let den := Array.foldl (fun acc i =>
|
||
let w := div one (add distances[i]! epsilon)
|
||
add acc (mul w similarities[i]!)
|
||
) zero (Array.range n)
|
||
if den.val == 0 then zero else div num den
|
||
|
||
-- Row 74: surprise = log(1 + |MI_actual - MI_predicted|)
|
||
-- Approximated in Q16.16: surprise ≈ |diff| (natural log not available in integer—use diff directly as ordinal surprise)
|
||
def surpriseMetric (r : MIRecord) : Q16_16 :=
|
||
let miActual := mutualInformationSignal r
|
||
let diff := abs (sub miActual r.miPredicted)
|
||
-- log(1+x) ≈ x for small x; represent as direct delta in Q16.16
|
||
add one diff
|
||
|
||
-- Row 75: ρ(x) = MI(x) / (cost(x) + ε)
|
||
-- Structure yield: information per unit compute cost
|
||
def structureYield (mi cost : Q16_16) : Q16_16 :=
|
||
div mi (add cost epsilon)
|
||
|
||
-- Row 76: d(z₁, z₂) = √( Σ w_i · ((z₁_i - z₂_i) / s_i)² )
|
||
-- Weighted feature distance over 9-dim vector
|
||
-- Uses integer arithmetic: no float sqrt; return squared distance as cost proxy
|
||
def weightedFeatureDistanceSq (z1 z2 weights scales : Array Q16_16) : Q16_16 :=
|
||
let n := z1.size
|
||
if n == 0 then zero
|
||
else
|
||
Array.foldl (fun acc i =>
|
||
if i < z2.size && i < weights.size && i < scales.size then
|
||
let diff := abs (sub z1[i]! z2[i]!)
|
||
let scaled := div diff (add scales[i]! epsilon)
|
||
let sq := mul scaled scaled
|
||
add acc (mul weights[i]! sq)
|
||
else acc
|
||
) zero (Array.range n)
|
||
|
||
def miInvariant (r : MIRecord) : String :=
|
||
s!"mi:baseline={r.baselineBpb.val},actual={r.actualBpb.val}"
|
||
|
||
def miCost (a b : MIRecord) (_m : Metric) : UInt32 :=
|
||
let ma := mutualInformationSignal a
|
||
let mb := mutualInformationSignal b
|
||
(abs (sub ma mb)).val
|
||
|
||
def miSignalBind (a b : MIRecord) (m : Metric) : Bind MIRecord MIRecord :=
|
||
informationalBind a b m miCost miInvariant miInvariant
|
||
|
||
-- Verify
|
||
#eval mutualInformationSignal { baselineBpb := ⟨5 * 65536⟩, actualBpb := ⟨3 * 65536⟩, miPredicted := ⟨2 * 65536⟩ }
|
||
#eval surpriseMetric { baselineBpb := ⟨5 * 65536⟩, actualBpb := ⟨3 * 65536⟩, miPredicted := ⟨65536⟩ }
|
||
|
||
end Semantics.MISignal
|