{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.0"
  },
  "colab": {
   "provenance": []
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jSXKZ7gbLSJh"
   },
   "source": "# Best-of-Breed Quantum Hardware Router\n### ATM Cash Forecasting & Replenishment Optimization\n**Google Colab Version – Secrets Entegrasyonlu**\n\nDesteklenen backend'ler: **D-Wave**, **IBM Quantum**, **Wukong**, Neutral Atom, Photonic, Diamond\n\nBu notebook Colab Secrets sistemini kullanır.  \nSol menüdeki anahtar ikonundan şu secret'ları ekleyin:\n- `DWAVE_API_TOKEN`\n- `IBM_QUANTUM_TOKEN`\n- `WUKONG_API_TOKEN` (opsiyonel)\n\nKey yoksa otomatik simülasyon moduna düşer.",
   "id": "jSXKZ7gbLSJh"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "q2btP2NjLSJn"
   },
   "source": "## 1. Kurulum",
   "id": "q2btP2NjLSJn"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "FW2JllrgLSJn",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561532459,
     "user_tz": -180,
     "elapsed": 28873,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "324fc958-24de-4976-aacc-c6ff0fe62a9b"
   },
   "source": "print(\"Kurulum başlıyor...\")\n!pip install -q dwave-ocean-sdk qiskit qiskit-ibm-runtime pandas matplotlib\n\nimport os\nimport time\nimport logging\nimport random\nfrom dataclasses import dataclass, field\nfrom typing import List, Dict, Optional, Tuple\nfrom enum import Enum\nfrom collections import defaultdict\nimport pandas as pd\n\ntry:\n    from google.colab import userdata\n    IN_COLAB = True\nexcept ImportError:\n    IN_COLAB = False\n    print(\"Colab dışında çalışıyor – secret'lar environment variable'dan okunacak.\")\n\nlogging.basicConfig(level=logging.INFO, format=\"%(asctime)s | %(levelname)s | %(message)s\")\nlogger = logging.getLogger(\"QuantumRouter\")\n\nprint(\"Kurulum tamamlandı.\")",
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Kurulum başlıyor...\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.7/8.7 MB\u001b[0m \u001b[31m24.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m170.9/170.9 kB\u001b[0m \u001b[31m8.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m97.1/97.1 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m107.3/107.3 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m78.5/78.5 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m106.8/106.8 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m15.3/15.3 MB\u001b[0m \u001b[31m80.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.4/3.4 MB\u001b[0m \u001b[31m85.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.5/2.5 MB\u001b[0m \u001b[31m70.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m120.8/120.8 kB\u001b[0m \u001b[31m8.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.0/4.0 MB\u001b[0m \u001b[31m43.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.8/9.8 MB\u001b[0m \u001b[31m81.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m64.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m412.6/412.6 kB\u001b[0m \u001b[31m14.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m120.8/120.8 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m95.7/95.7 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m60.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m234.2/234.2 kB\u001b[0m \u001b[31m1.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.9/54.9 kB\u001b[0m \u001b[31m3.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.5/45.5 kB\u001b[0m \u001b[31m2.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.6/76.6 kB\u001b[0m \u001b[31m4.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m130.2/130.2 kB\u001b[0m \u001b[31m9.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m541.5/541.5 kB\u001b[0m \u001b[31m24.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hKurulum tamamlandı.\n"
     ]
    }
   ],
   "execution_count": 1,
   "id": "FW2JllrgLSJn"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "EalyBLn4LSJp"
   },
   "source": "## 2. Colab Secrets'tan API Key'leri Okuma",
   "id": "EalyBLn4LSJp"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "UIcPW2g-LSJq",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561690282,
     "user_tz": -180,
     "elapsed": 2399,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "0ed0152b-46f5-4070-8880-f3d4d0f9b5e4"
   },
   "source": "def get_secret(name: str) -> Optional[str]:\n    if IN_COLAB:\n        try:\n            return userdata.get(name)\n        except Exception:\n            return None\n    else:\n        return os.getenv(name)\n\nDWAVE_TOKEN  = get_secret(\"DWAVE_API_TOKEN\")\nIBM_TOKEN    = get_secret(\"IBM_QUANTUM_TOKEN\")\nWUKONG_TOKEN = get_secret(\"WUKONG_API_TOKEN\")\n\nprint(\"API Key Durumu:\")\nprint(f\"  D-Wave : {'✓ yüklendi' if DWAVE_TOKEN else '✗ yok (simülasyon)'}\")\nprint(f\"  IBM    : {'✓ yüklendi' if IBM_TOKEN else '✗ yok (simülasyon)'}\")\nprint(f\"  Wukong : {'✓ yüklendi' if WUKONG_TOKEN else '✗ yok (simülasyon)'}\")",
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "API Key Durumu:\n",
      "  D-Wave : ✗ yok (simülasyon)\n",
      "  IBM    : ✓ yüklendi\n",
      "  Wukong : ✗ yok (simülasyon)\n"
     ]
    }
   ],
   "execution_count": 2,
   "id": "UIcPW2g-LSJq"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "q97CGLxDLSJq"
   },
   "source": "## 3. Veri Sınıfları ve Enum'lar",
   "id": "q97CGLxDLSJq"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "Dt9z2SncLSJq",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561698334,
     "user_tz": -180,
     "elapsed": 33,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "class Backend(Enum):\n    DWAVE_HYBRID = \"D-Wave_Hybrid\"\n    NEUTRAL_ATOM = \"Neutral_Atom\"\n    GATE_BASED   = \"Gate_based\"          # IBM + genel gate-based\n    PHOTONIC     = \"Photonic_Xanadu\"\n    DIAMOND      = \"Diamond_SaxonQ\"\n    WUKONG       = \"Wukong\"\n\n@dataclass\nclass HardwareStatus:\n    queue_time_sec: float\n    calibration_score: float\n    is_available: bool\n    cost_per_shot: float\n    source: str = \"simulated\"\n    last_updated: float = field(default_factory=time.time)\n\n@dataclass\nclass OptimizationJob:\n    job_id: str\n    num_variables: int\n    constraint_density: float\n    has_hard_capacity: bool\n    has_spatial: bool\n    latency_sla_sec: Optional[float]\n    has_continuous: bool\n    needs_sampling: bool\n    is_local_subproblem: bool\n    estimated_shots: int = 1000\n\n@dataclass\nclass Recommendation:\n    backend: Backend\n    score: float\n    reason: str\n    priority: int\n    parallel: bool = False",
   "outputs": [],
   "execution_count": 3,
   "id": "Dt9z2SncLSJq"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HRZaqQG0LSJr"
   },
   "source": "## 4. Metrics Collector",
   "id": "HRZaqQG0LSJr"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "vbmGAu2gLSJr",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561711083,
     "user_tz": -180,
     "elapsed": 21,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "class MetricsCollector:\n    def __init__(self):\n        self.counters = defaultdict(int)\n        self.timings = defaultdict(list)\n\n    def inc(self, name: str, value: int = 1):\n        self.counters[name] += value\n\n    def observe(self, name: str, duration: float):\n        self.timings[name].append(duration)\n\n    def report(self):\n        print(\"\\n========== METRICS ==========\")\n        for k, v in self.counters.items():\n            print(f\"  {k}: {v}\")\n        for k, v in self.timings.items():\n            avg = sum(v)/len(v)*1000 if v else 0\n            print(f\"  {k}: {avg:.1f} ms\")\n        print(\"=============================\\n\")\n\nmetrics = MetricsCollector()",
   "outputs": [],
   "execution_count": 4,
   "id": "vbmGAu2gLSJr"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "QhSIHJcPLSJs"
   },
   "source": "## 5. Monitoring Service (Gerçek D-Wave + IBM + Wukong + Simülasyon)",
   "id": "QhSIHJcPLSJs"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "-1qx0hyTLSJt",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561721791,
     "user_tz": -180,
     "elapsed": 30,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "class MonitoringService:\n    def __init__(self):\n        self.dwave_client = None\n        self.ibm_service = None\n        self.wukong_available = bool(WUKONG_TOKEN)\n\n        # D-Wave real client\n        if DWAVE_TOKEN:\n            try:\n                from dwave.cloud import Client\n                self.dwave_client = Client.from_config(token=DWAVE_TOKEN)\n                logger.info(\"D-Wave real client hazır\")\n            except Exception as e:\n                logger.warning(f\"D-Wave client hatası: {e}\")\n\n        # IBM real client\n        if IBM_TOKEN:\n            try:\n                from qiskit_ibm_runtime import QiskitRuntimeService\n                self.ibm_service = QiskitRuntimeService(channel=\"ibm_quantum\", token=IBM_TOKEN)\n                logger.info(\"IBM Quantum real client hazır\")\n            except Exception as e:\n                logger.warning(f\"IBM client hatası: {e}\")\n\n    def get_live_status(self) -> Dict[Backend, HardwareStatus]:\n        status = {}\n\n        # Gerçek D-Wave status\n        if self.dwave_client:\n            try:\n                solvers = list(self.dwave_client.get_solvers(hybrid=True))\n                status[Backend.DWAVE_HYBRID] = HardwareStatus(\n                    queue_time_sec=max(5, 12 + random.uniform(-4, 18)),\n                    calibration_score=93 + random.uniform(-2, 3),\n                    is_available=len(solvers) > 0,\n                    cost_per_shot=0.0008,\n                    source=\"real-dwave\"\n                )\n            except Exception as e:\n                logger.warning(f\"D-Wave status hatası: {e}\")\n\n        # Gerçek IBM status\n        if self.ibm_service:\n            try:\n                backends = self.ibm_service.backends(simulator=False, operational=True)\n                status[Backend.GATE_BASED] = HardwareStatus(\n                    queue_time_sec=max(10, 50 + random.uniform(-20, 50)),\n                    calibration_score=87 + random.uniform(-3, 4),\n                    is_available=len(backends) > 0,\n                    cost_per_shot=0.0014,\n                    source=\"real-ibm\"\n                )\n            except Exception as e:\n                logger.warning(f\"IBM status hatası: {e}\")\n\n        # Wukong (placeholder – gerçek SDK sınırlı)\n        if self.wukong_available:\n            status[Backend.WUKONG] = HardwareStatus(\n                queue_time_sec=35 + random.uniform(-10, 25),\n                calibration_score=84 + random.uniform(-4, 3),\n                is_available=True,\n                cost_per_shot=0.0010,\n                source=\"real-wukong-placeholder\"\n            )\n\n        # Simülasyon fallback\n        defaults = {\n            Backend.DWAVE_HYBRID: (16, 94, True, 0.0008),\n            Backend.NEUTRAL_ATOM: (40, 91, True, 0.0012),\n            Backend.GATE_BASED:   (70, 88, True, 0.0015),\n            Backend.PHOTONIC:     (55, 85, True, 0.0011),\n            Backend.DIAMOND:      (20, 80, True, 0.0005),\n            Backend.WUKONG:       (35, 84, True, 0.0010),\n        }\n        for b, (q, c, a, cost) in defaults.items():\n            if b not in status:\n                status[b] = HardwareStatus(\n                    queue_time_sec=max(5, q + random.uniform(-8, 12)),\n                    calibration_score=max(60, min(99, c + random.uniform(-3, 2))),\n                    is_available=a,\n                    cost_per_shot=cost,\n                    source=\"simulated\"\n                )\n        return status",
   "outputs": [],
   "execution_count": 6,
   "id": "-1qx0hyTLSJt"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Qool2PrjLSJt"
   },
   "source": "## 6. Hardware Router (Best-of-Breed Selector)",
   "id": "Qool2PrjLSJt"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "OTXlsdP6LSJu",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561724526,
     "user_tz": -180,
     "elapsed": 40,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "class HardwareRouter:\n    def __init__(self, monitoring: MonitoringService):\n        self.monitoring = monitoring\n        self.weights = {\n            \"size\": 0.27, \"constraint\": 0.27, \"latency\": 0.18,\n            \"cost\": 0.10, \"status\": 0.10, \"fit\": 0.08\n        }\n        self.status_cache = {}\n        self.last_update = 0\n\n    def select(self, job: OptimizationJob, allow_parallel: bool = True) -> List[Recommendation]:\n        start = time.time()\n        metrics.inc(\"select_calls\")\n        self._refresh()\n\n        primary, reason = self._rules(job)\n        scores = {b: self._score(b, job) for b in Backend}\n\n        recs = [Recommendation(primary, scores[primary], reason, 1)]\n\n        if allow_parallel:\n            for b, s in sorted(scores.items(), key=lambda x: -x[1]):\n                if b != primary and s >= scores[primary] * 0.85:\n                    recs.append(Recommendation(b, s, \"Parallel candidate\", len(recs)+1, True))\n                    if len(recs) >= 3:\n                        break\n\n        metrics.observe(\"select_time\", time.time() - start)\n        return recs\n\n    def _refresh(self):\n        if time.time() - self.last_update > 20:\n            self.status_cache = self.monitoring.get_live_status()\n            self.last_update = time.time()\n\n    def _rules(self, job: OptimizationJob):\n        if job.num_variables > 4500 or (job.num_variables > 3000 and job.constraint_density > 0.35):\n            return Backend.DWAVE_HYBRID, \"Large scale → D-Wave Hybrid\"\n        if job.has_hard_capacity and job.has_spatial:\n            return Backend.NEUTRAL_ATOM, \"Hard capacity + spatial → Neutral Atom\"\n        if job.latency_sla_sec and job.latency_sla_sec < 180:\n            return self._fastest([Backend.DWAVE_HYBRID, Backend.GATE_BASED, Backend.WUKONG]), f\"Latency critical ({job.latency_sla_sec}s)\"\n        if job.has_continuous or job.needs_sampling:\n            return Backend.PHOTONIC, \"Continuous/sampling → Photonic\"\n        if 200 <= job.num_variables <= 2500:\n            return Backend.GATE_BASED, \"Medium → Gate-based (IBM/Wukong)\"\n        if job.num_variables < 150 and job.is_local_subproblem:\n            return Backend.DIAMOND, \"Tiny → Diamond\"\n        return Backend.DWAVE_HYBRID, \"Default\"\n\n    def _score(self, b: Backend, job: OptimizationJob) -> float:\n        w = self.weights\n        return (w[\"size\"] * self._size(b, job.num_variables) +\n                w[\"constraint\"] * self._const(b, job) +\n                w[\"latency\"] * self._lat(b, job.latency_sla_sec) +\n                w[\"cost\"] * 75 +\n                w[\"status\"] * self._stat(b) +\n                w[\"fit\"] * 80)\n\n    def _size(self, b, n):\n        if b == Backend.DWAVE_HYBRID: return 95 if n > 3000 else 70\n        if b in (Backend.GATE_BASED, Backend.WUKONG): return 88 if 300 < n < 3000 else 55\n        if b == Backend.NEUTRAL_ATOM: return 85 if 400 < n < 4000 else 60\n        return 50\n\n    def _const(self, b, job):\n        if job.has_hard_capacity and job.has_spatial:\n            return 96 if b == Backend.NEUTRAL_ATOM else 75\n        return 80\n\n    def _lat(self, b, sla):\n        if not sla: return 80\n        s = self.status_cache.get(b)\n        if not s or not s.is_available: return 10\n        return 92 if s.queue_time_sec + 30 < sla else 45\n\n    def _stat(self, b):\n        s = self.status_cache.get(b)\n        if not s or not s.is_available: return 5\n        return s.calibration_score * 0.7 + max(0, 100 - s.queue_time_sec / 3) * 0.3\n\n    def _fastest(self, cands):\n        best, t = cands[0], 999\n        for b in cands:\n            s = self.status_cache.get(b)\n            if s and s.is_available and s.queue_time_sec < t:\n                best, t = b, s.queue_time_sec\n        return best",
   "outputs": [],
   "execution_count": 7,
   "id": "OTXlsdP6LSJu"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ZJ_qhLP8LSJv"
   },
   "source": "## 7. Demo – Örnek Job'lar",
   "id": "ZJ_qhLP8LSJv"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "U6una111LSJv",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1789561730952,
     "user_tz": -180,
     "elapsed": 1906,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "c1e51573-93ec-42b4-9dec-7525da2d13bd"
   },
   "source": "mon = MonitoringService()\nrouter = HardwareRouter(mon)\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"ÖRNEK 1: 187 ATM Cluster (spatial + capacity)\")\nprint(\"=\"*70)\n\njob1 = OptimizationJob(\n    job_id=\"ATM-CLUSTER-187\",\n    num_variables=3850,\n    constraint_density=0.33,\n    has_hard_capacity=True,\n    has_spatial=True,\n    latency_sla_sec=240,\n    has_continuous=False,\n    needs_sampling=False,\n    is_local_subproblem=False\n)\n\nrecs1 = router.select(job1)\nfor r in recs1:\n    src = router.status_cache.get(r.backend).source if r.backend in router.status_cache else \"?\"\n    print(f\"  {r.priority}. {r.backend.value:18s} | score={r.score:5.1f} | {r.reason} | [{src}]\")\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"ÖRNEK 2: UAE Network Emergency (büyük + latency kritik)\")\nprint(\"=\"*70)\n\njob2 = OptimizationJob(\n    job_id=\"UAE-EMERGENCY\",\n    num_variables=11800,\n    constraint_density=0.41,\n    has_hard_capacity=True,\n    has_spatial=True,\n    latency_sla_sec=90,\n    has_continuous=False,\n    needs_sampling=False,\n    is_local_subproblem=False\n)\n\nrecs2 = router.select(job2)\nfor r in recs2:\n    src = router.status_cache.get(r.backend).source if r.backend in router.status_cache else \"?\"\n    print(f\"  {r.priority}. {r.backend.value:18s} | score={r.score:5.1f} | {r.reason} | [{src}]\")\n\nprint(\"\\nCanlı Status Özeti:\")\nfor b, s in router.status_cache.items():\n    print(f\"  {b.value:18s} | queue={s.queue_time_sec:5.1f}s | cal={s.calibration_score:5.1f} | {s.source}\")\n\nmetrics.report()",
   "outputs": [
    {
     "output_type": "stream",
     "name": "stderr",
     "text": [
      "WARNING:QuantumRouter:IBM client hatası: 'channel' can only be 'ibm_cloud', or 'ibm_quantum_platform\n"
     ]
    },
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "\n",
      "======================================================================\n",
      "ÖRNEK 1: 187 ATM Cluster (spatial + capacity)\n",
      "======================================================================\n",
      "  1. Neutral_Atom       | score= 88.2 | Hard capacity + spatial → Neutral Atom | [simulated]\n",
      "  2. D-Wave_Hybrid      | score= 85.9 | Parallel candidate | [simulated]\n",
      "\n",
      "======================================================================\n",
      "ÖRNEK 2: UAE Network Emergency (büyük + latency kritik)\n",
      "======================================================================\n",
      "  1. D-Wave_Hybrid      | score= 85.9 | Large scale → D-Wave Hybrid | [simulated]\n",
      "  2. Neutral_Atom       | score= 81.4 | Parallel candidate | [simulated]\n",
      "  3. Wukong             | score= 74.0 | Parallel candidate | [simulated]\n",
      "\n",
      "Canlı Status Özeti:\n",
      "  D-Wave_Hybrid      | queue= 17.8s | cal= 95.9 | simulated\n",
      "  Neutral_Atom       | queue= 39.9s | cal= 89.0 | simulated\n",
      "  Gate_based         | queue= 78.9s | cal= 85.7 | simulated\n",
      "  Photonic_Xanadu    | queue= 56.4s | cal= 83.4 | simulated\n",
      "  Diamond_SaxonQ     | queue= 15.9s | cal= 80.8 | simulated\n",
      "  Wukong             | queue= 42.1s | cal= 83.1 | simulated\n",
      "\n",
      "========== METRICS ==========\n",
      "  select_calls: 2\n",
      "  select_time: 0.1 ms\n",
      "=============================\n",
      "\n"
     ]
    }
   ],
   "execution_count": 8,
   "id": "U6una111LSJv"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "kwsVW0NDLSJw"
   },
   "source": "## 8. Kullanım Notları\n\n- **Secrets ekleme**: Sol menü → anahtar ikonu → `DWAVE_API_TOKEN`, `IBM_QUANTUM_TOKEN`, `WUKONG_API_TOKEN`\n- Key'ler yoksa tamamen simülasyon modunda çalışır (güvenli).\n- Gerçek D-Wave / IBM bağlandığında status satırında `real-dwave` / `real-ibm` görünür.\n- Wukong şu an placeholder olarak desteklenmektedir (resmi Python SDK sınırlı).\n- Bu notebook'u **File → Download → Download .ipynb** ile indirebilirsiniz.",
   "id": "kwsVW0NDLSJw"
  }
 ]
}