Research-Stack/5-Applications/scripts/convert_equations_to_phinary.py

155 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
Convert Research Stack equation IDs to Phinary (Zeckendorf) representation.
Adapted from MOIM's phinary number system for equation indexing.
"""
import csv
from pathlib import Path
from typing import List, Tuple
def fib(n: int) -> int:
"""Compute nth Fibonacci number."""
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
def find_largest_fib(n: int) -> int:
"""Find largest k such that fib(k+2) <= n."""
k = 0
while fib(k + 2) <= n:
k += 1
return k - 1
def nat_to_zeckendorf(n: int) -> List[int]:
"""Convert natural number to Zeckendorf representation (list of 0s and 1s)."""
if n == 0:
return [0]
result = []
remaining = n
while remaining > 0:
k = find_largest_fib(remaining)
# Pad with zeros to reach position k
while len(result) <= k:
result.append(0)
result[k] = 1
remaining -= fib(k + 2)
return result
def zeckendorf_to_nat(digits: List[int]) -> int:
"""Convert Zeckendorf digits back to natural number."""
result = 0
for idx, digit in enumerate(digits):
result += digit * fib(idx + 2)
return result
def valid_phinary_digits(digits: List[int]) -> bool:
"""Check if phinary digits satisfy Zeckendorf constraint (no adjacent 1s)."""
for i in range(len(digits) - 1):
if digits[i] == 1 and digits[i + 1] == 1:
return False
return True
def phinary_to_string(digits: List[int]) -> str:
"""Convert phinary digits to string representation."""
return ''.join(str(d) for d in digits)
def equation_id_to_phinary(eq_id: int) -> Tuple[str, bool]:
"""Convert equation ID to phinary string representation."""
digits = nat_to_zeckendorf(eq_id)
valid = valid_phinary_digits(digits)
return phinary_to_string(digits), valid
def process_math_model_map(input_path: str, output_path: str):
"""Process MATH_MODEL_MAP.tsv and add phinary representation."""
with open(input_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
# Find start of actual data (skip comment lines)
start_idx = 0
for i, line in enumerate(lines):
if line.startswith('1\t') or line.startswith('#\t'):
start_idx = i
break
# Read header and data
reader = csv.DictReader(lines[start_idx:], delimiter='\t')
fieldnames = reader.fieldnames
# Clean fieldnames (remove None values)
fieldnames = [f for f in fieldnames if f is not None]
# Add phinary column
new_fieldnames = fieldnames + ['Phinary_ID', 'Phinary_Valid']
with open(output_path, 'w', encoding='utf-8') as out:
writer = csv.DictWriter(out, fieldnames=new_fieldnames, delimiter='\t')
writer.writeheader()
for row in reader:
# Clean row dict (remove None keys)
clean_row = {k: v for k, v in row.items() if k is not None}
# Get equation ID
eq_id_str = clean_row.get('#', clean_row.get('ID', '0'))
try:
eq_id = int(eq_id_str)
except (ValueError, TypeError):
eq_id = 0
# Convert to phinary
phinary_str, valid = equation_id_to_phinary(eq_id)
# Add new columns
clean_row['Phinary_ID'] = phinary_str
clean_row['Phinary_Valid'] = 'TRUE' if valid else 'FALSE'
writer.writerow(clean_row)
print(f"✅ Converted equations to phinary representation")
print(f" Input: {input_path}")
print(f" Output: {output_path}")
def analyze_phinary_distribution(input_path: str):
"""Analyze distribution of phinary representations."""
phinary_lengths = {}
valid_count = 0
invalid_count = 0
with open(input_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f, delimiter='\t')
for row in reader:
phinary_id = row.get('Phinary_ID', '')
is_valid = row.get('Phinary_Valid', 'FALSE') == 'TRUE'
length = len(phinary_id)
phinary_lengths[length] = phinary_lengths.get(length, 0) + 1
if is_valid:
valid_count += 1
else:
invalid_count += 1
print(f"\n📊 Phinary Distribution Analysis:")
print(f" Total equations: {valid_count + invalid_count}")
print(f" Valid phinary: {valid_count}")
print(f" Invalid phinary: {invalid_count}")
print(f"\n Length distribution:")
for length in sorted(phinary_lengths.keys()):
print(f" {length} digits: {phinary_lengths[length]} equations")
if __name__ == "__main__":
base_path = Path(__file__).resolve().parent.parent.parent
input_path = base_path / "3-Mathematical-Models" / "MATH_MODEL_MAP.tsv"
output_path = base_path / "3-Mathematical-Models" / "MATH_MODEL_MAP_phinary.tsv"
print("🔄 Converting equation IDs to phinary representation...")
process_math_model_map(str(input_path), str(output_path))
analyze_phinary_distribution(str(output_path))