Commit e913d2a9 authored by Abhishek's avatar Abhishek

-

parent 29784826
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# **Quantum Computing: Lab 11** #"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this lab we are going to work on creating Error Correction Codes on Quantum Circuits."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before you begin, execute this cell to import numpy and packages from the D-Wave Ocean suite, and all necessary functions for the gate-model framework you are going to use, whether that is the Forest SDK or Qiskit. In the case of Forest SDK, it also starts the qvm and quilc servers."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Available frameworks:\n",
"Qiskit\n",
"D-Wave Ocean\n"
]
}
],
"source": [
"%run -i \"assignment_helper_QML.py\"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kernel methods are widespread in machine learning and they were particularly common before deep learning became a dominant paradigm. The core idea is to introduce a new notion of distance between high-dimensional data points by replacing the inner product $(x_i, x_j)$ by a function that retains many properties of the inner product, yet which is nonlinear. This function $k(.,.)$ is called a kernel. Then, in many cases, wherever a learning algorithm would use an inner product, the kernel function is used instead.\n",
"\n",
"The intuition is that the kernel function acts as an inner product on a higher dimensional space and encompasses some $\\phi(.)$ mapping from the original space of the data points to this space. So intuitively, the kernel function is $k(x_i, x_j)=(\\phi(x_i), \\phi(x_j))$. The hope is that points that were not linearly separable in the original space become linearly separable in the higher dimensional space. The $\\phi(.)$ function may map to an infinite dimensional space and it does not actually have to be specified. As long as the kernel function is positive semidefinite, the idea works.\n",
"\n",
"Many kernel-based learning algorithms are instance-based, which means that the final model retains some or all of the training instances and they play a role in the actual prediction. Support vector machines belong here: support vectors are the training instances which are critically important in defining the boundary between two classes. Some important kernels are listed below.\n",
"\n",
"| Name |             Kernel function|\n",
"|------|-----------------|\n",
"|Linear | $(x_i,x_j)$|\n",
"|Polynomial| $((x_i,x_j)+c)^d$|\n",
"|Radial basis function|$\\exp(-\\gamma\\|x_i-x_j\\|^2)$|\n",
"\n",
"The choice of kernel and the parameters of the kernel are often arbitrary and either some trial and error on the dataset or hyperparameter optimization helps choose the right combination. Quantum computers naturally give rise to certain kernels and it is worth looking at a specific variant of how it is constructed.\n",
"\n",
"\n",
"# Thinking backward: learning methods based on what the hardware can do\n",
"\n",
"Instead of twisting a machine learning algorithm until only contains subroutines that have quantum variants, we can reverse our thinking and ask: given a piece of quantum hardware and its constraints, can we come up with a new learning method? For instance, interference is a very natural thing to do: we showed an option in the first notebook on quantum states, and it can also be done with a Hadamard gate. For instance, imagine that you have training vectors encoded in some register, and this register is entangled with the $|0\\rangle$ in the superposition of an ancilla. The ancilla's $|1\\rangle$ of the superposition is entangled with another register that contains the test vector. Applying the Hadamard on the ancilla interferes the test and training instances. Measuring and post-selecting on the ancilla gives rise to a kernel [[1](#1)].\n",
"\n",
"Let's get the basic initialization out of the way:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:52.516626Z",
"start_time": "2019-02-01T23:26:51.787904Z"
}
},
"outputs": [],
"source": [
"from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit\n",
"from qiskit import execute\n",
"from qiskit import BasicAer\n",
"import numpy as np\n",
"%matplotlib inline\n",
"\n",
"q = QuantumRegister(4)\n",
"c = ClassicalRegister(4)\n",
"backend = BasicAer.get_backend('qasm_simulator')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are constructing an instance-based classifier: we will calculate a kernel between all training instances and a test example. In this sense, this learning algorithm is lazy: no actual learning happens and each prediction includes the entire training set.\n",
"\n",
"As a consequence, state preparation is critical to this protocol. We have to encode the training instances in a superposition in a register, and the test instances in another register. Consider the following training instances of the [Iris dataset](https://archive.ics.uci.edu/ml/datasets/iris): $S = \\{(\\begin{bmatrix}0 \\\\ 1\\end{bmatrix}, 0), (\\begin{bmatrix}0.78861006 \\\\ 0.61489363\\end{bmatrix}, 1)\\}$, that is, one example from class 0 and one example from class 1. Furthermore, let's have two test instances, $\\{\\begin{bmatrix}-0.549\\\\ 0.836\\end{bmatrix}, \\begin{bmatrix}0.053 \\\\ 0.999\\end{bmatrix}\\}$. These examples were cherry-picked because they are relatively straightforward to prepare."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:52.525627Z",
"start_time": "2019-02-01T23:26:52.518665Z"
}
},
"outputs": [],
"source": [
"training_set = [[0, 1], [0.78861006, 0.61489363]]\n",
"labels = [0, 1]\n",
"test_set = [[-0.549, 0.836], [0.053 , 0.999]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" We use amplitude encoding, which means that, for instance, the second training vector will be encoded as $0.78861006|0\\rangle + 0.61489363|1\\rangle$. Preparing these vectors only needs a rotation, and we only need to specify the corresponding angles. The first element of the training set does not even need that: it is just the $|1\\rangle$ state, so we don't specify an angle for it."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get the angle we need to solve the equation $a|0\\rangle + b|1\\rangle=\\cos\\left(\\frac{\\theta}{2}\\right)|0\\rangle + i \\sin \\left(\\frac{\\theta}{2}\\right) |1\\rangle$. Therefore, we will use $\\theta=2 \\arccos(a)$"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def get_angle(amplitude_0):\n",
" return 2*np.arccos(amplitude_0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In practice, the state preparation procedure we will consider requires the application of several rotations by $\\theta$ and $-\\theta$ in order to prepare each data point in the good register (see circuit below). As a consequence, we need to divide the test angles by $2$ (we apply two rotations) and the training angles by $4$ (we apply four rotations). Don't hesitate to check it by yourself by running the circuit below with a pen and paper."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:52.546765Z",
"start_time": "2019-02-01T23:26:52.527115Z"
}
},
"outputs": [],
"source": [
"test_angles = [get_angle(test_set[0][0])/2, get_angle(test_set[1][0])/2]\n",
"training_angle = get_angle(training_set[1][0])/4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following function does the state preparation. We plot it and explain it in more details below."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:52.589616Z",
"start_time": "2019-02-01T23:26:52.548747Z"
}
},
"outputs": [],
"source": [
"def prepare_state(q, c, angles):\n",
" ancilla_qubit = q[0]\n",
" index_qubit = q[1]\n",
" data_qubit = q[2]\n",
" class_qubit = q[3]\n",
" circuit = QuantumCircuit(q, c)\n",
" # Put the ancilla and the index qubits into uniform superposition\n",
" circuit.h(ancilla_qubit)\n",
" circuit.h(index_qubit)\n",
"\n",
" # Prepare the test vector\n",
" circuit.cx(ancilla_qubit, data_qubit)\n",
" circuit.u3(-angles[0], 0, 0, data_qubit)\n",
" circuit.cx(ancilla_qubit, data_qubit)\n",
" circuit.u3(angles[0], 0, 0, data_qubit)\n",
" # Flip the ancilla qubit > this moves the input \n",
" # vector to the |0> state of the ancilla\n",
" circuit.x(ancilla_qubit)\n",
" circuit.barrier()\n",
"\n",
" # Prepare the first training vector\n",
" # [0,1] -> class 0\n",
" # We can prepare this with a Toffoli\n",
" circuit.ccx(ancilla_qubit, index_qubit, data_qubit)\n",
" # Flip the index qubit > moves the first training vector to the \n",
" # |0> state of the index qubit\n",
" circuit.x(index_qubit)\n",
" circuit.barrier()\n",
"\n",
" # Prepare the second training vector\n",
" # [0.78861, 0.61489] -> class 1\n",
"\n",
" circuit.ccx(ancilla_qubit, index_qubit, data_qubit)\n",
" circuit.cx(index_qubit, data_qubit)\n",
" circuit.u3(angles[1], 0, 0, data_qubit)\n",
" circuit.cx(index_qubit, data_qubit)\n",
" circuit.u3(-angles[1], 0, 0, data_qubit)\n",
" circuit.ccx(ancilla_qubit, index_qubit, data_qubit)\n",
" circuit.cx(index_qubit, data_qubit)\n",
" circuit.u3(-angles[1], 0, 0, data_qubit)\n",
" circuit.cx(index_qubit, data_qubit)\n",
" circuit.u3(angles[1], 0, 0, data_qubit)\n",
" circuit.barrier()\n",
"\n",
" # Flip the class label for training vector #2\n",
" circuit.cx(index_qubit, class_qubit)\n",
" circuit.barrier()\n",
" return circuit"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's dissect the last part where we prepare the second training state, which is $\\begin{pmatrix}0.78861 \\\\ 0.61489\\end{pmatrix}$ and we entangle it with the excited state of the ancilla and the excited state of the index qubit. We use `angles[1]`, which is `1.3245021469658966/4`. Why? We have to rotate the basis state $|0\\rangle$ to contain the vector we want. We could write this generic state as $\\begin{pmatrix} \\cos(\\theta/2) \\\\ \\sin(\\theta/2)\\end{pmatrix}$. Looking at the documentation of the gate implementing the rotation, you'll see that the function argument divides the angle by two, so we have to adjust for that -- this is why we divided $\\theta$ by two. If you calculate the arccos or arcsin values, you will get the value in `angles[1]`.\n",
"\n",
"What is this the change of sign of $\\theta$ between the steps? If you change the sign of $\\theta$, you reverse the unitary; check this on paper. By flipping the sign, you uncompute the register. So what you see there is a series of uncomputation to get the entanglement right between the different register."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us see the circuit for preparing state with the first test instance:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:53.878539Z",
"start_time": "2019-02-01T23:26:52.591175Z"
}
},
"outputs": [
{
"data": {
"image/png": "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9YZhERERERERERGxFssXBEtKSsjKyuLnP/95g7ZPTk5m7dq1Xo5KRET8afjw4WaHIAFM+SEiIiIiwcbyBcEmTZpQVVVldhgiImKiN954w+wQJIApP0REREQk2FhuDUEREZHLTZkyxewQJIApP0REREQk2KggKCIilrdmzRqzQ5AApvwQERERkWCjgqCIiIiIiIiIiIiFqCAoIiIiIiIiIiJiISoIioiI5e3atcvsECSAKT9EREREJNhY/i3DwerV+8yOQER87dyoMWaHEDQWLlzIhAkTzA5DApTyQ0RERESCjWYIioiI5T3//PNmhyABTPkhIiIiIsFGBUERERERERERERELUUFQRERERERERETEQlQQFBERy3v99dfNDkECmPJDRERERIKNCoIiImJ5qampZocgAUz5ISIiIiLBRgVBERGxvGHDhpkdggQw5YeIiIiIBBsVBEVERERERERERCxEBUEREbG8QYMGmR2CBDDlh4iIiIgEGxUERUTE8jZu3Gh2CBLAlB8iIiIiEmxUEBQREREREREREbEQFQRFREREREREREQsRAVBERGxvMWLF5sdggQw5YeIiIiIBBsVBEVERERERERERCxEBUEREbG88ePHmx2CBDDlh4iIiIgEGxUERURERERERERELCTM7ADENx571/8/89X7/P8zRUTE/yJWLPf7zzw3aozff6aIiIiISLDSDEEREbG8qVOnmh2CBDDlh4iIiIgEGxUERUTE8qZNm2Z2CBLAlB8iIiIiEmxUEBQREctLS0szOwQJYMoPEREREQk2KgiKiIjlHT9+3OwQJIApP0REREQk2KggKCIiIiIiIiIiYiEqCIqIiOX17NnT7BAkgCk/RERERCTYqCAoIiKW9/7775sdggQw5YeIiIiIBBsVBF0oLi7m0UcfJTExkZiYGIYOHcq6devMDktERLxs+vTpZocgAUz5ISIiIiLBRgXBOtjtdsaNG8eHH37I7NmzSU9PJyEhgVGjRrF582azwxMRES9atGiR2SF4rLrq4v9XnjMvDitpTPlxqbOnzY7Ac+UVkFsIR4qgssp9f7EWux3yi+FQIZScNTsaCUTlpRf/3243L476qKwyxrzcQmMMFLnciRI4dAJOnjE7EglWYWYHEKiWLl1KRkYGy5YtY8yYMQCkpaWRmprKs88+y7Jly0yO0Lv+b1pbBt/5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b9+effv2eTlCERERw6XrqakYKK4EejHwUpdeCKsYKK6oGCjOhDXCYsmlY52KgeKKioHiK5YfekpKSsjKymLAgAEN2n7mzJnk5uZSXl7OiRMnyM3NpXNnN6tki4hIQBk+fLjZIUgAU36IiIiISLCx/D22Jk2aUFVVZXYYIiJiojfe0LqpUjflh4iIiIgEG8vPEBQREZkyZYrZIUgAU36IiIiISLBRQVBERCxvzZo1ZocgAUz5ISIiIiLBRgVBERERERERERERC1FBUERERERERERExEJUEBQREcvbtWuX2SFIAFN+iIiIiEiwUUFQREQsb+HChWaHIAFM+SEiIiIiwSbM7ADEN169z+wIREQaj+eff54JEyaYHUajcW7UGLND8Cvlh4iIiIgEG80QFBERERERERERsRAVBEVERERERERERCxEBUEREbG8119/3ewQJIApP0REREQk2KggKCIilpeammp2CBLAlB8iIiIiEmxUEBQREcsbNmyY2SFIAFN+iIiIiEiwUUFQRERERERERETEQlQQFBERERERERERsRAVBEVExPIGDRpkdggSwJQfIiIiIhJsVBAUERHL27hxo9khSABTfoiIiIhIsFFBUERERERERERExEJUEBQREREREREREbEQFQRFRMTyFi9ebHYIEsCUHyIiIiISbFQQFBERERERERERsRAVBEVExPLGjx9vdggSwJQfIiIiIhJsVBAUERERERERERGxkDCzAxAJRhW/nm92CKYL/8M9ZocQsJQfyg8RaRw0Xmu8dkX5ofwIRspr5bUryo/gyg/NEBQREcubOnWq2SFIAFN+iIiIiEiwUUFQREQsb9q0aWaHIAFM+SEiIiIiwUaPDEujc64SNh+Efccgt/Bi++xl0D4OuraGvldBWKh5MYp57HbIPgbbc+HQJfnx0hJo2xI6xsPATtAixrwYJfCkpaWxdu1as8OoU3U1FOyDEwfgdP7F9q/+AU2ToEU7aJ0CYZGmhRjUAj0/AE4fh/zv4fTRi23r/gKx8dCsNbTuAbFx5sXnTHmF8+P5/1tuHM+7t4Ze7XU8tyq7HfbkQ+ZhOHTiYvtL6dCuJVydAAOvhmbRpoUoJisrhqO74NRRKDl+sf3bhdAsCRK7GeOfzWZejJerrDLOUbOOOo57v19qjHudE6F/R4gMNy9GMdehQtia4zjuvfhvaNMC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cy6//PIMGTIk++23X04//fQ89NBDVcfqcdddd13VEYpgzgAAAEAVFIIfoaOjI5MnT85dd92VefPmZfny5WloaMhZZ52VJ554oup4PWrJkiVVR/hEPuhInnk5WbUuuW9d8vympKOj6lSf3GdlzgAAAMCepb7qAH3VPffck+bm5qxYsSLnnHNOkmTs2LFpamrKtddemxUrVlScsGwvvpb848PJa21djx82KLn4z5JDD6omFwAAAEBfV+QKwQ8++CDz5s3L8OHDM2DAgJx44olpbm7OiBEjcumllyZJ7r777hx88MGZOHFi53X77LNPpk2blvvuuy9vv/12VfGL99s3k5v/NXl9B/8LXtmc/MOq5PW22s8AAAAAKLQQvOSSS3LDDTfksssuy7333pspU6bkggsuyPPPP59TTjklSbJu3bo0NTWlrq6uy7XHH3982tvb8/TTT1cRvVc0NzdXHeFj/X8/T9o/2PHjwR0dyTvvb3uEuK/r63MGAAAA9kzFPTK8aNGi3HbbbVmzZk3GjRuXJDnzzDPz+OOP584778zJJ5+cJHnjjTfS2NhYc/3gwYM7P99TrV+/PkOGDKk6xg699U7yq98kH/eqwI4kj72QfO2LyT59+De8L88ZAAAA2HP14bqkZ8yZMycTJ07sLAO3O+aYY7L33ntn1KhRu3S/6667LnfccUd+/etfZ/HixTnvvPO6M+4O/fGqxQ+vYNyZq6++eqfnzJ8//2PPmz9//i79zO50yLAvZtp31u70vPYPkobDhub3r73YC6l2bGez3tmct58DAAAAsCMdu7m7alGPDLe2tmbdunU5//zzaz7buHFjmpqa0r9//yTbVgK++eabNedtXxm4faXgxIkT8+Mf/zhjx47tweRs9/47v//E525514sEAQAAAD6sqBWCra2tSZJDDz20y/F33nknzc3NnbsJJ0lTU1OWL1+ejo6OLqvw1q9fn/r6+owcOTJJ8qUvfakXknfV0dGRM844I0myZs2aXbr2k7z7cP78+Z2bq+zIjTfeuEs/szt1dCRz/iV57fcf/dhwXV3yhYbknd+/1qvZPmxns97ZnJNqZw0AAADsmYpaIdjQ0JAkaWlp6XJ87ty5efnllzs3FEmSyZMn57XXXsvKlSs7j23ZsiV33HFHxo8fn/333793Qlfg+uuvrzrCR6qrS8Y37eQdgh3J/1L7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WJFzzjknSTJ27Ng0NTXl2muvzYoVKypOuOd76Nnuvd8HHcm//zr58onde18AAACAz5IiVwh+8MEHmTdvXoYPH54BAwbkxBNPTHNzc0aMGJFLL700SXL33Xfn4IMPzsSJEzuv22effTJt2rTcd999efvtPrTUbA/0wQfJ4xu6/74/64F7AgAAAHyWFFkIXnLJJbnhhhty2WWX5d57782UKVNywQUX5Pnnn88pp5ySJFm3bl2amppSV1fX5drjjz8+7e3tefrpp6uI3iuam5urjpBNv0/e3dL99329LXn7ve6/7+7oC3MGAAAAylPcI8OLFi3KbbfdljVr1mTcuHFJkjPPPDOPP/547rzzzpx88slJkjfeeCONjY011w8ePLjz8z3V+vXrM2TIkEozvPK7nrv3b3+XDD+k5+7/SfWFOQMAAADlKa4QnDNnTiZOnNhZBm53zDHHZO+9986oUaN26X5f/epX8/zzz6dfv37Ze++9M2fOnIwfP747I9f441WLH17BuDNXX331Ts+ZP3/+x543f/78XfqZu+O4MRfn7Mtu63JsZzsJf9TnV/3Prv8+e+L/mg1P9vw7IHc2653Nefs5AAAAADvS0dGxW9cVVQi2trZm3bp1OyxhNm7cmKampvTv3z/JtpWAb775Zs1521cGbl8peNttt2XQoEFJkieeeCJnnHFG3njjjfTr16+nvkYRtrb33HO9W7f0kWeGAQAAACpQXCGYJIceemiX4++8806am5s7dxNOkqampixfvjwdHR1dVuGtX78+9fX1GTlyZJJ0loFJsnnz5tTV1e12O/tJdXR05IwzzkiSrFmzZpeu/STvPpw/f37n5io7cuONN+7Sz9wdrW8k8+7teuzDK/22274y8KM+/7Bf/PRfM2i/3c/2Se1s1jubc9I7swYAAADKUtSmIg0NDUmSlpaWLsfnzp2bl19+uXNDkSSZPHlyXnvttaxcubLz2JYtW3LHHXdk/Pjx2X///TuPz5w5M8OGDctf/MVfZNmyZamv/2z3rNdff33VEXLoQUl9D/x2HjAgOWjf7r/v7ugLcwYAAADK89lurnbRsGHDMmrUqMyZMyeDBw/O4YcfnqVLl2bFim3vk/vjQnDSpEkZM2ZMpk+fnrlz5+awww7LzTffnI0bN2bRokVd7vv9738/ybZdY6+++uo88MADGThwYO99sW42ZcqUqiOkvl9ywp8mT7zYvfc96chkF1+72GP6wpwBAACA8hS1QnCvvfbKkiVL0tTUlBkzZmT69OlpaGjIzJkz069fvy4bitTV1WX58uU599xzM2vWrEyaNCmbNm3KqlWruhSHf2zcuHHZa6+98vDDD/fWV+oRxx13XNURkiR/Nrz773n6sd1/z93VV+YMAAAAlKWoFYJJcuyxx2b16tVdjl100UVpbGzMvvt2fZZ00KBBWbhwYRYuXLjDe7W1teX111/PUUcdlWTbpiLPPfecoqebDBuSHH9Esq61e+7334/Z9igyAAAAQMmKKwR35LHHHstpp522y9e9/fbbmTp1atra2lJfX58BAwbkn/7pn3LkkUf2QMry1NUlU0YnL7yavP0xGwN/ks1EPrd/Mvnk7ssGAAAA8FlVfCHY1taWlpaWXHHFFbt87SGHHJJHH320B1JVa/sOxn3Bgfsml52ZLPi35N0tu3ePAwYkl5+ZDNi7e7N9Wn1pzgAAAEA5ii8EBw4cmK1bt1Ydo0+55ZZbqo7QxZEHJ//bWcn/+3DyyuZdu/ZPBycX/1nScEDPZPs0+tqcAQAAgDIUtakIn8yMGTOqjlDjTz6XXHNOcvbxyb6fYKXfwP7JpJOSqyb0zTIw6ZtzBgAAAPZ8xa8QpNaaNWuqjrBDe/dLvnxiMr4peXJj8uv/SFrfSH7/7rb3DR6477YVgcMPSUb9aVLfr+rEH6+vzhkAAADYsykE+czZpz4ZPWzbHwAAAAB2jUeGAQAAAKAgCkFqPPXUU1VHKII5AwAAAFVQCFJj8eLFVUcogjkDAAAAVVAIUmP27NlVRyiCOQMAAABVUAgCAAAAQEEUggAAAABQEIUgNRYsWFB1hCKYMwAAAFAFhSA1mpqaqo5QBHMGAAAAqqAQpMa4ceOqjlAEcwYAAACqoBAEAAAAgILUVx2A3jVy5MidnjN79uxPdB4fb2czNGcAAACgClYIUuPb3/521RGKYM4AAABAFRSCAAAAAFAQhSAAAAAAFEQhCAAAAAAFUQgCAAAAQEEUggAAAABQEIUgAAAAABREIQgAAAAABVEIFm7mzJmpr6+vOgYAAAAAvUQhWLAHH3wwbW1tVccAAAAAoBcpBAv13nvv5Zvf/GbmzZtXdRQAAAAAepFCsFDf+c53cskll+Tzn/981VEAAAAA6EUKwQL94he/yE9+8pNMnz696igAAAAA9DKFYIEefvjh/OpXv8oXvvCFDB06NFu3bs3QoUPz1ltvVR0NAAAAgB6mENwNa9euzZe//OUMGjQo+++/f0477bQsXry46lif2IwZM/Lb3/42GzZsyIYNG9KvX79s2LAhBx54YNXRAAAAAOhh9VUH+KxZvXp1JkyYkAEDBmTatGk54IADsmzZskydOjUvvfRSrrnmmqojAgAAAMBHskJwF7S3t+ev/uqvstdee+WBBx7ID3/4w/z93/99fv7zn+fYY4/Nt771rbz44otVx9xl7e3tnX/fsqU965/dkA86OipMBAAAAEBPUQh+yN13352vfOUrGTJkSPr375+jjjoqF154YX75y1/m/vvvz3PPPZcLL7wwJ510Uuc1Bx10UL71rW/l/fffz49+9KMK0396P/350/nHO1flpd9uqjoKAAAAAD3AI8N/0N7enosvvji33357jjzyyHzta1/LgQcemJaWlixbtixf//rX88ADDyRJzj777JrrJ0yYkCRpbm7u1dzdacuW9qz5yZMZduRhOerwQ6qOAwAAAEAPUAj+wTe+8Y3cfvvtufLKKzN//vzU1//XaFpbW3PQQQfl1ltvTZIMHz685vpDDz00AwcOzLPPPttrmbvbT3/+dH7f9p+ZNunPq44CAAAAQA9RCCZ58MEH84Mf/CATJ07MP/zDP6Surq7L50cccUSSZPPmzUm2PSK8IwceeGDnOT3pm3/3wzy/8eXOv3e3/3vRPd1+TwAAAAC613f/+tLdus47BJPcdNNNSZLvfve7NWUgAAAAAOxJrBBMsmrVqgwdOjQnnnjix563fWXgR60CfOutt/K5z33uU+f54w1LduS7f31p3n35V51//7S2bGnP3B/ekc8PPiiXXjDpU98PAAAAgL6r+ELwd7/7Xdra2vLFL35xp+duf3fgs88+m1NOOaXLZ6+88kra2toyevToT51p+4rFj/LNv/thBhzW2Pn37vL7tv/skUeQAQAAAOh+HhneTR0dHUmSTZs27fTccePGJdm2ovDDVq5c2eUcAAAAAOiL6jq2N2IFO/roo/PCCy9k1apVGT9+fJfPnnnmmYwYMSJJ0t7enhEjRuQ3v/lNHn300c5Hezdv3pzRo0dnw4YNeeaZZzJ06NDe/gq77eHH1uVf/u2R/NUFX8nRR/5J1XEAAAAA6GEKwSSLFy/O1KlTU19fn8mTJ+foo4/Opk2b8sgjj6SxsTF33XVX57mrV6/OhAkTMmDAgEybNi0HHHBAli1blhdffDHz5s3LNddcU+E32TXtW7fm736wyLsDAQAAAAqiEPyDlStX5nvf+17Wrl2bd999N0OGDMno0aNz1VVXZcyYMV3O/elPf5rZs2fnkUceyZYtW3LCCSdk1qxZmTp1akXpd9+G1leyd319Dj+0oeooAAAAAPQChSAAAAAAFKT4TUUAAAAAoCQKQQAAAAAoiEIQAAAAAAqiEAQAAACAgigEAQAAAKAgCkEAAAAAKIhCEAAAAAAKohAEAAAAgIIoBAEAAACgIApBAAAAACiIQhAAAAAACqIQBAAAAICCKAQBAAAAoCAKQQAAAAAoiEIQAAAAAAqiEAQAAACAgigEAQAAAKAgCkEAAAAAKIhCEAAAAAAKohAEAAAAgIIoBAEAAACgIApBAAAAACiIQhAAAAAACqIQBAAAAICCKAQBAAAAoCAKQQAAAAAoiEIQAAAAAAqiEAQAAACAgigEAQAAAKAgCkEAAAAAKIhCEAAAAAAK8v8DPhg2BOy57N4AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 1672.36x686.28 with 1 Axes>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit.tools.visualization import circuit_drawer\n",
"angles = [test_angles[0], training_angle]\n",
"state_preparation_0 = prepare_state(q, c, angles)\n",
"circuit_drawer(state_preparation_0, output='mpl')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The vertical lines are barriers to make sure that all gates are finished by that point. They also make a natural segmentation of the state preparation.\n",
"\n",
"The test instance is prepared until the first barrier. The ancilla and index qubits (registers 0 and 1) are put into the uniform superposition. The test instance is entangled with the ground state of the ancilla. \n",
"\n",
"Then between the first and second barriers, we prepare the state $|1\\rangle$, which is the first training instance, and entangle it with the excited state of the ancilla and the ground state of the index qubit with a Toffoli gate and a Pauli-X gate. The Toffoli gate is also called the controlled-controlled-not gate, describing its action.\n",
"\n",
"The third section prepares the second training instance and entangles it with the excited state of the ancilla and the index qubit.\n",
"\n",
"The final part flips the class qubit conditioned on the index qubit. This creates the connection between the encoded training instances and the corresponding class label."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# A natural kernel on a shallow circuit\n",
"\n",
"Having down the state preparation, the actual prediction is nothing but a Hadamard gate applied on the ancilla, followed by measurements. Since the ancilla is in a uniform superposition at the end of the state preparation and it is entangled with the registers encoding the test and training instances, applying a second Hadamard on the ancilla interferes the entangled registers. The state before the measurement is $\\frac{1}{2\\sqrt{2}}\\sum_{i=0}^1|0\\rangle|i\\rangle(|x_t\\rangle+|x_i\\rangle)|y_i\\rangle+|1\\rangle|i\\rangle(|x_t\\rangle-|x_i\\rangle)|y_i\\rangle$, where $|x_t\\rangle$ is the encoded test instance and $|x_i\\rangle$ is a training instance."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:53.884698Z",
"start_time": "2019-02-01T23:26:53.880801Z"
}
},
"outputs": [],
"source": [
"def interfere_data_and_test_instances(circuit, q, c, angles):\n",
" circuit.h(q[0])\n",
" circuit.barrier()\n",
" circuit.measure(q, c)\n",
" return circuit"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we measure the ancilla, the outcome probability of observing 0 will be $\\frac{1}{4N}\\sum_{i=1}^N |x_t + x_i|^2$. This creates a kernel of the following form:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:54.007377Z",
"start_time": "2019-02-01T23:26:53.886046Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7f30e89d1860>]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"%matplotlib inline\n",
"x = np.linspace(-2, 2, 100)\n",
"plt.xlim(-2, 2)\n",
"plt.ylim(0, 1.1)\n",
"plt.plot(x, 1-x**2/4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is the kernel that performs the classification. We perform the post-selection on observing 0 on the measurement on the ancilla and calculate the probabilities of the test instance belonging to either class:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:54.017909Z",
"start_time": "2019-02-01T23:26:54.009283Z"
}
},
"outputs": [],
"source": [
"def postselect(result_counts):\n",
" total_samples = sum(result_counts.values())\n",
"\n",
" # define lambda function that retrieves only results where the ancilla is in the |0> state\n",
" post_select = lambda counts: [(state, occurences) for state, occurences in counts.items() if state[-1] == '0']\n",
"\n",
" # perform the postselection\n",
" postselection = dict(post_select(result_counts))\n",
" postselected_samples = sum(postselection.values())\n",
"\n",
" print(f'Ancilla post-selection probability was found to be {postselected_samples/total_samples}')\n",
"\n",
" retrieve_class = lambda binary_class: [occurences for state, occurences in postselection.items() if state[0] == str(binary_class)]\n",
"\n",
" prob_class0 = sum(retrieve_class(0))/postselected_samples\n",
" prob_class1 = sum(retrieve_class(1))/postselected_samples\n",
"\n",
" print('Probability for class 0 is', prob_class0)\n",
" print('Probability for class 1 is', prob_class1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For the first instance we have:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:54.546426Z",
"start_time": "2019-02-01T23:26:54.019350Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ancilla post-selection probability was found to be 0.732421875\n",
"Probability for class 0 is 0.6306666666666667\n",
"Probability for class 1 is 0.36933333333333335\n"
]
}
],
"source": [
"circuit_0 = interfere_data_and_test_instances(state_preparation_0, q, c, angles)\n",
"job = execute(circuit_0, backend)\n",
"result = job.result()\n",
"postselect(result.get_counts(circuit_0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And for the second one:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"ExecuteTime": {
"end_time": "2019-02-01T23:26:54.627141Z",
"start_time": "2019-02-01T23:26:54.548825Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ancilla post-selection probability was found to be 0.912109375\n",
"Probability for class 0 is 0.5524625267665952\n",
"Probability for class 1 is 0.4475374732334047\n"
]
}
],
"source": [
"angles = [test_angles[1], training_angle]\n",
"state_preparation_1 = prepare_state(q, c, angles)\n",
"circuit_1 = interfere_data_and_test_instances(state_preparation_1, q, c, angles)\n",
"job = execute(circuit_1, backend)\n",
"result = job.result()\n",
"postselect(result.get_counts(circuit_1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# References\n",
"\n",
"[1] M. Schuld, M. Fingerhuth, F. Petruccione. (2017). [Implementing a distance-based classifier with a quantum interference circuit](https://doi.org/10.1209/0295-5075/119/60002). *Europhysics Letters*, 119(6), 60002. <a id='1'></a>"
]
}
],
"metadata": {
"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.7"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment