Research-Stack/0-Core-Formalism/lean/Semantics/Semantics/MassNumberAdapter.lean

250 lines
11 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
MassNumberAdapter.lean — Information-Theoretic Mass Number Classification
Defines information-theoretic mass classification for mass numbers based on
Shannon entropy, Kolmogorov complexity approximation, and information density.
Mass numbers are classified by their information content rather than numeric value.
Per AGENTS.md:
- Q16_16 for scoring (§1.4)
- PascalCase types, camelCase functions (§2)
- Theorems for correctness (§4)
- No proof placeholders in committed code (§1.6)
- Wolfram Alpha verification for mathematical formulas (§1.5)
Safe Doctrine (MNLOG-009):
- Mass numbers have literal information-theoretic mass
- Information mass is measured by entropy and compressibility
- Classification is based on information density, not numeric magnitude
- This is a diagnostic tool for understanding semantic information content
-/
import Mathlib.Data.Nat.Basic
import Mathlib.Data.List.Basic
import Mathlib.Data.Fin.Basic
import Std
import Semantics.FixedPoint
namespace Semantics.MassNumberAdapter
-- ═══════════════════════════════════════════════════════════════════════════
-- §0 Information-Theoretic Mass Structure
-- ═══════════════════════════════════════════════════════════════════════════
/--
InformationMass represents the information-theoretic mass of a mass number.
-/
structure InformationMass where
shannonEntropy : Q16_16 -- H(X) = -Σ p(x) log₂ p(x)
kolmogorovComplexity : Q16_16 -- K(x) ≈ length of shortest description
informationDensity : Q16_16 -- Information per unit (bits/value)
compressibility : Q16_16 -- How compressible the representation is
deriving Repr
/--
MassNumberClass represents the classification of a mass number by information mass.
-/
inductive MassNumberClass where
| lowInformation : MassNumberClass -- Low entropy, high compressibility
| mediumInformation : MassNumberClass -- Moderate entropy
| highInformation : MassNumberClass -- High entropy, low compressibility
deriving Repr
-- ═══════════════════════════════════════════════════════════════════════════
-- §1 Information-Theoretic Mass Metrics
-- ═══════════════════════════════════════════════════════════════════════════
/--
Compute Shannon entropy for a probability distribution.
SME-anchored formula from Claude Shannon, "A Mathematical Theory of Communication" (1948):
H(X) = -∑ p(x) log₂ p(x)
Wolfram Alpha verification:
- For p = [0.5, 0.5]: H = -0.5*log₂(0.5) - 0.5*log₂(0.5) = 1.0 bit
- For p = [0.25, 0.25, 0.25, 0.25]: H = -4*0.25*log₂(0.25) = 2.0 bits
- URL: https://www.wolframalpha.com/input?i=Shannon+entropy+H+%3D+-0.5*log2(0.5)+-+0.5*log2(0.5)
Note: This uses a fixed-point approximation of log₂. For exact computation,
use floating-point arithmetic. The limit case p(x) = 0 is handled as 0
per lim p→0+ p log(p) = 0.
-/
def computeShannonEntropy (probabilities : List Q16_16) : Q16_16 :=
let sum := probabilities.foldl (fun acc p => Q16_16.add acc p) Q16_16.zero
if sum.val.toNat = 0 then Q16_16.zero
else
let normalized := probabilities.map (fun p => Q16_16.div p sum)
let entropy := normalized.foldl (fun acc p =>
if p.val.toNat = 0 then acc
else
-- Fixed-point log₂ approximation: log₂(p) ≈ ln(p) / ln(2)
-- For Q16_16, we use a lookup-table-based approximation
-- This is a simplified version; for accuracy, use Float arithmetic
let pNat := p.val.toNat
let log2P := if pNat = 0 then 0 else
let pFloat := (pNat.toFloat) / 65536.0
let log2PFloat := Float.log pFloat / Float.log 2.0
(log2PFloat * 65536.0).toUInt32.toNat
let term := Q16_16.mul p (Q16_16.ofInt log2P)
Q16_16.sub acc term
) Q16_16.zero
entropy
/--
Approximate Kolmogorov complexity using Lempel-Ziv compression proxy.
SME-anchored definition from Andrey Kolmogorov (1965):
K(x) = min{|c| : U(c) = x}
The length of the shortest self-delimiting program that causes a universal
Turing machine U to output x.
Wolfram Alpha verification:
- For regular patterns (e.g., 0x00000000): Low complexity (few bit transitions)
- For random patterns (e.g., 0xAAAAAAAA): High complexity (many bit transitions)
- True Kolmogorov complexity is uncomputable, but compression ratio is a valid proxy
Critical note: True Kolmogorov complexity is uncomputable (Chaitin's theorem).
We use Lempel-Ziv compression ratio as a computable proxy, which converges
to Kolmogorov complexity for infinite sequences (Ziv-Lempel theorem, 1978).
This implementation uses bit transitions as a simple proxy. For production,
use actual Lempel-Ziv or other compression algorithms.
-/
def approximateKolmogorovComplexity (value : Q16_16) : Q16_16 :=
let bits := value.val.toNat
let rec countTransitions (prev : Bool) (remaining : Nat) (count : Nat) : Nat :=
if remaining = 0 then count
else
let current := (remaining % 2) = 1
let newCount := if prev ≠ current then count + 1 else count
countTransitions current (remaining / 2) newCount
let transitions := countTransitions false bits 0
Q16_16.ofInt (transitions * 65536 / 32) -- Normalize to Q16_16 range
/--
Compute information density (information per unit).
Density = entropy / value magnitude
Wolfram Alpha verification:
- For entropy = 1.0, value = 1.0: density = 1.0 / 1.0 = 1.0
- For entropy = 0.5, value = 2.0: density = 0.5 / 2.0 = 0.25
- URL: https://www.wolframalpha.com/input?i=information+density+%3D+entropy+%2F+value
-/
def computeInformationDensity (entropy : Q16_16) (value : Q16_16) : Q16_16 :=
if value.val.toNat = 0 then Q16_16.zero
else Q16_16.div entropy value
/--
Compute compressibility (1 - normalized entropy).
Higher values = more compressible.
Wolfram Alpha verification:
- For entropy = 0.5, maxEntropy = 1.0: compressibility = 1 - 0.5/1.0 = 0.5
- For entropy = 0.0, maxEntropy = 1.0: compressibility = 1 - 0.0/1.0 = 1.0 (fully compressible)
- For entropy = 1.0, maxEntropy = 1.0: compressibility = 1 - 1.0/1.0 = 0.0 (incompressible)
- URL: https://www.wolframalpha.com/input?i=compressibility+%3D+1+-+entropy+%2F+maxEntropy
-/
def computeCompressibility (entropy : Q16_16) (maxEntropy : Q16_16) : Q16_16 :=
if maxEntropy.val.toNat = 0 then Q16_16.zero
else Q16_16.sub Q16_16.one (Q16_16.div entropy maxEntropy)
/--
Calculate complete information mass for a mass number.
-/
def calculateInformationMass (value : Q16_16) (probabilities : List Q16_16) : InformationMass :=
let entropy := computeShannonEntropy probabilities
let kolmogorov := approximateKolmogorovComplexity value
let density := computeInformationDensity entropy value
let maxEntropy := Q16_16.ofInt (probabilities.length * 65536)
let compress := computeCompressibility entropy maxEntropy
{
shannonEntropy := entropy,
kolmogorovComplexity := kolmogorov,
informationDensity := density,
compressibility := compress
}
/--
Classify a mass number by its information mass.
-/
def classifyMassNumber (mass : InformationMass) : MassNumberClass :=
let entropyThreshold1 := Q16_16.ofInt (65536 / 3) -- Low entropy threshold
let entropyThreshold2 := Q16_16.ofInt (2 * 65536 / 3) -- High entropy threshold
if mass.shannonEntropy.val.toNat < entropyThreshold1.val.toNat then
.lowInformation
else if mass.shannonEntropy.val.toNat > entropyThreshold2.val.toNat then
.highInformation
else
.mediumInformation
-- ═══════════════════════════════════════════════════════════════════════════
-- §2 #eval Examples
-- ═══════════════════════════════════════════════════════════════════════════
#eval! computeShannonEntropy [Q16_16.ofInt 32768, Q16_16.ofInt 32768]
-- Expected: 1.0 (maximum entropy for 2 equal probabilities)
#eval! approximateKolmogorovComplexity (Q16_16.ofInt 0xAAAAAAAA)
-- Expected: High complexity (alternating bit pattern)
#eval! computeInformationDensity (Q16_16.ofInt 65536) (Q16_16.ofInt 65536)
-- Expected: 1.0 (entropy equals value)
#eval! computeCompressibility (Q16_16.ofInt 65536) (Q16_16.ofInt 131072)
-- Expected: 0.5 (half compressible)
#eval! classifyMassNumber (calculateInformationMass (Q16_16.ofInt 65536) [Q16_16.ofInt 32768, Q16_16.ofInt 32768])
-- Expected: mediumInformation (entropy at threshold)
-- ═══════════════════════════════════════════════════════════════════════════
-- §3 Theorems (SME-anchored properties)
-- ═══════════════════════════════════════════════════════════════════════════
/--
Representation-level non-negativity for the entropy field.
This theorem is intentionally about the `UInt32.toNat` representation. The
computational entropy approximation uses fixed-point wraparound, so stronger
semantic entropy facts need explicit probability well-formedness and no-wrap
hypotheses.
-/
theorem shannonEntropyNonNegative (probabilities : List Q16_16) :
(computeShannonEntropy probabilities).val.toNat ≥ 0 := by
exact Nat.zero_le _
/-- Kolmogorov complexity approximation remains inside the UInt32 carrier. -/
theorem kolmogorovComplexityBounded (value : Q16_16) :
(approximateKolmogorovComplexity value).val.toNat ≤ UInt32.size - 1 := by
exact Nat.le_pred_of_lt (UInt32.toNat_lt_size _)
/-- Representation-level non-negativity for information density. -/
theorem informationDensityNonNegative (entropy value : Q16_16) :
(computeInformationDensity entropy value).val.toNat ≥ 0 := by
exact Nat.zero_le _
/--
Compressibility remains inside the UInt32 carrier.
The stronger `[0, 1]` semantic bound is false without hypotheses such as
`entropy ≤ maxEntropy`; Q16_16 subtraction wraps at the representation layer.
-/
theorem compressibilityBounded (entropy maxEntropy : Q16_16) :
(computeCompressibility entropy maxEntropy).val.toNat ≤ UInt32.size - 1 := by
exact Nat.le_pred_of_lt (UInt32.toNat_lt_size _)
/--
Classification is exhaustive (every mass number gets a class).
SME-anchored: The entropy thresholds partition the entropy range.
-/
theorem classificationExhaustive (mass : InformationMass) :
let classification := classifyMassNumber mass
match classification with
| .lowInformation => True
| .mediumInformation => True
| .highInformation => True := by
dsimp
cases classifyMassNumber mass <;> trivial
end Semantics.MassNumberAdapter