mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-30 18:56:16 +00:00
- SDPVerify.lean: certificate verification engine (714 lines, compiles cleanly) - GoormaghtighCert.lean: Goormaghtigh conjecture SDP certificate - HachimojiManifoldAxiom/HachimojiSubstitution: Hachimoji DNA encoding - GeneticBraidBridge.lean: genetic algorithm braid bridge - load_dependency_graph/load_module_graph: Gremlin Cosmos DB graph loaders - test_graph_queries/rrc_math_xref: graph verification queries - Gremlin mathblob DB provisioned and accessible - Branch cleanup: deleted 11 stale remote branches Build: 3297 jobs, 0 errors (lake build Semantics.SDPVerify)
268 lines
10 KiB
Python
268 lines
10 KiB
Python
#!/usr/bin/env -S uv run
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = ["gremlinpython", "python-dotenv"]
|
|
# ///
|
|
"""
|
|
ingest_math_modules.py — Ingest full math metadata into Gremlin
|
|
|
|
For every .lean file: parses sorry count, theorem/def/structure/inductive counts,
|
|
namespace, and dominant math kind. Updates existing module vertices with these
|
|
properties, then adds RRC equation vertices linked to their implementing modules.
|
|
|
|
Run: uv run scripts/ingest_math_modules.py
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
LEAN_DIR = ROOT / "0-Core-Formalism/lean/Semantics/Semantics"
|
|
ENV_FILE = ROOT / ".env.gremlin"
|
|
load_dotenv(ENV_FILE)
|
|
|
|
NEON_HOST = "neon-64gb"
|
|
CONTAINER = "arxiv-pg"
|
|
DB = "arxiv"
|
|
|
|
BATCH = 30 # small batches — free tier RU limit
|
|
|
|
# ── Lean file parser ──────────────────────────────────────────────────────────
|
|
|
|
MATH_KINDS = {
|
|
"braid": ["braid","crossing","slug3","ternary","anyon","fusion","topo"],
|
|
"number_theory":["sidon","erdos","prime","diophantine","goormaghtigh","zeckendorf"],
|
|
"geometry": ["manifold","geodesic","curvature","christoffel","riemannian","spherion"],
|
|
"algebra": ["quaternion","algebra","ring","field","group","monoid","category"],
|
|
"analysis": ["convergence","continuity","lipschitz","cauchy","measure","integral"],
|
|
"quantum": ["yangmills","lattice","hamiltonian","energy","entropy","quantum"],
|
|
"fixedpoint": ["fix16","q16","fixedpoint","saturate","phasemodulus"],
|
|
"routing": ["route","cfd","navier","burgers","canal","flow","pressure"],
|
|
}
|
|
|
|
def dominant_kind(text: str) -> str:
|
|
text_l = text.lower()
|
|
scores = {k: sum(text_l.count(w) for w in ws) for k, ws in MATH_KINDS.items()}
|
|
best = max(scores, key=scores.get)
|
|
return best if scores[best] > 0 else "general"
|
|
|
|
def parse_lean(path: Path) -> dict:
|
|
try:
|
|
text = path.read_text(errors="replace")
|
|
except Exception:
|
|
return {}
|
|
|
|
# Module id
|
|
rel = path.relative_to(ROOT / "0-Core-Formalism/lean/Semantics")
|
|
module_id = ".".join(rel.with_suffix("").parts)
|
|
|
|
# Namespace
|
|
ns_match = re.search(r"^namespace\s+(\S+)", text, re.MULTILINE)
|
|
namespace = ns_match.group(1) if ns_match else ""
|
|
|
|
return {
|
|
"id": module_id,
|
|
"namespace": namespace,
|
|
"sorry_count": text.count("sorry"),
|
|
"theorem_count": len(re.findall(r"^theorem\s", text, re.MULTILINE)),
|
|
"def_count": len(re.findall(r"^def\s", text, re.MULTILINE)),
|
|
"struct_count": len(re.findall(r"^structure\s",text, re.MULTILINE)),
|
|
"inductive_count": len(re.findall(r"^inductive\s",text, re.MULTILINE)),
|
|
"line_count": text.count("\n"),
|
|
"math_kind": dominant_kind(text),
|
|
}
|
|
|
|
# ── Gremlin ───────────────────────────────────────────────────────────────────
|
|
|
|
from gremlin_python.driver import client as gc, serializer
|
|
|
|
_client = None
|
|
def gremlin():
|
|
global _client
|
|
if _client is None:
|
|
_client = gc.Client(
|
|
os.environ["GREMLIN_ENDPOINT"], "g",
|
|
username=os.environ["GREMLIN_USERNAME"],
|
|
password=os.environ["GREMLIN_PASSWORD"],
|
|
message_serializer=serializer.GraphSONSerializersV2d0(),
|
|
)
|
|
return _client
|
|
|
|
def gq(q: str, b: dict = None) -> list:
|
|
try:
|
|
return gremlin().submitAsync(q, b or {}).result().all().result()
|
|
except Exception as e:
|
|
print(f" ERR: {str(e)[:100]}")
|
|
return []
|
|
|
|
def update_module_vertex(m: dict):
|
|
"""Add math metadata properties to existing module vertex."""
|
|
gq(
|
|
"g.V().has('module','id',vid)"
|
|
".property('namespace',ns)"
|
|
".property('sorry_count',sc)"
|
|
".property('theorem_count',tc)"
|
|
".property('def_count',dc)"
|
|
".property('struct_count',stc)"
|
|
".property('inductive_count',ic)"
|
|
".property('line_count',lc)"
|
|
".property('math_kind',mk)",
|
|
{
|
|
"vid": m["id"],
|
|
"ns": m["namespace"],
|
|
"sc": m["sorry_count"],
|
|
"tc": m["theorem_count"],
|
|
"dc": m["def_count"],
|
|
"stc": m["struct_count"],
|
|
"ic": m["inductive_count"],
|
|
"lc": m["line_count"],
|
|
"mk": m["math_kind"],
|
|
}
|
|
)
|
|
|
|
# ── Neon: load RRC equations ──────────────────────────────────────────────────
|
|
|
|
def neon(sql: str) -> list[list[str]]:
|
|
r = subprocess.run(
|
|
["ssh", NEON_HOST,
|
|
f"podman exec {CONTAINER} psql -U postgres -d {DB} -t -A -F '|' -c \"{sql}\""],
|
|
capture_output=True, text=True, timeout=60,
|
|
)
|
|
return [ln.split("|") for ln in r.stdout.strip().split("\n") if ln]
|
|
|
|
def load_rrc_equations() -> list[dict]:
|
|
rows = neon("SELECT equation_id, name FROM rrc_equation_codes8 ORDER BY name")
|
|
return [{"id": r[0], "name": r[1]} for r in rows if len(r) >= 2]
|
|
|
|
def upsert_equation_vertex(eq: dict):
|
|
gq(
|
|
"g.V().has('equation','id',vid).fold()"
|
|
".coalesce(unfold(),"
|
|
" addV('equation').property('id',vid).property('pk',vid).property('name',nm))"
|
|
".property('name',nm)",
|
|
{"vid": eq["id"], "nm": eq["name"]}
|
|
)
|
|
|
|
def link_equation_to_modules(eq: dict, module_ids: list[str]):
|
|
"""Create 'implements' edges from module → equation."""
|
|
for mid in module_ids:
|
|
gq(
|
|
"g.V().has('module','id',src).as('m')"
|
|
".V().has('equation','id',dst)"
|
|
".coalesce("
|
|
" __.in('implements').where(eq('m')),"
|
|
" addE('implements').from('m')"
|
|
")",
|
|
{"src": mid, "dst": eq["id"]}
|
|
)
|
|
|
|
# ── Module → equation linking heuristic ──────────────────────────────────────
|
|
|
|
EQ_MODULE_MAP = {
|
|
# equation name substring → module name substrings
|
|
"Chirality": ["Chirality","Braid","SLUG3","Topo"],
|
|
"BLINK_GATE": ["SLUG3","Ternary","Blink","Gate"],
|
|
"Christoffel": ["Christoffel","Geometry","Manifold","Classical"],
|
|
"Stereographic": ["Spherion","Topo","Geometry","Chart"],
|
|
"Affine_Mapping": ["Affine","LTSF","Linear","Mapping"],
|
|
"BitFlip": ["Gradient","Flip","Signal","Energy"],
|
|
"DAG_Force": ["DAG","Force","Equilibrium","YangMills"],
|
|
"Energy_Function": ["Energy","Entropy","Hamiltonian","Physics"],
|
|
"Energy_Monoton": ["Energy","Monoton","Convergence","AVMR"],
|
|
}
|
|
|
|
def modules_for_equation(eq_name: str, all_module_ids: list[str]) -> list[str]:
|
|
hits = []
|
|
for prefix, kws in EQ_MODULE_MAP.items():
|
|
if prefix.lower() in eq_name.lower():
|
|
for mid in all_module_ids:
|
|
short = mid.split(".")[-1]
|
|
if any(kw.lower() in short.lower() for kw in kws):
|
|
hits.append(mid)
|
|
return list(set(hits))
|
|
|
|
# ── Main ──────────────────────────────────────────────────────────────────────
|
|
|
|
def main():
|
|
# ── 1. Parse all .lean files ──
|
|
files = sorted(LEAN_DIR.rglob("*.lean"))
|
|
print(f"Parsing {len(files)} .lean files...")
|
|
modules = []
|
|
for f in files:
|
|
m = parse_lean(f)
|
|
if m:
|
|
modules.append(m)
|
|
print(f" parsed {len(modules)} modules")
|
|
|
|
# Summary
|
|
total_sorry = sum(m["sorry_count"] for m in modules)
|
|
total_thm = sum(m["theorem_count"] for m in modules)
|
|
total_def = sum(m["def_count"] for m in modules)
|
|
total_struct = sum(m["struct_count"] for m in modules)
|
|
kind_counts = {}
|
|
for m in modules:
|
|
kind_counts[m["math_kind"]] = kind_counts.get(m["math_kind"], 0) + 1
|
|
print(f" sorries={total_sorry} theorems={total_thm} defs={total_def} structs={total_struct}")
|
|
print(f" math kinds: {dict(sorted(kind_counts.items(), key=lambda x: -x[1]))}")
|
|
print()
|
|
|
|
# ── 2. Update existing module vertices with math metadata ──
|
|
print(f"Updating {len(modules)} module vertices with math metadata...")
|
|
for i, m in enumerate(modules):
|
|
update_module_vertex(m)
|
|
if (i+1) % BATCH == 0:
|
|
print(f" {i+1}/{len(modules)}", end="\r")
|
|
time.sleep(0.05)
|
|
print(f"\n done.")
|
|
|
|
# ── 3. Load RRC equations from Neon ──
|
|
print("\nLoading RRC equations from Neon...")
|
|
equations = load_rrc_equations()
|
|
print(f" {len(equations)} equations")
|
|
|
|
all_module_ids = [m["id"] for m in modules]
|
|
|
|
print(f"Ingesting {len(equations)} equation vertices...")
|
|
for i, eq in enumerate(equations):
|
|
upsert_equation_vertex(eq)
|
|
# Link to implementing modules
|
|
mods = modules_for_equation(eq["name"], all_module_ids)
|
|
if mods:
|
|
link_equation_to_modules(eq, mods[:5])
|
|
if (i+1) % BATCH == 0:
|
|
print(f" {i+1}/{len(equations)}", end="\r")
|
|
time.sleep(0.05)
|
|
print(f"\n done.")
|
|
|
|
# ── 4. Final counts ──
|
|
v = gq("g.V().count()")
|
|
e = gq("g.E().count()")
|
|
print(f"\nGraph: {v} vertices, {e} edges")
|
|
|
|
# ── 5. Top sorry modules ──
|
|
print("\nTop 10 modules by sorry count:")
|
|
results = gq(
|
|
"g.V().hasLabel('module').has('sorry_count', gt(0))"
|
|
".order().by('sorry_count', decr).limit(10)"
|
|
".project('module','sorries','kind')"
|
|
".by('id').by('sorry_count').by('math_kind')"
|
|
)
|
|
if results:
|
|
for r in results:
|
|
print(f" {r.get('module','?').split('.')[-1]:40s} sorry={r.get('sorries','?')} ({r.get('kind','?')})")
|
|
|
|
# ── 6. Most connected math kinds ──
|
|
print("\nModules by math_kind:")
|
|
for kind in sorted(kind_counts, key=lambda k: -kind_counts[k])[:6]:
|
|
count = kind_counts[kind]
|
|
print(f" {kind:20s} {count} modules")
|
|
|
|
gremlin().close()
|
|
print("\nIngest complete.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|