{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MxdcZtbtsnFd"
   },
   "source": "# Quantum-Driven Adaptive Metasurface\n## Unit-Cell, Surrogate and QUBO Benchmark Notebook v1.0\n\nBu notebook, laboratuvar ölçeğinde **reconfigurable metasurface / elektromanyetik response optimization** araştırması için solver-independent bir computational pipeline kurar.\n\n```text\nCST / HFSS / COMSOL\n        ↓\nCSV export\n        ↓\nschema validation\n        ↓\nEM feature engineering\n        ↓\nsurrogate model\n        ↓\nbinary configuration objective\n        ↓\nQUBO\n        ↓\nexact / classical / quantum benchmark\n        ↓\nfull-wave validation\n```\n\nİlk yazılım doğrulama sistemi 4×4 = 16 binary variable ve 2^16 = 65,536 configuration içerir.\n\n> Synthetic data cells are for pipeline testing only and must not be presented as physical simulation results.",
   "id": "MxdcZtbtsnFd"
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "5wzoZxtzsnFk",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060326552,
     "user_tz": -180,
     "elapsed": 1346,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "7986449c-7a88-448e-ef07-ea9d2d41f874"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Ready: /content\n"
     ]
    }
   ],
   "source": "from pathlib import Path\nimport itertools\nimport json\nimport math\nimport time\nimport warnings\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.neural_network import MLPRegressor\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n\nRANDOM_SEED = 42\nrng = np.random.default_rng(RANDOM_SEED)\n\nBASE_DIR = Path.cwd()\nDATA_DIR = BASE_DIR / \"data\"\nRAW_DIR = DATA_DIR / \"raw_em\"\nMASTER_DIR = DATA_DIR / \"master\"\n\nfor p in [RAW_DIR, MASTER_DIR]:\n    p.mkdir(parents=True, exist_ok=True)\n\nprint(\"Ready:\", BASE_DIR)",
   "id": "5wzoZxtzsnFk"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "o_tZDdlFsnFp"
   },
   "source": "## 1. Canonical Unit-Cell Specification\n\nOrtak değişken isimleri:\n\n| Variable | Meaning | Initial |\n|---|---|---:|\n| `px_mm` | period X | 12.0 |\n| `py_mm` | period Y | 12.0 |\n| `h_mm` | substrate thickness | 1.60 |\n| `er` | relative permittivity | 3.5 |\n| `tanD` | dielectric loss tangent | 0.015 |\n| `tm_mm` | metal thickness | 0.035 |\n| `lr_mm` | resonator length | 9.0 |\n| `wr_mm` | resonator width | 1.8 |\n| `gs_mm` | switch gap | 0.40 |\n| `wb_mm` | bias-line width | 0.30 |\n| `br_mm` | branch length | 3.0 |\n| `bw_mm` | branch width | 0.60 |\n| `ox_mm` | X offset | 0 |\n| `oy_mm` | Y offset | 0 |\n\nState:\n\n\\[\nb_i \\in \\{0,1\\}\n\\]\n\nX-band development range: 8–12 GHz.  \nK-band development range: 18–27 GHz.",
   "id": "o_tZDdlFsnFp"
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "jlqZeguNsnFp",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060326556,
     "user_tz": -180,
     "elapsed": 139,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "921bd242-be76-4c53-ea24-1a625c586ea0"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "(True, [])\n"
     ]
    }
   ],
   "source": "GEOMETRY_RANGES = {\n    \"px_mm\": (10.0, 14.0),\n    \"py_mm\": (10.0, 14.0),\n    \"h_mm\": (0.8, 2.4),\n    \"er\": (2.5, 6.0),\n    \"tanD\": (0.005, 0.040),\n    \"tm_mm\": (0.018, 0.070),\n    \"lr_mm\": (7.0, 11.0),\n    \"wr_mm\": (1.0, 3.0),\n    \"gs_mm\": (0.15, 0.80),\n    \"wb_mm\": (0.15, 0.60),\n    \"br_mm\": (1.0, 5.0),\n    \"bw_mm\": (0.20, 1.0),\n    \"ox_mm\": (-1.0, 1.0),\n    \"oy_mm\": (-1.0, 1.0),\n}\n\ndef geometry_constraints(g):\n    issues = []\n    if not (g[\"lr_mm\"] < g[\"px_mm\"] - 2.0):\n        issues.append(\"lr_mm < px_mm - 2.0\")\n    if not (g[\"wr_mm\"] < g[\"py_mm\"] - 2.0):\n        issues.append(\"wr_mm < py_mm - 2.0\")\n    if not (g[\"gs_mm\"] < g[\"lr_mm\"] / 4.0):\n        issues.append(\"gs_mm < lr_mm/4\")\n    if not (g[\"br_mm\"] < g[\"lr_mm\"] / 2.0):\n        issues.append(\"br_mm < lr_mm/2\")\n    if not (g[\"wb_mm\"] < g[\"wr_mm\"]):\n        issues.append(\"wb_mm < wr_mm\")\n    return len(issues) == 0, issues\n\ndefault_geometry = {\n    \"geometry_id\":\"G000001\",\n    \"px_mm\":12.0, \"py_mm\":12.0, \"h_mm\":1.60,\n    \"er\":3.5, \"tanD\":0.015, \"tm_mm\":0.035,\n    \"lr_mm\":9.0, \"wr_mm\":1.8, \"gs_mm\":0.40, \"wb_mm\":0.30,\n    \"br_mm\":3.0, \"bw_mm\":0.60, \"ox_mm\":0.0, \"oy_mm\":0.0,\n}\n\nprint(geometry_constraints(default_geometry))",
   "id": "jlqZeguNsnFp"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "GPg-4hwPsnFq"
   },
   "source": "## 2. Solver-independent EM CSV schema\n\nRequired:\n\n```text\nsample_id\ngeometry_id\nconfiguration_id\nenvironment_id\nfrequency_GHz\ntheta_deg\nphi_deg\npolarization\nstate\nS11_real\nS11_imag\nS21_real\nS21_imag\n```\n\nOptional:\n\n```text\nS11_mag\nS11_phase_deg\nS21_mag\nS21_phase_deg\nreturn_loss_dB\ntransmission_dB\nRCS_dBsm\nmesh_converged\nsolver_status\nsolver\nsolver_version\nmodel_version\nmaterial_version\nmesh_version\n```\n\n`Hamming_Distance` artık zorunlu kolon değildir. Transition cost, iki binary configuration state üzerinden hesaplanır.",
   "id": "GPg-4hwPsnFq"
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "vLjbJnUxsnFr",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060326557,
     "user_tz": -180,
     "elapsed": 85,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "outputs": [],
   "source": "REQUIRED_EM_COLUMNS = [\n    \"sample_id\",\"geometry_id\",\"configuration_id\",\"environment_id\",\n    \"frequency_GHz\",\"theta_deg\",\"phi_deg\",\"polarization\",\"state\",\n    \"S11_real\",\"S11_imag\",\"S21_real\",\"S21_imag\"\n]\n\ndef validate_em_schema(df, strict=False):\n    missing = [c for c in REQUIRED_EM_COLUMNS if c not in df.columns]\n    if missing:\n        raise ValueError(f\"Missing required columns: {missing}\")\n\n    if not df[\"polarization\"].isin([\"TE\",\"TM\"]).all():\n        raise ValueError(\"polarization must be TE or TM\")\n\n    state = pd.to_numeric(df[\"state\"], errors=\"coerce\")\n    if state.isna().any() or not state.isin([0,1]).all():\n        raise ValueError(\"state must be binary 0/1\")\n\n    for c in [\"frequency_GHz\",\"theta_deg\",\"phi_deg\",\n              \"S11_real\",\"S11_imag\",\"S21_real\",\"S21_imag\"]:\n        if pd.to_numeric(df[c], errors=\"coerce\").isna().any():\n            raise ValueError(f\"{c} contains invalid values\")\n\n    if strict and \"mesh_converged\" in df.columns:\n        bad = df[\"mesh_converged\"].astype(str).str.lower().isin([\"0\",\"false\",\"no\"])\n        if bad.any():\n            warnings.warn(f\"{bad.sum()} rows are not mesh-converged\")\n    return True\n\ndef add_em_features(df):\n    out = df.copy()\n    s11r = pd.to_numeric(out[\"S11_real\"], errors=\"coerce\")\n    s11i = pd.to_numeric(out[\"S11_imag\"], errors=\"coerce\")\n    s21r = pd.to_numeric(out[\"S21_real\"], errors=\"coerce\")\n    s21i = pd.to_numeric(out[\"S21_imag\"], errors=\"coerce\")\n\n    out[\"S11_mag\"] = np.sqrt(s11r**2 + s11i**2)\n    out[\"S21_mag\"] = np.sqrt(s21r**2 + s21i**2)\n    out[\"S11_phase_deg\"] = np.degrees(np.arctan2(s11i, s11r))\n    out[\"S21_phase_deg\"] = np.degrees(np.arctan2(s21i, s21r))\n    out[\"return_loss_dB\"] = -20*np.log10(np.maximum(out[\"S11_mag\"], 1e-12))\n    out[\"transmission_dB\"] = 20*np.log10(np.maximum(out[\"S21_mag\"], 1e-12))\n    return out",
   "id": "vLjbJnUxsnFr"
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Mh7mCpUesnFr",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060326561,
     "user_tz": -180,
     "elapsed": 85,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "02be962e-527d-41a7-d463-459aa6c60bb1"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "CSV loader ready.\n"
     ]
    }
   ],
   "source": "def load_em_csv_folder(folder=RAW_DIR):\n    files = sorted(Path(folder).glob(\"*.csv\"))\n    if not files:\n        return pd.DataFrame()\n    frames = []\n    for f in files:\n        df = pd.read_csv(f)\n        validate_em_schema(df)\n        df = add_em_features(df)\n        df[\"source_file\"] = f.name\n        frames.append(df)\n    return pd.concat(frames, ignore_index=True)\n\nprint(\"CSV loader ready.\")",
   "id": "Mh7mCpUesnFr"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "sE6hufJIsnFs"
   },
   "source": "## 3. Synthetic fallback\n\nAşağıdaki model fiziksel solver değildir. Sadece:\n\n- parser\n- surrogate\n- objective\n- QUBO\n- exact/classical benchmark\n\npipeline'ını uçtan uca test etmek içindir.",
   "id": "sE6hufJIsnFs"
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "3jXubntdsnFt",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060327049,
     "user_tz": -180,
     "elapsed": 500,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "bcb4a88b-fc00-455a-9d7a-14607b2906bb"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Synthetic rows: 20400\n"
     ]
    }
   ],
   "source": "def synthetic_em_response(frequency_GHz, theta_deg, polarization,\n                          state, er, tanD, geometry=None):\n    g = geometry or default_geometry\n\n    fx = 10.0 + 0.35*(er-3.5) - 0.20*state + 0.02*(g[\"lr_mm\"]-9.0)\n    fk = 24.0 + 0.50*(er-3.5) - 0.30*state + 0.03*(g[\"lr_mm\"]-9.0)\n    bwx = 0.85 + 0.06*g[\"wr_mm\"]\n    bwk = 1.25 + 0.10*g[\"wr_mm\"]\n\n    dip_x = np.exp(-0.5*((frequency_GHz-fx)/bwx)**2)\n    dip_k = np.exp(-0.5*((frequency_GHz-fk)/bwk)**2)\n\n    angle_factor = max(0.50, 1.0 - 0.003*(theta_deg**2))\n    pol_factor = 1.0 if polarization == \"TE\" else 0.96\n\n    mag = np.clip(\n        0.82 - 0.48*dip_x - 0.28*dip_k + 0.03*tanD*100 + 0.02*state,\n        0.02, 0.98\n    )\n    mag *= angle_factor*pol_factor\n\n    phase = 150*np.tanh((frequency_GHz-fx)/bwx)           + 85*np.tanh((frequency_GHz-fk)/bwk)           + 25*state\n\n    pr = np.radians(phase)\n    s11r, s11i = mag*np.cos(pr), mag*np.sin(pr)\n\n    s21mag = np.clip(0.08 + 0.20*(1-dip_x) + 0.10*(1-dip_k), 0.001, 0.45)\n    s21r, s21i = s21mag*np.cos(pr/2), s21mag*np.sin(pr/2)\n\n    return s11r, s11i, s21r, s21i\n\ndef generate_synthetic_em(n_geometries=20):\n    rows = []\n    frequencies = np.arange(8.0, 12.01, 0.25)\n    angles = [0,10,20,30,40]\n    pols = [\"TE\",\"TM\"]\n\n    environments = [\n        (\"E0001\",2.5,0.010),\n        (\"E0002\",4.0,0.020),\n        (\"E0003\",6.0,0.035),\n    ]\n\n    for gi in range(n_geometries):\n        g = default_geometry.copy()\n        g[\"geometry_id\"] = f\"G{gi+1:06d}\"\n\n        for k,(lo,hi) in GEOMETRY_RANGES.items():\n            g[k] = rng.uniform(lo,hi)\n\n        g[\"lr_mm\"] = min(g[\"lr_mm\"], g[\"px_mm\"]-2.1)\n        g[\"wr_mm\"] = min(g[\"wr_mm\"], g[\"py_mm\"]-2.1)\n        g[\"gs_mm\"] = min(g[\"gs_mm\"], g[\"lr_mm\"]/4.0-0.02)\n        g[\"br_mm\"] = min(g[\"br_mm\"], g[\"lr_mm\"]/2.0-0.05)\n        g[\"wb_mm\"] = min(g[\"wb_mm\"], g[\"wr_mm\"]-0.05)\n\n        for env_id,er,tanD in environments:\n            for state in [0,1]:\n                for pol in pols:\n                    for theta in angles:\n                        for f in frequencies:\n                            s11r,s11i,s21r,s21i = synthetic_em_response(\n                                f,theta,pol,state,er,tanD,g\n                            )\n                            rows.append({\n                                \"sample_id\":f\"S{len(rows)+1:08d}\",\n                                \"geometry_id\":g[\"geometry_id\"],\n                                \"configuration_id\":f\"{g['geometry_id']}_S{state}\",\n                                \"environment_id\":env_id,\n                                \"frequency_GHz\":f,\n                                \"theta_deg\":theta,\n                                \"phi_deg\":0.0,\n                                \"polarization\":pol,\n                                \"state\":state,\n                                \"er\":er, \"tanD\":tanD,\n                                \"px_mm\":g[\"px_mm\"], \"py_mm\":g[\"py_mm\"], \"h_mm\":g[\"h_mm\"],\n                                \"lr_mm\":g[\"lr_mm\"], \"wr_mm\":g[\"wr_mm\"],\n                                \"gs_mm\":g[\"gs_mm\"], \"wb_mm\":g[\"wb_mm\"],\n                                \"tm_mm\":g[\"tm_mm\"],\n                                \"S11_real\":s11r, \"S11_imag\":s11i,\n                                \"S21_real\":s21r, \"S21_imag\":s21i,\n                                \"mesh_converged\":1,\n                                \"solver_status\":\"SYNTHETIC_ONLY\",\n                            })\n    return add_em_features(pd.DataFrame(rows))\n\nsynthetic_df = generate_synthetic_em(20)\nprint(\"Synthetic rows:\", len(synthetic_df))",
   "id": "3jXubntdsnFt"
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 407
    },
    "id": "1z2j6PhysnFu",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060327320,
     "user_tz": -180,
     "elapsed": 267,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "cd013aec-ba55-463e-b088-26055bd345e2"
   },
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ],
      "image/png": "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\n"
     },
     "metadata": {}
    }
   ],
   "source": "example = synthetic_df[\n    (synthetic_df.environment_id==\"E0001\") &\n    (synthetic_df.state==0) &\n    (synthetic_df.polarization==\"TE\") &\n    (synthetic_df.theta_deg==0)\n]\n\nplt.figure(figsize=(8,4))\nplt.plot(example.frequency_GHz, example.S11_mag, marker=\"o\", ms=3)\nplt.xlabel(\"Frequency (GHz)\")\nplt.ylabel(\"|S11|\")\nplt.title(\"Synthetic pipeline sanity check\")\nplt.grid(True, alpha=0.25)\nplt.tight_layout()\nplt.show()",
   "id": "1z2j6PhysnFu"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "sedZCNGSsnFv"
   },
   "source": "## 4. Surrogate model\n\nInput:\n\n\\[\nX=[p_x,p_y,h,\\epsilon_r,\tan\\delta,l_r,w_r,g_s,w_b,state,f,\theta,pol]\n\\]\n\nOutput:\n\n\\[\nY=[Re(S_{11}),Im(S_{11}),Re(S_{21}),Im(S_{21})]\n\\]",
   "id": "sedZCNGSsnFv"
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Wp9X7sPssnFw",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060336081,
     "user_tz": -180,
     "elapsed": 8763,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "9c5951f0-a549-4616-a5d6-e8fd449f8178"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Overall RMSE: 0.007494458398215648\n",
      "Overall MAE : 0.005628816320273098\n",
      "Overall R2  : 0.9989581903196803\n"
     ]
    }
   ],
   "source": "model_df = pd.get_dummies(synthetic_df, columns=[\"polarization\"], dtype=float)\n\nfeatures = [\n    \"px_mm\",\"py_mm\",\"h_mm\",\"er\",\"tanD\",\n    \"lr_mm\",\"wr_mm\",\"gs_mm\",\"wb_mm\",\n    \"state\",\"frequency_GHz\",\"theta_deg\",\n    \"polarization_TE\",\"polarization_TM\"\n]\ntargets = [\"S11_real\",\"S11_imag\",\"S21_real\",\"S21_imag\"]\n\nX = model_df[features].astype(float)\nY = model_df[targets].astype(float)\n\nX_train,X_test,Y_train,Y_test = train_test_split(\n    X,Y,test_size=0.20,random_state=RANDOM_SEED\n)\n\nsurrogate = Pipeline([\n    (\"scale\", StandardScaler()),\n    (\"mlp\", MLPRegressor(\n        hidden_layer_sizes=(128,64,32),\n        activation=\"relu\",\n        random_state=RANDOM_SEED,\n        max_iter=1200,\n        early_stopping=True,\n        validation_fraction=0.15,\n    ))\n])\n\nsurrogate.fit(X_train,Y_train)\nY_pred = surrogate.predict(X_test)\n\nprint(\"Overall RMSE:\", np.sqrt(mean_squared_error(Y_test,Y_pred)))\nprint(\"Overall MAE :\", mean_absolute_error(Y_test,Y_pred))\nprint(\"Overall R2  :\", r2_score(Y_test,Y_pred))",
   "id": "Wp9X7sPssnFw"
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 173
    },
    "id": "W-raJglCsnFx",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060336142,
     "user_tz": -180,
     "elapsed": 58,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "ea1ee468-fd1d-4efa-f78c-bf976bad2a5a"
   },
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "     target      RMSE       MAE        R2\n",
       "0  S11_real  0.009014  0.006900  0.999134\n",
       "1  S11_imag  0.009337  0.007240  0.998694\n",
       "2  S21_real  0.005036  0.003961  0.998839\n",
       "3  S21_imag  0.005557  0.004415  0.999166"
      ],
      "text/html": [
       "\n",
       "  <div id=\"df-cf51da31-088f-46fc-bcd9-02f423bb1b0e\" class=\"colab-df-container\">\n",
       "    <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>target</th>\n",
       "      <th>RMSE</th>\n",
       "      <th>MAE</th>\n",
       "      <th>R2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>S11_real</td>\n",
       "      <td>0.009014</td>\n",
       "      <td>0.006900</td>\n",
       "      <td>0.999134</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>S11_imag</td>\n",
       "      <td>0.009337</td>\n",
       "      <td>0.007240</td>\n",
       "      <td>0.998694</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>S21_real</td>\n",
       "      <td>0.005036</td>\n",
       "      <td>0.003961</td>\n",
       "      <td>0.998839</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>S21_imag</td>\n",
       "      <td>0.005557</td>\n",
       "      <td>0.004415</td>\n",
       "      <td>0.999166</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-cf51da31-088f-46fc-bcd9-02f423bb1b0e')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-cf51da31-088f-46fc-bcd9-02f423bb1b0e button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-cf51da31-088f-46fc-bcd9-02f423bb1b0e');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "  <div id=\"id_96a208bf-1f6c-4a56-9d1b-af4f0e2a0562\">\n",
       "    <style>\n",
       "      .colab-df-generate {\n",
       "        background-color: #E8F0FE;\n",
       "        border: none;\n",
       "        border-radius: 50%;\n",
       "        cursor: pointer;\n",
       "        display: none;\n",
       "        fill: #1967D2;\n",
       "        height: 32px;\n",
       "        padding: 0 0 0 0;\n",
       "        width: 32px;\n",
       "      }\n",
       "\n",
       "      .colab-df-generate:hover {\n",
       "        background-color: #E2EBFA;\n",
       "        box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "        fill: #174EA6;\n",
       "      }\n",
       "\n",
       "      [theme=dark] .colab-df-generate {\n",
       "        background-color: #3B4455;\n",
       "        fill: #D2E3FC;\n",
       "      }\n",
       "\n",
       "      [theme=dark] .colab-df-generate:hover {\n",
       "        background-color: #434B5C;\n",
       "        box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "        filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "        fill: #FFFFFF;\n",
       "      }\n",
       "    </style>\n",
       "    <button class=\"colab-df-generate\" onclick=\"generateWithVariable('surrogate_metrics')\"\n",
       "            title=\"Generate code using this dataframe.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
       "       width=\"24px\">\n",
       "    <path d=\"M7,19H8.4L18.45,9,17,7.55,7,17.6ZM5,21V16.75L18.45,3.32a2,2,0,0,1,2.83,0l1.4,1.43a1.91,1.91,0,0,1,.58,1.4,1.91,1.91,0,0,1-.58,1.4L9.25,21ZM18.45,9,17,7.55Zm-12,3A5.31,5.31,0,0,0,4.9,8.1,5.31,5.31,0,0,0,1,6.5,5.31,5.31,0,0,0,4.9,4.9,5.31,5.31,0,0,0,6.5,1,5.31,5.31,0,0,0,8.1,4.9,5.31,5.31,0,0,0,12,6.5,5.46,5.46,0,0,0,6.5,12Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "    <script>\n",
       "      (() => {\n",
       "      const buttonEl =\n",
       "        document.querySelector('#id_96a208bf-1f6c-4a56-9d1b-af4f0e2a0562 button.colab-df-generate');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      buttonEl.onclick = () => {\n",
       "        google.colab.notebook.generateWithVariable('surrogate_metrics');\n",
       "      }\n",
       "      })();\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "dataframe",
       "variable_name": "surrogate_metrics",
       "summary": "{\n  \"name\": \"surrogate_metrics\",\n  \"rows\": 4,\n  \"fields\": [\n    {\n      \"column\": \"target\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 4,\n        \"samples\": [\n          \"S11_imag\",\n          \"S21_imag\",\n          \"S11_real\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"RMSE\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.0022532863254386723,\n        \"min\": 0.005036205727929492,\n        \"max\": 0.009336573462672835,\n        \"num_unique_values\": 4,\n        \"samples\": [\n          0.009336573462672835,\n          0.005556994999342426,\n          0.009014014707648703\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"MAE\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.001680165031364843,\n        \"min\": 0.003960528308650299,\n        \"max\": 0.007240232643922374,\n        \"num_unique_values\": 4,\n        \"samples\": [\n          0.007240232643922374,\n          0.004414795133701136,\n          0.00689970919481854\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"R2\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.00022979046486868064,\n        \"min\": 0.9986937583426205,\n        \"max\": 0.9991662269013807,\n        \"num_unique_values\": 4,\n        \"samples\": [\n          0.9986937583426205,\n          0.9991662269013807,\n          0.9991340654751988\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}"
      }
     },
     "metadata": {},
     "execution_count": 8
    }
   ],
   "source": "rows=[]\nfor i,t in enumerate(targets):\n    yt = Y_test.iloc[:,i].to_numpy()\n    yp = Y_pred[:,i]\n    rows.append({\n        \"target\":t,\n        \"RMSE\":np.sqrt(mean_squared_error(yt,yp)),\n        \"MAE\":mean_absolute_error(yt,yp),\n        \"R2\":r2_score(yt,yp)\n    })\nsurrogate_metrics = pd.DataFrame(rows)\nsurrogate_metrics",
   "id": "W-raJglCsnFx"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "NG9ALeIVsnFx"
   },
   "source": "## 5. 4×4 binary array benchmark\n\n\\[\nN=16\n\\]\n\n\\[\n2^{16}=65,536\n\\]\n\nconfiguration.\n\nBu exact enumeration sonucu, classical/quantum optimizerlar için ground-truth benchmark olarak kullanılır.",
   "id": "NG9ALeIVsnFx"
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "KVYzgZBZsnFy",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060336330,
     "user_tz": -180,
     "elapsed": 105,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "f4ced3a7-69ac-4bc4-9089-2bbfb67dc0ef"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Variables: 16\n",
      "Exact search space: 65536\n"
     ]
    }
   ],
   "source": "N_CELLS = 16\nCELL_POSITIONS = [(ix,iy) for iy in range(4) for ix in range(4)]\n\ndef interaction_matrix(n, decay=0.75):\n    coords = np.array(CELL_POSITIONS[:n], dtype=float)\n    M = np.zeros((n,n))\n    for i in range(n):\n        for j in range(i+1,n):\n            d = np.linalg.norm(coords[i]-coords[j])\n            M[i,j] = M[j,i] = np.exp(-d/decay)\n    return M\n\nINTERACTION = interaction_matrix(N_CELLS)\n\ndef hamming_distance(a,b):\n    a=np.asarray(a,dtype=np.int8)\n    b=np.asarray(b,dtype=np.int8)\n    if a.shape != b.shape:\n        raise ValueError(f\"Shape mismatch: {a.shape} != {b.shape}\")\n    return int(np.count_nonzero(a!=b))\n\nlinear_bias = np.linspace(-0.20,0.25,N_CELLS)\n\ndef benchmark_binary_objective(b):\n    b=np.asarray(b,dtype=float)\n    linear = np.dot(linear_bias,b)\n    pairwise = 0.30*np.sum(np.triu(INTERACTION,1)*(b[:,None]*b[None,:]))\n    return float(linear + pairwise)\n\nprint(\"Variables:\", N_CELLS)\nprint(\"Exact search space:\", 2**N_CELLS)",
   "id": "KVYzgZBZsnFy"
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "wY_sCDTJsnFz",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060337441,
     "user_tz": -180,
     "elapsed": 1107,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "c9a244e7-6798-4c5d-b5b8-e174eff4e662"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Exact value : -0.3745811315318213\n",
      "Exact state : 1101000000000000\n",
      "Exact runtime: 1.1911054009999873 s\n"
     ]
    }
   ],
   "source": "def exact_binary_optimum(n, objective):\n    best_state = None\n    best_value = np.inf\n    for bits in itertools.product([0,1], repeat=n):\n        b = np.asarray(bits,dtype=np.int8)\n        v = objective(b)\n        if v < best_value:\n            best_value = v\n            best_state = b.copy()\n    return best_state, float(best_value)\n\nt0=time.perf_counter()\nexact_state, exact_value = exact_binary_optimum(N_CELLS, benchmark_binary_objective)\nexact_runtime=time.perf_counter()-t0\n\nprint(\"Exact value :\", exact_value)\nprint(\"Exact state :\", \"\".join(map(str,exact_state)))\nprint(\"Exact runtime:\", exact_runtime, \"s\")",
   "id": "wY_sCDTJsnFz"
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "82GbiNGXsnFz",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060338126,
     "user_tz": -180,
     "elapsed": 682,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "ce9ff150-3ab0-42b9-acc6-d3f5bb09d5d4"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "SA value: -0.3745811315318213\n",
      "SA gap  : 0.0\n",
      "SA state: 1101000000000000\n"
     ]
    }
   ],
   "source": "def simulated_annealing(objective,n,steps=25000,T0=1.0,Tend=1e-4,seed=42):\n    local_rng=np.random.default_rng(seed)\n    state=local_rng.integers(0,2,size=n,dtype=np.int8)\n    value=objective(state)\n    best_state=state.copy()\n    best_value=value\n\n    for k in range(steps):\n        T=T0*(Tend/T0)**(k/max(steps-1,1))\n        j=local_rng.integers(0,n)\n        cand=state.copy()\n        cand[j]^=1\n        cand_value=objective(cand)\n        delta=cand_value-value\n\n        if delta < 0 or local_rng.random()<np.exp(-delta/max(T,1e-12)):\n            state,value=cand,cand_value\n            if value<best_value:\n                best_state,best_value=state.copy(),value\n\n    return best_state,float(best_value)\n\nt0=time.perf_counter()\nsa_state,sa_value=simulated_annealing(\n    benchmark_binary_objective,N_CELLS,seed=RANDOM_SEED\n)\nsa_runtime=time.perf_counter()-t0\n\nprint(\"SA value:\",sa_value)\nprint(\"SA gap  :\",sa_value-exact_value)\nprint(\"SA state:\", \"\".join(map(str,sa_state)))",
   "id": "82GbiNGXsnFz"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cEECyzHisnF0"
   },
   "source": "## 6. QUBO\n\n\\[\nJ(b)=c+\\sum_i a_i b_i+\\sum_{i<j}q_{ij}b_i b_j\n\\]\n\nve:\n\n\\[\nJ(b)=b^TQb+c.\n\\]\n\nQuadratic model, sampled objective valuesinden fit edilir.",
   "id": "cEECyzHisnF0"
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "vJtgz_PvsnF0",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060339992,
     "user_tz": -180,
     "elapsed": 1736,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "f924222e-7a1d-4d7b-b7da-2f39f8f524d0"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "QUBO reconstruction RMSE: 7.36822885071232e-15\n",
      "Max abs error: 1.8207657603852567e-14\n"
     ]
    }
   ],
   "source": "def sample_binary_objective(objective,n):\n    states=np.array(list(itertools.product([0,1],repeat=n)),dtype=float)\n    values=np.array([objective(x) for x in states],dtype=float)\n    return states,values\n\ndef fit_qubo(X,y):\n    X=np.asarray(X,dtype=float)\n    y=np.asarray(y,dtype=float)\n    n=X.shape[1]\n\n    features=[np.ones(len(X))]\n    for i in range(n):\n        features.append(X[:,i])\n\n    pairs=[]\n    for i in range(n):\n        for j in range(i+1,n):\n            features.append(X[:,i]*X[:,j])\n            pairs.append((i,j))\n\n    A=np.column_stack(features)\n    coef,*_=np.linalg.lstsq(A,y,rcond=None)\n\n    c=float(coef[0])\n    Q=np.zeros((n,n))\n\n    for i in range(n):\n        Q[i,i]=coef[1+i]\n\n    offset=1+n\n    for k,(i,j) in enumerate(pairs):\n        # Split cross-term equally across Q_ij and Q_ji.\n        q=coef[offset+k]/2.0\n        Q[i,j]=Q[j,i]=q\n\n    return Q,c\n\ndef qubo_energy(b,Q,c=0.0):\n    b=np.asarray(b,dtype=float)\n    return float(b@Q@b+c)\n\nX_bin,y_bin=sample_binary_objective(benchmark_binary_objective,N_CELLS)\nQ,c0=fit_qubo(X_bin,y_bin)\n\nqubo_reconstruction=np.array([qubo_energy(b,Q,c0) for b in X_bin])\nprint(\"QUBO reconstruction RMSE:\",\n      np.sqrt(np.mean((qubo_reconstruction-y_bin)**2)))\nprint(\"Max abs error:\",\n      np.max(np.abs(qubo_reconstruction-y_bin)))",
   "id": "vJtgz_PvsnF0"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hEkApzlssnF1"
   },
   "source": "## 7. Optional quantum interface\n\nQiskit/PennyLane/CUDA-Q/D-Wave gibi backend'leri aynı QUBO API'si altında tutmak için:\n\n```python\nsolution = optimizer.solve(Q=Q)\n```\n\nkullanılır.\n\nAşağıdaki hücre Qiskit stack'i varsa keşfeder. Yoksa notebook çalışmaya devam eder.",
   "id": "hEkApzlssnF1"
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Sjz7EDuJsnF1",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060340064,
     "user_tz": -180,
     "elapsed": 69,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "87da4820-6a02-452c-dba2-e538ea26c4cf"
   },
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "{'qiskit': None, 'pennylane': None, 'cudaq': None}"
      ]
     },
     "metadata": {},
     "execution_count": 13
    }
   ],
   "source": "def detect_quantum_stacks():\n    stacks={}\n    try:\n        import qiskit\n        stacks[\"qiskit\"]=getattr(qiskit,\"__version__\",\"installed\")\n    except Exception as e:\n        stacks[\"qiskit\"]=None\n\n    try:\n        import pennylane\n        stacks[\"pennylane\"]=getattr(pennylane,\"__version__\",\"installed\")\n    except Exception:\n        stacks[\"pennylane\"]=None\n\n    try:\n        import cudaq\n        stacks[\"cudaq\"]=\"installed\"\n    except Exception:\n        stacks[\"cudaq\"]=None\n\n    return stacks\n\ndetect_quantum_stacks()",
   "id": "Sjz7EDuJsnF1"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "gDko-EiosnF2"
   },
   "source": "## 8. Benchmark reporting\n\nHer optimizer için:\n\n\\[\ngap = J_{method}-J_{exact}\n\\]\n\n\\[\ngap_\\% = 100\frac{J_{method}-J_{exact}}{|J_{exact}|}\n\\]\n\nve:\n\n\\[\nH(b_{method},b_{exact})\n\\]\n\nraporlanır.\n\nRuntime ölçümlerinde local compute time ile gerçek quantum-cloud queue time ayrı tutulmalıdır.",
   "id": "gDko-EiosnF2"
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 111
    },
    "id": "wRSnTzY1snF2",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060340189,
     "user_tz": -180,
     "elapsed": 76,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "15db9dee-388c-4c88-eee6-7acee3a67daa"
   },
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "                method  objective  gap_vs_exact  gap_pct  hamming_vs_exact  \\\n",
       "0                Exact  -0.374581           0.0      0.0                 0   \n",
       "1  Simulated Annealing  -0.374581           0.0      0.0                 0   \n",
       "\n",
       "   runtime_s             state  \n",
       "0   1.191105  1101000000000000  \n",
       "1   0.638084  1101000000000000  "
      ],
      "text/html": [
       "\n",
       "  <div id=\"df-de00f8c4-4c57-4e36-b51e-15ec4f305418\" class=\"colab-df-container\">\n",
       "    <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>method</th>\n",
       "      <th>objective</th>\n",
       "      <th>gap_vs_exact</th>\n",
       "      <th>gap_pct</th>\n",
       "      <th>hamming_vs_exact</th>\n",
       "      <th>runtime_s</th>\n",
       "      <th>state</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Exact</td>\n",
       "      <td>-0.374581</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>1.191105</td>\n",
       "      <td>1101000000000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Simulated Annealing</td>\n",
       "      <td>-0.374581</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.638084</td>\n",
       "      <td>1101000000000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-de00f8c4-4c57-4e36-b51e-15ec4f305418')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-de00f8c4-4c57-4e36-b51e-15ec4f305418 button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-de00f8c4-4c57-4e36-b51e-15ec4f305418');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "  <div id=\"id_27e3a8b6-bdac-4f16-8ad1-54fa737e7ac8\">\n",
       "    <style>\n",
       "      .colab-df-generate {\n",
       "        background-color: #E8F0FE;\n",
       "        border: none;\n",
       "        border-radius: 50%;\n",
       "        cursor: pointer;\n",
       "        display: none;\n",
       "        fill: #1967D2;\n",
       "        height: 32px;\n",
       "        padding: 0 0 0 0;\n",
       "        width: 32px;\n",
       "      }\n",
       "\n",
       "      .colab-df-generate:hover {\n",
       "        background-color: #E2EBFA;\n",
       "        box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "        fill: #174EA6;\n",
       "      }\n",
       "\n",
       "      [theme=dark] .colab-df-generate {\n",
       "        background-color: #3B4455;\n",
       "        fill: #D2E3FC;\n",
       "      }\n",
       "\n",
       "      [theme=dark] .colab-df-generate:hover {\n",
       "        background-color: #434B5C;\n",
       "        box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "        filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "        fill: #FFFFFF;\n",
       "      }\n",
       "    </style>\n",
       "    <button class=\"colab-df-generate\" onclick=\"generateWithVariable('benchmark_df')\"\n",
       "            title=\"Generate code using this dataframe.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
       "       width=\"24px\">\n",
       "    <path d=\"M7,19H8.4L18.45,9,17,7.55,7,17.6ZM5,21V16.75L18.45,3.32a2,2,0,0,1,2.83,0l1.4,1.43a1.91,1.91,0,0,1,.58,1.4,1.91,1.91,0,0,1-.58,1.4L9.25,21ZM18.45,9,17,7.55Zm-12,3A5.31,5.31,0,0,0,4.9,8.1,5.31,5.31,0,0,0,1,6.5,5.31,5.31,0,0,0,4.9,4.9,5.31,5.31,0,0,0,6.5,1,5.31,5.31,0,0,0,8.1,4.9,5.31,5.31,0,0,0,12,6.5,5.46,5.46,0,0,0,6.5,12Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "    <script>\n",
       "      (() => {\n",
       "      const buttonEl =\n",
       "        document.querySelector('#id_27e3a8b6-bdac-4f16-8ad1-54fa737e7ac8 button.colab-df-generate');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      buttonEl.onclick = () => {\n",
       "        google.colab.notebook.generateWithVariable('benchmark_df');\n",
       "      }\n",
       "      })();\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "dataframe",
       "variable_name": "benchmark_df",
       "summary": "{\n  \"name\": \"benchmark_df\",\n  \"rows\": 2,\n  \"fields\": [\n    {\n      \"column\": \"method\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 2,\n        \"samples\": [\n          \"Simulated Annealing\",\n          \"Exact\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"objective\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.0,\n        \"min\": -0.3745811315318213,\n        \"max\": -0.3745811315318213,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          -0.3745811315318213\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"gap_vs_exact\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.0,\n        \"min\": 0.0,\n        \"max\": 0.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          0.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"gap_pct\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.0,\n        \"min\": 0.0,\n        \"max\": 0.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          0.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"hamming_vs_exact\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0,\n        \"min\": 0,\n        \"max\": 0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"runtime_s\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 0.39104490701673916,\n        \"min\": 0.6380843899999888,\n        \"max\": 1.1911054009999873,\n        \"num_unique_values\": 2,\n        \"samples\": [\n          0.6380843899999888\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"state\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"1101000000000000\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}"
      }
     },
     "metadata": {},
     "execution_count": 14
    }
   ],
   "source": "def benchmark_row(name,state,value,runtime):\n    gap=value-exact_value\n    return {\n        \"method\":name,\n        \"objective\":value,\n        \"gap_vs_exact\":gap,\n        \"gap_pct\":100*gap/max(abs(exact_value),1e-12),\n        \"hamming_vs_exact\":hamming_distance(state,exact_state),\n        \"runtime_s\":runtime,\n        \"state\":\"\".join(map(str,state)),\n    }\n\nbenchmark_df=pd.DataFrame([\n    benchmark_row(\"Exact\",exact_state,exact_value,exact_runtime),\n    benchmark_row(\"Simulated Annealing\",sa_state,sa_value,sa_runtime),\n])\nbenchmark_df",
   "id": "wRSnTzY1snF2"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4iMyvpX7snF2"
   },
   "source": "## 9. Adaptive transition layer\n\nEnvironment transition:\n\n\\[\nE_1\nightarrow E_2\n\\]\n\niçin:\n\n\\[\nb^*(E_1),\\quad b^*(E_2)\n\\]\n\nve:\n\n\\[\nH(b^*(E_1),b^*(E_2))\n\\]\n\nhesaplanır.\n\nBu, daha sonra surrogate-derived EM objective ile beslenir.",
   "id": "4iMyvpX7snF2"
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "WlVwimbIsnF3",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060342740,
     "user_tz": -180,
     "elapsed": 2548,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "1565974d-1288-4ded-e946-d306a50ea77d"
   },
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "{'state_a': '1101000000000000',\n",
       " 'state_b': '1000000000000000',\n",
       " 'objective_a': -0.3745811315318213,\n",
       " 'objective_b': -0.05000000000000002,\n",
       " 'hamming_distance': 2}"
      ]
     },
     "metadata": {},
     "execution_count": 15
    }
   ],
   "source": "def compare_transition(state_a,value_a,state_b,value_b):\n    return {\n        \"state_a\":\"\".join(map(str,state_a)),\n        \"state_b\":\"\".join(map(str,state_b)),\n        \"objective_a\":float(value_a),\n        \"objective_b\":float(value_b),\n        \"hamming_distance\":hamming_distance(state_a,state_b),\n    }\n\nobj_E1=lambda b: benchmark_binary_objective(b)\nobj_E2=lambda b: benchmark_binary_objective(\n    b\n)+0.15*np.sum(np.asarray(b))\n\nstate_E1,val_E1=exact_binary_optimum(N_CELLS,obj_E1)\nstate_E2,val_E2=exact_binary_optimum(N_CELLS,obj_E2)\n\ncompare_transition(state_E1,val_E1,state_E2,val_E2)",
   "id": "WlVwimbIsnF3"
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "kLDm9mAdsnF4",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1788060342764,
     "user_tz": -180,
     "elapsed": 22,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "f2b9e831-9ce0-4c69-fcb5-a4133e499a7e"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Artifacts exported to: /content/data/master\n"
     ]
    }
   ],
   "source": "# 10. Export pipeline artifacts\n\nsurrogate_metrics.to_csv(\n    MASTER_DIR/\"surrogate_metrics_synthetic.csv\", index=False\n)\nnp.save(MASTER_DIR/\"qubo_matrix_synthetic.npy\",Q)\n\n(MASTER_DIR/\"qubo_metadata_synthetic.json\").write_text(\n    json.dumps({\n        \"n_variables\":N_CELLS,\n        \"constant\":c0,\n        \"seed\":RANDOM_SEED,\n        \"source\":\"synthetic_pipeline_validation_only\"\n    },indent=2)\n)\n\nbenchmark_df.to_csv(\n    MASTER_DIR/\"benchmark_results_synthetic.csv\", index=False\n)\n\nprint(\"Artifacts exported to:\", MASTER_DIR)",
   "id": "kLDm9mAdsnF4"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "kBGTt9zvsnF4"
   },
   "source": "# 11. Replacing synthetic data with real solver output\n\nGerçek CST/HFSS/COMSOL sonuçları `data/raw_em/` altına CSV olarak konur.\n\nArdından:\n\n```python\nmaster_em = load_em_csv_folder()\nmaster_em.to_csv(\n    MASTER_DIR / \"em_master.csv\",\n    index=False\n)\n```\n\nSonraki aşama:\n\n```text\nreal EM CSV\n    ↓\nsurrogate retraining\n    ↓\narray objective\n    ↓\nQUBO\n    ↓\nexact 4×4 benchmark\n    ↓\nQAOA / annealing / classical\n    ↓\nfull-wave array validation\n```\n\nÖnemli deneysel ayrım:\n\n**cell-wise surrogate optimum ≠ guaranteed array full-wave optimum**\n\nçünkü mutual coupling ve finite-array effects ayrıca doğrulanmalıdır.\n\n## Publication checklist\n\n- [ ] mesh convergence\n- [ ] material provenance\n- [ ] geometry-level train/test split\n- [ ] surrogate MAE/RMSE/R²\n- [ ] QUBO reconstruction error\n- [ ] exact 2^16 benchmark\n- [ ] multiple seeds for classical baselines\n- [ ] same objective/budget across optimizers\n- [ ] full-wave 4×4 validation\n- [ ] independent test geometry\n- [ ] X-band validation\n- [ ] K-band validation\n- [ ] hardware measurement, when available",
   "id": "kBGTt9zvsnF4"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.13.5"
  },
  "colab": {
   "provenance": []
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}