{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "#Installing all dependencies\n", "\n", "import strawberryfields as sf\n", "from strawberryfields.ops import *\n", "from strawberryfields.utils import scale\n", "from numpy import pi, sqrt\n", "import math\n", "import random\n", "from scipy.optimize import minimize\n", "\n", "import numpy as np\n", "\n", "from matplotlib import pyplot as plt\n", "from mpl_toolkits.mplot3d import Axes3D" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Table of Contents**\n", "\n", "**Part 1: Theory**\n", "\n", "1. The Variational Quantum Eigensolver\n", "2. The Quantum Approximate Optimization Algorithm\n", "3. Continuous-Variable QAOA\n", "\n", "**Part 2: Simulations**\n", "\n", "4. A Small Tangent: Creating Quadrature Plots With Strawberry Fields and Matplotlib\n", "5. Simulating Continuous-Variable QAOA For a Simple Problem\n", "6. Simulating Continuous-Variable QAOA For Harder Problems\n", "7. The Not-So Grand Finale: A Quartic Function With Two Global Minima\n", "8. Another Small Tangent: Higher-Order Gate Decomposition\n", "9. I Promise This is Our Last Detour: Numerically Calculating the Cost Hamiltonian Expectation Value\n", "

\n", "10. Conclusion\n", "11. Acknowledgments and References\n", "\n", "\n", "
\n", "\n", "**Introduction**\n", "\n", "The goal of this notebook is to provide the reader with a concrete understanding of QAOA over Continuous Variables. Despite this, the first section of this notebook is dedicated to understanding the **physics** that allows algorithms like QAOA to function properly. The reason I have included this is because I want to provide an end-to-end explanation of why CV QAOA works, starting from first principles with the variational principle and AQT, working up to the theory behind CV QAOA, then in Part 2, launching into actual concrete simulations of the CV QAOA problem applied to different problems.\n", "\n", "This is the **first version** of this notebook. Becausse it is so long, I am almost 100% sure that I will find mistakes in it somewhere as I edit it over the coming weeks. I will try to keep an Erratum at the bottom of this notebook, as I make updates! I also welcome feedback, suggestions, and people pointing our where I made mistakes, so do not hesitate to reach out!\n", "\n", "Without further delay, let's get started!\n", "\n", "**The Variational Quantum Eigensolver**
\n", "\n", "Before we jump into QAOA, it is good to require a more general process, that of the **Variational Quantum Eigensolver**. VQE is essentially a process that allows us to find the ground eigenvalue of some specified Hamiltonian, by repeatedlly \"guessing\" some quantum state that is parametrized by some parameters, calculating the expectation value of the Hamiltonian, then using a classical optimizer to update the parameters as this process is repeated until the algorithm converges on the optimal solution. Basically, we have:\n", "\n", "1. Pick some set of parameters $\\{\\alpha_1, \\ ..., \\ \\alpha_n\\}$\n", "2. Generate some parametrized quantum state $|\\alpha_1, \\ ..., \\ \\alpha_n\\rangle$ using parametrized quantum gates (which are of course parametrized according to each parameter).\n", "3. Calculate $\\langle H \\rangle$ for this particular state.\n", "4. Feed this value into a classical optimizer, which generates a new set of parameters, then go back to Step 2. Repeat this process until we have found the optimal $|\\alpha\\rangle_{O}$, corresponding to the optimal energy $E_{O}$.\n", "\n", "The reason that VQE works is because of an idea within quantum mechanics called the **variational principle**, which states that if I have some Hamiltonian describing a quantum system, and I choose some state vector $|\\psi\\rangle$, then:\n", "\n", "

\n", "\n", "$$\\langle \\psi | H | \\psi \\rangle \\ \\geq \\ E_0$$\n", "\n", "

\n", "\n", "Where $E_0$ is the ground-state energy. The proof of this is fairly straightforward. Any state vector $|\\psi\\rangle$ can be expressed as a linear combination of energy eigenstates:\n", "\n", "

\n", "\n", "$$|\\psi\\rangle \\ = \\ \\displaystyle\\sum_{n} \\ c_n |E_n\\rangle$$\n", "\n", "

\n", "\n", "So we then have:\n", "\n", "

\n", "\n", "$$\\langle \\psi | H | \\psi \\rangle \\ = \\ \\Bigg( \\displaystyle\\sum_{n} \\ c_n^* \\langle E_n| \\Bigg) H \\Bigg( \\displaystyle\\sum_{n} \\ c_n | E_n \\rangle \\Bigg) \\ = \\ \\Bigg( \\displaystyle\\sum_{n} \\ c_n^* \\langle E_n| \\Bigg) \\Bigg( \\displaystyle\\sum_{n} \\ c_n H | E_n \\rangle \\Bigg) \\ = \\ \\Bigg( \\displaystyle\\sum_{n} \\ c_n^* \\langle E_n| \\Bigg) \\Bigg( \\displaystyle\\sum_{n} \\ c_n E_n | E_n \\rangle \\Bigg)$$ \n", "\n", "

\n", "\n", "$$\\Rightarrow \\ \\Bigg( \\displaystyle\\sum_{n} \\ c_n^* \\langle E_n| \\Bigg) \\Bigg( \\displaystyle\\sum_{n} \\ c_n E_n | E_n \\rangle \\Bigg) \\ = \\ \\displaystyle\\sum_{n} \\ |c_n|^2 \\ E_n$$\n", "\n", "

\n", "\n", "And so, it follows that the minimum possible energy for the this sum is when $|c_0|^2 \\ = \\ 1$ and the rest of the coefficients equal $0$ (because of the normalization condition). This is the ground state energy, so it follows that:\n", "\n", "

\n", "\n", "$$E_0 \\ \\leq \\ \\displaystyle\\sum_{n} \\ |c_n|^2 \\ E_n \\ = \\ \\langle \\psi | H | \\psi \\rangle$$\n", "\n", "

\n", "\n", "This is super cool! This bascially means that if I have some Hamiltonian, I can pick any quantum state I want and the expectation value of the Hamiltonian corresponding to this state will **always** be greater than or equal to the ground state energy. Now, let's say that I have some optimization problem, which I must solve by minimizing some cost function. Well, if I can write this cost function as a Hamiltonian that acts on quantum states, then, I can create a process in which I guess an initial wavefunction, calculate the expectation value of the Hamiltonian, then pass that result through a classical optimizer and continue to vary the parameters of the initial wavefunction until I find the lowest energy state, corresponding to $E_0$. The variational principle tells me that I can never \"wrongly guess\" a wavefunction: I can't choose a wavefunction that corresponds to an expected energy below the ground state, thus throwing off my optimization process.\n", "\n", "**The Quantum Apprroximate Optimization Algorithm**
\n", "\n", "I like to think of QAOA as a sort of sub-class of VQE, but not really. Specifically, I like to think of QAOA as VQE, but with a particular ansatz strategy that draws influence from quantum mechanics. When I say an \"ansatz strategy\", I am simply referring to the **method used to prepare the parametrized state** (which gates are used). For QAOA, we repeatedly apply to our initial qubit state the parametrized gate given by:\n", "\n", "

\n", "$$U(\\gamma, \\ \\alpha) \\ = \\ e^{-i\\alpha H_{M}} e^{-i\\gamma H_{C}}$$\n", "

\n", "\n", "Where $H_{C}$ is the cost Hamiltonian that we are trying to minimize, and $H_{M}$ is a non-commuting mixer Hamiltonian, which we choose to expand our search space (that's the intuitive explanation, we will see what the mixer Hamiltonian actually means soon).\n", "\n", "By using this gate sequence, the quantum state is recursively evolved to some state, corresponding to the optimal state of some Hamiltonian. The total evolution of the state through QAOA is given as:\n", "\n", "

\n", "$$|s\\rangle \\ \\rightarrow \\ |s'\\rangle \\ = \\ \\textbf{U} |s\\rangle \\ = \\ \\displaystyle\\prod_{k} \\ U(\\gamma_k, \\ \\alpha_k) |s\\rangle \\ \\ \\ \\ \\ \\ \\gamma_k \\ \\in \\ \\boldsymbol \\gamma, \\ \\ \\alpha_k \\ \\in \\ \\boldsymbol \\alpha \\ \\ \\ \\forall k$$\n", "

\n", "\n", "Where $\\boldsymbol \\gamma$ and $\\boldsymbol \\alpha$ are sets of parameters used for our run of the algorithm. We are able to set the value of $k$, with $k \\ \\rightarrow \\ \\infty$ theoretically leading to $\\epsilon \\ \\rightarrow \\ 0$, hwoever, this is not the case in reality, as increasing circuit depth increases error, so it is up to the individual utilizing the algorithm to \"turn the knobs\" to set $k$ to a value that gives error below a desired threshold, while also keeping in mind quantum hardware limitations and noise.\n", "\n", "Since this is a variational algorithm, a classical optimizer will optimize our $\\gamma$ and $\\alpha$ parameters over repeated runs of the circuit, until we converge on parameters that yield a state, which, when measured, yields the lowest value of the cost function.\n", "\n", "You may be wondering now **why** QAOA actually makes sense as an \"ansatz strategy\". Basically, we have some cost function that we want to minimize, which we express as a Hamiltonian acting on quantum state vectors, called $H_{C}$. Well, there is no guarentee that our Hamiltonian $H_{C}$ is unitary (and can thus represent a quantum gate operation). However, it is true that an operator of the form $e^{ikH}$ is unitary. In fact, recall from quantum mechanics the time-dependent Schrödinger equation:\n", "\n", "

\n", "$$i\\hbar \\frac{d |\\Psi(t)\\rangle}{dt} \\ = \\ \\hat{H} |\\Psi(t)\\rangle \\ \\Rightarrow \\ i\\hbar \\frac{d}{dt} \\displaystyle\\sum \\ c_n(t) |E_n\\rangle \\ = \\ \\hat{H} \\ \\displaystyle\\sum c_n(t) |E_n\\rangle$$\n", "

\n", "\n", "Where we also have:\n", "\n", "

\n", "$$\\hat{H} |E_n\\rangle \\ = \\ E_n |E_n\\rangle \\ \\ \\forall \\ n$$\n", "

\n", "\n", "Expanding in this basis yields uncoupled differential equation describing the components $c_n(t)$, which we then solve to get the generaal time-dependence of energy eigenstates:\n", "\n", "

\n", "$$\\hat{H} \\ \\displaystyle\\sum c_n(t) |E_n\\rangle \\ = \\ \\displaystyle\\sum c_n(t) E_n |E_n\\rangle \\ \\Rightarrow \\ i\\hbar \\frac{d c_n(t)}{dt} \\ = \\ c_n(t) E_n \\ \\Rightarrow \\ c_n(t) \\ = \\ c_n(0) e^{-iE_n t/\\hbar}$$\n", "

\n", "\n", "But, we also have:\n", "\n", "

\n", "$$|\\Psi(0)\\rangle \\ = \\ \\displaystyle\\sum c_n(0) |E_n\\rangle \\ \\Rightarrow \\ c_k(0) \\ = \\ \\langle E_k | \\Psi(0) \\rangle$$\n", "

\n", "\n", "Putting this all together, we have:\n", "\n", "

\n", "$$|\\Psi(t)\\rangle \\ = \\ \\displaystyle\\sum e^{-iE_n t/\\hbar} \\langle E_n | \\Psi(0) \\rangle |E_n\\rangle \\ = \\ \\Big( \\displaystyle\\sum e^{-iE_n t/\\hbar} | E_n \\rangle \\langle E_n | \\Big) |\\Psi(0)\\rangle$$\n", "

\n", "\n", "So, since the $|E_n\\rangle$ states form a complete basis, we have:\n", "\n", "

\n", "$$\\Big( \\displaystyle\\sum |E_n\\rangle \\langle E_n| \\Big) \\ = \\ \\mathbb{I}$$\n", "

\n", "\n", "We can exploit this, but we first have to deal with the exponential. It turns out, we have:\n", "\n", "

\n", "$$\\Big( \\displaystyle\\sum e^{-iE_n t/\\hbar} | E_n \\rangle \\langle E_n | \\Big) |\\Psi(0)\\rangle \\ = \\ e^{-i\\hat{H} t/\\hbar} \\mathbb{I} |\\Psi(0)\\rangle \\ = \\ e^{-i\\hat{H} t/\\hbar} |\\Psi(0)\\rangle$$\n", "

\n", "\n", "Which we can easily show:\n", "\n", "

\n", "$$e^{-i\\hat{H} t/\\hbar} |\\Psi(0)\\rangle \\ = \\ \\displaystyle\\sum c_n(0) e^{-i\\hat{H} t/\\hbar} |E_n\\rangle \\ = \\ \\displaystyle\\sum c_n(0) \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-it/\\hbar)^k \\hat{H}^k}{k!} |E_n\\rangle \\ = \\ \\displaystyle\\sum c_n(0) \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-it/\\hbar)^k E_n^k}{k!} |E_n\\rangle$$\n", "
\n", "$$\\Rightarrow \\displaystyle\\sum c_n(0) e^{-iE_n t/\\hbar} |E_n\\rangle \\ = \\ \\Big( \\displaystyle\\sum e^{-iE_n t/\\hbar} | E_n \\rangle \\langle E_n | \\Big) |\\Psi(0)\\rangle$$\n", "

\n", "\n", "So we have a unitary called $U$, which we call the time-evolution operator, as it performs the transformation:\n", "\n", "

\n", "$$|\\Psi(0)\\rangle \\ \\rightarrow \\ |\\Psi(t)\\rangle \\ = \\ U |\\Psi(0)\\rangle \\ \\Rightarrow \\ U \\ = \\ e^{-i\\hat{H} t/\\hbar}$$\n", "

\n", "\n", "Well, this looks awfully similar to the parametrized unitaries that we use for QAOA, $e^{-i\\gamma H_{C}}$ and $e^{-i \\alpha H_{M}}$! This is no coincidence! The idea with QAOA is that we evolve our state in \"time\" to the ground state of our cost Hamiltonian. In order for this idea to fully make sense, we need to discuss quantum adiabatic evolution. Consider the Hamiltonian that evolves in time due to some continuously applied perturbation:\n", "\n", "

\n", "$$\\hat{H}(t) \\ = \\ \\frac{t}{T} \\hat{H}_{C} \\ + \\ \\Big(1 \\ - \\ \\frac{t}{T} \\Big) \\hat{H}_{M}$$\n", "

\n", "\n", "The idea is that if we have some quantum system that starts (at $t \\ = \\ 0$) in the ground state of some mixer Hamiltonian $\\hat{H}_M$, and we slowly evolve the Hamiltonian over time, then the evolution of our quantum state will tend towards the ground state of the new, cost Hamiltonian $\\hat{H}_{C}$. This is formally known as the **quantum adiabatic theorem**. The parameter $T$ allows us to control how quickly we evolve from $\\hat{H}_{M}$ to $\\hat{H}_{C}$. Theoretically, as $T \\ \\rightarrow \\ \\infty$, our state approaches the ground state of $\\hat{H}_{C}$ with probability of $1$. For QAOA, we are basically utilizing a discrete version of this process. We start our qubit state in the ground state of $\\hat{H}_M$, which we call $|M_0\\rangle$.\n", "\n", "Now, things are going to get a bit hairy. Time-evolution according to as time-dependent Hamiltonian is different than a time-independent one. We must use something called a **Dyson Series** which I won't go into in this article to arrive at the fact that between $t_1$ and $t_2$, the time-evolution operator is given as:\n", "\n", "

\n", "$$U(t_1, \\ t_2) \\ = \\ \\tau \\exp \\Big( -\\frac{i}{\\hbar} \\displaystyle\\int_{t_1}^{t_2} H(t) dt \\Big)$$\n", "

\n", "\n", "Well, let's compute this integral and see what happens!\n", "\n", "

\n", "$$\\displaystyle\\int_{t_1}^{t_2} H(t) dt \\ = \\ \\displaystyle\\int_{t_1}^{t_2} \\frac{t}{T} \\hat{H}_{C} \\ + \\ \\Big(1 \\ - \\ \\frac{t}{T} \\Big) \\hat{H}_{M} dt \\ = \\ \\frac{t^2}{2T} \\hat{H}_{C} \\ - \\ \\frac{T}{2} \\Big(1 \\ - \\ \\frac{t}{T} \\Big)^2 \\hat{H}_{M} \\biggr\\rvert_{t_1}^{t_2}$$\n", "

\n", "\n", "We are evolving our quantum system from $t \\ = \\ 0$ to $t \\ = \\ T$, so we have:\n", "\n", "

\n", "$$\\frac{t^2}{2T} \\hat{H}_{C} \\ - \\ \\frac{T}{2} \\Big(1 \\ - \\ \\frac{t}{T} \\Big)^2 \\hat{H}_{M} \\biggr\\rvert_{0}^{T} \\ = \\ \\frac{T}{2} (\\hat{H}_{M} \\ + \\ \\hat{H}_{C} )$$\n", "

\n", "\n", "Since we are not dealing with products of operators, the time-ordering operator $\\tau$ drops away. So the time-evolution of our quantum state from $t \\ = \\ 0$ to $t \\ = \\ T$ is given as:\n", "\n", "

\n", "$$|M_0\\rangle \\ \\rightarrow \\ U |M_0\\rangle \\ = \\ e^{-iT (\\hat{H}_{M} \\ + \\ \\hat{H}_{C})/2\\hbar} |M_0\\rangle$$\n", "

\n", "\n", "In order to realize this operator on a quantum circuit, we have to Trotterize it. When I say Trotterize, I mean we have to perform a Trotter-Suzuki decomposition, which says that:\n", "\n", "

\n", "$$e^{i t \\sum H_k} \\ \\approx \\ \\Big ( \\displaystyle\\prod_k e^{i \\frac{t}{G} H_k} \\Big)^{G}$$\n", "

\n", "\n", "Where the approximation gets better as $G$ increases. This equates to an increased number of steps in our algorithm (applications of $U(\\gamma, \\ \\alpha)$)! From this, we have:\n", "\n", "

\n", "$$e^{-iT (\\hat{H}_{M} \\ + \\ \\hat{H}_{C})/2\\hbar} \\ = \\ \\Big( e^{-i\\frac{T}{2G\\hbar} \\hat{H}_{M}} e^{-i\\frac{T}{2G\\hbar} \\hat{H}_{C}} \\Big)^{G}$$\n", "

\n", "\n", "Now, we have a nice ansatz that should evolve our quantum state to the ground state of $\\hat{H}_{C}$. However, where do the parameters $\\alpha$ and $\\gamma$ come into play? Since the Trotter-Suzuki decomposition is not exact (the exact form of the expansion of the exponential is given by the Baker-Campbell-Hausdorff formula, which is an infinite product of commutators of the operators in the exponential), and we are limited to a finite value of $G$ (actually, $G$ has to be pretty small to keep circuit depth low). In addition, we can't always initialize our system in the ground state of the mixer Hamiltonian, as often, strategies are utilized where the mixer's purpose is to \"search\" the space of feasible solutions or encode hard-constraints. In these cases, the initial state is often set to overlap many possible states/states that obey the hard-constraints. This means that we need to introduce another degree (or degrees plural) of freedom to our state preparation circuit, in order to get the acceptable results. Thus, we **parametrize** our exponential operators with the sets $\\boldsymbol \\alpha$ and $\\boldsymbol \\gamma$, where $|\\boldsymbol \\gamma| \\ = \\ |\\boldsymbol \\alpha| \\ = \\ G$.\n", "\n", "The final evolution of our state after applying the QAOA ansatz is given as:\n", "\n", "

\n", "$$|M_0\\rangle \\ \\rightarrow \\ \\Big( e^{-i \\alpha H_{M}} e^{-i \\gamma H_{C}} \\Big)^{G} |M_0\\rangle \\ \\approx \\ |C_0\\rangle$$\n", "

\n", "\n", "So if we have done everything correct, we should get a state that is approximately the ground state of our cost Hamiltonian, which is exactly the problem we are attempting to solve!\n", "\n", "Now consider what happens when we take a measurement of the quantum state we have preparred, which you should recall is denoted as $|s'\\rangle \\ = \\ \\textbf{U} |s\\rangle$. Now that we have preparred our quantum state (as one does in a variational algorithm), we must calculate $\\langle s' | H_{C} | s'\\rangle$. \n", "\n", "To do this we sample our circuit repeatedly, measuring in the basis of energy eigenstates of $H_{C}$. In most cases, for the discrete QAOA, we express our cost function with $\\sigma^z$ operators, so this ends up being the standard computational basis. In CV QAOA, we will soon show that our cost functions are expressed in terms of $\\hat{x}$ operations, so we take an X-Homodyne measurement. \n", "\n", "From measurement, we obtain a result $|k\\rangle$, and we then feed the value associated with $|k\\rangle$, which we will call $k$, into our classical cost function, and after many samples of the circuit, take the average of the sum of all outputs of the cost function. If we sample the circuit $N$ times, we get the quantity:\n", "\n", "

\n", "$$\\frac{1}{N} \\displaystyle\\sum_{i} n_i E_i \\ \\approx \\ \\displaystyle\\sum_{i} \\text{Pr} (E_i) E_i \\ = \\ \\displaystyle\\sum_{i} \\langle s' | E_i \\rangle \\langle E_i | s' \\rangle E_i \\ = \\ \\langle s' | \\Big( \\displaystyle\\sum_{i} E_i |E_i\\rangle \\langle E_i| \\Big) | s' \\rangle \\ = \\ \\langle s' | \\Big( \\displaystyle\\sum_{i} \\hat{H}_{C} |E_i\\rangle \\langle E_i| \\Big) | s' \\rangle$$\n", "
\n", "$$\\Rightarrow \\ \\langle s' | \\hat{H}_{C} \\Big( \\displaystyle\\sum_{i} |E_i\\rangle \\langle E_i| \\Big) | s' \\rangle \\ = \\ \\langle s' | \\hat{H}_{C} | s' \\rangle$$\n", "

\n", "\n", "Where $n_i$ is the number of time $|E_i\\rangle$ is measured. So we have proven that our method of calculating the cost function is valid, as the quantity that we calculate by sampling our circuit is equivalent to $\\langle s' | H_{C} | s' \\rangle$! The same kind of logic applies for continuous spectra of energy, but we are approximating the integral over all possible values with a Reimann sum. \n", "\n", "**Continuous-Variable QAOA**
\n", "\n", "This is going to be the coolest section of the Notebook (in my opinion), because despite being short, we will get some more intuition as to why the **continuous-variable analogue** of QAOA actually works! Of course, the method that we outlined in the previous section generalizes well to a continuous or discrete qudit model, however, the introduction in the paper provides even more intuition as to why this method works!\n", "\n", "In order to create QAOA over continuous-variables, we follow the same process of creating a mixer and a cost Hamiltonian. For the cost unitary, we will initilize our cost Hamiltonian (the unitary is given by the imaginary exponential) by creating a **function with respect to the position quadrature**, which is just the observable operator that corresponds to \"position\" (well, not actually position, a qumode doesn't actually \"move around\" like a particle in some potential, but it behaves pretty much identically to how the position operator behaves when acted upon by other operators in the Heisenberg picture. In reality, the two quadratures that we use in photonic QC represent in-phase and out-of-phase components of an electric field). Anyways, if we have some scalar function, we will transform it as $f(x) \\ \\rightarrow \\ f(\\hat{x})$. For example, $f(x) \\ = \\ x^3 \\ \\rightarrow \\ f(\\hat{x}) \\ = \\ \\hat{x}^3$. Our cost unitary then looks something like this:\n", "\n", "

\n", "$$U_C \\ = \\ e^{i \\gamma f(\\hat{x})}$$\n", "

\n", "\n", "Where $f(x)$ is the actual cost function that we are trying to minimize.\n", "\n", "In order to implement continuous-variable QAOA, we follow the same general process as the discrete version of QAOA. We choose a cost and a mixer Hamiltonian, which we then Trotterize and recurrsivley act upon our photonic modes. For each step of the algorithm, we write the unitary as:\n", "\n", "

\n", "$$U(\\gamma, \\ \\alpha) \\ = \\ e^{-i \\alpha \\hat{H}_M} e^{-i\\gamma \\hat{H}_C}$$\n", "

\n", "\n", "For our mixer, we are required to define our mixer Hamiltonian. Let's first consider a mixer which we will call the **kinetic mixer**, defined by the Hamiltonian, and thus the unitary:\n", "\n", "

\n", "$$H_{K} \\ = \\ \\frac{1}{2} \\displaystyle\\sum_{i} \\hat{p}^2_i \\ \\Rightarrow \\ U_{K} \\ = \\ e^{-i \\alpha \\frac{1}{2}\\hat{p^2}}$$\n", "

\n", "\n", "Where the sum over all modes is implied in the exponential. Consider how an application of this gate transforms our $\\hat{x}$ operator, if we consider evolution of quantum states in terms of the Heisenberg picture, where quantum states remain fixed, but the operators themselves evolve:\n", "\n", "

