SilverSight/scripts/decompress_equations.py
allaun 85141a4b94 feat(nuvmap,braid): NUVMAP port + Rossby/Kelvin braid correspondence
- Port NUVMAP projection engine from Research Stack to SilverSight
  with Q16_16 fixed-point (zero Float) and CBOR serialization
- Add Rotational Wave — Braid Correspondence formalization at boundary
  (ChiralLabel, RossbyDrift, rossby_convergence_bound stubbed,
   kelvin_wave_eigensolid proven)
- Add auto-pipeline CI workflow, webhook receiver, Forgejo MCP server
- Add SOPS/Age encryption config
- Add stack compose for portable deployment
- Add rotational wave design doc
2026-06-30 16:38:11 -05:00

160 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""Decompress the BWT+MTF+LZW equation database files."""
import json, struct, sys
from pathlib import Path
def lzw_decode(data: bytes, max_dict: int = 4096) -> list[int]:
"""Decode LZW-compressed data into a list of integers."""
result = []
if not data:
return result
dict_size = 256
dictionary = {i: bytes([i]) for i in range(dict_size)}
# Read 12-bit values regardless of max_dict
bits = []
for byte in data:
bits.extend([(byte >> (7 - i)) & 1 for i in range(8)])
pos = 0
def read_bits(n):
nonlocal pos
val = 0
for _ in range(n):
val = (val << 1) | bits[pos]
pos += 1
return val
code_bits = 9
prev = read_bits(code_bits)
result.append(prev)
prev_bytes = dictionary[prev]
while pos < len(bits):
code = read_bits(code_bits)
if code in dictionary:
entry = dictionary[code]
elif code == dict_size:
entry = prev_bytes + prev_bytes[:1]
else:
break
result.extend(entry)
dictionary[dict_size] = prev_bytes + entry[:1]
dict_size += 1
if dict_size >= (1 << code_bits) and code_bits < 12:
code_bits += 1
prev_bytes = entry
return result
def mtf_decode(data: list[int]) -> list[int]:
"""Move-to-front decoding."""
alphabet = list(range(256))
result = []
for code in data:
if code < len(alphabet):
val = alphabet[code]
result.append(val)
alphabet.pop(code)
alphabet.insert(0, val)
return result
def bwt_inverse(data: list[int], primary_index: int) -> bytes:
"""Inverse Burrows-Wheeler transform."""
if not data:
return b''
n = len(data)
# Count occurrences
counts = [0] * 256
for b in data:
counts[b] += 1
# Compute cumulative counts (start positions)
start = [0] * 256
total = 0
for i in range(256):
start[i] = total
total += counts[i]
# Build next array
next_idx = [0] * n
temp_count = [0] * 256
for i in range(n):
b = data[i]
next_idx[i] = start[b] + temp_count[b]
temp_count[b] += 1
# Reconstruct
result = bytearray()
idx = primary_index
for _ in range(n):
idx = next_idx[idx]
result.append(data[idx])
return bytes(result)
def decompress(path: Path) -> dict:
"""Decompress an equation database file."""
raw = path.read_bytes()
# Read header
offset = 0
header_len = struct.unpack('>I', raw[offset:offset+4])[0]
offset += 4
header = json.loads(raw[offset:offset+header_len].decode())
offset += header_len
chain = header.get("chain", ["bwt", "mtf", "lzw"])
meta = header.get("metadata", {})
compressed = raw[offset:]
# Apply decompression steps in reverse order
data = compressed
# Step 1: LZW decode
lzw_meta = meta.get("lzw", {})
integers = lzw_decode(data, lzw_meta.get("max_dict", 4096))
# Step 2: MTF decode
integers = mtf_decode(integers)
# Step 3: BWT inverse
bwt_meta = meta.get("bwt", {})
primary = bwt_meta.get("primary_index", 0)
raw_bytes = bwt_inverse(integers, primary)
# Parse as JSON
return json.loads(raw_bytes.decode("utf-8"))
def main():
path = Path(sys.argv[1]) if len(sys.argv) > 1 else \
"/home/allaun/Research Stack/3-Mathematical-Models/equations_compressed/chain_equations_20260504_134248.compressed"
print(f"Decompressing {path}...")
data = decompress(path)
if isinstance(data, dict):
print(f"Type: dict with {len(data)} keys")
for k, v in data.items():
if isinstance(v, list):
print(f" {k}: list[{len(v)}]")
if len(v) > 0:
print(f" first: {str(v[0])[:200]}")
elif isinstance(v, dict):
print(f" {k}: dict with {len(v)} keys")
else:
print(f" {k}: {type(v).__name__} = {str(v)[:200]}")
elif isinstance(data, list):
print(f"Type: list[{len(data)}]")
if len(data) > 0:
print(f" first: {str(data[0])[:200]}")
if __name__ == "__main__":
main()