{
"cells": [
{
"cell_type": "markdown",
"id": "b7bf6219",
"metadata": {},
"source": [
"# TNFR Spectral Factorization Regression & Telemetry Notebook\n",
"\n",
"\n",
"This notebook accompanies the spectral factorization lab. It exercises both regression paths (FFT-enabled and arithmetic-cache) and captures `SpectralAnalysisResult` telemetry for exploratory plotting."
]
},
{
"cell_type": "markdown",
"id": "9747ad85",
"metadata": {},
"source": [
"## 1. Configure Environment and Imports\n",
"\n",
"\n",
"Prepare deterministic settings, import scientific libraries, and wire the spectral factorizer module for notebook execution."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3ce04f9c",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import math\n",
"import os\n",
"import sys\n",
"import time\n",
"from pathlib import Path\n",
"from typing import Any, Dict, List\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"\n",
"REPO_ROOT = Path.cwd().resolve()\n",
"if not (REPO_ROOT / \"factorization-lab\").exists():\n",
" for parent in REPO_ROOT.parents:\n",
" candidate = parent / \"factorization-lab\"\n",
" if candidate.exists():\n",
" REPO_ROOT = parent\n",
" break\n",
"\n",
"LAB_ROOT = REPO_ROOT / \"factorization-lab\"\n",
"if LAB_ROOT.exists() and str(LAB_ROOT) not in sys.path:\n",
" sys.path.insert(0, str(LAB_ROOT))\n",
"\n",
"from tnfr_factorization import SpectralPaleyFactorizer # type: ignore[import]\n",
"import tnfr_factorization.spectral_paley as sp # type: ignore[import]\n",
"\n",
"sns.set_theme(style=\"whitegrid\")\n",
"np.random.seed(42)\n"
]
},
{
"cell_type": "markdown",
"id": "5656beb4",
"metadata": {},
"source": [
"## 2. Load or Stub Spectral Analysis Components\n",
"\n",
"\n",
"Instantiate canonical analyzers and lightweight stubs so we can deterministically trigger FFT-enabled and arithmetic-cache behaviors."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "fa66dabb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'canonical': <tnfr_factorization.spectral_paley.SpectralPaleyFactorizer at 0x223aee792b0>,\n",
" 'stubbed': <tnfr_factorization.spectral_paley.SpectralPaleyFactorizer at 0x223aeeada90>}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class DeterministicSpectralState:\n",
" \"\"\"Minimal container mimicking TNFR spectral state outputs.\"\"\"\n",
"\n",
" def __init__(self, node_count: int, coherence_length: float = 4.0) -> None:\n",
" self.eigenvalues = np.linspace(0.0, 1.0, max(node_count, 1), dtype=float)\n",
" self.coherence_length = coherence_length\n",
"\n",
"\n",
"class RecordingFFTEngine:\n",
" \"\"\"Notebook-friendly stub that records how often it is used.\"\"\"\n",
"\n",
" def __init__(self, coherence_length: float = 4.0) -> None:\n",
" self.coherence_length = coherence_length\n",
" self.calls: List[int] = []\n",
"\n",
" def get_spectral_state(self, graph: Any, force_recompute: bool = False) -> DeterministicSpectralState:\n",
" self.calls.append(graph.number_of_nodes())\n",
" return DeterministicSpectralState(graph.number_of_nodes(), self.coherence_length)\n",
"\n",
"\n",
"def build_factorizers() -> Dict[str, SpectralPaleyFactorizer]:\n",
" \"\"\"Return both canonical and stubbed factorizers for experiments.\"\"\"\n",
"\n",
" canonical = SpectralPaleyFactorizer()\n",
" stubbed = SpectralPaleyFactorizer(fft_engine=RecordingFFTEngine(coherence_length=6.25))\n",
" return {\"canonical\": canonical, \"stubbed\": stubbed}\n",
"\n",
"\n",
"factories = build_factorizers()\n",
"factories"
]
},