hv-octonion-tree / example.py
zeechimp's picture
Create example.py
51da68e verified
Raw History Blame Contribute Delete
6.23 kB
#!/usr/bin/env python3
"""
example.py β€” Demonstrate hv_octonion_tree.
NumPy only.
"""
import numpy as np
from hv_octonion_tree import (
orandom, omul, oconj, random_tree, eval_tree, batch_eval,
all_trees, tree_depth, tree_key, unique_random_trees,
injectivity_exhaustive, injectivity_sampled,
mitm_analysis, hierarchical_injectivity,
check_alternativity, check_moufang, check_norm_preservation,
noise_test, structured_input_test,
notarize, hierarchical_key,
)
def demo_single_tree():
print("=" * 72)
print("Demo 1 β€” single tree evaluation")
print("=" * 72)
print()
rng = np.random.default_rng(0)
n = 8
vals = np.stack([orandom(rng) for _ in range(n)])
tree = random_tree(n, rng)
product = eval_tree(tree, vals)
print(f" n = {n}")
print(f" tree depth = {tree_depth(tree)}")
print(f" ||product|| = {np.linalg.norm(product):.15f}")
print(f" product = {np.round(product, 4)}")
print()
def demo_batch():
print("=" * 72)
print("Demo 2 β€” batched evaluation")
print("=" * 72)
print()
rng = np.random.default_rng(0)
n = 8
vals = np.stack([orandom(rng) for _ in range(n)])
trees = unique_random_trees(n, 100, rng)
products = batch_eval(trees, vals)
print(f" n = {n}, K = {len(trees)} trees")
print(f" products shape: {products.shape}")
print(f" pairwise min distance: ", end="")
D = np.linalg.norm(products[:, None, :] - products[None, :, :], axis=-1)
iu = np.triu_indices(len(products), k=1)
print(f"{D[iu].min():.4f}")
print()
def demo_injectivity():
print("=" * 72)
print("Demo 3 β€” injectivity tests")
print("=" * 72)
print()
print(" Exhaustive:")
for n in [6, 8, 10]:
r = injectivity_exhaustive(n)
print(f" n={n:>2d} {r['K']:>5d} trees min_d={r['min_d']:.6f} "
f"distinct={r['distinct']}")
print()
print(" Sampled:")
for n, K in [(16, 500), (24, 500), (32, 500)]:
r = injectivity_sampled(n, K)
print(f" n={n:>2d} {r['K']:>5d} trees min_d={r['min_d']:.6f} "
f"distinct={r['distinct']}")
print()
def demo_mitm():
print("=" * 72)
print("Demo 4 β€” MITM analysis (correction to #100)")
print("=" * 72)
print()
print(f" {'n':>3s} {'brute':>12s} {'mitm':>10s} {'saved':>8s}")
print(" " + "-" * 40)
for n in [8, 10, 12, 14, 16, 18, 20]:
r = mitm_analysis(n)
print(f" {n:>3d} {r['brute_force']:>12d} {r['mitm_cost']:>10d} "
f"{r['bits_saved']:>8.2f}")
print()
def demo_moufang():
print("=" * 72)
print("Demo 5 β€” algebraic properties (correction to #100)")
print("=" * 72)
print()
alt = check_alternativity()
mouf = check_moufang()
print(f" left alternativity: {alt['left_alt_err']:.2e}")
print(f" right alternativity: {alt['right_alt_err']:.2e}")
print(f" left Moufang: {mouf['left_moufang_err']:.2e}")
print(f" right Moufang: {mouf['right_moufang_err']:.2e} "
f"(#100 said this fails)")
print(f" middle Moufang: {mouf['mid_moufang_err']:.2e}")
print()
def demo_norm():
print("=" * 72)
print("Demo 6 β€” norm preservation")
print("=" * 72)
print()
norm_results = check_norm_preservation()
for n, nm in norm_results:
print(f" n={n:>5d} ||product|| = {nm:.15f} "
f"deviation = {abs(nm - 1.0):.2e}")
print()
def demo_noise():
print("=" * 72)
print("Demo 7 β€” noise sensitivity (correction to #100)")
print("=" * 72)
print()
for n, sigma in [(8, 0.01), (16, 0.01), (32, 0.01)]:
r = noise_test(n=n, sigma=sigma, seed=n)
print(f" n={n:>3d} sigma={sigma:.3f} "
f"mean_err={r['mean_err']:.5f} "
f"sqrt(n)*sigma={r['sqrt_n_sigma']:.5f} "
f"ratio={r['ratio_to_sqrt_n_sigma']:.3f}")
print()
def demo_structured():
print("=" * 72)
print("Demo 8 β€” structured inputs break injectivity")
print("=" * 72)
print()
s = structured_input_test(n=8, K=200)
for name, vals in s.items():
print(f" {name:<14s} min_d={vals['min_d']:.6f} "
f"mean_d={vals['mean_d']:.4f}")
print()
def demo_notarize():
print("=" * 72)
print("Demo 9 β€” notarization (proof of computation)")
print("=" * 72)
print()
rng = np.random.default_rng(0)
n = 8
operands = np.stack([orandom(rng) for _ in range(n)])
tree = random_tree(n, rng)
proof = notarize(operands, tree, withhold_bits=32)
print(f" Published operands (n={n}), product, commitment = "
f"{proof['commitment']}")
print(f" Tree withheld. Verify by guessing the tree:")
# Verifier guesses a random tree
guess_wrong = random_tree(n, rng)
guess_right = tree
print(f" guess (random): {proof['verify'](guess_wrong)}")
print(f" guess (correct): {proof['verify'](guess_right)}")
print()
def demo_hierarchical_key():
print("=" * 72)
print("Demo 10 β€” hierarchical key derivation")
print("=" * 72)
print()
rng = np.random.default_rng(0)
k, m = 4, 3
n = k * m
operands = np.stack([orandom(rng) for _ in range(n)])
sub_shapes = unique_random_trees(k, 5, rng)
top_shapes = unique_random_trees(m, 5, rng)
print(f" k={k}, m={m}, key space = Cat({k-1})^{m} * Cat({m-1}) = "
f"{hierarchical_injectivity(k, m, 1)['total_programs']}")
print(f" Sample keys:")
seen = set()
for _ in range(5):
top = top_shapes[int(rng.integers(0, len(top_shapes)))]
subs = [sub_shapes[int(rng.integers(0, len(sub_shapes)))]
for _ in range(m)]
key = hierarchical_key(operands, top, subs, k)
key_hash = hash(round(float(key.sum()), 8))
print(f" key = {np.round(key[:4], 4)}... hash = "
f"{key_hash % 10000:04d}")
print()
def main():
demo_single_tree()
demo_batch()
demo_injectivity()
demo_mitm()
demo_moufang()
demo_norm()
demo_noise()
demo_structured()
demo_notarize()
demo_hierarchical_key()
if __name__ == "__main__":
main()