{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Implementation of a Quantum Linear Solver"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Motivation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "<img src=\"images/DSC00764.JPG\" width=\"50%\" height=\"50%\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Sources \n",
    "\n",
    "[1] D.Dervovic, M. Herbster, P. Mountney,S. Severini, N. Usher, L. Wossnig [*Quantum linear systems algorithms: a primer*](https://arxiv.org/abs/1802.08227)\n",
    "\n",
    "[2] A. Harrow, A. Hassim, and S. Lloyd *Quantum algorithm for linear systems of equations*\n",
    "\n",
    "[3] C. Bravo-Prieto, R. LaRose, M. Cerezo, Y. Subasi, L. Cincio, and P. Coles \n",
    "*Variational Quantum Linear Solver: A Hybrid Algorithm for linear systems*\n",
    "\n",
    "[4] https://qiskit.org/textbook"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Outline\n",
    "\n",
    "> Quantum Algorithms \n",
    "\n",
    "> Qiskit\n",
    "\n",
    "> HHL\n",
    "\n",
    "> VQLS "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Quantum advantage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "Reality of Quantum Computers\n",
    "\n",
    "* NISQ\n",
    "\n",
    "* Simulation "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Quantum Algorithms "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "* Leveraging quantum information\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Gate Model with Unitary matrices\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "Most common gates\n",
    "\n",
    "* Hadamard, CNot\n",
    "\n",
    "* Pauli $X,Y,Z$\n",
    "\n",
    "* Rotations $R_x, R_y R_z$\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Qiskit "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'qiskit-terra': '0.12.0',\n",
       " 'qiskit-aer': '0.4.0',\n",
       " 'qiskit-ignis': '0.2.0',\n",
       " 'qiskit-ibmq-provider': '0.4.6',\n",
       " 'qiskit-aqua': '0.6.4',\n",
       " 'qiskit': '0.15.0'}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
    "from qiskit import IBMQ, Aer, execute, circuit\n",
    "from qiskit.providers.ibmq import least_busy\n",
    "from qiskit.providers.aer import noise\n",
    "\n",
    "# HHL \n",
    "from qiskit.aqua import run_algorithm\n",
    "from qiskit.quantum_info import state_fidelity\n",
    "from qiskit.aqua.algorithms.classical import ExactLSsolver\n",
    "\n",
    "#Visualize\n",
    "import matplotlib.pyplot as plt \n",
    "from qiskit.tools.visualization import plot_histogram\n",
    "from qiskit.tools.visualization import plot_bloch_vector\n",
    "\n",
    "import math\n",
    "import random\n",
    "import numpy as np\n",
    "from scipy.optimize import minimize\n",
    "\n",
    "qiskit.__qiskit_version__\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Four Elements Earth - Air - Water - Fire\n",
    "\n",
    "* Compile\n",
    "\n",
    "* OpenQasm \n",
    "\n",
    "* Backend "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Gateset\n",
    "\n",
    "* $U_1, U_2, U_3$ and Cnot\n",
    "\n",
    "Where \n",
    "\n",
    "$U_1(\\lambda) = \\begin{bmatrix}\n",
    "        1 & 0 \\\\\n",
    "        0 & e^{i\\lambda} \n",
    "        \\end{bmatrix} $\n",
    "\n",
    "$U_2(\\theta,\\lambda) = \\frac{1}{\\sqrt{2}}\\begin{bmatrix}\n",
    "        1 & -e^{i\\lambda} \\\\\n",
    "        e^{i\\theta} & e^{i(\\lambda+\\theta)} \n",
    "        \\end{bmatrix} $\n",
    "        \n",
    "$U_3(\\phi,\\theta,\\lambda) = \\begin{bmatrix}\n",
    "        cos(\\frac{\\theta}{2}) & -e^{i\\lambda}sin(\\frac{\\theta}{2}) \\\\\n",
    "        e^{i\\theta}sin(\\frac{\\theta}{2}) & e^{i(\\lambda+\\theta)} \n",
    "        \\end{bmatrix} $\n",
    "        \n",
    "      "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Simulations\n",
    "\n",
    "* Perfect \n",
    "\n",
    "* Noise "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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g4+PT4XXvby8UFhYiNu3b1s076ylay36/kRERGT7lsyMNHpd6/74ZMU++ugjAMCSJUus/pMRERERkblV/eAreqq0tDQ0b94c7dpV/uT5MmXf3fm0mcY7d+7Azc3N7PnKM+WThbls23MQWdkXMHPKaJ7KJqJKPXxUjPsPHqJ+XVfRUUySf/0WGnlY/ne3Od0tvAel0g61nWuJjmISW6z1jYI7qOtaGw72NbvNqtlHZyEFBQW4e/cugoMrv3vsSWXXQp47d67C+leuXEFhYSG6dLH84yxEns7+35WbhO2biIiIjMfT2RZWdhnp1atXDa4bGvr4u19TU1MrvHbgwAG9dYiIiIhsBW+sqSYfHx/k5OQgNTUVffv21Xvt7NmzaNPm8ddNlZSUoE2bNrh06dJTHzZ+9uxZNG/eXOpDsJhrNwqw/LNE9OwcaFVfA0ZERETmwyaymrZvLJRVHwAAAZJJREFU345Ro0ZBqVQiPDwcPj4+uHr1Ko4cOYK2bdti586dunUPHTqEAQMGoFatWoiIiECdOnWQnJyM33//HcuWLbPoF9qLwGshiYiIaj42kc/gwIED+PDDD5GZmYkHDx6gYcOG6NKlC2bMmIGePXvqrfuf//wH8+bNw5EjR1BcXIzAwEDExMRg1KhRgtJbRmlpKTbtTEMD93qchSQiIqrB2ESSRZSWllr9A3iJiIio+thEEhEREZHJOFVERERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQmYxNJRERERCZjE0lEREREJmMTSUREREQm+/95wm3muFYvygAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 851.228x385.28 with 1 Axes>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Bernstein-Vazirani Algorithm\n",
    "nQubits = 5  # number of qubits needed \n",
    "s = 22       # Secret number\n",
    "\n",
    "\n",
    "qr = QuantumRegister(nQubits)\n",
    "# Classical bits\n",
    "cr = ClassicalRegister(nQubits)\n",
    "\n",
    "bvCircuit = QuantumCircuit(qr, cr)\n",
    "barriers = True\n",
    "\n",
    "# Apply Hadamard gates \n",
    "for i in range(nQubits):\n",
    "    bvCircuit.h(qr[i])\n",
    "    \n",
    "# Apply barrier \n",
    "if barriers:\n",
    "    bvCircuit.barrier()\n",
    "\n",
    "# Oracle\n",
    "for i in range(nQubits):\n",
    "    if (s & (1 << i)):\n",
    "        bvCircuit.z(qr[i])\n",
    "    else:\n",
    "        bvCircuit.iden(qr[i])\n",
    "        \n",
    "# Apply barrier \n",
    "if barriers:\n",
    "    bvCircuit.barrier()\n",
    "\n",
    "#Apply Hadamard gates after querying the oracle\n",
    "for i in range(nQubits):\n",
    "    bvCircuit.h(qr[i])\n",
    "    \n",
    "# Apply barrier \n",
    "if barriers:\n",
    "    bvCircuit.barrier()\n",
    "\n",
    "# Measurement\n",
    "bvCircuit.measure(qr, cr)\n",
    "bvCircuit.draw(output='mpl')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# use local simulator\n",
    "backend = Aer.get_backend('qasm_simulator')\n",
    "shots = 1024\n",
    "results = execute(bvCircuit, backend=backend, shots=shots).result()\n",
    "answer = results.get_counts()\n",
    "plot_histogram(answer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\sigag\\Anaconda3\\envs\\quantum\\lib\\site-packages\\qiskit\\providers\\aer\\noise\\device\\basic_device_model.py:112: DeprecationWarning: This function is been deprecated and moved to a method of the`NoiseModel` class. For equivalent functionality use `NoiseModel.from_backend(properties, **kwargs).\n",
      "  DeprecationWarning)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Use noise \n",
    "IBMQ.load_account()\n",
    "provider = IBMQ.get_provider(group='open')\n",
    "device = provider.get_backend('ibmq_16_melbourne')\n",
    "properties = device.properties()\n",
    "\n",
    "coupling_map = device.configuration().coupling_map\n",
    "noise_model = noise.device.basic_device_noise_model(properties)\n",
    "basis_gates = noise_model.basis_gates\n",
    "\n",
    "noise_results= execute(bvCircuit, backend,\n",
    "                  coupling_map=coupling_map,\n",
    "                  noise_model=noise_model,\n",
    "                  basis_gates=basis_gates).result()\n",
    "\n",
    "noiseanswer = noise_results.get_counts(bvCircuit)\n",
    "\n",
    "\n",
    "plot_histogram(noiseanswer)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Quantum Linear Solver"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Quantum Formulation of the linear solver\n",
    "\n",
    "> Let A be an $N \\times N$ Hermitian matrix with a unit determinant. Let b and x be N-dimentional vectors such that $x:=A^{-1}b$. Let the quantum state on $\\lceil log(N)\\rceil$ qubits |b> be given by $$ \\frac{\\sum_i b_i |i>}{|| \\sum_i b_i |i> ||_2} $$ and for |x> by $$ \\frac{\\sum_i x_i |i>}{|| \\sum_i x_i |i> ||_2} $$\n",
    "where $b_i, x_i$ are the i-th components of b and x respectively. Given A and |b>, output a state $|\\tilde{x}>$ such that $||(|\\tilde{x}> - |x>) ||_2 \\leq \\epsilon $, with some probability larger than 1/2.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## HHL\n",
    "\n",
    "<img src=\"images/HHLCircuit.png\" width=\"80%\" height=\"80%\" />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Hamiltonian Simulation\n",
    "\n",
    "* Turning A into a Unitary operator $ e^{iAt} $\n",
    "\n",
    "* ~$ O(log(N)s^2 t) $"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "### Phase Estimation\n",
    "* Quantum Fourier transform\n",
    "\n",
    "* Requires n extra control qubits\n",
    "\n",
    "* Estimates the eigenvalues of A"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Rotation\n",
    "* Ancilla qubit dependent on the eigenvalues\n",
    "\n",
    "* Needs to be measured |1>  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "### Uncompute\n",
    "\n",
    "* Use the inverses to uncompute C and B \n",
    "\n",
    "* B now contains $|x>$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Improvements and variations\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "<img src=\"images/Evolution.png\" width=\"50%\" height=\"50%\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "params = {\n",
    "    'problem': {\n",
    "        'name': 'linear_system'\n",
    "    },\n",
    "    'algorithm': {\n",
    "        'name': 'HHL'\n",
    "    },\n",
    "    'eigs': {\n",
    "        'expansion_mode': 'suzuki',\n",
    "        'expansion_order': 2,\n",
    "        'name': 'EigsQPE',\n",
    "        'num_ancillae': 3,\n",
    "        'num_time_slices': 50\n",
    "    },\n",
    "    'reciprocal': {\n",
    "        'name': 'Lookup'\n",
    "    },\n",
    "    'backend': {\n",
    "        'provider': 'qiskit.BasicAer',\n",
    "        'name': 'statevector_simulator'\n",
    "    }\n",
    "}\n",
    "\n",
    "def fidelity(hhl, ref):\n",
    "    solution_hhl_normed = hhl / np.linalg.norm(hhl)\n",
    "    solution_ref_normed = ref / np.linalg.norm(ref)\n",
    "    fidelity = state_fidelity(solution_hhl_normed, solution_ref_normed)\n",
    "    print(\"fidelity %f\" % fidelity)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "matrix = [[1, 0], [0, 2]]\n",
    "vector = [1, 4]\n",
    "params['input'] = {\n",
    "    'name': 'LinearSystemInput',\n",
    "    'matrix': matrix,\n",
    "    'vector': vector\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\sigag\\Anaconda3\\envs\\quantum\\lib\\site-packages\\qiskit\\aqua\\qiskit_aqua.py:119: DeprecationWarning: Declarative API will be removed next Aqua release. Please construct classes and call appropriate methods.\n",
      "  warnings.warn(aqua_globals.CONFIG_DEPRECATION_MSG, DeprecationWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "solution  [1.05859-0.j 1.99245-0.j]\n",
      "classical solution  [1. 2.]\n",
      "probability 0.024630\n",
      "fidelity 0.999389\n"
     ]
    }
   ],
   "source": [
    "hhl_output = run_algorithm(params)\n",
    "print(\"solution \", np.round(hhl_output['solution'], 5))\n",
    "\n",
    "result_ref = ExactLSsolver(matrix, vector).run()\n",
    "print(\"classical solution \", np.round(result_ref['solution'], 5))\n",
    "\n",
    "print(\"probability %f\" % hhl_output['probability_result'])\n",
    "fidelity(hhl_output['solution'], result_ref['solution'])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\sigag\\Anaconda3\\envs\\quantum\\lib\\site-packages\\qiskit\\aqua\\qiskit_aqua.py:119: DeprecationWarning: Declarative API will be removed next Aqua release. Please construct classes and call appropriate methods.\n",
      "  warnings.warn(aqua_globals.CONFIG_DEPRECATION_MSG, DeprecationWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "solution  [0.84664+0.j 2.01762+0.j]\n",
      "classical solution  [1. 2.]\n",
      "probability 0.361437\n",
      "fidelity 0.995605\n",
      "circuit_width 7\n",
      "circuit_depth 129\n"
     ]
    }
   ],
   "source": [
    "params2 = params\n",
    "params2['reciprocal'] = {\n",
    "    'scale': 0.5\n",
    "}\n",
    "\n",
    "hhl_output2 = run_algorithm(params2)\n",
    "print(\"solution \", np.round(hhl_output2['solution'], 5))\n",
    "\n",
    "result_ref2 = ExactLSsolver(matrix, vector).run()\n",
    "print(\"classical solution \", np.round(result_ref2['solution'], 5))\n",
    "\n",
    "print(\"probability %f\" % hhl_output2['probability_result'])\n",
    "fidelity(hhl_output2['solution'], result_ref['solution'])\n",
    "\n",
    "print(\"circuit_width\", hhl_output2['circuit_info']['width'])\n",
    "print(\"circuit_depth\", hhl_output2['circuit_info']['depth'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Hybrid Algorithms \n",
    "* Both Quantum and Classical\n",
    "\n",
    "* Desegined wiht NISQ in mind\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### VQLS\n",
    "\n",
    "<img src=\"images\\VQLSCircuit.png\" width=\"80%\" height=\"80%\" />\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def apply_fixed_ansatz(qubits, parameters):\n",
    "    for iz in range(0, len(qubits)):\n",
    "        circ.ry(parameters[0][iz], qubits[iz])\n",
    "\n",
    "    circ.cz(qubits[0], qubits[1])\n",
    "    circ.cz(qubits[2], qubits[0])\n",
    "\n",
    "    for iz in range(0, len(qubits)):\n",
    "        circ.ry(parameters[1][iz], qubits[iz])\n",
    "\n",
    "    circ.cz(qubits[1], qubits[2])\n",
    "    circ.cz(qubits[2], qubits[0])\n",
    "\n",
    "    for iz in range(0, len(qubits)):\n",
    "        circ.ry(parameters[2][iz], qubits[iz])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "def had_test(gate_type, qubits, ancilla_index, parameters):\n",
    "    # Creates the Hadamard test\n",
    "    circ.h(ancilla_index)\n",
    "\n",
    "    apply_fixed_ansatz(qubits, parameters)\n",
    "\n",
    "    for ie in range(0, len(gate_type[0])):\n",
    "        if (gate_type[0][ie] == 1):\n",
    "            circ.cz(ancilla_index, qubits[ie])\n",
    "\n",
    "    for ie in range(0, len(gate_type[1])):\n",
    "        if (gate_type[1][ie] == 1):\n",
    "            circ.cz(ancilla_index, qubits[ie])\n",
    "\n",
    "    circ.h(ancilla_index)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "def control_fixed_ansatz(qubits, parameters, ancilla, reg):\n",
    "\n",
    "    for i in range(0, len(qubits)):\n",
    "        circ.cry(parameters[0][i], qiskit.circuit.Qubit(reg, ancilla),\n",
    "                 qiskit.circuit.Qubit(reg, qubits[i]))\n",
    "\n",
    "    circ.ccx(ancilla, qubits[1], 4)\n",
    "    circ.cz(qubits[0], 4)\n",
    "    circ.ccx(ancilla, qubits[1], 4)\n",
    "\n",
    "    circ.ccx(ancilla, qubits[0], 4)\n",
    "    circ.cz(qubits[2], 4)\n",
    "    circ.ccx(ancilla, qubits[0], 4)\n",
    "\n",
    "    for i in range(0, len(qubits)):\n",
    "        circ.cry(parameters[1][i], qiskit.circuit.Qubit(reg, ancilla),\n",
    "                 qiskit.circuit.Qubit(reg, qubits[i]))\n",
    "\n",
    "    circ.ccx(ancilla, qubits[2], 4)\n",
    "    circ.cz(qubits[1], 4)\n",
    "    circ.ccx(ancilla, qubits[2], 4)\n",
    "\n",
    "    circ.ccx(ancilla, qubits[0], 4)\n",
    "    circ.cz(qubits[2], 4)\n",
    "    circ.ccx(ancilla, qubits[0], 4)\n",
    "\n",
    "    for i in range(0, len(qubits)):\n",
    "        circ.cry(parameters[2][i], qiskit.circuit.Qubit(reg, ancilla),\n",
    "                 qiskit.circuit.Qubit(reg, qubits[i]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def control_b(ancilla, qubits):\n",
    "    for ia in qubits:\n",
    "        circ.ch(ancilla, ia)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "def special_had_test(gate_type, qubits, ancilla_index, parameters, reg):\n",
    "\n",
    "    circ.h(ancilla_index)\n",
    "\n",
    "    control_fixed_ansatz(qubits, parameters, ancilla_index, reg)\n",
    "\n",
    "    for ty in range(0, len(gate_type)):\n",
    "        if (gate_type[ty] == 1):\n",
    "            circ.cz(ancilla_index, qubits[ty])\n",
    "\n",
    "    control_b(ancilla_index, qubits)\n",
    "\n",
    "    circ.h(ancilla_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "def calculate_cost_function(parameters):\n",
    "    global opt\n",
    "\n",
    "    overall_sum_1 = 0\n",
    "    \n",
    "    parameters = [parameters[0:3], parameters[3:6], parameters[6:9]]\n",
    "\n",
    "    for i in range(0, len(gate_set)):\n",
    "        for j in range(0, len(gate_set)):\n",
    "\n",
    "            global circ\n",
    "\n",
    "            qctl = QuantumRegister(5)\n",
    "            qc = ClassicalRegister(5)\n",
    "            circ = QuantumCircuit(qctl, qc)\n",
    "\n",
    "            backend = Aer.get_backend('statevector_simulator')\n",
    "            \n",
    "            multiply = coefficient_set[i]*coefficient_set[j]\n",
    "\n",
    "            had_test([gate_set[i], gate_set[j]], [1, 2, 3], 0, parameters)\n",
    "\n",
    "            job = execute(circ, backend)\n",
    "\n",
    "            result = job.result()\n",
    "            outputstate = np.real(result.get_statevector(circ, decimals=100))\n",
    "            o = outputstate\n",
    "\n",
    "            m_sum = 0\n",
    "            for l in range (0, len(o)):\n",
    "                if (l%2 == 1):\n",
    "                    n = o[l]**2\n",
    "                    m_sum+=n\n",
    "\n",
    "            overall_sum_1+=multiply*(1-(2*m_sum))\n",
    "\n",
    "    overall_sum_2 = 0\n",
    "\n",
    "    for i in range(0, len(gate_set)):\n",
    "        for j in range(0, len(gate_set)):\n",
    "\n",
    "            multiply = coefficient_set[i]*coefficient_set[j]\n",
    "            mult = 1\n",
    "\n",
    "            for extra in range(0, 2):\n",
    "\n",
    "                qctl = QuantumRegister(5)\n",
    "                qc = ClassicalRegister(5)\n",
    "                circ = QuantumCircuit(qctl, qc)\n",
    "\n",
    "                backend = Aer.get_backend('statevector_simulator')\n",
    "\n",
    "                if (extra == 0):\n",
    "                    special_had_test(gate_set[i], [1, 2, 3], 0, parameters, qctl)\n",
    "                if (extra == 1):\n",
    "                    special_had_test(gate_set[j], [1, 2, 3], 0, parameters, qctl)\n",
    "\n",
    "                job = execute(circ, backend)\n",
    "\n",
    "                result = job.result()\n",
    "                outputstate = np.real(result.get_statevector(circ, decimals=100))\n",
    "                o = outputstate\n",
    "\n",
    "                m_sum = 0\n",
    "                for l in range (0, len(o)):\n",
    "                    if (l%2 == 1):\n",
    "                        n = o[l]**2\n",
    "                        m_sum+=n\n",
    "                mult = mult*(1-(2*m_sum))\n",
    "\n",
    "            overall_sum_2+=multiply*mult\n",
    "            \n",
    "    print(1-float(overall_sum_2/overall_sum_1))\n",
    "\n",
    "    return 1-float(overall_sum_2/overall_sum_1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "The problem is $$ A = \\alpha_1 \\mathbb{Z} + \\alpha_2 \\mathbb{I} $$ $$ b = \\begin{bmatrix}\n",
    "        \\frac{1}{\\sqrt{8}} \\\\\n",
    "        \\cdots \\\\\n",
    "        \\frac{1}{\\sqrt{8}}\n",
    "        \\end{bmatrix}  $$ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9889759175732641\n",
      "0.9984515010031692\n",
      "0.9941961555905245\n",
      "0.7962256723668557\n",
      "0.7683322520541489\n",
      "0.7554331064406511\n",
      "0.7440202216776846\n",
      "0.5715702194434831\n",
      "0.6217323263729735\n",
      "0.591788596885295\n",
      "0.5764212965342479\n",
      "0.6066163602743924\n",
      "0.4640735501687303\n",
      "0.5014852564327783\n",
      "0.45066834911979403\n",
      "0.5608640795676592\n",
      "0.5051130270442901\n",
      "0.4955050569401631\n",
      "0.49662206240177587\n",
      "0.48116385372945636\n",
      "0.4245320497812296\n",
      "0.45324095755279303\n",
      "0.5278716142128606\n",
      "0.4561708227588923\n",
      "0.39401171987738814\n",
      "0.3695447900611939\n",
      "0.3842709697808988\n",
      "0.3737849176747825\n",
      "0.3696828996388364\n",
      "0.3822230530808529\n",
      "0.3863180843188695\n",
      "0.3799493780309503\n",
      "0.3521844490392141\n",
      "0.3575829357595032\n",
      "0.35179963497753675\n",
      "0.3695181143783566\n",
      "0.3672546675197844\n",
      "0.31239337518581245\n",
      "0.322920713486611\n",
      "0.31870263306673663\n",
      "0.30276225280431623\n",
      "0.29657771641567887\n",
      "0.2527173834365227\n",
      "0.1989617733132364\n",
      "0.18140550653719179\n",
      "0.3251723839924441\n",
      "0.23156670946970248\n",
      "0.3553589730833254\n",
      "0.2112665623929041\n",
      "0.2488083394205306\n",
      "0.1816457780556724\n",
      "0.22987901865814797\n",
      "0.21697752616087485\n",
      "0.08160720129615784\n",
      "0.1512719552304982\n",
      "0.2019214790555227\n",
      "0.19133205559581146\n",
      "0.03951271892171393\n",
      "0.06292873784739961\n",
      "0.07776820205281276\n",
      "0.056428417888647275\n",
      "0.06065937605619798\n",
      "0.045024356727531134\n",
      "0.12046609027396538\n",
      "0.04885010598676409\n",
      "0.08900337510262235\n",
      "0.05159164113215131\n",
      "0.035832715853342356\n",
      "0.04009304758213805\n",
      "0.025912388261197572\n",
      "0.029230540816498674\n",
      "0.02508592143126953\n",
      "0.02504544774487949\n",
      "0.026237861599294643\n",
      "0.016097404557340544\n",
      "0.014252761846747397\n",
      "0.011163322602730341\n",
      "0.014351853384833135\n",
      "0.011892210204530684\n",
      "0.023480363822280026\n",
      "0.013319256767773902\n",
      "0.011032844487760651\n",
      "0.011411303782623672\n",
      "0.012408642470552511\n",
      "0.013361348518754257\n",
      "0.012719782210880881\n",
      "0.009152309393913538\n",
      "0.009124243233920026\n",
      "0.009112621874199367\n",
      "0.012535004243010683\n",
      "0.009543125160681343\n",
      "0.008481758670231043\n",
      "0.007964702567977766\n",
      "0.009951651312102072\n",
      "0.007645516382548956\n",
      "0.006571760911464275\n",
      "0.011829494352708303\n",
      "0.00915909118170144\n",
      "0.0065299604630797425\n",
      "0.006802151702324899\n",
      "0.006855861375200667\n",
      "0.006531203592778589\n",
      "0.00709727176103625\n",
      "0.006505779061771189\n",
      "0.007237651713594806\n",
      "0.006369533758857959\n",
      "0.006147856616633418\n",
      "0.00669347144210497\n",
      "0.0058232681016213705\n",
      "0.005449851829838259\n",
      "0.004988385399137263\n",
      "0.005287521407351892\n",
      "0.004794481327912936\n",
      "0.004717532785580181\n",
      "0.004796084555451663\n",
      "0.004390370107143271\n",
      "0.0048509027947511996\n",
      "0.0048900390202871735\n",
      "0.004294156816097683\n",
      "0.00424508243709687\n",
      "0.005028130349823745\n",
      "0.004179589960530805\n",
      "0.004846010392390854\n",
      "0.0041635830747788205\n",
      "0.003922963991466744\n",
      "0.004688467997058465\n",
      "0.004086971187056143\n",
      "0.004475494403551217\n",
      "0.004286035411222522\n",
      "0.0039013972698591637\n",
      "0.003911474558110251\n",
      "0.004002540053318571\n",
      "0.003890179138127836\n",
      "0.004181874365885796\n",
      "0.0038660517377951953\n",
      "0.0035440128353283473\n",
      "0.0037168152569568846\n",
      "0.0034915579626847437\n",
      "0.00344884182816918\n",
      "0.0034537783348733697\n",
      "0.0034201362819988868\n",
      "0.0033070012745620714\n",
      "0.0033038161953125034\n",
      "0.0032921804476883088\n",
      "0.00329366029638134\n",
      "0.0033486493860021005\n",
      "0.003245992074624948\n",
      "0.0031233915545592073\n",
      "0.0031277138581854436\n",
      "0.0031264600377813867\n",
      "0.0031051206676491194\n",
      "0.003190125956444634\n",
      "0.00294633698214386\n",
      "0.0028666755195551064\n",
      "0.0027981649914513573\n",
      "0.002734281284566653\n",
      "0.0027287377444159544\n",
      "0.0027406485490993893\n",
      "0.0026501963828013952\n",
      "0.0025298451309253567\n",
      "0.0023976027704553093\n",
      "0.0022724231077434487\n",
      "0.0021802164335545937\n",
      "0.0020815540819723033\n",
      "0.001989713036606\n",
      "0.0018995091750780846\n",
      "0.0018453374414021395\n",
      "0.0018060697246821134\n",
      "0.0018006539262667154\n",
      "0.0018071677587647716\n",
      "0.0018595274186867794\n",
      "0.001827008595447488\n",
      "0.001704073507387882\n",
      "0.0016817804261602953\n",
      "0.0017244149887346572\n",
      "0.00166731834860534\n",
      "0.0016859876043772148\n",
      "0.0017009566991295078\n",
      "0.0016138933284964851\n",
      "0.0015484085154158223\n",
      "0.0015303707476062023\n",
      "0.001539229828772526\n",
      "0.0015039921129651468\n",
      "0.0015038026016579442\n",
      "0.0016095371558042526\n",
      "0.0013693472920862648\n",
      "0.0012992450404657463\n",
      "0.0012976922027362336\n",
      "0.0012878996072699378\n",
      "0.0012672666346135175\n",
      "0.0012575181220599863\n",
      "0.0012967192288401153\n",
      "0.0012956776408704629\n",
      "0.0011917489504714718\n",
      "0.0011104703111803893\n",
      "0.001062976023134432\n",
      "0.001071609692518516\n",
      "0.0010527894300814689\n",
      "0.0010329896878037426\n",
      "0.0010351013293538047\n",
      "     fun: 0.0010329896878037426\n",
      "   maxcv: 0.0\n",
      " message: 'Maximum number of function evaluations has been exceeded.'\n",
      "    nfev: 200\n",
      "  status: 2\n",
      " success: False\n",
      "       x: array([ 3.14101808, -0.37908964,  2.65451285,  3.0539403 ,  1.11376314,\n",
      "        2.64700199,  1.61171681,  0.13796044,  2.94237266])\n",
      "(0.9989670103250222-0j)\n"
     ]
    }
   ],
   "source": [
    "coefficient_set = [0.55, 0.45]\n",
    "gate_set = [[0, 0, 0], [0, 0, 1]]\n",
    "\n",
    "out = minimize(calculate_cost_function, x0=[float(random.randint(0,3000))/1000 for i in range(0, 9)], method=\"COBYLA\", options={'maxiter':200})\n",
    "print(out)\n",
    "\n",
    "out_f = [out['x'][0:3], out['x'][3:6], out['x'][6:9]]\n",
    "\n",
    "circ = QuantumCircuit(3, 3)\n",
    "apply_fixed_ansatz([0, 1, 2], out_f)\n",
    "\n",
    "backend = Aer.get_backend('statevector_simulator')\n",
    "\n",
    "job = execute(circ, backend)\n",
    "\n",
    "result = job.result()\n",
    "o = result.get_statevector(circ, decimals=10)\n",
    "\n",
    "a1 = coefficient_set[1]*np.array([[1,0,0,0,0,0,0,0], [0,1,0,0,0,0,0,0], [0,0,1,0,0,0,0,0], [0,0,0,1,0,0,0,0], [0,0,0,0,-1,0,0,0], [0,0,0,0,0,-1,0,0], [0,0,0,0,0,0,-1,0], [0,0,0,0,0,0,0,-1]])\n",
    "a2 = coefficient_set[0]*np.array([[1,0,0,0,0,0,0,0], [0,1,0,0,0,0,0,0], [0,0,1,0,0,0,0,0], [0,0,0,1,0,0,0,0], [0,0,0,0,1,0,0,0], [0,0,0,0,0,1,0,0], [0,0,0,0,0,0,1,0], [0,0,0,0,0,0,0,1]])\n",
    "a3 = np.add(a1, a2)\n",
    "\n",
    "b = np.array([float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8)),float(1/np.sqrt(8))])\n",
    "\n",
    "print((b.dot(a3.dot(o)/(np.linalg.norm(a3.dot(o)))))**2)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# My Thesis "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Thesis questions\n",
    "\n",
    "* What approaches are there to solve linear systems on Quantum computers\n",
    "\n",
    "* Can you get near term supremacy with these approaches?\n",
    "\n",
    "* Can you build on these implamentations?"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.6"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
