diff --git a/machine_learning/vqe_vqa_applications_hybridNN.ipynb b/machine_learning/vqe_vqa_applications_hybridNN.ipynb new file mode 100644 index 00000000..174cd118 --- /dev/null +++ b/machine_learning/vqe_vqa_applications_hybridNN.ipynb @@ -0,0 +1,1483 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "030cdabf", + "metadata": {}, + "source": [ + "# Quantum Machine Learning: Learning through examples\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c8b160ad", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "# Importing standard Qiskit libraries\n", + "from qiskit import QuantumCircuit, transpile, Aer, IBMQ\n", + "from qiskit.tools.jupyter import *\n", + "from qiskit.visualization import *\n", + "from ibm_quantum_widgets import *\n", + "\n", + "# Supress warnings\n", + "import warnings\n", + "warnings.filterwarnings('ignore')\n", + "\n", + "# Loading your IBM Quantum account(s)\n", + "provider = IBMQ.load_account()" + ] + }, + { + "cell_type": "markdown", + "id": "1e37755c", + "metadata": {}, + "source": [ + "# Overview\n", + "1. Simple VQE example\n", + "2. VQE for LiH\n", + "3. VQA introduction\n", + "4. VQA applications - QAOA\n", + "5. VQA limitations - NISQ\n", + "6. Hybrid algorithms" + ] + }, + { + "cell_type": "markdown", + "id": "be962a00", + "metadata": {}, + "source": [ + "# VQE\n", + "VQE are used for calculating the smallest eigenvalue of a given Hamiltonian. Hamiltonians are energy operators and represent energy evolution in a physical system. Thus, the least eigenvalue of a Hamiltonian corresponds to the energy of the least energy state, or the ground state." + ] + }, + { + "cell_type": "markdown", + "id": "2ccc44a3", + "metadata": {}, + "source": [ + "# Simple VQE example\n", + "Hamiltonians are Hermitian operators. So in the first example we discuss, we will hand-create a Hermitian matrix instead of simulating a physical system. \n", + "## Step 1: Obtaining the operator" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7eb134e9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ┌───┐\n", + "q_0: ┤ X ├\n", + " ├───┤\n", + "q_1: ┤ X ├\n", + " └───┘\n" + ] + } + ], + "source": [ + "from qiskit.quantum_info.operators import Operator\n", + "from qiskit.quantum_info import Pauli\n", + "from qiskit.aqua.operators import OperatorBase\n", + "from qiskit.aqua.operators.primitive_ops import PrimitiveOp\n", + "from qiskit.opflow import CX,X\n", + "import numpy as np\n", + "\n", + "op=QuantumCircuit(2)\n", + "op.x(0)\n", + "op.x(1)\n", + "\n", + "print(op)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ff1737", + "metadata": {}, + "source": [ + "We can manually verify that the lowest eigenvalue of this matrix is -1. It is obtained when the system is in the following state:\n", + "\\begin{equation*}\n", + "\\frac{\\left(\\left|0\\right\\rangle - \\left|1\\right\\rangle\\right)}{\\sqrt{2}}\\frac{\\left(\\left|0\\right\\rangle + \\left|1\\right\\rangle\\right)}{\\sqrt{2}}\n", + "\\end{equation*}" + ] + }, + { + "cell_type": "markdown", + "id": "8b196ed2", + "metadata": {}, + "source": [ + "## Step 2: Defining the ansatz" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "af5b7e0f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit.circuit import Parameter, QuantumCircuit, ParameterVector\n", + "ansatz=QuantumCircuit(2)\n", + "parameters=ParameterVector('x',length=2*6)\n", + "\n", + "param_no=0\n", + "for i in range(2):\n", + " ansatz.rz(parameters[param_no],i)\n", + " param_no+=1\n", + " ansatz.ry(parameters[param_no],i)\n", + " param_no+=1\n", + " ansatz.rz(parameters[param_no],i)\n", + " param_no+=1\n", + "ansatz.cx(0,1)\n", + "for i in range(2):\n", + " ansatz.rz(parameters[param_no],i)\n", + " param_no+=1\n", + " ansatz.ry(parameters[param_no],i)\n", + " param_no+=1\n", + " ansatz.rz(parameters[param_no],i)\n", + " param_no+=1\n", + " \n", + "ansatz.draw()" + ] + }, + { + "cell_type": "markdown", + "id": "a924638e", + "metadata": {}, + "source": [ + "## Step 3: Optimisation of parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "eccf5e91", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Measured eigenvalue after optimisiation is: -0.9999994805699511\n" + ] + } + ], + "source": [ + "from qiskit.algorithms import VQE\n", + "from qiskit.algorithms.optimizers import COBYLA\n", + "from qiskit.aqua.operators import PauliExpectation\n", + "\n", + "from qiskit import Aer\n", + "backend = Aer.get_backend('statevector_simulator')\n", + "\n", + "algorithm = VQE(ansatz,\n", + " optimizer=COBYLA(),\n", + " quantum_instance=backend,\n", + " expectation=PauliExpectation())\n", + "result = algorithm.compute_minimum_eigenvalue(op)\n", + "print(\"Measured eigenvalue after optimisiation is:\", result.eigenvalue)" + ] + }, + { + "cell_type": "markdown", + "id": "b1d10834", + "metadata": {}, + "source": [ + "# LiH example\n", + "Now that we have a better understanding of how VQE works, let's look at a slightly more complicated example with the LiH molecule. The code for this example has been derived from the qiskit textbook" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7fe65db0", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.aqua.algorithms import VQE, NumPyEigensolver\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from qiskit.chemistry.components.variational_forms import UCCSD\n", + "from qiskit.chemistry.components.initial_states import HartreeFock\n", + "from qiskit.circuit.library import EfficientSU2\n", + "from qiskit.algorithms.optimizers import COBYLA, SPSA, SLSQP\n", + "from qiskit.aqua.operators import Z2Symmetries\n", + "from qiskit import IBMQ, BasicAer, Aer\n", + "from qiskit.chemistry.drivers import PySCFDriver, UnitsType\n", + "from qiskit.chemistry import FermionicOperator\n", + "from qiskit.aqua import QuantumInstance\n", + "from qiskit.ignis.mitigation.measurement import CompleteMeasFitter\n", + "from qiskit.providers.aer.noise import NoiseModel" + ] + }, + { + "cell_type": "markdown", + "id": "feeada11", + "metadata": {}, + "source": [ + "## Step 1: Obtaining the operator\n", + "We will create a function that returns the Hamiltonian of the LiH system at a specified interatomic distance. Remember that the smallest eigenvalue of the obtained energy operator corresponds to the energy of the ground state of the molecule at the interatomic distance" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "abd8b117", + "metadata": {}, + "outputs": [], + "source": [ + "def get_qubit_op(dist):\n", + " driver = PySCFDriver(atom=\"Li .0 .0 .0; H .0 .0 \" + str(dist), unit=UnitsType.ANGSTROM, \n", + " charge=0, spin=0, basis='sto3g')\n", + " molecule = driver.run()\n", + " freeze_list = [0]\n", + " remove_list = [-3, -2]\n", + " repulsion_energy = molecule.nuclear_repulsion_energy\n", + " num_particles = molecule.num_alpha + molecule.num_beta\n", + " num_spin_orbitals = molecule.num_orbitals * 2\n", + " remove_list = [x % molecule.num_orbitals for x in remove_list]\n", + " freeze_list = [x % molecule.num_orbitals for x in freeze_list]\n", + " remove_list = [x - len(freeze_list) for x in remove_list]\n", + " remove_list += [x + molecule.num_orbitals - len(freeze_list) for x in remove_list]\n", + " freeze_list += [x + molecule.num_orbitals for x in freeze_list]\n", + " ferOp = FermionicOperator(h1=molecule.one_body_integrals, h2=molecule.two_body_integrals)\n", + " ferOp, energy_shift = ferOp.fermion_mode_freezing(freeze_list)\n", + " num_spin_orbitals -= len(freeze_list)\n", + " num_particles -= len(freeze_list)\n", + " ferOp = ferOp.fermion_mode_elimination(remove_list)\n", + " num_spin_orbitals -= len(remove_list)\n", + " qubitOp = ferOp.mapping(map_type='parity', threshold=0.00000001)\n", + " qubitOp = Z2Symmetries.two_qubit_reduction(qubitOp, num_particles)\n", + " shift = energy_shift + repulsion_energy\n", + " return qubitOp, num_particles, num_spin_orbitals, shift" + ] + }, + { + "cell_type": "markdown", + "id": "9ddbe62d", + "metadata": {}, + "source": [ + "## Step 2: Defining the ansatz\n", + "We will be using the UCCSD ansatz in this example which was developed specifically for the task and provides good convergence, though with a higher circuit cost." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "17c352f4", + "metadata": {}, + "outputs": [], + "source": [ + "def get_ansatz(num_spin_orbitals, num_particles, initial_state):\n", + " return UCCSD(\n", + " num_orbitals=num_spin_orbitals,\n", + " num_particles=num_particles,\n", + " initial_state=initial_state,\n", + " qubit_mapping='parity')" + ] + }, + { + "cell_type": "markdown", + "id": "54ad7df7", + "metadata": {}, + "source": [ + "## Step 3: Optimisation of parameters\n", + "We appeal to the VQE algorithm for distances in the range of $[0.5,4]$ to get estimates for the ground state energies at those distances." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "32eb1537", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Interatomic Distance: 0.5 VQE Result: -7.039673441154231 Exact Energy: [-7.03973252]\n", + "Interatomic Distance: 0.6 VQE Result: -7.313308879471847 Exact Energy: [-7.31334583]\n", + "Interatomic Distance: 0.7 VQE Result: -7.500887035140407 Exact Energy: [-7.50092209]\n", + "Interatomic Distance: 0.8 VQE Result: -7.6309454092259745 Exact Energy: [-7.63097825]\n", + "Interatomic Distance: 0.9 VQE Result: -7.720781099267077 Exact Energy: [-7.72081241]\n", + "Interatomic Distance: 1.0 VQE Result: -7.782211598710951 Exact Energy: [-7.7822424]\n", + "Interatomic Distance: 1.1 VQE Result: -7.823568081535827 Exact Energy: [-7.82359928]\n", + "Interatomic Distance: 1.2 VQE Result: -7.850666132758831 Exact Energy: [-7.85069838]\n", + "Interatomic Distance: 1.3 VQE Result: -7.867529585505405 Exact Energy: [-7.86756329]\n", + "Interatomic Distance: 1.4 VQE Result: -7.8769662539147 Exact Energy: [-7.87700149]\n", + "Interatomic Distance: 1.5 VQE Result: -7.880979506618974 Exact Energy: [-7.88101572]\n", + "Interatomic Distance: 1.6 VQE Result: -7.8810366152224 Exact Energy: [-7.88107204]\n", + "Interatomic Distance: 1.7 VQE Result: -7.878236971026453 Exact Energy: [-7.87826817]\n", + "Interatomic Distance: 1.8 VQE Result: -7.87334521780764 Exact Energy: [-7.87344029]\n", + "Interatomic Distance: 1.9 VQE Result: -7.8671375073664205 Exact Energy: [-7.86723396]\n", + "Interatomic Distance: 2.0 VQE Result: -7.860068380674124 Exact Energy: [-7.86015321]\n", + "Interatomic Distance: 2.1 VQE Result: -7.852535223876043 Exact Energy: [-7.85259583]\n", + "Interatomic Distance: 2.2 VQE Result: -7.844839386841703 Exact Energy: [-7.84487909]\n", + "Interatomic Distance: 2.3 VQE Result: -7.837212706530124 Exact Energy: [-7.83725797]\n", + "Interatomic Distance: 2.4 VQE Result: -7.829853246675605 Exact Energy: [-7.829937]\n", + "Interatomic Distance: 2.5 VQE Result: -7.822930295457727 Exact Energy: [-7.82307664]\n", + "Interatomic Distance: 2.6 VQE Result: -7.816588433692077 Exact Energy: [-7.81679515]\n", + "Interatomic Distance: 2.7 VQE Result: -7.8109343679657055 Exact Energy: [-7.81116828]\n", + "Interatomic Distance: 2.8 VQE Result: -7.806014817613859 Exact Energy: [-7.80622956]\n", + "Interatomic Distance: 2.9 VQE Result: -7.801736627861576 Exact Energy: [-7.8019736]\n", + "Interatomic Distance: 3.0 VQE Result: -7.7980835315372 Exact Energy: [-7.79836343]\n", + "Interatomic Distance: 3.1 VQE Result: -7.795060173703503 Exact Energy: [-7.79534045]\n", + "Interatomic Distance: 3.2 VQE Result: -7.792367398755882 Exact Energy: [-7.79283481]\n", + "Interatomic Distance: 3.3 VQE Result: -7.789686205531288 Exact Energy: [-7.79077401]\n", + "Interatomic Distance: 3.4 VQE Result: -7.787375439134955 Exact Energy: [-7.7890889]\n", + "Interatomic Distance: 3.5 VQE Result: -7.785627456314653 Exact Energy: [-7.78771697]\n", + "Interatomic Distance: 3.6 VQE Result: -7.784375121676893 Exact Energy: [-7.78660376]\n", + "Interatomic Distance: 3.7 VQE Result: -7.783495991918261 Exact Energy: [-7.78570291]\n", + "Interatomic Distance: 3.8 VQE Result: -7.782885672131588 Exact Energy: [-7.78497559]\n", + "Interatomic Distance: 3.9 VQE Result: -7.782466678845639 Exact Energy: [-7.78438961]\n", + "All energies have been calculated\n" + ] + } + ], + "source": [ + "backend = BasicAer.get_backend(\"statevector_simulator\")\n", + "distances = np.arange(0.5, 4.0, 0.1)\n", + "exact_energies = []\n", + "vqe_energies = []\n", + "optimizer = SLSQP(maxiter=5)\n", + "for dist in distances:\n", + " qubitOp, num_particles, num_spin_orbitals, shift = get_qubit_op(dist)\n", + " result = NumPyEigensolver(qubitOp).run()\n", + " exact_energies.append(np.real(result.eigenvalues) + shift)\n", + " initial_state = HartreeFock(\n", + " num_spin_orbitals,\n", + " num_particles,\n", + " qubit_mapping='parity'\n", + " ) \n", + " var_form = get_ansatz(num_spin_orbitals, num_particles, initial_state)\n", + "# var_form = UCCSD(\n", + "# num_orbitals=num_spin_orbitals,\n", + "# num_particles=num_particles,\n", + "# initial_state=initial_state,\n", + "# qubit_mapping='parity'\n", + "# )\n", + " vqe = VQE(qubitOp, var_form, optimizer)\n", + " vqe_result = np.real(vqe.run(backend)['eigenvalue'] + shift)\n", + " vqe_energies.append(vqe_result)\n", + " print(\"Interatomic Distance:\", np.round(dist, 2), \"VQE Result:\", vqe_result, \"Exact Energy:\", exact_energies[-1])\n", + " \n", + "print(\"All energies have been calculated\")" + ] + }, + { + "cell_type": "markdown", + "id": "0df9c7fc", + "metadata": {}, + "source": [ + "We can verify the correctness of VQE here: the graph for energy vs distance matches the graph we get experimentally" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "e69e0369", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(distances, exact_energies, label=\"Exact Energy\")\n", + "plt.plot(distances, vqe_energies, label=\"VQE Energy\")\n", + "plt.xlabel('Atomic distance (Angstrom)')\n", + "plt.ylabel('Energy')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "635a0495", + "metadata": {}, + "source": [ + "Note that the VQE results are very close to the exact results, and so the exact energy curve is hidden by the VQE curve." + ] + }, + { + "cell_type": "markdown", + "id": "3c6b86d6", + "metadata": {}, + "source": [ + "## Observations about VQE\n", + "1. VQEs introduce us to an interesting paradigm: we create circuits with variable gates, which can potentially capture a target state given good values of the variables, and then delegate the solving process to a classical optimizer. This paradigm captures the essence of **Variational Quantum Algorithms**. \n", + "2. VQAs are a natural extension to classical neural network models (see also [this review on VQAs](https://arxiv.org/abs/2012.09265) ), as is evident from the very similar approach employed for both. Just like classical neural network models, clever choices for the network and cost functions can generate excellent algorithms for solving many problems. In fact, as we will see later, they are so similar that we can easily embed quantum circuit layers into classical neural networks." + ] + }, + { + "cell_type": "markdown", + "id": "92148bb8", + "metadata": {}, + "source": [ + "# Variational Quantum Algorithms" + ] + }, + { + "cell_type": "markdown", + "id": "76f187db", + "metadata": {}, + "source": [ + "## Why VQA?\n", + "If they are so similar, why go for quantum, and why VQAs in general?\n", + "Provable gaurantees of efficiency of quantum over classical" + ] + }, + { + "cell_type": "markdown", + "id": "0ede7af0", + "metadata": {}, + "source": [ + "In the following section we will go over one of the many applications for VQAs" + ] + }, + { + "cell_type": "markdown", + "id": "857461f2", + "metadata": {}, + "source": [ + "## QAOA\n", + "The Quantum Approximate Optimisation Algorithm is one of most famous applications of VQAs. The algorithm is designed for combinatorial optimisation problems, in which we have to choose one of many possibilities. The max-cut problem, is one such combinatorial optimisation problem. Given an undirected flow graph, the objective is to partition the set of verticies in two, such that the sum of flows between the two partitions is maximised." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0afcba29", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import networkx as nx\n", + "\n", + "from qiskit import BasicAer\n", + "from qiskit.aqua.algorithms import NumPyMinimumEigensolver\n", + "from qiskit.optimization.applications.ising import graph_partition\n", + "from qiskit.optimization.applications.ising import max_cut\n", + "from qiskit.optimization.applications.ising.common import random_graph, sample_most_likely" + ] + }, + { + "cell_type": "markdown", + "id": "ac1422dd", + "metadata": {}, + "source": [ + "We will be working with the very simple flow graph as shown below. ( This graph has been taken from the great QAOA tutorial at this [blog](https://www.mustythoughts.com/quantum-approximate-optimization-algorithm-explained) )" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f390a7d3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 0 10 10]\n", + " [10 0 1]\n", + " [10 1 0]]\n" + ] + } + ], + "source": [ + "num_nodes = 3\n", + "w = np.array([[0, 10, 10], [10, 0, 1], [10, 1, 0]])\n", + "print(w)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a06667aa", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "G = nx.from_numpy_matrix(w)\n", + "layout = nx.random_layout(G, seed=10)\n", + "colors = ['r', 'g', 'b']\n", + "nx.draw(G, layout, node_color=colors)\n", + "labels = nx.get_edge_attributes(G, 'weight')\n", + "nx.draw_networkx_edge_labels(G, pos=layout, edge_labels=labels);" + ] + }, + { + "cell_type": "markdown", + "id": "0fd0a11f", + "metadata": {}, + "source": [ + "You will find that the process followed for VQAs is very similar to the VQE procedure" + ] + }, + { + "cell_type": "markdown", + "id": "af064c55", + "metadata": {}, + "source": [ + "## Step 1: Obtaining the Operator\n", + "We model the max-cut problem as a cost maximisation problem. To do so, we model each vertex in the graph as a single qubit. The qubit being in state $\\left|0\\right\\rangle$ or $\\left|1\\right\\rangle$ represents whether the corresponding vertex is in the first or the second partition.\n", + "\n", + "We devise the following cost hamiltonian. \n", + "\n", + "\\begin{equation*}\n", + "H_C = \\sum_{i,j} \\frac{w_{i,j}}{2} (1 - \\sigma_z^i\\sigma_z^j)\n", + "\\end{equation*}\n", + "\n", + "Every state in which each qubit is either in either $\\left|0\\right\\rangle$ or $\\left|1\\right\\rangle$ is an eigenstate of this hamiltonian. The product $\\sigma_z^i\\sigma_z^j$ is 1 or -1 depending on whether vertices $i$ and $j$ are in the same or in different partitions. Thus the eigenvalue corresponding to any such state is equal to the sum of weights of edges going between the partitions. This is the exact value that we want to maximise in max-cut and hence we are satisfied with this construction of ours." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2eae1d11", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 0, 0]\n", + "0.0\n", + "[0, 0, 1]\n", + "11.0\n", + "[0, 1, 0]\n", + "11.0\n", + "[0, 1, 1]\n", + "20.0\n", + "[1, 0, 0]\n", + "20.0\n", + "[1, 0, 1]\n", + "11.0\n", + "[1, 1, 0]\n", + "11.0\n", + "[1, 1, 1]\n", + "0.0\n", + "Objective value computed by the brute-force method is 20.0\n" + ] + } + ], + "source": [ + "def brute_force():\n", + " # use the brute-force way to generate the oracle\n", + " def bitfield(n, L):\n", + " result = np.binary_repr(n, L)\n", + " return [int(digit) for digit in result] # [2:] to chop off the \"0b\" part\n", + "\n", + " L = num_nodes\n", + " max = 2**L\n", + " maximal_v = -np.inf\n", + " for i in range(max):\n", + " cur = bitfield(i, L)\n", + " cur_v = 0\n", + " \n", + " for j in range(num_nodes):\n", + " for k in range(num_nodes):\n", + " if cur[j]!=cur[k]:\n", + " cur_v += w[j][k]\n", + " \n", + " cur_v/=2\n", + " print(cur)\n", + " print(cur_v)\n", + " if cur_v > maximal_v:\n", + " maximal_v = cur_v\n", + " return maximal_v\n", + "\n", + "sol = brute_force()\n", + "print(f'Objective value computed by the brute-force method is {sol}')" + ] + }, + { + "cell_type": "markdown", + "id": "161dd095", + "metadata": {}, + "source": [ + "## Step 2: Defining the ansatz\n", + "We use the following ansatz. It is developed by taking inspiration from adiabatic computation and trotterization, but is beyond the scope of this talk. Note that we take p as a parameter, which dictates the number of layers in our circuit. The higher the p the better results we get." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a693f42e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit.circuit import Parameter, QuantumCircuit, QuantumRegister, ParameterVector\n", + "\n", + "def get_qaoa_ansatz(p=1, show=False):\n", + "\n", + " ansatz = QuantumCircuit(num_nodes)\n", + " gamma = ParameterVector('g',p)\n", + " beta = ParameterVector('b',p)\n", + " \n", + " for i in range(num_nodes):\n", + " ansatz.h(i)\n", + "\n", + " for layer in range(p):\n", + " if show:\n", + " ansatz.barrier()\n", + "\n", + " for i in range(num_nodes):\n", + " for j in range(i+1, num_nodes):\n", + " ansatz.crz(-w[i][j]*2*gamma[layer], i, j)\n", + " ansatz.rz(gamma[layer]*w[i][j], i)\n", + " ansatz.rz(gamma[layer]*w[i][j], j)\n", + "\n", + " if show:\n", + " ansatz.barrier()\n", + "\n", + " for i in range(num_nodes):\n", + " ansatz.rx(beta[layer]*2,i)\n", + "\n", + "# ansatz.barrier()\n", + "\n", + " # ansatz.measure(range(num_nodes), range(num_nodes))\n", + "\n", + "# ansatz.draw()\n", + " \n", + " return ansatz\n", + "\n", + "get_qaoa_ansatz(1, True).draw()" + ] + }, + { + "cell_type": "markdown", + "id": "0b21a466", + "metadata": {}, + "source": [ + "## Step 3: Optimising the parameters\n", + "Note the use of VQE routine of qiskit, to illustrate the similarity" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9a92e139", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "optimal function value: 20.0\n", + "optimal value: [1. 0. 0.]\n", + "status: SUCCESS\n" + ] + } + ], + "source": [ + "from qiskit import Aer\n", + "from qiskit.algorithms import VQE, QAOA\n", + "from IPython.display import display, clear_output\n", + "from qiskit.algorithms.optimizers import COBYLA\n", + "# provider = IBMQ.load_account()\n", + "\n", + "def callback(eval_count, parameters, mean, std): \n", + " # Overwrites the same line when printing\n", + " display(\"Evaluation: {}, Energy: {}, Std: {}\".format(eval_count, mean, std))\n", + " clear_output(wait=True)\n", + " counts.append(eval_count)\n", + " values.append(mean)\n", + " \n", + " \n", + "def run_qaoa(layers, backend_name):\n", + " if backend_name != \"statevector_simulator\":\n", + " backend = provider.get_backend(backend_name)\n", + " else:\n", + " backend = Aer.get_backend(backend_name)\n", + "\n", + " ansatz = get_qaoa_ansatz(layers)\n", + "\n", + " # Set initial parameters of the ansatz\n", + " # We choose a fixed small displacement\n", + " try:\n", + " initial_point = [0.01] * len(ansatz.ordered_parameters)\n", + " except:\n", + " initial_point = [0.01] * ansatz.num_parameters\n", + "\n", + " from qiskit_optimization import QuadraticProgram\n", + " from qiskit_optimization.algorithms import MinimumEigenOptimizer\n", + " problem = QuadraticProgram()\n", + " _ = [problem.binary_var('x{}'.format(i)) for i in range(num_nodes)] # create n binary variables\n", + " linear = w.dot(np.ones(num_nodes))\n", + " quadratic = -w\n", + " problem.maximize(linear=linear, quadratic=quadratic)\n", + "\n", + " from qiskit.aqua.operators import PauliExpectation\n", + " # qaoa = QAOA(optimizer = COBYLA(maxiter=5000), \n", + " # reps=layers, \n", + " # quantum_instance=backend, \n", + " # callback = callback, \n", + " # initial_point = initial_point)\n", + " qaoa = VQE(ansatz, optimizer=COBYLA(maxiter=10), quantum_instance=backend, callback = callback, initial_point= initial_point)\n", + " algorithm = MinimumEigenOptimizer(qaoa)\n", + " result = algorithm.solve(problem)\n", + " return result, counts, values\n", + "\n", + "\n", + "counts = []\n", + "values = [] \n", + "result, counts, values = run_qaoa(1,\"statevector_simulator\")\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "bdfb0a22", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "fig, ax = plt.subplots(1, 1)\n", + "ax.set_xlabel('Iterations')\n", + "ax.set_ylabel('Cost')\n", + "ax.grid()\n", + "ax.plot(counts, values)\n", + "ax.axhline(20, linestyle='--')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c2539bbb", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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UUREBCVEERERQAlRREQEUEIUEREBlBBFREQAJUQRERFACVFERARQQhQREQGUEEVERAAlRBGpZ8GCBaSlpZGamsrUqVP32z5z5kyGDh3K8OHDyc3NrV0JfdmyZQwfPpzhw4czbNgw5s6dC8CaNWtqy4cPH07Xrl2ZPn16OA9JpFk0l6mI1KqurmbQoEEsXLiQpKQkRowYwezZs/dZXWPHjh107doVgBdffJFHH32UBQsW8Pnnn9OxY0fi4uL48MMPGTZsGB988AFxcXH7PH5iYiJFRUUcf/zxYT8+kabmMtVqFyJt4Nrpbfv4j9/aNo+7bNkyUlNTGTBgABCs1zhv3rx9EmJNMgTYvXs3ZgZA586da8v37t1bW17XokWLOOGEE5QMJSopIYpIrfLycpKTk2vvJyUlUVRUtF+9Rx55hIceeojKykpee+212vKioiKuvvpqNm7cyKxZs/Y5OwTIz8/nsssua7sDEDkEuoYoIi1244038v777zNt2jTuvffe2vLs7GxWrVrFW2+9xZQpU9i7d2/ttsrKSl588UUuvvjiSIQsckBKiCJSKzExkU2bNtXeLysrIzExsdH6l156KS+88MJ+5YMHDyYhIYGVK1fWls2fP5/MzEx69+7dqjGLtBYlRBGpNWLECNatW0dpaSmVlZXk5+eTl5e3T51169bV3n7ppZcYOHAgAKWlpVRVVQGwceNG3n33XVJSUmrrzp49W82lEtV0DVFEasXFxTFjxgzGjh1LdXU1V199NRkZGUyaNImsrCzy8vKYMWMGf/3rX+nQoQPdunXjqaeeAqCgoICpU6fSoUMH2rVrx6OPPkrPnj2BoPPNwoULeeyxxyJ5eCJN0rALkTYQq71MRQ53TQ27UJOpiIgISogiIiKAEqKIiAighCgiIgIoIYqIiABKiCIiIoASooiICKCEKCIiAighioiIAEqIIiIigBKiiIgIoIQoIiICaLULEalHE5PLkUpniCIiIighioiIAEqIIiIigBKiiIgIoIQoIiICKCGKiIgASogiIiKAEqKIiAighCgiIgIoIYqIiABKiCIiIoASooiICKCEKCIiAighioiIAEqIIiIigBKiiIgIoIQoIiICRCAhmtkNZlZqZnvNbLmZndlE3VFm9ncz22Zme8zsXTO7I5zxiojIkSEunP+ZmY0HHgZuAApC/843s3R3/3cD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a9Yshg4dyvDhwwG477779hvELSJHLiXEJixYsIBbbrmF6upqrrnmGn784x/vs72iooIrrriC5cuX06NHD+bMmUNKSgrbtm3joosu4q233uLKK69kxowZtfvMmTOHX/3qV1RXV3Puuecybdq0cB9WTDjYGUcuv/xyLr/88v3Kc3Nza9e9ExFpiJpMG3Eoq2936tSJX/7ylzz44IP71N+2bRt33nknixYtYtWqVWzevJlFixaF7ZhERKRxSoiNOJTVt48++mhyc3Pp1KnTPvXXr1/PwIEDOfbYYwE4++yz+fOf/xyeAxIRkSapybQRDY2FKyoqarRO3bFwPXv2bPAxU1NTWbNmDRs2bCApKYkXXniBysrKtjuIGKcB1iISTkqIYdStWzd+97vfMX78eNq1a8fpp5/O+++/H+mwREQENZk2qrXGwtV33nnnUVRURGFhIWlpaQwaNKj1gxcRkRZTQmzEoYyFa8rWrVsB+OSTT3j00Ue55ppr2uYARESkRdRk2ohDXX07JSWFHTt2UFlZyQsvvMCrr75Keno6t9xyCytWrABg0qRJOkMUEYkSSohNOJTVt2vW56tv9uzZrRafiIi0HjWZioiIoIQoIiKtYMGCBaSlpZGamsrUqVP3215RUcH48eNJTU0lOzt7n1a0KVOmkJqaSlpaGq+88kpteUpKSu10i1lZWW1+DGoyPYC2HAsHGg8nIrGvZmavhQsXkpSUxIgRI8jLy9tnAe66M3vl5+dz1113MWfOHFavXk1+fj6rVq3igw8+4Oyzz2bt2rW0b98egL/97W+Nju1ubTpDFBGRQ3IoM3vNmzePSy+9lPj4ePr3709qairLli2LxGEoIYqIyKFpaGav8vLyRuvUndmrqX3NjK9//euccsop/P73v2/z41CTqYiIRKWCggISExPZunUrY8aM4cQTT2TkyJFt9v/pDFFERA7Joczs1dS+Nf/26tWL888/v82bUpUQRUTkkBzKzF55eXnk5+dTUVFBaWkp69at49RTT2X37t3s3LkTgN27d/Pqq68yZMiQNj0ONZmKiMghOZSZvTIyMrjkkktIT08nLi6ORx55hPbt27NlyxbOP/98IDij/M53vsM555zTtsfRpo/eADO7AbgTOA5YBdzq7q83UX8U8BCQAXwA3O/uM8MRq4iINM+hzOz1k5/8hJ/85Cf7lA0YMKB2mstwCWuTqZmNBx4G7gNOBv4OzDezfo3U7w+8HKp3MjAF+K2ZXRieiEVE5EgR7jPE24En3f3x0P2bzewc4AfA3Q3Uvx74wN1vDt3/l5llA3cAWmpeRCRKHA6TmITtDNHMOgKnAK/W2/QqcHoju+U0UP8VIMvMOrRuhCIiciQLZ5NpT6A9sKVe+RagTyP79Gmkflzo8URERFqFuXt4/iOzvkA5MMrdl9YpnwRMcPe0BvZZCzzj7vfUKRsJLAH6uvuH9epfB1wXupsGrGn1AzmwnsDHEfh/W0Msxw6xHb9ij5xYjl+xt9zx7n5sQxvCeQ3xY6Aa6F2vvDewuZF9NjdSv4oGnkh3/z3Q9vP7NMHMit297adlbwOxHDvEdvyKPXJiOX7F3rrC1mTq7pXAcmBMvU1jCHqRNqSwkfrF7v5F60YoIiJHsnDPVPMQcKWZXWNmg83sYaAvMBPAzJ42s6fr1J8JJJrZ9FD9a4ArgQfDHLeIiBzmwjrswt3nmFkP4KcEA/NXAuPcfWOoSr969UvNbBzw/xMMzfgA+KG7R/OQi4g22R6iWI4dYjt+xR45sRy/Ym9FYetUIyIiEs00ubeIiAhKiCIiIoASYqszM4t0DCIi0nJKiK3MdVE2IvRDREQOlTrVtAIziwdOAs4HPiNY1uo9YJO77zYzU6IMDz3X4Wdm7dz9y0jHcSSq+9zrvX/olBBbgZn9BrgA+BDoBqQQDBF5AZju7usjFlwzmVl7ghPcmPpiM7MEYCRwKfAJsA5YC6x09w8iGVtzmVkc8GWsPfcSHcysi7vvjHQchwMlxENkZunAm8BFwHJ332ZmxwITge8TTFB+C/B4NP56M7NT3H15vbL2BF/QURdvfWb2FEFCXEfwYySZIDG+TfCcvxa56JpmZrnuXlCvLGaSo5klA1cDI4D3CeYOXgX8090/idYzlrpxxdLzXZeZDSZYTu9kgtaofwMrgKXuvilUJyqf/2imhHiIzOy/gHPcfWTofpy7V9XZfh/B2eNZ0XbGYmYDCb7EVhMsszXL3f9RZ7sRTN5wMvB2aPq9qBH6MVJEMJ3fW+5ebWbHAJcA1wBZwD3AvURZgjezEwme993AS8Bv3f2NOtsN6ACMBZa5e/1VXyIqtHj3n4GjgLeAIQTzDG8DXgcecvf3Ixdh40I/WAfXW2TACFbjqY6m90lDzOwEgoXTtwBvACcS/PCOJ0iOf3D3+svmRQUz603weX3Z3bc3Ua9DJKbnVKeaQ/cv4DgzSwVw9yozizOzTqHtjwOfE5xBRpvLCH7ZLwROA/5iZm+a2Y/MLDn0xdCL4Ay4VwTjbMzXgRXu/mYoGXZ098/c/XF3zwZuJEiMJ0Thl9wFBL/o7wMSgSVmttnMHjSzmni/AswDOkYuzEbdRbB6zVfd/Qp3zyRYv/RPwLnAm2b2rUgG2ITJwOLQ8/2ImaV7oMrd3czamVk/M7s41FoSbe4guCzwTXe/293PB74N/IYgMc41s4kRjK8pPwWeBt4zs+fMbFyoD0YtM+sH3FK/PByUEA/dUoLVN/5iZpeYWXzog7UXgunnCH55VkQyyEakEfzSnAZcC/wXwXR63wUKzez/gMeAf7l7WcSibNwK4Hgz+xoEE8iHfowcFdr+HLCRIPFHm0SCX/ePAd8CzgL+G/gmsM7M/gnkEzz3myIWZeMygCXuvtnMOoRaRv7t7tPc/Xjgr8D1oeQSbT2ARxDMk/w7IBdYaWbvmdl/mVn3UPPp94Bp7l4dyUAbcTxQ4u47zay9mbV39y3u/mSopWomcK2ZdY5wnA3JIvi++f8ILnHMBUrN7Ldmlhmqcy1wvbuH/zvT3fV3iH8EE5TP4T9Nj/cSfMENAh4GPgKOjnSc9WKOA74D3F2vvDvBL/2bgP8BvgQmRjreRo6hE8HZ7YfA9cBRDdR5G7gx0rHWi6k9MA64oV55R4L5fM8laFn4Ergq0vE2cgyTQ89tlzplHWpeA4JE8z5wWqRjrRf38cArBIsEtCP4YTIWeITgOtyXBD9UtgO3RTreRo7hllCsJ9Z773QM3U4HSgnO3iMeb50Y+xL8SL0udD+OoLn3rtB7qRp4h+Aywi2RiFHXEFtJaNLycwnaxwcQnH11I1jM+DF3z49geAfUUJu9mV0APA8kuPvnkYmsaaGzwV8RNEnvIWjenQfsAq4i+GJOi9b4oeFhC2Y2FphPlD73ZnYK8H8Ea5ZOdvcX620/keBLrns0xW9mXQmGR21w9yV1yo8i+MI+BbiB4H3Txd33RCTQJoSu3/4vQZP6L939v+ttHwKUAF+Jsuf+aIITha3uXlRvW2eC69B3EFxOiMhzr4R4CMwsCUgN3d1NcIa4hyAhJhBcO/zYm7h4HCmNjR0L9bqrdnc3sweBLHcfHfYAmyHUVFQdGnqRC5xJcC00k+As7K8EPU3nRzDM/YSaEK2h579OnclAjruPDVtgzVTTezF03fx+gue8pjPNfIIzlIuAUne/JHKRNq2mI43X6QQXKv8TkBit73sIhloAU4AJBGfmrxK834cQfBbedvcrIhfhgTXUC9bMniS45n9mRGJSQjw4ZvYDgi7nwwgS33qgDPgb8LxH53WfWnWSuRE0E61x9811thvBta1yd38rMlG2jJl1BI4l+FHSCfjM3XdHNqqDY2ajgY/cfVWEQ2lSqPPY2QQtI6cSXFvcTtDk+4z/Z2m3qFW3hylBr9mlwBSPwmXmQrG2C/0Q7AQMJRh2dBbBD8FS4Bngf+t+nqOBmbUjGOvcYNIJnaXPA37n7nPDGlxNDEqILRdqHn0P+DXBhfljCb4URhP8Oq5Zt3F1NI4FqpfMdxMcSxlBc+ML7r4mguEdkJkdVbc55UAftGhSP/ZYE3quv0Xwnj+K4Drh6+7+WegL2gmauz6OYJgNqhd7Z4JeskvcfWudOvHA2e7+UmSibDmrM27YzI5x988iHdPBMLMOBC1ShRGLIQa+Q6KOmd0MfNeDrv31t+USNGUkAqdG2xfDAZL5YILEeFsombf3KOtlZ2bdCHqXvkTwS/jvNYmwbmK0YOBymUfRDB4HiL3uYPHBwIfu/mmkYm1IqJnuj8BXCVoVyglaGD4naK57xt3XhepG1XRuDcReRpC89xJc55/l7u9GLsKmhZJFf2CjN9D7Mhp/eNc4UOzRRMMuDk4l0CV08Roziw811+HBzCMTCD5oX49ciI36DrDW3e91923u/q67z3D3iwhm1ulMMISkZ7Qlw5DvEgwAP4Wgaes9M7vHzNLcveZXcjLwLEGyjyZNxV6TDGti7x65MBv1Q4LOYuPcvTfBe+nXwD8JOpQ9ZMGgd6IpGYbUj30CMJ2gV+PXgftrYo9SNwL/AGaa2Xlm1qfuGMnQ+76rmX0jlICiSZOxQ9DZycy+WfM9Gik6QzwIobOsJQRNjLfVnIXYvhPt/p2g+fH+yEW6PzP7PkG37UvcfWWoicg9NAuNBYNiFwD3uvuzEQy1QWb2OMG1nkkEg5AvI+jAMYBgxpT/BnoAP3H3hEjF2ZBYjh3AzF4H5rr7Q/XK2wNnEJyBve/u50QivqbEcuwAZlZI8CM7DjidYNjFXILepu+EmqyvB65099MiF+n+Yil2nSG2UOii9naCGRfGAB+Y2R9D3dCxYIaL7xJc7P6fyEXaqOcJmoxutWBS4AoPBrS3A3D3fwOfAkkRjLFBoeS9mmAVka3u/k93v5tgsO/Y0LbJBMMwpkUs0AbEcuxQ2/t4JXBhzZmUBYPC27l7tQfToF0PJJnZsEjGWl8sxw61U819QdBj+kyCsZR/JDgrXwq8ZmZ3AbcSTGUYNWIudo+CAZux+EcwBugkgg/SKwTj3nYRXJ97n2BsVsTjrBezhf6+TTCDy06CN+cpBD+O+hE06+0EUiIdbyPHEA/0Cd1uT9Djru720QQJPynSsR5OsYfiOy303p4G9G5ge3LoM5AY6VgPs9iPA24Dxjaw7WSCSQW2hd47URV/rMWuJtMWMLNewOUE0w59TNC9/1OggKD5tAPBUIYF7r42QmEekJl9hSD5nU4wSPmM0KbNBAlzlrtPjkhwTagz/m0AsNvrTHhdZ9skgqaXAZGLdH+xHDvUdlhqRzDZwX0EzV9/Jpih6d8EPw7PBdLdfUSk4mxILMdeIzQkwd19b6iVCvjPguRm9iuC66MnRyrGxsRS7EqILWDBoNEMghk6thN0fBhKMEXbVuCnXm8GhmgR68m8Tvy3EzzXVQRTtj1HMOZqd+jDdi3wgbv/JWLB1hPLsTck9IPqSoJONcMJWhT2ElwHnRKtnwGI+dgb7ElqwSwvJcAT7h51ze0QO7ErITZT6AtrJ8EvmaV1yvoB2QSrKgwg6KxSErFAGxHLyRwajf9kgrkQy4AHPHqXvHmSGI0daqc721n3Cy101tWJYEamIQRnvVH3/onl2KHh+Buo0wkYD8z2KFqiLRZjV0JsJjPLIFh94Fp3f7OB7fEEkwIv9KCzRNQ4DJJ5Y/EnEVwbupbgYv1l0RZ/LMdew8weA5aF/ja6+44G6nTzKFwUOJZjh2bH/xWPsjGrEKOxR/oiZqz8EczKsQgoBAZSr0NEqM7NBHMIRjzeenFlEIy3anDlAYLOHsUETUYRj/cg4u8YrfHHcuyh+C4j6PDwKcH0hI8RTL6cyn9WtkgAXgCGRjrewyX2JuI/HzihTvw1050NiXS8h0PsOkNsATM7jWCtsT0EL/Ai4BN33xVqC38a2Ovu341gmPsJXdT+C8Gg+ysIxlvVX13hZoJlnoaHP8KmxXL8sRw77DN28n6CZPI9gi+1NQRraS4iGPD+sLtH1ULGsRw7xHb8sRq7EmILWTA7zc+APIJ5QAsJ1js8m6CjxDXu/k7kImxYrCbzGrEcf6zGHhq/9yOgq7v/uE55BkFT70UE1+K+Ajzl7lGzSnssxw6xHX9Mx66EeHBCPQe/STCmby/BwN/nPLrnQ4zJZF4jluOP1dgtmH+1t7u/a8G0Wl94nS8NMxsPzAYy3f3tCIXZoFiOHWI7/liNXQmxFViUTWR8ILGYzOuK5fhjOfYaoV6a5sESRNcSNHt1jnRczRHLsUNsxx8LsSshHuFiLZnXF8vxx3LsNczsdoJFdh+IdCwtFcuxQ2zHH62xKyGKyEGzYGWF6lhM7LEcO8R2/NEauxKiiIgIWu1CREQEUEIUEREBlBBFREQAJUQRERFACVFERARQQhQREQHg/wFBJtZK9LyffAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit.visualization import plot_histogram\n", + "\n", + "hist={}\n", + "labels=[]\n", + "\n", + "for entry in result.raw_samples:\n", + "# hist.append({\"\".join([str(dig) for dig in entry.x]): entry.probability*1024})\n", + " hist[\"\".join([str(dig) for dig in entry.x])]= entry.probability*1024\n", + " \n", + "plot_histogram(hist)" + ] + }, + { + "cell_type": "markdown", + "id": "a6e46bf6", + "metadata": {}, + "source": [ + "We get 70% probability of the best states, in just 10 steps!" + ] + }, + { + "cell_type": "markdown", + "id": "db8ae3ee", + "metadata": {}, + "source": [ + "# NISQ\n", + "Let's run the previous algorithm on real IBM hardware. We optimise for 10 steps to restrict the number of calls made to the hardware." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03f960d4", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.8/site-packages/qiskit/utils/run_circuits.py:382: DeprecationWarning: Passing a Qobj to Backend.run is deprecated and will be removed in a future release. Please pass in circuits or pulse schedules instead.\n", + " job = backend.run(qobj, **backend_options, **noise_config)\n" + ] + } + ], + "source": [ + "counts = []\n", + "values = [] \n", + "result, counts, values = run_qaoa(1,\"ibmq_belem\")\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed5704ea", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1, 1)\n", + "ax.set_xlabel('Iterations')\n", + "ax.set_ylabel('Cost')\n", + "ax.grid()\n", + "ax.plot(counts, values)\n", + "ax.axhline(20, linestyle='--')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c347ba2", + "metadata": {}, + "outputs": [], + "source": [ + "hist={}\n", + "labels=[]\n", + "\n", + "for entry in result.raw_samples:\n", + "# hist.append({\"\".join([str(dig) for dig in entry.x]): entry.probability*1024})\n", + " hist[\"\".join([str(dig) for dig in entry.x])]= entry.probability*1024\n", + " \n", + "plot_histogram(hist)" + ] + }, + { + "cell_type": "markdown", + "id": "ef1a0aa3", + "metadata": {}, + "source": [ + "The hardware reports the following frequency of occurence of states out of 1024, after 10 optimisation steps." + ] + }, + { + "cell_type": "markdown", + "id": "c36ec367", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "id": "64376ca7", + "metadata": {}, + "source": [ + "Note that the probability of the best states are only slightly more than 25%, compared to 70% from the simulator. Besides, we could have got 25% from the uniform distribution itself. But, we only optimised for 10 steps and results are not totally dissapointing. The worst states have a significantly smaller probability than the uniform distribution." + ] + }, + { + "cell_type": "markdown", + "id": "318ad114", + "metadata": {}, + "source": [ + "# Hybrid NN for MNIST\n", + "Hybrid NN strive to overcome difficulties of using QNNs by running shallow circuits, and on very few qubits. They still potentially provide assurances similar to VQAs by interleaving quantum layers with classical layers.\n", + "In this example, derived from the qiskit textbook, we will append a quantum layer to a classical NN and attempt classification of 0 and 1 on the MNIST dataset. The purpose of this example is to illustrate the compatibility between quantum and classical neural networks and not to illustrate the advantages/disadvantages of any approach" + ] + }, + { + "cell_type": "markdown", + "id": "5cd3ed33", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "id": "bd0b25c6", + "metadata": {}, + "source": [ + "### Code!" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "95e25a0e", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import torch\n", + "from torch.autograd import Function\n", + "from torchvision import datasets, transforms\n", + "import torch.optim as optim\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "\n", + "import qiskit\n", + "from qiskit import transpile, assemble\n", + "from qiskit.visualization import *" + ] + }, + { + "cell_type": "markdown", + "id": "ea0b7c1c", + "metadata": {}, + "source": [ + "## 1. The quantum layer" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a047d635", + "metadata": {}, + "outputs": [], + "source": [ + "class QuantumCircuit:\n", + " \"\"\" \n", + " This class provides a simple interface for interaction \n", + " with the quantum circuit \n", + " \"\"\"\n", + " \n", + " def __init__(self, n_qubits, backend, shots):\n", + " # --- Circuit definition ---\n", + " self._circuit = qiskit.QuantumCircuit(n_qubits)\n", + " \n", + " all_qubits = [i for i in range(n_qubits)]\n", + " self.theta = qiskit.circuit.Parameter('theta')\n", + " \n", + " self._circuit.h(all_qubits)\n", + " self._circuit.barrier()\n", + " self._circuit.ry(self.theta, all_qubits)\n", + " \n", + " self._circuit.measure_all()\n", + " # ---------------------------\n", + "\n", + " self.backend = backend\n", + " self.shots = shots\n", + " \n", + " def run(self, thetas):\n", + " t_qc = transpile(self._circuit,\n", + " self.backend)\n", + " qobj = assemble(t_qc,\n", + " shots=self.shots,\n", + " parameter_binds = [{self.theta: theta} for theta in thetas])\n", + " job = self.backend.run(qobj)\n", + " result = job.result().get_counts()\n", + " \n", + " counts = np.array(list(result.values()))\n", + " states = np.array(list(result.keys())).astype(float)\n", + " \n", + " # Compute probabilities for each state\n", + " probabilities = counts / self.shots\n", + " # Get state expectation\n", + " expectation = np.sum(states * probabilities)\n", + " \n", + " return np.array([expectation])" + ] + }, + { + "cell_type": "markdown", + "id": "c0077ff2", + "metadata": {}, + "source": [ + "## 2. Define forward and backward passes\n", + "Treat the quantum layer as a black box and compute gradients on the quantum layer using stochastic approximation" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c6e4b4ba", + "metadata": {}, + "outputs": [], + "source": [ + "class HybridFunction(Function):\n", + " \"\"\" Hybrid quantum - classical function definition \"\"\"\n", + " \n", + " @staticmethod\n", + " def forward(ctx, input, quantum_circuit, shift):\n", + " \"\"\" Forward pass computation \"\"\"\n", + " ctx.shift = shift\n", + " ctx.quantum_circuit = quantum_circuit\n", + "\n", + " expectation_z = ctx.quantum_circuit.run(input[0].tolist())\n", + " result = torch.tensor([expectation_z])\n", + " ctx.save_for_backward(input, result)\n", + "\n", + " return result\n", + " \n", + " @staticmethod\n", + " def backward(ctx, grad_output):\n", + " \"\"\" Backward pass computation \"\"\"\n", + " input, expectation_z = ctx.saved_tensors\n", + " input_list = np.array(input.tolist())\n", + " \n", + " shift_right = input_list + np.ones(input_list.shape) * ctx.shift\n", + " shift_left = input_list - np.ones(input_list.shape) * ctx.shift\n", + " \n", + " gradients = []\n", + " for i in range(len(input_list)):\n", + " expectation_right = ctx.quantum_circuit.run(shift_right[i])\n", + " expectation_left = ctx.quantum_circuit.run(shift_left[i])\n", + " \n", + " gradient = torch.tensor([expectation_right]) - torch.tensor([expectation_left])\n", + " gradients.append(gradient)\n", + " gradients = np.array([gradients]).T\n", + " return torch.tensor([gradients]).float() * grad_output.float(), None, None\n", + "\n", + "class Hybrid(nn.Module):\n", + " \"\"\" Hybrid quantum - classical layer definition \"\"\"\n", + " \n", + " def __init__(self, backend, shots, shift):\n", + " super(Hybrid, self).__init__()\n", + " self.quantum_circuit = QuantumCircuit(1, backend, shots)\n", + " self.shift = shift\n", + " \n", + " def forward(self, input):\n", + " return HybridFunction.apply(input, self.quantum_circuit, self.shift)" + ] + }, + { + "cell_type": "markdown", + "id": "7bfd0905", + "metadata": {}, + "source": [ + "## 3. Creating the final NN" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "67ea52b5", + "metadata": {}, + "outputs": [], + "source": [ + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super(Net, self).__init__()\n", + " self.conv1 = nn.Conv2d(1, 6, kernel_size=5)\n", + " self.conv2 = nn.Conv2d(6, 16, kernel_size=5)\n", + " self.dropout = nn.Dropout2d()\n", + " self.fc1 = nn.Linear(256, 64)\n", + " self.fc2 = nn.Linear(64, 1)\n", + " self.hybrid = Hybrid(qiskit.Aer.get_backend('qasm_simulator'), 100, np.pi / 2)\n", + "\n", + " def forward(self, x):\n", + " x = F.relu(self.conv1(x))\n", + " x = F.max_pool2d(x, 2)\n", + " x = F.relu(self.conv2(x))\n", + " x = F.max_pool2d(x, 2)\n", + " x = self.dropout(x)\n", + " x = x.view(1, -1)\n", + " x = F.relu(self.fc1(x))\n", + " x = self.fc2(x)\n", + " x = self.hybrid(x)\n", + " return torch.cat((x, 1 - x), -1)" + ] + }, + { + "cell_type": "markdown", + "id": "424418b7", + "metadata": {}, + "source": [ + "### Data Loading" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ee949c4d", + "metadata": {}, + "outputs": [], + "source": [ + "# Concentrating on the first 100 samples\n", + "n_samples = 100\n", + "\n", + "X_train = datasets.MNIST(root='./data', train=True, download=True,\n", + " transform=transforms.Compose([transforms.ToTensor()]))\n", + "\n", + "# Leaving only labels 0 and 1 \n", + "idx = np.append(np.where(X_train.targets == 0)[0][:n_samples], \n", + " np.where(X_train.targets == 1)[0][:n_samples])\n", + "\n", + "X_train.data = X_train.data[idx]\n", + "X_train.targets = X_train.targets[idx]\n", + "\n", + "train_loader = torch.utils.data.DataLoader(X_train, batch_size=1, shuffle=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d59eeba4", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "n_samples_show = 6\n", + "\n", + "data_iter = iter(train_loader)\n", + "fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))\n", + "\n", + "while n_samples_show > 0:\n", + " images, targets = data_iter.__next__()\n", + "\n", + " axes[n_samples_show - 1].imshow(images[0].numpy().squeeze(), cmap='gray')\n", + " axes[n_samples_show - 1].set_xticks([])\n", + " axes[n_samples_show - 1].set_yticks([])\n", + " axes[n_samples_show - 1].set_title(\"Labeled: {}\".format(targets.item()))\n", + " \n", + " n_samples_show -= 1" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "3f871357", + "metadata": {}, + "outputs": [], + "source": [ + "n_samples = 50\n", + "\n", + "X_test = datasets.MNIST(root='./data', train=False, download=True,\n", + " transform=transforms.Compose([transforms.ToTensor()]))\n", + "\n", + "idx = np.append(np.where(X_test.targets == 0)[0][:n_samples], \n", + " np.where(X_test.targets == 1)[0][:n_samples])\n", + "\n", + "X_test.data = X_test.data[idx]\n", + "X_test.targets = X_test.targets[idx]\n", + "\n", + "test_loader = torch.utils.data.DataLoader(X_test, batch_size=1, shuffle=True)" + ] + }, + { + "cell_type": "markdown", + "id": "05bc8590", + "metadata": {}, + "source": [ + "## 4. Training" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1019c10c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training [5%]\tLoss: -0.7814\n", + "Training [10%]\tLoss: -0.9142\n", + "Training [15%]\tLoss: -0.9305\n", + "Training [20%]\tLoss: -0.9376\n", + "Training [25%]\tLoss: -0.9483\n", + "Training [30%]\tLoss: -0.9558\n", + "Training [35%]\tLoss: -0.9576\n", + "Training [40%]\tLoss: -0.9570\n", + "Training [45%]\tLoss: -0.9698\n", + "Training [50%]\tLoss: -0.9646\n", + "Training [55%]\tLoss: -0.9806\n", + "Training [60%]\tLoss: -0.9727\n", + "Training [65%]\tLoss: -0.9788\n", + "Training [70%]\tLoss: -0.9855\n", + "Training [75%]\tLoss: -0.9863\n", + "Training [80%]\tLoss: -0.9840\n", + "Training [85%]\tLoss: -0.9869\n", + "Training [90%]\tLoss: -0.9862\n", + "Training [95%]\tLoss: -0.9843\n", + "Training [100%]\tLoss: -0.9885\n" + ] + } + ], + "source": [ + "model = Net()\n", + "optimizer = optim.Adam(model.parameters(), lr=0.001)\n", + "loss_func = nn.NLLLoss()\n", + "\n", + "epochs = 20\n", + "loss_list = []\n", + "\n", + "model.train()\n", + "for epoch in range(epochs):\n", + " total_loss = []\n", + " for batch_idx, (data, target) in enumerate(train_loader):\n", + " optimizer.zero_grad()\n", + " # Forward pass\n", + " output = model(data)\n", + " # Calculating loss\n", + " loss = loss_func(output, target)\n", + " # Backward pass\n", + " loss.backward()\n", + " # Optimize the weights\n", + " optimizer.step()\n", + " \n", + " total_loss.append(loss.item())\n", + " loss_list.append(sum(total_loss)/len(total_loss))\n", + " print('Training [{:.0f}%]\\tLoss: {:.4f}'.format(\n", + " 100. * (epoch + 1) / epochs, loss_list[-1]))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5a49ec19", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Neg Log Likelihood Loss')" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(loss_list)\n", + "plt.title('Hybrid NN Training Convergence')\n", + "plt.xlabel('Training Iterations')\n", + "plt.ylabel('Neg Log Likelihood Loss')" + ] + }, + { + "cell_type": "markdown", + "id": "53cdc592", + "metadata": {}, + "source": [ + "### Testing" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "573de21e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Performance on test data:\n", + "\tLoss: -0.9860\n", + "\tAccuracy: 100.0%\n" + ] + } + ], + "source": [ + "model.eval()\n", + "with torch.no_grad():\n", + " \n", + " correct = 0\n", + " for batch_idx, (data, target) in enumerate(test_loader):\n", + " output = model(data)\n", + " \n", + " pred = output.argmax(dim=1, keepdim=True) \n", + " correct += pred.eq(target.view_as(pred)).sum().item()\n", + " \n", + " loss = loss_func(output, target)\n", + " total_loss.append(loss.item())\n", + " \n", + " print('Performance on test data:\\n\\tLoss: {:.4f}\\n\\tAccuracy: {:.1f}%'.format(\n", + " sum(total_loss) / len(total_loss),\n", + " correct / len(test_loader) * 100)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "374c43e3", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "n_samples_show = 6\n", + "count = 0\n", + "fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))\n", + "\n", + "model.eval()\n", + "with torch.no_grad():\n", + " for batch_idx, (data, target) in enumerate(test_loader):\n", + " if count == n_samples_show:\n", + " break\n", + " output = model(data)\n", + " \n", + " pred = output.argmax(dim=1, keepdim=True) \n", + "\n", + " axes[count].imshow(data[0].numpy().squeeze(), cmap='gray')\n", + "\n", + " axes[count].set_xticks([])\n", + " axes[count].set_yticks([])\n", + " axes[count].set_title('Predicted {}'.format(pred.item()))\n", + " \n", + " count += 1" + ] + }, + { + "cell_type": "markdown", + "id": "dbf083ba", + "metadata": {}, + "source": [ + "# Takeaways\n", + "1. Learnt VQE implementation and how they work\n", + "2. VQEs/VQAs have provable efficiencies gaurantees over classical techniques in many cases\n", + "3. Learnt QAOA implementation\n", + "4. VQAs are similar to classical NN and can be embedded into classical NNs\n", + "5. SOTA hardware work. But do introduce a lot of noise to the system. Need workarounds" + ] + }, + { + "cell_type": "markdown", + "id": "8b81d96f", + "metadata": {}, + "source": [ + "# Questions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea4de6c7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}