{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a3721c91-63df-473c-8a98-fc5d731a90fd",
   "metadata": {},
   "source": [
    "## Qiskit Tutorial\n",
    "29/11/2023 Κυριάκος Σγάρμπας (https://goo.gl/8roJe)  \n",
    "updated 19/02/2026"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5505eace-9775-409f-baa9-2c86ba751a28",
   "metadata": {},
   "source": [
    "Το JupyterLab τρέχει από command line / terminal ως εξής:"
   ]
  },
  {
   "cell_type": "raw",
   "id": "88f5a951-d0a4-4cf5-81f9-f4ddecd28f75",
   "metadata": {},
   "source": [
    "(OS prompt) jupyter lab"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "242c2adf-322e-4027-be89-0d3193e5fae8",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 0. Έλεγχος εκδόσεων και εγκατάσταση"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05820d21-0d67-4cff-b341-f57311db62a0",
   "metadata": {},
   "source": [
    "Για να ελέγξουμε την έκδοση της Python που τρέχει στο JupyterLab δίνουμε:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c83ce4d7-fcbe-4a02-a3c6-8ed9c1e04c6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "sys.version_info(major=3, minor=13, micro=9, releaselevel='final', serial=0)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "sys.version_info"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43d4f1ae-14ae-429e-b892-b5fdf24c7cf0",
   "metadata": {},
   "source": [
    "Για να ελέγξουμε την έκδοση του qiskit που έχει εγκατασταθεί και τρέχει στην παραπάνω έκδοση της Python που χρησιμοποιεί το JupyterLab δίνουμε:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a183f28f-3859-4775-94b0-eed4c66b0e85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2.2.1'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "#qiskit.__qiskit_version__\n",
    "qiskit.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "64c18486-5557-412b-ba4b-867016f27059",
   "metadata": {},
   "source": [
    "Αν χρειάζεται εγκατάσταση πακέτων ή ενημέρωση έκδοσης αυτά συνήθως γίνονται πάλι από command line / terminal ως:"
   ]
  },
  {
   "cell_type": "raw",
   "id": "3c0d4a61-c66d-4500-b63e-3a48e13055f8",
   "metadata": {},
   "source": [
    "(OS prompt) python (ή py) -m pip install ...\n",
    "(OS prompt) python (ή py) -m pip --upgrade (ή -U) ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e659778-eb94-4f11-be02-815f8164b876",
   "metadata": {},
   "source": [
    "Αν όμως στον υπολογιστή έχουν εγκατασταθεί διάφορες εκδόσεις της Python και θέλουμε να είμαστε σίγουροι ότι τα πακέτα θα εγκατασταθούν στα σωστά paths για την έκδοση της Python που θα χρησιμοποιήσουμε μέσα από το JupyterLab, τότε βολεύει να κάνουμε την εγκατάστασή τους μέσα από το περιβάλλον του JupyterLab ως εξής:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7a11d3eb-80af-430f-99f7-8404faf641a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Εξασφαλίζει ότι η εγκατάσταση των εξωτερικών πακέτων θα γίνει στη σωστή θέση.\n",
    "\n",
    "import sys\n",
    "import os\n",
    "\n",
    "def run_terminal(command, mdf=\"my_dummy_file.txt\"):\n",
    "\tos.system(command+\" > \"+mdf)\n",
    "\tf=open(mdf, \"r\")\n",
    "\tcont=f.read()\n",
    "\tf.close()\n",
    "\tprint(cont)\n",
    "\tif os.path.exists(mdf): os.remove(mdf)\n",
    "\telse: print(\"ERROR: Cannot delete \"+mdf+\" The file does not exist\")\n",
    "\n",
    "# Τώρα μπορούμε να τρέχουμε εντολές του command line / terminal μέσα από το περιβάλλον, ως εξης:\n",
    "# run_terminal(\"ls -l\")\n",
    "# run_terminal(\"pwd\")\n",
    "# run_terminal(sys.executable + \" -m pip list\")\n",
    "\n",
    "# Και ειδικά για εντολές pip ορίζουμε:\n",
    "\n",
    "def run_pip(command):\n",
    "\trun_terminal(sys.executable + \" -m pip \" + command)\n",
    "\n",
    "# Παραδείγματα χρήσης:\n",
    "# run_pip(\"list -v\")\n",
    "# run_pip(\"show qiskit\")\n",
    "# run_pip(\"install --upgrade qiskit\")\n",
    "# run_pip(\"uninstall qiskit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bb3494b-e817-4694-b24d-b5edd5184a50",
   "metadata": {},
   "source": [
    "Για ενημέρωση εκδόσεων:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3975c026-f218-44c1-9e3d-13cb0fd94c7f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#run_pip(\"show pip\")\n",
    "#run_pip(\"install --upgrade pip\")\n",
    "\n",
    "#run_pip(\"show jupyterlab\")\n",
    "#run_pip(\"install --upgrade jupyterlab\")\n",
    "\n",
    "#run_pip(\"show qiskit\")\n",
    "#run_pip(\"install --upgrade qiskit\")\n",
    "\n",
    "#run_pip(\"show qiskit-aer\")\n",
    "#run_pip(\"install --upgrade qiskit-aer\")\n",
    "\n",
    "#run_pip(\"show qiskit-ibm-runtime\")\n",
    "#run_pip(\"install --upgrade qiskit-ibm-runtime\")\n",
    "\n",
    "#run_pip(\"install --upgrade 'qiskit[visualization]'\")\n",
    "\n",
    "#run_pip(\"show sympy\")\n",
    "#run_pip(\"install --upgrade sympy\")\n",
    "\n",
    "# Αν κάτι δε δουλεύει σωστά, απεγκατάσταση και επανεγκατάσταση:\n",
    "#run_pip(\"uninstall qiskit qiskit-aer qiskit-ibm-runtime -y\")\n",
    "#run_pip(\"cache purge\")\n",
    "#run_pip(\"install qiskit==2.2.1\")\n",
    "\n",
    "# Εναλλακτικά:\n",
    "# %pip install\n",
    "# Χρησιμοποιώντας το σύμβολο %, αναγκάζουμε το Jupyter να εγκαταστήσει τη βιβλιοθήκη ακριβώς\n",
    "# στον πυρήνα που χρησιμοποιεί εκείνη τη στιγμή το notebook."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e84b0fb2-33b2-4bb1-95c4-ce7a2b831a66",
   "metadata": {},
   "source": [
    "Άλλες παραμέτρους περιβάλλοντος μπορούμε να δούμε με:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8eb9d8c4-cb33-45ae-9934-61ab280ccf41",
   "metadata": {},
   "outputs": [],
   "source": [
    "#print(os.getcwd())\n",
    "#print(os.listdir())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffb86150-51a0-4939-a781-219669005c53",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 1. Δημιουργία και οπτικοποίηση κβαντικής κατάστασης"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cd6672d6-3ba8-41af-b17e-e5a209cafc53",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statevector([8.0000000e-01+0.j , 3.6739404e-17+0.6j],\n",
      "            dims=(2,))\n"
     ]
    }
   ],
   "source": [
    "import qiskit, cmath           # Προτιμούμε τη cmath αντί της math\n",
    "\n",
    "π = cmath.pi                   # Ορίζουμε σταθερές\n",
    "e = cmath.e\n",
    "i = 1j\n",
    "\n",
    "# s = a|0> + b|1>              # 4 βαθμοί ελευθερίας\n",
    "# s = ma|0> + mb*e**(i*φ)|1>   # 3 βαθμοί ελευθερίας (ma, mb : μέτρα)\n",
    "\n",
    "mb = 0.6      # Εδώ ορίζεται η κατάσταση\n",
    "φ = π/2       # ---\"\"----\n",
    "\n",
    "ma = (1-mb*mb)**0.5            # μείωση κατά 1 βαθμό ελευθερίας\n",
    "a = ma\n",
    "b = mb*e**(i*φ)\n",
    "\n",
    "# Το b αρκεί για να καθοριστεί μονοσήμαντα η κατάσταση. # 2 βαθμοί ελευθερίας (μέτρο, φάση)\n",
    "# Το a έχει προκύψει από το b.\n",
    "\n",
    "s = qiskit.quantum_info.Statevector([a,b])\n",
    "print(s)    # Σπάνια τυπώνουμε έτσι ένα διάνυσμα κατάστασης"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8bbf4e1c-b722-4c01-91b2-fa9ea017d220",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\\frac{4}{5} |0\\rangle+\\frac{3 i}{5} |1\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s.draw(output='latex')   # Σε αλγεβρική μορφή"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "7c8f136a-9a42-4bce-9776-006e5760f2f9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\n",
       "\n",
       "\\begin{bmatrix}\n",
       "\\frac{4}{5} & \\frac{3 i}{5}  \\\\\n",
       " \\end{bmatrix}\n",
       "$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qiskit.visualization.array_to_latex(s)   # Σε μορφή διανύσματος"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "bfd7dc84-b555-40c2-9b79-f05a1ea4678c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 102496 characters]",
      "text/plain": [
       "<Figure size 480x480 with 1 Axes>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s.draw(output='bloch')    # Σε σφαίρα Bloch"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "103c2a9f-4581-498b-a82a-0e311bae3977",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 2. Σχεδίαση και προσομοίωση κυκλωμάτων"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7dfbefc7-c555-4b20-8854-fcd10ad15554",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 10692 characters]",
      "text/plain": [
       "<Figure size 538.33x284.278 with 1 Axes>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "\n",
    "circuit = qiskit.QuantumCircuit(3)   # Δημιουργία αντικειμένου (κυκλώματος)\n",
    "\n",
    "circuit.h(1)          # Εισαγωγή πυλών\n",
    "circuit.cx(1, 0)\n",
    "circuit.cx(0, 2)\n",
    "circuit.h(2)\n",
    "circuit.ccx(0,2,1)\n",
    "\n",
    "circuit.draw('mpl', style='iqp', reverse_bits=True)   # Σχεδίαση (style='clifford' or 'iqp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b8531794-0627-48b7-a62d-e0996acc6960",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\n",
       "\n",
       "\\begin{bmatrix}\n",
       "\\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2} & 0  \\\\\n",
       " 0 & \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2}  \\\\\n",
       " 0 & \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & - \\frac{1}{2}  \\\\\n",
       " \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & - \\frac{1}{2} & 0  \\\\\n",
       " \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & - \\frac{1}{2} & 0  \\\\\n",
       " - \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & - \\frac{1}{2} & 0  \\\\\n",
       " 0 & \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & \\frac{1}{2}  \\\\\n",
       " 0 & - \\frac{1}{2} & 0 & - \\frac{1}{2} & 0 & \\frac{1}{2} & 0 & \\frac{1}{2}  \\\\\n",
       " \\end{bmatrix}\n",
       "$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Όλο το κύκλωμα ισοδυναμεί με αυτόν τον πίνακα:\n",
    "U = qiskit.quantum_info.Operator(circuit)\n",
    "U.draw(\"latex\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "63fc2a5b-b239-45c1-bcb9-8cb8c03233c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$ |110\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Έχουμε πολλούς εναλλακτικούς τρόπους να δώσουμε την αρχική κατάσταση:\n",
    "\n",
    "#state = qiskit.quantum_info.Statevector([0,0,0,0,0,0,1,0])\n",
    "state = qiskit.quantum_info.Statevector.from_label(\"110\")\n",
    "#state = qiskit.quantum_info.Statevector.from_int(6,2**3)\n",
    "\n",
    "state.draw(output='latex')   # Εμφάνιση αρχικής κατάστασης"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b7422b05-5e7f-4c4c-8719-de6607139ce5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\\frac{1}{2} |000\\rangle- \\frac{1}{2} |011\\rangle- \\frac{1}{2} |100\\rangle- \\frac{1}{2} |101\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "state = state.evolve(circuit)   # Υπολογισμός της τελικής κατάστασης\n",
    "\n",
    "state.draw('latex')   # Εμφάνιση τελικής κατάστασης"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b7cfd4d8-6129-4d06-a44d-ad95a72af683",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\n",
       "\n",
       "\\begin{bmatrix}\n",
       "\\frac{1}{2} & 0 & 0 & - \\frac{1}{2} & - \\frac{1}{2} & - \\frac{1}{2} & 0 & 0  \\\\\n",
       " \\end{bmatrix}\n",
       "$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qiskit.visualization.array_to_latex(state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "cb347f21-d75a-412c-a44f-6bf882e1658b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 137224 characters]",
      "text/plain": [
       "<Figure size 1440x480 with 3 Axes>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "state.draw('bloch')\n",
    "#qiskit.visualization.plot_bloch_multivector(state) # εναλλακτικά"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20e803ae-6c63-4633-836a-ce03844bb865",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 3. Aer Simulator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "b0bf579a-2980-4106-971e-21e3164ffabe",
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_aer\n",
    "\n",
    "backend = qiskit_aer.Aer.get_backend('statevector_simulator')\n",
    "#backend = qiskit_aer.Aer.get_backend('qasm_simulator')\n",
    "#backend = qiskit_aer.Aer.get_backend('unitary_simulator')\n",
    "#backend = qiskit_aer.Aer.get_backend('aer_simulator')\n",
    "\n",
    "#qiskit_aer.Aer.backends()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "051d49ea-6b53-470e-847b-24bad90a6b26",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statevector([ 0.5+0.j,  0. +0.j,  0. +0.j,  0.5-0.j,  0.5+0.j, -0.5+0.j,\n",
      "              0. +0.j,  0. +0.j],\n",
      "            dims=(2, 2, 2)) {np.str_('000'): np.float64(0.25), np.str_('011'): np.float64(0.25), np.str_('100'): np.float64(0.25), np.str_('101'): np.float64(0.25)}\n"
     ]
    }
   ],
   "source": [
    "#result = qiskit_aer.Aer.execute(circuit, backend).result()\n",
    "result = backend.run(circuit).result()\n",
    "statevector = result.get_statevector(decimals=3)\n",
    "counts = result.get_counts()\n",
    "print(statevector, counts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "53af7142-6ca0-4af7-b1cb-4b6009c4729d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 137140 characters]",
      "text/plain": [
       "<Figure size 1440x480 with 3 Axes>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "statevector.draw('bloch')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "cf9216ef-09ca-482e-9fc7-e8a79be3dd0d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 19864 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qiskit.visualization.plot_histogram(counts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "9afee416-3837-4016-a66a-330951ec1ccf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Result(backend_name='statevector_simulator', backend_version='0.12.2', qobj_id='', job_id='78017634-c238-44cb-811b-16a53f1fbff7', success=True, results=[ExperimentResult(shots=1, success=True, meas_level=2, data=ExperimentResultData(statevector=Statevector([ 0.5+0.000000e+00j,  0. +0.000000e+00j,  0. +0.000000e+00j,\n",
      "              0.5-6.123234e-17j,  0.5+0.000000e+00j, -0.5+6.123234e-17j,\n",
      "              0. +0.000000e+00j,  0. +0.000000e+00j],\n",
      "            dims=(2, 2, 2))), header=QobjExperimentHeader(creg_sizes=[], global_phase=0.0, memory_slots=0, n_qubits=3, name='circuit-152', qreg_sizes=[['q', 3]], metadata={}), status=DONE, seed_simulator=1474591533, metadata={'noise': 'ideal', 'batched_shots_optimization': False, 'remapped_qubits': False, 'parallel_state_update': 4, 'parallel_shots': 1, 'device': 'CPU', 'active_input_qubits': [0, 1, 2], 'measure_sampling': True, 'num_clbits': 0, 'input_qubit_map': [[2, 2], [1, 1], [0, 0]], 'num_qubits': 3, 'method': 'statevector', 'result_subtypes': {'statevector': 'single'}, 'result_types': {'statevector': 'save_statevector'}, 'fusion': {'applied': False, 'max_fused_qubits': 5, 'threshold': 14, 'enabled': True}}, time_taken=0.011353619)], date=2025-10-28T13:20:38.539164, status=COMPLETED, header=None, metadata={'mpi_rank': 0, 'num_mpi_processes': 1, 'num_processes_per_experiments': 1, 'max_gpu_memory_mb': 0, 'time_taken_execute': 0.011466201, 'max_memory_mb': 8192, 'parallel_experiments': 1, 'omp_enabled': True}, time_taken=0.015614986419677734)\n"
     ]
    }
   ],
   "source": [
    "print(result)\n",
    "#dir(result)\n",
    "#result.to_dict()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cb65e35-736c-4a63-b1f4-ad353430a359",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 4. Παράδειγμα: Tυχαία κβαντικά κυκλώματα, πίνακας κυκλώματος, ορισμός πύλης"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a1431291-5938-4ad2-9191-bcd101d7d9cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit, random\n",
    "    \n",
    "def rand_H(circuit):\n",
    "    circuit.h(random.randint(0,circuit.num_qubits-1))\n",
    "    return\n",
    "\n",
    "def rand_X(circuit):\n",
    "    circuit.x(random.randint(0,circuit.num_qubits-1))\n",
    "    return\n",
    "\n",
    "def rand_Y(circuit):\n",
    "    circuit.y(random.randint(0,circuit.num_qubits-1))\n",
    "    return\n",
    "\n",
    "def rand_Z(circuit):\n",
    "    circuit.z(random.randint(0,circuit.num_qubits-1))\n",
    "    return\n",
    "\n",
    "def rand_CX(circuit):\n",
    "    i=random.randint(0,circuit.num_qubits-1)\n",
    "    j=i\n",
    "    while j==i:\n",
    "        j=random.randint(0,circuit.num_qubits-1)    \n",
    "    circuit.cx(i,j)\n",
    "    return\n",
    "\n",
    "def rand_CCX(circuit):\n",
    "    L = list(range(circuit.num_qubits))\n",
    "    random.shuffle(L)\n",
    "    i,j,k = tuple(L[:3])\n",
    "    circuit.ccx(i,j,k)\n",
    "    return\n",
    "\n",
    "def rand_circ(no_of_qubits=3, no_of_gates=15):\n",
    "    RD = {\"H\":30, \"X\":10, \"Y\":5, \"Z\":5, \"CX\":20, \"CCX\":5}  # Εδώ ορίζουμε τις αναλογίες για την κατανομή των πυλών\n",
    "    L = []\n",
    "    for i in RD:\n",
    "        L += [i]*RD[i]\n",
    "    L2 = L*(int(no_of_gates/len(L))+1)\n",
    "    random.shuffle(L2)\n",
    "    L3 = L2[:no_of_gates]\n",
    "    \n",
    "    circuit = qiskit.QuantumCircuit(no_of_qubits)   # Δημιουργία αντικειμένου (κυκλώματος)\n",
    "    for G in L3:\n",
    "        if G == \"H\" : rand_H(circuit)\n",
    "        elif G == \"X\" : rand_X(circuit)\n",
    "        elif G == \"Z\" : rand_Z(circuit)\n",
    "        elif G == \"Y\" : rand_Y(circuit)\n",
    "        elif G == \"CX\" : rand_CX(circuit)\n",
    "        elif G == \"CCX\" : rand_CCX(circuit)\n",
    "    return circuit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7da4d028-710f-43eb-b28b-74d7022d90cd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26696 characters]",
      "text/plain": [
       "<Figure size 1290.83x367.889 with 1 Axes>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "circ = rand_circ(4,20) # Δίνουμε πλήθος qubits και πλήθος πυλών στο κύκλωμα\n",
    "circ.draw('mpl', style='iqp', reverse_bits=True)   # Σχεδίαση iqp είναι το νέο standard για matplotlib,\n",
    "                                                   # reverse bits = MSB πάνω, όπως στο βιβλίο."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10d9782c-cbcd-481a-bc79-f8eaf05bdae0",
   "metadata": {},
   "source": [
    "Ορίζουμε την αρχική κατάσταση:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "5ed273cb-c45d-4429-b142-96d8c2c746e1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$ |0000\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_state = qiskit.quantum_info.Statevector.from_label(\"0\"*circ.num_qubits)\n",
    "initial_state.draw('latex')   # Εμφάνιση αρχικής κατάστασης"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4a4418a-a1b4-4c19-872b-c9d19c460ba5",
   "metadata": {},
   "source": [
    "... και με τη μέθοδο evolve υπολογίζουμε την κατάσταση στο τέλος του κυκλώματος:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "bea57159-0037-4d9d-8ad3-18e18051d59a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$- \\frac{1}{2} |0010\\rangle+\\frac{1}{2} |0011\\rangle- \\frac{1}{2} |1000\\rangle+\\frac{1}{2} |1001\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "final_state = initial_state.evolve(circ)   # Υπολογισμός της τελικής κατάστασης\n",
    "final_state.draw('latex')   # Εμφάνιση τελικής κατάστασης"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7cf352b-2462-4b56-8fd1-62d02d2edf93",
   "metadata": {},
   "source": [
    "Για την ακρίβεια, σε κάθε κύκλωμα αντιστοιχεί ένας πίνακας που εμπεριέχει τη δράση όλων των πυλών του κυκλώματος:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "09bd8188-fa6c-4f92-a42a-c4f5680f117f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$\n",
       "\n",
       "\\begin{bmatrix}\n",
       "0 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0  \\\\\n",
       " 0 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0  \\\\\n",
       " - \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} & - \\frac{1}{2} & \\cdots & 0 & 0 & 0  \\\\\n",
       " \\frac{1}{2} & \\frac{1}{2} & - \\frac{1}{2} & - \\frac{1}{2} & \\cdots & 0 & 0 & 0  \\\\\n",
       " \\vdots & \\vdots & \\vdots & \\vdots & \\ddots & \\vdots & \\vdots & \\vdots \\\\\n",
       " 0 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0  \\\\\n",
       " 0 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0  \\\\\n",
       " 0 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0  \\\\\n",
       " \\end{bmatrix}\n",
       "$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U = qiskit.quantum_info.Operator(circ)\n",
    "U.draw(\"latex\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33aace2d-87b6-4efe-b4fa-69e25b77a3d2",
   "metadata": {},
   "source": [
    "...και με αυτόν μπορούμε να πάμε απευθείας από την αρχική κατάσταση στην τελική, και φυσικά με τον αντίστροφό του μπορούμε να πάμε από την τελική στην αρχική. Αυτόν τον πίνακα μπορούμε ακόμα να τον ορίσουμε ως νέα πύλη:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b37104a2-8ecb-41b2-abb2-4772b5c391ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "my_gate = qiskit.quantum_info.operators.Operator(U)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c084ca9-ceb0-4f13-9fea-256733c80051",
   "metadata": {},
   "source": [
    "... την οποία πλέον μπορούμε να χρησιμοποιούμε στα κυκλώματά μας:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "5f5a7494-3fa9-42eb-9373-0a7f7ed4bfe2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 9516 characters]",
      "text/plain": [
       "<Figure size 287.496x367.889 with 1 Axes>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "circuit2 = qiskit.QuantumCircuit(my_gate.num_qubits)\n",
    "circuit2.unitary(my_gate,range(my_gate.num_qubits), label=\"My Gate\")\n",
    "circuit2.draw('mpl', style='iqp', reverse_bits=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "e2b0e568-bb7f-456a-aee2-30a2399b422d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$$- \\frac{1}{2} |0010\\rangle+\\frac{1}{2} |0011\\rangle- \\frac{1}{2} |1000\\rangle+\\frac{1}{2} |1001\\rangle$$"
      ],
      "text/plain": [
       "<IPython.core.display.Latex object>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "final_state2 = initial_state.evolve(circuit2)\n",
    "final_state2.draw('latex')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "79449f14-8c22-46b9-9964-217ea55ae7c5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "final_state == final_state2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "24a2c35f-d69e-453b-b811-f4fa61a41f08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 308820 characters]",
      "text/plain": [
       "<Figure size 1600x400 with 4 Axes>"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "final_state.draw(\"bloch\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6bdeced-dcff-4dd0-b727-ead7bed73081",
   "metadata": {},
   "source": [
    "Εναλλακτικά, με τον εσωτερικό προσομοιωτή Aer της qiskit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "9d3aa3e8-fded-4ae2-a5a2-8dd34a25b6ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "backend = qiskit_aer.Aer.get_backend('statevector_simulator')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "82f747d3-de2b-452a-aefc-1c8187bf956c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'backend_name': 'statevector_simulator',\n",
       " 'backend_version': '0.17.2',\n",
       " 'date': '2026-02-19T16:31:07.179575',\n",
       " 'header': None,\n",
       " 'job_id': 'fa16976f-ed6c-41ae-b7ab-2e6fd55b75a1',\n",
       " 'status': 'COMPLETED',\n",
       " 'success': True,\n",
       " 'results': [{'shots': 1,\n",
       "   'success': True,\n",
       "   'data': {'statevector': Statevector([ 0.00000000e+00+0.00000000e+00j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                 -5.00000000e-01+9.18485099e-17j,\n",
       "                  5.00000000e-01-9.18485099e-17j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                  8.32667268e-17-3.06161700e-17j,\n",
       "                 -1.11022302e-16+3.06161700e-17j,\n",
       "                 -5.00000000e-01+3.06161700e-17j,\n",
       "                  5.00000000e-01-3.06161700e-17j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                  0.00000000e+00+3.06161700e-17j,\n",
       "                  0.00000000e+00-3.06161700e-17j,\n",
       "                  0.00000000e+00+0.00000000e+00j,\n",
       "                  0.00000000e+00+0.00000000e+00j],\n",
       "                dims=(2, 2, 2, 2))},\n",
       "   'meas_level': <MeasLevel.CLASSIFIED: 2>,\n",
       "   'header': {'creg_sizes': [],\n",
       "    'global_phase': 0.0,\n",
       "    'memory_slots': 0,\n",
       "    'n_qubits': 4,\n",
       "    'name': 'circuit-51',\n",
       "    'qreg_sizes': [['q', 4]],\n",
       "    'metadata': {}},\n",
       "   'status': 'DONE',\n",
       "   'seed_simulator': 1598496495,\n",
       "   'metadata': {'num_bind_params': 1,\n",
       "    'runtime_parameter_bind': False,\n",
       "    'parallel_state_update': 8,\n",
       "    'parallel_shots': 1,\n",
       "    'noise': 'ideal',\n",
       "    'batched_shots_optimization': False,\n",
       "    'remapped_qubits': False,\n",
       "    'active_input_qubits': [0, 1, 2, 3],\n",
       "    'device': 'CPU',\n",
       "    'time_taken': 0.000158166,\n",
       "    'measure_sampling': True,\n",
       "    'num_clbits': 0,\n",
       "    'max_memory_mb': 16384,\n",
       "    'input_qubit_map': [[3, 3], [2, 2], [1, 1], [0, 0]],\n",
       "    'num_qubits': 4,\n",
       "    'method': 'statevector',\n",
       "    'required_memory_mb': 1,\n",
       "    'result_subtypes': {'statevector': 'single'},\n",
       "    'result_types': {'statevector': 'save_statevector'},\n",
       "    'fusion': {'enabled': True,\n",
       "     'threshold': 14,\n",
       "     'applied': False,\n",
       "     'max_fused_qubits': 5}},\n",
       "   'time_taken': 0.000158166}],\n",
       " 'qobj_id': '',\n",
       " 'metadata': {'time_taken_parameter_binding': 2.0084e-05,\n",
       "  'max_memory_mb': 16384,\n",
       "  'time_taken_execute': 0.000241375,\n",
       "  'omp_enabled': True,\n",
       "  'max_gpu_memory_mb': 0,\n",
       "  'parallel_experiments': 1},\n",
       " 'time_taken': 0.0014889240264892578}"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = backend.run(circ).result()\n",
    "result.to_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "828904d3-d36c-4cf3-915e-ba8c4f251f82",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statevector([ 0. +0.j,  0. +0.j, -0.5+0.j,  0.5-0.j,  0. +0.j,  0. +0.j,\n",
      "              0. -0.j, -0. +0.j, -0.5+0.j,  0.5-0.j,  0. +0.j,  0. +0.j,\n",
      "              0. +0.j,  0. -0.j,  0. +0.j,  0. +0.j],\n",
      "            dims=(2, 2, 2, 2))\n"
     ]
    }
   ],
   "source": [
    "print(result.get_statevector(decimals=3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "a735c847-e4cb-4462-ae3e-2ffd69beddf1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20244 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qiskit.visualization.plot_histogram(result.get_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51ff186c-05df-479c-afd6-3b9b8038d7f0",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 5. Παράδειγμα: Το κύκλωμα Error Detection/Correction 5x5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "c8233b2e-2523-47b0-b015-e55994aed444",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 25080 characters]",
      "text/plain": [
       "<Figure size 872.774x535.111 with 1 Axes>"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "circuit = qiskit.QuantumCircuit(5,2)\n",
    "\n",
    "#circuit.x(4)  # Θέση 01\n",
    "#circuit.x(3)  # θέση 10\n",
    "circuit.x(2)  # θέση 11\n",
    "\n",
    "circuit.barrier()\n",
    "\n",
    "circuit.cx(4, 0)\n",
    "circuit.cx(3, 0)\n",
    "circuit.cx(3, 1)\n",
    "circuit.cx(2, 1)\n",
    "circuit.cx(1, 0)\n",
    "\n",
    "circuit.measure(0,0)\n",
    "circuit.measure(1,1)\n",
    "\n",
    "circuit.draw('mpl', style='iqp', reverse_bits=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75d6fc87-b87f-4741-b7bb-32f13ce0a8ee",
   "metadata": {},
   "source": [
    "Το τρέχουμε στον simulator του qiskit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "0335806c-d0ee-4e17-a948-c0416b30548b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12308 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit_aer\n",
    "backend = qiskit_aer.Aer.get_backend('statevector_simulator')\n",
    "result = backend.run(circuit).result()\n",
    "qiskit.visualization.plot_histogram(result.get_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "2c8499d8-86da-43a7-9e64-f8270a821017",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[AerSimulator('aer_simulator'),\n",
       " AerSimulator('aer_simulator_statevector'),\n",
       " AerSimulator('aer_simulator_density_matrix'),\n",
       " AerSimulator('aer_simulator_stabilizer'),\n",
       " AerSimulator('aer_simulator_matrix_product_state'),\n",
       " AerSimulator('aer_simulator_extended_stabilizer'),\n",
       " AerSimulator('aer_simulator_unitary'),\n",
       " AerSimulator('aer_simulator_superop'),\n",
       " QasmSimulator('qasm_simulator'),\n",
       " StatevectorSimulator('statevector_simulator'),\n",
       " UnitarySimulator('unitary_simulator'),\n",
       " PulseSimulator('pulse_simulator')]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qiskit_aer.Aer.backends()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "87b68ae6-59ad-4132-9a2d-8a17dfeec436",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12724 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "backend = qiskit_aer.Aer.get_backend('aer_simulator')\n",
    "result = backend.run(circuit).result()\n",
    "qiskit.visualization.plot_histogram(result.get_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5141d233-b9fa-4576-b601-c35e5170eaf6",
   "metadata": {},
   "source": [
    "Υβριδικό κύκλωμα με διόρθωση:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "7d71a308-d115-4917-a05c-2b3cc2cee62c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 50980 characters]",
      "text/plain": [
       "<Figure size 1681.36x535.111 with 1 Axes>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Define quantum and classical registers\n",
    "qr = qiskit.QuantumRegister(5,'qReg')\n",
    "cr = qiskit.ClassicalRegister(5,'cReg')\n",
    "circuit = qiskit.QuantumCircuit(qr,cr)\n",
    "\n",
    "# Circuit operations\n",
    "#circuit.x(4)  # Θέση 01\n",
    "#circuit.x(3)  # θέση 10\n",
    "circuit.x(2)  # θέση 11\n",
    "\n",
    "circuit.barrier()\n",
    "\n",
    "circuit.cx(4, 0)\n",
    "circuit.cx(3, 0)\n",
    "circuit.cx(3, 1)\n",
    "circuit.cx(2, 1)\n",
    "circuit.cx(1, 0)\n",
    "\n",
    "circuit.measure(0,0)  # Measure qubit 0 to classical bit 0\n",
    "circuit.measure(1,1)  # Measure qubit 1 to classical bit 1\n",
    "\n",
    "def conditional(xq,ifq): # Conditional X gates using IfElseOp\n",
    "    truebody = qiskit.QuantumCircuit(qr, cr)\n",
    "    truebody.x(xq)\n",
    "    ifelse = qiskit.circuit.IfElseOp((cr, ifq), true_body=truebody)\n",
    "    circuit.append(ifelse, qargs=qr, cargs=cr)\n",
    "\n",
    "conditional(2,3)\n",
    "conditional(3,2)\n",
    "conditional(4,1)\n",
    "\n",
    "# Measure remaining qubits\n",
    "circuit.measure([2,3,4],[2,3,4])\n",
    "\n",
    "# Draw the circuit (requires matplotlib and pylatexenc)\n",
    "circuit.draw('mpl', style='iqp', reverse_bits=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "d03c5e2c-e804-48df-907a-9059b5889950",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counts: {'00011': 1024}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 13932 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "backend = qiskit_aer.Aer.get_backend('aer_simulator')\n",
    "# backend = qiskit_aer.AerSimulator()   # Εναλλακτικά\n",
    "result = backend.run(circuit).result()\n",
    "print(\"Counts:\", result.get_counts())\n",
    "qiskit.visualization.plot_histogram(result.get_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74971939-86a8-4c3e-a03b-9d550a9b0924",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