\n", "$$e^{i \\alpha \\frac{1}{2} \\hat{p}^2} \\ = \\ e^{i \\alpha \\frac{1}{2} (p \\mathbb{I})^2} \\ = \\displaystyle\\sum_{n \\ = \\ 0}^{\\infty} \\Big( \\frac{i \\alpha}{2} \\Big)^n \\frac{(p \\mathbb{I})^{2n}}{n!} \\ = \\ \\mathbb{I} \\displaystyle\\sum_{n \\ = \\ 0}^{\\infty} \\Big( \\frac{i \\alpha}{2} \\Big)^n \\frac{p^{2n}}{n!} \\ = \\ \\mathbb{I} e^{i \\alpha \\frac{1}{2} \\hat{p}^2}$$\n", "

\n", "$$e^{i \\alpha \\frac{1}{2} \\hat{p}^2} \\hat{x} e^{-i \\alpha \\frac{1}{2} \\hat{p}^2} \\ = \\ \\mathbb{I} e^{i \\alpha \\frac{1}{2} p^2} \\Big(-\\frac{\\hbar}{i} \\Big) \\nabla_p \\mathbb{I} e^{-i \\alpha \\frac{1}{2} p^2} \\ = \\ \\mathbb{I} e^{i \\alpha \\frac{1}{2} p^2} e^{-i \\alpha \\frac{1}{2} p^2} \\Big(-\\frac{\\hbar}{i} \\Big) \\nabla_p \\ - \\ \\mathbb{I} e^{i \\alpha \\frac{1}{2} p^2} \\Big(-\\frac{\\hbar}{i} \\Big) \\mathbb{I} \\alpha p e^{-i \\alpha \\frac{1}{2} p^2} \\ = \\ \\hat{x} \\ + \\ \\hbar \\alpha \\hat{p}$$\n", "

\n", "\n", "If the idea of removing the identity matrix doesn't sit well with you (it makes sense, we are choosing to do our calculations in the basis that allows us to write our operator in this fashion), we can also use our good old friend the Taylor series to perform an identical calculation:\n", "\n", "

\n", "$$e^{i \\alpha \\frac{1}{2} \\hat{p}^2} \\hat{x} e^{-i \\alpha \\frac{1}{2} \\hat{p}^2} \\ = \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k \\hat{p}^{2k}}{k!} \\Big) \\hat{x} \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-\\frac{1}{2} i \\alpha)^k \\hat{p}^{2k}}{k!} \\Big) \\ = \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big) \\Big( -\\frac{\\hbar}{i} \\Big) \\frac{\\partial}{\\partial p} \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big)$$\n", "

\n", "$$\\Rightarrow \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big) \\Big( \\Big( -\\frac{\\hbar}{i} \\Big) \\frac{\\partial}{\\partial p} (1) \\ + \\ 2 \\Big( -\\frac{\\hbar}{i} \\Big) \\displaystyle\\sum_{k \\ = \\ 1}^{\\infty} \\frac{(-\\frac{1}{2} i \\alpha)^k p^{2k \\ - \\ 1}}{(k \\ - \\ 1)!} \\Big)$$\n", "

\n", "$$\\Rightarrow \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big) \\Big( \\Big( -\\frac{\\hbar}{i} \\Big) \\frac{\\partial}{\\partial p} (1) \\ + \\ 2 \\Big( -\\frac{\\hbar}{i} \\Big) \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-\\frac{1}{2} i \\alpha)^{(k \\ + \\ 1)} p^{2k \\ + \\ 1}}{k!} \\Big)$$\n", "

\n", "$$\\Rightarrow \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big) \\Big( \\Big( -\\frac{\\hbar}{i} \\Big) \\frac{\\partial}{\\partial p} (1) \\ + \\ i\\alpha \\Big( \\frac{\\hbar}{i} \\Big) p \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(-\\frac{1}{2} i \\alpha)^{k} p^{2k}}{k!} \\Big) \\ = \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k p^{2k}}{k!} \\Big) x \\ + \\ \\hbar \\alpha \\hat{p}$$\n", "

\n", "$$\\Rightarrow \\ \\Big( \\displaystyle\\sum_{k \\ = \\ 0}^{\\infty} \\frac{(\\frac{1}{2} i \\alpha)^k \\Big( \\Big( -\\frac{\\hbar}{i} \\Big) \\frac{\\partial}{\\partial x} \\Big)^{2k}}{k!} \\Big) x \\ + \\ \\hbar \\alpha \\hat{p} \\ = \\ \\hat{x} \\ + \\ \\hbar \\alpha \\hat{p}$$\n", "

\n", "\n", "Thank goodness for the power of matrix exponentials. Now, consider what happens when we evolve our $\\hat{p}$ operator with our cost unitary:\n", "\n", "

\n", "$$e^{i \\gamma f(\\hat{x})} \\ = \\ e^{i \\gamma f(\\mathbb{I} x)} \\ = \\ g(x) \\ = \\ \\displaystyle\\sum_{n \\ = \\ 0}^{\\infty} g^{(n)}(0) \\frac{(\\mathbb{I} x)^{n}}{n!} \\ = \\ \\mathbb{I} \\displaystyle\\sum_{n \\ = \\ 0}^{\\infty} g^{(n)}(0) \\frac{x^n}{n!} \\ = \\ \\mathbb{I} e^{i \\gamma f(x)}$$\n", "

\n", "$$e^{i \\gamma f(\\hat{x})} \\hat{p} e^{-i \\gamma f(\\hat{x})} \\ = \\ \\mathbb{I} e^{i \\gamma f(x)} \\Big(\\frac{\\hbar}{i} \\Big) \\nabla_{x} \\mathbb{I} e^{-i \\gamma f(x)} \\ = \\ \\mathbb{I} e^{i \\gamma f(x)} \\Big( \\hat{p} \\ - \\ \\hbar \\gamma \\nabla_x f(x) \\Big) \\mathbb{I} e^{-i \\gamma f(x)} \\ = \\ \\hat{p} \\ - \\hbar \\gamma \\nabla f(\\hat{x}) $$\n", "

\n", "\n", "Where we can absorb the $\\mathbb{I}$ into the function by a proof that is practically identical to the one we already demonstrated, with the Taylor series. This basically follows the same method as the mixer. Notice that in order to the first line, where we do the Taylor expansion, $f(x)$ must be an **analytic** function (can be expanded as a Taylor series). This provision is stated in the original CV QAOA paper, so it feels good to know that we're going in the right direction! Now, let's consider what happens when we put examine our **total** evolution of $\\hat{x}$, after applications of the cost, then the mixer unitary:\n", "\n", "

\n", "$$\\hat{x} \\ \\rightarrow \\ \\hat{x} \\ + \\ \\alpha \\hat{p} \\ \\rightarrow \\ \\hat{x} \\ + \\ \\alpha (\\hat{p} \\ - \\ \\gamma \\nabla f(\\hat{x})) \\ = \\ \\hat{x} \\ + \\ \\alpha \\hat{p} \\ - \\ \\alpha \\gamma \\nabla f(\\hat{x})$$\n", "

\n", "\n", "This is very cool, because if both $\\alpha$ and $\\gamma$ are infinitessimal units of time, $dt$, then this equation is identical to the dynamics of a classical point-mass under the influence of some potential, $f(x)$, as:\n", "\n", "

\n", "$$\\hat{a} \\ \\propto \\ \\hat{F} \\ = \\ -\\nabla f(\\hat{x})$$\n", "

\n", "\n", "Where $\\hat{a}$ and $\\hat{F}$ are operators corresponding to acceleration and force, so we will have (if we set mass to $1$):\n", "\n", "

\n", "$$\\hat{x} \\ \\rightarrow \\ \\hat{x} \\ + \\ \\hat{v} t \\ + \\ \\hat{a} t^2$$\n", "

\n", "\n", "This is a staggeringly elegant interpretation of the QAOA ansatz over continuous-variables. With our classical optimizer, we have to find the \"amount of time\" which we must evolve our system (which can be visualized as a particle travelling around in a potential landscape), such that it ends up in position with that minimizes potential energy (equilibrium). This is also the exact same procedure as **gradient descent**, we are choosing parameters such that our \"particle\" ends up at the bottom of a potential landscape, where it evolves in the **direction of the negative gradient**. From a physical perspective, it is being acted upon by some **force**, and thus tends towards the position where the force vector field is \"pointing\", which evenually ends up being a point of equilibrium.\n", "\n", "Now let's consider another mixer, which we will call the **number mixer**, defined by the Hamiltonian (leading to the unitary):\n", "\n", "

\n", "$$\\hat{H}_N \\ = \\ \\hat{a}^{\\dagger} \\hat{a} \\ \\Rightarrow \\ \\hat{U}_{N} \\ = \\ e^{-i \\alpha \\hat{a}^{\\dagger} \\hat{a}}$$\n", "

\n", "\n", "If we perform similar calculations to the process we followed to find the evolution of the $\\hat{x}$ operator when the previous mixer was applied, we get:\n", "\n", "

\n", "$$e^{i \\alpha \\hat{a}^{\\dagger} \\hat{a}} \\hat{x} e^{-i \\alpha \\hat{a}^{\\dagger} \\hat{a}} \\ = \\ \\hat{x} \\ + \\ \\alpha \\hat{p} \\ + \\ O(\\alpha^2)$$\n", "

\n", "\n", "Which is identical to our kinetic Hamiltonian, up to a small correction term.\n", "\n", "We can also do something else with the mixers: we can look at them from the **original perspective of the adiabatic theorem**, by understanding the physical Hamiltonians that each of our mixers represent! This just serves to provide even more physical intuition!\n", "\n", "Intuitively, we can think of the kinetic mixer as \"adding freedom\" to our states! Consider the Hamiltonian describing a single particle in a potential field, given as:\n", "\n", "

\n", "$$\\hat{H} \\ = \\ \\frac{\\hat{p}^2}{2m} \\ + \\ V(x)$$\n", "

\n", "\n", "So this mixer corresponds to the time-evolution operator of a system with a Hamiltonian describing the motion of a free particle. This is kind of intuitive, the logic is that we are expanding our search space by evolving our system with a \"dynamic\" Hamiltonian. The other mixer that we will investigate is the number mixer, which is given by:\n", "\n", "

\n", "$$\\hat{H}_{N} \\ = \\ e^{-i \\alpha \\hat{a}^{\\dagger} \\hat{a}}$$\n", "

\n", "\n", "Where $\\hat{a}^{\\dagger}$ and $\\hat{a}$ are the creation and annhiliation operators respectively. This operator also has a conceptual meaning. The Hamiltonian for the quantum harmonic oscillator (the same potential that qumodes are subjected to), is given as:\n", "\n", "

\n", "$$\\hat{H} \\ = \\ \\Big( \\hat{a}^{\\dagger} \\hat{a} \\ + \\ \\frac{1}{2} \\Big)$$\n", "

\n", "\n", "So up to an overall phase, our number mixer corresponds to time-evolution of a state in the quantum harmonic oscillator potential, which again, helps to expand our search space.\n", "\n", "**A Small Tangent: Creating Quadrature Plots With Strawberry Fields and Matplotlib**
\n", "\n", "I promise this is the last section before we start creating our actual simulation! One of the best ways to visualize the state of a continuous-variable quantum system is with the wigner function, which is a 3D graph in $\\hat{x} \\hat{p}$ phase space. Each point, analogous to the quantum-mechanical probability density tells us the probability of measuring a particle's $x$ and $p$ quadrature values between $x$, and $x \\ + \\ dx$ and $p$ and $p \\ + \\ dp$.\n", "\n", "Luckily, Strawberry Fields has a fantastic built-in feature that we can use to get the Wigner graphs. However, for the purposes of our simulation, we will only be interested in the $\\hat{x}$-quadrature probabilities (as we discussed previously). Strawberry Fields doesn't have a feature that outputs quadrature probabilities quite yet, so in order to get the probabilitiy distribution for $\\hat{x}$, we will have to integrate our Wigner function across $\\hat{p}$:\n", "\n", "

\n", "$$P(x) \\ = \\ \\displaystyle\\int_{-\\infty}^{\\infty} W(x, \\ p) dp$$\n", "

\n", "\n", "Now, the function that returns the Wigner function in Strawberry Fields gives us a 2D array of numerical values, thus, we must integrate numerically across all points $(x, \\ p_i)$, for each of the returned values of $x$. We can do this fairly easily using the built-in Simpson's method function in Scipy. Let's do a quick example, to show that it works. Consider the preparation of the $|2\\rangle$ Fock state in Strawberry Fields:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from scipy.integrate import simps\n", "\n", "sf.hbar = 0.5\n", "eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":10})\n", "prog = sf.Program(2)\n", "\n", "with prog.context as q:\n", " \n", " Fock(2) | q[0]\n", "\n", "state = eng.run(prog, run_options={\"eval\": False}).state\n", "wigner = a = state.wigner(0, [i/10 for i in range(-40, 40)], [i/10 for i in range(-40, 40)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's compose our integrating method. Notice how when we sample Wigner function values, we only get points ranging from $-4$ to $4$. The peak of our distribution should be around $1$, so outisde of these bounds (especially $-4$), the probability of any measurement will be practically $0$, thus we approximate $\\pm \\infty$ to $\\pm 4$. We have to integrate across each set of points with the same value of $x$, as this will give us the **total probability** of measuring that specific value of $x$, for any arbitrary value of $p$. Thus, we have:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "x = [i/10 for i in range(-40, 40)]\n", "\n", "def wigner_transform(x, wigner):\n", "\n", " y = []\n", "\n", " for i in range(0, len(x)):\n", " res = simps([wigner[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", " return y\n", "\n", "data = wigner_transform(x, wigner)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we have to plot our data as a quadrature graph:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEGCAYAAABo25JHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3deXxb53Xg/d8BSAAkuK9aSFuyJFuWbdmxFTtxLDdrazepPc0ytZvMW6fJ5H1n6mkyad8mmXTyNulMl7RNmzZu3zhpmjSb46bNxG2cyerEtrJY3ldZouSFlCiuIEGCBEAAz/xxcUmYokiAuBf3Ajjfz0cWsRA8Mkmc+zznec4jxhiUUkrVr4DXASillPKWJgKllKpzmgiUUqrOaSJQSqk6p4lAKaXqXIPXAZSqp6fH7Nixw+swlFKqqjz00EOTxpjetR6rukSwY8cOHnzwQa/DUEqpqiIiL5ztMZ0aUkqpOqeJQCml6pwmAqWUqnOaCJRSqs5pIlBKqTqniUAppeqcJgKllKpzmghUVXjw+WkeeG7a6zBqyrceH+WFqYTXYSgf0ESgfO/0bJJ3/sNh3n/no+j5Gc6YTqS59asP839/8SHSmZzX4SiPaSJQvmaM4ff/15PMpTKMxBZ5fmrB65Bqwv1DkxgDR07P8Xc/Ou51OMpjmgiUr/3r46N8/5kx3n7VOQDcd2zC44hqw31HJ2hvauSN+7fyqXuOcXRszuuQlIc0ESjfmk6k+YO7nuLSwQ4+duPFDHY1ce/RSa/DqnrGGO47Nsk1u3v42A0X0RJu4Pe+/jjZnE671StNBMq3PvqvTzGXXOLjb9lPMCAc3NPLT49PspTVOe1yDI3Pczqe5OCeHrpbwvzBDRfx6PAM/3DoOa9DUx7RRKB86Z4j43zz0VP81mt2c8GWVgCu3dNDIp3lkRdnPI6uut17zBpVXbOnB4AbLt3G6/b28efffZbhaa3B1CNXE4GIXCciz4rIkIh8cI3HbxGRCRF5NP/n3W7Go6rHPz88Ql9rmP/86t3L971yVw/BgHDvUa0TlOPeoxOc1xtloLMZABHhozdeRHIpx91PjHocnfKCa4lARILAbcD1wD7gZhHZt8ZTv2aMuSz/57NuxaOqy5HTc1w62EGoYeVHtL2pkcsGO7RgXIbkUpafPzfFtXteej7JQGczW9oiPHtai8b1yM0RwZXAkDHmhDEmDdwB3Oji11M1IrmU5cTEPBfmp4QKHdzTw+MnZ4kl0h5EVv0eeiFGcinHtef3nPHY3q2tPKOJoC65mQi2A8MFt0fy9632FhF5XES+LiKDa72QiLxHRB4UkQcnJvRqsNYNjc+TM3DBlrYzHrv2/F6MgUPHdfXQZtx7bILGoHDVzu4zHtu7pY2h8Tktxtchr4vF/wrsMMbsB74HfGGtJxljbjfGHDDGHOjtXfPITVVDnhmNA9YV6mr7t7fTFmngPl1Guin3HZ3kinM7iYbPPKX2wq2tLGUNJya07US9cTMRnAQKr/AH8vctM8ZMGWNS+ZufBa5wMR5VJY6cniPcEGBHd/SMxxqCAV61u4d7j01ou4kSTcyleHo0zsE9a19M7c2PwI6cjlcyLOUDbiaCw8AeEdkpIiHgJuCuwieIyNaCmzcAz7gYj6oSR07HuWBLK8GArPn4wT29jM4mOT4xX+HIqtv9Q9a06i+cv3YiOK83SmNQeGZU6wT1xrVEYIzJALcC38F6g7/TGPOUiHxMRG7IP+23ReQpEXkM+G3gFrfiUdXjyOgce9coFNsO5te/6y7j0tx3dJKuaIh9W8+svQA0BgPs7mvVEUEdOnOi0EHGmLuBu1fd95GCjz8EfMjNGFR1mZhLMZVIL09TrGWwq5ntHU08Mqwby0rxyPAMV+7oInCWkRbAhVta+emJqQpGpfzA62KxUi9hX42uVSguNNjVxKmZxUqEVBOMMZyaWWSwq2nd5+3d2srobJKZBV2eW080EShfOZKfn15vRACwrb2JUU0ERZtOpEllcmxt3yARLBeMtU5QTzQRKF955nSc/rYwXdHQus/b2hFhbC6lHTOLNDqbBGBbR2Td59kjsSOjWieoJ5oIlK9YheL1RwMAW9ubyOYM43PJCkRV/exptI1GBL0tYbqjIR0R1BlNBMo3lrI5hsbnN6wPwMqV7akZTQTFsEcEWzcYEYiItpqoQ5oIlG88N5kgnc1xYZEjAoDRWa0TFOPU7CKNQaEnGt7wuXu3tHH09JxOu9URTQTKN9ZrLbHaNjsR6IigKKMzSba0R9ZdOmrbu6WVxaUsL+rZBHVDE4HyjSOn52gMCuf1tGz43LamBppDQU7piKAoo7OLG9YHbBfmN5xpwbh+aCJQvnFkNM6u3paXnEFwNiLCto4mHREU6dRMku0dxSWC3X0tBAStE9QRTQTKN46cnlu+Gi3G1vaI1giKkM0ZxuJJtravXyi2RRqDnNfboiOCOqKJQPnCzEKa0dnkuj2GVtvW3sSpWR0RbGRyPkUmZ9ha5IgArDqBLiGtH5oIlC/Ybzp7SxkRdESYnE+RzuhBKuux9xBsK3JEAFad4MXpBeZTGbfCUj6iiUD5gn1WbqkjAmNgLK6jgvXYey2KLRYDXNBvfR+OjumooB5oIlC+8OL0Ak2NQfpaN17nbtu6vKlM6wTrsesoG7WXKLSjpxmAYV1CWhc0EShfGIktMNDZhMjG69xtK5vKdESwnlMzSZoag7Q3NRb9OQOdViIYiWmSrQeaCJQvDE8vMtBZ/NQFFLSZ0JVD6xqdXWRrR6SkJBtpDNLTEtYRQZ3QRKB8YSS2wGBXc0mf0xxqoL2pUfcSbODUbHJ5J3YpBruadERQJzQRKM/NLi4RT2ZKHhGA7iUoxujMYtF7CAoNdDYzHNMRQT3QRKA8N5J/sxnsLG1EALCto0k7kK4jnckxMZ8qaQ+BbbDTOgVOm8/VPk0EynPD09YV/cAmEsHW9ojWCNYxFk9iTGl7CGwDnc0sZY0uz60DmgiU55ZHBBucp7uWbR1NzCwssZjOOh1WTVg5h6D0/7f2VJ3WCWqfJgLluZHYIi3hhpKWN9rsuW8dFaxteQ/BJkYEdvFeVw7VPk0EynOb2UNg26rnEqxreVfxJkYE2zoiiOiIoB5oIlCes/YQlF4fAJZbK+uIYG2js4u0RRpoCTeU/LnhhiD9rRFdOVQHNBEoTxlj8nsISr9iBehvt1pS6IhgbadmFtm2idGAbaCzabmGo2qXJgLlqdjCEol0dtMjgnCDtQNW9xKs7dRM8ecQrGWwq3l5VZeqXZoIlKdW9hBs/qp1W0dEzyU4C6u9RHkjgtPxJJmstvquZZoIlKfK2UNg29oeYVQ7kJ5hMZ0ltrC0qRVDtsHOZrI5o439apwmAuUpe0QwsMkaAVgrh/SN6kz2dFkp5xCsZu8l0IJxbXM1EYjIdSLyrIgMicgH13neW0TEiMgBN+NR/jMcW6C9qZG2SOl7CGzbOiLMpzLEk0sORlb9VjaTlVcjABjROkFNcy0RiEgQuA24HtgH3Cwi+9Z4XivwXuDnbsWi/GsktrjpFUM23UuwtpUjKjf//3dLe4SAoCuHapybI4IrgSFjzAljTBq4A7hxjef9IfCngP4W16Hh6QUGOjZfHwB/nUsQS6T52x8N+aK4ao8ItpRRI2gMBtja3sSwbiqraW4mgu3AcMHtkfx9y0TkcmDQGPOt9V5IRN4jIg+KyIMTExPOR6o8Ye0hqK0RwVcPv8jH//ez/OzEtNehMDq7SHc0RKQxWNbr6F6C2udZsVhEAsAngN/Z6LnGmNuNMQeMMQd6e3vdD05VxMR8ilQmV9aKIYC+1jAi/jjE/idDUwAcOj7pcSQwFk/R37b50YBN9xLUPjcTwUlgsOD2QP4+WytwMfAjEXkeeAVwlxaM64fdw6bcEUFDMEB7UyPTibQTYW1acinLA89bI4FDQ94ngqlEmu6WUNmvM9DZxNhcklRGO7zWKjcTwWFgj4jsFJEQcBNwl/2gMWbWGNNjjNlhjNkB/Ay4wRjzoIsxKR+xu1qWOyIA6IqGPE8ED70QI53JcelgB0+cnGVmwdt4phMpuqLlJ4LBzmaMQQ8AqmGuJQJjTAa4FfgO8AxwpzHmKRH5mIjc4NbXVdXDHhFs5ojK1bp9kAgODU3SEBDe/4bzMQZ+enzK03hiiSVHEsHKuQRaJ6hVpbckLIEx5m7g7lX3feQsz321m7Eo/xmJLdAdDdEcKv/HsLM5xAtT3r5RHRqa5LLBDq7e1U00FOTQ8Umuv2SrJ7GkMlnmUxm6mh0YESyfS6B1glqlO4uVZ0Ziiwx0lT8tBNDdEmLKwxHB7MISj5+c5VW7e2gMBnjFed0cGvJuRGCPjrocqBH0t0VoDIqOCGqYJgLlmeHpBUemhcCqEcQW0hjjzUHrPz0xhTFwzZ4eAF61u4fnJhOevXnaiaDbgamhYEDY1qF7CWqZJgLliVzOcHJmkUEHCsVgTQ1lc4b4YsaR1yvVoaFJmkNBLh3oAKxEACvLSSvNTgSdDkwNge4lqHWaCJQnxuaSLGWNYyMCe5nkVCLlyOuV6tDQJFft7CLUYP1Knd/fQk9L2LP9BMsjAgemhsBaOaQ1gtqliUB5YmUPgTMjgq6odVJZzIMlm6dmFjkxmVgeBQCICNfs7ubQ0KQn01XLNYL8/5dyDXQ2MTmfYjGtewlqkSYC5YmT+USwvYxDUwrZq2Om5iufCOzNY3Z9wPaq3T1Mzqd5dmyu4jFNJ9IEBNqbNt/VtZC918MP/ZyU8zQRKE+cnHE4EeSnQLzYS3BoaJKelhAX9Le+5H57hHD/scpPD00l0nQ0hwgGxJHXs889PqUHANUkTQTKE6dmFumKhmgKldcQzWaPCKYrPDVkjOHQ8Smu3tWDyEvfdLd1NHFeT5SfeLCxLJZIO7KZzLbc4VUTQU3SRKA8cWpmcfnNxQlNoSBNjUGmKzw1dHwiwcRcilft7l7z8at3d/OzE1PkcpWtE0w5nAj626xzCU7qEtKapIlAeeLkzGJZB6asxYt+Q/YRjrv7Wtd8fE9fKwvpbMWL2NOJtCO7im2NwQD9bRFOar+hmqSJQFWcMYaTscXleWeneLG7eDzf+rq/be3VOfb9Y/HKLmuNJdKO7CoutK2jSaeGapQmAlVx8WSGRDrrWKHY1tkcqviVt/0G39u6diLoy58HMDZXuSvpXM4QW0g7squ40LaOJl01VKM0EaiKWz5L1+kRQTRU8eWjY/EkXdEQ4Ya1i972wTDjFTw0Z2ZxiZxxblexbXtHE6MzyYrXO5T7NBGoiltJBM4Vi8GbGsFYPEXfWUYDAL0tlZ8acnpXsW17R4R0NsekR7u3lXs0EaiKO+XwHgJbZzTE4lK2ortfx+eS6x4HGWoI0B0NVfQYzZVdxc5PDYEeUFOLNBGoijs5kyQUDNDT4kz7A5s9J17JvQRj8eRZC8W2vrZIhUcE1tdyLxFonaDWaCJQFXdqZpGtHRECDu16tdlvfJXaS5DNGSbmNj4gvr8tzHgFi8XTiSXAvUSgewlqjyYCVXGnXNhDAAWJoEIjgqn5FDmzsjLobPpbIxWeGnJnRNAWaaAl3LDcHkTVDk0EquKsXcUuJoIKFTPt6Z7+dYrFYI0IJuZSZCu02mYqkaYl3HDWlUybJSJs64jo1FAN0kSgKmopm+N0PMl2h1cMAXTnWy5Xagnp2PJmsvX/Lb1tEXLGGkFUQiyRpjPqTNfR1XQvQW3SRKAqaiyeJGec30MA0NbUQDAgFdtUZm8S27BG0FrZJaRWnyFnC/G27R1NumqoBmkiUBVlv4m4kQhEhM7myu0lGIunEIGeDdbr24miUnWC6YTzu4pt2zqamE6k9YCaGlNUIhCRfxGRN4qIJg5VFrd2Fdsqubt4PJ6kpyVMQ3D9X4v+CreZiCXSju8qttl7P3R6qLYU+8b+t8CvA8dE5E9E5AIXY1I17KRLu4ptXdHK9RsqZg8BWCMGkcpMDRljmEqkHd9VbNMlpLWpqERgjPm+MebtwOXA88D3ReQnIvJOEXGnKqVq0qmZRTqbG2kONbjy+l3RynUgHYun6G/dOKE15DfPVaLf0EI6SyqTc3zpqE0PqKlNRU/1iEg3cAvwbuAR4JNYieF7rkSmatKpmUW2d7ozLQSV7Tc0PpfccA+Brb8tXJEagVvtJWz2ATWaCGpLUZdlIvIN4ALgi8CvGGNG8w99TUQedCs4VXtOzSQ5t7vZtdfvioaYWVgik81tOHdfjqVsjsn5dFFTQ2BtKhudrWAicKlGoAfU1KZif1M+Y4zZZ4z5YzsJiEgYwBhzwLXoVM1xazOZzb4Snllccu1rAEzM5TeTFTki6GuLVKTNxHIicKlGAHpATS0qNhH8jzXu++lGnyQi14nIsyIyJCIfXOPx/0dEnhCRR0XkfhHZV2Q8qgrFk0vMpTKOdx0ttLK72N3pofF8IlivBXWh/rYwk/NplrI5N8NaaUHt0tQQ5PcS6KqhmrJuIhCRLSJyBdAkIi8Tkcvzf14NrDu+F5EgcBtwPbAPuHmNN/qvGGMuMcZcBnwc+MRm/yHK/+yVJm6OCOw3QLeXkBa7q9hmP88eSbjFTgSdLiaCbXpATc3ZqEbwS1gF4gFe+iY9B/y3DT73SmDIGHMCQETuAG4EnrafYIyJFzw/CuhPVg1z60CaQvYboNtLSO0VQH3F1giWzy5OupoIpxJpGoNCa9idVVnw0gNq+opYNaX8b92fFmPMF4AviMhbjDH/XOJrbweGC26PAFetfpKI/BbwfiAEvLbEr6GqiFsH0hRaHhG4PDU0Fk8RDMhyf6ON2G+Ybu8liCXSdEVDiDjb4rtQ4V4CTQS1Yd1EICLvMMZ8CdghIu9f/bgxpuypHGPMbcBtIvLrwO8Dv7FGHO8B3gNwzjnnlPsllUdOziRpDIrjB9IU6qzQmQRj8SS9LWGCRZ6psHx2scsF4ykXdxXbCk8qe5n+OtaEjYrF0fzfLUDrGn/WcxIYLLg9kL/vbO4A/t1aDxhjbjfGHDDGHOjt7d3gyyq/OjWzyNb2JscPpCnUGAzQGmlwfWpobC5V9NJRsEYqwYC4vpdgOpFybVexTU8qqz0bTQ19Ov/3Rzfx2oeBPSKyEysB3ITVpmKZiOwxxhzL33wjcAxVs6ylo+5PJXRXYHfxeDzJYFfx+yECAaGvNez+1NDCEts73dunAXpATS3aaGror9d73Bjz2+s8lhGRW4HvAEHgc8aYp0TkY8CDxpi7gFtF5PXAEhBjjWkhVTtOzSzyyl09rn8da3exu2+4Y/EkB3Z0lvQ51tnFLk8NzadcXToKekBNLdpoacFD5by4MeZu4O5V932k4OP3lvP6qnpkXDyQZrWuaMjVna+pTJbYwlJRfYYK9beGeWFqwaWorN3O8WTG9RoB6F6CWlPMqiGlynY6fyDNVhdXDNm6oiGeODnr2uuPx0vbVWzrawvzwPPTboQErCyZdXNXsW1bRxOPDs+4/nVUZWw0NfRXxpj3ici/ssYaf2PMDa5FpmrKSH4z2YCLDedsXdEw04k0xhhXllHaK3+K3UNg62+NMLOwRHIpS6TR2fOEoTK7im3bO5uILSyRSGWIurhnQVXGRt/BL+b//nO3A1G1zU4Egy4XMgG6oo0sZQ1zqQxtEee7pI9tckRQuLu4lEJzsewls5WYGrK/jyOxRS7YstECQuV36y4fNcY8lP/7x1i9hWLANPDT/H1KFWV4egER2FqRGoF1pR5zaeVQqe0lbH0Fu4vdMJ2fGnJ7+SisjOyGp92reajKKfaoyjcCx4G/Bj4FDInI9W4GpmrLcGyBLW0Rwg3OT4ms5vbu4rF4isag0Nlc2mhj5exid1Y0uX0WQSF7RDMc00RQC4qd3PsL4DXGmCEAEdkFfAv4tluBqdoyElusyLQQuL+7eDyepK81UnL9we1D7O1E0NHk/qGB3dEQTY3B5Sk/Vd2KbUM9ZyeBvBNYjeeUKsrI9EJFCsWwMiJwa3fx2FxxZxWv1tncSGNQXDvEPpZI09Hc6OqBPDYRYaCzSaeGasRGq4benP/wQRG5G7gTa/XQ27B2Diu1oXTG2kMw4EKBdC1udyAdi6fY09dS8ueJCH2tkeXlp06bXlhy7WSytQx2NeuIoEZsNDX0KwUfjwG/kP94AqjM5Z2qeqOzi+RMZZaOAkRDQRqDwnTCnVPKxuJJrtm9uR3Sbp5dbI8IKmWgs4nDLu6LUJWz0Yayd1YqEFW7hqcrt3QUrCvvzuaQK6uGFtNZ5pIZeos8mWy1/rYIR8fcmVWdTqQr0svJNtjZzFwyw+zCEu0VTEDKecUeXh8B3gVcBCz/pBljftOluFQNGcmvLBnsqtwgsisaWl5O6aTJeWtap3eTrbS7W0JMnXBnyiq2kOaibW2uvPZalpeQxhZob26v2NdVziu2qvRFYAvWiWU/xmoprcViVZTh2ALBgLClxHX35ehsDjHjQiIod4lmVzTMzMISGRfOLo4tpCuydNRmLyEd0SWkVa/YRLDbGPPfgUS+/9AbWeO0MaXWMhKz2k9XYjWLzepA6mIi2OSmrZUVTc7WLxbTWZJLOVfPKl7NHhFowbj6Ffubaf/UzojIxUA70OdOSKrWDE8vMNBRmfqAraO50fE3W1jZpNZT5BGVq9m7fp1OUvY0WKmb3MrR3tRIa7hBl5DWgGITwe0i0gn8d+AurAPo/9S1qFRNGYktVrQ+ANaIYGYhTS53Rq/EstjnHGx2RNC1vOvZ2SWkdmG8En2GbCLCgC4hrQlFFYuNMZ/Nf/hj4Dz3wlG1JrmUZXwuVbEVQ7bO5hA5A/HkEh0OvjlOzacJNQSIhjbXKsM+7H7K4V3Pyy2oKzg1BNb00AtTiYp+TeW8YnsNdYvI34jIwyLykIj8lYh0ux2cqn7L7ac9GBGA81MwU4k03dHQpttbuxWX/XqVrBGAtYR0eHoRY5wdeanKKnZq6A5gHHgL8FZgEviaW0Gp2rG8dLTCIwJ7Y5XTu4unE+WtzLHn8J1uiOfF1BBYI4LFpawrhXlVOcUmgq3GmD80xjyX//M/gH43A1O1YXj5QJrKJoKVK29nC8ZTZSaChmCAjuZGx89Unl5YQsQq4FbSShdSrRNUs2ITwXdF5CYRCeT//HusQ+mVWtdIbIFQQ4C+Te7E3Sz7ytjp3cXTifIPh3djaWsskaajqZFgwPkT2dazsoRUVw5Vs42azs1hNZkT4H3Al/IPBYB54HddjU5VvZHpRQY6mghU+A2qy6XGc9Pzabo3uavY1hMNu1IsrnR9AApGBNM6IqhmG/Ua0jPoVFmGYwtsr1CzuULNoSChYMDRNhPJpSyJdLbslTld0RBDE/MORWWJLaQrXh8AaAk30NncqAfUVLmiT50WkRuAa/M3f2SM+Td3QlK1ZCS2yMXbK9+HRkTojDY6OjU05dDh8F0tIaafd3rKaontHd40BB7o1L0E1a7Y5aN/ArwXayPZ08B7ReSP3QxMVb9EKsN0Il2x9tOrdTaHHC0W2yeelTsi6I6GiC2kyTq42S2WSNMV9aYD6GBXEyO6u7iqFVss/mXgDcaYzxljPgdch9VvSKmzsq8SK7101GbvLnaKvRu43MPhu6IhjMGx2IwxntUIID8imFl0fBe3qpxSuoB1FHysPWfVhuweNIMVOplstU6HW1GvdB4tr1js9KayxaUsqUyuoqeTFRrsbCKdyTEx787Ja8p9xdYI/hh4RETuwVpBdC3wQdeiUjXBLiB6NzXkbI3AfuMud0TQk191NJVIs6fsqAp2FXuUCOw9IsPTC/RXsNW4cs6GiUCsvfT3A68AXp6/+wPGmNNuBqaq30hskabGYNnF1c3qag4xs7hENmccWV8/lUjTGBRaw0WvsVg7LodHBLF8HcSrqSG7oeBIbJEDOzwJQZVpw59oY4wRkbuNMZdgdR5VqijD0wsMdDZtui9PuTrzc/Gzi0uONGObmk/RVUafIZudGKccmkqZXm44502xeHvHyohAVadiawQPi8jLN37aS4nIdSLyrIgMicgZU0ki8n4ReVpEHheRH4jIuaV+DeVfVvtpb+oD4PymMqvPUPk7pDuXW1E7E9fMgrdTQ02hID0tYV1CWsWKTQRXAT8TkeP5N+0nROTx9T5BRILAbcD1wD7gZhHZt+ppjwAHjDH7ga8DHy8tfOVXxhiGYwsMelQfAJbbTztVJ7A7j5arMRigLdLg2NSQ1zUCsKaHdFNZ9Sp2svOXNvHaVwJDxpgTACJyB3Aj1j4EAIwx9xQ8/2fAOzbxdZQPTSfSzCUznNMd9SwGexWNk2+4Ti2F7W4JOzYiiCXSBATaKtxwrtC5Xc088Ny0Z19flWfdEYGIRETkfcD/i7V34KQx5gX7zwavvR0YLrg9kr/vbN4FfPsscbxHRB4UkQcnJiY2+LLKD05MWoeVnNfrXSLojDrbinp63rnD4buioeUNauWaXkjT0RyqeMO5Quf1tnBqNslCOuNZDGrzNpoa+gJwAHgCa4rnL9wIQkTekf86f7bW48aY240xB4wxB3p7e90IQTns+LjVS2d3b4tnMazUCMrfXZzKZJlLZegpc+mordvBDqSxhaWKnlW8ll357/OJCT2trBptNDW0L79aCBH5e+CBEl77JDBYcHsgf99LiMjrgQ8Dv2CM0R0pNeLEZIJQQ4BtHvW/AWhqDBJqCDhSI7CXaDpRLAZrL8LDL8448lqxhDcN5wrZI78TkwlPekup8mw0Ili+lDLGlDrmOwzsEZGdIhICbmLV8lMReRnwaeAGY8x4ia+vfOzExDzn9UQ9na4QEbqanbnynswv9XRyaii2kHakLcN0wrv2EradPVFErO+7qj4bJYJLRSSe/zMH7Lc/FpH4ep+YTxy3Yh1g8wxwpzHmKRH5WL6TKVhTQS3AP4nIoyKi+xRqxPGJhKf1AVtn/g23XE7tKrZ1RcNkc4bZxfKnrWILac/aS9gijUG2dzRxXKeGqtJG5xEEy3lxY8zdwN2r7vtIwcevL+f1lT+lMzlenF7gTfu3eh0KXdFGR0YEK32GnKsRgLUktZyreWMMscSS5yMCsOoEOiKoTqU0nVOqKC9OJ8jmjD9GBM0hZhwoFjt1FoHNqTYTC+ks6XZj604AABpTSURBVGzOs13Fhc7rjXJiIqFdSKuQJgLlOHt6YJeHK4Zsnc3OdCCdTqQIBoS2iDNvuCuJoLz1EXYi6fB4agis7/fiUpbT8aTXoagSaSJQjjuenx7Y2eODEUE0xOziEplsrqzXsdpLhBw7e7mwA2k57PqH1zUCWFk5dFynh6qOJgLluBMTCfpaw7Q6dPVcjq7mxuXGc+WYnHemvYTN3uxW7iH2y+0lfFAj2K17CaqWJgLluOMT876YFoKVN8hyN5XZIwKnhBuCtIbL7zdk1z+cjG2zelvDtIQbdERQhTQRKEcZYzjhk6WjsNKIrdwlpE4nArAOsS93amil4Zz3oy8RYVe+YKyqiyYC5aipRJrZxSXfjAicWp0zNZ9y/ICdrmio7GJxbCHfcM4H03Bg9RzSEUH10USgHGVfDfpmRBAtvxX1UjZHPJlxrL2ErTsacqRG0NnsXBG7XLt6o4xq87mqo4lAOcreUOSbEYHdirqMqaGYw7uKbd3RcNkjldiC9+0lCp2nBeOqpIlAOer4xDzhhgDbPWw2V6gpFCTcEChrU5nTm8lsXS1WHyRjNr8BK5bwvvNoIfsCQKeHqosmAuWoExMJdvZEfTNVAfZc/OavvO3pG6eLxd3REJmcIb64+WmU2IL3nUcLndvdnG8+pyOCaqKJQDnKT0tHbZ3NobJqBFP5gq7TU0Ndy/2GNl8wdmM1UzkijUEGO5t1RFBlNBEox6QyWYZji74pFNu6ouW1mVhpOOdssbjcFU3GGN/VCGCl55CqHpoIlGNenFogmzP+GxFEy2s8N50/E7jD4TOBu6PltZlIpLMsZY0v2ksU2tXbwonJeW0+V0U0ESjHHPfZ0lFbZ3N5rainXFqi2dVS3oggttxwzj/FYrC+/8mlHKPafK5qaCJQjrHnhc/z24igubzGc9PzacfrA7CyCmmzicDpMxKcsrxyaFzrBNVCE4FyzImJBP1tVr8ZP7HfKGc22XjOrYJspDFINBTc9KYyu+7hxxoB6LGV1UQTgXKMH1cMwcob5WavvCcTqeX5fKdZ/YY2t2oottxnyF+JoLclTGukQY+trCKaCJQjsjnDs6fnOL+/1etQztCb7/0/Obe5N9wpl6aGwCoYT85vLq6J/L+nt9WdJLVZIsIF/a08M7rusebKRzQRKEcMjc+zuJRl/0C716Gcob/NeqMcmyu9eJlcyjK7uER/W8TpsAArtvH45hLBWDxFS7jBd1NxAJcMtPPkqdmyDwRSlaGJQDni8ZEZAPYPdHgcyZn68m/iY5t4wx3Lr3xxKxFsaYssf41Sjc0l6Wvz12jAdulAB8mlHENaJ6gKmgiUI544OUs0FOQ8HxxPuZp91byZN1w7efS79Ibb1xYhnsywmM6W/Lnj8ST9re4kqHJdkh8ZPj4y63EkqhiaCJQjHhuZ5eLt7b7qMVSob5NTMG6PCPqXRyubS1JuJahy7eyO0hpuWB4pKn/TRKDKls7keGY0zqWD/psWsvW3bm4KphJTQwCnS4zNGMNYPOlaXOUKBISLt7fzhI4IqoImAlW2o2NzpDM5Ltnuv0Kxrb8tvKli8Vg8SaQxQFvEnYLsciG7xEQQX8yQyuSW6x9+tH+gnWdGrZ8N5W+aCFTZ7HlgP64YsvW3RRiLp0ru/X86nqK/LYKIO1Ne/e3WG3mp01Z2UvPr1BBYdYJ0Nsezp+e8DkVtQBOBKtsTJ2dob2rknK5mr0M5q762COlMjtkSdxe7Pf3SGm6gqTFY8tSQ21NWTrg0v4Ls8ZNaJ/A7TQSqbI+PzLJ/oN21q2YnrEzBlHblPe5yIhARa9qq5ESQX83k01VDAAOdTXQ0N2qdoApoIlBlSS5lefb0nK/rA7C51TnGGE7Hk/S7vHO3vy1S+tRQ/t/h130EYCW5S7a385gmAt9zNRGIyHUi8qyIDInIB9d4/FoReVhEMiLyVjdjUe54ZjROJmd8uZGskH3lXEoiiCczJJdybGl396q7vy1S8tTQeDxJW6SBSGPQpaiccelAB0fH5kgulb5PQlWOa4lARILAbcD1wD7gZhHZt+ppLwK3AF9xKw7lridO+r9QDCtXzuMl9BsaX77qdjsRWFNDpRSyx/JFbL+7ZKCdbM7wtPYd8jU3RwRXAkPGmBPGmDRwB3Bj4ROMMc8bYx4HdH1ZlXpseJaelhBbXb5qLlekMUh7U2NJIwL7Kn2L64kgQqrEQvbYnH/3EBSyLxAeH9aCsZ+5mQi2A8MFt0fy95VMRN4jIg+KyIMTExOOBKec8cTJGfYPdPi6UGwrtSjrdnsJW/8meiGNx1O+rg/YtrRF6G0N8/hJrRP4WVUUi40xtxtjDhhjDvT29nodjspLpDIMjc/7vlBss/cSFKtSSzTtGkSxSSqXM4xXyYhARNivO4x9z81EcBIYLLg9kL9P1YinTsXJGf/XB2x9rZHlef9ijMWTtDc1ul6QtQvZxRaMYwtplrLG9dVMTrlkoJ2hiXnmUxmvQ1Fn4WYiOAzsEZGdIhICbgLucvHrqQqzG4pdUiWJoL8tzPhcilyuuKKstZnM/Tfb5UJ2kYlgZcrK/yMCsFYOGQNP6fSQb7mWCIwxGeBW4DvAM8CdxpinRORjInIDgIi8XERGgLcBnxaRp9yKRznvsZFZtrZH6PPxpqZC/W0RMjmzfNbvRk5XaGVOpDFIR3Nj0dNWdnsJP/cZKnRxfurwMe1E6luuHm1kjLkbuHvVfR8p+Pgw1pSRqjLZnOHQ0CTX7unxOpSiFTZ462nZ+Ep/PJ5kT19l/n39rcXvJRiP+7/PUKHe1jC7eqPcd2yS91y7y+tw1Bqqolis/OexkRmmE2les7fP61CKZl9BF7OLN5szjM9Vrt9/f3vx9Qt75OC3s4rX89q9ffz8xDQJrRP4kiYCtSn3HBknIPAL51fPKq5S2kxMJVJkc6Zi8/D9reHip4biSbqiIcIN/t5VXOg1e/tIZ3PcPzTpdShqDZoI1Kb88Mg4V5zbSUdzyOtQitbbUnzjufEKF2T72yJMzFvJZyNj8RR9VTQaAHj5ji5aww3cc2Tc61DUGjQRqJKNxZM8dSpeVdNCAKGGAN3RUFEH1JyerWyb5/72CNmcYWq+iCRVJXsICjUGAxw8v4d7nh0v+UwI5T5NBKpk9lXda6ssEYBVJyhmLt5OFm63l7DZewKKKRhXalmr015zQR9j8RRPndK+Q36jiUCV7IdHxtnWHuGC/lavQymZ1WZi46vusdkkItDTUpmpr5XdxevHls0ZJuaqo+Hcaq++wLpw0Okh/9FEoEqSymS5f2iS1+ztq4r+QqsVe4j9WDxFT0uYhmBlfkWKLWRPzafImerZQ1CotzXMpQPt/PBZTQR+o4lAleSB56ZZSGercloIrBHB5HyKTHb9hrdjc8mKTQsBdEdDBGTjRLByMln1TQ2BtXro0eGZomohqnI0EaiS/PDIOOGGAFfvqp6NZIX62iLkDEwl1t9dfHq2svPwDcEAva0bd0ethrOK1/PavX0YAz8+ql2E/UQTgSrJPUfGeeWubppC1bOGvVCxUzDjc6mKT78U0x3VLmJXayK4eFs7PS1hfqh1Al/RRKCKdmJinuenFnhdlU4LQXGH2KcyWaYT6YpODYGdCDYYEVS4iO20QEB4zQW93Ht0YsPpOVU5mghU0eyruGrbP1ComBHBeIUOpFmtmINzKl3EdsNr9/YRT2Y4/HzM61BUXvX+NKmKyuUMX/n5i1w62MFAZ7PX4WyaXZRdby/BuEfdPftbI8QWlkhlzn7Qu3VEZXUWim3Xnt9La7iBL//8Ba9DUXmaCFRRfnBknBOTCd59zU6vQylLQzBAT8v6ewlOz1qPVXxqqH3jpnhj8dTyQTbVKhpu4OarzuHbT55meHrB63AUmghUkT5z7wm2dzRx/cVbvA6lbP1tkXXbTHi1Mqe4aatkVe4hWO2Wq3cgwD8cet7rUBSaCFQRHh2e4YHnp/nNa3ZW9dy0baPdxWPxJKFggM7mxgpGtVKTOFubiXQmx1QiXfVTQwDbOpp40/6tfO3wi8wuLnkdTt2r/t9q5brP3HeC1kgDv/bywY2fXAU26jc0Fk/S1xau+M7pLW3rt5mYmK+uIyo38u6D55FIZ7njgRe9DqXuaSJQ6xqeXuDbT4zy61eeQ0vY1QPtKqa/NcJUIs1ieu2i7KkZb7p7tjc1Em4IcDK2uObjp2as+2thRADWEZZX7+rmHw49TzqjS0m9pIlAretzh54jIMItr9rhdSiOuXTQOkP38PPTZzyWXMry6MgMlw50VDosRIRLBzrWjAus9h4A+z2IzS3/8drzOB1P8q0nTnkdSl3TRKDOanZxiTsPD/Mrl25ja3uT1+E45qqd3YSCAe47dmabgweemyadyXHwfG9aaBzc08OTp2aZXqMFxr1HJ9i3ta2o85arxavP72VPXwufufc5PafAQ5oI1Fn95feOkkhneffB6l4yulpTKMiBHZ3cd+zMYxPvH5okFAxw1c4uDyKDa/b0YAwcWnWkYyKV4eEXYxzcU509ns5GRPiPB8/j6dE433jkpNfh1C1NBGpN33t6jM//5HluuXoHF21r9zocxx3c08uR03PLm8ds9x6d4IpzO2kOeVMP2T/QQVuk4YzRygPPTbOUNRzcUz1nRBfrzZdv58odXfz+/3qSExPzXodTlzQRqDOcnFnkd//pMS7e3saHfnmv1+G4wr6yLrzyHp9LcuT0HNd4eNUdDAiv2t3D/ccmXzJVcu+xCcINAQ7s6PQsNrc0BAN88ubLCDcE+K2vPEJy6ew7q5U7NBGol8hkc7z3q4+Qyeb4m5svJ9xQnV1GN7Jvaxtd0dBLpofspHCtx1fdB/f0cmo2yfGJxPJ99x+b5MqdXUQaa/P7sbW9iT9/26U8Mxrnj+5+xutw6o4mAvUSf/n9ozz4Qow/evMl7OyJeh2OawJrXHnfd2ySzuZGLtrW5mls9mjl/vz00OjsIsfG52uuPrDa6y7s513X7OQff/oC335i1Otw6oomAgWAMYbP3f8cf/uj4/zagUFuvGy71yG57uDuHsbnUhwdm8cYw/3HJnnV7h4CAW+P4BzsamZHd/PyaOX+/N/X7K69+sBqH7huL/sH2vm9rz+uZxtXkCYCRSKV4b989RE+9m9P8/oL+/mDGy7yOqSKsGsB9x2b4OjYPONzKd9cdV+zp4efnZginclx37FJelrC7N3S6nVYrgs1BPi7d1zBQFczv/mFw3zie0fJ5nRZqds0EdS5ofF5brztEHc/McoHrtvLp99xRdWePlaqbR1N7OqNct+xyeVVOtf4ZFXOwT29JNJZHn4xxqGhSa7Z3e35SKVStnc08S//6Wre/LIB/voHx3jn5w8T2+BoUVWe2ugZoEr2zGicf/zpC3zjkRGioQa+9K6ruHq3P66GK+ngnl7uOPwiqUyW83qjbO/wx8a5V+7qJhgQbr/3BFOJtG8SVKU0hYL8+dv2c/m5HXz0rqd5/Sd+zM1XnsPbX3FOTW1u9AtXE4GIXAd8EggCnzXG/Mmqx8PAPwJXAFPArxljnnczpnpljGF4epHDz0/ztcPDPPD8NOGGADdeto3/+obz6/aX6+CeHj7/k+f52Ylpbrl6h9fhLGuLNHLZYMfyqXB+mbKqJBHh7Vedy/7tHXzyB8e47UdD/N2Pj/OL+/r5dy/bzuXndNLbWju7rL3kWiIQkSBwG/AGYAQ4LCJ3GWOeLnjau4CYMWa3iNwE/Cnwa27FVKuMMaQyOeZTGRZSWWILaU7Hk4zFk5yetdbGPzo8s9y24JyuZj78yxfytgMDdDRX59m3TrnqvG4aAkImZ7jGZyOia3b38NALMc7vb6mZjqObcclAO5/9jQMMTy/wpZ+/wNcOD/PtJ08D1jTSZed0sLu3hS3tEfrbwvS3RWiLNNISbqA5HKzZJdBOcnNEcCUwZIw5ASAidwA3AoWJ4EbgD/Iffx34lIiIcaHpyJ2Hh/nMfSecftmirfcPWv3PNfn/mPxjBsgZQy5n/Z3NGTI5w1I2RyZrSGdzZy2oNQSEHT1RXru3j8sGO7hssIMLt7YRrJP55o20hBu4/NxOHn4hxit2dXsdzktce34Pn/zBsZrcTbwZg13NfOj6C/mvrz+fJ0/O8ujwDI+8OMOjL85w9xOjnO1dozEoNAYDNATyfweFoAgiQjAgiIBgjUAEIH/btlE78kr+Jv326/bwK5duc/x13UwE24HhgtsjwFVne44xJiMis0A38JJGKyLyHuA9AOecc86mgulobmRPf8umPtcpst6PjJx50/7BFGH5Bzcg1u7ThvwPd2MwQCgYIBpuIBoO0hxqoKOpkS3tEfrawvREw3VTZNys971+D8fG5n3XZvuywU7+06t3cVONnAPhlEhjkAM7ujiwY6Uf1FI2x8RcitPxJOPxJPFkhoVUhkQ6SyKVYSmbYym7cvGUM4asMRhjXVyZVRdeyza4JDUbPcFh7U3uHJbkr5/8szDG3A7cDnDgwIFN/Z//xYu28IsXVf8xi8p5V+/q4epd/poWAivhf+C62mzx4bTGYIBtHU1s80mxv9q4uXz0JFB4KTOQv2/N54hIA9COVTRWSilVIW4mgsPAHhHZKSIh4CbgrlXPuQv4jfzHbwV+6EZ9QCml1Nm5NjWUn/O/FfgO1vLRzxljnhKRjwEPGmPuAv4e+KKIDAHTWMlCKaVUBblaIzDG3A3cveq+jxR8nATe5mYMSiml1qctJpRSqs5pIlBKqTqniUAppeqcJgKllKpzUm2rNUVkAnhhk5/ew6pdyz7i19j8Ghf4Nza/xgX+jc2vcUHtxHauMWbNfiVVlwjKISIPGmMOeB3HWvwam1/jAv/G5te4wL+x+TUuqI/YdGpIKaXqnCYCpZSqc/WWCG73OoB1+DU2v8YF/o3Nr3GBf2Pza1xQB7HVVY1AKaXUmeptRKCUUmoVTQRKKVXn6jYRiMjviIgREd+cSCIifygij4vIoyLyXRFx/ky6TRCRPxORI/nYviEiHV7HZBORt4nIUyKSExHPl/iJyHUi8qyIDInIB72OxyYinxORcRF50utYConIoIjcIyJP57+P7/U6JpuIRETkARF5LB/bR72OqZCIBEXkERH5t3Jfqy4TgYgMAr8IvOh1LKv8mTFmvzHmMuDfgI9s9AkV8j3gYmPMfuAo8CGP4yn0JPBm4F6vAxGRIHAbcD2wD7hZRPZ5G9WyzwPXeR3EGjLA7xhj9gGvAH7LR//PUsBrjTGXApcB14nIKzyOqdB7gWeceKG6TATAXwK/x4YnklaWMSZecDOKT+IzxnzXGJPJ3/wZ1mlzvmCMecYY86zXceRdCQwZY04YY9LAHcCNHscEgDHmXqwzP3zFGDNqjHk4//Ec1hvbdm+jshjLfP5mY/6PL34nRWQAeCPwWSder+4SgYjcCJw0xjzmdSxrEZH/KSLDwNvxz4ig0G8C3/Y6CJ/aDgwX3B7BJ29q1UBEdgAvA37ubSQr8tMvjwLjwPeMMX6J7a+wLmZzTrxYVRxeXyoR+T6w1kn1Hwb+G9a0kCfWi80Y801jzIeBD4vIh4Bbgf/PD3Hln/NhrKH8lysRUymxqeomIi3APwPvWzUy9pQxJgtclq+LfUNELjbGeFpnEZE3AePGmIdE5NVOvGZNJgJjzOvXul9ELgF2Ao+JCFhTHA+LyJXGmNNexraGL2Od7laRRLBRXCJyC/Am4HWVPle6hP9nXjsJDBbcHsjfp9YhIo1YSeDLxph/8TqetRhjZkTkHqw6i9cF91cBN4jILwMRoE1EvmSMecdmX7CupoaMMU8YY/qMMTuMMTuwhu6XVyoJbERE9hTcvBE44lUshUTkOqxh6A3GmAWv4/Gxw8AeEdkpIiGsM7jv8jgmXxPriuzvgWeMMZ/wOp5CItJrr5ATkSbgDfjgd9IY8yFjzED+Pewm4IflJAGos0RQBf5ERJ4Ukcexpq/8spTuU0Ar8L380tb/3+uAbCLyqyIyArwS+JaIfMerWPIF9VuB72AVPe80xjzlVTyFROSrwE+BC0RkRETe5XVMea8C/gPw2vzP1qP5K10/2Arck/99PIxVIyh7qaYfaYsJpZSqczoiUEqpOqeJQCml6pwmAqWUqnOaCJRSqs5pIlBKqTqniUDVhXyHy19add/7ROTvNvi8+fUedyCuXhH5eb6L5MGC+4Mi8pCIXFtw33dF5G1uxqPqkyYCVS++irX5ptBN+fu99DrgCWPMy4wx99l35lsb/GfgUyLSKCI3AzljzD95FaiqXbqPQNUFEenC2hU6YIxJ5xuc3Quci9Xp9ZtAJ1aHyd8v6K80b4xpyfd0+V1jzJvy938KeNAY83kRuQL4BNACTAK3GGNGV339HcDngB5gAngn0IW187gJqxXFK40xi6s+79P51/x14A3GmCHn/q8oZdERgaoLxphp4AGsswLAGg3cme+blAR+1RhzOfAa4C/yrQ82lO+T8zfAW40xV2C92f/PNZ76N8AX8mc6fBn4a2PMo1gdZr9mjLlsdRLI+xDwPuArmgSUW2qy6ZxSZ2FPD30z/7fdZkGAP8rPx+ewWkf3A8X0oLoAuBir/QZAEBhd43mvxDpAB+CLwMeLjPlaYDb/NZRyhY4IVD35JvA6EbkcaDbGPJS//+1AL3BF/nS4MayujoUyvPT3xX5cgKfyV/SXGWMuMcY40uZcRKJYCeO1QJ+PevCoGqOJQNWN/GlT92BN3xQWidux+rsvichrsOoGq70A7BORcL4j5evy9z8L9IrIK8GaKhKRi9b4/J+wUqx+O3DfGs9Z7SNY01dHsArHfykiqxOUUmXTRKDqzVeBS3lpIvgycEBEngD+L9ZoNWyMGQbuxOpFfyfwSP7+NPBW4E9F5DHgUeDqNb7ufwHeme9k+R/YoLNsPpn8Kvl6gzHmEayuph8o9h+qVLF01ZBSStU5HREopVSd00SglFJ1ThOBUkrVOU0ESilV5zQRKKVUndNEoJRSdU4TgVJK1bn/A94o9qpf7TsgAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(x, data)\n", "plt.xlabel(\"Value of X\")\n", "plt.ylabel(\"Probability\")\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It works!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Simulating Continuous-Variable QAOA For a Simple Problem**
\n", "\n", "Now that we understand why QAOA/VQE actually work, let's try to implement a basic simulation of the algorithm for a basic cost function. Consider the horizontally translated parabloa:\n", "\n", "

\n", "$$f(x) \\ = \\ (x \\ - \\ a)^2$$\n", "

\n", "\n", "We can easily translate this to the language of \"quantum cost Hamiltonians\" with the method outlined in the previous section to get:\n", "\n", "

\n", "$$\\hat{H}_{C} \\ = \\ (\\hat{x} \\ - \\ a)^2$$\n", "

\n", "\n", "For our circuit, the unitary $U(\\alpha, \\ \\gamma)$ is given as:\n", "\n", "

\n", "$$U(\\alpha, \\ \\gamma) \\ = \\ e^{-i \\alpha \\hat{H}_{M}} e^{-i \\gamma (\\hat{x} \\ - \\ a)^2} \\ \\Rightarrow \\ \\hat{H}_{M} \\ \\in \\ \\{ \\hat{H}_{K}, \\ \\hat{H}_{N} \\}$$\n", "

\n", "\n", "In order to implement this on a photonic quantum circuit, we need to express these unitaries in terms of products of gates in the allowed gate set for our quantum computer. For our simulations, we will be using Strawberry Fields, so we are confined to the gate state that the Strawberry Fields library provides (we can technically make custom gates, but that feels like cheating). Anyways, let's expand and **separate**. Now, I hope you're saying (unless you're on step ahead of me): \"Jack, separating a matrix exponential??? Don't you need an infinite number of terms for the Baker-Campbell-Hausdorff expansion???\". Well, the answer is yes, but practically all of those terms end up being equal to one. The operators $\\hat{x}^{n}$ and $\\hat{x}^{m}$ will commute, thus Baker-Campbell-Hausdorff greatly reduces, ands we get:\n", "\n", "

\n", "$$e^{-i \\gamma (\\hat{x} \\ - \\ a)^2} \\ = \\ e^{-i \\gamma (\\hat{x}^2 \\ - \\ 2a\\hat{x} \\ + \\ a^2)} \\ = \\ e^{-i \\gamma \\hat{x}^2} e^{i \\gamma 2a \\hat{x}} e^{-i \\gamma a^2} \\ \\Rightarrow \\ e^{-i \\gamma \\hat{x}^2} e^{i \\gamma 2a \\hat{x}}$$\n", "

\n", "\n", "We just dropped the exponential $e^{-i \\gamma a^2}$ because it is an overall phase and does not affect our quantum state. Conceptually, this makes sense, as $a^2$ simply acts to shift our entire parabola vertically, not affecting the $x$-coordinate of the global minimum, thus we mught as well drop it from the cost function (we'll keep it in there for the classical post-processing). We have two gates that we need to act upon a photonic mode. In order to implement these unitaries on the quantum circuit, we express them as momentum displacement and quadratic phase operator. First, the momentum displacement operator is defined as:\n", "\n", "

\n", "$$Z(p) \\ = \\ \\exp(i p \\hat{x}/ \\hbar)$$\n", "

\n", "\n", "So we then have:\n", "\n", "

\n", "$$e^{i \\gamma 2a \\hat{x}} \\ \\Rightarrow \\ 2\\gamma a \\ = \\ \\frac{p}{\\hbar} \\ \\Rightarrow \\ p \\ = \\ 2 \\gamma a \\hbar$$\n", "

\n", "\n", "We also utilize the quadratic phase gate:\n", "\n", "

\n", "$$P(s) \\ = \\ \\exp \\Big( i \\frac{s}{2\\hbar} \\hat{x}^2 \\Big) \\ \\Rightarrow \\ e^{-i \\gamma \\hat{x}^2} \\ \\Rightarrow \\ -\\gamma \\ = \\ \\frac{s}{2\\hbar} \\ \\Rightarrow \\ s \\ = \\ -2 \\gamma \\hbar$$\n", "

\n", "\n", "We can code this up in Strawberry Fields! First, we have to initialize the value of Planck's constant, as well as the value of $a$. For now, we will pick some arbitrary value (I chose $0.83$). You can change this later, if you want to convince yourself that the algorithm works for other values of $a$ as well:" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [], "source": [ "#Defines the value of h-bar\n", "\n", "sf.hbar = 0.5\n", "hbar = 0.5\n", "\n", "#Defines the value of the parabolic minimum\n", "\n", "parabolic_min = 0.83" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will now define our classical cost function, which is fairly easy in Python:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [], "source": [ "#Defines the classical cost function\n", "\n", "def function_optimize(x, parabolic_min):\n", " y = (x - parabolic_min)**2\n", " return y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now have to define our cost unitary, to be used in the QAOA process, which again, we can do fairly easily:" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "#Defines the cost unitary for QAOA\n", "\n", "def cost_ham(q, p):\n", "\n", " Zgate(parabolic_min*2*hbar*p) | q[0]\n", " Pgate(-2*hbar*p) | q[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can turn our attention to implementing the mixer Hamiltonian. Let's start with the kinetic mixer, then move to the number mixer. In order to implement this gate, we simply perform a Fourier gate-operation on both sides of the qudratic phase gate:\n", "\n", "

\n", "$$\\exp \\Big( i \\frac{s}{2\\hbar} \\hat{p}^2 \\Big) \\ = \\ \\exp \\Big( i \\frac{s}{2\\hbar} F^{\\dagger} \\hat{x} F F^{\\dagger} \\hat{x} F \\Big) \\ = \\ \\exp \\Big( i \\frac{s}{2\\hbar} F^{\\dagger} \\hat{x}^2 F \\Big) \\ = \\ \\displaystyle\\sum_{i \\ = \\ 0}^{\\infty} \\frac{(i \\frac{s}{2\\hbar})^{i} (F^{\\dagger} \\hat{x}^2 F)^{i}}{i!} \\ = \\ F^{\\dagger} \\displaystyle\\sum_{i \\ = \\ 0}^{\\infty} \\frac{(i \\frac{s}{2\\hbar})^{i} (\\hat{x}^2)^{i} }{i!} F \\ = \\ F^{\\dagger} P(s) F$$\n", "

\n", "\n", "If the removal of those Fourier operations from the sum made you do a double-take, never fear! Consider the following:\n", "\n", "

\n", "$$M N^n M^{-1} \\ = \\ M (N \\mathbb{I})^n M^{-1} \\ = \\ M (N M^{-1} M)^n M^{-1} \\ = \\ (M N M^{-1})^n$$\n", "

\n", "\n", "Since $F^{\\dagger}$ is the inverse of $F$, as these operations are unitary, the same logic follows. We can then code this into our Strawberry Fields program, with the parameter $s \\ = \\ -\\frac{1}{2} \\hbar \\alpha$:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "#Defines the kinetic mixer unitary for QAOA\n", "\n", "def mixer_ham(q, p):\n", "\n", " Rgate(-1*math.pi/2) | q[0]\n", " Pgate(-1*hbar*p) | q[0]\n", " Rgate(math.pi/2) | q[0]\n", "\n", " return q " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have a few more parameters that we have to define as well before we run our simulation. We have to choose our circuit depth, which is the number of times the cost-mixer unitary is applied and the photon cutoff dimension for our Strawberry Fields simulation. In addition, we have to choose our **squeezing parameter**. We will be initializing our simulation in a squeezed state over the $x$-quadrature, in order to ensure that our algorithm searches over a large space of possible solutions:" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [], "source": [ "#Defines the circuit depth, cutoff dimension, and the squeezing parameter\n", "\n", "circuit_depth = 3\n", "squeezing = -0.5\n", "cutoff = 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we are in a position to define our first circuit, which will return numerical values for our graphical visualization. Note that this is not the function that we will be using for the actual optimization of the circuit, as this function does not sample the circuit, but rather returns Wigner function values for our graph. We will find Wigner function values ranging from $-30$ to $30$, for both the $x$ and $p$ quadratures, with a spacing of $0.1$ between measured values. In addition, we will only optimize over one parameter, as the function we are optimizing is a fairly simple one:" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [], "source": [ "#Defines the function used to run the circuit and return numerical data\n", "\n", "def run_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(1)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[0] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", "\n", " for i in range(0, circuit_depth):\n", "\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param2[i])\n", "\n", " state = eng.run(prog, run_options={\"eval\": False}).state\n", " a = state.wigner(0, [i/10 for i in range(-30, 30)], [i/10 for i in range(-30, 30)])\n", " return a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we will define our \"sampling function\", which is identical to the one that we just provided, except instead of returning numerical Wigner function values, we will actually sample the circuit for individual values:" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [], "source": [ "#Defines the sampling circuit simulation\n", "\n", "def old_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(1)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[0] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", "\n", " for i in range(0,circuit_depth):\n", "\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param2[i])\n", "\n", " MeasureX | q[0]\n", "\n", " result = eng.run(prog)\n", " return result.samples[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now have to specify how many times we will sample the circuit, to obtain a decently accurate value for the expectation value of our cost Hamiltonian. For now, we will choose $15$ as the number of our samples." ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [], "source": [ "#Defines the number of iterations that the circuit is sampled\n", "\n", "shots = 15" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now have to define our **objective function**, which is the function that we will attempt to optimize with our classical optimizer. As the cost, we will return the average of our repeated samples of the circuit:" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [], "source": [ "#Defines the objective function that is minimized\n", "\n", "def objective(param):\n", "\n", " costly = 0\n", "\n", " for i in range(0, shots):\n", "\n", " av = old_circuit(param)\n", " result1 = av\n", " calculation = function_optimize(result1, parabolic_min)\n", " costly = costly + calculation\n", "\n", " costly = costly/shots\n", "\n", "\n", " print(\"Paramter: \"+str(param))\n", " print(\"Value of Cost Function: \"+str(costly))\n", "\n", " return costly" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we will define the actual classical optimizer that we will use to minimize the objective function. For this implementation, we will use the Nelder-Mead optimizer. For our initial parameter, we will choose a random value from $-3$ to $3$ (this was arbitrary, there is probably a better way to choose this initial parameter based on traditional gradient descent methods, but for now, a random value in this aarbitrary range will suffice). Finally, we will run our numerical circuit one more time with the optimal parameters, in order to get Wigner function values for our graphical visualization:" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Paramter: [-0.97]\n", "Value of Cost Function: 0.43513583550542007\n", "Paramter: [-1.0185]\n", "Value of Cost Function: 0.10466390018776067\n", "Paramter: [-1.067]\n", "Value of Cost Function: 0.28793846946881885\n", "Paramter: [-1.04275]\n", "Value of Cost Function: 0.07749277235325454\n", "Paramter: [-1.067]\n", "Value of Cost Function: 0.29722133474386286\n", "Paramter: [-1.030625]\n", "Value of Cost Function: 0.1406666464284185\n", "Paramter: [-1.030625]\n", "Value of Cost Function: 0.32884805827517055\n", "Paramter: [-1.054875]\n", "Value of Cost Function: 0.4038743309571217\n", "Paramter: [-1.0366875]\n", "Value of Cost Function: 0.14403148505285468\n", "Paramter: [-1.0488125]\n", "Value of Cost Function: 0.4279020773256463\n", "Paramter: [-1.03971875]\n", "Value of Cost Function: 0.1297114614271474\n", "Paramter: [-1.04578125]\n", "Value of Cost Function: 0.15324513427691774\n", "Paramter: [-1.04123437]\n", "Value of Cost Function: 0.3287606707487621\n", "Paramter: [-1.04123437]\n", "Value of Cost Function: 0.18736305537192782\n", "Paramter: [-1.04426562]\n", "Value of Cost Function: 0.32546063976980594\n", "Paramter: [-1.04199219]\n", "Value of Cost Function: 0.17254752940822338\n", "Paramter: [-1.04350781]\n", "Value of Cost Function: 0.246146854294028\n", "Paramter: [-1.04237109]\n", "Value of Cost Function: 0.46377050883868975\n", "Paramter: [-1.04237109]\n", "Value of Cost Function: 0.2517918099032421\n", "Paramter: [-1.04312891]\n", "Value of Cost Function: 0.19642742420506457\n", "Paramter: [-1.04293945]\n", "Value of Cost Function: 0.16555155290005938\n", "Paramter: [-1.04256055]\n", "Value of Cost Function: 0.17187502865160909\n", "Paramter: [-1.04284473]\n", "Value of Cost Function: 0.16441491059799376\n", "Paramter: [-1.04265527]\n", "Value of Cost Function: 0.791914683648038\n", "Paramter: [-1.04279736]\n", "Value of Cost Function: 0.11846711056525452\n", "Paramter: [-1.04270264]\n", "Value of Cost Function: 0.1226002940285107\n", "Paramter: [-1.04277368]\n", "Value of Cost Function: 0.2190922309842671\n", "Paramter: [-1.04277368]\n", "Value of Cost Function: 0.19993733905101063\n", "Paramter: [-1.04272632]\n", "Value of Cost Function: 0.09028367923944633\n", "Paramter: [-1.04273816]\n", "Value of Cost Function: 0.5125227484692737\n", "Paramter: [-1.04276184]\n", "Value of Cost Function: 0.1403272178932151\n", "Paramter: [-1.04273816]\n", "Value of Cost Function: 0.08868306149925179\n", "Paramter: [-1.04274408]\n", "Value of Cost Function: 0.43367333798361574\n", "Paramter: [-1.04275592]\n", "Value of Cost Function: 0.1042678753539703\n", "Paramter: [-1.04274408]\n", "Value of Cost Function: 0.43379467143293926\n", "Paramter: [-1.04275296]\n", "Value of Cost Function: 0.15888683280632412\n", "Paramter: [-1.04275296]\n", "Value of Cost Function: 0.1253630990390012\n", "Paramter: [-1.04274704]\n", "Value of Cost Function: 0.11222731740601559\n", "Paramter: [-1.04274852]\n", "Value of Cost Function: 0.10721451795319427\n", "Paramter: [-1.04275148]\n", "Value of Cost Function: 0.8135714167218675\n", "Paramter: [-1.04274926]\n", "Value of Cost Function: 0.1517654416552132\n", "Paramter: [-1.04274926]\n", "Value of Cost Function: 0.24417941801883244\n", "Paramter: [-1.04275074]\n", "Value of Cost Function: 0.25164353894317143\n", "Paramter: [-1.04274963]\n", "Value of Cost Function: 0.17375151637850914\n", "Paramter: [-1.04275037]\n", "Value of Cost Function: 0.15341986838758243\n", "Paramter: [-1.04275019]\n", "Value of Cost Function: 0.15385799514874038\n", "Paramter: [-1.04274981]\n", "Value of Cost Function: 0.11648799712318365\n", "Paramter: [-1.04275019]\n", "Value of Cost Function: 0.26441816153167885\n", "Paramter: [-1.04274991]\n", "Value of Cost Function: 0.2331637154952169\n", "Paramter: [-1.04274991]\n", "Value of Cost Function: 0.18887568990446724\n", " final_simplex: (array([[-1.04275 ],\n", " [-1.04274991]]), array([0.07749277, 0.18887569]))\n", " fun: 0.07749277235325454\n", " message: 'Maximum number of iterations has been exceeded.'\n", " nfev: 50\n", " nit: 20\n", " status: 2\n", " success: False\n", " x: array([-1.04275])\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "#Defines the optimizer that minimizes the objective function\n", "\n", "out = minimize(objective, x0=[random.randint(-150,150)/100], method=\"Nelder-Mead\", options={'maxiter':20})\n", "print(out)\n", "\n", "#Creates the graphical visualization\n", "\n", "final = run_circuit(out['x'])\n", "\n", "x = [i/10 for i in range(-30, 30)]\n", "y = []\n", "\n", "\n", "for i in range(0, len(x)):\n", " res = simps([final[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", "plt.plot(x, y)\n", "plt.plot([parabolic_min, parabolic_min, parabolic_min, parabolic_min, parabolic_min], [0, 0.25*max(y), 0.5*max(y), 0.75*max(y), max(y)])\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So the optimizer performs decently well. As you can see, the $x$-quadrature has spiked pretty close to the optimal point, which is marked by the orange line!\n", "\n", "You are welcome to play around further with other mixers, parameters, circuit depth, etc. to see what works the best before you proceed in this notebook, but for now, I'm going to move onto something a bit more interesting! For some reason, the optimizer does not do as well when $a$ is chosen outside the range of $-1$ to $1$, but this can be improved by playing around with the squeezing parameters, as well as the value of Planck's constant. For instance, let's increase the value of Planck's constant to one and try to run the simulation for a larger value of $a$ (I include the results as an image so I don't have to re-write all the code below). All other parameters were kept constant, except the value of Planck's constant, and the value of $a$, which is now $-1.41$:\n", "\n", "
\n", "\n", "
\n", "\n", "As you can see, we get pretty decent results! It is important to note that when I was playing around with it, the optimizer was super finicky, and sometimes would not work. There are a lot of sources of error that could account for this, including limits in classical optimizers when sampling stochastic functions, low cutoff dimension, etc." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Simulating Continuous-Variable QAOA For Harder Problems**
\n", "\n", "Anyways, we have solved a very simple problem, but what if we want to solve something a bit more complex, like a question involving two variables? Well, we can implement that as well, but this time, we will have to use two optical modes instead of one, to encode both variables in our cost function. Let's try to minimize the function given by:\n", "\n", "

\n", "$$f(x, \\ y) \\ = \\ (2x-y)^2 + (x-1)(y+1) \\ = \\ x^2 \\ + \\ y^2 \\ + \\ x \\ + \\ y \\ + \\ xy$$\n", "\n", "$$\\Rightarrow \\ \\min f(x, \\ y) \\ = \\ -\\frac{1}{3} \\ \\Rightarrow \\ (x, \\ y) \\ = \\ \\Big( -\\frac{1}{3}, \\ -\\frac{1}{3} \\Big) \\ \\approx \\ (-0.333333333, \\ -0.333333333)$$\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As far as more complex functions go, this one is fairly simple and \"symetric\" in terms of its minimum. We can put this in the form of our unitary:\n", "\n", "

\n", "$$U(\\alpha, \\ \\gamma) \\ = \\ e^{-i\\alpha \\hat{H}_{M}} e^{-i \\gamma (\\hat{x}^2 \\ + \\ \\hat{x}\\hat{y} \\ + \\ \\hat{x} \\ + \\ \\hat{y}^2 \\ + \\ \\hat{y})}$$\n", "

\n", "\n", "Since the position operators all commute, we can write this unitary as a series of exponentials, which we can translate to photonic gates. We have:\n", "\n", "

\n", "$$e^{-i \\gamma (\\hat{x}^2 \\ + \\ \\hat{x}\\hat{y} \\ + \\ \\hat{x} \\ + \\ \\hat{y}^2 \\ + \\ \\hat{y})} \\ = \\ e^{-i \\gamma \\hat{x}^2} e^{-i \\gamma \\hat{x}\\hat{y}} e^{-i \\gamma \\hat{x}} e^{-i \\gamma \\hat{y}^2} e^{-i \\gamma \\hat{y}}$$\n", "

\n", "\n", "And then, doing all of the necessary algebra, we find that we can represent this series of unitaries as photonic gates:\n", "\n", "

\n", "$$\\Rightarrow \\ e^{-i \\gamma \\hat{x}^2} \\ = \\ P_{1}(-2 \\hbar \\gamma)$$\n", "
\n", "$$\\Rightarrow \\ e^{-i \\gamma \\hat{x}\\hat{y}} \\ = \\ CZ_{12}(-3 \\hbar \\gamma)$$\n", "
\n", "$$\\Rightarrow \\ e^{-i \\gamma \\hat{x}} \\ = \\ Z_{1}(-\\hbar \\gamma)$$\n", "
\n", "$$\\Rightarrow \\ e^{-i \\gamma \\hat{y}^2} \\ = \\ P_{2}(-2 \\hbar \\gamma)$$\n", "
\n", "$$\\Rightarrow \\ e^{-i \\gamma \\hat{y}} \\ = \\ Z_{2}(-\\hbar\\gamma)$$\n", "
\n", "$$U(\\alpha, \\ \\gamma) \\ = \\ e^{-i\\alpha \\hat{H}_{M}} \\ P_{1}(-2 \\hbar \\gamma) \\ CZ_{12}(-3 \\hbar \\gamma) \\ Z_{1}(-\\hbar \\gamma) \\ P_{2}(-2 \\hbar \\gamma) \\ Z_{2}(-\\hbar\\gamma)$$\n", "

\n", "\n", "Next, let's code this into our pre-existing simulation. We'll try both of the previous mixers in our simulations. Let's start with the kinetic mixer again, giving us a final unitary of:\n", "\n", "

\n", "$$U(\\alpha, \\ \\gamma) \\ = \\ F^{\\dagger}_{1} \\ F^{\\dagger}_{2} \\ P_{1}(-\\hbar\\alpha) \\ P_{2}(-\\hbar\\alpha) \\ F_{1} \\ F_{2} \\ P_{1}(-2 \\hbar \\gamma) \\ CZ_{12}(-3 \\hbar \\gamma) \\ Z_{1}(-\\hbar \\gamma) \\ P_{2}(-2 \\hbar \\gamma) \\ Z_{2}(-\\hbar\\gamma)$$\n", "

\n", "\n", "Without further delay, let's code up our simulation! We have a new classical cost function that we have to implement first. In addition, we have define the value of Planck's constant:" ] }, { "cell_type": "code", "execution_count": 190, "metadata": {}, "outputs": [], "source": [ "#Defining the value of h-bar\n", "\n", "sf.hbar = 0.5\n", "hbar = 0.5\n", "\n", "#Defining the classical cost function\n", "\n", "def function_optimize(x1, x2):\n", " y = x1**2 + x2**2 + x1 + x2 + x1*x2\n", " return y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we will have to define the new cost unitary, which we will be using in the QAOA procedure. This is fairly simple to do, as we have already come up with a gate-sequence that gives us our desired gate:" ] }, { "cell_type": "code", "execution_count": 191, "metadata": {}, "outputs": [], "source": [ "#Defining the cost unitary used in the QAOA procedure\n", "\n", "def cost_ham(q, p):\n", "\n", " Zgate(-1**hbar*p) | q[1]\n", " Pgate(-2*hbar*p) | q[1]\n", " Zgate(-1*hbar*p) | q[0]\n", " Pgate(-2*hbar*p) | q[0]\n", " CZgate(-3*hbar*p) | (q[0], q[1])\n", "\n", " return q" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will also implement the kinetic mixer for two modes:" ] }, { "cell_type": "code", "execution_count": 192, "metadata": {}, "outputs": [], "source": [ "#Defining the mixer unitary used in the QAOA process\n", "\n", "def mixer_ham(q, p):\n", "\n", " Rgate(-1*math.pi/2) | q[0]\n", " Rgate(-1*math.pi/2) | q[1]\n", "\n", " Pgate(-1*hbar*p) | q[0]\n", " Pgate(-1*hbar*p) | q[1]\n", "\n", " Rgate(math.pi/2) | q[0]\n", " Rgate(math.pi/2) | q[1]\n", "\n", " return q" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just as we did before, we will assert the parameters that we will use to run our simulation. These parameters, like before, will be the squeezing parameter, the circuit depth, and the cutoff dimension:" ] }, { "cell_type": "code", "execution_count": 198, "metadata": {}, "outputs": [], "source": [ "#Defining circuit depth, cutoff dimension, and squeezing parameter\n", "\n", "squeezing = -0.4\n", "cutoff = 8\n", "circuit_depth = 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once again, like we did before, we will define wo functions that run our circuit, one that returns numerical data for our visualizations, and one that samples the circuit. Again, we will optimize over only one parameter:" ] }, { "cell_type": "code", "execution_count": 199, "metadata": {}, "outputs": [], "source": [ "#Defining the function that simulates the circuit and returns results\n", "\n", "def run_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(2)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[1] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", " Squeezed(squeezing,0) | q[1]\n", "\n", " for i in range(0, circuit_depth):\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param2[i])\n", "\n", " state = eng.run(prog, run_options={\"eval\": False}).state\n", "\n", " a = state.wigner(0, [i/10 for i in range(-40, 40)], [i/10 for i in range(-40, 40)])\n", " b = state.wigner(1, [i/10 for i in range(-40, 40)], [i/10 for i in range(-40, 40)])\n", "\n", " return [a, b]\n", "\n", "#Defining the sampling circuit\n", "\n", "def old_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(2)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[1] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", " Squeezed(squeezing,0) | q[1]\n", "\n", " for i in range(0, circuit_depth):\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param2[i])\n", "\n", "\n", " MeasureX | q[0]\n", " MeasureX | q[1]\n", "\n", " result = eng.run(prog)\n", " return [result.samples[0], result.samples[1]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will choose our number of iterations, and specify the objective function:" ] }, { "cell_type": "code", "execution_count": 200, "metadata": {}, "outputs": [], "source": [ "#Define the number of iterations that should be sampled from the circuit\n", "\n", "shots = 15\n", "\n", "#Defining the objective function that is optimized\n", "\n", "def objective(param):\n", "\n", " costly = 0\n", "\n", " for i in range(0, shots):\n", "\n", " av = old_circuit(param)\n", " result1 = av[0]\n", " result2 = av[1]\n", " calculation = function_optimize(result1, result2)\n", " costly = costly + calculation\n", "\n", " costly = costly/shots\n", "\n", " print(\"Paramter: \"+str(param))\n", " print(\"Value of Cost Function: \"+str(costly))\n", "\n", " return costly" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then, we choose our optimizer once again. Finally, we can construct our visualizations, just as we did before. This time, we will examine a contour plot showing the probability of measuring a specific point $(x, \\ y)$, as well as the quadratures showing the probability densities for the individual modes. It is important to note that the contour plot is not exact: since we passed the modes through a controlled-phase gate, they are no longer \"independent\", and thus, the probability of a particular measurement can't be determined by simply multiplying the individual probabilities of measurement. However, we can still get a decent approximation from the contour plot, so it is useful to examine as well:" ] }, { "cell_type": "code", "execution_count": 201, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Paramter: [-0.92 -0.73]\n", "Value of Cost Function: 0.5713355408870178\n", "Paramter: [ 0.08 -0.73]\n", "Value of Cost Function: 2.5985616017388455\n", "Paramter: [-0.92 0.27]\n", "Value of Cost Function: 0.1254065636853998\n", "Paramter: [-1.89665061 0.48483386]\n", "Value of Cost Function: 0.7668995318806139\n", "Paramter: [-0.48949667 0.52429684]\n", "Value of Cost Function: 0.9983159216519352\n", "Paramter: [-1.1653949 0.31776341]\n", "Value of Cost Function: 0.44530958211377786\n", "Paramter: [-0.8920057 0.02157231]\n", "Value of Cost Function: -0.026378065058663313\n", "Paramter: [-0.65922841 -0.06961286]\n", "Value of Cost Function: 0.275405087907551\n", "Paramter: [-1.00412325 -0.03369661]\n", "Value of Cost Function: -0.13363035449372687\n", "Paramter: [-1.08834697 -0.12606201]\n", "Value of Cost Function: -0.05705895587341165\n", "Paramter: [-1.08235807 0.06379346]\n", "Value of Cost Function: 0.03548072024419\n", "Paramter: [-0.94527083 -0.05473568]\n", "Value of Cost Function: 0.004073661972832032\n", "Paramter: [-1.02392954 -0.05786836]\n", "Value of Cost Function: 0.12359246140353562\n", "Paramter: [-1.00050393 -0.00265691]\n", "Value of Cost Function: 0.0025752036038145356\n", "Paramter: [-0.98924939 -0.03848294]\n", "Value of Cost Function: 0.1906365720123769\n", "Paramter: [-1.01191117 -0.03431594]\n", "Value of Cost Function: 0.16709473517799409\n", "Paramter: [-1.00276178 -0.02600365]\n", "Value of Cost Function: 0.12876995828628865\n", "Paramter: [-1.00134826 -0.03644583]\n", "Value of Cost Function: 0.052893244492933984\n", "Paramter: [-1.0060308 -0.03411611]\n", "Value of Cost Function: 0.3688779277550006\n", "Paramter: [-1.00295679 -0.03213006]\n", "Value of Cost Function: 0.2540588325845793\n", "-----------------------------\n", " fun: -0.13363035449372687\n", " maxcv: 0.0\n", " message: 'Maximum number of function evaluations has been exceeded.'\n", " nfev: 20\n", " status: 2\n", " success: False\n", " x: array([-1.00412325, -0.03369661])\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "out = minimize(objective, x0=[random.randint(-100,100)/100, random.randint(-100,100)/100], method=\"COBYLA\", options={'maxiter':20})\n", "print(\"-----------------------------\")\n", "print(out)\n", "\n", "#Define the y array for the first mode\n", "\n", "f = run_circuit(out['x'])\n", "final = f[0]\n", "\n", "x = [i/10 for i in range(-40, 40)]\n", "y = []\n", "\n", "for i in range(0, len(x)):\n", " res = simps([final[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", "#Define the y array for the second mode\n", "\n", "final2 = f[1]\n", "\n", "x2 = [i/10 for i in range(-40, 40)]\n", "y2 = []\n", "\n", "for i in range(0, len(x2)):\n", " res = simps([final2[k][i] for k in range(0, len(x2))], x2)\n", " y2.append(res)\n", "\n", "\n", "#Defines the contour plot that gives the final probability density function\n", "\n", "fig = plt.figure(figsize=(6,5))\n", "left, bottom, width, height = 0.1, 0.1, 0.8, 0.8\n", "ax = fig.add_axes([left, bottom, width, height])\n", "\n", "x_vals = x\n", "y_vals = x2\n", "X, Y = np.meshgrid(x, x2)\n", "\n", "\n", "Z = np.array([[i*j for i in y] for j in y2])\n", "\n", "cp = plt.contourf(X, Y, Z)\n", "plt.colorbar(cp)\n", "\n", "ax.set_title('Contour Plot')\n", "plt.scatter([float(-1)/3], [float(-1)/3])\n", "plt.show()\n", "\n", "#Defines the probability density graph of the first mode\n", "\n", "plt.subplot(2, 1, 1)\n", "plt.plot(x, y)\n", "plt.plot([float(-1)/3 for o in range(0, 5)], [0, 0.25*max(y), 0.5*max(y), 0.75*max(y), max(y)])\n", "\n", "#Defines the probability density graph of the second mode\n", "\n", "plt.subplot(2, 1, 2)\n", "plt.plot(x2, y2)\n", "plt.plot([float(-1)/3 for o in range(0, 5)], [0, 0.25*max(y2), 0.5*max(y2), 0.75*max(y2), max(y2)])\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The blue dot on the contour graph corresponds to the optimal point. I really feel like I'm cheating with respect to this implementation, as I went through many different values of the parameters, like squeezing, cutoff dimension, and circuit depth to find this solution (which is really good)! For the most part, this example, when I ran it locally, was super volatile, and didn't work a lot of the time. I think it would be interesting to see an extension of this algorithm, where not only the unitaries are parametrized, but so are other parameters (like the squeezing parameter, cutoff dimension, and circuit depth). I would also hope that the algorithm performs better and more consistently when we are able to choose our initial parameters with an actual strategy rather than blinding picking some arbitrary set of numbers. Let's try another example, but this time, let's be a bit harder on ourselves and actually sample the function to obtain an optimal value (as one is supposed to do with an optimization algorithm)! Consider the function given as:\n", "\n", "

\n", "$$f(x, \\ y) \\ = \\ 2x^2 \\ + \\ 2xy \\ - \\ 6x \\ + \\ 2y^2 \\ - \\ 5y \\ + \\ 10$$\n", "
\n", "$$\\text{min} \\ f(x, \\ y) \\ = \\ \\frac{29}{6} \\ \\Rightarrow \\ (x, \\ y) \\ = \\ \\Big( \\frac{7}{6}, \\ \\frac{2}{3} \\Big)$$\n", "

\n", "\n", "Let's try optimizing this! For this function, since the distance between the optimal values of $x$ and $y$ is larger, we will st Planck's constant to $1$ to acheive larger variance without applying ridiculous amounts of squeezing (which can also mess up the simulation). By this point, you pretty much get the idea of how we implement the algorithm, so I won't go through all of it. Note that I am only re-defining the things that change, the rest will stay the same from the previous example:" ] }, { "cell_type": "code", "execution_count": 204, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Paramter: [ 0.34 -0.18]\n", "Value of Cost Function: 9.307803654742312\n", "Paramter: [ 1.34 -0.18]\n", "Value of Cost Function: 10.515795116050741\n", "Paramter: [0.34 0.82]\n", "Value of Cost Function: 28.928896420635517\n", "Paramter: [ 0.27855039 -1.17811019]\n", "Value of Cost Function: 37.125205767336155\n", "Paramter: [ 0.30927519 -0.67905509]\n", "Value of Cost Function: 41.5589217202785\n", "Paramter: [0.33533306 0.06995644]\n", "Value of Cost Function: 16.852676606646867\n", "Paramter: [ 0.21502178 -0.18233347]\n", "Value of Cost Function: 7.986790860885201\n", "Paramter: [ 0.13681649 -0.41978648]\n", "Value of Cost Function: 23.035260031563766\n", "Paramter: [ 0.19337873 -0.05922141]\n", "Value of Cost Function: 7.228862372524561\n", "Paramter: [ 0.13539445 -0.03589603]\n", "Value of Cost Function: 9.914897524558999\n", "Paramter: [ 0.25335664 -0.04164586]\n", "Value of Cost Function: 13.561299903975282\n", "Paramter: [ 0.18753864 -0.08992086]\n", "Value of Cost Function: 7.016913767840332\n", "Paramter: [ 0.20223573 -0.0952252 ]\n", "Value of Cost Function: 6.42747954561483\n", "Paramter: [ 0.21681059 -0.10085673]\n", "Value of Cost Function: 7.722192382942105\n", "Paramter: [ 0.19958356 -0.10257375]\n", "Value of Cost Function: 6.703187465612326\n", "Paramter: [ 0.21659225 -0.08905826]\n", "Value of Cost Function: 8.097349230041532\n", "Paramter: [ 0.20101469 -0.10294169]\n", "Value of Cost Function: 6.462703444089277\n", "Paramter: [ 0.19840113 -0.09448049]\n", "Value of Cost Function: 9.384309374582392\n", "Paramter: [ 0.20609754 -0.09581275]\n", "Value of Cost Function: 9.079922163001934\n", "Paramter: [ 0.20030868 -0.09490714]\n", "Value of Cost Function: 6.129689786649431\n", "-----------------------------\n", " fun: 6.129689786649431\n", " maxcv: 0.0\n", " message: 'Maximum number of function evaluations has been exceeded.'\n", " nfev: 20\n", " status: 2\n", " success: False\n", " x: array([ 0.20030868, -0.09490714])\n", "[0.6353063530635303, 0.8517085170851715]\n", "[1.6167161671616714, 0.4753047530475314]\n", "[1.3669136691366912, 0.7941079410794121]\n", "[0.945909459094592, 0.6279062790627918]\n", "[0.9221092210922119, 0.848308483084832]\n", "[1.0373103731037308, 0.6443064430644316]\n", "[1.2763127631276312, 0.5753057530575312]\n", "The Optimal Value Is: [1.2763127631276312, 0.5753057530575312]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "#Defining the value of h-bar\n", "\n", "sf.hbar = 2\n", "hbar = 2\n", "\n", "#Defining the classical cost function\n", "\n", "def function_optimize(x1, x2):\n", " y = 2*(x1**2) + 2*x1*x2 - 6*x1 + 2*(x2**2) - 5*x2 + 10\n", " return y\n", "\n", "#Defining the cost unitary used in the QAOA procedure\n", "\n", "def cost_ham(q, p):\n", "\n", " Zgate(5*hbar*p) | q[1]\n", " Pgate(-4*hbar*p) | q[1]\n", " Zgate(6*hbar*p) | q[0]\n", " Pgate(-4*hbar*p) | q[0]\n", " CZgate(-6*hbar*p) | (q[0], q[1])\n", "\n", " return q\n", "\n", "#Defining the mixer unitary used in the QAOA process\n", "\n", "def mixer_ham(q, p):\n", "\n", " Rgate(-1*math.pi/2) | q[0]\n", " Rgate(-1*math.pi/2) | q[1]\n", "\n", " Pgate(-1*hbar*p) | q[0]\n", " Pgate(-1*hbar*p) | q[1]\n", "\n", " Rgate(math.pi/2) | q[0]\n", " Rgate(math.pi/2) | q[1]\n", "\n", " return q\n", "\n", "#Defining circuit depth, cutoff dimension, and squeezing parameter\n", "\n", "squeezing = -0.4\n", "cutoff = 6\n", "circuit_depth = 4\n", "\n", "#Define the number of iterations that should be sampled from the circuit\n", "\n", "shots = 15\n", "\n", "#Defining the function that simulates the circuit and returns results\n", "\n", "def run_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(2)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[1] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", " Squeezed(squeezing,0) | q[1]\n", "\n", " for i in range(0, circuit_depth):\n", " if (i%2 == 0):\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param1[i])\n", " else:\n", " cost_ham(q, param2[i])\n", " mixer_ham(q, param2[i])\n", "\n", " state = eng.run(prog, run_options={\"eval\": False}).state\n", "\n", " a = state.wigner(0, [i/10 for i in range(-40, 40)], [i/10 for i in range(-40, 40)])\n", " b = state.wigner(1, [i/10 for i in range(-40, 40)], [i/10 for i in range(-40, 40)])\n", "\n", " return [a, b]\n", "\n", "#Defining the sampling circuit\n", "\n", "def old_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(2)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[1] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", " Squeezed(squeezing,0) | q[1]\n", "\n", " for i in range(0, circuit_depth):\n", " if (i%2 == 0):\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param1[i])\n", " else:\n", " cost_ham(q, param2[i])\n", " mixer_ham(q, param2[i])\n", "\n", "\n", " MeasureX | q[0]\n", " MeasureX | q[1]\n", "\n", " result = eng.run(prog)\n", " return [result.samples[0], result.samples[1]]\n", "\n", "#Defining the objective function that is optimized\n", "\n", "def objective(param):\n", "\n", " costly = 0\n", "\n", " for i in range(0, shots):\n", "\n", " av = old_circuit(param)\n", " result1 = av[0]\n", " result2 = av[1]\n", " calculation = function_optimize(result1, result2)\n", " costly = costly + calculation\n", "\n", " costly = costly/shots\n", "\n", " print(\"Paramter: \"+str(param))\n", " print(\"Value of Cost Function: \"+str(costly))\n", "\n", " return costly\n", "\n", "#Define the optimizer that is used to find the optimal value of the objective function\n", "\n", "out = minimize(objective, x0=[random.randint(-50,50)/100, random.randint(-50,50)/100], method=\"COBYLA\", options={'maxiter':20})\n", "print(\"-----------------------------\")\n", "print(out)\n", "\n", "#Defines the sampling method that finds the exact optimal value\n", "samples = 200\n", "\n", "optimal_cost = math.inf\n", "optimal_val = 0\n", "\n", "for t in range(0, samples):\n", " final_function = old_circuit(out['x'])\n", " if (function_optimize(final_function[0], final_function[1]) < optimal_cost):\n", " optimal_val = final_function\n", " print(optimal_val)\n", " optimal_cost = function_optimize(final_function[0], final_function[1])\n", "\n", "print(\"The Optimal Value Is: \"+str(optimal_val))\n", "\n", "\n", "#Define the y array for the first mode\n", "\n", "f = run_circuit(out['x'])\n", "final = f[0]\n", "\n", "x = [i/10 for i in range(-40, 40)]\n", "y = []\n", "\n", "for i in range(0, len(x)):\n", " res = simps([final[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", "#Define the y array for the second mode\n", "\n", "final2 = f[1]\n", "\n", "x2 = [i/10 for i in range(-40, 40)]\n", "y2 = []\n", "\n", "for i in range(0, len(x2)):\n", " res = simps([final2[k][i] for k in range(0, len(x2))], x2)\n", " y2.append(res)\n", "\n", "\n", "#Defines the contour plot that gives the final probability density function\n", "\n", "fig = plt.figure(figsize=(6,5))\n", "left, bottom, width, height = 0.1, 0.1, 0.8, 0.8\n", "ax = fig.add_axes([left, bottom, width, height])\n", "\n", "x_vals = x\n", "y_vals = x2\n", "X, Y = np.meshgrid(x, x2)\n", "\n", "\n", "Z = np.array([[i*j for i in y] for j in y2])\n", "\n", "cp = plt.contourf(X, Y, Z)\n", "plt.colorbar(cp)\n", "\n", "ax.set_title('Contour Plot')\n", "plt.scatter([float(7)/6], [float(2)/3])\n", "plt.show()\n", "\n", "#Defines the probability density graph of the first mode\n", "\n", "plt.subplot(2, 1, 1)\n", "plt.plot(x, y)\n", "plt.plot([float(7)/6 for o in range(0, 5)], [0, 0.25*max(y), 0.5*max(y), 0.75*max(y), max(y)])\n", "\n", "#Defines the probability density graph of the second mode\n", "\n", "plt.subplot(2, 1, 2)\n", "plt.plot(x2, y2)\n", "plt.plot([float(2)/3 for o in range(0, 5)], [0, 0.25*max(y2), 0.5*max(y2), 0.75*max(y2), max(y2)])\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So it's not awful, but it isn't amazing either. Even so, I still feel like I'm cheating because I'm still being super selective with the parameters. In addition, this implementation uses a new approach to applying the parameters, where two parameters are optimized, and applied to the circuit in both the mixer and cost unitaries on even and odd numbered iterations respectively. The algorithm does appear to favour a region fairly close to our optimal value, however, there is a lot of variance due to us setting Planck's constant to $2$.\n", "\n", "**The Not-So Grand Finale: A Quartic Function With Two Global Minima**
\n", "\n", "Now, for the grand finale! We will attempt to implement to apply CV QAOA to the optimization of a **quartic** function. However, before we do this, we need to take a bit of a detour, and discuss how the heck we are actually going to create a quartic phase gate." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Another Small Tangent: Higher-Order Gate Decomposition**
\n", "\n", "Now, you're probably thinking: \"hold on one second....how are we supposed to deal with exponentials of $\\hat{x}^4$?\". Well, never fear, we actually have a method to decompose this gate exactly, using the research presented by Kalajdzievski and Arrazola in the paper \"Exact gate decompositions for photonic quantum computing\" (see references for a link to the paper). The paper is genius, if you're interested I **highly** reccomend at least quickly going through it), but we can essentially decompose our quartic gate into a product of a bunch of lower-order gates. I'm not going to go through the proofs/calculations, but, for even $N$, the paper arrives at the relation:\n", "\n", "

\n", "$$e^{i \\alpha \\hat{x}_k^N} \\ = \\ e^{2i \\alpha \\hat{p}_j \\hat{x}_k^{N/2}} e^{i \\alpha \\hat{x}_j^2} e^{-2i \\alpha \\hat{p}_j \\hat{x}_k^{N/2}} e^{-i \\alpha \\hat{x}_j^2} e^{-2i \\alpha \\hat{x}_j \\hat{x}_k^{N/2}}$$\n", "

\n", "\n", "So for the case of $N \\ = \\ 4$, we get:\n", "\n", "

\n", "$$e^{i \\alpha \\hat{x}_k^4} \\ = \\ e^{2i \\alpha \\hat{p}_j \\hat{x}_k^{2}} e^{i \\alpha \\hat{x}_j^2} e^{-2i \\alpha \\hat{p}_j \\hat{x}_k^{2}} e^{-i \\alpha \\hat{x}_j^2} e^{-2i \\alpha \\hat{x}_j \\hat{x}_k^{2}} \\ = \\ e^{2i \\alpha \\hat{p}_j \\hat{x}_k^{2}} e^{i \\alpha \\hat{x}_j^2} e^{-2i \\alpha \\hat{p}_j \\hat{x}_k^{2}} e^{-i \\alpha \\hat{x}_j^2} F^{\\dagger}_j e^{-2i \\alpha \\hat{p}_j \\hat{x}_k^{2}} F_j$$\n", "

\n", "\n", "The paper also gives as an identity:\n", "\n", "

\n", "$$e^{i3\\beta^2 t \\hat{p}_k \\hat{x}_j^2} \\ = \\ e^{i2\\beta \\hat{x}_j \\hat{x}_k} e^{i t \\hat{p}_k^3} e^{-i \\beta \\hat{x}_j \\hat{x}_k} e^{-i t \\hat{p}_k^3} e^{-i2\\beta \\hat{x}_j \\hat{x}_k} e^{i t \\hat{p}_k^3} e^{i \\beta \\hat{x}_j \\hat{x}_k} e^{-i t \\hat{p}_k^3} e^{i \\beta^3 t \\frac{3}{4} \\hat{x}^3_j}$$\n", "

\n", "$$\\Rightarrow \\ e^{i3 t \\hat{p}_k \\hat{x}_j^2} \\ = \\ e^{i2 \\hat{x}_j \\hat{x}_k} e^{i t \\hat{p}_k^3} e^{-i \\hat{x}_j \\hat{x}_k} e^{-i t \\hat{p}_k^3} e^{-i2 \\hat{x}_j \\hat{x}_k} e^{i t \\hat{p}_k^3} e^{i \\hat{x}_j \\hat{x}_k} e^{-i t \\hat{p}_k^3} e^{i t \\frac{3}{4} \\hat{x}^3_j} \\ = \\ e^{i2 \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{-i t \\hat{x}_k^3} F e^{-i \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{i t \\hat{x}_k^3} F e^{-i2 \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{-i t \\hat{x}_k^3} F e^{i \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{i t \\hat{x}_k^3} F e^{i t \\frac{3}{4} \\hat{x}^3_j}$$\n", "

\n", "$$\\Rightarrow e^{i \\omega \\hat{p}_k \\hat{x}_j^2} \\ = \\ e^{i2 \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{-i \\frac{\\omega}{3} \\hat{x}_k^3} F e^{-i \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{i \\frac{\\omega}{3} \\hat{x}_k^3} F e^{-i2 \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{-i \\frac{\\omega}{3} \\hat{x}_k^3} F e^{i \\hat{x}_j \\hat{x}_k} F^{\\dagger} e^{i \\frac{\\omega}{3} \\hat{x}_k^3} F e^{i \\frac{\\omega}{4} \\hat{x}^3_j}$$\n", "

\n", "\n", "So we have a method to implement gates of the form $e^{i \\alpha \\hat{p}_k \\hat{x}_j^2}$, as well as gates of the form $e^{i \\alpha \\hat{x}_k \\hat{x}_j^2}$ (all we have to do is use a couple Fourier gates). I know, it's a bit of a mess, but we'll break it down, and implement it into our simulation in chunks. We can start by creating a function that generates this specific gate:" ] }, { "cell_type": "code", "execution_count": 211, "metadata": {}, "outputs": [], "source": [ "#Implementing the sub-component gate involved in quartic decomposition\n", "\n", "def crazy_gate(omega, q, selector):\n", "\n", " Vgate(0.25*3*hbar*omega) | q[selector+1]\n", " Rgate(math.pi/2) | q[selector]\n", " Vgate(hbar*omega) | q[selector]\n", " Rgate(-1*math.pi/2) | q[selector]\n", " CZgate(hbar) | (q[selector], q[selector+1])\n", " Rgate(math.pi/2) | q[selector]\n", " Vgate(-1*hbar*omega) | q[selector]\n", " Rgate(-1*math.pi/2) | q[selector]\n", " CZgate(-2*hbar) | (q[selector], q[selector+1])\n", " Rgate(math.pi/2) | q[selector]\n", " Vgate(hbar*omega) | q[selector]\n", " Rgate(-1*math.pi/2) | q[selector]\n", " CZgate(-1*hbar) | (q[selector], q[selector+1])\n", " Rgate(math.pi/2) | q[selector]\n", " Vgate(-1*hbar*omega) | q[selector]\n", " Rgate(-1*math.pi/2) | q[selector]\n", " CZgate(2*hbar) | (q[selector], q[selector+1])\n", " \n", " return q" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then construct a function that returns the quartic gate:" ] }, { "cell_type": "code", "execution_count": 212, "metadata": {}, "outputs": [], "source": [ "#Defining the quartic gate, in terms of a decomposition\n", "\n", "def quartic_gate(q, alpha, selector):\n", "\n", " Rgate(math.pi/2) | q[selector+1]\n", " crazy_gate(-2*alpha, q, selector)\n", " Rgate(math.pi/2) | q[selector+1]\n", " Pgate(-2*hbar*alpha) | q[selector+1]\n", " crazy_gate(-2*alpha, q, selector)\n", " Pgate(2*hbar*alpha) | q[selector+1]\n", " crazy_gate(2*alpha, q, selector)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And that concludes our small detour! Now, let us turn our attention to the function that we wish to optimize, which is:\n", "\n", "

\n", "$$f(x, \\ y) \\ = \\ 0.5x^4 \\ - \\ 8x^2$$\n", "
\n", "$$\\text{min} \\ f(x, \\ y) \\ = \\ -32 \\ \\Rightarrow \\ x \\ = \\ \\pm \\ 2 \\sqrt{2}$$\n", "

\n", "\n", "Excellent, so we can now implement our simulation one more time. As usual, we first have to define our value of Planck's constant, ass well as our classical cost function, which will be given as:" ] }, { "cell_type": "code", "execution_count": 224, "metadata": {}, "outputs": [], "source": [ "#Defining the value of h-bar\n", "\n", "sf.hbar = 1\n", "hbar = 1\n", "\n", "#Defining the classical cost function that we are trying to optimize\n", "\n", "def function_optimize(x1):\n", " y = 0.5*(x1**4) - 8*(x1**2)\n", " return y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define our cost and mixer unitaries:" ] }, { "cell_type": "code", "execution_count": 225, "metadata": {}, "outputs": [], "source": [ "#Defining the cost unitary to be used in QAOA\n", "\n", "def cost_ham(q, p):\n", "\n", " quartic_gate(q, -0.5, 0)\n", " Pgate(16*hbar*p) | q[0]\n", "\n", "#Defining the kinetic mixer unitary to be used in QAOA\n", "\n", "def mixer_ham(q, p):\n", "\n", " Rgate(-1*math.pi/2) | q[0]\n", " Pgate(-1*hbar*p) | q[0]\n", " Rgate(math.pi/2) | q[0]\n", "\n", " return q" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We then define our parameters, and our numerical circuit simulator:" ] }, { "cell_type": "code", "execution_count": 226, "metadata": {}, "outputs": [], "source": [ "#Defining the depth of the QAOA circuit to be constructed, the squeezing parameter, and the cutoff dimension\n", "\n", "circuit_depth = 10\n", "squeezing = -0.5\n", "cutoff = 7\n", "\n", "\n", "# Defining the function that simulates the circuit, and returns the results\n", "\n", "def run_circuit(param):\n", "\n", " eng = sf.Engine(\"fock\", backend_options={\"cutoff_dim\":cutoff})\n", " prog = sf.Program(2)\n", "\n", " param1 = [param[0] for i in range(0, circuit_depth)]\n", " param2 = [param[1] for i in range(0, circuit_depth)]\n", "\n", " with prog.context as q:\n", "\n", " Squeezed(squeezing,0) | q[0]\n", "\n", " for i in range(0, circuit_depth):\n", "\n", " cost_ham(q, param1[i])\n", " mixer_ham(q, param2[i])\n", "\n", " state = eng.run(prog, run_options={\"eval\": False}).state\n", " a = state.wigner(0, [i/100 for i in range(-500, 500)], [i/100 for i in range(-500,500)])\n", "\n", " return a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now here is where things get interesting........." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**I Promise This is Our Last Detour: Numerically Calculating the Cost Hamiltonian Expectation Value**
\n", "\n", "The next step of our simulation should be to define our objective function, which we will minimize. Usually we would od this through finite sampling, but in thi case, we will try something new.\n", "\n", "Our cost Hamiltonian is of the form:\n", "\n", "

\n", "$$H_{C} \\ = \\ \\hat{x}^4 \\ - \\ 8\\hat{x}^2$$\n", "

\n", "\n", "Thus, when QAOA terminates for each iteration, we want to find, for the prepared state vector $|s\\rangle$:\n", "\n", "

\n", "$$\\langle H_{C} \\rangle \\ = \\ \\langle s | 0.5\\hat{x}^4 \\ - \\ 8\\hat{x}^2 | s \\rangle$$\n", "

\n", "\n", "Usually, we would have to sample the circuit repeatedly to obtain this expectation value. However, we're going to be sneaky for this simulation, because sampling a circuit this deep will take a nightmarishly long time (not really, but I'm super impatient). We have:\n", "\n", "

\n", "$$\\langle s | 0.5\\hat{x}^4 \\ - \\ 8\\hat{x}^2 | s \\rangle \\ = \\ 0.5 \\langle s | \\hat{x}^4 | s \\rangle \\ - \\ 8 \\langle s |\\hat{x}^2 | s\\rangle \\ = \\ 0.5 \\displaystyle\\int \\langle s | x \\rangle \\langle x | dx \\ \\hat{x}^4 \\displaystyle\\int |y \\rangle \\langle y | s \\rangle dy \\ - \\ 8 \\displaystyle\\int \\langle s | x \\rangle \\langle x | dx \\ \\hat{x}^2 \\displaystyle\\int | y \\rangle \\langle y | s\\rangle dy$$\n", "
\n", "$$\\Rightarrow \\ 0.5 \\displaystyle\\int \\displaystyle\\int x^4 \\langle s | x \\rangle \\langle x |y \\rangle \\langle y | s \\rangle \\ dy \\ dx \\ - \\ 8 \\displaystyle\\int \\displaystyle\\int x^2 \\langle s | x \\rangle \\langle x |y \\rangle \\langle y | s\\rangle \\ dy \\ dx \\ = \\ 0.5 \\displaystyle\\int x^4 \\langle s | x \\rangle \\langle x | s \\rangle \\ dx \\ - \\ 8 \\displaystyle\\int x^2 \\langle s | x \\rangle \\langle x | s \\rangle \\ dx$$\n", "
\n", "$$\\Rightarrow \\ 0.5 \\displaystyle\\int x^4 |\\langle x | s \\rangle|^2 \\ dx \\ - \\ 8 \\displaystyle\\int x^2 |\\langle x | s \\rangle|^2 \\ dx$$\n", "

\n", "\n", "This tells us something very useful. Essentially, we already know $|\\langle x | s \\rangle|^2$, this is just the $x$-quadrature probability values. We also already know how to integrate over it numerically, thus, while we take this integral, we simply have multiply either $x^2$ or $x^4$ inside the integrand, and then put the obtained values back into this formula to get the expectation value of the cost Hamiltonian by only evaluating the circuit once! This, technically, is cheating, but we are just experimenting, so I'm going to accept that this is allowed.\n", "\n", "Based on what we have just found, we define our new, **numerical** objective function:" ] }, { "cell_type": "code", "execution_count": 227, "metadata": {}, "outputs": [], "source": [ "#Defining the objective function that will be minimized by the optimizer\n", "\n", "def new_objective(param):\n", "\n", " av = run_circuit(param)\n", "\n", " y = []\n", " x = [i/100 for i in range(-500, 500)]\n", " for i in range(0, len(x)):\n", " res = simps([av[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", " norm_factor = simps(y, x)\n", " y = [y[i]/norm_factor for i in range(0, len(y))]\n", "\n", " first_x_2 = [(x[i]**2)*y[i] for i in range(0, len(x))]\n", " first_x_4 = [(x[i]**4)*y[i] for i in range(0, len(x))]\n", "\n", " i2 = simps(first_x_2, x)\n", " i3 = simps(first_x_4, x)\n", "\n", " calculation = 0.5*i3 - 8*i2\n", "\n", " print(\"Value of Cost Function: \"+str(calculation))\n", "\n", " return calculation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, we run the numerical circuit simulator once, and integrate to get expectation values for $x^4$ and $x^2$. You should also notice that we normalize our data points before integrating. This is just due to quartic gates leading to highly unnormalized final states, with ridiculously small values as data points. This leads to Python occasionally getting confused, and thinking it is dividing by $0$ (yes, the probabilities get that small). To get around this issue, we simply normalize the data before we calculate the expectation values.\n", "\n", "Finally, we define our optimizer and our visualization:" ] }, { "cell_type": "code", "execution_count": 228, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value of Cost Function: -14.734068693168158\n", "Value of Cost Function: -17.930193380724567\n", "Value of Cost Function: -20.093765483118634\n", "Value of Cost Function: -18.698065406581467\n", "Value of Cost Function: -15.811369770776526\n", "Value of Cost Function: -18.995351697864237\n", "Value of Cost Function: -19.847406828613828\n", "Value of Cost Function: -21.312945562458165\n", "Value of Cost Function: -18.902524037664346\n", "Value of Cost Function: -21.251191041874723\n", "Value of Cost Function: -20.091239240508703\n", "Value of Cost Function: -20.595074750185233\n", "Value of Cost Function: -21.417078158874855\n", "Value of Cost Function: -20.824062080423104\n", "Value of Cost Function: -21.39646803297549\n", "Value of Cost Function: -20.895055242608997\n", "Value of Cost Function: -21.200454402697652\n", "Value of Cost Function: -21.480567520829833\n", "Value of Cost Function: -21.48280024797965\n", "Value of Cost Function: -21.48828950990507\n", " fun: -21.48828950990507\n", " maxcv: 0.0\n", " message: 'Maximum number of function evaluations has been exceeded.'\n", " nfev: 20\n", " status: 2\n", " success: False\n", " x: array([0.25413526, 3.63197931])\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEDCAYAAADQunSaAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3dd3iUVd7/8fc3vfcQSCcQSggQSOiIoqgoCCoWFFHUFVz7rmXX1W3PrruuPuuqq65iFxU7ogIiCBY6CRCSkAChBNIbaaTPnN8fCf6yPrSQmblnJud1XblMptz3Z2TyzZlznyJKKTRN0zTn5GJ0AE3TNM16dJHXNE1zYrrIa5qmOTFd5DVN05yYLvKapmlOTBd5TdM0J2Z3RV5E3hCRchHJtsCxUkRks4jkiMhuEbm+y30XisgOEckWkbdFxK2n59M0TbM3Ym/j5EVkCtAAvKOUSu7hsQYBSim1X0QigQxgKFAHFAAXKaX2icj/AAVKqdd7GF/TNM2u2F1LXin1A1Dd9TYRGSAiX4tIhoj8KCJDzvJY+5RS+zu/LwbKgXAgFGhVSu3rfOgaYI7FXoSmaZqdsLsifwqLgXuVUqnAQ8BL3T2AiIwFPIADQCXgJiJpnXdfA8RYKKumaZrdsPt+aBHxAyYCH4vIiZs9O++7GvifkzytSCl1aZdj9AOWALcopcydt80F/iUinsA3gMlqL0LTNM0gdl/k6fi0UaOUSvn5HUqpz4DPTvdkEQkAVgCPKaW2dHnuZuC8zsdcAgyyZGhN0zR7YPfdNUqpOuCQiFwLIB1Gns1zRcQDWEbHRdxPfnZfn87/egK/AV62aHBN0zQ7YHdFXkSWApuBwSJSKCK3A/OA20UkE8gBZp/l4a4DpgALRGRX59eJTwQPi0gusBv4Uim1zrKvRNM0zXh2N4RS0zRNsxy7a8lrmqZplmNXF17DwsJUfHy80TE0TdMcSkZGRqVSKvxk99lVkY+Pjyc9Pd3oGJqmaQ5FRApOdZ/urtE0TXNiushrmqY5MbvqrtF67h/b/gHAb8b+htqmNl75/gDf5pbTZjYzPiGUX54/gJgQH4NTalqnVb/t+O9lTxqbw4npIu9k8qrzAMgvb+CWN7ZRUtvEpIFheLm78mlGIZ/vLOK5uaO4OCnC4KSaBpRmGZ3A6eki74TaTGZufHULZgWf3TWJlJggAIpqmvjluxnc9V4GbywYw3mJJ70Yr2maE9F98k4ov6KBuuY2ltw+9qcCDxAV5M27vxjHwD7+3Lkkg8OVxw1MqWmaLegi72TK61qobWzjDzOHMbRfwP+5P8DLnddvScPN1YX7P9xFm8lsQEpN02xFF3knUt/cxtFjjQR4uXPD2FMvjx8Z5M3frhpO5tEa3t502HYBNU2zOV3kncirPxykzWQmLtSHLmvvn9SMEf24cEgfnl27n/K6Zhsl1DTN1nSRdxLHW9p5e3MBIb4e+Hqe3fX0P8xMorXdzJNf51k5naZpRtFF3kl8uP0otU1tRAZ5n/Vz4sN8uXVyPMt2FrGvrN6K6TRNM4ou8k6g3WTm9Q2HGBsfgt9ZtuJPuHPKAHw93Hjmm31nfrCmaQ5HF3kn8MP+Copqmrhtcny3nxvs68Htk/vzdU4pWYW1lg+naZqhdJF3Ah9tLyTMz4OLhp7bLNbbz+tPkI87/1yz18LJNE0zmi7yDq6qoYW1uWVcNSoKd9dz++cM8HJn4ZQEvttbwY4jxyycUNM0I+ki7+CW7Syi3ay4Nu3U4+LPxi0T4gnx9eDZtfstlEzTNHugi7yD+ySjkJSYIAZF+PfoOL6ebiycksAP+yrIKNCteU1zFrrIO7D88nrySuu5MiXSIsebPz6uszWvR9polmUyKz7fWcT9H+zkl+9m8PqGQzS0tBsdq1ew+iqUIuIKpANFSqmZ1j5fb7JidykicPnwfhY5nq+nG4umJPD3VXlkFFSTGhdikeNqvVtxTRN3vpvB7sJaIgI88XZ3ZVV2Ka/9eJA1we3dHvardY8tWvL3A7k2OE+vszKrhDFxIfQJ8LLYMedPiCNU981rFlJe18y1L2/mUMVx/n3DKLY8ehHfPTyVT385EVcXYU9JnW7RW5lVi7yIRAMzgNeseZ7eKL+8gb1l9Vw+vK9Fj+vj4cai8xP4cX8l6YerLXpsrXdpbjNx61vbqWls5f07xnPFyMif1lRKjQvm019OxM1F2FtWz7HjrQandV7Wbsk/CzwCnHI9WxFZKCLpIpJeUVFh5TjOY2VWCSJwmYW6arq6aXwcYX4ePPetbs1r5+6ZNfvIKa7j+RtGMTw68P/cHxHgxeC+/rSbzPzpyxwDEvYOVivyIjITKFdKZZzucUqpxUqpNKVUWni43qnobK3MKiEtLpgIC3bVnODj4caiKQN0a147Z9sPV/Pqjwe5cVzsaSfp+Xq4ERXkzfJdxazfW27DhL2HNVvyk4BZInIY+AC4UETeteL5eo2CquPkldYzPdnyrfgT5o2PJcxP981r3WcyK/6wPIfIQG8eu3zoGR8fGeRNfKgPT67Mw2RWNkjYu1ityCulHlVKRSul4oG5wDql1E3WOl9v8m1uR4tn2tA+VjuHj4cbd54/gA35lWzXrXmtGz7dUUhuSR2/uWzIWS177SLCI9OHsLesnk93FNogYe+ix8k7oHV55Qzs40dcqK9VzzNvXBxhfp78Y1UeSukWlnZmja3t/PObvaTEBHHFiLP/pHlZcl+SowJ4+fsDujVvYTYp8kqp7/QYecuob25j66EqLhpivVb8Cd4erjx86SDSC46xbGeR1c+nOb53NhdQVtfC4zOGnnF3sq5EhDvPH8DBiuOs2VNqxYS9j27JO5gN+ytpM6lzXnGyu65NjSElJoi/rcyltqnNJufUHFNzm4nXfjzIeYlhpMV3fyLdZcn9iAv14aXvDuhPjhaki7yDWZtbTqC3O6Njg2xyPhcX4S+zk6k63sqTq/Q2gdqpfbDtCJUNrdwzdeA5Pd/VRfjFeQnsLqxl19EaC6frvXSRdyAms+K7veVcMDgct3NcVvhcDI8OZOF5CSzddoQ1e8psdl7NcbS2m3nlh4OMiQ9mXELoOR/nqlFR+Hq48t7WIxZM17vpIu9AMgtrqDrearOumq5+fckgkvoF8JtPd1Ne12zz82v27bMdhZTUNnP3ObbiT/DzdGP2qCi+zCymtlF3D1qCLvIOZF1uOa4uwvmJtp805unmyvM3pNDUamLhkgya20w2z6DZp3aTmf98f4DhUYGcP6jn780bx8bS0m7ms516OKUl6CLvQNbmlpEWF0ygj7sh5x/Yx59/XZ/CrqM1PPhRph7qpgGwIquEgqpG7p46sFsjak4lOSqQlJgglm47oi/AWoAu8g6iqKaJvNJ6LrLiBKizMT25L49dPpQVWSX8+qNdtJtOuSyR1guYzYoX1+eT2MePS5Is1414bVo0+8oayCmus9gxeytd5B3EuryOWa5G9Mf/3B1TEnj40sEs31XMPe/vpKlVd930Vmtzy9hX1sDdUwfi4tLzVvwJM4b3w8PVhc926PkZPaWLvINYl1tGXKgPCWHWneV6tu6eOpDfz0xi9Z5SrntlM6W1+mJsb6NURys+NsSHmd2Y3Xo2gnw8mDoknC8yi/WnxR7SRd4BNLWa2HSgiguH9LFIn6el3D65P6/dnMbBigaueGEDGQV6jZveZGN+FZmFtdx5/gCrDOm9alQ0lQ0t/JhfafFj9ya6yDuAzQcraWk3c6ENljLorouGRrDs7kn4ergyd/EW3ttaoC+W9RIvrN9PRIAnc1KjrHL8qUPCCfR2Z5nusukRXeQdwLq8cnw8XBnb3z73XB0U4c/yuyczaWAYjy3L5tHPsmhp1/30ziyjoJotB6u547wEPN1crXIOTzdXZo7oxzd7SvUWgT2gi7ydU0qxPq+CSQPDrPbLZAmBPu68fssY7pk6kA+2H+X6V7bofnonpZTif1fvI9TXgxvHxVr1XFePjqK5zczX2XrRsnOli7yd21fWQFFNk1121fycq4vw0KWDefmm0ewrq2fOfzZRUHXc6FiahW3Ir2TzwSruuXAgPh5nXi++J0bHBhMd7M0XmcVWPY8z00Xezp3YEm3qYPsv8idMT+7HR4sm0NjaznWvbOZgRYPRkTQLMZsVT329l+hgb6u34qFjCeLZKZFszK+kor7F6udzRrrI27l1eeUM7RdA30DL7+VqTclRgXywcAIms2L+69v0ejdOYnlmEVlFtfxq2iCbdR/OTonCZFaszCqxyfmcjS7ydqy2sY2MgmNcOMQxNzgf3NefNxeM5VhjKwve3E59s15wypHVNrbxxIpcUmKCuGqUdUbUnMygCH+G9PXn8116lM250EXejv2wvwKTWTlEf/ypDI8O5D83pbK3rJ6HPs7Uwysd2FOr86g+3spfr0y26OzWszE7JYqdR2o4UtVo0/M6A13k7dj6vHKCfdxJiQk2OkqPnD8onEcvG8LqnDJe+eGg0XG0c7B2TxnvbT3CbZP6kxwVaPPzXzGyY0btF5m6Nd9dusjbKZNZ8d2+Cs4fFI6rjVtN1nD75P7MGN6Pp77OY9MBPYPRkRTXNPHwJ5kMiwzg4emDDckQHezDmPhgPt9VrD8NdpMu8nYqs7CG6uOtTHXgrpquRIR/XDOC+DBffv1hJjWNrUZH0s5CbWMbC97cRptJ8fwNowydqzErJYr88gZyS+oNy+CIdJG3U9/lleMiWGQTBnvh5+nGc9ePorKhhceWZesWmZ0rr2/mxte2cKjyOIvnpzIg3M/QPDOG98PNRViuu2y6RRd5O7Umt5zUuGCCfDyMjmJRw6MD+fUlg1iRVcKnek0Su/X9vgpm/XsjByuOs/jmNCYODDM6EiG+HpyXGMaXu4ox6w1rzpou8nboaHUjuSV1XDqsr9FRrGLRlAGM7R/CH5dn69ESdqS5zcTX2aXc+OoWbnljG76ernx85wS7mog3OyWK4tpm0guOGR3FYVh3TrJ2Tr7ZUwbAxRbcaceeuLoI/7o+henP/sADH+7ko0UTrLJUrXZqzW0m8krryS6qJae4lpziOvJK62ltNxPm58njM4Zy0/g4vNzta72ki5Mi8HZ3ZfmuIrtdsM/e6CJvh1bnlDKkrz9xofaxQYg1RAV588RVw7lv6U6e+3Y/D15izKiN3qS0tpllO4tYl1fGjiM1P+3RG+jtTnJUAAsmxjMlMZxxCSG42+kfXV9PNy5OimBFVgl/vGIYHm72mdOe6CJvZ6oaWkg/XM09UwcaHcXqZo2M5Id9FbywPp+JA8KYMCDU6EhO6WBFA/9au59VWSW0mxXJUQEsmpLAiOgghkUGEB3sbVeb0ZzJ7JRIvsgsZkN+BRcOcc5Pu5Zk1SIvIjHAO0AEoIDFSqnnrHlOR/dtXjlmBZc4aX/8z/151jAyCo7xqw93ser+8wj2da4LzUZqbjPx9Oq9vL3pMJ5uLiyYGM/8CXEO/wnxvMRwgnzcWb6rWBf5s2DtzzrtwINKqSRgPHC3iCRZ+ZwO7ZucMiIDvRgWGWB0FJvw9XTj+bmjqDrewsOf7NajJixkf1k9s1/YyOsbDnFtWgzfPTyVx2cmOXyBB/Bwc+Hy4f34JqeMxla9mciZWLXIK6VKlFI7Or+vB3IB261s5GAaW9v5cX8Flwzr61Afn3tqeHQgj142lLW5ZTz77X6j4zg0pRQfbT/KFS9soLKhhbduHcPfrx5OuL+n0dEsavbISJraTKzpHKSgnZrNrlqISDwwCtj6s9sXiki6iKRXVFTYKo5dWptbTku7menJvaOrpqtbJ8VzbWo0z3+7ny/1BhHnpL65jQc+3MUjn+5mdGwwq+4/jwvsaPijJY2JD6FfoBdf7NLvlTOxSZEXET/gU+ABpVRd1/uUUouVUmlKqbTwcOeZ3XkuvswsJiLAk7HxvW9omIjw16uSGRMfzIMfZ/Lj/t79B7+7dhfWMPPfG/gys5iHLhnEktvH0SfAsfYg6A4XF2HWyEi+31fBseN6iYzTsXqRFxF3Ogr8e0qpz6x9PkdV29TG93srmDki0ubLuNoLTzdXFs9PIyHMl1+8nc6G/XohszMxmxWv/nCQOf/ZRGu7mQ8XTeCeCxOdYlG7M5mVEkm7WbEyW28mcjrWHl0jwOtArlLqGWuey9Gt2VNGq8nMzBH9jI5iqGBfD96/Yzw3vrqFW9/axl9mJzN3rPW3meuqzWRmy8EqdhfWUnisCXdXISHMl6lD+tjVhcvS2mYe/HgXG/OruCQpgqeuGeF0y2CcTlK/AAb28WP5rmLmjYszOo7dsvY4+UnAfCBLRHZ13vY7pdRKK5/X4XyZWUx0sDcpMUFGRzFciK8HHy6cwL0f7OS3n2Wx+WAVf7xiGCFWHl557Hgrr204yPtbj3CssWMXq1BfD1pNZuqb2/nTl3uY0rk2/tB+xo1+MpsVH6Uf5e+r8mhtN/Pk1cO5fkxMr7pYD537v46M5J9r9lFc00RkkLfRkeySVYu8UmoD0Lveeeeg+ngrG/IrWTglodf9op5KoI87b9ySxovrD/DC+v18t7eC2yf355aJ8QR6u1v0XCeK+1sbD9PYZuLSpL5cPTqKCQNC8fdyRylF4bEmlu8q4tUfDzHj+R+5Z+pA7rso0ebLMWQereHPX+aw40gNY+NDeHLOcBIMXh3SSLNSOor8F5nF3Hn+AKPj2CU949UOLN9VhMmsmJ0SaXQUu+Lm6sL90xKZntyXp1fn8cyafby4Pp9pSRHMHN6PCQNCe9Q9UX28lVd/PMg7mzqK+4zh/bjvokQGRfj/1+NEhJgQH+65MJGbxsfxl69yeX5dPtsPH+Plm1IJ9LHsH52TySqs5dm1+/g2r5xQXw/+ee1Irh4d1esbBXGhvqTEBPHZjkIW6UbSSekibwc+Si9kRHQgQ/r2jglQ3TW4rz+v3TKG7KJaPko/yle7S1ixuwQRGNo3gLT4YJIjA0mOCiQxwu+0664opcgqquXj9EI+3VFIU5uJy4f34/6TFPeTCfLx4J/XjWTCgFAe/Ww3c17exJsLxhAT4mPJl/yT7KJanl27n7W5ZQR6u/PwpYO5ZWI8fp76V/eEG8bG8JtPs9h++JhetOwk9DvFYNlFteSW1PGX2cOMjmL3kqM6CvnvZyaxu7CGTflVbDpQxWc7inhncwHQMRtyQLgf0cHeRAd7E+jtjpuLcKyxjaPVjew4cozKhlY83VyYMbwfd00dwMA+Zy7uP3dNajRRQd4sWpLOVS91FPrh0Zbb+3RPcR3Prt3HN3vKCPBy48GLB7FgUjz+Xtb/1OBorhgZyV9X5PLulgJd5E9CF3mDfZx+FA83F2aN1BOBz5a7qwupcSGkxoVw70WJmM2Kw1XHyS6uI7uolvzyBgqqjrMxv5LGVhMAPh6u9A3wYkpiOOMTQrk0uW+P+/YnDAjl019OZMGb27nulc28OG9Uj9dSySut49k1+/k6pxR/LzcemJbIbZP7E6CL+yn5eLhxTWo0724poKI+yelm9/aULvIGam4zsTyzmOnD+tqkX9dZubgICeF+JIT7MWvkf1/XMJsV7WZltSVpEyP8WXb3RG57azu/eDudv145nBvHdX/I597Sep77dh8rs0rx93TjvosSuX1yf4tfZHZW88bF8ebGw3yUfpS7e8EKrt2hi7yBvsgspqaxjRtsPA68N3FxETysPDGoj79Xx5DPpTv53bIsdh45xh9nDTurfvP9ZfU89+1+VmSV4Ovhxr0XDuT2yf171Xh3SxjYx4+JA0J5f+sRFk5JsNv18I2gi7xBlFK8tfEwgyP8GZ+g+xEdna+nG4vnp/Ls2v289F0+mw9W8dAlg7liZOT/mX1qMis2H6jijY2HWJdXjq+HK3ddMIBfTE7QSy33wK2T+nPHO+ms2F3ClaN09+cJusgbJL3gGHtK6vjbVcP1sC8n4ebqwkOXDmbKoHD+sDybBz7cxd9W5nJeYjhxoT60mxUHKxrYcrCKyoZWwvw8eGBaIjdPiLf6RK/e4KIhfUjs48fL3x9gdkqk/r3qpIu8Qd7aeJhAb3euHKXHxjubsf1DWHnfeXyzp4xlOwv5YX8FFTtaAIgJ8e648DusLxcnRdjdHqqOzMVFWDglgYc/2c33+yqcdgXO7tJF3gAHKxpYlV3CHVMS8PHQ/wTOyMVFmJ7c96dlo1vbzbgIesNyK5udEsUza/bx8vcHdJHvpN9xBnhx/QE83Fz4xeQEo6NoNuLh5qILvA14uLlw++T+bDlYzeYDVUbHsQv6XWdjR6oa+XxXETeMjdXjeTXNCm4aH0ffAC+eWp2HUno7SV3kbeyF9ftxdRG9mJKmWYmXuysPTEtk55Ea1uaWGx3HcLrI29Ce4jo+zijkpnFxRDjxrj2aZrRrUqNJCPPlH1/n0WYyGx3HULrI24hSiidW7iHQ2537L0o0Oo6mOTU3Vxd+d/lQ8ssbeH3DIaPjGEoXeRtZm1vOxvwqHrgoUS9hoGk2MC0pgmlDI3hu7X6KapqMjmMYXeRtoK65jd9/ns2gCD/mjdfblGmarfxpVhIAjy/L6rUXYXWRt4G/r8ylvL6Zp68ZqdfU0DQbig724ZHpg1m/t4IlWwqMjmMIXXGsbFVWCUu3HeWOKQmM1Pu3aprNLZgYzwWDw3liRS57S+uNjmNzushb0aHK4zz8yW5SYoJ48OLBRsfRtF5JRHj6mpH4e7lzxzvpVB9vNTqSTekibyVVDS3c9tZ23FyFF+eNttp65pqmnVm4vyeLb06lrK6Zhe+k09xmMjqSzejKYwV1zW3c9nY6xTVNvHZzGlFB3kZH0rReb3RsMM9cl0J6wTHufDej1xR6XeQtrPp4K/Ne3UpOUS3/vmEUafF6rXhNsxczRvTjyauH8/2+Cm5/ezv1zW1GR7I6XeQtKLuoltkvbmBfWT2v3pzGJcP6Gh1J07SfmTs2lv+9ZiRbDlZz5YsbyS9vMDqSVekibwHtJjOvbzjEnP9sot2k+GDheKYO0cucapq9mpMazbu3j6OmsY1ZL2zgzY2HMJmdcxy9LvI9oJTi+30VzH5xI3/5ag8TB4Ty5b2TGRUbbHQ0TdPOYMKAUL66bzJj4kP485d7mP3iBtbvLXe6SVN6x4pzUNvUxordJSzddoSsoloiA714ad5oLkvuq7cc0zQH0i/Qm7duHcMXmcU8vXovt765naR+AdwwNoZZI6OcYgkSqxd5EZkOPAe4Aq8ppZ609jktrbapjbySOjKOHGPD/krSDx+j1WQmsY8ff796OHNGR+shkprmoESE2SlRXJbcj093FPLulgJ+vzyHP325h9GxQUxJDCclNohhkYEOuRevVYu8iLgCLwIXA4XAdhH5Qim1x5LnaTOZaWozYTYrzApMZoVSCpNSnd933GZWHV8mM53/VRxvaed4azvHW0wcb2mnoaWdivoWSmqbKa1rprC6keLa5p/ONaSvP7dMjOOKkZEMjwrULXdNcxIebi7cMDaWG8bGkl1Uy9fZpXy/r4J/rtn302PC/T2JDvYmMsibqCBvgnzcCfByJ8DbnQAvN7zdXXF3c8HD1QUPNxfcXV1wdxXcXV0QAAEXEYTO/woIgriAh6uLVfb8tXZLfiyQr5Q6CCAiHwCzAYsW+dU5pdzz/k6LHc/DzYW+AV70DfRibP8QBvcNYEg/f4ZHBRLmp3dz0jRnlxwVSHJUIA9dOpiaxlb2FNeRU1zHvrJ6imubyCmqZc2eMlrbLbdW/Z3nD+C3lw2x2PFOsHaRjwKOdvm5EBjX9QEishBYCBAbG3tOJ0nqF8DjM4biIoKri+AiHRspu4jgKtL5Pbi6CHLits6ffTzc8PV0xc/TDd/OrwAvN4dtoQ8JsfybRNOspu9woxOcUZCPBxMHhjFxYNh/3a6UoqXdTF1TG3XNbdQ2tdHcZqbVZKat3UybSdFm6vzZZEYpUB1PxKw6nm/uvE0pxYho66xtJda8kiwi1wDTlVK/6Px5PjBOKXXPyR6flpam0tPTrZZH0zTNGYlIhlIq7WT3WftqYREQ0+Xn6M7bNE3TNBuwdpHfDiSKSH8R8QDmAl9Y+ZyapmlaJ6t21wCIyOXAs3QMoXxDKfXEaR5bATjiyv5hQKXRIWxMv+beQb9mxxCnlAo/2R1WL/K9gYikn6o/zFnp19w76Nfs+PQMHk3TNCemi7ymaZoT00XeMhYbHcAA+jX3Dvo1OzjdJ69pmubEdEte0zTNiekir2ma5sR0kbcwEXlQRJSIhJ350Y5NRJ4WkTwR2S0iy0TEOotvGExEpovIXhHJF5HfGp3H2kQkRkTWi8geEckRkfuNzmQrIuIqIjtF5Cujs1iKLvIWJCIxwCXAEaOz2MgaIFkpNQLYBzxqcB6L67Jc9mVAEnCDiCQZm8rq2oEHlVJJwHjg7l7wmk+4H8g1OoQl6SJvWf8CHqFzsTlnp5T6RinV3vnjFjrWJnI2Py2XrZRqBU4sl+20lFIlSqkdnd/X01H0ooxNZX0iEg3MAF4zOosl6SJvISIyGyhSSmUancUgtwGrjA5hBSdbLtvpC94JIhIPjAK2GpvEJp6lo5FmuUXi7YDe47UbRGQt0Pckdz0G/I6OrhqncrrXrJRa3vmYx+j4iP+eLbNp1iUifsCnwANKqTqj81iTiMwEypVSGSJygdF5LEkX+W5QSk072e0iMhzoD2R2bjYSDewQkbFKqVIbRrS4U73mE0RkATATuEg556SLXrlctoi401Hg31NKfWZ0HhuYBMzqXFDRCwgQkXeVUjcZnKvH9GQoKxCRw0CaUsrRVrLrls5N2p8BzldKVRidxxpExI2Oi8oX0VHctwM3KqVyDA1mRdLRUnkbqFZKPWB0HlvrbMk/pJSaaXQWS9B98lpPvAD4A2tEZJeIvGx0IEvrvLB8D7CajguQHzlzge80CZgPXNj577qrs4WrOSDdktc0TXNiuiWvaZrmxHSR1zRNc2K6yGuapjkxuxpCGRYWpuLj442OoWma5lAyMjIqT7XHq9WLfOcwu+fo2Mj7NaXUk6d6bHx8POnp6daOpGma5lREpOBU91m1u6aXLu6kaZpmN6zdkv9pcScAETmxuNMeS56kqqGFLQeruWRYBO6u+jKD1nMms0SO/KgAACAASURBVKK8vpnyuhaa2ky0tptRgJ+nK36e7kQEeBLk42F0TE07I2sX+ZMt7jSu6wNEZCGwECA2NvacTrLxQBX3Ld3JV/dOJjkq8Byjar1Va7uZnUeOkV5wjOyiWnKK6yiqacJkPv0ckgAvN+LDfEmOCmRUTBBj4kOID/O1UWpNOzuGX3hVSi2mc+PctLS0c5qZNTq2Y6+KHUeO6SKvnZXjLe2s2VPGiqwSNuVXcrzVBEBcqA/JUQHMGhlJvyAvIvy98PFwxcOt4xNiQ0s7DS3tlNY2U1DVyMHKBr7MLOb9rR1bCCSE+XLhkD5cPqIfo2KC6FzLSNNO69m1+xgTH8KkgZbfa8jaRd4miztFBXkT7u/JjoJj3Dwh3tKH15xIVmEtb248xKrsUpraTEQGenHlqCimDApnfEIogd7u3T6m2aw4WNnApgNVrM0t553NBby24RAD+/hxTWo0c8fE6K4d7ZTqmtt47tv9PHDRIIcs8tuBRBHpT0dxnwvcaOmTiAijY4PYebTG0ofWnIBSijV7ynj1x4NsP3wMXw9XrhwVxVWjokiLC8bFpWetbRcXYWAffwb28efmCfHUN7exMquEj9MLeXJVHs9/u5/rx8Twi/MSiAryttCr0pxF5tEalILRcdbZPdOqRV4p1S4iJxZ3cgXesNbiTqNjg1mdU0ZlQwthfp7WOIXmgDbsr+Sp1XnsLqwlOtibx2cM5boxMQR4db/Ffrb8vdy5fkws14+JZW9pPa/8cIAlmwtYsrmAuWNjuP+iQYT76/eo1mFHQQ0ikBLjgEUeQCm1Elhp7fOMjgsGYOeRGi5OirD26TQ7l19ez5++2MOG/Eqigrx5+poRXDUqCjcbj74a3NefZ65L4aFLBvOf7w6wdNsRlu0o4s7zB3DHlAS83F1tmkezPzuOHGNQH3/8rdTwcJrxhsOjAnFzEXYeOWZ0FM1ATa0mnvo6j8ue+5HdhTX8fmYS6x46n2vTYmxe4LuKDPLmL1cm882vpjA5MYx/rtnHpc/+wMZ8p95yQDsDs1mx88gxq3XVgB2MrrEUL3dXkiID2KGLfK+17VA1D368i6PVTcwZHc2jlw+xu667hHA/Xpmfxqb8Sn63LIt5r23lmtRofj8jiUAf63UhafbpYGUDdc3tjIoNtto5nKYlDx398plHa2k3OdU+vNoZtLab+cfXeVy/eDMuInywcDz/vG6k3RX4riYODOPrB6Zw1wUD+HxnEdOf+4EtB6uMjqXZ2I6CjsEio3WRPzujYoNoajORV1pvdBTNRg5UNHDVSxv5z3cHuD4thpX3ncf4hFCjY50VL3dXHpk+hE9/OREvd1dueHULT6/Oo003UnqNjIJjBPm4k2DFSXROVeRP/DXUQyl7h9U5pcx+YSPFNU0snp/Kk3NG4OvpeD2QI2OC+OreyVybGs2L6w8w77WtVNS3GB1Ls4EdR44xKiaox8N4T8epinx0sDdhfp7sLND98s7MZFY8vTqPRUsyGBDuy4r7zuOSYX2NjtUjvp5uPHXNSJ6bm8LuwhpmvbCBTN1YcWq1TW3sL2+walcNOFmRPzEpKkNffHVa9c1t3PbWdl5cf4C5Y2L4cNEEIp1ogtHslCg+/eVEXES49pXNfJx+9MxP0hzSiZGAJ4Z/W4tTFXmAsf1DKKhqpKyu2egomoWV1DZx7cub2ZBfyRNXJfPknBFOOc58WGQgX947mTHxwTz8yW6eWbMPpc5pWSfNjm07VI2bizAq1nrDJ8FJizzA1kPVBifRLCm3pI6rXtxE4bEm3lwwhnnj4oyOZFUhvh68detYrkuL5vlv9/PwJ7v1BVkns+1QNclRgfh4WPc6ktMV+aR+Afh5urHtkB6O5iw2Hajk2pc3A/DRoglMGXTSXc6cjrurC/+YM4IHpiXySUYht721nYaWdqNjaRbQ3GYis7CGcQkhVj+X0xV5N1cXUuOC2aZb8k5hfV45t765nX6BXiy7eyJJkQFGR7IpEeGBaYN4as4INh2oYv7rW6ltajM6ltZDO4/U0GZSjOuvi/w5Gds/hH1lDVQfbzU6itYDq7JKWLgkncQIPz5cNIF+gc5zgbW7rhsTw4s3jia7qJYbX92i39sObuuhKkQgNU4X+XNy4q/j9sO6Ne+oPs0o5O73dzAiOoj37xhPiK9ej316cl8W35xGfnkDcxdvprxeDy5wVNsOVTO0b8A57V/QXU5Z5IdHB+Lp5qK7bBzUpxmFPPRJJhMGhLLk9rFWXRbY0Uwd3Ic3F4zhaHUT17+yRY8ic0Ct7WZ2HDn20yARa3PKIu/p5sqo2CBd5B3Ql5nFPPxJJpMGhPH6LWOsPvLAEU0cGMaS28dSVtfMvNe2UtWgZ8c6kqyiWprbzDbpjwcnLfIAY/uHklNcS32zvkjlKFbnlPLAh7tIiw/h1ZvTnHIMvKWkxYfw+i1jOFrdyPzXt1HbqN/njuJE43OMLvI9M65/CGYF6XqJA4ewPq+ce97fwYjoQN5YMAZvD13gz2TCgNCf+uhveXObHl7pILYeqmJAuK/NVkl12iI/KjYId1fRy7c6gM0Hqlj0bgaD+/rz1q1j8XPARcaMcv6gcF64cRRZRbXc9tZ2mlpNRkfSTqPdZCb98DHG9rfdSqlOW+R9PNwYFRusd96xc7kldSx8J53YEB+W3DbOJqMNnM0lw/ryr+tT2H64mnuX7tT7KdixzMJaGlramTwwzGbn7FGRF5FrRSRHRMwikvaz+x4VkXwR2Ssil/Ys5rmZPDCMnOI6PabYThUea+SWN7bh6+nGO7eNJVgPkzxns0ZG8udZw1ibW8bvl+fotW7s1Mb8SkQ6utpspact+WzgauCHrjeKSBIwFxgGTAdeEhGbd7JOTgxDqY5p8Zp9OXa8lZvf2EZzm4l3bh/rVCtJGuXmCfHcdcEAlm47wr/X5RsdRzuJDfmVDIsMsOm8jx4VeaVUrlJq70numg18oJRqUUodAvKBsT0517kYERWIv5eb7rKxM02tJm57ezuFx5p47ZYxDIrwNzqS03j40sFcPTqKZ9bs48PtR4yOo3VxvKWdnUeOMcmGXTVgvY28o4AtXX4u7LzNptxcXZiQEMqP+ytRSiFivd1XtLNjMivuXbqDzKM1vDQv1WYTQnoLEeEfc0ZQ2dDK75ZlE+7vyYVDIoyOpQHbDlfTZlI27Y+Hs2jJi8haEck+yddsSwQQkYUiki4i6RUVFZY45H+ZnBhG4bEmjlQ3WvzYWvf9bWUua3PL+dOsYUxPduzdnOyVu6sL/5k3mqR+Adz93k6yi2qNjqQBG/dX4uHmwph42zZszljklVLTlFLJJ/lafpqnFQExXX6O7rztZMdfrJRKU0qlhYdbfgnZE381f9yvu2yM9t7WAl7fcIgFE+O5eUK80XGcmq+nG68vSCPYx5073kmnXC9/YLgN+ZWkxQXbfJKftYZQfgHMFRFPEekPJALbrHSu0+of5ktkoJfulzfYhv2V/GF5DhcMDufxGUONjtMr9PH34rVbxlDb1MYd76TrMfQGqmxoIa+03ub98dDzIZRXiUghMAFYISKrAZRSOcBHwB7ga+BupZQh7zARYXJiGJsOVGEy62FlRsgvb+CX73Vsuv3vG0bh5uq00zPsTlJkAM/NHcXuoloe+jgTs/4dMMSP+zu6os9LdLAir5RappSKVkp5KqUilFKXdrnvCaXUAKXUYKXUqp5HPXeTBoZR29RGZmGNkTF6pWPHW7n97e14uLrw+i1j8NcrStrcxUkRPHrZEFZklfDs2n1Gx+mV1uVVEObnSXJkoM3P3SuaVOcPCsdFOtZH0Wyntd3MonczKKltZvHNqcSE+Bgdqde647yEjv1i1+Xz+c6TXh7TrKTdZOaHfRVcMDgcFxfbj/DrFUU+yMeDtLgQvs3VRd6W/vLVHrYdquapOSNssgOOdmoiwl+vHM64/iE88uludutPtTaz62gNtU1tTB3cx5Dz94oiDzB1SB/2lNRRWqtHGdjCx+lHWbKlgIVTErhylM2nSGgn4eHmwkvzRhPu58miJRlU1Ot16G1h/d5yXF06rg0aodcU+YuGdvwVXae7bKwuu6iWxz7PZuKAUB65dLDRcbQuQv08eWV+KtXHW7n7/R206cXMrG59XgWpccGGLb7Xa4p8Yh8/ooO9WZdXZnQUp1Z9vJVFSzII8/XQI2nsVHJUIP+YM4Jth6r561d7jI7j1Eprm9lTUmdYVw30oiIvIlw0pA8b8itpbtPjha2h3WTm3qU7qGho4eX5qYTaaFMErfuuHBXFLyb35+3NBXyUftToOE7ru70dPQdTh1h+oufZ6jVFHuDCoRE0t5nZfEBvJGIN//vNPjbmV/HX2cmMiA4yOo52Br+9bAiTBoby+LJsdh7RO6hZw5o9ZUQFeTPYwEX4elWRH9c/BG93V90vbwWrskp4+fsD3DguluvGxJz5CZrh3Fxd+PcNo+kT4Mmd72ZQXq8HJVhSQ0s7P+ZXcsmwCEMXR+xVRd7L3ZXJiWGszS3TM/8saH9ZPQ99nMmo2CD+eEWS0XG0bgjx9WDx/DRqm9q4690dtLbrC7GW8v3eClrbzUwfZuxCfL2qyANMH9aXktpmPfvVQuqa21i0JANvD1f+My8VTze9AbejSYoM4KlrRpJecIy/6AuxFrM6p5RQXw/SbLzq5M/1uiI/bWgE7q7CquxSo6M4PLNZ8eBHmRRUN/LijaPpG+hldCTtHM0aGckd5/VnyZYCPtYXYnuspd3Eurxypg2NwNWAWa5d9boiH+jjzqSBYazKLtH7YPbQS9/ls2ZPGY9dPpRxCbbbs1Kzjt9MH8KEhFAe+zybrEK9Bn1PbDpQRUNLO5cmG79hS68r8gCXJ/fjaHUTOcV1RkdxWN/tLeefa/YxOyWSWyfFGx1HswA3VxdeuHEUYb4e3PluBlUNekbsufompxQ/TzcmDjBmlmtXvbLIX5zU8RFqZVaJ0VEc0pGqRu7/YBdD+gbw5NUj9LaKTiTUz5OX56dS0dDCvUt30q5nxHZbm8nM6pwypg7pY/MNQk6mVxb5YF8PJg4IZVV2qe6y6aamVhOL3s1AKcUrN6Xi7WH8m1izrBHRQfz1ymQ2HajiqdV7jY7jcDbkV1J9vJVZIyONjgL00iIPcFlyPw5VHtddNt2glOLRz3aTV1rHczeMIjZULx3srK5Li+Gm8bEs/uEgX2YWGx3HoXy5q5gALzemDDK+qwZ6dZHvi7ur6LW1u+GtTYf5fFcxv542yNC1ODTb+MPMYaTGBfPIJ7vZW1pvdByH0NxmYnVOKZcP72c3w4l7bZEP9vXggsF9WJ5ZrLcFPAtbD1bxxIpcLk6K4O6pA42Oo9nAiaWJ/bzcWLQkndqmNqMj2b1vc8s53mqym64a6MVFHuDqUVFU1Lew6YDe5Pt0Smubufv9ncSG+PDP60YasruNZoyIAC9emjeawmNNPPDBTj1T/Ay+yCyij7+nXQ0p7ulG3k+LSJ6I7BaRZSIS1OW+R0UkX0T2isilpzuOUaYO6YO/lxvLdugum1NpaTfxy/cyaGxt55X5qQToPVp7nTHxIfzhiiTW763g2W/3Gx3HbtU2trE+r4IZI/oZPgGqq5625NcAyUqpEcA+4FEAEUkC5gLDgOnASyJiHx1UXXi5uzJzRD++zimlsbXd6Dh26X++3MPOIzX877UjSTRwJT3NWPPHxzFndDTPf7uftXv0ngwnszyziFaTmTmjo42O8l96VOSVUt8opU5Uxy3AiVc3G/hAKdWilDoE5ANje3Iua7kyJYrG1o6LJdp/+2j7Ud7beoRF5ydw+fB+RsfRDCQiPHFVMslRAfzqw10crGgwOpLd+XD7UYZFBpAcFWh0lP9iyT7524BVnd9HAV0XwCjsvM3ujIkPIS7Uh6Xb9HodXe06WsPjn2dzXmIYj1w6xOg4mh3wcnfl5ZtScXMVFi3JoKFFf/o9IbuolpziOq5Ls79lts9Y5EVkrYhkn+RrdpfHPAa0A+91N4CILBSRdBFJr6io6O7Te8zFRZg7JpZth6rJL9fDxAAq6lu4c0kGfQI8eX7uKLvqX9SMFR3sw79vGM2BigYe+SRTTybs9FH6UTzcXLgyxf7asmcs8kqpaUqp5JN8LQcQkQXATGCe+v//4kVA1z9p0Z23nez4i5VSaUqptPBwY7bIujYtGndX4f2tujXfZjJz9/s7qGlq5ZX5qQT7ehgdSbMzkxPD+M30IazMKuXl7w8aHcdwzW0mPt9ZxPRhfQn0sb+BCT0dXTMdeASYpZRq7HLXF8BcEfEUkf5AIrCtJ+eypjA/Ty4Z1pdPdxT2+v1f/7Yyl22Hqnny6hEMi7SvvkXNfiycksCMEf14enUeP+63/Sdwe7Iqu4S65naut9Md0XraJ/8C4A+sEZFdIvIygFIqB/gI2AN8DdytlLLr6nnj2Fhqm9pYld17Fy37bEchb248zG2T+nPlKPv72KnZDxHhqTkjSOzjz71Ld3K0uvHMT3JSb20qICHclwl2NDa+q56OrhmolIpRSqV0ft3Z5b4nlFIDlFKDlVKrTnccezAhIZT4UB/e2VxgdBRDZBfV8uhnWYzrH8Kjl+sLrdqZ+Xq68cr8VExmxZ3vZvTKT8E7jhwj82gNCybG2+0kwV4947UrFxdhwcR4dh6pIaOgd+1cX328lUVLMgjx9eDFeaNxd9VvC+3sxIf58tzcFHKK6/jdZ1m97kLsWxsP4+/pxtV2Nja+K/3b3MW1aTEEeLnxxoZDRkexmdZ2M3e+m0FFQwsv35RKmJ+n0ZE0B3PhkAgemJbIZzuLetUn4bK6ZlZmlXDdmBj8PN2MjnNKush34evpxo3j4liVXdIr+hiVUjz+eRbbDlXz9DUjGBkTdOYnadpJ3HdhItOG9uEvX+1h26Fqo+PYxLtbCjApxS0T4o2Oclq6yP/MgonxuIjw5sbDRkexutc3HOKj9ELuvXAgs+1wfK/mOFxchGeuTyEmxIe73ttBaW2z0ZGsqr65jbc3HeaSpAi731dBF/mf6RvoxRUjI/lw+xGOHW81Oo7VrMsr428rc7ksuS+/mjbI6DiaEwjwcueV+ak0trZzxzvpTr0e1JItBdQ1t3PP1ESjo5yRLvIncdcFA2hsM/Hqj8450WNvaT33Ld3F0H4BeulgzaIGRfjz/NxR5BTXcv8Hu5xyr4bG1nZe+/EQ5w8KZ3i0/c8l0UX+JBIj/Jk5IpK3Nx2m2sla85UNLdz+9na8PVx57ZY0fDzs94KR5pimJUXwh5lJrNlTxhMrco2OY3FLtx2l+ngr917oGJvn6CJ/CvdfNJDGNhOLf3Ce1nxjazu3v7WdivoWXr05jX6B3kZH0pzUgkn9uXVSPG9sPMTbmw4bHcdimlpNLP7hAOMTQkiLDzE6zlnRRf4UBvbxZ9bISN7ZfJjKhhaj4/RYu8nM3e/tIKuolhduHE2KHkmjWdnjM5K4OCmCP3+Zw7e5zrEG/RsbD1FW18KvLx5sdJSzpov8adx3USIt7Wb+tWaf0VF6RCnF75ZlsX5vBX+5MpmLkyKMjqT1Aq4uwnNzU0iOCuTepTvZdbTG6Eg9Un28lZe/O8C0oX0Y298xWvGgi/xpDQj3Y/74OJZuO0JuSZ3Rcc7Zv9bu56P0Qu67cCDzxsUZHUfrRXw83HjtljTC/DxZ8OY29pc57nLe/163n+Ot7fxmumMt+6GL/Bk8MC2RAG93/rpij0NO2V6ypYDnv93PtanR/OpiPVRSs70+/l68e/s4PFxduOn1rQ450XBfWT1LNhdwXVqMw22DqYv8GQT5ePCraYPYmF/FNw62t+XH6Uf5/efZXDSkD3+7ejgieqikZozYUB/euX0sTa0m5r++lYp6x7nO1TEzPBtfTzcevtRx+uJP0EX+LNw4LpbBEf78cXkOdc1tRsc5K19kFvObT3dzXmKYXnRMswtD+gbw5q1jKatr4eY3tjnMZMPPdxWx7VA1j0wfTKgDru2kf/PPgrurC/+4ZgTl9c38fWWe0XHO6OvsUn714S7S4kNYPD8NL3dXoyNpGgCpccEsvjmVAxUN3PjaVrufh1JR38L/fLmHkTFBzB0Ta3Scc6KL/FlKiQnitkn9WbrtCBvzK42Oc0ordpdwz/s7GB4VyBsLxuDtoQu8Zl/OSwzn9VvSOFjRwI2vbqHKTocoK6V49LMsjrea+N9rRjjsXse6yHfDg5cMJiHMl199uMsu35gfpx/l3qU7GBUbxDu3j7Xr5U+13u28xHDeWDCGw1XHueHVLXbZR/9xeiFrc8t45NLBDnextStd5LvB28OVf984ipqmNh78OBOzHa3L8c7mwzz8yW4mDQzj7dvGEuBlfxsKa1pXkwaG8cYtYzha3cSc/2zicOVxoyP9ZE9xHX/4IpsJCaHcNqm/0XF6RBf5bhoWGcjvZwzlu70VPL9uv9FxMJsVf1+Vyx+W5zBtaASv3qzXo9Ecx8SBYbx/xzgaWtqZ859NZNrBhKnaxjbufDeDQG93nr9hlMMv4KeL/Dm4aXwcV4+O4tm1+1m+q8iwHE2tJu5+fwevfH+Qm8bH8vJNo/VFVs3hjIoN5pM7J+Dj6crcxVv4JqfUsCwt7Sbuej+DktomXpqXSri/442m+bkeFXkR+YuI7BaRXSLyjYhEdt4uIvK8iOR33j/aMnHtg4jw96uHM7Z/CA9/sptNB2x/Ibaopom5izfzdU4pj88Yyl9mJ+Omh0lqDioh3I9PfzmRxAg/Fi7J4Jlv9tp8mWKzWfHgR5lszK/iyatHkBoXbNPzW0tPq8LTSqkRSqkU4CvgD523XwYkdn4tBP7Tw/PYHU83V165KZX+ob7c9tZ2Nh+ostm51+WVMeP5HzlQcZxXbkrlF+cl6IlOmsPr4+/FR4smcG1qNM+vy+f2t7dT02ibIZYms+K3n+3mq90l/PayIcxJtd+NuburR0VeKdV1QRdf4MSf3tnAO6rDFiBIRPr15Fz2KNjXg/fuGEdMsA+3vbWdNVaeEdvUauKvX+3htrfSiQz05st7J3PJsL5WPaem2ZKXuytPXTOCv16ZzMb8Si599ge+21tu1XO2tpu5b+nOn9Z3WjQlwarns7Uef74XkSdE5Cgwj//fko8CjnZ5WGHnbSd7/kIRSReR9IqKip7GsbkwP0/ev2N858fMdBb/cMAqa9xsPVjFZc/9wGsbDnHT+Fg+u2si/cN8LX4eTTOaiHDT+DiW3TWJAC93Fry5nd8ty6K20fKzzUtrm7l+8WZWZJXwu8uH8OtLBjvdp2I5U0ESkbXAyZqLjymllnd53KOAl1LqjyLyFfCkUmpD533fAr9RSqWf7lxpaWkqPf20D7FbTa0mHvx4FyuzSjl/UDhPXTOCiACvHh/3aHUj//xmL5/vKiY2xIcn5wxn4oAwCyTWNPvX3GbimTX7ePXHgwT7ePDgJYO4Pi3GItefvs4u5fHPs2hqNfHUNSOZMcJxOxtEJEMplXbS+yzV6hSRWGClUipZRF4BvlNKLe28by9wgVKq5HTHcOQiDx0z5JZsKeBvK3Nxd3XhrgsGcuuk+HMa8XKgooE3Nx7io+2FiMBtk/tz74UD9fBIrVfKKa7lz1/uYduhauJCfVg0ZQBzUqPwdOv+79a+snqeXr2XNXvKGNovgOfnpjj0ZCewYpEXkUSl1P7O7+8FzldKXSMiM4B7gMuBccDzSqmxZzqeoxf5Ew5WNPDEily+zSsnzM+Da1JjuHp0FIl9/E77UbCqoYU1e8pYkVXCj/sr8XB14erRUdw/LVFv1af1ekop1uwp44X1+ewurCXIx52ZI/pxxYhIRsUG4+F26tZ9c5uJ7/aW80lGEWtzy/D1cOW+ixK5bXJ/p1i8z5pF/lNgMGAGCoA7lVJF0lHJXgCmA43ArWfqqgHnKfInbD1YxesbDvFtXjkmsyIiwJOR0UHEhfoQ6O2Oi4tQ29hGcW0zOcW1HKzomPEXE+LNnNHRzBsX5xTjdDXNkpRSbDpQxYfbj/LNnlKa28x4u7syIjqQhHBf+vh74eXuSnObicqGFvJK68kuqqWl3UyorwfzxsVy66T+BPt6GP1SLMYm3TWW4GxF/oSyumbW5ZWzIb+SfaX1HKlupKXdDICHmwsRAZ4MjgggJSaQqUP6kNQvwOku/miaNdQ3t7Exv5LNB6rIKqrlcFXjTytbikCwjwf9w3xJiQni/EHhTBwQ6pTzSXSRtzNKKdrNCpNZ4enmogu6plmQ2axoaTfj7ipOWdBP5nRFXl/FM4CI4O4q6BUINM3yXFxEL7HdRe/4M6dpmtZL6SKvaZrmxOyqT15EKugYpXMuwgB73bLJXrPpXN2jc3WPztU9PckVp5QKP9kddlXke0JE0k914cFo9ppN5+oenat7dK7usVYu3V2jaZrmxHSR1zRNc2LOVOQXGx3gNOw1m87VPTpX9+hc3WOVXE7TJ69pmqb9X87Uktc0TdN+Rhd5TdM0J+aURV5EHhQRJSJ2sbvGqTY8N5qIPC0ieZ3ZlolIkNGZAETkWhHJERGziBg+1E1EpovI3s6N6X9rdJ4TROQNESkXkWyjs3QlIjEisl5E9nT+O95vdCYAEfESkW0iktmZ689GZzpBRFxFZGfnhksW5XRFXkRigEuAI0Zn6eJUG54bbQ2QrJQaAewDHjU4zwnZwNXAD0YHERFX4EU6NqdPAm4QkSRjU/3kLTqW87Y37cCDSqkkYDxwt538P2sBLlRKjQRSgOkiMt7gTCfcD+Ra48BOV+SBfwGP8P83FTfcaTY8N5RS6hulVHvnj1sAu9iiXimVq5Taa3SOTmOBfKXUQaVUK/ABHRvVG04p9QNQbXSOn1NKlSildnR+X09H8TrpHs+2pDo0dP7o3vll+O+iiEQDM4DXrHF8pyryIjIbKFJKZRqd5edOseG5PbkNWGV0CDt01pvSa/+XiMQDo4Ctxibp0NktsgsoB9YoHXYSOQAAAeZJREFUpewh17N0NEzN1ji4wy01fLqNxYHf0dFVY3Nn2vBcKfUY8Fjnhuf3AH+0h1ydj3mMjo/Y79ki09nm0hybiPgBnwIP/OzTrGGUUiYgpfP60zIRSVZKGXZNQ0RmAuVKqQwRucAa53C4Iq+Umnay20VkONAfyOzchCMa2CEiY5VSpUblOon3gJXYqMifKZeILABmAhcpG06a6Mb/L6MVATFdfo7uvE07DRFxp6PAv6eU+szoPD+nlKoRkfV0XNMw8sL1JGCWiFwOeAEBIvKuUuomS53AabprlFJZSqk+Sql4pVQ8HR+rR9uiwJ+JiCR2+XE2kGdUlq5EZDodHxNnKaUajc5jp7YDiSLSX0Q8gLnAFwZnsmudezy/DuQqpZ4xOs8JIhJ+YgSZiHgDF2Pw76JS6lGlVHRnzZoLrLNkgQcnKvJ27kkRyRaR3XR0J9nFkDI6Nlv3B9Z0Du982ehAACJylYgUAhOAFSKy2qgsnRem7wFW03EB8SOlVI5ReboSkaXAZmCwiBSKyO1GZ+o0CZgPXNj5vtrV2VI1Wj9gfefv4XY6+uQtPmTR3uhlDTRN05yYbslrmqY5MV3kNU3TnJgu8pqmaU5MF3lN0zQnpou8pmmaE9NFXtM0zYnpIq9pmubE/h+h42lD2dj/ZQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "#Define the optimizer that is used to find the optimal value of the cost function\n", "\n", "out = minimize(new_objective, x0=[random.randint(-500,500)/100, random.randint(-500,500)/100], method=\"COBYLA\", options={'maxiter':20})\n", "print(out)\n", "\n", "#Runs the circuit a final time, with the optimal parameters\n", "\n", "final = run_circuit(out['x'])\n", "\n", "#Define the arrays used for the graphical visualization\n", "\n", "x = [i/100 for i in range(-500, 500)]\n", "x2 = [i/100 for i in range(-400, 400)]\n", "y = []\n", "\n", "#Construct the quadrature graph\n", "\n", "for i in range(0, len(x)):\n", " res = simps([final[k][i] for k in range(0, len(x))], x)\n", " y.append(res)\n", "\n", "plt.subplot(2, 1, 1)\n", "plt.plot(x, y)\n", "\n", "#Plot vertical lines corresponding to the actual optimal solutions\n", "\n", "plt.plot([2*math.sqrt(2) for i in range(0, 5)], [0, 0.25*max(y), 0.5*max(y), 0.75*max(y), max(y)])\n", "plt.plot([-2*math.sqrt(2) for i in range(0, 5)], [0, 0.25*max(y), 0.5*max(y), 0.75*max(y), max(y)])\n", "\n", "#Plot the actual cost function itself\n", "\n", "plt.subplot(2, 1, 2)\n", "plt.plot(x2, [function_optimize(x2[i]) for i in range(0, len(x2))])\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we get pretty great results, with two \"spikes\" appearing at the minima of the cost function. This simulation, however, required a very deep circuit (depth of $8$), so there is definitely a trade-off that must be considered, between accuracy of the algorithms, and dpeth of the circuit (which on a real quantum computer, would lead to loss of coherence).\n", "\n", "**Conclusion**
\n", "\n", "In conclusion, this notebook was meant to act as expository material, to give the reader an idea of what QAOA and CV QAOA are all about through some interesting physical theory in the first section, and concrete simulations in the second part. I really hope you, the reader, has gained more clarity about the power of an algorithm like QAOA (specifically CV QAOA)!\n", "\n", "To address to topic of the accuracy of these simulations, I feel like for a lot of these results, I kind of got lucky. When I ran tests locally, I got a lot of great results, but at the same time, I got a lot of not-so-great results. I also feel as though I am \"selecting\" ideal parameters for each of the simulations, as a lot of the squeezing parameters, cutoff dimensions, etc. that I tested (which I didn't include in this notebook), did not work very well. Nevertheless, I think this is an interesting starting point to dive further into CV QAOA and conceptualize better training techniques, and more general ways to choose parameters such that convergence of the algorithm can be ensured to a higher degree.\n", "\n", "**Acknowledgements**
\n", "\n", "This notebook would not have been compelted without all the help of Guillaume Verdon, Josh Izaac, Nicolas Quesada, Juan Miguel Arrazola, and Nathan Killoran. Thank you to all of you guys, I really appreciate that you took the time to answer my never-ending stream of questions!\n", "\n", "**References**\n", "\n", "Original CV QAOA Paper: [https://arxiv.org/abs/1902.00409](https://arxiv.org/abs/1902.00409)\n", "
\n", "CV Gate Decomposition Paper: [https://arxiv.org/abs/1811.10651](https://arxiv.org/abs/1811.10651)\n", "
\n", "The Code for the Contour Graph was Based Off of a StackExchange Answer (Will Update With Link)\n", "
\n", "Gaussian Quantum Information: [https://arxiv.org/abs/1110.3234](https://arxiv.org/abs/1110.3234)\n", "
\n", "Original QAOA Paper: [https://arxiv.org/abs/1411.4028](https://arxiv.org/abs/1411.4028)\n", "
\n", "Basic Explanation of QAE For QC: [https://quantumcomputing.stackexchange.com/a/5572/4907](https://quantumcomputing.stackexchange.com/a/5572/4907)" ] }, { "cell_type": "code", "execution_count": null, "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.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }