From c7291d0e52b6ff8e0451675b7aebf14c47996645 Mon Sep 17 00:00:00 2001 From: "A.C.E07" Date: Fri, 14 Mar 2025 18:35:52 +0800 Subject: [PATCH 1/4] Added `quick.circuit.Ansatz` --- notebooks/Training Ansatzes.ipynb | 363 ++++++++++++++++++++++++++ quick/circuit/__init__.py | 2 + quick/circuit/ansatz.py | 255 ++++++++++++++++++ quick/circuit/circuit_utils.py | 84 +++++- stubs/quick/circuit/ansatz.pyi | 36 +++ stubs/quick/circuit/circuit_utils.pyi | 9 +- tests/circuit/test_ansatz.py | 256 ++++++++++++++++++ 7 files changed, 1002 insertions(+), 3 deletions(-) create mode 100644 notebooks/Training Ansatzes.ipynb create mode 100644 quick/circuit/ansatz.py create mode 100644 stubs/quick/circuit/ansatz.pyi create mode 100644 tests/circuit/test_ansatz.py diff --git a/notebooks/Training Ansatzes.ipynb b/notebooks/Training Ansatzes.ipynb new file mode 100644 index 0000000..cbead33 --- /dev/null +++ b/notebooks/Training Ansatzes.ipynb @@ -0,0 +1,363 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import `quick` modules. For this demo, we will import the circuit instances." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from quick.circuit import QiskitCircuit, Ansatz\n", + "from quick.circuit.circuit_utils import flatten, reshape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also import some basic modules for angle calculations." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variational Quantum Computing\n", + "\n", + "Quantum Circuits with single qubit rotation gates are known as Parameterized Quantum Circuits (PQC). If we variationally update the rotation angles of a PQC to minimize a cost function, we call the PQC an Ansatze for clarity in notation.\n", + "\n", + "In `quick.circuit`, we provide the Ansatze as a separate class for brevity and easier readability. You can use `quick.circuit.Ansatz` to \"convert\" ordinary `quick.circuit.Circuit` instances to ansatzes. This is done by simply using the `.update()` where we just change the rotation angle values and update to re-construct the updated circuit. Use-cases of variational quantum circuits include:\n", + "- Supervised QML\n", + "- Approximate Quantum Compilation (AQC)\n", + "- Quantum Approximate Optimization Algorithm (QAOA)\n", + "- Variational Quantum Eigensolver (VQE)\n", + "\n", + "For this notebook, we will mainly focus on AQC." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will use `scipy.optimize.minimize` for optimizing the parameters. Scipy provides an elegant and minimalistic interface for accessing a variety of SOTA optimization algorithms without the hassle of manually setting each one up or passing a multitude of hyper-parameters. For our use-case in this notebook, scipy is an excellet fit. It should however be noted that if the use-case requires more sophisticated optimization techniques depending on the cost landscape, users are urged to implement their own optimization routines and/or use more advanced optimization libraries." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.optimize import minimize" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we will generate a random state to be encoded using Shende's synthesis as our initial parameter." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from quick.random import generate_random_state\n", + "\n", + "random_state = generate_random_state(6)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "circuit = QiskitCircuit(6)\n", + "circuit.initialize(random_state, range(6))\n", + "\n", + "ansatz = Ansatz(circuit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we will define our target state (the state which we want to prepare). The goal of our VQA is to variationally train the circuit such that the inner-product between the statevector represented by our ansatz and the target state is maximized, or in other words the infidelity is minimized.\n", + "\n", + "We can use any arbitrary statevector, but for visualization purposes let's use a MNIST image instance." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "# Load in the resized MNIST dataset\n", + "dataset = pd.read_csv('datasets/mnist-resized.csv')\n", + "\n", + "# Convert the dataset to a numpy array\n", + "images = dataset.to_numpy()[:,1:].reshape(30018, 8, 8)\n", + "\n", + "# Get the first image\n", + "test_image = images.reshape(30018, 8, 8)[0, :]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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tB555JH0V3bcqj777DNVV1dr7Nixqqur0/Lly7Vy5Uq98cYbXk9zZceOHbp48aKeeeYZzzb0+W9TRv8SjUZ1/PhxX7y3Lkn33XefmpubFY/H9dZbb6miokL19fW3dGRaWlq0atUq7dmzR4MGDfJ6TreVl5en/3dxcbGmTZumoqIi/eEPf9Czzz7r4bKupVIplZaWau3atZKkSZMm6fjx43rttddUUVHh8brue/3111VeXq6CggLPNvj+DubOO+9UVlaWLly40On5CxcuaOTIkR6t+nZYsWKF3n33XX3wwQfmX8HQW7Kzs3XPPfdo8uTJisViKikp0SuvvOL1rC41NTWptbVVDz74oILBoILBoOrr6/Xqq68qGAyqo6PD64ndcscdd+jee+/VqVOnvJ7Spfz8/Gv+D8f999/vi7f3vvHFF19o7969+tGPfuTpDt8HJjs7W5MnT9a+ffvSz6VSKe3bt8837637jeM4WrFihWpra/X+++9rzJgxXk/KWCqVUjKZ9HpGl2bNmqVjx46pubk5fZSWlmrJkiVqbm5WVlaW1xO75dKlS/r000+Vn5/v9ZQulZWVXfNj95988omKioo8WuReTU2N8vLyNG/ePE939Iu3yCorK1VRUaHS0lJNnTpV69evV3t7u5YuXer1tC5dunSp0/+bO336tJqbmzV06FCNGjXKw2Vdi0aj2rp1q3bu3KmcnJz0Z13hcFiDBw/2eN2NVVVVqby8XKNGjVJbW5u2bt2q/fv3q66uzutpXcrJybnm863bbrtNw4YNu6U/93rhhRc0f/58FRUV6dy5c1qzZo2ysrK0ePFir6d16fnnn9dDDz2ktWvX6qmnntLhw4e1adMmbdq0yetp3ZJKpVRTU6OKigoFgx7/J96Tn10z8Otf/9oZNWqUk52d7UydOtVpaGjwetJNffDBB46ka46Kigqvp3XpepslOTU1NV5P69KyZcucoqIiJzs72xk+fLgza9Ys57333vN6Vkb88GPKixYtcvLz853s7Gznu9/9rrNo0SLn1KlTXs/qlnfeeceZOHGiEwqFnHHjxjmbNm3yelK31dXVOZKcEydOeD3F4df1AwBM+P4zGADArYnAAABMEBgAgAkCAwAwQWAAACYIDADABIEBAJggMAAAEwQGAGCCwAAATBAYAIAJAgMAMPF/NSeMDcFGZn0AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Plot the first image\n", + "plt.imshow(test_image)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "target_state = test_image.flatten() / np.linalg.norm(test_image.flatten())" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.24593246121529486+0.14333213936238834j)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "target_state.conj().T @ ansatz.ansatz.get_statevector()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will then define the training routine and plot the improvements as we optimize. In case the scipy optimizer keeps going after the `max_iter` threshold, feel free to interrupt the cell." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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4xUUFODs2bPw8/Pj59KaWHpGc21au3atcHJyEnFxceLkyZNi/PjxwtPT02DWur3Jz88XR48eFUePHhUAxLx588TRo0fF33//LYQoWwru6ekptmzZIo4fPy4GDRpU5VLwrl27iv3794tff/1VtG7d2mApeE5OjvDx8REjRowQSUlJYu3atcLFxcXmloJPmjRJeHh4iN27dxssE7169apcZuLEiaJp06bip59+EocOHRKhoaEiNDRUfr18mWj//v1FYmKiiI+PF97e3lUuE33ttdfEqVOnxOLFi21ymeibb74p9uzZI1JSUsTx48fFm2++KSRJEj/++KMQgufSFBVXSwnBc1kTr7zyiti9e7dISUkRe/fuFWFhYcLLy0tkZmYKIXgurYVdhRshhPjkk09E06ZNhUajET169BC///67pZtkUbt27RIAKj1GjRolhChbDv7uu+8KHx8f4eTkJPr27SuSk5MN6rh8+bIYNmyYcHNzE+7u7iIqKkrk5+cblDl27Ji4//77hZOTk2jcuLGYM2dObb3FWlPVeQQgYmNj5TLXrl0T//rXv0T9+vWFi4uLePLJJ0VaWppBPefPnxcDBgwQzs7OwsvLS7zyyivi+vXrBmV27dolgoKChEajES1atDA4hq14/vnnRbNmzYRGoxHe3t6ib9++crARgufSFLeGG57L6ouMjBR+fn5Co9GIxo0bi8jISHHmzBn5dZ5L6yAJIYRl+oyIiIiIlGc3c26IiIjIPjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RkdwICArBgwQJLN4OIzIThhojMavTo0YiIiAAA9OnTB1OnTq21Y8fFxcHT07PS9oMHD2L8+PG11g4iql0Olm4AEVFNlZSUQKPRGL2/t7e3gq0hImvDnhsiqhWjR4/Gnj17sHDhQkiSBEmScP78eQBAUlISBgwYADc3N/j4+GDEiBHIysqS9+3Tpw+mTJmCqVOnwsvLC+Hh4QCAefPmoVOnTnB1dYW/vz/+9a9/oaCgAACwe/duREVFITc3Vz7ezJkzAVQelkpNTcWgQYPg5uYGd3d3DB06FBkZGfLrM2fORFBQEFauXImAgAB4eHjgmWeeQX5+vnlPGhEZheGGiGrFwoULERoainHjxiEtLQ1paWnw9/dHTk4OHn74YXTt2hWHDh1CfHw8MjIyMHToUIP9V6xYAY1Gg71792LZsmUAAJVKhY8//hh//PEHVqxYgZ9++gmvv/46AKBnz55YsGAB3N3d5eO9+uqrldql1+sxaNAgZGdnY8+ePdixYwfOnTuHyMhIg3Jnz57F5s2bsW3bNmzbtg179uzBnDlzzHS2iMgUHJYiolrh4eEBjUYDFxcX+Pr6ytsXLVqErl274v3335e3LV++HP7+/jh9+jTatGkDAGjdujU++OADgzorzt8JCAjA//3f/2HixIlYsmQJNBoNPDw8IEmSwfFulZCQgBMnTiAlJQX+/v4AgK+++godOnTAwYMHce+99wIoC0FxcXGoV68eAGDEiBFISEjAv//9b9NODBEpjj03RGRRx44dw65du+Dm5iY/2rVrB6Cst6RccHBwpX137tyJvn37onHjxqhXrx5GjBiBy5cv4+rVq9U+/qlTp+Dv7y8HGwAIDAyEp6cnTp06JW8LCAiQgw0A+Pn5ITMzs0bvlYhqB3tuiMiiCgoKMHDgQMydO7fSa35+fvLPrq6uBq+dP38ejz/+OCZNmoR///vfaNCgAX799VeMGTMGJSUlcHFxUbSdjo6OBs8lSYJer1f0GESkDIYbIqo1Go0GOp3OYFu3bt2wceNGBAQEwMGh+r+SDh8+DL1ej48++ggqVVkn9Pr16+96vFu1b98eFy5cwIULF+Tem5MnTyInJweBgYHVbg8RWQ8OSxFRrQkICMD+/ftx/vx5ZGVlQa/XY/LkycjOzsawYcNw8OBBnD17Fj/88AOioqLuGExatWqF69ev45NPPsG5c+ewcuVKeaJxxeMVFBQgISEBWVlZVQ5XhYWFoVOnThg+fDiOHDmCAwcOYOTIkejduze6d++u+DkgIvNjuCGiWvPqq69CrVYjMDAQ3t7eSE1NRaNGjbB3717odDr0798fnTp1wtSpU+Hp6Sn3yFSlS5cumDdvHubOnYuOHTti1apViImJMSjTs2dPTJw4EZGRkfD29q40IRkoG17asmUL6tevjwcffBBhYWFo0aIF1q1bp/j7J6LaIQkhhKUbQURERKQU9twQERGRTWG4ISIiIpvCcENEREQ2heGGiIiIbArDDREREdkUhhsiIiKyKQw3REREZFMYboiIiMimMNwQERGRTWG4ISIiIpvCcENEREQ2heGGiIiIbMr/A1dtVLlToV3aAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "from IPython.display import display, clear_output\n", + "\n", + "infidelities = []\n", + "\n", + "def cost_function(thetas, shape) -> complex:\n", + " ansatz.thetas = reshape(thetas, shape)\n", + "\n", + " infidelity = 1 - target_state.conj().T @ ansatz.ansatz.get_statevector()\n", + "\n", + " infidelities.append(infidelity)\n", + " update_plot(infidelities)\n", + "\n", + " return infidelity\n", + "\n", + "# Create a figure and axis for dynamic plotting\n", + "fig, ax = plt.subplots()\n", + "line, = ax.plot([], [], 'r-', label='Infidelity')\n", + "smooth_line, = ax.plot([], [], 'b-', label='Smoothed Infidelity')\n", + "ax.set_xlim(0, 1)\n", + "ax.set_ylim(0, 1)\n", + "ax.set_title('Infidelities Over Time')\n", + "ax.set_xlabel('Iteration')\n", + "ax.set_ylabel('Infidelity')\n", + "ax.legend()\n", + "\n", + "# Function to update the plot\n", + "def update_plot(new_data):\n", + " line.set_xdata(range(len(new_data)))\n", + " line.set_ydata(new_data)\n", + "\n", + " # Calculate the moving average\n", + " window_size = 5\n", + " if len(new_data) >= window_size:\n", + " smoothed_data = np.convolve(new_data, np.ones(window_size)/window_size, mode='valid')\n", + " smooth_line.set_xdata(range(window_size-1, len(new_data)))\n", + " smooth_line.set_ydata(smoothed_data)\n", + "\n", + " ax.set_xlim(0, len(new_data))\n", + " ax.set_ylim(0, max(new_data) + 0.1)\n", + " clear_output(wait=True)\n", + " display(fig)\n", + " plt.pause(0.1)\n", + "\n", + "# Initial parameters for the ansatz\n", + "initial_params, shape = flatten(ansatz.thetas)\n", + "\n", + "# Define bounds for each parameter to be between 0 and 2*pi\n", + "bounds = [(0, 2*np.pi) for _ in initial_params]\n", + "\n", + "# Perform the optimization\n", + "result = minimize(cost_function, initial_params, args=(shape), method=\"BFGS\", options={'maxiter': 2000})\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's the fidelity." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.9184301235740799-0.11993565640369458j)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.inner(target_state.conj().T, ansatz.ansatz.get_statevector())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whilst the inner-product is a fundamental measure of similarity, let us use our own eyes to assess the quality of the approximation." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxoAAAGKCAYAAACLuTc4AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFO9JREFUeJzt3X2QVwW9x/HvbxcURNi9wK4WKiM+i5gN2CVIcHyARukK5TUNFCWJIdNpJjNnyoDJFMZLY1Nopg0+hCPyYJp2KRtxLAWRLOdOTTcwddQ0cHkQBRHYc/9w2OtK2h77rgfk9Zphxj2c3f3sb3AP7z27P2pFURQBAACQqK7qAQAAwIeP0AAAANIJDQAAIJ3QAAAA0gkNAAAgndAAAADSCQ0AACCd0AAAANIJDQAAIJ3QAAAA0gkNdlGr1Tr06+GHH/6X39fmzZtj+vTpHX5bDz/8cNRqtVi4cOG//L53Z/Pnz48JEybEEUccEbVaLU4++eSqJwFUyrWpWi0tLXHdddfFiBEjoqmpKRobG2Po0KExf/78qqexG+tS9QB2P3fccUe7l2+//fZ48MEHdzl+zDHH/Mvva/PmzTFjxoyICH+Zfpsbb7wxfve738WJJ54YLS0tVc8BqJxrU7WWLVsW3/zmN+OMM86Ib33rW9GlS5dYtGhRnHvuufGnP/2p7fGCtxMa7GLChAntXl6+fHk8+OCDuxyn89xxxx3Rr1+/qKuri+OOO67qOQCVc22q1sCBA2PVqlXRv3//tmNf/vKX47TTTotZs2bFFVdcET169KhwIbsj3zrF+9La2hrXX399DBw4MLp16xYHHHBATJkyJdavX9/uvJUrV8bo0aOjb9++0b179zj00ENj0qRJERHx7LPPRlNTU0REzJgxo+229/Tp00ttmT59etRqtfjLX/4SEyZMiIaGhmhqaoqrrroqiqKI559/Ps4666zo1atXHHjggTF79ux2r//mm2/Gt7/97Rg8eHA0NDREjx494qSTToqlS5fu8r5aWlri/PPPj169ekVjY2NMnDgxnnrqqajVanHrrbe2O/fPf/5znH322dG7d+/o1q1bDBkyJO67774OfUwHH3xw1NX53xOgDNemzrs2HXrooe0iI+Ktb2cbO3ZsbN26Nf7617+WenzYO7ijwfsyZcqUuPXWW+Oiiy6Kyy67LJ555pn44Q9/GL///e/j0Ucfja5du8aaNWti1KhR0dTUFFdeeWU0NjbGs88+G4sXL46IiKamprjxxhtj6tSpMW7cuPjsZz8bERHHH3/8+9r0+c9/Po455piYOXNmPPDAA3H11VdH796946abbopTTjklZs2aFfPmzYvLL788TjzxxBgxYkRERLz66qtxyy23xHnnnReTJ0+OTZs2xU9+8pMYPXp0rFixIk444YSIeOsC9pnPfCZWrFgRU6dOjaOPPjruvffemDhx4i5b/vjHP8bw4cOjX79+ceWVV0aPHj3i7rvvjrFjx8aiRYti3Lhx7+tjBODduTZ98Neml19+OSIi+vbt+74eHz7kCvgnLrnkkuLtf1R+85vfFBFRzJs3r915S5YsaXf8nnvuKSKieOKJJ971ba9du7aIiGLatGkd2rJ06dIiIooFCxa0HZs2bVoREcWXvvSltmPbt28vDjrooKJWqxUzZ85sO75+/fqie/fuxcSJE9udu3Xr1nbvZ/369cUBBxxQTJo0qe3YokWLiogorr/++rZjO3bsKE455ZQiIoq5c+e2HT/11FOLQYMGFW+88UbbsdbW1mLYsGHFEUcc0aGPdaeBAwcWI0eOLPU6AB92rk1vqeraVBRF0dLSUjQ3NxcnnXRS6ddl7+B7MyhtwYIF0dDQEKeffnq88sorbb8GDx4c+++/f9tt3cbGxoiIuP/++2Pbtm2dvuviiy9u++/6+voYMmRIFEURX/ziF9uONzY2xlFHHdXuFm99fX3ss88+EfHWV4bWrVsX27dvjyFDhsSTTz7Zdt6SJUuia9euMXny5LZjdXV1cckll7TbsW7dunjooYfinHPOiU2bNrU9Pi0tLTF69OhYtWpVvPjii+kfP8DezLXpg702tba2xvjx42PDhg3xgx/8oOMPCHsVoUFpq1atio0bN0Zzc3M0NTW1+/Xaa6/FmjVrIiJi5MiR8bnPfS5mzJgRffv2jbPOOivmzp0bW7du7ZRdhxxySLuXGxoaolu3brvczm1oaNjl+3Vvu+22OP7446Nbt27Rp0+faGpqigceeCA2btzYds5zzz0XH/nIR2K//fZr97qHH354u5dXr14dRVHEVVddtcvjM23atIiItscIgByuTR/stenSSy+NJUuWxC233BIf+9jHOvx67F38jAaltba2RnNzc8ybN+8f/v7OH6Lb+Zziy5cvj5///Ofxy1/+MiZNmhSzZ8+O5cuXx/7775+6q76+vkPHIiKKomj775/+9Kdx4YUXxtixY+PrX/96NDc3R319fVx77bXx9NNPl97R2toaERGXX355jB49+h+e884LAAD/Gtem95Z5bZoxY0bccMMNMXPmzDj//PNLb2HvITQo7bDDDotf//rXMXz48Ojevfs/PX/o0KExdOjQ+O53vxt33nlnjB8/Pu666664+OKLo1arfQCL39vChQtjwIABsXjx4nZ7dn6FZ6f+/fvH0qVLY/Pmze2+crR69ep25w0YMCAiIrp27RqnnXZaJy4HYCfXpg/m2jRnzpyYPn16fPWrX41vfOMb7/vtsHfwrVOUds4558SOHTviO9/5zi6/t3379tiwYUNERKxfv77dV2ciou1ZMnbeot75SXHn61Rh51eW3r718ccfj2XLlrU7b/To0bFt27a4+eab2461trbGnDlz2p3X3NwcJ598ctx0003x0ksv7fL+1q5dmzkfgHBt+iCuTfPnz4/LLrssxo8fH9/73vdKfTzsndzRoLSRI0fGlClT4tprr40//OEPMWrUqOjatWusWrUqFixYEN///vfj7LPPjttuuy1uuOGGGDduXBx22GGxadOmuPnmm6NXr15xxhlnRERE9+7d49hjj4358+fHkUceGb17947jjjvuA/1H6saMGROLFy+OcePGxZlnnhnPPPNM/OhHP4pjjz02Xnvttbbzxo4dG5/4xCfia1/7WqxevTqOPvrouO+++2LdunUREe2+4jRnzpz41Kc+FYMGDYrJkyfHgAED4u9//3ssW7YsXnjhhXjqqafec9MjjzwSjzzySES89cn/9ddfj6uvvjoiIkaMGNH29IcAvMW1qXOvTStWrIgLLrgg+vTpE6eeeuou36I2bNiwtrsm0Kaqp7tiz/HOpxDc6cc//nExePDgonv37kXPnj2LQYMGFVdccUXxt7/9rSiKonjyySeL8847rzjkkEOKfffdt2hubi7GjBlTrFy5st3beeyxx4rBgwcX++yzzz99OsH3egrBtWvXtjt34sSJRY8ePXZ5GyNHjiwGDhzY9nJra2txzTXXFP379y/23Xff4uMf/3hx//33FxMnTiz69+/f7nXXrl1bfOELXyh69uxZNDQ0FBdeeGHx6KOPFhFR3HXXXe3Offrpp4sLLrigOPDAA4uuXbsW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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create a figure with two subplots\n", + "fig, axes = plt.subplots(1, 2, figsize=(10, 5))\n", + "\n", + "# Plot the first image\n", + "axes[0].imshow(abs(ansatz.ansatz.get_statevector()).reshape(8, 8))\n", + "axes[0].set_title('Test Image 1')\n", + "axes[0].axis('off')\n", + "\n", + "# Plot the second image\n", + "axes[1].imshow(test_image)\n", + "axes[1].set_title('Test Image 2')\n", + "axes[1].axis('off')\n", + "\n", + "# Display the plot\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For AQC, we often would use a much smaller ansatz so as to justify the training cost. However, for ease in demonstration and better fidelity we used an exact circuit and simply updated the parameters to what Shende's synthesis would have gotten to." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

