[404218]: / Code / PennyLane / Quantum Parameters II / CY 1Layers DiffAdjoint A100 Lightning.gpu Kernel 37.62s kkawchak.ipynb

Download this file

1279 lines (1279 with data), 137.7 kB

{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 596,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "U9bYOT8V3fHC",
        "outputId": "7454f5ef-50a5-4d28-8a71-e67aafaa9148"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Time in seconds since beginning of run: 1699857296.6519265\n",
            "Mon Nov 13 06:34:56 2023\n"
          ]
        }
      ],
      "source": [
        "# This cell is added by sphinx-gallery\n",
        "# It can be customized to whatever you like\n",
        "%matplotlib inline\n",
        "# !pip install pennylane custatevec-cu11 pennylane-lightning-gpu\n",
        "import time\n",
        "seconds = time.time()\n",
        "print(\"Time in seconds since beginning of run:\", seconds)\n",
        "local_time = time.ctime(seconds)\n",
        "print(local_time)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1wO15tC53fHE"
      },
      "source": [
        "::: {#kernel_based_training}\n",
        ":::\n",
        "\n",
        "Kernel-based training of quantum models with scikit-learn\n",
        "=========================================================\n",
        "\n",
        "::: {.meta}\n",
        ":property=\\\"og:description\\\": Train a quantum machine learning model\n",
        "based on the idea of quantum kernels. :property=\\\"og:image\\\":\n",
        "<https://pennylane.ai/qml/_images/kernel_based_scaling.png>\n",
        ":::\n",
        "\n",
        "::: {.related}\n",
        "tutorial\\_variational\\_classifier Variational classifier\n",
        ":::\n",
        "\n",
        "*Author: Maria Schuld --- Posted: 03 February 2021. Last updated: 3\n",
        "February 2021.*\n",
        "\n",
        "Over the last few years, quantum machine learning research has provided\n",
        "a lot of insights on how we can understand and train quantum circuits as\n",
        "machine learning models. While many connections to neural networks have\n",
        "been made, it becomes increasingly clear that their mathematical\n",
        "foundation is intimately related to so-called *kernel methods*, the most\n",
        "famous of which is the [support vector machine\n",
        "(SVM)](https://en.wikipedia.org/wiki/Support-vector_machine) (see for\n",
        "example [Schuld and Killoran (2018)](https://arxiv.org/abs/1803.07128),\n",
        "[Havlicek et al. (2018)](https://arxiv.org/abs/1804.11326), [Liu et al.\n",
        "(2020)](https://arxiv.org/abs/2010.02174), [Huang et al.\n",
        "(2020)](https://arxiv.org/pdf/2011.01938), and, for a systematic summary\n",
        "which we will follow here, [Schuld\n",
        "(2021)](https://arxiv.org/abs/2101.11020)).\n",
        "\n",
        "The link between quantum models and kernel methods has important\n",
        "practical implications: we can replace the common [variational\n",
        "approach](https://pennylane.ai/qml/glossary/variational_circuit.html) to\n",
        "quantum machine learning with a classical kernel method where the\n",
        "kernel---a small building block of the overall algorithm---is computed\n",
        "by a quantum device. In many situations there are guarantees that we get\n",
        "better or at least equally good results.\n",
        "\n",
        "This demonstration explores how kernel-based training compares with\n",
        "[variational\n",
        "training](https://pennylane.ai/qml/demos/tutorial_variational_classifier.html)\n",
        "in terms of the number of quantum circuits that have to be evaluated.\n",
        "For this we train a quantum machine learning model with a kernel-based\n",
        "approach using a combination of PennyLane and the\n",
        "[scikit-learn](https://scikit-learn.org/) machine learning library. We\n",
        "compare this strategy with a variational quantum circuit trained via\n",
        "stochastic gradient descent using\n",
        "[PyTorch](https://pennylane.readthedocs.io/en/stable/introduction/interfaces/torch.html).\n",
        "\n",
        "We will see that in a typical small-scale example, kernel-based training\n",
        "requires only a fraction of the number of quantum circuit evaluations\n",
        "used by variational circuit training, while each evaluation runs a much\n",
        "shorter circuit. In general, the relative efficiency of kernel-based\n",
        "methods compared to variational circuits depends on the number of\n",
        "parameters used in the variational model.\n",
        "\n",
        "![](../demonstrations/kernel_based_training/scaling.png){.align-center}\n",
        "\n",
        "If the number of variational parameters remains small, e.g., there is a\n",
        "square-root-like scaling with the number of data samples (green line),\n",
        "variational circuits are almost as efficient as neural networks (blue\n",
        "line), and require much fewer circuit evaluations than the quadratic\n",
        "scaling of kernel methods (red line). However, with current\n",
        "hardware-compatible training strategies, kernel methods scale much\n",
        "better than variational circuits that require a number of parameters of\n",
        "the order of the training set size (orange line).\n",
        "\n",
        "In conclusion, **for quantum machine learning applications with many\n",
        "parameters, kernel-based training can be a great alternative to the\n",
        "variational approach to quantum machine learning**.\n",
        "\n",
        "After working through this demo, you will:\n",
        "\n",
        "-   be able to use a support vector machine with a quantum kernel\n",
        "    computed with PennyLane, and\n",
        "-   be able to compare the scaling of quantum circuit evaluations\n",
        "    required in kernel-based versus variational training.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e-EHd-BN3fHG"
      },
      "source": [
        "Background\n",
        "==========\n",
        "\n",
        "Let us consider a *quantum model* of the form\n",
        "\n",
        "$$f(x) = \\langle \\phi(x) | \\mathcal{M} | \\phi(x)\\rangle,$$\n",
        "\n",
        "where $| \\phi(x)\\rangle$ is prepared by a fixed [embedding\n",
        "circuit](https://pennylane.ai/qml/glossary/quantum_embedding.html) that\n",
        "encodes data inputs $x$, and $\\mathcal{M}$ is an arbitrary observable.\n",
        "This model includes variational quantum machine learning models, since\n",
        "the observable can effectively be implemented by a simple measurement\n",
        "that is preceded by a variational circuit:\n",
        "\n",
        "![](../demonstrations/kernel_based_training/quantum_model.png){.align-center}\n",
        "\n",
        "|\n",
        "\n",
        "For example, applying a circuit $G(\\theta)$ and then measuring the\n",
        "Pauli-Z observable $\\sigma^0_z$ of the first qubit implements the\n",
        "trainable measurement\n",
        "$\\mathcal{M}(\\theta) = G^{\\dagger}(\\theta) \\sigma^0_z G(\\theta)$.\n",
        "\n",
        "The main practical consequence of approaching quantum machine learning\n",
        "with a kernel approach is that instead of training $f$ variationally, we\n",
        "can often train an equivalent classical kernel method with a kernel\n",
        "executed on a quantum device. This *quantum kernel* is given by the\n",
        "mutual overlap of two data-encoding quantum states,\n",
        "\n",
        "$$\\kappa(x, x') = | \\langle \\phi(x') | \\phi(x)\\rangle|^2.$$\n",
        "\n",
        "Kernel-based training therefore bypasses the processing and measurement\n",
        "parts of common variational circuits, and only depends on the data\n",
        "encoding.\n",
        "\n",
        "If the loss function $L$ is the [hinge\n",
        "loss](https://en.wikipedia.org/wiki/Hinge_loss), the kernel method\n",
        "corresponds to a standard [support vector\n",
        "machine](https://en.wikipedia.org/wiki/Support-vector_machine) (SVM) in\n",
        "the sense of a maximum-margin classifier. Other convex loss functions\n",
        "lead to more general variations of support vector machines.\n",
        "\n",
        "::: {.note}\n",
        "::: {.title}\n",
        "Note\n",
        ":::\n",
        "\n",
        "More precisely, we can replace variational with kernel-based training if\n",
        "the optimisation problem can be written as minimizing a cost of the form\n",
        "\n",
        "$$\\min_f  \\lambda\\;  \\mathrm{tr}\\{\\mathcal{M}^2\\} + \\frac{1}{M}\\sum_{m=1}^M L(f(x^m), y^m),$$\n",
        "\n",
        "which is a regularized empirical risk with training data samples\n",
        "$(x^m, y^m)_{m=1\\dots M}$, regularization strength\n",
        "$\\lambda \\in \\mathbb{R}$, and loss function $L$.\n",
        "\n",
        "Theory predicts that kernel-based training will always find better or\n",
        "equally good minima of this risk. However, to show this here we would\n",
        "have to either regularize the variational training by the trace of the\n",
        "squared observable, or switch off regularization in the classical SVM,\n",
        "which removes a lot of its strength. The kernel-based and the\n",
        "variational training in this demonstration therefore optimize slightly\n",
        "different cost functions, and it is out of our scope to establish\n",
        "whether one training method finds a better minimum than the other.\n",
        ":::\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "a9S8DPih3fHG"
      },
      "source": [
        "Kernel-based training\n",
        "=====================\n",
        "\n",
        "First, we will turn to kernel-based training of quantum models. As\n",
        "stated above, an example implementation is a standard support vector\n",
        "machine with a kernel computed by a quantum circuit.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-EVcxqDw3fHH"
      },
      "source": [
        "We begin by importing all sorts of useful methods:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 597,
      "metadata": {
        "id": "NM4EoXYV3fHH"
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import torch\n",
        "from torch.nn.functional import relu\n",
        "\n",
        "from sklearn.svm import SVC\n",
        "from sklearn.datasets import load_iris\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.metrics import accuracy_score\n",
        "\n",
        "import pennylane as qml\n",
        "from pennylane.templates import AngleEmbedding, StronglyEntanglingLayers\n",
        "from pennylane.operation import Tensor\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "np.random.seed(42)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uPSsNb3A3fHH"
      },
      "source": [
        "The second step is to define a data set. Since the performance of the\n",
        "models is not the focus of this demo, we can just use the first two\n",
        "classes of the famous [Iris data\n",
        "set](https://en.wikipedia.org/wiki/Iris_flower_data_set). Dating back to\n",
        "as far as 1936, this toy data set consists of 100 samples of four\n",
        "features each, and gives rise to a very simple classification problem.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 598,
      "metadata": {
        "id": "RxclQl753fHH"
      },
      "outputs": [],
      "source": [
        "X, y = load_iris(return_X_y=True)\n",
        "\n",
        "# pick inputs and labels from the first two classes only,\n",
        "# corresponding to the first 100 samples\n",
        "X = X[:100]\n",
        "y = y[:100]\n",
        "\n",
        "# scaling the inputs is important since the embedding we use is periodic\n",
        "scaler = StandardScaler().fit(X)\n",
        "X_scaled = scaler.transform(X)\n",
        "\n",
        "# scaling the labels to -1, 1 is important for the SVM and the\n",
        "# definition of a hinge loss\n",
        "y_scaled = 2 * (y - 0.5)\n",
        "\n",
        "X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4ir_h10o3fHI"
      },
      "source": [
        "We use the [angle-embedding\n",
        "template](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.templates.embeddings.AngleEmbedding.html)\n",
        "which needs as many qubits as there are features:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 599,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "_PetxK4z3fHI",
        "outputId": "d3644d77-69e4-4ebc-c4db-78a4dda11b59"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "4"
            ]
          },
          "metadata": {},
          "execution_count": 599
        }
      ],
      "source": [
        "n_qubits = len(X_train[0])\n",
        "n_qubits"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lyB-seGk3fHI"
      },
      "source": [
        "To implement the kernel we could prepare the two states\n",
        "$| \\phi(x) \\rangle$, $| \\phi(x') \\rangle$ on different sets of qubits\n",
        "with angle-embedding routines $S(x), S(x')$, and measure their overlap\n",
        "with a small routine called a [SWAP\n",
        "test](https://en.wikipedia.org/wiki/Swap_test).\n",
        "\n",
        "However, we need only half the number of qubits if we prepare\n",
        "$| \\phi(x)\\rangle$ and then apply the inverse embedding with $x'$ on the\n",
        "same qubits. We then measure the projector onto the initial state\n",
        "$|0..0\\rangle \\langle 0..0|$.\n",
        "\n",
        "![](../demonstrations/kernel_based_training/kernel_circuit.png){.align-center}\n",
        "\n",
        "To verify that this gives us the kernel:\n",
        "\n",
        "$$\\begin{aligned}\n",
        "\\begin{align*}\n",
        "    \\langle 0..0 |S(x') S(x)^{\\dagger} \\mathcal{M} S(x')^{\\dagger} S(x)  | 0..0\\rangle &= \\langle 0..0 |S(x') S(x)^{\\dagger} |0..0\\rangle \\langle 0..0| S(x')^{\\dagger} S(x)  | 0..0\\rangle  \\\\\n",
        "    &= |\\langle 0..0| S(x')^{\\dagger} S(x)  | 0..0\\rangle |^2\\\\\n",
        "    &= | \\langle \\phi(x') | \\phi(x)\\rangle|^2 \\\\\n",
        "    &= \\kappa(x, x').\n",
        "\\end{align*}\n",
        "\\end{aligned}$$\n",
        "\n",
        "Note that a projector $|0..0 \\rangle \\langle 0..0|$ can be constructed\n",
        "using the `qml.Hermitian` observable in PennyLane.\n",
        "\n",
        "Altogether, we use the following quantum node as a *quantum kernel\n",
        "evaluator*:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 600,
      "metadata": {
        "id": "mIbEaOoy3fHI"
      },
      "outputs": [],
      "source": [
        "dev_kernel = qml.device(\"lightning.gpu\", wires=n_qubits)\n",
        "\n",
        "projector = np.zeros((2**n_qubits, 2**n_qubits))\n",
        "projector[0, 0] = 1\n",
        "\n",
        "@qml.qnode(dev_kernel, interface=\"autograd\", diff_method=\"adjoint\")\n",
        "def kernel(x1, x2):\n",
        "    \"\"\"The quantum kernel.\"\"\"\n",
        "    AngleEmbedding(x1, wires=range(n_qubits))\n",
        "    qml.adjoint(AngleEmbedding)(x2, wires=range(n_qubits))\n",
        "    return qml.expval(qml.Hermitian(projector, wires=range(n_qubits)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "U6aPSXgH3fHI"
      },
      "source": [
        "A good sanity check is whether evaluating the kernel of a data point and\n",
        "itself returns 1:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 601,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "q9TzLmmP3fHI",
        "outputId": "de16023d-d860-473c-9b29-4a7739641e41"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array(1.)"
            ]
          },
          "metadata": {},
          "execution_count": 601
        }
      ],
      "source": [
        "kernel(X_train[0], X_train[0])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XsItzCZ73fHI"
      },
      "source": [
        "The way an SVM with a custom kernel is implemented in scikit-learn\n",
        "requires us to pass a function that computes a matrix of kernel\n",
        "evaluations for samples in two different datasets A, B. If A=B, this is\n",
        "the [Gram matrix](https://en.wikipedia.org/wiki/Gramian_matrix).\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 602,
      "metadata": {
        "id": "ktqS-uFf3fHI"
      },
      "outputs": [],
      "source": [
        "def kernel_matrix(A, B):\n",
        "    \"\"\"Compute the matrix whose entries are the kernel\n",
        "       evaluated on pairwise data from sets A and B.\"\"\"\n",
        "    return np.array([[kernel(a, b) for b in B] for a in A])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z2q2cVnO3fHJ"
      },
      "source": [
        "Training the SVM optimizes internal parameters that basically weigh\n",
        "kernel functions. It is a breeze in scikit-learn, which is designed as a\n",
        "high-level machine learning library:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 603,
      "metadata": {
        "id": "c-28Bjs33fHJ"
      },
      "outputs": [],
      "source": [
        "svm = SVC(kernel=kernel_matrix).fit(X_train, y_train)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LdqczWbW3fHJ"
      },
      "source": [
        "Let's compute the accuracy on the test set.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 604,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "TiO_t3bQ3fHJ",
        "outputId": "edc21bd6-85bb-41b3-b3e6-c02dc2bff49f"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1.0"
            ]
          },
          "metadata": {},
          "execution_count": 604
        }
      ],
      "source": [
        "predictions = svm.predict(X_test)\n",
        "accuracy_score(predictions, y_test)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oKR_CF363fHJ"
      },
      "source": [
        "The SVM predicted all test points correctly. How many times was the\n",
        "quantum device evaluated?\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 605,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "4TWrXNDn3fHJ",
        "outputId": "dd9895e4-43f8-4a8d-93f7-8b9fae4a7cce"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "7501"
            ]
          },
          "metadata": {},
          "execution_count": 605
        }
      ],
      "source": [
        "dev_kernel.num_executions"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Pp30o1Sl3fHJ"
      },
      "source": [
        "This number can be derived as follows: For $M$ training samples, the SVM\n",
        "must construct the $M \\times M$ dimensional kernel gram matrix for\n",
        "training. To classify $M_{\\rm pred}$ new samples, the SVM needs to\n",
        "evaluate the kernel at most $M_{\\rm pred}M$ times to get the pairwise\n",
        "distances between training vectors and test samples.\n",
        "\n",
        "::: {.note}\n",
        "::: {.title}\n",
        "Note\n",
        ":::\n",
        "\n",
        "Depending on the implementation of the SVM, only $S \\leq M_{\\rm pred}$\n",
        "*support vectors* are needed.\n",
        ":::\n",
        "\n",
        "Let us formulate this as a function, which can be used at the end of the\n",
        "demo to construct the scaling plot shown in the introduction.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 606,
      "metadata": {
        "id": "zI2lIUTV3fHJ"
      },
      "outputs": [],
      "source": [
        "def circuit_evals_kernel(n_data, split):\n",
        "    \"\"\"Compute how many circuit evaluations one needs for kernel-based\n",
        "       training and prediction.\"\"\"\n",
        "\n",
        "    M = int(np.ceil(split * n_data))\n",
        "    Mpred = n_data - M\n",
        "\n",
        "    n_training = M * M\n",
        "    n_prediction = M * Mpred\n",
        "\n",
        "    return n_training + n_prediction"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "x0ayC5We3fHJ"
      },
      "source": [
        "With $M = 75$ and $M_{\\rm pred} = 25$, the number of kernel evaluations\n",
        "can therefore be estimated as:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 607,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "0aoJPwOj3fHJ",
        "outputId": "51bb7ece-68ac-4781-c3da-1d166d870166"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "7500"
            ]
          },
          "metadata": {},
          "execution_count": 607
        }
      ],
      "source": [
        "circuit_evals_kernel(n_data=len(X), split=len(X_train) /(len(X_train) + len(X_test)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dRDQOR7K3fHJ"
      },
      "source": [
        "The single additional evaluation can be attributed to evaluating the\n",
        "kernel once above as a sanity check.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b8IBcump3fHJ"
      },
      "source": [
        "A similar example using variational training\n",
        "============================================\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rl4V3vyC3fHJ"
      },
      "source": [
        "Using the variational principle of training, we can propose an *ansatz*\n",
        "for the variational circuit and train it directly. By increasing the\n",
        "number of layers of the ansatz, its expressivity increases. Depending on\n",
        "the ansatz, we may only search through a subspace of all measurements\n",
        "for the best candidate.\n",
        "\n",
        "Remember from above, the variational training does not optimize\n",
        "*exactly* the same cost as the SVM, but we try to match them as closely\n",
        "as possible. For this we use a bias term in the quantum model, and train\n",
        "on the hinge loss.\n",
        "\n",
        "We also explicitly use the\n",
        "[parameter-shift](https://pennylane.ai/qml/glossary/parameter_shift.html)\n",
        "differentiation method in the quantum node, since this is a method which\n",
        "works on hardware as well. While `diff_method='backprop'` or\n",
        "`diff_method='adjoint'` would reduce the number of circuit evaluations\n",
        "significantly, they are based on tricks that are only suitable for\n",
        "simulators, and can therefore not scale to more than a few dozen qubits.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 608,
      "metadata": {
        "id": "3Givezqc3fHJ"
      },
      "outputs": [],
      "source": [
        "dev_var = qml.device(\"lightning.gpu\", wires=n_qubits)\n",
        "\n",
        "@qml.qnode(dev_var, interface=\"torch\", diff_method=\"adjoint\")\n",
        "def quantum_model(x, params):\n",
        "    \"\"\"A variational quantum model.\"\"\"\n",
        "\n",
        "    # embedding\n",
        "    AngleEmbedding(x, wires=range(n_qubits))\n",
        "\n",
        "    # trainable measurement\n",
        "    StronglyEntanglingLayers(params, wires=range(n_qubits), imprimitive=qml.ops.CY)\n",
        "    return qml.expval(qml.PauliZ(0))\n",
        "\n",
        "def quantum_model_plus_bias(x, params, bias):\n",
        "    \"\"\"Adding a bias.\"\"\"\n",
        "    return quantum_model(x, params) + bias\n",
        "\n",
        "def hinge_loss(predictions, targets):\n",
        "    \"\"\"Implements the hinge loss.\"\"\"\n",
        "    all_ones = torch.ones_like(targets)\n",
        "    hinge_loss = all_ones - predictions * targets\n",
        "    # trick: since the max(0,x) function is not differentiable,\n",
        "    # use the mathematically equivalent relu instead\n",
        "    hinge_loss = relu(hinge_loss)\n",
        "    return hinge_loss"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mIsEpYgJ3fHJ"
      },
      "source": [
        "We now summarize the usual training and prediction steps into two\n",
        "functions similar to scikit-learn\\'s `fit()` and `predict()`. While it\n",
        "feels cumbersome compared to the one-liner used to train the kernel\n",
        "method, PennyLane---like other differentiable programming\n",
        "libraries---provides a lot more control over the particulars of\n",
        "training.\n",
        "\n",
        "In our case, most of the work is to convert between numpy and torch,\n",
        "which we need for the differentiable `relu` function used in the hinge\n",
        "loss.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 609,
      "metadata": {
        "id": "EFIiA8SW3fHK"
      },
      "outputs": [],
      "source": [
        "def quantum_model_train(n_layers, steps, batch_size):\n",
        "    \"\"\"Train the quantum model defined above.\"\"\"\n",
        "\n",
        "    params = np.random.random((n_layers, n_qubits, 3))\n",
        "    params_torch = torch.tensor(params, requires_grad=True)\n",
        "    bias_torch = torch.tensor(0.0)\n",
        "\n",
        "    opt = torch.optim.Adam([params_torch, bias_torch], lr=0.1)\n",
        "\n",
        "    loss_history = []\n",
        "    for i in range(steps):\n",
        "\n",
        "        batch_ids = np.random.choice(len(X_train), batch_size)\n",
        "\n",
        "        X_batch = X_train[batch_ids]\n",
        "        y_batch = y_train[batch_ids]\n",
        "\n",
        "        X_batch_torch = torch.tensor(X_batch, requires_grad=False)\n",
        "        y_batch_torch = torch.tensor(y_batch, requires_grad=False)\n",
        "\n",
        "        def closure():\n",
        "            opt.zero_grad()\n",
        "            preds = torch.stack(\n",
        "                [quantum_model_plus_bias(x, params_torch, bias_torch) for x in X_batch_torch]\n",
        "            )\n",
        "            loss = torch.mean(hinge_loss(preds, y_batch_torch))\n",
        "\n",
        "            # bookkeeping\n",
        "            current_loss = loss.detach().numpy().item()\n",
        "            loss_history.append(current_loss)\n",
        "            if i % 10 == 0:\n",
        "                print(\"step\", i, \", loss\", current_loss)\n",
        "\n",
        "            loss.backward()\n",
        "            return loss\n",
        "\n",
        "        opt.step(closure)\n",
        "\n",
        "    return params_torch, bias_torch, loss_history\n",
        "\n",
        "\n",
        "def quantum_model_predict(X_pred, trained_params, trained_bias):\n",
        "    \"\"\"Predict using the quantum model defined above.\"\"\"\n",
        "\n",
        "    p = []\n",
        "    for x in X_pred:\n",
        "\n",
        "        x_torch = torch.tensor(x)\n",
        "        pred_torch = quantum_model_plus_bias(x_torch, trained_params, trained_bias)\n",
        "        pred = pred_torch.detach().numpy().item()\n",
        "        if pred > 0:\n",
        "            pred = 1\n",
        "        else:\n",
        "            pred = -1\n",
        "\n",
        "        p.append(pred)\n",
        "    return p"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HZ4ANAAf3fHK"
      },
      "source": [
        "Let's train the variational model and see how well we are doing on the\n",
        "test set.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 610,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 656
        },
        "id": "4Orrciwd3fHK",
        "outputId": "fa05d9a4-6a0f-4bea-8ffd-dad2d3320eb5"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "step 0 , loss 1.0747495430798675\n",
            "step 10 , loss 0.8235271035087279\n",
            "step 20 , loss 0.67232732284016\n",
            "step 30 , loss 0.6479418129833524\n",
            "step 40 , loss 0.6443837810804036\n",
            "step 50 , loss 0.6413347377269304\n",
            "step 60 , loss 0.6624464786675602\n",
            "step 70 , loss 0.5319603762957765\n",
            "step 80 , loss 0.5233274890720542\n",
            "step 90 , loss 0.630691835373497\n",
            "accuracy on test set: 0.76\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAG2CAYAAACDLKdOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB3zUlEQVR4nO3deXgb5bU/8O9IsiTve2zHceLsC1lJSHDCVkgJhbJ0pUCbkFJ6aYFCcy8FSiGlLQTaWy6/21JoaYH2FgqFAoVCAyEQIBASshNC9sXOYsf7bq3z+0N6RyN5JI02a/H38zx5ILJsTWRJc+ac855XkmVZBhEREVGGMCT7AIiIiIjiicENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWWUpAY37733Hi699FKMHDkSkiTh5ZdfDvs969atw+mnnw6LxYIJEybgqaeeSvhxEhERUfpIanDT29uLWbNm4ZFHHtF1/8OHD+OSSy7B5z73OWzfvh233norvvOd7+CNN95I8JESERFRupBSZeNMSZLw0ksv4Yorrgh6n9tvvx2vvfYadu3apdz2jW98Ax0dHVi9evUQHCURERGlOlOyDyASGzZswOLFi/1uW7JkCW699dag32Oz2WCz2ZS/u91utLW1obS0FJIkJepQiYiIKI5kWUZ3dzdGjhwJgyF04SmtgpvGxkZUVFT43VZRUYGuri709/cjOzt70PesWrUK995771AdIhERESVQQ0MDRo0aFfI+aRXcROPOO+/EihUrlL93dnZi9OjRaGhoQEFBQRKPDLj8t+txsLkXv7vmdJwzqTypx0JERJTKurq6UFNTg/z8/LD3TavgprKyEk1NTX63NTU1oaCgQDNrAwAWiwUWi2XQ7QUFBUkPbmaNq8LhrhM43OnGF5N8LEREROlAT0tJWs25qaurw9q1a/1uW7NmDerq6pJ0RLGZXl0IAPj0RFeSj4SIiChzJDW46enpwfbt27F9+3YAnqXe27dvR319PQBPSWnp0qXK/W+44QYcOnQIP/rRj7Bnzx787ne/w9///nf88Ic/TMbhx2zaSE+2ZteJziQfCRERUeZIanCzefNmzJkzB3PmzAEArFixAnPmzME999wDADh58qQS6ADA2LFj8dprr2HNmjWYNWsWfv3rX+OPf/wjlixZkpTjj9VpIz2Zm2Pt/ejscyT5aIiIiDJDysy5GSpdXV0oLCxEZ2dn0ntuAODsX76NhrZ+PPOdBVg4oSzZh0NERJSSIjl/p1XPTSaa7s3esDRFREQUHwxukkw0FX9ynE3FRERE8cDgJslmiODmWEdyD4SIiChDMLhJspmjPMHNkdY+NhUTERHFAYObJCvKMWN0SQ4A9t0QERHFA4ObFDDDm73ZwdIUERFRzBjcpICZSt8NMzdERESxYnCTAkTmZieDGyIiopgxuEkBYsXU8Y5+tPbYknw0RERE6Y3BTQrIt2ZhXHkuAOCT48zeEBERxYLBTYoQfTcsTREREcWGwU2KmDGqCACDGyIiolgxuEkRYpjfJ8c7knsgREREaY7BTYo4bWQBDBLQ1GVDU9dAsg+HiIgobTG4SRE5ZhMmjsgHwNIUERFRLBjcpBAx74abaBIREUWPwU0KEX03O7kcnIiIKGoMblLIDNU2DLIsJ/loiIiI0hODmxQytaoAJoOE1l47jnf0J/twiIiI0hKDmxRizTJicqWnqZibaBIREUWHwU2KYd8NERFRbBjcpJgZ1UUAmLkhIiKKFoObFKNkbo51wO1mUzEREVGkGNykmEkV+cizmNA14MQzm+qTfThERERph8FNijGbDFjx+UkAgFWvf4aGtr4kHxEREVF6YXCTgq5dWIv5tSXotbtwx4s7OfOGiIgoAgxuUpDBIOHBr86ENcuADw60sjxFREQUAQY3KWpsWS5uWzIFAHD/a5/hWDvLU0RERHowuElh1y6sxbwxxZ7y1D8+YXmKiIhIBwY3KcxokPCrr82CxWTA+gMteGHLsWQfEtGw0mNz4qo/fIS/bDiS7EMhoggwuElxY8ty8R/njgcAvPVZU5KPhmh42XK0HRsOteKvHx1N9qEQUQQY3KSBaVUFAIDGLtuQPN6f1h/GKztODMljEaWyAYcLANBrcyX5SIgoEqZkHwCFV1loBQA0dQ4k/LGOtPTi5//aDYvJgIunV8JkZPxLw5fN6QYA9NmdST4SIooEz1xpoLLAE9w099jgSvCWDLtPdgHwfKif6Eh8MEWUypTMjZ2ZG6J0wuAmDZTlmWGQAJdbRktPYktTexq7lf8/3Nqb0MciSnUic2N3uuF0uZN8NESkF4ObNGAyGlCebwEANCa4NLW3sUv5/6MMbmiYszl8GZs+B7M3ROmCwU2aEKWpxq5EBzeqzE0Lgxsa3kTmBgD62FRMlDYY3KSJCm9w05TA4KbP7sRR1UadR1s5FZmGN3XmppdNxURpg8FNmhArphJZltrf1AP1EOQjzNzQMDfAzA1RWmJwkyYqhqAsJUpSY8tyAQAN7X1soqRhjZkbovTE4CZNVA5BWUqslDp3UjksJgMcLpnLwWlY8+u5YXBDlDYY3KSJoShL7W3yrJSaWpWPMaU5ALgcnIa3AXXmhmUporTB4CZN+BqKEzfnRpSlJlcWYEyppzTF5eA0nDFzQ5SeGNykCZG56bE50WOL/4dsS48NLT12SBIwqSJP6bvhcnAazvyDG2ZuiNIFg5s0kWcxIc/i2QosEaUpkbUZXZKDHLNJKUtxOTgNZ+qyFIMbovTB4CaNVBR4phQnoqlYNBNPrsgHAIz1lqW4HJyGM3XmpjcBGVMiSgwGN2kkkU3FYtuFKZWe4GYMl4MTMXNDlKYY3KSRRM66UTcTA0BVgZXLwWnYY+aGKD0xuEkjiZp143bL2NfUAwCY7M3cGAyS0ndzhCumaJiyOZm5IUpHDG7SSKLKUg3tfeh3uGA2GVDrDWgAKMvBGdzQcDXgUGVuuBScKG0wuEkjido8UzQTTxyRB5PR95IQy8GPtHDFFA1PNvbcEKUlBjdppDJBg/x8/Tb5frezLEXDHYf4EaUnBjdpRJSlmntscLnlMPfWTwQ3UwKCm2DLwWVZxm3P78Ctz26DLMfvOIhSiSzL/sENt18gShsMbtJIWZ4FRoMEl1tGS0/47M2/dp7AL/61G10DjpD32+NdBi5WSgnBloNvPNyG57ccw8vbTyR0l3KiZFIHNgB7bojSiSnZB0D6GQ0SyvMsaOwaQGPngNKDE8jmdOGnr+zG3zbVAwDq2/rw+2/NhSRJg+474HDhiHcKcWDmRiwHtzndONExgNHeMtVfPzqq3Ke1x46qwuy4/PuIUklgcMPMDVH6YOYmzVQUhp51c7yjH19/bAP+tqkekgRkGSW8ubsJj79/SPP+B071wOWWUZSThRH5Fr+vaS0Hb+624Y1PG5X7tPXaY/43EaUidTMx4MncsAxLlB4Y3KSZyhBbMKzf34Iv/u/72HGsE0U5WXhq+XysvPQ0AMCDq/di46HWQd+zV7XtglZmJ3A5+N83N8Dh8n3AM7ihTBWYuXHLg28jotTE4CbNiBVTgbNudh7rwNInNqK9z4EZ1YV49aazcO6kclyzYDS+NKcaLreMm/62Dae6fd/XY3Pi7b2nAAwuSQnq5eAut6yUunLMRgBAK4MbylBigF+B1Ve955RiovTA4CbNBCtLvbztBNwycPbEMjx/Qx1qSjzlJEmScN+XpmNSRR6au224+Zlt2NvYjZX/3IUz71+L13aeBADMGFWk+XjqstR7+5pxrL0fhdlZuHTmSABAW298l6UTpQoxwC/HbII1y/NRyVk3ROmBDcVpJtgWDO94MzDXLBgNa5bR72s5ZhMe/eZcXPab9dh4uA1LHn5P+dr48lxcu7AWX5pTrfl4Y1VlKdFI/NW5o1BgzQLAshRFRpZlzfJnKhKZG2uWAbkuEwYcdgY3RGmCmZs0o1WWOtTcg8MtvcgySjhrYrnm940vz8MvvzoLAGCQgM9Pq8Bfr1uAt1aci2/V1cJo0D7hiOXgR1v7lADq6gWjUZJnBuBZLUWkx90v78Kcn6/Bsfb0mHgtMjcWkxE5Fs8FA5eDE6UHZm7SzAiNKcVv7/EEHQvGliLPEvxXesnMKowrPxsF2VmoLtK3fFu9HBwAFo4vxfjyPKURmZkb0uvN3Y3o6HNg9a5GfOfscck+nLBE5saSZYAked5XXA5OlB6YuUkzYkpxj82JHm9zo8iofG7KiLDfP7WqQHdgA/gvBweAb545BgBQkuvJ3DC4IT3sTjdOdXsC8g8PDl61l4ps3syN1WRUGuiZuSFKD0kPbh555BHU1tbCarViwYIF2LRpU8j7P/zww5g8eTKys7NRU1ODH/7whxgYGD5TcvMsJiU709g5gO4BBzYdbgMAnK8juImGWA5enm/B56dVAABKvcENV0uRHic7+yFGxGw63OY38TpVDagyN7ne9xz3l6LhRJZluOO41c9QSmpw89xzz2HFihVYuXIltm7dilmzZmHJkiU4deqU5v2feeYZ3HHHHVi5ciU+++wz/OlPf8Jzzz2HH//4x0N85MlVoZp1s35/CxwuGePKcpVl2/E2d0wxAGBZ3RhkeXcNF5mbzn4HHGlwoqLkOt7er/x/j82JT453JvFo9LEpPTcGZHub9HtZlqJhZOkTm7D4f95VSrTpJKnBzUMPPYTrr78ey5cvx7Rp0/DYY48hJycHTzzxhOb9P/zwQyxatAhXX301amtrceGFF+Kqq64Km+3JNKI01dg5oPTb6ClJRevbi8bipe8vxPfPm6DcVpRjhuhBbu9j9oZCO9bR7/f3dChNiT4zS5ZRydz0c7UUDROyLOP9/S041NyL/U09yT6ciCUtuLHb7diyZQsWL17sOxiDAYsXL8aGDRs0v2fhwoXYsmWLEswcOnQIr7/+Oi6++OKgj2Oz2dDV1eX3J92JPaVOdvYr/TaJKkkBgNlkwJzRxTCoVlQZDRKKc+Lfd2NzunDHP3bixa3H4vYzKflOeIMbi8nzkbMhDYKbAe/2CxaTgT03NOyI1YIAcLilN4lHEp2kBTctLS1wuVyoqKjwu72iogKNjY2a33P11VfjZz/7Gc466yxkZWVh/PjxOO+880KWpVatWoXCwkLlT01NTVz/HckgloO/9dkptPTYkWcx4YzakiE/DlGaiudy8DW7m/Dsxw2499XdaVvrpcFEWeqi6ZUAgI+PtKV8qltkbqyqzA3n3NBw0a/aW+0Ig5vEWrduHe6//3787ne/w9atW/Hiiy/itddew89//vOg33PnnXeis7NT+dPQ0DCER5wYoiy1vaEDgGcqsdk09L/KkgQ0FYtyRWe/Aweb0y8VStqOezM3504qR3m+BTanG9vqO5J7UGEoS8HVmRtuv0DDhDq4OdyafsFN0ubclJWVwWg0oqmpye/2pqYmVFZWan7P3XffjW9961v4zne+AwCYMWMGent78d3vfhd33XUXDIbBJ3iLxQKLxTLo9nQmylJCIvttQin1DvJr64nfFgzqcsXmo+2YWKG95xWlFxHcVBdlo25cKV7ZcQIfHmzFmeNKk3xkwamH+OWambmh4UXdX8ayVATMZjPmzp2LtWvXKre53W6sXbsWdXV1mt/T19c3KIAxGj1XVLI8fEoYlYHBzeTkBDfxnnVzoqPf70308ZG2uPxcSi63W8bJDs+4huribCwc7wloNhxsSeZhhaXefkGZUMzMDQ0T6uAmHctSSZ1QvGLFCixbtgzz5s3D/Pnz8fDDD6O3txfLly8HACxduhTV1dVYtWoVAODSSy/FQw89hDlz5mDBggU4cOAA7r77blx66aVKkDMciLIUAMwaVYjy/ORkpkpyPY8br7KUyNqYTQbYnW5sOdoel59LydXcY4Pd5YZB8gTmC8eXAQC21Xegz+5Ejjk1B6Uzc0PDmbos1d7nQGefA4U5WUk8osgk9VPlyiuvRHNzM+655x40NjZi9uzZWL16tdJkXF9f75ep+clPfgJJkvCTn/wEx48fR3l5OS699FLcd999yfonJEVZngVGgwSXW8b5UyrCf0OClMY5cyP6bb4+bxSe3liPo619ONU9gBH51jDfSansmLeZuLLACpPRgJqSbFQXZeN4Rz8+PtKOcydp74eWbMpScJMB2VwtRcOMOrgBPH03s3OKknMwUUh6Q/FNN92Eo0ePwmazYePGjViwYIHytXXr1uGpp55S/m4ymbBy5UocOHAA/f39qK+vxyOPPIKioqKhP/AkMhokTByRB4MEXHha8oKbeDYUy7KslCmWnFaJyd5emy1HmL1Jd0q/TbFn2w9JkpTS1IcpXJqyOURZype54ZwbGi76AwL5YKWpNz9txENv7k251a1JD24oOr//1lz8/T/qMLWqIGnHEM/MzdHWPpzoHECWUcK8MSXK0vaPGdykvROqZmJh4QTRd5O6824GVJkb7gpOw01g5uaQRnAjyzLuePET/O/bB/DR4dR6L6dmsZvCGlOaq+z5lCwlefELbkRJas7oYmSbjZhXW4z/++gothxlU3EidA048M9tx/Hy9hOYNaoI91w6LWGPJWbciMwNANSN8/Td7DrembK1fJG5sWQZfD03abr9QteAA1999EP02lw4Z1I5zp1UhoUTylBgTb3nnVJDv91/Wx2tzE1DW7/y+b+/qUfpp0sFDG4oaqIs1d5nh8stw6iaYBwpUZ4Q5Yp53szNrhNdKd10mk5kWcbW+nY8s7EBr31yQmmY/fREZ2KDGyVz49tdvrLQinHluTjU3IuNh1tx4Wna4x+SSRnilwG7gr++8yT2eUfo/21TPf62qR5Gg4Qzaovxq6/OQk1JTpifQMONyNzkmI3os7twRGPWzc7jHcr/7z/VPVSHpgvLUhQ1sf2CLAMdMewv5em38WRuRORfXZSNqkIrXG5ZGVZIsfnduoP4yqMb8I+txzDgcCsbrQ443AndpVsrcwNA1XeTWulsYUCdufFOKB5wuOFKsd4CPV7deQIA8NW5o3DtwlqMK8+Fyy3jo0NteGELtzqhwUTPzeRKT//j4ZbeQSNXdh7zbYCbavtPMbihqGUZDSjM9qS1YylN7WvqQWuvHdYsA2bXFCm3i+zNZvbdxMztlvHkB0cAAF+cWYV/fG8hVt96tvL1RO12Lcuy3wA/NVGa2pyipUe707cUXGRuAKAvzbI3p7oHlIuHWy6YiJ9edhre/s/zcMsFEwH4VrMRqYnMzRRvcNM94Bz0Ob9DdeF54BSDG8ogpXFYMSVKUmfUlvhtIzFvTDEAz6Riis2OYx1o6bEhz2LCQ1+fjbljimExGWE2ep7vngSdsLv6nejxDr4LDG7GlHpKIae64jfhOp58e0sZYDEZIKqu6Tbr5t+fNMItA7NrivzKTyJzd6y9L1mHRilM9NwU5ZiV9656yKrLLWPXcV/mprXXjtY4TquPFYMbiklpHJqKPwwoSQnzaj3Bzdaj7WlZCkglaz/z7B5/7qRyvwAy17sKqGcgMcHNsQ7PibMk16zMihHUr51UnDDu2xXcCEmS0naQ36s7PCWpS2eN9Lt9lLdMKDJrRGpKz02WEbVlnqBYHdwcau5Br92FHLMRI72DZVMpe8PghmIS66wbT91fBDf++wxNqSxAnsWEHpsTextTq1kt3bz1mWcPt8XT/LfqyLN6Ttg9CdpWQOm3CcjaAL7XjtMto6s/8aUeWZbhiKC3SD3ED0BabsFwvKMfm4+2Q5KAS2ZU+X1N9EA1dg4ktOeK0pPouck2G1HrXZmrbire4e23mT6yUOnL2c/ghjKF2IKhrSe64ObTE53oHnAi32rCaSP9Z/YYDRLmjC4CgIxdEv7KjhP4R4IbOo+192FPYzcMEnDeJP/gRmQjEnXC1ppxI1hMRuR5G3VbexOfzr72yY9xzi/f0d0zM6Aa4gcgLTM3r3kbiefXlvht2wIAI/KtyDJKcLplNHWnTjkh3dmdbnz10Q9x3VMfp2RGUq9+1etflDCPtPhKmDuPdQAAZowqVDY4ZuaGMoav5ya6D8f393v6bRaMLYXJOPjlOG9M5g7z67U5seK57fjP53egoS1xfQ+iJDWvtgTF3t+XIIKLhGVuOrRXSgmiNBWv/cmCcbrceH9/M052DuDgqfCbADpdbji9pdBBmZs0aih+dcdJAINLUoDn4qGq0FuaYlNx3HxwoAWbj7Zj7Z5TCXtfDYV+76iI7Cxf5kZdlhKZm5mjCjFhRB6A1FoOzuEhFJNIylL9dhd+/eZe7G3qxsnOATR2Dihv/sCSlHCGt+8mEzfRPNnZr5xA395zCssW1ibkcZSS1NTBu8cnvCwVInMDeF4/R1v70Bpl5k+vlh47RNuWnkDcrirTWLK8wU2aDfI73NKLT453wmiQ8IXp2nOEqouyUd/Wh2PtfZg/tkTXz311xwmc6OjHf5w7Pp6HmzH+veuk8v8tPXbkp+mgRFGWyjEbMbbcV5bylHdlfHaiCwAwa1QR2vt8g/xSBYMbionSFKrj5LTmsyb8cf3hQbfXlGTj4oB+AGH26CIYDRKOd/TjREc/RgY5Saaj4x0Dyv+/szcxwU33gEPpabpg6uB9yMT8lkSVpYLNuBHivflqMI1dvue6XcdMJjHgEPCUzwAgN80G+f3L20i8aEIZSvMsmvdRmop1Zm7cbhm3/2Mn+uwuXDKzCqOKOfxPzeFy483dTcrfW3psSkkn3ShlKbMRNcU5MEiekuypbhtOddlgd7lRmJ2FMaU5ynngVLctZSaOM7ihmJREcHIS/RcLxpbgBxdMRGWhFZUFVuUEqyXH7OnF2XmsE5uPtuOyDApuTqpWqWw42Ip+u2vQiqJYvbevBQ6XjHFluRhfnjfo6/miLJWg1VLhMjel3p6tRC8hbez0Pdd6skQ2p+eDPcsoKZO3cywic5MewY0Y3HfpTO0LB8AXdOpdMXWq26b0HLX3OjCqOMaDzDAbD7Who8+h/D2VlkZHSmwSm51lhNlkwKjiHNS39eFwS6/SWzNzVCEkSUK+NQtVhVac7BzAgeZuzB2jLwuYSOy5oZhEUpYS80xm1xRh0YQyjC/PCxnYCDOqCwEAe052xXCkqedEpy+bYHO6E7JD9lpvSeoCjZIU4MvcJGLOzYDDhRZvIBG0LDVEPTeNqudaTyBuc/i2XhByskTmxr8sJcsyHly9B899XB+PQ42LvY3d2NfUA7PREHJrC/F70TvIr17VG9Ztc4S45/CkLkkBQHOCy63BHG7pRWdfbL8fkb0UAyxrlabiXqWZeOaoQuX+St9NipSmGNxQTMSVd3ufPeyW903dnhPMiAJryPsFmqg0q6XGmyZeROYmy+jJDLy951Rcf77T5cbbez0/c7FGSQpQBTcJyNyIbECO2YiiIGnqoStL+a6gdZWlnL6tFwTxXPUHBDefnezGo+sO4icv70qZBlIx2+bcyeXKFHEtoqykN3OjDm4Sle1LVy63jDc+9VxMjPYOS2xJwiq0xs4BLH7oXSx9clNMP0esKsz2BvVjvUM3D7f2KtsuzBxVpNx/4ojUWg7O4IZiUpzr+eB0uWV0DYS+Umj2nmBG5GvX/4OZ5F1muL8pdTrx4+GEt1SyxHtlvW5vc1yXjm6t70BHnwOF2VmYO0a7fpCfwJ4b9YwbSdLeVNW3WiqxJ4EmVc+NrrKUw7f1ghBs80wRGDhcMj44EP/sWzREFvCiMBuSqgf5hbs4AQIyNwxu/Gw+0oaWHhsKrCZ80VsKbElCWepQcw9cbhkHYvy87A8YhSB6h3af6MI+78+epQ5uKlLrIpTBDcXEYjIqJ8hwpYVTInMTYXAjZigcbetTZo9kgpPehuKvnD4KFpMBxzv6lZ2b40Gskjp/ygjNZfaAKnOTgBVA4ZaBA745SYleLXVS1XOjqywlBvhpZG4CV0upf/a6vc0xHWc8yLKs9ERMC5gdFaiy0AqD5JnNoudErB5ZkCpZqlTx712NAIDF0ypQ5Z0plOjXtZY2b2ay1+5S9keLlNstK2Wp7ICy1IaDrXDLns9x9ewkkWGPNaiKFwY3FLMSHVswyLKMJm/mpiLCslRZnhlFOVmQZeBgs/6Tf2PnQMqOlpdlWcncjC3LRZ13KXw8S1Nvhem3AVTbLySgfyLUAD9hqMpSTaqyVJuu1VK+rReEYJmbE6pVb+/uPZX0wW3NPTZ0DThhkBB2pU6W0YBK7/vxmI73in/mhj03gtst441PPcHNxdOrUOZdnZaMzI36vdTRH937yqYKisTrXryWxPgKdUkK8PXcnFCN+EgmBjcUM6WpOMRVSo/NqaQ5RxRElrmRJAmTRD1XZ2bD6XLj8kfW4wsPv5eUD5hwOvocypVRZaEV50/xBCDvxCm4OdLSi0PNvTAZJJwzqTzo/fKtoiyVgMxNmGXgwNDsLyXLcuQNxQFbLwDBJxSrMzcnOgfimn2Lhsja1JTkKCWFUMTvR09TsX9DcXxPYLIs4/H3DsXtPTCUth/rwMnOAeSajThrom/pfdKDmyibitVTvEVTfXVRNkwGX3l5lqqZGPBssCmCuoMpUJpicEMx03P1fcrbWJdnMSnD0CIxoSKyCZgnOgbQ1OW5gn12U+qsYhFERqkszwxrlhGfm+wJbrbUt8e8ygHwZbimVOWjIMQQsURuv3BMR+ZmKPaX6ur3BdaA5wM/3F5KYim4VVWWCra3lCgvih3W1+1N7slZBDeiTBCO0lQcJrjpt7vQrGqQjXfPzcHmXtz3+mf44d+3Jz37FanV3pLU+VMrYM0yoswbtLckoyyl+hxujzIj2q9kLg0weAMak9GgNEoDwMyaokHfl0qLPxjcUMx8s26CX6WIhs5IszbCJO+bRu9V8dE235jwv35Un3IbA570ZhLE+PuakhxMGJEHl1vGe/tj79sQ/U9iNVswYkJxvK/CgdCbZgrq/aVaYmgq/vcnJ/HvT05qfk0M8Mu3miD6mjv6QweQAyEaigMzN0pj+HRfY3gyieBmvM7gRvx+jneE3gKkod3/6/FeLSVOyh19Dr8xCalOlmVlCfjF3tdAmbevsMfmHPI+Qf+ylPbrXJZl3Pb8Dtz32m7Nr4tjDpy7pS5zzqz2z9wA6qbi5PfdMLihmIkUbKiGYnHFF2kzsRDpxmzq9Hlj14Df1NBUIEoZI4t8/UfxLE2JDzhR9gkmL0GrpZwutxJUhCpLAf6lqWi099px09+24ea/bUOnxoe5chxF2SjyLosO91gic6MuSynbL6hS9m63rATuV82vAQB8fKQtqf0o4j0yQWNooxa9Zan6Vv/gJt7/RnXfVzrNtPr0RBca2vphzTLg3MmeEnC+xQSz97Uz1KUp/7KU9uu8sWsAz285hsffP6zZdNxv9864CShriqbi0SU5g/apA9RNxczcUAbQVZZSloFH1kwsiCuCo629uq6ExAexODk99eGRqB43UUQTqsjcAFBKU+v2NetalhuKmIxaqvEBpKasALK74IrxMdWaum1wuWWYDFLY37menq1QPjneCZdbhtMt45BGw3mTNwtQUWBVPpDDPZbI3Kh7VrR6blp6bHC4ZBgkz87bY8ty4XTL+OBAa1T/lnhQghvdZSl9WzAc9V4wiPJbvJtG1WWuPY3Jv/LXSzQSnzdphBIAS5KEstzklKb8ylJBStzq17/WhY0I4K0BmZvZ3lLUognaewFOSKFZNwxuKGZ6tmAQV7cVUZalyvMsKMrJglvniimRubl2YS2MBgmbDrfhsxS6GhQridSZm3m1xci3mNDWa8cO7wTQaIksWkm4spRqQnQ890wSJ8qqIquyfUEwse4s/8nxTuX/1bsWC74SoFX36izNzI1Gz40on4zIt8JkNOBcb/N2svpuOvsdSn9bpGWpY+39IXtdxDLwSZWenxvvnht1sLQ7hd6r4Rxq9rzmzgjYeFSUpoZ6kJ+ehmJ1ll0rSBU9N9kBmZsvzqzC/103Hz++eKrmzxUXoQ3tfYOGXQ41BjcUsxIdVyinumPL3EiS5Et56rgqOOrN3JxRW6IMMvvLhiNhv8/mdOGf24/j1R0nsK+pG44E9eqIspQ6c5NlNODsSWUAEHMZTSlLhcncWEwGZQVEPEtTon8jVL+NIPqC9Gy+qmWXKrgRJxq1xi5f5kYJxMMsB1eG+GVpr5YSQYCYMl3lDVI/5y0txnsgo17ivVFRYAnZSK4mNqPtd7iCXukDvguGaVWe2TlxD27UmZs0Cm7E8NLASdDJWA4uy7LfBO5gZSl1o7HW71Fkx3MCMjeSJOHsieVBdzovzTWjOIqxHYnA4IZippycQlx5KwP8oszcAL6+m31hhkTJsqxcZY4pzVF2235p2/GQK5GaugbwjT98hFue3Y6b/7YNF/7Pe5h2z2pc+D/v4s4Xd8a1MVCUpQJ3Ob9kxkgAwF8/Ohr0g0mPNiVzEzq4kSRJaSqOZ4Oo+PdVF4XfNTrW/aXCZW5E1rCy0KpkssIFUmL7Bb+9pbyZG6dbht0b9IrMzUhvkLpgbAmsWQY0dg1gbxKGmR1UVkrl6/4ea5YR5d4sQ6jSlAhuThvpaSRNZFnqcIu+8nMqEM+DGKsglEX4uj7R0Y9rn9yEd/dF35DebXPC4fIF1dFmbkTpVc8oATXPRWhk/ZGJwuCGYlaiY1ZJrD03gGqZYZhmtfY+h7L6p6YkB2fUFmNKZT4GHG78fXOD5vdsrW/Hpb9Zj231HSiwmjBndBHyLCY4XDL2NfXgb5sa8HqQ1TiRcqmaUNVlKQD4wvRKTKnMR/eAE4+9eyjqxxA19XANxYAvIxHPk9UxHTNuhNIINl8N1N5r92uE1bpaFGWpygIrSnJFQ3Hoq2mtzI26uVJMKVYyN95JrdYsI+rGefoR3tkz9KumDjRH1m8j+EpT2ium3G7fBcNp3qnHPTZnXLNT6tefWw5/EZMqRFAWGNyIhRbNOstSq3c1Yt3eZvyfjgxzMIFLv4Pto6Z+/WsN8AxWltIj0rEdicLghmImTk4Olxx0SbFSloohc6PsMRXmikBcYVYUWGDNMkKSJFzrzd785aMjgxpnn/u4Ht/4/Uc41W3DpIo8vHLTWXjp+4vwyU8vxAd3nI8r53lWwYRa4rvlaDt+/NInSoYqlOZuG5xuGUaNZluDQcJ/XTgZAPDUh4dxqiu6JbGifyXcUnBAvWIqflfKytYLReGDWd9qqcjT97tOeLI24kP4SGvvoGZszcxNmFlCviF+vg93k9Gg9OCI/iSln0eVgfOVpoa+7ybSZeCCeo8pLc09NticbhgNkpJBdbllv/lBsQosj+w5mS7Bjee1FFgGjLQsJbKteoMhLYEXCMEyN21hylKiXyZwKbgeei9CE43BDcXMmmVUarNa6f5em1O5Kot2KTjge9OEWzF1tNVTmhhT4pvJcPnsahRmZ6GhrR83/HULvv/0Fix7YhMu/+163P6PT2B3ubHktAq8+P1FynJHSZJQXZSNr84bBQB4b39z0BVF9776KZ7ZWI+bn9kWdtWRmItSkW/RbLa9YOoInD66CAMON37z9oGQP0tLn92prPYp0ZG5UcpScdyC4Xi76LnRUZaKYX8pUZI6d1I5sowSBhxunFQFhDanS/kgryxQNxSHy9wMHuIHDJ51I36XI1V77Jw3yTuQ8Wh72M1k4y3SZeBCuOXg4oKhuigbBVYTxMs2nn034vWX632OP2tMj74b8Ryom/MBqAb56QxuvFmWWFZXicxNltHzCwq2/YL6vaaVsQ3Wc6NHquwOzuCG4qIkRGlBZG1yzMZBHwCRKM+3oDDbs2JKq3FUEMvAa1TTNLPNRnzjDE8GZs3uJrz+SSPe3deMHcc8J8f//PwkPHrNXM3jm1NThHyrCR19DuzUWMV0rL0PO70/Z+PhNvzv2v0h/x0ng/TbCJIk4bYlUwAAf9tUP2i+SDjig8tsMignilDivXmmLMu6Ns0UYilLiWbi2aOLlOmp6uXgohxqNhlQlJOleym4VuYGUM+6EWWpwZmb0aU5GFfuWRL+wuZjEf+bojXgcCmD9iItS40qChPceF+Do0tyPH1a3tdMPIMb8bNO9+5gn0qrG4NxutzKayGwLFWuZG70va5FYNLcY4u63CfeQ2NKPRdo7X0OzZ+lLldp9dpF23MDeN6LL35/If5506KIvzeeGNxQXIRaYitKKyPyLZCk0MuCQ5EkCZN01HPrVc3Eaj+4YCJ+fPEU3H7RFPzs8tPw66/NwmPfPB1rfngObr5gojJmPJDJaMDZEz2rmLRKU2L0ungOfvP2fmw4GHzOibJSKsRKorrxpTh7YhmcbhkPv7Uv6P20qFdK6Xm+84JsKxCtdtW+WVWF+stS7VHsLyUyNzOqCzG2zPPaUDcVq5eBS5Kk/I6C9SIIWkvBAd9Go302J5wut1KGHBnw77x0pqcx/Gf/2o07/rHTb/Bfohxs7oEse1btlOnI2KkpWzAEKUuJ95S4YBCrZeI5yE9kEM6o9Syp3tPYnfLbMKhLuYEriJThpjozNyIwsTvd6IoyaBQB0jhv9tnudGuWDqNdCq5HnsWE00cX616tlygMbiguQm3BEOsycLUJOjbQFMPG1PugAJ4MxXfPGY/vnTceS+tq8ZW5o3DR9CqlhyAUUWrQWskggpubz5+Ar80dBbcM3PrctqAfauIEEnhCDPQjb/bmpe3HsTeCoWZ6V0oJeZb4NhSLFTfl+RZdV37R7i/V2edAQ5vnsaaPLMT4cs8Hujqrp14Grn6scBt1ag3xA3yZm167C03dNrhlTwlA9FcIN50/ATd+bjwkCXj24wZc+pv12H0isZkI9Z5SkV5E+MpS2lnChoD3VL41/k3oIoMwZ3QRjAYJHX0Ov93cU5EoO1pMBmUisSACzPY+h66REupm4GiXj4v3fk1Jjq80pdF3E67nZiCG4CZVMLihuFD6JjQyN7HuK6UmMjehVlIoH8QBmZtYiJ21dxzr8PtgONU1gC317QCAi6ZX4d7LT8P48lw0ddnwX8/v0Jw0HK4sJcwYVYiLZ1RCloH/fnOv7mMVH4ylefqe79x4BzcRzLgBot9fSjQTjy7JQWFOlrLvzSFV5qZJtVIK8AU3oZrfAR2ZG7tTWSlVWWgdlPXLMhpw25IpePq6BRiRb8HB5l5c8cgH+PvH2qv14uFghJOJ1cTvqnvAqdknVB8suIlnWcr7+yjNtSiZh1Tvuwm2UgoAinPMSk+dnq1F1NnEaAf/qS9sCrO1s5ROl9sv4NHM3MTQUJwqGNxQXCgrXjTqy81xzNyEa1YbcLiUq/UxJfELbioLrZhSmQ9ZBt5XbWz5xqeNkGXP1WZloRU5ZhN+e/XpMJsMeGdvM/60/vCgn+Ub4Bf++Vjx+ckwSJ4+oWBX1YH0DvAT8i3xPVEd07FhZqBo9pdSl6QAYJy3iVbdc6MuSwHhm9+FsJkbm0uZcaMexBho4YQyrL71HFwwZQTsLjd+8vKuhJWool0GDngC3OIcTxlBa9ZNYHCTiJ6bHlWgMNU7KDDV+25EWU5rqJ3BICnBdLgVUG637DdAMdqmYvV7X/w+A2d7BW6mGarnhsENDXsiBXtSY+lyPJaBC5PC7DHlGSHvWXGhtyyj13nevZ/eVfXd/NtbkhJTkAFgalUB7vniNADA/7y1b9BxKoPfdJz8J4zIQ623OTDcxoZCpGWp3DhvnhlJM7EQzf5SIriZ7g1uRObmeEe/8pw3BZSl1I8Vakpx0MyNeXDmJlx5sSTXjD8um4d8qwl2lzvsHk7RinYZuBBsxVS/3aW8h0cH9tzE6TXjcPl6Q/IsJkyp8lzEpPpy8GAD/IQyHZsKA54gUb3KMuqylPc1XZxrRnGOryzmd5+AY4l3z02qYHBDcTG50nulpdFXEOu+Umrl+RYUWE1BV0zVt3luG12aG1Pzshaxb9C73o0t23rt2Hi4DQDwhelVfve9ZsFoVBdlo8/uwvr9LcrtNqdLuYrTk7kBfB+QeudftEYZ3MS75yaizE0U+0vtCsjclOWZkW81QZZ92280qmbcCEpwEyKQUlZLBSwFz1ZlbrRm3AQjxgoA+oPUSDhdbqWROtJl4MIo77L94wEZQpExLLCaUOjNBojxAfFqKFYH1nlWE6Z6P0/2pHFZClAtBw/z3g183cfac1Oaa1Z+V4FlqcALCK0ANZal4KmCwQ3FhTjBHGrpHfSBF8+GYs+KKVGaGnxV51uyqv/Eqte82mLkWUxo7bXj0xNdWLO7ES63jGlVBYP6eyRJwuKpnkzPGtU+UU2dnufCYjLoDj7EaPxIh4HpLkvFuTlUzH6JLLiJbH+pzn6HEsBMr/acCCVJUno1Drd4shiNnSEyNyGupsWHe+BScCVz43D6Nj/VGaSKFUnHgqxIisXRtj44XDKys4wRPe9q1UEG+YnnWf0aj3cpUwQJ1iwDsowGJXNzsDm1t2EQn3XBRlzoHeQXGIDEGtwUq8tS/dqZG9Em1qMRoMayFDxVMLihuCjJNSsfqp8GZG/US8HjQaxu0loxdVRZBp476GuxyjIasGiCZ7T+ur2nlJLUF6ZXat7/89M8t6/d06SknJWhb0XZujNLkQ4DizhzY45zWSqCrReESPeX+tSbtakpyUZRju/fKfpuDjZ7JhWLrGGVVuYmZFlK9NwEDPHznsT61JmbED03aqPCrEiKha8klRt0pEE4wTJLgf02gC8gjlfPjQis8yyeE3JlgRVFOVlwueWk71EUSpeSudFe9qz3vdvW6x9gNHdH3nNjd7qV30epuiwV8J4SK1pFWZxlKaIwxJ4z6l2aBxwu5QNgREHsmRvAN6lYa8VUQ8A8jng717sk/LVPTuKDA55y0xdmaAc3C8aVIN9qQkuPHdsbPCuqImkmFpSrP50feK0RrpbKi2Pmps/uVGr8kQQ3kQ7yC2wmFsYqmZtetPba4XTLkCRf9gsASnLCZ26UvaWCZG567U7VvCK9mRtvZiQBZaloJxOrBduCIXDGDRD/8QGBvSuSJGFKpbfvJoIxCENNd89NmIxke0A2JZrMjdho12iQUGDNUpWlAjM3nr+LYFUr+zbAhmIiH3GiUe/SLCbEWkwGFAT5AIhUqD2mRAo9niul1M6d7Om72dPYDYdLxoQRecrsnUBZRgPO9+4z9OanntKU2C1b79U+AJQluCwVzxOVOHHnW0wRDfGKdH8p8RoTO1QL45RZNz1K1qYsz4Iso++jTskSBTnhyLKs7Aoe2HMjMjcdfQ5lRctInb/LRPbcxLIMXAjWUBw44wbwZSritb2EVnlnSmX0K6a6Bxwx7dEUyeMAwTM3yuaZ4TI3ff6ThaMJbsSFQXFOFgwGScncdPZrZ27EkNNeu2vQljH97Lkh8pk+ynOiUWduxATXEQWxTSdWm1qVD0nyXJ2rtyZwu+Wg04njpbooW8kcAcFLUsLnp1UA8PXdnIhgQ0khkg34BhwupV6uZ18pQL1aKvbehmNRrJQCIt9fSpQ+g2VuDrX0DloGLoSbUuxwyRDz/YJlbsTu49Ysz7YOeoSbAhyLWJaBCzUlOTAZJLT12vF/Hx1VbtcqS8Uz2wdo7880VayYirCpePWuRpz14Ds4/7/XRTRaIBriuINduPnKUqGPQxynWA3aEsUWDO1KcON5zKJs7cyNCIJGq/be6w0YT8CeGyIVdVOx+NATE0Yr4tBMLJTmWXDWBM92CP/Y6tu7R71zsZ5l1tE6z5u9AYAlp4UObsSGjodaenHgVE9EK2wE8QGp50pUfHBlGSWl6TMcZVdwu1Nz6GAkfMFbZM9/JGWprgGHsjIoWHDT0efAHu8Vf0VAOTTUwEnAtwwcGLwUXMy5EdmMkYX6e6dEwNfcbYtrk6xb1ZcSS3BTYM3CDy6YCABY+c9dWLO7CbIsh+y5iVdDsVZ5xzfrRt82DP12F3780ie44a9b0NnvQLfNibf3JHZn9mCbZgp6L0x8wY0noBtwuNFrj+w1EthrV5SjHcSLx6oqtMLszWiqf49ut6z0nLHnhgieN3JVoRWyDGXUvDpzE09fnevZqfvFbceUE7IoSY0ssvqVIeJNNAqPK8tV+oyCybdmYeF4TyD25u5G5eQfSc+Nb7VU+L2XxGqjEp37SgG+D2ZZBvpiPOlG00wMRLa/1KfHPa+t6qJsZSNMIcdsUp7bDYc8+3tVDgpuPFe0wUpgYoAfoBXceD7sRQyot98G8JQLxMniRJDsjd3pjjgbcrJrAH12F0wGKeZG+pvPn4Ar59XALQM3/20r1uxugs3phkHyn8uUbxF7S8UpuBFBgiq4mTgiHwbJczIOV9bZ09iFy367Hs9srAfgy4C8k/DgJnRZSrx323rtIS8cRNaluihbeY1FOqVYBDEiuCnO1R7ip56DpZWBG1AF9+y5IfISPRCiJyKey8DVLpxWiTyLCQ1t/fj4iGfWjNYVZiLMH1uCJ66dhz9de4auAEJdmoomsyGu/uyu8Bvqie0LxNJqPaxZBqWRMdYVU8ejzNxEsr9U4HybQKLvZvNRTxN3ZaF25qa9V7tfRD3AL/D3K7ZfECLpnZIkKWjTrvC132/AWQ++HdH8mMPeeU9jSnNiDuolScIvvjQd500ux4DDjRuf2QrAE9iof3a8xwcomRtVBiTbbESt2IYhxDC/Dw+04LLffoD9p3pQnm/B/103Hw9+ZSYA4L19zbr2dYpWuDk34nXtcsuDJgOrqYfvRVKGVmvtCcjceLdf6Oj33xncL7jRmDTdr8oYWU0MbogA+E444gQUz32l1LLNRlwywzM474UtntJUfat3gF9J/JeBBzp/SoVSAglHBDfb6juU4CSSspQ1y6h86IdNb3s/4Eoj2BVakqS4jdOPNnNjMan+jWGaikW/i5iFEmisakdkQCtz43luemxOvxKUMKCslBr88SjKUoLeGTdCsKZdwHOFvaOhAx19jog2ShXZ0UgCrVCyjAY8cvXpmF5dAIfLc1IM7GFTX/EHNqNGo1sjcwP4SlMbDrZqfp8sy3jwjb2wO904e2IZVt9yNs6eWI5Zo4pQmmtGt82pXPwkQrjgJsvo68kK9d5tVwUckY5+UH5GX2BZyvO4LrdvHzVZlv3up7WYwNdvY4h6rEAqYHBDcTVjlP9y8HjuKxXoq/M8panXPzmJPrtzyDI3kaoosGLWKF+WId9qClqjD0ZZMRUmVR3p1gtCXpy2YFB2PI+i56lE5/5S4oRSnKP9bxxX5t93Epi5KbCaYAqxoaEIeLSaKXMDgptIglQg9HLwfaqhlOK1rEdrFAFtOLkWE5649gzleAPLXeqTeWAzajR8vSv+5Z1LZ44EADy98ahmNmvL0XbsaOiA2WTA/1w5W1mdZDBIynYpb3+WuNKUrywV/P3sG+UQ/L3b6hfciBVWkTVDB/bcWLOMShm0w5ul7BpwKgGrX1lKdVGTCTuCAwxuKM7EPj8Hm3vQZ3cqS8HjNcBPbd6YYowpzUGv3YU3Pm1UDfBLreAG8GVvAP1Lh9X0rrqIdICfID7kYgluHC63kqkbFU1wo3N/qa4wJxRRlhICgxtJkpReHa3HCrb1AgDkDCpLRZi58W5xoDXIT52taWjTv6IqmlKkHiPyrXj6Owtw7cJaXH/2OL+vWUxGpRk1Hn03PTbt3+mF0yowvjwX3QNOPO3tp1F7/P1DAIAvz6lWggLhAu+E8Lf3Jia4kWVZ1QgdfMWcsiAgSCbG4fIN3yvJMeu+kAnUrvHeLwrYgkEE87lmo19GWDz/gHoZeHxGdyQLgxuKqxH5VlQUWOD2NhU3dQ8efx8vkiThy3M82ZsXthzTnMeRKi5UraoaGUETqiAaE5u7B29MqtamnOgiC27EcvBYNkJs7ByAWwbMRsOgE40epcoqptAf6r5ptkGCm8DMjcZrL9Ry8GBbLwCDMzeRZqhC9dzsb4oucyOGO5blx3ejWMCTsfnpZadplmC1rvqjFWwYnsEg4YZzxwMA/rT+sN8qsyMtvXjTO2LhurPGDvqZZ00sg8kg4VBzL460DN6HLlZ9dpfSWB4qc1MaZpCfeA0aJKAgOyvqnhutrK1YMSX6fZT7eAOuPI1J0/2qslQ6S++jp5Q03dtUvOVoOzq8nfqJyNwAwJdPrwYAfHiwVclqBO7zlAomjshTMkqRljIA9ZLSMJkbpakwsuc7HmUpX0nKGlWtXgQc4faX6g4z8r66OFvJKuRbTErgplYcYkpxsK0XxG3qHuOIMzchem72qoKbhgi2aBDBYFmcMzfh+LZgiH2QX0+IJdWXz67GyEIrmrttfqMfnvjgMGTZM5pBbMmiVmDNwvyxJQCQkCXh4nVoNEghSzjlYYIV0dhelGOG0SChPMqem7aAOTee//e8RzoCMjdiSrdmz40j/acTAwxuKAFEaUp8oJiN+gedRaqmJAdnjitRhq4V52RFNBl3qEiShK+c7skyzakpivj79V7NibJUpP0XoYKbDw+2KFtNhBJtM7Ggd3+pnjBNnEaDpASSFUGCj1BTioNtvQB4fo8ie5NvMYUsR2gRmZumrgGl4RnwlDj8y1LJ7bnRIy8O2T4h1LwYs8mA68/xlMV+/+4hOF1udPTZ8fxmT6ATWDJTExPCExPc+KYqh1o1Ga5BWASnIhDReyGjpm4UVr8OlLJUrwhuPI8lsjuaPTd29twQaRIrpsRS3PL8+E0n1iKCBiA1S1LCTZ+bgNW3nu13vHpFOgwsXmWpAYcLy5/8GMuf+jhsVifaZeCC3kF+epo4Rd9NsMxKqLKUeim4FnFFG8mMG6Es1wKzyQC37NuxHPCcyNSTZBu7BjRXcmkRr4loSoGxiOcgP/G6C1wtJVx5Rg2Kc7JQ39aH13c14umN9eh3uDC1qgALx5cG/bkiuNl4uDVuy9aFrjBBthAuWBGZG1GWLVNK0PozN902X6OwOnMTWJby9eR5HiNfI3OjbJrJnhsifzO8K4PEEtF4LwMP9IUZVcpVxugE7AYeLwaDhCmVBVGVbHxNifrGuMdrtdSx9n7YnG7Yne6w2waIzE2006H17C/lcsvK5NZQK87E7uDBghtxAtAKpETmJtjoebEFQzRLrw0GSWm2Ptbhy86IfpsxpTnIMRshy/o22JRlOYmZm/gN8utRtjHQzoTlmE1YvsjTV/O7dw7gzx8eAQBcf/bYkBdO48rzMLYsFw6XjPX7m2M+Tr9j1tFMDPh6boJdmPhm3ARmbvQHN6KUKxqFBV9ZyuF3P/Fa0cq+9SmZm/QOD9L76CklVRRY/XZhTlS/jZBnMeGSmZ6ZN5Mroh8/n8r0rKCwOV3KB26kK2eU2nvAiUo9STfcyfZEZ2yZGz37S6mvMINd5QPA1fNH48tzqnHtwsGNpoAqkNJcLRU6cyNWkUTTGA74ynbq51P020yuyEeNdw+qBh3BTbfNCbt3SN1QZ24KlFk3sfXcOF1uJVsQKmBdVleLXLMRexq7carbhooCC77oXSoeyucmJ6Y0pSeDCPguTII2FAdckIj799ld6NO5zF49BFBNGeQnem4CZuHkeQMzLgUn0kk9PTYRK6UCrbx0Gu770nRcu0j7ZJbuylW7CwfbnkBkbUwGCQXZkaWUc5X0tH8pxC+40Zm5ibbnRk9ZSpxQzCaDZk+MUFOSg4eunI1pQbbHEB/ubZqrpcJkbizRZ24AX9+Nuql4nwhuKvNR4y2t6lkxJYLdPItpyDc51FppEw11wKrV/C0U5mTh6gWjlb8vW1gLc5AAVE1ZEr6nOea909TCbZoplIV57wY2AudZTEpgLVbChaNkZAKDmxz/zTMHNxR7XjN+ZSk7G4qJgpquOqkkOnMDeFLD1ywYE/FwvHQhMmF2pztoA6e4MiyOYF8pIdicG73BjSzLytdHFUXX96RnfynxIRzuhBKOEtyEGOIXLHMjsmK1OidUBxKZLfXzua/JM3V5YkU+ako8X9fTVBxtA3k85McpuBHfbzEZwgYr3zl7HHLMRhRmZ+Ga+WN0/fwzakuQZzGhpceGXSc6YzpWNXVDcSjK9ilB3ruBpWRJkvwCokDv7WtW5kkpPyNI5kYETINWS4nMjWVw5kbpuclK789SBjeUENNVmZtETCcebqxZRuVDNFhpqjXKZmJA+woOAI53+D5Eg232CHiaJW1ONyRp8NA8vfTsLxVuF+ZIHyvUUvBgwc3tX5iCe744DReF2RE+GN9ycE/wIssy9jX6ylKiKV5XcNMT3VyjeIhXz02wGTdaKgqs+PctZ+NfN5+FQp0rMM0mA86e6Nm8dm0cpxWHG0kgZJuNSp+W1ns3cNsEQFWGDghuPjzQgqVPbMLNz2zzuz1Yr53I3CgNxWJURMCcG63tF7LN6R0epPfRU8qaodpuINENxcNFuCnFygC/KK7ixfLmwOBGb8+NyEJU5Ft1lQq06NlfqkfnCSUccRLo6LMP2htJ9BwEK/OMLcvFt88aG/W/c5S3p0Y8Zyc7B9Btc8JkkDC2LFcJbvSUpUSD+VD32wDqzTNj67nR25grjCnNVUp3ep3lDW62NXRE9H2hhNtXSk0EK1olV6UspQpMgs26+dC7x9bHR9uUwBZQ9e3kBAY3Zr+vB66m9O0p5/sdsueGKITKAquyqWDgvjQUnXCrKKId4AeEKEt1+gKaUJkb30qp2LJ04faX6tJZCghHpOvdMtAZsFtzuMxNrERZ6mTHAFxuWem3GVuWC7PJoJy4I8rcJDW4iTFzE6dsXChjvJvpngzTNxYJvZkbIPT+UlqBie/+/u+D7d7gTJaB91Srv1oDJg8LInPTNeBEj82plJxEcK/+HYpScH+Y4D5dMLihhJAkCX9YOg+PXnO67t2zKTSlDh+kLBXtjBtAe1Kp2y3jpKos1dg1AIfLPeh7AV/gU10c25yhcPtLRVLCCCXLaFD6dgKXnivbLyTow72iwAqTQYLTLaOpa0AJbiZVeqbsitVSXQNOdPaFzoq0Kpmb9O25iVfAGooIuk909Aft54qU0nOjJ3MTYpBf4Aomz/0HX8i43TJ2qDJP6/b6gpugmZtsX+AltqDIMkrKcy3+65Z9QY1oKObeUkRBTK8uxBdmVCX7MDJGeZA6vODL3MQnuGnptcHucsMgeT4Q3TIGNTIKsQ7wE0pD9MIAqp6bGIMbIPieP4nO3BgNkjIA8Fh7P/Y2epqJJ3u3EMg2G5WTW7htGJI1wA/QbkaNRk+YAX7xIGYv9dpdQfu5IqV3tRSAoDt999mdyuo8/+BmcDB0qKXHryH5vX3NSkk12Ia5JqNBCUIPNvco9xELDnLMRmU7EfF79A3xS+/wIL2PnmgYCVuWimHljHqIn7iyPdHh2/RUnByC9d0ci3EZuFDoncsRWCoSwg17i0RJkCnFyvYLCUzLixVlxzv6fJkb1Yym0d4VU+H6bpI1wA/wvWa6Yg1uRHkngZkba5ZRCZzDjTTQK5IsohgmGVhqFEG82WRAjmrptVZD8bb6DgDA6aOLkG8xob3PgZ3HPLdpNSULojR1sLnXex9fICxJ0qBBfv3cfoGIhpLY9bk5yOyLaHcEB3zzRdTpafXEYZGRUffgqPmWgccW3PhWdwTL3MSvhBFsSvFAmKXg8SCCwIa2fuw/JYIb3+aPevtuWpTfeSY0FCe2DCIC9FC9Y5HwDfELH2hPrfKMxvg0YCm62HqhJMd/fIPWlg2i32ZebYnSIC1KU20hsrbidX7Im7kJ/HzIDxjgye0XiGhIhcvctPVG31Dsl572nmxOdPiCm1CZG1mWccx7Eo41cyN6BIL1mnTH8UQYbBfycNsvxIMY5LfhYCsGHG6YTQa/xnu9K6ZEg2p5fvJ6bgYc7qC9WHrEs9QYisienAwSoEcqkrEEp430rB492Nyr9HQBwefTaDUgi+Bmdk0RzptcDgB4d1+z3/wcrSC3SAluRObG/7ECl4MzcxMnjzzyCGpra2G1WrFgwQJs2rQp5P07Ojpw4403oqqqChaLBZMmTcLrr78+REdLlDx6y1LR9NxIkoQ8s/8V3HEluLGqBs8N7rlp7PItZa6NcWVcUcBeOIEiWaESjrIyK7AsNRSZG+/z+fGRNgDAhPI8GFV7jumZUmx3upWSUDIyN+qTeix9N74gIfbfaSgjQ7yGoxHJUvCKAgtKc81wuWXsUe3+7tt6wf/fLiaSd9ucGHC40G93Kd83u6YI507yTF3ecawDh1o8GRmjQdI8FnHBIO43KLhRloMHZG4Y3ETvueeew4oVK7By5Ups3boVs2bNwpIlS3DqlPagJbvdjs9//vM4cuQIXnjhBezduxePP/44qqurh/jIiYZeuWq1VOCKD5vTpXw4RTvQzbcc3PPhdkLVJKw1VVcQH7piKXMsCpVdjIOslorjVb5YWRLYvCwaPBMZ3IhZN05vQ+jkyny/r4sVU8dCzBYSx200SCjMTmxgoMVkNCgnwFhWTImyVqIzN9VxLEvZnC5lTy89gbYkScpWIOrSVOAu3UJBtglmo3cLBu9kZZdbxoh8C6oKragstGJKZT5kGXh52wkAnvKT1qa8YvNMrcZlQLW/lI0NxXHz0EMP4frrr8fy5csxbdo0PPbYY8jJycETTzyhef8nnngCbW1tePnll7Fo0SLU1tbi3HPPxaxZs4b4yImGnui5sTndg2aLiNp9LCe63IAVU6K/ZmRhtlJu0joxKNN1A07Q0RDH3hlsQrFN32aFeojVZ42d/lfyInMzFGUpQd1vAwCjS0Vw0zdoyKDQoppOHM1O8/GgLAePoe9G6blJ8NYp8ey5UQdzevu/xNT2T090Kbf5lnD7v2clSVKaxFt67NjubSaeXVOk9Oac590Q9J/bj3t+Rq72+74oYHl4YHDj67nx/A59e0ux5yYqdrsdW7ZsweLFi30HYzBg8eLF2LBhg+b3vPLKK6irq8ONN96IiooKTJ8+Hffffz9cLpfm/QHAZrOhq6vL7w9ROsoxm3xj3AP6RFq9jaXBrt70GBTceNP3gT03gVmjvaqtA2Ll67kJnbmJx4lQ7A112Dv/Q0j0UnDAs0WF+tc0KWA3+8oCK7KMEhwuOejy+5YkDvATlH6NWDI3EZR3YqGedRMrdb+NUef77TQlc+M7BwXruQH8+262e1dFzaopUr5+7iRP381Jb3AerBxdFBA4BWZ21WMgXG5Zef2zLBWllpYWuFwuVFRU+N1eUVGBxsZGze85dOgQXnjhBbhcLrz++uu4++678etf/xq/+MUvgj7OqlWrUFhYqPypqamJ67+DaCgF23MmlgF+Qr5qOXi/3aX8zOribKUZs9/hGtQPszdgCF0sAvfCCRTPnhsxXPJUt80vE+YrSyXuwz3LaEBlgW+ac2DmxmiQlDJKsL6bZA7wE8TvIVxZqrPfgbte+gRv7W4a9DXRDJvoTW/F89nYNQBnDA3QQHSr9kRT8Z6TXcrjt4fok1PPtRKZmzmq4GZebbHf4wcLbooDMjeBgZSyu7u3v0dgcDOE3G43RowYgT/84Q+YO3currzyStx111147LHHgn7PnXfeic7OTuVPQ0PDEB4xUXwFG+MebOO8SOSqNs8UJak8iwkFVhOsWb7Bcuq+G5dbxv5TnkbFKfEIbrxzbvrsLqU8pNYdx4FvhdlZSmBwRJW98ZWlEvvxKEp9uWaj5vDDcMvBkznAT8jXGP4YSJZl/NfzO/D0xnr88o09g74+VKulyvIsyjDKU0GmfOsVSTOxMKYkB3kWE2xOtzJzRtlXKkcrc+O5bU9jN4539EOS/PfsyzIasGhCqfL3mDM3A77tGYDEZi6HQtKOvqysDEajEU1N/pF8U1MTKiu1d9utqqrCpEmTYDT6IsqpU6eisbERdrt2GttisaCgoMDvD1G6CjbGPXC332ioy1InVCulRI2/2pvWVwc3R1p7YXe6Yc0yKE2wsci3mpQl6YP3fHLB7nQr94sHkb0R01uBoRniB/iaiidU5GuWEsMFN7HsAh8vvi0YgvfcPPHBEazxZmyOtPbBHdBD5Cs1JrYp2mCQlB3r9ZamXv/kJK7/y+ZBr8VoghuDQcLUKs8FgGgqDpVxFUGreO4mjsgblLEUfTfA4K0XhLA9N6ql4Opl4Mnq44qXpAU3ZrMZc+fOxdq1a5Xb3G431q5di7q6Os3vWbRoEQ4cOAC325dS3LdvH6qqqmA2J+8NTjRUgu0v1RrDAD9BXZZSz7gRRKZBPetGNBNPCnKCjpRB1RAdOOtGXfrIjVOz49iAvhu3W1ZWwST6ynWMt2l4WpV2xkvMumkIsmIqJXpuAqbbBtpW345Vr3+m/N3udKOp29dD5HS5lWxBontuAE9zPKBvSnFj5wD+6/kdWLO7Ca9/ctLva5EM8FMTpSnRd9Ouo+dGHOtsVUlKEPNugFBlKd8xStLgYEcrc5NtTu+SFJDkstSKFSvw+OOP489//jM+++wzfO9730Nvby+WL18OAFi6dCnuvPNO5f7f+9730NbWhltuuQX79u3Da6+9hvvvvx833nhjsv4JRENK1OED96jxXQFGf6LLVc27OK5qJhbEiUF91bsnjs3Egm/FlH9w0xNFE2c448o9jbwiuLGrejESvSvyN88cgx+cPwHfP2+C5tdFJixYz01LCvTcKP0aGj03HX123PTMNjjdMi6ZUaUEc0dbff8eMXYA8L3+Esm3HDz8rJsH/v0Z+ryZjCMBTefRltLUy8Hdbhnt3gBeKzAR/XXC7JriQfepKsxWysEVqh4uNXUwU5xjHvTeUffcZMoAPwBI6lqvK6+8Es3NzbjnnnvQ2NiI2bNnY/Xq1UqTcX19PQwGX/xVU1ODN954Az/84Q8xc+ZMVFdX45ZbbsHtt9+erH8C0ZAKNsgvHmUp35wbp/LhXa2VuVEFN2JfpHgsAxeKsrNwFIMH+UUyEVavwMzNwBD2HJTlWbDiwslBvx5uSnFrKvTciBkpAcGNp89mJ4539GNMaQ5WfWUGbnx6K4629qG+tQ9njvP0iogl5BaTIeYZSXroXQ6++UgbXt5+Qvn7kVbt4EbPpplq072Zm90nutA14FCW+Qf2xQCDg1atzA0APPiVmXhzdyMWT6vQ/Hq+xQSD5NlapVjjcTI1c5P0hew33XQTbrrpJs2vrVu3btBtdXV1+OijjxJ8VESpKVhwo555Ei1l80y7U5mbI5bPev5/8IlhbwKCG98gv4DgJo4zboRx3uDmUHMvZNm3DNYgAaYk9xzUeDfPbO62od/uGnTCSeammUK+Rbvn5skPjuCtz5pgNhrwyNWno8CahTGlOXh/P3C0zRcoRNO7Egs9wY3LLeOnr34KABhXnotDzb040uIfYPbYoitLTazIg9loQNeAEzuPefpu8iwmzZV55aqgNTvLOGhcgDCrpshviXggg0FCUY4Zbb12zcyuX89NhkwnBtJstRTRcCf2EFIHNw1tfdjh/aCcMEL7A1AP0cfSPeD0G+AnBE4pHnC4lHR9PMtSYtZNR8Csm0SsqhldmgOD5Plgb+6x+e0rpd7IMBkKs7OUE8+xdv+TqyzLSp9VcjM3g1dLybKMR989CAD4yRenKsPrxpR4Akl1WapniJaBCyM1muID/X1zA3Yd70K+1YRffdUzIPZIa69fI3R3lPOWsowGTKr0vEff3+/Z9DJYr4z69zpjVCFMxuhP1+I9pfVYYtuLwIbidMfghiiNlGlswfCn9YfhcstYNKF00LyUSKg30Dup0XMjgpuWHjsGHC4cONUDt+xJqZfnx+8EK1L0wXpu4jHjRrCYjMqqpcPNvUOyI7hekiQpfTcNAcFNV78TDpfn9x/L8v9YafXcHDjVg+ZuGywmA648wzdXTExdVpfZEvE7DUW8hk92avfcdPY78Ks39gIAbl08CTNHFcJokGBzutGoGqYYS6B9WpUn2Ht/fwsA7WZiwBPciuzhnBCZGT3Ee0qrbK0exCiCG2sGlKWS/w4mIt1EcDPgcKPX7kJ7rx3PfeyZ3fQf54yP6WeLq+ejrX2wu9wwSFCWzgKeD8gc74feiY5+v8nE8cxy+DI3gT033lJAnK/yRd/NoZbeIdkRPBJK302rf3DT4s3a5FtMST1WrSF+Gw61AgDOqC3xK7doNRQP1QA/ocob3HT2OzRn8/y/t/ajrdeOCSPysLRuDLKMBtR4e83UfTddUa6WAoDTqj1NxaIZP3DrBcFg8G3BEKzfRi8xR0erbC2ee7vLrVxQ5KTI6z8WDG6I0kiuxaQEGC3dNvz1o6Pod7gwtaoAZ08si+lniw85sfKqosCKLFUqXJIkVc/CQEKaiYHgPTfKHkRx7s8YV+5rKh6KHcEjIbIdgcvBxRDHwBU1Qy1PY4jfhwc8wU3d+FK/+4pArbPfoSzzVyb9DlHPjRhKCQAnA0pTR1p68ecNRwAAKy+dprz2xTYd6r6bWF6LYhsGIVjmBgCW1tViwdgSnDOpPOh99BCv8fHlg8vW6sBSDDfMhIbi1HgHE5Fu6vkXT314BABww7njYs6eBC7FHakxNdfXd9PnWwYe7+AmyFLwRKyWAvybiodi64VIiEF+6iGDQGoM8AN8q4VEkOJ2y0rmJjC4yTGbMMIbjImm4njuFabXyCA73L+5uxEut4yF40tx9kRfMFFb6g1uWuPTCD2lsgDqt2qo3+GNn5uA5/6jLuZl8is+PxnPffdMXDpr5KCvGQ2ScsEk5melSuYyFgxuiNKMWCL62LsH0dprR3VRNi6eURXzzw0MGrSCG9+JQZW5iWMzMRB888xuW2L6M8aWea5mD7X0DNnWC3qJXovNR9rhUM3gaVUG+CU3uFH3acmyjN0nu9DZ70CexYSZ1YWD7h9YmuqJ43YaegWbdfOBN+N0/pQRfrePVTI36uDGE8wVRPFazLWYlIAaCJ25iZdssxELxpUGnQ8l3vvN3tcVG4qJaMiJzI1oSLzurLF+5aNoBZ5g1MvAhVHe/oPPTnYpTZkT4x3cBNk8M1HLhsd6U/b1rX3KyTZVMjfTqgpQlJOFHpsTO707QwPqAX7JLUuJQNPh8iyj33DQEyDMH1uiubpntHfFlGgqHuql4ID2cnC7041Nh9sAAGcFlHdFQKaVuYk2iygmFQPBt00YSuK9LzI3OSxLEdFQU/dZFGZn+a1IiUVgE6HWZo4i4PnggCewGlloVcpI8aIEN32Bq6US059RVWCFNcsAp1tWNjS0pEjmxmCQsGi852S7fn+rcnsqbL0AeF4zosTSPeBUSlILA0pSgi9z4y1LKQ3FQ7NaClAFN52+4GZbfTv6HS6U5ZkHZSJF5uaod18sp8utTC6ONihT990MReYmHFEWbPZujcGeGyIacuqr9aV1Y+I2tt5gkJCr+lBTz7gRqos8Jyfx4T4pzv02AFDo3RlcPcEViH4qbDgGg6T0VXx20rPnT6pkbgBg0QRPcCMCSsA3wC+ZWy8AnucuzzsfqaPPjo3e4EZMIA4UWJYa6oZiwBegqzM34rldOL5sUO9adVE2TN7l4Ce7Bvy2jIi2ROqXuUmB4EY8/6KXiz03RDTkxEwZs8mApXW1cf3Z6pOMds+Nf6kq3s3EgK+hWJb9J98m8ipfrCZRgpsUydwAwFne4GZrfTt6vc9BKgzwE0T24sODrei1u1CYnYVpVQWa9xUrpgJ7bpLRUKzuuVnvDW7Ec61mMhp8x93SqywDj2XLCHXmJiWCG+/z7x2dxbIUEQ29syeUoSzPjFsumBjX4XmA/4oprbJUZYEV6p7EeDcTA56gTXy4qldMJbI/Y5y3qfiYd8l1qiwFBzzLwWtKsuF0y0pfiOi5SfZqKcAXEL+5uxEAUDeuNOgO8WO8GbLGrgEMOFx+m6EOlZHKIL9+uN0yugccyoTvhRNCZ5wOt/bG5XVYnGvGJTOqMHNUoRI4JVPgBQMbioloyNWW5WLzTz6PGz+nvZt0LMQVdK7ZiILswR/eJqMBlardh2OZiByK1iC/RJYwxqpWrwCpl5YXGQWRYUiVnhvAV5r56JAn8AoWIACejRvFa6yhrU+1Am7ogpuKfAsMkqcJuqXHho2H2uByy6gtzVGmVQeqVa2Y6o5hgJ/aI9ecjlduOisuiwFiFfj8p9rrPxrJf1aJKGWIzM3Iouygc3PE7uAGKba9rEIJHOQny3LChvgBvhVTQiplbgBPLwjg6Q2xOV1K9qA8BYIbkXUR/VHBmokBzyDI0aq+m54E7BcWjjpAP97Rjw8OevttNEpSgm/3+L6Evg6TJTBzxoZiIsoo6uAmGPG12rLchF3hBW6e2Wd3QfQW5yei56YsMLhJrQ93ETDsaexWtr0wGSTN7NpQU5/ky/MtmlNw1ZSm4rY+1QaUQ7daClCXpgaUZmKtfhtBNJwfjVNZKtUEBpfsuSGijCJKBiI7o0X04iSi30YI3DxTnFBMBikhA/aKcsx+jZ2pMsRPKM2zKE26r2w/4b3NnPSdywH/k3zduNKwxyRm3Rxq7kG/w7PyaCgzN4AvuNne0IF9TT2QJM+xB6MsB2/rU16TQ9knlGiDMjcsSxFRJhHj/qcGWe0CAF+aU42F40uxbGFtwo4jcNaNut8mUSd0dd9NqmVuAN9wuVd3eoKbVFgpBfj3noQqSQkic7PbuzINGPpAQQQ3L207DsCzeinUvJmqQiuyjBLsTrcymXuodjIfCuy5IaKM9r3zxuPZ756Jb4QYDDixIh/PXH9m0Fkm8VAQ0FA8FI2n/sFN6n00ink3TV2p00wM+AcmojcoFBHc7DnpCRJiWVIdLTHSQEzkXRTmuE1GgxL47zruWVmVUWUp9twQUSazZhlx5rjSpK/gKPIO8gssSyVyku04VVNxKl65nlFbDLPq91KWAsvAAd9JvrooGzUlwcuZglgOLkpSyQgSAgdULgrRbyOMVQY9Zl7mJjC4CZxWno6i+gT7y1/+ApvNNuh2u92Ov/zlLzEfFBENb76eG09Dcc8QNHGOS/HMTY7ZhNPHFCl/L4vzjKNoTa8uhEECvjirSlfJsLLA6hekJaN3Rd0wbzYacEZtSdjvEcvB7d4NTOM9KTuZAnuehm3mZvny5ejs7Bx0e3d3N5YvXx7zQRHR8BY450aZLZLAE6HYHRxIrQnFauoVPakwwA8AzqgtwbZ7LsQdF03RdX+jQcIoVYZnqJuJAf8BlaePKdJ1Mq8NWFGXSQ3F6tVqkpSawX2kovoXyLKsGaEfO3YMhYWDt7knIopEYcDO4EMxW2RMaY6yCaQ1BRuKAf/ySar03ACeLTMiafQeo5rKm4wgoSDbpOyjFq7fRqgt9R/wl1FlKdX7KjvLmBKr8GIV0atqzpw5kCQJkiThggsugMnk+3aXy4XDhw/joosuivtBEtHwInpuROamawiGvVmzjBhVnI2Gtv6UTcvPqC5EvtWE7gFn0jfNjIWn76YZQHKCBEmSMGNUIT4+0o4Lplbo+h4x60bIpIbiXIvv9Z4Jy8CBCIObK664AgCwfft2LFmyBHl5vjSu2WxGbW0tvvKVr8T1AIlo+FH33MiyrOq5SeyJ8LYlU7BuzynMHVOc0MeJlslowI8vnor39zejTsey61Sl3k9pKDfNVPvt1aejpceGKZXBxx6ojSzKhtloUHpuMim4sZiMMJsMsDvdKdlMH42IfjsrV64EANTW1uIb3/gGLJbUSYsSUeYQO4M7XDL6HS7fnJsEnwgvmzUSl80amdDHiNVV80fjqvmjk30YMRmjKvEko+cG8MwJimRWkNHg2TriwKkeAJkV3ACeILPVaU/ZrGWkouq5Of/889Hc3Kz8fdOmTbj11lvxhz/8IW4HRkTDV47ZiCyjp+7f0edQem4yaYXKcOYX3KRRY6667yaTem4AX5CZCVsvAFEGN1dffTXeeecdAEBjYyMWL16MTZs24a677sLPfvazuB4gEQ0/kiShUNV30z1EZSkaGqOKfc3bycrcREPdd5NpmRsRZGZKWSqq4GbXrl2YP38+AODvf/87ZsyYgQ8//BBPP/00nnrqqXgeHxENU8oWDP12ZUJxOl3lU3DWLKOyM3c6BaxiObjRIGVM460g3luZ8u+KKrhxOBxKv81bb72Fyy67DAAwZcoUnDx5Mn5HR0TDlph109nn8M25ybCr5eFswgjPgpRUmdejh9iiI8+SuD3OkkW8t4Z1cHPaaafhsccew/vvv481a9Yoy79PnDiB0tL07eAnotRRpJp10zMES8FpaP344qm4bclknD9lRLIPRbfZNUWYMCIPF8+oTPahxJ3I3GRKz01UnxQPPvggvvSlL+FXv/oVli1bhlmzZgEAXnnlFaVcRUQUC7F5Zme/r+emII1KGBTa1KqCkLvPp6JciwlvrTg32YeREOLCwTqcg5vzzjsPLS0t6OrqQnGxbx7Ed7/7XeTk5IT4TiIifcQgv9Yem7LJIntuiBKjIt/TA5UqG7LGKupPCqPRCKfTifXr1wMAJk+ejNra2ngdFxENc6Isday9X7mNZSmixFhaV4uiXDO+OKMq2YcSF1H13PT29uLb3/42qqqqcM455+Ccc87ByJEjcd1116Gvry/ex0hEw1BgcGPNMiDLmP4b+hGlosKcLHzrzDEozpDMTVSfFCtWrMC7776LV199FR0dHejo6MA///lPvPvuu/jP//zPeB8jEQ1DYkpxQ7vngimdlgwTUXJFleP9xz/+gRdeeAHnnXeectvFF1+M7OxsfP3rX8ejjz4ar+MjomGqKMd/88xk7UFEROknqsxNX18fKioG76Q6YsQIlqWIKC5E5kbgjBsi0iuq4Kaurg4rV67EwMCAclt/fz/uvfde1NXVxe3giGj4KgoIbthMTER6RfVp8fDDD+Oiiy7CqFGjlBk3O3bsgMViwZtvvhnXAySi4Uk0FAv5FvbcEJE+UQU3M2bMwP79+/H0009jz549AICrrroK11xzDbKzs+N6gEQ0POVbsyBJgCx7/s7MDRHpFdWnxapVq1BRUYHrr7/e7/YnnngCzc3NuP322+NycEQ0fBkNEgqsWejs575SRBSZqHpufv/732PKlCmDbhd7ThERxYO6NMXVUkSkV1TBTWNjI6qqBk8xLC8v567gRBQ36hVTnHNDRHpFFdzU1NTggw8+GHT7Bx98gJEjR8Z8UEREQGBww8wNEekT1afF9ddfj1tvvRUOhwPnn38+AGDt2rX40Y9+xAnFRBQ3YpAfwIZiItIvqk+L2267Da2trfj+978Pu90OALBarbj99ttx5513xvUAiWj4KmJZioiiEFVwI0kSHnzwQdx999347LPPkJ2djYkTJ8JiscT7+IhoGFM3FOexoZiIdIrp0yIvLw9nnHFGvI6FiMiPuuemgGUpItIpqoZiIqKhwJ4bIooGgxsiSllcCk5E0WBwQ0QpS/TcSBKQk2VM8tEQUbpgcENEKassz7NIoTjHDINBSvLREFG6YBGbiFLW2LJc3LZkMmpLc5N9KESURhjcEFFKu/FzE5J9CESUZliWIiIioozC4IaIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMkpKBDePPPIIamtrYbVasWDBAmzatEnX9z377LOQJAlXXHFFYg+QiIiI0kbSg5vnnnsOK1aswMqVK7F161bMmjULS5YswalTp0J+35EjR/Bf//VfOPvss4foSImIiCgdJD24eeihh3D99ddj+fLlmDZtGh577DHk5OTgiSeeCPo9LpcL11xzDe69916MGzduCI+WiIiIUl1Sgxu73Y4tW7Zg8eLFym0GgwGLFy/Ghg0bgn7fz372M4wYMQLXXXdd2Mew2Wzo6ury+0NERESZK6nBTUtLC1wuFyoqKvxur6ioQGNjo+b3rF+/Hn/605/w+OOP63qMVatWobCwUPlTU1MT83ETERFR6kp6WSoS3d3d+Na3voXHH38cZWVlur7nzjvvRGdnp/KnoaEhwUdJREREyWRK5oOXlZXBaDSiqanJ7/ampiZUVlYOuv/Bgwdx5MgRXHrppcptbrcbAGAymbB3716MHz/e73ssFgssFksCjp6IiIhSUVIzN2azGXPnzsXatWuV29xuN9auXYu6urpB958yZQo++eQTbN++Xflz2WWX4XOf+xy2b9/OkhMRERElN3MDACtWrMCyZcswb948zJ8/Hw8//DB6e3uxfPlyAMDSpUtRXV2NVatWwWq1Yvr06X7fX1RUBACDbiciIqLhKenBzZVXXonm5mbcc889aGxsxOzZs7F69Wqlybi+vh4GQ1q1BhEREVESSbIsy8k+iKHU1dWFwsJCdHZ2oqCgINmHQ0RERDpEcv5mSoSIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIiIgyCoMbIiIiyigMboiIiCijMLghIiKijMLghoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIiIgyCoMbIiIiyigMboiIiCijpERw88gjj6C2thZWqxULFizApk2bgt738ccfx9lnn43i4mIUFxdj8eLFIe9PREREw0vSg5vnnnsOK1aswMqVK7F161bMmjULS5YswalTpzTvv27dOlx11VV45513sGHDBtTU1ODCCy/E8ePHh/jIiYiIKBVJsizLyTyABQsW4IwzzsBvf/tbAIDb7UZNTQ1uvvlm3HHHHWG/3+Vyobi4GL/97W+xdOnSsPfv6upCYWEhOjs7UVBQEPPxExERUeJFcv5OaubGbrdjy5YtWLx4sXKbwWDA4sWLsWHDBl0/o6+vDw6HAyUlJZpft9ls6Orq8vtDREREmSupwU1LSwtcLhcqKir8bq+oqEBjY6Oun3H77bdj5MiRfgGS2qpVq1BYWKj8qampifm4iYiIKHUlvecmFg888ACeffZZvPTSS7BarZr3ufPOO9HZ2an8aWhoGOKjJCIioqFkSuaDl5WVwWg0oqmpye/2pqYmVFZWhvze//7v/8YDDzyAt956CzNnzgx6P4vFAovFEpfjJSIiotSX1MyN2WzG3LlzsXbtWuU2t9uNtWvXoq6uLuj3/fKXv8TPf/5zrF69GvPmzRuKQyUiIqI0kdTMDQCsWLECy5Ytw7x58zB//nw8/PDD6O3txfLlywEAS5cuRXV1NVatWgUAePDBB3HPPffgmWeeQW1trdKbk5eXh7y8vKT9O4iIiCg1JD24ufLKK9Hc3Ix77rkHjY2NmD17NlavXq00GdfX18Ng8CWYHn30Udjtdnz1q1/1+zkrV67ET3/606E8dCIiIkpBSZ9zM9Q454aIiCj9pM2cGyIiIqJ4Y3BDREREGYXBDREREWUUBjdERESUURjcEBERUUZhcENEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWUUBjdERESUURjcEBERUUZhcENEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWUUBjdERESUURjcEBERUUZhcENEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWUUBjdERESUURjcEBERUUZhcENEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWUUBjdERESUURjcEBERUUZhcENEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGYXBDREREWWUlAhuHnnkEdTW1sJqtWLBggXYtGlTyPs///zzmDJlCqxWK2bMmIHXX399iI6UiIiIUl3Sg5vnnnsOK1aswMqVK7F161bMmjULS5YswalTpzTv/+GHH+Kqq67Cddddh23btuGKK67AFVdcgV27dg3xkRMREVEqkmRZlpN5AAsWLMAZZ5yB3/72twAAt9uNmpoa3HzzzbjjjjsG3f/KK69Eb28v/vWvfym3nXnmmZg9ezYee+yxsI/X1dWFwsJCdHZ2oqCgIH7/ECIiIkqYSM7fpiE6Jk12ux1btmzBnXfeqdxmMBiwePFibNiwQfN7NmzYgBUrVvjdtmTJErz88sua97fZbLDZbMrfOzs7AXieJCIiIkoP4rytJyeT1OCmpaUFLpcLFRUVfrdXVFRgz549mt/T2Nioef/GxkbN+69atQr33nvvoNtramqiPGoiIiJKlu7ubhQWFoa8T1KDm6Fw5513+mV63G432traUFpaCkmS4vpYXV1dqKmpQUNDA0teCcbneujwuR46fK6HDp/roROv51qWZXR3d2PkyJFh75vU4KasrAxGoxFNTU1+tzc1NaGyslLzeyorKyO6v8VigcVi8butqKgo+oPWoaCggG+WIcLneujwuR46fK6HDp/roROP5zpcxkZI6mops9mMuXPnYu3atcptbrcba9euRV1dneb31NXV+d0fANasWRP0/kRERDS8JL0stWLFCixbtgzz5s3D/Pnz8fDDD6O3txfLly8HACxduhTV1dVYtWoVAOCWW27Bueeei1//+te45JJL8Oyzz2Lz5s34wx/+kMx/BhEREaWIpAc3V155JZqbm3HPPfegsbERs2fPxurVq5Wm4fr6ehgMvgTTwoUL8cwzz+AnP/kJfvzjH2PixIl4+eWXMX369GT9ExQWiwUrV64cVAaj+ONzPXT4XA8dPtdDh8/10EnGc530OTdERERE8ZT0CcVERERE8cTghoiIiDIKgxsiIiLKKAxuiIiIKKMwuImTRx55BLW1tbBarViwYAE2bdqU7ENKe6tWrcIZZ5yB/Px8jBgxAldccQX27t3rd5+BgQHceOONKC0tRV5eHr7yla8MGvJIkXvggQcgSRJuvfVW5TY+1/Fz/PhxfPOb30RpaSmys7MxY8YMbN68Wfm6LMu45557UFVVhezsbCxevBj79+9P4hGnJ5fLhbvvvhtjx45FdnY2xo8fj5///Od+exPxuY7ee++9h0svvRQjR46EJEmD9njU89y2tbXhmmuuQUFBAYqKinDdddehp6cn9oOTKWbPPvusbDab5SeeeEL+9NNP5euvv14uKiqSm5qakn1oaW3JkiXyk08+Ke/atUvevn27fPHFF8ujR4+We3p6lPvccMMNck1Njbx27Vp58+bN8plnnikvXLgwiUed/jZt2iTX1tbKM2fOlG+55Rbldj7X8dHW1iaPGTNGvvbaa+WNGzfKhw4dkt944w35wIEDyn0eeOABubCwUH755ZflHTt2yJdddpk8duxYub+/P4lHnn7uu+8+ubS0VP7Xv/4lHz58WH7++eflvLw8+f/9v/+n3IfPdfRef/11+a677pJffPFFGYD80ksv+X1dz3N70UUXybNmzZI/+ugj+f3335cnTJggX3XVVTEfG4ObOJg/f7584403Kn93uVzyyJEj5VWrViXxqDLPqVOnZADyu+++K8uyLHd0dMhZWVny888/r9zns88+kwHIGzZsSNZhprXu7m554sSJ8po1a+Rzzz1XCW74XMfP7bffLp911llBv+52u+XKykr5V7/6lXJbR0eHbLFY5L/97W9DcYgZ45JLLpG//e1v+9325S9/Wb7mmmtkWeZzHU+BwY2e53b37t0yAPnjjz9W7vPvf/9bliRJPn78eEzHw7JUjOx2O7Zs2YLFixcrtxkMBixevBgbNmxI4pFlns7OTgBASUkJAGDLli1wOBx+z/2UKVMwevRoPvdRuvHGG3HJJZf4PacAn+t4euWVVzBv3jx87Wtfw4gRIzBnzhw8/vjjytcPHz6MxsZGv+e6sLAQCxYs4HMdoYULF2Lt2rXYt28fAGDHjh1Yv349vvCFLwDgc51Iep7bDRs2oKioCPPmzVPus3jxYhgMBmzcuDGmx0/6hOJ019LSApfLpUxUFioqKrBnz54kHVXmcbvduPXWW7Fo0SJlGnVjYyPMZvOgjVArKirQ2NiYhKNMb88++yy2bt2Kjz/+eNDX+FzHz6FDh/Doo49ixYoV+PGPf4yPP/4YP/jBD2A2m7Fs2TLl+dT6TOFzHZk77rgDXV1dmDJlCoxGI1wuF+677z5cc801AMDnOoH0PLeNjY0YMWKE39dNJhNKSkpifv4Z3FBauPHGG7Fr1y6sX78+2YeSkRoaGnDLLbdgzZo1sFqtyT6cjOZ2uzFv3jzcf//9AIA5c+Zg165deOyxx7Bs2bIkH11m+fvf/46nn34azzzzDE477TRs374dt956K0aOHMnnOsOxLBWjsrIyGI3GQatGmpqaUFlZmaSjyiw33XQT/vWvf+Gdd97BqFGjlNsrKytht9vR0dHhd38+95HbsmULTp06hdNPPx0mkwkmkwnvvvsu/vd//xcmkwkVFRV8ruOkqqoK06ZN87tt6tSpqK+vBwDl+eRnSuxuu+023HHHHfjGN76BGTNm4Fvf+hZ++MMfKhsx87lOHD3PbWVlJU6dOuX3dafTiba2tpiffwY3MTKbzZg7dy7Wrl2r3OZ2u7F27VrU1dUl8cjSnyzLuOmmm/DSSy/h7bffxtixY/2+PnfuXGRlZfk993v37kV9fT2f+whdcMEF+OSTT7B9+3blz7x583DNNdco/8/nOj4WLVo0aKTBvn37MGbMGADA2LFjUVlZ6fdcd3V1YePGjXyuI9TX1+e38TIAGI1GuN1uAHyuE0nPc1tXV4eOjg5s2bJFuc/bb78Nt9uNBQsWxHYAMbUjkyzLnqXgFotFfuqpp+Tdu3fL3/3ud+WioiK5sbEx2YeW1r73ve/JhYWF8rp16+STJ08qf/r6+pT73HDDDfLo0aPlt99+W968ebNcV1cn19XVJfGoM4d6tZQs87mOl02bNskmk0m+77775P3798tPP/20nJOTI//1r39V7vPAAw/IRUVF8j//+U95586d8uWXX87lyVFYtmyZXF1drSwFf/HFF+WysjL5Rz/6kXIfPtfR6+7ulrdt2yZv27ZNBiA/9NBD8rZt2+SjR4/Ksqzvub3ooovkOXPmyBs3bpTXr18vT5w4kUvBU8lvfvMbefTo0bLZbJbnz58vf/TRR8k+pLQHQPPPk08+qdynv79f/v73vy8XFxfLOTk58pe+9CX55MmTyTvoDBIY3PC5jp9XX31Vnj59umyxWOQpU6bIf/jDH/y+7na75bvvvluuqKiQLRaLfMEFF8h79+5N0tGmr66uLvmWW26RR48eLVutVnncuHHyXXfdJdtsNuU+fK6j984772h+Ri9btkyWZX3PbWtrq3zVVVfJeXl5ckFBgbx8+XK5u7s75mOTZFk1qpGIiIgozbHnhoiIiDIKgxsiIiLKKAxuiIiIKKMwuCEiIqKMwuCGiIiIMgqDGyIiIsooDG6IiIgoozC4ISIioozC4IaIUt61116LK664ItmHQURpgsENERERZRQGN0SUMl544QXMmDED2dnZKC0txeLFi3Hbbbfhz3/+M/75z39CkiRIkoR169YBABoaGvD1r38dRUVFKCkpweWXX44jR44oP09kfO69916Ul5ejoKAAN9xwA+x2e8jH7O3tHeJ/ORHFkynZB0BEBAAnT57EVVddhV/+8pf40pe+hO7ubrz//vtYunQp6uvr0dXVhSeffBIAUFJSAofDgSVLlqCurg7vv/8+TCYTfvGLX+Ciiy7Czp07YTabAQBr166F1WrFunXrcOTIESxfvhylpaW47777gj4mt9wjSm8MbogoJZw8eRJOpxNf/vKXMWbMGADAjBkzAADZ2dmw2WyorKxU7v/Xv/4Vbrcbf/zjHyFJEgDgySefRFFREdatW4cLL7wQAGA2m/HEE08gJycHp512Gn72s5/htttuw89//vOQj0lE6YtlKSJKCbNmzcIFF1yAGTNm4Gtf+xoef/xxtLe3B73/jh07cODAAeTn5yMvLw95eXkoKSnBwMAADh486Pdzc3JylL/X1dWhp6cHDQ0NET8mEaUHBjdElBKMRiPWrFmDf//735g2bRp+85vfYPLkyTh8+LDm/Xt6ejB37lxs377d78++fftw9dVXJ+QxiSg9MLghopQhSRIWLVqEe++9F9u2bYPZbMZLL70Es9kMl8vld9/TTz8d+/fvx4gRIzBhwgS/P4WFhcr9duzYgf7+fuXvH330EfLy8lBTUxPyMYkofTG4IaKUsHHjRtx///3YvHkz6uvr8eKLL6K5uRlTp05FbW0tdu7cib1796KlpQUOhwPXXHMNysrKcPnll+P999/H4cOHsW7dOvzgBz/AsWPHlJ9rt9tx3XXXYffu3Xj99dexcuVK3HTTTTAYDCEfk4jSFxuKiSglFBQU4L333sPDDz+Mrq4ujBkzBr/+9a/xhS98AfPmzcO6deswb9489PT04J133sF5552H9957D7fffju+/OUvo7u7G9XV1bjgggtQUFCg/NwLLrgAEydOxDnnnAObzYarrroKP/3pT8M+JhGlL0nmmkciylDXXnstOjo68PLLLyf7UIhoCLEsRURERBmFwQ0RERFlFJaliIiIKKMwc0NEREQZhcENERERZRQGN0RERJRRGNwQERFRRmFwQ0RERBmFwQ0RERFlFAY3RERElFEY3BAREVFGYXBDREREGeX/A8YTl7t2oiRNAAAAAElFTkSuQmCC\n"
          },
          "metadata": {}
        }
      ],
      "source": [
        "n_layers = 1\n",
        "batch_size = 20\n",
        "steps = 100\n",
        "trained_params, trained_bias, loss_history = quantum_model_train(n_layers, steps, batch_size)\n",
        "\n",
        "pred_test = quantum_model_predict(X_test, trained_params, trained_bias)\n",
        "print(\"accuracy on test set:\", accuracy_score(pred_test, y_test))\n",
        "\n",
        "plt.plot(loss_history)\n",
        "plt.ylim((0, 1))\n",
        "plt.xlabel(\"steps\")\n",
        "plt.ylabel(\"cost\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0kRgFZwr3fHK"
      },
      "source": [
        "The variational circuit has a slightly lower accuracy than the SVM---but\n",
        "this depends very much on the training settings we used. Different\n",
        "random parameter initializations, more layers, or more steps may indeed\n",
        "get perfect test accuracy.\n",
        "\n",
        "How often was the device executed?\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 611,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "VGhHTCTP3fHK",
        "outputId": "58325120-adb7-431f-9661-85eae220b173"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "2025"
            ]
          },
          "metadata": {},
          "execution_count": 611
        }
      ],
      "source": [
        "dev_var.num_executions"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mJyxRIhl3fHK"
      },
      "source": [
        "That is a lot more than the kernel method took!\n",
        "\n",
        "Let's try to understand this value. In each optimization step, the\n",
        "variational circuit needs to compute the partial derivative of all\n",
        "trainable parameters for each sample in a batch. Using parameter-shift\n",
        "rules, we require roughly two circuit evaluations per partial\n",
        "derivative. Prediction uses only one circuit evaluation per sample.\n",
        "\n",
        "We can formulate this as another function that will be used in the\n",
        "scaling plot below.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 612,
      "metadata": {
        "id": "FMFvt86o3fHK"
      },
      "outputs": [],
      "source": [
        "def circuit_evals_variational(n_data, n_params, n_steps, shift_terms, split, batch_size):\n",
        "    \"\"\"Compute how many circuit evaluations are needed for\n",
        "       variational training and prediction.\"\"\"\n",
        "\n",
        "    M = int(np.ceil(split * n_data))\n",
        "    Mpred = n_data - M\n",
        "\n",
        "    n_training = n_params * n_steps * batch_size * shift_terms\n",
        "    n_prediction = Mpred\n",
        "\n",
        "    return n_training + n_prediction"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "c8coagmG3fHK"
      },
      "source": [
        "This estimates the circuit evaluations in variational training as:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 613,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "esATEcjo3fHR",
        "outputId": "838018ea-56bd-4971-d441-7e8b57dbf6ef"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "48025"
            ]
          },
          "metadata": {},
          "execution_count": 613
        }
      ],
      "source": [
        "circuit_evals_variational(\n",
        "    n_data=len(X),\n",
        "    n_params=len(trained_params.flatten()),\n",
        "    n_steps=steps,\n",
        "    shift_terms=2,\n",
        "    split=len(X_train) /(len(X_train) + len(X_test)),\n",
        "    batch_size=batch_size,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nfqqOSzb3fHR"
      },
      "source": [
        "The estimate is a bit higher because it does not account for some\n",
        "optimizations that PennyLane performs under the hood.\n",
        "\n",
        "It is important to note that while they are trained in a similar manner,\n",
        "the number of variational circuit evaluations differs from the number of\n",
        "neural network model evaluations in classical machine learning, which\n",
        "would be given by:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 614,
      "metadata": {
        "id": "uumnwm6l3fHR"
      },
      "outputs": [],
      "source": [
        "def model_evals_nn(n_data, n_params, n_steps, split, batch_size):\n",
        "    \"\"\"Compute how many model evaluations are needed for neural\n",
        "       network training and prediction.\"\"\"\n",
        "\n",
        "    M = int(np.ceil(split * n_data))\n",
        "    Mpred = n_data - M\n",
        "\n",
        "    n_training = n_steps * batch_size\n",
        "    n_prediction = Mpred\n",
        "\n",
        "    return n_training + n_prediction"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JnHDNbRt3fHR"
      },
      "source": [
        "In each step of neural network training, and due to the clever\n",
        "implementations of automatic differentiation, the backpropagation\n",
        "algorithm can compute a gradient for all parameters in (more-or-less) a\n",
        "single run. For all we know at this stage, the no-cloning principle\n",
        "prevents variational circuits from using these tricks, which leads to\n",
        "`n_training` in `circuit_evals_variational` depending on the number of\n",
        "parameters, but not in `model_evals_nn`.\n",
        "\n",
        "For the same example as used here, a neural network would therefore have\n",
        "far fewer model evaluations than both variational and kernel-based\n",
        "training:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 615,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "PhQiOZWj3fHR",
        "outputId": "74cc2b3f-319e-42bc-9a75-d24665a67d7c"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "2025"
            ]
          },
          "metadata": {},
          "execution_count": 615
        }
      ],
      "source": [
        "model_evals_nn(\n",
        "    n_data=len(X),\n",
        "    n_params=len(trained_params.flatten()),\n",
        "    n_steps=steps,\n",
        "    split=len(X_train) /(len(X_train) + len(X_test)),\n",
        "    batch_size=batch_size,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lW-D9kig3fHR"
      },
      "source": [
        "Which method scales best?\n",
        "=========================\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mICU026f3fHR"
      },
      "source": [
        "The answer to this question depends on how the variational model is set\n",
        "up, and we need to make a few assumptions:\n",
        "\n",
        "1.  Even if we use single-batch stochastic gradient descent, in which\n",
        "    every training step uses exactly one training sample, we would want\n",
        "    to see every training sample at least once on average. Therefore,\n",
        "    the number of steps should scale at least linearly with the number\n",
        "    of training data samples.\n",
        "\n",
        "2.  Modern neural networks often have many more parameters than training\n",
        "    samples. But we do not know yet whether variational circuits really\n",
        "    need that many parameters as well. We will therefore use two cases\n",
        "    for comparison:\n",
        "\n",
        "    2a) the number of parameters grows linearly with the training data,\n",
        "    or `n_params = M`,\n",
        "\n",
        "    2b) the number of parameters saturates at some point, which we model\n",
        "    by setting `n_params = sqrt(M)`.\n",
        "\n",
        "Note that compared to the example above with 75 training samples and 24\n",
        "parameters, a) overestimates the number of evaluations, while b)\n",
        "underestimates it.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9j20OPV03fHS"
      },
      "source": [
        "This is how the three methods compare:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 616,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 487
        },
        "id": "Neg50ctN3fHS",
        "outputId": "62e6e0a5-2c9d-43c1-ee53-56489b5faf55"
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnYAAAHWCAYAAAD6oMSKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACWHklEQVR4nOzdd3QUVRvH8e/uJpteSUINCb2E3ot0lC4dRRRE7CKiYnstgIqgImJXUMECgiBNmvQqIF2aNIEghJrek937/jFkyZJCFhIm5fmcsyc7M3dnnl1C8sudO3cMSimFEEIIIYQo8ox6FyCEEEIIIfKHBDshhBBCiGJCgp0QQgghRDEhwU4IIYQQopiQYCeEEEIIUUxIsBNCCCGEKCYk2AkhhBBCFBMS7IQQQgghigkJdkIIIYQQxYQEOyGEEEKIYqLYBLtNmzbRq1cvypUrh8FgYNGiRQ7vQynF5MmTqV69Oi4uLpQvX54JEybkf7FCCCGEEAXASe8C8ktCQgL169fnkUceoV+/fre0j+eee45Vq1YxefJk6tatS2RkJJGRkflcqRBCCCFEwTAopZTeReQ3g8HAwoUL6dOnj21dSkoKr7/+Or/88gvR0dHUqVOH999/n/bt2wNw5MgR6tWrx8GDB6lRo4Y+hQshhBBC3IZicyr2ZkaOHMm2bduYM2cOf//9NwMHDqRr164cP34cgN9//53KlSuzdOlSKlWqRGhoKI8++qj02AkhhBCiyCgRwS48PJwZM2Ywb9482rRpQ5UqVRgzZgx33XUXM2bMAODff//lzJkzzJs3jx9//JGZM2eye/duBgwYoHP1QgghhBB5U2zG2OXmwIEDWCwWqlevbrc+JSWFUqVKAWC1WklJSeHHH3+0tfvuu+9o3LgxR48eldOzQgghhCj0SkSwi4+Px2QysXv3bkwmk902T09PAMqWLYuTk5Nd+KtVqxag9fhJsBNCCCFEYVcigl3Dhg2xWCxcunSJNm3aZNumdevWpKenc/LkSapUqQLAsWPHAAgJCbljtQohhBBC3Kpic1VsfHw8J06cALQgN2XKFDp06IC/vz8VK1bkwQcfZOvWrXz00Uc0bNiQy5cvs3btWurVq0ePHj2wWq00bdoUT09Ppk6ditVq5ZlnnsHb25tVq1bp/O6EEEIIIW6u2AS7DRs20KFDhyzrhw0bxsyZM0lLS+Pdd9/lxx9/5Ny5cwQEBNCiRQvGjx9P3bp1ATh//jzPPvssq1atwsPDg27duvHRRx/h7+9/p9+OEEIIIYTDik2wE0IIIYQo6UrEdCdCCCGEECWBBDshhBBCiGKiSF8Va7VaOX/+PF5eXhgMBr3LEUIIIYTId0op4uLiKFeuHEZj7n1yRTrYnT9/nuDgYL3LEEIIIYQocGfPnqVChQq5tinSwc7LywvQ3qi3t7fO1QghhBBC5L/Y2FiCg4NtuSc3RTrYZZx+9fb2lmAnhBBCiGItL8PO5OIJIYQQQohiQoKdEEIIIUQxIcFOCCGEEKKYKNJj7PLKYrGQlpamdxlCiGLCbDbfdMoBIYTQQ7EOdkopLly4QHR0tN6lCCGKEaPRSKVKlTCbzXqXIoQQdop1sMsIdUFBQbi7u8skxkKI25YxMXpERAQVK1aUnytCiEKl2AY7i8ViC3WlSpXSuxwhRDESGBjI+fPnSU9Px9nZWe9yhBDCptgOEskYU+fu7q5zJUKI4ibjFKzFYtG5EiGEsFdsg10GOU0ihMhv8nNFCFFYFftgJ4QQQghRUkiwEw6bOXMmvr6+epchhBBCiBtIsBOFVmhoKFOnTtW7DCGEEKLIkGAnbFJTU/UuQQghhBC3QYJdIdS+fXtGjRrFyy+/jL+/P2XKlGHcuHF2baKjo3n00UcJDAzE29ubjh07sn//ftv2hx9+mD59+ti9ZvTo0bRv397uOCNHjmT06NEEBATQpUsXAKZMmULdunXx8PAgODiYp59+mvj4+DzXf/r0aQwGAwsWLKBDhw64u7tTv359tm3bZtduy5YttGnTBjc3N4KDgxk1ahQJCQm22s6cOcPzzz+PwWCQwepCCCEKnwsHIeGq3lXYKZHBLjE1PcdHcpolX9veqh9++AEPDw927NjBBx98wNtvv83q1att2wcOHMilS5dYsWIFu3fvplGjRnTq1InIyEiHj2M2m9m6dStff/01oM2q/+mnn3Lo0CF++OEH1q1bx8svv+zwe3j99dcZM2YM+/bto3r16gwePJj0dO0zOXnyJF27dqV///78/fffzJ07ly1btjBy5EgAFixYQIUKFXj77beJiIggIiLC4eMLIYQQBSYxEmbfB1/fBRcP6V2NTbGdoDg3td/6I8dtHWoEMmN4M9ty43fWkJSW/VxVzSv5M/eJlrblu95fT2SC/enM05N63FKN9erVY+zYsQBUq1aNzz//nLVr13L33XezZcsW/vrrLy5duoSLiwsAkydPZtGiRcyfP5/HH388z8epVq0aH3zwgd260aNH256Hhoby7rvv8uSTT/Lll1869B7GjBlDjx7a+x8/fjxhYWGcOHGCmjVrMnHiRIYMGWI7VrVq1fj0009p164dX331Ff7+/phMJry8vChTpoxDxxVCCCEKlFKw6CmI/Q/8K4NPsN4V2ZTIYFcU1KtXz265bNmyXLp0CYD9+/cTHx+f5Y4aSUlJnDx50qHjNG7cOMu6NWvWMHHiRP755x9iY2NJT08nOTmZxMREhyZ8zvweypYtC8ClS5eoWbMm+/fv5++//2bWrFm2NkoprFYrp06dolatWg69DyGEEOKO2fY5HFsJJhcYOBNcvfWuyKZEBrvDb3fJcZvxhrFcu9/snOe2W17pcHuFZXLjbYoMBgNWqxWA+Ph4ypYty4YNG7K8LmMaEqPRiFLKblvG3Tgy8/DwsFs+ffo0PXv25KmnnmLChAn4+/uzZcsWRowYQWpqqkPBLvN7yBgjl/k9PPHEE4waNSrL6ypWrJjnYwghhBB31Nm/YM047XnXiVC2vq7l3KhEBjt3c97fdkG1vR2NGjXiwoULODk5ERoamm2bwMBADh48aLdu3759N72v5e7du7FarXz00UcYjdoQzF9//TVf6s6sUaNGHD58mKpVq+bYxmw2yy2bhBBCFB6JkTBvOFjTIawfNHlE74qyKJEXTxR1nTt3pmXLlvTp04dVq1Zx+vRp/vzzT15//XV27doFQMeOHdm1axc//vgjx48fZ+zYsVmCXnaqVq1KWloan332Gf/++y8//fST7aKK/PTKK6/w559/MnLkSPbt28fx48dZvHix7eIJ0Mb3bdq0iXPnznHlypV8r0EIIYTIsxvH1fX6BArhjA0S7Iogg8HA8uXLadu2LcOHD6d69ercf//9nDlzhtKlSwPQpUsX3nzzTV5++WWaNm1KXFwcQ4cOvem+69evz5QpU3j//fepU6cOs2bNYuLEifn+HurVq8fGjRs5duwYbdq0oWHDhrz11luUK1fO1ubtt9/m9OnTVKlShcDAwHyvQQghhMizQjyuLjODunEg1h0UGhrKmTNnsqx/+umn+eKLL276+tjYWHx8fIiJicHb2/4DTk5O5tSpU1SqVAlXV9d8q1kIIeTnixAlzNm/YEY37RRsjynQdMQdPXxueedGuo6x27lzp90YqoMHD3L33XczcOBAHasSQgghhLimCIyry0zXYHfj6bVJkyZRpUoV2rVrp1NFQgghhBDXFJFxdZkVmjF2qamp/PzzzzzyyCNy+yghhBBC6K+IjKvLrNBMd7Jo0SKio6N5+OGHc2yTkpJCSkqKbTk2NvYOVCaEEEKIEqeQz1eXk0LTY/fdd9/RrVs3u6sibzRx4kR8fHxsj+DgwnMLDyGEEEIUE0VsXF1mhSLYnTlzhjVr1vDoo4/m2u61114jJibG9jh79uwdqlAIIYQQJUIRHFeXWaE4FTtjxgyCgoJsN4zPiYuLi+2m90IIIYQQ+a4IjqvLTPceO6vVyowZMxg2bBhOToUiZwohhBCiJCqi4+oy0z3YrVmzhvDwcB55pOicvxZCCCFEMVOEx9Vlpnuwu+eee1BKUb16db1LETdhMBhYtGhRgR5jw4YNGAwGoqOjb+n1bdu2Zfbs2bblzDWfPn0ag8HAvn37br9QoYsb/w1v9/slJ/fffz8fffRRvu5TCFGIFfFxdZnpHuxE0REREUG3bt0K9BitWrUiIiICHx8fAGbOnImvr2+eXrtkyRIuXrzI/fffn+324OBgIiIiqFOnTn6VK3R24/dLfnnjjTeYMGECMTEx+bpfIUQhVcTH1WUmwa6ESE1Nve19lClTJteLV9LS0m77GGazmTJlytzSJNWffvopw4cPx2jM/tvaZDJRpkwZ3cdyWiwWrFbrHTtefvzbF1a38/2Smzp16lClShV+/vnnfN2vEKIQKgbj6jKTYFfITJs2jXLlymX5xd+7d2/bOMSTJ0/Su3dvSpcujaenJ02bNmXNmjV27UNDQ3nnnXcYOnQo3t7ePP7443k6/vfff09YWBguLi6ULVuWkSNH2rZld1pz7ty5tGvXDldXV2bNmpXrPrI7FRodHY3BYGDDhg2A/am1DRs2MHz4cGJiYjAYDBgMBsaNG5dt3ZcvX2bdunX06tUrx/eW02m8tWvX0qRJE9zd3WnVqhVHjx61e93ixYtp1KgRrq6uVK5cmfHjx5Oenm7bPmXKFOrWrYuHhwfBwcE8/fTTxMfH27Zn9DouWbKE2rVr4+LiQnh4eJb6MupZtmwZ9erVw9XVlRYtWnDw4EFbm6tXrzJ48GDKly+Pu7s7devW5ZdffrHbT/v27Rk5ciSjR48mICCALl26OFTn0qVLqVGjBu7u7gwYMIDExER++OEHQkND8fPzY9SoUXb3eL7R/v376dChA15eXnh7e9O4cWN27dpl275161bat2+Pu7s7fn5+dOnShaioKABWrlzJXXfdha+vL6VKlaJnz56cPHkyx2PdeCo24z388ccf1KpVC09PT7p27UpERITtNenp6YwaNcp2jFdeeYVhw4bRp08fu3336tWLOXPm5HhsIUQxUEzG1WVWsoKdUpCacOcfSuW5xIEDB3L16lXWr19vWxcZGcnKlSsZMmQIAPHx8XTv3p21a9eyd+9eunbtSq9evbKEhcmTJ1O/fn327t3Lm2++edNjf/XVVzzzzDM8/vjjHDhwgCVLllC1atVcX/Pqq6/y3HPPceTIEbp06XJL+8hJq1atmDp1Kt7e3kRERBAREcGYMWOybbtlyxbc3d2pVauWw8d5/fXX+eijj9i1axdOTk52F/Js3ryZoUOH8txzz3H48GG++eYbZs6cyYQJE2xtjEYjn376KYcOHeKHH35g3bp1vPzyy3bHSExM5P333+fbb7/l0KFDBAUF5VjPSy+9xEcffcTOnTsJDAykV69ett7Q5ORkGjduzLJlyzh48CCPP/44Dz30EH/99ZfdPn744QfMZjNbt27l66+/dqjOTz/9lDlz5rBy5Uo2bNhA3759Wb58OcuXL+enn37im2++Yf78+TnWP2TIECpUqMDOnTvZvXs3r776Ks7OzgDs27ePTp06Ubt2bbZt28aWLVvo1auXLSgmJCTwwgsvsGvXLtauXYvRaKRv374O9XAmJiYyefJkfvrpJzZt2kR4eLjd983777/PrFmzmDFjBlu3biU2NjbbsaPNmjXjr7/+srvbjRCiGClG4+rsqCIsJiZGASomJibLtqSkJHX48GGVlJR0fWVKvFJjve/8IyXeoffVu3dv9cgjj9iWv/nmG1WuXDllsVhyfE1YWJj67LPPbMshISGqT58+Dh23XLly6vXXX89xO6AWLlyolFLq1KlTClBTp07N8z4yXrN3717buqioKAWo9evXK6WUWr9+vQJUVFSUUkqpGTNmKB8fn5vW/vHHH6vKlSvnqeaM42cca82aNbb2y5YtU4Dt+6ZTp07qvffes9vnTz/9pMqWLZtjLfPmzVOlSpWyLc+YMUMBat++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\n"
          },
          "metadata": {}
        }
      ],
      "source": [
        "\n",
        "variational_training1 = []\n",
        "variational_training2 = []\n",
        "kernelbased_training = []\n",
        "nn_training = []\n",
        "x_axis = range(0, 2000, 100)\n",
        "\n",
        "for M in x_axis:\n",
        "\n",
        "    var1 = circuit_evals_variational(\n",
        "        n_data=M, n_params=M, n_steps=M,  shift_terms=2, split=0.75, batch_size=1\n",
        "    )\n",
        "    variational_training1.append(var1)\n",
        "\n",
        "    var2 = circuit_evals_variational(\n",
        "        n_data=M, n_params=round(np.sqrt(M)), n_steps=M,\n",
        "        shift_terms=2, split=0.75, batch_size=1\n",
        "    )\n",
        "    variational_training2.append(var2)\n",
        "\n",
        "    kernel = circuit_evals_kernel(n_data=M, split=0.75)\n",
        "    kernelbased_training.append(kernel)\n",
        "\n",
        "    nn = model_evals_nn(\n",
        "        n_data=M, n_params=M, n_steps=M, split=0.75, batch_size=1\n",
        "    )\n",
        "    nn_training.append(nn)\n",
        "\n",
        "\n",
        "plt.plot(x_axis, nn_training, linestyle='--', label=\"neural net\")\n",
        "plt.plot(x_axis, variational_training1, label=\"var. circuit (linear param scaling)\")\n",
        "plt.plot(x_axis, variational_training2, label=\"var. circuit (srqt param scaling)\")\n",
        "plt.plot(x_axis, kernelbased_training, label=\"(quantum) kernel\")\n",
        "plt.xlabel(\"size of data set\")\n",
        "plt.ylabel(\"number of evaluations\")\n",
        "plt.legend()\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "q5iOsnGW3fHS"
      },
      "source": [
        "This is the plot we saw at the beginning. With current\n",
        "hardware-compatible training methods, whether kernel-based training\n",
        "requires more or fewer quantum circuit evaluations than variational\n",
        "training depends on how many parameters the latter needs. If variational\n",
        "circuits turn out to be as parameter-hungry as neural networks,\n",
        "kernel-based training will outperform them for common machine learning\n",
        "tasks. However, if variational learning only turns out to require few\n",
        "parameters (or if more efficient training methods are found),\n",
        "variational circuits could in principle match the linear scaling of\n",
        "neural networks trained with backpropagation.\n",
        "\n",
        "The practical take-away from this demo is that unless your variational\n",
        "circuit has significantly fewer parameters than training data, kernel\n",
        "methods could be a much faster alternative!\n",
        "\n",
        "Finally, it is important to note that fault-tolerant quantum computers\n",
        "may change the picture for both quantum and classical machine learning.\n",
        "As mentioned in [Schuld (2021)](https://arxiv.org/abs/2101.11020), early\n",
        "results from the quantum machine learning literature show that larger\n",
        "quantum computers will most likely enable us to reduce the quadratic\n",
        "scaling of kernel methods to linear scaling, which may make classical as\n",
        "well as quantum kernel methods a strong alternative to neural networks\n",
        "for big data processing one day.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "obtp3eCY3fHS"
      },
      "source": [
        "About the author\n",
        "================\n"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "seconds = time.time()\n",
        "print(\"Time in seconds since end of run:\", seconds)\n",
        "local_time = time.ctime(seconds)\n",
        "print(local_time)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 0
        },
        "id": "SOIzdbnn30P-",
        "outputId": "7801e44c-5af3-41c9-cdbc-39ca983dd41f"
      },
      "execution_count": 617,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Time in seconds since end of run: 1699857334.2728398\n",
            "Mon Nov 13 06:35:34 2023\n"
          ]
        }
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.18"
    },
    "colab": {
      "provenance": [],
      "machine_shape": "hm",
      "gpuType": "A100"
    },
    "accelerator": "GPU"
  },
  "nbformat": 4,
  "nbformat_minor": 0
}