/- 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 DiffusionSNRBias.lean — SNR-t Bias Correction for Diffusion Probabilistic Models This module formalizes the SNR-t bias phenomenon and differential correction method from "Elucidating the SNR-t Bias of Diffusion Probabilistic Models" (arXiv:2604.16044, 2026). Key contributions from the paper: 1. SNR-t Bias: The actual SNR of predicted samples xHat_t in reverse process is always lower than that of perturbed sample x_t in forward process. 2. Differential Correction: Uses differential signal Δ_t = xHat_{t-1} - xTheta^0(xHat_t, t) to guide denoising toward ideal perturbed samples. 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: alphaXiv.org/abs/2604.16044 -/ import Mathlib.Data.Nat.Basic import Mathlib.Data.Real.Basic import Mathlib.Data.Fin.Basic namespace Semantics.DiffusionSNRBias -- ════════════════════════════════════════════════════════════ -- §0 Fixed-Point Precision (Q16.16 for diffusion scores) -- ════════════════════════════════════════════════════════════ /-- Q16.16 fixed-point for SNR 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 epsilon : Q1616 := ⟨1⟩ -- 2^{-16} def ofNat (n : Nat) : Q1616 := ⟨n * 65536⟩ -- Integer to Q16.16 def toFloat (q : Q1616) : Float := (Float.ofInt q.raw) / 65536.0 def add (a b : Q1616) : Q1616 := ⟨a.raw + b.raw⟩ def sub (a b : Q1616) : Q1616 := ⟨a.raw - b.raw⟩ def mul (a b : Q1616) : Q1616 := ⟨(a.raw * b.raw) / 65536⟩ def div (a b : Q1616) : Q1616 := ⟨(a.raw * 65536) / b.raw⟩ instance : Add Q1616 := ⟨add⟩ instance : Sub Q1616 := ⟨sub⟩ instance : Mul Q1616 := ⟨mul⟩ instance : Div Q1616 := ⟨div⟩ 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⟩ /-- Square root via Newton-Raphson (seeded). -/ def sqrt (x : Q1616) : Q1616 := if x.raw ≤ 0 then zero else -- 3 iterations of Newton-Raphson let seed := ⟨65536⟩ -- Initial guess = 1.0 let iter1 := (seed + x / seed) / ofNat 2 let iter2 := (iter1 + x / iter1) / ofNat 2 let iter3 := (iter2 + x / iter2) / ofNat 2 iter3 /-- Clip value to [lo, hi] range. -/ def clip (x lo hi : Q1616) : Q1616 := if x < lo then lo else if x > hi then hi else x end Q1616 -- ════════════════════════════════════════════════════════════ -- §1 Diffusion Process Definitions -- ════════════════════════════════════════════════════════════ /-- Timestep in diffusion process (T down to 0). -/ abbrev Timestep := Nat /-- Image/tensor dimensions (H × W × C). -/ structure ImageShape where height : Nat width : Nat channels : Nat deriving Repr, Inhabited /-- Noised sample x_t at timestep t. -/ structure PerturbedSample (shape : ImageShape) where data : Array Q1616 -- Flattened tensor timestep : Timestep wf : data.size = shape.height * shape.width * shape.channels deriving Repr /-- Predicted sample xHat_t from reverse process. -/ structure PredictedSample (shape : ImageShape) where data : Array Q1616 timestep : Timestep wf : data.size = shape.height * shape.width * shape.channels deriving Repr /-- Reconstructed sample xTheta^0(x_t, t) = predicted x_0. -/ structure ReconstructedSample (shape : ImageShape) where data : Array Q1616 timestep : Timestep wf : data.size = shape.height * shape.width * shape.channels deriving Repr /-- Noise prediction ε_θ(x_t, t). -/ structure NoisePrediction (shape : ImageShape) where data : Array Q1616 timestep : Timestep wf : data.size = shape.height * shape.width * shape.channels deriving Repr -- ════════════════════════════════════════════════════════════ -- §2 Signal-to-Noise Ratio (SNR) Computation -- ════════════════════════════════════════════════════════════ /-- Compute mean squared norm ||x||²_2. -/ def meanSquaredNorm (x : Array Q1616) : Q1616 := let sqSum := x.foldl (fun acc v => acc + (v * v)) Q1616.zero sqSum / Q1616.ofNat x.size /-- SNR of a sample: ratio of signal power to noise power. For diffusion: SNR(t) ≈ α_t² / σ_t² -/ structure SNR where value : Q1616 -- Signal-to-noise ratio logSNR : Q1616 -- log(SNR) for stability deriving Repr, Inhabited namespace SNR /-- Compute SNR from mean squared norms. -/ def fromSignalNoise (signal : Q1616) (noise : Q1616) : SNR := let snr := if noise.raw = 0 then Q1616.ofNat 1000 else signal / noise { value := snr logSNR := Q1616.ofNat 0 } -- Placeholder for log /-- Compare SNR values (paper finding: SNR_reverse < SNR_forward). -/ def lessThan (a b : SNR) : Bool := a.value < b.value instance : LT SNR := ⟨fun a b => a.value < b.value⟩ end SNR -- ════════════════════════════════════════════════════════════ -- §3 SNR-t Bias Phenomenon (Paper Section 4) -- ════════════════════════════════════════════════════════════ /-- SNR-t Bias: The mismatch between predicted sample SNR and timestep SNR. Paper Key Finding 1: The network produces significantly inaccurate predictions when processing samples with mismatched SNR and timesteps. Key Finding 2: The actual SNR of xHat_t in reverse process is always lower than x_t at the same timestep t in forward process. -/ structure SNRTBias (shape : ImageShape) where -- Forward perturbed sample at timestep t forwardSample : PerturbedSample shape -- Reverse predicted sample at same timestep t reverseSample : PredictedSample shape -- SNR values forwardSNR : SNR reverseSNR : SNR -- Bias indicator: reverseSNR.value < forwardSNR.value biasExists : Bool deriving Repr namespace SNRTBias /-- Detect if SNR-t bias exists (paper's experimental finding). -/ def detectBias {shape : ImageShape} (x_t : PerturbedSample shape) (xHat_t : PredictedSample shape) : SNRTBias shape := let signalFwd := meanSquaredNorm x_t.data let signalRev := meanSquaredNorm xHat_t.data let snrFwd := SNR.fromSignalNoise signalFwd (Q1616.ofNat 1) let snrRev := SNR.fromSignalNoise signalRev (Q1616.ofNat 1) { forwardSample := x_t reverseSample := xHat_t forwardSNR := snrFwd reverseSNR := snrRev biasExists := SNR.lessThan snrRev snrFwd } /-- Axiom: SNR-t bias always exists (paper's theoretical result, Assumption 5.1). The actual SNR of xHat_t is always lower than SNR of x_t at same t. This is an axiom because it depends on the information-loss bound from Assumption 5.1: ‖x̂θ⁰(x_t,t)‖² ≤ ‖x_t‖² — a property of the trained denoising network, not derivable from the algebraic structure alone. See: arXiv:2604.16044, Section 4, Key Finding 2. -/ axiom snrBiasAlwaysExists {shape : ImageShape} (bias : SNRTBias shape) (hValid : bias.forwardSample.timestep = bias.reverseSample.timestep) : bias.biasExists = true end SNRTBias -- ════════════════════════════════════════════════════════════ -- §4 Differential Correction Method (Paper Section 5.2) -- ════════════════════════════════════════════════════════════ /-- Differential signal Δ_t = xHat_{t-1} - xTheta^0(xHat_t, t) This signal contains directional information pointing toward x_{t-1}. Paper Eq. 16: Contains gradient toward ideal perturbed sample. -/ def differentialSignal {shape : ImageShape} (xHat_t_minus_1 : PredictedSample shape) (xTheta0 : ReconstructedSample shape) : Array Q1616 := -- Element-wise subtraction: xHat_{t-1} - xTheta^0(xHat_t, t) Array.zipWith (fun a b => a - b) xHat_t_minus_1.data xTheta0.data /-- Differential correction with guidance factor λ_t. Paper Eq. 17: xHat_{t-1}^{corrected} = xHat_{t-1} + λ_t · Δ_t where λ_t adjusts magnitude of differential signal effect. -/ def differentialCorrection {shape : ImageShape} (xHat_t_minus_1 : PredictedSample shape) (xTheta0 : ReconstructedSample shape) (lambda_t : Q1616) -- Guidance factor (hyperparameter) : PredictedSample shape := let delta := differentialSignal xHat_t_minus_1 xTheta0 let correction := delta.map (fun d => lambda_t * d) let corrected := Array.zipWith (fun a c => a + c) xHat_t_minus_1.data correction { data := corrected timestep := xHat_t_minus_1.timestep wf := by have hShape : xHat_t_minus_1.data.size = xTheta0.data.size := by rw [xHat_t_minus_1.wf, xTheta0.wf] have h1 : (Array.zipWith (fun a b => a - b) xHat_t_minus_1.data xTheta0.data).size = xHat_t_minus_1.data.size := by rw [Array.size_zipWith] rw [hShape] simp have h2 : (Array.map (fun d => lambda_t * d) (Array.zipWith (fun a b => a - b) xHat_t_minus_1.data xTheta0.data)).size = xHat_t_minus_1.data.size := by rw [Array.size_map] exact h1 have h3 : (Array.zipWith (fun a c => a + c) xHat_t_minus_1.data (Array.map (fun d => lambda_t * d) (Array.zipWith (fun a b => a - b) xHat_t_minus_1.data xTheta0.data))).size = xHat_t_minus_1.data.size := by rw [Array.size_zipWith] rw [h2] simp exact h3.trans xHat_t_minus_1.wf } /-- Guidance factor strategy (paper Section 6.4 / Appendix D). -/ structure GuidanceStrategy (shape : ImageShape) where -- Linear schedule: λ_t decreases over timesteps linearSchedule : Timestep → Q1616 -- Constant guidance: λ_t = λ for all t constantValue : Q1616 -- Adaptive: based on estimated SNR mismatch adaptive : SNRTBias shape → Q1616 instance : Repr (GuidanceStrategy shape) where reprPrec _ _ := "" namespace GuidanceStrategy /-- Default linear schedule: λ_t = λ_max · (1 - t/T). -/ def defaultLinear (shape : ImageShape) (maxLambda : Q1616) (totalSteps : Timestep) : GuidanceStrategy shape := { linearSchedule := fun t => maxLambda * Q1616.ofNat (totalSteps - t) / Q1616.ofNat totalSteps constantValue := maxLambda adaptive := fun _ => maxLambda } end GuidanceStrategy -- ════════════════════════════════════════════════════════════ -- §5 Assumption 5.1: Reconstruction Model (Paper Section 5.1) -- ════════════════════════════════════════════════════════════ /-- Paper Assumption 5.1: Reconstruction model formulation. xTheta^0(x_t, t) = γ_t · x_0 + φ_t · ε_t where: - 0 < γ_t ≤ 1 (energy/information loss during reconstruction) - φ_t < M (bounded noise coefficient) - ε_t ~ N(0, I) -/ structure ReconstructionModel where gamma_t : Q1616 -- Data preservation coefficient (0 < γ_t ≤ 1) phi_t : Q1616 -- Noise coefficient (bounded) wf_gamma : gamma_t.raw > 0 ∧ gamma_t.raw ≤ 65536 wf_phi : phi_t.raw < 6553600 -- Some large bound M deriving Repr namespace ReconstructionModel /-- Energy conservation check: ||xTheta^0||² ≤ ||x_0||² + φ_t². -/ def energyConservation (model : ReconstructionModel) (x0_norm : Q1616) : Bool := -- Variance identity: E[||x||²] = ||x̄||² + Var(||x||) -- Non-negativity of variance implies energy constraint model.gamma_t ≤ Q1616.one /-- Axiom 5.1: SNR of biased sample xHat_t is no higher than x_t. Paper Eq. 12: SNR(xHat_t) = γ̂_t² / (φ_{t+1}² + ψ_{t-1}²) where γ̂_t = γ_{t+1} · ψ_{t-1}. Axiom because the inequality depends on: (1) γ̂_t² ≤ γ_t (information loss bound from Assumption 5.1 — a property of the trained denoising network) (2) φ_t² + ψ_{t-1}² ≥ 1 (noise denominator is at least unit scale — physical constraint on the noise schedule) (3) The division is monotone in numerator. These are theoretical results from the paper, not derivable from the Q16.16 algebraic structure alone. See: arXiv:2604.16044, Section 5.1, Eq. 12. -/ axiom snrOfBiasedSample (model : ReconstructionModel) (gamma_hat : Q1616) (psi_t_minus_1 : Q1616) (h_gamma_bound : gamma_hat.raw ≤ model.gamma_t.raw) (h_denom_nonzero : (model.phi_t * model.phi_t + psi_t_minus_1 * psi_t_minus_1).raw ≠ 0) (h_snr_mono : ∀ (n1 n2 d : Q1616), n1.raw ≤ n2.raw → (SNR.fromSignalNoise n1 d).value.raw ≤ (SNR.fromSignalNoise n2 d).value.raw) : let numerator := gamma_hat * gamma_hat let denominator := model.phi_t * model.phi_t + psi_t_minus_1 * psi_t_minus_1 ¬ (SNR.fromSignalNoise model.gamma_t Q1616.one < SNR.fromSignalNoise numerator denominator) end ReconstructionModel -- ════════════════════════════════════════════════════════════ -- §6 Correction Verification Metrics -- ════════════════════════════════════════════════════════════ /-- Correction effectiveness metrics. -/ structure CorrectionMetrics where -- SNR improvement after correction snrImprovement : Q1616 -- Noise prediction accuracy: ||ε_θ(xHat_t, t) - ε_t|| noiseAccuracy : Q1616 -- Sample quality: reduced artifacts / improved coherence qualityScore : Q1616 deriving Repr, Inhabited /-- Evaluate correction effectiveness. -/ def evaluateCorrection {shape : ImageShape} (before : PredictedSample shape) (after : PredictedSample shape) (target : PerturbedSample shape) : CorrectionMetrics := let snrBefore := meanSquaredNorm before.data let snrAfter := meanSquaredNorm after.data let snrTarget := meanSquaredNorm target.data { snrImprovement := snrAfter - snrBefore noiseAccuracy := snrTarget - snrAfter -- Distance to ideal qualityScore := Q1616.ofNat 0 } -- Placeholder for perceptual metric -- ════════════════════════════════════════════════════════════ -- §7 Integration with Ordered Field Tokens -- ════════════════════════════════════════════════════════════ /-- Token for diffusion correction in OrderedFieldTokens framework. -/ inductive DiffusionToken (shape : ImageShape) | applyDifferentialCorrection (t : Timestep) (lambda : Q1616) | estimateSNRBias (t : Timestep) | correctWithGuidance (strategy : GuidanceStrategy shape) deriving Repr -- ════════════════════════════════════════════════════════════ -- §8 Verification Examples (AGENTS.md §4 requirement) -- ════════════════════════════════════════════════════════════ #eval Q1616.ofNat 100 -- 100.0 in Q16.16 #eval Q1616.sqrt (Q1616.ofNat 4) -- ~2.0 in Q16.16 #eval GuidanceStrategy.defaultLinear { height := 1, width := 1, channels := 1 } (Q1616.ofNat 1) 1000 -- Linear schedule from 1.0 down to 0.0 over 1000 steps end Semantics.DiffusionSNRBias