--- a +++ b/Code/All Qiskit, PennyLane QML Nov 23/31a Quantum Graph RNN 8of8 kkawchak.ipynb @@ -0,0 +1,1401 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "id": "e-qZmPKaLbJ7" + }, + "outputs": [], + "source": [ + "# This cell is added by sphinx-gallery\n", + "# It can be customized to whatever you like\n", + "%matplotlib inline\n", + "# !pip install pennylane" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZPrrGxMTLbJ7" + }, + "source": [ + "The Quantum Graph Recurrent Neural Network\n", + "==========================================\n", + "\n", + "::: {.meta}\n", + ":property=\\\"og:description\\\": Using a quantum graph recurrent neural\n", + "network to learn quantum dynamics. :property=\\\"og:image\\\":\n", + "<https://pennylane.ai/qml/_images/qgrnn_thumbnail.png>\n", + ":::\n", + "\n", + "*Author: Jack Ceroni --- Posted: 27 July 2020. Last updated: 25 March\n", + "2021.*\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CU3x_5JALbJ8" + }, + "source": [ + "This demonstration investigates quantum graph recurrent neural networks\n", + "(QGRNN), which are the quantum analogue of a classical graph recurrent\n", + "neural network, and a subclass of the more general quantum graph neural\n", + "network ansatz. Both the QGNN and QGRNN were introduced in [this paper\n", + "(2019)](https://arxiv.org/abs/1909.12264).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3M64CbeaLbJ8" + }, + "source": [ + "The Idea\n", + "========\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "H3vGd3-BLbJ8" + }, + "source": [ + "A graph is defined as a set of *nodes* along with a set of **edges**,\n", + "which represent connections between nodes. Information can be encoded\n", + "into graphs by assigning numbers to nodes and edges, which we call\n", + "**weights**. It is usually convenient to think of a graph visually:\n", + "\n", + "{.align-center width=\"70.0%\"}\n", + "\n", + "In recent years, the concept of a [graph neural\n", + "network](https://arxiv.org/abs/1812.08434) (GNN) has been receiving a\n", + "lot of attention from the machine learning community. A GNN seeks to\n", + "learn a representation (a mapping of data into a low-dimensional vector\n", + "space) of a given graph with feature vectors assigned to nodes and\n", + "edges. Each of the vectors in the learned representation preserves not\n", + "only the features, but also the overall topology of the graph, i.e.,\n", + "which nodes are connected by edges. The quantum graph neural network\n", + "attempts to do something similar, but for features that are\n", + "quantum-mechanical; for instance, a collection of quantum states.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "T3MTH5BWLbJ8" + }, + "source": [ + "Consider the class of qubit Hamiltonians that are *quadratic*, meaning\n", + "that the terms of the Hamiltonian represent either interactions between\n", + "two qubits, or the energy of individual qubits. This class of\n", + "Hamiltonians is naturally described by graphs, with second-order terms\n", + "between qubits corresponding to weighted edges between nodes, and\n", + "first-order terms corresponding to node weights.\n", + "\n", + "A well known example of a quadratic Hamiltonian is the transverse-field\n", + "Ising model, which is defined as\n", + "\n", + "$$\\hat{H}_{\\text{Ising}}(\\boldsymbol\\theta) \\ = \\ \\displaystyle\\sum_{(i, j) \\in E}\n", + "\\theta_{ij}^{(1)} Z_{i} Z_{j} \\ + \\ \\displaystyle\\sum_{i} \\theta_{i}^{(2)} Z_{i} \\ + \\\n", + "\\displaystyle\\sum_{i} X_{i},$$\n", + "\n", + "where $\\boldsymbol\\theta \\ = \\ \\{\\theta^{(1)}, \\ \\theta^{(2)}\\}$. In\n", + "this Hamiltonian, the set $E$ that determines which pairs of qubits have\n", + "$ZZ$ interactions can be represented by the set of edges for some graph.\n", + "With the qubits as nodes, this graph is called the *interaction graph*.\n", + "The $\\theta^{(1)}$ parameters correspond to the edge weights and the\n", + "$\\theta^{(2)}$ parameters correspond to weights on the nodes.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "4fIzrPwnLbJ9" + }, + "source": [ + "This result implies that we can think about *quantum circuits* with\n", + "graph-theoretic properties. Recall that the time-evolution operator with\n", + "respect to some Hamiltonian $H$ is defined as:\n", + "\n", + "$$U \\ = \\ e^{-it H}.$$\n", + "\n", + "Thus, we have a clean way of taking quadratic Hamiltonians and turning\n", + "them into unitaries (quantum circuits) that preserve the same\n", + "correspondance to a graph. In the case of the Ising Hamiltonian, we\n", + "have:\n", + "\n", + "$$U_{\\text{Ising}} \\ = \\ e^{-it \\hat{H}_{\\text{Ising}} (\\boldsymbol\\theta)} \\ = \\ \\exp \\Big[ -it\n", + "\\Big( \\displaystyle\\sum_{(i, j) \\in E} \\theta_{ij}^{(1)} Z_{i} Z_{j} \\ + \\\n", + "\\displaystyle\\sum_{i} \\theta_{i}^{(2)} Z_{i} \\ + \\ \\displaystyle\\sum_{i} X_{i} \\Big) \\Big]$$\n", + "\n", + "In general, this kind of unitary is very difficult to implement on a\n", + "quantum computer. However, we can approximate it using the\n", + "[Trotter-Suzuki\n", + "decomposition](https://en.wikipedia.org/wiki/Time-evolving_block_decimation#The_Suzuki-Trotter_expansion):\n", + "\n", + "$$\\exp \\Big[ -it \\Big( \\displaystyle\\sum_{(i, j) \\in E} \\theta_{ij}^{(1)} Z_{i} Z_{j} \\ + \\\n", + "\\displaystyle\\sum_{i} \\theta_{i}^{(2)} Z_{i} \\ + \\ \\displaystyle\\sum_{i} X_{i} \\Big) \\Big]\n", + "\\ \\approx \\ \\displaystyle\\prod_{k \\ = \\ 1}^{t / \\Delta} \\Bigg[ \\displaystyle\\prod_{j \\ = \\\n", + "1}^{Q} e^{-i \\Delta \\hat{H}_{\\text{Ising}}^{j}(\\boldsymbol\\theta)} \\Bigg]$$\n", + "\n", + "where $\\hat{H}_{\\text{Ising}}^{j}(\\boldsymbol\\theta)$ is the $j$-th term\n", + "of the Ising Hamiltonian and $\\Delta$ is some small number.\n", + "\n", + "This circuit is a specific instance of the **Quantum Graph Recurrent\n", + "Neural Network**, which in general is defined as a variational ansatz of\n", + "the form\n", + "\n", + "$$U_{H}(\\boldsymbol\\mu, \\ \\boldsymbol\\gamma) \\ = \\ \\displaystyle\\prod_{i \\ = \\ 1}^{P} \\Bigg[\n", + "\\displaystyle\\prod_{j \\ = \\ 1}^{Q} e^{-i \\gamma_j H^{j}(\\boldsymbol\\mu)} \\Bigg],$$\n", + "\n", + "for some parametrized quadratic Hamiltonian, $H(\\boldsymbol\\mu)$.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uKXgaaF1LbJ9" + }, + "source": [ + "Using the QGRNN\n", + "===============\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GDA7lU2tLbJ9" + }, + "source": [ + "Since the QGRNN ansatz is equivalent to the approximate time evolution\n", + "of some quadratic Hamiltonian, we can use it to learn the dynamics of a\n", + "quantum system.\n", + "\n", + "Continuing with the Ising model example, let\\'s imagine we have some\n", + "system governed by $\\hat{H}_{\\text{Ising}}(\\boldsymbol\\alpha)$ for an\n", + "unknown set of target parameters, $\\boldsymbol\\alpha$ and an unknown\n", + "interaction graph $G$. Let\\'s also suppose we have access to copies of\n", + "some low-energy, non-ground state of the target Hamiltonian,\n", + "$|\\psi_0\\rangle$. In addition, we have access to a collection of\n", + "time-evolved states,\n", + "$\\{ |\\psi(t_1)\\rangle, \\ |\\psi(t_2)\\rangle, \\ ..., \\ |\\psi(t_N)\\rangle \\}$,\n", + "defined by:\n", + "\n", + "$$|\\psi(t_k)\\rangle \\ = \\ e^{-i t_k \\hat{H}_{\\text{Ising}}(\\boldsymbol\\alpha)} |\\psi_0\\rangle.$$\n", + "\n", + "We call the low-energy states and the collection of time-evolved states\n", + "*quantum data*. From here, we randomly pick a number of time-evolved\n", + "states from our collection. For any state that we choose, which is\n", + "evolved to some time $t_k$, we compare it to\n", + "\n", + "$$U_{\\hat{H}_{\\text{Ising}}}(\\boldsymbol\\mu, \\ \\Delta) |\\psi_0\\rangle \\ \\approx \\ e^{-i t_k\n", + "\\hat{H}_{\\text{Ising}}(\\boldsymbol\\mu)} |\\psi_0\\rangle.$$\n", + "\n", + "This is done by feeding one of the copies of $|\\psi_0\\rangle$ into a\n", + "quantum circuit with the QGRNN ansatz, with some guessed set of\n", + "parameters $\\boldsymbol\\mu$ and a guessed interaction graph, $G'$. We\n", + "then use a classical optimizer to maximize the average \\\"similarity\\\"\n", + "between the time-evolved states and the states prepared with the QGRNN.\n", + "\n", + "As the QGRNN states becomes more similar to each time-evolved state for\n", + "each sampled time, it follows that\n", + "$\\boldsymbol\\mu \\ \\rightarrow \\ \\boldsymbol\\alpha$ and we are able to\n", + "learn the unknown parameters of the Hamiltonian.\n", + "\n", + "{.align-center\n", + "width=\"90.0%\"}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hYWy2SBeLbJ9" + }, + "source": [ + "Learning an Ising Model with the QGRNN\n", + "======================================\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HlWNWZZULbJ9" + }, + "source": [ + "We now attempt to use the QGRNN to learn the parameters corresponding to\n", + "an arbitrary transverse-field Ising model Hamiltonian.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GpdeYnFwLbJ-" + }, + "source": [ + "Getting Started\n", + "===============\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-5FbshFpLbJ-" + }, + "source": [ + "We begin by importing the necessary dependencies:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "id": "WoSjhgrvLbJ_" + }, + "outputs": [], + "source": [ + "import pennylane as qml\n", + "from matplotlib import pyplot as plt\n", + "from pennylane import numpy as np\n", + "import scipy\n", + "import networkx as nx\n", + "import copy" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SgJGdX-wLbJ_" + }, + "source": [ + "We also define some fixed values that are used throughout the\n", + "simulation.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "id": "FCZr2sEhLbJ_" + }, + "outputs": [], + "source": [ + "qubit_number = 4\n", + "qubits = range(qubit_number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LLRw3rbhLbJ_" + }, + "source": [ + "In this simulation, we don\\'t have quantum data readily available to\n", + "pass into the QGRNN, so we have to generate it ourselves. To do this, we\n", + "must have knowledge of the target interaction graph and the target\n", + "Hamiltonian.\n", + "\n", + "Let us use the following cyclic graph as the target interaction graph of\n", + "the Ising Hamiltonian:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 534 + }, + "id": "BBidusUTLbJ_", + "outputId": "cd3690af-48c6-4b0d-96bf-1daeb63a530c" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Edges: [(0, 1), (0, 3), (1, 2), (2, 3)]\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "ising_graph = nx.cycle_graph(qubit_number)\n", + "\n", + "print(f\"Edges: {ising_graph.edges}\")\n", + "nx.draw(ising_graph)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "U1Dum11GLbJ_" + }, + "source": [ + "We can then initialize the \"unknown\" target parameters that describe the\n", + "target Hamiltonian,\n", + "$\\boldsymbol\\alpha \\ = \\ \\{\\alpha^{(1)}, \\ \\alpha^{(2)}\\}$. Recall from\n", + "the introduction that we have defined our parametrized Ising Hamiltonian\n", + "to be of the form:\n", + "\n", + "$$\\hat{H}_{\\text{Ising}}(\\boldsymbol\\theta) \\ = \\ \\displaystyle\\sum_{(i, j) \\in E}\n", + "\\theta_{ij}^{(1)} Z_{i} Z_{j} \\ + \\ \\displaystyle\\sum_{i} \\theta_{i}^{(2)} Z_{i} \\ + \\\n", + "\\displaystyle\\sum_{i} X_{i},$$\n", + "\n", + "where $E$ is the set of edges in the interaction graph, and $X_i$ and\n", + "$Z_i$ are the Pauli-X and Pauli-Z on the $i$-th qubit.\n", + "\n", + "For this tutorial, we choose the target parameters by sampling from a\n", + "uniform probability distribution ranging from $-2$ to $2$, with\n", + "two-decimal precision.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "id": "dguKYJmcLbJ_" + }, + "outputs": [], + "source": [ + "target_weights = [0.56, 1.24, 1.67, -0.79]\n", + "target_bias = [-1.44, -1.43, 1.18, -0.93]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AiyO6svHLbJ_" + }, + "source": [ + "In theory, these parameters can be any value we want, provided they are\n", + "reasonably small enough that the QGRNN can reach them in a tractable\n", + "number of optimization steps. In `matrix_params`, the first list\n", + "represents the $ZZ$ interaction parameters and the second list\n", + "represents the single-qubit $Z$ parameters.\n", + "\n", + "Finally, we use this information to generate the matrix form of the\n", + "Ising model Hamiltonian in the computational basis:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 437 + }, + "id": "xDSq-w2_LbJ_", + "outputId": "b44d353e-345e-4409-c18d-52763b0aa3b4" + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "<Figure size 480x480 with 1 Axes>" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaMAAAGkCAYAAACckEpMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAdLElEQVR4nO3df2xV9f3H8deltZeuaa+2jpY7W+kMEQXEH4VG8bvB10bSIEoWdRrEBjedWxFqDYNuK/7Eim6u/iBFzHfC9hXFfCPoSNSwiqARCm2tk2zjR+ywSkpnor1SxoW05/vHd959K4W2cD5991yej+TE3HMP7/PK8d6+cu49PQ15nucJAABDI6wDAABAGQEAzFFGAABzlBEAwBxlBAAwRxkBAMxRRgAAc5QRAMAcZQQAMEcZAQDMBbqMVqxYoTFjxmjkyJEqLi7Wjh07rCP1q6amRpMnT1ZmZqZGjRql2bNna/fu3daxBu2xxx5TKBRSRUWFdZQB+eyzz3TbbbcpJydH6enpmjhxohobG61j9au7u1vV1dUqLCxUenq6LrjgAj388MMabnfx2rp1q2bNmqVoNKpQKKQNGzb0et7zPC1dulSjR49Wenq6SkpKtHfvXpuw33Cy7MeOHdPixYs1ceJEZWRkKBqN6vbbb9eBAwfsAv9Lf8f8/7v77rsVCoVUW1s7ZPkGK7BltG7dOlVWVur+++9Xc3OzJk2apBkzZqijo8M62klt2bJF5eXl2r59uzZt2qRjx47p2muvVVdXl3W0Adu5c6eee+45XXLJJdZRBuSLL77Q1KlTddZZZ+mNN97QX/7yF/3mN7/ROeecYx2tX8uXL1ddXZ2effZZ/fWvf9Xy5cv1+OOP65lnnrGO1ktXV5cmTZqkFStW9Pn8448/rqefflorV65UQ0ODMjIyNGPGDB05cmSIkx7vZNkPHz6s5uZmVVdXq7m5Wa+++qp2796t66+/3iBpb/0d86+tX79e27dvVzQaHaJkp8gLqClTpnjl5eWJx93d3V40GvVqamoMUw1eR0eHJ8nbsmWLdZQB+eqrr7yxY8d6mzZt8r7//e97CxcutI7Ur8WLF3tXX321dYxTMnPmTO+OO+7ote4HP/iBN2fOHKNE/ZPkrV+/PvG4p6fHy8vL85544onEui+//NILh8PeSy+9ZJDwxL6ZvS87duzwJHn79+8fmlADcKLcn376qfed73zH27Vrl3f++ed7v/3tb4c820AF8szo6NGjampqUklJSWLdiBEjVFJSom3bthkmG7zOzk5JUnZ2tnGSgSkvL9fMmTN7Hfvh7vXXX1dRUZFuuukmjRo1Spdddpmef/5561gDctVVV6m+vl579uyRJH344Yd67733VFpaapxs4FpbW9Xe3t7rNROJRFRcXBy496v0f+/ZUCiks88+2zrKSfX09Gju3LlatGiRxo8fbx2nX6nWAU7F559/ru7ubuXm5vZan5ubq7/97W9GqQavp6dHFRUVmjp1qiZMmGAdp18vv/yympubtXPnTusog/Lxxx+rrq5OlZWV+sUvfqGdO3dqwYIFSktLU1lZmXW8k1qyZIlisZjGjRunlJQUdXd3a9myZZozZ451tAFrb2+XpD7fr18/FxRHjhzR4sWLdeuttyorK8s6zkktX75cqampWrBggXWUAQlkGSWL8vJy7dq1S++99551lH61tbVp4cKF2rRpk0aOHGkdZ1B6enpUVFSkRx99VJJ02WWXadeuXVq5cuWwL6NXXnlFL774otauXavx48erpaVFFRUVikajwz57sjl27JhuvvlmeZ6nuro66zgn1dTUpKeeekrNzc0KhULWcQYkkB/TnXvuuUpJSdHBgwd7rT948KDy8vKMUg3O/PnztXHjRm3evFnnnXeedZx+NTU1qaOjQ5dffrlSU1OVmpqqLVu26Omnn1Zqaqq6u7utI57Q6NGjdfHFF/dad9FFF+mTTz4xSjRwixYt0pIlS3TLLbdo4sSJmjt3ru69917V1NRYRxuwr9+TQX6/fl1E+/fv16ZNm4b9WdG7776rjo4OFRQUJN6v+/fv13333acxY8ZYx+tTIMsoLS1NV1xxherr6xPrenp6VF9fryuvvNIwWf88z9P8+fO1fv16vf322yosLLSONCDXXHONPvroI7W0tCSWoqIizZkzRy0tLUpJSbGOeEJTp0497vL5PXv26PzzzzdKNHCHDx/WiBG936YpKSnq6ekxSjR4hYWFysvL6/V+jcViamhoGPbvV+nfRbR371796U9/Uk5OjnWkfs2dO1d//vOfe71fo9GoFi1apLfeess6Xp8C+zFdZWWlysrKVFRUpClTpqi2tlZdXV2aN2+edbSTKi8v19q1a/Xaa68pMzMz8Zl5JBJRenq6cboTy8zM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\n" + }, + "metadata": {} + } + ], + "source": [ + "def create_hamiltonian_matrix(n_qubits, graph, weights, bias):\n", + "\n", + " full_matrix = np.zeros((2 ** n_qubits, 2 ** n_qubits))\n", + "\n", + " # Creates the interaction component of the Hamiltonian\n", + " for i, edge in enumerate(graph.edges):\n", + " interaction_term = 1\n", + " for qubit in range(0, n_qubits):\n", + " if qubit in edge:\n", + " interaction_term = np.kron(interaction_term, qml.matrix(qml.PauliZ)(0))\n", + " else:\n", + " interaction_term = np.kron(interaction_term, np.identity(2))\n", + " full_matrix += weights[i] * interaction_term\n", + "\n", + " # Creates the bias components of the matrix\n", + " for i in range(0, n_qubits):\n", + " z_term = x_term = 1\n", + " for j in range(0, n_qubits):\n", + " if j == i:\n", + " z_term = np.kron(z_term, qml.matrix(qml.PauliZ)(0))\n", + " x_term = np.kron(x_term, qml.matrix(qml.PauliX)(0))\n", + " else:\n", + " z_term = np.kron(z_term, np.identity(2))\n", + " x_term = np.kron(x_term, np.identity(2))\n", + " full_matrix += bias[i] * z_term + x_term\n", + "\n", + " return full_matrix\n", + "\n", + "\n", + "# Prints a visual representation of the Hamiltonian matrix\n", + "ham_matrix = create_hamiltonian_matrix(qubit_number, ising_graph, target_weights, target_bias)\n", + "plt.matshow(ham_matrix, cmap=\"hot\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EZSqkuz8LbJ_" + }, + "source": [ + "Preparing Quantum Data\n", + "======================\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PmSFvIn5LbJ_" + }, + "source": [ + "The collection of quantum data needed to run the QGRNN has two\n", + "components: (i) copies of a low-energy state, and (ii) a collection of\n", + "time-evolved states, each of which are simply the low-energy state\n", + "evolved to different times. The following is a low-energy state of the\n", + "target Hamiltonian:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "id": "TvhFkhYOLbJ_" + }, + "outputs": [], + "source": [ + "low_energy_state = [\n", + " (-0.054661080280306085 + 0.016713907320174026j),\n", + " (0.12290003656489545 - 0.03758500591109822j),\n", + " (0.3649337966440005 - 0.11158863596657455j),\n", + " (-0.8205175732627094 + 0.25093231967092877j),\n", + " (0.010369790825776609 - 0.0031706387262686003j),\n", + " (-0.02331544978544721 + 0.007129899300113728j),\n", + " (-0.06923183949694546 + 0.0211684344103713j),\n", + " (0.15566094863283836 - 0.04760201916285508j),\n", + " (0.014520590919500158 - 0.004441887836078486j),\n", + " (-0.032648113364535575 + 0.009988590222879195j),\n", + " (-0.09694382811137187 + 0.02965579457620536j),\n", + " (0.21796861485652747 - 0.06668776658411019j),\n", + " (-0.0027547112135013247 + 0.0008426289322652901j),\n", + " (0.006193695872468649 - 0.0018948418969390599j),\n", + " (0.018391279795405405 - 0.005625722994009138j),\n", + " (-0.041350974715649635 + 0.012650711602265649j),\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nZ5F5vM7LbJ_" + }, + "source": [ + "This state can be obtained by using a decoupled version of the\n", + "`Variational Quantum Eigensolver </demos/tutorial_vqe>`{.interpreted-text\n", + "role=\"doc\"} algorithm (VQE). Essentially, we choose a VQE ansatz such\n", + "that the circuit cannot learn the exact ground state, but it can get\n", + "fairly close. Another way to arrive at the same result is to perform VQE\n", + "with a reasonable ansatz, but to terminate the algorithm before it\n", + "converges to the ground state. If we used the exact ground state\n", + "$|\\psi_0\\rangle$, the time-dependence would be trivial and the data\n", + "would not provide enough information about the Hamiltonian parameters.\n", + "\n", + "We can verify that this is a low-energy state by numerically finding the\n", + "lowest eigenvalue of the Hamiltonian and comparing it to the energy\n", + "expectation of this low-energy state:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "ZBpXVqTtLbJ_", + "outputId": "24e5e819-1d3e-4ae2-a4fb-05a400e4d001" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Energy Expectation: -7.244508985189116\n", + "Ground State Energy: -7.330689661291244\n" + ] + } + ], + "source": [ + "res = np.vdot(low_energy_state, (ham_matrix @ low_energy_state))\n", + "energy_exp = np.real_if_close(res)\n", + "print(f\"Energy Expectation: {energy_exp}\")\n", + "\n", + "\n", + "ground_state_energy = np.real_if_close(min(np.linalg.eig(ham_matrix)[0]))\n", + "print(f\"Ground State Energy: {ground_state_energy}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dQRr5pFSLbKA" + }, + "source": [ + "We have in fact found a low-energy, non-ground state, as the energy\n", + "expectation is slightly greater than the energy of the true ground\n", + "state. This, however, is only half of the information we need. We also\n", + "require a collection of time-evolved, low-energy states. Evolving the\n", + "low-energy state forward in time is fairly straightforward: all we have\n", + "to do is multiply the initial state by a time-evolution unitary. This\n", + "operation can be defined as a custom gate in PennyLane:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "id": "zxIkTaPiLbKA" + }, + "outputs": [], + "source": [ + "def state_evolve(hamiltonian, qubits, time):\n", + "\n", + " U = scipy.linalg.expm(-1j * hamiltonian * time)\n", + " qml.QubitUnitary(U, wires=qubits)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "auVMu4Q4LbKA" + }, + "source": [ + "We don\\'t actually generate time-evolved quantum data quite yet, but we\n", + "now have all the pieces required for its preparation.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XUMWybNQLbKA" + }, + "source": [ + "Learning the Hamiltonian\n", + "========================\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TrYpMK0NLbKA" + }, + "source": [ + "With the quantum data defined, we are able to construct the QGRNN and\n", + "learn the target Hamiltonian. Each of the exponentiated Hamiltonians in\n", + "the QGRNN ansatz, $\\hat{H}^{j}_{\\text{Ising}}(\\boldsymbol\\mu)$, are the\n", + "$ZZ$, $Z$, and $X$ terms from the Ising Hamiltonian. This gives:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "id": "RewvANn3LbKA" + }, + "outputs": [], + "source": [ + "def qgrnn_layer(weights, bias, qubits, graph, trotter_step):\n", + "\n", + " # Applies a layer of RZZ gates (based on a graph)\n", + " for i, edge in enumerate(graph.edges):\n", + " qml.MultiRZ(2 * weights[i] * trotter_step, wires=(edge[0], edge[1]))\n", + "\n", + " # Applies a layer of RZ gates\n", + " for i, qubit in enumerate(qubits):\n", + " qml.RZ(2 * bias[i] * trotter_step, wires=qubit)\n", + "\n", + " # Applies a layer of RX gates\n", + " for qubit in qubits:\n", + " qml.RX(2 * trotter_step, wires=qubit)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZcYEXhauLbKA" + }, + "source": [ + "As was mentioned in the first section, the QGRNN has two registers. In\n", + "one register, some piece of quantum data $|\\psi(t)\\rangle$ is prepared\n", + "and in the other we have\n", + "$U_{H}(\\boldsymbol\\mu, \\ \\Delta) |\\psi_0\\rangle$. We need a way to\n", + "measure the similarity between these states. This can be done by using\n", + "the fidelity, which is simply the modulus squared of the inner product\n", + "between the states,\n", + "$| \\langle \\psi(t) | U_{H}(\\Delta, \\ \\boldsymbol\\mu) |\\psi_0\\rangle |^2$.\n", + "To calculate this value, we use a [SWAP\n", + "test](https://en.wikipedia.org/wiki/Swap_test) between the registers:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "id": "-5RqUqBKLbKA" + }, + "outputs": [], + "source": [ + "def swap_test(control, register1, register2):\n", + "\n", + " qml.Hadamard(wires=control)\n", + " for reg1_qubit, reg2_qubit in zip(register1, register2):\n", + " qml.CSWAP(wires=(control, reg1_qubit, reg2_qubit))\n", + " qml.Hadamard(wires=control)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "To4GLL8VLbKA" + }, + "source": [ + "After performing this procedure, the value returned from a measurement\n", + "of the circuit is $\\langle Z \\rangle$, with respect to the `control`\n", + "qubit. The probability of measuring the $|0\\rangle$ state in this\n", + "control qubit is related to both the fidelity between registers and\n", + "$\\langle Z \\rangle$. Thus, with a bit of algebra, we find that\n", + "$\\langle Z \\rangle$ is equal to the fidelity.\n", + "\n", + "Before creating the full QGRNN and the cost function, we define a few\n", + "more fixed values. Among these is a \\\"guessed\\\" interaction graph, which\n", + "we set to be a [complete\n", + "graph](https://en.wikipedia.org/wiki/Complete_graph). This choice is\n", + "motivated by the fact that any target interaction graph will be a\n", + "subgraph of this initial guess. Part of the idea behind the QGRNN is\n", + "that we don't know the interaction graph, and it has to be learned. In\n", + "this case, the graph is learned *automatically* as the target parameters\n", + "are optimized. The $\\boldsymbol\\mu$ parameters that correspond to edges\n", + "that don\\'t exist in the target graph will simply approach $0$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 534 + }, + "id": "C5JNAOMSLbKA", + "outputId": "208b5841-e93b-42b0-a68c-308299c6a182" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Edges: [(4, 5), (4, 6), (4, 7), (5, 6), (5, 7), (6, 7)]\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAAHzCAYAAACe1o1DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACBFklEQVR4nO3dd1RU58I18D0DUiVYsEtHQGpU7L33Ap6JGls0atQYjYUUU0y5McUajYma2BULKGjsotiwAVEERJpS7AVFBKkz3x/3jd81ExOVGZ4p+7eWK2td4znbXGU2T5WpVCoViIiIiIhekVx0ACIiIiLSbyyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUISyURERERFQhLJREREREVCEslERERERUIaaiAxAREdGzCorLkHm/ACVlSpiZyuFU0xrW5vzIJt3FP51EREQ6IO12PjadzUZUyh1k5xZC9T8/JwPgUMMKnT1qY3hLBzSqYyMqJtHfkqlUKtW//2tERESkDTm5hZgdnoAT6fdgIpehXPn8j+U/f769mx3mBvrCvoZVJSYlej4WSiIiIkG2xGRjzq4klClV/1gk/8pELoOpXIYvB3hjaHMHLSYkejEslERERAL8FJWG+QdTK/ycWT3cMaVzIw0kInp13OVNRERUybbEZGukTALA/IOp2BqTrZFnEb0qFkoiIqJKlJNbiDm7kjT6zM93JSEnt1CjzyR6GSyURERElWh2eALKXmK95IsoU6owOzxBo88kehkslERERJUk7XY+TqTfe6kNOC+iXKnCifR7SL+Tr9HnEr0oFkoiIqJKsulsNkzkMq0820Quw8YzXEtJYrBQEhERVZKolDsaH538U7lShajUO1p5NtG/YaEkIiKq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\n" + }, + "metadata": {} + } + ], + "source": [ + "# Defines some fixed values\n", + "\n", + "reg1 = tuple(range(qubit_number)) # First qubit register\n", + "reg2 = tuple(range(qubit_number, 2 * qubit_number)) # Second qubit register\n", + "\n", + "control = 2 * qubit_number # Index of control qubit\n", + "trotter_step = 0.01 # Trotter step size\n", + "\n", + "# Defines the interaction graph for the new qubit system\n", + "\n", + "new_ising_graph = nx.complete_graph(reg2)\n", + "\n", + "print(f\"Edges: {new_ising_graph.edges}\")\n", + "nx.draw(new_ising_graph)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "4fc6XyLdLbKA" + }, + "source": [ + "With this done, we implement the QGRNN circuit for some given time\n", + "value:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "id": "iu4hcd2oLbKA" + }, + "outputs": [], + "source": [ + "def qgrnn(weights, bias, time=None):\n", + "\n", + " # Prepares the low energy state in the two registers\n", + " qml.QubitStateVector(np.kron(low_energy_state, low_energy_state), wires=reg1 + reg2)\n", + "\n", + " # Evolves the first qubit register with the time-evolution circuit to\n", + " # prepare a piece of quantum data\n", + " state_evolve(ham_matrix, reg1, time)\n", + "\n", + " # Applies the QGRNN layers to the second qubit register\n", + " depth = time / trotter_step # P = t/Delta\n", + " for _ in range(0, int(depth)):\n", + " qgrnn_layer(weights, bias, reg2, new_ising_graph, trotter_step)\n", + "\n", + " # Applies the SWAP test between the registers\n", + " swap_test(control, reg1, reg2)\n", + "\n", + " # Returns the results of the SWAP test\n", + " return qml.expval(qml.PauliZ(control))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zUGsNfnsLbKA" + }, + "source": [ + "We have the full QGRNN circuit, but we still need to define a cost\n", + "function. We know that\n", + "$| \\langle \\psi(t) | U_{H}(\\boldsymbol\\mu, \\ \\Delta) |\\psi_0\\rangle |^2$\n", + "approaches $1$ as the states become more similar and approaches $0$ as\n", + "the states become orthogonal. Thus, we choose to minimize the quantity\n", + "$-| \\langle \\psi(t) | U_{H}(\\boldsymbol\\mu, \\ \\Delta) |\\psi_0\\rangle |^2$.\n", + "Since we are interested in calculating this value for many different\n", + "pieces of quantum data, the final cost function is the average negative\n", + "fidelity\\* between registers:\n", + "\n", + "$$\\mathcal{L}(\\boldsymbol\\mu, \\ \\Delta) \\ = \\ - \\frac{1}{N} \\displaystyle\\sum_{i \\ = \\ 1}^{N} |\n", + "\\langle \\psi(t_i) | \\ U_{H}(\\boldsymbol\\mu, \\ \\Delta) \\ |\\psi_0\\rangle |^2,$$\n", + "\n", + "where we use $N$ pieces of quantum data.\n", + "\n", + "Before creating the cost function, we must define a few more fixed\n", + "variables:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "id": "R7jK3kMqLbKB" + }, + "outputs": [], + "source": [ + "N = 15 # The number of pieces of quantum data that are used for each step\n", + "max_time = 0.2 # The maximum value of time that can be used for quantum data" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "X_e9a1jVLbKB" + }, + "source": [ + "We then define the negative fidelity cost function:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "id": "qizc8MsqLbKB" + }, + "outputs": [], + "source": [ + "rng = np.random.default_rng(seed=42)\n", + "\n", + "def cost_function(weight_params, bias_params):\n", + "\n", + " # Randomly samples times at which the QGRNN runs\n", + " times_sampled = rng.random(size=N) * max_time\n", + "\n", + " # Cycles through each of the sampled times and calculates the cost\n", + " total_cost = 0\n", + " for dt in times_sampled:\n", + " result = qgrnn_qnode(weight_params, bias_params, time=dt)\n", + " total_cost += -1 * result\n", + "\n", + " return total_cost / N" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "m5WwkvDHLbKB" + }, + "source": [ + "Next we set up for optimization.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "id": "3bzbEsNJLbKB" + }, + "outputs": [], + "source": [ + "# Defines the new device\n", + "qgrnn_dev = qml.device(\"default.qubit\", wires=2 * qubit_number + 1)\n", + "\n", + "# Defines the new QNode\n", + "qgrnn_qnode = qml.QNode(qgrnn, qgrnn_dev, interface=\"autograd\")\n", + "\n", + "steps = 300\n", + "\n", + "optimizer = qml.AdamOptimizer(stepsize=0.3)\n", + "\n", + "weights = rng.random(size=len(new_ising_graph.edges), requires_grad=True) - 0.5\n", + "bias = rng.random(size=qubit_number, requires_grad=True) - 0.5\n", + "\n", + "initial_weights = copy.copy(weights)\n", + "initial_bias = copy.copy(bias)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Hik8L3erLbKB" + }, + "source": [ + "All that remains is executing the optimization loop.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "gPvXgB7MLbKB", + "outputId": "5a6cae32-ba71-4c61-a7bd-7f8b4eae994e" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Cost at Step 0: -0.9200037151976073\n", + "Weights at Step 0: [-0.02604279 0.23887717 0.65859707 0.49736665 -0.10582356 0.17562328]\n", + "Bias at Step 0: [-0.03885835 -0.01393335 -0.07188937 0.25038476]\n", + "---------------------------------------------\n", + "Cost at Step 5: -0.9876137799242335\n", + "Weights at Step 5: [-0.81760068 1.07671595 1.07494562 1.60282598 0.31500454 -0.28622538]\n", + "Bias at Step 5: [-0.67907189 -1.06371582 1.08870454 0.45516335]\n", + "---------------------------------------------\n", + "Cost at Step 10: -0.9939998594645669\n", + "Weights at Step 10: [-0.43814796 0.80264963 0.57854353 1.85158146 -0.18336282 0.11078154]\n", + "Bias at Step 10: [-0.12267109 -1.14443619 1.52017786 -0.1666818 ]\n", + "---------------------------------------------\n", + "Cost at Step 15: -0.9962208086076164\n", + "Weights at Step 15: [-0.0458325 0.53694835 0.83652816 1.67543427 -0.04470958 -0.18638833]\n", + "Bias at Step 15: [ 0.15793529 -0.84003603 1.48310022 0.06806457]\n", + "---------------------------------------------\n", + "Cost at Step 20: -0.9957637238497249\n", + "Weights at Step 20: [-0.07603609 0.63861577 1.18121102 1.51006722 0.03769834 -0.36072003]\n", + "Bias at Step 20: [-0.14566065 -0.67592464 1.28609151 0.19641753]\n", + "---------------------------------------------\n", + "Cost at Step 25: -0.9985000854660584\n", + "Weights at Step 25: [-0.18753806 0.69333152 1.0960544 1.49819549 -0.28526971 -0.04521121]\n", + "Bias at Step 25: [-0.41378647 -0.79473119 1.05817856 -0.20199664]\n", + "---------------------------------------------\n", + "Cost at Step 30: -0.9990738993626694\n", + "Weights at Step 30: [-0.15888399 0.56544228 1.21966075 1.65606117 -0.18698724 -0.15012618]\n", + "Bias at Step 30: [-0.38261198 -1.08390677 0.99514117 -0.19462826]\n", + "---------------------------------------------\n", + "Cost at Step 35: -0.9987693982588911\n", + "Weights at Step 35: [ 0.0041808 0.40612704 1.31527388 1.73532362 -0.09044603 -0.30497354]\n", + "Bias at Step 35: [-0.26884218 -1.17947084 1.02164299 -0.15211727]\n", + "---------------------------------------------\n", + "Cost at Step 40: -0.999251583470993\n", + "Weights at Step 40: [ 0.08561847 0.44006962 1.26170355 1.71272203 -0.23442009 -0.25474802]\n", + "Bias at Step 40: [-0.39159587 -1.08813802 1.07704208 -0.33745963]\n", + "---------------------------------------------\n", + "Cost at Step 45: -0.9994248986650188\n", + "Weights at Step 45: [ 0.07116764 0.55172578 1.33103119 1.70750705 -0.21790431 -0.35000642]\n", + "Bias at Step 45: [-0.62786818 -1.04579562 1.1153243 -0.37204428]\n", + "---------------------------------------------\n", + "Cost at Step 50: -0.9997718604833874\n", + "Weights at Step 50: [ 0.1900666 0.42787454 1.31858733 1.69897373 -0.1718078 -0.43140288]\n", + "Bias at Step 50: [-0.60423116 -1.07738709 1.04408277 -0.39652431]\n", + "---------------------------------------------\n", + "Cost at Step 55: -0.999669403963809\n", + "Weights at Step 55: [ 0.2305871 0.35165699 1.2576529 1.73740749 -0.17028966 -0.442958 ]\n", + "Bias at Step 55: [-0.63471799 -1.18549027 0.98129106 -0.48831366]\n", + "---------------------------------------------\n", + "Cost at Step 60: -0.9997005090875465\n", + "Weights at Step 60: [ 0.20331843 0.38880673 1.27280954 1.76327852 -0.13054908 -0.50743354]\n", + "Bias at Step 60: [-0.7910831 -1.24264842 0.96725342 -0.52888411]\n", + "---------------------------------------------\n", + "Cost at Step 65: -0.9998390095668767\n", + "Weights at Step 65: [ 0.30186983 0.32982277 1.24436455 1.7115331 -0.13431685 -0.54688054]\n", + "Bias at Step 65: [-0.82692488 -1.17879019 0.94225638 -0.58835058]\n", + "---------------------------------------------\n", + "Cost at Step 70: -0.9998463728006276\n", + "Weights at Step 70: [ 0.33581306 0.31530544 1.2493993 1.73269036 -0.10367132 -0.60587018]\n", + "Bias at Step 70: [-0.89656392 -1.20165109 0.97059225 -0.627371 ]\n", + "---------------------------------------------\n", + "Cost at Step 75: -0.9998905983157391\n", + "Weights at Step 75: [ 0.35154619 0.29213052 1.23876733 1.761073 -0.09648422 -0.62632222]\n", + "Bias at Step 75: [-0.96644772 -1.25589463 0.97507609 -0.69733436]\n", + "---------------------------------------------\n", + "Cost at Step 80: -0.9999350358165905\n", + "Weights at Step 80: [ 0.3975706 0.24247701 1.25163179 1.74455824 -0.07453551 -0.66367459]\n", + "Bias at Step 80: [-1.00917765 -1.2587604 0.94837798 -0.7332096 ]\n", + "---------------------------------------------\n", + "Cost at Step 85: -0.9999482967482567\n", + "Weights at Step 85: [ 0.41868748 0.22580496 1.2624984 1.74189597 -0.06696401 -0.6861869 ]\n", + "Bias at Step 85: [-1.07178528 -1.26425295 0.95234717 -0.77745452]\n", + "---------------------------------------------\n", + "Cost at Step 90: -0.9999499223797544\n", + "Weights at Step 90: [ 0.44145933 0.20337243 1.26625822 1.75621405 -0.05869247 -0.70630086]\n", + "Bias at Step 90: [-1.11358328 -1.28462283 0.97855525 -0.82000899]\n", + "---------------------------------------------\n", + "Cost at Step 95: -0.9999530455182971\n", + "Weights at Step 95: [ 0.47019264 0.16924721 1.27286026 1.75455497 -0.04395194 -0.73007002]\n", + "Bias at Step 95: [-1.14431545 -1.29386251 0.98742393 -0.84928015]\n", + "---------------------------------------------\n", + "Cost at Step 100: -0.9999570613439416\n", + "Weights at Step 100: [ 0.47977166 0.1527456 1.2786519 1.74980484 -0.0376303 -0.74275152]\n", + "Bias at Step 100: [-1.19436854 -1.30286407 0.99081851 -0.88267418]\n", + "---------------------------------------------\n", + "Cost at Step 105: -0.9999659889339071\n", + "Weights at Step 105: [ 0.49797231 0.12660509 1.28150049 1.74863372 -0.02753168 -0.75842501]\n", + "Bias at Step 105: [-1.22175318 -1.31296261 1.00050975 -0.90640742]\n", + "---------------------------------------------\n", + "Cost at Step 110: -0.9999614306765608\n", + "Weights at Step 110: [ 0.51039217 0.108355 1.28185308 1.74980865 -0.01942516 -0.7717866 ]\n", + "Bias at Step 110: [-1.24962622 -1.32278602 1.01768796 -0.92703101]\n", + "---------------------------------------------\n", + "Cost at Step 115: -0.9999645085259455\n", + "Weights at Step 115: [ 0.51904442 0.0937446 1.28176882 1.74326512 -0.01427955 -0.78148372]\n", + "Bias at Step 115: [-1.28134793 -1.32636187 1.02802729 -0.94518626]\n", + "---------------------------------------------\n", + "Cost at Step 120: -0.9999658547475359\n", + "Weights at Step 120: [ 0.52937688 0.07449026 1.28280811 1.73964609 -0.00689253 -0.791763 ]\n", + "Bias at Step 120: [-1.30153182 -1.33478832 1.03688605 -0.95706145]\n", + "---------------------------------------------\n", + "Cost at Step 125: -0.9999793528715321\n", + "Weights at Step 125: [ 0.53401302 0.06310458 1.28238925 1.73934318 -0.0048274 -0.79646285]\n", + "Bias at Step 125: [-1.32357896 -1.34453438 1.05006482 -0.970321 ]\n", + "---------------------------------------------\n", + "Cost at Step 130: -0.9999731145828665\n", + "Weights at Step 130: [ 5.41717330e-01 5.04455290e-02 1.28195070e+00 1.73376924e+00\n", + " -7.59893845e-04 -8.02921942e-01]\n", + "Bias at Step 130: [-1.33898192 -1.34763312 1.06002129 -0.97591873]\n", + "---------------------------------------------\n", + "Cost at Step 135: -0.9999645116649636\n", + "Weights at Step 135: [ 5.45131959e-01 4.15869725e-02 1.28088552e+00 1.72997634e+00\n", + " 1.62744688e-03 -8.06309183e-01]\n", + "Bias at Step 135: [-1.35449293 -1.3536153 1.06941714 -0.98066205]\n", + "---------------------------------------------\n", + "Cost at Step 140: -0.9999829047160226\n", + "Weights at Step 140: [ 0.54851223 0.03324994 1.2806549 1.72782976 0.00237586 -0.8076513 ]\n", + "Bias at Step 140: [-1.36559068 -1.3606077 1.07837369 -0.98460471]\n", + "---------------------------------------------\n", + "Cost at Step 145: -0.9999743662393943\n", + "Weights at Step 145: [ 0.55235459 0.0260732 1.2815596 1.72423595 0.00309675 -0.80902489]\n", + "Bias at Step 145: [-1.37442418 -1.36484585 1.08631493 -0.98585999]\n", + "---------------------------------------------\n", + "Cost at Step 150: -0.9999606848437312\n", + "Weights at Step 150: [ 0.55462097 0.02104848 1.28302845 1.72185621 0.00271517 -0.80898188]\n", + "Bias at Step 150: [-1.38263744 -1.36993282 1.09403396 -0.98705602]\n", + "---------------------------------------------\n", + "Cost at Step 155: -0.9999747378172825\n", + "Weights at Step 155: [ 0.55765123 0.01560964 1.28466486 1.720109 0.00243074 -0.80895633]\n", + "Bias at Step 155: [-1.38780256 -1.37503766 1.10026774 -0.98736767]\n", + "---------------------------------------------\n", + "Cost at Step 160: -0.9999700507088615\n", + "Weights at Step 160: [ 5.59715925e-01 1.23133184e-02 1.28640194e+00 1.71845447e+00\n", + " 1.15008368e-03 -8.08173611e-01]\n", + "Bias at Step 160: [-1.39332194 -1.37895061 1.10516714 -0.98828012]\n", + "---------------------------------------------\n", + "Cost at Step 165: -0.9999651137969857\n", + "Weights at Step 165: [ 5.62028643e-01 9.10515307e-03 1.28677042e+00 1.71699151e+00\n", + " 9.99079774e-04 -8.08321718e-01]\n", + "Bias at Step 165: [-1.39726695 -1.38258107 1.1092578 -0.98797408]\n", + "---------------------------------------------\n", + "Cost at Step 170: -0.9999661855526563\n", + "Weights at Step 170: [ 5.62722835e-01 7.81477874e-03 1.28453351e+00 1.71510396e+00\n", + " 1.69146530e-03 -8.08719332e-01]\n", + "Bias at Step 170: [-1.40203213 -1.38561494 1.11288641 -0.98677472]\n", + "---------------------------------------------\n", + "Cost at Step 175: -0.99996407898796\n", + "Weights at Step 175: [ 0.56337362 0.00643977 1.28023851 1.71193883 0.00268434 -0.80881327]\n", + "Bias at Step 175: [-1.40567588 -1.38739124 1.11554171 -0.98479634]\n", + "---------------------------------------------\n", + "Cost at Step 180: -0.9999705772704096\n", + "Weights at Step 180: [ 0.56440049 0.00498719 1.27961208 1.71017108 0.00200665 -0.80777554]\n", + "Bias at Step 180: [-1.40805298 -1.38959252 1.11850884 -0.98414075]\n", + "---------------------------------------------\n", + "Cost at Step 185: -0.9999647185725978\n", + "Weights at Step 185: [ 5.65697073e-01 3.41802737e-03 1.28381210e+00 1.71001790e+00\n", + " 1.51458946e-03 -8.07541145e-01]\n", + "Bias at Step 185: [-1.40919496 -1.39235911 1.12136856 -0.98324964]\n", + "---------------------------------------------\n", + "Cost at Step 190: -0.9999820714011165\n", + "Weights at Step 190: [ 5.67656332e-01 1.65939568e-03 1.28905401e+00 1.71115773e+00\n", + " -1.58943223e-03 -8.05499833e-01]\n", + "Bias at Step 190: [-1.40938345 -1.39505231 1.12327923 -0.98576181]\n", + "---------------------------------------------\n", + "Cost at Step 195: -0.9999721725175995\n", + "Weights at Step 195: [ 5.69078605e-01 3.19307125e-04 1.29022164e+00 1.71130035e+00\n", + " -1.93048878e-03 -8.05618606e-01]\n", + "Bias at Step 195: [-1.409569 -1.39672737 1.12401443 -0.98634514]\n", + "---------------------------------------------\n", + "Cost at Step 200: -0.9999716673699605\n", + "Weights at Step 200: [ 5.68108650e-01 1.50034573e-03 1.28598793e+00 1.70934498e+00\n", + " 1.79335677e-04 -8.07216423e-01]\n", + "Bias at Step 200: [-1.41251555 -1.39653278 1.12414059 -0.98483861]\n", + "---------------------------------------------\n", + "Cost at Step 205: -0.999967337096922\n", + "Weights at Step 205: [ 5.67962666e-01 1.65394273e-03 1.28137364e+00 1.70799044e+00\n", + " 1.07180131e-03 -8.07624878e-01]\n", + "Bias at Step 205: [-1.41371181 -1.39643454 1.12439429 -0.98454151]\n", + "---------------------------------------------\n", + "Cost at Step 210: -0.9999597249749356\n", + "Weights at Step 210: [ 0.56679395 0.00215734 1.27660492 1.70559496 0.00340459 -0.80860628]\n", + "Bias at Step 210: [-1.41510044 -1.39604973 1.12519955 -0.98170126]\n", + "---------------------------------------------\n", + "Cost at Step 215: -0.9999671554651333\n", + "Weights at Step 215: [ 0.56580182 0.00258571 1.27674703 1.70435164 0.00342218 -0.80786668]\n", + "Bias at Step 215: [-1.41599831 -1.39619867 1.12694426 -0.98017017]\n", + "---------------------------------------------\n", + "Cost at Step 220: -0.9999715338643669\n", + "Weights at Step 220: [ 5.66588969e-01 1.02605629e-03 1.27935976e+00 1.70518290e+00\n", + " 1.89260756e-03 -8.06276743e-01]\n", + "Bias at Step 220: [-1.41413444 -1.39786349 1.1290968 -0.97998546]\n", + "---------------------------------------------\n", + "Cost at Step 225: -0.9999694513275535\n", + "Weights at Step 225: [ 5.68001012e-01 -2.25324860e-04 1.28607362e+00 1.70655065e+00\n", + " -1.84796869e-03 -8.03852243e-01]\n", + "Bias at Step 225: [-1.41315297 -1.39882146 1.12925114 -0.9824492 ]\n", + "---------------------------------------------\n", + "Cost at Step 230: -0.9999712850331097\n", + "Weights at Step 230: [ 5.67823711e-01 -5.75559436e-04 1.28513172e+00 1.70681191e+00\n", + " -6.91515391e-04 -8.04711553e-01]\n", + "Bias at Step 230: [-1.41271395 -1.39998171 1.1297646 -0.98119998]\n", + "---------------------------------------------\n", + "Cost at Step 235: -0.9999716632843586\n", + "Weights at Step 235: [ 0.56559617 0.00182221 1.27857022 1.70406892 0.0018423 -0.80616132]\n", + "Bias at Step 235: [-1.41567961 -1.39826585 1.12985088 -0.97868671]\n", + "---------------------------------------------\n", + "Cost at Step 240: -0.9999695425149614\n", + "Weights at Step 240: [ 0.56460828 0.00205178 1.27380322 1.70235747 0.0031743 -0.80618508]\n", + "Bias at Step 240: [-1.41588328 -1.39816865 1.13047453 -0.97683213]\n", + "---------------------------------------------\n", + "Cost at Step 245: -0.9999719017506331\n", + "Weights at Step 245: [ 5.65379689e-01 1.44108182e-03 1.27631625e+00 1.70187293e+00\n", + " 1.83225937e-03 -8.05104919e-01]\n", + "Bias at Step 245: [-1.41519852 -1.39780059 1.13130158 -0.97657538]\n", + "---------------------------------------------\n", + "Cost at Step 250: -0.9999642093465221\n", + "Weights at Step 250: [ 5.64927285e-01 8.05466285e-04 1.27861820e+00 1.70322069e+00\n", + " 9.20435825e-04 -8.03766904e-01]\n", + "Bias at Step 250: [-1.41425627 -1.40049156 1.13287755 -0.9762609 ]\n", + "---------------------------------------------\n", + "Cost at Step 255: -0.9999673002203916\n", + "Weights at Step 255: [ 5.66149124e-01 3.74489949e-04 1.28303523e+00 1.70300340e+00\n", + " -9.70218223e-04 -8.02854506e-01]\n", + "Bias at Step 255: [-1.41382909 -1.39972652 1.13332627 -0.97682702]\n", + "---------------------------------------------\n", + "Cost at Step 260: -0.9999725764393814\n", + "Weights at Step 260: [ 5.66744271e-01 -5.85227561e-04 1.28332621e+00 1.70473394e+00\n", + " -9.66624175e-04 -8.03090881e-01]\n", + "Bias at Step 260: [-1.41266324 -1.40189907 1.13314778 -0.97751041]\n", + "---------------------------------------------\n", + "Cost at Step 265: -0.99997700688611\n", + "Weights at Step 265: [ 5.67955357e-01 2.49009781e-04 1.28566521e+00 1.70443852e+00\n", + " -2.08620074e-03 -8.03711145e-01]\n", + "Bias at Step 265: [-1.41437269 -1.3997801 1.13100823 -0.9795543 ]\n", + "---------------------------------------------\n", + "Cost at Step 270: -0.9999723168047122\n", + "Weights at Step 270: [ 5.68822651e-01 -3.72727155e-04 1.28579703e+00 1.70726892e+00\n", + " -9.35459262e-04 -8.05425130e-01]\n", + "Bias at Step 270: [-1.41362172 -1.40198586 1.13000907 -0.98099361]\n", + "---------------------------------------------\n", + "Cost at Step 275: -0.9999759744633254\n", + "Weights at Step 275: [ 5.68377559e-01 1.18935595e-03 1.28261418e+00 1.70588648e+00\n", + " 8.41927708e-04 -8.07290065e-01]\n", + "Bias at Step 275: [-1.41621484 -1.39944358 1.12753119 -0.9811974 ]\n", + "---------------------------------------------\n", + "Cost at Step 280: -0.999980268847315\n", + "Weights at Step 280: [ 5.68202452e-01 1.26697841e-03 1.27938719e+00 1.70616137e+00\n", + " 1.83906158e-03 -8.07718046e-01]\n", + "Bias at Step 280: [-1.41621027 -1.39903808 1.12718675 -0.98181853]\n", + "---------------------------------------------\n", + "Cost at Step 285: -0.999972323321855\n", + "Weights at Step 285: [ 5.67134077e-01 1.39995118e-03 1.27652308e+00 1.70439308e+00\n", + " 2.69895484e-03 -8.07217640e-01]\n", + "Bias at Step 285: [-1.41640681 -1.39773383 1.12741628 -0.9806237 ]\n", + "---------------------------------------------\n", + "Cost at Step 290: -0.9999763275488955\n", + "Weights at Step 290: [ 5.66245659e-01 9.98465858e-04 1.27857178e+00 1.70372033e+00\n", + " 2.10556959e-03 -8.05656845e-01]\n", + "Bias at Step 290: [-1.41516483 -1.39775812 1.12993268 -0.97934084]\n", + "---------------------------------------------\n", + "Cost at Step 295: -0.9999754977222791\n", + "Weights at Step 295: [ 5.67315312e-01 -5.81346798e-04 1.28555806e+00 1.70597285e+00\n", + " -1.35596411e-03 -8.03269162e-01]\n", + "Bias at Step 295: [-1.41261443 -1.39942783 1.13166477 -0.98126421]\n", + "---------------------------------------------\n" + ] + } + ], + "source": [ + "for i in range(0, steps):\n", + " (weights, bias), cost = optimizer.step_and_cost(cost_function, weights, bias)\n", + "\n", + " # Prints the value of the cost function\n", + " if i % 5 == 0:\n", + " print(f\"Cost at Step {i}: {cost}\")\n", + " print(f\"Weights at Step {i}: {weights}\")\n", + " print(f\"Bias at Step {i}: {bias}\")\n", + " print(\"---------------------------------------------\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TLYEfeyjLbKB" + }, + "source": [ + "With the learned parameters, we construct a visual representation of the\n", + "Hamiltonian to which they correspond and compare it to the target\n", + "Hamiltonian, and the initial guessed Hamiltonian:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 210 + }, + "id": "QnPHQC1PLbKB", + "outputId": "0f35b639-e268-4c10-afc5-5d5b69f6c78e" + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "<Figure size 600x600 with 3 Axes>" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "new_ham_matrix = create_hamiltonian_matrix(\n", + " qubit_number, nx.complete_graph(qubit_number), weights, bias\n", + ")\n", + "\n", + "init_ham = create_hamiltonian_matrix(\n", + " qubit_number, nx.complete_graph(qubit_number), initial_weights, initial_bias\n", + ")\n", + "\n", + "fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(6, 6))\n", + "\n", + "axes[0].matshow(ham_matrix, vmin=-7, vmax=7, cmap=\"hot\")\n", + "axes[0].set_title(\"Target\", y=1.13)\n", + "\n", + "axes[1].matshow(init_ham, vmin=-7, vmax=7, cmap=\"hot\")\n", + "axes[1].set_title(\"Initial\", y=1.13)\n", + "\n", + "axes[2].matshow(new_ham_matrix, vmin=-7, vmax=7, cmap=\"hot\")\n", + "axes[2].set_title(\"Learned\", y=1.13)\n", + "\n", + "plt.subplots_adjust(wspace=0.3, hspace=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zspKar5SLbKB" + }, + "source": [ + "These images look very similar, indicating that the QGRNN has done a\n", + "good job learning the target Hamiltonian.\n", + "\n", + "We can also look at the exact values of the target and learned\n", + "parameters. Recall how the target interaction graph has $4$ edges while\n", + "the complete graph has $6$. Thus, as the QGRNN converges to the optimal\n", + "solution, the weights corresponding to edges $(1, 3)$ and $(2, 0)$ in\n", + "the complete graph should go to $0$, as this indicates that they have no\n", + "effect, and effectively do not exist in the learned Hamiltonian.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "id": "-ql-50F_LbKB" + }, + "outputs": [], + "source": [ + "# We first pick out the weights of edges (1, 3) and (2, 0)\n", + "# and then remove them from the list of target parameters\n", + "\n", + "weights_noedge = []\n", + "weights_edge = []\n", + "for ii, edge in enumerate(new_ising_graph.edges):\n", + " if (edge[0] - qubit_number, edge[1] - qubit_number) in ising_graph.edges:\n", + " weights_edge.append(weights[ii])\n", + " else:\n", + " weights_noedge.append(weights[ii])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "WL7HVML3LbKB" + }, + "source": [ + "Then, we print all of the weights:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "rlB_pAzGLbKB", + "outputId": "c235e602-520b-478c-d776-6f572cf47e5f" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Target parameters Learned parameters\n", + "Weights\n", + "-----------------------------------------\n", + "0.56 | 0.5672676805384127\n", + "1.24 | 1.2857436286533876\n", + "1.67 | 1.7058998728541068\n", + "-0.79 | -0.8036274381843119\n", + "\n", + "Bias\n", + "-----------------------------------------\n", + "-1.44 | -1.4125211271033382\n", + "-1.43 | -1.399740283512748\n", + "1.18 | 1.1309679803706985\n", + "-0.93 | -0.980899993652891\n", + "\n", + "Non-Existing Edge Parameters: [-0.0007816284360817366, -0.0013441949060740517]\n" + ] + } + ], + "source": [ + "print(\"Target parameters Learned parameters\")\n", + "print(\"Weights\")\n", + "print(\"-\" * 41)\n", + "for ii_target, ii_learned in zip(target_weights, weights_edge):\n", + " print(f\"{ii_target : <20}|{ii_learned : >20}\")\n", + "\n", + "print(\"\\nBias\")\n", + "print(\"-\"*41)\n", + "for ii_target, ii_learned in zip(target_bias, bias):\n", + " print(f\"{ii_target : <20}|{ii_learned : >20}\")\n", + "\n", + "print(f\"\\nNon-Existing Edge Parameters: {[val.unwrap() for val in weights_noedge]}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "K4jKWHsELbKB" + }, + "source": [ + "The weights of edges $(1, 3)$ and $(2, 0)$ are very close to $0$,\n", + "indicating we have learned the cycle graph from the complete graph. In\n", + "addition, the remaining learned weights are fairly close to those of the\n", + "target Hamiltonian. Thus, the QGRNN is functioning properly, and has\n", + "learned the target Ising Hamiltonian to a high degree of accuracy!\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0BWaZBY7LbKB" + }, + "source": [ + "References\n", + "==========\n", + "\n", + "1. Verdon, G., McCourt, T., Luzhnica, E., Singh, V., Leichenauer, S., &\n", + " Hidary, J. (2019). Quantum Graph Neural Networks. arXiv preprint\n", + " [arXiv:1909.12264](https://arxiv.org/abs/1909.12264).\n", + "\n", + "About the author\n", + "================\n" + ] + } + ], + "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.9.17" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}