mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-08-20 11:57:29 +00:00
fix: regenerate PIST predictions pipeline, fix Matrices250 kernel blowup
- generate_predictions.py: reads 278 equations from classifier receipt, builds 8×8 strand adjacency matrices, deduplicates to 250 by equation_id - build_pist_matrices_250.py: emit each matrix as a separate Lean def (match-based findMatrix) to avoid kernel term-size blowup - rrc_pist_predictions_250_v1.json regenerated in Research Stack shared-data/ - Shakeout finding: text-derived matrices have spectral radius < 2.0, so classifyExact returns none (expected — 250 non-zero matrices, weak features)
This commit is contained in:
parent
e104df6cc3
commit
862992ec98
2 changed files with 153 additions and 32 deletions
|
|
@ -7,11 +7,9 @@
|
||||||
Build formal/SilverSight/PIST/Matrices250.lean from
|
Build formal/SilverSight/PIST/Matrices250.lean from
|
||||||
shared-data/rrc_pist_predictions_250_v1.json (or a local copy).
|
shared-data/rrc_pist_predictions_250_v1.json (or a local copy).
|
||||||
|
|
||||||
Python's role: read the predictions artifact, serialize each 8×8 matrix as a
|
Each 8×8 matrix is emitted as its own named `def` to avoid overwhelming
|
||||||
Lean Array (Array Int) literal, emit an association list keyed by rrc_eq_<hex>.
|
Lean's kernel with a single large term. `findMatrix` is a `match` on the
|
||||||
|
equation_id string that delegates to the individual def.
|
||||||
The generated Lean file is consumed by SilverSight.PIST.Classify
|
|
||||||
(classifyProxy/classifyExact) to produce pistProxyLabel/pistExactLabel.
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
python3 python/build_pist_matrices_250.py
|
python3 python/build_pist_matrices_250.py
|
||||||
|
|
@ -20,23 +18,25 @@ Usage:
|
||||||
--out-lean formal/SilverSight/PIST/Matrices250.lean
|
--out-lean formal/SilverSight/PIST/Matrices250.lean
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import argparse, hashlib, json, sys
|
import argparse, hashlib, json, re, sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def lean_str(s: str) -> str:
|
def lean_matrix_def_name(eid: str) -> str:
|
||||||
s = s.replace("\\", "\\\\").replace('"', '\\"')
|
"""Sanitize equation_id to a valid Lean identifier."""
|
||||||
return f'"{s}"'
|
name = re.sub(r"[^a-zA-Z0-9_]", "_", eid)
|
||||||
|
if name[0].isdigit():
|
||||||
|
name = "m_" + name
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
def lean_array_int(xs: list[int]) -> str:
|
def lean_array_int(xs: list[int]) -> str:
|
||||||
inner = ", ".join(str(x) for x in xs)
|
return "#[" + ", ".join(str(x) for x in xs) + "]"
|
||||||
return f"#[{inner}]"
|
|
||||||
|
|
||||||
|
|
||||||
def lean_matrix_rows(rows: list[list[int]]) -> str:
|
def lean_matrix_rows(rows: list[list[int]]) -> str:
|
||||||
inner = ",\n ".join(lean_array_int(r) for r in rows)
|
inner = ",\n ".join(lean_array_int(r) for r in rows)
|
||||||
return f"#[\n {inner}\n ]"
|
return "#[\n " + inner + "\n ]"
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
|
|
@ -61,24 +61,23 @@ def main() -> int:
|
||||||
raw = preds.get("predictions", [])
|
raw = preds.get("predictions", [])
|
||||||
print(f"Loaded {len(raw)} predictions from {args.predictions}", file=sys.stderr)
|
print(f"Loaded {len(raw)} predictions from {args.predictions}", file=sys.stderr)
|
||||||
|
|
||||||
# Deterministic order by equation_id for reproducible builds.
|
|
||||||
raw_sorted = sorted(raw, key=lambda p: p.get("equation_id", ""))
|
raw_sorted = sorted(raw, key=lambda p: p.get("equation_id", ""))
|
||||||
|
|
||||||
entries: list[str] = []
|
defs: list[str] = []
|
||||||
|
find_cases: list[str] = []
|
||||||
for p in raw_sorted:
|
for p in raw_sorted:
|
||||||
eid = p.get("equation_id", "")
|
eid = p.get("equation_id", "")
|
||||||
mat = p.get("matrix_8x8", [])
|
mat = p.get("matrix_8x8", [])
|
||||||
if not eid or len(mat) != 8:
|
if not eid or len(mat) != 8:
|
||||||
print(f"WARNING: skipping malformed entry {eid}", file=sys.stderr)
|
print(f"WARNING: skipping malformed entry {eid}", file=sys.stderr)
|
||||||
continue
|
continue
|
||||||
matrix_lean = lean_matrix_rows(mat)
|
name = lean_matrix_def_name(eid)
|
||||||
entries.append(f" ({lean_str(eid)}, {matrix_lean})")
|
defs.append(f"def {name} : Array (Array Int) :=\n {lean_matrix_rows(mat)}")
|
||||||
|
find_cases.append(f" | \"{eid}\" => some {name}")
|
||||||
|
|
||||||
# Include a content hash so the generated file can be validated.
|
|
||||||
content_blob = json.dumps(
|
content_blob = json.dumps(
|
||||||
{p.get("equation_id"): p.get("matrix_8x8") for p in raw_sorted},
|
{p.get("equation_id"): p.get("matrix_8x8") for p in raw_sorted},
|
||||||
sort_keys=True,
|
sort_keys=True, separators=(",", ":"),
|
||||||
separators=(",", ":"),
|
|
||||||
).encode("utf-8")
|
).encode("utf-8")
|
||||||
content_hash = hashlib.sha256(content_blob).hexdigest()
|
content_hash = hashlib.sha256(content_blob).hexdigest()
|
||||||
|
|
||||||
|
|
@ -90,26 +89,20 @@ def main() -> int:
|
||||||
"-- Source: rrc_pist_predictions_250_v1.json",
|
"-- Source: rrc_pist_predictions_250_v1.json",
|
||||||
"-- Content hash (SHA-256 canonical matrices): " + content_hash,
|
"-- Content hash (SHA-256 canonical matrices): " + content_hash,
|
||||||
"--",
|
"--",
|
||||||
"-- This file is consumed by SilverSight.PIST.Classify (classifyProxy/",
|
"-- This file is consumed by SilverSight.RRC.Q16_16Manifold at compile time",
|
||||||
"-- classifyExact) at compile time to produce pistProxyLabel/",
|
"-- to produce pistProxyLabel/pistExactLabel for each equation_id.",
|
||||||
"-- pistExactLabel for each invariant equation_id.",
|
|
||||||
"",
|
"",
|
||||||
"namespace SilverSight.PIST.Matrices250",
|
"namespace SilverSight.PIST.Matrices250",
|
||||||
"",
|
"",
|
||||||
"/-- All matrices in this list have dimension 8×8 (the canonical strand count).",
|
|
||||||
" Stored as association list (key → matrix). Generated from",
|
|
||||||
" rrc_pist_predictions_250_v1.json.",
|
|
||||||
f" Entries: {len(entries)}. -/",
|
|
||||||
f"def pistMatrixDim : Nat := 8",
|
f"def pistMatrixDim : Nat := 8",
|
||||||
"",
|
"",
|
||||||
"def pistMatrices250 : List (String × Array (Array Int)) :=",
|
*defs,
|
||||||
" [",
|
|
||||||
",\n".join(entries),
|
|
||||||
" ]",
|
|
||||||
"",
|
"",
|
||||||
"/-- Look up an 8×8 matrix by invariant equation_id. -/",
|
"/-- Look up an 8×8 matrix by invariant equation_id. -/",
|
||||||
"def findMatrix (eqId : String) : Option (Array (Array Int)) :=",
|
"def findMatrix (eqId : String) : Option (Array (Array Int)) :=",
|
||||||
" pistMatrices250.find? (fun (k, _) => k = eqId) |>.map (fun (_, v) => v)",
|
" match eqId with",
|
||||||
|
*find_cases,
|
||||||
|
" | _ => none",
|
||||||
"",
|
"",
|
||||||
"end SilverSight.PIST.Matrices250",
|
"end SilverSight.PIST.Matrices250",
|
||||||
"",
|
"",
|
||||||
|
|
@ -117,7 +110,7 @@ def main() -> int:
|
||||||
|
|
||||||
args.out_lean.parent.mkdir(parents=True, exist_ok=True)
|
args.out_lean.parent.mkdir(parents=True, exist_ok=True)
|
||||||
args.out_lean.write_text("\n".join(lines))
|
args.out_lean.write_text("\n".join(lines))
|
||||||
print(f"Wrote {args.out_lean} ({len(entries)} entries)", file=sys.stderr)
|
print(f"Wrote {args.out_lean} ({len(defs)} entries)", file=sys.stderr)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
128
python/generate_predictions.py
Normal file
128
python/generate_predictions.py
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
#!/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, 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,
|
||||||
|
"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 equation_id: deterministic representative selection per AGENTS.md
|
||||||
|
# representative = min(records, key = equation_record.equation_id)
|
||||||
|
merged: dict[str, dict] = OrderedDict()
|
||||||
|
for eq in equations:
|
||||||
|
rec = eq.get("equation_record", eq)
|
||||||
|
eid = rec["equation_id"]
|
||||||
|
name = rec.get("name", eid)
|
||||||
|
text = rec.get("equation", "")
|
||||||
|
|
||||||
|
if eid not in merged:
|
||||||
|
merged[eid] = build_record(text, eid, name)
|
||||||
|
merged[eid]["source_records"] = []
|
||||||
|
|
||||||
|
merged[eid]["source_records"].append({
|
||||||
|
"equation_record_id": eid,
|
||||||
|
"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()
|
||||||
Loading…
Add table
Reference in a new issue