© 2025 Qualition Computing, all rights reserved.

" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/quick/circuit/__init__.py b/quick/circuit/__init__.py index 094488f..1226eab 100644 --- a/quick/circuit/__init__.py +++ b/quick/circuit/__init__.py @@ -16,6 +16,7 @@ "dag", "gate_matrix", "from_framework", + "Ansatz", "Circuit", "CirqCircuit", "PennylaneCircuit", @@ -32,5 +33,6 @@ from quick.circuit.pennylanecircuit import PennylaneCircuit from quick.circuit.quimbcircuit import QuimbCircuit from quick.circuit.tketcircuit import TKETCircuit +from quick.circuit.ansatz import Ansatz import quick.circuit.from_framework as from_framework import quick.circuit.dag as dag \ No newline at end of file diff --git a/quick/circuit/ansatz.py b/quick/circuit/ansatz.py new file mode 100644 index 0000000..bb5e00f --- /dev/null +++ b/quick/circuit/ansatz.py @@ -0,0 +1,255 @@ +# Copyright 2023-2025 Qualition Computing LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://github.com/Qualition/quick/blob/main/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" Ansatz for variational quantum circuits. +""" + +from __future__ import annotations + +__all__ = ["Ansatz"] + +from quick.circuit import Circuit + +# Type hint for nested lists of floats +Params = list[list[float] | float] | list[float] + + +class Ansatz: + """ `quick.circuit.Ansatz` class for parameterized quantum circuits + which can be used as variational ansatz for quantum machine learning + models. + + Notes + ----- + The `Ansatz` class is a wrapper around the `quick.circuit.Circuit` class + which provides a more user-friendly interface for parameterized quantum + circuits, and means for variationally updating them. + + Use-cases of variational quantum circuits include: + - Supervised QML + - Approximate Quantum Compilation (AQC) + - Quantum Approximate Optimization Algorithm (QAOA) + - Variational Quantum Eigensolver (VQE) + + This class is meant to provide a simple interface for specifically updating + the rotation angles of a parameterized quantum circuit. Users can use the class + in the following manner: + + ```python + from quick.circuit import Ansatz, QiskitCircuit + from quick.circuit.circuit_utils import reshape, flatten + from quick.random import generate_random_state + from scipy.optimize import minimize + + # Create a parameterized quantum circuit with + # random state initialization + circuit = QiskitCircuit(2) + circuit.initialize(generate_random_state(2), [0, 1]) + + # Define a target state + target_state = generate_random_state(2) + + # Create an ansatz object + ansatz = Ansatz(circuit) + + # Define the cost function + def cost_function(thetas, shape): + ansatz.thetas = reshape(thetas, shape) + return 1 - target_state.conj().T @ ansatz.ansatz.state + + initial_thetas, shape = flatten(ansatz.thetas) + + # Optimize the ansatz circuit + result = minimize(cost_function, initial_thetas, args=(shape), method="BFGS") + ``` + + This example demonstrates how one can use the Ansatz class to perform approximate + state preparation by variationally updating the circuit where the cost function is + simply the fidelity between the target state and the state prepared by the ansatz. + + For simplicity, we do not bother with defining specific optimization interfaces so + users can use whatever means of optimization they prefer as long as they update the + parameters of the ansatz circuit per iteration. Our recommendation is to use the + `scipy.optimize.minimize` function which provides a minimalistic and elegant interface + to access a variety of optimization algorithms. It should however be noted that if + the use-case requires more sophisticated optimization techniques depending on the + cost landscape, users are urged to implement their own optimization routines and/or + use more advanced optimization libraries. + + Lastly, `flatten` and `reshape` functions are used to convert the parameters of the + ansatz circuit to a 1D array and vice versa. This is necessary because the optimization + routine expects a 1D array of parameters to optimize over, while the ansatz circuit + requires the original shape to update its definition. Feel free to use these functions + or implement your own as needed. + + You may also make a PR to exclude the need for `flatten` and `reshape` by providing a + more elegant way of handling the parameter updates. + + Parameters + ---------- + `ansatz` : quick.circuit.Circuit + The parameterized quantum circuit to be used as the ansatz. + `ignore_global_phase` : bool, optional, default=True + Whether to ignore the global phase when setting the parameters + of the ansatz. + + Attributes + ---------- + `ansatz` : quick.circuit.Circuit + The parameterized quantum circuit to be used as the ansatz. + `thetas` : numpy.ndarray + The parameters of the ansatz circuit. + `num_params` : int + The number of parameters in the ansatz circuit. + `num_parameterized_gates` : int + The number of parameterized gates in the ansatz circuit. + + Raises + ------ + TypeError + - If the `ansatz` is not an instance of the `quick.circuit.Circuit`. + + Usage + ----- + >>> from quick.circuit import QiskitCircuit + >>> circuit = QiskitCircuit(2) + >>> circuit.H(0) + >>> circuit.CX(0, 1) + >>> ansatz = Ansatz(circuit) + """ + def __init__( + self, + ansatz: Circuit, + ignore_global_phase: bool = True + ) -> None: + """ Initialize a `quick.circuit.Ansatz` instance. + """ + if not isinstance(ansatz, Circuit): + raise TypeError( + "The `ansatz` must be an instance of the `quick.circuit.Circuit`. " + f"Received {type(ansatz)} instead." + ) + + self.ansatz = ansatz + self.ignore_global_phase = ignore_global_phase + + if not self.is_parameterized: + raise ValueError("The `ansatz` must contain parameterized gates.") + + @property + def thetas(self) -> Params: + """ The parameters of the ansatz circuit. + + Returns + ------- + Params + The parameters of the ansatz circuit. + + Usage + ----- + >>> ansatz.thetas + """ + thetas: Params = [] + + for gate in self.ansatz.circuit_log: + if "angles" in gate: + thetas.append(gate["angles"]) + elif "angle" in gate: + if gate["gate"] == "GlobalPhase" and self.ignore_global_phase: + continue + thetas.append(gate["angle"]) + + return thetas + + @thetas.setter + def thetas( + self, + thetas: Params + ) -> None: + """ Set the parameters of the ansatz circuit. + + Parameters + ---------- + `thetas` : Params + The parameters to set for the ansatz circuit. + + Usage + ----- + >>> # Set the parameters of the ansatz circuit + ... # with one U3 gate + >>> ansatz.thetas = np.array([0.1, 0.2, 0.3]) + """ + for gate in self.ansatz.circuit_log: + if "angles" in gate: + gate["angles"] = thetas.pop(0) + elif "angle" in gate: + if gate["gate"] == "GlobalPhase" and self.ignore_global_phase: + continue + gate["angle"] = thetas.pop(0) + + self.ansatz.update() + + @property + def num_params(self) -> int: + """ The number of parameters in the ansatz circuit. + + Returns + ------- + int + The number of parameters in the ansatz circuit. + + Usage + ----- + >>> ansatz.num_params + """ + flattened_thetas: list[float] = [] + + for theta in self.thetas: + if isinstance(theta, list): + flattened_thetas.extend(theta) + else: + flattened_thetas.append(theta) + + return len(flattened_thetas) + + @property + def num_parameterized_gates(self) -> int: + """ The number of parameterized gates in the ansatz circuit. + + Returns + ------- + int + The number of parameterized gates in the ansatz circuit. + + Usage + ----- + >>> ansatz.num_parameterized_gates + """ + return len(self.thetas) + + @property + def is_parameterized(self) -> bool: + """ Check if the ansatz circuit contains parameterized gates. + + Returns + ------- + bool + True if the ansatz circuit contains parameterized gates, + False otherwise. + + Usage + ----- + >>> ansatz.is_parameterized + """ + return len(self.thetas) > 0 \ No newline at end of file diff --git a/quick/circuit/circuit_utils.py b/quick/circuit/circuit_utils.py index 1c9595c..29695a0 100644 --- a/quick/circuit/circuit_utils.py +++ b/quick/circuit/circuit_utils.py @@ -25,7 +25,9 @@ "multiplexor_diagonal_matrix", "simplify", "repetition_search", - "repetition_verify" + "repetition_verify", + "flatten", + "reshape" ] import numpy as np @@ -44,6 +46,9 @@ SQRT2, -SQRT2 ) +# Type hint for nested lists of floats +Params = list[list[float] | float] | list[float] + def decompose_multiplexor_rotations( angles: NDArray[np.float64], @@ -517,4 +522,79 @@ def repetition_verify( mux_copy[next_base] = None base, next_base, i = base + 1, next_base + 1, i + 1 - return True, mux_copy \ No newline at end of file + return True, mux_copy + +def flatten(array: Params) -> tuple[list[float], Params]: + """ Flatten a Tree into a list of floats and + the original shape. + + Parameters + ---------- + `array` : Tree + The nested list of floats. + + Returns + ------- + `flattened` : list[float] + The flattened list of parameters. + `shape` : Tree + The shape of the original array. + """ + flattened: list[float] = [] + shape: Params = [] + consecutive_ints = 0 + + for item in array: + if isinstance(item, float): + flattened.append(item) + consecutive_ints += 1 + + # Explicit type check for pylance + elif isinstance(item, list): + flattened.extend(item) + if consecutive_ints: + shape.append(consecutive_ints) + consecutive_ints = 0 + shape.append([len(item)]) # type: ignore + + if consecutive_ints: + shape.append(consecutive_ints) + + return flattened, shape + +def reshape( + flattened: list[float], + shape: Params + ) -> Params: + """ Reshape a flattened list given a shape instruction. + + Parameters + ---------- + `flattened` : list[float] + The flat list of floats. + `shape` : Tree + The shape instruction. + + Returns + ------- + `reshaped` : Tree + The reshaped list of floats. + """ + reshaped: Params = [] + result_index = 0 + + for dim in shape: + if isinstance(dim, int): + subtree = reshaped + + elif isinstance(dim, list): + subtree = [] + reshaped.append(subtree) # type: ignore + dim = dim[0] + + for i in range(result_index, result_index + dim): # type: ignore + subtree.append(flattened[i]) + + result_index += dim # type: ignore + + return reshaped \ No newline at end of file diff --git a/stubs/quick/circuit/ansatz.pyi b/stubs/quick/circuit/ansatz.pyi new file mode 100644 index 0000000..044585f --- /dev/null +++ b/stubs/quick/circuit/ansatz.pyi @@ -0,0 +1,36 @@ +# Copyright 2023-2025 Qualition Computing LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://github.com/Qualition/quick/blob/main/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +from numpy.typing import NDArray +from quick.circuit import Circuit + +__all__ = ["Ansatz"] + +Params = list[list[float] | float] | list[float] + +class Ansatz: + ansatz: Circuit + ignore_global_phase: bool = True + def __init__(self, ansatz: Circuit, ignore_global_phase: bool = True) -> None: ... + @property + def thetas(self) -> Params: ... + @thetas.setter + def thetas(self, theta_values: Params) -> None: ... + @property + def num_params(self) -> int: ... + @property + def num_parameterized_gates(self) -> int: ... + @property + def is_parameterized(self) -> bool: ... diff --git a/stubs/quick/circuit/circuit_utils.pyi b/stubs/quick/circuit/circuit_utils.pyi index e2f018a..d7a1ba0 100644 --- a/stubs/quick/circuit/circuit_utils.pyi +++ b/stubs/quick/circuit/circuit_utils.pyi @@ -23,9 +23,14 @@ __all__ = [ "multiplexor_diagonal_matrix", "simplify", "repetition_search", - "repetition_verify" + "repetition_verify", + "flatten", + "reshape" ] +Params = list[list[float] | float] | list[float] + + def decompose_multiplexor_rotations( angles: NDArray[np.float64], start_index: int, @@ -55,3 +60,5 @@ def repetition_search( level: int ) -> tuple[set[int], list[NDArray[np.complex128]]]: ... def repetition_verify(base, d, mux, mux_copy) -> tuple[bool, list[NDArray[np.complex128]]]: ... +def flatten(array: Params) -> tuple[list[float], Params]: ... +def reshape(flattened: list[float], shape: Params) -> Params: ... diff --git a/tests/circuit/test_ansatz.py b/tests/circuit/test_ansatz.py new file mode 100644 index 0000000..0a4b46b --- /dev/null +++ b/tests/circuit/test_ansatz.py @@ -0,0 +1,256 @@ +# Copyright 2023-2025 Qualition Computing LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://github.com/Qualition/quick/blob/main/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +__all__ = ["TestAnsatz"] + +import pytest +from quick.circuit import Ansatz, Circuit +from typing import Type + +from tests.circuit import CIRCUIT_FRAMEWORKS + + +class TestAnsatz: + def test_init_type_error(self) -> None: + """ Test TypeError raised when invalid type is passed to Ansatz. + """ + with pytest.raises(TypeError): + Ansatz(2) # type: ignore + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_init_value_error( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test ValueError raised when the circuit used is not + parameterized. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(2) + + circuit.CX(0, 1) + + with pytest.raises(ValueError): + Ansatz(circuit) + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_thetas( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test thetas property of Ansatz. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + + ansatz = Ansatz(circuit) + + assert ansatz.thetas == [0.3] + + circuit = circuit_framework(2) + circuit.RY(0.3, 0) + circuit.RY(0.2, 1) + + ansatz = Ansatz(circuit) + + assert ansatz.thetas == [0.3, 0.2] + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_set_thetas( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test thetas setter of Ansatz. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + + ansatz = Ansatz(circuit) + + ansatz.thetas = [0.3] + + assert ansatz.thetas == [0.3] + assert circuit.circuit_log[0]["angle"] == 0.3 + + circuit = circuit_framework(2) + circuit.RY(0.3, 0) + circuit.RY(0.2, 1) + + ansatz = Ansatz(circuit) + + ansatz.thetas = [0.3, 0.2] + + assert ansatz.thetas == [0.3, 0.2] + assert circuit.circuit_log[0]["angle"] == 0.3 + assert circuit.circuit_log[1]["angle"] == 0.2 + + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + circuit.U3([0.1, 0.2, 0.3], 0) + circuit.RX(0.2, 0) + + ansatz = Ansatz(circuit) + + ansatz.thetas = [0.1, [0.2, 0.3, 0.4], 0.5] + + assert circuit.circuit_log[0]["angle"] == 0.1 + assert circuit.circuit_log[1]["angles"] == [0.2, 0.3, 0.4] + assert circuit.circuit_log[2]["angle"] == 0.5 + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_num_params( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test num_params property of Ansatz. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + + ansatz = Ansatz(circuit) + + assert ansatz.num_params == 1 + + circuit = circuit_framework(2) + circuit.RY(0.3, 0) + circuit.RY(0.2, 1) + + ansatz = Ansatz(circuit) + + assert ansatz.num_params == 2 + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_num_parameterized_gates( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test num_parameterized_gates property of Ansatz. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + + ansatz = Ansatz(circuit) + + assert ansatz.num_parameterized_gates == 1 + + circuit = circuit_framework(2) + circuit.RY(0.3, 0) + circuit.RY(0.2, 1) + + ansatz = Ansatz(circuit) + + assert ansatz.num_parameterized_gates == 2 + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_is_parameterized( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test is_parameterized property of Ansatz. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.RY(0.3, 0) + + ansatz = Ansatz(circuit) + + assert ansatz.is_parameterized + + circuit = circuit_framework(2) + circuit.RY(0.3, 0) + circuit.RY(0.2, 1) + + ansatz = Ansatz(circuit) + + assert ansatz.is_parameterized + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_is_parameterized_error( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test is_parameterized property of Ansatz when circuit is not + parameterized. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(2) + + circuit.CX(0, 1) + + with pytest.raises(ValueError): + Ansatz(circuit) + + @pytest.mark.parametrize("circuit_framework", CIRCUIT_FRAMEWORKS) + def test_is_parameterized_with_ignore_global_phase( + self, + circuit_framework: Type[Circuit] + ) -> None: + """ Test is_parameterized property of Ansatz with ignore_global_phase + set to True. + + Parameters + ---------- + `circuit_framework`: Type[quick.circuit.Circuit] + The circuit framework to use for testing. + """ + circuit = circuit_framework(1) + + circuit.GlobalPhase(0.3) + + ansatz = Ansatz(circuit, ignore_global_phase=False) + + assert ansatz.is_parameterized + + with pytest.raises(ValueError): + Ansatz(circuit, ignore_global_phase=True) \ No newline at end of file From 1c43c85e445fbb24a3e67dc4c18f36d84436fe16 Mon Sep 17 00:00:00 2001 From: "A.C.E07" Date: Fri, 14 Mar 2025 18:56:17 +0800 Subject: [PATCH 2/4] Update circuit_utils.py --- quick/circuit/circuit_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quick/circuit/circuit_utils.py b/quick/circuit/circuit_utils.py index 29695a0..32c84d7 100644 --- a/quick/circuit/circuit_utils.py +++ b/quick/circuit/circuit_utils.py @@ -524,6 +524,7 @@ def repetition_verify( return True, mux_copy +# pragma: no cover def flatten(array: Params) -> tuple[list[float], Params]: """ Flatten a Tree into a list of floats and the original shape. @@ -562,6 +563,7 @@ def flatten(array: Params) -> tuple[list[float], Params]: return flattened, shape +# pragma: no cover def reshape( flattened: list[float], shape: Params From 7ea0c02799e74bb31126e2c962d0d647de716190 Mon Sep 17 00:00:00 2001 From: "A.C.E07" Date: Fri, 14 Mar 2025 19:11:16 +0800 Subject: [PATCH 3/4] Update circuit_utils.py --- quick/circuit/circuit_utils.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/quick/circuit/circuit_utils.py b/quick/circuit/circuit_utils.py index 32c84d7..46070ce 100644 --- a/quick/circuit/circuit_utils.py +++ b/quick/circuit/circuit_utils.py @@ -524,8 +524,7 @@ def repetition_verify( return True, mux_copy -# pragma: no cover -def flatten(array: Params) -> tuple[list[float], Params]: +def flatten(array: Params) -> tuple[list[float], Params]: # pragma: no cover """ Flatten a Tree into a list of floats and the original shape. @@ -563,11 +562,11 @@ def flatten(array: Params) -> tuple[list[float], Params]: return flattened, shape -# pragma: no cover + def reshape( flattened: list[float], shape: Params - ) -> Params: + ) -> Params: # pragma: no cover """ Reshape a flattened list given a shape instruction. Parameters From b49a3f2d55a995338590459b256d467dd5d8f322 Mon Sep 17 00:00:00 2001 From: "A.C.E07" Date: Sat, 15 Mar 2025 20:53:16 +0800 Subject: [PATCH 4/4] Update Training Ansatzes.ipynb --- notebooks/Training Ansatzes.ipynb | 62 ++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/notebooks/Training Ansatzes.ipynb b/notebooks/Training Ansatzes.ipynb index cbead33..dd11cac 100644 --- a/notebooks/Training Ansatzes.ipynb +++ b/notebooks/Training Ansatzes.ipynb @@ -190,13 +190,41 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAU9hJREFUeJzt3XlcVFXjBvDnzsAwLAIaCKgo7oobiklopSVKViZZSmYu5P5qZbbaIpq/N7S3XMqtTTBf98wlM0pJrczcUUnDVAxfYxGRVQGZOb8/kCsjqDBzhxlmnu/nMx+ZO+eee+Y2MQ9nuVcSQggQERER2QiVpRtAREREpCSGGyIiIrIpDDdERERkUxhuiIiIyKYw3BAREZFNYbghIiIim8JwQ0RERDaF4YaIiIhsCsMNERER2RSGG6I6qKCgAGPHjoWvry8kScLUqVNx/vx5SJKEuLi4u+4/evRoBAQEGHXsPn36oE+fPvLzmhwXACRJwsyZM406Nhmq6bknshcMN0QWEBcXB0mScOjQIaP2f//99xEXF4dJkyZh5cqVGDFihMItNM327dutLsBcvnwZr732Gtq2bQutVosGDRogPDwc27Zts3TTDMycOROSJN31UTFgEpEhB0s3gIhq7qeffsJ9992H6OhoeZsQAteuXYOjo2OttqVZs2aVjrt9+3YsXry4yoBz7do1ODjU7q+e5ORk9O3bF5cuXUJUVBS6d++OnJwcrFq1CgMHDsSrr76K//znP7XaptsZPHgwWrVqJT8vKCjApEmT8OSTT2Lw4MHydh8fnyrPPREx3BDVSZmZmQgMDDTYJkkStFptrbelpset7TZev34dTz/9NK5cuYKff/4ZISEh8msvv/wyhg8fjg8//BDdu3dHZGRkrbWrtLQUer0eGo3GYHvnzp3RuXNn+XlWVhYmTZqEzp0747nnnqtUjyX+mxNZOw5LEVmJ0aNHw83NDRcvXkRERATc3Nzg7e2NV199FTqdDgCwe/duSJKElJQUfPfdd/IQxfnz5287/2Lz5s3o2LEjtFotOnbsiE2bNlV5fL1ejwULFqBDhw7QarXw8fHBhAkTcOXKlTu2+9bjjh49GosXLwYAg2GUclXNubl48SKef/55+Pj4wMnJCR06dMDy5csrHeuTTz5Bhw4d4OLigvr166N79+5YvXr1Hdu3ceNGJCUl4c033zQINgCgVqvx6aefwtPTU25TRkYGHBwcMGvWrEp1JScnQ5IkLFq0SN6Wk5ODqVOnwt/fH05OTmjVqhXmzp0LvV5f6Rx9+OGHWLBgAVq2bAknJyecPHnyjm2/m6r+m5d/jlJTU/H444/Dzc0NjRs3lv+bnDhxAg8//DBcXV3RrFmzKs9fdd4TkTVjzw2RFdHpdAgPD0dISAg+/PBD7Ny5Ex999BFatmyJSZMmoX379li5ciVefvllNGnSBK+88goAwNvbG5cuXapU348//oinnnoKgYGBiImJweXLlxEVFYUmTZpUKjthwgTExcUhKioKL774IlJSUrBo0SIcPXoUe/furfbQx4QJE/DPP/9gx44dWLly5V3LZ2Rk4L777oMkSZgyZQq8vb3x/fffY8yYMcjLy8PUqVMBAJ9//jlefPFFPP3003jppZdQVFSE48ePY//+/Xj22WdvW/+3334LABg5cmSVr3t4eGDQoEFYsWIFzpw5g1atWqF3795Yv369wbAfAKxbtw5qtRpDhgwBAFy9ehW9e/fGxYsXMWHCBDRt2hS//fYbpk+fjrS0NCxYsMBg/9jYWBQVFWH8+PFwcnJCgwYN7np+jKHT6TBgwAA8+OCD+OCDD7Bq1SpMmTIFrq6uePvttzF8+HAMHjwYy5Ytw8iRIxEaGormzZsb9Z6IrJIgoloXGxsrAIiDBw/K20aNGiUAiPfee8+gbNeuXUVwcLDBtmbNmonHHnvMYFtKSooAIGJjY+VtQUFBws/PT+Tk5MjbfvzxRwFANGvWTN72yy+/CABi1apVBnXGx8dX2t67d2/Ru3fvOx538uTJ4na/XgCI6Oho+fmYMWOEn5+fyMrKMij3zDPPCA8PD3H16lUhhBCDBg0SHTp0qLLOOwkKChIeHh53LDNv3jwBQGzdulUIIcSnn34qAIgTJ04YlAsMDBQPP/yw/Hz27NnC1dVVnD592qDcm2++KdRqtUhNTRVC3DxH7u7uIjMzs0btv3TpUqVzVq6qc1/+OXr//fflbVeuXBHOzs5CkiSxdu1aefuff/5Zqe7qvicia8ZhKSIrM3HiRIPnDzzwAM6dO1fjetLS0pCYmIhRo0bBw8ND3t6vX79K83U2bNgADw8P9OvXD1lZWfIjODgYbm5u2LVrl3Fv5i6EENi4cSMGDhwIIYTBscPDw5Gbm4sjR44AADw9PfG///0PBw8erNEx8vPzUa9evTuWKX89Ly8PQNmkXgcHB6xbt04uk5SUhJMnTxrMy9mwYQMeeOAB1K9f36DtYWFh0Ol0+Pnnnw2O89RTT8Hb27tG7TfW2LFj5Z89PT3Rtm1buLq6YujQofL2tm3bwtPT0+DzVdP3RGSNOCxFZEW0Wm2lL7/69evfdd5LVf7++28AQOvWrSu91rZtWzk0AMBff/2F3NxcNGzYsMq6MjMza3z86rh06RJycnLw2Wef4bPPPrvjsd944w3s3LkTPXr0QKtWrdC/f388++yz6NWr1x2PUa9ePWRlZd2xTH5+vlwWALy8vNC3b1+sX78es2fPBlA2JOXg4GCwYumvv/7C8ePHbxtYbj1v5UM/5lbV58jDwwNNmjQxmP9Uvr3i56um74nIGjHcEFkRtVptkePq9Xo0bNgQq1atqvJ1c/U2lE9Qfe655zBq1Kgqy5SvHGrfvj2Sk5Oxbds2xMfHY+PGjViyZAlmzJhR5eTfcu3bt0diYiJSU1PRtGnTKsscP34cAAx6tJ555hlERUUhMTERQUFBWL9+Pfr27QsvLy+D9vfr1w+vv/56lfW2adPG4Lmzs/Nt26mk232ObrddCCH/XNP3RGSNGG6IbFSzZs0AlP0lfqvk5GSD5y1btsTOnTvRq1cvRb6Ab+0duB1vb2/Uq1cPOp0OYWFhdy3v6uqKyMhIREZGoqSkBIMHD8a///1vTJ8+/bZLoh9//HGsWbMGX331Fd55551Kr+fl5WHLli1o166dwfVlIiIiMGHCBHlo6vTp05g+fbrBvi1btkRBQUG12l5X2OJ7IvvDOTdENsrPzw9BQUFYsWIFcnNz5e07duyotAR56NCh0Ol08hBMRaWlpcjJyanRsV1dXQHgrvup1Wo89dRT8nLtW1VcAXb58mWD1zQaDQIDAyGEwPXr1297jKeffhqBgYGYM2dOpStC6/V6TJo0CVeuXKm0MsrT0xPh4eFYv3491q5dC41Gg4iICIMyQ4cOxb59+/DDDz9UOm5OTg5KS0tv2y5rZYvviewPe26IbFhMTAwee+wx3H///Xj++eeRnZ0tXyumoKBALte7d29MmDABMTExSExMRP/+/eHo6Ii//voLGzZswMKFC/H0009X+7jBwcEAgBdffBHh4eFQq9V45plnqiw7Z84c7Nq1CyEhIRg3bhwCAwORnZ2NI0eOYOfOncjOzgYA9O/fH76+vujVqxd8fHxw6tQpLFq0CI899tgdJwxrNBp8/fXX6Nu3L+6//36DKxSvXr0aR44cwSuvvFJl+yIjI/Hcc89hyZIlCA8Ph6enp8Hrr732GrZu3YrHH38co0ePRnBwMAoLC3HixAl8/fXXOH/+vMEwVl1gi++J7A/DDZENe+SRR7Bhwwa88847mD59Olq2bInY2Fhs2bIFu3fvNii7bNkyBAcH49NPP8Vbb70FBwcHBAQE4LnnnrvrpN1bDR48GC+88ALWrl2L//73vxBC3Dbc+Pj44MCBA3jvvffwzTffYMmSJbjnnnvQoUMHzJ07Vy43YcIErFq1CvPmzUNBQQGaNGmCF198scqhplu1b98ex44dw5w5c7B161bExsbC2dkZ3bt3x9atWzFw4MAq93viiSfg7OyM/Pz8Kq9e7OLigj179uD999/Hhg0b8NVXX8Hd3R1t2rTBrFmzDFap1RW2+J7I/kii4kwyIiIiojqOc26IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFLu7zo1er8c///yDevXqVfsS8URERGRZQgjk5+ejUaNGUKnu3Ddjd+Hmn3/+gb+/v6WbQUREREa4cOECmjRpcscydhduyi/TfuHCBbi7u1u4NURERFQdeXl58Pf3v+PtVsrZXbgpH4pyd3dnuCEiIqpjqjOlhBOKiYiIyKYw3BAREZFNYbghIiIim2J3c26IiOo6vV6PkpISSzeDSHEajeauy7yrg+GGiKgOKSkpQUpKCvR6vaWbQqQ4lUqF5s2bQ6PRmFQPww0RUR0hhEBaWhrUajX8/f0V+QuXyFqUX2Q3LS0NTZs2NelCuww3RER1RGlpKa5evYpGjRrBxcXF0s0hUpy3tzf++ecflJaWwtHR0eh6GPuJiOoInU4HACZ32RNZq/LPdvln3VgMN0REdQzvi0e2SqnPNsMNERER2RSGGyIisirp6eno168fXF1d4enpCaDsL/rNmzffdp/z589DkiQkJiZW+zh9+vTB1KlT5ecBAQFYsGCBUW0m68IJxUREZFajR49GTk7OHcNJRfPnz0daWhoSExPh4eEBAEhLS0P9+vXN2Erg4MGDcHV1lZ9LkoRNmzYhIiLCrMcl5THcEBGRVTl79iyCg4PRunVreZuvr6/Zj+vt7W32Y1Dt4LAUERHVmj59+uDFF1/E66+/jgYNGsDX1xczZ86UXw8ICMDGjRvx1VdfQZIkjB49GkDlYakDBw6ga9eu0Gq16N69O44ePVrpWElJSRgwYADc3Nzg4+ODESNGICsr67ZtqzgsFRAQAAB48sknIUkSAgICcP78eahUKhw6dMhgvwULFqBZs2a8sKIVYbghIqqrhAAKCy3zEMLoZq9YsQKurq7Yv38/PvjgA7z33nvYsWMHgLKhoUceeQRDhw5FWloaFi5cWGn/goICPP744wgMDMThw4cxc+ZMvPrqqwZlcnJy8PDDD6Nr1644dOgQ4uPjkZGRgaFDh1arjQcPHgQAxMbGIi0tDQcPHkRAQADCwsIQGxtrUDY2NhajR4/mRRWtCIeliIjqqqtXATc3yxy7oACoMD+lJjp37ozo6GgAQOvWrbFo0SIkJCSgX79+8Pb2hpOTE5ydnW87FLV69Wro9Xp8+eWX0Gq16NChA/73v/9h0qRJcplFixaha9eueP/99+Vty5cvh7+/P06fPo02bdrcsY3lQ1Senp4G7Rg7diwmTpyIefPmwcnJCUeOHMGJEyewZcsWo84FmQdjJhER1arOnTsbPPfz80NmZma19z916hQ6d+4MrVYrbwsNDTUoc+zYMezatQtubm7yo127dgDK5vQYKyIiAmq1Gps2bQIAxMXF4aGHHpKHscg6sOeGiKiucnEp60Gx1LGNdOtl9SVJUny+SkFBAQYOHIi5c+dWes3Pz8/oejUaDUaOHInY2FgMHjwYq1evrnLojCyL4YaIqK6SJKOHhuqy9u3bY+XKlSgqKpJ7b37//XeDMt26dcPGjRsREBAABwfjvuocHR2rvA3A2LFj0bFjRyxZsgSlpaUYPHiwUfWT+XBYioiI6pRnn30WkiRh3LhxOHnyJLZv344PP/zQoMzkyZORnZ2NYcOG4eDBgzh79ix++OEHREVFVfu+RQEBAUhISEB6ejquXLkib2/fvj3uu+8+vPHGGxg2bBicnZ0VfX9kOoYbIiKqU9zc3PDtt9/ixIkT6Nq1K95+++1Kw0+NGjXC3r17odPp0L9/f3Tq1AlTp06Fp6dntVc1ffTRR9ixYwf8/f3RtWtXg9fGjBmDkpISPP/884q9L1KOJIQJ6/nqoLy8PHh4eCA3Nxfu7u6Wbg4RUbUVFRUhJSUFzZs3N5hMS7Vv9uzZ2LBhA44fP27pptiUO33Ga/L9zZ4bIiKiaiooKEBSUhIWLVqEF154wdLNodtguCEiIqqmKVOmIDg4GH369OGQlBXjaikiIqJqiouLQ1xcnKWbQXfBnhsiIiKyKQw3REREZFM4LKWA0ozLOBafBp1eUqxOnzYeaNariWL1ERER2QuGG1MVFmKUfwJWX6/enWZr4mDcH+g+qoPi9RIREdkyhhtTZWbiz+stAQANVVlwUV0zucq0Um8UQ4vTB3PRfZTJ1REREdkVhhsFCJQNR634zguPPGJ6ff3uOYyd2cGwr8srEhERKYMTik0lhBxuJIWm3EgQ5VUTEZEFSJKEzZs3K15vnz59MHXqVEXrFEJg/PjxaNCgASRJQmJiYrWOExAQgAULFlT7ODNnzkRQUJD8fPTo0YiIiDCqzebGcKMA/Y3TWM3bldxVeUZiuCEiW3Dp0iVMmjQJTZs2hZOTE3x9fREeHo69e/daummVvrAtLS4uDp6enjXaJz4+HnFxcdi2bRvS0tLQsWNHfPPNN5g9e7Z5GnnDwoULDa75Y47gZiwOS5nKHD030o2eGyi3+oqIyFKeeuoplJSUYMWKFWjRogUyMjKQkJCAy5cvW7ppNuHs2bPw8/NDz5495W0NGjQw+3E9PDzMfgxjsedGAWYbltKz64aI6racnBz88ssvmDt3Lh566CE0a9YMPXr0wPTp0/HEE0/I5SRJwqefforHH38cLi4uaN++Pfbt24czZ86gT58+cHV1Rc+ePXH27FmD+pcuXYqWLVtCo9Ggbdu2WLlypcHrqampGDRoENzc3ODu7o6hQ4ciIyMDQFkvyaxZs3Ds2DFIkgRJkgx6IrKysvDkk0/CxcUFrVu3xtatWw3qTkpKwoABA+Dm5gYfHx+MGDECWVlZ8uuFhYUYOXIk3Nzc4Ofnh48++qjG56+8Z2nlypUICAiAh4cHnnnmGeTn5wMoGxp64YUXkJqaCkmSEBAQAKByL0pmZiYGDhwIZ2dnNG/eHKtWrap0rJycHIwdOxbe3t5wd3fHww8/jGPHjt22bRWHpUaPHo09e/Zg4cKF8rlMSUlBq1at8OGHHxrsl5iYCEmScObMmRqfj+piuDGVWebc3KiaPTdEdAdCAIWFlnlUd9jczc0Nbm5u2Lx5M4qLi+9Ydvbs2Rg5ciQSExPRrl07PPvss5gwYQKmT5+OQ4cOQQiBKVOmyOU3bdqEl156Ca+88gqSkpIwYcIEREVFYdeuXQAAvV6PQYMGITs7G3v27MGOHTtw7tw5REZGAgAiIyPxyiuvoEOHDkhLS0NaWpr8GgDMmjULQ4cOxfHjx/Hoo49i+PDhyM7OBlAWBB5++GF07doVhw4dQnx8PDIyMjB06M3Lgrz22mvYs2cPtmzZgh9//BG7d+/GkSNHqnfiKjh79iw2b96Mbdu2Ydu2bdizZw/mzJkDoGxo6L333kOTJk2QlpaGgwcPVlnH6NGjceHCBezatQtff/01lixZgszMTIMyQ4YMQWZmJr7//nscPnwY3bp1Q9++feX3fCcLFy5EaGgoxo0bJ5/Lpk2b4vnnn0dsbKxB2djYWDz44INo1apVjc9FtQk7k5ubKwCI3NxcZSr86y/RHn8IQIhdu5Sp8lGv3wUgxPJxvylTIRHZhGvXromTJ0+Ka9euCSGEKCgQoixm1P6joKD67f76669F/fr1hVarFT179hTTp08Xx44dMygDQLzzzjvy83379gkA4ssvv5S3rVmzRmi1Wvl5z549xbhx4wzqGTJkiHj00UeFEEL8+OOPQq1Wi9TUVPn1P/74QwAQBw4cEEIIER0dLbp06VKpzbe2p6CgQAAQ33//vRBCiNmzZ4v+/fsb7HPhwgUBQCQnJ4v8/Hyh0WjE+vXr5dcvX74snJ2dxUsvvXTbcxUbGys8PDzk59HR0cLFxUXk5eXJ21577TUREhIiP58/f75o1qyZQT29e/eWj5OcnGzwnoUQ4tSpUwKAmD9/vhBCiF9++UW4u7uLoqIig3patmwpPv30U7ktFc/VqFGjxKBBg6o8ZrmLFy8KtVot9u/fL4QQoqSkRHh5eYm4uLgq3/+tn/GKavL9zZ4bBXC1FBHR7T311FP4559/sHXrVjzyyCPYvXs3unXrVukGlJ07d5Z/9vHxAQB06tTJYFtRURHy8vIAAKdOnUKvXr0M6ujVqxdOnTolv+7v7w9/f3/59cDAQHh6espl7qRie1xdXeHu7i73dhw7dgy7du2Se6bc3NzQrl07AGU9LWfPnkVJSQlCQkLkOho0aIC2bdve9bi3CggIQL169eTnfn5+lXpd7uTUqVNwcHBAcHCwvK1du3YGE5ePHTuGgoIC3HPPPQbvKSUlpdJQYE00atQIjz32GJYvXw4A+Pbbb1FcXIwhQ4YYXWd1cEKxqcw5LMVwQ0R34OICFBRY7tg1odVq0a9fP/Tr1w/vvvsuxo4di+joaIwePVou4+joKP8s3fiFWtU2vV5vfMNroOKxy49ffuyCggIMHDgQc+fOrbSfn5+fovNJ7tQOpRQUFMDPzw+7d++u9FpNV2/dauzYsRgxYgTmz5+P2NhYREZGwqWmH6AaYrhRgOJLwblaioiqQZIAV1dLt8I4gYGBJl9Hpn379ti7dy9Gjbp5Kfe9e/ciMDBQfv3ChQu4cOGC3Htz8uRJ5OTkyGU0Gg10Ol2Nj92tWzds3LgRAQEBcHCo/FXasmVLODo6Yv/+/WjatCkA4MqVKzh9+jR69+5d4+OZol27digtLcXhw4dx7733AgCSk5ORk5Mjl+nWrRvS09Ph4OAgT0quqdudy0cffRSurq5YunQp4uPj8fPPPxtVf01wWMpU5uy54WopIqrjLl++jIcffhj//e9/cfz4caSkpGDDhg344IMPMGjQIJPqfu211xAXF4elS5fir7/+wrx58/DNN9/g1VdfBQCEhYWhU6dOGD58OI4cOYIDBw5g5MiR6N27N7p37w6gbMgnJSUFiYmJyMrKuuuk53KTJ09GdnY2hg0bhoMHD+Ls2bP44YcfEBUVBZ1OBzc3N4wZMwavvfYafvrpJyQlJWH06NFQKfVXcA20bdsWjzzyCCZMmID9+/fj8OHDGDt2LJydneUyYWFhCA0NRUREBH788UecP38ev/32G95++20cOnSoWscJCAjA/v37cf78eWRlZcm9S2q1GqNHj8b06dPRunVrhIaGmuV9VsRwowCzzblhzw0R1XFubm4ICQnB/Pnz8eCDD6Jjx4549913MW7cOCxatMikuiMiIrBw4UJ8+OGH6NChAz799FPExsaiT58+AMqGb7Zs2YL69evjwQcfRFhYGFq0aIF169bJdTz11FN45JFH8NBDD8Hb2xtr1qyp1rEbNWqEvXv3QqfToX///ujUqROmTp0KT09POcD85z//wQMPPICBAwciLCwM999/v8G8l9oUGxuLRo0aoXfv3hg8eDDGjx+Phg0byq9LkoTt27fjwQcfRFRUFNq0aYNnnnkGf//9tzz/6W5effVVqNVqBAYGwtvbG6mpqfJrY8aMQUlJCaKiohR/b1WRhLCvmR15eXnw8PBAbm4u3N3dTa8wORkt2zngHFrit98AJQLpkz57sTmzF5aO+h0T4+4zvUIisglFRUVISUlB8+bNodVqLd0comr75Zdf0LdvX1y4cOGOYelOn/GafH9zzo0CePsFIiKiyoqLi3Hp0iXMnDkTQ4YMqXYvkKk4LKUApYelVJLeoF4iIqK6aM2aNWjWrBlycnLwwQcf1NpxLRpufv75ZwwcOBCNGjWq9h1Yy6+P4OTkhFatWlW6TkKt44RiIiKiKo0ePRo6nQ6HDx9G48aNa+24Fg03hYWF6NKlCxYvXlyt8ikpKXjsscfw0EMPITExEVOnTsXYsWPxww8/mLmld8al4ERERNbDonNuBgwYgAEDBlS7/LJly9C8eXP55mPt27fHr7/+ivnz5yM8PNxczbwzXsSPiGqZna0DITui1Ge7Ts252bdvH8LCwgy2hYeHY9++fRZqURnFw43E2y8QUWVqtRoAUFJSYuGWEJlH+We7/LNurDq1Wio9Pb3STGsfHx/k5eXh2rVrBhckKldcXGxwUabye5IoRgh5WIr3liIic3JwcICLiwsuXboER0dHi1wQjshc9Ho9Ll26BBcXlyqv+lwTdSrcGCMmJgazZs0y6zHKe24UXwrOOTdEVIEkSfDz80NKSgr+/vtvSzeHSHEqlQpNmzaV7yNmrDoVbnx9fZGRkWGwLSMjA+7u7lX22gDA9OnTMW3aNPl5Xl6ewR1ilWC+YSl23RCRIY1Gg9atW3NoimySRqNRpEeyToWb0NBQbN++3WDbjh077nifCicnJzg5OZmvUWadUMyeGyKqTKVS8QrFRHdg0QHbgoICJCYmIjExEQDkm5eV349i+vTpGDlypFx+4sSJOHfuHF5//XX8+eefWLJkCdavX4+XX37ZEs2XmW0pODtuiIiIasyi4ebQoUPo2rUrunbtCgCYNm0aunbtihkzZgAA0tLSDG681bx5c3z33XfYsWMHunTpgo8++ghffPGF5ZaBA1wKTkREZGUsOizVp0+fO84rqerqw3369MHRo0fN2KqaM99dwYmIiKimuI7QVOZYCi6VV805N0RERDXFcKMA5ZeCl/XZ6PXK1EdERGRPGG4UYLal4MpUR0REZFcYbkzFpeBERERWheFGAVwKTkREZD0Ybkxlhp4bFe8tRUREZDSGGwXwruBERETWg+HGVGa5K/iNqpWpjoiIyK4w3ChA8aXgcs8NJxQTERHVFMONAnj7BSIiIuvBcGMqsywF55wbIiIiYzHcKED5peBl/zLbEBER1RzDjamEgFB8QjF7boiIiIzFcGOiigFE+aXgnFBMRERUUww3JhL6m+lG8WEp9twQERHVGMONiczSc1NF3URERFQ9DDcmMk+4KatUz2EpIiKiGmO4MZF55tzcqFuZ6oiIiOwKw42J9PqbPys256Z8tZT+LgWJiIioEoYbE1WcUKz4ailwWIqIiKimGG5MxAnFRERE1oXhxkRmGZaSeBE/IiIiYzHcmMgcPTeq8jk3ylRHRERkVxhuTGTW1VJMN0RERDXGcGMic17nhrdfICIiqjmGGxOZZ85N2b/suCEiIqo5hhsTmXUpONMNERFRjTHcmMi8S8E5LEVERFRTDDcm4lJwIiIi68JwYyJexI+IiMi6MNyYyKyrpZSpjoiIyK4w3JjIHL0r5SFJzzk3RERENcZwY6LyOTcq6BSrk3NuiIiIjMdwY6LyACIpOIjE1VJERETGY7gxkVnCDS/iR0REZDSGGxPpdWURRCUp2XPDYSkiIiJjMdyYSNwYRFJ2WIr3liIiIjIWw42Jym+/YJZhKfbcEBER1RjDjYnKV0spG254nRsiIiJjMdyYqHxYSgX9XUpWH1dLERERGY/hxkQ3h6WUo+J1boiIiIzGcGMieSm4kqulOCxFRERkNIYbE928QrGCw1LyhGIOSxEREdUUw42JzHuFYsWqJCIishsMNya6GW6Uw4v4ERERGY/hxkTyUnBF59yU/SsUjUxERET2geHGROW9K8rOuSmrVM+eGyIiohpjuDER7wpORERkXRhuTGTWu4Kz54aIiKjGGG5MJC8FN8ddwRWrkYiIyH4w3JjIPD03vCs4ERGRsRhuTGSWu4KX182uGyIiohpjuDGR/kbviqLXuZGXghMREVFNWTzcLF68GAEBAdBqtQgJCcGBAwfuWH7BggVo27YtnJ2d4e/vj5dffhlFRUW11NrK5KXgkpJ3BeewFBERkbEsGm7WrVuHadOmITo6GkeOHEGXLl0QHh6OzMzMKsuvXr0ab775JqKjo3Hq1Cl8+eWXWLduHd56661abvlNZl0tpViNRERE9sOi4WbevHkYN24coqKiEBgYiGXLlsHFxQXLly+vsvxvv/2GXr164dlnn0VAQAD69++PYcOG3bW3x5zMO6FYsSqJiIjshsXCTUlJCQ4fPoywsLCbjVGpEBYWhn379lW5T8+ePXH48GE5zJw7dw7bt2/Ho48+etvjFBcXIy8vz+ChJPMsBS/DYSkiIqKac7DUgbOysqDT6eDj42Ow3cfHB3/++WeV+zz77LPIysrC/fffDyEESktLMXHixDsOS8XExGDWrFmKtr0ic/TcqNhzQ0REZDSLTyiuid27d+P999/HkiVLcOTIEXzzzTf47rvvMHv27NvuM336dOTm5sqPCxcuKNomsywF55wbIiIio1ms58bLywtqtRoZGRkG2zMyMuDr61vlPu+++y5GjBiBsWPHAgA6deqEwsJCjB8/Hm+//TZUqspZzcnJCU5OTsq/gRvKl4KrzHL7BQ5LERER1ZTFem40Gg2Cg4ORkJAgb9Pr9UhISEBoaGiV+1y9erVSgFGr1QAAYaExHHlYygy3X+BdwYmIiGrOYj03ADBt2jSMGjUK3bt3R48ePbBgwQIUFhYiKioKADBy5Eg0btwYMTExAICBAwdi3rx56Nq1K0JCQnDmzBm8++67GDhwoBxyapt57grO69wQEREZy6LhJjIyEpcuXcKMGTOQnp6OoKAgxMfHy5OMU1NTDXpq3nnnHUiShHfeeQcXL16Et7c3Bg4ciH//+9+Wegu8zg0REZGVsWi4AYApU6ZgypQpVb62e/dug+cODg6Ijo5GdHR0LbSsesyyFJxzboiIiIxWp1ZLWSOzDkspViMREZH9YLgx0c1wo5ybPTcKVkpERGQnGG5MdHNYSsEbZ0qcUExERGQshhsTiRt9NsoOS5XXTURERDXFcGOim1coVg4nFBMRERmP4cZE5r3OjWJVEhER2Q2LLwW3lGUjfoWzo6vJ9Zw8VfavsnNuyv5ltiEiIqo5uw03b2y9H4C7YvVp1aWK1cVhKSIiIuPZbbh5svF+OKpM77kBALVKYPxUZeoCeJ0bIiIiU9htuIk7GQJ3d+V6bpTEnhsiIiLjcUKxFVJJnFBMRERkLIYbK1R+ET89e26IiIhqjOHGCkk3xqXYcUNERFRzDDdW6OZ1bthzQ0REVFMMN1aIq6WIiIiMx3BjhaQb/1U4oZiIiKjmGG6skHzjTA5LERER1RjDjRXisBQREZHxGG6sEC/iR0REZDyGGyvEG2cSEREZj+HGCnEpOBERkfEYbqwQe26IiIiMx3BjhW7OubFsO4iIiOoihhsrdHO1FIeliIiIaorhxgqx54aIiMh4DDdWiEvBiYiIjMdwY4XKh6X0DDdEREQ15mDpBlBlqhuRs+Q6cG53qmL1Nr2vERy0/E9ORES2jd90Vqi85+ZcnjdaPqRcvfe6/oEDBR2Uq5CIiMgKMdxYoa4jO6Hzt3/gbGkzReoTkHAVrjhY2AFC3JzTQ0REZIsYbqxQvYi+OHZdufqyTmbCu4MrAECvB9Rq5eomIiKyNpxQbAccHG921eh0FmwIERFRLWC4sQMOFfrnSq/z4jlERGTbGG7sgIPm5n/m0hK9BVtCRERkfgw3dqDisBR7boiIyNYZFW4CAgLw3nvvITVVuWuwkPmoHSrMuSlluCEiIttmVLiZOnUqvvnmG7Ro0QL9+vXD2rVrUVxcrHTbSCGSSoIKZTOJ2XNDRES2zuhwk5iYiAMHDqB9+/Z44YUX4OfnhylTpuDIkSNKt5FMpVLBAaUAOOeGiIhsn0lzbrp164aPP/4Y//zzD6Kjo/HFF1/g3nvvRVBQEJYvXw7B21pbB0m6GW5KLdwWIiIiMzPpIn7Xr1/Hpk2bEBsbix07duC+++7DmDFj8L///Q9vvfUWdu7cidWrVyvVVjKWJEF9Y1iKc26IiMjWGRVujhw5gtjYWKxZswYqlQojR47E/Pnz0a5dO7nMk08+iXvvvVexhpIJKvbccM4NERHZOKPCzb333ot+/fph6dKliIiIgKOjY6UyzZs3xzPPPGNyA0kBFefcMNwQEZGNMyrcnDt3Ds2a3fmmjq6uroiNjTWqUaQw9twQEZEdMWpC8UMPPYTLly9X2p6Tk4MWLVqY3ChSWMU5NzqGGyIism1GhZvz589DV8UdGIuLi3Hx4kWTG0UKM+i5sXBbiIiIzKxGw1Jbt26Vf/7hhx/g4eEhP9fpdEhISEBAQIBijSOFcM4NERHZkRqFm4iICACAJEkYNWqUwWuOjo4ICAjARx99pFjjSCEVem64FJyIiGxdjcKNXl92ddvmzZvj4MGD8PLyMkujSGG8iB8REdkRo1ZLpaSkKN0OMqcKE4o5LEVERLau2uHm448/xvjx46HVavHxxx/fseyLL75ocsNIQVwKTkREdqTa4Wb+/PkYPnw4tFot5s+ff9tykiQx3Fghec5N5UVuRERENqXa4abiUBSHpeqem3Nu2HNDRES2zaS7gith8eLFCAgIgFarRUhICA4cOHDH8jk5OZg8eTL8/Pzg5OSENm3aYPv27bXU2rpLjbLJ4LzODRER2bpq99xMmzat2pXOmzevWuXWrVuHadOmYdmyZQgJCcGCBQsQHh6O5ORkNGzYsFL5kpIS9OvXDw0bNsTXX3+Nxo0b4++//4anp2e122avHKRSQHDODRER2b5qh5ujR49Wq5wkSdU++Lx58zBu3DhERUUBAJYtW4bvvvsOy5cvx5tvvlmp/PLly5GdnY3ffvtNvlknLxpYPQ7y7Rcs3BAiIiIzq3a42bVrl6IHLikpweHDhzF9+nR5m0qlQlhYGPbt21flPlu3bkVoaCgmT56MLVu2wNvbG88++yzeeOMNqNXqKvcpLi5GcXGx/DwvL0/R91FXyD03vM4NERHZOJPm3Jw5cwY//PADrl27BgAQovpDHllZWdDpdPDx8THY7uPjg/T09Cr3OXfuHL7++mvodDps374d7777Lj766CP83//9322PExMTAw8PD/nh7+9f7TbaEvk6Nww3RERk44wKN5cvX0bfvn3Rpk0bPProo0hLSwMAjBkzBq+88oqiDaxIr9ejYcOG+OyzzxAcHIzIyEi8/fbbWLZs2W33mT59OnJzc+XHhQsXzNY+a+bAi/gREZGdMCrcvPzyy3B0dERqaipcXFzk7ZGRkYiPj69WHV5eXlCr1cjIyDDYnpGRAV9f3yr38fPzQ5s2bQyGoNq3b4/09HSUlJRUuY+TkxPc3d0NHvbIQeKcGyIisg9GhZsff/wRc+fORZMmTQy2t27dGn///Xe16tBoNAgODkZCQoK8Ta/XIyEhAaGhoVXu06tXL5w5c0a+xxUAnD59Gn5+ftBoNEa8E/vhIPHeUkREZB+MCjeFhYUGPTblsrOz4eTkVO16pk2bhs8//xwrVqzAqVOnMGnSJBQWFsqrp0aOHGkw4XjSpEnIzs7GSy+9hNOnT+O7777D+++/j8mTJxvzNuyKA+fcEBGRnTDqxpkPPPAAvvrqK8yePRtA2fJvvV6PDz74AA899FC164mMjMSlS5cwY8YMpKenIygoCPHx8fIk49TUVKhUN/OXv78/fvjhB7z88svo3LkzGjdujJdeeglvvPGGMW/DrqhvDEudO5KD37+oesJ2TWnrOaLz022gUld/+T8REZG5SaImS5xuSEpKQt++fdGtWzf89NNPeOKJJ/DHH38gOzsbe/fuRcuWLc3RVkXk5eXBw8MDubm5djX/ZrzTCnxeMkrxet/ruwfv7uyteL1EREQV1eT726iem44dO+L06dNYtGgR6tWrh4KCAgwePFi+LQJZn+HPCuxblYyrQqtIfbk6N1wW9+DEX8rUR0REpBSjem7qMnvtuVHaiud+xOhV/RHum4j4tCBLN4eIiGycWXpujh8/Xu0GdO7cudplqW7ycC2bw5Nb4mzhlhARERmqdrgJCgqCJEkQQhjcP6q846fiNh0vpmLz3N3KluPnMdwQEZGVqfZS8JSUFJw7dw4pKSnYuHEjmjdvjiVLliAxMRGJiYlYsmQJWrZsiY0bN5qzvWQl5HBTynBDRETWpdo9N82aNZN/HjJkCD7++GM8+uij8rbOnTvD398f7777LiIiIhRtJFkfD/eyHru865Wvd0RERGRJRl3E78SJE2jevHml7c2bN8fJkydNbhRZP/d6ZeEmX+eMCheMJiIisjijloK3b98eMTEx+OKLL+TbHpSUlCAmJgbt27dXtIFkncp7bgRU2PTuEThrlJln1SyoPjoMaqVIXUREZJ+MCjfLli3DwIED0aRJE3ll1PHjxyFJEr799ltFG0jWyameBk4oQjG0ePr9borW/ef2c2g7oIWidRIRkf0wKtz06NED586dw6pVq/Dnn38CKLuVwrPPPgtXV1dFG0jWSer9IGZ12ICvU4IVq/OPqwG4Bhf8nXgFbQcoVi0REdkZo8INALi6umL8+PFKtoXqEjc3vJE0Akre1aub8ykcLWoPnZ73qiIiIuNVO9xs3boVAwYMgKOjI7Zu3XrHsk888YTJDSP7o5bKZibzMklERGSKaoebiIgIpKeno2HDhndc6i1JEi/iR0Ypv3M5Pz5ERGSKaocbfYX1vnqu/SUzYM8NEREpodrXuWnQoAGysrIAAM8//zzy8/PN1iiyT3K44ZwbIiIyQbXDTUlJCfLy8gAAK1asQFFRkdkaRfZJDfbcEBGR6ao9LBUaGoqIiAgEBwdDCIEXX3wRzs5V31do+fLlijWQ7Ed5zw1HPYmIyBTVDjf//e9/MX/+fJw9exaSJCE3N5e9N6QozrkhIiIlVDvc+Pj4YM6cOQDK7iG1cuVK3HPPPWZrGNkflTznxsINISKiOs2oi/ilpKQo3Q6iCj03nFBMRETGM/oKxQkJCUhISEBmZmalpeGcc0PG4LAUEREpwahwM2vWLLz33nvo3r07/Pz8IEn8S5tMJ6+W4rAUERGZwOi7gsfFxWHEiBFKt4fsGIeliIhICdW+zk1FJSUl6Nmzp9JtITvHYSkiIlKCUeFm7NixWL16tdJtITvHKxQTEZESjBqWKioqwmeffYadO3eic+fOcHR0NHh93rx5ijSO7Asv4kdEREowKtwcP34cQUFBAICkpCQl20N2TK3isBQREZnOqHCza9cupdtBxGEpIiJSRI3CzeDBg+9aRpIkbNy40egGkf3ihGIiIlJCjcKNh4eHudpBBLUkALDnhoiITFOjcBMbG2uudhBBVR5u2HNDREQmMGopOJE5cM4NEREpgeGGrIaadwUnIiIFMNyQ1bi5FJw9N0REZDyGG7IaHJYiIiIlMNyQ1ShfLcUrFBMRkSkYbshqsOeGiIiUwHBDVkOec8OeGyIiMgHDDVkNXsSPiIiUwHBDVuPm7RcYboiIyHgMN2Q11Cr23BARkekYbshqcEIxEREpgeGGrIZ8bylOKCYiIhMw3JDV4LAUEREpgeGGrEb5sJSe4YaIiEzAcENWgz03RESkBIYbshq8KzgRESmB4YasBntuiIhICQw3ZDVu3n6B4YaIiIzHcENWg7dfICIiJTDckNXgsBQRESnBwdINICpXPiyV+o8DFg3Zo1i9/cc2RZvw5orVR0RE1o3hhqyGi3PZv2cK/PDC136K1dvh27+QVKRYdUREZOWsItwsXrwY//nPf5Ceno4uXbrgk08+QY8ePe6639q1azFs2DAMGjQImzdvNn9Dyaz6xoRh6qh4XCzwUKS+3GuO+PFyd2SW1FekPiIiqhssHm7WrVuHadOmYdmyZQgJCcGCBQsQHh6O5ORkNGzY8Lb7nT9/Hq+++ioeeOCBWmwtmZNzj06Yf6qTYvWd2nIagRGAjlPLiIjsisV/68+bNw/jxo1DVFQUAgMDsWzZMri4uGD58uW33Uen02H48OGYNWsWWrRoUYutpbpEdePTrYPasg0hIqJaZdFwU1JSgsOHDyMsLEzeplKpEBYWhn379t12v/feew8NGzbEmDFj7nqM4uJi5OXlGTzIPqgdylZdMdwQEdkXi4abrKws6HQ6+Pj4GGz38fFBenp6lfv8+uuv+PLLL/H5559X6xgxMTHw8PCQH/7+/ia3m+oG9Y1MoxMW76AkIqJaVKd+6+fn52PEiBH4/PPP4eXlVa19pk+fjtzcXPlx4cIFM7eSrIUcbthzQ0RkVyw6odjLywtqtRoZGRkG2zMyMuDr61up/NmzZ3H+/HkMHDhQ3qbXl10bxcHBAcnJyWjZsqXBPk5OTnBycjJD68nacViKiMg+WbTnRqPRIDg4GAkJCfI2vV6PhIQEhIaGVirfrl07nDhxAomJifLjiSeewEMPPYTExEQOOZGBmz03Fl8USEREtcjiv/WnTZuGUaNGoXv37ujRowcWLFiAwsJCREVFAQBGjhyJxo0bIyYmBlqtFh07djTY39PTEwAqbScq77kBAL3+5uopIiKybRYPN5GRkbh06RJmzJiB9PR0BAUFIT4+Xp5knJqaChW/lcgI6gqjUTodww0Rkb2QhBDC0o2oTXl5efDw8EBubi7c3d0t3Rwyo9yj5+DZrew6SNeuAVqthRtERERGq8n3N/+WJZt1a88NERHZB4YbslkV59ww3BAR2Q+GG7JZFXtublwxgIiI7ADDDdks9twQEdknhhuyWSo1ww0RkT1iuCGbJakkqFCWahhuiIjsB8MN2S5JgprhhojI7jDckO1iuCEisksMN2S7GG6IiOwSww3ZLoYbIiK7xHBDtovhhojILjHckO1iuCEisksMN2S7GG6IiOwSww3ZLoYbIiK7xHBDtqtiuCkVFm4MERHVFoYbsl0MN0REdonhhmwXww0RkV1iuCHbZTDnhuGGiMheMNyQ7TLoubFwW4iIqNYw3JDt4rAUEZFdYrgh28VwQ0RklxhuyHbxOjdERHaJ4YZsF3tuiIjsEsMN2S723BAR2SWGG7Jd7LkhIrJLDDdku3idGyIiu8RwQ7aL17khIrJLDDdku9hzQ0RklxhuyHax54aIyC45WLoBRGZjhtVSIj0DL9+3D3svtVGmwhva+V5B7Mn74OCkVrReIiJ7xHBDtqtCuFkz528kxWaYXGVeYgq+0EWZXM+tDp0DJq75C71Gt1a8biIie8NwQ7ZLrYanugDQATv+1x47/tdegUr7AAAGue/C+GluCtQHRP9bg0PXuyD5lB69FKmRiMi+MdyQ7VKpMOvLJgj4LAElOuWGe1xcJUxa3Bne7e5RpL7ti9fj0KUuWLlChwsHditSp0oFPPVSEwQ+0UqR+oiI6hKGG7JpzUc9iPdGWboVd9axYSZwCdidEYjdGYGK1Rt/8AT25ilWHRFRncFwQ2Rhz33RBxdfjMflqy6K1JeR7YBv0noivchDkfqIiOoahhsiC3O7ryNmH+ioWH3HYo/gm+eBq3qtYnUSEdUlvM4NkY1xdS37t1CvTE8QEVFdw3BDZGNcXCUAQKFwhuCFmYnIDjHcENkY1xsr1PVQo7jYsm0hIrIEhhsiG+PqdvN/66tXLdgQIiILYbghsjEOWgdoUNZlU1ho4cYQEVkAww2RrVGr4YKyLhuGGyKyRww3RLbGwQGuKEs1DDdEZI8YbohsjVothxvOuSEie8SL+BHZGgcHuOIKAOD/nklCI5crilRb312Ht9Z0hlebBorUR0RkLgw3RLbG3R2NpOM4KoAf/1HuyscAEDB9D17c2FvROomIlMZwQ2RrPDywaKUnHl7zE0r1yow8b/q5AX4v7IzcPEmR+oiIzInhhsgGBQzvhWnDlavvYsed+P0PoOi6WrlKiYjMhBOKieiutA46AEBRCX9lEJH1428qIrorrUMpAPbcEFHdwHBDRHeldSzruSku5a8MIrJ+/E1FRHdVHm6KrnOaHhFZP6sIN4sXL0ZAQAC0Wi1CQkJw4MCB25b9/PPP8cADD6B+/fqoX78+wsLC7lieiEznJIcbDksRkfWzeLhZt24dpk2bhujoaBw5cgRdunRBeHg4MjMzqyy/e/duDBs2DLt27cK+ffvg7++P/v374+LFi7XcciL7IU8oLmXPDRFZP4uHm3nz5mHcuHGIiopCYGAgli1bBhcXFyxfvrzK8qtWrcK//vUvBAUFoV27dvjiiy+g1+uRkJBQyy0nsh9ajR4AUFTKnhsisn4WDTclJSU4fPgwwsLC5G0qlQphYWHYt29fteq4evUqrl+/jgYNqr4kfHFxMfLy8gweRFQz5eGmmD03RFQHWDTcZGVlQafTwcfHx2C7j48P0tPTq1XHG2+8gUaNGhkEpIpiYmLg4eEhP/z9/U1uN5G9kScUs+eGiOoAiw9LmWLOnDlYu3YtNm3aBK1WW2WZ6dOnIzc3V35cuHChlltJVPc5OZYPSzlauCVERHdn0T5mLy8vqNVqZGRkGGzPyMiAr6/vHff98MMPMWfOHOzcuROdO3e+bTknJyc4OTkp0l4ie3Vzzg2HpYjI+lm050aj0SA4ONhgMnD55ODQ0NDb7vfBBx9g9uzZiI+PR/fu3WujqUR2TZ5zo2O4ISLrZ/HfVNOmTcOoUaPQvXt39OjRAwsWLEBhYSGioqIAACNHjkTjxo0RExMDAJg7dy5mzJiB1atXIyAgQJ6b4+bmBjc3N4u9DyJbpnUSAICCEkccWXVKsXpbPtAIHk09FKuPiAiwgnATGRmJS5cuYcaMGUhPT0dQUBDi4+PlScapqalQqW52MC1duhQlJSV4+umnDeqJjo7GzJkza7PpRHajPNxcuV4Pwc+1V6xeb+kSUrOLoPWses4cEZExJCGEsHQjalNeXh48PDyQm5sLd3d3SzeHqE7Qn/gDT92fgUOF7RSr83+6RgCAv/eno2mPO8+xIyKqyfe3xXtuiMj6qTp1wKbcDorW6SnlIBeeKLpmV39fEVEtqNNLwYmo7tKiGABQdFVv4ZYQka1huCEii9BKRQDAnhsiUhzDDRFZhHN5uCliuCEiZTHcEJFFaKUbw1LsuSEihTHcEJFF3Aw3Fm4IEdkchhsisgitVAIAKCqycEOIyOYw3BCRRWhVHJYiIvNguCEii2DPDRGZC8MNEVmE3HNTbOGGEJHNYbghIovQqq4DYM8NESmP4YaILEKrKh+WkizcEiKyNQw3RGQR5eHmGsMNESmMN84kIovQqsuGpc4kXcOueUcVqdNBo0LI6PbQuGkUqc9eiewr2Pz2QVzIdFK03r6jmqDDEy0VrZMU8NdfwLlzQHi4pVuiGIYbIrIIZ3VZz83Xx9rg61eUq/f5T37Bl8kPKFehHfp98koMXvui4vW2/PZvnClRvFoyVZs2Zf/u2wfcd59l26IQhhsisoghL/jix5gjyNHVU6S+vFIXXNA1xukMD0Xqs2dp/5Rde8jbIRt9G/1pcn2FRWp8mxmCtOteJtdFZnTwIMMNEZEp2r/zFH59R7n64t/+BQPeb4yrpcoOpdijoutqAECXFvlYk9zT5PrS9p3Htz2BImhNrovMSNjOBTU5oZiIbIKLS9m/V/UMN6YqDzdaR70i9Wldyr5q9FCjtFSRKskcGG6IiKyLi3PZL+arOoYbUxXpyjr1tRqdIvWVhxuA1zWyagw3RETWpbznplDnbNmG2ICi6zfCjUI9N07am8v9GW6sGMMNEZF14bCUcopKle25UTmq4QjeS8zq2VC44YRiIrIJ5eHmmnCGXg+oFPjTrWjPfgx8TI+/ivxNr6yCAe1SsDTJeperF+kcAQBajTI9N1CpoEURrkOD4iIBgBdutEp6hf57WwGGGyKyCS6uhkMf5WHHFPsXH8LOwsmmV3SLZX80wQdZxajnZZ29TDd7bhT6S16thhZFyIc7iq4x3Fgt9twQEVkXZ5ebX5hXryoTbtJzypYuB3udx9IPr5pe4fXr6DOuFa7CFRkXSqw23FwrVbjnRq2GE8rOX9FVHRSZEXHxIkZ3PITvcnuZXlcFbdz+wc6/28C5vh0uW2e4ISKyLmqNGk4oQjG0uKpADgGA9NyyycmtGl3FvaMCTa9Qr4fvuBScQ0tkXCxFq66mV2kO8rCUk7LDUgBQVKhMnQXf/4IVOc8oUldFWfleOLj2Dzw4qYPidVs9DksREVkZtRouuKpsuMl3BQD4ehYrU6FKBR8pE+dES2T8o8xkXXO4OedG2WEpADeGpUx3Obusp04jleDIplRF6hw+tATHSgJx+bLt9GDUCHtuiIisjIMDXHAVV9AA//fkIXg7F5pc5c6z7QAAvg0UCjcAfNRZQCmw9dM05P5+SpE6Nc5qPP5mR3j4uytS382eG4W+7Cr03BRfU6Z3IDu3bGjrHqcCdBjUSpE6mzj9jGMlwOVs+1pIvAiTMQdvYvnpX9Df0o1RCMMNEdkGT080RCYuoglW/dld0aoDApSrq5HTZaAUWHGkE1YcUa7eCXt+xbKk+xWpS/FwY46em5yyr68GToUAGihS5z2aPABA9hX7mvD8AhYBABb8di/DDRGRVWnRAl/M3o6N3++CEMp9OXk3lPDkLOVuJjgl2guX5v+CwlJlJqxmF2rw+9Uu2JfaSJH6AKBIr3y4cUJZ75dS4SY7r+zr6x6t6T105e7RFAAALufYV89NuZRsT0s3QTEMN0RkM7q98yi6KXgzTnNo/9rjWP+acvWdX7IdzSd3wan8Jni1+25F6jyV3waAeYallA43DbTXFKkPuBmUkv8EDsb9AZUkIEmAJMHwZxUgQdz8WSp7Lv8sCahulJVUEup1bg4nN0eDY0mqWwK4JEG6dZMRZSrtU60yZc+vFDri2PrkSvtbi4KrBdUuy3BDRFSHNeviiXuQhcvwwkeH+yha9z1+GmUqkiQ53IyZWg9jpipR6QAAwD0uCs0eB+B1Y57Wlj/bYkuUYtXWGRnXPBAU6WHpZtxBXrVLMtwQEdVhUs9QbJy6Bdt/81S0Xv+mEh78lzJzeACgd6uL2HhGseoAACro8NBDyg1BPjqlBXq8fAwZpfdAQIK+rH/mxs8qCCHdYTvKfr5lux4SrkOhkGhm9aUr0ErKTZ5Xml7kI6OaHX+SEDa09qsa8vLy4OHhgdzcXLi7K7OygIiI7kKvR87ZyygpUa5KrYcT3JtY+e9xvR5Xs64aXEJG6A2/du/6/JZv6Rrvr7+1AlGpTs9mHnB0MRw6szY1+f5mzw0REZmfSgXP1t6WbkXtU6ng0tDN0q2wO/Y5JZyIiIhsFsMNERER2RSGGyIiIrIpDDdERERkUxhuiIiIyKYw3BAREZFNYbghIiIim8JwQ0RERDaF4YaIiIhsCsMNERER2RSGGyIiIrIpDDdERERkUxhuiIiIyKYw3BAREZFNYbghIiIim8JwQ0RERDaF4YaIiIhsCsMNERER2RSrCDeLFy9GQEAAtFotQkJCcODAgTuW37BhA9q1awetVotOnTph+/bttdRSIiIisnYWDzfr1q3DtGnTEB0djSNHjqBLly4IDw9HZmZmleV/++03DBs2DGPGjMHRo0cRERGBiIgIJCUl1XLLiYiIyBpJQghhyQaEhITg3nvvxaJFiwAAer0e/v7+eOGFF/Dmm29WKh8ZGYnCwkJs27ZN3nbfffchKCgIy5Ytu+vx8vLy4OHhgdzcXLi7uyv3RoiIiMhsavL9bdGem5KSEhw+fBhhYWHyNpVKhbCwMOzbt6/Kffbt22dQHgDCw8NvW56IiIjsi4MlD56VlQWdTgcfHx+D7T4+Pvjzzz+r3Cc9Pb3K8unp6VWWLy4uRnFxsfw8NzcXQFkCJCIiorqh/Hu7OgNOFg03tSEmJgazZs2qtN3f398CrSEiIiJT5Ofnw8PD445lLBpuvLy8oFarkZGRYbA9IyMDvr6+Ve7j6+tbo/LTp0/HtGnT5Oc5OTlo1qwZUlNT73py6M7y8vLg7++PCxcucP6SAng+lcNzqRyeS+XwXJpGCIH8/Hw0atTormUtGm40Gg2Cg4ORkJCAiIgIAGUTihMSEjBlypQq9wkNDUVCQgKmTp0qb9uxYwdCQ0OrLO/k5AQnJ6dK2z08PPjhUoi7uzvPpYJ4PpXDc6kcnkvl8Fwar7qdEhYflpo2bRpGjRqF7t27o0ePHliwYAEKCwsRFRUFABg5ciQaN26MmJgYAMBLL72E3r1746OPPsJjjz2GtWvX4tChQ/jss88s+TaIiIjISlg83ERGRuLSpUuYMWMG0tPTERQUhPj4eHnScGpqKlSqm4u6evbsidWrV+Odd97BW2+9hdatW2Pz5s3o2LGjpd4CERERWRGLhxsAmDJlym2HoXbv3l1p25AhQzBkyBCjjuXk5ITo6Ogqh6qoZngulcXzqRyeS+XwXCqH57L2WPwifkRERERKsvjtF4iIiIiUxHBDRERENoXhhoiIiGwKww0RERHZFLsLN4sXL0ZAQAC0Wi1CQkJw4MABSzfJon7++WcMHDgQjRo1giRJ2Lx5s8HrQgjMmDEDfn5+cHZ2RlhYGP766y+DMtnZ2Rg+fDjc3d3h6emJMWPGoKCgwKDM8ePH8cADD0Cr1cLf3x8ffPCBud9arYuJicG9996LevXqoWHDhoiIiEBycrJBmaKiIkyePBn33HMP3Nzc8NRTT1W64nZqaioee+wxuLi4oGHDhnjttddQWlpqUGb37t3o1q0bnJyc0KpVK8TFxZn77dW6pUuXonPnzvIFz0JDQ/H999/Lr/NcGmfOnDmQJMngQqg8l9U3c+ZMSJJk8GjXrp38Os+llRB2ZO3atUKj0Yjly5eLP/74Q4wbN054enqKjIwMSzfNYrZv3y7efvtt8c033wgAYtOmTQavz5kzR3h4eIjNmzeLY8eOiSeeeEI0b95cXLt2TS7zyCOPiC5duojff/9d/PLLL6JVq1Zi2LBh8uu5ubnCx8dHDB8+XCQlJYk1a9YIZ2dn8emnn9bW26wV4eHhIjY2ViQlJYnExETx6KOPiqZNm4qCggK5zMSJE4W/v79ISEgQhw4dEvfdd5/o2bOn/Hppaano2LGjCAsLE0ePHhXbt28XXl5eYvr06XKZc+fOCRcXFzFt2jRx8uRJ8cknnwi1Wi3i4+Nr9f2a29atW8V3330nTp8+LZKTk8Vbb70lHB0dRVJSkhCC59IYBw4cEAEBAaJz587ipZdekrfzXFZfdHS06NChg0hLS5Mfly5dkl/nubQOdhVuevToISZPniw/1+l0olGjRiImJsaCrbIet4YbvV4vfH19xX/+8x95W05OjnBychJr1qwRQghx8uRJAUAcPHhQLvP9998LSZLExYsXhRBCLFmyRNSvX18UFxfLZd544w3Rtm1bM78jy8rMzBQAxJ49e4QQZefO0dFRbNiwQS5z6tQpAUDs27dPCFEWNlUqlUhPT5fLLF26VLi7u8vn7/XXXxcdOnQwOFZkZKQIDw8391uyuPr164svvviC59II+fn5onXr1mLHjh2id+/ecrjhuayZ6Oho0aVLlypf47m0HnYzLFVSUoLDhw8jLCxM3qZSqRAWFoZ9+/ZZsGXWKyUlBenp6QbnzMPDAyEhIfI527dvHzw9PdG9e3e5TFhYGFQqFfbv3y+XefDBB6HRaOQy4eHhSE5OxpUrV2rp3dS+3NxcAECDBg0AAIcPH8b169cNzme7du3QtGlTg/PZqVMn+QrdQNm5ysvLwx9//CGXqVhHeRlb/hzrdDqsXbsWhYWFCA0N5bk0wuTJk/HYY49Ver88lzX3119/oVGjRmjRogWGDx+O1NRUADyX1sRuwk1WVhZ0Op3BBwoAfHx8kJ6ebqFWWbfy83Knc5aeno6GDRsavO7g4IAGDRoYlKmqjorHsDV6vR5Tp05Fr1695FuDpKenQ6PRwNPT06DsrefzbufqdmXy8vJw7do1c7wdizlx4gTc3Nzg5OSEiRMnYtOmTQgMDOS5rKG1a9fiyJEj8j36KuK5rJmQkBDExcUhPj4eS5cuRUpKCh544AHk5+fzXFoRq7j9ApGtmTx5MpKSkvDrr79auil1Wtu2bZGYmIjc3Fx8/fXXGDVqFPbs2WPpZtUpFy5cwEsvvYQdO3ZAq9Vaujl13oABA+SfO3fujJCQEDRr1gzr16+Hs7OzBVtGFdlNz42XlxfUanWlWesZGRnw9fW1UKusW/l5udM58/X1RWZmpsHrpaWlyM7ONihTVR0Vj2FLpkyZgm3btmHXrl1o0qSJvN3X1xclJSXIyckxKH/r+bzbubpdGXd3d5v75arRaNCqVSsEBwcjJiYGXbp0wcKFC3kua+Dw4cPIzMxEt27d4ODgAAcHB+zZswcff/wxHBwc4OPjw3NpAk9PT7Rp0wZnzpzh59KK2E240Wg0CA4ORkJCgrxNr9cjISEBoaGhFmyZ9WrevDl8fX0NzlleXh72798vn7PQ0FDk5OTg8OHDcpmffvoJer0eISEhcpmff/4Z169fl8vs2LEDbdu2Rf369Wvp3ZifEAJTpkzBpk2b8NNPP6F58+YGrwcHB8PR0dHgfCYnJyM1NdXgfJ44ccIgMO7YsQPu7u4IDAyUy1Sso7yMPXyO9Xo9iouLeS5roG/fvjhx4gQSExPlR/fu3TF8+HD5Z55L4xUUFODs2bPw8/Pj59KaWHpGc21au3atcHJyEnFxceLkyZNi/PjxwtPT02DWur3Jz88XR48eFUePHhUAxLx588TRo0fF33//LYQoWwru6ekptmzZIo4fPy4GDRpU5VLwrl27iv3794tff/1VtG7d2mApeE5OjvDx8REjRowQSUlJYu3atcLFxcXmloJPmjRJeHh4iN27dxssE7169apcZuLEiaJp06bip59+EocOHRKhoaEiNDRUfr18mWj//v1FYmKiiI+PF97e3lUuE33ttdfEqVOnxOLFi21ymeibb74p9uzZI1JSUsTx48fFm2++KSRJEj/++KMQgufSFBVXSwnBc1kTr7zyiti9e7dISUkRe/fuFWFhYcLLy0tkZmYKIXgurYVdhRshhPjkk09E06ZNhUajET169BC///67pZtkUbt27RIAKj1GjRolhChbDv7uu+8KHx8f4eTkJPr27SuSk5MN6rh8+bIYNmyYcHNzE+7u7iIqKkrk5+cblDl27Ji4//77hZOTk2jcuLGYM2dObb3FWlPVeQQgYmNj5TLXrl0T//rXv0T9+vWFi4uLePLJJ0VaWppBPefPnxcDBgwQzs7OwsvLS7zyyivi+vXrBmV27dolgoKChEajES1atDA4hq14/vnnRbNmzYRGoxHe3t6ib9++crARgufSFLeGG57L6ouMjBR+fn5Co9GIxo0bi8jISHHmzBn5dZ5L6yAJIYRl+oyIiIiIlGc3c26IiIjIPjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RkdwICArBgwQJLN4OIzIThhojMavTo0YiIiAAA9OnTB1OnTq21Y8fFxcHT07PS9oMHD2L8+PG11g4iql0Olm4AEVFNlZSUQKPRGL2/t7e3gq0hImvDnhsiqhWjR4/Gnj17sHDhQkiSBEmScP78eQBAUlISBgwYADc3N/j4+GDEiBHIysqS9+3Tpw+mTJmCqVOnwsvLC+Hh4QCAefPmoVOnTnB1dYW/vz/+9a9/oaCgAACwe/duREVFITc3Vz7ezJkzAVQelkpNTcWgQYPg5uYGd3d3DB06FBkZGfLrM2fORFBQEFauXImAgAB4eHjgmWeeQX5+vnlPGhEZheGGiGrFwoULERoainHjxiEtLQ1paWnw9/dHTk4OHn74YXTt2hWHDh1CfHw8MjIyMHToUIP9V6xYAY1Gg71792LZsmUAAJVKhY8//hh//PEHVqxYgZ9++gmvv/46AKBnz55YsGAB3N3d5eO9+uqrldql1+sxaNAgZGdnY8+ePdixYwfOnTuHyMhIg3Jnz57F5s2bsW3bNmzbtg179uzBnDlzzHS2iMgUHJYiolrh4eEBjUYDFxcX+Pr6ytsXLVqErl274v3335e3LV++HP7+/jh9+jTatGkDAGjdujU++OADgzorzt8JCAjA//3f/2HixIlYsmQJNBoNPDw8IEmSwfFulZCQgBMnTiAlJQX+/v4AgK+++godOnTAwYMHce+99wIoC0FxcXGoV68eAGDEiBFISEjAv//9b9NODBEpjj03RGRRx44dw65du+Dm5iY/2rVrB6Cst6RccHBwpX137tyJvn37onHjxqhXrx5GjBiBy5cv4+rVq9U+/qlTp+Dv7y8HGwAIDAyEp6cnTp06JW8LCAiQgw0A+Pn5ITMzs0bvlYhqB3tuiMiiCgoKMHDgQMydO7fSa35+fvLPrq6uBq+dP38ejz/+OCZNmoR///vfaNCgAX799VeMGTMGJSUlcHFxUbSdjo6OBs8lSYJer1f0GESkDIYbIqo1Go0GOp3OYFu3bt2wceNGBAQEwMGh+r+SDh8+DL1ej48++ggqVVkn9Pr16+96vFu1b98eFy5cwIULF+Tem5MnTyInJweBgYHVbg8RWQ8OSxFRrQkICMD+/ftx/vx5ZGVlQa/XY/LkycjOzsawYcNw8OBBnD17Fj/88AOioqLuGExatWqF69ev45NPPsG5c+ewcuVKeaJxxeMVFBQgISEBWVlZVQ5XhYWFoVOnThg+fDiOHDmCAwcOYOTIkejduze6d++u+DkgIvNjuCGiWvPqq69CrVYjMDAQ3t7eSE1NRaNGjbB3717odDr0798fnTp1wtSpU+Hp6Sn3yFSlS5cumDdvHubOnYuOHTti1apViImJMSjTs2dPTJw4EZGRkfD29q40IRkoG17asmUL6tevjwcffBBhYWFo0aIF1q1bp/j7J6LaIQkhhKUbQURERKQU9twQERGRTWG4ISIiIpvCcENEREQ2heGGiIiIbArDDREREdkUhhsiIiKyKQw3REREZFMYboiIiMimMNwQERGRTWG4ISIiIpvCcENEREQ2heGGiIiIbMr/A1dtVLlToV3aAAAAAElFTkSuQmCC", + "image/png": "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5x8cPHiwWue4evUqGjVqVGmdku25ubkAiicEW1lZYePGjXKdpKQknDhxQm8ez6ZNm3D//fejcePGerEHBgZCq9Xi119/1TvPU089hWbNmlUrfkONGzdO/tnZ2RkdO3aEvb09hg8fLpd37NgRzs7Oer9f1b0mInPHoSsiM2JjY1PmRti4ceO7zpMpz/nz5wEA7du3L7OtY8eOcgIBAH///TdycnLQvHnzco916dKlap+/KjIzM5GdnY1PPvkEn3zySaXnfuONN/Dzzz/Dz88P7dq1w8CBA/Hss8+ib9++lZ6jUaNGyMrKqrTO1atX5boA4OLiggEDBuDrr7/G3LlzARQPW1lZWek9+fT333/j2LFjFSYvpdutZHiorpX3e+Tk5ISWLVvqzZcqKb/z96u610Rk7pjoEJkRpVJpkvPqdDo0b94c69atK3d7XfVClExufe655zB69Ohy65Q8gdS5c2ckJydj+/btiImJwbfffosVK1Zg1qxZ5U4cLtG5c2ckJiYiNTUVrVq1KrfOsWPHAECvp+uZZ55BWFgYEhMT4e3tja+//hoDBgyAi4uLXvwPP/wwXn/99XKP26FDB73vtra2FcZZmyr6PaqoXAgh/1zdayIyd0x0iOqp1q1bAyj+P/TSkpOT9b63bdsWP//8M/r27VsrN+PSvQYVadasGRo1agStVovAwMC71re3t0dISAhCQkJQWFiIoUOH4r333kNERESFj1k//vjj+Oqrr/DFF1/g7bffLrM9NzcXW7duRadOnfTWrwkODsaECRPk4atTp04hIiJCb9+2bdsiLy+vSrFbivp4TdSwcY4OUT3l7u4Ob29vfP7558jJyZHLd+3aVeax5uHDh0Or1crDNHe6efMmsrOzq3Vue3t7ALjrfkqlEk899ZT8CHhpdz5JdvnyZb1tKpUKXl5eEEKgqKiownM8/fTT8PLywvz588usRK3T6TBx4kT8999/ZZ6wcnZ2RlBQEL7++mts2LABKpUKwcHBenWGDx+OuLg47Ny5s8x5s7OzcfPmzQrjMlf18ZqoYWOPDlE9FhkZiUGDBuG+++7D888/jytXrshr0eTl5cn1+vXrhwkTJiAyMhKJiYkYOHAgrK2t8ffff2PTpk1YunQpnn766Sqf18fHBwAwZcoUBAUFQalU4plnnim37vz587F79274+/tj/Pjx8PLywpUr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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 52\u001b[0m\n\u001b[1;32m 49\u001b[0m bounds \u001b[38;5;241m=\u001b[39m [(\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m2\u001b[39m\u001b[38;5;241m*\u001b[39mnp\u001b[38;5;241m.\u001b[39mpi) \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m initial_params]\n\u001b[1;32m 51\u001b[0m \u001b[38;5;66;03m# Perform the optimization\u001b[39;00m\n\u001b[0;32m---> 52\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mminimize\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcost_function\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minitial_params\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mshape\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mBFGS\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mmaxiter\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m2000\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 54\u001b[0m plt\u001b[38;5;241m.\u001b[39mshow()\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_minimize.py:726\u001b[0m, in \u001b[0;36mminimize\u001b[0;34m(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)\u001b[0m\n\u001b[1;32m 724\u001b[0m res \u001b[38;5;241m=\u001b[39m _minimize_cg(fun, x0, args, jac, callback, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions)\n\u001b[1;32m 725\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m meth \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbfgs\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[0;32m--> 726\u001b[0m res \u001b[38;5;241m=\u001b[39m \u001b[43m_minimize_bfgs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfun\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mx0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mjac\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallback\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43moptions\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 727\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m meth \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnewton-cg\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[1;32m 728\u001b[0m res \u001b[38;5;241m=\u001b[39m _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback,\n\u001b[1;32m 729\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions)\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_optimize.py:1397\u001b[0m, in \u001b[0;36m_minimize_bfgs\u001b[0;34m(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, finite_diff_rel_step, xrtol, c1, c2, hess_inv0, **unknown_options)\u001b[0m\n\u001b[1;32m 1394\u001b[0m pk \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m-\u001b[39mnp\u001b[38;5;241m.\u001b[39mdot(Hk, gfk)\n\u001b[1;32m 1395\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1396\u001b[0m alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 \u001b[38;5;241m=\u001b[39m \\\n\u001b[0;32m-> 1397\u001b[0m \u001b[43m_line_search_wolfe12\u001b[49m\u001b[43m(\u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmyfprime\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mxk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgfk\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1398\u001b[0m \u001b[43m \u001b[49m\u001b[43mold_fval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mold_old_fval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamin\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1e-100\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1399\u001b[0m \u001b[43m \u001b[49m\u001b[43mamax\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1e100\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mc1\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mc1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mc2\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mc2\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1400\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m _LineSearchError:\n\u001b[1;32m 1401\u001b[0m \u001b[38;5;66;03m# Line search failed to find a better solution.\u001b[39;00m\n\u001b[1;32m 1402\u001b[0m warnflag \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2\u001b[39m\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_optimize.py:1133\u001b[0m, in \u001b[0;36m_line_search_wolfe12\u001b[0;34m(f, fprime, xk, pk, gfk, old_fval, old_old_fval, **kwargs)\u001b[0m\n\u001b[1;32m 1119\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 1120\u001b[0m \u001b[38;5;124;03mSame as line_search_wolfe1, but fall back to line_search_wolfe2 if\u001b[39;00m\n\u001b[1;32m 1121\u001b[0m \u001b[38;5;124;03msuitable step length is not found, and raise an exception if a\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1128\u001b[0m \n\u001b[1;32m 1129\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 1131\u001b[0m extra_condition \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mextra_condition\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m-> 1133\u001b[0m ret \u001b[38;5;241m=\u001b[39m \u001b[43mline_search_wolfe1\u001b[49m\u001b[43m(\u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfprime\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mxk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgfk\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1134\u001b[0m \u001b[43m \u001b[49m\u001b[43mold_fval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mold_old_fval\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1135\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1137\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ret[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m extra_condition \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1138\u001b[0m xp1 \u001b[38;5;241m=\u001b[39m xk \u001b[38;5;241m+\u001b[39m ret[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m*\u001b[39m pk\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_linesearch.py:93\u001b[0m, in \u001b[0;36mline_search_wolfe1\u001b[0;34m(f, fprime, xk, pk, gfk, old_fval, old_old_fval, args, c1, c2, amax, amin, xtol)\u001b[0m\n\u001b[1;32m 89\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m np\u001b[38;5;241m.\u001b[39mdot(gval[\u001b[38;5;241m0\u001b[39m], pk)\n\u001b[1;32m 91\u001b[0m derphi0 \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mdot(gfk, pk)\n\u001b[0;32m---> 93\u001b[0m stp, fval, old_fval \u001b[38;5;241m=\u001b[39m \u001b[43mscalar_search_wolfe1\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 94\u001b[0m \u001b[43m \u001b[49m\u001b[43mphi\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mderphi\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mold_fval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mold_old_fval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mderphi0\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 95\u001b[0m \u001b[43m \u001b[49m\u001b[43mc1\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mc1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mc2\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mc2\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamax\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mamax\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamin\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mamin\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mxtol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mxtol\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m stp, fc[\u001b[38;5;241m0\u001b[39m], gc[\u001b[38;5;241m0\u001b[39m], fval, old_fval, gval[\u001b[38;5;241m0\u001b[39m]\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_linesearch.py:170\u001b[0m, in \u001b[0;36mscalar_search_wolfe1\u001b[0;34m(phi, derphi, phi0, old_phi0, derphi0, c1, c2, amax, amin, xtol)\u001b[0m\n\u001b[1;32m 167\u001b[0m maxiter \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m100\u001b[39m\n\u001b[1;32m 169\u001b[0m dcsrch \u001b[38;5;241m=\u001b[39m DCSRCH(phi, derphi, c1, c2, xtol, amin, amax)\n\u001b[0;32m--> 170\u001b[0m stp, phi1, phi0, task \u001b[38;5;241m=\u001b[39m \u001b[43mdcsrch\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 171\u001b[0m \u001b[43m \u001b[49m\u001b[43malpha1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mphi0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mphi0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mderphi0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mderphi0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmaxiter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmaxiter\u001b[49m\n\u001b[1;32m 172\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 174\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m stp, phi1, phi0\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_dcsrch.py:256\u001b[0m, in \u001b[0;36mDCSRCH.__call__\u001b[0;34m(self, alpha1, phi0, derphi0, maxiter)\u001b[0m\n\u001b[1;32m 254\u001b[0m alpha1 \u001b[38;5;241m=\u001b[39m stp\n\u001b[1;32m 255\u001b[0m phi1 \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mphi(stp)\n\u001b[0;32m--> 256\u001b[0m derphi1 \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mderphi\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstp\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 257\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_linesearch.py:87\u001b[0m, in \u001b[0;36mline_search_wolfe1..derphi\u001b[0;34m(s)\u001b[0m\n\u001b[1;32m 86\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mderphi\u001b[39m(s):\n\u001b[0;32m---> 87\u001b[0m gval[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mfprime\u001b[49m\u001b[43m(\u001b[49m\u001b[43mxk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[43ms\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mpk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 88\u001b[0m gc[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 89\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m np\u001b[38;5;241m.\u001b[39mdot(gval[\u001b[38;5;241m0\u001b[39m], pk)\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_differentiable_functions.py:331\u001b[0m, in \u001b[0;36mScalarFunction.grad\u001b[0;34m(self, x)\u001b[0m\n\u001b[1;32m 329\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m np\u001b[38;5;241m.\u001b[39marray_equal(x, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mx):\n\u001b[1;32m 330\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_update_x(x)\n\u001b[0;32m--> 331\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_update_grad\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 332\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mg\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_differentiable_functions.py:306\u001b[0m, in \u001b[0;36mScalarFunction._update_grad\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 304\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_orig_grad \u001b[38;5;129;01min\u001b[39;00m FD_METHODS:\n\u001b[1;32m 305\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_update_fun()\n\u001b[0;32m--> 306\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mg \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_wrapped_grad\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mf0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mf\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 307\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mg_updated \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_differentiable_functions.py:47\u001b[0m, in \u001b[0;36m_wrapper_grad..wrapped1\u001b[0;34m(x, f0)\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapped1\u001b[39m(x, f0\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[1;32m 46\u001b[0m ncalls[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m---> 47\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mapprox_derivative\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 48\u001b[0m \u001b[43m \u001b[49m\u001b[43mfun\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mf0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mf0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mfinite_diff_options\u001b[49m\n\u001b[1;32m 49\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_numdiff.py:519\u001b[0m, in \u001b[0;36mapprox_derivative\u001b[0;34m(fun, x0, method, rel_step, abs_step, f0, bounds, sparsity, as_linear_operator, args, kwargs)\u001b[0m\n\u001b[1;32m 516\u001b[0m use_one_sided \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 518\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m sparsity \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 519\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_dense_difference\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfun_wrapped\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mx0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mf0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mh\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 520\u001b[0m \u001b[43m \u001b[49m\u001b[43muse_one_sided\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 521\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 522\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m issparse(sparsity) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(sparsity) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m2\u001b[39m:\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_numdiff.py:592\u001b[0m, in \u001b[0;36m_dense_difference\u001b[0;34m(fun, x0, f0, h, use_one_sided, method)\u001b[0m\n\u001b[1;32m 590\u001b[0m x1[i] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m h[i]\n\u001b[1;32m 591\u001b[0m dx \u001b[38;5;241m=\u001b[39m x1[i] \u001b[38;5;241m-\u001b[39m x0[i] \u001b[38;5;66;03m# Recompute dx as exactly representable number.\u001b[39;00m\n\u001b[0;32m--> 592\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43mfun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx1\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;241m-\u001b[39m f0\n\u001b[1;32m 593\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m method \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m3-point\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m use_one_sided[i]:\n\u001b[1;32m 594\u001b[0m x1[i] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m h[i]\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_numdiff.py:470\u001b[0m, in \u001b[0;36mapprox_derivative..fun_wrapped\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 467\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m xp\u001b[38;5;241m.\u001b[39misdtype(x\u001b[38;5;241m.\u001b[39mdtype, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreal floating\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 468\u001b[0m x \u001b[38;5;241m=\u001b[39m xp\u001b[38;5;241m.\u001b[39mastype(x, x0\u001b[38;5;241m.\u001b[39mdtype)\n\u001b[0;32m--> 470\u001b[0m f \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39matleast_1d(\u001b[43mfun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[1;32m 471\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m f\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 472\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`fun` return value has \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 473\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmore than 1 dimension.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/scipy/optimize/_differentiable_functions.py:20\u001b[0m, in \u001b[0;36m_wrapper_fun..wrapped\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 16\u001b[0m ncalls[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 17\u001b[0m \u001b[38;5;66;03m# Send a copy because the user may overwrite it.\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;66;03m# Overwriting results in undefined behaviour because\u001b[39;00m\n\u001b[1;32m 19\u001b[0m \u001b[38;5;66;03m# fun(self.x) will change self.x, with the two no longer linked.\u001b[39;00m\n\u001b[0;32m---> 20\u001b[0m fx \u001b[38;5;241m=\u001b[39m \u001b[43mfun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcopy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 21\u001b[0m \u001b[38;5;66;03m# Make sure the function returns a true scalar\u001b[39;00m\n\u001b[1;32m 22\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m np\u001b[38;5;241m.\u001b[39misscalar(fx):\n", + "Cell \u001b[0;32mIn[11], line 12\u001b[0m, in \u001b[0;36mcost_function\u001b[0;34m(thetas, shape)\u001b[0m\n\u001b[1;32m 9\u001b[0m infidelity \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m \u001b[38;5;241m-\u001b[39m \u001b[38;5;28mabs\u001b[39m(target_state\u001b[38;5;241m.\u001b[39mconj()\u001b[38;5;241m.\u001b[39mT \u001b[38;5;241m@\u001b[39m ansatz\u001b[38;5;241m.\u001b[39mansatz\u001b[38;5;241m.\u001b[39mget_statevector())\n\u001b[1;32m 11\u001b[0m infidelities\u001b[38;5;241m.\u001b[39mappend(infidelity)\n\u001b[0;32m---> 12\u001b[0m \u001b[43mupdate_plot\u001b[49m\u001b[43m(\u001b[49m\u001b[43minfidelities\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m infidelity\n", + "Cell \u001b[0;32mIn[11], line 43\u001b[0m, in \u001b[0;36mupdate_plot\u001b[0;34m(new_data)\u001b[0m\n\u001b[1;32m 41\u001b[0m clear_output(wait\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[1;32m 42\u001b[0m display(fig)\n\u001b[0;32m---> 43\u001b[0m \u001b[43mplt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpause\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m0.1\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/matplotlib/pyplot.py:760\u001b[0m, in \u001b[0;36mpause\u001b[0;34m(interval)\u001b[0m\n\u001b[1;32m 758\u001b[0m canvas\u001b[38;5;241m.\u001b[39mstart_event_loop(interval)\n\u001b[1;32m 759\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 760\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(interval)\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] } ], "source": [ @@ -208,7 +236,7 @@ "def cost_function(thetas, shape) -> complex:\n", " ansatz.thetas = reshape(thetas, shape)\n", "\n", - " infidelity = 1 - target_state.conj().T @ ansatz.ansatz.get_statevector()\n", + " infidelity = 1 - abs(target_state.conj().T @ ansatz.ansatz.get_statevector())\n", "\n", " infidelities.append(infidelity)\n", " update_plot(infidelities)\n", @@ -260,7 +288,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Here's the fidelity." + "Note that we performed the training with the absolute of the probability amplitudes as the image encoding does not require the inner product to be specifically 1+0j. For general state preparation, you need to use\n", + "```py\n", + "def cost_function(thetas, shape) -> complex:\n", + " ansatz.thetas = reshape(thetas, shape)\n", + "\n", + " infidelity = 1 - target_state.conj().T @ ansatz.ansatz.get_statevector()\n", + "\n", + " infidelities.append(infidelity)\n", + " update_plot(infidelities)\n", + "\n", + " return infidelity\n", + "```\n", + "Which will push the fidelity to be exactly 1+0j. However, note that would limit the good parameter space to a very tiny space, whereas for the absolute approach there are many more possible parameter states to choose from. This is how we reach convergence easier compared to a general state. With that being said, pay close attention to the task and what the cost function really needs to do." ] }, { @@ -271,7 +311,7 @@ { "data": { "text/plain": [ - "(0.9184301235740799-0.11993565640369458j)" + "(0.5896664357293144+0.807564869009721j)" ] }, "execution_count": 12, @@ -297,7 +337,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxoAAAGKCAYAAACLuTc4AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFO9JREFUeJzt3X2QVwW9x/HvbxcURNi9wK4WKiM+i5gN2CVIcHyARukK5TUNFCWJIdNpJjNnyoDJFMZLY1Nopg0+hCPyYJp2KRtxLAWRLOdOTTcwddQ0cHkQBRHYc/9w2OtK2h77rgfk9Zphxj2c3f3sb3AP7z27P2pFURQBAACQqK7qAQAAwIeP0AAAANIJDQAAIJ3QAAAA0gkNAAAgndAAAADSCQ0AACCd0AAAANIJDQAAIJ3QAAAA0gkNdlGr1Tr06+GHH/6X39fmzZtj+vTpHX5bDz/8cNRqtVi4cOG//L53Z/Pnz48JEybEEUccEbVaLU4++eSqJwFUyrWpWi0tLXHdddfFiBEjoqmpKRobG2Po0KExf/78qqexG+tS9QB2P3fccUe7l2+//fZ48MEHdzl+zDHH/Mvva/PmzTFjxoyICH+Zfpsbb7wxfve738WJJ54YLS0tVc8BqJxrU7WWLVsW3/zmN+OMM86Ib33rW9GlS5dYtGhRnHvuufGnP/2p7fGCtxMa7GLChAntXl6+fHk8+OCDuxyn89xxxx3Rr1+/qKuri+OOO67qOQCVc22q1sCBA2PVqlXRv3//tmNf/vKX47TTTotZs2bFFVdcET169KhwIbsj3zrF+9La2hrXX399DBw4MLp16xYHHHBATJkyJdavX9/uvJUrV8bo0aOjb9++0b179zj00ENj0qRJERHx7LPPRlNTU0REzJgxo+229/Tp00ttmT59etRqtfjLX/4SEyZMiIaGhmhqaoqrrroqiqKI559/Ps4666zo1atXHHjggTF79ux2r//mm2/Gt7/97Rg8eHA0NDREjx494qSTToqlS5fu8r5aWlri/PPPj169ekVjY2NMnDgxnnrqqajVanHrrbe2O/fPf/5znH322dG7d+/o1q1bDBkyJO67774OfUwHH3xw1NX53xOgDNemzrs2HXrooe0iI+Ktb2cbO3ZsbN26Nf7617+WenzYO7ijwfsyZcqUuPXWW+Oiiy6Kyy67LJ555pn44Q9/GL///e/j0Ucfja5du8aaNWti1KhR0dTUFFdeeWU0NjbGs88+G4sXL46IiKamprjxxhtj6tSpMW7cuPjsZz8bERHHH3/8+9r0+c9/Po455piYOXNmPPDAA3H11VdH796946abbopTTjklZs2aFfPmzYvLL788TjzxxBgxYkRERLz66qtxyy23xHnnnReTJ0+OTZs2xU9+8pMYPXp0rFixIk444YSIeOsC9pnPfCZWrFgRU6dOjaOPPjruvffemDhx4i5b/vjHP8bw4cOjX79+ceWVV0aPHj3i7rvvjrFjx8aiRYti3Lhx7+tjBODduTZ98Neml19+OSIi+vbt+74eHz7kCvgnLrnkkuLtf1R+85vfFBFRzJs3r915S5YsaXf8nnvuKSKieOKJJ971ba9du7aIiGLatGkd2rJ06dIiIooFCxa0HZs2bVoREcWXvvSltmPbt28vDjrooKJWqxUzZ85sO75+/fqie/fuxcSJE9udu3Xr1nbvZ/369cUBBxxQTJo0qe3YokWLiogorr/++rZjO3bsKE455ZQiIoq5c+e2HT/11FOLQYMGFW+88UbbsdbW1mLYsGHFEUcc0aGPdaeBAwcWI0eOLPU6AB92rk1vqeraVBRF0dLSUjQ3NxcnnXRS6ddl7+B7MyhtwYIF0dDQEKeffnq88sorbb8GDx4c+++/f9tt3cbGxoiIuP/++2Pbtm2dvuviiy9u++/6+voYMmRIFEURX/ziF9uONzY2xlFHHdXuFm99fX3ss88+EfHWV4bWrVsX27dvjyFDhsSTTz7Zdt6SJUuia9euMXny5LZjdXV1cckll7TbsW7dunjooYfinHPOiU2bNrU9Pi0tLTF69OhYtWpVvPjii+kfP8DezLXpg702tba2xvjx42PDhg3xgx/8oOMPCHsVoUFpq1atio0bN0Zzc3M0NTW1+/Xaa6/FmjVrIiJi5MiR8bnPfS5mzJgRffv2jbPOOivmzp0bW7du7ZRdhxxySLuXGxoaolu3brvczm1oaNjl+3Vvu+22OP7446Nbt27Rp0+faGpqigceeCA2btzYds5zzz0XH/nIR2K//fZr97qHH354u5dXr14dRVHEVVddtcvjM23atIiItscIgByuTR/stenSSy+NJUuWxC233BIf+9jHOvx67F38jAaltba2RnNzc8ybN+8f/v7OH6Lb+Zziy5cvj5///Ofxy1/+MiZNmhSzZ8+O5cuXx/7775+6q76+vkPHIiKKomj775/+9Kdx4YUXxtixY+PrX/96NDc3R319fVx77bXx9NNPl97R2toaERGXX355jB49+h+e884LAAD/Gtem95Z5bZoxY0bccMMNMXPmzDj//PNLb2HvITQo7bDDDotf//rXMXz48Ojevfs/PX/o0KExdOjQ+O53vxt33nlnjB8/Pu666664+OKLo1arfQCL39vChQtjwIABsXjx4nZ7dn6FZ6f+/fvH0qVLY/Pmze2+crR69ep25w0YMCAiIrp27RqnnXZaJy4HYCfXpg/m2jRnzpyYPn16fPWrX41vfOMb7/vtsHfwrVOUds4558SOHTviO9/5zi6/t3379tiwYUNERKxfv77dV2ciou1ZMnbeot75SXHn61Rh51eW3r718ccfj2XLlrU7b/To0bFt27a4+eab2461trbGnDlz2p3X3NwcJ598ctx0003x0ksv7fL+1q5dmzkfgHBt+iCuTfPnz4/LLrssxo8fH9/73vdKfTzsndzRoLSRI0fGlClT4tprr40//OEPMWrUqOjatWusWrUqFixYEN///vfj7LPPjttuuy1uuOGGGDduXBx22GGxadOmuPnmm6NXr15xxhlnRERE9+7d49hjj4358+fHkUceGb17947jjjvuA/1H6saMGROLFy+OcePGxZlnnhnPPPNM/OhHP4pjjz02Xnvttbbzxo4dG5/4xCfia1/7WqxevTqOPvrouO+++2LdunUREe2+4jRnzpz41Kc+FYMGDYrJkyfHgAED4u9//3ssW7YsXnjhhXjqqafec9MjjzwSjzzySES89cn/9ddfj6uvvjoiIkaMGNH29IcAvMW1qXOvTStWrIgLLrgg+vTpE6eeeuou36I2bNiwtrsm0Kaqp7tiz/HOpxDc6cc//nExePDgonv37kXPnj2LQYMGFVdccUXxt7/9rSiKonjyySeL8847rzjkkEOKfffdt2hubi7GjBlTrFy5st3beeyxx4rBgwcX++yzzz99OsH3egrBtWvXtjt34sSJRY8ePXZ5GyNHjiwGDhzY9nJra2txzTXXFP379y/23Xff4uMf/3hx//33FxMnTiz69+/f7nXXrl1bfOELXyh69uxZNDQ0FBdeeGHx6KOPFhFR3HXXXe3Offrpp4sLLrigOPDAA4uuXbsW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", + "image/png": "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fx6TJ0+O+fPnx/r16+PYY49Nnatr164HdCwioiiK9l//+Mc/jquuuirGjh0bX/va16KhoSG6du0aN910Uzz77LNlz9HW1hYREdddd100NTX923PevgAA+GDspneXuZvmzp0bt99+e8ybNy8mTZpU9iwcPYQGZTv11FPjF7/4RYwcOTJqamre8/zhw4fH8OHD4zvf+U488MADMWHChFiyZElcc801UVVVdRAmfnfLly+PAQMGxMqVK0vm2f8Kz379+/ePNWvWxM6dO0teOdq8eXPJeQMGDIiIiOrq6rj44os7cXIA9rObDs5uWrBgQcyZMye+8pWvxNe//vX3/XU4OvjWKco2bty42Lt3b3z729/u8Ht79uyJV155JSIitm/fXvLqTES0v0vG/kvU+/9Q3H+bStj/ytJbZ/31r38d69atKzmvqakpdu/eHXfddVf7sba2tliwYEHJeQ0NDXHBBRfEwoUL429/+1uH+9u6dWvm+ACE3XQwdtPSpUtjxowZMWHChLj11lvLejwcnVzRoGyNjY0xderUuOmmm+L3v/99jB49Oqqrq2PTpk2xbNmy+N73vheXX3553HfffXH77bdHc3NznHrqqbFjx4646667onfv3nHppZdGRERNTU0MGjQoli5dGh/96EejT58+cdZZZx3Uf6RuzJgxsXLlymhubo5PfepT8dxzz8UPf/jDGDRoULz22mvt540dOzY+8YlPxFe/+tXYvHlznHHGGfHwww/Htm3bIiJKXnFasGBBfPKTn4whQ4bElClTYsCAAfH3v/891q1bF3/5y1/i6aeffteZnnjiiXjiiSciYt8f/v/617/ihhtuiIiIUaNGtb/9IQD72E2du5s2bNgQV155ZRx33HFx0UUXdfgWtREjRrRfNYF2lXq7Kw4fb38Lwf3uvPPOYujQoUVNTU3Rq1evYsiQIcX1119f/PWvfy2KoiieeuqpYvz48cXJJ59cdO/evWhoaCjGjBlTbNy4seTrrF27thg6dGhxzDHHvOfbCb7bWwhu3bq15NyWlpaiZ8+eHb5GY2NjMXjw4PbP29raihtvvLHo379/0b179+LjH/948cgjjxQtLS1F//79S267devW4oorrih69epV1NbWFldddVXx5JNPFhFRLFmypOTcZ599trjyyiuLE044oaiuri769etXjBkzpli+fPk7Pr63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", "text/plain": [ "
" ] @@ -328,7 +368,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For AQC, we often would use a much smaller ansatz so as to justify the training cost. However, for ease in demonstration and better fidelity we used an exact circuit and simply updated the parameters to what Shende's synthesis would have gotten to." + "For AQC, we often would use a much smaller ansatz so as to justify the training cost. However, for ease in demonstration and better fidelity we used an exact circuit and simply updated the parameters to what Shende's synthesis would have gotten to.\n", + "\n", + "It should also be noted that when we attempt a global optimization of the circuit like we did here, we are prone to the **\"orthogonality catastrophe\"**. Orthogonality catastrophe in quantum machine learning refers to a situation where a small change in the parameters of a quantum model causes the quantum state to change drastically, becoming almost completely different (orthogonal) from the original state. This causes an exponential decay in the fidelity measure as the size of the system (number of qubits) increases. That is why for the 6 qubit instance we have 94 fidelity, but for 3 or 4 qubits we can reach 99.999.\n", + "\n", + "This can cause problems during training because:\n", + "- **Vanishing Gradients:** The changes in the cost function become very small, making it hard to update the parameters.\n", + "- **Optimization Instability:** The training process can become unstable and not converge properly.\n", + "\n", + "In Layman terms, the larger the circuit, the harder it is to train when done globally.\n", + "\n", + "To deal with this, techniques like careful parameter initialization, regularization, and adaptive optimization algorithms are used to make the training process smoother and more stable. We can also trade time to run with better convergence by training a batch of parameters at a time instead of all. This means many more runs of the circuit, but mitigates the orthogonality issue." ] }, {