{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "aee4cea9-ff2a-4c2b-a552-e2bc294414cb",
   "metadata": {},
   "source": [
    "# Quantum Computation, part 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e6cd111-2dcb-47ff-bda1-ef14a3dd60cb",
   "metadata": {},
   "source": [
    "Computational note for Quantum Computation course (MAT3420), spring 2026\n",
    "\n",
    "Part 2 covers from lecture 12 to 19"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "770e7714-4d11-45ff-a516-09d7609bb284",
   "metadata": {},
   "outputs": [],
   "source": [
    "# print options\n",
    "import sympy as sy\n",
    "sy.init_printing(use_unicode=True)\n",
    "import numpy as np\n",
    "np.set_printoptions(suppress=True, legacy='1.25')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "455d8a0c-9fa8-4f6c-a424-855a37cb457c",
   "metadata": {},
   "source": [
    "## Lecture 12"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "708956f8-8b48-4144-8467-cbd510ff5577",
   "metadata": {},
   "source": [
    "The CHSH game:\n",
    "two cooperating players Alice and Bob plays the following game\n",
    "- Charlie (referee) gives them input bits $x$ and $y$ separately\n",
    "- they need to independently give back answer bits $a$ and $b$\n",
    "- they win if $a + b = x y \\bmod{2}$ holds, lose otherwise\n",
    "\n",
    "Alice and Bob prepares the EPR pair state before the game, and share the   ($H_A = \\mathbb{C}^2 = H_B$):\n",
    "$$ w = \\frac{1}{\\sqrt{2}} (\\ket{00} + \\ket{11}) \\in H_A \\otimes H_B $$\n",
    "\n",
    "For Alice's part, if $x = 0$, she will measure her part in the computational basis to decide $a$.\n",
    "Otherwise, she will measure it in the $(\\ket{+}, \\ket{-})$-basis, and reply with $a = 0$ in the \"+\" case, $a = 1$ in the \"-\" case.\n",
    "\n",
    "For Bob's part, he is going to work with the orthonormal basis\n",
    "$$ v = \\cos \\frac{\\pi}{8} \\ket{0} + \\sin \\frac{\\pi}{8} \\ket{1}, \\quad\n",
    "v' = \\cos \\frac{5\\pi}{8} \\ket{0} + \\sin \\frac{5\\pi}{8} \\ket{1} $$\n",
    "if $y = 0$, and otherwise with the orthonormal basis\n",
    "$$ w = \\cos \\frac{-\\pi}{8} \\ket{0} + \\sin \\frac{-\\pi}{8} \\ket{1}, \\quad\n",
    "w' = \\cos \\frac{3\\pi}{8} \\ket{0} + \\sin \\frac{3\\pi}{8} \\ket{1}. $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2d8f057e-5047-41c1-b5a2-442510a3110f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "rng = np.random.default_rng()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ec09a01c-ed02-421b-bcbd-079361cf5e6b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.70710678, 0.        , 0.        , 0.70710678])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeroket = np.array([1, 0])\n",
    "oneket = np.array([0, 1])\n",
    "plusket = np.array([1, 1]) / np.sqrt(2)\n",
    "minusket = np.array([1, -1]) / np.sqrt(2)\n",
    "EPR_stt = (np.kron(zeroket, zeroket) + np.kron(oneket, oneket)) / np.sqrt(2)\n",
    "EPR_stt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "62e30b4e-e111-4930-b32f-b120f93f83ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "bob_v = np.array([np.cos(np.pi / 8), np.sin(np.pi / 8)])\n",
    "bob_vp = np.array([np.cos(5 * np.pi / 8), np.sin(5 * np.pi / 8)])\n",
    "bob_w = np.array([np.cos(-np.pi / 8), np.sin(-np.pi / 8)])\n",
    "bob_wp = np.array([np.cos(3 * np.pi / 8), np.sin(3 * np.pi / 8)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "08fabb07-144b-43e1-a67a-3516be87adc7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def col_vec_inn_prod(v1, v2):\n",
    "    \"\"\"Hilbert space inner product of column vectors.\"\"\"\n",
    "    return np.conjugate(v1).dot(v2)\n",
    "\n",
    "\n",
    "def measure_part_in_twoqubit(v, loc, basis_choice):\n",
    "    \"\"\"Measure one qubit of a two-qubit state in a specified basis.\n",
    "\n",
    "    The function performs a projective measurement on one subsystem of a\n",
    "    two-qubit state and returns both the measurement outcome and the\n",
    "    post-measurement state.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    v : numpy.ndarray\n",
    "        One-dimensional complex array of length 4 representing a two-qubit\n",
    "        state in the computational basis.\n",
    "    loc : {\"A\", \"B\"}\n",
    "        Which qubit to measure.\n",
    "        ``\"A\"`` measures the left (first) qubit,\n",
    "        ``\"B\"`` measures the right (second) qubit.\n",
    "    basis_choice : int\n",
    "        Choice of measurement basis for the measured qubit:\n",
    "        ``0`` for the computational basis,\n",
    "        ``1`` for the |+⟩ / |−⟩ basis;\n",
    "        ``2`` for Bob's first basis;\n",
    "        ``3`` for Bob's second basis.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    int\n",
    "        Measurement outcome, ``0`` or ``1``, in the chosen basis.\n",
    "    numpy.ndarray\n",
    "        One-dimensional complex array of length 4 representing the\n",
    "        normalized post-measurement two-qubit state.\n",
    "    \"\"\"\n",
    "    # to be on the safe side, do not assume ||v|| = 1\n",
    "    # normalize the input vector\n",
    "    norm_v = np.sqrt(np.real(col_vec_inn_prod(v, v)))\n",
    "    v = v / norm_v\n",
    "    # decide basis\n",
    "    match basis_choice:\n",
    "        case 0:\n",
    "            basis_v0 = zeroket\n",
    "            basis_v1 = oneket\n",
    "        case 1:\n",
    "            basis_v0 = plusket\n",
    "            basis_v1 = minusket\n",
    "        case 2:\n",
    "            basis_v0 = bob_v\n",
    "            basis_v1 = bob_vp\n",
    "        case _:\n",
    "            basis_v0 = bob_w\n",
    "            basis_v1 = bob_wp\n",
    "    # decide PVM\n",
    "    sE0 = np.atleast_2d(basis_v0).T @ np.atleast_2d(basis_v0)\n",
    "    sE1 = np.atleast_2d(basis_v1).T @ np.atleast_2d(basis_v1)\n",
    "    if loc == \"A\":\n",
    "        E0 = np.kron(sE0, np.eye(2))\n",
    "        E1 = np.kron(sE1, np.eye(2))\n",
    "    else:\n",
    "        E0 = np.kron(np.eye(2), sE0)\n",
    "        E1 = np.kron(np.eye(2), sE1)\n",
    "    # the case 0 happens with probability ⟨v, E0(v)⟩\n",
    "    threshold = col_vec_inn_prod(v, E0 @ v)\n",
    "    rand_num = rng.random()\n",
    "    if rand_num < threshold:\n",
    "        E0v = E0 @ v\n",
    "        norm_E0v = np.sqrt(np.real(col_vec_inn_prod(E0v, E0v)))\n",
    "        new_state = E0v / norm_E0v\n",
    "        return (0, new_state)\n",
    "    else:\n",
    "        E1v = E1 @ v\n",
    "        norm_E1v = np.sqrt(np.real(col_vec_inn_prod(E1v, E1v)))\n",
    "        new_state = E1v / norm_E1v\n",
    "        return (1, new_state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "899165f6-e3df-4a9b-a698-ab6ae8fe287e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, array([0.5, 0.5, 0.5, 0.5]))"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "measure_part_in_twoqubit(EPR_stt, \"A\", 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "cd03b21c-53f5-46dd-a584-3b7fc9bb412b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, array([ 0.14644661, -0.35355339, -0.35355339,  0.85355339]))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "measure_part_in_twoqubit(EPR_stt, \"B\", 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "38e07b24-f53c-4c27-b762-e278ba8e9c41",
   "metadata": {},
   "outputs": [],
   "source": [
    "def play_CHSH():\n",
    "    init_vec = EPR_stt\n",
    "    # Charlie's question bits\n",
    "    x, y = rng.integers(2), rng.integers(2)\n",
    "    # Alice computes her answer first\n",
    "    a, new_state = measure_part_in_twoqubit(init_vec, \"A\", x)\n",
    "    # Bob computes his answer next\n",
    "    b, _ = measure_part_in_twoqubit(new_state, \"B\", y + 2)\n",
    "    # they win if a + b = x y mod 2\n",
    "    if (a + b) % 2 == (x * y) % 2:\n",
    "        return \"win\"\n",
    "    else:\n",
    "        return \"lose\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "bb49e1da-aa61-490c-9120-7651c3eec0e8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABlElEQVQ4EYWUzVECQRBGQRNYzcDlykn0TpWYAYaghmB5Yq+YAaYAGeCBuyUZ4NUbksH63jCzNYtYdlXT833T038zS7eu645SVVWBeQ5g/yOew79lnH4l+ClyV9itGH4dOAOqk8lkltbJws3RcYZL8DJhLXiK1uhIfGJUoj9gPkKG9s89MK96Cn7MXThrtTt0Lh8CYnvorcQ/MmJ/QxDHkYtjKeDLFPAdYgyxPHC2oll20oOf+FjRMSm69q3gZMnjAPZDt2oTLCL3p8Fnw2aJ7aYKO4A7yNd4yspsb39zkTxmOHcJX6Lh5vOAVmcrVmZrOjmvVDXwqNjZAr8Xd0PLAG95gG1uMAbS2SQX4F9zg3O+ttpcaKrQFtNjZRlm6uystkBtvyUEsYjzPJgOp6gH4Kv8vbnXGQ6H36vVqs/yi3XzTvF1DH2sQYOwLvE9O2FhKzuJuHdoTNh8fvh5CdfYVkdwJtmmGdqSbd/EBCybL8gHGwaONekSbRLoF2XEfi9/h2a2bT/2JK0/Bw6E95Y2D+ya/cEPPpPKOHD7VQQAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle 82$"
      ],
      "text/plain": [
       "82"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[play_CHSH() for _ in range(100)].count(\"win\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ad1037d-f3b1-4c99-acc5-e596203ab8ce",
   "metadata": {},
   "source": [
    "## Lecture 13"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0874735c-5af0-495e-a872-d688313a7519",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sy\n",
    "from sympy.physics.quantum import TensorProduct\n",
    "from functools import reduce\n",
    "import itertools as it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "01b788c6-92ff-4043-8de8-4772c02a97dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "zeroket = sy.Matrix([1, 0])\n",
    "oneket = sy.Matrix([0, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8031eefc-9818-4513-896a-922e1ee13e1e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def comp_basis(x):\n",
    "    \"\"\"Return the computational basis vector |x⟩.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    x : iterable of int\n",
    "        Iterable of bits (0 or 1) specifying the computational basis\n",
    "        index.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    sympy.Matrix\n",
    "        One-dimensional SymPy column matrix representing the vector |x⟩.\n",
    "    \"\"\"\n",
    "    vec_seq = (zeroket if xi == 0 else oneket for xi in x)\n",
    "    return reduce(TensorProduct, vec_seq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "68847437-dc64-43c8-82a5-7cbf10123184",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}0\\\\1\\\\0\\\\0\\end{matrix}\\right], \\  \\left[\\begin{matrix}0\\\\0\\\\1\\\\0\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡0⎤  ⎡0⎤⎞\n",
       "⎜⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢1⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥, ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢1⎥⎟\n",
       "⎜⎢ ⎥  ⎢ ⎥⎟\n",
       "⎝⎣0⎦  ⎣0⎦⎠"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# |01⟩ and |10⟩\n",
    "comp_basis([0, 1]), comp_basis([1, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d10a7668-3ddb-4ab7-aae0-46d08d11f4b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def dot_pr(x, y):\n",
    "    \"\"\"Return the dot product of (integer) sequences.\"\"\"\n",
    "    return sum(xi * yi for xi, yi in it.zip_longest(x, y))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "b303562b-958c-4797-8292-45785cfcc158",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAOCAYAAAASVl2WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAZElEQVQYGWP8//8/Aww0NDQYAdmrgdgYyP4AEmcBMgSA9GwgfgfEJkCsBMRwAFIAUhkKEgGyy4AUyBQ4YIKzcDBGFUACBj0chKHhJQQLN0ZQZAGDGBRBIOACxKC4OQfE94B4NwDm+hiAOyllRAAAAABJRU5ErkJggg==",
      "text/latex": [
       "$\\displaystyle 1$"
      ],
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dot_pr([0, 1], [1, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "0e61644f-1bbf-4b38-9167-7c56be0aa29d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def v_y(y):\n",
    "    \"\"\"Construct the state vector from Proposition 13.1.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    y : iterable of int\n",
    "        Iterable of bits (0 or 1).\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    sympy.Matrix\n",
    "        One-dimensional SymPy column matrix representing the normalized sum of\n",
    "        (-1)^(x · y) |x⟩ over all bit strings x of the same length as y.\n",
    "    \"\"\"\n",
    "    n = len(y)\n",
    "    ind_list = it.product(range(2), repeat=n)\n",
    "    res = sy.Matrix([0] * 2**n)\n",
    "    for x in ind_list:\n",
    "        res += comp_basis(x) * (1/sy.sqrt(2**n)) * (-1)**dot_pr(x, y)\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1bd16cdd-1be3-44c3-a1bb-a6853d1d14e3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}\\frac{1}{2}\\\\\\frac{1}{2}\\\\\\frac{1}{2}\\\\\\frac{1}{2}\\end{matrix}\\right], \\  \\left[\\begin{matrix}\\frac{1}{2}\\\\- \\frac{1}{2}\\\\- \\frac{1}{2}\\\\\\frac{1}{2}\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡1/2⎤  ⎡1/2 ⎤⎞\n",
       "⎜⎢   ⎥  ⎢    ⎥⎟\n",
       "⎜⎢1/2⎥  ⎢-1/2⎥⎟\n",
       "⎜⎢   ⎥, ⎢    ⎥⎟\n",
       "⎜⎢1/2⎥  ⎢-1/2⎥⎟\n",
       "⎜⎢   ⎥  ⎢    ⎥⎟\n",
       "⎝⎣1/2⎦  ⎣1/2 ⎦⎠"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v_y([0, 0]), v_y([1, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "d7ccfa59-b2fd-4761-a580-ca82a39ea288",
   "metadata": {},
   "outputs": [],
   "source": [
    "def tens_pow_H(k):\n",
    "    \"\"\"Return the tensor product of copies of the Hadamard matrix.\"\"\"\n",
    "    H = sy.Matrix([[1, 1],\n",
    "                   [1, -1]]) * (1/sy.sqrt(2))\n",
    "    return reduce(TensorProduct, (H,) * k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "cc17f6d0-ad18-4bf0-9c78-db55207d7ca6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2}\\\\\\frac{1}{2} & - \\frac{1}{2} & \\frac{1}{2} & - \\frac{1}{2}\\\\\\frac{1}{2} & \\frac{1}{2} & - \\frac{1}{2} & - \\frac{1}{2}\\\\\\frac{1}{2} & - \\frac{1}{2} & - \\frac{1}{2} & \\frac{1}{2}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡1/2  1/2   1/2   1/2 ⎤\n",
       "⎢                     ⎥\n",
       "⎢1/2  -1/2  1/2   -1/2⎥\n",
       "⎢                     ⎥\n",
       "⎢1/2  1/2   -1/2  -1/2⎥\n",
       "⎢                     ⎥\n",
       "⎣1/2  -1/2  -1/2  1/2 ⎦"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tens_pow_H(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "077b77d0-4c8d-466b-b031-c923901b67ee",
   "metadata": {},
   "source": [
    "### Deutsch-Josza problem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "69e128c6-ace1-4834-93d2-c95d9c63ba22",
   "metadata": {},
   "outputs": [],
   "source": [
    "def U(k, f):\n",
    "    \"\"\"Return the U_f gate for the Deutsch-Josza problem.\"\"\"\n",
    "    ind_list = it.product(range(2), repeat=k+1)\n",
    "    res = sy.zeros(2**(k+1))\n",
    "    for in_x in ind_list:\n",
    "        out_x = in_x[:-1] + (f(in_x[:-1]) ^ in_x[-1],)\n",
    "        res += comp_basis(out_x) * comp_basis(in_x).T\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "d037d22b-8af3-4af6-acd6-ba864435d39c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}0 & 1 & 0 & 0\\\\1 & 0 & 0 & 0\\\\0 & 0 & 0 & 1\\\\0 & 0 & 1 & 0\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡0  1  0  0⎤\n",
       "⎢          ⎥\n",
       "⎢1  0  0  0⎥\n",
       "⎢          ⎥\n",
       "⎢0  0  0  1⎥\n",
       "⎢          ⎥\n",
       "⎣0  0  1  0⎦"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U(1, lambda x: 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad4a0d9d-7c40-4a3b-af4e-b505253a1ad9",
   "metadata": {},
   "source": [
    "the vector $v_y$ for $y = 1 \\cdots 1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "9ed6d854-96ba-4e1e-a686-92a1839b9d23",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡ √2 ⎤\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎣ 4  ⎦"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v_y([1] * 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81e60671-f56a-41a4-bdcc-4056128e4c12",
   "metadata": {},
   "source": [
    "the constant case gives $\\pm v_y$ for $y = 1 \\cdots 1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "fcf60d26-4816-4a7c-9641-353196d2b354",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡-√2 ⎤\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎣ 4  ⎦"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U(2, lambda x: 1) * v_y([1] * 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ff5da84-9621-4a9f-833e-b6501277c46e",
   "metadata": {},
   "source": [
    "the balanced case gives a vector orthogonal to the above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d4fd780a-b56b-4db7-bcdb-73af84be9f2e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\- \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡ √2 ⎤\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢-√2 ⎥\n",
       "⎢────⎥\n",
       "⎢ 4  ⎥\n",
       "⎢    ⎥\n",
       "⎢ √2 ⎥\n",
       "⎢ ── ⎥\n",
       "⎣ 4  ⎦"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U(2, lambda x: x[0]) * v_y([1] * 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "e93d2c31-1af3-4297-aa66-259ddfc119e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}0\\\\0\\\\0\\\\0\\\\0\\\\0\\\\0\\\\1\\end{matrix}\\right], \\  \\left[\\begin{matrix}0\\\\0\\\\0\\\\0\\\\0\\\\0\\\\0\\\\-1\\end{matrix}\\right], \\  \\left[\\begin{matrix}0\\\\0\\\\0\\\\1\\\\0\\\\0\\\\0\\\\0\\end{matrix}\\right], \\  \\left[\\begin{matrix}0\\\\1\\\\0\\\\0\\\\0\\\\0\\\\0\\\\0\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡0⎤  ⎡0 ⎤  ⎡0⎤  ⎡0⎤⎞\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢0⎥  ⎢1⎥⎟\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢0⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢1⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥, ⎢  ⎥, ⎢ ⎥, ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢0⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢0⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0 ⎥  ⎢0⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥  ⎢  ⎥  ⎢ ⎥  ⎢ ⎥⎟\n",
       "⎝⎣1⎦  ⎣-1⎦  ⎣0⎦  ⎣0⎦⎠"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# computational basis presentation\n",
    "Hpow = tens_pow_H(3)\n",
    "Hpow * U(2, lambda x: 0) * Hpow * comp_basis([1] * 3), \\\n",
    "    Hpow * U(2, lambda x: 1) * Hpow * comp_basis([1] * 3), \\\n",
    "    Hpow * U(2, lambda x: x[0]) * Hpow * comp_basis([1] * 3), \\\n",
    "    Hpow * U(2, lambda x: (x[0] + x[1]) % 2) * Hpow * comp_basis([1] * 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50423d86-a493-4b6f-8092-242ea4146abe",
   "metadata": {},
   "source": [
    "### Bernstein-Vazirani problem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "ad23dd27-5341-43a9-883f-e2e917098572",
   "metadata": {},
   "outputs": [],
   "source": [
    "def V(k, f):\n",
    "    \"\"\"Return V_f gate for the Bernstein-Vazirani problem.\"\"\"\n",
    "    ind_list = it.product(range(2), repeat=k)\n",
    "    res = sy.zeros(2**k)\n",
    "    for x in ind_list:\n",
    "        res += comp_basis(x) * comp_basis(x).T * (-1)**f(x)\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "9fd9521c-a06b-4e2a-9444-0ee200c8daea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAABkCAYAAACWwst8AAAACXBIWXMAAA7EAAAOxAGVKw4bAAASTklEQVR4Ae2dT47cNhrFO4Yxy6ATA7Of9g3c8Qls77NInBPYuUGM7LILnBvYPoFjL2bv+ASO+wbOAQYYxxjMcoDMe2p9BZWapVapRPKx+xFQUX/Jpx+/+vSJUrE+++uvv47mpJ9++uk99nuC/LfU/lh/B+u5Tyq9xvZvUxu8zgRIAPbxAdlJiga2fZZaX3IdNNi+SwK/QnUttW0cx+/DG0ynmP80B8nNOTuhsGfY7w/kSWc+KuMXLPPLOUx/DBc8bwIJAk8T6x5g3TeJ9TVX2b5r0m+z7kW2DX9Ln/sap/wC06yA+FKHjgL5hXqI6R+Y5qRnFDJnR+9jAkEANvM85iPHOs6qOXTbdzSQ81kEDrFtHMtekT8xPU6VMxYw6dBRwDEO4NWBhc4K+ccV7FpGebyFfYVp9u3ErrLWXA9dcTX9N8q9jekp1klcoJS1sQ3U9VFjiQQOkrbNc2+5jZS1Z9bG6PwN6vgN06QvunGJgdOZM+y/ED1dclxyM8o5xvQKE7twWHayzzR5cIGV0MVnAO+Q8wLGW+snmAiyuk5lbWwadX3UmDPh/KVtm+fechspa8+tDeWzq5tdL/Sbk2mnQ0chjDJ4u0untkpCmZ8wfYvpexT4cpVCVyoEmh6jKH4pCa5LmOddySyQ/SFZMmVtPGF1fVkaZVQobQWTpG233kbK9lVQG/3wfdQ32QW506HjYEbQZyhgzoNQ2kzribc1Z4mTeId1BMnup1pJWRuZqOur1W5K9bbcRsrai2iD/2FXC31xdAknbSvp0PurACP01aLzZO1aK+9DzseEpOiz4vZaSVkbmajrq9VuSvW23EbK2ktqoz8+gX/+YZdhJR06dv4R09zXFHeV3cz6mdH3lzVOSFkbeajrq9FmanW23EbK2ktrQ33sQWCUTv+cTBccOg5iZM7p0g74ZIltrgxnPfUmT60uF2VtbG11fW1a5LqqW24jZe01tNEv81lfsi/9gkPHzuH9V3mzZV27rFraraq1T1eurI3K1fVN070eW1tuI2Xtq2qDI4+XNsJPb1nnlkPHzoxC6fn5vuNUtLpVyBVYSPWdx2nFVZjvpddIytrIQ11fjTZTq7PlNlLWXksbnfod+Og7Y0PbcujYyF+EMl2n7pajwcUr1a0S6+Lh6DmhQp/K2ohAXV+hZpKupuU2UtZeUVv45+/Ghjd26HwFh+m6vKp4frbnnzznk+GKfj4i9JpMlLURk7q+RLNeu1Utt5Gy9uLacCFhnUz87cxW2jh07MRIlK/g8O2W69TdEkA4DMFXsTDITzHP9/FrMlHWRlTq+gbNeW1nW24jZe21tNGp8+HoVrfLxqFjY3S3RKd7bsuPhwURAeeub7J8gOFD4I/IN0+PMc+LHLk8mjw480ZlbTx1dX2ZmydVvJRtt95GyvZVUdub3vC2ul1uDqyRQ5UyxY7nSyt/AgCvaEy8G2Di2C7sn+aYKbXfrGE0zsG47iLnQ1Dm97B8hrx2UtZGNur6srcf7ETZtltvI2X7qqEtul3Cj3b2/Vn8wQWM8U+sYQi/6M8EcBxDfw5udRvzVR4gdmfkjytDAHbEPkIOV7vIJtcEYftek6bLWsO2UUb8O9EXmO+6hLsuFyywa4GTHbFtzQRMwATaIBA9B5tnf9GHHmG7HXobDWmVJmACJvB7j2DzYDQcevSfh8c3KhMwARMwAW0C7OJmCv99FA49QvZ359v9aQImYAImIE4gIvTw3xuHftILd5eLeAtangmYgAn0BMJf8/lnlyJCjxWxQ2x3bgImYAImIEgg3myhNMx3/eg3MBPROVd+EtRtSSZgAiZgAmkCEYR3fpwRejwhjQ3pw7zWBEzABExAjUAE4RuHHhF6bFATbD0mYAImYAJpAhGI3+JmRujdDPKpsX25r5MJmIAJmIAWgfDbXWDOsVyKR+joq49/ruZ4KbcxcfyUuNJo4UqogVZ2U3HcjtOSzx3UuanrSzTl6qtaZwD9VWx7TkMos62oLXpWNg79uIcZnn4O28X74MT5MvzPyLtRHZGz/vfIH2CSdeq9zhfQSk587zMuhJjNn1C/NDd1fflbqHvTQLqNdjGobdu7dA3XK9uXiLbOj98AtC+H4HLO48Q52BIHANsM0Yt5XmG4HP/CkVPC4rKpE9O3mL5HIS8XF7TgQNQpzU1d3wLkex/SMgNor2bbc0ArsxXQxl4Ops6P06FHhE7HmjvxH5HOEpXwF6r3ASe0JHa51qvUuanrK2E8ZpCPsjLb2trCb3e+s2iEjvbmIGCprp3oaolBwvKZRpslq3NT11ei1c0gH2VltlLa6NAjRegey6vmM6PvYt0/q55cxsLUuanry9g0m6LNYINi9RlltiLatgLkoUOP0H31RukLDGc9VU9325BLQKPlqnNT11ei2c0gH2VltnLa6NCVnGi8E5/PPK5myerc1PWVsAozyEdZmW1ubVsB8s0B478N5pfMft4fFPm4jK1bg9HGuNJl6/bpb4/eot59LmB8q+VspLX0YlVuM042p76/z6i/1C6f9xVFPqw3J4NhPcn5hm07eT6jlVXZjrSMFw/RtpZt/y9E0Q6GDv2/sSFHjsr4ahSLTjnUWBcPR1eXwPpR6OnqBWcusDa3y05PXd9l+tfYXptBq7Y9h31ttlMaFbUN+9APdej/6U8+8hQL/lP1SWJDROjxT9aJXa71KnVuufT9S6jVw64jH0vLxWBcz3VcVma7VNtatr1lj0OHXsJQ+HP5zb9rDCpk5HzWRxqD1Z7tCahzU9dXwpDMIB9lZbZS2oo6dDjs52jzj8i/ibbHPLtbHmJ6FOsayONBR9xZZJWszk1dX9bG6Qu/QgyK2vactlFmq6Zt2Ic+h+0a+zAa52Bcd5HzISjze1g+Qy6doJFXY6b759nRK6xjv/8b5LxY5Uzq3NT15WybKLtZBpVtO/hN5cpsZbQVd+gwHD6c5HgozSVo5898qyR1bur6SjRaywxq2vactlFmq6StaJfLnIbzPiZgAiZgAssI2KEv4+ajTMAETECOgB26XJNYkAmYgAksI2CHvoybjzIBEzABOQJ26HJNYkEmYAImsIyAHfoybj7KBEzABOQI8LVFvj/NgWIOfQ+c72PzdcSpAWuw2ckEZhPgz6pVXnG1fc9uNu84g8Batk27/Cfr4+uTjND5f5VfY7qD6ZB0goP5v6BFfj15iFAf2wwB/oBL5b9mbd/NmE0TQteybdol/ffXcOjHdOhOJmACJmACV4CAHfoVaESfwjYBRirba7xkAteDQPGf/hMrvnBPe7wcy+U2Jo7twr6g6klZG+FAH7vGOKbMKeY/cZ1KUmAHDXTmfyLn6J0cY6NoUmAwdcLq+qa0z9mG86vy/VDhWjxCx4m/R8O8Q/4E0y+Yf4KJg1uxL6hqUtUGXceYOBAY+5NfYKrOatxQKuyggxc5BgdkVjRSV2EwbptYVtcXOvfN2c6Yqn0/lLgWdeg4cT6AJfzX0WiY5xeQy1Uffolr+wR9/Ds8vvHxMtip5GrsoId3fQwUiiU1BuMTV9c31rvPMs6t2vdDjWtRh45G4miFqdcj32H9fcApGlGNjEZZ20iq3KIiu7v8ohckpchgePrq+oZaW5qX4lraofNVndR76tF/zu21krK2Wkzm1ivFrg8Msv3h+A4oUgwSGtX1JSQ3sUqKazGHPjP6rvIOu7I2dZMWZfcYuvh8pkgSZbA5d3V9G6GNzShyLebQ0VbhrKdug2t1uShrUzdzOXYlnXnfOHIMRkajrm8kt5lFOa4lHfqcVro1Z6dK+yhrq4RkdrVmd3SkzkBd32xjE9uxKNebBU8+1Xce1ceVrnS/Z9SvrC00quZml34uFO1V27apQ7qN+q6Lt9C5zx063/o6C8iVcjmuQ4c+1RVyMC/A56tFLCfVaLEuHo4eXN8+BShr2+c8auxrdueDIqnaNm1CvY2oDzJPa9jvIXUqch12uYRTPeQcLzuWI4ydJHaKKIbbayVlbbWYzK3X7I6O1Bmo65tra2r7SXEdOvQSoPiT9a8SFfHqzJ9q80pdKylrq8Vkbr1mdz4cg6ptsx3dRnOteb/9ZLjSf9KhhxONKHm/09ljb1TIsdc/Iv8mDsM87wweYnoU62rkytpGPOIhS/b2GtW7c7EhdjvP4dAN6gzU9R3Kf3B80e+HANctPzDsQx8wyTrLaJyDcd1FzoegzO9hufYDDsjo+vEktYEPIwGm++fZEceu4DMHjoPDC2XtpNyupdioM1DXt7idKn8/ZLjSofNJbYn+866xAJ53BCr/QtNpig9xbfyJsWxSZlcKmjoDdX2HtBPOrdr3Q4nrsMulmFM/pOF8rAmYgAmYwIZA+G0Gykd06PEu5a3NLp4xARMwARNogUD0oXd+3BF6C01mjSZgAiaQJrAzQg9Pnz7Ma03ABEzABNQIRM+KI3S1lrEeEzABE9iTQETo3a/s2eXyoS/AEfqeJL27CZiACVQmcNLX3/lxOvQYPyU2VNbn6k3ABEzABGYSiEB8E6GHQ4/QfWY53s0ETMAETKAygQjEzx06XooPh36E+dhYWaOrNwETMAETmEEgAvFNhM5jwqnboc8g6F1MwARMoDaBQQDOock/UU+M5XKGeTrzIg4dlT9l5Ugcy+U2Jo6fEhcVrq+WrC0vevC9gxo4Ls0p5jsjzFtj2dKV7Yck1PVNtZa6dugrbdvhrze+Mxz6O4DkCIgcZCZrwkm/RwU/I3/NipDzluE98geYNsK4rXRC/daWAXrfxi9QNN+V5RCzYYgZaqtXpLL9kIq6vqmWU9UOXfRftWybFxAmjsnepRt9zgidKTWe8/mWFT5x8o9RzDHyzpmzSMwzSuPyMy7XStaWjzzbGBP/MoyDsr3MV1O9kpXth1TU9U21nLJ2aKtp2xyplokBeZfCof/eL4fH7xdXzzgiWlw8hoVT0H3A4dWuVrK2WuSvRr3K9kPC6vqmrKBl7VPndei28NfbETqvMii56+7AfM7bYY7lzdvucYquFm6vlaytFvmrUa+y/ZCwur4pK2hZ+9R5Ld7WB7/01ZsHoiwsInTORzcI4a2eZkbfX65e8YwCrW0GJO+yk4Cy/VC0ur6dYBvXPnVeK2wLP72Jzlnm0KG/6St5sEJlqSLCWfNuYFeq1eVibbtaxOvnEFC2H+pX1zfFuGXtU+d16Lbv+gK2nkltHDqu4vT0dLab//s8tMYFx8fIYQsOzX6ItWVHfKUrULYfglfXN2UcLWufOq+pbV2EDr8dPSvdvjdHR/yK5cfY6Q6m1MPL0e57Lab6zqOAuArzvfQaydomqMMWeOf0FtM+d1B8q2VtG5pQWXWTsv0QjLq+qcZrWfvUeS3eRv+Mg/ld3HLmLHDs0PmDD75ayHB+1S8jRLDzHsUmnUI4ing4yv2KJWubRk0+2ON0eq/ru1XZftgq6vqmLKdl7VPndeC2LjpHGVvdLSxz0+XCBcCLbhc69RyJ5Z8kCo4IfauDP7FfzlXWlpPu1S9b2X5IX13flIW0rH3qvJZuY8DNAPlChL7l0PvSf0Z+jJ3jKrC00tRxvANI/XiJ0d8Z6mQkWCtZWy3yV6NeZfshYXV9U1bQsvap89p7G3wku1s4PU8dfMGh44Bf+h35q75VE8qmiI/INw9eMc/uloeYHq1a2Z6FWduewJbvHg+w4q5seUlCRyrbDzGp65tqyoa0l7DtH3tWDLwvpHEfeuxAp/4DQDJSXztqZjTOwbjuIudDUOb3sLxqnz3KXJKsbQm1GcegfRllMcWd3yus4zOTN8iT0Ua3d1sfyvZDkur6plpbVnsp20Y9DH4ZDL/GfNIv73Lo9P4/YOLV4Amm1VIvZPXofw2B1rYGxXQZYMufb1/ppGw/BK+ub8o4lLVDWynbjmebO33yhS6XQcPzoC5KnwLtbSZgAiZgAkUIMMB+jgvIzrcBkw6d0nAQu114YPTZcLWTCZiACZhAYQLwx+wxYZfLzuicknY6dG5Eiij95HzRnyZgAiZgAiUJwJnTkfNPgb7HfLLvPPRMOnQczPcc+cDqWRzg3ARMwARMoCgB/oHGb/DHl748MOnQKRmF8AHmCfLokOdqJxMwARMwgcwE4Hf5VhinWQ9ed73lMpbJwt6i8F8xTYb82O8D9hkfz9dsZgkaH+jl60EA9vEBZ9pC157t+3qY5GpneaBts3eE4yJd5nc7vbMcOgrjrzjpkPljkF0F8wHqrtcRdz6V7VT4wwTO+wiVOdi+lVtHWxv7v/dO8LnHOIj95hz6YFb6P3MOcJ6ROPDbAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\0 & -1 & 0 & 0\\\\0 & 0 & 1 & 0\\\\0 & 0 & 0 & -1\\end{matrix}\\right], \\  \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\0 & -1 & 0 & 0\\\\0 & 0 & -1 & 0\\\\0 & 0 & 0 & 1\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡1  0   0  0 ⎤  ⎡1  0   0   0⎤⎞\n",
       "⎜⎢            ⎥  ⎢            ⎥⎟\n",
       "⎜⎢0  -1  0  0 ⎥  ⎢0  -1  0   0⎥⎟\n",
       "⎜⎢            ⎥, ⎢            ⎥⎟\n",
       "⎜⎢0  0   1  0 ⎥  ⎢0  0   -1  0⎥⎟\n",
       "⎜⎢            ⎥  ⎢            ⎥⎟\n",
       "⎝⎣0  0   0  -1⎦  ⎣0  0   0   1⎦⎠"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "V(2, lambda x: dot_pr(x, [0, 1])), V(2, lambda x: dot_pr(x, [1, 1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "1bd9c8a3-3e50-44e2-aee5-709267a6e4ea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}\\frac{1}{2}\\\\- \\frac{1}{2}\\\\\\frac{1}{2}\\\\- \\frac{1}{2}\\end{matrix}\\right], \\  \\left[\\begin{matrix}\\frac{1}{2}\\\\- \\frac{1}{2}\\\\\\frac{1}{2}\\\\- \\frac{1}{2}\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡1/2 ⎤  ⎡1/2 ⎤⎞\n",
       "⎜⎢    ⎥  ⎢    ⎥⎟\n",
       "⎜⎢-1/2⎥  ⎢-1/2⎥⎟\n",
       "⎜⎢    ⎥, ⎢    ⎥⎟\n",
       "⎜⎢1/2 ⎥  ⎢1/2 ⎥⎟\n",
       "⎜⎢    ⎥  ⎢    ⎥⎟\n",
       "⎝⎣-1/2⎦  ⎣-1/2⎦⎠"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# check Proposition 13.3\n",
    "s = [0, 1]\n",
    "V(2, lambda x: dot_pr(x, s)) * v_y([0, 0]), v_y(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "f135e0df-d567-4c12-bc0d-e328a325301b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}0\\\\1\\\\0\\\\0\\end{matrix}\\right], \\  \\left[\\begin{matrix}0\\\\1\\\\0\\\\0\\end{matrix}\\right]\\right)$"
      ],
      "text/plain": [
       "⎛⎡0⎤  ⎡0⎤⎞\n",
       "⎜⎢ ⎥  ⎢ ⎥⎟\n",
       "⎜⎢1⎥  ⎢1⎥⎟\n",
       "⎜⎢ ⎥, ⎢ ⎥⎟\n",
       "⎜⎢0⎥  ⎢0⎥⎟\n",
       "⎜⎢ ⎥  ⎢ ⎥⎟\n",
       "⎝⎣0⎦  ⎣0⎦⎠"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [0, 1]\n",
    "tens_pow_H(2) * V(2, lambda x: dot_pr(x, s)) * v_y([0, 0]), comp_basis(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9de85a23-f1a7-4d6c-ba69-7d397d4ff433",
   "metadata": {},
   "source": [
    "## Lecture 14"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69ef11cd-ab5c-40f6-bd80-508b5e95cb0b",
   "metadata": {},
   "source": [
    "Simon's problem: we work with Boolean functions $f \\colon \\{0, 1 \\}^k \\to  \\{0, 1 \\}^k$ and a secret string  $s \\in \\{0, 1 \\}^k$ that contains $1$.\n",
    "We know that $f(x) = f(y)$ if and only if either $x = y$ or $y$ is the bitwise-XOR, and want to work out $s$ from $f$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "38de3296-d4ec-41d1-b99f-23ceacd23ffe",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "rng = np.random.default_rng()\n",
    "import itertools as it\n",
    "from functools import reduce"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "ac112b5a-509e-4d8d-aba2-83201782ce86",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set secret string\n",
    "k = 4  # 5 is the sensible maximum of naive implementation?\n",
    "s = tuple([rng.integers(2) for _ in range(k)])\n",
    "if 1 not in s:\n",
    "    # try again\n",
    "    s = tuple([rng.integers(2) for _ in range(k)])\n",
    "    if 1 not in s:\n",
    "        print(\"we could not generate a secret string.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "bc0c4c67-5e09-4e7d-b6c1-b2c416ac99fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# function satisfying the above condition\n",
    "def f_from_s(x):\n",
    "    \"\"\"Return x or x XOR s according to a fixed selection rule.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    x : tuple of int\n",
    "        Tuple of bits (0 or 1) of length ``k`` representing the input.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    tuple of int\n",
    "        A tuple equal to either ``x`` (if ``s`` is the sequence of 0's)\n",
    "        or ``x XOR s``.\n",
    "    \"\"\"\n",
    "    ind_s_1 = [i for i in range(k) if s[i] == 1][0]\n",
    "\n",
    "    if x[ind_s_1] == 0:\n",
    "        return x\n",
    "    y_l = [x[i] ^ s[i] for i in range(k)]\n",
    "    return tuple(y_l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "0030a649-883a-4fb9-b1e5-e9b76ea9004a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((0, 1, 0, 1), (0, 0, 0, 0), (0, 0, 0, 0), (1, 0, 1, 0))"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s, f_from_s(s), f_from_s((0,) * k), f_from_s((1,) * k)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4d5fb63-b12c-4c9d-b38d-91ad6c3da3f0",
   "metadata": {},
   "source": [
    "### classical algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce6bff0d-8bb5-4997-aa34-c71cdd214a77",
   "metadata": {},
   "source": [
    "Th classical \"birthday attack\" algorithm works by picking input strings $x^1, x^2, \\ldots$ and querying $f(x^1), f(x^2), \\ldots$, recording the results.\n",
    "It stops when it sees a pair $x^i, x^j$ such that $f(x^i) = f(x^j)$.\n",
    "Then the secret is $s = x^i \\oplus x^j$, the bitwise XOR."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "c84c2f04-b072-46a1-8ff5-8feb117be1a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "found secret (0, 1, 0, 1) after 5 queries\n"
     ]
    }
   ],
   "source": [
    "res_rec = {}  # dictionary of f(x) as key and x as value\n",
    "ind_list = it.product(range(2), repeat=k)\n",
    "for x in ind_list:\n",
    "    f_x = f_from_s(x)\n",
    "    if f_x in res_rec.keys():\n",
    "        prev_x = res_rec[f_x]\n",
    "        found_secret = tuple(x[i] ^ prev_x[i] for i in range(k))\n",
    "        print(f\"found secret {found_secret} after {1 + len(res_rec)} queries\")\n",
    "        break\n",
    "    # if f(x) is not found, record the results and continue with next x\n",
    "    res_rec[f_x] = x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7928a1a5-745b-4b63-a856-5cf61cbf0391",
   "metadata": {},
   "source": [
    "the expected run time is $\\sqrt{2^k}$, where $k$ is the length of secret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "36d00761-fe2f-4a19-a4a9-938a7d2075c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABdklEQVQ4EZWU7VHCQBCGgaEABjuIHejQQUpQrEDpQP7mn4MdaAvagemAkQ5MB2A6iM97k2VyZA/Jzmz27t2v7N7djpumGXlUFMUN+Aq58vQehu2mxffIa3gDVgmb6JOgD/B5QteDCfgNuEWu4VfWa/iLdSZjNxHKZykvJeyfsJ0hP82Hdc1a+zdhvUQYqGUyEl9K9xjuHOMtWE7MWS8RigcU747TOShHeXAMwvmA51EiEqhloVTHyYX0t64iBufHRDhk6Gqk/UVsmt7ZhTnX6qh1uspDW5ZOH2uuQkUk0K0Z1LJOHO9sTG3V7idty3Q1h7YsBMPPWuadlWHVFGudzQIHPdAu6ZpnLV4h9QBTVKJQnFOyisopAWQkjgj8F6BE6o38R/pJGz9d21s2O2LU4Yy6ms5aZVvpAcZBLW5gjZsjsdclOiDvDGQt3yX8KGx8OlQx0KVQG/QIRRojmmGaXyPkD0KVRsOWvQKrqhrWUF3AL+BhYvwBQvh/HPlSYygAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle 4.0$"
      ],
      "text/plain": [
       "4.0"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(2**k)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80e331a0-cb69-4bcc-bb0d-0f3884e5cb8e",
   "metadata": {},
   "source": [
    "### Simon's quantum algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a1d2967-1880-4a31-9905-32dc448fa641",
   "metadata": {},
   "source": [
    "the quantum algorithm looks at the state\n",
    "$$ v = (H^{\\otimes k} \\otimes I_{2^k}) U_f (H^{\\otimes k} \\otimes I_{2^k}) \\ket{0 \\cdots 0} $$\n",
    "in the $2k$-qubit space $\\mathbb{C}^{2^{2 k}} = \\mathbb{C}^{2^k} \\otimes \\mathbb{C}^{2^k}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "84d37ee3-1a44-444e-86aa-e4ce8a1ae13d",
   "metadata": {},
   "outputs": [],
   "source": [
    "zeroket = np.array([1, 0])\n",
    "oneket = np.array([0, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "57aae6a3-bf07-411a-ada9-e7e57f10cd9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def comp_basis(x):\n",
    "    # computational basis vector\n",
    "    # input\n",
    "    #   x: array of int (0 or 1)\n",
    "    # output\n",
    "    #   numpy.array, 1-dimensional array representing |x⟩\n",
    "    vec_seq = (zeroket if xi == 0 else oneket for xi in x)\n",
    "    return reduce(np.kron, vec_seq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "afd18dda-79e0-46d4-8a7b-303cc8f57e08",
   "metadata": {},
   "outputs": [],
   "source": [
    "def tens_pow_H(k):\n",
    "    # tensor product of copies of the Hadamard matrix\n",
    "    H = np.array([[1, 1],\n",
    "                  [1, -1]]) * (1/np.sqrt(2))\n",
    "    return reduce(np.kron, [H] * k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "50818f7f-3353-4b5b-9b16-c7b4c5b9384e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def termwise_XOR(x, y):\n",
    "    # termwise XOR of tuples\n",
    "    return tuple([xi ^ yi for xi, yi in it.zip_longest(x, y)])\n",
    "\n",
    "\n",
    "def U(k, f):\n",
    "    # U_f gate for the Simon algorithm\n",
    "    ind_list = it.product(range(2), repeat=2*k)\n",
    "    res = np.zeros((2**(2*k), 2**(2*k)), dtype=np.int8)\n",
    "    for in_x in ind_list:\n",
    "        out_x = in_x[0:k] + termwise_XOR(f(in_x[0:k]), in_x[k:2*k])\n",
    "        in_as_row = np.atleast_2d(comp_basis(in_x))\n",
    "        out_as_column = np.atleast_2d(comp_basis(out_x)).T\n",
    "        res += out_as_column @ in_as_row\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "3379fa9e-efa9-4472-8c1d-7961473e266d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFkAAAAVCAYAAAAtkUK4AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD20lEQVRYCe2Z7VEbMRCGjScFOKQD0wEfFQQ6AFIB0EHyE/5lkg6ACgJ0EFJC6AA6CLgD8jyydMhnnTGO7YOZ7IwsabWSVq9Wq9W58/j42MnT8fFxP6//L4/i8xweJfy6nYxOTk4+U13PWFMX6TvWD16P1J96kJYE56x7n/HEsaIVd0aiYZdsi/xLYMQf6oKUeJuU763Dv4kiIaP+QKFHSnzL0gZtg2Hx6Rfet6daKP2oj1lrf3GV8VrRnXkFeUB+ptIBZCoC8ot8Q2Yi6ip5Sr6T8QTHQXbgX2f8W8qrJMe6I12RviIzAnAc85I2Nyr0J7e+Tr5GPheK87SmO/P/ZiEfyQfv4ooE7rSwOvlHOZ9OgnMIT2DeZ2038PeyelPRflpttUHU08Y09ZmF37bu4hl06Ebt91l0MO3aarap39ImCDkJ0Iv9LePokvTdI3PB91RUpyWf6B/KrerOelyjuPa6/Lhwj3eJBPMOmZEjnwnWwc+aikVPhb6qabxipxmZr0F3cd3XXWhB+dGt1gQYTcc/RBK0p0su9KGuGxH4DyT9uT45l/HidNPs/4n0h6QfvoRX1IG2mYjxXoPurmlHkF14yR8XFxcBym/tJCe4F7QHKyVXRleTX5DKSJvwU8TSofxAOiB5WS6MGN/NXabuBgPbXX5c+D1pWvLiukLh73kH6oIZAJZP2aPiToYNpJ4ANooY8cnIXJDOMxmqC6Fl6y6ufUFeJVXgTFoaIAiYx73pKNa7C7TBudaTqOT/DXfcBE/VQqgl3V1rT5CnIpTU366Sj0UB8H6SBKqJjETSRqa8JJtvRql9Jh5zt6V7MGBB1qS1okZCSSOQNfLKginnFqoFlsZwkg6y6fLTfZTkFJNKVj5smfGXudvU3bXeC3I40k1rQEkvi7HnNjyVT778DLnSa81YNY8adDcla/WlaWhXyVKetBmIP09t6Z5pppHdCbJWtpU1VEWUFBAvC4+7T9QqwTuiPojCgR/LIaMtfSTJrd/o4Zo2X0KBKAvmPulgyAmWL8+IY5ILSuLFnL6t6F5TRuO5WeHTnJZqnDpmifAMQUqW51g+o6tvHXFRKSxzB7Vyn+BpI+wTCJ4gC6SkbD2e7iDj3FLxA9Owqfk39m9F96RV1OEofSByQXswk+9Mcq3m6KNL0vLHNqpVxaaYHJ3dYAOCtW6UH/uYMsU4yxDxLnhzAEdgPNXBLQaQWYiPgzxaWAaAE+dAJ92Jz+43R+iuFYtneHQlS3YhXlBTP6/tsGA6RMmRV+WC55vn8OJYfSKu/hlxhrgDu294cfMEaqaxwM6oys8OVcz/F6MGOzRSzAclAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left( 256, \\  256\\right)$"
      ],
      "text/plain": [
       "(256, 256)"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U(k, f_from_s).shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "5f31c599-b790-4848-9e10-308144c57053",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]]\n"
     ]
    }
   ],
   "source": [
    "# first 20 x 20 portion of U_f\n",
    "print(U(k, f_from_s)[0:20, 0:20])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "a58cc63a-17ef-446f-8230-5f2ec4bb3bfb",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]\n",
      " [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "# bottom right 20x20 portion\n",
    "print(U(k, f_from_s)[-20:, -20:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "2cf02e84-a537-4920-b042-247b2c0e6099",
   "metadata": {},
   "outputs": [],
   "source": [
    "H_pow_ampl = np.kron(tens_pow_H(k), np.identity(2**k))\n",
    "simon_gate = H_pow_ampl @ U(k, f_from_s) @ H_pow_ampl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "81af28e7-b336-4791-b9a2-b2c0700f38b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = simon_gate @ comp_basis([0] * (2 * k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "7d0ce930-4a6f-4b38-8947-b4bdcbb2e478",
   "metadata": {},
   "outputs": [],
   "source": [
    "def proj(x):\n",
    "    \"\"\"Return the projection for the computational basis.\"\"\"\n",
    "    basis_vec = np.atleast_2d(comp_basis(x))\n",
    "    return basis_vec.T @ basis_vec\n",
    "\n",
    "\n",
    "def meas_prob(x):\n",
    "    \"\"\"Return the probability of observing x in the first half of v.\"\"\"\n",
    "    return np.dot(v, np.kron(proj(x), np.identity(2**k)) @ v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "0cc5d542-8578-4692-b88e-ef48230acd80",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 0, 0, 0) with probability 0.12499999999999983\n",
      "(0, 0, 0, 1) with probability 2.403565585645449e-64\n",
      "(0, 0, 1, 0) with probability 0.12499999999999983\n",
      "(0, 0, 1, 1) with probability 2.403565585645449e-64\n",
      "(0, 1, 0, 0) with probability 2.403565585645449e-64\n",
      "(0, 1, 0, 1) with probability 0.12499999999999983\n",
      "(0, 1, 1, 0) with probability 2.403565585645449e-64\n",
      "(0, 1, 1, 1) with probability 0.12499999999999983\n",
      "(1, 0, 0, 0) with probability 0.12499999999999983\n",
      "(1, 0, 0, 1) with probability 2.403565585645449e-64\n",
      "(1, 0, 1, 0) with probability 0.12499999999999983\n",
      "(1, 0, 1, 1) with probability 2.403565585645449e-64\n",
      "(1, 1, 0, 0) with probability 2.403565585645449e-64\n",
      "(1, 1, 0, 1) with probability 0.12499999999999983\n",
      "(1, 1, 1, 0) with probability 2.403565585645449e-64\n",
      "(1, 1, 1, 1) with probability 0.12499999999999983\n"
     ]
    }
   ],
   "source": [
    "intervals = {}\n",
    "t = 0.0\n",
    "for x in it.product(range(2), repeat=k):\n",
    "    prob_for_x = meas_prob(x)\n",
    "    intervals[x] = (t, t + prob_for_x)\n",
    "    t += prob_for_x\n",
    "    print(f\"{x} with probability {prob_for_x}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "23eba243-74db-4962-a2a2-11565bcc18b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "x_samples = []\n",
    "for _ in range(k):  # when k is small, it's better to repeat a bit more\n",
    "    rand_num = rng.random()\n",
    "    for x in it.product(range(2), repeat=k):\n",
    "        if intervals[x][0] < rand_num and rand_num < intervals[x][1]:\n",
    "            x_samples.append(x)\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "b38d7882-fd0c-4aaf-962d-db6feccf984e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[ \\left( 0, \\  0, \\  0, \\  0\\right), \\  \\left( 1, \\  1, \\  1, \\  1\\right), \\  \\left( 1, \\  1, \\  0, \\  1\\right), \\  \\left( 0, \\  1, \\  0, \\  1\\right)\\right]$"
      ],
      "text/plain": [
       "[(0, 0, 0, 0), (1, 1, 1, 1), (1, 1, 0, 1), (0, 1, 0, 1)]"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "2ff6fc0c-48b7-43c8-bed9-d0dd94d8c3e8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 1, 0, 1) is a candidate for the secret\n"
     ]
    }
   ],
   "source": [
    "# find s by solving x∙s = 0 mod 2 for the x in the above samples\n",
    "def inn_prod(x, s):\n",
    "    return sum(xi * si for xi, si in it.zip_longest(x, s))\n",
    "\n",
    "\n",
    "def predicate(s):\n",
    "    if s == (0,) * k:\n",
    "        return False\n",
    "    inn_prod_mod_2_list = [inn_prod(x, s) % 2 for x in x_samples]\n",
    "    if 1 in inn_prod_mod_2_list:\n",
    "        return False\n",
    "    return True\n",
    "\n",
    "\n",
    "for s_cand in it.product(range(2), repeat=k):\n",
    "    if predicate(s_cand):\n",
    "        print(f\"{s_cand} is a candidate for the secret\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f1addf3-f495-41fe-843b-0e376e3008aa",
   "metadata": {},
   "source": [
    "Variation: every time we get a new candidate for $x^i = x^i_1 \\cdots x^i_k$, we set the syste of linear equations\n",
    "$$ x^i_1 s_1 + x^i_2 s_2 + \\cdots + x^i_k s_k = 0 \\bmod 2 \\quad (i = 1, 2, \\ldots )$$\n",
    "and continue until there is only one non-zero solution for $s$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "26a9c99b-1f1c-440b-9cc5-82428aed1939",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{s_3: 0}\n",
      "{s_1: -s_2 - s_4, s_3: 0}\n",
      "{s_1: 0, s_2: -s_4, s_3: 0}\n",
      "got a unique solution after 4 trials\n"
     ]
    }
   ],
   "source": [
    "import sympy as sy\n",
    "# prepare variables s_1, ..., s_k\n",
    "s_var = [sy.Symbol(f\"s_{j+1}\") for j in range(k)]\n",
    "\n",
    "x_samples = []\n",
    "l_poly = []\n",
    "for trial_cnt in range(2 * k):\n",
    "    rand_num = rng.random()\n",
    "    for x in it.product(range(2), repeat=k):\n",
    "        if intervals[x][0] < rand_num and rand_num < intervals[x][1]:\n",
    "            new_x = x\n",
    "            break\n",
    "    # ignore x^i = (0,..,0), otherwise set linear polynomial with\n",
    "    # coefficients x^i_j\n",
    "    if new_x == (0,) * k:\n",
    "        continue\n",
    "    else:\n",
    "        f2 = sy.FF(2)\n",
    "        i_th_lin_poly = sy.Poly(sum(f2(new_x[j]) * s_var[j] for j in range(k)))\n",
    "        l_poly.append(i_th_lin_poly)\n",
    "    # find solutions\n",
    "    ans_set = sy.solve(l_poly)\n",
    "    print(ans_set)\n",
    "    if len(ans_set) == k - 1:\n",
    "        print(f\"got a unique solution after {trial_cnt + 1} trials\")\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "677d5eeb-f497-49b0-a428-e68af80d402b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGEAAAAVCAYAAABWtYB0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACNUlEQVRYCe2Z4U3DMBCFU8QAFWxQNqB0g7IBZQPKBvxt/6GyATABgg3oBqjdADagMALfS3MVTRwUNbFxBCddHTvmLu+e7UuOzmQyuUqS5BKVjKbT6XJ9+f/rKwLEeCvmHUiY4eyZG3NfTv/tuiNAzNPY77tvr0ezSeq8o0fojLE3DTQt2D3G5iPa5/qzaftmL0ZMpSTwsAse/Jr2SQBouzQL2lO0ESIym/fYXaEnaA/1JviLEtOeCzEPO2a8S5sSoDlca3Wqf6t+EyKbqPKQctJDEzbLbOAjWkxOEgAyQl0J+oXxIYC0K9om0WIqI2FIhHVE5MWOId1vm0SLqUBCxVV+0CYGYsdUIIHgWoB/ekNp23EUNSYXCVUW+WGVSS2b82uYXCS4coHF01aUvhvaJFFjKpDA+WnHkOvIsTFL0K0gInZMBRKyqKqE0XNE2HZCG0sc0WIqI0HlA33B5qXPwPLbykq4tt2Rn9tovwE/0WGyADlJAPAdE1a0ZzYxC8I5/Yvc2Af3VA6oK5YYbbdt7GW+a/nBRlSYNuC4KK2iZsBV5VOOUCIeoKolbX1J039lXLJT4Y2/1wqV6GNKu0r2lXNU2VXgUqnrR0awIfsxYUqrqKUkpMgr/gBOO2ZOK8K8SSg/AhDCFz5SEpzH0Q5RHGDQKwHZM4XyI3fBfNUmgeBri3v/bgjlR9EP6Uv+apOAjTEPfSNjniWUH8EI6WuTmO0tSLX9rcTrObB/0jwxtv8x601w9AVyhxLs2v2PiQAAAABJRU5ErkJggg==",
      "text/latex": [
       "$\\displaystyle \\left[ 0, \\  1, \\  0, \\  1\\right]$"
      ],
      "text/plain": [
       "[0, 1, 0, 1]"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# find free variables\n",
    "free_vars = set()\n",
    "for key in ans_set.keys():\n",
    "    free_vars |= ans_set[key].free_symbols\n",
    "# get the nonzero solution as a string\n",
    "if len(free_vars) == 0:\n",
    "    subs_dict = {}\n",
    "else:\n",
    "    subs_dict = {list(free_vars)[0]: 1}\n",
    "\n",
    "ans_seq = []\n",
    "for the_var in s_var:\n",
    "    if the_var in ans_set.keys():\n",
    "        ans_seq.append(ans_set[the_var].subs(subs_dict) % 2)\n",
    "    else:\n",
    "        ans_seq.append(1)\n",
    "\n",
    "ans_seq"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8c74e11-cd72-44d0-8325-6a7bd073f7f2",
   "metadata": {},
   "source": [
    "#### optimization 1: sparse matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2358f1f8-c2bb-41c6-8e08-7e8e38cb7396",
   "metadata": {},
   "source": [
    "try bigger $k$ with sparse matrix algorithms from `scipy` library"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "360f9994-420e-415c-9447-982c734ff26d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set secret string\n",
    "k = 7\n",
    "s = tuple([rng.integers(2) for _ in range(k)])\n",
    "if 1 not in s:\n",
    "    # try again\n",
    "    s = tuple([rng.integers(2) for _ in range(k)])\n",
    "    if 1 not in s:\n",
    "        print(\"we could not generate a secret string.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "b8efd579-1190-4abd-947a-bff9584c6e4a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 1, 0, 0, 0, 0, 1)"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "8ceb53ea-1534-4306-82d8-e1ce85795e6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sparse matrix for large k\n",
    "import scipy.sparse as spa\n",
    "\n",
    "\n",
    "def ind_from_seq(x):\n",
    "    \"\"\"Convert the binary sequence of length k to matrix index 0...2**k-1.\"\"\"\n",
    "    return sum(2**(len(x)-j-1) * x[j] for j in range(len(x)))\n",
    "\n",
    "\n",
    "def comp_basis_sp(x):\n",
    "    \"\"\"Return 2-d column vector representing the x-th basis.\"\"\"\n",
    "    mat_size = 2**len(x)\n",
    "    res = spa.dok_matrix((mat_size, 1))\n",
    "    res[ind_from_seq(x), 0] = 1\n",
    "    return res.tocsr()\n",
    "\n",
    "\n",
    "def U_sp(k, f):\n",
    "    \"\"\"Return U_f gate for Simon's algorithm.\"\"\"\n",
    "    mat_size = 2**(2*k)\n",
    "    res = spa.dok_matrix((mat_size, mat_size))\n",
    "    ind_list = it.product(range(2), repeat=2*k)\n",
    "    for in_x in ind_list:\n",
    "        out_x = in_x[0:k] + termwise_XOR(f(in_x[0:k]), in_x[k:2*k])\n",
    "        res[ind_from_seq(out_x), ind_from_seq(in_x)] = 1\n",
    "    return res.tocsr()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "7f84bdfe-881f-4b21-a362-8457e8519b4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "H_pow_ampl_sp = spa.kron(tens_pow_H(k), np.identity(2**k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "1eea58ab-b69c-4a71-b87f-2f39f0e4d6d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "simon_gate_sp = H_pow_ampl_sp @ U_sp(k, f_from_s) @ H_pow_ampl_sp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "d587ee95-b496-468d-9098-9c5478bfc142",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = simon_gate_sp.dot(comp_basis_sp([0] * (2 * k)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "88d4ab04-01e0-4295-8be8-936ee2b00dbf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sparse version of helper commands\n",
    "def proj(x):\n",
    "    \"\"\"Return projection for the computational basis.\"\"\"\n",
    "    basis_vec = comp_basis_sp(x)\n",
    "    return basis_vec @ basis_vec.T\n",
    "\n",
    "\n",
    "def meas_prob(x):\n",
    "    \"\"\"Return the probability of observing x in the first half of v.\"\"\"\n",
    "    return (v.T @ spa.kron(proj(x), np.identity(2**k)) @ v)[0, 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "022adc66-c94f-478b-ba05-be4745decd8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "intervals = {}\n",
    "t = 0.0\n",
    "for x in it.product(range(2), repeat=k):\n",
    "    prob_for_x = meas_prob(x)\n",
    "    intervals[x] = (t, t + prob_for_x)\n",
    "    t += prob_for_x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "67f905de-d7bb-44d0-897d-a641d8c96c7b",
   "metadata": {},
   "outputs": [],
   "source": [
    "x_samples = []\n",
    "for _ in range(k):  # when k is small, it's better to repeat a bit more\n",
    "    rand_num = rng.random()\n",
    "    for x in it.product(range(2), repeat=k):\n",
    "        if intervals[x][0] < rand_num and rand_num < intervals[x][1]:\n",
    "            x_samples.append(x)\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "58af8a76-5413-46fa-921b-346bb6f3f5af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[ \\left( 1, \\  0, \\  1, \\  1, \\  0, \\  0, \\  0\\right), \\  \\left( 1, \\  0, \\  0, \\  0, \\  1, \\  1, \\  0\\right), \\  \\left( 1, \\  1, \\  0, \\  1, \\  1, \\  0, \\  1\\right), \\  \\left( 1, \\  0, \\  0, \\  0, \\  1, \\  0, \\  0\\right), \\  \\left( 1, \\  1, \\  0, \\  1, \\  0, \\  0, \\  1\\right), \\  \\left( 1, \\  1, \\  1, \\  0, \\  0, \\  0, \\  1\\right), \\  \\left( 0, \\  0, \\  1, \\  0, \\  0, \\  0, \\  0\\right)\\right]$"
      ],
      "text/plain": [
       "[(1, 0, 1, 1, 0, 0, 0), (1, 0, 0, 0, 1, 1, 0), (1, 1, 0, 1, 1, 0, 1), (1, 0, 0 ↪\n",
       "\n",
       "↪ , 0, 1, 0, 0), (1, 1, 0, 1, 0, 0, 1), (1, 1, 1, 0, 0, 0, 1), (0, 0, 1, 0, 0, ↪\n",
       "\n",
       "↪  0, 0)]"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "2331ecbe-660f-4647-804c-6d692756ae47",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 1, 0, 0, 0, 0, 1) is a candidate for the secret\n"
     ]
    }
   ],
   "source": [
    "for s_cand in it.product(range(2), repeat=k):\n",
    "    if predicate(s_cand):\n",
    "        print(f\"{s_cand} is a candidate for the secret\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72635b98-e7bf-4c62-8ea9-a6bd06a56e4e",
   "metadata": {},
   "source": [
    "#### optimization 2: fast Walsh-Hadamard transform"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a094d9c-9276-45c9-afdc-073646616fbd",
   "metadata": {},
   "source": [
    "we avoid creating matrices and do in-place manipulation as much as possible"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "78fa068c-04f8-4d88-b632-679b8ff262b0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 0, 0, 1, 0, 0, 1, 0, 1, 1)"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# set secret string\n",
    "k = 10\n",
    "s = tuple([rng.integers(2) for _ in range(k)])\n",
    "if 1 not in s:\n",
    "    # try again\n",
    "    s = tuple([rng.integers(2) for _ in range(k)])\n",
    "    if 1 not in s:\n",
    "        print(\"we could not generate a secret string.\")\n",
    "\n",
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "13ebef43-d7ad-41ad-9085-b990c37f8214",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fwht(a):\n",
    "    \"\"\"Perform the in-place Fast Walsh–Hadamard Transform of array a.\"\"\"\n",
    "    h = 1\n",
    "    n = len(a)\n",
    "    while h < n:\n",
    "        # perform FWHT\n",
    "        for i in range(0, n, h * 2):\n",
    "            for j in range(i, i + h):\n",
    "                x = a[j]\n",
    "                y = a[j + h]\n",
    "                a[j] = x + y\n",
    "                a[j + h] = x - y\n",
    "        # normalize and increment h\n",
    "        a *= 1/np.sqrt(2)\n",
    "        h *= 2\n",
    "\n",
    "\n",
    "def H_pow_ampl_fwht(x, k):\n",
    "    \"\"\"Apply (H^{⊗k} ⊗ I_{2^k}) to x using FWHT.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    x : numpy.ndarray\n",
    "        One-dimensional array of length ``2**(2*k)`` representing a state\n",
    "        on $2k$ qubits.\n",
    "    k : int\n",
    "        Number of qubits on which H^{⊗k} acts (the first subsystem).\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    numpy.ndarray\n",
    "        One-dimensional array representing (H^{⊗k} ⊗ I_{2^k}) x.\n",
    "    \"\"\"\n",
    "    x = x.reshape(2**k, 2**k)  # shape (2^k, 2^k)\n",
    "\n",
    "    # Apply FWHT along axis 0\n",
    "    for col in range(2**k):\n",
    "        fwht(x[:, col])\n",
    "\n",
    "    return x.reshape(2**(2*k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "64c1c76c-65ba-43d0-8d34-4fadec922ed5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def apply_index_permutation(x, perm):\n",
    "    \"\"\"Apply a basis index permutation to a state vector.\n",
    "\n",
    "    The permutation ``perm`` is regarded as the action on computational\n",
    "    basis indices, and the function returns the permuted state\n",
    "    y = P x, where P|i⟩ = |perm[i]⟩.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    x : numpy.ndarray\n",
    "        One-dimensional array of length ``N``, representing a vector in an\n",
    "        ``N``-dimensional vector space.\n",
    "    perm : array_like of int\n",
    "        One-dimensional array-like of length ``N`` representing a permutation\n",
    "        of ``range(N)``.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    numpy.ndarray\n",
    "        One-dimensional array ``y`` of the same shape and dtype as ``x``,\n",
    "        satisfying ``y[perm[i]] = x[i]`` for all ``i``.\n",
    "    \"\"\"\n",
    "    perm = np.asarray(perm)\n",
    "    y = np.empty_like(x)\n",
    "    y[perm] = x  # y[perm[i]] = x[i]\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "a03f0651-9359-4d28-98db-6f1d993b735e",
   "metadata": {},
   "outputs": [],
   "source": [
    "perm_rep_Uf = [0] * 2**(2*k)\n",
    "ind_list = it.product(range(2), repeat=2*k)\n",
    "for in_x in ind_list:\n",
    "    out_x = in_x[0:k] + termwise_XOR(f_from_s(in_x[0:k]), in_x[k:2*k])\n",
    "    perm_rep_Uf[ind_from_seq(in_x)] = ind_from_seq(out_x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "d363d493-b4f3-4a0b-a6c1-34f6a07a8fcb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def comp_basis_big(x):\n",
    "    \"\"\"Return 2-d column vector representing the x-th basis.\"\"\"\n",
    "    res = np.array([0] * 2**len(x), dtype='float64')\n",
    "    res[ind_from_seq(x)] = 1\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "e0ef2eb7-48cb-4ce3-bf91-764a56830bea",
   "metadata": {},
   "outputs": [],
   "source": [
    "start_vec = comp_basis_big([0] * (2 * k))\n",
    "first_H_eff_vec = H_pow_ampl_fwht(start_vec, k)\n",
    "permed_vec = apply_index_permutation(first_H_eff_vec, perm_rep_Uf)\n",
    "second_H_eff_vec = H_pow_ampl_fwht(permed_vec, k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "4a16eacf-bcb5-4c59-849b-05520d922a8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# adaptation of helper commands\n",
    "def pair_first_half(v, w):\n",
    "    \"\"\"Contract a 2k-qubit state v with a k-qubit state w over the first k\n",
    "    qubits. (Components are assumed to be real.)\n",
    "\n",
    "    The input state ``v`` is interpreted as a bipartite state on\n",
    "    H_A ⊗ H_B, where each subsystem has k qubits. The function\n",
    "    contracts against a state ``w`` on H_A to produce a state on H_B.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    v : numpy.ndarray\n",
    "        One-dimensional array of length ``2**(2*k)`` representing a state\n",
    "        on $2k$ qubits.\n",
    "    w : numpy.ndarray\n",
    "        One-dimensional array of length ``2**k`` representing a state on\n",
    "        the first $k$ qubits.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    numpy.ndarray\n",
    "        One-dimensional array of length ``2**k`` representing the resulting\n",
    "        state on the last ``k`` qubits.\n",
    "    \"\"\"\n",
    "    # Reshape v as a bipartite state: (first k qubits, last k qubits)\n",
    "    v_reshaped = v.reshape(2**k, 2**k)\n",
    "\n",
    "    # Contract over the first subsystem: u = (<w| ⊗ I) |v>\n",
    "    # This is u = w.conj().T @ v_reshaped\n",
    "    return w.T @ v_reshaped\n",
    "\n",
    "\n",
    "def meas_prob(x, v):\n",
    "    \"\"\"Return the probability of observing x in the first half of v.\"\"\"\n",
    "    w = comp_basis_big(x)\n",
    "    u = pair_first_half(v, w)\n",
    "    return np.dot(u, u)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "fbeba937-ef55-41df-9ab4-0039211e50ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "intervals = {}\n",
    "t = 0.0\n",
    "for x in it.product(range(2), repeat=k):\n",
    "    prob_for_x = meas_prob(x, second_H_eff_vec)\n",
    "    intervals[x] = (t, t + prob_for_x)\n",
    "    t += prob_for_x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99a5db36-01f3-419e-94f9-f084b56e8fdd",
   "metadata": {},
   "source": [
    "perform the measurement to get strings $x^1, x^2, \\dots$, then solve the linear equations to get the secret string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "1be2ad4d-2d6d-44f1-9b3e-f423f4acbd9a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{s_1: -s_2 - s_5 - s_6}\n",
      "{s_1: -s_10 - s_3 - s_4 - s_5 - s_6 - s_8, s_2: s_10 + s_3 + s_4 + s_8}\n",
      "{s_1: -s_10 - s_6 + s_7, s_2: s_10 - s_5 - s_7, s_3: -s_4 - s_5 - s_7 - s_8}\n",
      "{s_1: -s_10 - s_6 + s_7, s_2: s_10 - s_5 - s_7, s_3: -s_10 - s_9, s_4: s_10 - s_5 - s_7 - s_8 + s_9}\n",
      "{s_1: -s_10 - s_6 + s_7, s_2: s_10 - s_5 - s_7, s_3: -s_10 - s_9, s_4: s_10 - s_5 - s_7 - s_8 + s_9}\n",
      "{s_1: -s_10 - s_6 + s_7, s_2: -s_7 - s_9, s_3: -s_10 - s_9, s_4: -s_7 - s_8, s_5: s_10 + s_9}\n",
      "{s_1: s_7 + s_8 + s_9, s_2: -s_7 - s_9, s_3: -s_10 - s_9, s_4: -s_7 - s_8, s_5: s_10 + s_9, s_6: -s_10 - s_8 - s_9}\n",
      "{s_1: -s_10 + s_7, s_2: -s_7 - s_9, s_3: -s_10 - s_9, s_4: s_10 - s_7 + s_9, s_5: s_10 + s_9, s_6: 0, s_8: -s_10 - s_9}\n",
      "{s_1: -3*s_10 - s_9, s_2: 2*s_10, s_3: -s_10 - s_9, s_4: 3*s_10 + 2*s_9, s_5: s_10 + s_9, s_6: 0, s_7: -2*s_10 - s_9, s_8: -s_10 - s_9}\n",
      "{s_1: -2*s_10, s_2: 2*s_10, s_3: 0, s_4: s_10, s_5: 0, s_6: 0, s_7: -s_10, s_8: 0, s_9: -s_10}\n",
      "got a unique solution after 10 trials\n"
     ]
    }
   ],
   "source": [
    "import sympy as sy\n",
    "\n",
    "f2 = sy.FF(2)\n",
    "\n",
    "# prepare variables s_1, ..., s_k\n",
    "s_var = [sy.Symbol(f\"s_{j+1}\") for j in range(k)]\n",
    "\n",
    "x_samples = []\n",
    "l_poly = []\n",
    "coeff_list = []\n",
    "for trial_cnt in range(2 * k):\n",
    "    rand_num = rng.random()\n",
    "    for x in it.product(range(2), repeat=k):\n",
    "        if intervals[x][0] < rand_num and rand_num < intervals[x][1]:\n",
    "            new_x = x\n",
    "            break\n",
    "    # ignore x^i = (0,..,0), otherwise set linear polynomial with\n",
    "    # coefficients x^i_j\n",
    "    if new_x == (0,) * k:\n",
    "        continue\n",
    "    else:\n",
    "        i_th_lin_poly = sy.Poly(sum(new_x[j] * s_var[j] for j in range(k)), domain=f2)\n",
    "        l_poly.append(i_th_lin_poly)\n",
    "        coeff_list.append(list(new_x))\n",
    "    # find solutions\n",
    "    ans_set = sy.solve(l_poly, s_var)\n",
    "    print(ans_set)\n",
    "    if len(ans_set) == k - 1:\n",
    "        print(f\"got a unique solution after {trial_cnt + 1} trials\")\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "8d82573a-6864-4e36-81b4-9d691b6ecafb",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAATEAAAAVCAYAAAAuL9n8AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEmElEQVR4Ae1c0VHcMBQ0GQpgSAfQAYQOSAe5dBDoIPmEvwzpgKSCTOgAUkGG6wA6CKGE7Bo/z+GzOFt+WmyP3oyQLdlv31uZPVn23dbZ2dnnoihOUWiL8/Pz5dNm/psZyAxkBsbHADTqmWZtQcQuEOY1Om7GF26OKDOQGcgMtDMAzSq1a7u9e3grAPbg5Uvl6R3qB+6j3XWmp8Kp8iiAR+Jof1H2US7Qds8Gb4PfA/j8hXKI7Udv/+ZPnJOMP8svtp4j/7Fc2HkqTojXFSuJiAGcAnaJ+v1K8rx4b9mG4jLrU+Gs5HCL7a/AvWIb6h1UlpOLkFU+f8AvRZ/iTy6TGfCS52TBK7EMs289Z/77cmHHKzmJwXpjgTrXFCxbZytdIzjOyjib4MzCy1Q4BeI/QdA7qEsBYwLYZj7cv+S+h9EnCtcmyd9PD58hH8CQ5ER8JVYo3y7tiHOW/HfJPXSMmJPe/KcSsWMQcofkOVNZNc7AKAReswsVDnNYoLTdCv9B+3FLrjxn7KbMSYk1dt4tvsyJMTGgTiViFKt7Knggtqa4BQ7b2KzCYSAUTN7iNc1uI9k/NVPmpMSayjhkThxGatvBx5oLiBc/YdqMC9UF+ttmNG3Hv9gmxOkiursvBjuyTnAny0mJNTKag+FkToLU9O5INRNbCwSDRgHjbaQ9sVw7xqMhEY4JVGhmydC7iIJHil4+lDkpsbz4Se0nc+LEsEzEEC8X9K8gMt+cYg+5UeE08d82G2awr8xJiTWVocmcdBip1tvJaqr7G+f3mV0E3/aHPz694xpZ6DazQ6ibD0mI07YWZgHZJyrfG5uSKXOSYXlfuwkHNHPiRG5IxHjbdOiBgYuKj/F3UdfvjHn4bfpIiQPffOxLyDZRtzZb4G+GNsp9ZU5qLBDucu2mHLjMiR+7SW8nMVAfEOo+6noGhu09Fr8UygcFChw+CW2L22Zi7J+aKXNSYk1lHDInDiOVTMQgVAeI7wh1cyGfglNPpdFvM5modFQ4CI5rbXyDvmn81F8iDs5eSxuak/nZVDvgKHNSYm2izqV/Yvy75LzJiQMnmyDW+pOIGBLhjIUXLV9s5deP6oK2U+yX//CoKWD/UPOrL70N50lwGBiwvqN6QE0RLg3bjP8jyqenlvK4QTmZn6q2hV2b7dXdFXY0d3QEH7KclFg1ScM3ZsP/cCpqD0k5qVGeNoJYq8cl+RULXLB3AKHAtBlnLYfWUR3L3d5fclbhrMRKgeJXnR5RuJB/hMLvUi5R1zYkJzrB+fwAoB2jEJP+uebGXxuh8JQ2FIdO4EOSkxqrJCjyDziZJf+RdJSniTnpyj//F6+TiFhfskAQZzc3qCkOyUyFwwRUWCocZU5qLOLF2lz5j+WD56k4AU4pYkluJyMI4NpZUgGrYlLhEE6FpcJR5qTGIl6szZX/WD54npKT4tVFDOLF25nk71ipcDiCKiwVjjInNRbxYm2u/MfywfOUnFicry5iCOQEiad+i5/5qnCUWHPMSckfsYbYXPmfCidlnLYmZk/cFhCUZ4vUQ7LJ52YGMgOZAW8GoFH2G/t8ar/4D3pbA4t00LYNAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left[ -2, \\  2, \\  0, \\  1, \\  0, \\  0, \\  -1, \\  0, \\  -1, \\  1\\right]$"
      ],
      "text/plain": [
       "[-2, 2, 0, 1, 0, 0, -1, 0, -1, 1]"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# find free variables\n",
    "free_vars = set()\n",
    "for key in ans_set.keys():\n",
    "    free_vars |= ans_set[key].free_symbols\n",
    "# get the nonzero solution as a string\n",
    "if len(free_vars) == 0:\n",
    "    free_vars = set(s_var).difference(ans_set.keys())\n",
    "\n",
    "subs_dict = {list(free_vars)[0]: 1}\n",
    "\n",
    "ans_seq = []\n",
    "for the_var in s_var:\n",
    "    if the_var in ans_set.keys():\n",
    "        ans_seq.append(ans_set[the_var].subs(subs_dict))\n",
    "    else:\n",
    "        ans_seq.append(1)\n",
    "\n",
    "ans_seq"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1b9cd69-cb0f-46bf-b58c-801ad59b8c19",
   "metadata": {},
   "source": [
    "`sympy.solve` does not handle polynomial over finite fields correctly, and we get bad guess when there are fractions with even numbers in the denominator.\n",
    "We try our own Gaussian elimination algorithm over the binary field GF(2).\n",
    "(If this happens, most likely we have not found enough conditions, and will get an incorrect guess anyway.\n",
    "The more sensible thing is to integrate this in the above search part.)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d4f82c6-64a2-4f13-9c68-af46f85f2d10",
   "metadata": {},
   "source": [
    "The Gaussian elimination goes as follows.\n",
    "* input: matrix A\n",
    "* output: the row echelon form B of A, and the list of pivot column indexes\n",
    "\n",
    "1. start with copying A as B, setting m = number of rows, n = number of columns\n",
    "2. set cur_row (this will be where we place the pivot) to 0\n",
    "3. start with col index from 0 to n - 1, and transform B according the following:\n",
    "    1. find a pivot row at or below the current row, in this column: start with r = cur_row to m - 1, set pivot = 0 if B[r][col] == 1\n",
    "    2. if there is no pivot in this column, skip to next column.\n",
    "    3. if we have found the pivot, swap the pivot row and the current row (if needed).\n",
    "    4. record the pivot column index\n",
    "    5. eliminate all 1's below the pivot in this column using XOR: start with r = cur_row + 1 to m - 1, and set B[r] to B[r] XOR B[cur_row] if B[r][col] == 1.\n",
    "    6. if we've used all rows, stop.\n",
    "    7. otherwise, increase cur_row by 1, and look for the next pivot.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "7c5f8791-6793-407b-ad70-e2b95781556e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def gauss_elim_f2(A):\n",
    "    \"\"\"\n",
    "    Perform Gaussian elimination over F2 (mod 2) using XOR.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "        A : list\n",
    "            2-D list representing a binary matrix of shape (m, n)\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "        B : list\n",
    "            Row echelon form of A over F2\n",
    "        pivots : list\n",
    "            List of pivot column indices\n",
    "    \"\"\"\n",
    "    B = A\n",
    "    m, n = len(B), len(B[0])\n",
    "    pivots = []\n",
    "    row = 0\n",
    "\n",
    "    for col in range(n):\n",
    "        pivot = None\n",
    "        for r in range(row, m):\n",
    "            if B[r][col] == 1:\n",
    "                pivot = r\n",
    "                break\n",
    "\n",
    "        if pivot is None:\n",
    "            continue\n",
    "\n",
    "        if pivot != row:\n",
    "            B_piv = B[pivot]\n",
    "            B[pivot] = B[row]\n",
    "            B[row] = B_piv\n",
    "\n",
    "        pivots.append(col)\n",
    "\n",
    "        for r in range(row + 1, m):\n",
    "            if B[r][col] == 1:\n",
    "                B_r = B[r]\n",
    "                B[r] = [B_r[j] ^ B[row][j] for j in range(n)]\n",
    "\n",
    "        row += 1\n",
    "        if row == m:\n",
    "            break\n",
    "\n",
    "    return B, pivots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "de5a4a7b-5e0d-4db3-bfa8-9f455d693a4e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\left[ \\left[ 1, \\  1, \\  0, \\  0, \\  1, \\  1, \\  0, \\  0, \\  0, \\  0\\right], \\  \\left[ 0, \\  1, \\  1, \\  1, \\  0, \\  0, \\  0, \\  1, \\  0, \\  1\\right], \\  \\left[ 0, \\  0, \\  1, \\  1, \\  1, \\  0, \\  1, \\  1, \\  0, \\  0\\right], \\  \\left[ 0, \\  0, \\  0, \\  1, \\  1, \\  0, \\  1, \\  1, \\  1, \\  1\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  1, \\  0, \\  0, \\  0, \\  1, \\  1\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  0, \\  1, \\  0, \\  1, \\  1, \\  1\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  1, \\  0, \\  1, \\  0\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  1, \\  1, \\  1\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  1, \\  1\\right], \\  \\left[ 0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0, \\  0\\right]\\right], \\  \\left[ 0, \\  1, \\  2, \\  3, \\  4, \\  5, \\  6, \\  7, \\  8\\right]\\right)$"
      ],
      "text/plain": [
       "([[1, 1, 0, 0, 1, 1, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 0, 1, 0, 1], [0, 0, 1, 1, ↪\n",
       "\n",
       "↪  1, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 1, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, ↪\n",
       "\n",
       "↪  1, 1], [0, 0, 0, 0, 0, 1, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 1, 0, 1, 0], [0,  ↪\n",
       "\n",
       "↪ 0, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0,  ↪\n",
       "\n",
       "↪ 0, 0, 0, 0, 0]], [0, 1, 2, 3, 4, 5, 6, 7, 8])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A, pivots = gauss_elim_f2(coeff_list)\n",
    "A, pivots"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16d840f6-d9f2-4b2e-9657-48d9ff9e5813",
   "metadata": {},
   "source": [
    "`pivot` gives the list of indexes for the dependent variables, while the missing one is free variable index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "6e070774-1659-43dc-b5d0-d5b8a0b9d252",
   "metadata": {},
   "outputs": [],
   "source": [
    "free_var_index_s = set(range(k)).difference(set(pivots))\n",
    "free_var_index_l = list(free_var_index_s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "9894630d-8f41-4e80-92b5-de0419ad34cc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "There are 1 free variables.\n",
      "[0, 0, 0, 1, 0, 0, 1, 0, 1, 1]\n"
     ]
    }
   ],
   "source": [
    "m = len(A)  # row count for A\n",
    "n = len(free_var_index_l)\n",
    "print(f\"There are {n} free variables.\")\n",
    "\n",
    "for val_cand in it.product(range(2), repeat=n):\n",
    "    if val_cand == (0,) * n:\n",
    "        continue\n",
    "    # initialize the free variables\n",
    "    x = [0] * k\n",
    "    for j in range(n):\n",
    "        x[free_var_index_l[j]] = val_cand[j]\n",
    "\n",
    "    for i in range(m - 1, -1, -1):\n",
    "        Ai = A[i]\n",
    "        if 1 not in Ai:\n",
    "            continue\n",
    "        first_nonzero_ent_ind = Ai.index(1)\n",
    "        Ai_rest = Ai.copy()\n",
    "        Ai_rest[first_nonzero_ent_ind] = 0\n",
    "        new_val = sum(x[j] for j in range(k) if Ai_rest[j] == 1) % 2\n",
    "        x[first_nonzero_ent_ind] = new_val\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5cea2f5-8aed-4ada-b3f2-47105281b3f0",
   "metadata": {},
   "source": [
    "How about the classical algorithm?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "e98f0b1f-e089-4938-b652-4c0cdfda7458",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAACQAAAAOCAYAAABHN77IAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACNUlEQVQ4EZ2V7U0DMQyGr4gBStkANigwAWUDWIFuQMW//kOwAawAG9ANgG5AmYCPDcrzhDjqhWuRsBS99hvHduLcpbdcLhtlOp3uAeNkNE0f1L6Gn2UuQfabZO4Q/GBM4OeZ+xPwvc5O7+A+wzwLuZ4FYViAZBQkdwp3zzhDfwDlLPIWPNFW0A1+wThBbxXvfC34vMBdgRHT3HKuX2zlBefgOYRFhETwyyBAk5ei5VnjaX0xLH6j4GuePpiK0Rndtdq32lGQx+2EI0l2DDNwhPLKXD+IjBZvIk9wk5wx2dXaJ/iRcbddjWLAHfUQuDitVHnm9RsyVwoP/4x1odV044buahI73R9wlAqqHUjowtQe9BIA3R12yVCS+a7dJ3/m/ipWv0GrIBYZ2GKOGAZ/ZmyUvMZWxZe3zn+QJ9adrtM/LYsIeYdpl+i27AUsX1n4VehlfsDvpuL/Y+7Gpf61mATefHdzj9553PDerwW4rpWrcT9WjUqP03tPBRHQi5ruQeUYLbONLcHfT3gAln9Sy6Ey8ItWdW0uuPIf8sdke2KiCtc28bOd+2A5GfQ9R9vzl+VX2uUTJzSLllm990BclcNsGCgJPp7kEVhfYovc1BbXe98ipnbIAcrc/PF0ePwNxOonbgIDjIMH3d0joxSIHuKPzXepAT3pT4ZJTFYE+xXDt8872oD6vjGO0eepoDzhPSktQDd563FlgcG6jhy6nTz7zsD6qbEA/3F2w8fVX4xvW/q6vwF+KOWE9iRiKQAAAABJRU5ErkJggg==",
      "text/latex": [
       "$\\displaystyle 32.0$"
      ],
      "text/plain": [
       "32.0"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# query count estimate\n",
    "np.sqrt(2**k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "3a8f67c2-32a7-4964-8085-8c091d6f9ca4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "found secret (0, 0, 0, 1, 0, 0, 1, 0, 1, 1) after 12 queries\n"
     ]
    }
   ],
   "source": [
    "res_rec = {}  # dictionary of f(x) as key and x as value\n",
    "for _ in range(2**k):\n",
    "    x = tuple(rng.integers(2) for _ in range(k))\n",
    "    if x in res_rec.values():\n",
    "        continue\n",
    "    f_x = f_from_s(x)\n",
    "    if f_x in res_rec.keys():\n",
    "        prev_x = res_rec[f_x]\n",
    "        found_secret = tuple(x[i] ^ prev_x[i] for i in range(k))\n",
    "        print(f\"found secret {found_secret} after {1 + len(res_rec)} queries\")\n",
    "        break\n",
    "    # if f(x) is not found, record the results and continue with next x\n",
    "    res_rec[f_x] = x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a25b1f6-0930-4215-9496-84e8e3c424ed",
   "metadata": {},
   "source": [
    "## Lecture 15"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "473578af-c7f0-477b-b8e5-a78e2b40ba48",
   "metadata": {},
   "source": [
    "### Extended Euclidean division algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13a3803f-6b25-4a39-bf49-e949c6acd740",
   "metadata": {},
   "source": [
    "find $x$ and $y$ satisfying\n",
    "$$ a x + b y = \\operatorname{gcd}(a, b) $$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f64fab9-9f2b-45ed-a2bb-17cec25fe1bc",
   "metadata": {},
   "source": [
    "construct three sequences $r_i$, $s_i$, and $t_i$ in the following way:\n",
    "- $i = 0$: $r_0 = a$, $s_0 = 1$, $t_0 = 0$;\n",
    "- $i = 1$: $r_1 = b$, $s_1 = 0$, $t_1 = 1$;\n",
    "- the $(i+1)$-th step:\n",
    "    + find $q_i$ such that $r_{i + 1} = r_{i - 1} - q_i r_i$ holds for $0 \\le r_{i + 1} < r_i$;\n",
    "    + if $r_{i + 1} = 0$, then terminate the algorithm with output $x = s_i$, $y = t_i$, and $\\gcd(a, b) = r_i$;\n",
    "    + otherwise set $s_{i + 1} = s_{i-1} - q_i s_i$ and $t_{i + 1} = t_{i -1} - q_i t_i$ and proceed to the next step.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f75f3c16-284e-4ae6-ba01-02f06182a31f",
   "metadata": {},
   "source": [
    "The algorithm is set up to keep the condition\n",
    "$$ a s_i + b t_i = r_i \\quad (i = 0, 1, \\ldots) $$\n",
    "while making $r_i$ smaller at each step.\n",
    "At each step, $r_{i+1}$ is the remainder of $r_{i-1}$ divided by $r_i$, and $q_i$ is the quotient\n",
    "We get the correct answer because $\\gcd(a, b)$ is the smallest positive integer solution $k$ for $a x + b y = k$ with (possively negative) integers $x$ and $y$.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "05e8b864-74b7-42f4-9bbd-a9e76f9a92eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ext_Euclid_div(a, b, report=False):\n",
    "    \"\"\"Returns (gcd(a,b), x, y) such that a * x + b * y = gcd(a, b).\"\"\"\n",
    "    # i = 0 and i = 1\n",
    "    r = [a, b]\n",
    "    s = [1, 0]\n",
    "    t = [0, 1]\n",
    "    for i in range(2, max(a, b)**2):\n",
    "        q_i, rem = divmod(r[-2], r[-1])\n",
    "        if rem == 0:\n",
    "            if report:\n",
    "                print(f\"found {r[-1]} = gcd({a}, {b}) after {i} steps\")\n",
    "            return (r[-1], s[-1], t[-1])\n",
    "        # add next terms, then continue\n",
    "        r.append(rem)\n",
    "        s.append(s[-2] - q_i * s[-1])\n",
    "        t.append(t[-2] - q_i * t[-1])\n",
    "        if report:\n",
    "            print(f\"we now have r: {r[-1]}, s: {s[-1]}, t: {t[-1]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "b0797ff5-4fc2-4dd5-a3cd-591697e247d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "we now have r: 16762, s: 1, t: -1\n",
      "we now have r: 7378, s: -1, t: 2\n",
      "we now have r: 2006, s: 3, t: -5\n",
      "we now have r: 1360, s: -10, t: 17\n",
      "we now have r: 646, s: 13, t: -22\n",
      "we now have r: 68, s: -36, t: 61\n",
      "we now have r: 34, s: 337, t: -571\n",
      "found 34 = gcd(40902, 24140) after 9 steps\n"
     ]
    }
   ],
   "source": [
    "a, b = 40902, 24140  # from Knuth's book\n",
    "gcd, x, y = ext_Euclid_div(a, b, report=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "9c8cd499-0a58-4bc1-b500-6b103b10ff2d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(34, True)"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a * x + b * y, gcd == a * x + b * y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55958580-f726-422f-ab21-da280dd647d1",
   "metadata": {},
   "source": [
    "### RSA cryptsystem"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3a835b7-08e9-4885-b699-a421feb3997b",
   "metadata": {},
   "source": [
    "Preparation: first Alice chooses (big) prime numbers $p$ and $q$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "088107ea-c4f9-4cb5-9161-1517474627b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# helper function to compute exponentioal modulo k for big exponent\n",
    "from functools import reduce\n",
    "\n",
    "\n",
    "def pow_mod(base, expo, k):\n",
    "    \"\"\"Returns base**expo mod k, allowing numpy integer inputs.\"\"\"\n",
    "    if expo < 0:\n",
    "        return None\n",
    "    return reduce(lambda s, t: (s * t) % k, [base] * expo)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cd04338-d40c-457a-a4f4-a21b5efb9926",
   "metadata": {},
   "source": [
    "We take lange integers at random and check if it is prime or not by [the Miller-Rabin primality test](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test). The code is taken from [Rosetta Code](https://rosettacode.org/wiki/Miller-Rabin_primality_test#Python:_Probably_correct_answers) and lightly modified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "ccf8d5e2-1d0f-44e8-ab15-a9fd4707d39b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "rng = np.random.default_rng()\n",
    "\n",
    "\n",
    "def is_prime(n: np.int64):\n",
    "    \"\"\"\n",
    "    Miller-Rabin primality test.\n",
    "\n",
    "    A return value of False means n is certainly not prime. A return value of\n",
    "    True means n is very likely a prime.\n",
    "    \"\"\"\n",
    "    # special cases for small n\n",
    "    if n in [2, 3, 5, 7]:\n",
    "        return True\n",
    "    elif n < 10:\n",
    "        return False\n",
    "\n",
    "    s = 0\n",
    "    d = n-1\n",
    "    while d % 2 == 0:\n",
    "        d >>= 1\n",
    "        s += 1\n",
    "    assert (2**s * d == n-1)\n",
    "\n",
    "    def trial_composite(a):\n",
    "        if pow_mod(a, d, n) == 1:\n",
    "            return False\n",
    "        for i in range(s):\n",
    "            if pow_mod(a, 2**i * d, n) == n-1:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "    for i in range(8):  # number of trials\n",
    "        a = rng.integers(2, n)\n",
    "        if trial_composite(a):\n",
    "            return False\n",
    "\n",
    "    return True\n",
    "\n",
    "\n",
    "def getLargePrime(keysize=1024, report=False):\n",
    "    \"\"\"Generate a random prime number with specified keysize\"\"\"\n",
    "    for try_count in range(keysize ** 2):\n",
    "        num = rng.integers(2**(keysize-1), 2**(keysize))\n",
    "        if is_prime(num):\n",
    "            if report:\n",
    "                print(f\"found a prime number {num} after {try_count} trials.\")\n",
    "            return num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "9bfbdee7-67d4-46e0-b3a2-1d850cc47181",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "found a prime number 691 after 4 trials.\n",
      "found a prime number 859 after 0 trials.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(691, 859)"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p = getLargePrime(10, report=True)\n",
    "q = getLargePrime(10, report=True)\n",
    "p, q"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d36d0ce4-0fb2-4f62-a869-eb705e50eba6",
   "metadata": {},
   "source": [
    "she chooses another integer $e$ that is coprime to the least common multiple $\\operatorname{lcm}(p-1,q-1)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "671e354a-655b-46b6-804a-02100f8b599a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFoAAAAVCAYAAADGpvm7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFBElEQVRYCe2Z71GTQRDGQ8YColZg6AChA+hAsAKgAxk+wTcGOkAqEOhArEChA7ACkQ7w+S2357733huTmIDDuDOXu9vd29t7du9Pkt79/X0vlr29vWHs/2838RkHjxqGL3qB9vf3P6h7k0qQPG5Tfgw146rKqdp3jzt792wT+DWU7juVI7e2QIQgBKpWVO8YI3yIdxy6r9TeFK8BgPoD8XeDHv0z8S8CLzfFP8ydh8Yn8a5oqsaXswd29fNOOi+jRH2390P8RZVD8UiamdEkfkmXpMXPjzhgGa2OgaT6bfQq8S/FO1bboqN6Sf3v6KrEhbCw7WI8QA9Uzp2vNtkKiDtqWxBU06cAELSigizahw+R6Y1k0Hh8PFBt86hmPZeq11RqNiSeisb2S/MeqeCD7Uo/OsiGmLXuxYkarxjkDLWvVL4l/TX46m+pYrElbYrxRSUDrTaAkr0x0wGmAYjkZlv8TOIRpJ7qbE9t5i6DSSahw5padsSbmmS3ZU+8ll9pAuYH2+1+YmxI2VI89b1iCzcASAK2+KrGABBEJrYcMEn4kD722BGNucQn8+L4r2FYbLZ2jYTrKnbkREW1sRF9LMRTdSfxq6c1sU6wHfT1UQUTYXLltuIS5yC0/FDZojj8P4dxiMqdwtFCtt2lcdVK8pyxriAetg68H2qOkpqPniDIZ0IT+uVz4scGRweZFLexKQCGCm0uv5JeJ0beMskJgvZTbc5QshzgI2gE5kY8svq9CgFDr/PSlKwnfeZZUl2ezZ4MqHVRzf8u3Yn4XX4VRsB2ra8PFn9dCL0LSAamM1INUFBeqCZlC/uRQPaRSeWWdv1lQFPhwiDLAZogdRH2KCU5iKN2iM9Zjp1Fv8uvaBtshwCNI7Wth/ImHwIhbz+1AdkX5tsTHYCCT4YSRQJ0nfjIfcFkpgdEKkan+jwJOomds5mztrXrstLohu++0VoTSuUP6xvHL7AdcnSQFQ6cmr9Jxjg+3ojDJQTAOM2FQAFYA1oybn6ee/6843JDfqYCgBGkHBzJnHixYGNZJeoix2ZtDLKuBEHm2e73CbxZ0ii/4jz4PgDokSSQCIIDaLri+TZ2AOgTkEzSOVchu9k6RJ4+8mpQEYjIkpJyQEuB7Pk94rslqjjPfYyyWbQ7/SqMWyL3xSQr3KlCp7NLdl+khTJ2QLvUFo9Fcs57dpGto+ZqgKLx6AJ+y7Z4TtisBSjO6bozqcf0y+diDbcAzeJqjvZkkCcbr4gMTmpzZtsLQH1AILOqNiRjrB8HPOBrenwjxYbrqWvEUQKNOiI4nlzPlNMHNvlyhX9Gaud1OG/K2ucb5ZebJuA3AH2lwlfLGgFKaYyFbctpxjnx4rCv286glg7nLk88y1TVZDc7wY+entosfkPFLl7VkRyYDFYU0tZ4LtZb1Wxlo5rNxCNpuA/+lv7oV5jAAr6gn/Q4BgCJ87RF4jsobrz65pUednZVYmC6dLHp9og4v1PEwIllIBJogOFHrPgeR5xJMmxh806Fy4/EadmUnj9jubjRnYo0diy/MJ7m3LZf71JnXXVrsVN58g8P0hrJfLtf5u2m5iIg7OjFfpqMbGi8LObtxBPa56fgqbN5Qr+5x+xEMKA1MeccP1YTgWdLWh9HzLze1Q3cEpZgal/OPKNR4kLjVfCcaUsLzz/5znmhYJlPifwPC5OmKPCkeyxn5rzWpzEv/Ph3hS9o+XvBL+gLGInJtXa3AAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left( 98670, \\  7\\right)$"
      ],
      "text/plain": [
       "(98670, 7)"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gcd, _, _ = ext_Euclid_div(p-1, q-1)\n",
    "c = int((p - 1) * (q - 1) / gcd)  # lcm\n",
    "e_cands = [3, 5, 7, 11, 13, 17, 19]\n",
    "for e_cand in e_cands:\n",
    "    gcd_e_c, _, _ = ext_Euclid_div(e_cand, c)\n",
    "    if gcd_e_c == 1:\n",
    "        e = e_cand\n",
    "        break\n",
    "    e = None\n",
    "c, e"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce84955d-f946-4d3f-a682-d00a421226b3",
   "metadata": {},
   "source": [
    "she finds $d$ satisfying $e d \\equiv 1 \\bmod \\operatorname{lcm}(p-1,q-1)$ (this is the *private key*)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "c7b9d36f-a6d0-4297-b922-2c986396307d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFoAAAAVCAYAAADGpvm7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEu0lEQVRYCe2Z4VEVMRDHT8cCHtoBdoBSgdgBYAVABzp+gm+OdABUoNABUIFKB9KBSAf4+4XbmLsLcsq8Y4ZxZ/ay2Ww2yT+bvbx7zdXVVVPy9vb2Yln/L3fxGYNHDcPHTUE7OztvqS4VqgZdp24buhm8WNr9lzsILIKPWGZ65A5JNKxSLFO+S4r2Qf0n4gw+a1XK0gvaLq/F3090H3/XkvQJXfRtkN2grdZGX9Y/oj9pdamgbtv7Qmf9sG9nO7pRPgtfdxYZ0wA8hG/CQaAvsdt3sAQ0FRdxSvlCZUnovlN/CmtzDh/BH9BfUmai7mId+B1yAo3S+hLlcw0p9SGoAbQ6N1i7NWR9J0Leg7OdSurauXGl3WifyfEdHozrWAfwBfwSFuwF9B0s0CVC/w3hle1PWp1RuNfK/eIMw7W+slIPEMrIdGJuTtAmwib+juEAK+yN3qSjTTsn2acNFKdw9LV9lE8N70rMS0ATFsiDNFvxL6Ziu/W4bVynYwrxivGtKvoale5uxwf613LhwBTiZHME0J7lws4TUPYrmgbiWJ+DjvNWsDbxENvZEx6CVEbdv4zvETcf1UDL/mg3eheyAqEdX1V5or5Qf0vbMaUpJfwOTh5tY306xn2Q2K6bOoycOL7VibAYj+cMfgabi83R+QVH3Xx1js6ofgP/gI3K6ssLfSLsVxDS0ULOpwH5SKbNIPiJ7Ataf2XKoTokbKs+h5aTacT2tUALUhlN/RkI8GcWkKKKUqC/U5oWYoO0kV6iy7cWZEHagMuc2lB3QwRkGXbDvsIdwsZIdl5uspthZFhWaYzPasf5K71MrJijBenipvFYgIAmkLVBdsECnDaHeoDs7SJHpbbQZ/igsElK6r5gd2FfLJ/gb8hGb6a27rhGsuPFBnfsogP2t/oM24lLsV0U6KdwBnLkJATbS7mLD1LXJ28OboSnpkr4MNod3zSjbUNpFLvBXhVNSaa3uPkMNs4+JWE/8Fm2TyyLy0ygbyQmbE6sXbOij78QY5OijLayTBuCrVFv2uhTpA7TiWSKyClIBf0Ez+h2M8JO/VifdLsXSoEs0IZ2iqTKNIzEWpudXaT5VfJo1+xSI4+IdjfNNHGjbdtWbmD4cDz9CHgav2241Wd2cD+Ca70QaCefIq4yj30WZxT1yYiKF6Ft5uuaD39peu0L20vq3igsS4rUctK22afmzz5OPPxZv9WnRhI+7Ts1GRTnAm1U+vavkT+DOzcS6vGxJHKmCzDKBCnfCpBd1Dq8UTg2HXg3zoSdLzdtt5AFTdJ3ztlJw4N2c7fpLE6ITaN80scxvAX9KRXqbyx51ZXK03Wt6T4NtrNHfNJbQnBRtcht0BtZkS91aqrxJRWgUL0mdALtgiRt+/dt/Xka8iYh67/2Ucl5vYcdL6h6L/8Ln161pOqHoOumPz8Zy08NkutwrQaqG28A9G9dDTrH3IqPSla8t9rpQRNr9ARFiprrWhnLIHIDnps6JCOx86UsaR/mY5mFD07jnJZqJkjpNAHNwIZ8/148p7Hvzy3r9Kj/mGIGjGU0i2lKJxHRjm3e7Lz4VD4w2mThuxOtSSxzlsj/sDh4uwurE05mojVPOwz4eTPzGptvR78AFiUfyaj4XkkAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle \\left( 56383, \\  1\\right)$"
      ],
      "text/plain": [
       "(56383, 1)"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "_, d, _ = ext_Euclid_div(e, c)\n",
    "if d < 0:\n",
    "    d = d % c\n",
    "d, (e * d) % c"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3def09a-130f-448f-887a-1dfb56e56b86",
   "metadata": {},
   "source": [
    "she advertises $N = p q$ and $e$ as the *public key*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "bed0aeda-fdcd-4e78-b129-f67edea40c4a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Public key: N=593569, e=7\n"
     ]
    }
   ],
   "source": [
    "N = p * q\n",
    "print(f\"Public key: N={N}, e={e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d92db874-16ae-4809-8393-e68e59969bee",
   "metadata": {},
   "source": [
    "Now, suppose that Bob wants to send a message represented by an integer $x$ to Alice.\n",
    "He first checks that $x$ does not share prime factors with $N$ (if it does have one of them as a prime factor, he asks for a new public key)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "bba29203-ed79-4ce1-ad56-3b1d03e67145",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 42"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "506700ba-e790-4778-ba0c-57c93369a839",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gcd, _, _ = ext_Euclid_div(x, N)\n",
    "gcd == 1  # should be true"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6266eae-8390-434a-8093-65dc222695af",
   "metadata": {},
   "source": [
    "he computes $y = x^e$, and sends it to Alice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "83cf5e51-1654-4e39-9a43-dfdfd81157ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "101493"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = pow_mod(x, e, N)\n",
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef091e0e-3096-4db7-8cd5-7233e62545dd",
   "metadata": {},
   "source": [
    "Alice recoves $x$ as $x \\equiv y^d \\bmod N$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "be25c6dd-918f-42f5-9fcd-c1532fc48492",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "42"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pow_mod(y, d, N)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0b1a532-1142-4653-8cb7-e74ac6101187",
   "metadata": {},
   "source": [
    "## Lecture 16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "8eed13ad-2151-4076-adb6-e62979d26a71",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "rng = np.random.default_rng()\n",
    "import itertools as it\n",
    "from functools import reduce"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "226f92c7-ab82-4fd8-823b-802b9f1776f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 15\n",
    "k = 4\n",
    "Q = 2**k\n",
    "# this should be bigger than N^2 to allow s not dividing Q\n",
    "# for N=15, we know s=2 (z=4,11,14) or s=4 (z=2,7,8,13) will divide Q,\n",
    "# so Q > N is enough"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "d5f4b356-966a-41c7-8eca-a46e809b8c33",
   "metadata": {},
   "outputs": [],
   "source": [
    "zeroket = np.array([1, 0])\n",
    "oneket = np.array([0, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "7a5d5e32-983f-4164-9750-25cc74eb03f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def bin_seq_for_int(x: int):\n",
    "    \"\"\"Returns binary sequence representation of the integer x.\n",
    "\n",
    "    Parameters\n",
    "    ==========\n",
    "        x: int\n",
    "\n",
    "    Returns\n",
    "    =======\n",
    "        tuple of int\n",
    "          (x0, x1, ..., x(k-1)) with xi = 0, 1 and\n",
    "          x = x0 + 2 * x1 + ... + 2**(k-1) * x(k-1)\n",
    "    \"\"\"\n",
    "    # for i=0,..., k-1, do bit shift by i and bitwise AND with 1\n",
    "    return tuple((x >> i) & 1 for i in range(k))\n",
    "\n",
    "\n",
    "def int_from_bin_seq(x_seq):\n",
    "    \"\"\"Returns integer for the binary sequence of length k.\"\"\"\n",
    "    return sum(2**n * x_seq[n] for n in range(k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "ae4bdc99-39a3-4d92-bcfa-031fbcb07069",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPQAAAAVCAYAAABxN8PZAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFM0lEQVR4Ae1c0XETMRB1UkGADkwHCakA0oGTDkg6gM/kjwkdABUwSQdABQzpIHSQ4A7Cexqt5yzrpLWk25zH1oyiO+1q3+4+SXdn+zJ5enqadOvl5eW0ex4e5+Sh/u58Ob8l+RhDzsfgQ0nuNnWMJt8xnf1Jp1xdXX3A6WGna+kwJ19S3p20zMDU576lTbWtHe/qVLVU1HC+orPHHYwFpM3QHKP96DqCPwo5N4Ib1CPozoPhzU5h+9obe0D7GvUafX+bAXhDVjiE02BBh5vtHO1X76JJA7zcvLDi3QpnNPNLw3mo4xY0Og8wO36hPYrNkj657/+GMY+ob1CZ9BfoH2RBw+4f2P+E9hbtBC39Zt8JjpstatgywfExqLG8X2/RDpJf+tMtwInOC98/OO9WOBIz8NRcyJiSdh0cr5vkvKsjt9zclb4knIvKYYhXjFPUC4z9nhhfLQLGOYwcoHWLmQZxzInN85TvVFUXKxw6VIDFOOUKoo6pQvFZeSe/qNs+vzScL3RkQZ8hcalbuZy8Ys6oh55C8y6i/Rt97+A/ryYtihUOfV0Ly3NELlrFmsvXGHjP+dhKvhYXFaBr4Wg47+rs44TPSL23qzl5RWDrDn2HAby1D4v4TnmLYoVDX0uwGO9Zi0BTNkbEe8rNlrISLkrwS3A0nDsdXqFPUH8mPMvJE0PbiDC5NFekl7VoVjj0swKLXJGTocuz8z50gGK/ggsxoWorcDScOx0uaH6YdZ/wKCdPDG0mksXKZ+a+oln0fWOl3wqHeKVY5GoqDg/YjoH3AcNbMl3KxZIRxUkpjoZzp8MFzYUQu5UV/3Jy0Xvu9pWRA1Y4DCeGRa4sFvSm8G5Ee5SLIbBLOXfzgguau8Y84VlOnhjaTJTacGTXe2iAZoVDV0ux+KzExTZ0GQPvQ8co9ku5kPHathRHw7nT4YIefcGzh2w4sYksfQyoqljh0MkKrG1aaFV8agdXcKGFcHoVOBrOnQ4XNHcNWRQxB3Py2Jgh+vjQH7vVZCAslLcoVjj0tQSLXKV2+hY5oI2x8N4qnpydEi5yNmPyEhwN506HC5pXtthCEWdyctFLttidUptGcqwX8mel/KAmLEfouOvsfpNKLCscxqHG6gTNDSx7N1KZA8KNhfdO6P2HDeJVc1GJpcbpRKvh3OlwQd+hHncGh4c5uejLw7xcMaV/4hPwDy1/WldUMJY/fHlEOxMD3i6/k30f9BVjWeHQXy2WxOZbt4EFfUunPi/FOfDGRsF7J7Ctml+duHmY5Vx09vAK1iFObjAJ+KLDSkF/Ts4dh4VfmPMqzInA3f2Hn7A4dJNXvhorfnnDT1T+HHGOyg/BuBHxt93EXBScV2FZ4dBhLZYE52O7QMtbt97i9SgvyjfGj4J3+LG180vI9VwmORcd9y40FvU9F3bfu6M5ed+4sB92ZqgHYf8Q51ZYVjjMEbCmqPfafNX6RizU3nlh5cfYcDwXJnMZ+c9y3tXhLTcLr3p8waKv5OR948J+vp7Jq6tFscKywmHO+GorudCWWt82jffaeLV5pZ4VlobzhY5b0FhkfD7ly9LRD8dyck0WYIO34y2+K87CWWFZ4TBgYJEbcpR6iWaRmxa+eazeebEASxy08CNhfiGywiGgFRZwspyHOm5B+6zwLZDUa4g5uTfT25wD/HOvtK3ACssKh9khN6m7qDCDrXzbFN5bxRvmMXZuhaXhfEln8R9L6LVf7bO+hZeTxyLf9dVnAHnnfyu5RZv9uqoebdXCjvfVnAzdo+E8pvMfXOd0GQxjhgMAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle \\left( \\left( 1, \\  0, \\  0, \\  0\\right), \\  \\left( 1, \\  1, \\  0, \\  0\\right)\\right)$"
      ],
      "text/plain": [
       "((1, 0, 0, 0), (1, 1, 0, 0))"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bin_seq_for_int(1), bin_seq_for_int(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e319815-760c-4366-8459-e1f3122b2f30",
   "metadata": {},
   "source": [
    "### Fourier transform"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "id": "52b8c399-3f38-4eb3-8aaf-fe09e4d3bc93",
   "metadata": {},
   "outputs": [],
   "source": [
    "def Fourier(n, j, l):\n",
    "    \"\"\"Returns the coefficient of Fourier transform matrix of size n.\"\"\"\n",
    "    return np.exp(2 * 1j * np.pi * j * l / n) / np.sqrt(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f1d9d3b-03d0-4a58-ad0d-34bfb3443e24",
   "metadata": {},
   "source": [
    "Me need to take care of different conventions for indexing:\n",
    "On one hand, we say bit strings $x_0 x_1 \\cdots x_{k-1}$ represents the integer\n",
    "$$ x = x_0 + 2 x_1 + \\cdots 2^{k-1} x_{k-1}. $$\n",
    "On the other, the Kronecker product convention says that this string corresponds to the $j$-th row / column of the matrix, where\n",
    "$$ j = 2^{k-1} x_0 + 2^{k-2} x_1 + \\cdots + x_{k-1}. $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "id": "7a202794-c59c-47f1-8867-3a050825ed1e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPQAAAAVCAYAAABxN8PZAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFaElEQVR4Ae2c8XXURhDGDRU4oQPTAYYKAh0YOgA6SP60/8sjHYRUkAcdABXwcAdOBxB34Hw/ZfdOp9PujnZXg/24fU9eaWd2vpn5NCvp7uSjm5ubo/F2fn5+Mj6e7pfkU/3D8W5+a/JxG3J+G3yoyd1dnWPJ95zO/aNRu7i4+FWHj0ZDO7sl+Y7y4aBnBk5C7nvaNNs68G5OVU9FC+d7OvdYwWgi7UzdE/W/DQOTPwY5C8E7bafSvZ5M73Yo22+Csa/qH2p7o7F/ugEEQ144wFmwpMNie63+bXDRpRNe8ryw+N3DSS8cfHXGytaMfClyPtUZClqDx4rlk/rTOQJS8jD+l+Z80/ZYGw7+pPFVClp2v8j+7+rfqz9Sj9+MPdN+t6KWLRecEIMZK/j1i/pV8os/4yac5HnhlSMvHOL2wBIGOTXXTPApy/lYJ95yc9X7k6ASbVYuQ1wxnmt7rXl/J+Z2GRbGKxk6Vj8UM0a1z4nNcc53VM3NCweHKrCIM96hmGNqUEzxfuCiMqmcs9qW1IyF841OLOgXAsndypXkleEtmvZc2pczMz5r7Kn8Z+Xr0bxw8HURVuAILnrFWspXivdFfpdAMnIvHFzwxMqEvCuycD7Wua8DnpGSt6sl+S78qkdPZZ1b+2mLviPv0bxw8LUGi3hf9Ag0Z6PAe43fObiUzAsHfE+sVLypcQvngw5X6GfaPqYsGeSZqX1EOrksV6SfW9G8cPCzAQuu4GztNnteNPi9yF8vHJzyxFqUhK2yhfNBh4Lmw6yr7dy9vZJ8b8IKA7FYeWZONUvRp+bGcS8c8Gqx4OokOrxin+K91u+lrnrh4Jcn1tI8oG/hfNChoCmEuVtZDNFK8v+1vv/fB04ueOEQzhwWXHkUdAvvc36vQY8XToqLNWKas2nhfNChoFmdrueshLGSPDO1myi34MTV9WsHNC8cXK3F4lmJYlu7pXiv9Xupv144+OWJtTQP6Fs4H3Qo6Fvf9IwTF5y5EzmOEVBT88LByQasVKE1xW6d3OC3FWLQ88IBzBNrURK2yhbOBx0KmtUpFsXWxHavJN9qrrvHQ//crSaB0JD3aF44+FqDBVe5K0qPHGAjx3uN3zV+eeHgmyfW0lxYOB90KGiubHOFEkFL8qiX7bUK5haN7Nwg5GelfFAzbacauBytsqy4LVheOMRhxhoFzQJWvBtpzAFwOd7Nfjf64YVDvJ5Y4C1pFs4HHQr6UtuTjPWSPE6NH1DEK2YcjwX2r8jlZ45VTXP54cs39WfRgPYpXL6TfTkZq8bywsFfK1aMLfTDAjYZ2zkMeanOQTCW5N3qd6sfXjjE64k1IitZMyMddoucR517egXrkQ7eKSBedNhrGi/JWdlofDFPgXEisLp/CEnS7pCw+NVY9csbsod9fo54rY0PwViI+G03mJum4yYsLxwctmLF4EJsr9Vzi5hsQQ95Vb41v8T7D8tFh9yaaiaSG/CynEed4V1oFfUVhZ16d7QkT82bjsvOmbbj6fgax15YXjjkSFgn2q6s+Wr1DSxtyfPCy4/bhhO4cDmXlf8i52MdbrlpXPV4wSLVSvLUvOk4r2dydfVoXlheOOSMV1vhwtpafbtrvLfGa80rel5YFs43OkNBq8h4PuVl6dkPx0pySxZkg1u0Ht8VF+G8sLxwCFhYcANHuZdoNrnp4VvASp4XG7DMTg8/MuY3Ii8cAL2whFPkfKozFHTICm+b5F5DLMmDmWT3SuB/JKV9BV5YXjhkB25yd1HTDPby7a7w3iveaR7njr2wLJzv6Gz+Ywleh2o/SxVeST4X+WGsPQPKO/+54r364tdV7Wj7Fg687+dk7REL53M6/wG9MZVRgZObhwAAAABJRU5ErkJggg==",
      "text/latex": [
       "$\\displaystyle \\left( \\left( 1, \\  0, \\  0, \\  0\\right), \\  \\left( 0, \\  0, \\  0, \\  1\\right)\\right)$"
      ],
      "text/plain": [
       "((1, 0, 0, 0), (0, 0, 0, 1))"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bin_seq_for_int(1), bin_seq_for_int(1)[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "34eeef78-11e5-4ae9-8ffb-18767113dfeb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADsAAAAVCAYAAAD4g5b1AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADJklEQVRYCdWX7XETMRCGHQ8FmNCB0wEhFRB34KQDkg7M8Mv+Cx0kqSCTdECogMEd2B0Q3IF5HnE6dHdysMdfeGdkSavV3r67q5Xcms/nrbQNh8NuOj/UcQ5Hu5XQaDQaMH2bsA552C3wlBiOjJzEQp/ujP5jYBQ/zDsMPyU85w/wnxLeRofo1uEPtFPGs7pyeF140c53jJ+dwx+nsswN3oz+Vn4Ay0QA3+hPZaYE74Z2XeNpyD38x5S/zhhd2nBH03ABCPg1/ApY5gLVph59IMafGQisx7gSBOY/4L+nn8U0VviGViEErmAoXKcPMNJo19dXnmsM7YKmY+9fUKCtdecbZZ1iEOokLve0IthLPhJCXZM8YV56sLa2r+k5H55gr5mQkhHtwDfyJRW4xNdp8+NZnZar1cF3pn1kviqcLGUzIVnf5lBQU+yppHfywdTOyBbf5St+jFwlz6MECh9tzHXIL8ami9EW/MbOK/qWJr57sUA43CKsV4pUISu+nmlsMZgUzEZXKI8pbkRNo5zCxt5dMbBRoKZvrND1T4uvK1jDbgXMEoqMqiljRPWQSj0z8v8XsjCZhV8WGCS+APaYQTb/2Ww1tpx7h3lOTPmYRnfMc+cDkd0RNlhttS3alfu4Z7ZjZF8i07aSGij1rBplgZrSeyNsMRjH9P+6MUJABWuIGxFCgTxL+Yy+QvD0lKBVshfCBo/RCX0ZUcY+ET1mdRLLs2A1vCHAJkF60TfW4EsqKKs4cs53QnzLgtR42sLTAbn6Y1CmXj1j2hktR3rNd3B4bkUB5qaP14+OatEL1KtpTGs8OZVZkd4U8iH90r3o1/kWpCfG9VffObxckdKm8RF/hfSSgDyHDYLvuk/D1GONPwLIxesr+3hvKM4w0BGfe9YCHWggdKiODddf8Z1F2ZZ1drHnOvyXBfBE0Ov+d0VHn9ZZV88m92NPlzZRZxuvSVbdyuM6cFf/8RzNVt+21R3eJuL7A7ZIkUWVbClL0GHa/VxKeEdC2GS6iyscgRhZP28xqh94+cvSFUpzxWHZ/duQE8/fjE3PR5Hfg5R3qGOwDMST2v8bvrIcfYePPD4AAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle \\left( 8, \\  12\\right)$"
      ],
      "text/plain": [
       "(8, 12)"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def converted_index(x):\n",
    "    \"\"\"Returns j = 2^{k-1} x_0 + 2^{k-2} x_1 + ... + x_{k-1}.\"\"\"\n",
    "    x_seq = bin_seq_for_int(x)\n",
    "    j = sum(2**(k-1-n) * x_seq[n] for n in range(k))\n",
    "    return j\n",
    "\n",
    "\n",
    "# x = 1 gives the sequence (1, 0, 0, 0), hence j = 8, and vice versa\n",
    "# x = 3 gives the sequence (1, 1, 0, 0), hence j = 12, and vice versa\n",
    "converted_index(1), converted_index(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "0ee7c7d2-79a2-477d-a66f-fadc17b10047",
   "metadata": {},
   "outputs": [],
   "source": [
    "Fourier_Q_mat = np.array([[Fourier(Q, converted_index(j), converted_index(l))\n",
    "                           for l in range(Q)] for j in range(Q)])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cac37667-3ebe-458a-8223-f89c2c61b19b",
   "metadata": {},
   "source": [
    "### Shor's algorithm for period finding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "b91fff20-741a-43af-9d1e-8a22cfab726b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def tens_pow_H(k):\n",
    "    # tensor product of copies of the Hadamard matrix\n",
    "    H = np.array([[1, 1],\n",
    "                  [1, -1]]) * (1/np.sqrt(2))\n",
    "    return reduce(np.kron, [H] * k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "03e4a68b-f785-4950-810d-c4b9ae32f5a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def termwise_XOR(x, y):\n",
    "    # termwise XOR of tuples\n",
    "    return tuple(xi ^ yi for xi, yi in it.zip_longest(x, y))\n",
    "\n",
    "\n",
    "def comp_basis(x_seq):\n",
    "    \"\"\"Returns computational basis vector for binary sequence.\n",
    "\n",
    "    Parameters\n",
    "    ==========\n",
    "        x_seq: list of int\n",
    "\n",
    "    Returns\n",
    "    =======\n",
    "        numpy.array\n",
    "          1-dimensional array representing |x⟩\n",
    "    \"\"\"\n",
    "    vec_seq = (zeroket if xi == 0 else oneket for xi in x_seq)\n",
    "    return reduce(np.kron, vec_seq)\n",
    "\n",
    "\n",
    "def U(k, f):\n",
    "    # U_f gate for the Shor's algorithm\n",
    "    res = np.zeros((2**(2*k), 2**(2*k)), dtype=np.int8)\n",
    "    for in_x in range(Q):\n",
    "        in_x_seq = bin_seq_for_int(in_x)\n",
    "        f_x_seq = bin_seq_for_int(f(in_x))\n",
    "        out_x_seq = in_x_seq + f_x_seq\n",
    "        in_as_row = np.atleast_2d(comp_basis(in_x_seq + (0,) * k))\n",
    "        out_as_column = np.atleast_2d(comp_basis(out_x_seq)).T\n",
    "        res += out_as_column @ in_as_row\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "2eac836a-280a-464d-b3b7-ae0799133723",
   "metadata": {},
   "outputs": [],
   "source": [
    "z = 2  # coprime to N=15, period 4\n",
    "\n",
    "\n",
    "def f_from_z(x):\n",
    "    return z**x % N"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "780c1c4f-6d8d-4330-9e13-46e102020981",
   "metadata": {},
   "outputs": [],
   "source": [
    "H_pow_ampl = np.kron(tens_pow_H(k), np.identity(2**k))\n",
    "F_Q_ampl = np.kron(Fourier_Q_mat, np.identity(2**k))\n",
    "Shor_gate = F_Q_ampl @ U(k, f_from_z) @ H_pow_ampl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "fced37d7-0dc2-41d6-83dd-ea9772771f92",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = Shor_gate @ comp_basis((0,) * (2 * k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "0ce449e7-f599-4b1b-8edf-e30b5625970b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def proj(x):\n",
    "    \"\"\"Return the projection for the computational basis.\"\"\"\n",
    "    basis_vec = np.atleast_2d(comp_basis(x))\n",
    "    return basis_vec.T @ basis_vec\n",
    "\n",
    "\n",
    "def meas_prob(x):\n",
    "    \"\"\"Return the probability of observing x in the first half of v.\"\"\"\n",
    "    return np.real(np.dot(np.conjugate(v), np.kron(proj(x), np.identity(2**k))\n",
    "                          @ v))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "d91336ed-272c-40cc-b25a-3921486602ab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 0, 0, 0) with probability 0.24999999999999983\n",
      "(0, 0, 0, 1) with probability 0.24999999999999983\n",
      "(0, 0, 1, 0) with probability 0.24999999999999983\n",
      "(0, 0, 1, 1) with probability 0.24999999999999983\n",
      "(0, 1, 0, 0) with probability 2.490901373688428e-33\n",
      "(0, 1, 0, 1) with probability 4.027722318042177e-31\n",
      "(0, 1, 1, 0) with probability 4.2853361082501866e-32\n",
      "(0, 1, 1, 1) with probability 2.1901643103849205e-31\n",
      "(1, 0, 0, 0) with probability 3.392850582730631e-33\n",
      "(1, 0, 0, 1) with probability 1.9709433046355512e-31\n",
      "(1, 0, 1, 0) with probability 5.661795627457957e-32\n",
      "(1, 0, 1, 1) with probability 5.268444744125783e-31\n",
      "(1, 1, 0, 0) with probability 1.3154137496480876e-32\n",
      "(1, 1, 0, 1) with probability 7.5363004251521216e-31\n",
      "(1, 1, 1, 0) with probability 1.2936396563271622e-31\n",
      "(1, 1, 1, 1) with probability 1.1502059203743868e-30\n"
     ]
    }
   ],
   "source": [
    "intervals = {}\n",
    "t = 0.0\n",
    "for x in it.product(range(2), repeat=k):\n",
    "    prob_for_x = meas_prob(x)\n",
    "    intervals[x] = (t, t + prob_for_x)\n",
    "    t += prob_for_x\n",
    "    print(f\"{x} with probability {prob_for_x}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "b03aca49-ffcf-4a90-86c1-73ce90cfa57e",
   "metadata": {},
   "outputs": [],
   "source": [
    "x_samples = []\n",
    "for _ in range(k):  # when k is small, it's better to repeat a bit more\n",
    "    rand_num = rng.random()\n",
    "    for x in it.product(range(2), repeat=k):\n",
    "        if intervals[x][0] < rand_num and rand_num < intervals[x][1]:\n",
    "            x_samples.append(x)\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "969b1f0f-6f9c-429d-a1f8-9d8dd7a058cb",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[ \\left( 0, \\  0, \\  0, \\  1\\right), \\  \\left( 0, \\  0, \\  0, \\  0\\right), \\  \\left( 0, \\  0, \\  1, \\  1\\right), \\  \\left( 0, \\  0, \\  1, \\  1\\right)\\right]$"
      ],
      "text/plain": [
       "[(0, 0, 0, 1), (0, 0, 0, 0), (0, 0, 1, 1), (0, 0, 1, 1)]"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_samples  # binary sequnces replesenting c*L for L = Q/s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "1ee8e55e-913e-4861-974f-b207a56df899",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADEAAAAVCAYAAADvoQY8AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMElEQVRYCc2X4VECMRCFT8YCbrSDswOQDqQDxA6gAxx/wV/tQFvAEuzAkQ6gA4UO8H2Z3BEgd+QuDENmQnK72by3l93NkWw2m8Ttk8kkc58vbe7j10qcNp1Ox3psO6JLnGaWZ8GtcEKKvqS3Gj8LrWcifVv93aM6uciHJdkXQBqHOaBxQoJUgheNz7miYpxJd1OhP6XKiyWebwIZWd5JfhKvEh59uzIi3M7SArDgC+/CiYGMPqrYSU+urG2vWhqtC8GyfOGdtvRDLiwDkJ+sYcDS6CWhWPAeEE49dZMsZdAiTxgdDbcy+zrymljw7uHEvfqiDEibZtKtNYacVtk2QfIGWPDOcILK9FeBQhWozJcK27qquljwNk5QLknYgyby1OJzhVETLKIj5SS8zR5tqvFcYdQEyxzAtTzgSAip/UYudOUEF47bKLVc/ciXGkMuSNfeN2+KZVIBJ3jTbLLTRI7MP6hakq+Qa3x0DfTMm/SGpbvON5ddLSxnD05iSTjN1buO4tgU73dODgckW2n8OWZcU3+AtWff0fP8Sp+2hMdMBO72Fuw8Sk+Cc2IPVsGH4rfkfMckGvMy3dF8bdc0GmRfiZVvajFH5r+EHFngTOx/B+3RV09j9wmxF06mvmAt4UTjQ2pkZnE/FIKoU6gBT0HZfgAKmMuMinOQ4KGbypb4/Q1dH7PO8oSvuYTzk2BPqk3MxTbUpiY/YggG2sJzGzlu/Nk4G7uyS5uL4xieLq9/YN9nOhF026wAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle \\left( 4, \\  4\\right)$"
      ],
      "text/plain": [
       "(4, 4)"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# get L as the greatest common divisor of integers c*L\n",
    "from math import gcd\n",
    "L = reduce(gcd, (int_from_bin_seq(x_seq) for x_seq in x_samples))\n",
    "s = Q // L\n",
    "L, s"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cfc51e35-a2f2-4bc0-a6b5-3d46cc3e9973",
   "metadata": {},
   "source": [
    "### continued fraction"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b41f234-0dbd-4c7b-bddb-dd32096d5044",
   "metadata": {},
   "source": [
    "code sample from [sympy documentation](https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#example-continued-fractions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "id": "96ccbb02-afcd-4a47-a17b-210a0441ca86",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "id": "8f5065e4-9b1b-4a07-a8ab-41a21d664f16",
   "metadata": {},
   "outputs": [],
   "source": [
    "def list_to_frac(coeff_list):\n",
    "    \"\"\"Returns continued fraction with the given coefficients.\"\"\"\n",
    "    expr = sy.Integer(0)\n",
    "    for i in reversed(coeff_list[1:]):\n",
    "        expr += i\n",
    "        expr = 1/expr\n",
    "    return coeff_list[0] + expr"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf188e84-9d4a-4bc9-9acd-16920c9233fc",
   "metadata": {},
   "source": [
    "continued fraction approximation of $\\sqrt{2} = [1; 2, 2, \\cdots]$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "id": "a39fcc3d-5efa-4dbd-ba94-937b84958237",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAG8AAAAyCAYAAABS1YVJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHxUlEQVR4Ae2c63EUORDH1y4HYHwRnJ2BwRFgMsB1ERxkAMU3f3NBBkAEB5cBXAQHzgBngNkMfP+fVq2ahzQPzWOn6qartNK0Wt2tbrWkmdHswcPDw6YNrq+vv4jmtfLbNtq1fpgFZONjcfisdKXytonbQZvzxABGX5R/aGI0d530OZXMS6VPbZ2cW7eivBw91eZcPLD746a+NTpPDWFwp/x1UaFiWXUY8aXHMWq4fiv8V4+bJBP/52KMfinYiuZRqnJMvOQkjZ2rp2+HHc9Suh6lKtTohepOlV810OAsplNz3kZljEqkEvZ/p9qOgL8QDwbIXYQXEZkccBH63ij1jb5/VLpXeqLEoI1Blp7YTulC6bNS1AdR54nYRY80eRzTpoDDwS9Ej7PMURZxb1RnuEKT8YqS+azKzeu+KehTJRnlWvxZj5xRVX6lMtEXBdVn6al2BMYPJWxcW7YOo9IUOcLfqEFsVBebsIGhEyQHahPKhpso/zfBl6kmzAQJmjnRQ/VkBqFPx1Wla5EnIqLpRPm7KnH1WjREWWldEY5pE3i/y6b5lZxaVAv3VtJuppGYx3WonrRXYhajb6VBGYs8iGoh2kV1CWGtcUJUzuLRRU6MRvKY6s+VL/p2JlNPoo+pkz4GKEWeKpm7Cc9eo1ftmO9xHIszxvumNDcwaEhLh956yr5flbArbcPmpRp5hCVh2mvdgrHSOyUY/6X0XWWbPnU5LUgWI/JSuW2WphWYyX2gngTUc/EIa19wnpBED0boFXXVfogPaxHOZ4sbBFXpRr5m0LVtrkYWmcVuiJ42MNmTOAjO0xWLIje2ndcMHE7asSr92rTJVDoHEOX3cwgaKCNbT9mZgMCBDAAHRedhaPOur27NvouCKXKuCKsp5GUzY9C5xcJIevJEiQcn9HfjnKcLogcHcH/XBzBYbI184pn0HQx9ZButyVp65I2h5yffaTejWeTZ9NbX2GxhSw7XQGBqYCC8VHmOaEAWMIesnaT6728edVKvCpjBenp70k/3xObIs+aC9a7Xoi/6D0rs8oo35IT0M+H6DgSvSu+MNZoOpZ5k9GbYtYH6yDQG2OBnk4YNY29hxtKT/YTbZ7i3ChL4S4hvymvP4IRfYUEWkI+413ul/OBQP4QzqVfULag//zdVftBh+e2SNY9pDnDIXXH9XbAF7DbsvOi8NfIW7LGCauanM5xnOyRDFujW4tIsoOmSzRlwgvNY7wBD7q7W36Vb4Bjn2T3K0m9yl27MOfUj0EqRN6fwVdYwCxBox9ykuzWvMJd2Yiv69gOfnpNoDzox7Ui0T9mo2Ed+xy7Bs6+NTuwJS1cZgS5DWGg7tLBP2ei+b/lmP9Y8t9ZJIdu4WN2aL9sC9zjPdpl2yzC5yvscKPuUPaJh8dUW5/30TGeJPG+8X8p5Fzgr7FP2BB29K0beBPzrLGVAIp0HAsfemHWijhi1P6+SwlPptIrnWvjRZMf4z4gj0O7ZsNj9Xda06Q1lR8t54Qi/xi+K1OZMifd+Q+Ef8aEjt54RZSB50ntE2TtJ+hVPBhGvh6IfhqiewdTLRqKPgnhZH7c4zx6LRUdrlINHeqXeKw+vklTmlQVHI9re6XEOn8NKQ8AGHsajH/DjpPe2helg2ZKBEVu/VRAdds21Uawb5qefR2LOsT2IkqM1xsHjcFQ4EANOvIg6TjgxEkunqakHVE/Hba11uMwfdA/nGLvwGEu2+DBAnGyVm75VyLJRQ1/MeW7Ng45Ra2csGtrVqi6F4UMInFEE3qIn1x7Vcfq39Th9keGI5bll59oo1WVz3u2hp2DNMGSqUQyPk/h+j1EYg6pTHc0eHbfZg+wsG8WM6XEX5OrHHWsewCEidxpXyJQjHGHxR7SpKcvtAlVvG4lis1HLksEUzSDhATsDkDVvcrmS0wkmsBGR7M4HWeTZ21kqBoGUxXEY0XZXg/i1NMZpfNbMUXvkkdgsDe5Hi9xB1bk2UjvsSp/diT3nPCEZqUTcH0pDgY0KZzknX9Mkgx0tejtQmbWbUVk8zbarXNZvro1sULpdukUeXeNAp1VmdVXGw2isganpNItvz0Y4MJwq7tl2cvKBNuKWDPvSx92Jaa8xo4EdYpYD1c4+ygz3fJ7vJJnkcTay6REb08uiYAQb8WAjzCoh8sTY7YpU2Ttq1BamPDUJbVWeevRzaxNz0InwG8lfzKbF6zPIRuqPfR0UPloNzkOAgBtK7oNiRnEE1R/RskHhiUV1g4Ky91X6Ea85rR37mwtmDrcbG1HWIFYj2Qj7lr4LOSpqJSEYBAe+Uao6o0jqyqI9VYHpli83Qzh7wkvhpty08MiJFJ7wqMyTDiDMALvLyX/tHBBRHzZQSJVOg20kHgxI+JSWpJLzECbAaRilyzNCtqwwtZBWMcCk05b0Y+HmXxJs0GA4Iv134UoGDBqNXJAcBi6AcYHYtwpj2Miizm1UdqI2m+g/IEkpNgJEU2v0GaM1n8YC8gEDgwHwSOXSoDxMiPxTeNY+omqF/VqAmeWq6jhUijpPhEx5N0o2JUG7wswWkB/Yf/DmJPrqLOo8dFQDNhtbzwDUCjNaQHZnumTTl9x8JZ2Hnr4hDNj2rzCTBWRvbr+IuqdNIhudR0Mx4iUtnyjDcIWJLSA7c4/9UempyqUNSlX0fxCwBDPemVLFAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left( \\frac{3}{2}, \\  \\frac{7}{5}, \\  \\frac{17}{12}\\right)$"
      ],
      "text/plain": [
       "⎛          17⎞\n",
       "⎜3/2, 7/5, ──⎟\n",
       "⎝          12⎠"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list_to_frac([1, 2]), list_to_frac([1, 2, 2]), \\\n",
    "  list_to_frac([1, 2, 2, 2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "e680d797-1818-4c63-840b-08ce8b77688c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sqrt2_approx_error(k):\n",
    "    \"\"\"Approximation error of continued fracton of sqrt(2).\"\"\"\n",
    "    frac_at_k = list_to_frac([1] + [2] * k)\n",
    "    error = sy.N(sy.sqrt(2) - frac_at_k)\n",
    "    err_abs = error if error > 0 else -error\n",
    "    return err_abs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "id": "0e919932-0f63-4177-a74b-9b2fa9ac6879",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x110c38c20>]"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "k_seq = [k for k in range(2, 7)]\n",
    "y_seq = [sqrt2_approx_error(k) for k in k_seq]\n",
    "ax.set_title(\"$|\\\\sqrt{2}-[1;2,\\\\cdots,2]|$ for the $k$-th cut-off\")\n",
    "ax.set_xticks(k_seq)\n",
    "ax.set_xlabel(\"$k$\")\n",
    "ax.plot(k_seq, y_seq)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f250585-97cf-4fee-91d7-7ce6628cf6fc",
   "metadata": {},
   "source": [
    "error estimate with signs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "9254b434-c3f6-4bed-8a2b-347ed9be013c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABUAAAArCAYAAACXZ8NLAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACUklEQVRIDe2X7VHbQBCGZYYCHKgA0wFJOkg6MCUESmDyy/5LCYQKGKeD0AEfHSQlMO7AeR6h1ejOkix5wq+wM+u929t9b7X3tZ5sNpuiScvl8oz+Cv5Ie90cs41uhris9FOk/Wv095WuOLSBwsFb+AX+BGu4RZXdFTJA9Z1j+At5Dv/U6cAfOutKqfGdug66QH+BrUBBEeH3UJSg0Rkgn7ExJXVaDCj3Kz8/V3b1ATCqD83xRtQ3oR8bafiVEsAvNK7hS9o/YnBUpOEEgDtEwM+wKXmEa9oXVCC5YAIX7QmZrr6D+xJgbiMXa0V7Ks6onOJ0JuuYUXy+KRkHiv2THBEJ0EZjc+pn3gOa701PoVQehDbQ49fx4giZO19VY7VgAhfKXLqtSvtJXCgovEQk86KRq/sH9lzXe5C24+dw0IxGcqHUoGHxL+So1R864Tvo0EwNt/vPczpZLBbpGz08dZ2W7yeqMzV7D7zJPm27pJMIuT+9W+uShrZ9H7kodxL7suMl3cdsuZt8HN0Knuf66Pd+PtFYkPnY5fQNRTP6ZLwXFMtT+GviMaCzC/QBjDkR+06ZyyDrp7ogC2XInScKMB/EqEd9TY3eScoCN4CaclekBc6+nPGaGqGvaVlHNYGa7SGgRrmGjdBtNIN/M1lETzel3s/H0dX3D0Ve45sSJzphTJnQrkj93KQqAcRcGrULZyq2qBMUZ52mbZGgs3IR3NJoi/pA/Sz/tZjDNnLS1qPaCVqhuPJ1MRvITGSu3VZGvEW9C6U1jha5HskX+xX1Xih/ATR5/lS4K5uLAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\frac{13}{8}$"
      ],
      "text/plain": [
       "13/8"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c_seq = [1, 1, 1, 1, 1, 1]\n",
    "cont_frac = list_to_frac(c_seq)\n",
    "cont_frac"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "id": "fd3e4c56-46a2-497c-bde2-565ecd832046",
   "metadata": {},
   "outputs": [],
   "source": [
    "def error_from_cutoff(k):\n",
    "    \"\"\"Difference between the cut-off at the k-th term (inclusive).\"\"\"\n",
    "    cut_off = list_to_frac(c_seq[0:k+1])\n",
    "    return cont_frac - cut_off"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "2edfb177-5f4e-4f13-a607-056233d6eb9b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x110d934d0>]"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig2, ax2 = plt.subplots()\n",
    "k_seq = [k for k in range(1, len(c_seq))]\n",
    "y_seq = [error_from_cutoff(k) for k in k_seq]\n",
    "ax2.set_title(\"difference with the $k$-th cut-off\")\n",
    "ax2.set_xticks(k_seq)\n",
    "ax2.set_xlabel(\"$k$\")\n",
    "sec_xax = ax2.secondary_xaxis(0, transform=ax2.transData)\n",
    "sec_xax.set_xticks([])\n",
    "ax2.plot(k_seq, y_seq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "id": "cced615d-b478-4799-8976-f64d4c3466ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "def coeff_for_cont_frac(rat: sy.Rational):\n",
    "    \"\"\"Returns the coefficients for continued fraction.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    rat : sympy.Rational\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    list\n",
    "        list of integers c0, c1, ..., cM satisfying\n",
    "        rat = [c0; c1, ..., cM].\n",
    "    \"\"\"\n",
    "    rat = sy.simplify(rat)\n",
    "    num, denom = rat.as_numer_denom()\n",
    "    if denom == 1:\n",
    "        return [num]\n",
    "    c0 = num // denom\n",
    "    next_rat = 1 / (rat - c0)\n",
    "    return [c0] + coeff_for_cont_frac(next_rat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "67b0991b-0a61-47ce-89b9-75ffd6606ba3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAACwAAAAVCAYAAAA98QxkAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABvElEQVRIDc2X23HCMBBFRSYFMJQAHeTRAekgboF0kHzi36QDakg6gBZCB9BBHiXkXMfWEGPZu9iZQTOyZGm992i9ksej5XL5GEJ4oKpkeZ5vf7vncYXnD98I4GfQ1kxszgOxmQK+gvOyeToEDKbMPZXzN7Sfumd80Dfg1WkELp2saO9K4EBfK3zXGHWQt4EfBcWlc1EB1VrBVXldTOFc0f6mvhYDw1zcOingOTw7IMc1LkV2XEamNnXSrVsnBSywPWCKaFOpL6TJxjLm1knlcJZQu9I4Cxlk4+HHrZOK8BEvzgU7pVYnx5HNEANdOmZgYLTZ3nD4MgRYi49WHRMwkCsElNOpV9iib5+y6HQC42SB5IQ2nsl2BLulVacVGCf3SM5oY2TpT1XtKN2WHp0kME60yW5p65tMi9BnuijM9zrirDqVXupYUwSV/BscKn8Py5yxYuOVsF+0W+r1oZGlzzMmnUNfqQivMZIz5W+9xo8Jgurvqfr6nRJpkw7+Y0lFeBYtOjqAKseVJu6iZ70PpSLs9aNcj5H3Puyx7w0MqFLhwyPax7Y3MOILoP/76xfXWP0iVTl4zv90E6izH9Y+w76fIsLcAAAAAElFTkSuQmCC",
      "text/latex": [
       "$\\displaystyle \\left[ 2, \\  2\\right]$"
      ],
      "text/plain": [
       "[2, 2]"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coeff_for_cont_frac(sy.Rational(5, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1aea9b97-11f2-4ae8-b151-cb87e548ebc6",
   "metadata": {},
   "source": [
    "In Shor's algorithm, we want to estimate $b = \\frac{c}{s}$ from $a = \\frac{x}{Q}$ using $s < N$, $N^2 < Q$, and $|a-b| \\le \\frac{1}{Q} < \\frac{1}{N^2}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "0962bee0-1b82-424b-b791-701642108779",
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 21  # 3 * 7\n",
    "Q = 2**9  # 512 > 21 * 21 = 441"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37b098d9-6933-45ed-b7fc-ed2d70ec5105",
   "metadata": {},
   "source": [
    "if we choose $z = 2$ (coprime to $N = 21$), we actually know that the period is $s = 6$ from $2^6 = 64 = 3 \\times 21 + 1$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "5659547f-44df-4407-aa56-119fdb8be30e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[ 2, \\  4, \\  8, \\  16, \\  11, \\  1, \\  2, \\  4, \\  8, \\  16, \\  11, \\  1, \\  2, \\  4, \\  8, \\  16, \\  11, \\  1, \\  2, \\  4\\right]$"
      ],
      "text/plain": [
       "[2, 4, 8, 16, 11, 1, 2, 4, 8, 16, 11, 1, 2, 4, 8, 16, 11, 1, 2, 4]"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[2**a % N for a in range(1, N)]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c012d29b-371a-40c0-96ec-e8e283d0728e",
   "metadata": {},
   "source": [
    "we can get $x = 85$, that makes $a$ closer to $\\frac{1}{6}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "4286fdea-6bd5-49d0-9dcb-c5399c642c64",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( -0.000651041666666667, \\  0.00226757369614512\\right)$"
      ],
      "text/plain": [
       "(-0.000651041666666667, 0.00226757369614512)"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = 85\n",
    "a = sy.Rational(x, Q)\n",
    "sy.N(a - sy.Rational(1, 6)), sy.N(sy.Rational(1, N**2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "748452fe-8e46-4eb6-b0b9-ba9e8bfaae0a",
   "metadata": {},
   "source": [
    "To work out $s$ from $a$, we get the continued fraction coefficients of $a$, and find a candidate of $b$ that has small denominator ($s < N$) but close enough to $a$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "6749ecc9-07ca-4201-aee6-18c7aaf5150e",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cutoff at k=0 gives b=0 with denominator=1\n",
      "👎 the error 0.166015625000000 is too big against 1/N**2 = 0.00226757369614512\n",
      "cutoff at k=1 gives b=1/6 with denominator=6\n",
      "👍 this is a good candidate!\n",
      "cutoff at k=2 gives b=42/253 with denominator=253\n",
      "👎 the denominator is too big against N=21.\n",
      "cutoff at k=3 gives b=85/512 with denominator=512\n",
      "👎 the denominator is too big against N=21.\n"
     ]
    }
   ],
   "source": [
    "a_coeff = coeff_for_cont_frac(a)\n",
    "\n",
    "\n",
    "def cutoff_denom(k):\n",
    "    cutoff_rat = sy.simplify(list_to_frac(a_coeff[:k+1]))\n",
    "    _, denom = cutoff_rat.as_numer_denom()\n",
    "    return denom\n",
    "\n",
    "\n",
    "for k in range(len(a_coeff)):\n",
    "    b_cand = sy.simplify(list_to_frac(a_coeff[:k+1]))\n",
    "    b_cand_denom = cutoff_denom(k)\n",
    "    print(f\"cutoff at k={k} gives b={b_cand} with denominator={b_cand_denom}\")\n",
    "    error = sy.N(a - b_cand)\n",
    "    if b_cand_denom > N:\n",
    "        print(f\"👎 the denominator is too big against N={N}.\")\n",
    "    elif error > sy.N(1/N**2):\n",
    "        print(f\"👎 the error {error} is too big against 1/N**2 = {sy.N(1/N**2)}\")\n",
    "    else:\n",
    "        print(\"👍 this is a good candidate!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb22ce47-7276-4676-bd4f-525aef2ee0aa",
   "metadata": {},
   "source": [
    "## Lecture 17"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c45bf5b0-910b-484e-a8d5-96a4c0fd97c6",
   "metadata": {},
   "source": [
    "Recursive relation for the Fourier transform (Proposition 17.1)\n",
    "$$\n",
    "F_Q = \\frac{1}{\\sqrt{2}} \\begin{bmatrix}\n",
    "\tF_{Q/2} & B_{Q/2} F_{Q/2} \\\\\n",
    "\tF_{Q/2} & - B_{Q/2} F_{Q/2}\n",
    "\\end{bmatrix},\n",
    "$$\n",
    "with\n",
    "$$\n",
    "[F_{Q}]_{j, l} = \\frac{1}{\\sqrt{Q}} \\exp\\left(\\frac{2 \\pi i}{Q} j l \\right),\n",
    "$$\n",
    "where $\\tilde{l}$ is the integer obtained by reordering the bit representation of $l$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "54790a46-1d1c-4196-ab09-b2d7fce7a2b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sy\n",
    "from sympy.physics.quantum.dagger import Dagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "615d5882-9e39-411a-932c-8cf5d58463fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "k = 4\n",
    "Q = 2**k\n",
    "Q2 = 2**(k-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "ce821cfc-84a7-4e5d-b77d-3f15ddc0eaf3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from Lecture 16\n",
    "def bin_seq_for_int(k, x: int):\n",
    "    \"\"\"Returns binary sequence representation of the integer x.\n",
    "\n",
    "    Parameters\n",
    "    ==========\n",
    "        x: int\n",
    "\n",
    "    Returns\n",
    "    =======\n",
    "        tuple of int\n",
    "          (x0, x1, ..., x(k-1)) with xi = 0, 1 and\n",
    "          x = x0 + 2 * x1 + ... + 2**(k-1) * x(k-1)\n",
    "    \"\"\"\n",
    "    # for i=0,..., k-1, do bit shift by i and bitwise AND with 1\n",
    "    return tuple((x >> i) & 1 for i in range(k))\n",
    "\n",
    "\n",
    "def int_from_bin_seq(k, x_seq):\n",
    "    \"\"\"Returns integer for the binary sequence of length k.\"\"\"\n",
    "    return sum(2**n * x_seq[n] for n in range(k))\n",
    "\n",
    "\n",
    "# convert k-bit integer to another with reversed bit sequence\n",
    "def converted_index(k, x):\n",
    "    \"\"\"Returns j = 2^{k-1} x_0 + 2^{k-2} x_1 + ... + x_{k-1}.\"\"\"\n",
    "    x_seq = bin_seq_for_int(k, x)\n",
    "    j = sum(2**(k-1-n) * x_seq[n] for n in range(k))\n",
    "    return j"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "93e2b5db-33e7-405f-ba45-c6d8ebb78418",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from Lecture 16\n",
    "def Fourier(n, j, l):\n",
    "    \"\"\"Returns the coefficient of Fourier transform matrix of size n.\"\"\"\n",
    "    return sy.exp(2 * sy.I * sy.pi * j * l / n) / sy.sqrt(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "id": "8d7e3833-b59d-448c-b6a9-8f38e002e4d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "F_Q = sy.Matrix([[Fourier(Q, j, converted_index(k, l))\n",
    "                  for l in range(Q)] for j in range(Q)])\n",
    "F_Q2 = sy.Matrix([[Fourier(Q2, j, converted_index(k-1, l))\n",
    "                   for l in range(Q2)] for j in range(Q2)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "9c94eb03-aff9-4bd9-bbad-968045756a2c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{array}{cccccccccccccccc}\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4}\\end{array}\\right]$"
      ],
      "text/plain": [
       "⎡1/4  1/4   1/4   1/4     1/4       1/4       1/4       1/4       1/4       1/ ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                          ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -7⋅ ↪\n",
       "⎢                          ───     ───────    ─────     ─────      ───     ─── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ      ℯ       ℯ          ℯ         ℯ          ℯ       ℯ    ↪\n",
       "⎢1/4  -1/4   ─    ───     ────    ────────   ──────    ──────     ────    ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                  ⅈ⋅π       ⅈ ↪\n",
       "⎢                                                                  ───       ─ ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                          ⅈ         ⅈ        -ⅈ        -ⅈ        ℯ         ℯ  ↪\n",
       "⎢1/4  1/4   -1/4  -1/4     ─         ─        ───       ───       ────      ── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π    -5⋅ ↪\n",
       "⎢                         ─────     ─────      ───     ───────    ─────    ─── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ          ℯ       ℯ          ℯ        ℯ    ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────     ────    ────────   ──────   ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                  ⅈ         ⅈ ↪\n",
       "⎢1/4  1/4   1/4   1/4     -1/4      -1/4      -1/4      -1/4       ─         ─ ↪\n",
       "⎢                                                                  4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                        -3⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      3⋅ⅈ⋅π     5⋅ⅈ⋅π    -3⋅ ↪\n",
       "⎢                        ───────     ───      ─────     ─────     ─────    ─── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ    ℯ           ℯ        ℯ         ℯ         ℯ        ℯ    ↪\n",
       "⎢1/4  -1/4   ─    ───   ────────    ────     ──────    ──────    ──────   ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 3⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                                                                 ─────     ── ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                         -ⅈ        -ⅈ         ⅈ         ⅈ       ℯ         ℯ   ↪\n",
       "⎢1/4  1/4   -1/4  -1/4    ───       ───        ─         ─       ──────    ─── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         -ⅈ⋅π      3⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π      7⋅ⅈ⋅π     -ⅈ ↪\n",
       "⎢                         ─────     ─────    ───────     ───      ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ        ℯ           ℯ        ℯ         ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────   ────────    ────     ──────    ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢1/4  1/4   1/4   1/4     1/4       1/4       1/4       1/4       -1/4      -1 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                          ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π     -7⋅ⅈ⋅π      ⅈ ↪\n",
       "⎢                          ───     ───────    ─────     ─────    ───────     ─ ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ      ℯ       ℯ          ℯ         ℯ        ℯ           ℯ  ↪\n",
       "⎢1/4  -1/4   ─    ───     ────    ────────   ──────    ──────   ────────    ── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                -3⋅ⅈ⋅π    -3⋅ ↪\n",
       "⎢                                                                ───────   ─── ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                          ⅈ         ⅈ        -ⅈ        -ⅈ      ℯ         ℯ    ↪\n",
       "⎢1/4  1/4   -1/4  -1/4     ─         ─        ───       ───     ────────  ──── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -3⋅ⅈ⋅π    -5⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                         ─────     ─────      ───     ───────   ───────    ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ          ℯ       ℯ         ℯ          ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────     ────    ────────  ────────   ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 -ⅈ        -ⅈ ↪\n",
       "⎢1/4  1/4   1/4   1/4     -1/4      -1/4      -1/4      -1/4      ───       ── ↪\n",
       "⎢                                                                  4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                        -3⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      3⋅ⅈ⋅π    -3⋅ⅈ⋅π     5⋅ ↪\n",
       "⎢                        ───────     ───      ─────     ─────    ───────    ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ    ℯ           ℯ        ℯ         ℯ        ℯ          ℯ   ↪\n",
       "⎢1/4  -1/4   ─    ───   ────────    ────     ──────    ──────   ────────   ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 -ⅈ⋅π      -ⅈ ↪\n",
       "⎢                                                                 ─────     ── ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                         -ⅈ        -ⅈ         ⅈ         ⅈ       ℯ         ℯ   ↪\n",
       "⎢1/4  1/4   -1/4  -1/4    ───       ───        ─         ─       ──────    ─── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         -ⅈ⋅π      3⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      7⋅ ↪\n",
       "⎢                         ─────     ─────    ───────     ───      ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ        ℯ           ℯ        ℯ         ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────   ────────    ────     ──────    ─── ↪\n",
       "⎣            4     4       4         4         4         4         4         4 ↪\n",
       "\n",
       "↪ 4       1/4       1/4       1/4       1/4       1/4       1/4   ⎤\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π     5⋅ⅈ⋅π    -3⋅ⅈ⋅π     3⋅ⅈ⋅π    -5⋅ⅈ⋅π     7⋅ⅈ⋅π     -ⅈ⋅π  ⎥\n",
       "↪ ────    ─────    ───────    ─────    ───────    ─────     ───── ⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪        ℯ        ℯ          ℯ        ℯ          ℯ         ℯ      ⎥\n",
       "↪ ────   ──────   ────────   ──────   ────────   ──────    ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⋅π     -3⋅ⅈ⋅π    -3⋅ⅈ⋅π     3⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π      -ⅈ⋅π  ⎥\n",
       "↪ ──     ───────   ───────    ─────     ─────     ─────     ───── ⎥\n",
       "↪ 4         4         4         4         4         4         4   ⎥\n",
       "↪       ℯ         ℯ          ℯ         ℯ         ℯ         ℯ      ⎥\n",
       "↪ ──    ────────  ────────   ──────    ──────    ──────    ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π     -ⅈ⋅π      7⋅ⅈ⋅π    -7⋅ⅈ⋅π      ⅈ⋅π      5⋅ⅈ⋅π    -3⋅ⅈ⋅π ⎥\n",
       "↪ ────    ─────     ─────    ───────     ───      ─────    ───────⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪        ℯ         ℯ        ℯ           ℯ        ℯ        ℯ       ⎥\n",
       "↪ ────   ──────    ──────   ────────    ────     ──────   ────────⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪          ⅈ         ⅈ        -ⅈ        -ⅈ        -ⅈ        -ⅈ    ⎥\n",
       "↪          ─         ─        ───       ───       ───       ───   ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π    -7⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      7⋅ⅈ⋅π     3⋅ⅈ⋅π    -5⋅ⅈ⋅π ⎥\n",
       "↪ ────   ───────     ───      ─────     ─────     ─────    ───────⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪       ℯ           ℯ        ℯ         ℯ         ℯ        ℯ       ⎥\n",
       "↪ ────  ────────    ────     ──────    ──────    ──────   ────────⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π     -ⅈ⋅π      -ⅈ⋅π       ⅈ⋅π       ⅈ⋅π     -3⋅ⅈ⋅π    -3⋅ⅈ⋅π ⎥\n",
       "↪ ───     ─────     ─────      ───       ───     ───────   ───────⎥\n",
       "↪ 4         4         4         4         4         4         4   ⎥\n",
       "↪        ℯ         ℯ          ℯ         ℯ       ℯ         ℯ       ⎥\n",
       "↪ ───    ──────    ──────     ────      ────    ────────  ────────⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⋅π      3⋅ⅈ⋅π    -5⋅ⅈ⋅π     5⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π     -7⋅ⅈ⋅π ⎥\n",
       "↪ ───     ─────    ───────    ─────    ───────     ───     ───────⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪        ℯ        ℯ          ℯ        ℯ           ℯ       ℯ       ⎥\n",
       "↪ ───    ──────   ────────   ──────   ────────    ────    ────────⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ /4      -1/4      -1/4      -1/4      -1/4      -1/4      -1/4  ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⋅π     -3⋅ⅈ⋅π     5⋅ⅈ⋅π    -5⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π      7⋅ⅈ⋅π ⎥\n",
       "↪ ──     ───────    ─────    ───────    ─────     ─────     ───── ⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪       ℯ          ℯ        ℯ          ℯ         ℯ         ℯ      ⎥\n",
       "↪ ──    ────────   ──────   ────────   ──────    ──────    ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π      ⅈ⋅π       ⅈ⋅π      -ⅈ⋅π      -ⅈ⋅π      3⋅ⅈ⋅π     3⋅ⅈ⋅π ⎥\n",
       "↪ ────     ───       ───      ─────     ─────     ─────     ───── ⎥\n",
       "↪ 4         4         4         4         4         4         4   ⎥\n",
       "↪         ℯ         ℯ        ℯ         ℯ         ℯ         ℯ      ⎥\n",
       "↪ ────    ────      ────     ──────    ──────    ──────    ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π     7⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -7⋅ⅈ⋅π    -3⋅ⅈ⋅π     5⋅ⅈ⋅π ⎥\n",
       "↪ ───     ─────     ─────      ───     ───────   ───────    ───── ⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪        ℯ         ℯ          ℯ       ℯ         ℯ          ℯ      ⎥\n",
       "↪ ───    ──────    ──────     ────    ────────  ────────   ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪         -ⅈ        -ⅈ         ⅈ         ⅈ         ⅈ         ⅈ    ⎥\n",
       "↪ ─       ───       ───        ─         ─         ─         ─    ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π      ⅈ⋅π     -7⋅ⅈ⋅π     7⋅ⅈ⋅π     -ⅈ⋅π     -5⋅ⅈ⋅π     3⋅ⅈ⋅π ⎥\n",
       "↪ ───      ───     ───────    ─────     ─────    ───────    ───── ⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪         ℯ       ℯ          ℯ         ℯ        ℯ          ℯ      ⎥\n",
       "↪ ───     ────    ────────   ──────    ──────   ────────   ────── ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⋅π      3⋅ⅈ⋅π     3⋅ⅈ⋅π    -3⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π       ⅈ⋅π  ⎥\n",
       "↪ ───     ─────     ─────    ───────   ───────     ───       ───  ⎥\n",
       "↪ 4         4         4         4         4         4         4   ⎥\n",
       "↪        ℯ         ℯ        ℯ         ℯ           ℯ         ℯ     ⎥\n",
       "↪ ───    ──────    ──────   ────────  ────────    ────      ────  ⎥\n",
       "↪          4         4         4         4         4         4    ⎥\n",
       "↪                                                                 ⎥\n",
       "↪ ⅈ⋅π    -5⋅ⅈ⋅π     3⋅ⅈ⋅π    -3⋅ⅈ⋅π     5⋅ⅈ⋅π    -7⋅ⅈ⋅π      ⅈ⋅π  ⎥\n",
       "↪ ───    ───────    ─────    ───────    ─────    ───────     ───  ⎥\n",
       "↪ 8         8         8         8         8         8         8   ⎥\n",
       "↪       ℯ          ℯ        ℯ          ℯ        ℯ           ℯ     ⎥\n",
       "↪ ───   ────────   ──────   ────────   ──────   ────────    ────  ⎥\n",
       "↪          4         4         4         4         4         4    ⎦"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "F_Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "id": "013bee23-219d-4838-9055-030915f7c828",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2} i}{4} & - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} e^{\\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{i \\pi}{4}}}{4}\\\\\\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} i}{4} & - \\frac{\\sqrt{2} i}{4} & - \\frac{\\sqrt{2} i}{4}\\\\\\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{3 i \\pi}{4}}}{4}\\\\\\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4}\\\\\\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2} i}{4} & - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{3 i \\pi}{4}}}{4}\\\\\\frac{\\sqrt{2}}{4} & \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2} i}{4} & - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} i}{4}\\\\\\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2}}{4} & - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{2} e^{- \\frac{i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{\\sqrt{2} e^{\\frac{i \\pi}{4}}}{4}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡√2   √2     √2      √2        √2           √2           √2           √2     ⎤\n",
       "⎢──   ──     ──      ──        ──           ──           ──           ──     ⎥\n",
       "⎢4    4      4       4         4            4            4            4      ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢                                ⅈ⋅π        -3⋅ⅈ⋅π        3⋅ⅈ⋅π        -ⅈ⋅π  ⎥\n",
       "⎢                                ───        ───────       ─────        ───── ⎥\n",
       "⎢                                 4            4            4            4   ⎥\n",
       "⎢√2  -√2    √2⋅ⅈ   -√2⋅ⅈ     √2⋅ℯ       √2⋅ℯ          √2⋅ℯ         √2⋅ℯ      ⎥\n",
       "⎢──  ────   ────   ──────    ───────    ───────────   ─────────    ───────── ⎥\n",
       "⎢4    4      4       4          4            4            4            4     ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢√2   √2    -√2     -√2       √2⋅ⅈ         √2⋅ⅈ        -√2⋅ⅈ        -√2⋅ⅈ    ⎥\n",
       "⎢──   ──    ────    ────      ────         ────        ──────       ──────   ⎥\n",
       "⎢4    4      4       4         4            4            4            4      ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢                               3⋅ⅈ⋅π        -ⅈ⋅π          ⅈ⋅π        -3⋅ⅈ⋅π ⎥\n",
       "⎢                               ─────        ─────         ───        ───────⎥\n",
       "⎢                                 4            4            4            4   ⎥\n",
       "⎢√2  -√2   -√2⋅ⅈ    √2⋅ⅈ    √2⋅ℯ         √2⋅ℯ          √2⋅ℯ       √2⋅ℯ       ⎥\n",
       "⎢──  ────  ──────   ────    ─────────    ─────────     ───────    ───────────⎥\n",
       "⎢4    4      4       4          4            4            4            4     ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢√2   √2     √2      √2       -√2          -√2          -√2          -√2     ⎥\n",
       "⎢──   ──     ──      ──       ────         ────         ────         ────    ⎥\n",
       "⎢4    4      4       4         4            4            4            4      ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢                              -3⋅ⅈ⋅π         ⅈ⋅π         -ⅈ⋅π         3⋅ⅈ⋅π ⎥\n",
       "⎢                              ───────        ───         ─────        ───── ⎥\n",
       "⎢                                 4            4            4            4   ⎥\n",
       "⎢√2  -√2    √2⋅ⅈ   -√2⋅ⅈ   √2⋅ℯ           √2⋅ℯ        √2⋅ℯ         √2⋅ℯ      ⎥\n",
       "⎢──  ────   ────   ──────  ───────────    ───────     ─────────    ───────── ⎥\n",
       "⎢4    4      4       4          4            4            4            4     ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢√2   √2    -√2     -√2      -√2⋅ⅈ        -√2⋅ⅈ         √2⋅ⅈ         √2⋅ⅈ    ⎥\n",
       "⎢──   ──    ────    ────     ──────       ──────        ────         ────    ⎥\n",
       "⎢4    4      4       4         4            4            4            4      ⎥\n",
       "⎢                                                                            ⎥\n",
       "⎢                               -ⅈ⋅π         3⋅ⅈ⋅π       -3⋅ⅈ⋅π         ⅈ⋅π  ⎥\n",
       "⎢                               ─────        ─────       ───────        ───  ⎥\n",
       "⎢                                 4            4            4            4   ⎥\n",
       "⎢√2  -√2   -√2⋅ⅈ    √2⋅ⅈ    √2⋅ℯ         √2⋅ℯ        √2⋅ℯ           √2⋅ℯ     ⎥\n",
       "⎢──  ────  ──────   ────    ─────────    ─────────   ───────────    ───────  ⎥\n",
       "⎣4    4      4       4          4            4            4            4     ⎦"
      ]
     },
     "execution_count": 131,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "F_Q2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eeb7c441-84e3-4e5d-9a87-3c655b392b45",
   "metadata": {},
   "source": [
    "$B_{Q/2}$ is a diagonal matrix of size $2^{k-1} = Q/2$, with components $1, \\exp(\\frac{2\\pi i}{Q}), \\exp(2\\frac{2\\pi i}{Q}), \\cdots, \\exp((2^{k-1}-1)\\frac{2\\pi i}{Q})$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "id": "01a81933-3222-4e51-90e0-3219ce2d111a",
   "metadata": {},
   "outputs": [],
   "source": [
    "diag_list = [sy.exp(j * 2 * sy.pi * sy.I / Q) for j in range(2**(k-1))]\n",
    "B_Q2 = sy.diag(*diag_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "id": "7f78cd66-3a8b-4980-af0c-a8974bb68aca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAADVCAYAAAC8Lzw2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAgAElEQVR4Ae1dy47cRpatGmjdMCyg910GZt+StW9A0h9YamBmLesPVBDQAzfQC8P6A1n7AWTpDySjP6AkYdYDyLM3MAXBHzCec1i8VCSLmbxkkhlxI08AkfFgBHnPucy4jAeDp999992tk5OT9/BD7vXf//73B0MHlCcGxIAYEANxGUDb/hHSnw0hwLHTG8mBZ4izcOp+SROKiwExIAbEQDUM/DCA5D7yvmF+ahyew1qMGgOUYU/jFfxtxD/xJCU5yGSA/xdyfQX/gwdXSRhMlpqwGCaGEXFJ5lSDZcUj6mYOg0vjxPl+7MuBPGY1xuFf+geH0qjwBfwr+Oc4/gJ+sCsyVPeQeZCPw2MXCM/h2RM6h3+DeJHy7uKmJiwpzoi4JHOqwbLiEXUzh8EcOL3G4ROEewD/GMBezgG3dh3I9i2uQSP22q6FOHs2TNOohXE1YUlJj4hLMqcaLCseUTdzGMyF02Uc5gDKUIcT5x8GrnuBvHsg+IuBY6Vm1YQl5TgiLsmcarCseETdzGEwC86ajMM9sH45wLzNo/B4FFcTlpTziLgkc6rBsuIRdTOHwSw4qzAOzl7Bl3O0cug6NWFJuYuISzKnGiwrHlE3cxjMibMK4wDSreHftXoqyrBSTVjS/0NEXJI51WBZ8Yi6mcNgNpy1GAcP6Tc9hYKUqQlLSnlEXJI51WBZ8Yi6mcPgKjhrMQ5Dcw1GsllevvcQwdWEJeU7Ii7JnGqwrHhE3cxhMBvOKowDxuVsOGlo6MjybGJ6joIOVqcmLClpEXFJ5lSDZcUj6mYOgzlxVmEcWtLfIjwbUID1HHg8iqsJS8p5RFySOdVgWfGIupnDYBacNRkHbunx9QDzt5H3IbHAA0WKy6oJS0puRFySOdVgWfGIupnDYBacc4yDTX7YE/kcsIvXQePPfUIuETb7gvACiHNI6SH8I6ajuJqwpJxHxCWZUw2WFY+omzkM5sJ5wyssBKT1ouMLGXTca4nj+Ny76NoGTk2Jw/+wl8CN9u4g5AQ0w7tIf0AYzdWEJeU+Ii7JnGqwrHhE3cxh8OA4T5PvOXzVNvZzBFcdMSAGxIAYCM4AbAD3qOMO3adzhpWCw5f4YkAMiAExMMaAjMMYQzouBsSAGDhCBmQcjlDpgiwGxIAYGGNAxmGMIR0XA2JADBwhAzIOR6h0QRYDYkAMjDEg4zDGkI6LATEgBo6QARmHI1S6IIsBMSAGxhio1jhgne6bMfA6LgbEgBgQA8MM1Gwc7g9DVq4YEANiQAyMMeDePmPsRKUcR4+Beys122cg/szkQpzbfvwAfwbPbT8sfIdjj5GWEwNiQAyIgZaBWnsOF8D3VV/LMALcn+THNJRh6LOktBgQA2Lg5KQ644DG/jUUy57A81TByH8Lbx/+4aFb6XHFxYAYEANi4DMDNRoHGoAzGAJ+w6HbvruF/BShTVSzTGosPrOimBgQA2LgyBmYNOeAxpRj9nTcDpvDNtweu6jPb0KeT5QJ/gnk628lfoF8flWJ7vwqKPcXshbP9xz2IuKSzHM0fZg6EXUzh5lD43Rv2Q3B3gPQ9wg5bHOCkE/dzLuPeFEGgvJFd+C0Sr4j4pLM5f6bIupmDpuHwonrdFt2u3oObYUvEDaGgeAQ5xM60xzbL2LZKOT5nbLNcah7OqfeGnUgCxVUPN9TsUfEJZmnavlw5SPqZg47uXC6jAMAPYAf+poaVwU9gfBsyD7NAb5kHchQTAO/J64QfM/AGBGXZJ6h6ANViaibOdRkwek1DveAqD9+T5A2nMTjXa+CB0pxMBh8n4Erk/jNaw6FcaLa5h2QLNKF5XuEzYi4JPOIUjMejqibOXRlwXljTFI0pJ4VPWx4V3WtHFxtxMlwOk6InyN/rMfCSXNa3sYhzm9hF2scWpyttFuD1fneeuWZByLikswzlX2AahF1M4eWnDhHjQMAWUO0qxH2GJA53DR1QBAtJ+c2HiDeDG8hvIU0jcXYqiOuUPqYlHuJeMkuO98rkRMRl2Re6WZY4LQRdTMHdjacNA6X8P8J/39zJG/r3Nyj7s6qaNg5LMR3Ex6bYWgr0GDYOwtt1mDA4bA78LYstOtFDJaOkbka35nhR8QlmTPfNDsuH1E3O+BsPbQkzv/GVWgPTmgcaJn+Df4/4Iccjcc2Z1bNhnq2ldsnnz0GOk56890FOpLxBmnP8NALlGsMAkK+FPczwj/B7+oJ8Rq5XG6+18IdEZdkXutu2P+8EXUzB/Whcf4rhKQ9+PfRN6STRnRo6MjybGJ6DvixOuwhvIYczxLPuYZRw4AyJl9zDaQ5af7T2AVzHoeMZrQ2ZG9lsrw1+V4FfkRcknmVW2GRk0bUzRzgOXGy5+BxbIg5vNN31nMYbaj7FSemuWR2siOx8C/h2eNgo8vG9VVC+ORzHqhCbr7XghkRl2Re627Y/7wRdTMHdRacXuPAFT42Zp+Cu40El4ay4V3L8Sl5cEwN1/0GfucS2rHjawm953lz8r2n6DurR8QlmXeqNOvBiLqZQ1gWnKPDSkSCBpaTupcIu43sEOdT+EP4R/BrOholDi11jteG51zEhy6zogiw5eR7NSYj4pLMq90Oe584om7mgM6F09tzICb2EvjOAFf+cAKa4V2kV22gSQw8jQGNBJek0jFd+wd6svB9Re+qvxFxSeZVb4m9Th5RN3MAHxyne+O9OWhURwyIATEgBuIwgIdu7uv2HOGpa1gpDjRJKgbEgBgQA0swIOOwBIs6hxgQA2KgMgZkHCpTqOCIATEgBpZgQMZhCRZ1DjEgBsRAZQzQOPyhxWRhZRAFRwyIATEgBpwM/NHK0Tj81iYstGMKxYAYEANi4LgY+NXgaljJmCg4xLIyz+6zBSOQaGJADERjQMYhgMZgHIr4RncAqiSiGBADCzEw5Q3phS6p03gZgFHgdiXNG+mIP7N6iHM7Eb4xfgbPvacsfIdjtb85DrhyYkAMrM2Aeg5rM7z/+S9wCn4SdcPBCPB1em4t0oUyDBsUKSEGxMAeDMg47EHe2lXR2HPHWfYE7INHzSWR/xaeGx+au2URhWJADIiBJRiQcViCxZXO0RqAM4TcFr3bEbe9HL+fbRPVLJMai5Uk0mnFgBg4FgYmzTmgAbJvOnBXVg51cJfWor5KFkFG780FLPxY0S/w/FgRt/FO3QXy+REQuvOrIMYv5C7+PuozKZn7jJSTjqibOewdGqd7V1YI9h6AvkfYfFwHIZ9UmXcf8SIMRAQZ59wUNdWJqCPJXO4dGFE3c9g8FE5cZ9qurG0FfkOh++oa4p8AkumN8fA5wJeoE0HGJXBGPkdEHUnmcu+4iLqZw2YunN5hpQcANfRRH66keQLhaThoLHK6CDK6+QGfv7sL9wqi7mkvq5RkRB1J5lLunutyRNTNdRTjOVlweo0D19X3x7wJyYaTeLzrVfBABhdBRjctBTfwbgwDBSPqSDIPKLKQrIi6mUNdFpw3ICkbeC6XvBySGo2UZxXMl0N1D5UXQcaUi1ZerjbixD4dJ/fPke/ufaEsVyo9mFKHF8rlWsxjl896H/WFk8x9RspJR9TNHPYy4OQil+ZFWi5lPYPnvMG2P6bl72q4PAYEl1jNRZCxAQ9l8ymAE/kvEX9Gjzj5p7FwOdThpBH1FsmF0VFCqmROyCgsGlE3cyg8NE62T2yPTpZ6z+HmHNQHrpNdRjTqbND5xM8lwOkcDhVi7yzspAX1+L6DLWHdWTbgwew6msGZZJ5B2oGqRNTNHGpWwclhpTE3ONzUVjKrZsMjY+da63gEGYm9scgIOYHPdxfoqNg3SI82+ChzC2Xt3QfWjeSi6CjlVDKnbJQVj6ibOQxmwznac0CDZMNJQ0NHlmcT03PA710ngowtSPYQXkPeZjipDTnX4DEM5PprT9m9CV3hBJC7+PuoD1sy9xkpJx1RN3PYy4nT03MgJjZeQ2Pc1nMYbdzmEDOxTgQZCYnLf+c4cp32OKiPp7h5nsNnNc4TwETRUQpJMqdslBWPqJs5DGbBOdpzaJG8Qvj1AKrbyOO+P/ZUOFDkYFkRZGQjPjg+CA77eydtEEcDAM/J66ElxRtlC05E0FGfPsncZ6ScdETdzGEvC06XcUCjxAbpMm3AEOcwx0P4R3PQLl0ngozAzD2FOLTUOfIIz7mID13mjgjKcs6Bw1Kn8BySitJrOIGsxd9Hfeolc5+RctIRdTOHvVw4vcNKxMReAlfZ3EHICWiGd5F2NWooewhXtIxUMjyNAY3Ex5YQpo/pAz1F62jLTSqZtxBTQHZE3cyh7eA43RvvzUGjOmJADIgBMRCHATyoTtt4Lw40SSoGxIAYEANLMOCac1jiQjqHGBADYkAMxGGAxuEPrbgWxpFekooBMSAGxMCSDPzRTkbj8FubsNCOKRQDYkAMiIHjYuBXg6thJWNCoRgQA2JADHQMyDh0VCgiBsSAGBADxoCMgzGhUAyIATEgBjoGprwE11VSRAxMZQDrp2+hjm3Bwhd6uCfUxguUSHN32vtTz63yYkAMLM+Aeg7Lc6ozDjPAt8LfofHnFhr8dsWLfjEZhj4jSouBfAyo55CP+2O7cvNJUxiAMwD/K7x92+IEedx0sNmWBXFuLtg4xLkPFY0K63APKQtpZI5pyxFAlxMDh2VAPYfD8n20V0Njzg0D2bizwb+Ef9cj4wJpfkt7w6EOh6C4J1UXIi7DsMGSEmJgeQZkHJbnVGccYICGAZ7bjnNYib2B94hzZ98ThK8RsMHvehNt/lsrwzQc5y3kxIAYOAADMg4HIPnYL9E28LYLLelojILx0h6n8eC3QfrftXiKcvZ9bZbZqGvnUCgGxMCyDEyac8Afk098dNyym0MA3MK7qO8JRJCRBHpcLViAg0NKj+G54yMbd84v3Gc+eWAIz14Fv6vNnkXqLpDPL2HRnV8Fh/+FDMXf+31WIsrcx+BJC6eHpell3Ft2QwHvcfrvEXII4AQh/+TM45+8CAMBOYqXkdx5XE1YPHhLLhNRFxFlnnMPCOey7S/47LbsZs+BDTvHezlJOOjaCvwoTWMYWAhxPu0xzXHi7GvTIUvzVNrKRBFPEC9KxkYox09NWFo9/O6APbkIeDqdXGlihYi6iCjzRLU0xYVzlfaXvfRmwQeNA1eQsIFnZtPNR9h3D5Cx8cJSW4ArTJ5ASTQc2+r2z7VWOoKMXuw1YTnBvbF6I+4ldka5iLqIKPMM1ZwI5/LtL1cT0h786J1zYIX+WDCVacNJPN71Knggg4sgo5eWmrCMYobx4AMKVyJ9Cc/hSk5M2zwDklldRF1ElHmOkoXzijXysHj7e2NMI/iT8s865vinzuYiyOglJxqWVl6uKOIiBTouVDhH/pSeJBc28CmwcYi/QiS7cWixtVJtDbLe+32pIsrcx+BJC+cGS6vcg6PGASLYhXf92T0GZAPNwokIMnohh8GCPyifWNgF5dvPzbAjwltI01hMWVnEFUlc6mp1XiJegguji4SsiDIn4rujwvmZqlXaX49x+CzC9tjN7YeKORJBRi9Z2bGgMedQEN8/4BLVdD6KBsPeS/Di4ZDlHXhbLtr1IrwnyFguuy5mYI8o8wyYJ8I5h7W2jsc4bF3FhHOY9bYhhT1E2atqBBm9AKNgYY+BjosR+H4CHf+M3Fl16pDQC9RpDAJCvgT3M8I/we/qrfJ6a7soukh5iChzKr83Lpwrt7+jb0gnf9Chrovl2cS0V7GLlosgoxdwICzsIbyGvM8Sz7mGSYYB5e0eaihCmhNrP3n5WrMcZDHjtCFje03Ly3rv9/FHlLmPwZMWzoalVe9BT8+BUvAPz2GEvrOew6QGoX+ShdIRZPRCjYKFS5n3cvyTw7+EZ++DjTFv+FfJn3+v8y9QOYouUqgRZU7l98aF84op8rC48xoHrh6x8eBUiNtIcNkh/9S5XQQZvRxFwMIn5sExXdwP38C7l9ZNKeslcMFyEXTRhxtR5j4GT1o4V2x/R4eVqCH8eTlheImw2xQNcT7hPYR/BJ/dRZDRS1IQLHxY4NBS53hPwHMu4kOXGTwSRBcbLEeUeQOAMyGc67a/3p4D1cVeAtejc1UJJ6AZ3kW6pIYggoygzeWKxsI/JjyNAY2E7bjKdI3fWihaF1vupogyb4GyM1s4d9Iz/yA33vsLqv8T/s/4Y//X/FOpphgQA2JADERmADbgb5D/HwhPOaz0WwvGwsjYJLsYEANiQAzMZ+BXq+qac7DCCsWAGBADYuA4GJBxOA49C6UYEANiYBIDMg6T6FJhMSAGxMBxMCDjcBx6FkoxIAbEwCQGZBwm0aXCYkAMiIHjYEDG4Tj0LJRiQAyIgUkMyDhMokuFxYAYEAPHwYCMw3HoWSjFgBgQA5MYkHGYRJcKiwExIAaOg4Epeyud4JVq25mVeyvxW8Hca6m0/eyLl9F7a0Xg24slLRcdF+Tn9uJfISx6H6noPKf3zK64cO5iZ/4xd88BCniPy/Bbv/ygyzPE+b1ffvXrbP7ll60ZQUYv4pqwpJgrwUWjUMI29Sm1G/FKeN7ANJQQzvXaXxoHPvnzZt/62T0o4Fsc546b3R79iPPPwbR9LhLRfC6CjF52asKSYq4FF3Cw18CHoyJdLTyPkSucq7S//HBQ0yOmceCTPxt4+6obotccv+87tDX3BfLvQUn8tkNuF0FGL0c1YUkx14orxVhC/Fh4Fs7l219+o6V54Kdx8DhWGOpZ2HwDj+d2EWT0clQTlhRzrbhSjCXEj4Vn4by628jD4u7G2BmdvYJdvY6xS+x9PIKMXpA1YUkxR8fVys/hVS7EeI80v45YnIvOs5dQ4dxgapX219NzsAvvmoDLPawUQcYNbe5I1IQlhRkd11M0SFyIse27xSnWnPHoPHu5E87PTK3S/nqMw2cRtsdubj9UzJEIMnrJqglLirlIXDAKtyAk59foOM5tw6lNRsCfInlegUfh3INUj3EYmmuwS5r15nsPOV0EGb381IQlxRwZ1y8wELZS7yFAvUyBFRaPzPMUKoXz8yKiVdrfUeOAP4UNJw11XSwv65NUBBm9d31NWFLMkXGZ7Ai/ASbe80XON5Bvk7WVk1mpK+L/mgo0Ny6cDXOr6nPUOLTK49rXswFFWs+Bx3O7CDJ6OaoJS4o5Oq6nAPOaDRO8/TFTfKXEo/Ps5VE4r5giD4s7r3HgJNzXA1e/jbwPiRUfKHKwrAgyesmoCUuKOSyu1hhw7sFe+qShKNWF5XkiocK5YvvrMg74Y7AbfYmQ3erGtX8Wjr8+arOyBhFk9BJUE5YUc3BcTc8ZGN7CM/4xxVZSPDjPbiqF82TV9nf0PYdEU+wlcKO9Owg5AcLwLtIfEJbiIsjo5aomLCnmkLh4n8NzSInvOpwgLHbeoSU7JM/pjeKMC6eTqKnFTr/77ru/oNI/4f+MG/6/pp5A5cWAGBADYqAOBmAD/gYk/0B4ymGl31pYFtaBUijEgBgQA2JgKgO/WgXXnIMVVigGxIAYEAPHwYCMw3HoWSjFgBgQA5MYkHGYRJcKiwExIAaOgwEZh+PQs1CKATEgBiYxIOMwiS4VFgPlMoAVJvxa4xklTOPlSizJSmZAxqFk7Ug2MTCNAb4U9RGG4XeEfHv42uZ0OPZm2ilV+lgZmPIS3LFyJNxiIAwDaPxPdwmL4/d3HdcxMWAMyDgYEwrFQAUMoPHnhoDcB43bjHe7JSPOrW+a3Q0Q50eLGof4PUR+gOdwFMtb+A7Hmg/NI0/uCBnQsNIRKl2Qq2WAw0j30Khzl85vEDZbfSRoLxDnZ043HMpxC4of0xBxGYYNlo4vIeNwfDoX4noZ4KaA9lEi7v1kO8ietPls8Ls80oB81km3H+fOs3Ji4ETGQTeBGKiHgf/pQflk6dYAnCHkBoLd7srtcW4/bhPVLJMaCzuFwiNjgHMOHGfkE8W1lQ19LnDTcGySjruysnvKXVq7cU0eyO0iyOjlqCYsKeaIuILI/AhysuH/Ep7/z7vGO/L5gSLOQzxBXn9H2Qvk2wdjzq1OlBCyF98uLcHlgXDyPmiGFLkrK7uR7+G/wsW3NvQ4xjLfI2y6rQj5dMG8+7vq4fjBXAQZvWTUhCXFHBFXRJlTzmuOH4tuDoUT1+E81XOEza6so/dOW4Ev2Nh45gni7LIyvTGGOXqylQpEkNELvSYsKeaIuCLKnHJec/xYdJMLp3cp6wPcZEMf9eHqhycQnoajG9/MdENGkNFLTU1YUswRcYWQGf8/vvi2uMN5d743sfgFp50whG6mQRosnQWn1zhwLXR/nJIobBiKx7teBQ9kcBFk9NJSE5YUc0RcIWQuvBFP74El4yF0swDgLDhvjAmOm86zcoETYNlcBBm95NSEJcUcEVcpMrdycEURF4LQcbL5HPmTeusof4Z6nGPk/5X/a65csoloJOO4lpMxgbO2S2PCeY7nxDlqHADACN51I3oMiIeLuWUiyOjFVhOWFHNEXNllRuPAp0bO6z1AvBnaRXgLaRqLqSuLuLqQQxSNQ5z7L4U0DpA7u26uWFz9NxtOj3HwoL/pKZS5TAQZvRTVhCXFHBHXajKj8eaTPt8/eIx4OudHg2HvJaT8jcW5ZPUjCplReTlWIfjx1XRTGC+r4PQYh13vP5hVs+5uLs4iyOjlpiYsKeaIuHLLbCsBueCD7yfQsSF4g/ScJ37OG96Bt/cCul4E8qK53Lo5FF/ZcI6+IY2b0IaThoaOLM8mpg9F2MZ1Isi4IfCORE1YUpgRcRUgM3sIryHHs8RzrmGOYaA6XqAuh6eaOQukf0bc/sM8HsZB7uLbpSXIzIlz1Di0AHkzsovbd9ZzmHuz9s+3TzqCjF58NWFJMUfElVtmLhff2/WNANJcXfjT3ifOe4LcujkU+iw4vcaBE1fcBrjvbiODKx7MivePHzIdQUYvHzVhSTFHxJVTZvbIB8eT8Z/r74+U8nwt3v5HXyLke0nfMkShV23+tfJBMnLq5pAUZcFJ4/CHFqWF10DjBuJY5SXC7oZEnN1Rfnnq0bUKGTIiyOilpSYsKeaIuDLLzLkBDi11DvJw/oFzER+6TGcE9WyIittzc6iKT6RhHeQvvl1agtwD4/yjycwJ6d/ahIV2rB+yl8ClcJzQ4gQ0w7tIT75JUW8tF0FGL/aasKSYI+LKIjMbBXgaAxoJrjKiY1rfWrjigr9ZdPP58geLHQrnr4bIvfGeVVAoBsSAGBADdTKAB49pG+/VSYNQiQExIAbEwDYGvBPS2+orXwyIATEgBipkQMahQqUKkhgQA2JgXwZkHPZlUPXFgBgQAxUyIONQoVIFSQyIATGwLwMyDvsyqPpiQAyIgQoZkHGoUKmCJAbEgBjYlwHPrqz7XkP1xYAYEAOLMYC1+LdwMtvOhy+HPUfexsu4SHPn2vuLXfQIT6SewxEqXZDFQHAG+Mb4OzT+3D6D37V40ccjw9BnZHqaPQfbU8nC6WdRDTEgBsTA4RjgtuOf4M9wyb/C23cvTpDH/d+aLX4Qf2YiIc49qmhUWIcbGlpII6PtSEBI67q9ldhzsD2VLLRCCsWAGBADxTGAxtwMAxv8S/h3PSEvkOY3KzYc6nEIivtVdaEMwwZFTHR7K9E4yIkBMSAGwjCABv0M/hd4DiuxN/Ae8eajRQj5nQr2BLreBOInyH9rZZiG47yF3A4GZBx2kKNDYkAMlMVA28DbDrUUrjEKJmV7nMaD35npPjHQHn+K0L69zTIbde0cCq8YmLRaCWTSStNxy25227iFd9ZPhFKY1EWQMZV3V7wmLCnOiLgkc6rBfHHogUNKj+G5eygbd84v3Gc+pWIIz14FP2bEnkXqLpBv37A4Tw9EiEP2g7a/7i27Idh7EPg9QnbbThBSMcyjYoowEJCjeBnJncfVhCXFGxGXZE41qHgOBg51D+I63Zbdrp5DW+ELhI1hIDmI00IzzbG97OuJIUvzJNHKRBFPEC9KxkYox09NWFK4EXFJ5lSD+ePQx+9rSIHznq5x3iXOmesedBkHAHwAv/GSSQuaqwL4TVoajqZb1+bnCCLI6OWlJiwp5oi4JHOqwczxkhvxFanJcg96J6RtyVgfvw0n8XhuF0FGL0c1YUkxR8QlmVMNBovDmPBNaQ6BR3ZZ7sEbY4w5if1y7DxrHo8goxd/TVhSzBFxSeZUg+vHW765oogLXui46OUc+bNGJVCPQ81nPFFUl/Me9PQcrOHfpaDcljmCjN77syYsKeaIuCRzqsEV42gE+XTMBSUvEX9GjzjnM2ksJjvU5zJWW5k0uX5BFbLdgx7j4OHppqdQ5jIRZPRSVBOWFHNEXJI51eCMOBpyPt3z/QMujU/nNmkw7L0E95lxjlsozMUoNuztrhu04Cr34OiwEsji6+nbnFk16wZuK7d2fgQZvRzUhCXFHBGXZE41uF6cPQQ6Lmzh+wl0bPA4XzDp6R/lOYrxNcL+Ow48Z0SX7R68ARI/gLGty7hwnBaYpA4NHVleVgsdQUYS6HE1YUnxRsQlmVMNrhpnD+E1+O42ytvjanxgTY0MeyVPcW5u6521nZqD6dD3IK5Ho9oYVhoHdsE41vfVDvJovUly31nPYZJ1759koXQEGb1Qa8KSYo6ISzKnGlwvzmXxe7u2DeOcBR9cOSFdgzvYPQjepr0EB3Zfwdur2ynZt5HgHiaf0sxM8QgyeqmpCUuKOSIuyZxqcJ04n+gHx83RtnwD371867182yaxJ7JEb8R72bXKZbkHXRPSIJrdjEsqytAjTsv8EP6R5eUMI8jo5acmLCnmiLgkc6rB1eJ88OTQUufAO4eGOBfBYe+jdrnuQc+EtCmGvQSuJriDkBPQDO8iXZLyIsgI2lyuJiwp4Ii4JHOqwYXjbPzgaQxoJGzHVab1EZ7PXB/8HnRvvPdZRsXEgBgQA2KgRgZgkLs5B9ewUo0kCJMYEANiQAxsZ0DGYTs3OiIGxIAYOFoGZByOVvUCLgbEgBjYzi/bvdIAAAUnSURBVICMw3ZudEQMiAExcLQMyDgcreoFXAyIATGwnQEZh+3c6IgYEANi4GgZkHE4WtULuBgQAyUzgGWlr+DvwdsedtfExbHJu9ZeO8mWjCkvwW05hbLFgBgQA2JgBQa4713T+MMI2OkfIN5tJ4L4fTuwdCjjsDSjOp8YEANiYBkGuJNsszcUQhqKMzMMCLmVUbNbhZXhJRG/h4Bvmp/Bc88qC9/h2KQ3zjWsBPbkxIAYEAOlMWCNPkI28Bxe6noMrawXCPkp1Q2Hctxqg1uSdCHikwwDTyjjsEGrEmJADIiB4hjg3MPG7rJI01CwwbcPJTVCI/8tfDpHwR7HLCfjMIs2VRIDYkAMrM8AGno27mlj31y0NQAcZuInE7rdsluJ+N1tm6hmmWv123I7g0lzDriIfdOBu7KyO8NdWov6ulIEGXdqJDlYE5YE1klEXJI51WBZ8Yi6mcDglyh7bedrYP4E/ws8P6va/yTqBfL5gSC686tg+q97V1ZcjF+L+x5hM+6FkNaIefcRL8JARJDRq6KasKSYI+KSzKkGy4pH1E1ZDG5KAz6n7craVuD+6t2ECOKfcFqmN8a8Ni91uFQEGb1s1IQlxRwRl2RONVhWPKJuymJwtzTeYaUHOM21rg3yOFv+BEqi4aCxyOkiyOjlpyYsKeaIuCRzqsGy4hF142IQ7envroITC+G8p94qXuPAtbP9cS1ew4aTeLzrVfBABhdBRi8tNWFJMUfEJZlTDZYVj6gbF4NTGnHXCWcUujFWB0J6Zro5aZLNRZDRS05NWFLMEXFJ5lSDZcUj6sYYbGXniiIu7KHj4p5z5E8afUF5vv/A1Uxsf9lOc+WSTUQjuZ8bNQ44vTX8uwT3GJD9JN1dO4KMuxF8PloTls+oYtxHqbyMR9RFRJn7vHvSIXGi8WZvh/O03AajGapHeAtpGoupK4u4WpRDa41D/BUiBzUO7aV3Bjd3Hi3jYAQZvUzVhCXFHBGXZE41WFa8KN2g8eaTPt8/eIx4OodLg2HvJUxhkEtWP6KCGZWXUyqPlfX0HC53nMSst3WPdhRd9VAEGb0E1IQlxRwRl2RONVhWPKJubGUnF/Dw/QQ6GrA3SM954uc88B14e/+s60Ugb283+oY0hLbhpKGhI8uziem9BZpzgggyenHVhCXFHBGXZE41WFY8om7AIHsIryH7s8RzrmGOYaBCXqAuh6eaOQukf0bc2mQe38uNGof27BSeXaK+s57DXHD98+2TjiCjF19NWFLMEXFJ5lSDZcUj6obL//d2fSOANFeL/rT3iZMTeI0DJzq+TupZ9DYinCG33oXl5wgjyOjlpSYsKeaIuCRzqsGy4tF0wxGWwXkQtKH9/ZF2Mt22uS8R8j2zbxmiAjfoW6wtdhkHXJBjW5cIOwCIs/vyEP4RfHYXQUYvSTVhSTFHxCWZUw2WFQ+oG84NcGipc8DA+QfORXzoMp0R1LMhKm7PzaEq9qQWc54JabsYewlcOsUJEE5AM7yL9GRQqLeWiyCjF3tNWFLMEXFJ5lSDZcXD6AZtJRtxGgMaCa4yomN68rcWrqqu++veeG9dMXR2MSAGxIAYyM0ADNW0jfdyC6zriwExIAbEwGEZcM05HFYkXU0MiAExIAZyMyDjkFsDur4YEANioEAGZBwKVIpEEgNiQAzkZiBdrfQRkxF9ebhUatFXsvsXUFoMiAExIAYOzwDadq6YOtt2ZRoHvpixbSlV1m0xtgmtfDEgBsSAGNibAduTafBE/w9kYJbSpSLjCQAAAABJRU5ErkJggg==",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\\\0 & e^{\\frac{i \\pi}{8}} & 0 & 0 & 0 & 0 & 0 & 0\\\\0 & 0 & e^{\\frac{i \\pi}{4}} & 0 & 0 & 0 & 0 & 0\\\\0 & 0 & 0 & e^{\\frac{3 i \\pi}{8}} & 0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0 & i & 0 & 0 & 0\\\\0 & 0 & 0 & 0 & 0 & e^{\\frac{5 i \\pi}{8}} & 0 & 0\\\\0 & 0 & 0 & 0 & 0 & 0 & e^{\\frac{3 i \\pi}{4}} & 0\\\\0 & 0 & 0 & 0 & 0 & 0 & 0 & e^{\\frac{7 i \\pi}{8}}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡1   0     0      0     0    0       0       0   ⎤\n",
       "⎢                                                ⎥\n",
       "⎢    ⅈ⋅π                                         ⎥\n",
       "⎢    ───                                         ⎥\n",
       "⎢     8                                          ⎥\n",
       "⎢0  ℯ      0      0     0    0       0       0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢          ⅈ⋅π                                   ⎥\n",
       "⎢          ───                                   ⎥\n",
       "⎢           4                                    ⎥\n",
       "⎢0   0    ℯ       0     0    0       0       0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢                3⋅ⅈ⋅π                           ⎥\n",
       "⎢                ─────                           ⎥\n",
       "⎢                  8                             ⎥\n",
       "⎢0   0     0    ℯ       0    0       0       0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢0   0     0      0     ⅈ    0       0       0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢                           5⋅ⅈ⋅π                ⎥\n",
       "⎢                           ─────                ⎥\n",
       "⎢                             8                  ⎥\n",
       "⎢0   0     0      0     0  ℯ         0       0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢                                   3⋅ⅈ⋅π        ⎥\n",
       "⎢                                   ─────        ⎥\n",
       "⎢                                     4          ⎥\n",
       "⎢0   0     0      0     0    0     ℯ         0   ⎥\n",
       "⎢                                                ⎥\n",
       "⎢                                           7⋅ⅈ⋅π⎥\n",
       "⎢                                           ─────⎥\n",
       "⎢                                             8  ⎥\n",
       "⎣0   0     0      0     0    0       0     ℯ     ⎦"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B_Q2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "id": "350b5a16-abbb-41cf-9e6d-65ea798c4fee",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = sy.Matrix(sy.BlockMatrix([[F_Q2, B_Q2 * F_Q2],\n",
    "                             [F_Q2, -B_Q2 * F_Q2]])) * (1/sy.sqrt(2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "id": "d8d28c56-3cca-47cc-a858-c4c7311800ee",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{array}{cccccccccccccccc}\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & - \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{i e^{\\frac{i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & - \\frac{e^{\\frac{i \\pi}{4}}}{4} & - \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{i e^{\\frac{i \\pi}{4}}}{4} & \\frac{i e^{\\frac{i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{5 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{- \\frac{7 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & - \\frac{e^{\\frac{i \\pi}{8}}}{4} & \\frac{e^{\\frac{i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{i \\pi}{8}}}{4} & \\frac{i e^{\\frac{i \\pi}{8}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{5 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{e^{\\frac{i \\pi}{4}}}{4} & - \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{i \\pi}{4}}}{4} & \\frac{i e^{\\frac{i \\pi}{4}}}{4} & \\frac{i e^{\\frac{i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{7 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{i \\pi}{8}}}{4} & - \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{3 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & \\frac{i}{4} & - \\frac{i}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{5 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{i \\pi}{8}}}{4} & - \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{5 i \\pi}{8}}}{4}\\\\\\frac{1}{4} & \\frac{1}{4} & - \\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{i}{4} & - \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{4}}}{4} & - \\frac{i e^{\\frac{3 i \\pi}{4}}}{4}\\\\\\frac{1}{4} & - \\frac{1}{4} & - \\frac{i}{4} & \\frac{i}{4} & \\frac{e^{- \\frac{i \\pi}{4}}}{4} & \\frac{e^{\\frac{3 i \\pi}{4}}}{4} & \\frac{e^{- \\frac{3 i \\pi}{4}}}{4} & \\frac{e^{\\frac{i \\pi}{4}}}{4} & - \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{e^{\\frac{7 i \\pi}{8}}}{4} & \\frac{i e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{i e^{\\frac{7 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{5 i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{3 i \\pi}{8}}}{4} & - \\frac{e^{\\frac{i \\pi}{8}}}{4} & - \\frac{e^{- \\frac{7 i \\pi}{8}}}{4}\\end{array}\\right]$"
      ],
      "text/plain": [
       "⎡1/4  1/4   1/4   1/4     1/4       1/4       1/4       1/4       1/4       1/ ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                          ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π       ⅈ ↪\n",
       "⎢                          ───     ───────    ─────     ─────      ───       ─ ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ      ℯ       ℯ          ℯ         ℯ          ℯ        -ℯ  ↪\n",
       "⎢1/4  -1/4   ─    ───     ────    ────────   ──────    ──────     ────     ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                  ⅈ⋅π       ⅈ ↪\n",
       "⎢                                                                  ───       ─ ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                          ⅈ         ⅈ        -ⅈ        -ⅈ        ℯ         ℯ  ↪\n",
       "⎢1/4  1/4   -1/4  -1/4     ─         ─        ───       ───       ────      ── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                         ─────     ─────      ───     ───────    ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ          ℯ       ℯ          ℯ        -ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────     ────    ────────   ──────   ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                  ⅈ         ⅈ ↪\n",
       "⎢1/4  1/4   1/4   1/4     -1/4      -1/4      -1/4      -1/4       ─         ─ ↪\n",
       "⎢                                                                  4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                        -3⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      3⋅ⅈ⋅π     5⋅ⅈ⋅π     5⋅ ↪\n",
       "⎢                        ───────     ───      ─────     ─────     ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ    ℯ           ℯ        ℯ         ℯ         ℯ        -ℯ   ↪\n",
       "⎢1/4  -1/4   ─    ───   ────────    ────     ──────    ──────    ──────   ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 3⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                                                                 ─────     ── ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                         -ⅈ        -ⅈ         ⅈ         ⅈ       ℯ         ℯ   ↪\n",
       "⎢1/4  1/4   -1/4  -1/4    ───       ───        ─         ─       ──────    ─── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         -ⅈ⋅π      3⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π      7⋅ⅈ⋅π     7⋅ ↪\n",
       "⎢                         ─────     ─────    ───────     ───      ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ        ℯ           ℯ        ℯ        -ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────   ────────    ────     ──────   ──── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢1/4  1/4   1/4   1/4     1/4       1/4       1/4       1/4       -1/4      -1 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                          ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π       ⅈ ↪\n",
       "⎢                          ───     ───────    ─────     ─────      ───       ─ ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ      ℯ       ℯ          ℯ         ℯ         -ℯ         ℯ  ↪\n",
       "⎢1/4  -1/4   ─    ───     ────    ────────   ──────    ──────    ──────     ── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                  ⅈ⋅π       ⅈ ↪\n",
       "⎢                                                                  ───       ─ ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                          ⅈ         ⅈ        -ⅈ        -ⅈ       -ℯ        -ℯ  ↪\n",
       "⎢1/4  1/4   -1/4  -1/4     ─         ─        ───       ───      ──────    ─── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         3⋅ⅈ⋅π     -ⅈ⋅π       ⅈ⋅π     -3⋅ⅈ⋅π     3⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                         ─────     ─────      ───     ───────    ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ          ℯ       ℯ         -ℯ         ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────     ────    ────────  ────────   ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 -ⅈ        -ⅈ ↪\n",
       "⎢1/4  1/4   1/4   1/4     -1/4      -1/4      -1/4      -1/4      ───       ── ↪\n",
       "⎢                                                                  4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                        -3⋅ⅈ⋅π      ⅈ⋅π      -ⅈ⋅π      3⋅ⅈ⋅π     5⋅ⅈ⋅π     5⋅ ↪\n",
       "⎢                        ───────     ───      ─────     ─────     ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢            ⅈ    -ⅈ    ℯ           ℯ        ℯ         ℯ        -ℯ         ℯ   ↪\n",
       "⎢1/4  -1/4   ─    ───   ────────    ────     ──────    ──────   ────────   ─── ↪\n",
       "⎢            4     4       4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                                                                 3⋅ⅈ⋅π     3⋅ ↪\n",
       "⎢                                                                 ─────     ── ↪\n",
       "⎢                                                                   4          ↪\n",
       "⎢                         -ⅈ        -ⅈ         ⅈ         ⅈ      -ℯ        -ℯ   ↪\n",
       "⎢1/4  1/4   -1/4  -1/4    ───       ───        ─         ─      ────────  ──── ↪\n",
       "⎢                          4         4         4         4         4         4 ↪\n",
       "⎢                                                                              ↪\n",
       "⎢                         -ⅈ⋅π      3⋅ⅈ⋅π    -3⋅ⅈ⋅π      ⅈ⋅π      7⋅ⅈ⋅π     7⋅ ↪\n",
       "⎢                         ─────     ─────    ───────     ───      ─────     ── ↪\n",
       "⎢                           4         4         4         4         8          ↪\n",
       "⎢           -ⅈ     ⅈ     ℯ         ℯ        ℯ           ℯ       -ℯ         ℯ   ↪\n",
       "⎢1/4  -1/4  ───    ─     ──────    ──────   ────────    ────    ────────   ─── ↪\n",
       "⎣            4     4       4         4         4         4         4         4 ↪\n",
       "\n",
       "↪ 4        1/4         1/4         1/4         1/4         1/4         1/4     ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⋅π         ⅈ⋅π         ⅈ⋅π       3⋅ⅈ⋅π      -5⋅ⅈ⋅π       7⋅ⅈ⋅π       -ⅈ⋅π    ↪\n",
       "↪ ──         ───         ───       ─────      ───────      ─────       ─────   ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪         ⅈ⋅ℯ        -ⅈ⋅ℯ         ℯ          ℯ            ℯ           ℯ        ↪\n",
       "↪ ───     ──────     ────────     ──────     ────────     ──────      ──────   ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⋅π        ⅈ⋅π         ⅈ⋅π          ⅈ⋅π         ⅈ⋅π         ⅈ⋅π         ⅈ⋅π   ↪\n",
       "↪ ──        ───         ───          ───         ───         ───         ───   ↪\n",
       "↪ 4          4           4            4           4           4           4    ↪\n",
       "↪         -ℯ          -ℯ          ⅈ⋅ℯ         ⅈ⋅ℯ        -ⅈ⋅ℯ        -ⅈ⋅ℯ      ↪\n",
       "↪ ──      ──────      ──────      ──────      ──────     ────────    ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π     -7⋅ⅈ⋅π        ⅈ⋅π        5⋅ⅈ⋅π      -3⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────     ───────       ───        ─────      ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪       -ⅈ⋅ℯ         ⅈ⋅ℯ         ℯ             ℯ          ℯ          ℯ         ↪\n",
       "↪ ────  ──────────   ────────    ────────      ────       ──────     ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪           ⅈ           ⅈ          -ⅈ          -ⅈ          -ⅈ          -ⅈ      ↪\n",
       "↪           ─           ─          ───         ───         ───         ───     ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       5⋅ⅈ⋅π       5⋅ⅈ⋅π      -ⅈ⋅π        7⋅ⅈ⋅π       3⋅ⅈ⋅π      -5⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────      ─────       ─────       ─────      ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪        ⅈ⋅ℯ        -ⅈ⋅ℯ          ℯ           ℯ           ℯ          ℯ         ↪\n",
       "↪ ────   ────────   ──────────    ──────      ──────      ──────     ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π      3⋅ⅈ⋅π       3⋅ⅈ⋅π        3⋅ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π  ↪\n",
       "↪ ───      ─────       ─────        ─────       ─────       ─────       ─────  ↪\n",
       "↪ 4          4           4            4           4           4           4    ↪\n",
       "↪        -ℯ          -ℯ         -ⅈ⋅ℯ        -ⅈ⋅ℯ         ⅈ⋅ℯ         ⅈ⋅ℯ       ↪\n",
       "↪ ───    ────────    ────────   ──────────  ──────────   ────────    ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       7⋅ⅈ⋅π       7⋅ⅈ⋅π      5⋅ⅈ⋅π      -3⋅ⅈ⋅π        ⅈ⋅π       -7⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────      ─────      ───────       ───       ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪       -ⅈ⋅ℯ         ⅈ⋅ℯ          ℯ          ℯ             ℯ         ℯ         ↪\n",
       "↪ ────  ──────────   ────────     ──────     ────────      ────      ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ /4       -1/4        -1/4        -1/4        -1/4        -1/4        -1/4    ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⋅π         ⅈ⋅π         ⅈ⋅π       3⋅ⅈ⋅π      -5⋅ⅈ⋅π       7⋅ⅈ⋅π       -ⅈ⋅π    ↪\n",
       "↪ ──         ───         ───       ─────      ───────      ─────       ─────   ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪        -ⅈ⋅ℯ         ⅈ⋅ℯ        -ℯ         -ℯ           -ℯ          -ℯ        ↪\n",
       "↪ ──     ────────     ──────     ────────   ──────────   ────────    ────────  ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⋅π        ⅈ⋅π         ⅈ⋅π          ⅈ⋅π         ⅈ⋅π         ⅈ⋅π         ⅈ⋅π   ↪\n",
       "↪ ──        ───         ───          ───         ───         ───         ───   ↪\n",
       "↪ 4          4           4            4           4           4           4    ↪\n",
       "↪          ℯ           ℯ         -ⅈ⋅ℯ        -ⅈ⋅ℯ         ⅈ⋅ℯ         ⅈ⋅ℯ      ↪\n",
       "↪ ───      ────        ────      ────────    ────────     ──────      ──────   ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π     -7⋅ⅈ⋅π        ⅈ⋅π        5⋅ⅈ⋅π      -3⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────     ───────       ───        ─────      ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪        ⅈ⋅ℯ        -ⅈ⋅ℯ        -ℯ            -ℯ         -ℯ         -ℯ         ↪\n",
       "↪ ───    ────────   ──────────  ──────────    ──────     ────────   ────────── ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪          -ⅈ          -ⅈ           ⅈ           ⅈ           ⅈ           ⅈ      ↪\n",
       "↪ ─        ───         ───          ─           ─           ─           ─      ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       5⋅ⅈ⋅π       5⋅ⅈ⋅π      -ⅈ⋅π        7⋅ⅈ⋅π       3⋅ⅈ⋅π      -5⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────      ─────       ─────       ─────      ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪       -ⅈ⋅ℯ         ⅈ⋅ℯ         -ℯ          -ℯ          -ℯ         -ℯ         ↪\n",
       "↪ ───   ──────────   ────────    ────────    ────────    ────────   ────────── ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π      3⋅ⅈ⋅π       3⋅ⅈ⋅π        3⋅ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π       3⋅ⅈ⋅π  ↪\n",
       "↪ ───      ─────       ─────        ─────       ─────       ─────       ─────  ↪\n",
       "↪ 4          4           4            4           4           4           4    ↪\n",
       "↪         ℯ           ℯ          ⅈ⋅ℯ         ⅈ⋅ℯ        -ⅈ⋅ℯ        -ⅈ⋅ℯ       ↪\n",
       "↪ ────    ──────      ──────     ────────    ────────   ──────────  ────────── ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "↪                                                                              ↪\n",
       "↪ ⅈ⋅π       7⋅ⅈ⋅π       7⋅ⅈ⋅π      5⋅ⅈ⋅π      -3⋅ⅈ⋅π        ⅈ⋅π       -7⋅ⅈ⋅π   ↪\n",
       "↪ ───       ─────       ─────      ─────      ───────       ───       ───────  ↪\n",
       "↪ 8           8           8          8           8           8           8     ↪\n",
       "↪        ⅈ⋅ℯ        -ⅈ⋅ℯ         -ℯ         -ℯ            -ℯ        -ℯ         ↪\n",
       "↪ ───    ────────   ──────────   ────────   ──────────    ──────    ────────── ↪\n",
       "↪           4           4           4           4           4           4      ↪\n",
       "\n",
       "↪ ⎤\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎥\n",
       "↪ ⎦"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "3217db7b-5d3c-4795-8067-94b9310088eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sy.simplify(A) == sy.simplify(F_Q)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a5b1900-2866-496f-9957-80f4cddbf5fd",
   "metadata": {},
   "source": [
    "## Lecture 19"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "id": "55781adf-028e-4b3b-820e-8f12c0924aa1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sy\n",
    "from sympy.physics.quantum.dagger import Dagger"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86026fa9-c440-4c82-ba6b-df91239febf4",
   "metadata": {},
   "source": [
    "We want to decompose a given unitary matrix $U$ as a product of two-level unitary matrices."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b069395f-6765-4c51-a84b-62239b055fbc",
   "metadata": {},
   "source": [
    "We start by finding a unitary matrix $U_1$ such that $U_1 U$ has the first column of the form\n",
    "$$\n",
    "\\begin{bmatrix}\n",
    "u'_{11} \\\\\n",
    "0 \\\\\n",
    "*\n",
    "\\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09782f23-3ca2-442b-a025-fc6246dcdd1f",
   "metadata": {},
   "source": [
    "If the first column of $U$ starts with $a$, $c$, then we can take\n",
    "$$\n",
    "U_1 = \\begin{bmatrix}\n",
    "a^* / r & c^* / r & 0 & \\cdots \\\\\n",
    "c / r & -a /r & 0 \\cdots \\\\\n",
    "0 & 0 & 1 & 0 & \\cdots \\\\\n",
    "0 & 0 & 0 & \\ddots\n",
    "\\end{bmatrix}\n",
    "$$\n",
    "where $r = \\sqrt{|a|^2 + |c|^2}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "e5941f9d-d0e6-4830-9ef5-3d77956a3db3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Fourier transform matrix of size 3\n",
    "U = sy.Matrix([[1, 1, 1],\n",
    "               [1, sy.exp(2 * sy.I * sy.pi/3), sy.exp(-2 * sy.I * sy.pi/3)],\n",
    "               [1, sy.exp(-2 * sy.I * sy.pi/3), sy.exp(2 * sy.I * sy.pi/3)]]) \\\n",
    "    * (1/sy.sqrt(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "a3792292-9828-43d8-812c-85d03ab3fa83",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\frac{\\sqrt{3}}{3}, \\  \\frac{\\sqrt{3}}{3}, \\  \\frac{\\sqrt{6}}{3}\\right)$"
      ],
      "text/plain": [
       "⎛√3  √3  √6⎞\n",
       "⎜──, ──, ──⎟\n",
       "⎝3   3   3 ⎠"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = U[0, 0]  # matrix index is 0-based in sympy\n",
    "c = U[1, 0]\n",
    "r = sy.sqrt(a * sy.conjugate(a) + c * sy.conjugate(c))\n",
    "a, c, r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "c872491d-efd8-49a5-987e-349b2875601d",
   "metadata": {},
   "outputs": [],
   "source": [
    "U1 = sy.Matrix([[sy.conjugate(a) / r, sy.conjugate(c) / r, 0],\n",
    "                [c / r, -a / r, 0],\n",
    "                [0, 0, 1]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "45016c79-cd34-435d-bbcd-e80ea7962d9f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{\\sqrt{6}}{3} & \\frac{\\sqrt{6}}{6} + \\frac{\\sqrt{6} e^{\\frac{2 i \\pi}{3}}}{6} & \\frac{\\sqrt{6}}{6} + \\frac{\\sqrt{6} e^{- \\frac{2 i \\pi}{3}}}{6}\\\\0 & \\frac{\\sqrt{6}}{6} - \\frac{\\sqrt{6} e^{\\frac{2 i \\pi}{3}}}{6} & \\frac{\\sqrt{6}}{6} - \\frac{\\sqrt{6} e^{- \\frac{2 i \\pi}{3}}}{6}\\\\\\frac{\\sqrt{3}}{3} & \\frac{\\sqrt{3} e^{- \\frac{2 i \\pi}{3}}}{3} & \\frac{\\sqrt{3} e^{\\frac{2 i \\pi}{3}}}{3}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡             2⋅ⅈ⋅π           -2⋅ⅈ⋅π ⎤\n",
       "⎢             ─────           ───────⎥\n",
       "⎢               3                3   ⎥\n",
       "⎢√6  √6   √6⋅ℯ       √6   √6⋅ℯ       ⎥\n",
       "⎢──  ── + ─────────  ── + ───────────⎥\n",
       "⎢3   6        6      6         6     ⎥\n",
       "⎢                                    ⎥\n",
       "⎢             2⋅ⅈ⋅π           -2⋅ⅈ⋅π ⎥\n",
       "⎢             ─────           ───────⎥\n",
       "⎢               3                3   ⎥\n",
       "⎢    √6   √6⋅ℯ       √6   √6⋅ℯ       ⎥\n",
       "⎢0   ── - ─────────  ── - ───────────⎥\n",
       "⎢    6        6      6         6     ⎥\n",
       "⎢                                    ⎥\n",
       "⎢         -2⋅ⅈ⋅π            2⋅ⅈ⋅π    ⎥\n",
       "⎢         ───────           ─────    ⎥\n",
       "⎢            3                3      ⎥\n",
       "⎢√3   √3⋅ℯ              √3⋅ℯ         ⎥\n",
       "⎢──   ───────────       ─────────    ⎥\n",
       "⎣3         3                3        ⎦"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U1 * U"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d74085d2-72e2-4281-a5eb-ccb0e588efea",
   "metadata": {},
   "source": [
    "Then find $U_2$ such that $U_2 U_1 U$ has the first column of the form\n",
    "$$\n",
    "\\begin{bmatrix}\n",
    "u''_{11} \\\\\n",
    "0 \\\\\n",
    "0 \\\\\n",
    "*\n",
    "\\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26b421b5-c472-493b-b671-cd808425ee46",
   "metadata": {},
   "source": [
    "We can take\n",
    "$$\n",
    "U_2 = \\begin{bmatrix}\n",
    "a^* / r & 0 & c^* / r & 0 & \\cdots \\\\\n",
    "0 & 1 & 0 & 0 & \\cdots \\\\\n",
    "c / r & 0 & -a /r & 0 & \\cdots \\\\\n",
    "0 & 0 & 0 & 1 & \\cdots\n",
    "\\end{bmatrix}\n",
    "$$\n",
    "with $a = u'_{11}$, $c = u'_{31}$, and $r = \\sqrt{|a|^2 + |c|^2}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "id": "ccd5da6d-3265-4973-809f-43019c782e15",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( \\frac{\\sqrt{6}}{3}, \\  \\frac{\\sqrt{3}}{3}, \\  1\\right)$"
      ],
      "text/plain": [
       "⎛√6  √3   ⎞\n",
       "⎜──, ──, 1⎟\n",
       "⎝3   3    ⎠"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Up = U1 * U\n",
    "a = Up[0, 0]\n",
    "c = Up[2, 0]\n",
    "r = sy.sqrt(a * sy.conjugate(a) + c * sy.conjugate(c))\n",
    "a, c, r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "477e3720-7872-48a9-9282-c85453dacf87",
   "metadata": {},
   "outputs": [],
   "source": [
    "U2 = sy.Matrix([[sy.conjugate(a) / r, 0, sy.conjugate(c) / r],\n",
    "                [0, 1, 0],\n",
    "                [c / r, 0, -a / r]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "id": "39480755-dfea-4559-a57d-a88b38a655f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}1 & \\frac{1}{3} + \\frac{e^{- \\frac{2 i \\pi}{3}}}{3} + \\frac{e^{\\frac{2 i \\pi}{3}}}{3} & \\frac{1}{3} + \\frac{e^{- \\frac{2 i \\pi}{3}}}{3} + \\frac{e^{\\frac{2 i \\pi}{3}}}{3}\\\\0 & \\frac{\\sqrt{6}}{6} - \\frac{\\sqrt{6} e^{\\frac{2 i \\pi}{3}}}{6} & \\frac{\\sqrt{6}}{6} - \\frac{\\sqrt{6} e^{- \\frac{2 i \\pi}{3}}}{6}\\\\0 & \\frac{\\sqrt{2}}{6} + \\frac{\\sqrt{2} e^{\\frac{2 i \\pi}{3}}}{6} - \\frac{\\sqrt{2} e^{- \\frac{2 i \\pi}{3}}}{3} & \\frac{\\sqrt{2}}{6} - \\frac{\\sqrt{2} e^{\\frac{2 i \\pi}{3}}}{3} + \\frac{\\sqrt{2} e^{- \\frac{2 i \\pi}{3}}}{6}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡           -2⋅ⅈ⋅π     2⋅ⅈ⋅π              -2⋅ⅈ⋅π     2⋅ⅈ⋅π    ⎤\n",
       "⎢           ───────    ─────              ───────    ─────    ⎥\n",
       "⎢              3         3                   3         3      ⎥\n",
       "⎢      1   ℯ          ℯ              1   ℯ          ℯ         ⎥\n",
       "⎢1     ─ + ──────── + ──────         ─ + ──────── + ──────    ⎥\n",
       "⎢      3      3         3            3      3         3       ⎥\n",
       "⎢                                                             ⎥\n",
       "⎢                   2⋅ⅈ⋅π                        -2⋅ⅈ⋅π       ⎥\n",
       "⎢                   ─────                        ───────      ⎥\n",
       "⎢                     3                             3         ⎥\n",
       "⎢          √6   √6⋅ℯ                    √6   √6⋅ℯ             ⎥\n",
       "⎢0         ── - ─────────               ── - ───────────      ⎥\n",
       "⎢          6        6                   6         6           ⎥\n",
       "⎢                                                             ⎥\n",
       "⎢            2⋅ⅈ⋅π       -2⋅ⅈ⋅π            2⋅ⅈ⋅π       -2⋅ⅈ⋅π ⎥\n",
       "⎢            ─────       ───────           ─────       ───────⎥\n",
       "⎢              3            3                3            3   ⎥\n",
       "⎢   √2   √2⋅ℯ        √2⋅ℯ         √2   √2⋅ℯ        √2⋅ℯ       ⎥\n",
       "⎢0  ── + ───────── - ───────────  ── - ───────── + ───────────⎥\n",
       "⎣   6        6            3       6        3            6     ⎦"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U2 * U1 * U"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "f48cbaee-bda1-4d08-9c96-818fea2eb12d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0\\\\0 & \\frac{\\sqrt{6}}{4} - \\frac{\\sqrt{2} i}{4} & \\frac{\\sqrt{6}}{4} + \\frac{\\sqrt{2} i}{4}\\\\0 & \\frac{\\sqrt{2}}{4} + \\frac{\\sqrt{6} i}{4} & \\frac{\\sqrt{2}}{4} - \\frac{\\sqrt{6} i}{4}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "⎡1      0          0    ⎤\n",
       "⎢                       ⎥\n",
       "⎢   √6   √2⋅ⅈ  √6   √2⋅ⅈ⎥\n",
       "⎢0  ── - ────  ── + ────⎥\n",
       "⎢   4     4    4     4  ⎥\n",
       "⎢                       ⎥\n",
       "⎢   √2   √6⋅ⅈ  √2   √6⋅ⅈ⎥\n",
       "⎢0  ── + ────  ── - ────⎥\n",
       "⎣   4     4    4     4  ⎦"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = (U2 * U1 * U)\n",
    "sy.Matrix([[A[j, k].rewrite(sy.sin).simplify()\n",
    "            for k in range(3)] for j in range(3)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2aa265ab-de2a-40dc-8e5b-767dbfbfaab9",
   "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.14.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
