{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Grover Search Algorithm\n", "\n", "This notebook is an adapted version from https://github.com/QISKit/qiskit-tutorial. We show to to perform the Grover Search algorithm both on a local simulator and on the Quantum Inspire backend.\n", "\n", "For more information about how to use the IBM Q Experience (QX), consult the [tutorials](https://quantumexperience.ng.bluemix.net/qstage/#/tutorial?sectionId=c59b3710b928891a1420190148a72cce&pageIndex=0), or check out the [community](https://quantumexperience.ng.bluemix.net/qstage/#/community).\n", "\n", "*Contributors*\n", "Pieter Eendebak, Giacomo Nannicini and Rudy Raymond (based on [this article](https://arxiv.org/abs/1708.03684)) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction\n", "\n", "Grover search is one of the most popular algorithms used for searching a solution among many possible candidates using Quantum Computers. If there are $N$ possible solutions among which there is exactly one solution (that can be verified by some function evaluation), then Grover search can be used to find the solution with $O(\\sqrt{N})$ function evaluations. This is in contrast to classical computers that require $\\Omega(N)$ function evaluations: the Grover search is a quantum algorithm that provably can be used search the correct solutions quadratically faster than its classical counterparts. \n", "\n", "Here, we are going to illustrate the use of Grover search to find a particular value in a binary number.\n", "The key elements of Grovers algorithm are:\n", "1. Initialization to a uniform superposition\n", "2. The oracle function\n", "3. Reflections (amplitude amplification)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import os\n", "from getpass import getpass\n", "\n", "from qiskit.tools.visualization import circuit_drawer, plot_histogram\n", "from qiskit import execute, QuantumCircuit, QuantumRegister, ClassicalRegister\n", "from qiskit import BasicAer\n", "from IPython.display import display, Math, Latex\n", "\n", "from quantuminspire.credentials import load_account, get_token_authentication, get_basic_authentication\n", "from quantuminspire.api import QuantumInspireAPI\n", "from quantuminspire.qiskit import QI\n", "\n", "QI_EMAIL = os.getenv('QI_EMAIL')\n", "QI_PASSWORD = os.getenv('QI_PASSWORD')\n", "QI_URL = os.getenv('API_URL', 'https://api.quantum-inspire.com/')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The oracle function\n", "\n", "We implement an oracle function (black box) that acts as -1 on a single basis state, and +1 on all other status. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def format_vector(state_vector, decimal_precision=7):\n", " \"\"\" Format the state vector into a LaTeX formatted string.\n", "\n", " Args:\n", " state_vector (list or array): The state vector with complex\n", " values e.g. [-1, 2j+1].\n", "\n", " Returns:\n", " str: The LaTeX format.\n", " \"\"\"\n", " result = []\n", " epsilon = 1/pow(10, decimal_precision)\n", " bit_length = (len(state_vector) - 1).bit_length()\n", " for index, complex_value in enumerate(state_vector):\n", " has_imag_part = np.round(complex_value.imag, decimal_precision) != 0.0\n", " value = complex_value if has_imag_part else complex_value.real\n", " value_round = np.round(value, decimal_precision)\n", " if np.abs(value_round) < epsilon:\n", " continue\n", "\n", " binary_state = '{0:0{1}b}'.format(index, bit_length)\n", " result.append(r'{0:+2g}\\left\\lvert {1}\\right\\rangle '.format(value_round, binary_state))\n", " return ''.join(result)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def run_circuit(q_circuit, q_register, number_of_qubits=None, backend_name='statevector_simulator'):\n", " \"\"\" Run a circuit on all base state vectors and show the output.\n", "\n", " Args:\n", " q_circuit (QuantumCircuit):\n", " q_register (QuantumRegister)\n", " number_of_qubits (int or None): The number of qubits.\n", " backend (str): ...\n", " \"\"\"\n", " if not isinstance(number_of_qubits, int):\n", " number_of_qubits = q_register.size\n", "\n", " if q_register.size != number_of_qubits:\n", " warnings.warn('incorrect register size?')\n", "\n", " latex_text = r'\\mathrm{running\\ circuit\\ on\\ set\\ of\\ basis\\ states:}'\n", " display(Math(latex_text))\n", "\n", " base_states = 2 ** number_of_qubits\n", " backend = BasicAer.get_backend(backend_name)\n", " for base_state in range(base_states):\n", " pre_circuit = QuantumCircuit(q_register)\n", " state = base_state\n", " for kk in range(number_of_qubits):\n", " if state % 2 == 1:\n", " pre_circuit.x(q[kk])\n", " state = state // 2 \n", "\n", " input_state = r'\\left\\lvert{0:0{1}b}\\right\\rangle'.format(base_state, number_of_qubits)\n", " circuit_total = pre_circuit.combine(q_circuit)\n", " job = execute(circuit_total, backend=backend)\n", " output_state = job.result().get_statevector(circuit_total)\n", "\n", " latex_text = input_state + r'\\mathrm{transforms\\ to}: ' + format_vector(output_state)\n", " display(Math(latex_text))" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "black box circuit:\n" ] }, { "data": { "text/latex": [ "$\\displaystyle \\mathrm{running\\ circuit\\ on\\ set\\ of\\ basis\\ states:}$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert000\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 000\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert001\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 001\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert010\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 010\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert011\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 011\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert100\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 100\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert101\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 101\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert110\\right\\rangle\\mathrm{transforms\\ to}: +1\\left\\lvert 110\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert111\\right\\rangle\\mathrm{transforms\\ to}: -1\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "n=3\n", "N=2**n\n", "q = QuantumRegister(n)\n", "qc = QuantumCircuit(q)\n", "\n", "if n==1:\n", " def black_box(qc, q): \n", " qc.z(q)\n", "elif n==2:\n", " def black_box(qc, q):\n", " for i in range(n):\n", " qc.s(q[i])\n", " qc.h(q[1])\n", " qc.cx(q[0], q[1]) \n", " qc.h(q[1])\n", " for i in range(n):\n", " qc.s(q[i])\n", "else:\n", " def black_box(qc, q):\n", " qc.h(q[2])\n", " qc.ccx(q[0], q[1], q[2])\n", " qc.h(q[2])\n", "black_box(qc,q)\n", "cplot=qc.draw(output='mpl')\n", "display(cplot)\n", "\n", "print('black box circuit:')\n", "run_circuit(qc, q)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Inversion about the average\n", "\n", "Another important procedure in Grover search is to have an operation that perfom the *inversion-about-the-average* step, namely, it performs the following transformation:\n", "\n", "$$\n", "\\sum_{j=0}^{2^{n}-1} \\alpha_j |j\\rangle \\rightarrow \\sum_{j=0}^{2^{n}-1}\\left(2 \\left( \\sum_{k=0}^{k=2^{n}-1} \\frac{\\alpha_k}{2^n} \\right) - \\alpha_j \\right) |j\\rangle \n", "$$\n", "\n", "The above transformation can be used to amplify the probability amplitude $\\alpha_s$ when s is the solution and $\\alpha_s$ is negative (and small), while $\\alpha_j$ for $j \\neq s$ is positive. Roughly speaking, the value of $\\alpha_s$ increases by twice the average of the amplitudes, while others are reduced. The inversion-about-the-average can be realized with the sequence of unitary matrices as below:\n", "\n", "$$\n", "H^{\\otimes n} \\left(2|0\\rangle \\langle 0 | - I \\right) H^{\\otimes n}\n", "$$\n", "\n", "The first and last $H$ are just Hadamard gates applied to each qubit. The operation in the middle requires us to design a sub-circuit that flips the probability amplitude of the component of the quantum state corresponding to the all-zero binary string. The sub-circuit can be realized by the following function, which is a multi-qubit controlled-Z which flips the probability amplitude of the component of the quantum state corresponding to the all-one binary string. Applying X gates to all qubits before and after the function realizes the sub-circuit. " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def n_controlled_Z(circuit, controls, target):\n", " \"\"\"Implement a Z gate with multiple controls\"\"\"\n", " if (len(controls) > 2):\n", " raise ValueError('The controlled Z with more than 2 ' +\n", " 'controls is not implemented')\n", " elif (len(controls) == 1):\n", " circuit.h(target)\n", " circuit.cx(controls[0], target)\n", " circuit.h(target)\n", " elif (len(controls) == 2):\n", " circuit.h(target)\n", " circuit.ccx(controls[0], controls[1], target)\n", " circuit.h(target)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, the inversion-about-the-average circuit can be realized by the following function:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def inversion_about_average(circuit, f_in, n):\n", " \"\"\"Apply inversion about the average step of Grover's algorithm.\"\"\"\n", " # Hadamards everywhere\n", " if n==1:\n", " circuit.x(f_in[0])\n", " return\n", " for j in range(n):\n", " circuit.h(f_in[j])\n", " # D matrix: flips the sign of the state |000> only\n", " for j in range(n):\n", " circuit.x(f_in[j])\n", " n_controlled_Z(circuit, [f_in[j] for j in range(n-1)], f_in[n-1])\n", " for j in range(n):\n", " circuit.x(f_in[j])\n", " # Hadamards everywhere again\n", " for j in range(n):\n", " circuit.h(f_in[j])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We show the circuit that performs inversion about the average on $n$ qubits. We also show the effect of the circuit on the basis states." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "qInvAvg = QuantumCircuit(q)\n", "inversion_about_average(qInvAvg, q, n)\n", "qInvAvg.draw(output='mpl')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "inversion average circuit:\n" ] }, { "data": { "text/latex": [ "$\\displaystyle \\mathrm{running\\ circuit\\ on\\ set\\ of\\ basis\\ states:}$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert000\\right\\rangle\\mathrm{transforms\\ to}: +0.75\\left\\lvert 000\\right\\rangle -0.25\\left\\lvert 001\\right\\rangle -0.25\\left\\lvert 010\\right\\rangle -0.25\\left\\lvert 011\\right\\rangle -0.25\\left\\lvert 100\\right\\rangle -0.25\\left\\lvert 101\\right\\rangle -0.25\\left\\lvert 110\\right\\rangle -0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert001\\right\\rangle\\mathrm{transforms\\ to}: +0.25\\left\\lvert 000\\right\\rangle -0.75\\left\\lvert 001\\right\\rangle +0.25\\left\\lvert 010\\right\\rangle +0.25\\left\\lvert 011\\right\\rangle +0.25\\left\\lvert 100\\right\\rangle +0.25\\left\\lvert 101\\right\\rangle +0.25\\left\\lvert 110\\right\\rangle +0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert010\\right\\rangle\\mathrm{transforms\\ to}: +0.25\\left\\lvert 000\\right\\rangle +0.25\\left\\lvert 001\\right\\rangle -0.75\\left\\lvert 010\\right\\rangle +0.25\\left\\lvert 011\\right\\rangle +0.25\\left\\lvert 100\\right\\rangle +0.25\\left\\lvert 101\\right\\rangle +0.25\\left\\lvert 110\\right\\rangle +0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert011\\right\\rangle\\mathrm{transforms\\ to}: -0.25\\left\\lvert 000\\right\\rangle -0.25\\left\\lvert 001\\right\\rangle -0.25\\left\\lvert 010\\right\\rangle +0.75\\left\\lvert 011\\right\\rangle -0.25\\left\\lvert 100\\right\\rangle -0.25\\left\\lvert 101\\right\\rangle -0.25\\left\\lvert 110\\right\\rangle -0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert100\\right\\rangle\\mathrm{transforms\\ to}: +0.25\\left\\lvert 000\\right\\rangle +0.25\\left\\lvert 001\\right\\rangle +0.25\\left\\lvert 010\\right\\rangle +0.25\\left\\lvert 011\\right\\rangle -0.75\\left\\lvert 100\\right\\rangle +0.25\\left\\lvert 101\\right\\rangle +0.25\\left\\lvert 110\\right\\rangle +0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert101\\right\\rangle\\mathrm{transforms\\ to}: -0.25\\left\\lvert 000\\right\\rangle -0.25\\left\\lvert 001\\right\\rangle -0.25\\left\\lvert 010\\right\\rangle -0.25\\left\\lvert 011\\right\\rangle -0.25\\left\\lvert 100\\right\\rangle +0.75\\left\\lvert 101\\right\\rangle -0.25\\left\\lvert 110\\right\\rangle -0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert110\\right\\rangle\\mathrm{transforms\\ to}: -0.25\\left\\lvert 000\\right\\rangle -0.25\\left\\lvert 001\\right\\rangle -0.25\\left\\lvert 010\\right\\rangle -0.25\\left\\lvert 011\\right\\rangle -0.25\\left\\lvert 100\\right\\rangle -0.25\\left\\lvert 101\\right\\rangle +0.75\\left\\lvert 110\\right\\rangle -0.25\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/latex": [ "$\\displaystyle \\left\\lvert111\\right\\rangle\\mathrm{transforms\\ to}: +0.25\\left\\lvert 000\\right\\rangle +0.25\\left\\lvert 001\\right\\rangle +0.25\\left\\lvert 010\\right\\rangle +0.25\\left\\lvert 011\\right\\rangle +0.25\\left\\lvert 100\\right\\rangle +0.25\\left\\lvert 101\\right\\rangle +0.25\\left\\lvert 110\\right\\rangle -0.75\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "print('inversion average circuit:')\n", "qc = QuantumCircuit(q)\n", "inversion_about_average(qc, q, n) \n", "run_circuit(qc, q, n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Grover Search: putting all together\n", "\n", "The complete steps of Grover search is as follow.\n", "\n", "1. Create the superposition of all possible solutions as the initial state (with working qubits initialized to zero)\n", "$$ \\sum_{j=0}^{2^{n}-1} \\frac{1}{2^n} |j\\rangle |0\\rangle$$\n", "2. Repeat for $T$ times:\n", " * Apply the blackbox function\n", " * Apply the inversion-about-the-average function\n", " \n", "3. Measure to obtain the solution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before we go to the code to perform the Grover search we make some remarks on the number of repetitions $T$ that we have to perform (for details see [Grover algorithm, Wikipedia](https://en.wikipedia.org/wiki/Grover%27s_algorithm)).\n", "\n", "Each Grover step rotates the 'winner solution' by a fixed angle. This means that after a certain number of steps we arrive at the optimal approximation (e.g. the amplitude of the winner solution is maximal). If we then apply more iterations, the quality of our result will go _down_. For a database of size $N=2^n$ the optimal number of iterations is\n", "$$r=\\pi \\sqrt{N}/4$$" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\textrm{Rotation of the winner: } \\theta = 41.41 \\mathrm{\\ [deg]}$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Optimal number of Grover iterations for n=3: 2.2\n" ] } ], "source": [ "theta = 2*np.arcsin(1/np.sqrt(N))\n", "r=np.pi*np.sqrt(N)/4\n", "display(Math(r'\\textrm{Rotation of the winner: } \\theta = %.2f \\mathrm{\\ [deg]}' % (np.rad2deg(theta))) )\n", "print('Optimal number of Grover iterations for n=%d: %.1f' % (n,r) )\n", "T=int(r)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The probablity of the winner state after $T$ iterations is $\\sin( (T+1/2)\\theta)^2$" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 iterations: p 0.12\n", "1 iterations: p 0.78\n", "2 iterations: p 0.95\n", "3 iterations: p 0.33\n" ] } ], "source": [ "for i in range(int(r+2)):\n", " p=np.sin((i+1/2)*theta)**2\n", " print('%d iterations: p %.2f' % (i, p))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally we define the complete circuit for Grovers algorithm, excute it and show the results." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\mathrm{state\\ after\\ initialization:\\ }+0.353553\\left\\lvert 000\\right\\rangle +0.353553\\left\\lvert 001\\right\\rangle +0.353553\\left\\lvert 010\\right\\rangle +0.353553\\left\\lvert 011\\right\\rangle +0.353553\\left\\lvert 100\\right\\rangle +0.353553\\left\\lvert 101\\right\\rangle +0.353553\\left\\lvert 110\\right\\rangle +0.353553\\left\\lvert 111\\right\\rangle $" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "number of iterations T=2\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAc0AAAFDCAYAAABY/1W1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3de5hddX3v8ffXXIBAAjMxJjOkkxCTxklC45AcFLkYIHi4HD2IVLCoUC8clHopBcQ+ehSt2EYUqEerUnsA9XBRsIoFgZBULkGBJKSEhDQwJBhmiCE3Arkyfs8fe086mUwma8LcMvN+Pc9+Zu+1fmvt78pm89m/dfmtyEwkSdLevaGnC5AkaX9haEqSVJChKUlSQYamJEkFGZqSJBVkaEqSVNDAni6gJw0fPjxramp6ugxJUi/yxBNPvJSZI9qa169Ds6amhjlz5vR0GZKkXqSysnLlnua5e1aSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCurW0IyIEyLilxHxQkRkRFxQYJkjI+I3EbGlvNz/joho1eZ9EbEkIraV/763yzZCktRvdXdP8xBgMfAZYMveGkfEMOA+YDXw34BPA5cBl7RocwxwK/AT4K3lvz+NiLd1dvGSpP6tW29CnZl3AXcBRMQNBRY5DxgCnJ+ZW4DFEVELXBIR38rMBD4LzM3Mr5WX+VpEnFie/oHO3gZJUv/V249pHgM8WA7MZvcA1cDYFm3ubbXcPcA7urw6SVK/0q09zX0wCljVatrqFvOeK/9d3UabUW2tMCIuBC4EqKqqYsGCBQBUV1czZMgQnnnmGQAOPfRQxo0bx8KFCwEYMGAAU6dOZdmyZbz66qsA1NbWsm7dOlavLr396NGjGTx4MPX19QBUVFRQU1PDokWLABg0aBBHHnkkS5cuZcuW0u+ASZMmsWbNGtasWQPAmDFjiAhWrFgBwPDhw6mqqmLx4sUAHHDAAUyePJmnnnqKbdu2ATBlyhQaGxtZu3YtAGPHjiUzWblyJQAjRoxgxIgRLFmyBICDDjqI2tpannzySXbs2AHA1KlTef7551m/fj0A48aNY/v27axaVfrnHzlyJJWVlSxduhSAgw8+mIkTJ7Jo0SKampoAqKuro76+no0bNwIwfvx4Nm/eTENDA83/3sOGDWPZsmUADB06lAkTJrBw4UIyk4igrq6O5cuXs2nTJgAmTpzIyy+/TGNjo5+Tn5Ofk59Tt3xO7YnSHs7uFxGvAH+VmTe00+Ze4PeZ+dEW08YAK4BjMvO3EbEd+Ghm/qhFm/OB72fmge3VUFdXl3PmzHl9GyJJ6lMqKyvnZ+b0tub19t2zL7J7j/FN5b+r99Kmde9TkqTXpbeH5iPA8RHRssd4CtBAqbfZ3OaUVsudAszr8uokSf1Kd1+neUhEvDUi3lp+75ry65ry/K9HxP0tFvl/wGbghoiYEhFnAVcAzWfOAlwHnBQRn4+It0TE54ETgWu7bcMkqRvMnj2bo48+mmnTpnHttbv/L+73v/89Z555Jscddxzvfve7eeGFF3bOu/nmm5k+fTrTp0/n5ptv3jn9iSee4Nhjj2XatGlcccUV9NQhu/1Fd/c0pwMLy4+DgCvLz79Snl8FvLm5cWZupNRrrAYeB74DfBP4Vos284BzgfOB/wA+DJyTmb/r4m2RpG7T1NTE5Zdfzm233cYjjzzC7bffztNPP71Lmy9+8Yucc845PPTQQ1x22WV89atfBWD9+vXMmjWL++67j9mzZzNr1iw2bNgAwKWXXso111zD448/zrPPPsvs2bO7fdv2J90ampn575kZbTwuKM+/IDPHtlrmycw8ITMPzMyqzLwyW/0UysyfZeZbMnNwZtZm5h3dt1WS1PXmz5/PEUccwdixYxk8eDBnnXUWd9999y5tli1bxgknnADA8ccfz1133QXAnDlzmDFjBhUVFRx22GHMmDGD+++/nxdffJFNmzZx9NFHExGce+65O5dR23r7MU1JEtDY2Mjhhx++83V1dfXOS0eaTZkyhTvvvBOAX/3qV7zyyiusW7eOhoaG3ZZtaGigsbGR6urqdtepXRmakrQfaOtYY6thuPnKV77CvHnzeOc738nDDz9MVVUVAwcO3OOyRdapXfX2wQ0kSZR6gS1P7GloaGDUqF2vtquqquKmm24C4JVXXuHOO+9k2LBhHH744Tz00EO7LHvcccft7HG2t07typ6mJO0HjjrqKOrr61m5ciXbt2/njjvu4NRTT92lzdq1a/njH/8IwLXXXst5550HwEknncTcuXPZsGEDGzZsYO7cuZx00kmMGjWKQw45hMcee4zM5JZbbuH000/v9m3bn9jTlKT9wMCBA5k1axZnn302TU1NnHfeedTW1nLVVVdRV1fHaaedxkMPPcRXv/pVIoJjjjmGb3zjG0BpaLtLL72Uk08+GYDLLruMiooKAK6++mouvvhitm7dysyZM5k5c2aPbeP+oMeG0esNHEZPktTa/jyMniRJvYahKUlSQYamJEkFGZqSJBVkaEqSVJChKUlSQYamJEkFGZqSJBVkaEqSVJChKUlSQYamJEkFGZqSJBXkXU4k9TuX31jR0yWoC8w6f32Xv4c9TUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCur20IyIT0bEcxGxNSLmR8Tx7bS9ISKyjcerLdrM2EObt3TPFkmS+otuDc2IOAe4DrgKqAPmAXdHRM0eFvkMUNXqUQ/c1kbbya3aLe/U4iVJ/V539zQvAW7IzOszc2lmfgpoBD7RVuPM3JiZLzY/gDcD44Dr22j+h5ZtM7Opy7ZCktQvdVtoRsRgYBpwb6tZ9wLvKLiajwNPZea8NuY9HhGNEXF/RJz4OkqVJKlNA7vxvd4IDABWt5q+Gpi5t4Uj4lDgz4G/bTWruaf6GDAY+BBwf0TMyMwH2ljPhcCFAFVVVSxYsACA6upqhgwZwjPPPAPAoYceyrhx41i4cCEAAwYMYOrUqSxbtoxXXy0dUq2trWXdunWsXl3apNGjRzN48GDq6+sBqKiooKamhkWLFgEwaNAgjjzySJYuXcqWLVsAmDRpEmvWrGHNmjUAjBkzhohgxYoVAAwfPpyqqioWL14MwAEHHMDkyZN56qmn2LZtGwBTpkyhsbGRtWvXAjB27Fgyk5UrVwIwYsQIRowYwZIlSwA46KCDqK2t5cknn2THjh0ATJ06leeff57169cDMG7cOLZv386qVasAGDlyJJWVlSxduhSAgw8+mIkTJ7Jo0SKamkqd+rq6Ourr69m4cSMA48ePZ/PmzTQ0NND87z1s2DCWLVsGwNChQ5kwYQILFy4kM4kI6urqWL58OZs2bQJg4sSJvPzyyzQ2Nvo5+Tl12uekvmnt2rWd8n1qT2RmF25CizeKqAZeAE7IzAdbTP8S8IHMbPfEnYi4GPgmUJ2Z6/bS9i7gtcx8T3vt6urqcs6cOUU3QVIfcfmNFT1dgrrArPPXd8p6Kisr52fm9LbmdecxzZeAJmBUq+lvYvfeZ1s+Dty+t8As+x0woWPlSZLUvm4LzczcDswHTmk16xRKZ9HuUUS8DZhK2ycAteWtlHbbSpLUabrzmCbAt4AfRcSjwMPARUA18D2AiLgJIDM/3Gq5j1O6hOQ3rVcYEZ8FVgBPUTqm+UHgTOB9XbIFkqR+q1tDMzNvjYjhwBcoXUu5GDg9M1eWm+x2vWZEDAXOBb6SbR+AHQxcDRwObKEUnmdk5l1dsAmSpH6su3uaZOZ3ge/uYd6MNqZtAg5pZ32zgFmdVZ8kSXvi2LOSJBVkaEqSVJChKUlSQYamJEkFGZqSJBVkaEqSVFCHQjMi3h8R72rx+n9HxKqIuCciHAVZktSndbSn+eXmJxFxFKU7jvwjMIjSYOqSJPVZHR3cYAywrPz8vcC/ZuasiLgXuKdTK5MkqZfpaE9zKzC0/PxkYHb5+cYW0yVJ6pM62tN8EPhmRDwETAfOLk//U+D3nVmYJEm9TUd7mn8FbKcUlhdlZkN5+mm4e1aS1Md1qKeZmauAd7cx/bOdVpEkSb1Uh6/TjIgDI+LsiPhcRBxWnvbmiKjs/PIkSeo9OtTTjIjxlE7+OQQ4DPgpsAH4RPn1xzq7QEmSeouO9jSvBe4FRlK64XOzXwIndlZRkiT1Rh09e/YdwNszsykiWk5/HqjutKokSeqF9mXs2UFtTKuhdK2mJEl9VkdD817gkhavMyKGAVcC/9ZpVUmS1At1dPfsJcDciFgGHAjcCowHVgPv7+TaJEnqVTp6nWZDRLwV+ABwFKWe6g+An2TmlnYXliRpP9fRniblcPyX8kOSpH5jr6EZEWcBd2bmjvLzPcrMOzqtMkmSepkiPc2fAaOAP5Sf70kCAzqjKEmSeqO9hmZmvqGt55Ik9TcdCsGIOCEidgvaiBgQESd0XlmSJPU+He05zgXaGpj9sPI8SZL6rI6GZlA6dtnacODV11+OJEm9V6FLTiLil+WnCfw4Ira1mD0AmALM6+TaJEnqVYpep7m2/DeA9ex6h5PtwEPA9Z1YlyRJvU6h0MzMvwSIiBXA1ZnprlhJUr/T0WH0ruyqQiRJ6u2KjAj0H8A7M3N9RDxJ2ycCAZCZf9aZxUmS1JsU6WneDjSf+NPeiECSJPVpRUYEurKt55Ik9TcOiydJUkFFjmm2exyzJY9pSpL6sqJ3OZEkqd/r0DFNSZL6M49pSpJUkNdpSpJUkNdpSpJUkNdpSpJUUIfGnm0WEW8Gassvl2bms51XkiRJvVOHQjMihgM/BN4D/PG/JsevgI9k5to9LixJ0n6uo2fP/jMwHjgeOLD8OAE4Au+nKUnq4zq6e/a/Aydn5iMtpj0cEf8LmN15ZUmS1Pt0tKe5BmjrBtSbAXfNSpL6tI6G5leAayPi8OYJ5effLM+TJKnP2pcB248AVkTEC+XXhwNbgTdROuYpSVKf5IDtkiQV5IDtkiQV1O0DtkfEJyPiuYjYGhHzI+L4dtrOiIhs4/GWVu3eFxFLImJb+e97u35LJEn9TYdCMyIGR8SVEfGf5dBravkosPw5wHXAVUAdMA+4OyJq9rLoZKCqxWN5i3UeA9wK/AR4a/nvTyPibR3ZNkmS9qajPc2vAudTOlv2j8BlwHcoXW7yyQLLXwLckJnXZ+bSzPwU0Ah8Yi/L/SEzX2zxaBnQnwXmZubXyuv8GvDv5emSJHWajobm+4GLMvP7QBPwi8z8NPAl4JT2FoyIwcA04N5Ws+4F3rGX9308Ihoj4v6IOLHVvGPaWOc9BdYpSVKHdHREoJHAkvLzV4DDys9/DfzDXpZ9IzAAWN1q+mpg5h6Wae6FPgYMBj4E3B8RMzLzgXKbUXtY56i2VhgRFwIXAlRVVbFgwQIAqqurGTJkCM888wwAhx56KOPGjWPhwoUADBgwgKlTp7Js2TJefbU0vkNtbS3r1q1j9erS248ePZrBgwdTX18PQEVFBTU1NSxatAiAQYMGceSRR7J06VK2bNkCwKRJk1izZg1r1qwBYMyYMUQEK1asAGD48OFUVVWxePFiAA444AAmT57MU089xbZtpTu2TZkyhcbGRtauLY0vMXbsWDKTlStXAjBixAhGjBjBkiWlj+6ggw6itraWJ598kh07dgAwdepUnn/+edavXw/AuHHj2L59O6tWrQJg5MiRVFZWsnTpUgAOPvhgJk6cyKJFi2hqKnX86+rqqK+vZ+PGjQCMHz+ezZs309DQQPO/97Bhw1i2bBkAQ4cOZcKECSxcuJDMJCKoq6tj+fLlbNq0CYCJEyfy8ssv09jY6Ofk59Rpn5P6prVr13bK96k9kbnHe0rv3jjiaeCCzPxtRDwI3J2ZV0XEXwDXZObIdpatBl4ATsjMB1tM/xLwgcx8y56WbbWeu4DXMvM95dfbgY9m5o9atDkf+H5mHtjeuurq6nLOnDlF3lZSH3L5jRU9XYK6wKzz13fKeiorK+dn5vS25nV09+zPgZPLz68DroyI54Ab2PvABi9R2qXbugf4JnbvKbbnd8CEFq9f7IR1SpK0Vx3aPZuZn2/x/GcRsYrSscP/zMxf7WXZ7RExn9Kxz5+2mHUKcHsHyngrpd22zR4pr+MbrdY5rwPrlCRpr/bpJtTNMvO3wG87sMi3gB9FxKPAw8BFQDXwPYCIuKm83g+XX38WWAE8RemY5geBM4H3tVjndcADEfF5Sj3h9wInAsft63ZJktSWDodmRBxF6XKOSeVJSykdz1ywt2Uz89byjay/QOl6y8XA6Zm5styk9fWag4GrKY1vu4VSeJ6RmXe1WOe8iDgX+DvgSuBZ4JzM/F1Ht02SpPZ0KDQj4jzgJmAO0BxcbwcejYgLMvPHe1tHZn4X+O4e5s1o9XoWMKvAOn+GY+RKkrpYR3uaXwO+mJlXtZxY3jX6d8BeQ1OSpP1VR8+eHQHc1sb0n1I6Y1WSpD6ro6E5F5jRxvQZwG9ebzGSJPVmRW5CfVaLl3cDX4+I6fzXWbNvB84Cvtzp1UmS1Ivs602odw5F18K32cMJPpIk9QVFbkLd7ffclCSpNzIQJUkqqMOhGRFnRMQDEfFSRKyJiN9ExOldUZwkSb1Jh0IzIj5Gaai6Z4HPAVcAzwE/j4iPdH55kiT1Hh0d3OBzwCWZ+X9aTPtheSD2K4B/6bTKJEnqZTq6e7aG0g2nW7sbGPP6y5EkqffqaGg+T+m2W629C1jZxnRJkvqMju6evRr4dvlOJ/OApHQLrg8Bn+rk2iRJ6lU6ehPq70fEH4C/oTQKEJRuDfb+zPxFZxcnSVJvUjg0I2Igpd2wD2Tmz7uuJEmSeqfCxzQz8zXgDmBo15UjSVLv1dETgRYB47uiEEmSeruOhuaXgW9GxJkR8ScRUdny0QX1SZLUa3T07Nl/K/+9g9KZs82i/HpAZxQlSVJv1NHQPLFLqpAkaT9QKDQjYgjwDeBMYBAwG/h0Zr7UhbVJktSrFD2meSVwAaXdszdTGhXon7qoJkmSeqWiu2fPAj6ambcARMRPgIcjYkBmNnVZdZIk9SJFe5p/AjzY/CIzHwVeA6q7oihJknqjoqE5ANjeatprdPxEIkmS9ltFQy+AH0fEthbTDgSuj4jNzRMy8z2dWZwkSb1J0dC8sY1pP+7MQiRJ6u0KhWZm/mVXFyJJUm/X0WH0JEnqtwxNSZIKMjQlSSrI0JQkqSBDU5KkggxNSZIKMjQlSSrI0JQkqSBDU5KkggxNSZIKMjQlSSrI0JQkqSBDU5KkggxNSZIKMjQlSSrI0JQkqSBDU5KkggxNSZIKMjQlSSrI0JQkqSBDU5KkggxNSZIKMjQlSSrI0JQkqaBuD82I+GREPBcRWyNifkQc307bsyLi3ohYExGbIuJ3EfGeVm0uiIhs43Fg12+NJKk/6dbQjIhzgOuAq4A6YB5wd0TU7GGRdwJzgDPK7e8Cft5G0G4Gqlo+MnNr52+BJKk/G9jN73cJcENmXl9+/amIOBX4BPD51o0z8zOtJl0ZEWcAZwIP7to0X+yKgiVJatZtPc2IGAxMA+5tNete4B0dWNVQYH2raQdFxMqIWBURv4qIutdRqiRJberOnuYbgQHA6lbTVwMzi6wgIi4GRgM/ajF5GfARYBGlQP0M8HBETM3M5W2s40LgQoCqqioWLFgAQHV1NUOGDOGZZ54B4NBDD2XcuHEsXLgQgAEDBjB16lSWLVvGq6++CkBtbS3r1q1j9erSJo0ePZrBgwdTX18PQEVFBTU1NSxatAiAQYMGceSRR7J06VK2bNkCwKRJk1izZg1r1qwBYMyYMUQEK1asAGD48OFUVVWxePFiAA444AAmT57MU089xbZt2wCYMmUKjY2NrF27FoCxY8eSmaxcuRKAESNGMGLECJYsWQLAQQcdRG1tLU8++SQ7duwAYOrUqTz//POsX1/6PTJu3Di2b9/OqlWrABg5ciSVlZUsXboUgIMPPpiJEyeyaNEimpqaAKirq6O+vp6NGzcCMH78eDZv3kxDQwPN/97Dhg1j2bJlAAwdOpQJEyawcOFCMpOIoK6ujuXLl7Np0yYAJk6cyMsvv0xjY6Ofk59Tp31O6pvWrl3bKd+n9kRmduEmtHijiGrgBeCEzHywxfQvAR/IzLfsZfn3UQrLczPzl+20GwA8AczNzE+3t866urqcM2dOB7ZCUl9w+Y0VPV2CusCs81vvhNw3lZWV8zNzelvzuvNEoJeAJmBUq+lvYvfe5y5aBOaH2wtMgMxsAh4HJux7qZIk7a7bQjMztwPzgVNazTqF0lm0bYqI9wM/Bi7IzJ/t7X0iIoA/Axr3vVpJknbX3WfPfgv4UUQ8CjwMXARUA98DiIibADLzw+XX51LqYV4KPBARzb3U7Zm5rtzmS8BvgeXAMODTlELzE920TZKkfqJbQzMzb42I4cAXKF1PuRg4PTNXlpu0vl7zIko1Xlt+NPsNMKP8/DDgB5R2+24EFlI6bvpoV2yDJKn/6u6eJpn5XeC7e5g3o73Xe1jmr4G/7ozaJElqj2PPSpJUkKEpSVJBhqYkSQUZmpIkFWRoSpJUkKEpSVJBhqYkSQUZmpIkFWRoSpJUkKEpSVJBhqYkSQUZmpIkFWRoSpJUkKEpSVJBhqYkSQUZmpIkFWRoSpJUkKEpSVJBhqYkSQUZmpIkFWRo9nOzZ8/m6KOPZtq0aVx77bW7zZ83bx4zZsxgxIgR/OIXv9hl3s0338z06dOZPn06N998887pTzzxBMceeyzTpk3jiiuuIDO7fDskqTsYmv1YU1MTl19+ObfddhuPPPIIt99+O08//fQubUaPHs13vvMdzj777F2mr1+/nlmzZnHfffcxe/ZsZs2axYYNGwC49NJLueaaa3j88cd59tlnmT17drdtkyR1JUOzH5s/fz5HHHEEY8eOZfDgwZx11lncfffdu7Spqalh8uTJvOENu/6nMmfOHGbMmEFFRQWHHXYYM2bM4P777+fFF19k06ZNHH300UQE5557LnfddVd3bpYkdRlDsx9rbGzk8MMP3/m6urqaxsbGQss2NDTstmxDQwONjY1UV1fv0zolqbczNPuxto41RsTrWvb1rFOSejtDsx+rrq7mhRde2Pm6oaGBUaNGFVr28MMP323ZqqqqnT3OfVmnJPV2hmY/dtRRR1FfX8/KlSvZvn07d9xxB6eeemqhZU866STmzp3Lhg0b2LBhA3PnzuWkk05i1KhRHHLIITz22GNkJrfccgunn356F2+JJHWPgT1dgHrOwIEDmTVrFmeffTZNTU2cd9551NbWctVVV1FXV8dpp53GggUL+NCHPsTGjRv59a9/zd///d/zyCOPUFFRwaWXXsrJJ58MwGWXXUZFRQUAV199NRdffDFbt25l5syZzJw5syc3U5I6TfTna+jq6upyzpw5PV2GpG52+Y0VPV2CusCs89d3ynoqKyvnZ+b0tua5e1aSpIIMTUmSCvKYZidwV0/f1Fm7eiT1HfY0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIK6PTQj4pMR8VxEbI2I+RFx/F7av7PcbmtE1EfERa93nZIk7YtuDc2IOAe4DrgKqAPmAXdHRM0e2h8B3FVuVwd8Hfh2RLxvX9cpSdK+6u6e5iXADZl5fWYuzcxPAY3AJ/bQ/iKgITM/VW5/PXAjcOnrWKckSfuk20IzIgYD04B7W826F3jHHhY7po329wDTI2LQPq5TkqR90p09zTcCA4DVraavBkbtYZlRe2g/sLy+fVmnJEn7ZGAPvGe2eh1tTNtb++bp0U6bNtcZERcCF5ZfvlJZWbms3WrV2huBl3q6iO7wz3/d0xVIncLvbMeN2dOM7gzNl4Amdu8Bvonde4rNXtxD+9eAtZTCsUPrzMwfAD8oXLV2ERGPZ+b0nq5DUjF+ZztXt+2ezcztwHzglFazTqF0xmtbHgFmttH+8czcsY/rlCRpn3T37tlvAT+KiEeBhymdHVsNfA8gIm4CyMwPl9t/D/iriLgW+D5wLHAB8IGi65QkqbN0a2hm5q0RMRz4AlAFLAZOz8yV5SY1rdo/FxGnA9dQuoSkAfh0Zt7egXWqc7lrW9q/+J3tRJHZ3jk4kiSpmWPPSpJUkKEpSVJBhqY6JCJi760kqW/ymKYkSQX1xIhA2s9ExAHAnwHvBTYCTwHPAM9n5uaIiPTXl6R+wJ6m9ioi/hE4i9LdYyqAsZQu//k58I+Z+WzPVSdJ3cdjmmpXREyiNKDER4BTM3M8pethvwu8B1gcERd6rFNSf2BPU+2KiL+lFJYnlF8PzMzXWsy/ilIv9KTMbOihMiW1EBEjKQ0neldmrmun3aDM3NF9le3/7Glqb5YCVRExHiAzX4uIgRFxYHn+9cBm4M97qkBJu/kCcBPwTET8NCJOL5+bsFNE1ACfaT1d7TM0tTcPULqrzK8i4v0RcUBmvpaZW6E01CGle5pu7ckiJe1iOvAPwN9QOg/h58BzEfHtiDiq3ObjwEWZua2HatwvuXtWexUR1ZTG/z0SWAX8Dphbfn4x8BfA2Mx8tceKlATs/L5eB9yXmT+IiIHAeOB/UrrZxZHAEmAc8LeZeV2PFbsfMjRVSHlQ/DOAd1H6sk2k9Av2N8D3M/OWHixPUllEHAycBPwhM3/Xat4QYApwKaVzEYZm5pbur3L/ZWhqjyJiNKVfqACvUvp1uoVSaB5C6VjmS+2daCCpZ7V1HXVE3AC8OTOP75mq9l8ObqA2RcQnKF1mMpVSONYDvwf+HfhZZj7Tc9VJ2pOIeAOQzUHZRjoQgNUAAAN3SURBVGAeROmew9/qgfL2e/Y0tZvyrthngG8C/wSMAGYCJwKTgBco3dd0iaMBSfuXiBgETM/MR3q6lv2RoandRMSngA9m5tvamHcc8HXgcODozHypu+uTtLtyGB4BrPSM2K7jJSdqy3ZgaERMgdLYsxExGCAzHwLOo3SJybt6rkRJrVwMLAS+FxHvjohRETGgZYOIGBYRZzR/n9Vxhqba8jPgj8BnI2JoZm7LzO3lYyVk5vPABmB0TxYpaRfnAI9SOnnvX4FHgG9ExHERcWi5zV8AX8zM7T1U437P0NQuymPIrqM0osgpQENE/DAippXn10TEByld63Vbz1UqqVlEjAB2ANeXz4gdA/wQ+B+UBiiZExGfAz5L6Tpr7SOPaapNEXEYUAO8g9ItwY4tz3qR0o+tmzLzyz1TnaSWIqIKOBdYkpn3tJpXB3ysPL8C+JPMfKH7q+wbDE3tFBFvAj5Eaeitlyhdk7kBeJDSr9NBwJuBe4DlnjUr9R7lS0kyM7e2vOtQ8/c0Ir4GnJ6ZdT1VY19gaGqn8gXPk4E7Ke2iraS0G/ZPgT8AX2g9woik3mNPl4CVRwJaAPzfzPyH7q+s7zA0Bew8lrmJ0i/RB1pMqwHeDnyU0khA78/MBT1WqKRdRMQwYFN7e37KdyU6B7jZk4BeH08EUrNJwHOULjcBykOKZK7MzFuBd1PaVestwKTe5RvARyLiyHKAtuXAzLzRwHz9DE01q6e0C/aaiJjQfHlJs/LF0jcCp/VEcZJ2FxEfoHSLr28Cv6B0icl7I+LN5WOczcc6b2y+7lqvj7tntVNEvB34HqUTgL4P3A+sy8xXy8dEbgK2ZuYHe7BMSWURcT3QBMyidNeS8ymdrLcMuIvSd3gicF1mOqBBJzA0tYvyr9EvAu+hdGeTR4A1lMaebQQ+lplP9lyFkgDK98m8HBiWmVe0mD6ZUu/zbOBA4DDgxsz8aI8U2scYmmpT+fKTM4AzKQ2Ztxj4aWY+3aOFSdopIiqAkZn5dHlovB0tTwiKiHOAm4GjMvOJnqqzLzE0tVcR8YbM/GNP1yFp78rnI0RmNkXExyntmh3S03X1Fd5PU3tlYEr7j1bf16HAl3qqlr7InqYk9VHl24U1+cO38xiakiQV5HWakiQVZGhKklSQoSlJUkGGpiRJBRmakiQVZGhKklTQ/wdzVD+xb0jCpwAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"Grover search implemented in QISKit.\n", "\n", "This module contains the code necessary to run Grover search on 3\n", "qubits, both with a simulator and with a real quantum computing\n", "device. This code is the companion for the paper\n", "\"An introduction to quantum computing, without the physics\",\n", "Giacomo Nannicini, https://arxiv.org/abs/1708.03684.\n", "\n", "\"\"\"\n", "def input_state(circuit, f_in, n):\n", " \"\"\"(n+1)-qubit input state for Grover search.\"\"\"\n", " for j in range(n):\n", " circuit.h(f_in[j])\n", "\n", "q = QuantumRegister(n)\n", "ans = ClassicalRegister(n)\n", "qc = QuantumCircuit(q, ans)\n", "\n", "input_state(qc, q, n)\n", "\n", "backend=BasicAer.get_backend('statevector_simulator')\n", "job = execute(qc, backend=backend, shots=10)\n", "result = job.result()\n", "state_vector = result.get_statevector(qc)\n", "m=display( Math('\\mathrm{state\\ after\\ initialization:\\ }' +format_vector(state_vector)))\n", "\n", "# apply T rounds of oracle and inversion about the average\n", "print('number of iterations T=%d'% T)\n", "for t in range(T):\n", " for i in range(n):\n", " qc.barrier(q[i]) # for better visualization\n", " qc.iden(q[0])\n", " # Apply T full iterations\n", " black_box(qc, q)\n", " for i in range(n):\n", " qc.barrier(q[i])\n", " qc.iden(q[0])\n", " inversion_about_average(qc, q, n)\n", "\n", "# Measure the output register in the computational basis\n", "for j in range(n):\n", " qc.measure(q[j], ans[j])\n", "\n", "# Execute circuit\n", "backend=BasicAer.get_backend('qasm_simulator')\n", "job = execute(qc, backend=backend, shots=10)\n", "result = job.result()\n", "\n", "# Get counts and plot histogram\n", "counts = result.get_counts()\n", "plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As expected, the state that is indicated by the oracle function has the highest probability of begin measured.\n", "\n", "We show the full circuit that was generated by the code." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABP0AAAG5CAYAAAD1UkGwAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nOzdeXwU9f3H8ffsJiThDAYFReSQJCBCFCgF/ZV441HRooBSqReFotYLq7a0amtFRKr2tOIFKrZAUOFX4VepQgCRCigoIgREhGAIAnKEK2R3fn+sHAsku5vs7ndm9vV8PPIwmZ2dffP1u5+d/ezsjGXbti0AAAAAAAAAnuEzHQAAAAAAAABAfNH0AwAAAAAAADyGph8AAAAAAADgMTT9AAAAAAAAAI+h6QcAAAAAAAB4DE0/AAAAAAAAwGNo+gEAAAAAAAAeQ9MPAAAAAAAA8BiafgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6AQAAAAAAAB5D0w8AAAAAAADwGJp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfAAAAAAAA4DFppgMAxzN37twab3/55Zd1880317hO79694xkJDrJw4cKI67zwwgsaMmRIjev07NkzXpEiWrlyZVy206FDh7hsBwCSIVK9dlqtlqjXqJkb90Ek5jUApCqO9IMrjR8/3nQEONyLL75oOgIAIAJqNbyIeQ0AcAqafgAAAAAAAIDH0PQDAAAAAAAAPIamH1xp3LhxpiPA4V5++WXTEQAAEVCr4UXMawCAU9D0AwAAAAAAADyGph9caejQoaYjwOEiXd0ZAGAetRpexLwGADgFTT8AAAAAAADAY9JMB0B83D3RzOM+82Mzj2tSvVkzjTxu5cWXGXlcxCbh82PDl8ddXNf5YaKG1LV+8FxEJCbmiBufixKv5wmRoHoN1MTEvE7VuufG1xgkj1v3U934nsCyrPgEiZFt20YeN1Yc6QdXuummm0xHgMPdeuutpiMAACKgVsOLmNcAAKeg6QdX4lwpiGTIkCGmIwAAIqBWw4uY1wAAp6DpB1fq16+f6QhwuCuvvNJ0BABABNRqeBHzGgDgFDT94Epbt241HQEOt2XLFtMRAAARUKvhRcxrAIBT0PQDAAAAAAAAPIamH1wpLy/PdAQ4XH5+vukIAIAIqNXwIuY1AMApaPrBlZ5//nnTEeBw48ePNx0BABABtRpexLwGAO+oV6+e2rVrZzpGrdH0+05paanuvPNOnXPOOapfv74sy9Ly5ctNx0I1nnzySdMR4HCjR482HQEAEAG1Gl7EvAYA52nZsqVGjhypGTNmqKysTJWVldq7d69WrlypiRMnavDgwcrIyAi7T7169fTGG29owYIFOuOMMwwlrxuaft9Zs2aNJk2apOzsbBUWFpqOgwj+9a9/mY7gebYt7SyXvt0g7dluOk3spk2bZjoCkNICldL2jdL2UunAXtNp4FTUalRnf0VoH2RHmRQMmE4TG+Y1YJZtSxVbQjVkN9d/THnNmzfXxIkTtW7dOv3+97/XZZddphYtWig9PV2ZmZnKz8/XoEGD9Morr6i0tFT33XeffD7foYbfFVdcIb/fL7/fb/qfUis0/b7Tu3dvlZeXa8aMGRo4cKDpOAn3wh2naPmcF8OW2batZ4c01ppFbxpKlVps29aBq69RcOUq01HC2La08RPp/RekD1+VlkySFrwgLZ4kbf/adLrU4dT5cZDbaoi9d68O9L9OwXnzDy/bv19Vd49Q1e8ekx0MGkznLYFKadVsae6z0uJ/SIv/Kc39u/TZTKlyt+l01XPrHHHbc9GLnF6v3Wb3Vmnpm9K8v4f2QRZNlOY/J335X8l25tPQk5w8r91Y99z6GuNGm1dL/50gLRwfqiEfvCz99xVpyxemk1XPzfPD6c/Hvn376rPPPtOgQYNk27b++c9/qn///mrbtq3q1aunBg0aqGvXrrr99tu1ZMkSNWvWTE8++aQWLFigGTNm6IorrtCWLVt0wQUX6NNPPzX9z6mVlGj6BYNBjR07Vrm5ucrMzFRBQYGKi4uVn5+voUOHSpJ8vpQYCklSxbaN2r29TCeeVhC2fMfmtarct0vN23U3lMx7Dlx3g4L/fuf4N27aJO3bL6ttmyQmimzt+9Ln70j7doQv314qLfmntO0rM7m8yI3zQ3JnDbGysuS79hoFJv5Dtm3LDgQU+P3jUnq6/A/eLyuFXgMSKXBAWjJF2rAk9PtBdkAq+0z68HXnNv7cOEfc+Fx0K7fWa7ep+Eb6cKK0ZW348so90hfzQh8e2LaZbF7kxnnt1rrnxtcYNypdJn0yTao46ui+Xd+EPkwoW2EmVyRunR9Ofz5ef/31euONN5STk6N///vfat++va6//noVFRVp3bp1OnDggPbs2aOPP/5Yf/vb39S9e3ddfvnlKi0t1fe//31deOGF2rZtm6sbflKKNP1uueUWPfrooxo2bJhmzpypAQMG6Prrr9fatWvVrVs30/GSrnztIlk+v3JO7RS2fMv6ZarfpLka5bQylCx6U6dONR0hInvLFmnbNll5uce/fe2XUqtWso46b4BJuzZLXy6s5kY7tKO9/G13fM1m+vTppiPUyI3z4yC31hBf3yulrdtkz39fgWf+LHvLFvkfeUhWvXTT0Txj/RJpZ1n1t+/bIa2Zl7w8sXLbHHHrc/FITq/VkrvrtduseOe7Dwyqaext+lz6Zk1SI9UK8zpx3Fz33PYa4zb7d0ur3v3uj6NryHd/f/5v6cC+ZKaKnhvnh5Ofj927d9eECRPk9/v129/+VpdeeqnWr18f8X7vvvuuVqw43B3eunWrVq1y3hHPsUgzHSDRXn/9dU2YMEFz5sw5dK6+888/Xx999JHeeOONmJt+5eXlGjx4sObPn6/c3FyNHz9eZ599diKiJ0z52kVq2iJPafWywpZ/s36ZTmrrzE/HjrZq1So1a9bMdIwa2atKpIwM6bTTJEnB4rkKTPyHVL5ZVo/uslq0kNXeWVcBKl0aYQU79Gn7li+kk/KSEqnWVq5cqRNPPNF0jGq5cX4c5NYaYmVlytf/GgWefEpqmq20Z/4gq0F907E8ww5GUUMUetOee56UnpnwSDFz2xxx63PxSE6v1ZK767Wb7Npc84cGkiRL2vCxdNLx+1SOwbxOHDfXPbe9xrjN159GPgVA8LtvHpzmwON+3Dg/nPp8zMjI0Pjx45Wenq4///nPeuSRR6K638Fz+F1yySXaunWrdu3apdzcXD300EP69a9/ndjQCeT5pt/jjz+uSy+99JiLc7Rv317p6enq3LlzTNsbPny4OnTooGnTpunVV1/Vtddeq5KSkoSe1NGyrIjr3PVa9N91KF+7SNvL1+i5n4U3zQ7sr1D3K38Z92y18dZbb9V4+69+9auI6yQqW/o7M6Jazy5ZLav96bL8fgXfmaXAhNfk/+X9sjp2UPB/31Zw3Avy3XJT1I+bqH/Pkf521xLlntq1xnVs29aDd43Sy/9nrvC99NJLEde5//77I67Xq1eveEU6xK3zw0QNqWvmaMf6GPv2yT9wgKymTWt192Q8F92oaaPmmvzQpojrBQNSQYde+vyr6g4rjh8Tc8SNz0UpcfM6Uh02Vasl99Zrr7r0e7doxIAXa17JlkpX7VB3Kzs5oY7Dyfsgkpl5nap1z42vMV728E+mqlenvvL7qm9xBAJV+tvYf+iJf/4k4Xncup/qxvcER/vJT36iTp06adWqVbr//vujus+RF+04eA6/Ro0aad68efrFL36hP/3pT9q8eXNCc8fCjuFcF55u+pWWlmr58uW65557jrlt/fr16tSp0zGXZK7Jrl279Pbbb2vjxo3KysrS0KFDNWrUKC1cuFDnnntuPKMnVPmXi/X9fo+o4/+EF7uJv+ys5g7/hMxN7FUlsvLyZO/bp8BzL8h//wj5zgwd+uy7/DIF//Z3WbntDacMF7SrZNt2xAIWdMP3ex3OjfPjILfWkOB/3lNw0mRZfS5R4M1psi7rw85zHMVSF5xaQ9w2R9z6XHQbN9drNwna0dWFaNdDzdw6r91c99z2GuM2Ue1bWM6tIW6cH059Pt5+++2SpN/+9rfaty/y97mP1/A7eA6///3f/9VVV12lW2+9VY8//nhCcyeK55t+ktSiRYuw5Xv37lVxcbEuv/zymLa3evVq5eTkhH2ttHPnzlqxYkVCm37RdHHvnhjdtrZvWqP9u79V6y591Cjn1PDle7brpBhPthlLhzkWc+fOjbhO0wiffiQqW71ZM6Naz169Wr6LL5L9yadSICCrx/cO37htmyTJOj36r00k6t9zpNXF0leLal7Hsiw99fxDGn/aQwnPU52FC6M7Qqhjx4413p6IMXXr/DBRQ+qaOdqxlqTgh4sU+Mtf5f/dI7Jyc1X1k5tlz50nq7B3zI+bjOeiG9l26Ap5e7bVvJ6/nvTZFx/Kn4RT1JiYI258LkqJm9fR1GsTtVpyb732qj3bpQUvRFjJkk4/6wSjY+jkfRDJzLxO1brnxtcYL9vw8RHn9KuG35emu399k8b886aE53Hrfqob3xMc2Rxt27atCgoKtG3btqiuA1BTw0+Sxo0bp6uuuko/+tGPjmn6ueX56OkLeRxszpWUlIQtHzNmjMrKytS1a81fYzza7t271bhx47BljRs3VkVFRd2CJlH52kVKy6h/zBV2ylYvUMOcVmrQpLmhZLEZMWKE6Qg1sjd+Le2qkJWfK23fLjXNDitGwfdmSy1ayGrY0GDKY51aIKmmD5Qsqf4JUlPnniP5kAceeMB0hGq5dX5I7qwhwc9WKDBqtPy/GCFfl86Hz5ny2j9kByOc/AVRsyzptCheVk8tUFIafrFw4xxx43PxeJxcqyV312u3qZ8tNWunmvdDbKmVC06lzbxODLfWPTe+xrjRyWd8t39RXQ2xpLRMqXl+MlNF5tb54dTn48FrNixcuFCVlZU1rhup4SdJ8+fPlyR16dJF6ekO24GNkqebfu3atVOXLl00atQovfLKK3r33Xc1fPjwQ+fYOPoiHkVFRSoqKtLixYslSbNmzVJRUZFmzgx16Rs0aKBdu3aF3Wfnzp1q6LAXxJqUr12k5m2/J58//CDPsjUfOP6Q+CP17dvXdIQa2SUlUoMGUsuWUuvWUtkmBZd8JLuqSsG58xX852RHnhw5K1s6o893fxznBTMtQ+rSN/Tm3umuvvpq0xGq5db5IbmvhthfrlPgoUfkH/ZT+c4959ByX98fSjt2yJ7r4EvJulDLAql5h+pvz24ptTun+ttNcOsccdtzsTpOrtWSu+u1G3XsI2U1Ps4N3+13tDvHHR88Mq8Tw411z62vMW506H2KT8e+j7Ekn18quMpZHzy6eX449fmYlxe62uTy5ctrXC+ahp8U6vd89dVXysjIUOvWrROSOdE8/fVen8+nKVOmaNiwYRo+fLhycnJ044036vbbb9fIkSPVpUuXsPX79+8f9ve9994rSWrdurXWrVun3NxcbdmyRVu3blVOTo6k0GR68MEHk/MPioPeNzx13OUX3PxskpPUTWFhoYqLi03HqJa9qiR0cmTLkpWfJ/v6gQqMekJKT5fV6QxZue1lnX666ZjHdcqZUlaT0Nd8t6wNLfOlhZa3/l7oNjfo1auXPvjgA9MxjsvN88NtNcRq20bpUycfuzwzU+mTX096Hq+zLOnMK6QTTpPWL5F2bw0tz2wknXq21Kqr5HfYnofV1p1zxG3Pxeo4uVZL7q7XbpTRQPrej0P1o3SZVPXdqZiyW4autun0q/YexLxODDfWPautO19j3CqnrdTjx9K6D6XylaFllk9q0SH0Pqahwy6qbbV17/xw6vPxrbfe0pdffqnPP/+8xvUuu+yyiA2/g+666y5lZGSovLw83nGTwmG73vGXl5en2bNnhy0bPHiwOnbsqKys8EtLR/pOdqNGjXTFFVfo0Ucf1ejRo/Xaa6/Jsiz17Nkz7rnhbv6fDQ3/+8bB8t842FCa2DVtFfr5z9jQ3+f9PPTpGOLD7fMDqIllSS27SKd0lt79Q2jZuUPdcYQwcDTqdfLVqy+1/4HU7lzpve/eU3a/zmwmr2Few8sanSR1/uHhpt95dzrvA0ckzooVK7RixYqI602bNk3Dhw/X+++/X2PD7+C6bpaS03/x4sW1btQ9++yzuuGGG9S0aVPl5uZq6tSp8vvphsDbaPgBiNWRTT4afgBi5fP0SYgAJAsNP1Tn73//u+kISZFyT4GKigqVlJTotttuq9X9mzdvrlmzZsU5FWLVq1cv0xHgcIm8ojYAID6o1fAi5jUAwClSrunXsGFDBQIB0zFQR6NHjzYdAQ43duxY0xEAABFQq+FFzGsAgFNw4DxcyU0XT4EZ9913n+kIAIAIqNXwIuY1AMApaPrBlZx8RTQ4w/vvv286AgAgAmo1vIh5DQBwCpp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfXKm4uNh0BDgcXwEHAOejVsOLmNcAAKeg6QdXmj59uukIcLi33nrLdAQAQATUangR8xoA4BSWbdu26RDA0ebOnVvj7YWFhRGP9uvdu3c8I6Wk/4wN/fcih12EbuHChRHX6dWrV8RP2nv27BmvSBGtXLkyLtvp0KFDXLYDJINTawiSJ1K9dlqtlqjXTuLEGuLGfRCJeY3U48T6AWd48IlxkqTRDwwN+92rONIPAAAAAAAA8BiafgAAAAAAAIDH0PSDK40aNcp0BDjcmDFjTEcAAERArYYXMa8BAE5B0w+ulJ+fbzoCHI5zzgCA81Gr4UXMawCAU9D0gytdc801piPA4fr27Ws6AgAgAmo1vIh5DQBwCpp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfXKmgoMB0BDjc2WefbToCACACajW8iHkNAHAKmn5wpWXLlpmOAIf7+OOPTUcAAERArYYXMa8BAE5B0w8AAAAAAADwGJp+AAAAAAAAgMfQ9IMrjRs3znQEONzLL79sOgIAIAJqNbyIeQ0AcAqafgAAAAAAAIDH0PSDKw0dOtR0BDjczTffbDoCACACajW8iHkNAHAKmn4AAAAAAACAx6SZDoD4uHuimcd95sdmHhdwquqfix3i8wBLjr+4rs/FerNm1m0DtVB58WVJf0ykFjfOa17PAdSFif0QN+6DSOyHILHcOq9N7IewD5JYHOkHV7rppptMR4DD3XrrraYjAAAioFbDi5jXAACnoOkHV+JcKYhkyJAhpiMAACKgVsOLmNcAAKeg6QdX6tevn+kIcLgrr7zSdAQAQATUangR8xoA4BQ0/eBKW7duNR0BDrdlyxbTEQAAEVCr4UXMawCAU9D0AwAAAAAAADyGph9cKS8vz3QEOFx+fr7pCACACKjV8CLmNQDAKWj6wZWef/550xHgcOPHjzcdAQAQAbUaXsS8BgA4BU2/I5SWlurOO+/UOeeco/r168uyLC1fvtx0LBzHk08+aToCHG706NGmIwAAIqBWw4uY1wAAp6Dpd4Q1a9Zo0qRJys7OVmFhoek4qMG//vUv0xE8rapSKl16+O9l06QtX0h20FymWE2bNs10BCBl7d0hrZl7+O+Vs6SKb8zlgXNRq3E025a+LZWWv3142boPpco95jLFinkNmBOokspWHP7746nSppVSMGAuE2ASTb8j9O7dW+Xl5ZoxY4YGDhxoOk5CvXDHKVo+58WwZbZt69khjbVm0ZuGUsEJKr6RFrworfzP4WXfrJGWvil9NCXUEER8ue35aO/dqwP9r1Nw3vzDy/bvV9XdI1T1u8dkB13UHUbcfb1cev+F0Jv0g0qXSQsnSGs/MJcrErfOa7fVD6AmwaD02UxpyT9Db9IPWjNXev95adt6c9m8ym01xK21Gsmxb5f031ekz2YcXrZ1nbT8X9KHr0r7dxuLViM3z2u31ZBUlDJNv2AwqLFjxyo3N1eZmZkqKChQcXGx8vPzNXToUEmSz5caw1GxbaN2by/TiacVhC3fsXmtKvftUvN23Q0lg2lVldJHRcf5NN0O/efbDdKK/0t6LE9z4/PRysqS79prFJj4D9m2LTsQUOD3j0vp6fI/eL+sFKmlONahGmEf//a174eagk7kxnntxvoB1GTtfGnTwSN0jqojgSpp6RvS3u1Jj+VZbqwhbqzVSA47KH1cJO359ugbQv+p2CotezN0NLHTuHVeu7GGpCJnzp4EuOWWW/Too49q2LBhmjlzpgYMGKDrr79ea9euVbdu3UzHS6rytYtk+fzKObVT2PIt65epfpPmapTTylCy6E2dOtV0BE/atEKq3K1q37BL0uaS47yYOtD06dNNR4iKW5+Pvr5XSlu3yZ7/vgLP/Fn2li3yP/KQrHrppqPBoHUfSrIirPNfZ+5wS+6b126tH0dyS61G4lXtl9Z/VMMKthSsCj/9iFO5ZV67tYa4rVYjObZ+Ke3equrfx9jSzk2hDyidyI3z2q01JNWkmQ6QDK+//romTJigOXPmHDpX3/nnn6+PPvpIb7zxRsxNv4cfflhTpkzRypUrNXnyZF177bWJiH2IZUV4ByXprteifwdVvnaRmrbIU1q9rLDl36xfppPaxtaNjyZbbbz11ls13r5kyRL16NGjxnUSlc3Lxv7sPXVu21s+n7/G9W655kFNmv1EklId66WXXoq4ztKlS3XWWWfVuE6vXr3iFemQWJ6LUvyej3Wd7+nvzIi80pGPl5UpX/9rFHjyKalpttKe+YOsBvVj2wbPUU/Jymiotx7dIZ9V8+eJe76V2p3SWes2Jf6QPzfOa6+9nkeq16ZqdU3uueeeuGzn6aefjst2UkXvLv31m8GTa1zHtm0tefdr5Z1/apJSHcvJ+yCSmRrixn0Qif0Qr/nFwPG6sOuP5fdV3+IIBAP67T3j9Kc3bkt4HrfOazfWkFg9MPq5Q4975O9uYsfwCXpKNP0ef/xxXXrppcdcnKN9+/ZKT09X586dY9pebm6u/vjHP+o3v/lNPGMmTfnaRdpevkbP/axZ2PID+yvU/cpfGkoVm1GjRkVsDCJ2DbOaRmz4Be2gGmQ2SVKi2vvTn/4U1Y65aa5/Pu7bJ//AAbKaNjWdBIbVz2gUseF3kONriEvmtevrh9xTq5F40dQFy7LUILNxEtLUjVvmtetriEtqNZIjqn0L22YfJI5cX0NShOebfqWlpVq+fPlxP7Vdv369OnXqpIyMjJi2ecMNN0iSHnvssbhkjCSaLu7dE6PfXvmXi/X9fo+o4//8JGz5xF92VvMYjwyIpcMci7lz50Zcp2mEQpiobF629E1py1rV+PVen+XTI4/9Ui/OMFfIFy5cGNV6HTt2rPH2RMyRWJ6LUvyej3X9t9SbNTOm9YP/eU/BSZNl9blEgTenybqsT8yfkPEc9ZZAlVT8l9DX7yJZtHS+spKwz+3Gee211/No6rWJWl2TlStXRl4pCk899VRctpMqtnwpLY3i7C3NTm5k9PXDyfsgkpka4sZ9EIn9EK9Z+a5U+nHN6/j9abp52CCNmjgo4XncOq/dWENi9eAT4w497pG/e5Xnz+lXWloqSWrRokXY8r1796q4uDjlzue3fdMa7d/9rVp36aNGOace+gkc2Kf9e7brJE62mdJO6awaG36S5PNLLWrej0WU3Pp8DH64SIG//FX+h38j/20/k7Zvlz13nulYMMyfJp18RoSVLKnpaUpKwy9WbpvXbq0fQHVOaC1lNIy8XsuCyOsgMrfWELfVaiTPKWfGd71kcuO8dmsNSUWeb/o1axY61LSkpCRs+ZgxY1RWVqauXbuaiGVM+dpFSsuof8wVdspWL1DDnFZq0KS5oWSxGTFihOkIntSsnZQd4TQ5bXpK6ZnJyVMXDzzwgOkIEbnx+Rj8bIUCo0bL/4sR8nXpfPj8I6/9Q3YwaDoeDGvdQ0rL0PEv5mFJliWd/j/JThWZG+e1G+vH8bihViM5fD4pt7CGFSypflNnvmE/mhvmtRtriBtrNZKncXOpeYea12nZRWpwQnLyRMut89qNNSRVeb7p165dO3Xp0kWjRo3SK6+8onfffVfDhw8/dJ6No4/0KyoqUlFRkRYvXixJmjVrloqKijRzZmyH5zpV+dpFat72e/L5w7/ZXbbmg5i/CmRS3759TUfwJJ9POutHUrPTj73N8kvtzpXa9kx+rtq4+uqrTUeIyG3PR/vLdQo89Ij8w34q37nnHFru6/tDaccOx38iicSrny11u+74R/LVy5LOukbKPiX5uWri1nnttvpRHTfUaiRPi45Sxz6Sv96xtzVpIXUb+N0HCw7nhnntthri1lqN5Op0WaixdwxLOvVsKf+ipEeqkZvntdtqSCrz/Dn9fD6fpkyZomHDhmn48OHKycnRjTfeqNtvv10jR45Uly7hVaF///5hf997772SpNatW2vdunXJip0wvW84/vllLrj52SQnqZvCwkIVFxebjuFJaRmhxt/urdIHL4eW5V8oteggpWfVfF8n6dWrlz744APTMWrktuej1baN0qcee2VFKzNT6ZNfT3oeOFOjE6VzbpW2fSV9XBRa1rmvdOLpodMDOI3V1p3z2m31ozpuqNVIrpadpRb5UvkqacW/Q8t63CA1blHz/ZzEDfPabTXEauvOWo3k8vmljpeEDlKYHzpVm3ILQx8oRHP6gGSz2rp3XruthqQyzzf9JCkvL0+zZ88OWzZ48GB17NhRWVnhXYxoTuB44MABBQIBBYNBHThwQPv27VNGRobrLvMM1KRBzuHfW51tLgcA97EsKafN4b+b5xmLAsCF/PVC5xk+2PRzU8MPgHlHXuS79ffM5QCcwPNf763O4sWLa30Rj5/+9KfKysrSvHnzNGjQIGVlZemrr76Kc0IAAAAAAACgdlKy6VdRUaGSkpJaX8Rj/Pjxsm077KdNmzbxDYka9erVy3QEONy5555rOgIAIAJqNbyIeQ0AcIqU+Hrv0Ro2bKhAIGA6Bupg9OjRpiPA4caOHWs6AgAgAmo1vIh5DQBwipQ80g/u9+CDD5qOAIe77777TEcAAERArYYXMa8BAE5B0w+u5PQrosG8999/33QEAEAE1Gp4EeCrCqcAACAASURBVPMaAOAUNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT+4UnFxsekIcDi+Ag4AzkethhcxrwEATpGSV+/1omd+bDpBck2fPl19+/Y1HQMO9tZbb+nqq69O+uNW91xcuXJlXLbfoUOHuGznaJUXX5aQ7QImuXFep9rrualaDSSSyXntxv0QN9ZqIBK3zutU2w9JBRzpB1f6wx/+YDoCHO6JJ54wHQEAEAG1Gl7EvAYAOAVNPwAAAAAAAMBjaPoBAAAAAAAAHkPTD640atQo0xHgcGPGjDEdAQAQAbUaXsS8BgA4BU0/uFJ+fr7pCHC4RF3wAgAQP9RqeBHzGgDgFDT94ErXXHON6QhwOK7uDADOR62GFzGvAQBOQdMPAAAAAAAA8BiafnClgoIC0xHgcLfeeqvpCDH7y1/+YjoCACSVG2u1RL1GzZjXAACnoOkHV1q2bJnpCHC4IUOGmI4Qs7/+9a+mIwBAUrmxVkvUa9SMeQ0AcAqafgAAAAAAAIDH0PQDAAAAAAAAPIamH1xp3LhxpiMAcVdUVGQ6AgAgCtRreBHzGgC8h6YfAAAAAAAA4DE0/eBKQ4cONR0BiLtrr73WdAQAQBSo1/Ai5jUAeA9NPwAAAAAAAMBj0kwHQHzcPdHM4z7zYzOPaxJjnTzVj3XPuGz/n18cfzljnRx1Hed6s2bGJ0iMKi++rE73d+NYu5Ubx9p787ru9ZpaHc6N89qN2AdJHrfuW5uo127cB5GY18mUivMaNeNIP7jSTTfdZDoCEHe333676QgAgChQr+FFzGsA8B6afnClm2++2XQEIO7uuOMO0xEAAFGgXsOLmNcA4D00/eBK/fr1Mx3Bs2xb2rNd2rTy8LJ1H0pb1kqVe8zlSgW9e/c2HQGos2BA2rlJKl12eNmGj6TtG6XAAXO5gHiiXidO1X5p23rpq8WHl339mVSxJbSPgsRhXsML9u2UNq8+/PeX/5U2r5H27TKXCTCJc/rBlbZu3Wo6gucEqqSyz6TSpVLFN+G3rZl7+Pdm7aRWZ0sntJEsK6kRPe+bb76JvBLgUPt2SaUfSxs/lQ7sDb9t1Xuh//rrSSefIbXqKjU4IfkZgXihXsffjjJp/RJpc4lkB8NvW/HdKaaymkgtC6RTC6S0jORn9DrmNdzKDoYOWChdKu34Ovy2L+Yd/j371ND7mJPyeB+D1EHTD4B2lEkr/k/aHUUvdcva0M+JuVKHi6SMBonPB8C5bFv6+lOpZI4UqKx53UBlaId84ydSu3Ok1j0kH985AFJaVaW0pjj86ODq7N0R+iByw0dSx0tCH0QCSG27t4Xexxzd7Due7aWhn6atpI59pPrZic8HmMauNlwpLy/PdATP2PS5tOj16Bp+R/pmtfThq7HfD9U744wzTEcAYmIHpRX/lj5/J3LD7+j7fTFfWvoGX/mFO1Gv42N/hbRoYnQNv6Pvt/QNad1/E5MrVTGv4Tbbvgq9H4mm4XekbzdI/30l1AAEvI6mH1zp+eefNx3BEzavkZbPkFTLc+Tsr5CWTA6dOwN1N3XqVNMRgJisfFcqW177+29bJ30y/div8gFOR72uu6r90kdT6vbh4Zp50vqP4pcp1TGv4SY7vpaWvln7Dw8DldLHU6Vdm+ObC3Aamn5HKC0t1Z133qlzzjlH9evXl2VZWr68Du9mkDBPPvmk6Qiut3936FD4mhp+F90X+qlJ5e7QkT6cXLvuHnroIdMRgKhtXi1tjHB0TjQ1ZOuXvGmH+1Cv665kTuSGXzQ1ZPWcY89FjNphXsMtApWhAxeCVdWvE039CByQlr9d83YAt6Ppd4Q1a9Zo0qRJys7OVmFhoek4qMG//vUv0xFcb/UcqWpffLa17SupbEV8tpXKpkyZYjoCEJXAAWnlrPht74t5HDEMd6Fe1823paFzgcaDHZRWvMOHj/HAvIZbfLlQ2rs9PtvavVVatyg+2wKciKbfEXr37q3y8nLNmDFDAwcONB0noV644xQtn/Ni2DLbtvXskMZas+hNQ6m8yYljvW9X6ApX8bR+ifkdbieOtVe5baztvXt1oP91Cs6bf3jZ/v2qunuEqn73mOygc79f6sSx3rRSqtwTv+0FA6GLe5jmxLGuCfMa0XDiWK9fEt/t7SwL/ZjmxLH2IjeOs1vrtRPHOnAg9vOARlL6cWhfxCQnjnUkbp3XqSZlmn7BYFBjx45Vbm6uMjMzVVBQoOLiYuXn52vo0KGSJF+KXEKwYttG7d5ephNPKwhbvmPzWlXu26Xm7bobSuY9Th3rss9U6/P4Vadis7SrPL7bjOnxHTrWXuTGsbaysuS79hoFJv5Dtm3LDgQU+P3jUnq6/A/eL8uh9d+pYx2vI3SOtPFTsx8cOHWsa8K8RiROHOvKPdI3a+K/XdMfHDhxrL3IrePsxnrt1LHevDp0TtB4qtwjbfkivtuMhVPHOhI3zutUlDL/F2655RY9+uijGjZsmGbOnKkBAwbo+uuv19q1a9WtWzfT8ZKqfO0iWT6/ck7tFLZ8y/plqt+kuRrltDKULHpuOdGwU8d6+8YEbTfGK2fFk1PHOhbFxcWmI0TFrWPt63ultHWb7PnvK/DMn2Vv2SL/Iw/JqpduOlq1nDjWwSpp56b4b7dyt7R3R/y3Gy0njnU0mNdmUK9rb0eZ4v7Bo2R2H0Ry5ljHyg3z2s3j7LZ67dSx5n2Ms7htXqeilGj6vf7665owYYKmT5+u++67T+eff75GjhypXr16qaqqKqam3/79+3XTTTepZcuWys7O1gUXXKDPP/88genjr3ztIjVtkae0ellhy79Zv0wntXXmpwhHW7VqlekIUXHqWCfqKlUmj/Rz6ljH4rPPPjMdISpuHWsrK1O+/tco8ORTsj/5RGmjHpXVoL7pWDVy4lhXbE3c1XapIbFjXptBva69RO2D7NkWOrm/KU4c61i5YV67eZzdVq+dOtYJex9j8Cq+Th3raLhtXqeiNNMBkuHxxx/XpZdeeszFOdq3b6/09HR17tw56m1VVVWpffv2euyxx9SiRQs98cQTGjhwoD75JHHfKbAsK+I6d70W/Uem5WsXaXv5Gj33s2Zhyw/sr1D3K38Z92y18dZbb9V4+69+9auI6yQqmxfG+u3H96leWsahvyNd2aq62/8zNvzvqZOn6czLr65jusO8MNYH3XPPPRHXefrppyOu9/TTT8crUhgTY13XcU5/Z0bt7rhvn/wDB8hq2rRWd69rbjeO9ZHOzr1QY4b+J2xZvGrILTcO1Yz/Pl+HdOHcONbMazPz+kjU62PFc6x/duVTuqZ3+NjFq4Y0P/EUbY3Tyf1iGWfJmWN9JCfPa7fu75mo126s1VJ85/XL96/SqSfmhS2rqYZEWz8WffCxug/sWsd0h7l1rN04r2P1wOjnDj3ukb+7iR3DOXE83/QrLS3V8uXLj/sCtn79enXq1EkZGRnHuefxNWjQQL/+9a8P/f3zn/9cI0eO1L59+5SZmRmXzIlW/uVifb/fI+r4Pz8JWz7xl53V3OGfJLiNU8c6mKAz1SZqu9Fw6lh7kVvHOvif9xScNFlWn0sUeHOarMv6OP4F3oljncjnOTUkdsxr1MSJYx20E1hDEnUYchScONZe5OZxdlu9dupY8z7GWdw2r1NRSjT9JKlFixZhy/fu3avi4mJdfvnlddr+ggUL1KZNm4Q2/KLp4t49Mbptbd+0Rvt3f6vWXfqoUc6p4cv3bNdJMZ4kNJYOcyzmzp0bcZ2mET5FSFQ2L4z1By9Ju7cd/vvoT7oOOvjJWHW3H23QTf30yIT45fTCWB+0cmXkyyU//fTThy4sVJ2nnnoqXpHCmBjruo5zvVkzo143+OEiBf7yV/l/94is3FxV/eRm2XPnySrsHfPj1jW3G8f6SHu3S++/EL4sXjVk4pQXdULrFyOvGCU3jjXz2sy8PhL1+ljxHOv1H0kl74Uvi0cN8aVJW7ZvUrzOGx/tOEvOHesjOXleu3V/z0S9dmOtluI7rz8ukrauC192vBoR6z7IuRd0l/1H3se4cV7H6sEnxh163CN/9yrPn9OvWbPQIbIlJSVhy8eMGaOysjJ17Vr7Q3i//fZb3X777XrsscfqlDGZytcuUlpG/WOuDFS2eoEa5rRSgybNDSWLzYgRI0xHiMjJY92oReR1arVdQ/8kJ491LH7729+ajhCRG8c6+NkKBUaNlv8XI+Tr0vnwuUde+4fsoLmjQiJx6lhnNpHSEvQ5FzUkesxrs6jXtdc4QQ/b6CTFreEXK6eOdaycPq/dOs5urNdOHutE7SskqjZF4uSxrokb53Wq8nzTr127durSpYtGjRqlV155Re+++66GDx+ul156SZKOuYhHUVGRioqKtHjxYknSrFmzVFRUpJkzwzvee/fuVd++fTVw4EANGjQoOf+YOChfu0jN235PPn/4QZ5laz5w/KHDR+rbt6/pCBE5eaxz2sR/m5ZPOuG0+G83Gk4e61gMGDDAdISI3DbW9pfrFHjoEfmH/VS+c885tNzX94fSjh2y584zmK5mTh1ry0pMDWl8spRu6CwZTh3r6jCvzaNe117j5lJ6VuT1YpXTNv7bjJZTxzpWTp/Xbhxnt9ZrJ491op7rpmqIk8e6Om6d16nK81/v9fl8mjJlioYNG6bhw4crJydHN954o26//XaNHDlSXbp0CVu/f//+YX/fe++9kqTWrVtr3bp1kkIX8xgwYIByc3NddZSfJPW+4fiH5F9w87NJTlI3hYWFKi4uNh2jRk4e6+Z5Usls6cDe+G3zpFwpo2H8thcLJ491LDp27Oj4q4G7bayttm2UPnXyscszM5U++fWk54mFk8f61LOk8sjfFIt5m6Y4eayPx2rLvDaNel17vjTplM7SVx/Gb5uWT2oZ/XX54s6pYx0rp89rN46z1dad9drJY53dUmrQTNq9JX7bbHyyuSP9nDzW1bHaunNepyrPN/0kKS8vT7Nnzw5bNnjwYHXs2FFZWeEfNUbzXe4hQ4YoGAxq3Lhxcc0JJIsvTWrzfWn1nPhsz/KFtgcgNWS3DB3Zu219fLZX/wSpeX58tgXA+U7rKm1cJlXtj8/2WhaY++ARQHJZlnT6OdIn0+O3zXa94rctwGk8//Xe6ixevPiYr/ZG46uvvtKECRP03nvvKTs7Ww0bNlTDhg21fn2c3vkASXJaV6nJKfHZVtueoXPpAEgNliV17CP50+OxManTpZI/JT6GBCCFGnR5F8RnW1lNpPY/iM+2ALjDSXnx+7Dw5DOlZu3isy3AiVJyF7uiokIlJSW67bbbYr5v69atPX1lF7fo1YuPY+rK8kmdr5QW/0Pat/P460RztasT20ttesY3W6o677zzTEcAopbVROr8Q2nZNMmu5nzN0dSQDhfG7wMIIFmo13V38hnSrnJpw0fVrxOphqRlSF2ultLqxTdbqmJew006XiLt+Vbatfn4t0ezD9LkZCk/Th9AAE6Vkkf6NWzYUIFAQD//+c9NR0EtjR492nQET8hsJHW/Tmp4Yu3uf3KnUOPQ1NXyvObZZ5177g7geJqdLhVcHXrjHSvLHzpa0OS5/IDaol7XnWVJeefX/vQgmY2kbgOlRrXch8GxmNdwk7QMqesAqWmr2t0/p410dn8+NID38VYdrvTggw+ajuAZmY2lHjdIbXuF3oRHo14DqUtfqdNlki/K+yCy4cOHm44AxKxZO6nXzaEGYLSanCL1/InZE+8DdUG9jg/LCn01t9tAqX7TaO8UOodfz5s5tUi8Ma/hNumZocZf3gXRn3IkLUPqcLF01jU0/JAaUvLrvXC/Dz74wHQET/H5pdPPlVqdLX29XNq8Wqr4RgpWHV4nPVNq3CJ0dN9JuaGLgSC+5syZYzoCUCsZDaWzfhSqG6XLQhf42LMtfJ2sJqELgLQsCDX9LMtMViAeqNfx1bRV6MODrV9KG5dLO76WKncfvt3yha7W2ayt1LJLqJ4g/pjXcCPLCp2r/JROUtkKqXxV6NQBgQOH1/HXC12dt3kHqUVHmn1ILbxtB3BIvfpSmx6hn2BA2r8r9F9/vdCbet6kA6hJwxOlDheFfq+qDL1pt+1QbUnPNJsNgLNZvtARwwePGt6/W6raF1qe0YiL/QCoWVpG6ACGVmeHzjW8b1foAAZ/eqiG8D4GqYqXTwDH5fNLWdmmUwBwq7R6fJIOoPYyGoR+ACBWlo8jgoGDOKcfXKm4uNh0BCDuPv/8c9MRAABRoF7Di5jXAOA9NP3gStOnTzcdAYi7yZMnm44AAIgC9RpexLwGAO+xbNu2TYcAjjZ37twaby8sLIx4tF/v3r3jGQkOsnDhwrhsp2fPnnHZTjRWrlwZcZ2OHTtG/JS9Q4cO8YoEAAkXj3qdzFotUa9RMzfug0jMawA46MEnxkmSRj8wNOx3r+JIPwAAAAAAAMBjaPoBAAAAAAAAHkPTD640atQo0xGAuPvb3/5mOgIAIArUa3gR8xoAvIemH1wpPz/fdAQg7jp16mQ6AgAgCtRreBHzGgC8h6YfXOmaa64xHQGIu8LCQtMRAABRoF7Di5jXAOA9NP0AAAAAAAAAj6HpBwAAAAAAAHhMmukAwPH07t27xtsffvjhiOvAu3r27Gk6Qsw6dOgQcZ2HH344qvUAwC2o1/AaN85piXkNAKnKsm3bNh0CAAAAAAAASKQHnxgnSRr9wNCw372Kr/cCAAAAAAAAHkPTDwAAAAAAAPAYmn4AAAAAAACAx9D0AwAAAAAAADyGph8AAAAAAADgMTT9AAAAAAAAAI+h6ZdCLr74YhUUFKhLly669tprtXPnTtORAAAAAAAAXGHOnDnq1KmT2rdvryFDhigQCJiOVCOafimkqKhIy5Yt0yeffKLTTjtNTz31lOlIAAAAAAAAjhcMBjVkyBBNmTJFa9as0c6dO/Xaa6+ZjlUjmn4ppEmTJpJCE3X37t2yLMtwIgAAAAAAAOdbtGiRTjnlFJ1xxhmSpFtvvVVTp041nKpmNP1STN++fdWiRQutWrVKI0aMMB0HAAAAAAAgIWzb1p59+w/9HHT07wd/9u+vrHZbpaWlatWq1aG/TzvtNG3YsCExweMkzXQAJNf06dMVDAY1cuRIPffcczT+AAAAAACAZ736xjv6ckNZ2LLf/XHCcX+/6uJz1atrp+Nux7btsG9M2rYd56Txx5F+Kcjn8+mmm27S+PHjTUcBAAAAAABICMuy9MMLeymak5udlNNUPc7qWO3trVq10vr16w/9vWHDBp166qlxSJk4NP2+s2jRIl1++eXKzs5WgwYN1LNnT02ePNl0rLjZuXOnysoOd7anTp2qTp2O370GAAAAAADwgpbNm6lbl/yI6/3wwl7y+6pvk3Xv3l0bN27UihUrJEkvvvii+vXrF7ecicDXeyXNnj1bffr0UWZmpq677jo1atRIU6dO1cCBA7VhwwZPfAV2x44d6tevn/bt2yfLstShQwf9+c9/Nh0LAAAAAAAgofr84Hv6ZOVaVVYeOO7tHU4/TXltaz5qz+/36/nnn9e1116r/fv3q7CwUIMHD05E3LixbDd8CTmBqqqq1KFDB5WWlmrhwoU666yzJIWaZD169NC6detUUlKi1q1bG06aOLsq9qhBgyz5uJovAAAAAADwoDkLl+r/ij88ZrnPZ+meW/rrxJxsA6kSKyW+3jtt2jT98Ic/1EknnaSMjAy1bt1agwYN0qeffqr33ntPX3zxhQYNGnSo4SdJTZo00a9+9StVVlZqwoQJNWzd3Wzb1ktTZmriW7NMRwEAAAAAAEiIc7ufqROaNDpmea+unTzZ8JM83vSrqqrSddddp6uvvlrLli1Tv379dNddd+nss8/W1KlTtXHjRs2ZM0eSdMkllxxz/z59+kiSiouLkxk7qVas+Uplm7fqjPZtTEcBAAAAAABIiPS0NF12/vfDltXPytCF53YzlCjxPH1OvzvuuEOTJk3ST3/6Uz399NNq0KDBods2bNig7Oxsvfjii5Kk3NzcY+7fokULNWzYUKtXr05a5mSybVv/mb9EOdmNdVan9qbjAAAAAAAAJMyZeW3VttXJ+nJD6EKnF/9Pd9XPzDCcKnE8e06/efPmqXfv3rr00ks1Y8YMWdWcr+6SSy7RrFmztHr1arVvf2zjq2XLlqqoqNCOHTsSlvXBJ8YlbNsAAAAAAADwhtEPDI16Xc9+vfeZZ56RJI0ePbrahh8AAAAAAADgRZ79eu+sWbPUpk0bFRQU1LhekyZNJKnaI/l27typpk2bxj3fkWLp0sbLZ6vX6dU33lH/y89Tt855SX98AAAAAAAAEyorD6hevXTTMRLOk02/7du3a9euXerWLfLJGA+ey2/16tXHrL9p0yZVVFSoR48eCcl5kMmv906ZMUdTZswx9vgAAAAAAACITsp/vffgaQo3b94ccd3CwkJJ0jvvvHPMbf/+97/D1gEAAAAAAADcwLMX8mjfvr3Wrl2rd955RxdddFHYbatWrVJ+fr4kqaqqSvn5+dq4caMWLlyos846S1Lo6749evTQunXrtGrVKrVp0ybZ/4SEsG1bfxr/hioPHNC9QwbI7/Nk3xcAAAAAACClebbpN3nyZA0cOFB+v19XXXWV2rdvr82bN2vBggU644wz9Oabbx5ad/bs2erTp48yMzN13XXXqVGjRpo6daq++uorjR07ViNGjDD4L4mvQ+fyu+I8dTuTc/kBAAAAAAB4kWebflLo67lPPvmkFi1apH379umkk05Sjx49dPfdd+sHP/hB2LoffvihHn74YS1YsEAHDhxQ586dde+992rgwIGG0ifGxk1b9MFHn+lHl/6Ao/wAAAAAAAA8ytNNPwAAAAAAACAVcagXAAAAAAAA4DE0/QAAAAAAAACPoekHAAAAAAAAeAxNPwAAAAAAAMBjaPoBAAAAAAAAHkPTDwAAAAAAAPAYmn4AAAAAAACAx9D0AwAAAAAAADyGph8AAAAAAADgMTT9AAAAAAAAAI+h6QcAAAAAAAB4DE0/AAAAAAAAwGNo+gEAAAAAAAAeQ9MPAAAAAAAA8BiafgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6AQAAAAAAAB5D0w8AAAAAAADwGJp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfAAAAAAAA4DE0/QAAAAAAAACPoekHAAAAAAAAeAxNPwAAAAAAAMBjaPoBAAAAAAAAHkPTDwAAAAAAAPAYmn4AAAAAAACAx9D0AwAAAAAAADyGph8AAAAAAADgMTT9AAAAAAAAAI+h6QcAAAAAAAB4DE0/AAAAAAAAwGNo+gEAAAAAAAAeQ9MPAAAAAAAA8BiafgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6AQAAAAAAAB5D0w8AAAAAAADwGJp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfAAAAAAAA4DE0/QAAAAAAAACPoekHAAAAAAAAeAxNPwAAAAAAAMBjaPoBAAAAAAAAHkPTDwAAAAAAAPAYmn4AAAAAAACAx9D0AwAAAAAAADyGph8AAAAAAADgMTT9AAAAAAAAAI+h6QcAAAAAAAB4DE0/AAAAAAAAwGNo+gEAAAAAAAAeQ9MPAAAAAAAA8BiafgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6AQAAAAAAAB5D0w8AAAAAAADwGJp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfAAAAAAAA4DE0/QAAAAAAAACPoekHAAAAAAAAeAxNPwAAAAAAAMBjaPoBAAAAAAAAHkPT7zulpaW68847dc4556h+/fqyLEvLly83HQsAAAAAAACIGU2/76xZs0aTJk1Sdna2CgsLTccBAAAAAAAAao2m33d69+6t8vJyzZgxQwMHDjQdBwAAAAAAAKi1lGj6BYNBjR07Vrm5ucrMzFRBQYGKi4uVn5+voUOHSpJ8vpQYCgAAAAAAAKSANNMBkuGWW27Rm2++qd/85jfq1q2bFixYoOuvv17ffPON7r33XtPxAAAAAAAAgLjy/OFtr7/+uiZMmKDp06frvvvu0/nnn6+RI0eqV69eqqqqUrdu3WLaXnl5uS655BLVr19fBQUF+vjjjxOUHAAAAAAAAKgdzx/p9/jjj+vSSy895uIc7du3V3p6ujp37hzT9oYPH64OHTpo2rRpevXVV3XttdeqpKREfr+/1hnvvvtuSdIzzzxz3Nsty6r1tgEAAAAAAOANtm1Hva6nj/QrLS3V8uXL1b9//2NuW79+vTp16qSMjIyot7dr1y69/fbbeuihh5SVlaWhQ4cqEAho4cKFdcq5dOlSLV26tE7bAAAAAAAAAA7y9JF+paWlkqQWLVqELd+7d6+Ki4t1+eWXx7S91atXKycnR82aNTu0rHPnzlqxYoXOPffcugeuhm3bOu+88yRJc+bMSdjjAAAAAAAAwBs8faTfweZcSUlJ2PIxY8aorKxMXbt2jWl7u3fvVuPGjcOWNW7cWBUVFXULCgAAAAAAAMSRp4/0a9eunbp06aJRo0bphBNOUMuWLVVUVKQZM2ZI0jEX8SgqKpIkLV68WJI0a9YsrVy5Ug0aNNBll12mBg0aaNeuXWH32blzpxo2bJiEfw0AAAAAAAAQHcuO5QyALlRSUqJhw4bpww8/VE5Ojm688UY1atRII0eO1M6dO5WVlXVo3eoumNG6dWutW7dOu3btUrNmzfT1118rJydHktS2bVu99tprdfp6bzRf3eXrvQAAAAAAAIiWp4/0k6S8vDzNnj07bNngwYPVsWPHsIafFPkKKI0aNdIVV1yhRx99VKNHj9Zrr70my7LU20d2nwAAGClJREFUs2fPuOcGAAAAAAAAasvzTb/jWbx4ca0bdc8++6xuuOEGNW3aVLm5uZo6dar8fn+cEwIAAAAAAAC1l3JNv4qKCpWUlOi2226r1f2bN2+uWbNmxTkVAAAAAAAAED8p1/Rr2LChAoGA6RgAAAAAAABAwvhMBwAAAAAAAAAQXzT9AAAAAAAAAI+h6QcAAAAAAAB4DE0/AAAAAAAAwGNo+gEAAAAAAAAeQ9MPAAAAAAAA8BiafgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6AQAAAAAAAB5D0w8AAAAAAADwGJp+AAAAAAAAgMfQ9AMAAAAAAAA8hqYfAAAAAAAA4DE0/QAAAAAAAACPoekHAAAAAAAAeAxNPwAAAAAAAMBjaPoBAAAAAAAAHkPTDwAAAAAAAPCYNNMBEB+WZRl5XNu2jTwuAAAAAAAAqseRfgAAAAAAAIDH0PQDAAAAAAAAPIamHwAAAAAAAOAxNP0AAAAAAAAAj6HpBwAAAAAAAHgMTT8AAAAAAADAY2j6pSi/369OnTrpwgsv1EUXXaROnTrJ7/dXu36TJk10xx13JDEhAAAAAAAAaivNdAAnKS0t1ZgxY7R48WItXbpUe/fu1aeffqozzzzTdLS48Pv9uvLKK/Wzn/1MP/jBD1S/fv2w2/fs2aP58+frueee0/Tp01VVVSUp1PB755131KNHD9WvX19jxowxER8AAAAAAABR4ki/I6xZs0aTJk1Sdna2CgsL/7+9e4/SsizYBX7NDOdDgBCCIBABgiKjQoiHYNQPJfO0CUXx1PZL8JDHWpVZkZZ4SE1tfbrRlsH6tmiFka00TQ3QYrd1bIFiJCnKQRHTUsSUw8zsP9ywHEEYZIaRZ36/tWatd+7nfu73elnDP9e6n/du7Dj1atiwYVmwYEFmzZqVo446Km3atMmLL76YRx99NI8++miWLFmSNm3a5Mgjj8y9996bp59+OgceeGCtwm/JkiW5++67G/ujAAAAALANdvp9wMiRI7Nq1aokybRp0/Lggw82cqL6cdFFF+WGG25IWVlZlixZkltuuSV33XVXXn/99VrzOnfunAkTJuTCCy/MoEGD8qc//Skvv/xyevXqlSVLlqSioiLLly9vpE8BAAAAQF01mZ1+1dXVuf7669O/f/+0atUq5eXlmTt3bvbaa69MnDgxSVJaWrx/josvvjg33XRTysrKcv3112efffbJzTffvFnhlyRvvPFGfvKTn2Tw4MGb7unVq1feeOMNhR8AAADALqTJ7PQ766yzMmvWrHz3u9/N0KFDM2/evJxyyin5xz/+kUsvvbSx4zWIESNG5IYbbkjy/uf/2c9+Vqf7WrVqlYMPPjhJUlNTk06dOqV3795KPwAAAIBdRPG2tm3BjBkzMn369PzmN7/J17/+9Rx22GG5/PLLc9BBB2XDhg0ZOnTodq03efLk7L333iktLc3MmTMbKPWOad68eaZNm5bS0tJcffXVdS78Pvwdfj/5yU9SWlqaO++8My1atGjg1AAAAADUhyax0+/qq6/OmDFjNjuco1+/fmnevHn23Xff7Vqvf//+ufnmm/Pd7363PmN+pJKSki2+3pqxY8dmr732ynPPPZcrrriiTvd8uPCrqKjIqlWrMnr06AwaNCjjxo3LjBkzPjIbAAAAAA2npqamznMLv9NvxYoVWbhwYU488cTNri1btiz77LNPWrZsuV1rnnbaaRk9enRatWpVXzHr3TnnnJMk+fGPf5y1a9duc/6WCr/ly5dn3bp1ufHGG5Mk5557boNmBgAAAKB+FH6n34oVK5Ik3bp1qzX+7rvvZu7cuTn66KMbI9Z2qampSUVFRZJkzpw5W5zzwR13LVu2zCGHHJKqqqrNduZtyUcVfhvdfffdue2223LQQQelTZs2+fe//10rGwAAAACfLIXf6delS5ckyeLFi2uNX3fddVm5cmUOOOCAxojVoIYMGZLmzZtn0aJFefvtt7c6d1uFX5K88847efbZZ1NWVpby8vKGjA4AAABAPSj8Tr++fftmyJAhmTJlSnbbbbf06NEjM2fOzAMPPJAkmx3isfFgjsrKyiTJww8/nL/97W9p27ZtvvCFL+zc8B9Tjx49kiQvvPDCVufVpfDb6Pnnn095eXn22GOPes8LAAAAQP0qqWkCz2cuXrw4kyZNyhNPPJHOnTvnzDPPTPv27XP55Zdn9erVad269aa5H3UwRe/evfPSSy/VGquoqMhXv/rVjBs3bofybevR3brM+WDu0tLStG3bNiUlJVm9evVHrrnHHntk7ty5KS0t3WrhlyTt27dP8v6uv+rq6k3jTeDPBwAAAGCXU/idfkkyYMCAzJ49u9bY6aefnkGDBtUq/JK6lVjr169PVVVVqqurs379+rz33ntp2bLlJ+Yk2+rq6m0+1pskr7zySioqKlJaWrrVwi9JndYDAAAA4JOhSZR+W1JZWZkRI0Z8rHvPPvvsTJ8+PUny+OOPJ0lefPHF9OnTp77i7TQvv/xyY0cAAAAAoJ4V/iCPLVmzZk0WL178sQ/xmDZtWmpqamr97IqFHwAAAADF1CR3+rVr1y5VVVWNHQMAAAAAGkST3OkHAAAAAEWm9AMAAACAglH6AQAAAEDBKP0AAAAAoGCUfgAAAABQME3y9N4iqqmp2e57vnXt7bV+v+abE+srDgAAAACNyE4/AAAAACgYpR8AAAAAFIzSDwAAAAAKRukHAAAAAAWj9AMAAACAglH6AQAAAEDBKP0AAAAAoGCUfgAAAABQMEo/AAAAACgYpR8AAAAAFIzSDwAAAAAKRukHAAAAAAWj9AMAAACAglH6AQAAAEDBKP0AAAAAoGCaNXYAmraL79r573nTqTt2f0lJSf0E2U41NTWN8r4AAADArsdOPwAAAAAoGKUfAAAAABSM0g8AAAAACkbpBwAAAAAFo/QDAAAAgIJR+gEAAABAwSj94BOoQ4cOjR0BAAAA2IUp/T5gxYoVufDCC3PwwQenTZs2KSkpycKFCxs7FruosrKyHHPMMbnuuuvyyCOPZMGCBZk/f35++9vf5oorrsihhx66xfsmT56c+fPnp3fv3js5MQAAAFAUzRo7wCfJ888/n5///OcZOnRoRo0alQcffLCxI7ELKisry0UXXZRLLrkkPXv23Ox6eXl5vvjFL+Z73/teFi5cmKuuuir33HNPkvcLv+9///upqqrKAQcckKVLl+7s+AAAAEABKP0+YOTIkVm1alWSZNq0aUq/T6CffnWPjBj3gwyu+M9NYzU1NflfZ3fI6EnT0+9z/6MR0yUDBgzIXXfdlWHDhiVJnnvuudxzzz2prKzM8uXLU1JSkv79++fAAw/MqaeemsGDB+fuu+/O+PHjs3jx4nzjG99IVVVVTjvttMyaNatRPwsAAACw62oypV91dXVuvPHGTJ06NcuXL89ee+2VW265JRMnTsyoUaNy++23p7TU086fZGv++XLeeXNlPt2rvNb4W68tybr33s7ufYc1UrL3DRkyJI8++mi6dOmSZcuW5bzzzsv999+/2bz58+fnl7/8ZS677LJ8+ctfzo9+9KOccMIJSbKp8Nu48w8AAADg42gyLddZZ52VH/zgB5k0aVJ+97vf5aSTTsopp5ySJUuWZOjQoY0djzpYteTJlJSWpXPPfWqNv75sQdp02D3tO+/ZSMmSrl275qGHHkqXLl1y//33Z/DgwVss/D5o/fr1ueOOO3LnnXduGlu6dGlmzpzZ0HEBAACAgmsSpd+MGTMyffr0/OY3v8nXv/71HHbYYbn88stz0EEHZcOGDdtV+q1duzZf/vKX06NHj3Ts2DGHH354Fi1a1IDp2WjVkifTqduANGvRutb4P5YtSNfPNO4uv1tvvTXdunXLnDlzMnbs2Lz99tt1um/y5Mm55JJLUlVVlddeey19+/bNZZdd1sBpAQAAgKJrEo/3Xn311RkzZkxGjRpVa7xfv35p3rx59t133zqvtWHDhvTr1y9XXXVVunXrlmuvvTbjx4/P008/Xd+xNykpKdni6x31zWumfuT77CwX/e+aOs9dteTJvLnq+Uw9p0ut8fVr12TYsXUvyur7c1ZUVORLX/pSVq9enTPOOCPr1q2r030fPLTjtNNOy8qVKzNnzpx85zvfyR133JFXX321QXMDAAAAu5aamrr3KIXf6bdixYosXLgwJ5544mbXli1bln322SctW7as83pt27bNd77znfTo0SNlZWW54IIL8swzz+S9996rz9hswaoXK3Pg2O9nwlXza/00a946uzfiTr/zzz8/SXLjjTdm+fLldbrnw4XfPffck7lz5+ZXv/pVWrRoka985SsNGRkAAAAouMLv9FuxYkWSpFu3brXG33333cydOzdHH330Dq0/b9689OnTJ61atdqhdbampqYmFRUVSZI5c+bU27rfuvb2zd5nZ7v4rrrNe/PV57P2nX+l95Cj0r5zz9rj/34zXbfjEI8d/Zwf3HHXunXrHH/88amqqsodd9xRp/u3VPhtdNttt2Xs2LE55ZRT8sMf/rBecwMAAABNR+F3+nXp8v6joIsXL641ft1112XlypU54IADPvba//rXv3L++efnqquu2qGMbNuqJU+mWcs2m53cu/Lv89Ku855p22H3RslVXl6e5s2b59lnn80rr7yyzflbK/yS5LHHHsu6desycODAtGvXrqFiAwAAAAVX+J1+ffv2zZAhQzJlypTstttu6dGjR2bOnJkHHnggSTY7xGPjyamVlZVJkocffjh/+9vf0rZt23zhC1/YNO/dd9/Ncccdl/Hjx2fChAk76dM0XauWPJndP/O5lJbV/pNd+fz/adRHe/fee+8kyYIFC7Y5d1uFX5KsW7cuixYtSnl5eQYOHLjp7xAAAABgexS+9CstLc0vf/nLTJo0Keeee246d+6cM888M+eff34uv/zyDBkypNb8D3/336WXXpok6d27d1566aUk7x/mcdJJJ6V///52+e0kI0+7cYvjh//P23ZyktqefvrpXHnllXnqqae2Ou+www7bZuG30a233pru3btn1apV9R0XAAAAaCIKX/olyYABAzJ79uxaY6effnoGDRqU1q1b1xqvy/emfeUrX0l1dXVuv/32bc6l2CorK+u0G2/27Nm58sors2jRoq0Wfkn8XQEAAAA7rEmUfltSWVmZESNGbPd9S5cuzfTp09OqVat07Nhx0/hf//rX9OrVqz4jUjCTJ09u7AgAAABAE9EkS781a9Zk8eLFOe+887b73t69eztFFQAAAIBPtCZZ+rVr1y5VVVWNHQMAAAAAGkRpYwcAAAAAAOqX0g8AAAAACkbpBwAAAAAFo/QDAAAAgIJR+gEAAABAwSj9AAAAAKBgmjV2AJq2m05t7ATbr6amZrvmf+va25Mk13xzYq3XAAAAAA3FTj8AAAAAKBilHwAAAAAUjNIPAAAAAApG6QcAAAAABaP0AwAAAICCUfoBAAAAQMEo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\n", "text/plain": [ "
" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "qc.draw(output='mpl')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Run the cirquit on the Quantum Inspire simulator" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we make a connection to the Quantum Inspire website." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "token = load_account()\n", "if token is not None:\n", " authentication = get_token_authentication(token)\n", "else:\n", " if QI_EMAIL is None or QI_PASSWORD is None:\n", " print('Enter email')\n", " email = input()\n", " print('Enter password')\n", " password = getpass()\n", " else:\n", " email, password = QI_EMAIL, QI_PASSWORD\n", " authentication = get_basic_authentication(email, password)\n", "\n", "QI.set_authentication(authentication, QI_URL)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can list backends and perform other functions with the `QuantumInspireProvider`." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "QI.backends()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We create a QisKit backend for the Quantum Inspire interface and execute the circuit generated above." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "qi_backend = QI.get_backend('QX single-node simulator')\n", "j=execute(qc, backend=backend, shots=512)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can wait for the results and then print them" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Generated histogram:\n", "{'111': 481, '100': 2, '000': 5, '001': 6, '011': 9, '110': 2, '101': 4, '010': 3}\n" ] } ], "source": [ "result = j.result()\n", "print('Generated histogram:')\n", "print(result.get_counts())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Visualization can be done with the normal Python plotting routines, or with the QisKit SDK." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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D+vXr2fp0qXU7e/27dtTWVkJQLt27ejbty8zZszA3TEzKioqmD9/PmvXrgWgrKyMNWvWUF1drfdJ75Pepxx/n5rWqNh0K1asSMn71Bhz32G+SomoeXY9cKa7P5Ww/DfAAHcf0chzTyHULs9196dj/K+HgO7uflxj5SoqKnzSpElxX4KIiDTD1b/vlNbt3zq2/pm7nVNYWDjN3YckW9dizbPuXgNMA0bVWzWK0Is2KTM7DXgMOC9mwjTgAKB656MVERHZXks3z94BPGpm7wBvAhcDxcDdAGb2CIC7nxs9PoNQw/wRMMXM6s591rj7yqjM9cDfgflAe0KT7AGEHrkiIiIp06JJ093/ZGadgesI4ylnA8cnnKOsP17zYkKMd0W3OpOBI6P7HYF7CZ2JVgMzgCPc/Z10vAYREdl9tXhHIHf/LfDbBtYd2djjBp7zA+AHqYhNRESkMZp7VkREJCYlTRERkZiUNEVERGJS0hQREYlJSVNERCQmJU0REZGYlDRFRERiUtIUERGJSUlTREQkJiVNERGRmJQ0RUREYlLSFBERiUlJU0REJCYlTRERkZiUNEVERGJS0hQREYlJSVNERCQmJU0REZGYlDRFRERiUtIUERGJSUlTREQkJiVNERGRmJQ0RUREYlLSFBERiUlJU0REJCYlTRERkZiUNEVERGJS0hQREYlJSVNERCQmJU0REZGYlDRFRERiUtIUERGJSUlTREQkJiVNERGRmJQ0RUREYlLSFBERiUlJU0REJCYlTRERkZiUNEVERGJS0hQREYlJSVMkA1555RWGDh3K4MGDueuuu7Zbv2nTJi644AIGDx7MyJEjWbRoEQArV67kpJNOYp999uHqq6/e5jnPPPMMhx12GMOHD+fUU09lxYoVLfJaRHYnSpq7uVQfvNevX8/pp5/OwQcfzLBhw7jxxhtb7LXkitraWq6++mqefPJJ3nrrLZ555hnef//9bco89thjdOzYkWnTpnHJJZdwww03AFBQUMC1117LTTfdtE35LVu2cM011/DnP/+ZN954g/79+3Pfffe11EsS2W0oaTZTOmoM7733HocddhiDBw/mpz/9Ke6eltjTcfAGuOyyy3j77beZPHkyb7/9Ni+//HJa4s9V06ZNY99996V3797k5+czZswYJk6cuE2ZCRMmcMYZZwBw8sknM2XKFNydvfbai0MOOYSCgoJtyrs77s769etxd9auXUv37t1b7DXlkp39zgLceeedDB48mKFDh/Lqq69uXf7b3/6WYcOGceihh3LhhReycePGFnkt0vKUNJshXUnnRz/6EXfeeSfvvvsuH374Ia+88kpa4k/Hwbtt27YcfvjhAOTn53PAAQewdOnStMSfjoPf6tWrGTt2LAcffDAHH3ww77zzTsrjrq6upkePHlsfFxcXU11d3WCZVq1a0b59e1auXNngNlu3bs1tt93GYYcdRr9+/aisrOScc85Jeex10rHvIXynRowYsfUzl2rN+c6+//77jB8/nqlTp/LUU0/x4x//mNraWpYuXcq9997LpEmTmDp1KrW1tYwfPz4t8efqft+VKGk2QzqSzieffMLatWsZOnQoZsYZZ5zBhAkT0hJ/Og7eiVavXs2LL77IiBEjUhd0JB0HP4BrrrmGo48+mrfffpvXX3+dsrKylMeerOXAzJpcJtHmzZt56KGHmDx5MnPnzqV///7ceeedzQ82iXTte4C7776br3/962mJG5r3nZ04cSJjxoyhoKCAXr16se+++zJt2jQgNI9v3LiRLVu2sGHDhrTU8nN5v+9KlDSbIR1Jp7q6muLi4ka3mSrpOHjX2bJlCxdeeCHjxo2jd+/eOx1jQ9Jx8FuzZg1Tp07dWkPLz8+nQ4cOKY+9uLiYJUuWbH28dOnS7Q6yiWW2bNnCmjVr6NSpU4PbnDVrFgD77rsvZsbo0aPTUkuG9CWeJUuW8PLLL6e1htyc72xDzy0uLuayyy7jgAMOoLy8nPbt2/PNb34z5bHn8n7flShpNkM6ks7OJqmdkY6Dd50rr7yS/fbbj0suuSS1QUfScfBbuHAhXbp04bLLLmPEiBFcfvnlrFu3LuWxH3TQQVRVVbFw4UJqamoYP348xx577DZljjvuOJ544gkAnnvuOQ4//PBGPwdFRUVUVlby2WefAfDaa6+lreaQjn0PcO2113LDDTewxx7pOyw15zvb0PLPP/+ciRMnMmPGDObOncv69et58sknUxd0JJf3+65Ee6kZ0pF0iouLtzkHmGybqZKOgzfAzTffzJo1a7jlllvSEjek5+C3ZcsWZs6cyfnnn8/kyZNp27Zt0vNGzdWqVStuvfVWTj31VA455BBGjx5NeXk5t9xyy9aaw9lnn83KlSsZPHgwv/vd77j++uu3Pn/QoEFcd911/PGPf6R///68//77FBUVcfXVV3PCCScwfPhwZs+ezVVXXZXy2CE9+/7FF1+ka9euHHjggakLNInmfGcbeu7f/vY3SkpK6NKlC61bt+Zb3/pWWmr5ubzfdyWtMh1ALktMOkVFRYwfP5577713mzJ1SWfo0KGxkk737t3Ze++9+cc//sGQIUN44oknGDduXFriTzx419bWctZZZ209eFdUVHDcccdx9tlnc/HFFzN48GA6derE/fffv/X5gwYNYu3atWzevJkXXniBZ555hnbt2nH77bfTt29fjjzySAAuvPBCzj333JTG3jxc0N0AABEjSURBVJSDX48ePWId/IqLiykuLmbIkCFAaN5KR9IEGDVqFKNGjdpm2bXXXrv1/p577snDDz+c9LkzZ85Muvz888/n/PPPT1mMDUnHvv/rX//KxIkTefnll9m0aRNr167lu9/9Lvfcc09KY2/Od/bYY49l3LhxXHrppXzyySdUVVUxePBg9thjD959913Wr19PmzZtmDJlSlqSUC7v911JiydNM7sU+DFQBMwBrnT31xspPwK4A+gPLAVudfe7m7PNVElH0tl///257bbb+N73vsfGjRsZOXIkI0eOTNtrSMfBO25HoeZIx8EvLy+PHj16MH/+fPr27cvkyZPT0hEo16Vj3w8dOpSf/exnALzxxhv8+te/TsuBuznf2fLyckaPHs2wYcO2bicvL48hQ4Zw0kkncdRRR5GXl8cBBxzA2LFjUx57Lu/3XYmlawxg0n9mdjrwGHAp8Eb093ygn7svSlJ+X2A28CDwW2B49PcMd39mZ7aZqKKiwidNmpSaFyct7uWXX+baa6/devD74Q9/uM3Bb+PGjVx88cXMmjVr68GvrlPS7bffzuOPP06rVq24+eabt/5wmDVrFldccQU1NTX07t2bX//613Ts2DEt8V/9+x2fG26OW8euStu207Hv69QdvOtOC8hXcn2/58pnvrCwcJq7D0m2rqWT5tvAP939ooRl84Gn3f2aJOV/Doxx974Jy+4H+rv7sJ3ZZiIlzdz5EO+KtO9ld5Mrn/nGkmaLNc+aWT4wGLit3qqXgEMbeNqwaH2iF4GxZtYasJ3YZsrlygdBRIJ0fmf1fd21teQ5zS5AHrCs3vJlQEMn7boD9afDWUaIuwshaTZ1m7IL0cEvM/RDMXO07zOrxZpn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\n", "text/plain": [ "
" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot_histogram(result.get_counts(qc))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A screenshot from the execution result on the Quantum Inspire website." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![title](grover-qi.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References\n", "\n", "[1] \"[A fast quantum mechanical algorithm for database search](https://arxiv.org/abs/quant-ph/9605043)\", L. K. Grover, Proceedings of the 28th Annual ACM Symposium on the Theory of Computing (STOC 1996)\n", "\n", "[2] \"[Tight bounds on quantum searching](https://arxiv.org/abs/quant-ph/9605034)\", Boyer et al., Fortsch.Phys.46:493-506,1998\n", "\n", "[3] \"[Quantum Inspire](https://www.quantum-inspire.com/)\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "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.6.8" }, "latex_envs": { "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 0 }, "nav_menu": {}, "toc": { "navigate_menu": true, "number_sections": true, "sideBar": true, "threshold": 6, "toc_cell": false, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }