""" Real hardware-scaling benchmark scan and signed provenance export. Split out of the former monolithic dashboard_core.py (Phase 1 of the dashboard refactor) -- pure move, no behavior change. """ import hashlib import time import numpy as np import pandas as pd import dense_evolution as de def convert_numpy_types_to_python(obj): """Recursively converts numpy numeric types to plain Python types so a structure is JSON-serializable. Adapted from DiagnosticTools._convert_numpy_types_to_python (dash.py:2443).""" if isinstance(obj, np.integer): return int(obj) elif isinstance(obj, np.floating): return float(obj) elif isinstance(obj, np.ndarray): return obj.tolist() elif isinstance(obj, dict): return {k: convert_numpy_types_to_python(v) for k, v in obj.items()} elif isinstance(obj, list): return [convert_numpy_types_to_python(elem) for elem in obj] else: return obj def run_benchmark_scan(q_range=range(2, 15, 2)) -> pd.DataFrame: """Real hardware scaling scan: allocates a fresh DenseSVSimulator at each qubit count and times a Hadamard-on-every-qubit circuit. Adapted from DiagnosticTools.core_trigger_benchmark (dash.py:2460, canonical version). Genuinely slow (dense allocation up to 2**14) — caller should run this behind an explicit action + spinner, not automatically.""" import psutil processo_os = psutil.Process() ram_iniziale_rss = processo_os.memory_info().rss / (1024 ** 2) rows = [] for q in q_range: t0 = time.perf_counter() test_sim = de.DenseSVSimulator(n_qubits=q) circuito_stress = [["h", idx, -1] for idx in range(q)] test_sim.run_circuit_jit_beast_mode(circuito_stress) t_elapsed = time.perf_counter() - t0 ram_corrente_rss = processo_os.memory_info().rss / (1024 ** 2) delta_ram_rss = max(0.0, ram_corrente_rss - ram_iniziale_rss) rows.append({ 'Qubits': q, 'Hilbert_Dim': 2 ** q, 'Time_s': t_elapsed, 'RAM_Sim_MB': test_sim.memory_mb(), 'Delta_RAM_RSS_MB': delta_ram_rss, }) return pd.DataFrame(rows) def build_provenance_json(run_history: list) -> bytes: """Provenance export (metadata + run history), SHA-256-signed. Adapted from DiagnosticTools.core_trigger_export_json (dash.py:2511) — returns bytes for st.download_button instead of google.colab.files.download().""" import json import platform import sys import psutil try: py_ver = sys.version.split()[0] except Exception: py_ver = "3.x-unknown" serializable_runs = convert_numpy_types_to_python(run_history) provenance_payload = { "metadata": { "software_signature": f"dense-evolution-{de.__version__}", "export_timestamp_utc": time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()), "execution_environment": { "os": platform.system(), "architecture": platform.machine(), "python_version": py_ver, "hardware": { "cpu_cores_logical": psutil.cpu_count(logical=True), "total_ram_gb": round(psutil.virtual_memory().total / (1024 ** 3), 2), }, }, }, "records": serializable_runs, } raw_json_bytes = json.dumps(provenance_payload, sort_keys=True, indent=4).encode('utf-8') sha256_hash = hashlib.sha256(raw_json_bytes).hexdigest() provenance_payload["metadata"]["integrity_sha256"] = sha256_hash return json.dumps(provenance_payload, sort_keys=True, indent=4).encode('utf-8')