mirror of
https://github.com/saymrwulf/ltl-accumulator-verified.git
synced 2026-09-04 20:03:44 +00:00
107 lines
3.5 KiB
Python
107 lines
3.5 KiB
Python
|
|
"""Line-faithful Python transliteration of the LEAN definitions in
|
|||
|
|
Proofs/Basic.lean and Proofs/Completeness.lean (commit-current forms,
|
|||
|
|
including the decidable-if ConsRec base and the recursive kbelow).
|
|||
|
|
|
|||
|
|
Each function quotes its Lean source. The fidelity harness
|
|||
|
|
(run_fidelity.py) differential-tests these against the DEPLOYED pacta
|
|||
|
|
verifiers; any transliteration drift is caught by the exhaustive run,
|
|||
|
|
any Lean-vs-deployed drift is the finding the harness exists for.
|
|||
|
|
"""
|
|||
|
|
import hashlib
|
|||
|
|
|
|||
|
|
|
|||
|
|
def sha256(b: bytes) -> bytes:
|
|||
|
|
return hashlib.sha256(b).digest()
|
|||
|
|
|
|||
|
|
|
|||
|
|
def hleaf(d: bytes) -> bytes:
|
|||
|
|
# Lean: hleaf d = sha256 (0x00 :: d)
|
|||
|
|
return sha256(b"\x00" + d)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def hnode(x: bytes, y: bytes) -> bytes:
|
|||
|
|
# Lean: hnode x y = sha256 (0x01 :: (x.val ++ y.val))
|
|||
|
|
return sha256(b"\x01" + x + y)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def kbelow(n: int) -> int:
|
|||
|
|
# Lean: if n ≤ 2 then 1 else 2 * kbelow ((n + 1) / 2)
|
|||
|
|
if n <= 2:
|
|||
|
|
return 1
|
|||
|
|
return 2 * kbelow((n + 1) // 2)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def MTH(D: list) -> bytes:
|
|||
|
|
# Lean: if length = 0 then sha256 [] ; if length = 1 then hleaf (headD [])
|
|||
|
|
# else hnode (MTH (take k)) (MTH (drop k)), k = kbelow length
|
|||
|
|
if len(D) == 0:
|
|||
|
|
return sha256(b"")
|
|||
|
|
if len(D) == 1:
|
|||
|
|
return hleaf(D[0])
|
|||
|
|
k = kbelow(len(D))
|
|||
|
|
return hnode(MTH(D[:k]), MTH(D[k:]))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def Path(m: int, D: list) -> list:
|
|||
|
|
# Lean: if length ≤ 1 then [] else (m<k: Path m take ++ [MTH drop]
|
|||
|
|
# | else: Path (m-k) drop ++ [MTH take])
|
|||
|
|
if len(D) <= 1:
|
|||
|
|
return []
|
|||
|
|
k = kbelow(len(D))
|
|||
|
|
if m < k:
|
|||
|
|
return Path(m, D[:k]) + [MTH(D[k:])]
|
|||
|
|
return Path(m - k, D[k:]) + [MTH(D[:k])]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def Root(v: bytes, m: int, n: int, P: list):
|
|||
|
|
# Lean: n=1: (if P = [] then some v else none); n=0: none;
|
|||
|
|
# P.getLast? none: none; m<k: (Root v m k P').map (hnode · s)
|
|||
|
|
# else (Root v (m-k) (n-k) P').map (hnode s ·)
|
|||
|
|
if n == 1:
|
|||
|
|
return v if P == [] else None
|
|||
|
|
if n == 0:
|
|||
|
|
return None
|
|||
|
|
if P == []:
|
|||
|
|
return None
|
|||
|
|
s = P[-1]
|
|||
|
|
k = kbelow(n)
|
|||
|
|
if m < k:
|
|||
|
|
x = Root(v, m, k, P[:-1])
|
|||
|
|
return None if x is None else hnode(x, s)
|
|||
|
|
x = Root(v, m - k, n - k, P[:-1])
|
|||
|
|
return None if x is None else hnode(s, x)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def ConsRec(n0: int, n: int, C: list, b: bool, r: bytes):
|
|||
|
|
# Lean (post-refactor, machine-verified equivalent to the original):
|
|||
|
|
# n0=n: b: (if C = [] then some (r,r) else none)
|
|||
|
|
# ¬b: (if C.length = 1 then some (getLastD, getLastD) else none)
|
|||
|
|
# n0>n ∨ n0=0 ∨ n≤1: none ; getLast? none: none
|
|||
|
|
# n0≤k: sub.map (fun (x,y) => (x, hnode y s))
|
|||
|
|
# else: sub(false).map (fun (x,y) => (hnode s x, hnode s y))
|
|||
|
|
if n0 == n:
|
|||
|
|
if b:
|
|||
|
|
return (r, r) if C == [] else None
|
|||
|
|
return (C[-1], C[-1]) if len(C) == 1 else None
|
|||
|
|
if n0 > n or n0 == 0 or n <= 1:
|
|||
|
|
return None
|
|||
|
|
if C == []:
|
|||
|
|
return None
|
|||
|
|
s = C[-1]
|
|||
|
|
k = kbelow(n)
|
|||
|
|
if n0 <= k:
|
|||
|
|
sub = ConsRec(n0, k, C[:-1], b, r)
|
|||
|
|
return None if sub is None else (sub[0], hnode(sub[1], s))
|
|||
|
|
sub = ConsRec(n0 - k, n - k, C[:-1], False, r)
|
|||
|
|
return None if sub is None else (hnode(s, sub[0]), hnode(s, sub[1]))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def accept_incl(d: bytes, m: int, n: int, P: list, root: bytes) -> bool:
|
|||
|
|
# Lean acceptance: m < n ∧ Root (hleaf d) m n P = some root
|
|||
|
|
return m < n and Root(hleaf(d), m, n, P) == root
|
|||
|
|
|
|||
|
|
|
|||
|
|
def accept_cons(n0: int, n1: int, r0: bytes, r1: bytes, C: list) -> bool:
|
|||
|
|
# Lean acceptCons: n0 = 0 ∨ ConsRec n0 n1 C true r0 = some (r0, r1)
|
|||
|
|
return n0 == 0 or ConsRec(n0, n1, C, True, r0) == (r0, r1)
|