Research-Stack/0-Core-Formalism/lean/Semantics/Semantics/MISignal.lean
Brandon Schneider 835299fd9a fix(lean+shim): enforce lean-coding rules across audit surface
## Lean fixes

- RRCLogogramProjection.lean: replace `native_decide` → `decide` in 5
  compiler-surface theorem witnesses (semantic_tear_projects_after_repair,
  semantic_tear_does_not_merge, semantic_tear_uses_quarantine_lane,
  unrepaired_tear_does_not_project, ordinary_logogram_projects_and_merges).
  All 5 pass under `decide`; no logic change.

- PistSimulation.lean: add `-- expect: <value>` to every `#eval`/`#eval!`
  block across §6–§11 (~104 annotation lines). Document 8 undocumented
  `ofRawInt` magic integers in fixtureSpectralWindow (10.0, 20.0, 100.0,
  40.0, 20.0, 10.0, 5.0, 5.0 × 65536).

- DynamicCanal.lean: add `-- expect:` to all 15 #eval witness blocks in
  §17 (fixed-point constructors, DIAT encoding, coarse-graining tests).

- MISignal.lean: add `-- expect: 131072` to both #eval witnesses.

- Functions/BracketedCalculus.lean: add `-- expect: 327680` to #eval.

- AVMIsa/Emit.lean, RRC/Emit.lean, RRC/ReceiptDensity.lean, ReceiptCore.lean:
  previously-staged `-- expect:` additions (from prior session) carried
  forward in this commit.

## Python shim fixes

- Add `# PARTIAL BOUNDARY: contains domain logic; not a provable surface.
  Port to Lean/RRC before treating as authoritative.` to 9 shim files:
  pist_trace_classify_mcp.py, genus0_sphere_shell_demo.py,
  routing_benchmark.py, route_repair_v14a.py, pist_prove_and_classify.py,
  label_canary_theorems.py, validate_rrc_predictions.py,
  pist_receipt_density_injector.py, rrc_pist_shape_alignment.py.

## Build baseline

  lake build Compiler  →  3311 jobs, 0 errors
  lake build           →  3567 jobs, 0 errors

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-26 23:17:40 -05:00

93 lines
3.6 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.

/-
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 := Q16_16.ofRawInt 1
-- Scale constant: 8.0 in Q16.16 = 8 * 65536
def bitsPerByteMax : Q16_16 := Q16_16.ofRawInt (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) : Q16_16 :=
let ma := mutualInformationSignal a
let mb := mutualInformationSignal b
Q16_16.ofNat (abs (sub ma mb)).toBits.toNat
def miSignalBind (a b : MIRecord) (m : Metric) : Bind MIRecord MIRecord :=
informationalBind a b m miCost miInvariant miInvariant
-- Verify
#eval mutualInformationSignal { baselineBpb := Q16_16.ofRawInt (5 * 65536), actualBpb := Q16_16.ofRawInt (3 * 65536), miPredicted := Q16_16.ofRawInt (2 * 65536) } -- expect: 131072
#eval surpriseMetric { baselineBpb := Q16_16.ofRawInt (5 * 65536), actualBpb := Q16_16.ofRawInt (3 * 65536), miPredicted := Q16_16.ofRawInt 65536 } -- expect: 131072
end Semantics.MISignal