diff --git a/xtheta-lab/notebooks/06_synthetic_phi_recovery.ipynb b/xtheta-lab/notebooks/06_synthetic_phi_recovery.ipynb index 2220195..0be8d61 100644 --- a/xtheta-lab/notebooks/06_synthetic_phi_recovery.ipynb +++ b/xtheta-lab/notebooks/06_synthetic_phi_recovery.ipynb @@ -4,9 +4,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Notebook 06: Synthetic Phi Recovery\n", - "\n", - "This notebook validates the X-Theta fitting pipeline by generating synthetic Bell-test data with a known $\\Phi$ phase and attempting to recover it." + "# Notebook 06: Synthetic Phi Recovery + Model Comparison\n", + "**Goal:**\n", + "1. Fix small-phi recovery using direct curve fitting.\n", + "2. Compare Standard QM vs shifted X-Theta phase model.\n", + "3. Show why CHSH-only phi recovery is weak near phi=0.\n", + "4. Demonstrate the X-Theta residual signature test." ] }, { @@ -16,29 +19,177 @@ "outputs": [], "source": [ "from __future__ import annotations\n", - "import pandas as pd\n", + "\n", "import numpy as np\n", - "import sys\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", "import os\n", "from pathlib import Path\n", - "import matplotlib.pyplot as plt\n", "\n", - "# Standardized project root addition\n", - "project_root = Path(os.getcwd()).parent\n", - "if str(project_root) not in sys.path:\n", - " sys.path.append(str(project_root))\n", + "from scipy.optimize import curve_fit\n", + "from scipy.stats import chi2\n", + "\n", + "# Ensure output directory exists\n", + "output_dir = Path(\"../outputs\")\n", + "output_dir.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Theory functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def qm_standard(angle_diff):\n", + " \"\"\"\n", + " Standard flat-space singlet correlation.\n", + " \"\"\"\n", + " return -np.cos(angle_diff)\n", + "\n", + "\n", + "def xtheta_shifted(angle_diff, phi):\n", + " \"\"\"\n", + " X-Theta shifted phase model.\n", + " \"\"\"\n", + " return -np.cos(angle_diff + phi)\n", + "\n", + "\n", + "def xtheta_shifted_visibility(angle_diff, phi, visibility):\n", + " \"\"\"\n", + " X-Theta model with phase shift and visibility/noise parameter.\n", + " Useful for real experiments where contrast may be less than 1.\n", + " \"\"\"\n", + " return -visibility * np.cos(angle_diff + phi)\n", "\n", - "from xtheta.data.adapters.synthetic import generate_synthetic_xtheta_data\n", - "from xtheta.data.validation import run_open_data_chsh_validation" + "\n", + "def chsh_s_from_phi(phi):\n", + " \"\"\"\n", + " For ideal optimal CHSH settings with common phase shift phi:\n", + " |S(phi)| = 2 sqrt(2) |cos(phi)|\n", + " \"\"\"\n", + " return 2 * np.sqrt(2) * abs(np.cos(phi))\n", + "\n", + "\n", + "def phi_from_chsh_s(S):\n", + " \"\"\"\n", + " Invert ideal CHSH formula.\n", + " WARNING:\n", + " This is unstable near phi=0 because S changes quadratically.\n", + " It also cannot recover the sign of phi.\n", + " \"\"\"\n", + " ratio = np.clip(abs(S) / (2 * np.sqrt(2)), 0.0, 1.0)\n", + " return np.arccos(ratio)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Run Recovery for Multiple Phi Values\n", + "## 2. Synthetic data generation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def make_chsh4_settings():\n", + " \"\"\"\n", + " Four CHSH setting pairs.\n", + " This mimics Hensen-style four-setting data.\n", + " \"\"\"\n", + " return pd.DataFrame([\n", + " {\"setting\": \"00\", \"theta_A\": 0.0, \"theta_B\": np.pi / 4},\n", + " {\"setting\": \"01\", \"theta_A\": 0.0, \"theta_B\": -np.pi / 4},\n", + " {\"setting\": \"10\", \"theta_A\": np.pi / 2, \"theta_B\": np.pi / 4},\n", + " {\"setting\": \"11\", \"theta_A\": np.pi / 2, \"theta_B\": -np.pi / 4},\n", + " ])\n", + "\n", + "\n", + "def make_angle_scan_settings(n_angles=41):\n", + " \"\"\"\n", + " Many angle differences.\n", + " This is much better for detecting small phase shifts.\n", + " \"\"\"\n", + " angle_diffs = np.linspace(-np.pi, np.pi, n_angles)\n", + "\n", + " return pd.DataFrame({\n", + " \"setting\": [f\"scan_{i:02d}\" for i in range(n_angles)],\n", + " \"theta_A\": angle_diffs,\n", + " \"theta_B\": np.zeros_like(angle_diffs),\n", + " })\n", + "\n", "\n", - "We test a range of $\\Phi$ values from 0.0 to 0.3." + "def simulate_binary_product_data(\n", + " phi_true,\n", + " settings_df,\n", + " n_trials_per_setting=10000,\n", + " visibility=1.0,\n", + " seed=42\n", + "):\n", + " \"\"\"\n", + " Generate synthetic Bell correlation data.\n", + "\n", + " Instead of directly adding Gaussian noise to E, this simulates binary\n", + " product outcomes q = A*B in {-1,+1} with mean E.\n", + "\n", + " P(q=+1) = (1+E)/2\n", + " P(q=-1) = (1-E)/2\n", + " \"\"\"\n", + "\n", + " rng = np.random.default_rng(seed)\n", + "\n", + " rows = []\n", + "\n", + " for row in settings_df.itertuples(index=False):\n", + " angle_diff = row.theta_A - row.theta_B\n", + "\n", + " E_true = -visibility * np.cos(angle_diff + phi_true)\n", + "\n", + " p_plus = (1.0 + E_true) / 2.0\n", + " p_plus = np.clip(p_plus, 0.0, 1.0)\n", + "\n", + " products = rng.choice(\n", + " [+1, -1],\n", + " size=n_trials_per_setting,\n", + " p=[p_plus, 1.0 - p_plus]\n", + " )\n", + "\n", + " E_hat = products.mean()\n", + " N = len(products)\n", + "\n", + " # Standard error for mean of +/-1 variable\n", + " error = np.sqrt(max(1.0 - E_hat**2, 1e-12) / N)\n", + "\n", + " rows.append({\n", + " \"setting\": row.setting,\n", + " \"theta_A\": row.theta_A,\n", + " \"theta_B\": row.theta_B,\n", + " \"angle_diff\": angle_diff,\n", + " \"N\": N,\n", + " \"E_true\": E_true,\n", + " \"E\": E_hat,\n", + " \"Error\": max(error, 1e-9),\n", + " \"phi_true\": phi_true,\n", + " \"visibility_true\": visibility,\n", + " })\n", + "\n", + " return pd.DataFrame(rows)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. CHSH calculation" ] }, { @@ -47,30 +198,47 @@ "metadata": {}, "outputs": [], "source": [ - "phi_values = [0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3]\n", - "all_results = []\n", - "\n", - "for phi in phi_values:\n", - " data_iterator = generate_synthetic_xtheta_data(phi, n_trials=10000, seed=42)\n", - " res = run_open_data_chsh_validation(\n", - " data_iterator,\n", - " dataset_name=f\"synthetic_{phi:.2f}\",\n", - " output_dir=\"../outputs/synthetic_validation\",\n", - " bootstrap_samples=0, # No bootstrap for speed\n", - " claim_level=\"simulation\"\n", + "def compute_chsh_from_four_settings(df):\n", + " \"\"\"\n", + " Compute CHSH from four setting rows: 00, 01, 10, 11.\n", + "\n", + " Uses:\n", + " S = E00 + E01 + E10 - E11\n", + " \"\"\"\n", + "\n", + " lookup = {\n", + " row.setting: row.E\n", + " for row in df.itertuples(index=False)\n", + " }\n", + "\n", + " err_lookup = {\n", + " row.setting: row.Error\n", + " for row in df.itertuples(index=False)\n", + " }\n", + "\n", + " required = [\"00\", \"01\", \"10\", \"11\"]\n", + " for key in required:\n", + " if key not in lookup:\n", + " raise ValueError(f\"Missing setting {key}\")\n", + "\n", + " S = lookup[\"00\"] + lookup[\"01\"] + lookup[\"10\"] - lookup[\"11\"]\n", + "\n", + " # Independent-error approximation\n", + " S_error = np.sqrt(\n", + " err_lookup[\"00\"]**2 +\n", + " err_lookup[\"01\"]**2 +\n", + " err_lookup[\"10\"]**2 +\n", + " err_lookup[\"11\"]**2\n", " )\n", - " res['phi_true'] = phi\n", - " all_results.append(res)\n", "\n", - "df = pd.DataFrame(all_results)\n", - "df[['phi_true', 'phi_eff', 'CHSH_S', 'R_theta_eff']]" + " return abs(S), S_error" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Visualize Recovery Accuracy" + "## 4. Model fitting and comparison" ] }, { @@ -79,24 +247,168 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(8, 6))\n", - "plt.plot(df['phi_true'], df['phi_eff'], 'o-', label='Recovered')\n", - "plt.plot([0, 0.3], [0, 0.3], 'k--', label='Ideal')\n", - "plt.xlabel('True Phi')\n", - "plt.ylabel('Recovered Phi_eff')\n", - "plt.title('Synthetic Phi Recovery Validation')\n", - "plt.legend()\n", - "plt.grid(True)\n", - "plt.show()" + "def weighted_chi2(y, y_pred, errors):\n", + " errors = np.clip(errors, 1e-9, None)\n", + " return float(np.sum(((y - y_pred) / errors) ** 2))\n", + "\n", + "\n", + "def aic_from_chi2(chi2_value, k):\n", + " \"\"\"\n", + " Gaussian-error AIC up to an additive constant.\n", + " Lower is better.\n", + " \"\"\"\n", + " return chi2_value + 2 * k\n", + "\n", + "\n", + "def bic_from_chi2(chi2_value, k, n):\n", + " \"\"\"\n", + " Gaussian-error BIC up to an additive constant.\n", + " Lower is better.\n", + " \"\"\"\n", + " return chi2_value + k * np.log(n)\n", + "\n", + "\n", + "def fit_models(df, fit_visibility=False):\n", + " \"\"\"\n", + " Compare:\n", + "\n", + " Model 0: Standard QM\n", + " E = -cos(angle_diff)\n", + "\n", + " Model 1: Shifted X-Theta\n", + " E = -cos(angle_diff + phi)\n", + "\n", + " Optional Model 2:\n", + " E = -V cos(angle_diff + phi)\n", + "\n", + " Returns a dictionary with fitted parameters and model comparison.\n", + " \"\"\"\n", + "\n", + " x = df[\"angle_diff\"].values.astype(float)\n", + " y = df[\"E\"].values.astype(float)\n", + " err = df[\"Error\"].values.astype(float)\n", + " n = len(y)\n", + "\n", + " # ----------------------------\n", + " # Model 0: Standard QM, k=0\n", + " # ----------------------------\n", + " pred_qm = qm_standard(x)\n", + " chi2_qm = weighted_chi2(y, pred_qm, err)\n", + " rmse_qm = np.sqrt(np.mean((y - pred_qm)**2))\n", + "\n", + " result = {\n", + " \"n_points\": n,\n", + " \"qm_chi2\": chi2_qm,\n", + " \"qm_rmse\": rmse_qm,\n", + " \"qm_k\": 0,\n", + " \"qm_aic\": aic_from_chi2(chi2_qm, 0),\n", + " \"qm_bic\": bic_from_chi2(chi2_qm, 0, n),\n", + " }\n", + "\n", + " # ----------------------------\n", + " # Model 1: shifted phase, k=1\n", + " # ----------------------------\n", + " def model_shifted(x, phi):\n", + " return xtheta_shifted(x, phi)\n", + "\n", + " popt, pcov = curve_fit(\n", + " model_shifted,\n", + " x,\n", + " y,\n", + " sigma=err,\n", + " absolute_sigma=True,\n", + " p0=[0.0],\n", + " bounds=([-np.pi / 2], [np.pi / 2]),\n", + " maxfev=10000\n", + " )\n", + "\n", + " phi_hat = float(popt[0])\n", + " phi_se = float(np.sqrt(np.diag(pcov))[0])\n", + "\n", + " pred_shifted = model_shifted(x, phi_hat)\n", + " chi2_shifted = weighted_chi2(y, pred_shifted, err)\n", + " rmse_shifted = np.sqrt(np.mean((y - pred_shifted)**2))\n", + "\n", + " delta_chi2 = chi2_qm - chi2_shifted\n", + "\n", + " # Since shifted model has one extra parameter, use chi-square survival\n", + " # as an approximate likelihood-ratio p-value.\n", + " p_value_lrt = float(chi2.sf(max(delta_chi2, 0.0), df=1))\n", + "\n", + " result.update({\n", + " \"phi_hat\": phi_hat,\n", + " \"phi_se\": phi_se,\n", + " \"phi_z\": phi_hat / phi_se if phi_se > 0 else np.nan,\n", + " \"shifted_chi2\": chi2_shifted,\n", + " \"shifted_rmse\": rmse_shifted,\n", + " \"shifted_k\": 1,\n", + " \"shifted_aic\": aic_from_chi2(chi2_shifted, 1),\n", + " \"shifted_bic\": bic_from_chi2(chi2_shifted, 1, n),\n", + " \"delta_chi2_qm_minus_shifted\": delta_chi2,\n", + " \"lrt_p_value\": p_value_lrt,\n", + " \"preferred_by_aic\": \"shifted_xtheta\" if aic_from_chi2(chi2_shifted, 1) < aic_from_chi2(chi2_qm, 0) else \"standard_qm\",\n", + " \"preferred_by_bic\": \"shifted_xtheta\" if bic_from_chi2(chi2_shifted, 1, n) < bic_from_chi2(chi2_qm, 0, n) else \"standard_qm\",\n", + " })\n", + "\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Residual signature test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def residual_signature_test(df):\n", + " \"\"\"\n", + " Test whether residuals follow:\n", + " Delta E \u2248 phi * sin(angle_diff)\n", + "\n", + " This is the key X-Theta small-phase signature.\n", + " \"\"\"\n", + "\n", + " x = df[\"angle_diff\"].values.astype(float)\n", + " y = df[\"E\"].values.astype(float)\n", + " err = df[\"Error\"].values.astype(float)\n", + "\n", + " qm_pred = qm_standard(x)\n", + " residual = y - qm_pred\n", + "\n", + " signature = np.sin(x)\n", + "\n", + " # Estimate delta from linear regression:\n", + " # residual \u2248 phi * sin(x)\n", + " weights = 1.0 / np.clip(err, 1e-9, None)**2\n", + "\n", + " numerator = np.sum(weights * signature * residual)\n", + " denominator = np.sum(weights * signature**2)\n", + "\n", + " delta_signature = numerator / denominator\n", + " delta_signature_se = np.sqrt(1.0 / denominator)\n", + "\n", + " z = delta_signature / delta_signature_se\n", + "\n", + " return {\n", + " \"delta_signature\": delta_signature,\n", + " \"delta_signature_se\": delta_signature_se,\n", + " \"z\": z,\n", + " }" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. CHSH S Variation\n", + "## 6. Run recovery tests\n", "\n", - "Show how the CHSH S-statistic decreases as $\\Phi$ increases." + "We test for $\\phi \\in \\{0.0, 0.005, 0.01, 0.02, 0.05, 0.1\\}$." ] }, { @@ -105,14 +417,173 @@ "metadata": {}, "outputs": [], "source": [ + "def run_recovery_experiment(\n", + " mode,\n", + " phi_values,\n", + " n_trials_per_setting=10000,\n", + " visibility=1.0,\n", + " seed=42\n", + "):\n", + " \"\"\"\n", + " mode:\n", + " - \"chsh4\": only four CHSH settings\n", + " - \"angle_scan\": many angles, stronger small-phi detection\n", + " \"\"\"\n", + "\n", + " if mode == \"chsh4\":\n", + " settings = make_chsh4_settings()\n", + " elif mode == \"angle_scan\":\n", + " settings = make_angle_scan_settings(n_angles=41)\n", + " else:\n", + " raise ValueError(\"mode must be 'chsh4' or 'angle_scan'\")\n", + "\n", + " rows = []\n", + "\n", + " for phi in phi_values:\n", + " df = simulate_binary_product_data(\n", + " phi_true=phi,\n", + " settings_df=settings,\n", + " n_trials_per_setting=n_trials_per_setting,\n", + " visibility=visibility,\n", + " seed=seed\n", + " )\n", + "\n", + " fit = fit_models(df)\n", + " sig = residual_signature_test(df)\n", + "\n", + " row = {\n", + " \"mode\": mode,\n", + " \"phi_true\": phi,\n", + " \"phi_hat_direct_fit\": fit[\"phi_hat\"],\n", + " \"phi_se\": fit[\"phi_se\"],\n", + " \"phi_z\": fit[\"phi_z\"],\n", + " \"qm_chi2\": fit[\"qm_chi2\"],\n", + " \"shifted_chi2\": fit[\"shifted_chi2\"],\n", + " \"delta_chi2\": fit[\"delta_chi2_qm_minus_shifted\"],\n", + " \"lrt_p_value\": fit[\"lrt_p_value\"],\n", + " \"preferred_by_aic\": fit[\"preferred_by_aic\"],\n", + " \"preferred_by_bic\": fit[\"preferred_by_bic\"],\n", + " \"signature_z\": sig[\"z\"],\n", + " \"qm_rmse\": fit[\"qm_rmse\"],\n", + " \"shifted_rmse\": fit[\"shifted_rmse\"],\n", + " }\n", + "\n", + " if mode == \"chsh4\":\n", + " S, S_error = compute_chsh_from_four_settings(df)\n", + " row[\"CHSH_S\"] = S\n", + " row[\"CHSH_S_error\" ] = S_error\n", + " row[\"phi_from_chsh_only\"] = phi_from_chsh_s(S)\n", + " else:\n", + " row[\"CHSH_S\"] = np.nan\n", + " row[\"CHSH_S_error\"] = np.nan\n", + " row[\"phi_from_chsh_only\"] = np.nan\n", + "\n", + " rows.append(row)\n", + "\n", + " return pd.DataFrame(rows)\n", + "\n", + "\n", + "phi_values = [0.0, 0.005, 0.01, 0.02, 0.05, 0.1]\n", + "\n", + "df_chsh4 = run_recovery_experiment(\n", + " mode=\"chsh4\",\n", + " phi_values=phi_values,\n", + " n_trials_per_setting=100000, # Large N to see small effects\n", + " visibility=1.0,\n", + " seed=42\n", + ")\n", + "\n", + "df_scan = run_recovery_experiment(\n", + " mode=\"angle_scan\",\n", + " phi_values=phi_values,\n", + " n_trials_per_setting=10000,\n", + " visibility=1.0,\n", + " seed=42\n", + ")\n", + "\n", + "print(\"CHSH-4 recovery:\")\n", + "display(df_chsh4)\n", + "\n", + "print(\"Angle-scan recovery:\")\n", + "display(df_scan)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Visualization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 7.1 Recovery Accuracy\n", "plt.figure(figsize=(8, 6))\n", - "plt.plot(df['phi_true'], df['CHSH_S'], 's-')\n", - "plt.xlabel('True Phi')\n", - "plt.ylabel('CHSH S')\n", - "plt.title('CHSH S vs Relational Phase Phi')\n", - "plt.grid(True)\n", + "plt.errorbar(df_chsh4[\"phi_true\"], df_chsh4[\"phi_hat_direct_fit\"], yerr=df_chsh4[\"phi_se\"], fmt=\"o-\", label=\"4 CHSH settings\")\n", + "plt.errorbar(df_scan[\"phi_true\"], df_scan[\"phi_hat_direct_fit\"], yerr=df_scan[\"phi_se\"], fmt=\"s-\", label=\"Angle scan\")\n", + "plt.plot([0, 0.1], [0, 0.1], \"k--\", label=\"Ideal\")\n", + "plt.xlabel(\"True $\\\\phi$\")\n", + "plt.ylabel(\"Recovered $\\\\hat{\\\\phi}$\")\n", + "plt.title(\"Synthetic Phi Recovery Accuracy\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.savefig(output_dir / \"synthetic_phi_recovery_model_fit.png\")\n", + "plt.show()\n", + "\n", + "# 7.2 CHSH Instability\n", + "plt.figure(figsize=(8, 6))\n", + "plt.plot(df_chsh4[\"phi_true\"], df_chsh4[\"phi_from_chsh_only\"], \"o-\", label=\"Phi from CHSH magnitude\")\n", + "plt.plot([0, 0.1], [0, 0.1], \"k--\", label=\"Ideal\")\n", + "plt.xlabel(\"True $\\\\phi$\")\n", + "plt.ylabel(\"Recovered $\\\\phi$ (CHSH-only)\")\n", + "plt.title(\"CHSH-Only Phi Recovery Is Unstable Near Zero\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.savefig(output_dir / \"synthetic_phi_recovery_small_phi_error.png\")\n", + "plt.show()\n", + "\n", + "# 7.3 Model Comparison (Delta Chi2)\n", + "plt.figure(figsize=(8, 6))\n", + "plt.plot(df_chsh4[\"phi_true\"], df_chsh4[\"delta_chi2\"], \"o-\", label=\"4 CHSH settings\")\n", + "plt.plot(df_scan[\"phi_true\"], df_scan[\"delta_chi2\"], \"s-\", label=\"Angle scan\")\n", + "plt.axhline(3.84, color=\"r\", linestyle=\"--\", label=\"95% Confidence Threshold\")\n", + "plt.xlabel(\"True $\\\\phi$\")\n", + "plt.ylabel(\"$\\\\Delta\\\\chi^2 = \\\\chi^2_{QM} - \\\\chi^2_{shifted}$\")\n", + "plt.title(\"Model Comparison: X-Theta Improvement over QM\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.savefig(output_dir / \"synthetic_phi_recovery_model_comparison.png\")\n", + "plt.show()\n", + "\n", + "# 7.4 Residual Signature (Z-score)\n", + "plt.figure(figsize=(8, 6))\n", + "plt.plot(df_scan[\"phi_true\"], df_scan[\"signature_z\"], \"s-\", label=\"Residual Signature Z-score\")\n", + "plt.axhline(2.0, color=\"r\", linestyle=\"--\", label=\"Z=2 threshold\")\n", + "plt.xlabel(\"True $\\\\phi$\")\n", + "plt.ylabel(\"Signature Z-score\")\n", + "plt.title(\"Falsifiable X-Theta Residual Signature\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.savefig(output_dir / \"synthetic_phi_recovery_residuals.png\")\n", "plt.show()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Milestone 4: Unique Physical Prediction\n", + "\n", + "Standard QM can fit the dominant correlation curve, but it should not recover a stable hidden phase-offset parameter from residual structure. The shifted X-Theta phase model predicts a small but recoverable phase signature, especially visible through residual asymmetry and improved small-phi recovery.\n", + "\n", + "> **Crucial Claim:** Unlike standard flat-space quantum mechanics, which predicts no residual path-dependent angular phase after calibration, X-Theta predicts a transport-induced phase holonomy ($\\delta_{\\gamma}$) whose observable signature is a first-order residual ($\\Delta E \\approx \\delta_{\\gamma} \\sin(\\theta_a - \\theta_b)$).\n", + "\n", + "**Caveat:** This is a synthetic falsification/recovery test. It does not prove the theory from real experimental data, but it defines a measurable prediction that can later be tested against open Bell datasets." + ] } ], "metadata": {