
{
"cell_type": "markdown",
"id": "7a323cee",
"metadata": {},
"source": [
"## 3. Add Regression Tests for FFT-Enabled Path\n",
"\n",
"\n",
"Validate that the FFT-enabled branch produces deterministic Laplacian gaps and that the stubbed engine records spectral calls."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ae5061ba",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: gap=0.027778, phase_gradient=0.000751, calls=2\n"
]
}
],
"source": [
"def test_fft_branch_laplacian_gap_consistency(n: int = 37) -> None:\n",
" factorizer = factories[\"stubbed\"]\n",
" engine = factorizer._fft_engine # type: ignore[attr-defined]\n",
"\n",
" result = factorizer.analyze(n)\n",
"\n",
" expected_eigs = np.linspace(0.0, 1.0, result.node_count, dtype=float)\n",
" expected_gap = next((val for val in expected_eigs if val > 1e-9), 0.0)\n",
"\n",
" diff = abs(result.laplacian_gap - expected_gap)\n",
" assert diff <= 1e-9\n",
" assert np.isclose(result.coherence_length, engine.coherence_length)\n",
" assert len(engine.calls) >= 1\n",
"\n",
" print(\n",
" f\"PASS: gap={result.laplacian_gap:.6f}, phase_gradient={result.phase_gradient:.6f}, calls={len(engine.calls)}\"\n",
" )\n",
"\n",
"\n",
"test_fft_branch_laplacian_gap_consistency()\n"
]
},
{
"cell_type": "markdown",
"id": "384f1c5c",
"metadata": {},
"source": [
"## 4. Add Regression Tests for Arithmetic Cache Path\n",
"\n",
"\n",
"Exercise the canonical arithmetic telemetry cache to ensure ΔNFR data is memoized across repeated analyses."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "28510d41",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: cache hits verified for n=221, factors=[], ΔNFR=3.259e+00\n"
]
}
],
"source": [
"def test_arithmetic_cache_hits(n: int = 221) -> None:\n",
" factorizer = factories[\"canonical\"]\n",
"\n",
" cache_clear = getattr(sp._compute_arithmetic_telemetry, \"cache_clear\", None)\n",
" if callable(cache_clear):\n",
" cache_clear()\n",
"\n",
" original_prime_factorization = sp._prime_factorization\n",
" call_count = {\"value\": 0}\n",
"\n",
" def _instrumented_prime_factorization(value: int) -> Dict[int, int]:\n",
" call_count[\"value\"] += 1\n",
" return original_prime_factorization(value)\n",
"\n",
" sp._prime_factorization = _instrumented_prime_factorization # type: ignore[assignment]\n",
" try:\n",
" first = factorizer.analyze(n)\n",
" second = factorizer.analyze(n)\n",
" finally:\n",
" sp._prime_factorization = original_prime_factorization # type: ignore[assignment]\n",
"\n",
" assert call_count[\"value\"] == 1, \"prime factorization should be memoized\"\n",
" assert np.isclose(first.arithmetic_delta_nfr, second.arithmetic_delta_nfr)\n",
" assert first.candidate_factors == second.candidate_factors\n",
"\n",
" print(\n",
" f\"PASS: cache hits verified for n={n}, factors={first.candidate_factors}, ΔNFR={first.arithmetic_delta_nfr:.3e}\"\n",
" )\n",
"\n",
"\n",
"test_arithmetic_cache_hits()"
]
},
{
"cell_type": "markdown",
"id": "e4dc06cd",
"metadata": {},
"source": [
"## 5. Capture SpectralAnalysisResult History\n",
"\n",
"\n",
"Sweep both factorizers over a deterministic set of integers, persist the telemetry into a pandas DataFrame, and retain timestamps plus energy-derived metrics for downstream plotting."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "c7aa327e",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.microsoft.datawrangler.viewer.v0+json": {
"columns": [
{
"name": "index",
"rawType": "int64",
"type": "integer"
},
{
"name": "route",
"rawType": "object",
"type": "string"
},
{
"name": "n",
"rawType": "int64",
"type": "integer"
},
{
"name": "laplacian_gap",
"rawType": "float64",
"type": "float"
},
{
"name": "phase_gradient",
"rawType": "float64",
"type": "float"
},
{
"name": "coherence_score",
"rawType": "float64",
"type": "float"
},
{
"name": "phi_s",
"rawType": "float64",
"type": "float"
},
{
"name": "delta_nfr",
"rawType": "float64",
"type": "float"
},
{
"name": "timestamp",
"rawType": "float64",
"type": "float"
},
{
"name": "elapsed_ms",
"rawType": "float64",
"type": "float"
},
{
"name": "candidate_factors",
"rawType": "object",
"type": "string"
}
],
"ref": "563368ff-b9c8-4076-b6fd-1e46de3dd059",
"rows": [
[
"0",
"canonical",
"185",
"64.69926474563212",
"0.34972575538179523",
"0.29990508667963045",
"0.391304347826087",
"3.315721597113246",
"1764519101.735847",
"31.67379996739328",
"5"
],
[
"1",
"canonical",
"221",
"88.06696562634055",
"0.3984930571327627",
"0.25354324110521564",
"0.43636363636363634",
"3.259307194618086",
"1764519101.7490313",
"13.17879999987781",
"-"
],
[
"2",
"canonical",
"289",
"271.99999999999915",
"0.9411764705882324",
"0.031244079211110797",
"0.9444444444444444",
"2.0910378118623254",
"1764519101.831412",
"82.37409999128431",
"-"
],
[
"3",
"canonical",
"299",
"116.82532421355106",
"0.38812400070947195",
"0.2627598289437056",
"0.42",
"3.249823297092512",
"1764519101.9015465",
"70.13150001876056",
"-"
],
[
"4",
"canonical",
"323",
"93.94448724536001",
"0.2890599607549539",
"0.36787944117144233",
"0.37037037037037035",
"3.244294223231449",
"1764519101.9553466",
"53.796400083228946",
"-"
],
[
"5",
"stubbed",
"185",
"0.005434782608695652",
"2.9377203290246768e-05",
"0.43171052342907973",
"0.391304347826087",
"3.315721597113246",
"1764519101.960178",
"4.827999975532293",
"-"
],
[
"6",
"stubbed",
"221",
"0.004545454545454545",
"2.0567667626491154e-05",
"0.43171052342907973",
"0.43636363636363634",
"3.259307194618086",
"1764519101.9677835",
"7.603499921970069",
"-"
],
[
"7",
"stubbed",
"289",
"0.003472222222222222",
"1.2014609765474816e-05",
"0.3447415169719474",
"0.9444444444444444",
"2.0910378118623254",
"1764519101.9912243",
"23.438300006091595",
"-"
],
[
"8",
"stubbed",
"299",
"0.0033333333333333335",
"1.107419712070875e-05",
"0.43171052342907973",
"0.42",
"3.249823297092512",
"1764519102.0057118",
"14.483599923551083",
"-"
],
[
"9",
"stubbed",
"323",
"0.0030864197530864196",
"9.496676163342829e-06",
"0.43171052342907973",
"0.37037037037037035",
"3.244294223231449",
"1764519102.0207367",
"15.021100058220327",
"-"
]
],
"shape": {
"columns": 10,
"rows": 10
}
},
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>route</th>\n",
" <th>n</th>\n",
" <th>laplacian_gap</th>\n",
" <th>phase_gradient</th>\n",
" <th>coherence_score</th>\n",
" <th>phi_s</th>\n",
" <th>delta_nfr</th>\n",
" <th>timestamp</th>\n",
" <th>elapsed_ms</th>\n",
" <th>candidate_factors</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>canonical</td>\n",
" <td>185</td>\n",
" <td>64.699265</td>\n",
" <td>0.349726</td>\n",
" <td>0.299905</td>\n",
" <td>0.391304</td>\n",
" <td>3.315722</td>\n",
" <td>1.764519e+09</td>\n",
" <td>31.6738</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>canonical</td>\n",
" <td>221</td>\n",
" <td>88.066966</td>\n",
" <td>0.398493</td>\n",
" <td>0.253543</td>\n",
" <td>0.436364</td>\n",
" <td>3.259307</td>\n",
" <td>1.764519e+09</td>\n",
" <td>13.1788</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>canonical</td>\n",
" <td>289</td>\n",
" <td>272.000000</td>\n",
" <td>0.941176</td>\n",
" <td>0.031244</td>\n",
" <td>0.944444</td>\n",
" <td>2.091038</td>\n",
" <td>1.764519e+09</td>\n",
" <td>82.3741</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>canonical</td>\n",
" <td>299</td>\n",
" <td>116.825324</td>\n",
" <td>0.388124</td>\n",
" <td>0.262760</td>\n",
" <td>0.420000</td>\n",
" <td>3.249823</td>\n",
" <td>1.764519e+09</td>\n",
" <td>70.1315</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>canonical</td>\n",
" <td>323</td>\n",
" <td>93.944487</td>\n",
" <td>0.289060</td>\n",
" <td>0.367879</td>\n",
" <td>0.370370</td>\n",
" <td>3.244294</td>\n",
" <td>1.764519e+09</td>\n",
" <td>53.7964</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>stubbed</td>\n",
" <td>185</td>\n",
" <td>0.005435</td>\n",
" <td>0.000029</td>\n",
" <td>0.431711</td>\n",
" <td>0.391304</td>\n",
" <td>3.315722</td>\n",
" <td>1.764519e+09</td>\n",
" <td>4.8280</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>stubbed</td>\n",
" <td>221</td>\n",
" <td>0.004545</td>\n",
" <td>0.000021</td>\n",
" <td>0.431711</td>\n",
" <td>0.436364</td>\n",
" <td>3.259307</td>\n",
" <td>1.764519e+09</td>\n",
" <td>7.6035</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>stubbed</td>\n",
" <td>289</td>\n",
" <td>0.003472</td>\n",
" <td>0.000012</td>\n",
" <td>0.344742</td>\n",
" <td>0.944444</td>\n",
" <td>2.091038</td>\n",
" <td>1.764519e+09</td>\n",
" <td>23.4383</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>stubbed</td>\n",
" <td>299</td>\n",
" <td>0.003333</td>\n",
" <td>0.000011</td>\n",
" <td>0.431711</td>\n",
" <td>0.420000</td>\n",
" <td>3.249823</td>\n",
" <td>1.764519e+09</td>\n",
" <td>14.4836</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>stubbed</td>\n",
" <td>323</td>\n",
" <td>0.003086</td>\n",
" <td>0.000009</td>\n",
" <td>0.431711</td>\n",
" <td>0.370370</td>\n",
" <td>3.244294</td>\n",
" <td>1.764519e+09</td>\n",
" <td>15.0211</td>\n",
" <td>-</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" route n laplacian_gap phase_gradient coherence_score phi_s \\\n",
"0 canonical 185 64.699265 0.349726 0.299905 0.391304 \n",
"1 canonical 221 88.066966 0.398493 0.253543 0.436364 \n",
"2 canonical 289 272.000000 0.941176 0.031244 0.944444 \n",
"3 canonical 299 116.825324 0.388124 0.262760 0.420000 \n",
"4 canonical 323 93.944487 0.289060 0.367879 0.370370 \n",
"5 stubbed 185 0.005435 0.000029 0.431711 0.391304 \n",
"6 stubbed 221 0.004545 0.000021 0.431711 0.436364 \n",
"7 stubbed 289 0.003472 0.000012 0.344742 0.944444 \n",
"8 stubbed 299 0.003333 0.000011 0.431711 0.420000 \n",
"9 stubbed 323 0.003086 0.000009 0.431711 0.370370 \n",
"\n",
" delta_nfr timestamp elapsed_ms candidate_factors \n",
"0 3.315722 1.764519e+09 31.6738 5 \n",
"1 3.259307 1.764519e+09 13.1788 - \n",
"2 2.091038 1.764519e+09 82.3741 - \n",
"3 3.249823 1.764519e+09 70.1315 - \n",
"4 3.244294 1.764519e+09 53.7964 - \n",
"5 3.315722 1.764519e+09 4.8280 - \n",
"6 3.259307 1.764519e+09 7.6035 - \n",
"7 2.091038 1.764519e+09 23.4383 - \n",
"8 3.249823 1.764519e+09 14.4836 - \n",
"9 3.244294 1.764519e+09 15.0211 - "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def collect_history(samples: List[int] | None = None) -> pd.DataFrame:\n",
" samples = samples or [185, 221, 289, 299, 323]\n",
" records: List[Dict[str, Any]] = []\n",
"\n",
" for route, factorizer in factories.items():\n",
" for n in samples:\n",
" start = time.perf_counter()\n",
" result = factorizer.analyze(n)\n",
" elapsed_ms = (time.perf_counter() - start) * 1000.0\n",
" records.append(\n",
" {\n",
" \"route\": route,\n",
" \"n\": n,\n",
" \"laplacian_gap\": result.laplacian_gap,\n",
" \"phase_gradient\": result.phase_gradient,\n",
" \"coherence_score\": result.coherence_score,\n",
" \"phi_s\": result.phi_s,\n",
" \"delta_nfr\": result.arithmetic_delta_nfr,\n",
" \"timestamp\": time.time(),\n",
" \"elapsed_ms\": elapsed_ms,\n",
" \"candidate_factors\": \",\".join(map(str, result.candidate_factors)) or \"-\",\n",
" }\n",
" )\n",
" frame = pd.DataFrame.from_records(records).sort_values([\"route\", \"n\"]).reset_index(drop=True)\n",
" return frame\n",
"\n",
"\n",
"history_df = collect_history()\n",
"history_df"
]
},
{
"cell_type": "markdown",
"id": "e549a025",
"metadata": {},
"source": [
"## 6. Plot SpectralAnalysisResult History\n",
"\n",
"\n",
"Use seaborn/matplotlib visualizations plus a lightweight widget to compare FFT vs arithmetic-cache runs and highlight any regression anomalies."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "fa638d99",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f13467ba654a4d79845160a0375088ea",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"interactive(children=(Dropdown(description='Metric', options=('laplacian_gap', 'phase_gradient', 'coherence_sc…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.microsoft.datawrangler.viewer.v0+json": {
"columns": [
{
"name": "index",
"rawType": "int64",
"type": "integer"
},
{
"name": "route",
"rawType": "object",
"type": "string"
},
{
"name": "n",
"rawType": "int64",
"type": "integer"
},
{
"name": "laplacian_gap",
"rawType": "float64",
"type": "float"
},
{
"name": "phase_gradient",
"rawType": "float64",
"type": "float"
},
{
"name": "coherence_score",
"rawType": "float64",
"type": "float"
},
{
"name": "phi_s",
"rawType": "float64",
"type": "float"
},
{
"name": "delta_nfr",
"rawType": "float64",
"type": "float"
},
{
"name": "timestamp",
"rawType": "float64",
"type": "float"
},
{
"name": "elapsed_ms",
"rawType": "float64",
"type": "float"
},
{
"name": "candidate_factors",
"rawType": "object",
"type": "string"
}
],
"ref": "e5913f15-d709-40d7-bfb5-89ce8edda15a",
"rows": [
[
"0",
"canonical",
"185",
"64.69926474563212",
"0.34972575538179523",
"0.29990508667963045",
"0.391304347826087",
"3.315721597113246",
"1764519101.735847",
"31.67379996739328",
"5"
],
[
"1",
"canonical",
"221",
"88.06696562634055",
"0.3984930571327627",
"0.25354324110521564",
"0.43636363636363634",
"3.259307194618086",
"1764519101.7490313",
"13.17879999987781",
"-"
],
[
"2",
"canonical",
"289",
"271.99999999999915",
"0.9411764705882324",
"0.031244079211110797",
"0.9444444444444444",
"2.0910378118623254",
"1764519101.831412",
"82.37409999128431",
"-"
],
[
"3",
"canonical",
"299",
"116.82532421355106",
"0.38812400070947195",
"0.2627598289437056",
"0.42",
"3.249823297092512",
"1764519101.9015465",
"70.13150001876056",
"-"
],
[
"4",
"canonical",
"323",
"93.94448724536001",
"0.2890599607549539",
"0.36787944117144233",
"0.37037037037037035",
"3.244294223231449",
"1764519101.9553466",
"53.796400083228946",
"-"
],
[
"5",
"stubbed",
"185",
"0.005434782608695652",
"2.9377203290246768e-05",
"0.43171052342907973",
"0.391304347826087",
"3.315721597113246",
"1764519101.960178",
"4.827999975532293",
"-"
],
[
"6",
"stubbed",
"221",
"0.004545454545454545",
"2.0567667626491154e-05",
"0.43171052342907973",
"0.43636363636363634",
"3.259307194618086",
"1764519101.9677835",
"7.603499921970069",
"-"
],
[
"7",
"stubbed",
"289",
"0.003472222222222222",
"1.2014609765474816e-05",
"0.3447415169719474",
"0.9444444444444444",
"2.0910378118623254",
"1764519101.9912243",
"23.438300006091595",
"-"
],
[
"8",
"stubbed",
"299",
"0.0033333333333333335",
"1.107419712070875e-05",
"0.43171052342907973",
"0.42",
"3.249823297092512",
"1764519102.0057118",
"14.483599923551083",
"-"
],
[
"9",
"stubbed",
"323",
"0.0030864197530864196",
"9.496676163342829e-06",
"0.43171052342907973",
"0.37037037037037035",
"3.244294223231449",
"1764519102.0207367",
"15.021100058220327",
"-"
]
],
"shape": {
"columns": 10,
"rows": 10
}
},
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>route</th>\n",
" <th>n</th>\n",
" <th>laplacian_gap</th>\n",
" <th>phase_gradient</th>\n",
" <th>coherence_score</th>\n",
" <th>phi_s</th>\n",
" <th>delta_nfr</th>\n",
" <th>timestamp</th>\n",
" <th>elapsed_ms</th>\n",
" <th>candidate_factors</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>canonical</td>\n",
" <td>185</td>\n",
" <td>64.699265</td>\n",
" <td>0.349726</td>\n",
" <td>0.299905</td>\n",
" <td>0.391304</td>\n",
" <td>3.315722</td>\n",
" <td>1.764519e+09</td>\n",
" <td>31.6738</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>canonical</td>\n",
" <td>221</td>\n",
" <td>88.066966</td>\n",
" <td>0.398493</td>\n",
" <td>0.253543</td>\n",
" <td>0.436364</td>\n",
" <td>3.259307</td>\n",
" <td>1.764519e+09</td>\n",
" <td>13.1788</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>canonical</td>\n",
" <td>289</td>\n",
" <td>272.000000</td>\n",
" <td>0.941176</td>\n",
" <td>0.031244</td>\n",
" <td>0.944444</td>\n",
" <td>2.091038</td>\n",
" <td>1.764519e+09</td>\n",
" <td>82.3741</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>canonical</td>\n",
" <td>299</td>\n",
" <td>116.825324</td>\n",
" <td>0.388124</td>\n",
" <td>0.262760</td>\n",
" <td>0.420000</td>\n",
" <td>3.249823</td>\n",
" <td>1.764519e+09</td>\n",
" <td>70.1315</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>canonical</td>\n",
" <td>323</td>\n",
" <td>93.944487</td>\n",
" <td>0.289060</td>\n",
" <td>0.367879</td>\n",
" <td>0.370370</td>\n",
" <td>3.244294</td>\n",
" <td>1.764519e+09</td>\n",
" <td>53.7964</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>stubbed</td>\n",
" <td>185</td>\n",
" <td>0.005435</td>\n",
" <td>0.000029</td>\n",
" <td>0.431711</td>\n",
" <td>0.391304</td>\n",
" <td>3.315722</td>\n",
" <td>1.764519e+09</td>\n",
" <td>4.8280</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>stubbed</td>\n",
" <td>221</td>\n",
" <td>0.004545</td>\n",
" <td>0.000021</td>\n",
" <td>0.431711</td>\n",
" <td>0.436364</td>\n",
" <td>3.259307</td>\n",
" <td>1.764519e+09</td>\n",
" <td>7.6035</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>stubbed</td>\n",
" <td>289</td>\n",
" <td>0.003472</td>\n",
" <td>0.000012</td>\n",
" <td>0.344742</td>\n",
" <td>0.944444</td>\n",
" <td>2.091038</td>\n",
" <td>1.764519e+09</td>\n",
" <td>23.4383</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>stubbed</td>\n",
" <td>299</td>\n",
" <td>0.003333</td>\n",
" <td>0.000011</td>\n",
" <td>0.431711</td>\n",
" <td>0.420000</td>\n",
" <td>3.249823</td>\n",
" <td>1.764519e+09</td>\n",
" <td>14.4836</td>\n",
" <td>-</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>stubbed</td>\n",
" <td>323</td>\n",
" <td>0.003086</td>\n",
" <td>0.000009</td>\n",
" <td>0.431711</td>\n",
" <td>0.370370</td>\n",
" <td>3.244294</td>\n",
" <td>1.764519e+09</td>\n",
" <td>15.0211</td>\n",
" <td>-</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" route n laplacian_gap phase_gradient coherence_score phi_s \\\n",
"0 canonical 185 64.699265 0.349726 0.299905 0.391304 \n",
"1 canonical 221 88.066966 0.398493 0.253543 0.436364 \n",
"2 canonical 289 272.000000 0.941176 0.031244 0.944444 \n",
"3 canonical 299 116.825324 0.388124 0.262760 0.420000 \n",
"4 canonical 323 93.944487 0.289060 0.367879 0.370370 \n",
"5 stubbed 185 0.005435 0.000029 0.431711 0.391304 \n",
"6 stubbed 221 0.004545 0.000021 0.431711 0.436364 \n",
"7 stubbed 289 0.003472 0.000012 0.344742 0.944444 \n",
"8 stubbed 299 0.003333 0.000011 0.431711 0.420000 \n",
"9 stubbed 323 0.003086 0.000009 0.431711 0.370370 \n",
"\n",
" delta_nfr timestamp elapsed_ms candidate_factors \n",
"0 3.315722 1.764519e+09 31.6738 5 \n",
"1 3.259307 1.764519e+09 13.1788 - \n",
"2 2.091038 1.764519e+09 82.3741 - \n",
"3 3.249823 1.764519e+09 70.1315 - \n",
"4 3.244294 1.764519e+09 53.7964 - \n",
"5 3.315722 1.764519e+09 4.8280 - \n",
"6 3.259307 1.764519e+09 7.6035 - \n",
"7 2.091038 1.764519e+09 23.4383 - \n",
"8 3.249823 1.764519e+09 14.4836 - \n",
"9 3.244294 1.764519e+09 15.0211 - "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import display\n",
"import ipywidgets as widgets\n",
"\n",
"METRIC_OPTIONS = [\n",
" \"laplacian_gap\",\n",
" \"phase_gradient\",\n",
" \"coherence_score\",\n",
" \"phi_s\",\n",
" \"delta_nfr\",\n",
"]\n",
"\n",
"\n",
"def plot_metric(metric: str) -> None:\n",
" pivot = history_df.pivot(index=\"n\", columns=\"route\", values=metric)\n",
" plt.figure(figsize=(8, 4))\n",
" for route in pivot.columns:\n",
" plt.plot(pivot.index, pivot[route], marker=\"o\", label=route.title())\n",
" plt.title(f\"{metric} vs n\")\n",
" plt.xlabel(\"n\")\n",
" plt.ylabel(metric)\n",
" plt.legend()\n",
" plt.show()\n",
"\n",
" plt.figure(figsize=(6, 4))\n",
" sns.heatmap(pivot.fillna(0.0), annot=True, fmt=\".3f\", cmap=\"viridis\")\n",
" plt.title(f\"Heatmap of {metric} (route × n)\")\n",
" plt.show()\n",
"\n",
"\n",
"metric_selector = widgets.Dropdown(options=METRIC_OPTIONS, value=\"laplacian_gap\", description=\"Metric\")\n",
"widgets.interact(plot_metric, metric=metric_selector)\n",
"\n",
"display(history_df)"
]
},
{
"cell_type": "markdown",
"id": "1043297e",
"metadata": {},
"source": [
"## 7. Load Benchmark Snapshot\n",
"\n",
"Reference the automated Paley gap benchmark output to keep notebook analyses aligned with the reproducibility artifacts recorded under `results/benchmarks/`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "772e0fb9",
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"from pathlib import Path\n",
"\n",
"benchmark_dir = (Path(__file__).resolve().parent / \"../results/benchmarks\").resolve()\n",
"smoke_path = benchmark_dir / \"paley_gap_smoke.json\"\n",
"extended_path = benchmark_dir / \"paley_gap_extended.json\"\n",
"\n",
"\n",
"def _load(path: Path) -> tuple[pd.DataFrame, float]:\n",
" payload = json.loads(path.read_text())\n",
" frame = pd.DataFrame(payload[\"records\"])\n",
" frame[\"benchmark\"] = path.name\n",
" return frame, payload.get(\"timestamp\", 0.0)\n",
"\n",
"\n",
"smoke_df, smoke_ts = _load(smoke_path)\n",
"extended_df, extended_ts = _load(extended_path)\n",
"combined_df = pd.concat([smoke_df, extended_df], ignore_index=True)\n",
"\n",
"print(f\"Loaded smoke benchmark: {smoke_path} (ts={smoke_ts})\")\n",
"display(smoke_df)\n",
"print(f\"Loaded extended benchmark: {extended_path} (ts={extended_ts})\")\n",
"display(extended_df)\n",
"combined_df"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}