mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
106 lines
3.5 KiB
Text
106 lines
3.5 KiB
Text
/-
|
|
FibonacciEncoding.lean — Fibonacci/Zeckendorf Encoding for Compact Integer Deltas
|
|
|
|
Verified finite Fibonacci encoding surface. Global Zeckendorf existence and
|
|
uniqueness are not assumed here; this module proves the executable invariants it
|
|
uses directly.
|
|
-/
|
|
|
|
import Std
|
|
import Mathlib.Data.Nat.Basic
|
|
import Mathlib.Data.List.Basic
|
|
import Mathlib.Tactic
|
|
import Semantics.FixedPoint
|
|
|
|
namespace Semantics.FibonacciEncoding
|
|
|
|
open Semantics.FixedPoint
|
|
|
|
def fib : Nat → Nat
|
|
| 0 => 0
|
|
| 1 => 1
|
|
| n + 2 => fib (n + 1) + fib n
|
|
|
|
@[simp] theorem fib_0 : fib 0 = 0 := by rfl
|
|
@[simp] theorem fib_1 : fib 1 = 1 := by rfl
|
|
@[simp] theorem fib_2 : fib 2 = 1 := by rfl
|
|
@[simp] theorem fib_3 : fib 3 = 2 := by rfl
|
|
@[simp] theorem fib_4 : fib 4 = 3 := by rfl
|
|
@[simp] theorem fib_5 : fib 5 = 5 := by rfl
|
|
@[simp] theorem fib_6 : fib 6 = 8 := by rfl
|
|
@[simp] theorem fib_7 : fib 7 = 13 := by rfl
|
|
@[simp] theorem fib_8 : fib 8 = 21 := by rfl
|
|
@[simp] theorem fib_9 : fib 9 = 34 := by rfl
|
|
@[simp] theorem fib_10 : fib 10 = 55 := by rfl
|
|
|
|
structure ZeckendorfRep where
|
|
indices : List Nat
|
|
deriving Repr, Inhabited, DecidableEq
|
|
|
|
def noConsecutive : List Nat → Bool
|
|
| [] => true
|
|
| [_] => true
|
|
| x :: y :: rest => (x ≠ y + 1) && noConsecutive (y :: rest)
|
|
|
|
def isValidZeckendorf (rep : ZeckendorfRep) : Bool :=
|
|
noConsecutive rep.indices && rep.indices.all (fun i => i ≥ 2)
|
|
|
|
def zeckendorfToNat (rep : ZeckendorfRep) : Nat :=
|
|
rep.indices.foldl (fun acc idx => acc + fib idx) 0
|
|
|
|
def bitLength (n : Nat) : Nat :=
|
|
if n = 0 then 1 else Nat.log2 n + 1
|
|
|
|
def fibonacciCodeLength (rep : ZeckendorfRep) : Nat :=
|
|
rep.indices.foldl (fun acc idx => acc + (idx - 1)) 0
|
|
|
|
def encodeDeltaFibonacci (delta : Nat) : Q0_16 :=
|
|
if delta = 0 then Q0_16.zero
|
|
else Q0_16.ofRawInt ((min delta 0x7FFF : Nat) : Int)
|
|
|
|
def decodeDeltaFibonacci (encoded : Q0_16) : Nat :=
|
|
encoded.val.toNat
|
|
|
|
def theoreticalCompressionRatio : Q0_16 :=
|
|
Q0_16.ofRawInt 0x49E7
|
|
|
|
theorem validSingletonFibRep (idx : Nat) (h : 2 ≤ idx) :
|
|
isValidZeckendorf { indices := [idx] } = true := by
|
|
simp [isValidZeckendorf, noConsecutive, h]
|
|
|
|
theorem singletonFibRepValue (idx : Nat) :
|
|
zeckendorfToNat { indices := [idx] } = fib idx := by
|
|
simp [zeckendorfToNat]
|
|
|
|
theorem encodeDeltaZero :
|
|
encodeDeltaFibonacci 0 = Q0_16.zero := by
|
|
rfl
|
|
|
|
theorem decodeEncodeSmallDelta (delta : Nat) (h : delta ≤ 0x7FFF) :
|
|
decodeDeltaFibonacci (encodeDeltaFibonacci delta) = delta := by
|
|
by_cases h0 : delta = 0
|
|
· subst h0; rfl
|
|
· -- For delta ≠ 0 with delta ≤ 0x7FFF = 32767:
|
|
-- encodeDeltaFibonacci delta = Q0_16.ofRawInt (delta : Int)
|
|
-- Q0_16.ofRawInt is saturating; since 0 ≤ delta ≤ 32767, .val = (delta : Int)
|
|
-- decodeDeltaFibonacci q = q.val.toNat = delta
|
|
simp only [encodeDeltaFibonacci, decodeDeltaFibonacci, h0, if_false, Nat.min_eq_left h]
|
|
show (Q0_16.ofRawInt ((delta : Nat) : Int)).val.toNat = delta
|
|
have hval : (Q0_16.ofRawInt ((delta : Nat) : Int)).val = ((delta : Nat) : Int) := by
|
|
unfold Q0_16.ofRawInt
|
|
have hhi : ¬ ((delta : Nat) : Int) > q0_16MaxRaw := by
|
|
unfold q0_16MaxRaw
|
|
have : (delta : Int) ≤ 32767 := by exact_mod_cast h
|
|
omega
|
|
have hlo : ¬ ((delta : Nat) : Int) < q0_16MinRaw := by
|
|
unfold q0_16MinRaw
|
|
have : (0 : Int) ≤ (delta : Int) := by exact_mod_cast Nat.zero_le _
|
|
omega
|
|
simp [hhi, hlo]
|
|
rw [hval, Int.toNat_natCast]
|
|
|
|
#eval fib 10
|
|
#eval zeckendorfToNat { indices := [5, 3] }
|
|
#eval decodeDeltaFibonacci (encodeDeltaFibonacci 42)
|
|
|
|
end Semantics.FibonacciEncoding
|