#!/usr/bin/env python3 """Regenerate rrc_pist_predictions_250_v1.json from the classifier receipt. Reads all 278 compiled equations, builds 8×8 strand adjacency matrices, deduplicates by equation_id per the AGENTS.md merge rules, and writes the predictions artifact. Usage: python3 python/generate_predictions.py python3 python/generate_predictions.py \ --receipt /path/to/rrc_equation_classifier_receipt.json \ --output /path/to/rrc_pist_predictions_250_v1.json """ from __future__ import annotations import argparse import hashlib import json import re import sys from pathlib import Path from datetime import datetime, timezone from collections import OrderedDict def tokenize(text: str) -> list[str]: text = text.lower() return re.findall(r"[a-z0-9]+|[+\-*/=^(){}\[\]]", text) def build_matrix(tokens: list[str]) -> list[list[int]]: vocab = sorted(set(tokens)) matrix = [[0 for _ in range(8)] for _ in range(8)] for t_i, t_j in zip(tokens, tokens[1:]): matrix[vocab.index(t_i) % 8][vocab.index(t_j) % 8] += 1 return matrix def canonical_json_matrix(matrix: list[list[int]]) -> str: return json.dumps(matrix, separators=(",", ":")) def build_record(text: str, equation_id: str, object_id: str, name: str) -> dict: tokens = tokenize(text) vocab = sorted(set(tokens)) matrix = build_matrix(tokens) matrix_json = canonical_json_matrix(matrix) return { "equation_id": equation_id, "object_id": object_id, "name": name, "equation": text, "schema": "rrc_pist_predictions_250_v1", "claim_boundary": "matrix-only;no-classifier;no-lean-spectral", "proxy_pred": None, "exact_pred": None, "matrix_schema": "token_strand_adjacency_8x8_v1", "matrix_hash": hashlib.sha256(matrix_json.encode("utf-8")).hexdigest(), "matrix_8x8": matrix, "global_vocab_hash": hashlib.sha256( json.dumps(vocab, separators=(",", ":")).encode("utf-8") ).hexdigest(), "source_records": [], } def main(): parser = argparse.ArgumentParser(description="Regenerate PIST predictions") parser.add_argument("--receipt", type=Path, default=Path("/home/allaun/Research Stack/archive/experimental-shim-probes/rrc_equation_classifier_receipt.json")) parser.add_argument("--output", type=Path, default=Path("/home/allaun/Research Stack/shared-data/rrc_pist_predictions_250_v1.json")) args = parser.parse_args() receipt = json.loads(args.receipt.read_text()) equations = receipt["compiled_equations"] print(f"Loaded {len(equations)} source equations", file=sys.stderr) # Dedup by object_id (invariant receipt) which matches the manifold's lookup key. merged: dict[str, dict] = OrderedDict() for eq in equations: rec = eq.get("equation_record", eq) ir = eq.get("invariant_receipt", {}) eid = ir.get("object_id", rec["equation_id"]) # use object_id for lookup match name = rec.get("name", eid) text = rec.get("equation", "") if eid not in merged: oid = ir.get("object_id", rec["equation_id"]) merged[eid] = build_record(text, rec["equation_id"], oid, name) merged[eid]["source_records"] = [] merged[eid]["source_records"].append({ "equation_record_id": rec["equation_id"], "object_id": ir.get("object_id", rec["equation_id"]), "name": name, }) predictions = list(merged.values()) # Build global vocab all_tokens = set() for p in predictions: all_tokens.update(tokenize(p.get("equation", ""))) global_vocab = sorted(all_tokens) output = { "schema": "rrc_pist_predictions_250_v1", "generated_at": datetime.now(timezone.utc).isoformat(), "claim_boundary": "matrix-only;no-classifier;no-lean-spectral", "global_vocab_hash": hashlib.sha256( json.dumps(global_vocab, separators=(",", ":")).encode("utf-8") ).hexdigest(), "global_vocab": global_vocab, "matrix_schema": "token_strand_adjacency_8x8_v1", "summary": { "total_source_records": len(equations), "unique_equation_ids": len(predictions), }, "predictions": predictions, } args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text(json.dumps(output, indent=2) + "\n") print(f"Wrote {args.output} ({len(predictions)} unique predictions from {len(equations)} source records)", file=sys.stderr) if __name__ == "__main__": main()