#!/usr/bin/env python3 """ sidon_address.py — Sidon Address Assignment from Spectral Profile Maps an 8D spectral profile to a Sidon address from the set {1, 2, 4, 8, 16, 32, 64, 128}. These are the 8 powers of 2, forming a Sidon set (B_2 sequence): all pairwise sums a_i + a_j (i ≤ j) are distinct. This guarantees collision-free addressing. """ import hashlib from typing import List # ── Sidon Set ──────────────────────────────────────────────────────────── SIDON_ADDRESSES = [1, 2, 4, 8, 16, 32, 64, 128] _ADDRESS_TO_STRAND = {addr: i for i, addr in enumerate(SIDON_ADDRESSES)} _STRAND_TO_ADDRESS = {i: addr for i, addr in enumerate(SIDON_ADDRESSES)} # Verify Sidon property at module load _SIDON_SUMS = {} for i, a in enumerate(SIDON_ADDRESSES): for j, b in enumerate(SIDON_ADDRESSES): if i <= j: s = a + b if s in _SIDON_SUMS: raise RuntimeError(f"Sidon VIOLATED: {a}+{b}={s}") _SIDON_SUMS[s] = (a, b) def verify_sidon_property() -> bool: seen = set() for i, a in enumerate(SIDON_ADDRESSES): for j, b in enumerate(SIDON_ADDRESSES): if i <= j: s = a + b if s in seen: return False seen.add(s) return True def spectral_to_sidon_address(spectral_profile: List[float], hash_val: int = 0) -> List[int]: """Map 8D spectral profile to ordered Sidon address list. Uses the spectral profile weighted by a deterministic hash to select the primary strand. The hash ensures different equations map to different strands even when their spectral profiles are similar. Args: spectral_profile: 8D profile from compute_spectral_profile() hash_val: Optional integer hash for diversity (default 0) Returns: Ordered list of 8 Sidon addresses, primary first """ if len(spectral_profile) != 8: raise ValueError(f"Expected 8D profile, got {len(spectral_profile)}D") # Blend profile with hash-derived scores for diversity scores = [] for i in range(8): profile_score = spectral_profile[i] # Hash contribution: deterministic but different per equation hash_score = ((hash_val >> (i * 4)) & 0xF) / 16.0 # Blend: 70% profile, 30% hash (profile dominates structure) blended = 0.7 * profile_score + 0.3 * hash_score scores.append((i, blended)) # Sort by score descending sorted_strands = sorted(scores, key=lambda x: x[1], reverse=True) return [SIDON_ADDRESSES[s[0]] for s in sorted_strands] def hash_to_sidon_address(hash_val: int) -> int: return SIDON_ADDRESSES[hash_val % 8] def address_to_strand(address: int) -> int: if address not in _ADDRESS_TO_STRAND: raise ValueError(f"Invalid Sidon address: {address}") return _ADDRESS_TO_STRAND[address] def strand_to_address(strand: int) -> int: if strand < 0 or strand > 7: raise ValueError(f"Invalid strand: {strand}") return _STRAND_TO_ADDRESS[strand] def compute_full_address(equation: str) -> List[int]: """Compute full Sidon address list for an equation.""" from spectral_profile import compute_spectral_profile profile = compute_spectral_profile(equation) h = structural_hash(equation) return spectral_to_sidon_address(profile, h) def structural_hash(equation: str) -> int: return int(hashlib.sha256(equation.encode()).hexdigest(), 16)