From cb82af6374393085ad959a385d9ba8f4dde3db64 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 12 Jul 2023 12:49:18 +0100 Subject: [PATCH 001/139] update the tutorials --- docs/source/tutorials/QUBO_problem.ipynb | 608 ++++++++++++++++++ .../tutorials/portfolio_optimization.ipynb | 502 +++++++++++++++ 2 files changed, 1110 insertions(+) create mode 100644 docs/source/tutorials/QUBO_problem.ipynb create mode 100644 docs/source/tutorials/portfolio_optimization.ipynb diff --git a/docs/source/tutorials/QUBO_problem.ipynb b/docs/source/tutorials/QUBO_problem.ipynb new file mode 100644 index 00000000..2eb9f49e --- /dev/null +++ b/docs/source/tutorials/QUBO_problem.ipynb @@ -0,0 +1,608 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", + "metadata": {}, + "source": [ + "# Solving portfolio optimization as QUBO problem with QAOA\n", + "\n", + "## Overview\n", + "\n", + "In this tutorial we will demonstrate how to solve quadratic unconstrained binary optimization (QUBO) problems using QAOA.\n", + "\n", + "## QUBO problem\n", + "\n", + "### what is QUBO?\n", + "\n", + "Quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", + "\n", + "From a computational perspective, solving a QUBO problem is generally considered NP-hard. This classification implies that finding the optimal solution to a QUBO instance is believed to be computationally challenging, and there is no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", + "\n", + "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in this [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem solving. QAOA leverages the inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz. The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", + "\n", + "### General Case\n", + "\n", + "For the general QUBO case, we wish to minimize the cost function in the form of\n", + "\n", + "$$ x^T Q x$$\n", + "\n", + "where $x\\in\\{0,1\\}^n$ and $Q\\in\\mathbb{R}^{n\\times n}$ is a real symmetric matrix.\n", + "\n", + "This function maps to an Ising Hamiltonian \n", + "\n", + "$$\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i{n_qubits}}\"\n", + " states.append(a)\n", + "\n", + " # Calculate the probabilities of each state using the circuit's probability method\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + "\n", + " # Sort the states and probabilities in descending order based on the probabilities\n", + " sorted_indices = np.argsort(probs)[::-1]\n", + " if reverse == True:\n", + " sorted_indices = sorted_indices[::-1]\n", + " state_sorted = np.array(states)[sorted_indices]\n", + " prob_sorted = np.array(probs)[sorted_indices]\n", + "\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\tprobability\")\n", + " print(\"-------------------------------------\")\n", + " if wrap == False:\n", + " for i in range(len(states)):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " # Print the sorted states and their corresponding probabilities\n", + " elif wrap == True:\n", + " for i in range(4):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\" ... ...\")\n", + " for i in range(-4, -1):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "da315228", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 10\t |\t 0.8708\n", + " 11\t |\t 0.1251\n", + " 00\t |\t 0.0040\n", + " 01\t |\t 0.0001\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c = QAOA_ansatz_for_Ising(final_params, nlayers, pauli_terms, weights)\n", + "\n", + "print_result_prob(c)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "294ea9ce-5064-4176-94d0-8dbb7d1707f8", + "metadata": {}, + "outputs": [], + "source": [ + "def print_output(c):\n", + " n = c._nqubits\n", + " N = 2**n\n", + "\n", + " # Generate labels for the x-axis representing the binary states\n", + " x_label = r\"$\\left|{0:0\" + str(n) + r\"b}\\right>$\"\n", + " labels = [x_label.format(i) for i in range(N)]\n", + "\n", + " # Create a bar plot with the probabilities of each state\n", + " plt.bar(range(N), c.probability())\n", + "\n", + " # Set the x-axis ticks to the generated labels and rotate them for better visibility\n", + " plt.xticks(range(N), labels, rotation=70)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fc1353ab-7a7a-4cdc-931c-3b90417c4961", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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y/PPP19uv/323tvBXoMePDN8+PAycuTIMnXq1HL66af3+Vp1dXU59dRTy/e+973y+7//+/Z2EM+HPvSh8rWvfa38+Mc/Lt///vc9Z4fwnHrqqeX73/++52zlk74A08+8+Y78X//1Xy+tra3lv//7v8v69etLW1tb+au/+qvygQ98oEREOeecc0pDQ0P6es2R7+1rr71W1q5dW5566qmyYsWK8uEPf7j3ln5tbW2ZPn16+prNwOetXnaZNGnSQeFpBscM9CW1adOmpa91sI2XaY5jp556arz00kvx4IMPxte//vU466yzYsKECTF58uQYN25cPPXUU3H99dfHnj17spdKhfrb2/Hjx8fkyZOjvr4+1qxZEzfccEPs2LEje6lUYPjw4fGXf/mX8dhjj0V7e3t0dnb2+4PSxo0bF52dnQkr5EgNdG8bGhpiy5YtCSsc/NKLyPQ/n/3sZ8vatWsPus13/vnnl3nz5pVXXnml/PM//7M3SQ3CGcjePvzww97cOEjmzbtdn/70p0tPT0/Zs2dP6ezsLF/5ylfKjBkzyrhx48qwYcNKRJQxY8aU1tZWnzEySKaSvT399NPLN7/5TXt7ZJO+AHOI+ZM/+ZOyevXqcsopp/T79Ysuuqh873vfKxdddFH6Wo29NVG+9rWvlaVLl5axY8eWT33qU+X5558vPT095YUXXig333xzmT59ern++uvLa6+9lr5WY2+Ps0lfgDnEXHjhhWX79u3lpptuKmPGjDno69XV1WXdunXl05/+dPpajb090ae2trZ8/vOfL4sWLepz/B3veEdZtmxZ6ezsLLt37y49PT3ltttuKxE+f2KwjL39uUz6AsxhZu7cuaWzs7OsXr26fOQjHylnnnlmqaurK6ecckqZPn162b17d3nXu96Vvk5jb02Us846q5x77rklIkpNTc1BP9X1qquuKj09PeXss89OX6uxt8fZpC/AvMX86q/+avmXf/mXsnfv3rJt27by8MMPl/b29rJ58+Zy1113lYi3/lHW5vgcezt05819q6qq6n1v0KJFi8qPfvQj+zrIx94egz/Tn/0Dx5n6+vq49NJL44EHHoh9+/ZFRMQZZ5wRV1xxRVx88cXx0ksvxZo1a6KtrS12797tJ0EOIvZ2aGpoaIiLL744Hnjggd4PrIuIPh969dnPfja2bdsW999/f58Pu+P4Zm+PPTFynDrvvPPilltuidNOOy3+8z//M1atWhXf+ta3er/uG9TgZW+Hpv+9rxs3bowHHnggnnzyyT7njBgxIn7yk58krZAjZW+PPTFynBs5cmRceeWV8Zu/+ZvxC7/wC9HW1hb/8A//EN/97nezl8bbZG+Hpv+9r6eddlo8+eSTsWrVqnjppZeyl8bbZG+PHTFyHPu//w95/Pjx8Tu/8zvxwQ9+MEaNGhUf+9jH4tVXX01cIUfK3g5N9nXosrfHXvobV0zl8973vjd9DcbeGvtq7O3RGHdGAIBU1dkLAABObGIEAEglRgCAVGIEAEglRgCAVGIEAEglRgCAVGIEAEglRgCAVGIEAEglRgCAVP8PrA8rvOvd1LsAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_output(c)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c48e4a38", + "metadata": {}, + "source": [ + "## Improve the performance with CVaR\n", + "\n", + " Conditional Value-at-Risk (CVaR) is a risk measure that quantifies the potential loss beyond a certain threshold (alpha), considering the tail end of the distribution. In QAOA, incorporating CVaR as an objective function allows for addressing risk-averse optimization problems effectively. By optimizing for CVaR, the algorithm focuses on minimizing the expected value of the worst-case scenario, rather than solely optimizing for the mean or expected value, which usually lead to a faster convergence to a more accurate result.\n", + "\n", + " In order to showcase the performance of CVaR, a more complicated QUBO problem is used. The Q matrix is:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "02ec55b6", + "metadata": {}, + "outputs": [], + "source": [ + "Q = np.array(\n", + " [\n", + " [-60.3657, 11.68835, 12.23445, 11.7274, 11.9959, 11.80955],\n", + " [11.68835, -59.7527, 11.6231, 13.23295, 11.96335, 12.44725],\n", + " [12.23445, 11.6231, -59.69535, 11.29525, 12.00035, 11.78495],\n", + " [11.7274, 13.23295, 11.29525, -59.12165, 12.1006, 12.5461],\n", + " [11.9959, 11.96335, 12.00035, 12.1006, -60.45515, 12.07545],\n", + " [11.80955, 12.44725, 11.78495, 12.5461, 12.07545, -59.9126],\n", + " ]\n", + ")\n", + "pauli_terms, weights, offset = QUBO_to_Ising(Q)" + ] + }, + { + "cell_type": "markdown", + "id": "76879a55", + "metadata": {}, + "source": [ + "Then let's define a function to brutally calculate the costs (classical methods). The results are printed below." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "46e9cbd9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\t cost\n", + "-------------------------------------\n", + " 110010\t |\t-109.2784\n", + " 100011\t |\t-108.9717\n", + " 011010\t |\t-108.7296\n", + " 111000\t |\t-108.7219\n", + " 101100\t |\t-108.6685\n", + " 001110\t |\t-108.4798\n", + " 001011\t |\t-108.3416\n", + " 101001\t |\t-108.3157\n", + " ...\t |\t ...\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "def print_Q_cost(Q, wrap=False, reverse=False):\n", + " n_stocks = len(Q)\n", + " states = []\n", + " for i in range(2**n_stocks):\n", + " a = f\"{bin(i)[2:]:0>{n_stocks}}\"\n", + " n_ones = 0\n", + " for j in a:\n", + " if j == \"1\":\n", + " n_ones += 1\n", + " states.append(a)\n", + "\n", + " cost_dict = {}\n", + " for selection in states:\n", + " x = np.array([int(bit) for bit in selection])\n", + " cost_dict[selection] = np.dot(x, np.dot(Q, x))\n", + " cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1]))\n", + " if reverse == True:\n", + " cost_sorted = dict(\n", + " sorted(cost_dict.items(), key=lambda item: item[1], reverse=True)\n", + " )\n", + " num = 0\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\t cost\")\n", + " print(\"-------------------------------------\")\n", + " for k, v in cost_sorted.items():\n", + " print(\"%10s\\t |\\t%.4f\" % (k, v))\n", + " num += 1\n", + " if (num >= 8) & (wrap == True):\n", + " break\n", + " print(\" ...\\t |\\t ...\")\n", + " print(\"-------------------------------------\")\n", + "\n", + "print_Q_cost(Q, wrap=True)" + ] + }, + { + "cell_type": "markdown", + "id": "04d4ea38", + "metadata": {}, + "source": [ + "The QAOA with CVaR and different alpha will be run and a callback function will be used to record the parameters during the solving prosedure." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "d3b386d6", + "metadata": {}, + "outputs": [], + "source": [ + "# Set the number of layers to 2\n", + "nlayers = 2\n", + "\n", + "# Define a list of alpha values\n", + "alpha_list = [0.1, 0.25, 1]\n", + "\n", + "\n", + "# Define the callback function to record parameter values\n", + "def record_param(xk):\n", + " xk_list.append(xk)\n", + "\n", + "\n", + "# Generate initial parameters randomly for all alpha\n", + "init_params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5)\n", + "\n", + "# Create an empty list to store parameter values for each alpha\n", + "params_list = []\n", + "\n", + "# Iterate over each alpha value\n", + "for alpha in alpha_list:\n", + " # Create a new empty list for callback function\n", + " xk_list = []\n", + "\n", + " # Run the QUBO_QAOA_cvar function with the specified parameters\n", + " final_params = QUBO_QAOA_cvar(\n", + " Q,\n", + " nlayers,\n", + " alpha=alpha,\n", + " callback=record_param,\n", + " maxiter=100,\n", + " init_params=init_params,\n", + " )\n", + "\n", + " # Append the parameter values for the current alpha to the params_list\n", + " params_list.append(xk_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b3da7c48", + "metadata": {}, + "outputs": [], + "source": [ + "best = 50 # Represents the binary number 110010\n", + "prob_list = [] # Create an empty list to store probabilities\n", + "loss_list = [] # Create an empty list to store loss values\n", + "\n", + "# Iterate three times\n", + "for i in range(3):\n", + " c = QAOA_ansatz_for_Ising(init_params, nlayers, pauli_terms, weights)\n", + " loss = [cvar_loss(nlayers, Q, 1000, alpha_list[i], True, init_params)]\n", + " prob = [c.probability()[best].numpy()]\n", + "\n", + " # Iterate 100 times\n", + " for j in range(100):\n", + " if j < len(params_list[i]) - 1:\n", + " params = params_list[i][j]\n", + " else:\n", + " pass\n", + " c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights)\n", + " loss.append(cvar_loss(nlayers, Q, 1000, alpha_list[i], True, params))\n", + " prob.append(c.probability()[best].numpy())\n", + "\n", + " loss_list.append(loss) # Append the loss values to the loss_list\n", + " prob_list.append(prob) # Append the probability values to the prob_list" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "d1f375ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'loss')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkcAAAGwCAYAAACjPMHLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABvQUlEQVR4nO3deXxTVd4/8E/2tGm6UEoLhUJZFZEiCAoubKKojPvgNiPqOCNuo4+OC+LMKC6g/hA3Rh0XwHXcRkdFRUAdRiwqqIiyCZSt0H1vk2a7vz9u7s3N2iRNe5Pyeb9e94Emt8lp1Onn+Z7vOUcDQAARERERAQC0ag+AiIiIKJkwHBEREREpMBwRERERKTAcERERESkwHBEREREpMBwRERERKTAcERERESno1R5AKurXrx+am5vVHgYRERHFwGq14tChQx3ex3AUo379+qG8vFztYRAREVEcCgsLOwxIDEcxkipGhYWFrB4RERGlCKvVivLy8qh+dzMcxam5uZnhiIiIqAdiQzYRERGRAsMRERERkQLDEREREZECe46IiIiSUHp6Onr37g2NRqP2UFKCx+PB4cOH4XK5Ov1aDEdERERJRKPR4KqrrsKUKVPUHkrKsdvtmD9/Pqqrqzv1OgxHRERESeSqq67C5MmT8eabb2L79u0JqYQcCUwmE+bOnYs//vGPWLhwIQRBiPu1GI6IiIiShMViwZQpU/Dmm29i5cqVag8n5bz11lu4/vrrkZWVhYaGhrhfhw3ZRERESSI3NxcAsH37dpVHkpqqqqoAAJmZmZ16HYYjIiKiJCE1X3MqLT5utxsAOt3EznBEREREpMBwRERERKTAcERERESkwHCU5IxGk9pDICIiisr111+PsrIy2Gw2bNiwAePHjw9778iRI/HOO++grKwMgiDg5ptv7saRRsZwlMTOOvMifPzB9zhp4nS1h0JERBTR7Nmz8dhjj+G+++7D2LFjsXnzZqxatQp5eXkh709PT8eePXtw11134fDhw9082si4z1ESKxk9ATqdHsOHj8L60rVqD4eIiFRgTDOr8r4Omz2m+2+99VY8//zzWL58OQBg7ty5OPvss3H11Vfj4YcfDrp/48aN2LhxIwBg0aJFnR5vIjEcJbHMzGwAgF7Pf0xEREciY5oZC7/9QpX3njdhatQByWAwYNy4cVi4cKH8mCAIWLNmDSZOnNhVQ+wynFZLYlmZOQAYjoiIKLn17t0ber0elZWVfo9XVlaioKBApVHFj791k5hcOdLxHxMR0ZHIYbNj3oSpqr33kYq/dZNYVpZYOdLpDSqPhIiI1JIKIaWmpgYulwv5+fl+j+fn56OiokKlUcWP02pJSqfTI8NiBcBpNSIiSm5OpxObNm3C9Om+1dUajQbTp09HaWmpiiOLD3/rJilpSg3gtBoRESW/xx57DCtWrMDGjRvx7bff4pZbboHFYsGyZcsAACtWrEB5eTnuvvtuAGIT98iRIwEARqMRhYWFKCkpQUtLC3bv3q3azwEwHCWtLGU4YuWIiIiS3FtvvYW8vDwsWLAABQUF+PHHHzFz5kxUVVUBAIqKiuDxeOT7+/Xrhx9//FH++vbbb8ftt9+OL7/8ElOnqtNnJeFv3SQl9RsB7DkiIqLUsHTpUixdujTkc4GBZ9++fdBoNN0xrJix5yhJcVqNiIhIHQxHSUra4wjgtBoREVF3YjhKUsrKkY7hiIiIqNswHCUpZc+RXseeIyIiou7CcJSklJUjg4HhiIiIqLswHCUpZc+Rjg3ZRERE3YbhKEllcp8jIiIiVTAcJSn/niOGIyIiou7CcJSkMq3Z8t+5CSQREVH3YThKQlqtjtNqRESUcq6//nqUlZXBZrNhw4YNGD9+fNh7r7nmGqxbtw51dXWoq6vD6tWrg+5ftmwZBEHwuz755JOu/jEYjpKR1Zrp9zWn1YiIKNnNnj0bjz32GO677z6MHTsWmzdvxqpVq5CXlxfy/ilTpuCNN97A1KlTMXHiRBw4cACfffYZ+vXr53ffJ598goKCAvm69NJLu/xnYThKQsp+I4CVIyIiSn633nornn/+eSxfvhzbtm3D3Llz0dbWhquvvjrk/b/73e/wzDPPYPPmzdixYweuueYaaLVaTJ8+3e++9vZ2VFZWyldDQ0OX/yz8rZuElMv4Ae6QTUR0JEtPN6nyvm1t7VHfazAYMG7cOCxcuFB+TBAErFmzBhMnTozqNdLT02EwGFBXV+f3+JQpU1BZWYn6+np8/vnnuOeee4LuSTT+1k1CUr9RY2M9srJyuEM2EdERKj3dhJbWd1R57wzLRVEHpN69e0Ov16OystLv8crKShx11FFRvcbDDz+MQ4cOYc2aNfJjn376Kf7973+jrKwMQ4YMwUMPPYRPPvkEEydOhMfjif6HiRHDURKSptVq66rEcMTKERER9WB33nknLrnkEkyZMgXt7b5A9uabb8p///nnn/HTTz9hz549mDJlCj7//PMuG0+P+a07efJkfPnllyGfGz9+PDZu3AgAOPbYY7F06VKMHz8e1dXVeOqpp/Doo49240g7lumdVqurq8Hg4hEMR0RER6i2tnZkWC5S7b2jVVNTA5fLhfz8fL/H8/PzUVFREfF7b7vtNtx111047bTTsGXLloj3lpWVobq6GkOHDmU4isbXX3+NgoICv8fuv/9+TJ8+XQ5GVqsVn332GdasWYO5c+fi2GOPxUsvvYSGhgY8//zzagw7pCw5HFUD4PEhRERHslhCilqcTic2bdqE6dOn4z//+Q8AQKPRYPr06Xj66afDft/tt9+O+fPn44wzzsCmTZs6fJ/CwkLk5ubi8OHDCRt7KD3mt67T6fSb69Tr9Tj33HPx1FNPyY9dfvnlMBqNuPrqq+F0OrF161aMGTNG7rBPFlnenqO6uhr5Mb3eAJfLqdKIiIiIInvsscewYsUKbNy4Ed9++y1uueUWWCwWLFu2DACwYsUKlJeX4+677wYA3HHHHViwYAEuu+wy7N27V646tbS0oLW1FRaLBX//+9/x7rvvoqKiAkOGDMEjjzyCXbt2YdWqVV36s/SYcBTonHPOQW5urvwPBQAmTpyIdevWwen0hYxVq1bhrrvuQnZ2dsjlgUajESaTb6WA1Wrt0nEDQKai50ii1+sZjoiIKGm99dZbyMvLw4IFC1BQUIAff/wRM2fORFWV+LusqKjIr4n6uuuug8lkwrvvvuv3Ovfeey/uu+8+uN1ujB49GnPmzEF2djYOHTqEzz77DH/961/hcDi69GfpseHoD3/4A1atWoXy8nL5sYKCApSVlfndJ1WbCgoKQoajefPm4d577+3KoQaRKke13mk1gFNrRESU/JYuXYqlS5eGfG7q1Kl+XxcXF0d8LbvdjpkzZyZsbLFI+k0gFy5cGLR1eOA1YsQIv+8pLCzEGWecgRdffDEh75+ZmSlfhYWFnX7NjigbsiVsyiYiIuoeSf8bd/HixVi+fHnEe/bs2eP39VVXXYXa2lp88MEHfo9XVFSE7KSXngvF4XB0efkuUJa8z1Ed3G4XdDo99Dx8loiIqFskfTiqqalBTU1NxzcqXHXVVXj55Zfhcrn8Hi8tLcWDDz7o7d8Rn5sxYwa2b9/eLduRR0Or1cJqzQIgbgLpcnnDEafViIiIukXST6vFatq0aRg8eDBeeOGFoOdef/11OBwOvPjiixg5ciRmz56Nm2++GY899pgKIw0tw5IJrVb8x9LU3CiHOB4hQkRE1D163G/cP/zhD1i/fj127NgR9FxTUxNOP/10LF26FJs2bUJNTQ0WLFiQXMv4vSvVWlqa4Ha74HKLK9TYc0RERNQ9etxv3Msvvzzi81u2bMGpp57aTaOJnXyuWlMDAMDtrRzxfDUiIqLu0eOm1VKdVDlqaqwHAHlajZUjIiKi7sFwlGTkylFzAwDA5WbPERERUXdiOEoy0rlqQZUjrlYjIiLqFgxHSSa450hqyGbPERERUXdgOEoyUs9RY5O3cuSWeo5SNxzNOO1cXHj+FWoPg4iIutApp5yCDz74AOXl5RAEAeeee67aQ4obw1GSybRmAwCavJWjntCQfdstC3Dj9fPl4EdERD2PxWLB5s2bccMNN6g9lE5L3d+4PZRcOfL2HLndqR2OdDo9TCYzAMBisco/FxER9SyffvopPv30U7WHkRCp+Ru3BwsMRy6p5yhFG7KNRpP8d5PRrOJIiIhSk9mcpsr72u02Vd43GaTmb9weLNy0mi5Fe44MBqP8d5PJFOFOIiIKZDan4ZMPf1Tlvc/8zZgjNiCx5yiJaDQaxWq1wIbs1MyxRqMyHLFyREREyS81f+P2UBaLFTqdDoCvcuRO8X2OjH6VI3VKw0REqcput+HM34xR7b2PVKn5G7eHkvqNWltb5F4juecoZStHip4jTqsREcXsSA4paknN37g9lDSlJlWNAMXxISl68KxfzxEbsomIeiyLxYKhQ4fKXxcXF6OkpAR1dXU4cOCAiiOLHcNREpGODpH6jQDFtFoPqBwZWTkiIuqxjj/+eHz55Zfy10uWLAEALF++HFdddZVKo4pPav7G7aGyQlWOUjwcKStHZvYcERH1WP/973+h0WjUHkZCcLVaEskM2OMIUE6rpWY48q8ccVqNiIiSH8NREpErR80N8mOuFD941mDwjdtk5LQaERElP4ajJCL3HCkrRz1otRqn1YiIKBUwHCUReQNIv3DUc/Y5YkM2ERGlAoajJCLtcxSqIVvXAypH3CGbiCgyQRAApO5sgdqkjZSlzzFeDEdJRDpXzW8pv3x8SKr2HHGfIyKiaNXW1gIAjjrqKJVHkpr69OkDAGhqaurU6zCaJhFf5ShEz1GqTquxckREFLXW1lZ8+eWXmD17NgBg+/bt8gwCRWYymTB79mxs374djY2NnXqt1PyN20NF7DlK0RKrX+UoQjhKT7fAZDSjvqG2O4ZFRJS0li1bBgC4+OKLVR5J6rHb7Vi4cGGnp9VS8zduD2RJz5CnzhoVPUfStFrq9hwpw1H4huylT76F3r3z8dtLTuE5QkR0RBMEAS+99BL+9a9/oXfv3j1mY8Wu5na7UVFRkZBKW2r+xu2BrN6qkc3WCqfTIT+e6qvVlJUjY5ieI41Gg0EDxfN4euX0xqHDqXUGDxFRV2hra8P+/fvVHsYRKTV/4/ZAFRUHcfpZxyIjI9Pv8VTfBNJ/n6PQ4Ug53aY3pObPSUREPQdXqyURp9OB+voav8dcKT6t5lc5ChOOzGbf5pDK+4mIiNTAcJTk3Ek0rWYwGDBu7CS/alBHolmtZjan++5nOCIiIpUxHCW5ZFqtNuusi/H/Hl6G2RddHfX3KMNOuGk1ZeUoVacPiYio52A4SnIud/L0HPXJ6wsAyMsriPp7DIrKUbiGbGVo4rQaERGpjeEoyfkqR+qHI4N3Wb4hhqZpo+Jeo9EIrTb4XznltFosr01ERNQVGI6SnO/4EPWn1aSqTix9QYH9SaH6ldiQTUREyYThKMkl0z5HUlUnlgATeG+opuw0hiMiIkoiDEdJTtrnKBmW8ksVo1im+AIrRaEOn/WbVkuC6UMiIjqyMRwlOWmfI71O/dAgVXUMxsRWjjitRkREyYThKMm5k2gpf1w9R4aAnqMQ56v5haMYghcREVFXYDhKclLPUTJMq8mVo1h6jgLCjtmUFnQPp9WIiCiZMBwlOXmfo6RoyI49HElVJql3yhSicsSGbCIiSiYMR0kumfY5MsZTOfLe29zcJL5GiIZsE8MRERElEYajJJdMPUf6OJbyS6vVWlrFcBR6Wk0ZjtQPgUREdGRjOEpy0mo1XRJNq0XbkK3V6qDT6QAALd7KUahpNa5WIyKiZMJwlOTkfY50Omg0GlXHEmvPkXKPo+YW77QaN4EkIqIkx3CU5FxOp/x3tafWYu05UlaYWrzhyBTy+BCuViMiouTBcJTkpGk1ANCpvBFk7JUj30q1NlsrAP/mawmn1YiIKJkwHCU5abUaoH7lSO45inKjRul+p9MBR7sdQLjjQxiOiIgoeTAcJTm3O/nCERDd1gJSz5HD4UC7ox1AuIZs37SanqvViIhIZQxHKUBqylZ7I0hlxSiaCo90j8PpQHuEypGyITuWo0mIiIi6AsNRCvAdIaJeVSVw/6FowpGvctTuC0fmEJtAKlawJcNml0REdGRjOEoBUlO2mtNqgWHIGMX0l7LnKFzlSKfT+702e46IiEhtDEcpQN4lW8VptcDQEnPlyCGGo8B9jswBq9c4rUZERGpjOEoBcs9RElWODFGsWDMqK0d2MRyZA8JRWkA4YkM2ERGpjeEoBchHiKjYjxNY0YmucuRtyHY45MqRKahylO73NafViIhIbQxHKcCVhNNq0Ux/+fcciUv5jQE7ZAdOqzEcERGR2hiOUoDcc5RM02ox9hw5oq0ccbUaERGpjOEoBbjcUs+Rikv5jbGHI2XlyG4PHY7S0sTKkdRXxcoRERGpjeEoBcjTasnUcxTTDtm+1WqBS/mlabXmZvFg2mgavYmIiLoSw1EKSMpptShCTMiz1QIqRyaTNxy1eMMRp9WIiEhlDEcpQN4EMokasmPf5yj02WrSUv6WlsaoX5eIiKgrMRylAN/xIakVjnxnqzlht9sAiDtiK6cHpWm1pmYxHGm1WuhUPkOOiIiObAxHKaCzDdmW9AzMOO1cpKdb4h5DYM9RNEv5ffsc+VarAYBJsZxfWq3W3NQoPxZ4jhsREVF3YjhKAZ09PuTCC+bg7jsfwfnn/T7uMQTuXB3VtJqi58jpdMLj8YiPK/qO5IbsFmU44tQaERGph+EoBbg62ZBdkF8IAOiT1zfuMXS25wgA2tvFqTVziHDU2toihyeGIyIiUhPDUQrwHR8SXzjKyMgEAFgsGXGPIZ7jQ5Sr1QDIu2QrV6yleafV7PY2+T6uWCMiIjUxHKUAt3TwbJzTar5wZI17DAmpHHn7jkJNq9ntNl84YuWIiIhUxHCUAjq7CaTVKoajjASGo1jPVgMUlSO/hmxlOPKGQDZkExGRihiOUkDCptXS459Wi2cTSN9qNSkceXuOFIfNSqvVbIpptWiCFxERUVdhOEoBLmfnptWsGVkAEjutFk0VK7hy5J1WU1aOvFNsnFYjIqJkwXCUAuQdsuOoHGm1OrkRuzPhyOid6nJ7xxLdPkfeniOnOJ3mcAQ3ZEtVpPZ2G5wu9Q/YJSIi6lHhaNiwYXj//fdRXV2NxsZG/O9//8OUKVP87hkwYAA++ugjtLa2orKyEo888gh0Op06A46SS27Ijj00SFNqgLhaTauN7x+5VM1pbW3x+zqa75Gm1aRdspWHz/qm1XyVIyMPnyUiIhX1qHD00UcfQa/XY9q0aRg3bhw2b96Mjz76CPn5+QDEoylWrlwJo9GISZMmYc6cObjyyiuxYMEClUceWWeOD5GasSVpafHtki31GLW1SeGo46AWtnJkDrFazWaTpw85rUZERGrqMeEoNzcXw4cPx6JFi7Blyxbs2rULd911FywWC0aNGgUAOP300zFy5Ej87ne/w+bNm/Hpp5/ir3/9K2644YakPrLC3YlpNWuGfziKd8WaXDlqa/X7OprvcTr8e478K0fSarU2OLyVI06rERGRmnpMOKqtrcX27dtxxRVXID09HTqdDtdeey0qKyuxadMmAMDEiROxZcsWVFVVyd+3atUqZGVl4Zhjjgn5ukajEVar1e/qbq5OHB9itWb5fR1v35EUdOTKUSyr1ZzSPkf+PUcajQZpadImkDauViMioqTQo44/P+200/D++++jubkZHo8HVVVVmDlzJhoaGgAABQUFqKys9Pse6euCgoKQrzlv3jzce++9XTnsDrk60aicEVA5ineXbKNcOWrx+zqa75ErR1LPkTccKRuzbXab/HNyWo2IiNSU9JWjhQsXQhCEiNeIESMAAEuXLkVVVRVOOeUUTJgwAe+//z4+/PDDsMEn2vfPzMyUr8LCwkT9aFHrzD5H0jJ+SacrRzE0ZPt6jrzhyLtDthSKlPsdtbfbfNNqSTzFSUREPV/SV44WL16M5cuXR7xnz549mDZtGmbNmoWcnBw0NzcDAG644QbMmDEDc+bMwcMPP4yKigpMmDDB73ulZu2KioqQr+1wOOTVVmpxd2JaLSPDPwx1tueozRZdz5FWq4POO15fz5H/Dtlms29KTRAETqsREVFSSPpwVFNTg5qamg7vS08Xf9FKJ7tLPB6PvHy9tLQU8+fPR15eHqqrqwEAM2bMQGNjI7Zu3ZrgkSeO7/iQJKgctUVXOVIux/f1HPmfrabcABIAV6sREVFSSPpptWiVlpaivr4eK1aswOjRozFs2DA88sgjKC4uxsqVKwEAn332GbZu3YpXXnkFo0ePxumnn44HHngAS5cuVb06FInLLYYGXTw9R9YE9xxFOa2mfF4+PsQuhiNzwLSa3XusiJOr1YiIKAn0mHBUW1uLmTNnIiMjA59//jk2btyIk08+Geeeey5++uknAGIVadasWXC73SgtLcWrr76Kl19+GX/7299UHn1knZlWk5bySwElYZWjDgKM1G/kdrvg8bgBhKgcKabVAF9vEitHRESkpqSfVovFpk2bMHPmzIj37N+/H2effXY3jSgxOjWt5l3KX1lVjgH9ixMQjqLrOQrcHRsAHAH7HPn2OPJOq8mr1Vg5IiIi9fSYylFP1pmz1aSl/BWV5eLXcU6rSfsatUa5z1HgHkcAYJfCkUmsKqUpNoAEwINniYgoKTAcpYDO7HMkNWRXVojhKP7KkfjebVHucyTvju1tsgYUO2SbxFAUNK3mYDgiIiL1MRylALnnKJ5wZPWvHMUbjgIbsqWeorD3S3scOXyVI/lsNZO0lD/MtBobsomISEUMRylAnlaLsSFbq9X6ptXkylF802pSMJMqR8rHQpF3x3b6eo4Cz1aTwpGN02pERJREGI5SgNSQHesO2coqUWXVoaDHoqXRaBQHz/rCUaQQE6py5Os5Cr1azSlVjqI4t42IiKirMBylgHhXq0m7YdvtNjQ01AGILxwpK0TSajUgcjgyhKgcOYLCkf8mkNJO2pxWIyIiNTEcpQC3dxPIWKfVpGX8zS1NaG0Vj1RJT7NAo9HE9DpGvw0d7XB7p/mMEZbcGw3BlaPgs9UCKkecViMioiTAcJQCfNNqsVVUpH6jluZGtHjDkVarRXqaJabXUU5zOZ3OqFaVSd+jrBzZvTtkA+K0W2BDtjytxnBEREQqYjhKAa44d8hWVo6cTkfcu2QHTpHJx3xE6jkKtQmkwxeOzKa04HAkV444rUZEROphOEoB8W4CKR0d0tzSBADy1Fr84cjp/VMMMZGm1UJVjjwej+97TSZuAklEREmJ4SgFuOVNIGNsyPZWjlqaGwEArW3xhaPAZfnRhJhQPUcA0C7vdWQO0XPE40OIiEh9DEcpQOrF0eliCw3BlSNxGX6sR4jI56R5Q5HD2XFvkMHo/z2Sdm8QMhnNin2O/KfV9HpWjoiISD0MRykg3qX8cjiSKkednlZLYOXIbFb0HPlPq0WariMiIupqDEcpQDo+RKvVQquN/h+Z1JDd4q0ctSQ4HEU6Xy3UDtmAYq8jY4hpNa5WIyKiJMBwlAJcbt/hrboYVqxlhG3Ijm1azWgMUzmKsJO19D3K1WqAcpdsE8ymgE0g5VVwrBwREZF6GI5SgDStBsR2+GxG0LSa2HMUd+XIEf20WqgdsgHF+WrKpfzt/jtkR6pIERERdTWGoxTgH46irxxJPUctAZWjjDjDkUOuHHU8/RXqbDXxazEcWdIz5O8PnFaLJQASERElGsNRCvB43PLfY9kIMsMaOhx1R89R+MqRGJYyM7Plx0LtcxTrESdERESJwnCUIqTgoIuycqTRaJBhCb2UP+aeo3hWq4WpHLV7p9Cys3oBANxul1yJcjl9vVWsHhERkVoYjlKEbzl/dKEhPc0CnU4HwNdzlOjVapHG0lHlKCsrB4BvjyPAf08kbgRJRERqYThKEW53bOerSbtjOxztcvUm/mk1Mag45U0go1mtFm6fI7HnKNMbjuyKcORy+SpHXM5PRERqYThKEbFuBBm4ASQQ/1L+4IbsaHqODH7fI5ErR96eI6nfCAAEQZADEsMRERGpheEoRUiHz0bbcyRtACn1GwHK40MSc/BsdD1HgeHI23OULfYcKStHfq/NniMiIlIJw1GKkCoq+ijPVwtcxg/4eo7S0zNiWg0WdhPIOHbIlvY5ysoMnlYDopuyIyIi6koMRynCHeO0mrSMP9S0mlarRVpaetTvHbgJpFQNinzwbLh9jsSvpcqWTTGtBvhWrHFajYiI1MJwlCKkabXoe46Cp9Ucjna5khNLU7a0Ki2WnqNwlaPASlG73e73NafViIhIbQxHKSLWpfwZGWL4aVFUjoD4jhAJDDrRNE2HX63m/3XwtBorR0REpC6GoxThlo/WiL9yBMR3hEi4fY4i7UUUbp8jR7t/pcgeOK3m6njKjoiIqCsxHKUIeVotyoZsX89R6HAUy3L+wKDjiGq1mnf5f5h9jiS2oNVqUuWI02pERKQOhqMUIU2rRb2U31s5amn1D0ctcUyrBVeOvAEmzIoyrVar6FNy+j1ntwdWjsIs5WfliIiIVMJwlCLi3QSyJWzlKIZwZAzYBNIRuWlaGWyCV6tFnlaTgxcbsomISCUMRynC7Zb2OYpxKX9LQEN2W+zhSGrIdkW5CaTy8XBnq0lYOSIiomTDcJQiYl2tJjdkB1WOpF2yu67nSFqp5na75TPhJPZ2/zAUFI54fAgREamM4ShFxNxzFK5yFM+0Woxnq4VbqQYEr1YL3AQympVwREREXYnhKEW45dVqHYejtDQLdN77WloCG7K94Sg9EUv5I1eOAvuNgOB9jtoDwpIzit23iYiIuhLDUYqQGpWjaciWmrGdTkfQtFUilvJ3NPVl9FZ9QlWOAsNQ8D5HnFYjIiJ1MRylCJe3IVsXRc9RRoY0pdYU9Fx8O2T7h52Oqju+ylGIabWAylHgPkfS1F20vVVERESJxnCUIuSDZ6OYVpP6jQKX8QOd2yE7sOco3D5HkXqOAP8mbLst9Go1Y5jXJiIi6moMRykiloNnfZWjxqDnEjKt1kFDtlw5cgb3HAH+u2QHTavxbDUiIlIZw1GKiGUTSKs19LlqQCd3yHb4L+WXQlBH9wdyKPY6Cj54ltNqRESkLoajFCEv5Y/ibLVwu2MDvspRenr0lSNpiiuwcgSEDjEdVY6Uex0Fn60WuSpFRETU1RiOUoS8Q3ZU02qhz1UDfOFIp9MhLc3S4WtptVp5WwBHwA7Z4niCw1Fgj1IgZeWoPWBTSK5WIyIitTEcpYjYptW8PUchKkft7XY5gETTdxTqKBBlOApV4ZEqTaFWqwG+niO73QZBEPyek15bz00giYhIJQxHKcIVy2o16eiQEA3ZgPIIkY77jkKFI4/HI29KGWrFmrHD1WpiOArc8wjo+GgSIiKirsZwlCKk1WrRHB+SEWEpP6DYJTvGcCRVnABfVShUiDFE2CFbfFwMRYFHhwC+1WrsOSIiIrXEFY6uuOIKnHXWWfLXDz/8MOrr67F+/XoUFRUlbHDk4/YGE30MDdnhK0fRhyMppAQGnUi9QR1VjqSKUeBKNeX3cLUaERGpJa5wdPfdd8Pm3bzvxBNPxA033IA77rgDNTU1WLJkSUIHSKJYeo7kfY7CVI58u2R33HMk9f4ENlf7VpVFWK0WpnIkna8WMhyxIZuIiFQW3RHvAQYMGIBdu3YBAM477zy8++67eP7557F+/Xp8+eWXiRwfecUyrSYv5e+gchRLz1HgnkWReoM62iG73RuKAjeAVH6PgQ3ZRESkkrgqRy0tLcjNzQUAnH766Vi9ejUAsdE2LS0tcaMjWSzHh0hL+cNXjmKfVgsMOs4I4ahTlSM2ZBMRkcriqhytXr0aL7zwAn744QcMHz4cH3/8MQDgmGOOwd69exM5PvKSenw66sUxmczyUvpQO2QDsR0hEq4KFCnE+L7HGfQc0FHPEafViIhIXXFVjm644QaUlpYiLy8PF154Ierq6gAA48aNwxtvvJHQAZIo2rPVpCk1l8sJm6015D2xHCESPhyFX1Xm2+coTOWoPfxqNTl0sSGbiIhUElflqLGxETfddFPQ4/fee29nx0Nh+BqyI4cGqzUbANDUHLrfCIhtWi3cbtdyiAmxz1FHPUdfl67FpInT8PkXK4Oe47QaERGpLa7K0RlnnIGTTjpJ/vr666/HDz/8gNdeew3Z2dmJGhspuKNcrZaZKfUbJSYches5kvY5Cnm2miFyz9HuPTtw3Y0XYeOm9UHPcVqNiIjUFlc4evTRR5GZKU7fjBo1CosXL8bHH3+M4uJiPPbYYwkdIIlc0tlqHTRkW63RhCNph+zO9xyFmlaTqknhzlaLhKvViIhIbXFNqxUXF2Pr1q0AgAsvvBAfffQR5s+fj+OOO05uzqbEkqbVdB1Mq2V6p9UihqO2GKbVjHGsVuugchQJp9WIiEhtcVWOHA4H0tPTAQCnnXYaPvvsMwBAXV2dXFGixIp2E8hoKkfy8SHp0fQciWEscOVZxB2ywwSqaHATSCIiUltclaOvvvoKjz32GNavX48JEybg4osvBgAMHz4cBw8eTOgASSQd9BrttFp0DdkdT6uF7TmKWDmSVqvFP62m1Wqh1erg8bhjfg0iIqLOiKtydOONN8LlcuGiiy7Cddddh0OHDgEAzjzzTHz66acJHSCJpEpNRztkZ8bQcxTbPkf+laPOrFaLRPk9xhCvTURE1NXiqhwdOHAAv/nNb4Iev/XWWzs9IAot6qX8mdkAgKbmhrD3NDU1wO12Q6fT4+ijRmPb9p/C3htPQ3ZHO2RHogxhBoMx5EaRREREXSmuyhEgTntccMEFmD9/PubPn4/zzjsPWm3cL0cdkHfI7mBaTa4cNYWvHDmdDny25n0AwPVz50V8vbD7HDniP1stErfbBY/HA6DjIEhERNQV4kozQ4YMwbZt2/Dyyy/jggsuwAUXXIBXX30Vv/zyCwYPHpzoMRJib8iO1HMEAC8uexw2WytGHTMWU6ecFfa+cEEnYs9RJypHgC8IhqpKERERdbW4wtGTTz6J3bt3Y8CAARg3bhzGjRuHoqIilJWV4cknn0z0GAm+40N0Ue9z1BDxvtraKrz+r+cBANf+8XY50ASK5+DZcNWmaEUKXkRERF0trnA0efJk3HHHHaivr5cfq6urw1133YXJkycnbHDk4zt4tqNptWwAHVeOAOCtd15CZdUh5Pfph9kXXR3yng73OQq1Q3YHZ6t1RJqy03MjSCIiUkFc4ai9vR1Wa/AeORkZGXEt36aOSceHRKqm6HR6pKdbAERerSZxONrx3POPAgAuu+SPyM3tE3RPh2erBYxHo9F0qucI4LQaERGpK65w9NFHH+Gf//wnJkyYID92wgkn4Nlnn8UHH3yQsMGRjzStBgBarS7kPVaruAGnx+OR9zLqyBdffoyff/keaWkW/OGqW4Kel4OOI0w4ClhurwxL8QZlKYixIZuIiNQQVzj685//jN27d6O0tBR2ux12ux1ff/01du3ahVtuuSXBQyTA15ANhJ9as3qn1FpamuQVX9H4x7MLAQBnnnEhhg87xu+58D1HoXeyVn4db+WIR4gQEZGa4trnqLGxEeeddx6GDBmCo48+GgCwbds27N69O6GDIx9pqgkQw1Gofp5oNoAMZdv2n/D5FysxberZOG36Odj56y/ycx3vc+Rf3ZEauz0ej9+YYyFPq3ETSCIiUkHU4Wjx4sURn586dar899tuuy3+EVFIbsW0ml4Xerop2mX8oWzdthnTpp6N3gF9Rx2Fo8DqTrhKUyzkhmxOqxERkQqiDkfHHXdcVPcJghD3YDrruOOOw8MPP4zx48fD7Xbj3Xffxa233orW1lb5ngEDBuCZZ57B1KlT0dLSghUrVmDevHlwu5P7DC+PxwOPxwOtVhv2CBGpctTSEns4qquvBgDk5OT6PS4FlMCG7HDL7Tu7x1Gk1yYiIuoOUYejadOmdeU4Oq1v375Ys2YN3nzzTdx4443IzMzE448/juXLl+O3v/0tAHFX75UrV6KiogKTJk1C37598fLLL8PpdGL+/Pkq/wQdc7lcMBqNHfYcxVM5qq+vBQDk5PT2e9wYdil/5J6jzlSOuFqNiIjUFFfPUTKaNWsWnE4nbrjhBrl6NXfuXGzZsgVDhgzB7t27cfrpp2PkyJE47bTTUFVVhc2bN+Ovf/0rHn74Ydx7771Bh6sCYjgwmXwbJIbawqC7uN1OAMawR4hkZsbXcwT4Kke9AsJRrGerdXaPI+Vrc58jIiJSQ485DM1kMsHhcPhN69ls4qGlJ598MgBg4sSJ2LJlC6qqquR7Vq1ahaysLBxzjP8qLcm8efPQ1NQkX+Xl5V34U0TW0eGzcs9RhHPVwpEqR1ZrFgyKUCL9PdqeI9++SPE1Y4vfy2k1IiJST48JR59//jkKCgrwl7/8BQaDAdnZ2Vi0aBEAccoNAAoKClBZWen3fdLXBQUFIV934cKFyMzMlK/CwsIu/Ckik8JRRz1HHR0dEkpzc6MceHKyfdUjOew4/MNORz1Hzk5UjlxOTqsREZF6kj4cLVy4EIIgRLxGjBiBrVu3Ys6cObjtttvQ1taGiooKlJWVoaKiIqY9fwI5HA40Nzf7XWqRNoIMN60m9RzFM60GhO47CjutFuaIj86eq6Z8L65WIyIiNSR9z9HixYuxfPnyiPfs2bMHAPDGG2/gjTfeQJ8+fdDa2gpBEHDrrbfKz1dUVPjt6g0A+fn58nPJzt3B+WqdWcoPAPUNtejTpy969fKFo3BL88M1TSditZrTFbrZO5SCgv6orCxXdZUkERH1LEkfjmpqalBTUxPT90g9RVdddRXsdjtWr14NACgtLcX8+fORl5eH6mqxAXnGjBlobGzE1q1bEzvwLiBXjsJUVOLdBFJSVxe8nD9c5ajDabUEVI46CkcnTZyOBxb8A6+89gxeWv543O9HRESklPThKBY33HADvv76a7S0tGDGjBl49NFHcdddd6GxUQwLn332GbZu3YpXXnkFd9xxBwoKCvDAAw9g6dKlKXFgrtxzFHZaTaocNcT1+tK0Wq+cPPmxWA+eNRoSt1rN0MFqtWHDRop/Dj067vciIiIK1KPC0YQJE3DfffchIyMD27dvx7XXXotXX31Vft7j8WDWrFl45plnUFpaitbWVqxYsQJ/+9vfVBx19NzecBQqNGg0GmRkiAfPNsexWg0IvRFkR0v5tVotdDq9vIN3uH2RYhFuD6VAUm9UdnZuxPuIiIhi0aPC0Zw5czq8Z//+/Tj77LO7YTSJF6kh22KxQqsV++ubW5rien1f5UgMHVqtDjqdTnzvgKX5yvBjMBjlcORb3ZaAabUOGrKzs3v5/UlERJQISb9ajXykJuhQS/mlfqO2tta4D3ytqxN7u6SKjPLg16DjQxThR9mU3Z09R1KIC9y4koiIqDMYjlJIpE0gfUeHNMT9+vUN/uFIGU4Cw47H45bPozMoQpTFIu4gbrO3xT2OaFerSRUjo9GE9HRL3O9HRESkxHCUQtwRptU6c3SIRKocSUv5pXDi8Xjk91YKVeHJ79MPAFBZGf9O4tE2ZCs3q2TfERERJQrDUQrxVY6Cw5FVXsYfX78RANTVi+Eow2KF0Wjq8BDZkOEoXwpHh+Ieh7TBZKTKkdFogsWSIX+dw3BEREQJwnCUQpxR9BzFc3SIpLW1WV6Cn5PTO+wGkPJ45MNnfRWegnzxeJWKTlSOXFFMqwWGIeUKOyIios5gOEoh8g7ZuvA9R52ZVgN81aNeObkdHgXilHfsFu8zGIzIze0DAKjoROXIEcXxIYHTaKwcERFRojAcpZBoptXiPTpEotwIMtZpNanfyGZrRVNTfdxjkCtSxkiVI//l++w5IiKiRGE4SiHSPkeRp9USUznKUVSOwoYjhxRixApPIvqNAN+eShGn1QKW73OvIyIiShSGoxQi7ZAdarVaZ48OkdTX+5bzS6HHGWZDx8DKUSL6jYBop9X8wxD3OiIiokRhOEohLrnHJzg0ZGZmA0hA5UixnL+jylHg4bP53nDU6cpRNA3Z3jBUUXEQACtHRESUOAxHKUQ+PiRSz1Gc56pJ5I0gs6NoyA6Y/kpU5SjUKrhAUgP2nrKdANhzREREicNwlEKkhmxdhGm1xFWO8uSzzZzO0MeR+EKMVDnq/AaQgGJaLWLlSAxDZXt/Fb9mOCIiogRhOEoh7kir1TIyASSy5yiKhuwu6jnyNWR3vJS/zFs5ysrKCRkaiYiIYsVwlEJc7tA9R2ZzuhxQErfPUWxL+fV6Q0L2OFK+rjGKytG+/bvlM96ysnI69b5EREQAw1FKcYVZrSYt43c42tHebu/Ue0iVo/R0izxVF01Ddl7vfOh0OrS32+XXiFdHq9W0Wi2yMsUgVFtXjcbGOgDBex8RERHFg+EohYTb58iamZgNIAGgra1VDlh9+vQFEL4hW57+MhoTtlIN8F+tptFogp7PzMyGTqeDx+NBY2M96hvEcMSmbCIiSgSGoxQSrucoUzo6pKkhIe8jNWX38e543eG0mt6AggJvOKrqXL8R4L+vUqj+KikENTU1wONxo6FB3NU7cGNIIiKieDAcpRBXmLPV5JVqLU0JeR9pOX9BB+FIOa0mHR1SUdH5cKSsVIXa66iXt99ICkVyOOK0GhERJQCX96SQcPscJeroEImvciROq0WzQ3avXmLVprIqcdNq0msDrX7PS5WjOu85cNKfnFYjIqJEYOUohbjD7HOUqKNDJFJDtfS64TeB9K0qy+/jXcafgMqRIAi+vqMQTdk52WIQC64cMRwREVHnMRylEFdHPUeJqhwFrDaLZim/tMdRIipHga8dKCdHnD7zhSPvarUchiMiIuo8hqMUEm5aLZGr1QCg3jtNJemo58hkNiMvLx+A76yzznIqVsIFkipHdd5wVN/AaTUiIkochqMUIk016cI1ZHfyXDVJXX2139cdVY76FvSHXm+A0+lAbV11yHtjpVwJF0g6ZLbBG+KkaUAePktERInAcJRCpJ6jwGM1fA3ZDQl5n6DKkSvM2WreRu0B/YsBAFVVhyEIQkLG4HT5H2qrJC3Zr5crR9ImkKwcERFR5zEcpRB5Wi2oITsbQOKm1eoCqj8drVaTKleJ6jdSvnbIcOStEEnhSNoh22QyIz3dkrAxEBHRkYnhKIVIDdlBO2R7D51NXEN2dD1HgRWlRKxUC3zPUIfPypUj7zjtdhtsNnG5P/uOiIiosxiOUoi8CWRgOLImtiHbbm+DzdYmf91Rz5EkkZUj+WiSgMpRWpoFJpMZgG+1GuALdJxaIyKizmI4SiFueVrNV00xGIxIS0sHkLjjQwD/5fwd7XMkSdRKNeV7BoYjabm+zdYKu90mP94gr1hjUzYREXUOw1EKkZa3K6fVpKqR2+1Ca1tLwt6rXhGOpPcNHk/XVY7kpfwBq9WkypDUhC2R9jrqxfPViIiokxiOUkiofY58K9USc66apM4vHIXZ58jRdT1HLlfkylF9wEaV3OuIiIgSheEohbjlg2eDK0eJ6jeSKJfzR9Nz5Ha7UF1TmbD3d3grR3pD6MpRQ0DlqL6e02pERJQYDEcpxHd8iC8wSEeHtLQkNhwpl/NH03NUXV0Bj8edsPdXntum5Fup5l854vlqRESUKAxHKUSaVvPrOUrw0SGSesVKsI72OQIS228EhF+tli3vcRRQOZLCEc9XIyKiTmI4SiFy5SjEtFqijg6RKCtHHZ2tBiS230j5nvrAhmxv5Ui5jF/8WgxL7DkiIqLO0nd8CyULt3ykhgEzz7gARQMG44QJpwJI3NEhkmh6jlyKTSATXTkKu5RfqhwFNmR7v+a0GhERdRbDUQqRp9V0etz5l4V+z+3bvyeh7xXVPkeOrqscScHLaAwMR9K5aqGn1bKycqDV6hLa/0REREcWhqMU0tBQh/Vfr8WwoSOx/8AeHDhYhv0H9qCsbCc2//RdQt+rvr4GbrcbGo3Gb7NFJYdfz1GCp9UcoafVssNUjpqbG+F2u6HT6ZCd3SvofDgiIqJoMRylmHv+fn23vE97ux2PP3kvjEaTfG5ZIGdX9hy5ghuy9XoDMjOzAQRXjjweDxqb6tErpzdyGI6IiKgTGI4orI8+fivi8263C6s+ew8Z1iwcTuDRIUDopfzZWTny+4bqsaqvr0WvnN5syiYiok5hOKJOWfToXV3yulK1asCAwfJj2YoNIAVBCPoe7nVERESJwKX8lJT+99VqOJ0OlIwej7HHnQhAsQFkwDJ+SQP3OiIiogRgOKKkVFl1CB+ufBMA8Ier/g+AYhl/mHBUn+C9jgKbwQOd+5vLcPutDwZtN0BERKmN4YiS1quvPwu73YaRR4/BxBOnKo4OCROOErjX0cIHnsObr3+JvLyCkM/37p2PG6+/G2edeREmnzqz0+9HRETJg+GIklZ9fQ3efe9lAMAfrrwFvXqF3h1b4tslu3OHz+bnF+LEE6agV05vXDL7mpD3XHjeFXJl6bRpv+nU+xERUXJhOKKk9ubbL6KlpQlDhhyFGdPPBRChciT3HPXu1HuePOk0+e+zzpod9HppaRbMOnu2/PXx4yZ1OpAREVHyYDiipNbc3Ih/vf0iAF+jdUcN2Z0NKiefNB2AuEu30WjC7Auv8nv+rJkXIiMjE/sPlGH7ji3Q6fSYMvnMTr1noJLR4+Vz84iIqHsxHFHSe/ffL/tVi8JVjurqO7+UPysrB8eOOh4AsPSZhwAA5/zmUjmoaLU6XHj+HADAO/9ejjVrPwCQ2Km1U06egccXv4pnnnqb2xIQEamA4YiSnt3ehtfeeE7+OlzPUWOj2HNkMpmRlmaJ670mnjgVOp0OO3/9Be9/8Dp27d6G9HQLLjjv9wDE4NK3b380Ntbjs9Xv4/MvP4bb7cYxI49Dv74D4nrPQNJ7FRYOxKIH/xn3z0JERPFhOKKU8MFHb2Df/t1oamrAwfK9Ie+x221obW0BAJw44dS43kfqN1r/9VoAwGuvi6HsgvN+j/R0C2ZfJE6x/efD19Hebkd9fQ2+/7EUADA9AdWjgUVDMKbkBLjdbjQ01GH48FFY8PenOtxWgIiIEofhiFKC0+nAdTf+FpfPmYG2ttBnvQHARx+LeyPdfttDGDZ0ZEzvYTan4fhxJwEQN6EEgHVfrcL+/XuQmZmNO29fhJFHj4HD0Y73//Oa/H1r134IILqptRHDj8Ubr36O318e+oy8c2ZdAgAo3fAF7pz/R9hsrTh+3Em4645F0Gg0Mf08REQUH4YjShk2WytaWpoi3vPPFxbj2+/+h7S0dDx4/7PIze0T9euPP/5kmExmlB/aj7K9OwGIB9q+/i+xenTqyacDAFav/cCvKfx/61ejvd2OoqLBEQNZRkYm7v3r4yjIL8Sc39+IwcUj/J43m9Nw+ozzAIiVsp07f8bf7rsJLpcT06fOwvVz50X9sxARUfwYjqhH8XjcWPDALdi7bxfyeufjwQXPwGQyR/W9J580AwDw1frVfo+v+fwjHD7sO1j3nXeX+z3f1taKr0s/BwCcNj189ejOvyxEQUF/AIBOp8Ofb7zH7/lpU85GRkYmyg/tx8ZN6wEAGzetx6JHxPPrLrpgDq6+8paofhYiIoofwxH1OK1tLZj/17lobKzHiOGjcNcdD2Ng0RBMnzoL115zOx5Z9CLuvvNRv5VgOp0eE0+YAgD4av1av9dzu1149Y1nAADrSz/H3n27gt5zzefi1Nq0qbOg1Qb/Z3Xh+Vfg5JNOg8PhwF/vvQF2uw0loydg6pSz5HvO+c2lAICPVr7pd7Du2i8+wpNP3w8A+P3l1+HKK26K52MhIqIo6dUeAFFXOHT4AP567w1Y/MhyTDl1JqaEOOJj5NEluGPeH3Do8AF5X6H6+lps3fZD0L0ff/IODh7ci127t4V8v2+/+x8am+rRO7cPxpRMwPc/bJCfGzH8WFz7x9sBAM/8cxG+Wr8Gb7z5PK6a82dc96c7UbrhSwwsGoIRw0fB4XDgk1XvBr3+e/95FTqdDjdcdzfm/P5GeDwevPzqUr97igcNR0FBIbZu+xGNjfV+z2k0Gow+9nhMnzoLhYUDsW37T9j807fY8vP3sNvbAIgBcUD/QSgeNAyZmTnYu28Xdu/ZHjSVaTAYUdivCJmZ2aitq0Z1dQUcjna/ezIzc9AnrwBWaxbs7TbYbG3ypdPpkJaWLl5mC4xGIwRBgNvtgtvthsfjhscj+L2eVquB0WgSL4MJRpMJOp0eOq0WGq1WDqQOhwOOdjvaHXa0t7dDEDzQanXQarXePzXweAQIggcej3gp/y69t1arATQaaDVaaDRaBLZ7aTQa6PV66HQG6HQ66PV69oQRJZDD0Y5vvl2n2vszHFGPteXnTfh/j92DO/6yEO3tduwp24Fdu7dh795d+O1FV6GwcCCeeuJfuOvuP+Lkk7yr1ErXwuPxhHy9n7ZsDPteLpcT/123CufMugR/vXsJvv+hFD/+9C127NiCv92zBAaDEev+t0pu5P7XWy9g5ukXoG/f/vjdZdciJ1vchfu/6z4NCjaSd/69AhqtFtdfexeumvNneDwefPHfjzFtytmYNuUsDBo0TL539+7t+P7HDfj5500YMeJYTJ82C/l9+snPjz1uIi6/9Fq43S7s/HUrTCYTBvQvDnmIbkVlOfbs2QGzOQ2FhQOR17sgqDrW2FiP6poKmM1pyOtdEPVUJhFRKDW1VfjtJaeo9v4aAEKHd5HMarWiqakJmZmZaG5uVns4FIW0NAvs9ja/qaqcnN54+KHnMWzoSLS1tcLpciArMwfz5v8JG779b1zvM2TwCDy++FVkZGQGPXfo8AH86brz0drq+3fmpEnT8cB9/4DT6YDH44HJZMZNt1yKn3/5PuL7XDL7GrkSpeRwOFBRcRBFRYNDfl9LazPWrVuF7Tt+wtFHlaCkZELQ3kytrS0o27sTTU0NKB40HH379g/9Wi1NaGisQ26vvLD7MNXVVaOpqQFGkxlpZrFSZDanwePxiFUkexvs9jY4HO3QasTKjk4nXkGlGkEQq0LOdrS32+F0OuB0OSF4BG+1Rwy0RqMJJpMZJqMJRpMZGo0GHrf4vNvjhiAI0ADeapMOOq1WrBB5/67RaqHVaCAIgEcQq0qCIEDwBP/PpMvthNvthsvlgtvt8vv3i4g6p6mpAff8PfSq3njF8vub4ShGDEex0+n10Bn0cNjsag/FT3q6BfffuxRjj5sIQGysPu+iE+F0OuJ+TYPBgKNGjMZxY05EyegJGHXMcXC7Xfi/v8zBjp1bgu5/+KEXMGG8+P8d7d6zA9dce05U73PZJX/CH/9wG9xuFzZ9X4rPv1yJr9avQWtrM7Kze+G4khNw3JgTMXLkcTh0aD/WfP4hSjd8EfSz5ffph5Ejx6CtrQVlZb+iqvqw3/MWixVDhxyF4kHDYLO14WD5Phws3+tX3bJYrOiT1xd5eQWw29tQVV2B2tpKOJ3OoHFrtdqwlTkioq4U6+9vgVf0l9VqFQRBEKxWq+pjSZXr1rdXCH9b+4GgNxpVH0vgZTAYhL/NXyJ8sXqHMO+Oh7vg9Y1CWpol7PMD+hcLn328Rfhi9Q7hnFmXxvTagwYNE7KyclT/DHnx4sUrFa5Yfn+zchQjVo5iozMY8Mj3YlPdg2deiLqDh1QeUTCNRoNRx4zFrt3bYbOF32Cyq8w47VyMOmYslj7zUFBjMxERJUYsv7/ZkE1dymxJV/w9Oc8IEwQBW37epNr7r17zH6xe8x/V3p+IiPxxnyPqUqYMXyAyZyRnOCIiIlJiOKIuZUr3VY5MSVo5IiIiUmI4oi6lrBYpp9iIiIiSFcMRdSlln5GJ02pERJQCGI6oS/lXjhiOiIgo+TEcUZdiQzYREaUahiPqUn7Tauw5IiKiFJAy4ejuu+/G+vXr0draivr6+pD3DBgwAB999BFaW1tRWVmJRx55RDynSWHy5MnYtGkT7HY7fv31V8yZM6c7hn/EMrNyREREKSZlwpHRaMTbb7+NZ555JuTzWq0WK1euhNFoxKRJkzBnzhxceeWVWLBggXzPoEGDsHLlSnzxxRcYM2YMHn/8cbzwwgs4/fTTu+vHOOKYUmATSCIiokCqn3cSyzVnzhyhvr4+6PGZM2cKLpdL6NOnj/zYtddeKzQ0NAgGg0EAICxatEjYsmWL3/e98cYbwieffNIlZ7PwgnDxgvnC4i2lwuItpcK1/3xC9fHw4sWLF68j84rl93fKVI46MnHiRGzZsgVVVVXyY6tWrUJWVhaOOeYY+Z41a9b4fd+qVaswceLEsK9rNBphtVr9LoqesnLETSCJiCgV9JhwVFBQgMrKSr/HpK8LCgoi3pOVlQWz2RzydefNm4empib5Ki8v74LR91zsOSIiolSjajhauHAhBEGIeI0YMULNIWLhwoXIzMyUr8LCQlXHk2q4Wo2IiFKNXs03X7x4MZYvXx7xnj179kT1WhUVFZgwYYLfY/n5+fJz0p/SY8p7GhsbYbfbQ76uw+GAw+GIagwUzBTlJpBXXz0D/fr1wgMPvNkdwyIiIgpL1XBUU1ODmpqahLxWaWkp5s+fj7y8PFRXVwMAZsyYgcbGRmzdulW+56yzzvL7vhkzZqC0tDQhY6BggdNqGo0GgiAE3ff00rkwm41YvnwtDh5MzL8TRERE8UiZnqMBAwagpKQERUVF0Ol0KCkpQUlJCSzeasRnn32GrVu34pVXXsHo0aNx+umn44EHHsDSpUvlys+zzz6LwYMH4+GHH8aIESNw3XXXYfbs2ViyZImaP1qPFlgtMqanBd2TmZkOs9kIAMjLy+qWcREREUWi+vK6aK5ly5YJoUyePFm+p6ioSFi5cqXQ2toqVFVVCY8++qig0+n8Xmfy5MnC999/L9jtdmHXrl3CnDlzumwpYGcvqzVNuPDCSYLZbFT984/n0mg0wqOb18tL+RdvKRWy8vOC7isuzhc8woeCR/hQmDZttOrj5sWLFy9ePe+K5fe3qtNqsbjqqqtw1VVXRbxn//79OPvssyPe89///hdjx45N5NC6zN13z8add12EW27+J5588kO1hxMzY1oatFqxOOmw2WFMM8NssaAR1X735eZmyn/v1YtbJRARkbpSZlrtSDS6pBgAMHhwgcojiY/UjO12udBcW+f3mFJuri8Q5eRkdM/giIiIwmA4SmKDB4sr63rlpmY1xexdul9oaMGIbIf3seBwpKwWsXJERERqS5lptSONVqtFcbEYjpTTTqlEXKkm4IIRThi0Fjy3wxNyI0j/yhE3iiQiInUxHCWpwsJcGI0GAP7hIZWYMyww6wSY9BoAQIbBE3IjSE6rERFRMuG0WpIaMsTXZxQpHJ122hj8svUfOPvs8d0xrJiYLBak6Tzy1+k6T8hpNb9wxGk1IiJSGcNRklI2YUfqw5k9+2QcffQAvPb6XzBkSN/uGFrUzJZ0pOsF+es0vRCyIbuXYtqQlSMiIlIbw1GSUlaOcnIyoNOF/kfV27tpYmZmOt56+06YTIZuGV80TBYL0vS+ylFaNJUjhiMiIlIZw1GSKg5Yvh8uNPTu7au6HHfcECxZck2XjisW5gz/abU0feiGbP/VagxHRESkLoajJBU4RRZuxVpenvj4Qw++BY/Hg7nXnYVLLjm1y8cXDbPFgjTFtFq6XpCX9yuxckRERMmE4ShJSXsceTxi5SVcU7Z0Ftlrr32JhQ+9DQB47p83YNiwft0wyshMGRak6/yn1TraBDIryxJ2CpGIiKg78LdQEsrKssiVom3bDgIIHY70ep08JVVd3Yh7730dX365BVZrOl5/4/buG3AY5gz/ylGaPrjnSK/XISvL/7HsbFaPiIhIPQxHSUhaqVZZWY/9+8VzyEKFIykYeTwe1NW1wO324LJLH4XL5ca4cUPRt2+v7ht0COaghmwhqOdI+TO0ttoBcCNIIiJSF8NREpJWqu3eXYHa2iYAoXuOpH6juroWefqtoqIeZWWVAIARIwq7Y7hhmSzpQQ3ZgZtASg3YDQ2tqKkRf1b2HRERkZoYjpKQVDnas6cCdbXNAEKv4pL6jaqrG/0e37GjHID64chssfjvc6QTkBYQjqTQV1vbjPr6FgA8X42IiNTF40OSkByOdlfA7ZYaskNVjkKHo193lgMYjxEj+nftQDtgyvCvHGk0QFZ2YDgSg1BtbRPa2toBsHJERETqYuUoCQ0e4qscSdNqvUL0HEl7HEnTURKpcjRsuLor1rIy0yEtPJP6iaxmHfRGo3yPLxw1o76+FQD3OiIiInUxHCUhqXIk9hyJ02qhGrKlnqOa6sBwJK5wU3taLcdbJWpptePgwRoAwU3Z0s9VV9eC+jrxZ2XliIiI1MRwlGT0eh2KivIASJWjSOEocs9RcXE+jEZ1Zk51BgOsZh0AoLqqEdXeAJeu98BkUYYjb1N5bZPcc8RwREREamI4SjJFRXnQ63Ww2dpx+HCdIhwF9xzleqfVAsNRRUU9mpraoNPpVDuMVtzjSOw3qqpqlMcoHiHi6zuSptCUDdk5bMgmIiIVMRwlGSnM7NkjLsevq+u4chTYcwQAO3eK1aPhw9WZWlOuVKuubkSNFI50gt9GkL0Uq9Xq6hJfOcrNzcQTT/wJY8YMTthrEhFRz8ZwlGSkY0N27z4MAHLlyGw2Ij3d5Hev1HNUXR0cjtRezq/c46i62jetFnj4rHK1WldMq1122WTc9Off4O75sxP2mkRE1LMxHCUZqXJUtqcCANDSYoPD4QQQPLUWrucIAHaqHI6U02o11b5ptfSA89X8GrLlfY4SF46k/i3pTyIioo4wHCWZYsVKNUltmI0ge4fpOQJ8K9aGq1Y58p9W8/UcCTCl+3qOlEv567pgtVph/1wAQH/vn0RERB1hOEoyQxR7HElCrVjLyrLAYBBXooXqOfJNq6mzEaQ5w6KYVmuKMK0m9Rx1zbRaYaEYigoKcqDX6xL2ukRE1HMxHCWZwREqR8ppNanfqLm5De3tzqDX+fXXQwDE6pIax3EoD52tDphWkxqy09NNMJkMAPxXq1ks5oRtQSCFI61Wq/pBvERElBoYjpJI796ZyMxMh8fjwd69lfLjvsNnfSHH128UXDUCgLa2dhw4UA0AGK7CTtnmjHSk6YKn1cx63yaQUthrb3eitdWOxsY2+QDdRFWP+vXzBSJOrRERUTQYjpKIVDUqL6/1qwbVe5e4K8NRpH4jiZpTa6YMC9L1ymk1cZw6jW/5vnKlGgAIgoCGBukIkc5Xu3JzM2E2+44qkapIREREkTAcJZHAPY4kvsqRclot/B5HEjVXrGVlW6H3/ttVXd0Ih8OF1jYHAF+wU65UkySyKbuw0H8arX//3p1+TSIi6vkYjpKItMfRHu8eRxJ5tVoM02qAYiNIFcJRXh9xfO0Ol3zobH2jDQCQ6111p1ypJpEOn01MOPKvFHFajYiIosFwlESkaTXlSjUg9Go136GzHU+rqbFLdm/vtFh9k11+rE4KPtlpAPxXqkkSuddRYDgqZOWIiIiiwHCURAZ7p9WUK9UA5T5HvnAU7lw1JSkcDR3aF1pt9/6jzu0lNl3XN7TJj9V4f47sTDEcSQGoTlE5Suy0mhiOpKlHVo6IiCgaDEdJRJ5WC6ochV+tFqnnaP/+atjtDpjNRgwc2L07ROdkiRs91ir6iaQgl5UhNknnKs5VkzQkcK8jKRx9++1OAOw5IiKi6DAcJQmTySD/Mg9XOQq9lD985cjj8cj7HXX3irXsTDMA//BWVVkPAMi0iHsb9QpYrQYop9U6v1qtnxSOvtkhft2vV7dX0IiIKPXwN0WSGDQoH1qtFk1NbX5hAfCfapJ+uUc6dHb0jKk4ZuopAICdO8Vw1N17HUnVoeoqX3irPFwHALCaddBotWFWq4l/z05g5Wjjxl1wu90wGPTo420UJyIiCofhKEns3FmOwn5zMHXK3UHPSYFBq9UiO1vs5Qm3z1FaZiZ+98gCXLH4QZjS07HTe8ZaR5UjrU6H4RMnQGcwdPpnAQBrmrjDdaW3WgQAh8trxDHqPDBZ0sOsVkv8tNr+/dU4fLje7zEiIqJwGI6ShCAIOHy4Dj/8sDvoOafThaYmsbF57tMP4eolDyAjQ2xqDuw5yi8eCJ1eD73BgD6DB/lWrHWwnH/q1b/Dtf98ApOvuLTTP4tGo0GGWfxXq+JQrfx4ZYVYOUrTi0eIdOVqNZPJIAfI8vJaHDwoBjP2HRERUUcSc4AVdbna2mZkZqZj1IQSDHJpAdTD4XDKoUmSN2iA/Pe+Qwdjx45fAXS8EeSx0ycDAAaNObbTYzWmpyFNLx4dcri8Wn5cqnKl6cQjRKQAVNsFq9WkCpHN1o76+haUl4vBjCvWiIioI6wcpQipumLWC4ozy4L7jfIGDZT/nj+0WN4Isn//3rBYzCFfOz0rE4VHjxC/Z/CgTo/VrDg6RFk5ksabrvcg3ZohB6CumFaTwlF5ufj+5awcERFRlBiOUoQUINJ0Hr/T7gPlDfRVjgqGDEZ9fYt837BhoZuyh504Xm707tW/H/QmU6fGarZY5ABXpWjIlsah1wJFxQXye0rVIvHviZlW84UjsWIkTasVsnJEREQdYDhKEVI4MukEpOnEcBRqj6O8QUXy3wuGDQagPIA29NTa8BPHy3/XarV+ASsemb2yYJSrW75w1Npqh8Pl8RtLU1MbXC63fI9UOTIaDUhPjz+kBVaODh4U/2TliIiIOsJwlCLq65SVo+DgAQAarRa9i3yr0rLz+8BszZBXrB11VOgVa8MnTgAAONvbAXR+aq1vobjhpMsjBPVENdvEIDTMu+GlckoNEAOU0+kC0Lm9jqRwdEgOR9K0GitHREQUGcNRiqjzVlTMyspRQM9RdkEfGEwmuBwONFaJjdAFg4vx0097AQDHjR0S9Lq9i/qjV2FfuBwObFn7XwDhw9ExxxRh7ecPYvz4YRHHmt+3FwCgxe4Jeq6p1QEAGFwsBqjAPZ2AxDRl9wtTOeJSfiIi6gjDUYqwucV/VGatW252rmto9bunj7cZu2b/QRzeKW4JUDBssHx8xoQJw4NeV6oa7f1xCw78sk18nTDh6JZbzsXUqaNx218uiDjW/IIcAEBzmzPoucZmsTo1sDAbQHDlCADqpQNqOxGOCgvFgCaFo0PexvC0NFNCdt8mIqKei+EoRXiM4lllGkcrDB4xYLQL/jsxSMv4q/cdQMWuPQCA/CHF+PHHMjidLhQU5GDAAP8z1qRwtLP0O1Tt2St+T5hwNHHSUeKfE0dEHGt+n2wAQGOLI+i5+kYbAKCob/C5avI9CdjrKLDnyOFwoaqqAQCn1oiIKDKGoxShSRePvTDBBYNbDEcuQ7rfPdIy/up9+1GxWwxHBUMHw253yFNrJ5zgqx5pdToMnTAOALCz9FtUesNR3qAiaHU6v9fOzrZg5Eix2XvAgLyI01PS5osNTfag5+oaxB6k3CxxW4G6LphW02g06NdPrBxJ02nKv7Mpm4iIImE4ShGGbDGMpBkAs867usuS7XePtMqsumw/KnaVARDDEQB8F2JqbcCoo5FmzUBbYxMObtuBhsOVaG+zQW8woFd//2X/J554VMDX4atHud6Kj1QlUgqsFCnPVZN0dq+j3r0zYTQa4PF4cNh7nhsA7pJNRERRYThKEaa8vgAAa7oBGWaxqqPP8q/e5A0UKzvV+/ajcrcYjjJ758KSnSX3HY1XhCN5Sm3DdxA8HgiCgOq9+wEET61NmhQYjvy/VsrJFitatfWtQc8FblwZalqtQZ5Wi683SKpqVVU1+m0TUC5XjjitRkRE4TEcpQCNVouMfmJVKM1sQFaGuP+PFJgAQG8yIbuvuDy+au9+OGw21B48BADIHzoY334rHiNy/PFDodOJ/9il/Y12ln4rv07lHjFU5Q8u9hvDiRPFMPTVV1u9X4evHOVkilNmNTXBwafa2/cjCb1arXOVo8B+I4lvI0hWjoiIKDyGoxTQq19feAwmeATfY4IAWPr1l3uDehf1h1arRVtTE1rrGwBArh4VDCnG9u0H0dzcBovFjKOPHgCTJR0DR48CEBiO9gLwrxzpdFq5V+mxxe8BAMaNGwqDIfTRfJlWMbzVhNjBu7Ky3u/rSA3Z2TmWkK/fkQ7DEZfzExFRBAxHKSB/SDEADdraffsG2VyAzmBEr0KxetTHuzN2ddl++R5lU7bH48HGjbsAiH1HQ8ePhc6gR/W+A6g/VCF/j7Rirc9g3xlto0YNhNWajsbGVnzwwbeoqWmC2WzEmDH+1SVJZroYmgKDEAAcLq/x+zpUOJIasqOZVuvXr5d8DIkkcANIiRSWOK1GRESRMBylgPwhgwAAja3t8mMt3p2mpQqPr9/ogHxPxa++cAQA337ja8r2LeH3VY0AX+WoT7EvHE2adDQAYMOGHfB4PNiwYQeA8H1HVm9PVMXh2qDnDh+s8vtaea6aJNqG7IsvPgUHy1fg/vsv93tcCj/BlSOuViMioo4xHKUAqf+nXtHgLK0Ek0KMdKZa1d598j1y5WiI+P2+puxhfvsbKdUcOAi30wWzxYLs/D4AfP1GpV+Lm0RuKN3ufTy478hg0CPNKP5rFVglAoDKQzVwK6YHI20CGWmfI41Gg7/fexkA4Nq5Z8Jo9E3xBe6OLZG+zsxMh9WaFva1iYjoyMZwlAIKhorhprqyQX6s2nvorLSbtXIDSElV2T54PB5YcrKRkZsjh6Njjx2EfoOL4Ha6sOu7TX7v5XG5Ub1ffI18b6iSVqqVlooVow0bxHA0cWJw5Uja48gjAFWHgsORvaUVdpcGAOByudHYGLyiLZp9jn7zmwnyWXG9elkxa9YE+Tlfz1Gd3/e0ttrlqhSrR0REFA7DUZLTaDToUzwIAFBRXi0/XuENHvne56SjQ6oVlSOnvR21B8oBAH2HDkF5eS0OHaqFXq9DnzQXvnnvQ9ibg/cZ8vUdDUKfPtkYMqQvPB4PvvlGDEfffvsrPB4PBg3KR4H3qBBJXp4YjmxuDewtwcHHYbOhzSX+a1cfYqm/+Li3ITvbAo1GE/Ke2+8QjzCp8YbEK+ZMk58L15ANcK8jIiLqGMNRksvumw9TehpcTicOH6yUHy/fJzZR9ykeCEtONtKzxFBSs/+g3/dX7vYdIwIAW38VA1aewY41/1wW8j0ry/aK3zN4kFwd+uWX/WhqEne3bmmx4eefxRAWuBlkQT8xdNhcWthbQ4efVm9jeX1jW8jnpXCk0+mQmZke9PykSUfjpJNGor3didm/XQQAOPPMccjLy0JamkmuOIUOR2zKJiKiyBiOkpwUaqr37vdbGr9/90F43G6kZVoxeNwYAEDdocNw2tv9vj9wp2x7ViEAwFC7D42V1QhFuWJNnlL7ervfPRtKpaZs/3DUr794dpvNpUV7W/AO2QDQbBebyRubQj/f3u5EW5v4c4SaWpOqRi+vWIsvv9yCb7/dCYNBj0svPVU+cLa11R5yyq6clSMiIuoAw1GSK/A2Y1fs2uPXvFxZUSdv8jhq6qkAgBpFv5FEOoC2YOhgHH3qSWj3hqP+WaGnqwDFXkfFgzDRu1Lta28ztkTqOzoxoO+ooK9YkWlp90DweBBKU5tL/DPEwbSScCvWjjqqP84990R4PB4sXvw+ADEkAcAVc6ZHnFJTPs69joiIKByGoySSN6gImXn+FQ2pclS5Z69fOKqubkJVmTi1dfSpk8THQoUjxYq1M2/8Eypt4qqu4uJ85OZmhhyH1MidmZuN448fCgAoLfWvHEnN2ccfPwx6vbh0v0+fbMz902kAgJpmV9ifs957IG1Dc/DBtPI98hEi/uHoL385HwDw/vsbsHOn2E/1r3/9Dw6HE2PHDsHMmeJBuuHCkTStVshpNSIiCoPhKEnkDSrC9S8txXUvPu0XkORwtLvM76iNmpomefrLkp0FAHJYUqoq2w+3y4W0TCsKjx6OhsY27NgpVpzGjx8WcixOezvqD1Wgj9kFs9mImpom/PrrIb97du4sR319C9LTTRg9ehDS0kz4zwf3oKh/Lhratfhie+h+IwBYt6UWP9Sa8a+VW8PeE2rFWt++vfC7308FADz6yL/97v3oI3FLguuuPwtApHDEaTUiIoqM4ShJuBwOuBxO9CkeiOtfWorMPmLvjrQBpBiOlJWjRrlxWn4sROXI7XT6NWmve/kNfOOdEpswQQxHRUV5ePzxP+KnLU/jqaeuRXFxPqrK9qJvulj9CZxSAwBBEOTNICdNOhorXv4/nHDCCDQ22fDevizU1YUPR1XVzfjycAYq6tvD3hNqWu22286D0WjAunU/yyvnJC+v+BwA5AbuwN2xJb5wxMoRERGFxnCUJOoPVeAfV1+PuvLDYhXpxadRNPoYmC0WuJ0u1Ow/KC9bB7yVo4BKkXIZv5LUd9Ta0Ih1r76J77z7HZ119ni8/Mqt2LX7efz55nMwatRA3HDjLOz89Tn8fqIVQzPF8LIhYEpNIj1+/wO/w0UXnQSHw4m/PPgxGhw6tLeFXokGQF7ib7KEPztNOny2Vy8rTj55JFaveQC33iZOqSmrRpJPPtmEakXDeuAeRxJpWi03NxNpaaaw709EREeu0CeHkiqkgHTdi0uRN6gI1/7zCQBA9f4DcLtcqKiox5NPfIDmZhvsdodfOHK2t6P+cGXI1932v69Rcvo0fPLUc7C3tMqbQU6YMBwTJogHyq5e/QP+9cY6/Hb2yZg5cxxOGdMXgFQ5ChOOvJWjrCwx5Pzh6iexx5mDkUDIPY4k0hJ/c0b4cNTgrRzdedeFyM6eAwBwOJx48okP8fHHG4PudzpdeOP1/+LPN58DwFchCtTY2IqWFhsyMtLw667nsHbtT1i75kd8+eUWOBwu5ORkoFcvK3JyLEhLM8HhcMHhcHr/dMFmc6CtrR02Wzva2trhdntgMhlgNhthMhlgMhngdrvl+x0OF5xOFzweAYIgwOMR4PF4oNPpoNdrodfroNfroNVq4PEIcLs98Hg8cLs90Gg00Om00Gq10Go10GqDm+hdLg8cDiecTvE9XS43BEF8L0A8oFgSZsuooPt83+v/GhqNuO+WVquBRiNe0nsJAuDxNuBLz4V/LyHsc0REEpfLrdp7MxwlmfpDFXjm6htw3UtLkdu/HwBxSk1yyy3Py3+3NTWjqaYWmb1zUbP/YNjVYd+9vxJb1nwpB5bNm8uwf381Cgt74e231+P/PfpvfP/9bgDAsmVrMHr0INz70NU456zj0OIAHDn9Mfr0PhDcbrgcTlTs3oP6QxX45psdcLvd0Ol0uO++N7Bxrx3Tr5kBAGgPs8cRALR7x1FyxjQ019Tix0/XoLnWv9Lj2wgyAw6HEy+9uBoLF76DAwf8tx8wpqXBYRO3BHj55c/lcBSu5wgAHl/yH9z2l/PRr18ufv/7qfi9t4+JiIiSw6FDtehfeKVq768BwP83LgZWqxVNTU3IzMxEc3PwuWCJktO3ANe99DRy+xfi4yefxdrnV4S877oXn8bQCePw05ovseL/5kX9+r16WaHX61BV1RDy+bRMKxZv+BQeAO3u4NnX5to6HPhlG4anNaN3n2wctA5HRq9e8vPvLXwMX73+dsjXHnbC8bjmmcegNxgAAB63G79u+A57vt8MvdEIg9mE4YNyccvFI7FtXxP+/d/9qKprg9vlgiktDdl985FdIF6m9DQ01dTiwJat2P/zVtw9ZzSK+mbhtFmL4PRooDMa5PcRBAGCRwAEASazAePHDcHJJw7FxPHFGDksX/y5WtrR2GxDQ2Mb7DYn9AYtDHodDAYdjEY9zCY90sxGmM0GmE0GaLUaOJ1utDtccDjccLjc0Gm1MBjE7zHotdDrtCGrPgDgdLrh9laVpKqMVgNotVp4vON1ezzweAL/M9VAowG0Wg0M3soTEVFPUV3bgvzelyb0NWP5/c1wFKPuCkcAYO2di1HTTsX3K1ehvTV0D8+5d96CU393MT579iWsWvp8yHviNeXKyzFi0gRotFpodTpotVoY09OQP6RYDhxKzbV12PzZ5/jh49XY++NPEV87IzcHY844DWPPOh0DS0YlcNQCxH+tY6PVCBDzRyzfK3j/A4r2e8Q7NQC8E1CxDDEiDQQxVGn8RxPNf+AhR6EJ/lKA+H8ExWtqFH9qNL57JMGRjoioY43VtZg/5ZyEvibDURfqznAU1Xh652L8uWfhm39/iNb6hm55T73RiH4jhqLo2JEYcMxIuBwO/LT6C/z6zUZ43LHPEecO6I/jzjwNvQr7wWm3w2G3w2mzw+lwiNUUnU689Dq4HE40HK5EQ0Ul6g9XorW+Hn0GD0LRqJEYOPoYFB17DKy9e8HlcMLV7oDL6YDb6ZIrMxqtVu6Vcba3w2lvF1cKtrdDq9fDYDJBbzRCbzKKAdD721zsodHA43LBLV1OFzwet1yNEgQBAgS47O1ot9nhsNngsNnhcbthMBphSDPDYDLBaBYbwT0eDzxuDwSP+JlptDpodVr559VoxX4jjVYLjVYDDTTye3tcLrjdbjkLasSGIGiggQDfeML91y14PIr7fI9rvClHA+/raTTy68u9QoKib0jqS/K+kcb3gcnfGzgGwb/BKeDNA96LiI5IbY1N+Nc99yf0NRmOulCyhSMiIiLqWCy/v7mUn4iIiEghZcLR3XffjfXr16O1tRX19fUh73niiSewceNG2O12/PDDDyHvOfbYY7Fu3TrYbDbs378ft99+e1cOm4iIiFJMyoQjo9GIt99+G88880zE+1566SW8+eabIZ+zWq347LPPsG/fPowbNw6333477r33Xvzxj3/siiETERFRihJS6ZozZ45QX18f8Z6///3vwg8//BD0+Ny5c4Xa2lrBYDDIjy1cuFDYtm1b1O9vtVoFQRAEq9Wq+mfBixcvXrx48YruiuX3d8pUjhJh4sSJWLduHZxOp/zYqlWrcNRRRyE7Ozvk9xiNRlitVr+LiIiIeq4jKhwVFBSgstL/iA3p64KCgpDfM2/ePDQ1NclXeXl5l4+TiIiI1KNqOFq4cKHibKbQ14gRI9QcIhYuXIjMzEz5KiwsVHU8RERE1LVUPVtt8eLFWL58ecR79uzZk7D3q6ioQH5+vt9j0tcVFRUhv8fhcMDhcCRsDERERJTcVA1HNTU1qKkJfXp6VygtLcWDDz4IvV4Pl0s8cX7GjBnYvn07Ghoaum0cRERElLxSpudowIABKCkpQVFREXQ6HUpKSlBSUgKLxSLfM2TIEJSUlKCgoABpaWnyPQbvOWCvv/46HA4HXnzxRYwcORKzZ8/GzTffjMcee0ytH4uIiIiSkOrL66K5li1bJoQyefJk+Z4vvvgi5D0DBw6U7zn22GOFdevWCTabTThw4IBwxx13dNlSQF68ePHixYtXclyx/P7m2Wox4tlqREREqYdnqxERERHFieGIiIiISEHV1WqpjDtlExERpY5Yfm8zHMVI+nC5UzYREVHqsVqtHfYcsSE7Dv369euSZmyr1Yry8nIUFhay2bsL8XPuHvycuwc/5+7Dz7p7dOXnbLVacejQoQ7vY+UoDtF8sJ3R3NzM//C6AT/n7sHPuXvwc+4+/Ky7R1d8ztG+HhuyiYiIiBQYjoiIiIgUGI6SSHt7O+699160t7erPZQejZ9z9+Dn3D34OXcfftbdIxk+ZzZkExERESmwckRERESkwHBEREREpMBwRERERKTAcERERESkwHCUJK6//nqUlZXBZrNhw4YNGD9+vNpDSml33XUXvv32WzQ1NaGyshLvvfcehg8f7nePyWTC008/jZqaGjQ3N+Odd95Bnz59VBpxz3DnnXdCEAQsWbJEfoyfc+L069cPr7zyCmpqatDW1oaffvoJ48aN87vnvvvuw6FDh9DW1obVq1dj6NChKo02NWm1WixYsAB79uxBW1sbdu3ahXvuuSfoPn7OsTnllFPwwQcfoLy8HIIg4Nxzzw26p6PPNCcnB6+++ioaGxtRX1+PF154ARaLpcvGLPBS95o9e7Zgt9uFK6+8Ujj66KOF5557TqirqxPy8vJUH1uqXp988okwZ84cYeTIkcLo0aOFjz76SNi7d6+Qnp4u3/OPf/xD2LdvnzB16lRh7Nixwtdffy189dVXqo89Va/jjz9e2LNnj/Djjz8KS5Ys4eec4Cs7O1soKysTXnrpJWH8+PHCoEGDhBkzZgiDBw+W77njjjuE+vp64ZxzzhGOPfZY4f333xd2794tmEwm1cefKte8efOE6upq4ayzzhIGDhwoXHjhhUJTU5Nw00038XPuxDVz5kzh/vvvF8477zxBEATh3HPP9Xs+ms/0448/Fn744QdhwoQJwkknnSTs3LlTeO2117pqzOp/aEf6tWHDBuGpp56Sv9ZoNMLBgweFO++8U/Wx9ZSrd+/egiAIwimnnCIAEDIzM4X29nbhwgsvlO8ZMWKEIAiCcMIJJ6g+3lS7LBaLsGPHDmH69OnCF198IYcjfs6JuxYuXCisW7cu4j2HDh0SbrvtNvnrzMxMwWazCRdffLHq40+V68MPPxReeOEFv8feeecd4ZVXXuHnnKArVDjq6DM96qijBEEQhHHjxsn3nHHGGYLb7Rb69u2b8DFyWk1lBoMB48aNw5o1a+THBEHAmjVrMHHiRBVH1rNkZWUBAOrq6gAA48aNg9Fo9Pvcd+zYgX379vFzj8PSpUuxcuVKrF271u9xfs6Jc84552Djxo146623UFlZie+//x7XXHON/HxxcTH69u3r91k3NTXhm2++4Wcdg6+//hrTp0/HsGHDAACjR4/GySefjE8++QQAP+euEM1nOnHiRNTX12PTpk3yPWvWrIHH48EJJ5yQ8DHx4FmV9e7dG3q9HpWVlX6PV1ZW4qijjlJpVD2LRqPB448/jq+++gq//PILAKCgoADt7e1obGz0u7eyshIFBQVqDDNlXXzxxRg7dmzIPjl+zokzePBgXHfddXjsscfw0EMPYfz48XjyySfhcDjw8ssvy59nqP8t4WcdvUWLFiEzMxPbt2+H2+2GTqfD/Pnz8frrrwMAP+cuEM1nWlBQgKqqKr/n3W436urquuRzZziiHm/p0qUYNWoUTj75ZLWH0uP0798fTzzxBGbMmMEjFbqYVqvFxo0bMX/+fADAjz/+iFGjRmHu3Ll4+eWXVR5dzzF79mxcfvnluOyyy/DLL79gzJgxePzxx3Ho0CF+zkcQTquprKamBi6XC/n5+X6P5+fno6KiQqVR9RxPPfUUZs2ahalTp6K8vFx+vKKiAiaTSZ5uk/Bzj824ceOQn5+P77//Hk6nE06nE1OmTMGf//xnOJ1OVFZW8nNOkMOHD2Pr1q1+j23btg1FRUUAIH+e/N+Sznn00UexaNEivPnmm/j555/x6quvYsmSJZg3bx4Afs5dIZrPtKKiImiVq06nQ69evbrkc2c4UpnT6cSmTZswffp0+TGNRoPp06ejtLRUxZGlvqeeegrnn38+pk2bhr179/o9t2nTJjgcDr/Pffjw4Rg4cCA/9xisXbsWo0aNwpgxY+Tru+++w2uvvYYxY8Zg48aN/JwTZP369RgxYoTfY8OHD8e+ffsAAGVlZTh8+LDfZ221WnHCCSfws45Beno6PB6P32Nutxtarfjrkp9z4kXzmZaWliInJwdjx46V75k2bRq0Wi2++eabLhmX6p3rR/o1e/ZswWazCVdccYVw1FFHCc8++6xQV1cn9OnTR/Wxpeq1dOlSob6+Xjj11FOF/Px8+TKbzfI9//jHP4S9e/cKU6ZMEcaOHSusX79eWL9+vepjT/VLuVqNn3PiruOPP15wOBzCvHnzhCFDhgiXXnqp0NLSIlx22WXyPXfccYdQV1cn/OY3vxFGjRolvPfee1xiHuO1bNky4cCBA/JS/vPOO0+oqqoSFi1axM+5E5fFYhFKSkqEkpISQRAE4ZZbbhFKSkqEAQMGRP2Zfvzxx8KmTZuE8ePHC5MmTRJ27NjBpfw9/brhhhuEvXv3Cna7XdiwYYMwYcIE1ceUylc4c+bMke8xmUzC008/LdTW1gotLS3Cu+++K+Tn56s+9lS/AsMRP+fEXWeffbbw008/CTabTdi6datwzTXXBN1z3333CYcPHxZsNpuwevVqYdiwYaqPO5WujIwMYcmSJcLevXuFtrY2YdeuXcL9998vGAwGfs6duCZPnhzyf5OXLVsW9Weak5MjvPbaa0JTU5PQ0NAgvPjii4LFYumS8Wq8fyEiIiIisOeIiIiIyA/DEREREZECwxERERGRAsMRERERkQLDEREREZECwxERERGRAsMRERERkQLDEREREZECwxERJZ0vvvgCS5YsUXsYfgRBwLnnnqv2MIiom6i+rTgvXrx4Ka+cnBwhIyNDACCUlZUJN998c7e999///nfhhx9+CHo8Pz9fMBqNqn82vHjx6vpLDyKiJFNfX5/w1zQYDHA6nXF/f2VlZQJHQ0TJTvWExosXL17KSzq89osvvgg6qFK656STThLWrVsntLW1Cfv37xeeeOIJIT09XX6+rKxMuOeee4QVK1YIjY2N8gGXixYtEnbs2CG0trYKu3fvFhYsWCDo9XoBgDBnzpywhxULgiCce+658uuPGjVKWLt2rdDW1ibU1NQIzz33nN8hmMuWLRPee+894bbbbhMOHTok1NTUCE8//bT8XgCE6667Tti5c6dgs9mEiooK4e2331b9s+fFixcEJMEAePHixcvvksJRTk6OsH//fuGee+4R8vPzhfz8fAGAMHjwYKG5uVm4+eabhaFDhwoTJ04UNm3aJLz00kvya5SVlQkNDQ3CrbfeKgwePFgYPHiwAECYP3++MHHiRGHgwIHCrFmzhMOHDwu33367AEAwm83Co48+KmzZskV+P7PZLAD+4Sg9PV0oLy8X3nnnHeGYY44Rpk6dKuzevdvvhPFly5YJDQ0Nwj/+8Q9hxIgRwtlnny20tLQI11xzjQBAGDdunOB0OoVLLrlEKCoqEsaMGSPcdNNNqn/2vHjxgoAkGAAvXrx4+V1SOAJC9xw9//zzwrPPPuv32EknnSS4XC7BZDLJ3/fvf/+7w/e67bbbhO+++07+OlzPkTIcXXPNNUJtba1fperMM88UXC6X0KdPHwEQw1FZWZmg1Wrle958803hjTfeEAAI559/vtDQ0CD3VvHixSt5LvYcEVHKKSkpwejRo3H55ZfLj2k0Guh0OhQXF2P79u0AgI0bNwZ97+zZs/HnP/8ZQ4YMQUZGBvR6PZqammJ6/6OPPhqbN29GW1ub/Nj69euh0+kwYsQIVFVVAQB++eUXeDwe+Z7Dhw/j2GOPBQCsXr0a+/btw549e/Dpp5/i008/xXvvvQebzRbTWIgo8biUn4hSTkZGBp577jmMGTNGvkpKSjB06FDs3r1bvq+1tdXv+0488US89tpr+PjjjzFr1iwcd9xxePDBB2E0GrtknIEN4IIgQKsV/2e3paUFY8eOxaWXXorDhw9jwYIF2Lx5M7KysrpkLEQUPVaOiCipORwO6HQ6v8e+//57jBw50i8IRWPSpEnYt28fHnroIfmxgQMHdvh+gbZt24Yrr7wS6enpcvXopJNOgtvtxo4dO6Iej9vtxtq1a7F27Vrcd999aGhowLRp0/Dee+/F8FMRUaKxckRESW3v3r049dRT0a9fP+Tm5gIAHn74YUyaNAlPPfWUXDE655xz8NRTT0V8rV9//RVFRUW4+OKLMXjwYNx00004//zzg96vuLgYJSUlyM3NDVlVeu2112C327FixQocc8wxmDJlCp566im88sor8pRaR84++2zcdNNNKCkpQVFREa644gpotdqYwhURdQ2GIyJKan/7298waNAg7N69GzU1NQCALVu2YPLkyRg+fDj+97//4YcffsCCBQtw6NChiK/14YcfYsmSJXj66afx448/YtKkSbj//vv97nn33Xfx6aef4osvvkBNTQ0uvfTSoNex2Ww444wz0KtXL3z33Xd45513sHbtWtx4441R/1wNDQ244IIL8Pnnn2Pbtm2YO3cuLr30UmzdujXq1yCirqGB2JlNRERERGDliIiIiMgPwxERERGRAsMRERERkQLDEREREZECwxERERGRAsMRERERkQLDEREREZECwxERERGRAsMRERERkQLDEREREZECwxERERGRwv8HWlMAT8XjTSEAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for loss in loss_list:\n", + " plt.plot(loss)\n", + "plt.legend([0.1, 0.25, 1])\n", + "plt.xlabel('iterations')\n", + "plt.ylabel('loss')" + ] + }, + { + "cell_type": "markdown", + "id": "6a88dda3", + "metadata": {}, + "source": [ + "The depicted figure illustrates that the utilization of CVaR results in quicker convergence towards a lower loss." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f81fdeae", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'probability of the best answer')" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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gARecD3Hm4IopijWHKD4LrBc5X+87kUhaIIgCCITmjUIccSIEZg1axbWrVuHdevWYdasWRg5cmSuz3bUIvnjHCC21sIMQVsOUKoQtIcDVJBfbL6uKeE5Zyu8qas8HSCjBJa5AyRw7n9CHGe8NqIoaIrbBcZKYLlahGqckUpgBEEQRPZkLYBuvPFGzJ49G/X19XjyySfx5JNPoq6uDh999BFuuummljjjUYdo5ndk5gCxtngzBM2bZSTFKwStGaIkfgAhAOTnGw6QojQmPOdshWet9KqS2AafWQnMzgAlCCDzn1Q4qlhzgOK7wHJZAqMQNEEQBNEcsi6B3X333bj99tsxefJk67GnnnoK33zzDe6++24888wzOT3g0YgY5wD5A44MkN8PIUUJTNFZt5a7/RwAQnlFAABZbkh4blfVDshyDJLkg865W+CB+BJY6hB0TU0DBMHbAQKMszdFY5YDdDBLYCSACIIgiEzI2gFq06YNZs+enfD4J598gqKiopwc6miHtborbA6Qny0QNTNAbE2GbAgQv4cD5FUCCwbbAABisfqE5zRNxcdz3sWmresREVVX/sd4L7YKI7sSGA97kSvPG5voAaApHPUogZEAIgiCIA4PshZAH3zwAS6++OKExy+88EL8+9//zsmhjnasQYjMAbImQ7szQLLZBubVBh8/gBAAgoFCAEAkut/zfZ948l788YGboHPu/A9guz2ZlMCamqJQFOPsvM5Z5/U5gtkNkUhCCUySDkYIOpbkSoIgCIKwyagEdsstt1jfr1y5En/6058wfPhwzJ8/HwAwePBgDB06FI8//njLnPIog80BYl1gflM46CwDJDIBZIgStwBiDlCiAPL7CwAAkUhd8ve2WvDjBVBiF1iqYYW1+w2XiQMHXyCASGOjy5Wqb4g4SmAt5wDRMlSCIAiiOWQkgG6//XbXz/v27cMJJ5yAE044wXqstrYW11xzDR588MHcnvAoxF6FYU6C9scJINNRiSlMANliR1WNUpXk4QD5fIYAamrydoAAQGCzeORkJTDBziClECr79tnvkZefj0hjI/KCQfMRHfUNYUsABYN+cBxnCaBc7QHzOmM0mrsOM4IgCOLoJSMBdMwxx7T0OVoV8SFou6NLhyj5rFUUspxYAlM05tQkCiBJzAcANDbVJn9vtqw0aQks/S4wANhXYwugYKgAQBWK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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for prob in prob_list:\n", + " plt.plot(prob)\n", + "plt.legend([0.1, 0.25, 1])\n", + "plt.xlabel('iterations')\n", + "plt.ylabel('probability of the best answer')" + ] + }, + { + "cell_type": "markdown", + "id": "0ae45348", + "metadata": {}, + "source": [ + "The data presented in this figure indicates that QAOA with CVaR typically exhibits a higher probability of obtaining the correct measurement outcome." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc_dev", + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/portfolio_optimization.ipynb b/docs/source/tutorials/portfolio_optimization.ipynb new file mode 100644 index 00000000..3ed0f4e3 --- /dev/null +++ b/docs/source/tutorials/portfolio_optimization.ipynb @@ -0,0 +1,502 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", + "metadata": {}, + "source": [ + "# Portfolio Optimization\n", + "\n", + "## Introduction\n", + "\n", + "Consider the following scenario: Xiaoming, an astute individual, possesses a sum of money represented by $B$ and is contemplating investing it in the stock market. The market comprises of $n$ shares, each having an identical price. Xiaoming's objective is to maximize returns while minimizing risk, taking into account the varying levels of risk tolerance among individuals. Xiaoming's personal risk tolerance is represented by $p$. In light of these considerations, the question arises: which shares should Xiaoming choose to construct an optimal portfolio?\n", + "\n", + "Xiaoming's predicament falls under the purview of portfolio optimization problems. These problems are classified as Quadratic Unconstrained Binary Optimization (QUBO) problems, wherein binary numbers are utilized to represent decisions. In this case, \"1\" signifies selection, while \"0\" denotes the opposite. To address the challenge of portfolio optimization, the Quantum Approximate Optimization Algorithm (QAOA) is employed.\n", + "\n", + "## Solving portfolio optimization problems with QAOA\n", + "\n", + "In a simple boolean Markowitz portfolio optimization problem, we wish to solve \n", + "\n", + "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^T x$$\n", + "\n", + "subject to a constraint\n", + "\n", + "$$ 1^T x = B$$\n", + "\n", + "where \n", + "* $n$: number of assets under consideration\n", + "* $q > 0 $: risk-appetite\n", + "* $\\Sigma \\in \\mathbb{R}^{n\\times n}$: covariance matrix of the assets\n", + "* $\\mu\\in\\mathbb{R}^n$: mean return of the assets\n", + "* $B$: budget (i.e., total number of assets out of $n$ that can be selected)\n", + "\n", + "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and consider the alternative problem:\n", + "\n", + "$$ \\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2$$\n", + "\n", + "The variables in the linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be written in a squared form, since all boolean variables $0^2=0,\\ 1^2=1$. The same trick is applied on the middle term of $t(1^Tx-B)^2$. Then the function is written as\n", + "\n", + "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2$$\n", + "\n", + "which is a QUBO problem\n", + "\n", + "$$\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q X + tB^2$$\n", + "\n", + "where matrix $Q$ is\n", + "\n", + "$$ Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", + "1 & 1-2B & 1 & \\ldots \\\\1 & 1 & 1-2B \\\\\n", + "\\vdots\\end{pmatrix}$$\n", + "\n", + "and we ignore the constant term $t B^2$. We can now solve this by QAOA as above.\n", + "\n", + "## Set up" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "657c589a", + "metadata": {}, + "outputs": [], + "source": [ + "## delete before PR\n", + "import sys\n", + "\n", + "sys.path.append(\"D:\\OneDrive - Imperial College London\\文件\\Code\\TensorCircuit\")\n", + "sys.path.append(\"/Users/felixxu/Library/CloudStorage/OneDrive-ImperialCollegeLondon/文件/Code/TensorCircuit\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4f4feab6", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import numpy as np\n", + "import tensorflow as tf\n", + "import matplotlib.pyplot as plt\n", + "from IPython.display import clear_output\n", + "from functools import partial\n", + "import time\n", + "import scipy.optimize as optimize\n", + "\n", + "from tensorcircuit.templates.blocks import QAOA_ansatz_for_Ising\n", + "from tensorcircuit.templates.conversions import QUBO_to_Ising, QUBO_from_portfolio\n", + "from tensorcircuit.applications.optimization import QUBO_QAOA, QAOA_loss\n", + "from tensorcircuit.templates.conversions import StockData\n", + "\n", + "K = tc.set_backend(\"tensorflow\")\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "55659298", + "metadata": {}, + "source": [ + "## Import data\n", + "\n", + "To optimize a portfolio, it is essential to utilize historical data from various stocks within the same time frame. Websites such as [Nasdaq](Nasdaq.com) and [Yahoo Finance](https://finance.yahoo.com/) provide access to such data. The next step involves transforming this data into an annualized return ($\\mu$) and covariance matrix ($\\sigma$), which can be recognized by the Quantum Approximate Optimization Algorithm (QAOA). To simplify this process, we can utilize the `StockData` class. This class performs the necessary calculations for annualized return and covariance, as outlined in this [paper](https://doi.org/10.1007/s11128-022-03766-5). They are:\n", + "\n", + "$$\n", + "\\mu = \\left[\\prod ^m_{k=1}\\left(1+r_k^{(i)}\\right)\\right]^{\\frac{252}{m}}\\\\\n", + "\\sigma_{ij}=\\frac{252}{m}\\sum^m_{k=1}\\left(r_k^{(i)}-\\overline{r^{(i)}}\\right)\\left(r_k^{(j)}-\\overline{r^{(j)}}\\right)\n", + "$$\n", + "\n", + "Here is a demonstration of how to use this class:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "62bf0673", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/felixxu/Library/CloudStorage/OneDrive-ImperialCollegeLondon/文件/Code/TensorCircuit/tensorcircuit/templates/conversions.py:163: RuntimeWarning: invalid value encountered in power\n", + " ret = np.prod(change, axis=1) ** (252 / self.n_days)\n" + ] + } + ], + "source": [ + "import random\n", + "\n", + "# randomly generate historical data of 6 stocks in 1000 days\n", + "data = [[random.random() for i in range(1000)] for j in range(6)]\n", + "stock_data = StockData(data) # Create an instance\n", + "\n", + "# calculate the annualized return and covariance matrix\n", + "mu = stock_data.get_return()\n", + "sigma = stock_data.get_covariance()\n", + "\n", + "# some other information can also be obtained from this class\n", + "n_stocks = stock_data.n_stocks # number of stocks\n", + "n_days = stock_data.n_days # length of the time span\n", + "daily_change = stock_data.daily_change # relative change of each day" + ] + }, + { + "cell_type": "markdown", + "id": "0fb1d227", + "metadata": {}, + "source": [ + "In this analysis, we have carefully chosen six prominent stocks: Apple Inc. (AAPL), Microsoft Corporation (MSFT), NVIDIA Corporation (NVDA), Pfizer Inc. (PFE), Levi Strauss & Co. (LEVI), and Cisco Systems, Inc. (CSCO). We acquired their historical data spanning from 09/07/2022, to 09/07/2023 from Yahoo finance. Here are the return and covariance associated with this dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a7eb3a74", + "metadata": {}, + "outputs": [], + "source": [ + "# real-world stock data, calculated using the class above\n", + "# stock name: aapl, msft, nvda, pfe, levi, csco\n", + "# from 09/07/2022 to 09/07/2023\n", + "mu = [1.21141, 1.15325, 2.06457, 0.63539, 0.63827, 1.12224]\n", + "\n", + "sigma = np.array(\n", + " [\n", + " [0.08488, 0.06738, 0.09963, 0.02124, 0.05516, 0.04059],\n", + " [0.06738, 0.10196, 0.11912, 0.02163, 0.0498, 0.04049],\n", + " [0.09963, 0.11912, 0.31026, 0.01977, 0.10415, 0.06179],\n", + " [0.02124, 0.02163, 0.01977, 0.05175, 0.01792, 0.02137],\n", + " [0.05516, 0.0498, 0.10415, 0.01792, 0.19366, 0.0432],\n", + " [0.04059, 0.04049, 0.06179, 0.02137, 0.0432, 0.05052],\n", + " ]\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "f6dc53d4-7ed0-436d-aa1f-8674c56e756e", + "metadata": {}, + "source": [ + "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the pauli terms and weights" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3f6edcd5-3c10-49fc-86ea-160fc6d3187e", + "metadata": {}, + "outputs": [], + "source": [ + "q = 0.5 # the risk preference of investor\n", + "budget = 4 # Note that in this example, there are 6 assets, but a budget of only 4\n", + "penalty = 1.2\n", + "\n", + "Q = QUBO_from_portfolio(sigma, mu, q, budget, penalty)\n", + "portfolio_pauli_terms, portfolio_weights, portfolio_offset = QUBO_to_Ising(Q)" + ] + }, + { + "cell_type": "markdown", + "id": "730da712", + "metadata": {}, + "source": [ + "## Classical method\n", + "\n", + "We firstly use brutal force to calculate the cost of each combination. It will give us a clue on the performance of QAOA." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "168f7c36", + "metadata": {}, + "outputs": [], + "source": [ + "def print_Q_cost(Q, wrap=False, reverse=False):\n", + " n_stocks = len(Q)\n", + " states = []\n", + " for i in range(2**n_stocks):\n", + " a = f\"{bin(i)[2:]:0>{n_stocks}}\"\n", + " n_ones = 0\n", + " for j in a:\n", + " if j == \"1\":\n", + " n_ones += 1\n", + " states.append(a)\n", + "\n", + " cost_dict = {}\n", + " for selection in states:\n", + " x = np.array([int(bit) for bit in selection])\n", + " cost_dict[selection] = np.dot(x, np.dot(Q, x))\n", + " cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1]))\n", + " if reverse == True:\n", + " cost_sorted = dict(\n", + " sorted(cost_dict.items(), key=lambda item: item[1], reverse=True)\n", + " )\n", + " num = 0\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\t cost\")\n", + " print(\"-------------------------------------\")\n", + " for k, v in cost_sorted.items():\n", + " print(\"%10s\\t |\\t%.4f\" % (k, v))\n", + " num += 1\n", + " if (num >= 8) & (wrap == True):\n", + " break\n", + " print(\" ...\\t |\\t ...\")\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "6a9d41c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\t cost\n", + "-------------------------------------\n", + " 111001\t |\t-24.0487\n", + " 101101\t |\t-23.7205\n", + " 111100\t |\t-23.6414\n", + " 011101\t |\t-23.6340\n", + " 101011\t |\t-23.5123\n", + " 011011\t |\t-23.4316\n", + " 111010\t |\t-23.4269\n", + " 111101\t |\t-23.3742\n", + " ...\t |\t ...\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "print_Q_cost(Q, wrap=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c34f3398", + "metadata": {}, + "source": [ + "### Use QAOA\n", + "\n", + "Here, a standard QAOA ansatz with 12 layers is used. This circuit will be trained for 1200 times." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "9249ea96", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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xowZY2bOnGkSiYT5zne+Q10fxHbhhReau+++21x22WXGGGMuvfTSks8Hok7j8bjZsmWLefzxx81JJ51kZs+ebdrb2803v/nNgfgN9iuxnNurr75q5s+f770PBALmww8/NLfeeqv1sh2q27Bhw4wxxnzuc58zkkxdXZ1JJpNm5syZ3jEnnniiMcaY008/3Uj5/+FkMhlz1FFHecdce+21Zvfu3SYSiVj/TZW0xWIx895775np06ebpUuXekGEeh6Ybe7cuebFF1/c5zGbN2823/3ud733dXV1prOz08yePdtIMhMmTDDGGDN16lTvmAsuuMBks1lz9NFHW/+NlbL9+te/Ng8//HDJvl/+8pfm8ccfp64HaOsriAxEnV533XVmx44dJf9uzJ0716xdu/agy+zU0EwkEtHUqVO1ZMkSb58xRkuWLNGZZ55psWSHtsGDB0uSdu7cKUmaOnWqqqqqSur5vffe08aNG716PvPMM/Xmm29q27Zt3jHPPfecBg8erE996lNlLH3la2xs1OLFi/XCCy+U7KeeB8Yll1yiFStW6KmnnlJzc7NWrVqla665xvv8+OOP19FHH11Sz4lEQsuXLy+p5127dmnlypXeMUuWLFEul9Ppp59evh9T4V5++WVNnz5d48aNkySdfPLJOuuss/Tb3/5WEnXth4Gq0zPPPFMvvvii0um0d8xzzz2nCRMmaMiQIQdVxop/6N1AGjZsmMLhsJqbm0v2Nzc3a8KECZZKdWgLBAJ64IEH9NJLL+ntt9+WJI0YMULJZFJ79uwpOba5uVkjRozwjunrv0PxM+TNnj1bU6ZM6XMeE/U8ME444QRdf/31uv/++/X9739f06ZN049//GOlUik99thjXj31VY8967ln2JOkbDarnTt3Us893HPPPaqrq9O7776rbDarUCik22+/XU8++aQkUdc+GKg6HTFihNavX7/XdxQ/271798cuo1NBBAOvsbFREydO1FlnnWW7KIedY445Rj/60Y80Y8YMlrn2UTAY1IoVK3T77bdLklavXq2JEyfquuuu02OPPWa5dIeXWbNm6aqrrtKVV16pt99+W5MnT9YDDzygzZs3U9cOc2popqWlRZlMRvX19SX76+vrtXXrVkulOnTNnz9fX/rSl3TeeeepqanJ279161ZFo1FvyKaoZz1v3bq1z/8Oxc+QH3qpr6/XqlWrlE6nlU6nde655+of/uEflE6n1dzcTD0PgC1btuidd94p2bd27Vode+yxkrrraV//bmzdunWvu5VCoZCOOOII6rmH++67T/fcc49+/vOf66233tITTzyhefPmqaGhQRJ17YeBqlM//y1xKoik02mtXLlS06dP9/YFAgFNnz5dr7zyisWSHXrmz5+vyy+/XJ///Oe1YcOGks9WrlypVCpVUs/jx4/XmDFjvHp+5ZVXNGnSJA0fPtw7ZsaMGdqzZ89ejYKrXnjhBU2cOFGTJ0/2tj//+c9atGiRJk+erBUrVlDPA2DZsmU68cQTS/aNHz9eGzdulCStX79eW7ZsKanneDyu008/vaSehw4dqilTpnjHfP7zn1cwGNTy5cvL8CsODbW1tcrlciX7stmsgsF8U0RdD7yBqtNXXnlFZ599tsLh7oGUGTNm6N133z2oYZki67N8y7nNmjXLdHZ2mq9+9atmwoQJ5ic/+YnZuXNnyV0FbPveGhsbza5du8zZZ59t6uvrva26uto75qGHHjIbNmww5557rpkyZYpZtmyZWbZsmfd58bbS3/3ud+bkk082559/vmlubua20v1sPe+aoZ4HZjv11FNNKpUyDQ0NZuzYseaKK64wbW1t5sorr/SOueWWW8zOnTvNxRdfbCZOnGieeeaZPm9/XLlypZk2bZr5zGc+Y9577z2nbynta1u4cKHZtGmTd/vuZZddZrZt22buuece6vogtlgsZk455RRzyimnGGOMufHGG80pp5xiRo8ePWB1WldXZ7Zs2WIeffRRc9JJJ5lZs2aZtrY2bt/9uNvf//3fmw0bNpiuri7z6quvmtNOO816mQ6l7aN87Wtf846JRqPmwQcfNDt27DBtbW3m6aefNvX19SXfc+yxx5rFixeb9vZ2s23bNnPfffeZUChk/fdV8tY7iFDPA7N98YtfNGvWrDGdnZ3mnXfeMddcc81ex9x5551my5YtprOz0/z+978348aNK/l86NChZtGiRSaRSJjdu3eb//zP/zSxWMz6b6ukbdCgQWbevHlmw4YNpqOjw7z//vvm7rvv3utWcur6wLZzzjmnz3+TFy5cOKB1OmnSJPPiiy+azs5Os2nTJnPLLbcMSPkDhRcAAABl59QcEQAAUFkIIgAAwBqCCAAAsIYgAgAArCGIAAAAawgiAADAGoIIAACwhiACAACsIYgAAABrCCIAAMAagggAALCGIAIAAKz5/+r+so8y6PhtAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "iterations = 1000\n", + "nlayers = 12\n", + "loss_list = []\n", + "\n", + "# define a callback function to recode the loss\n", + "def record_loss(loss, params):\n", + " loss_list.append(loss)\n", + "\n", + "# apply QAOA on this portfolio optimization problem\n", + "final_params = QUBO_QAOA(Q, nlayers, iterations, callback=record_loss)\n", + "\n", + "p = plt.plot(loss_list)" + ] + }, + { + "cell_type": "markdown", + "id": "9126333d", + "metadata": {}, + "source": [ + "Create a function to visualize the results, listing all combinations in descending order of probability." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "4a2c60e4", + "metadata": {}, + "outputs": [], + "source": [ + "def print_result_prob(c, wrap=False, reverse=False):\n", + " states = []\n", + " n_qubits = c._nqubits\n", + " for i in range(2**n_qubits):\n", + " a = f\"{bin(i)[2:]:0>{n_qubits}}\"\n", + " states.append(a)\n", + " # Generate all possible binary states for the given number of qubits\n", + "\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + " # Calculate the probabilities of each state using the circuit's probability method\n", + "\n", + " sorted_indices = np.argsort(probs)[::-1]\n", + " if reverse == True:\n", + " sorted_indices = sorted_indices[::-1]\n", + " state_sorted = np.array(states)[sorted_indices]\n", + " prob_sorted = np.array(probs)[sorted_indices]\n", + " # Sort the states and probabilities in descending order based on the probabilities\n", + "\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\tprobability\")\n", + " print(\"-------------------------------------\")\n", + " if wrap == False:\n", + " for i in range(len(states)):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " # Print the sorted states and their corresponding probabilities\n", + " elif wrap == True:\n", + " for i in range(4):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\" ... ...\")\n", + " for i in range(-5, -1):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "680f52d2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 111001\t |\t 0.1169\n", + " 101101\t |\t 0.0872\n", + " 111100\t |\t 0.0823\n", + " 101011\t |\t 0.0809\n", + " ... ...\n", + " 000100\t |\t 0.0000\n", + " 010000\t |\t 0.0000\n", + " 000010\t |\t 0.0000\n", + " 000001\t |\t 0.0000\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c_final = QAOA_ansatz_for_Ising(\n", + " final_params, nlayers, portfolio_pauli_terms, portfolio_weights\n", + ")\n", + "print_result_prob(c_final, wrap=True)" + ] + }, + { + "cell_type": "markdown", + "id": "71c7a0e0", + "metadata": {}, + "source": [ + "The highest probability corresponds to the best combination, thereby ensuring consistency with the classical approach.\n", + "\n", + "## Use XY mixer to improve the performance\n", + "\n", + "In the context of QAOA, XY mixers serve as a specific type of quantum gate to augment the optimization process. XY mixers, which are quantum gates introducing qubit interactions through controlled rotations, enable modification of the quantum system's state. The utilization of XY mixers in QAOA provides several advantages. They facilitate more efficient exploration of the solution space, thereby potentially improving the algorithm's overall performance. Moreover, XY mixers can amplify gradients of the objective function during optimization and enhance quantum circuit depth. Notably, in scenarios like portfolio optimization (covered in another tutorial), where constraints exist, XY mixers preserve the constraints associated with individual combinations while allowing for smooth transitions between them.\n", + "\n", + "It is crucial to consider that the choice of mixers relies on the specific problem under consideration, its unique characteristics, and the quantum hardware available." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "3d558b9f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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VqxYoY6ODrtLGdY4zvHBcY4fjnV8cJzjYygc52E5YRcAAAxfjLwAAICEQngBAAAJhfACAAASCuEFAAAkFMJLP33lK1/RgQMH1NbWpl27dqmwsNDukhLKt771Lf3lL3+Rz+dTbW2tfvvb32rGjBk9+qSkpGj16tWqr69Xc3OzfvOb32jChAk9+kyaNEm///3v1dLSotraWn3/+9+Xy+WK51dJKA888ICMMXr00UcjyzjOsTNx4kQ9/fTTqq+vV2trq958803Nnz+/R58HH3xQR48eVWtrq/7whz9o+vTpPdZnZmZqw4YNampqktfr1bp165Senh7PrzGkOZ1OPfTQQ6qsrFRra6v279+v73znOx/px3GOzic+8Qk999xzqqqqkjFG11577Uf6xOKYzp49Wzt27FBbW5s++OADffOb34zZdzC0vttNN91k2tvbzW233WbOP/988/jjj5uGhgYzfvx422tLlLZlyxbzuc99zlxwwQVmzpw55ve//705ePCgSUtLi/T52c9+Zg4dOmSuuOIKU1BQYF577TWzc+fOyHqn02nefPNNs3XrVjN37lxz5ZVXmrq6OvMf//Eftn+/odguuugiU1lZafbs2WMeffRRjnOM29ixY82BAwfMf/7nf5rCwkJz7rnnmuLiYjN16tRIn/vvv994vV5zzTXXmNmzZ5vf/e535v333zcpKSmRPps3bzZ//etfzcUXX2wuvfRS8+6775qNGzfa/v2GSlu+fLk5duyY+dSnPmUmT55srr/+euPz+cxXv/pVjvMg2pVXXmm++93vmuuuu84YY8y1117bY30sjqnH4zHV1dXm6aefNhdccIG5+eabTUtLi/niF78Yi+9g/0Ec6m3Xrl3msccei7x3OBzmyJEj5oEHHrC9tkRt48aNM8YY84lPfMJIMhkZGaajo8Ncf/31kT4zZ840xhizYMECI3X+xxYMBs2ECRMifb70pS+ZxsZG43a7bf9OQ6mlp6ebd955xyxZssS8/PLLkfDCcY5dW7lypdmxY0effY4ePWr+5V/+JfI+IyPDtLW1mZtvvtlIMvn5+cYYY+bPnx/ps3TpUhMKhUxubq7t33EotOeff96sW7eux7Lf/OY35umnn+Y4x6j1Fl5icUzvuusuc/z48R7/bqxcudLs27dv0DVz2ugM3G635s+fr23btkWWGWO0bds2FRUV2VhZYhszZowkqaGhQZI0f/58JScn9zjO77zzjg4dOhQ5zkVFRdq7d6/q6uoifV566SWNGTNGs2bNimP1Q99Pf/pTvfDCC9q+fXuP5Rzn2Lnmmmv0xhtv6Ne//rVqa2tVXl6uO+64I7J+ypQpys3N7XGsfT6fdu/e3eNYe71elZWVRfps27ZN4XBYCxYsiN+XGcJee+01LVmyROedd54kac6cOfr4xz+uLVu2SOI4WyFWx7SoqEg7duxQIBCI9HnppZeUn5+vsWPHDqrGYflgxlgaN26ckpKSVFtb22N5bW2t8vPzbaoqsTkcDv3oRz/Szp079fe//12SlJOTo46ODjU1NfXoW1tbq5ycnEif3v536F6HTjfffLMKCgp6nZfFcY6dqVOn6stf/rJ++MMf6uGHH1ZhYaF+8pOfyO/366mnnoocq96O5anH+tSQKEmhUEgNDQ0c6y6PPPKIMjIyVFFRoVAoJJfLpW9/+9t65plnJInjbIFYHdOcnBwdOHDgI5/Rva6xsXHANRJeEHc//elPdeGFF+rjH/+43aUMO2effbZ+/OMfq7i4mFukW8zpdOqNN97Qt7/9bUnSnj17dOGFF+quu+7SU089ZXN1w8dNN92kkpIS3XLLLfr73/+uefPm6Uc/+pGOHj3KcR7BOG10BvX19QoGg8rOzu6xPDs7WzU1NTZVlbgee+wxLVu2TFdccYWqqqoiy2tqapSSkhI5ndTt1ONcU1PT6/8O3evQeVooOztb5eXlCgQCCgQCuvzyy3XPPfcoEAiotraW4xwj1dXVevvtt3ss27dvn8455xxJJ49VX/921NTUfORKL5fLpaysLI51lx/84Ad65JFH9Ktf/UpvvfWWNmzYoEcffVTLly+XxHG2QqyOqZX/lhBeziAQCKisrExLliyJLHM4HFqyZIlKS0ttrCzxPPbYY/rMZz6jxYsX6+DBgz3WlZWVye/39zjOM2bM0OTJkyPHubS0VLNnz9b48eMjfYqLi9XU1PSRH5GRavv27brwwgs1b968SHv99de1ceNGzZs3T2+88QbHOUZeffVVzZw5s8eyGTNm6NChQ5KkAwcOqLq6usex9ng8WrBgQY9jnZmZqYKCgkifxYsXy+l0avfu3XH4FkNfWlqawuFwj2WhUEhOZ+fPF8c59mJ1TEtLS7Vo0SIlJZ08yVNcXKyKiopBnTLqZvtM56HebrrpJtPW1mZuvfVWk5+fb37xi1+YhoaGHldj0PpuP/3pT43X6zWLFi0y2dnZkTZq1KhIn5/97Gfm4MGD5vLLLzcFBQXm1VdfNa+++mpkffclvC+++KKZM2eO+eQnP2lqa2u5hPcM7dSrjTjOsWsXXXSR8fv9Zvny5WbatGnms5/9rDlx4oS55ZZbIn3uv/9+09DQYK6++mpz4YUXmt/+9re9Xm5aVlZmCgsLzcKFC80777wzoi/h/XB78sknzeHDhyOXSl933XWmrq7OPPLIIxznQbT09HQzd+5cM3fuXGOMMffee6+ZO3eumTRpUsyOaUZGhqmurja//OUvzQUXXGBuuukmc+LECS6Vjme7++67zcGDB017e7vZtWuXufjii22vKZHa6Xzuc5+L9ElJSTGrV682x48fNydOnDDPPvusyc7O7vE555xzjnnhhRdMS0uLqaurMz/4wQ+My+Wy/fsN5fbh8MJxjl379Kc/bd58803T1tZm3n77bXPHHXd8pM+DDz5oqqurTVtbm/nDH/5gzjvvvB7rMzMzzcaNG43P5zONjY3miSeeMOnp6bZ/t6HSRo8ebR599FFz8OBB09raavbv32+++93vfuSyfY5zdO2yyy7r9d/kJ598MqbHdPbs2WbHjh2mra3NHD582Nx///0xqd/R9QIAACAhMOcFAAAkFMILAABIKIQXAACQUAgvAAAgoRBeAABAQiG8AACAhEJ4AQAACYXwAgAAEgrhBQAAJBTCCwAASCiEFwAAkFAILwAAIKH8f9rNGcxO0L85AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "loss_list = []\n", + "final_params = QUBO_QAOA(Q, nlayers, iterations, mixer=\"XY\", callback=record_loss)\n", + "\n", + "p = plt.plot(loss_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "d83fc94c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 111001\t |\t 0.1553\n", + " 001001\t |\t 0.1260\n", + " 101001\t |\t 0.1180\n", + " 111000\t |\t 0.0934\n", + " ... ...\n", + " 100110\t |\t 0.0000\n", + " 000111\t |\t 0.0000\n", + " 000101\t |\t 0.0000\n", + " 000100\t |\t 0.0000\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c_final = QAOA_ansatz_for_Ising(\n", + " final_params, nlayers, portfolio_pauli_terms, portfolio_weights, mixer='XY'\n", + ")\n", + "print_result_prob(c_final, wrap=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc_dev", + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 44783675609fe7169d19fe303b606e9929940c7b Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 12 Jul 2023 12:50:20 +0100 Subject: [PATCH 002/139] add functions relavent of QAOA --- docs/source/tutorials/QAOA_funcs.py | 439 +++++++++++++++++++++ tensorcircuit/applications/__init__.py | 2 + tensorcircuit/applications/optimization.py | 328 +++++++++++++++ tensorcircuit/templates/__init__.py | 1 + tensorcircuit/templates/blocks.py | 96 ++++- tensorcircuit/templates/conversions.py | 202 +++++++++- 6 files changed, 1066 insertions(+), 2 deletions(-) create mode 100644 docs/source/tutorials/QAOA_funcs.py create mode 100644 tensorcircuit/applications/optimization.py diff --git a/docs/source/tutorials/QAOA_funcs.py b/docs/source/tutorials/QAOA_funcs.py new file mode 100644 index 00000000..87d35d59 --- /dev/null +++ b/docs/source/tutorials/QAOA_funcs.py @@ -0,0 +1,439 @@ +### +### functions for QAOA problems +### + +from typing import List, Tuple, Callable, Any +import tensorcircuit as tc +import numpy as np +import tensorflow as tf +import matplotlib.pyplot as plt +from IPython.display import clear_output +from functools import partial +import scipy.optimize as optimize + +Array = any +Tensor = Any + + +# moved +def QUBO_to_Ising(Q: List[list]) -> Tuple[List[list], list, float]: + """ + Cnvert the Q matrix into a the indication of pauli terms, the corresponding weights, and the offset. + The outputs are used to construct an Ising Hamiltonian for QAOA. + + :param Q: The n-by-n square and symmetric Q-matrix. + :return pauli_terms: A list of 0/1 series, where each element represents a Pauli term. + A value of 1 indicates the presence of a Pauli-Z operator, while a value of 0 indicates its absence. + :return weights: A list of weights corresponding to each Pauli term. + :return offset: A float representing the offset term of the Ising Hamiltonian. + """ + + # input is n-by-n symmetric numpy array corresponding to Q-matrix + # output is the components of Ising Hamiltonian + + n = Q.shape[0] + + # square matrix check + if Q[0].shape[0] != n: + raise ValueError("Matrix is not a square matrix.") + + offset = ( + np.triu(Q, 0).sum() / 2 + ) # Calculate the offset term of the Ising Hamiltonian + pauli_terms = [] # List to store the Pauli terms + weights = ( + -np.sum(Q, axis=1) / 2 + ) # Calculate the weights corresponding to each Pauli term + + for i in range(n): + term = np.zeros(n) + term[i] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a single qubit + + for i in range(n - 1): + for j in range(i + 1, n): + term = np.zeros(n) + term[i] = 1 + term[j] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a two-qubit interaction + + weight = ( + Q[i][j] / 2 + ) # Calculate the weight for the two-qubit interaction term + weights = np.concatenate( + (weights, weight), axis=None + ) # Add the weight to the weights list + + return pauli_terms, weights, offset + + +def Ising_loss(c: tc.Circuit, pauli_terms: List[list], weights: list) -> float: + """ + computes the loss function for the Ising model based on a given quantum circuit, + a list of Pauli terms, and corresponding weights. + The offset is ignored. + + :param c: A quantum circuit object generating the state. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :return loss: A real number representing the computed loss value. + """ + loss = 0.0 + for k in range(len(pauli_terms)): + term = pauli_terms[k] + index_of_ones = [] + + for l in range(len(term)): + if term[l] == 1: + index_of_ones.append(l) + + # Compute expectation value based on the number of qubits involved in the Pauli term + if len(index_of_ones) == 1: + delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]]) + # Compute expectation value for a single-qubit Pauli term + else: + delta_loss = weights[k] * c.expectation_ps( + z=[index_of_ones[0], index_of_ones[1]] + ) + # Compute expectation value for a two-qubit Pauli term + + loss += delta_loss + + return K.real(loss) + + +def QAOA_loss( + nlayers: int, pauli_terms: List[list], weights: list, params: list +) -> float: + """ + computes the loss function for the Quantum Approximate Optimization Algorithm (QAOA) applied to the Ising model. + + :param nlayers: The number of layers in the QAOA ansatz. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :param params: A list of parameter values used in the QAOA ansatz. + :return: The computed loss value. + """ + c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights) + # Obtain the quantum circuit using QAOA_from_Ising function + + return Ising_loss(c, pauli_terms, weights) + # Compute the Ising loss using Ising_loss function on the obtained circuit + + +def QUBO_QAOA( + Q: List[list], + ansatz: Callable[[list, int, List[list], list], tc.Circuit], + nlayers: int, + iterations: int, + vvag: bool = False, + ncircuits: int = 10, +) -> list: + """ + Performs the QAOA on a given QUBO problem. + + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param ansatz: The ansatz function to be used for the QAOA. + :param nlayers: The number of layers in the QAOA ansatz. + :param iterations: The number of iterations to run the optimization. + :param vvag (optional): A flag indicating whether to use vectorized variational adjoint gradient. Default is False. + :param ncircuits (optional): The number of circuits when using vectorized variational adjoint gradient. Default is 10. + :return params: The optimized parameters for the ansatz circuit. + """ + try: + K + except NameError: + print("select a backend and assign it to K.") + + pauli_terms, weights, offset = QUBO_to_Ising(Q) + learning_rate = 1e-2 + + loss_val_grad = K.value_and_grad(partial(ansatz, nlayers, pauli_terms, weights)) + params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5) + # Initialize the parameters for the ansatz circuit + + if vvag == True: + loss_val_grad = tc.backend.vvag(loss_val_grad, argnums=0, vectorized_argnums=0) + params = K.implicit_randn(shape=[ncircuits, 2 * nlayers], stddev=0.1) + # Use vectorized variational adjoint gradient (vvag) if vvag flag is set to True + + loss_val_grad_jit = K.jit(loss_val_grad, static_argnums=(1, 2)) + + opt = K.optimizer(tf.keras.optimizers.Adam(learning_rate)) + # Define the optimizer (Adam optimizer) with the specified learning rate + + for i in range(iterations): + loss, grads = loss_val_grad_jit(params) + # Calculate the loss and gradients using the loss_val_grad_jit function + + params = opt.update(grads, params) + # Update the parameters using the optimizer and gradients + + if i % 100 == 0: # print the cost every 100 iterations + print(K.numpy(loss)) + + return params + + +# calcelled +def print_result_prob(c: tc.Circuit, wrap: bool = False, reverse: bool = False) -> None: + """ + Print the results and probabilities of a given quantum circuit. + The default order is from the highest probability to the lowest one + + :param c: The quantum circuit to print the results and probabilities. + :param wrap (optional): A flag indicating whether to wrap the output. Default is False. + :param reverse (optional): A flag indicating whether to reverse the order of the output. Default is False. + """ + try: + K + except NameError: + print("select a backend and assign it to K.") + + states = [] + n_qubits = c._nqubits + for i in range(2**n_qubits): + a = f"{bin(i)[2:]:0>{n_qubits}}" + states.append(a) + # Generate all possible binary states for the given number of qubits + + probs = K.numpy(c.probability()).round(decimals=4) + # Calculate the probabilities of each state using the circuit's probability method + + sorted_indices = np.argsort(probs)[::-1] + if reverse == True: + sorted_indices = sorted_indices[::-1] + state_sorted = np.array(states)[sorted_indices] + prob_sorted = np.array(probs)[sorted_indices] + # Sort the states and probabilities in descending order based on the probabilities + + print("\n-------------------------------------") + print(" selection\t |\tprobability") + print("-------------------------------------") + if wrap == False: + for i in range(len(states)): + print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) + # Print the sorted states and their corresponding probabilities + elif wrap == True: + for i in range(4): + print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) + print(" ... ...") + for i in range(-4, -1): + print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) + print("-------------------------------------") + + +# calcelled +def print_result_cost( + c: tc.Circuit, Q: List[list], wrap: bool = False, reverse: bool = False +) -> None: + """ + Print the results and costs of a given quantum circuit. + Specificly designed for the variational circuit. + The default order is from the highest probability to the lowest one. + + :param c: The quantum circuit to print the results and probabilities. + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param wrap (optional): A flag indicating whether to wrap the output. Default is False. + :param reverse (optional): A flag indicating whether to reverse the order of the output. Default is False. + """ + cost_dict = {} + states = [] + n_qubits = c._nqubits + for i in range(2**n_qubits): + a = f"{bin(i)[2:]:0>{n_qubits}}" + states.append(a) + # Generate all possible binary states for the given number of qubits + for selection in states: + x = np.array([int(bit) for bit in selection]) + cost_dict[selection] = np.dot(x, np.dot(Q, x)) + cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1])) + if reverse == True: + cost_sorted = dict( + sorted(cost_dict.items(), key=lambda item: item[1], reverse=True) + ) + num = 0 + print("\n-------------------------------------") + print(" selection\t |\t cost") + print("-------------------------------------") + for k, v in cost_sorted.items(): + print("%10s\t |\t%.4f" % (k, v)) + num += 1 + if (num >= 8) & (wrap == True): + break + print("-------------------------------------") + + +# cancelled +def print_Q_cost(Q: List[list], wrap: bool = False, reverse: bool = False) -> None: + n_stocks = len(Q) + states = [] + for i in range(2**n_stocks): + a = f"{bin(i)[2:]:0>{n_stocks}}" + n_ones = 0 + for j in a: + if j == "1": + n_ones += 1 + states.append(a) + + cost_dict = {} + for selection in states: + x = np.array([int(bit) for bit in selection]) + cost_dict[selection] = np.dot(x, np.dot(Q, x)) + cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1])) + if reverse == True: + cost_sorted = dict( + sorted(cost_dict.items(), key=lambda item: item[1], reverse=True) + ) + num = 0 + print("\n-------------------------------------") + print(" selection\t |\t cost") + print("-------------------------------------") + for k, v in cost_sorted.items(): + print("%10s\t |\t%.4f" % (k, v)) + num += 1 + if (num >= 8) & (wrap == True): + break + print("-------------------------------------") + + +# moved +class StockData: + """ + convert real-world stock data to the inputs of QAOA. + """ + + def __init__(self, data: Tensor) -> None: + """ + stock data object + + :param data: real-world stock data, in the form of several lists of daily price. + """ + self.data = data # add data + self.n_stocks = len(data) # num of stocks + self.n_days = len(data[1]) + + # check the number of days + n_days = [len(i) for i in data] + if max(n_days) != (sum(n_days) / len(n_days)): + raise Exception("timespan of stocks should be the same") + + # calculate the daily percentage price change + self.daily_change = [] # daily percentage price change + for i in range(self.n_stocks): + each_stcok = [] + for j in range(self.n_days - 1): + each_stcok.append((data[i][j + 1] - data[i][j]) / data[i][j]) + self.daily_change.append(each_stcok) + + def get_return(self) -> Array: + """ + :return ret: annualized return (mu) + """ + ret = np.mean(self.daily_change, axis=1) + return ret + + def get_covariance(self) -> Array: + """ + :return cov: symmetric annualized covariance matrix (sigma) + """ + return np.cov(self.daily_change) + + def get_pentalty( + self, cov: Array, ret: Array, risk_pre: float, budget: int + ) -> float: + """ + calculate the pentalty using the method in https://link.springer.com/article/10.1007/s11128-022-03766-5 + brutal force is used + + :param cov: symmetrix annualized covariance matrix (sigma) + :param ret: annualized return (ret) + :param risk_pre: risk preference of the investor + :param budge: the number of assets to be chosen for the portfolio + """ + # get all fesible and unfeasible states + self.f_state = [] # feasible states (num of '1's equal to budge) + self.uf_state = [] # unfeasible states + self.all_state = [] + for i in range(2**self.n_stocks): + state = f"{bin(i)[2:]:0>{self.n_stocks}}" + n_ones = 0 + for j in state: + if j == "1": + n_ones += 1 + self.all_state.append(state) + if n_ones == budget: + self.f_state.append(state) + else: + self.uf_state.append(state) + + # determine the penalty factor + mark = False + penalty = 0 # initial value + while mark == False: + R = np.diag(ret) + S = np.ones((self.n_stocks, self.n_stocks)) - 2 * budget * np.diag( + np.ones(self.n_stocks) + ) + Q = risk_pre * cov - R + penalty * S + F = [] + for state in self.f_state: + x = np.array([int(bit) for bit in state]) + F.append(np.dot(x, np.dot(Q, x)) + penalty * budget**2) + Fmin = np.amin(F) + Fbar = np.mean(F) + F = [] + for state in self.uf_state: + x = np.array([int(bit) for bit in state]) + F.append(np.dot(x, np.dot(Q, x)) + penalty * budget**2) + Fmin_uf = np.amin(F) + location = np.where(F == Fmin_uf)[0][0] + if Fmin_uf < 0.5 * (Fmin + Fbar): + n_ones = 0 + for j in self.uf_state[location]: + if j == "1": + n_ones += 1 + penalty += (0.5 * (Fmin + Fbar) - Fmin_uf) / (n_ones - budget) ** 2 + # mark = True + else: + mark = True # ready to return the penalty + return penalty + + +# moved +def QUBO_from_portfolio(cov: Array, mean: Array, q: float, B: int, t: float) -> Tensor: + """ + convert portfolio parameters to a Q matrix + :param cov: n-by-n covariance numpy array + :param mean: numpy array of means + :param q: the risk preference of investor + :param B: budget + :param t: penalty factor + :return Q: n-by-n symmetric Q matrix + """ + n = cov.shape[0] + R = np.diag(mean) + S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n)) + + Q = q * cov - R + t * S + return Q + + +def print_output(c): + n = c._nqubits + N = 2**n + # Calculate the total number of states based on the number of qubits + + x_label = r"$\left|{0:0" + str(n) + r"b}\right>$" + labels = [x_label.format(i) for i in range(N)] + # Generate labels for the x-axis representing the binary states + + plt.bar(range(N), c.probability()) + # Create a bar plot with the probabilities of each state + + plt.xticks(range(N), labels, rotation=70) + # Set the x-axis ticks to the generated labels and rotate them for better visibility diff --git a/tensorcircuit/applications/__init__.py b/tensorcircuit/applications/__init__.py index 70d128b0..200fcbe6 100644 --- a/tensorcircuit/applications/__init__.py +++ b/tensorcircuit/applications/__init__.py @@ -3,3 +3,5 @@ the code inside is subject to change, be caution to use. Most of the useful code is and will be refactored and copied to other parts of tensorcircuit. """ + +from . import optimization \ No newline at end of file diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py new file mode 100644 index 00000000..fd05b693 --- /dev/null +++ b/tensorcircuit/applications/optimization.py @@ -0,0 +1,328 @@ +""" +modules for QUBO problems in QAOA +""" + +from typing import List, Callable, Any + +import tensorcircuit as tc +import numpy as np +from functools import partial +import tensorflow as tf +import scipy.optimize as optimize + +from ..cons import backend +from ..templates.blocks import QAOA_ansatz_for_Ising +from ..templates.conversions import QUBO_to_Ising +from tensorflow.python.ops.numpy_ops import np_config + +np_config.enable_numpy_behavior() + +Circuit = Any +Tensor = Any + + +def Ising_loss(c: Circuit, pauli_terms: List[list], weights: list) -> float: + """ + computes the loss function for the Ising model based on a given quantum circuit, + a list of Pauli terms, and corresponding weights. + The offset is ignored. + + :param c: A quantum circuit object generating the state. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :return loss: A real number representing the computed loss value. + """ + loss = 0.0 + for k in range(len(pauli_terms)): + term = pauli_terms[k] + index_of_ones = [] + + for l in range(len(term)): + if term[l] == 1: + index_of_ones.append(l) + + # Compute expectation value based on the number of qubits involved in the Pauli term + if len(index_of_ones) == 1: + delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]]) + # Compute expectation value for a single-qubit Pauli term + else: + delta_loss = weights[k] * c.expectation_ps( + z=[index_of_ones[0], index_of_ones[1]] + ) + # Compute expectation value for a two-qubit Pauli term + + loss += delta_loss + + return backend.real(loss) + + +def QAOA_loss( + nlayers: int, pauli_terms: List[list], weights: list, params: list, mixer: str = "X" +) -> float: + """ + computes the loss function for the Quantum Approximate Optimization Algorithm (QAOA) applied to the Ising model. + + :param nlayers: The number of layers in the QAOA ansatz. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :param params: A list of parameter values used in the QAOA ansatz. + :return: The computed loss value. + """ + c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights, mixer=mixer) + # Obtain the quantum circuit using QAOA_from_Ising function + + return Ising_loss(c, pauli_terms, weights) + # Compute the Ising loss using Ising_loss function on the obtained circuit + + +def QUBO_QAOA( + Q: List[list], + nlayers: int, + iterations: int, + vvag: bool = False, + ncircuits: int = 10, + init_params: list = None, + mixer: str = "X", + learning_rate: float = 1e-2, + jit: bool = True, + callback: callable = None, +) -> list: + """ + Performs the QAOA on a given QUBO problem. + Adam optimizer from TensorFlow is used. + + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param iterations: The number of iterations to run the optimization. + :param vvag (optional): A flag indicating whether to use vectorized variational adjoint gradient. Default is False. + :param ncircuits (optional): The number of circuits when using vectorized variational adjoint gradient. Default is 10. + :param init_params (optional): The initial parameters for the ansatz circuit. Default is None, which initializes the parameters randomly. + :paran mixer (optional): The mixer operator to use. Default is "X". The other options are "X", "XY", "XY_full", and "ZZ". + :param learning_rate (optional): The learning rate for the Adam optimizer. Default is 1e-2. + :param jit (optional): A flag indicating whether to use just-in-time compilation. Default is True. + :param callback (optional): A callback function that is executed during each iteration. Default is None. + :return params: The optimized parameters for the ansatz circuit. + """ + if backend != tc.set_backend("tensorflow"): + raise ValueError("`QUBO_QAOA` is designed for tensorflow backend.") + # Check if the backend is set to TensorFlow. Raise an error if it is not. + + pauli_terms, weights, offset = QUBO_to_Ising(Q) + + loss_val_grad = backend.value_and_grad( + partial(QAOA_loss, nlayers, pauli_terms, weights, mixer=mixer) + ) + # Define the loss and gradients function using value_and_grad, which calculates both the loss value and gradients. + + if init_params is None: + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + if vvag == True: + loss_val_grad = tc.backend.vvag( + loss_val_grad, argnums=0, vectorized_argnums=0 + ) + params = backend.implicit_randn(shape=[ncircuits, 2 * nlayers], stddev=0.1) + # If init_params is not provided, initialize the parameters randomly. + # If vvag flag is set to True, use vectorized variational adjoint gradient (vvag) with multiple circuits. + else: + params = init_params + # If init_params is provided, use the provided parameters. + # Initialize the parameters for the ansatz circuit. + + if jit == True: + loss_val_grad = backend.jit(loss_val_grad, static_argnums=(1, 2)) + # Use just-in-time compilation (jit) if jit flag is set to True. + # This can improve the performance by pre-compiling the loss and gradients function. + + opt = backend.optimizer(tf.keras.optimizers.Adam(learning_rate)) + # Define the optimizer (Adam optimizer) with the specified learning rate. + + for i in range(iterations): + loss, grads = loss_val_grad(params) + # Calculate the loss and gradients using the loss_val_grad_jit function. + + params = opt.update(grads, params) + # Update the parameters using the optimizer and gradients. + + if callback is not None: + callback(loss, params) + # Execute the callback function with the current loss and parameters. + + return params + # Return the optimized parameters for the ansatz circuit. + + +def cvar_value(r: list, p: list, percent: float) -> float: + """ + Calculate the Conditional Value at Risk (CVaR) according to the measurement results. + + :param r: The results showing after measurements. + :param p: Probabilities corresponding to each result. + :param percent: The cut-off percentage of CVaR. + :return: The calculated CVaR value. + """ + sorted_indices = np.argsort(r) + p = np.array(p)[sorted_indices] + r = np.array(r)[sorted_indices] + + sump = 0.0 # The sum of probabilities. + count = 0 + cvar_result = 0.0 + + # Iterate over the sorted results and calculate CVaR. + while sump < percent: + if round(sump + p[count], 6) >= percent: + # Add the remaining portion of the last result that exceeds the cut-off percentage. + cvar_result += r[count] * (percent - sump) + count += 1 + break + else: + # Add the entire result to the CVaR calculation. + sump += p[count] + cvar_result += r[count] * p[count] + count += 1 + + cvar_result /= percent + return cvar_result + +def cvar_from_circuit( + circuit: Circuit, nsamples: int, Q: Tensor, alpha: float +) -> float: + """ + Directly calculate the Conditional Value at Risk (CVaR) from a circuit. + The CVaR depends on a bunch of measurements. + + :param circuit: The quantum circuit used to prepare the state. + :param nsamples: The number of samples to take for measurements. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param alpha: The cut-off percentage for CVaR. + :return: The calculated CVaR value. + """ + s = circuit.state() + results = tc.quantum.measurement_results( + s, counts=nsamples, format="count_dict_bin" + ) # Get readouts from the measurements. + results = {k: v / nsamples for k, v in results.items()} # Normalize the results. + values = [] # List to store the measurement values. + probabilities = [] # List to store the corresponding probabilities. + + # Iterate over the measurement results and calculate the values and probabilities. + for k, v in results.items(): + x = np.array([int(bit) for bit in k]) + values.append(np.dot(x, np.dot(Q, x))) + probabilities.append(v) + + cvar_result = cvar_value(values, probabilities, alpha) + # Calculate the CVaR using the cvar_value function. + + return cvar_result + + +def cvar_from_expectation(circuit, Q, alpha: float) -> float: + """ + Calculate the Conditional Value at Risk (CVaR) from the expectation values of a quantum circuit. + + :param circuit: The quantum circuit. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param alpha: The cut-off percentage for CVaR. + :return: The calculated CVaR value. + """ + prob = circuit.probability() # Get the probabilities of the circuit states. + prob /= np.sum(prob) + states = [] + + # Generate all possible binary states based on the length of Q. + for i in range(2 ** len(Q)): + a = f"{bin(i)[2:]:0>{len(Q)}}" + states.append(a) + + values = [] + for state in states: + x = np.array([int(bit) for bit in state]) + values.append(np.dot(x, np.dot(Q, x))) + # Calculate the values by taking the dot product of each state with the Q-matrix. + + cvar_result = cvar_value(values, prob, alpha) + # Calculate the CVaR using the cvar_value function. + + return cvar_result + + +def cvar_loss(nlayers, Q, nsamples, alpha, fake, params): + """ + Calculate the CVaR loss for a given QUBO problem using the QAOA ansatz. + + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param nsamples: The number of samples to take for measurements in the CVaR calculation. + :param alpha: The cut-off percentage for CVaR. + :param fake: A flag indicating the type of CVaR ansatz (circuit-based or expectation-based). + :param params: The parameters for the QAOA ansatz circuit. + :return: The calculated CVaR loss. + """ + pauli_terms, weights, offset = QUBO_to_Ising(Q) + + c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights) + # Generate the QAOA ansatz circuit for the given parameters. + + if fake == False: + return cvar_from_circuit(c, nsamples, Q, alpha) + # Calculate CVaR using circuit-based measurement results. + elif fake == True: + return cvar_from_expectation(c, Q, alpha) + # Calculate CVaR using expectation values of the circuit. + else: + raise ValueError("Invalid CVaR ansatz type.") + # Raise an error if an invalid CVaR ansatz type is provided. + + +def QUBO_QAOA_cvar( + Q: List[list], + nlayers: int, + alpha: int, + nsamples: int = 1000, + callback: callable = None, + fake: bool = False, + maxiter: int = 1000, + init_params: list = None, +) -> list: + """ + Perform the QUBO QAOA optimization with CVaR as the loss function. + + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param ansatz: The ansatz function to be used for QAOA. + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param alpha: The cut-off percentage for CVaR. + :param nsamples: The number of samples for measurements in the CVaR calculation. Default is 1000. + :param callback: A callback function to be called after each iteration. Default is None. + :param fake: A flag indicating the type of CVaR ansatz (circuit-based or expectation-based). Default is False. + :param maxiter: The maximum number of iterations for the optimization. Default is 1000. + :return: The optimized parameters for the ansatz circuit. + """ + loss = partial(cvar_loss, nlayers, Q, nsamples, alpha, fake) + + f_scipy = tc.interfaces.scipy_interface( + loss, shape=[2 * nlayers], jit=False, gradient=False + ) + + if init_params is None: + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + # If init_params is not provided, initialize the parameters randomly. + else: + params = init_params + # If init_params is provided, use the provided parameters. + + # Initialize the parameters for the ansatz circuit. + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + + r = optimize.minimize( + f_scipy, + params, + method="COBYLA", + callback=callback, + options={"maxiter": maxiter}, + # bounds=[(0, (2 - np.mod(i, 2))*np.pi) for i in range(2*nlayers)] + ) + # Perform the optimization using the COBYLA method from scipy.optimize. + + return r.x + # Return the optimized parameters for the ansatz circuit. diff --git a/tensorcircuit/templates/__init__.py b/tensorcircuit/templates/__init__.py index 85f350ea..be2236ab 100644 --- a/tensorcircuit/templates/__init__.py +++ b/tensorcircuit/templates/__init__.py @@ -4,5 +4,6 @@ from . import dataset from . import graphs from . import measurements +from . import conversions costfunctions = measurements diff --git a/tensorcircuit/templates/blocks.py b/tensorcircuit/templates/blocks.py index eacc2b42..655ac21e 100644 --- a/tensorcircuit/templates/blocks.py +++ b/tensorcircuit/templates/blocks.py @@ -5,7 +5,7 @@ # pylint: disable=invalid-name from functools import wraps -from typing import Any, Callable, Optional, Sequence, Tuple +from typing import Any, Callable, Optional, Sequence, Tuple, List import numpy as np @@ -200,3 +200,97 @@ def qft( for i in range(len(index) // 2): c.swap(index[i], index[len(index) - 1 - i]) return c + + +def QAOA_ansatz_for_Ising( + params: list, + nlayers: int, + pauli_terms: Tensor, + weights: list, + mixer: str = "X", + gap: int = 5, +) -> Circuit: + """ + Construct the QAOA ansatz for the Ising Model. + The number of qubits is determined by `pauli_terms`. + + :param params: A list of parameter values used in the QAOA ansatz. + :param nlayers: The number of layers in the QAOA ansatz. + :pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :param mixer: mixer type. The options are "X", "XY_ring", "XY_par_ring", "XY_full", and "QAMPA". + """ + nqubits = len(pauli_terms[0]) + c = Circ(nqubits) + for i in range(nqubits): + c.h(i) # Apply Hadamard gate to each qubit + + for j in range(nlayers): + # cost terms + for k in range(len(pauli_terms)): + term = pauli_terms[k] + index_of_ones = [] + for l in range(len(term)): + if term[l] == 1: + index_of_ones.append(l) + if len(index_of_ones) == 1: + c.rz(index_of_ones[0], theta=2 * weights[k] * params[2 * j]) + # Apply Rz gate with angle determined by weight and current parameter value + elif len(index_of_ones) == 2: + c.exp1( + index_of_ones[0], + index_of_ones[1], + unitary=G._zz_matrix, + theta=weights[k] * params[2 * j], + ) + # Apply exp1 gate with a custom unitary (zz_matrix) and angle determined by weight and current parameter value + else: + raise ValueError("Invalid number of Z terms") + + # standard mixer + if mixer == "X": + for i in range(nqubits): + c.rx( + i, theta=params[2 * j + 1] + ) # Apply Rx gate with angle determined by current parameter value + # Parity ring XY mixer + elif mixer == "XY": + pairs = [] + for index in [0, 1]: + while index + 2 <= nqubits: + pairs.append([index, index + 1]) + index += 2 + for pair in pairs: + c.exp1(pair[0], pair[1], unitary=G._xx_matrix, theta=params[2 * j + 1]) + c.exp1(pair[0], pair[1], unitary=G._yy_matrix, theta=params[2 * j + 1]) + c.exp1(nqubits - 1, 0, unitary=G._xx_matrix, theta=params[2 * j + 1]) + c.exp1(nqubits - 1, 0, unitary=G._yy_matrix, theta=params[2 * j + 1]) + + # XY mixer with full couplings + elif mixer == "XY_full": + for q0 in range(nqubits - 1): + for q1 in range(q0 + 1, nqubits): + c.exp1(q0, q1, unitary=G._xx_matrix, theta=params[2 * j + 1]) + c.exp1(q0, q1, unitary=G._yy_matrix, theta=params[2 * j + 1]) + + # Parity ring ZZ mixer + elif mixer == "ZZ": + pairs = [] + for index in [0, 1]: + while index + 2 <= nqubits: + pairs.append([index, index + 1]) + index += 2 + for pair in pairs: + c.exp1(pair[0], pair[1], unitary=G._zz_matrix, theta=params[2 * j + 1]) + c.exp1(nqubits - 1, 0, unitary=G._zz_matrix, theta=params[2 * j + 1]) + + # ZZ mixer with full couplings + elif mixer == "ZZ_full": + for q0 in range(nqubits - 1): + for q1 in range(q0, nqubits): + c.exp1(q0, q1, unitary=G._zz_matrix, theta=params[2 * j + 1]) + + else: + raise ValueError("Invalid mixer type.") + + return c diff --git a/tensorcircuit/templates/conversions.py b/tensorcircuit/templates/conversions.py index 2fc92463..513a79a5 100644 --- a/tensorcircuit/templates/conversions.py +++ b/tensorcircuit/templates/conversions.py @@ -2,11 +2,13 @@ helper functions for conversions """ -from typing import Any, Tuple +from typing import Any, Tuple, List +from ..cons import backend import numpy as np Tensor = Any +Array = Any def get_ps(qo: Any, n: int) -> Tuple[Tensor, Tensor]: @@ -36,3 +38,201 @@ def get_ps(qo: Any, n: int) -> Tuple[Tensor, Tensor]: res.append(res_t) wts.append(w) return np.array(res), np.array(wts) + + +def QUBO_to_Ising(Q: List[list]) -> Tuple[List[list], list, float]: + """ + Cnvert the Q matrix into a the indication of pauli terms, the corresponding weights, and the offset. + The outputs are used to construct an Ising Hamiltonian for QAOA. + + :param Q: The n-by-n square and symmetric Q-matrix. + :return pauli_terms: A list of 0/1 series, where each element represents a Pauli term. + A value of 1 indicates the presence of a Pauli-Z operator, while a value of 0 indicates its absence. + :return weights: A list of weights corresponding to each Pauli term. + :return offset: A float representing the offset term of the Ising Hamiltonian. + """ + + # input is n-by-n symmetric numpy array corresponding to Q-matrix + # output is the components of Ising Hamiltonian + + n = Q.shape[0] + + # square matrix check + if Q[0].shape[0] != n: + raise ValueError("Matrix is not a square matrix.") + + offset = ( + np.triu(Q, 0).sum() / 2 + ) # Calculate the offset term of the Ising Hamiltonian + pauli_terms = [] # List to store the Pauli terms + weights = ( + -np.sum(Q, axis=1) / 2 + ) # Calculate the weights corresponding to each Pauli term + + for i in range(n): + term = np.zeros(n) + term[i] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a single qubit + + for i in range(n - 1): + for j in range(i + 1, n): + term = np.zeros(n) + term[i] = 1 + term[j] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a two-qubit interaction + + weight = ( + Q[i][j] / 2 + ) # Calculate the weight for the two-qubit interaction term + weights = np.concatenate( + (weights, weight), axis=None + ) # Add the weight to the weights list + + return pauli_terms, weights, offset + + +def QUBO_from_portfolio(cov: Array, mean: Array, q: float, B: int, t: float) -> Tensor: + """ + convert portfolio parameters to a Q matrix + :param cov: n-by-n covariance numpy array + :param mean: numpy array of means + :param q: the risk preference of investor + :param B: budget + :param t: penalty factor + :return Q: n-by-n symmetric Q matrix + """ + n = cov.shape[0] + R = np.diag(mean) + S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n)) + + Q = q * cov - R + t * S + return Q + + +class StockData: + """ + A class for converting real-world stock data to an annualized covariance matrix and annualized return. + + Attributes: + - data: A list of continuous stock data in the same time span. + - n_stocks: The number of stocks in the data. + - n_days: The number of trading days in the data. + + Methods: + - __init__(self, data): Initializes the StockData object. + - get_return(self, decimals=5): Calculates the annualized return. + - get_covariance(self, decimals=5): Calculates the annualized covariance matrix. + - get_penalty(self, cov, ret, risk_pre, budget, decimals=5): Calculates the penalty factor. + """ + + def __init__(self, data): + """ + Initializes the StockData object. + + :param data: A list of continuous stock data in the same time span. + """ + self.data = data + self.n_stocks = len(data) + + # Check the number of days + n_days = [len(i) for i in data] + if max(n_days) != (sum(n_days) / len(n_days)): + raise Exception("Timespan of stocks should be the same") + self.n_days = len(data[1]) + + # Calculate the daily percentage price change + self.daily_change = [] + for i in range(self.n_stocks): + each_stock = [] + for j in range(self.n_days - 1): + each_stock.append((data[i][j + 1] - data[i][j]) / data[i][j + 1]) + self.daily_change.append(each_stock) + + def get_return(self, decimals=5): + """ + Calculates the annualized return (mu). + + :param decimals: Number of decimal places to round the result to (default: 5). + :return: The annualized return as an array rounded to the specified number of decimals. + """ + change = [[j + 1 for j in i] for i in self.daily_change] + ret = np.prod(change, axis=1) ** (252 / self.n_days) + return ret.round(decimals) + + def get_covariance(self, decimals=5): + """ + Calculates the annualized covariance matrix (sigma). + + :param decimals: Number of decimal places to round the result to (default: 5). + :return: The annualized covariance matrix rounded to the specified number of decimals. + """ + mean = np.mean(self.daily_change, axis=1) + relative_change = [ + [j - mean[i] for j in self.daily_change[i]] for i in range(6) + ] + cov = 252 / self.n_days * np.dot(relative_change, np.transpose(relative_change)) + return cov.round(decimals) + + def get_penalty(self, cov, ret, risk_pre, budget, decimals=5): + """ + Calculates the penalty factor. + + :param cov: The annualized covariance matrix. + :param ret: The annualized return. + :param risk_pre: The risk preference factor. + :param budget: The budget (number of stocks to select). + :param decimals: Number of decimal places to round the result to (default: 5). + :return: The penalty factor rounded to the specified number of decimals. + """ + # Get all feasible and unfeasible states + self.f_state = [] # Feasible states (number of '1's equal to budget) + self.uf_state = [] # Unfeasible states + self.all_state = [] + for i in range(2 ** self.n_stocks): + state = f"{bin(i)[2:]:0>{self.n_stocks}}" + n_ones = 0 + for j in state: + if j == "1": + n_ones += 1 + self.all_state.append(state) + if n_ones == budget: + self.f_state.append(state) + else: + self.uf_state.append(state) + + # Determine the penalty factor + mark = False + penalty = 0 # Initial value + while mark == False: + R = np.diag(ret) + S = np.ones((self.n_stocks, self.n_stocks)) - 2 * budget * np.diag( + np.ones(self.n_stocks) + ) + Q = risk_pre * cov - R + penalty * S + F = [] + for state in self.f_state: + x = np.array([int(bit) for bit in state]) + F.append(np.dot(x, np.dot(Q, x)) + penalty * budget ** 2) + Fmin = np.amin(F) + Fbar = np.mean(F) + F = [] + for state in self.uf_state: + x = np.array([int(bit) for bit in state]) + F.append(np.dot(x, np.dot(Q, x)) + penalty * budget ** 2) + Fmin_uf = np.amin(F) + location = np.where(F == Fmin_uf)[0][0] + if Fmin_uf < 0.5 * (Fmin + Fbar): + n_ones = 0 + for j in self.uf_state[location]: + if j == "1": + n_ones += 1 + penalty += (0.5 * (Fmin + Fbar) - Fmin_uf) / (n_ones - budget) ** 2 + else: + mark = True # Ready to return the penalty + return round(penalty, decimals) + + From ab9521fdba7a9009a31bc5faa9c4249656352df3 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Thu, 17 Aug 2023 01:52:33 +0200 Subject: [PATCH 003/139] add r qiskit gate to qiskit2c --- tensorcircuit/translation.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 6e867fd5..1cde9cef 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -486,6 +486,13 @@ def qiskit2tc( getattr(tc_circuit, gate_name)(*idx, theta=parameters) elif gate_name in ["crx_o0", "cry_o0", "crz_o0"]: getattr(tc_circuit, "o" + gate_name[1:-3])(*idx, theta=parameters) + elif gate_name in ["r"]: + getattr(tc_circuit, "u")( + *idx, + theta=parameters[0], + phi=parameters[1] - np.pi / 2, + lbd=-parameters[1] + np.pi / 2, + ) elif gate_name in ["u3", "u"]: getattr(tc_circuit, "u")( *idx, theta=parameters[0], phi=parameters[1], lbd=parameters[2] From ae55af987c16d6ad90ef6ae914b9008bbe5192e7 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Thu, 17 Aug 2023 11:20:45 +0200 Subject: [PATCH 004/139] add test for r-gate in test_qiskit2tc --- tests/test_circuit.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 04ba7cb2..10a73971 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1122,6 +1122,7 @@ def test_qiskit2tc(): qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) + qisc.r(np.random.uniform(), np.random.uniform(), 1) qisc.unitary(exp_op, [1, 3]) mcx_g = MCXGate(3, ctrl_state="010") qisc.append(mcx_g, [0, 1, 2, 3]) From eb24c881aab1f4321ed21337e5c0dcc4058a4aa6 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 10:46:40 +0000 Subject: [PATCH 005/139] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5dcdbbde..ca4b5cb3 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. Felix Xu
Felix Xu

💻 ⚠️ Hong-Ye Hu
Hong-Ye Hu

📖 peilin
peilin

💻 ⚠️ 📖 + Cristian Emiliano Godinez Ramirez
Cristian Emiliano Godinez Ramirez

💻 ⚠️ From 63a0d78acba2a56c06f3d3afc065419aea753cf2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 10:46:41 +0000 Subject: [PATCH 006/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index b1735deb..b76d6a80 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -272,6 +272,16 @@ "test", "doc" ] + }, + { + "login": "EmilianoG-byte", + "name": "Cristian Emiliano Godinez Ramirez", + "avatar_url": "https://avatars.githubusercontent.com/u/57567043?v=4", + "profile": "https://emilianog-byte.github.io", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 6, From 3ecc4edd1c072756401af010cbc39c50859f4c1c Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 17 Aug 2023 21:28:13 +0800 Subject: [PATCH 007/139] move to tn-ng --- requirements/requirements.txt | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 9532163a..5deccf0d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,7 +1,7 @@ numpy scipy -tensorflow==2.7 -tensornetwork +tensorflow +tensornetwork-ng graphviz jax jaxlib diff --git a/setup.py b/setup.py index 6e372719..ac6d4d57 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ url="https://github.com/tencent-quantum-lab/tensorcircuit", packages=setuptools.find_packages(), include_package_data=True, - install_requires=["numpy", "scipy", "tensornetwork", "networkx"], + install_requires=["numpy", "scipy", "tensornetwork-ng", "networkx"], extras_require={ "tensorflow": ["tensorflow"], "jax": ["jax", "jaxlib"], From 9e1e56f64f8e6fa22bfa90c4500fc07f39ab7b92 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 17 Aug 2023 21:48:49 +0800 Subject: [PATCH 008/139] upgrade ci to py3.10 --- .github/workflows/ci.yml | 2 +- .github/workflows/nightly_release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a0a7dff..e60133f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04, macos-latest] # macos-latest disabled to save quota - python-version: [3.8] + python-version: [3.10] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/nightly_release.yml b/.github/workflows/nightly_release.yml index ce62cc9c..dbb8fc76 100644 --- a/.github/workflows/nightly_release.yml +++ b/.github/workflows/nightly_release.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.10 cache: "pip" - name: install dependencies run: | From 3f246def8483e0784a4f3e465b32b50e04a7abbc Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 17 Aug 2023 21:58:12 +0800 Subject: [PATCH 009/139] stringfy the version --- .github/workflows/ci.yml | 2 +- .github/workflows/nightly_release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e60133f5..964f9d67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04, macos-latest] # macos-latest disabled to save quota - python-version: [3.10] + python-version: ["3.10"] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/nightly_release.yml b/.github/workflows/nightly_release.yml index dbb8fc76..8a1dbda8 100644 --- a/.github/workflows/nightly_release.yml +++ b/.github/workflows/nightly_release.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: "3.10" cache: "pip" - name: install dependencies run: | From 2d2245249cb606569e9bf40ed6ce0a009345da5a Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 17 Aug 2023 22:08:02 +0800 Subject: [PATCH 010/139] fix mypy --- tensorcircuit/backends/jax_ops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index 63cd2e33..743e0ad0 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -66,7 +66,7 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: return (grad_a,) -adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) +adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) # type: ignore adaware_svd_jit = jax.jit(adaware_svd) @@ -142,6 +142,6 @@ def _QrGradSquareAndDeepMatrices(q: Array, r: Array, dq: Array, dr: Array) -> Ar return (result,) -adaware_qr.defvjp(jaxqr_fwd, jaxqr_bwd) +adaware_qr.defvjp(jaxqr_fwd, jaxqr_bwd) # type: ignore adaware_qr_jit = jax.jit(adaware_qr) From 28bda817a60113bcdbd6140f8e452ea09742a66c Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 17 Aug 2023 23:07:02 +0800 Subject: [PATCH 011/139] black --- tensorcircuit/backends/jax_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index 743e0ad0..efcce174 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -66,7 +66,7 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: return (grad_a,) -adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) # type: ignore +adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) # type: ignore adaware_svd_jit = jax.jit(adaware_svd) From 0ec22166d974b76e00183cdcf6956572a20fd0ba Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 18 Aug 2023 09:55:45 +0800 Subject: [PATCH 012/139] new version of ci packages --- requirements/requirements-dev.txt | 7 +++---- tensorcircuit/applications/optimization.py | 4 ++-- tensorcircuit/translation.py | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index 753fe704..e6b3e293 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -1,13 +1,12 @@ -mypy==1.2.0 +mypy==1.5.1 pytest==6.2.4 pytest-cov pytest-benchmark pytest-xdist -black[jupyter]==23.3.0 +black[jupyter] sphinx>=4.0 pytest-lazy-fixture -pylint==2.11.1 -numpy==1.21.5 +pylint==2.17.5 furo sphinx-copybutton nbsphinx diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py index a579d6b8..bf0cc1c5 100644 --- a/tensorcircuit/applications/optimization.py +++ b/tensorcircuit/applications/optimization.py @@ -171,8 +171,8 @@ def cvar_value(r: List[float], p: List[float], percent: float) -> float: :return: The calculated CVaR value. """ sorted_indices = np.argsort(r) - p = np.array(p)[sorted_indices] - r = np.array(r)[sorted_indices] + p = np.array(p)[sorted_indices] # type: ignore + r = np.array(r)[sorted_indices] # type: ignore sump = 0.0 # The sum of probabilities. count = 0 diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 1cde9cef..045751c2 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -125,7 +125,7 @@ def qir2cirq( support more element in qir, e.g. barrier, measure... """ - class CustomizedCirqGate(cirq.Gate): + class CustomizedCirqGate(cirq.Gate): # type: ignore def __init__(self, uMatrix: Any, name: str, nqubit: int): super(CustomizedCirqGate, self) self.uMatrix = uMatrix From 018cc558468f838fa7944658f33c55e003e5b3d2 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 18 Aug 2023 10:47:21 +0800 Subject: [PATCH 013/139] move ensemble to applications --- CHANGELOG.md | 8 ++++++++ docs/source/api/applications/ai.rst | 2 +- .../api/{templates => applications/ai}/ensemble.rst | 4 ++-- docs/source/api/templates.rst | 1 - tensorcircuit/{templates => applications/ai}/ensemble.py | 5 +++-- tests/test_ensemble.py | 4 ++-- 6 files changed, 16 insertions(+), 8 deletions(-) rename docs/source/api/{templates => applications/ai}/ensemble.rst (63%) rename tensorcircuit/{templates => applications/ai}/ensemble.py (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 593ec9cb..6f7e7dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +### Added + +- Add translation of r gate from qiskit + +### Changed + +- move ensemble module to applications/ai (breaking changes) + ## 0.11.0 ### Added diff --git a/docs/source/api/applications/ai.rst b/docs/source/api/applications/ai.rst index c8749e92..96a22cdb 100644 --- a/docs/source/api/applications/ai.rst +++ b/docs/source/api/applications/ai.rst @@ -1,4 +1,4 @@ tensorcircuit.applications.ai ================================================================================ .. toctree:: - \ No newline at end of file + ai/ensemble.rst \ No newline at end of file diff --git a/docs/source/api/templates/ensemble.rst b/docs/source/api/applications/ai/ensemble.rst similarity index 63% rename from docs/source/api/templates/ensemble.rst rename to docs/source/api/applications/ai/ensemble.rst index fc086a35..0173ac00 100644 --- a/docs/source/api/templates/ensemble.rst +++ b/docs/source/api/applications/ai/ensemble.rst @@ -1,6 +1,6 @@ -tensorcircuit.templates.ensemble +tensorcircuit.applications.ai.ensemble ================================================================================ -.. automodule:: tensorcircuit.templates.ensemble +.. automodule:: tensorcircuit.applications.ai.ensemble :members: :undoc-members: :show-inheritance: diff --git a/docs/source/api/templates.rst b/docs/source/api/templates.rst index d76ab744..202b049d 100644 --- a/docs/source/api/templates.rst +++ b/docs/source/api/templates.rst @@ -6,6 +6,5 @@ tensorcircuit.templates templates/chems.rst templates/conversions.rst templates/dataset.rst - templates/ensemble.rst templates/graphs.rst templates/measurements.rst \ No newline at end of file diff --git a/tensorcircuit/templates/ensemble.py b/tensorcircuit/applications/ai/ensemble.py similarity index 96% rename from tensorcircuit/templates/ensemble.py rename to tensorcircuit/applications/ai/ensemble.py index 0c4a0fc3..7946cb4c 100644 --- a/tensorcircuit/templates/ensemble.py +++ b/tensorcircuit/applications/ai/ensemble.py @@ -55,8 +55,9 @@ def compile(self, **kwargs: kwargus) -> None: self.permit_train = True for i in range(self.count): if not self.model_trained[i]: - dic_kwargs = kwargs.copy() - self.models[i].compile(**dic_kwargs) + dict_kwargs = kwargs.copy() + # TODO(@refraction-ray): still not compatible with new optimizer + self.models[i].compile(**dict_kwargs) def __get_confidence(self, model_index: int, input: NDArray) -> NDArray: """ diff --git a/tests/test_ensemble.py b/tests/test_ensemble.py index 5aec52cc..097789dc 100644 --- a/tests/test_ensemble.py +++ b/tests/test_ensemble.py @@ -8,7 +8,7 @@ sys.path.insert(0, modulepath) -from tensorcircuit.templates.ensemble import bagging +from tensorcircuit.applications.ai.ensemble import bagging def test_ensemble_bagging(): @@ -52,7 +52,7 @@ def model(): obj_bagging.append(model(), False) obj_bagging.compile( loss=tf.keras.losses.BinaryCrossentropy(), - optimizer=tf.keras.optimizers.Adam(lr), + optimizer=tf.keras.optimizers.legacy.Adam(lr), metrics=[tf.keras.metrics.AUC(), "acc"], ) obj_bagging.train( From 1eddc6d2a10a5d3126297e7b53fb0a6a19ad5ee3 Mon Sep 17 00:00:00 2001 From: PeilinZHENG Date: Tue, 22 Aug 2023 12:49:29 +0800 Subject: [PATCH 014/139] Update shadows.py --- tensorcircuit/shadows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/shadows.py b/tensorcircuit/shadows.py index aa03574c..63cad7f6 100644 --- a/tensorcircuit/shadows.py +++ b/tensorcircuit/shadows.py @@ -83,7 +83,7 @@ def shadow_snapshots( backend.convert_to_tensor( [ [-np.pi / 2, np.pi / 4, 0], - [np.pi / 3, np.arccos(1 / np.sqrt(3)), np.pi / 4], + [np.pi / 4, np.pi / 2, 0], [0, 0, 0], ] ), From 98f7b39cff4cd8fd5e7e6cd1ec010d1ae7490036 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 23 Aug 2023 15:10:00 +0100 Subject: [PATCH 015/139] Delete QAOA_funcs.py --- docs/source/tutorials/QAOA_funcs.py | 439 ---------------------------- 1 file changed, 439 deletions(-) delete mode 100644 docs/source/tutorials/QAOA_funcs.py diff --git a/docs/source/tutorials/QAOA_funcs.py b/docs/source/tutorials/QAOA_funcs.py deleted file mode 100644 index 87d35d59..00000000 --- a/docs/source/tutorials/QAOA_funcs.py +++ /dev/null @@ -1,439 +0,0 @@ -### -### functions for QAOA problems -### - -from typing import List, Tuple, Callable, Any -import tensorcircuit as tc -import numpy as np -import tensorflow as tf -import matplotlib.pyplot as plt -from IPython.display import clear_output -from functools import partial -import scipy.optimize as optimize - -Array = any -Tensor = Any - - -# moved -def QUBO_to_Ising(Q: List[list]) -> Tuple[List[list], list, float]: - """ - Cnvert the Q matrix into a the indication of pauli terms, the corresponding weights, and the offset. - The outputs are used to construct an Ising Hamiltonian for QAOA. - - :param Q: The n-by-n square and symmetric Q-matrix. - :return pauli_terms: A list of 0/1 series, where each element represents a Pauli term. - A value of 1 indicates the presence of a Pauli-Z operator, while a value of 0 indicates its absence. - :return weights: A list of weights corresponding to each Pauli term. - :return offset: A float representing the offset term of the Ising Hamiltonian. - """ - - # input is n-by-n symmetric numpy array corresponding to Q-matrix - # output is the components of Ising Hamiltonian - - n = Q.shape[0] - - # square matrix check - if Q[0].shape[0] != n: - raise ValueError("Matrix is not a square matrix.") - - offset = ( - np.triu(Q, 0).sum() / 2 - ) # Calculate the offset term of the Ising Hamiltonian - pauli_terms = [] # List to store the Pauli terms - weights = ( - -np.sum(Q, axis=1) / 2 - ) # Calculate the weights corresponding to each Pauli term - - for i in range(n): - term = np.zeros(n) - term[i] = 1 - pauli_terms.append( - term.tolist() - ) # Add a Pauli term corresponding to a single qubit - - for i in range(n - 1): - for j in range(i + 1, n): - term = np.zeros(n) - term[i] = 1 - term[j] = 1 - pauli_terms.append( - term.tolist() - ) # Add a Pauli term corresponding to a two-qubit interaction - - weight = ( - Q[i][j] / 2 - ) # Calculate the weight for the two-qubit interaction term - weights = np.concatenate( - (weights, weight), axis=None - ) # Add the weight to the weights list - - return pauli_terms, weights, offset - - -def Ising_loss(c: tc.Circuit, pauli_terms: List[list], weights: list) -> float: - """ - computes the loss function for the Ising model based on a given quantum circuit, - a list of Pauli terms, and corresponding weights. - The offset is ignored. - - :param c: A quantum circuit object generating the state. - :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. - :param weights: A list of weights corresponding to each Pauli term. - :return loss: A real number representing the computed loss value. - """ - loss = 0.0 - for k in range(len(pauli_terms)): - term = pauli_terms[k] - index_of_ones = [] - - for l in range(len(term)): - if term[l] == 1: - index_of_ones.append(l) - - # Compute expectation value based on the number of qubits involved in the Pauli term - if len(index_of_ones) == 1: - delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]]) - # Compute expectation value for a single-qubit Pauli term - else: - delta_loss = weights[k] * c.expectation_ps( - z=[index_of_ones[0], index_of_ones[1]] - ) - # Compute expectation value for a two-qubit Pauli term - - loss += delta_loss - - return K.real(loss) - - -def QAOA_loss( - nlayers: int, pauli_terms: List[list], weights: list, params: list -) -> float: - """ - computes the loss function for the Quantum Approximate Optimization Algorithm (QAOA) applied to the Ising model. - - :param nlayers: The number of layers in the QAOA ansatz. - :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. - :param weights: A list of weights corresponding to each Pauli term. - :param params: A list of parameter values used in the QAOA ansatz. - :return: The computed loss value. - """ - c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights) - # Obtain the quantum circuit using QAOA_from_Ising function - - return Ising_loss(c, pauli_terms, weights) - # Compute the Ising loss using Ising_loss function on the obtained circuit - - -def QUBO_QAOA( - Q: List[list], - ansatz: Callable[[list, int, List[list], list], tc.Circuit], - nlayers: int, - iterations: int, - vvag: bool = False, - ncircuits: int = 10, -) -> list: - """ - Performs the QAOA on a given QUBO problem. - - :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. - :param ansatz: The ansatz function to be used for the QAOA. - :param nlayers: The number of layers in the QAOA ansatz. - :param iterations: The number of iterations to run the optimization. - :param vvag (optional): A flag indicating whether to use vectorized variational adjoint gradient. Default is False. - :param ncircuits (optional): The number of circuits when using vectorized variational adjoint gradient. Default is 10. - :return params: The optimized parameters for the ansatz circuit. - """ - try: - K - except NameError: - print("select a backend and assign it to K.") - - pauli_terms, weights, offset = QUBO_to_Ising(Q) - learning_rate = 1e-2 - - loss_val_grad = K.value_and_grad(partial(ansatz, nlayers, pauli_terms, weights)) - params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5) - # Initialize the parameters for the ansatz circuit - - if vvag == True: - loss_val_grad = tc.backend.vvag(loss_val_grad, argnums=0, vectorized_argnums=0) - params = K.implicit_randn(shape=[ncircuits, 2 * nlayers], stddev=0.1) - # Use vectorized variational adjoint gradient (vvag) if vvag flag is set to True - - loss_val_grad_jit = K.jit(loss_val_grad, static_argnums=(1, 2)) - - opt = K.optimizer(tf.keras.optimizers.Adam(learning_rate)) - # Define the optimizer (Adam optimizer) with the specified learning rate - - for i in range(iterations): - loss, grads = loss_val_grad_jit(params) - # Calculate the loss and gradients using the loss_val_grad_jit function - - params = opt.update(grads, params) - # Update the parameters using the optimizer and gradients - - if i % 100 == 0: # print the cost every 100 iterations - print(K.numpy(loss)) - - return params - - -# calcelled -def print_result_prob(c: tc.Circuit, wrap: bool = False, reverse: bool = False) -> None: - """ - Print the results and probabilities of a given quantum circuit. - The default order is from the highest probability to the lowest one - - :param c: The quantum circuit to print the results and probabilities. - :param wrap (optional): A flag indicating whether to wrap the output. Default is False. - :param reverse (optional): A flag indicating whether to reverse the order of the output. Default is False. - """ - try: - K - except NameError: - print("select a backend and assign it to K.") - - states = [] - n_qubits = c._nqubits - for i in range(2**n_qubits): - a = f"{bin(i)[2:]:0>{n_qubits}}" - states.append(a) - # Generate all possible binary states for the given number of qubits - - probs = K.numpy(c.probability()).round(decimals=4) - # Calculate the probabilities of each state using the circuit's probability method - - sorted_indices = np.argsort(probs)[::-1] - if reverse == True: - sorted_indices = sorted_indices[::-1] - state_sorted = np.array(states)[sorted_indices] - prob_sorted = np.array(probs)[sorted_indices] - # Sort the states and probabilities in descending order based on the probabilities - - print("\n-------------------------------------") - print(" selection\t |\tprobability") - print("-------------------------------------") - if wrap == False: - for i in range(len(states)): - print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) - # Print the sorted states and their corresponding probabilities - elif wrap == True: - for i in range(4): - print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) - print(" ... ...") - for i in range(-4, -1): - print("%10s\t |\t %.4f" % (state_sorted[i], prob_sorted[i])) - print("-------------------------------------") - - -# calcelled -def print_result_cost( - c: tc.Circuit, Q: List[list], wrap: bool = False, reverse: bool = False -) -> None: - """ - Print the results and costs of a given quantum circuit. - Specificly designed for the variational circuit. - The default order is from the highest probability to the lowest one. - - :param c: The quantum circuit to print the results and probabilities. - :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. - :param wrap (optional): A flag indicating whether to wrap the output. Default is False. - :param reverse (optional): A flag indicating whether to reverse the order of the output. Default is False. - """ - cost_dict = {} - states = [] - n_qubits = c._nqubits - for i in range(2**n_qubits): - a = f"{bin(i)[2:]:0>{n_qubits}}" - states.append(a) - # Generate all possible binary states for the given number of qubits - for selection in states: - x = np.array([int(bit) for bit in selection]) - cost_dict[selection] = np.dot(x, np.dot(Q, x)) - cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1])) - if reverse == True: - cost_sorted = dict( - sorted(cost_dict.items(), key=lambda item: item[1], reverse=True) - ) - num = 0 - print("\n-------------------------------------") - print(" selection\t |\t cost") - print("-------------------------------------") - for k, v in cost_sorted.items(): - print("%10s\t |\t%.4f" % (k, v)) - num += 1 - if (num >= 8) & (wrap == True): - break - print("-------------------------------------") - - -# cancelled -def print_Q_cost(Q: List[list], wrap: bool = False, reverse: bool = False) -> None: - n_stocks = len(Q) - states = [] - for i in range(2**n_stocks): - a = f"{bin(i)[2:]:0>{n_stocks}}" - n_ones = 0 - for j in a: - if j == "1": - n_ones += 1 - states.append(a) - - cost_dict = {} - for selection in states: - x = np.array([int(bit) for bit in selection]) - cost_dict[selection] = np.dot(x, np.dot(Q, x)) - cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1])) - if reverse == True: - cost_sorted = dict( - sorted(cost_dict.items(), key=lambda item: item[1], reverse=True) - ) - num = 0 - print("\n-------------------------------------") - print(" selection\t |\t cost") - print("-------------------------------------") - for k, v in cost_sorted.items(): - print("%10s\t |\t%.4f" % (k, v)) - num += 1 - if (num >= 8) & (wrap == True): - break - print("-------------------------------------") - - -# moved -class StockData: - """ - convert real-world stock data to the inputs of QAOA. - """ - - def __init__(self, data: Tensor) -> None: - """ - stock data object - - :param data: real-world stock data, in the form of several lists of daily price. - """ - self.data = data # add data - self.n_stocks = len(data) # num of stocks - self.n_days = len(data[1]) - - # check the number of days - n_days = [len(i) for i in data] - if max(n_days) != (sum(n_days) / len(n_days)): - raise Exception("timespan of stocks should be the same") - - # calculate the daily percentage price change - self.daily_change = [] # daily percentage price change - for i in range(self.n_stocks): - each_stcok = [] - for j in range(self.n_days - 1): - each_stcok.append((data[i][j + 1] - data[i][j]) / data[i][j]) - self.daily_change.append(each_stcok) - - def get_return(self) -> Array: - """ - :return ret: annualized return (mu) - """ - ret = np.mean(self.daily_change, axis=1) - return ret - - def get_covariance(self) -> Array: - """ - :return cov: symmetric annualized covariance matrix (sigma) - """ - return np.cov(self.daily_change) - - def get_pentalty( - self, cov: Array, ret: Array, risk_pre: float, budget: int - ) -> float: - """ - calculate the pentalty using the method in https://link.springer.com/article/10.1007/s11128-022-03766-5 - brutal force is used - - :param cov: symmetrix annualized covariance matrix (sigma) - :param ret: annualized return (ret) - :param risk_pre: risk preference of the investor - :param budge: the number of assets to be chosen for the portfolio - """ - # get all fesible and unfeasible states - self.f_state = [] # feasible states (num of '1's equal to budge) - self.uf_state = [] # unfeasible states - self.all_state = [] - for i in range(2**self.n_stocks): - state = f"{bin(i)[2:]:0>{self.n_stocks}}" - n_ones = 0 - for j in state: - if j == "1": - n_ones += 1 - self.all_state.append(state) - if n_ones == budget: - self.f_state.append(state) - else: - self.uf_state.append(state) - - # determine the penalty factor - mark = False - penalty = 0 # initial value - while mark == False: - R = np.diag(ret) - S = np.ones((self.n_stocks, self.n_stocks)) - 2 * budget * np.diag( - np.ones(self.n_stocks) - ) - Q = risk_pre * cov - R + penalty * S - F = [] - for state in self.f_state: - x = np.array([int(bit) for bit in state]) - F.append(np.dot(x, np.dot(Q, x)) + penalty * budget**2) - Fmin = np.amin(F) - Fbar = np.mean(F) - F = [] - for state in self.uf_state: - x = np.array([int(bit) for bit in state]) - F.append(np.dot(x, np.dot(Q, x)) + penalty * budget**2) - Fmin_uf = np.amin(F) - location = np.where(F == Fmin_uf)[0][0] - if Fmin_uf < 0.5 * (Fmin + Fbar): - n_ones = 0 - for j in self.uf_state[location]: - if j == "1": - n_ones += 1 - penalty += (0.5 * (Fmin + Fbar) - Fmin_uf) / (n_ones - budget) ** 2 - # mark = True - else: - mark = True # ready to return the penalty - return penalty - - -# moved -def QUBO_from_portfolio(cov: Array, mean: Array, q: float, B: int, t: float) -> Tensor: - """ - convert portfolio parameters to a Q matrix - :param cov: n-by-n covariance numpy array - :param mean: numpy array of means - :param q: the risk preference of investor - :param B: budget - :param t: penalty factor - :return Q: n-by-n symmetric Q matrix - """ - n = cov.shape[0] - R = np.diag(mean) - S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n)) - - Q = q * cov - R + t * S - return Q - - -def print_output(c): - n = c._nqubits - N = 2**n - # Calculate the total number of states based on the number of qubits - - x_label = r"$\left|{0:0" + str(n) + r"b}\right>$" - labels = [x_label.format(i) for i in range(N)] - # Generate labels for the x-axis representing the binary states - - plt.bar(range(N), c.probability()) - # Create a bar plot with the probabilities of each state - - plt.xticks(range(N), labels, rotation=70) - # Set the x-axis ticks to the generated labels and rotate them for better visibility From e3a9eda20ed66a5980b0132694f0acddb1b52258 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 23 Aug 2023 15:43:03 +0100 Subject: [PATCH 016/139] clear the imports --- docs/source/tutorials/QUBO_problem.ipynb | 18 +---------------- .../tutorials/portfolio_optimization.ipynb | 20 +++---------------- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/docs/source/tutorials/QUBO_problem.ipynb b/docs/source/tutorials/QUBO_problem.ipynb index 2eb9f49e..4a18510d 100644 --- a/docs/source/tutorials/QUBO_problem.ipynb +++ b/docs/source/tutorials/QUBO_problem.ipynb @@ -61,22 +61,6 @@ "## Setup" ] }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b6a2743e", - "metadata": {}, - "outputs": [], - "source": [ - "## delete before PR\n", - "import sys\n", - "\n", - "sys.path.append(\"D:\\OneDrive - Imperial College London\\文件\\Code\\TensorCircuit\")\n", - "sys.path.append(\n", - " \"/Users/felixxu/Library/CloudStorage/OneDrive-ImperialCollegeLondon/文件/Code/TensorCircuit\"\n", - ")" - ] - }, { "cell_type": "code", "execution_count": 2, @@ -99,7 +83,7 @@ "import time\n", "\n", "from tensorcircuit.applications.optimization import QUBO_QAOA, QUBO_QAOA_cvar, cvar_loss, QAOA_loss\n", - "from tensorcircuit.templates.blocks import QAOA_ansatz_for_Ising\n", + "from tensorcircuit.templates.ansatz import QAOA_ansatz_for_Ising\n", "from tensorcircuit.templates.conversions import QUBO_to_Ising\n", "\n", "K = tc.set_backend(\"tensorflow\")\n", diff --git a/docs/source/tutorials/portfolio_optimization.ipynb b/docs/source/tutorials/portfolio_optimization.ipynb index 3ed0f4e3..54a95062 100644 --- a/docs/source/tutorials/portfolio_optimization.ipynb +++ b/docs/source/tutorials/portfolio_optimization.ipynb @@ -54,20 +54,6 @@ "## Set up" ] }, - { - "cell_type": "code", - "execution_count": 1, - "id": "657c589a", - "metadata": {}, - "outputs": [], - "source": [ - "## delete before PR\n", - "import sys\n", - "\n", - "sys.path.append(\"D:\\OneDrive - Imperial College London\\文件\\Code\\TensorCircuit\")\n", - "sys.path.append(\"/Users/felixxu/Library/CloudStorage/OneDrive-ImperialCollegeLondon/文件/Code/TensorCircuit\")" - ] - }, { "cell_type": "code", "execution_count": 2, @@ -84,10 +70,10 @@ "import time\n", "import scipy.optimize as optimize\n", "\n", - "from tensorcircuit.templates.blocks import QAOA_ansatz_for_Ising\n", - "from tensorcircuit.templates.conversions import QUBO_to_Ising, QUBO_from_portfolio\n", + "from tensorcircuit.templates.ansatz import QAOA_ansatz_for_Ising\n", + "from tensorcircuit.templates.conversions import QUBO_to_Ising\n", "from tensorcircuit.applications.optimization import QUBO_QAOA, QAOA_loss\n", - "from tensorcircuit.templates.conversions import StockData\n", + "from tensorcircuit.applications.finance.portfolio import StockData, QUBO_from_portfolio\n", "\n", "K = tc.set_backend(\"tensorflow\")\n", "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" From 5f4202f1b493098ccaf95b02f3b7dc401ee1fe27 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:37:13 +0100 Subject: [PATCH 017/139] fixed minor grammar and format issues --- docs/source/tutorials/QUBO_problem.ipynb | 58 ++++++++----------- .../tutorials/portfolio_optimization.ipynb | 23 +++----- 2 files changed, 31 insertions(+), 50 deletions(-) diff --git a/docs/source/tutorials/QUBO_problem.ipynb b/docs/source/tutorials/QUBO_problem.ipynb index 4a18510d..b28717d3 100644 --- a/docs/source/tutorials/QUBO_problem.ipynb +++ b/docs/source/tutorials/QUBO_problem.ipynb @@ -6,7 +6,7 @@ "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", "metadata": {}, "source": [ - "# Solving portfolio optimization as QUBO problem with QAOA\n", + "# Solving portfolio optimization as a QUBO problem with QAOA\n", "\n", "## Overview\n", "\n", @@ -16,11 +16,11 @@ "\n", "### what is QUBO?\n", "\n", - "Quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", + "The quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", "\n", - "From a computational perspective, solving a QUBO problem is generally considered NP-hard. This classification implies that finding the optimal solution to a QUBO instance is believed to be computationally challenging, and there is no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", + "From a computational perspective, solving a QUBO problem is generally considered NP-hard. This classification implies that solving the optimal solution to a QUBO instance is believed to be computationally challenging, and there is no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", "\n", - "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in this [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem solving. QAOA leverages the inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz. The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", + "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in this [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem solving. QAOA leverages inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz. The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", "\n", "### General Case\n", "\n", @@ -34,7 +34,7 @@ "\n", "$$\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i Date: Thu, 24 Aug 2023 12:55:17 +0100 Subject: [PATCH 018/139] reverse two previously discarded changes --- tensorcircuit/applications/__init__.py | 2 - tensorcircuit/templates/blocks.py | 96 +------------------------- 2 files changed, 1 insertion(+), 97 deletions(-) diff --git a/tensorcircuit/applications/__init__.py b/tensorcircuit/applications/__init__.py index 200fcbe6..70d128b0 100644 --- a/tensorcircuit/applications/__init__.py +++ b/tensorcircuit/applications/__init__.py @@ -3,5 +3,3 @@ the code inside is subject to change, be caution to use. Most of the useful code is and will be refactored and copied to other parts of tensorcircuit. """ - -from . import optimization \ No newline at end of file diff --git a/tensorcircuit/templates/blocks.py b/tensorcircuit/templates/blocks.py index 655ac21e..eacc2b42 100644 --- a/tensorcircuit/templates/blocks.py +++ b/tensorcircuit/templates/blocks.py @@ -5,7 +5,7 @@ # pylint: disable=invalid-name from functools import wraps -from typing import Any, Callable, Optional, Sequence, Tuple, List +from typing import Any, Callable, Optional, Sequence, Tuple import numpy as np @@ -200,97 +200,3 @@ def qft( for i in range(len(index) // 2): c.swap(index[i], index[len(index) - 1 - i]) return c - - -def QAOA_ansatz_for_Ising( - params: list, - nlayers: int, - pauli_terms: Tensor, - weights: list, - mixer: str = "X", - gap: int = 5, -) -> Circuit: - """ - Construct the QAOA ansatz for the Ising Model. - The number of qubits is determined by `pauli_terms`. - - :param params: A list of parameter values used in the QAOA ansatz. - :param nlayers: The number of layers in the QAOA ansatz. - :pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. - :param weights: A list of weights corresponding to each Pauli term. - :param mixer: mixer type. The options are "X", "XY_ring", "XY_par_ring", "XY_full", and "QAMPA". - """ - nqubits = len(pauli_terms[0]) - c = Circ(nqubits) - for i in range(nqubits): - c.h(i) # Apply Hadamard gate to each qubit - - for j in range(nlayers): - # cost terms - for k in range(len(pauli_terms)): - term = pauli_terms[k] - index_of_ones = [] - for l in range(len(term)): - if term[l] == 1: - index_of_ones.append(l) - if len(index_of_ones) == 1: - c.rz(index_of_ones[0], theta=2 * weights[k] * params[2 * j]) - # Apply Rz gate with angle determined by weight and current parameter value - elif len(index_of_ones) == 2: - c.exp1( - index_of_ones[0], - index_of_ones[1], - unitary=G._zz_matrix, - theta=weights[k] * params[2 * j], - ) - # Apply exp1 gate with a custom unitary (zz_matrix) and angle determined by weight and current parameter value - else: - raise ValueError("Invalid number of Z terms") - - # standard mixer - if mixer == "X": - for i in range(nqubits): - c.rx( - i, theta=params[2 * j + 1] - ) # Apply Rx gate with angle determined by current parameter value - # Parity ring XY mixer - elif mixer == "XY": - pairs = [] - for index in [0, 1]: - while index + 2 <= nqubits: - pairs.append([index, index + 1]) - index += 2 - for pair in pairs: - c.exp1(pair[0], pair[1], unitary=G._xx_matrix, theta=params[2 * j + 1]) - c.exp1(pair[0], pair[1], unitary=G._yy_matrix, theta=params[2 * j + 1]) - c.exp1(nqubits - 1, 0, unitary=G._xx_matrix, theta=params[2 * j + 1]) - c.exp1(nqubits - 1, 0, unitary=G._yy_matrix, theta=params[2 * j + 1]) - - # XY mixer with full couplings - elif mixer == "XY_full": - for q0 in range(nqubits - 1): - for q1 in range(q0 + 1, nqubits): - c.exp1(q0, q1, unitary=G._xx_matrix, theta=params[2 * j + 1]) - c.exp1(q0, q1, unitary=G._yy_matrix, theta=params[2 * j + 1]) - - # Parity ring ZZ mixer - elif mixer == "ZZ": - pairs = [] - for index in [0, 1]: - while index + 2 <= nqubits: - pairs.append([index, index + 1]) - index += 2 - for pair in pairs: - c.exp1(pair[0], pair[1], unitary=G._zz_matrix, theta=params[2 * j + 1]) - c.exp1(nqubits - 1, 0, unitary=G._zz_matrix, theta=params[2 * j + 1]) - - # ZZ mixer with full couplings - elif mixer == "ZZ_full": - for q0 in range(nqubits - 1): - for q1 in range(q0, nqubits): - c.exp1(q0, q1, unitary=G._zz_matrix, theta=params[2 * j + 1]) - - else: - raise ValueError("Invalid mixer type.") - - return c From 85e9f6ab2217e8f44b9148a28c2157ae6aa97d40 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Fri, 25 Aug 2023 12:25:34 +0100 Subject: [PATCH 019/139] reviewed V2 --- docs/source/tutorial.rst | 3 +- docs/source/tutorials/QUBO_problem.ipynb | 4 +- .../tutorials/portfolio_optimization.ipynb | 16 +- .../qaoa_portfolio_optimization.ipynb | 602 ------------------ 4 files changed, 14 insertions(+), 611 deletions(-) delete mode 100644 docs/source/tutorials/qaoa_portfolio_optimization.ipynb diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst index c7bae543..538253d7 100644 --- a/docs/source/tutorial.rst +++ b/docs/source/tutorial.rst @@ -20,5 +20,6 @@ Jupyter Tutorials tutorials/vqex_mbl.ipynb tutorials/dqas.ipynb tutorials/barren_plateaus.ipynb - tutorials/qaoa_portfolio_optimization.ipynb + tutorials/QUBO_problem.ipynb + tutorials/portfolio_optimization.ipynb tutorials/qcloud_sdk_demo.ipynb \ No newline at end of file diff --git a/docs/source/tutorials/QUBO_problem.ipynb b/docs/source/tutorials/QUBO_problem.ipynb index b28717d3..86441d71 100644 --- a/docs/source/tutorials/QUBO_problem.ipynb +++ b/docs/source/tutorials/QUBO_problem.ipynb @@ -164,7 +164,7 @@ "source": [ "Note that with 2 layers and 500 iterations, the objective function does not in this case (although it depends on the initial parameters) converge to the true value of $-4.5$. However, the we see below that the final wavefunction does have significant overlap with the desired state $|10\\rangle$, and then the output of the QAOA algorithm will, with high probability, give the best combiantion.\n", "\n", - "Define a function a print a table of results, where all quantum states are listed in the order of possibilities." + "Define a function and print a table of results, where all quantum states are listed in the order of possibilities." ] }, { @@ -291,7 +291,7 @@ "\n", " Conditional Value-at-Risk (CVaR) is a risk measure that quantifies the potential loss beyond a certain threshold (alpha), considering the tail end of the distribution. In QAOA, incorporating CVaR as an objective function allows for addressing risk-averse optimization problems effectively. By optimizing for CVaR, the algorithm focuses on minimizing the expected value of the worst-case scenario, rather than solely optimizing for the mean or expected value, which usually lead to a faster convergence to a more accurate result.\n", "\n", - " In order to showcase the performance of CVaR, a more complicated QUBO problem is used. The Q matrix is:" + " In order to showcase the performance of CVaR, a more complicated QUBO problem is used. This QUBO problem is described as a randomly generated symmetric Q matrix. The Q matrix is:" ] }, { diff --git a/docs/source/tutorials/portfolio_optimization.ipynb b/docs/source/tutorials/portfolio_optimization.ipynb index 3eeeff1e..69d9628f 100644 --- a/docs/source/tutorials/portfolio_optimization.ipynb +++ b/docs/source/tutorials/portfolio_optimization.ipynb @@ -41,7 +41,7 @@ "\n", "which is a QUBO problem\n", "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q X + tB^2$$\n", + "$$\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q x + tB^2$$\n", "\n", "where matrix $Q$ is\n", "\n", @@ -65,10 +65,6 @@ "import numpy as np\n", "import tensorflow as tf\n", "import matplotlib.pyplot as plt\n", - "from IPython.display import clear_output\n", - "from functools import partial\n", - "import time\n", - "import scipy.optimize as optimize\n", "\n", "from tensorcircuit.templates.ansatz import QAOA_ansatz_for_Ising\n", "from tensorcircuit.templates.conversions import QUBO_to_Ising\n", @@ -455,6 +451,14 @@ ")\n", "print_result_prob(c_final, wrap=True)" ] + }, + { + "cell_type": "markdown", + "id": "917c9415", + "metadata": {}, + "source": [ + "Compared with standard X mixer, the XY mixer gives a higher probability to measure the best result." + ] } ], "metadata": { @@ -473,7 +477,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/docs/source/tutorials/qaoa_portfolio_optimization.ipynb b/docs/source/tutorials/qaoa_portfolio_optimization.ipynb deleted file mode 100644 index 7f390853..00000000 --- a/docs/source/tutorials/qaoa_portfolio_optimization.ipynb +++ /dev/null @@ -1,602 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", - "metadata": {}, - "source": [ - "# Solving QUBO problems using QAOA\n", - "\n", - "## Overview\n", - "\n", - "Here we show how to solve a quadratic unconstrained binary optimization (QUBO) problem using QAOA. Later on below we will extend this to show how to solve binary Markowitz portfolio optimization problems.\n", - "\n", - "Consider minimizing the following 2x2 QUBO objective function:\n", - "\n", - "$\\begin{pmatrix}x_1 & x_2\\end{pmatrix}\\begin{pmatrix}-5& -2 \\\\-2 & 6\\end{pmatrix}\\begin{pmatrix}x_1\\\\x_2\\end{pmatrix} = -5x_1^2 -4x_1x_2 +6x_2^2$\n", - "\n", - "Clearly this is minimized at $(x_1,x_2) = (1,0)$, with corresponding objective function value of $-5$\n", - "\n", - "We first convert this to an Ising Hamiltonian by mapping $x_i\\rightarrow \\frac{I-Z_i}{2}$\n", - "\n", - "This gives\n", - "\n", - "$$-\\frac{5}{4}(I-Z_1)^2 -\\frac{4}{4}(I-Z_1)(I-Z_2) + \\frac{6}{4}(I-Z_2)^2 $$\n", - "\n", - "which simplifies to\n", - "\n", - "$$-\\frac{1}{2}I +\\frac{7}{2}Z_1 -2Z_2 -Z_1Z_2$$ \n", - "\n", - "The $-I/2$ term is simply a constant offset, so we can solve the problem by finding the minimum of \n", - "\n", - "$$\\langle \\psi | \\frac{7}{2}Z_1 -2Z_2 -Z_1Z_2 |\\psi\\rangle$$ \n", - "\n", - "Note that the minimum should correspond to the computational basis state $|10\\rangle$, and the corresponding true objective function value should be $-4.5$ (ignoring the offset value of $-1/2$)" - ] - }, - { - "cell_type": "markdown", - "id": "8176aa81", - "metadata": {}, - "source": [ - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "45964c1f", - "metadata": {}, - "outputs": [], - "source": [ - "import tensorcircuit as tc\n", - "import numpy as np\n", - "import tensorflow as tf\n", - "import matplotlib.pyplot as plt\n", - "from functools import partial" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "4006848a-1a2f-407a-9f80-63e75ea0d3a4", - "metadata": {}, - "outputs": [], - "source": [ - "# we first manually encode the terms (-7/2) Z_1 - 2 Z_2 - Z_1Z_2 as:\n", - "pauli_terms = [\n", - " [1, 0],\n", - " [0, 1],\n", - " [1, 1],\n", - "] # see the TensorCircuit whitepaper for 'pauli structures'\n", - "weights = [7 / 2, -2, -1]\n", - "\n", - "# see below for a function to generate the pauli terms and weights from the QUBO matrix" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d197cf4a-1bad-4470-a846-998bfe68ba3c", - "metadata": {}, - "outputs": [], - "source": [ - "# Now we define the QAOA ansatz of depth nlayers\n", - "def QAOA_from_Ising(params, nlayers, pauli_terms, weights):\n", - " nqubits = len(pauli_terms[0])\n", - " c = tc.Circuit(nqubits)\n", - " for i in range(nqubits):\n", - " c.h(i)\n", - " for j in range(nlayers):\n", - " for k in range(len(pauli_terms)):\n", - " term = pauli_terms[k]\n", - " index_of_ones = []\n", - " for l in range(len(term)):\n", - " if term[l] == 1:\n", - " index_of_ones.append(l)\n", - " if len(index_of_ones) == 1:\n", - " c.rz(index_of_ones[0], theta=2 * weights[k] * params[2 * j])\n", - " elif len(index_of_ones) == 2:\n", - " c.exp1(\n", - " index_of_ones[0],\n", - " index_of_ones[1],\n", - " unitary=tc.gates._zz_matrix,\n", - " theta=weights[k] * params[2 * j],\n", - " )\n", - " else:\n", - " raise ValueError(\"Invalid number of Z terms\")\n", - "\n", - " for i in range(nqubits):\n", - " c.rx(i, theta=params[2 * j + 1]) # mixing terms\n", - " return c" - ] - }, - { - "cell_type": "markdown", - "id": "cb38c120-500a-44cc-96ec-fb5ceb11032d", - "metadata": {}, - "source": [ - "For a general state that is the output of a quantum circuit c, we first define the corresponding loss with respect to the Ising Hamiltonian." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "88cec9cf-3ab6-4a4c-b743-ed95ee8c3817", - "metadata": {}, - "outputs": [], - "source": [ - "def Ising_loss(c, pauli_terms, weights):\n", - " loss = 0.0\n", - " for k in range(len(pauli_terms)):\n", - " term = pauli_terms[k]\n", - " index_of_ones = []\n", - "\n", - " for l in range(len(term)):\n", - " if term[l] == 1:\n", - " index_of_ones.append(l)\n", - "\n", - " if len(index_of_ones) == 1:\n", - " delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]])\n", - "\n", - " else:\n", - " delta_loss = weights[k] * c.expectation_ps(\n", - " z=[index_of_ones[0], index_of_ones[1]]\n", - " )\n", - "\n", - " loss += delta_loss\n", - "\n", - " return K.real(loss)" - ] - }, - { - "cell_type": "markdown", - "id": "30a3aa96-7823-4337-9b2f-5170502bb893", - "metadata": {}, - "source": [ - "For the particular case of a circuit corresponding to a QAOA ansatz this is:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "26e4bec2-ce5b-4d0d-9e06-c80fda20619f", - "metadata": {}, - "outputs": [], - "source": [ - "def QAOA_loss(nlayers, pauli_terms, weights, params):\n", - " c = QAOA_from_Ising(params, nlayers, pauli_terms, weights)\n", - " return Ising_loss(c, pauli_terms, weights)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ca8b7a76-5c4f-4ad8-9173-90126b8bb93b", - "metadata": {}, - "outputs": [], - "source": [ - "K = tc.set_backend(\"tensorflow\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d5b1897f-cd77-4cd3-bd3b-ece64e6004fc", - "metadata": {}, - "outputs": [], - "source": [ - "def QAOA_solve(pauli_terms, weights, nlayers, iterations):\n", - " print_every = 100\n", - " learning_rate = 1e-2\n", - "\n", - " loss_val_grad = K.value_and_grad(partial(QAOA_loss, nlayers, pauli_terms, weights))\n", - " loss_val_grad_jit = K.jit(loss_val_grad)\n", - "\n", - " opt = K.optimizer(tf.keras.optimizers.Adam(learning_rate))\n", - "\n", - " params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5)\n", - " print(f\"initial params: {params}\")\n", - " for i in range(iterations):\n", - " loss, grads = loss_val_grad_jit(params)\n", - " if i % print_every == 0:\n", - " print(K.numpy(loss))\n", - " params = opt.update(grads, params)\n", - "\n", - " return params" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "2bc533da-b4f2-4ffb-b486-c65880a30a6d", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "initial params: [ 0.39931756 -0.49578992 -0.22545011 -0.40585193]\n", - "-2.1728685\n", - "-4.177884\n", - "-4.2291102\n", - "-4.2291365\n", - "-4.229136\n" - ] - } - ], - "source": [ - "iterations = 500\n", - "nlayers = 2\n", - "final_params = QAOA_solve(pauli_terms, weights, nlayers, iterations)" - ] - }, - { - "cell_type": "markdown", - "id": "e93d8cbe-2884-4f0a-80f8-3b600194927b", - "metadata": {}, - "source": [ - "We note that for nlayers=2 and 500 iterations, the objective function does not in this case (although it depends on the initial parameters)converge to the true value of $-4.5$. However, the we see below that the final wavefunction does have large overlap with the desired state $|10\\rangle$, so measuring the output of the QAOA algorithm will, with high probability, output the correct answer." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "294ea9ce-5064-4176-94d0-8dbb7d1707f8", - "metadata": {}, - "outputs": [], - "source": [ - "def print_output(c):\n", - " n = c._nqubits\n", - " N = 2**n\n", - " x_label = r\"$\\left|{0:0\" + str(n) + r\"b}\\right>$\"\n", - " labels = [x_label.format(i) for i in range(N)]\n", - " plt.bar(range(N), c.probability())\n", - " plt.xticks(range(N), labels, rotation=70);" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "fc1353ab-7a7a-4cdc-931c-3b90417c4961", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGwCAYAAAB7MGXBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAdrklEQVR4nO3df3DX9X3A8VcSIAEx0UpJhKamFVv1kGChpqCt/SMVN0bLRk/OUqGs02urzhrdlVgkqB3RbuXoTVqunuy6cx70x3Q/YNQay7UrdMzgDp2KqxaJ2oSgZxLiSJZ8v/ujIy4jKF8E33y/PB53+YNPPp/knXvlQ575fD/fb4qy2Ww2AAASKU69AADg1CZGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgqVGpF3A0MplMvPLKK3H66adHUVFR6uUAAEchm81GT09PTJo0KYqLj3z9Iy9i5JVXXonq6urUywAAjkFbW1u8733vO+L78yJGTj/99Ij43RdTXl6eeDUAwNHo7u6O6urqoZ/jR5IXMXLooZny8nIxAgB55u1usXADKwCQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgqVGpFwCQq5plm1Iv4ZS15+65qZdAAXJlBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFLHFCNr166NmpqaKCsri7q6utixY8db7r9mzZr48Ic/HGPHjo3q6uq4+eab4+DBg8e0YACgsOQcIxs3boyGhoZoamqKnTt3Rm1tbcyZMyf27ds34v4PPvhgLFu2LJqamuKZZ56J+++/PzZu3Bi33XbbO148AJD/co6R1atXx7XXXhtLly6NCy+8MNatWxfjxo2L9evXj7j/tm3b4tJLL43Pfe5zUVNTE1dccUVcffXVb3s1BQA4NeQUI/39/dHa2hr19fVvfoDi4qivr4/t27ePeMzs2bOjtbV1KD5eeOGF2Lx5c/z+7//+ET9PX19fdHd3D3sDAArTqFx23r9/fwwODkZlZeWw7ZWVlfHss8+OeMznPve52L9/f1x22WWRzWZjYGAgvvSlL73lwzTNzc1xxx135LI0ACBPnfBn02zdujVWrVoV3/nOd2Lnzp3xd3/3d7Fp06a46667jnhMY2NjdHV1Db21tbWd6GUCAInkdGVkwoQJUVJSEh0dHcO2d3R0RFVV1YjH3H777XHNNdfEn/zJn0RExEUXXRS9vb1x3XXXxde//vUoLj68h0pLS6O0tDSXpQEAeSqnKyNjxoyJGTNmREtLy9C2TCYTLS0tMWvWrBGPeeONNw4LjpKSkoiIyGazua4XACgwOV0ZiYhoaGiIJUuWxMyZM+OSSy6JNWvWRG9vbyxdujQiIhYvXhyTJ0+O5ubmiIiYN29erF69Oi6++OKoq6uLX//613H77bfHvHnzhqIEADh15RwjCxcujM7OzlixYkW0t7fH9OnTY8uWLUM3te7du3fYlZDly5dHUVFRLF++PF5++eV473vfG/PmzYs///M/P35fBQCQt4qyefBYSXd3d1RUVERXV1eUl5enXg6QWM2yTamXcMrac/fc1Esgjxztz29/mwYASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJDUMcXI2rVro6amJsrKyqKuri527Njxlvu//vrrcf3118fZZ58dpaWl8aEPfSg2b958TAsGAArLqFwP2LhxYzQ0NMS6deuirq4u1qxZE3PmzIndu3fHxIkTD9u/v78/PvWpT8XEiRPjRz/6UUyePDlefPHFOOOMM47H+gGAPJdzjKxevTquvfbaWLp0aURErFu3LjZt2hTr16+PZcuWHbb/+vXr47XXXott27bF6NGjIyKipqbmna0aACgYOT1M09/fH62trVFfX//mBygujvr6+ti+ffuIx/zDP/xDzJo1K66//vqorKyMqVOnxqpVq2JwcPCIn6evry+6u7uHvQEAhSmnGNm/f38MDg5GZWXlsO2VlZXR3t4+4jEvvPBC/OhHP4rBwcHYvHlz3H777fGtb30rvvGNbxzx8zQ3N0dFRcXQW3V1dS7LBADyyAl/Nk0mk4mJEyfG9773vZgxY0YsXLgwvv71r8e6deuOeExjY2N0dXUNvbW1tZ3oZQIAieR0z8iECROipKQkOjo6hm3v6OiIqqqqEY85++yzY/To0VFSUjK07YILLoj29vbo7++PMWPGHHZMaWlplJaW5rI0ACBP5XRlZMyYMTFjxoxoaWkZ2pbJZKKlpSVmzZo14jGXXnpp/PrXv45MJjO07bnnnouzzz57xBABAE4tOT9M09DQEPfdd198//vfj2eeeSa+/OUvR29v79CzaxYvXhyNjY1D+3/5y1+O1157LW666aZ47rnnYtOmTbFq1aq4/vrrj99XAQDkrZyf2rtw4cLo7OyMFStWRHt7e0yfPj22bNkydFPr3r17o7j4zcaprq6On/zkJ3HzzTfHtGnTYvLkyXHTTTfF1772teP3VQAAeasom81mUy/i7XR3d0dFRUV0dXVFeXl56uUAidUs25R6CaesPXfPTb0E8sjR/vz2t2kAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASOqYYmTt2rVRU1MTZWVlUVdXFzt27Diq4zZs2BBFRUUxf/78Y/m0AEAByjlGNm7cGA0NDdHU1BQ7d+6M2tramDNnTuzbt+8tj9uzZ0/ceuut8fGPf/yYFwsAFJ6cY2T16tVx7bXXxtKlS+PCCy+MdevWxbhx42L9+vVHPGZwcDAWLVoUd9xxR3zwgx98RwsGAApLTjHS398fra2tUV9f/+YHKC6O+vr62L59+xGPu/POO2PixInxxS9+8dhXCgAUpFG57Lx///4YHByMysrKYdsrKyvj2WefHfGYf/mXf4n7778//v3f//2oP09fX1/09fUN/bu7uzuXZQIAeeSEPpump6cnrrnmmrjvvvtiwoQJR31cc3NzVFRUDL1VV1efwFUCACnldGVkwoQJUVJSEh0dHcO2d3R0RFVV1WH7P//887Fnz56YN2/e0LZMJvO7TzxqVOzevTvOPffcw45rbGyMhoaGoX93d3cLEgAoUDnFyJgxY2LGjBnR0tIy9PTcTCYTLS0tccMNNxy2//nnnx9PPvnksG3Lly+Pnp6e+Pa3v33EwCgtLY3S0tJclgYA5KmcYiQioqGhIZYsWRIzZ86MSy65JNasWRO9vb2xdOnSiIhYvHhxTJ48OZqbm6OsrCymTp067PgzzjgjIuKw7QDAqSnnGFm4cGF0dnbGihUror29PaZPnx5btmwZuql17969UVzshV0BgKNTlM1ms6kX8Xa6u7ujoqIiurq6ory8PPVygMRqlm1KvYRT1p6756ZeAnnkaH9+u4QBACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABI6phiZO3atVFTUxNlZWVRV1cXO3bsOOK+9913X3z84x+PM888M84888yor69/y/0BgFNLzjGycePGaGhoiKampti5c2fU1tbGnDlzYt++fSPuv3Xr1rj66qvjZz/7WWzfvj2qq6vjiiuuiJdffvkdLx4AyH9F2Ww2m8sBdXV18dGPfjTuvffeiIjIZDJRXV0dN954Yyxbtuxtjx8cHIwzzzwz7r333li8ePFRfc7u7u6oqKiIrq6uKC8vz2W5QAGqWbYp9RJOWXvunpt6CeSRo/35ndOVkf7+/mhtbY36+vo3P0BxcdTX18f27duP6mO88cYb8d///d/xnve854j79PX1RXd397A3AKAw5RQj+/fvj8HBwaisrBy2vbKyMtrb24/qY3zta1+LSZMmDQua/6+5uTkqKiqG3qqrq3NZJgCQR97VZ9PcfffdsWHDhnjooYeirKzsiPs1NjZGV1fX0FtbW9u7uEoA4N00KpedJ0yYECUlJdHR0TFse0dHR1RVVb3lsX/5l38Zd999dzz66KMxbdq0t9y3tLQ0SktLc1kaAJCncroyMmbMmJgxY0a0tLQMbctkMtHS0hKzZs064nHf/OY346677ootW7bEzJkzj321AEDByenKSEREQ0NDLFmyJGbOnBmXXHJJrFmzJnp7e2Pp0qUREbF48eKYPHlyNDc3R0TEPffcEytWrIgHH3wwampqhu4tGT9+fIwfP/44fikAQD7KOUYWLlwYnZ2dsWLFimhvb4/p06fHli1bhm5q3bt3bxQXv3nB5bvf/W709/fHZz/72WEfp6mpKVauXPnOVg8A5L2cX2ckBa8zAvxfXmckHa8zQi5OyOuMAAAcb2IEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJIalXoBABARUbNsU+olnLL23D036ed3ZQQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICk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mUwmRo363ZPdqqqq4p577oklS5aYbR762c9+FitXroxf/OIXztsC5Zx958RIHvqP//iP+Nu//dvYvHlzlJeXxznnnBOLFy+OT33qU6mXxnHwf//zevLJJ2PBggWxe/duv13luaeffjo2bNgQ//RP/xTjx4933uap7NvcjOqcPTZi5CT3+uuvxxNPPBG//e1vo7+/P2bPnh0f+tCHht7f09MT48eP902fhw7Ntr29PTKZTHzsYx+Lc889d9g+fX190dnZGe973/v8fYs8NTAwECUlJcPO0Z6enhg3bpzfmAvQf/3Xf8X+/fujurraOZsDMXISOvQN/Nhjj8Xq1atj8+bN8f73vz+qqqriwIEDcf7558fChQtj7ty5MW7cON/weeStZtvb2xvnn39+LFq0KH7v934vSktLUy+XHBz6jbmzszMGBwdj4sSJw87LbDYbg4ODUVxc7HzNI283V44PMXISOvQD6yMf+UhMnz49Vq5cGaWlpdHa2hq7du2Kf/3Xf42XX345vvCFL8RXvvKV1MslB2ZbuA7N9g//8A+jq6srFi5cGJdddlmcc845MX78+GH7Pv300zEwMDDsab+cnHKZ6zPPPBP9/f1RW1ubaLV5LMEzeDgKr7zySvaMM87I/uY3vznsfc8991y2sbExW1RUlH3ggQfe/cXxjpht4XrppZeyo0ePzs6ePTtbWlqaraioyF511VXZH/zgB9nnn38+e/DgwWwmk8nOnz8/+41vfCObzXraZz4w1xPPtaaT1MGDB+ODH/xg/PjHPz7sfeedd16sWrUqrrvuunjkkUeiv78/wQo5VmZbeLL/e4F527ZtMWvWrHj44Yfj4MGDce+998ZLL70UCxcujE9+8pNx6623xt/8zd/E3//938dnPvOZxKvm7Zjru0eMnIQymUx84AMfiCuvvDK+//3vx49//OM4cODAYftNmTIldu3adcS/AsrJx2wL06GbU2tqauLKK68cmunnP//5+OUvfxn79++PG2+8MR599NFYunRp1NbWxtSpU71M+EnOXN897hk5ibW1tcUtt9wSDz30UMyePTuuueaa+OhHPxqjR4+O3bt3x5133hlXXXVVNDY2Dv0RJvKD2RamgYGB2LdvX0yaNGno30VFRcOeNTNlypS44YYb4qtf/arZ5glzfRekfIyIw23cuDH79NNPD9v2y1/+MrtgwYLsaaedlj3ttNOyF198cfb000/P3nTTTdkDBw5ks1mPT+YDsy1cI812cHAwOzAwkM1mfzfDgYGB7L/9279li4qKsvv27RvazsnLXN89roycRLLZbCxYsCAef/zxOOecc2LBggWxaNGieO973zu0z2OPPRa//e1vY+bMmTFlyhSvU5AnzLZw/f/ZXnXVVbFo0aJ4z3veM7TPoZcEb2tri61bt3plzjxgru8uMXKSee211+I3v/lNPPLII7Fly5Z48cUXY9q0afH5z38+PvvZzx72/Hbf+PnDbAvXSLOtra2Na665JhYsWDDs/oH+/n73AuUJc333iJGT1MDAQLz66qvx1FNPxebNm6OlpSUOHDgQn/jEJ+KP//iP47LLLhva99AI3TCVH8y2cP3/2T722GNx4MCB+OQnPxlf+MIX4tJLLx3a12zzh7meeGIkD/T19UV7e3s8/vjj8Y//+I+xffv2KCsri3nz5sXixYuHvTw8+cVsC5fZFiZzPTHESJ7p7e2NvXv3xs9//vP453/+5/jVr34VCxYsiJUrVw67/4D8Y7aFy2wLk7keP2IkT2Uymeju7o7//M//jK6urrjsssuirKws9bI4Dsy2cJltYTLXd06MAABJeQVWACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApP4H157oSnD133MAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "c = QAOA_from_Ising(final_params, nlayers, pauli_terms, weights)\n", - "\n", - "print_output(c)" - ] - }, - { - "cell_type": "markdown", - "id": "d155c5e5-5843-4bba-9edc-595a18cb0c9a", - "metadata": {}, - "source": [ - "## General Case\n", - "\n", - "For the general QUBO case, we wish to minimize\n", - "\n", - "$$ x^T Q x$$\n", - "\n", - "where $x\\in\\{0,1\\}^n$ and $Q\\in\\mathbb{R}^{n\\times n}$ is a real symmetric matrix.\n", - "\n", - "This maps to an Ising Hamiltonian \n", - "\n", - "$$\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i 0 $: risk-appetite\n", - "* $\\Sigma \\in \\mathbb{R}^{n\\times n}$: covariance matrix of the assets\n", - "* $\\mu\\in\\mathbb{R}^n$: mean return of the assets\n", - "* $B$: budget (i.e., total number of assets out of $n$ that can be selected)\n", - "\n", - "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and consider the alternative problem:\n", - "\n", - "$$ \\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2$$\n", - "\n", - "The variables in the linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be squared (since they are boolean variables), i.e. we can consider\n", - "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2$$\n", - "\n", - "which is a QUBO defined by the matrix $Q$ \n", - "\n", - "$$ Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", - "1 & 1-2B & 1 & \\ldots \\\\1 & 1 & 1-2B \\\\\n", - "\\vdots\\end{pmatrix}$$\n", - "\n", - "i.e., we wish to mimimize\n", - "\n", - "$$ x^T Q X + tB$$\n", - "\n", - "and we ignore the constant term $t B$.\n", - "We can now solve this by QAOA as above.\n", - "\n", - "Let us first define a function to convert portfolio data into a QUBO matrix:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "3080b901-fb6c-4bda-8348-c96540cbc39a", - "metadata": {}, - "outputs": [], - "source": [ - "def QUBO_from_portfolio(cov, mean, q, B, t):\n", - " # cov: n x n covariance numpy array\n", - " # mean: numpy array of means\n", - " n = cov.shape[0]\n", - " R = np.diag(mean)\n", - " S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n))\n", - "\n", - " Q = q * cov - R + t * S\n", - " return Q" - ] - }, - { - "cell_type": "markdown", - "id": "b4cdcb0e-15a2-461c-b487-084488486c67", - "metadata": {}, - "source": [ - "We can test this using the qiskit_finance package to generate some stock covariance and mean data:\n", - "\n", - "*Note that this was tested with qiskit version 0.39.3 and qiskit-finance version 0.3.4.*" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "2168c69e-73ce-4306-8a39-4ddc475acc8f", - "metadata": {}, - "outputs": [], - "source": [ - "import datetime\n", - "from qiskit_finance.data_providers import RandomDataProvider" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "6a7bc671-a496-4cd8-b954-50a280b5dd85", - "metadata": {}, - "outputs": [], - "source": [ - "num_assets = 4\n", - "seed = 123\n", - "\n", - "# Generate expected return and covariance matrix from (random) time-series\n", - "stocks = [(\"TICKER%s\" % i) for i in range(num_assets)]\n", - "data = RandomDataProvider(\n", - " tickers=stocks,\n", - " start=datetime.datetime(2016, 1, 1),\n", - " end=datetime.datetime(2016, 1, 30),\n", - " seed=seed,\n", - ")\n", - "data.run()\n", - "\n", - "mu = data.get_period_return_mean_vector()\n", - "sigma = data.get_period_return_covariance_matrix()" - ] - }, - { - "cell_type": "markdown", - "id": "f6dc53d4-7ed0-436d-aa1f-8674c56e756e", - "metadata": {}, - "source": [ - "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the pauli terms and weights" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "3f6edcd5-3c10-49fc-86ea-160fc6d3187e", - "metadata": {}, - "outputs": [], - "source": [ - "q = 0.5\n", - "budget = 3 # Note that in this example, there are 4 assets, but a budget of only 3\n", - "penalty = 3\n", - "\n", - "Q = QUBO_from_portfolio(sigma, mu, q, budget, penalty)\n", - "portfolio_pauli_terms, portfolio_weights, portfolio_offset = QUBO_to_Ising(Q)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "809b90fa-7047-4c88-b862-355da4f58a50", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0000: 21.006979417669037\n", - "0001: 6.006208358124514\n", - "0010: 6.006857249462996\n", - "0011: -2.994037697463167\n", - "0100: 6.007889613170697\n", - "0101: -2.992836964752989\n", - "0110: -2.992179512275861\n", - "0111: -5.9930299775811875\n", - "1000: 5.992965725313347\n", - "1001: -3.007905195444355\n", - "1010: -3.0070278423618397\n", - "1011: -6.008022650501182\n", - "1100: -3.0060506769683\n", - "1101: -6.006877116105166\n", - "1110: -6.005991201884008\n", - "1111: -3.006941528402507\n" - ] - } - ], - "source": [ - "# Brute force search over classical results for comparison before we run QAOA\n", - "for i in range(2):\n", - " for j in range(2):\n", - " for k in range(2):\n", - " for l in range(2):\n", - " x = np.array([i, j, k, l])\n", - " print(f\"{i}{j}{k}{l}: {np.dot(x,np.dot(Q,x))- portfolio_offset}\")" - ] - }, - { - "cell_type": "markdown", - "id": "b5e69a34-87dc-47b4-aeb2-3b9a03fd0974", - "metadata": {}, - "source": [ - "We see that, due to the penalty, the lowest energy solutions correspond to 0111, 1011, 1101, 1110, i.e. the portfolios with only 3 assets." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "80c1de6c-d3a4-4ea5-922a-bffb59dd1ea3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "initial params: [ 0.13778198 -0.75357753 -0.01271329 -0.5461785 -0.1501883 0.36323363]\n", - "-4.204754\n", - "-5.681799\n", - "-5.6837077\n", - "-5.6837044\n", - "-5.6837053\n", - "-5.683704\n", - "-5.6837063\n", - "-5.683709\n", - "-5.6837063\n", - "-5.683705\n" - ] - } - ], - "source": [ - "iterations = 1000\n", - "nlayers = 3\n", - "final_params = QAOA_solve(portfolio_pauli_terms, portfolio_weights, nlayers, iterations)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "8a9064e3-0c61-4d2d-baf9-bdf120c0331d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "c_final = QAOA_from_Ising(\n", - " final_params, nlayers, portfolio_pauli_terms, portfolio_weights\n", - ")\n", - "print_output(c_final)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.0" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 57d94bc736fd5ada3e5cad7afa99a95a32265855 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Fri, 25 Aug 2023 14:07:19 +0100 Subject: [PATCH 020/139] Rename QUBO_problem.ipynb to qubo_problem.ipynb --- docs/source/tutorials/{QUBO_problem.ipynb => qubo_problem.ipynb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/source/tutorials/{QUBO_problem.ipynb => qubo_problem.ipynb} (100%) diff --git a/docs/source/tutorials/QUBO_problem.ipynb b/docs/source/tutorials/qubo_problem.ipynb similarity index 100% rename from docs/source/tutorials/QUBO_problem.ipynb rename to docs/source/tutorials/qubo_problem.ipynb From c03cff49786d6b4c7a5fe3f537d5e5cefd8fb6d6 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 29 Aug 2023 14:55:08 +0800 Subject: [PATCH 021/139] tc2qiskit new measurement order --- CHANGELOG.md | 3 +++ README.md | 2 ++ tensorcircuit/translation.py | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f7e7dd9..2d87e8f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ - move ensemble module to applications/ai (breaking changes) +- tc2qiskit now record qiskit measure with incremental clbit from 0 + ## 0.11.0 ### Added @@ -39,6 +41,7 @@ - fix rem `apply_correction` bug when non-numpy backend is set - fix tf warning for `cast` with higher version of tf + ### Changed - The static method `BaseCircuit.copy` is renamed as `BaseCircuit.copy_nodes` (breaking changes) diff --git a/README.md b/README.md index ca4b5cb3..2b548913 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,8 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Practical advantage of quantum machine learning in ghost imaging: https://www.nature.com/articles/s42005-023-01290-1 (published in Communications Physics). +- Zero and Finite Temperature Quantum Simulations Powered by Quantum Magic: https://arxiv.org/abs/2308.11616. + If you want to highlight your research work here, feel free to add by opening PR. diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 045751c2..f300fc8a 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -235,6 +235,7 @@ def qir2qiskit( qiskit_circ = QuantumCircuit(n) if initialization is not None: qiskit_circ.initialize(initialization) + measure_cbit = 0 for gate_info in qir: index = gate_info["index"] gate_name = str(gate_info["gatef"]) @@ -325,7 +326,8 @@ def qir2qiskit( ) qiskit_circ.unitary(qop, index[::-1], label=qis_name) elif gate_name == "measure": - qiskit_circ.measure(index[0], index[0]) + qiskit_circ.measure(index[0], measure_cbit) + measure_cbit += 1 elif gate_name == "reset": qiskit_circ.reset(index[0]) elif gate_name == "barrier": From 435ffb27a825fb910fac36d0b29beae069669c24 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 30 Aug 2023 11:09:36 +0800 Subject: [PATCH 022/139] add det on backend --- CHANGELOG.md | 2 ++ tensorcircuit/backends/abstract_backend.py | 13 +++++++++++++ tensorcircuit/backends/jax_backend.py | 5 ++++- tensorcircuit/backends/numpy_backend.py | 3 +++ tensorcircuit/backends/pytorch_backend.py | 3 +++ tensorcircuit/backends/tensorflow_backend.py | 3 +++ tests/test_backends.py | 3 +++ 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d87e8f4..bfc11775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - Add translation of r gate from qiskit +- Add `det` method at backends + ### Changed - move ensemble module to applications/ai (breaking changes) diff --git a/tensorcircuit/backends/abstract_backend.py b/tensorcircuit/backends/abstract_backend.py index e6f69f97..71e90f68 100644 --- a/tensorcircuit/backends/abstract_backend.py +++ b/tensorcircuit/backends/abstract_backend.py @@ -345,6 +345,19 @@ def adjoint(self: Any, a: Tensor) -> Tensor: """ return self.conj(self.transpose(a)) + def det(self: Any, a: Tensor) -> Tensor: + """ + Return the determinant scalar of a tensor ``a`` + + :param a: Input tensor + :type a: Tensor + :return: determinant of ``a`` + :rtype: Tensor + """ + raise NotImplementedError( + "Backend '{}' has not implemented `det`.".format(self.name) + ) + def i(self: Any, dtype: str) -> Tensor: """ Return 1.j in as a tensor compatible with the backend. diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index 472066ea..d7e1e36f 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -295,7 +295,10 @@ def i(self, dtype: Any = None) -> Tensor: dtype = npdtype # type: ignore if isinstance(dtype, str): dtype = getattr(jnp, dtype) - return np.array(1j, dtype=dtype) + return jnp.array(1j, dtype=dtype) + + def det(self, a: Tensor) -> Tensor: + return jnp.linalg.det(a) def real(self, a: Tensor) -> Tensor: return jnp.real(a) diff --git a/tensorcircuit/backends/numpy_backend.py b/tensorcircuit/backends/numpy_backend.py index 2d22b94d..1cc9fac6 100644 --- a/tensorcircuit/backends/numpy_backend.py +++ b/tensorcircuit/backends/numpy_backend.py @@ -131,6 +131,9 @@ def dtype(self, a: Tensor) -> str: def numpy(self, a: Tensor) -> Tensor: return a + def det(self, a: Tensor) -> Tensor: + return np.linalg.det(a) + def i(self, dtype: Any = None) -> Tensor: if not dtype: dtype = npdtype # type: ignore diff --git a/tensorcircuit/backends/pytorch_backend.py b/tensorcircuit/backends/pytorch_backend.py index 7362cc47..3256a44e 100644 --- a/tensorcircuit/backends/pytorch_backend.py +++ b/tensorcircuit/backends/pytorch_backend.py @@ -306,6 +306,9 @@ def i(self, dtype: Any = None) -> Tensor: dtype = getattr(torchlib, dtype) return torchlib.tensor(1j, dtype=dtype) + def det(self, a: Tensor) -> Tensor: + return torchlib.linalg.det(a) + def real(self, a: Tensor) -> Tensor: try: a = torchlib.real(a) diff --git a/tensorcircuit/backends/tensorflow_backend.py b/tensorcircuit/backends/tensorflow_backend.py index 91b6be6e..632b558f 100644 --- a/tensorcircuit/backends/tensorflow_backend.py +++ b/tensorcircuit/backends/tensorflow_backend.py @@ -480,6 +480,9 @@ def i(self, dtype: Any = None) -> Tensor: dtype = getattr(tf, dtype) return tf.constant(1j, dtype=dtype) + def det(self, a: Tensor) -> Tensor: + return tf.linalg.det(a) + def min(self, a: Tensor, axis: Optional[int] = None) -> Tensor: return tf.reduce_min(a, axis=axis) diff --git a/tests/test_backends.py b/tests/test_backends.py index 6e387eb2..3c73c1ab 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -300,6 +300,9 @@ def test_backend_methods_2(backend): np.maximum(arr, 0), atol=1e-4, ) + np.testing.assert_allclose( + tc.backend.det(tc.backend.convert_to_tensor(np.eye(3) * 2)), 8, atol=1e-5 + ) # @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb"), lf("torchb")]) From 415f1789a54ac81b7ad1c4ff14995ef4b21008ce Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 31 Aug 2023 14:51:59 +0800 Subject: [PATCH 023/139] inital draft on fgs --- CHANGELOG.md | 2 + docs/source/api/fgs.rst | 7 + docs/source/modules.rst | 1 + requirements/requirements-extra.txt | 1 + tensorcircuit/__init__.py | 2 + tensorcircuit/backends/abstract_backend.py | 15 + tensorcircuit/backends/jax_backend.py | 3 + tensorcircuit/backends/numpy_backend.py | 5 +- tensorcircuit/fgs.py | 550 +++++++++++++++++++++ tests/test_fgs.py | 104 ++++ 10 files changed, 689 insertions(+), 1 deletion(-) create mode 100644 docs/source/api/fgs.rst create mode 100644 tensorcircuit/fgs.py create mode 100644 tests/test_fgs.py diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc11775..c2a51e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - Add `det` method at backends +- Add fermion Gaussian state simulator in `fgs.py` + ### Changed - move ensemble module to applications/ai (breaking changes) diff --git a/docs/source/api/fgs.rst b/docs/source/api/fgs.rst new file mode 100644 index 00000000..f00001b4 --- /dev/null +++ b/docs/source/api/fgs.rst @@ -0,0 +1,7 @@ +tensorcircuit.fgs +================================================================================ +.. automodule:: tensorcircuit.fgs + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/modules.rst b/docs/source/modules.rst index 5f08781f..0144a199 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -13,6 +13,7 @@ tensorcircuit ./api/cons.rst ./api/densitymatrix.rst ./api/experimental.rst + ./api/fgs.rst ./api/gates.rst ./api/interfaces.rst ./api/keras.rst diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index acd416e3..80fff586 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -6,3 +6,4 @@ torch jupyter mthree==1.1.0 mitiq +openfermion diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index 3bf75d98..a3993163 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -40,6 +40,8 @@ from .quantum import QuOperator, QuVector, QuAdjointVector, QuScalar from . import compiler from . import cloud +from . import fgs +from .fgs import FGSSimulator try: from . import keras diff --git a/tensorcircuit/backends/abstract_backend.py b/tensorcircuit/backends/abstract_backend.py index 71e90f68..472f0081 100644 --- a/tensorcircuit/backends/abstract_backend.py +++ b/tensorcircuit/backends/abstract_backend.py @@ -358,6 +358,21 @@ def det(self: Any, a: Tensor) -> Tensor: "Backend '{}' has not implemented `det`.".format(self.name) ) + def schur(self: Any, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + """ + Compute Schur decomposition of a matrix. + + :param a: _description_ + :type a: Tensor + :param output: _description_, defaults to "real" + :type output: str, optional + :return: T, Z so that ZTZ^H = a + :rtype: Tuple[Tensor, Tensor] + """ + raise NotImplementedError( + "Backend '{}' has not implemented `schur`.".format(self.name) + ) + def i(self: Any, dtype: str) -> Tensor: """ Return 1.j in as a tensor compatible with the backend. diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index d7e1e36f..c9ca0249 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -300,6 +300,9 @@ def i(self, dtype: Any = None) -> Tensor: def det(self, a: Tensor) -> Tensor: return jnp.linalg.det(a) + def schur(self, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + return jsp.linalg.schur(a, output=output) # type: ignore + def real(self, a: Tensor) -> Tensor: return jnp.real(a) diff --git a/tensorcircuit/backends/numpy_backend.py b/tensorcircuit/backends/numpy_backend.py index 1cc9fac6..83ef3040 100644 --- a/tensorcircuit/backends/numpy_backend.py +++ b/tensorcircuit/backends/numpy_backend.py @@ -9,7 +9,7 @@ import numpy as np import tensornetwork -from scipy.linalg import expm, solve +from scipy.linalg import expm, solve, schur from scipy.special import softmax, expit from scipy.sparse import coo_matrix, issparse from tensornetwork.backends.numpy import numpy_backend @@ -134,6 +134,9 @@ def numpy(self, a: Tensor) -> Tensor: def det(self, a: Tensor) -> Tensor: return np.linalg.det(a) + def schur(self, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + return schur(a, output=output) # type: ignore + def i(self, dtype: Any = None) -> Tensor: if not dtype: dtype = npdtype # type: ignore diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py new file mode 100644 index 00000000..9314fa63 --- /dev/null +++ b/tensorcircuit/fgs.py @@ -0,0 +1,550 @@ +""" +Fermion Gaussian state simulator +""" +from typing import Any, List, Optional, Tuple + +import numpy as np + +try: + import openfermion +except ModuleNotFoundError: + pass + +from .cons import backend, dtypestr +from .circuit import Circuit +from . import quantum + +Tensor = Any + + +def onehot_matrix(i: int, j: int, N: int) -> Tensor: + m = np.zeros([N, N]) + m[i, j] = 1 + m = backend.convert_to_tensor(m) + m = backend.cast(m, dtypestr) + return m + + +# TODO(@refraction-ray): efficiency benchmark with jit +# TODO(@refraction-ray): occupation number post-selection/measurement +# TODO(@refraction-ray): FGS mixed state support? +# TODO(@refraction-ray): overlap? + + +class FGSSimulator: + r""" + main refs: https://arxiv.org/pdf/2306.16595.pdf, + https://arxiv.org/abs/2209.06945, + https://scipost.org/SciPostPhysLectNotes.54/pdf + + convention: + for Hamiltonian (c^dagger, c)H(c, c^\dagger) + for correlation <(c, c^\dagger)(c^\dagger, c)> + c' = \alpha^\dagger (c, c^\dagger) + """ + + def __init__( + self, + L: int, + filled: Optional[List[int]] = None, + alpha: Optional[Tensor] = None, + hc: Optional[Tensor] = None, + cmatrix: Optional[Tensor] = None, + ): + """ + _summary_ + + :param L: system size + :type L: int + :param filled: the fermion site that is fully occupied, defaults to None + :type filled: Optional[List[int]], optional + :param cmatrix: only used for debug, defaults to None + :type cmatrix: Optional[Tensor], optional + """ + if filled is None: + filled = [] + self.L = L + if alpha is None: + if hc is None: + self.alpha = self.init_alpha(filled, L) + else: + _, _, self.alpha = self.fermion_diagonalization(hc, L) + else: + self.alpha = alpha + self.wtransform = self.wmatrix(L) + self.cmatrix = cmatrix + + @classmethod + def fermion_diagonalization( + cls, hc: Tensor, L: int + ) -> Tuple[Tensor, Tensor, Tensor]: + es, u = backend.eigh(hc) + es = es[::-1] + u = u[:, ::-1] + alpha = u[:, :L] + return es, u, alpha + + @classmethod + def fermion_diagonalization_2( + cls, hc: Tensor, L: int + ) -> Tuple[Tensor, Tensor, Tensor]: + w = cls.wmatrix(L) + hm = 0.25 * w @ hc @ backend.adjoint(w) + hm = backend.real((-1.0j) * hm) + hd, om = backend.schur(hm, output="real") + # order not kept + # eps = 1e-10 + # idm = backend.convert_to_tensor(np.array([[1.0, 0], [0, 1.0]])) + # idm = backend.cast(idm, dtypestr) + # xm = backend.convert_to_tensor(np.array([[0, 1.0], [1.0, 0]])) + # xm = backend.cast(xm, dtypestr) + # for i in range(0, 2 * L, 2): + # (backend.sign(hd[i, i + 1] + eps) + 1) / 2 * idm - ( + # backend.sign(hd[i, i + 1] + eps) - 1 + # ) / 2 * xm + # print(hd) + + es = backend.adjoint(w) @ (1.0j * hd) @ w + u = 0.5 * backend.adjoint(w) @ backend.transpose(om) @ w + alpha = backend.adjoint(u)[:, :L] + # c' = u@c + # e_k (c^\dagger_k c_k - c_k c^\dagger_k) + return (es, u, alpha) + + @staticmethod + def wmatrix(L: int) -> Tensor: + w = np.zeros([2 * L, 2 * L], dtype=complex) + for i in range(2 * L): + if i % 2 == 1: + w[i, (i - 1) // 2] = 1.0j + w[i, (i - 1) // 2 + L] = -1.0j + else: + w[i, i // 2] = 1 + w[i, i // 2 + L] = 1 + return backend.convert_to_tensor(w) + + @staticmethod + def init_alpha(filled: List[int], L: int) -> Tensor: + alpha = np.zeros([2 * L, L]) + for i in range(L): + if i not in filled: + alpha[i, i] = 1 + else: + alpha[i + L, i] = 1 + alpha = backend.convert_to_tensor(alpha) + alpha = backend.cast(alpha, dtypestr) + return alpha + + def get_alpha(self) -> Tensor: + return self.alpha + + def get_cmatrix(self) -> Tensor: + if self.cmatrix is not None: + return self.cmatrix + return self.alpha @ backend.adjoint(self.alpha) + + def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor: + m = self.get_cmatrix() + if subsystems_to_trace_out is None: + subsystems_to_trace_out = [] + keep = [i for i in range(self.L) if i not in subsystems_to_trace_out] + keep += [i + self.L for i in range(self.L) if i not in subsystems_to_trace_out] + keep = backend.convert_to_tensor(keep) + + def slice_(a: Tensor) -> Tensor: + return backend.gather1d(a, keep) + + slice_ = backend.vmap(slice_) + m = backend.gather1d(slice_(m), keep) + return m + + def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor: + """ + compute renyi_entropy of order ``n`` for the fermion state + + :param n: _description_ + :type n: int + :param subsystems_to_trace_out: system sites to be traced out + :type subsystems_to_trace_out: List[int] + :return: _description_ + :rtype: Tensor + """ + m = self.get_reduced_cmatrix(subsystems_to_trace_out) + lbd, _ = backend.eigh(m) + lbd = backend.real(lbd) + lbd = backend.relu(lbd) + eps = 1e-6 + + entropy = backend.sum(backend.log(lbd ** n + (1 - lbd) ** n + eps)) + s = 1 / (2 * (1 - n)) * entropy + return s + + def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor: + """ + compute von Neumann entropy for the fermion state + + :param subsystems_to_trace_out: _description_, defaults to None + :type subsystems_to_trace_out: Optional[List[int]], optional + :return: _description_ + :rtype: Tensor + """ + m = self.get_reduced_cmatrix(subsystems_to_trace_out) # type: ignore + lbd, _ = backend.eigh(m) + lbd = backend.real(lbd) + lbd = backend.relu(lbd) + # lbd /= backend.sum(lbd) + eps = 1e-6 + entropy = -backend.sum( + lbd * backend.log(lbd + eps) + (1 - lbd) * backend.log(1 - lbd + eps) + ) + return entropy / 2 + + def evol_hamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-i/2 \hat{h}}` + + :param h: _description_ + :type h: Tensor + """ + # e^{-i/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(-1.0j * h) @ self.alpha + + def evol_ihamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-1/2 \hat{h}}` + + :param h: _description_ + :type h: Tensor + """ + # e^{-1/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(h) @ self.alpha + self.orthogonal() + + def orthogonal(self) -> None: + q, _ = backend.qr(self.alpha) + self.alpha = q + + @staticmethod + def hopping(chi: Tensor, i: int, j: int, L: int) -> Tensor: + # chi * ci dagger cj + hc. + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, j, 2 * L) + m += -chi / 2 * onehot_matrix(j + L, i + L, 2 * L) + m += backend.adjoint(m) + return m + + def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_j +h.c.` + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.hopping(chi, i, j, self.L)) + + @staticmethod + def chemical_potential(chi: Tensor, i: int, L: int) -> Tensor: + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, i, 2 * L) + m += -chi / 2 * onehot_matrix(i + L, i + L, 2 * L) + return m + + @staticmethod + def sc_pairing(chi: Tensor, i: int, j: int, L: int) -> Tensor: + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, j + L, 2 * L) + m += -chi / 2 * onehot_matrix(j, i + L, 2 * L) + m += backend.adjoint(m) + return m + + def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_j^\dagger +h.c.` + + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.sc_pairing(chi, i, j, self.L)) + + def evol_cp(self, i: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` + + :param i: _description_ + :type i: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.chemical_potential(chi, i, self.L)) + + def evol_icp(self, i: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` with :math:`\exp^{-H/2}` + + :param i: _description_ + :type i: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_ihamiltonian(self.chemical_potential(chi, i, self.L)) + + def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]: + return ( + backend.gather1d( + self.alpha, backend.convert_to_tensor([i for i in range(self.L)]) + ), + backend.gather1d( + self.alpha, + backend.convert_to_tensor([i + self.L for i in range(self.L)]), + ), + ) + + def get_cmatrix_majorana(self) -> Tensor: + c = self.get_cmatrix() + return self.wtransform @ c @ backend.adjoint(self.wtransform) + + def get_covariance_matrix(self) -> Tensor: + m = self.get_cmatrix_majorana() + return -1.0j * (2 * m - backend.eye(self.L * 2)) + + # def product(self, other): + # # self@other + # gamma1 = self.get_covariance_matrix() + # gamma2 = other.get_covariance_matrix() + # den = backend.inv(1 + gamma1 @ gamma2) + # idm = backend.eye(2 * self.L) + # covm = idm - (idm - gamma2) @ den @ (idm - gamma1) + # cm = (1.0j * covm + idm) / 2 + # cmatrix = backend.adjoint(self.wtransform) @ cm @ self.wtransform * 0.25 + # return type(self)(self.L, cmatrix=cmatrix) + + # def overlap(self, other): + # # ? + # u, v = self.get_bogoliubov_uv() + # u1, v1 = other.get_bogoliubov_uv() + # return backend.det( + # backend.adjoint(u1) @ u + backend.adjoint(v1) @ v + # ) * backend.det(backend.adjoint(v1) @ v), backend.det( + # backend.adjoint(u1) @ u + backend.adjoint(v1) @ v + # ) * backend.det( + # backend.adjoint(u1) @ u + # ) + + +class FGSTestSimulator: + def __init__( + self, L: int, filled: Optional[List[int]] = None, hc: Optional[Tensor] = None + ): + if filled is None: + filled = [] + self.L = L + self.state = self.init_state(filled, L) + if hc is not None: + self.state = self.fermion_diagonalization(hc, L) + + @staticmethod + def init_state(filled: List[int], L: int) -> Tensor: + c = Circuit(L) + for i in filled: + c.x(i) # type: ignore + return c.state() + + @classmethod + def fermion_diagonalization(cls, hc: Tensor, L: int) -> Tensor: + h = cls.get_hmatrix(hc, L) + _, u = np.linalg.eigh(h) + return u[:, 0] + + @staticmethod + def get_hmatrix(hc: Tensor, L: int) -> Tensor: + hm = np.zeros([2 ** L, 2 ** L], dtype=complex) + for i in range(L): + for j in range(L): + op = openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L, 2 * L): + for j in range(L): + op = openfermion.FermionOperator(f"{str(i-L)} {str(j)}") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L): + for j in range(L, 2 * L): + op = openfermion.FermionOperator(f"{str(i)}^ {str(j-L)}^") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L, 2 * L): + for j in range(L, 2 * L): + op = openfermion.FermionOperator(f"{str(i-L)} {str(j-L)}^") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + return hm + + @staticmethod + def hopping_jw(chi: Tensor, i: int, j: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + np.conj( + chi + ) * openfermion.FermionOperator(f"{str(j)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + @staticmethod + def chemical_potential_jw(chi: Tensor, i: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + def evol_hamiltonian(self, h: Tensor) -> None: + self.state = backend.expm(-1 / 2 * 1.0j * h) @ backend.reshape( + self.state, [-1, 1] + ) + self.state = backend.reshape(self.state, [-1]) + + def evol_ihamiltonian(self, h: Tensor) -> None: + self.state = backend.expm(-1 / 2 * h) @ backend.reshape(self.state, [-1, 1]) + self.state = backend.reshape(self.state, [-1]) + self.orthogonal() + + def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.hopping_jw(chi, i, j, self.L)) + + def evol_cp(self, i: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.chemical_potential_jw(chi, i, self.L)) + + def evol_icp(self, i: int, chi: Tensor = 0) -> None: + self.evol_ihamiltonian(self.chemical_potential_jw(chi, i, self.L)) + + @staticmethod + def sc_pairing_jw(chi: Tensor, i: int, j: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(j)}^") + np.conj( + chi + ) * openfermion.FermionOperator(f"{str(j)} {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.sc_pairing_jw(chi, i, j, self.L)) + + def orthogonal(self) -> None: + self.state /= backend.norm(self.state) + + def get_cmatrix(self) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(self.L): + for j in range(self.L): + op = openfermion.FermionOperator(f"{str(i)} {str(j)}^") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L): + op = openfermion.FermionOperator(f"{str(i-self.L)}^ {str(j)}^") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L): + for j in range(self.L, 2 * self.L): + op = openfermion.FermionOperator(f"{str(i)} {str(j-self.L)}") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L, 2 * self.L): + op = openfermion.FermionOperator(f"{str(i-self.L)}^ {str(j-self.L)}") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + return cmatrix + + def get_cmatrix_majorana(self) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(2 * self.L): + for j in range(2 * self.L): + op = openfermion.MajoranaOperator((i,)) * openfermion.MajoranaOperator( + (j,) + ) + if j % 2 + i % 2 == 1: + op *= -1 + # convention diff in jordan wigner + # c\dagger = X\pm iY + + op = openfermion.jordan_wigner(op) + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + return cmatrix + + def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor: + rm = quantum.reduced_density_matrix(self.state, subsystems_to_trace_out) # type: ignore + return quantum.entropy(rm) + + def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor: + rm = quantum.reduced_density_matrix(self.state, subsystems_to_trace_out) + return quantum.renyi_entropy(rm, n) + + def overlap(self, other: "FGSTestSimulator") -> Tensor: + return backend.tensordot(backend.conj(self.state), other.state, 1) + + def get_dm(self) -> Tensor: + s = backend.reshape(self.state, [-1, 1]) + return s @ backend.adjoint(s) + + def product(self, other: "FGSTestSimulator") -> Tensor: + rho1 = self.get_dm() + rho2 = other.get_dm() + rho = rho1 @ rho2 + rho /= backend.trace(rho) + return rho diff --git a/tests/test_fgs.py b/tests/test_fgs.py new file mode 100644 index 00000000..2facc03c --- /dev/null +++ b/tests/test_fgs.py @@ -0,0 +1,104 @@ +import numpy as np +import pytest +from pytest_lazyfixture import lazy_fixture as lf +import tensorflow as tf +import optax + +try: + import openfermion as _ +except ModuleNotFoundError: + pytestmark = pytest.mark.skip("skip fgs test due to missing openfermion module") + +import tensorcircuit as tc + +F = tc.fgs.FGSSimulator +FT = tc.fgs.FGSTestSimulator + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_cmatrix(backend, highp): + c = tc.fgs.FGSSimulator(4, [0]) + c1 = tc.fgs.FGSTestSimulator(4, [0]) + c.evol_hp(0, 1, 1.2) + c1.evol_hp(0, 1, 1.2) + c.evol_icp(2, 0.5) + c1.evol_icp(2, 0.5) + c.evol_cp(0, -0.8) + c1.evol_cp(0, -0.8) + c.evol_sp(1, 0, 0.5) + c1.evol_sp(1, 0, 0.5) + c.evol_sp(1, 2, 1.5) + c1.evol_sp(1, 2, 1.5) + c.evol_ihamiltonian(c.chemical_potential(1.0, 1, 4)) + c1.evol_ihamiltonian(c1.chemical_potential_jw(1.0, 1, 4)) + np.testing.assert_allclose( + c1.get_cmatrix_majorana(), c.get_cmatrix_majorana(), atol=1e-5 + ) + np.testing.assert_allclose(c1.get_cmatrix(), c.get_cmatrix(), atol=1e-5) + np.testing.assert_allclose(c1.entropy([0, 2]), c.entropy([0, 2]), atol=1e-5) + np.testing.assert_allclose( + c1.renyi_entropy(2, [1]), c.renyi_entropy(2, [1]), atol=1e-5 + ) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_fgs_ad(backend, highp): + N = 18 + + def f(chi): + c = tc.fgs.FGSSimulator(N, [0]) + for i in range(N - 1): + c.evol_hp(i, i + 1, chi[i]) + cm = c.get_cmatrix() + return -tc.backend.real(1 - cm[N, N]) + + chi_vg = tc.backend.jit(tc.backend.value_and_grad(f)) + + if tc.backend.name == "tensorflow": + opt = tc.backend.optimizer(tf.keras.optimizers.Adam(1e-2)) + else: + opt = tc.backend.optimizer(optax.adam(1e-2)) + + param = tc.backend.ones([N - 1], dtype="float64") + for _ in range(300): + vs, gs = chi_vg(param) + param = opt.update(gs, param) + + np.testing.assert_allclose(vs, -0.9986, atol=1e-2) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_hamiltonian_generation(backend): + hc = F.chemical_potential(0.8, 0, 3) + h1 = FT.get_hmatrix(hc, 3) + 0.4 * tc.backend.eye(2**3) + # constant shift + h2 = FT.chemical_potential_jw(0.8, 0, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + hc = F.hopping(0.8j, 0, 1, 3) + h1 = FT.get_hmatrix(hc, 3) + h2 = FT.hopping_jw(0.8j, 0, 1, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + hc = F.sc_pairing(0.8, 1, 0, 3) + h1 = FT.get_hmatrix(hc, 3) + h2 = FT.sc_pairing_jw(0.8, 1, 0, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_ground_state(backend, highp): + N = 3 + hc = ( + F.hopping(1.0, 0, 1, N) + + F.hopping(1.0, 1, 2, N) + + F.chemical_potential(0.4, 0, N) + - F.chemical_potential(0.4, 1, N) + + F.sc_pairing(0.8, 0, 1, N) + ) + + c = F(N, hc=hc) + c1 = FT(N, hc=hc) + + np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-6) + np.testing.assert_allclose(c1.entropy([0]), c.entropy([0]), atol=1e-5) From e841ecb24c2060da5b08512fdbde18d339916636 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 31 Aug 2023 14:59:47 +0800 Subject: [PATCH 024/139] blacked --- tensorcircuit/fgs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index 9314fa63..4cdec5e6 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -175,7 +175,7 @@ def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor: lbd = backend.relu(lbd) eps = 1e-6 - entropy = backend.sum(backend.log(lbd ** n + (1 - lbd) ** n + eps)) + entropy = backend.sum(backend.log(lbd**n + (1 - lbd) ** n + eps)) s = 1 / (2 * (1 - n)) * entropy return s @@ -371,7 +371,7 @@ def fermion_diagonalization(cls, hc: Tensor, L: int) -> Tensor: @staticmethod def get_hmatrix(hc: Tensor, L: int) -> Tensor: - hm = np.zeros([2 ** L, 2 ** L], dtype=complex) + hm = np.zeros([2**L, 2**L], dtype=complex) for i in range(L): for j in range(L): op = openfermion.FermionOperator(f"{str(i)}^ {str(j)}") From 4c1436598f15abdf262ede32620d06d5886b7724 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 1 Sep 2023 11:48:36 +0800 Subject: [PATCH 025/139] add measurement in fgs --- tensorcircuit/fgs.py | 129 ++++++++++++++++++++++++++++++++++++++++--- tests/test_fgs.py | 64 ++++++++++++++++++++- 2 files changed, 185 insertions(+), 8 deletions(-) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index 4cdec5e6..f35fd595 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -10,7 +10,7 @@ except ModuleNotFoundError: pass -from .cons import backend, dtypestr +from .cons import backend, dtypestr, rdtypestr, get_backend from .circuit import Circuit from . import quantum @@ -314,6 +314,14 @@ def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]: ) def get_cmatrix_majorana(self) -> Tensor: + """ + correlation matrix defined in majorana basis + convention: gamma_0 = c0 + c0^\dagger + gamma_1 = i(c0 - c0^\dagger) + + :return: _description_ + :rtype: Tensor + """ c = self.get_cmatrix() return self.wtransform @ c @ backend.adjoint(self.wtransform) @@ -321,6 +329,85 @@ def get_covariance_matrix(self) -> Tensor: m = self.get_cmatrix_majorana() return -1.0j * (2 * m - backend.eye(self.L * 2)) + def post_select(self, i: int, keep: int = 1) -> None: + """ + post select (project) the fermion state to occupation eigenstate + = ``keep`` + + :param i: _description_ + :type i: int + :param keep: _description_, defaults to 1 + :type keep: int, optional + """ + # i is not jittable, keep is jittable + L = backend.convert_to_tensor(self.L) + i = backend.convert_to_tensor(i) + L = backend.cast(L, "int32") + i = backend.cast(i, "int32") + keep = backend.convert_to_tensor(keep) + keep = backend.cast(keep, "int32") + alpha = self.alpha + # if keep == 0: + i = i + L * (1 - keep) + i0 = backend.argmax(backend.abs(alpha[(i + L) % (2 * L), :])) + i0 = backend.cast(i0, "int32") + alpha1 = alpha - backend.reshape(alpha[:, i0], [-1, 1]) @ backend.reshape( + alpha[(i + L) % (2 * L), :] / alpha[(i + L) % (2 * L), i0], [1, -1] + ) + mask1 = backend.onehot(i0, alpha.shape[1]) + mask1 = backend.cast(mask1, dtypestr) + mask0 = backend.ones(alpha.shape[1]) - mask1 + mask12d = backend.tile(mask1[None, :], [alpha.shape[0], 1]) + mask02d = backend.tile(mask0[None, :], [alpha.shape[0], 1]) + alpha1 = mask02d * alpha1 + mask12d * alpha + r = [] + for j in range(2 * self.L): + indicator = ( + backend.sign(backend.cast((i - j), rdtypestr) ** 2 - 0.5) + 1 + ) / 2 + # i=j indicator = 0, i!=j indicator = 1 + indicator = backend.cast(indicator, dtypestr) + r.append( + backend.ones([self.L]) * indicator + + backend.ones([self.L]) * mask1 * (1 - indicator) + ) + # if j != i: + # r.append(backend.ones([L])) + # else: + # r.append(backend.ones([L]) * mask1) + mask2 = backend.stack(r) + alpha1 = alpha1 * mask2 + r = [] + for j in range(2 * self.L): + indicator = ( + backend.sign( + (backend.cast((i + L) % (2 * L) - j, rdtypestr)) ** 2 - 0.5 + ) + + 1 + ) / 2 + r.append(1 - indicator) + newcol = backend.stack(r) + # newcol = np.zeros([2 * self.L]) + # newcol[(i + L) % (2 * L)] = 1 + # newcol = backend.convert_to_tensor(newcol) + newcol = backend.cast(newcol, dtypestr) + alpha1 = alpha1 * mask02d + backend.tile(newcol[:, None], [1, self.L]) * mask12d + q, _ = backend.qr(alpha1) + self.alpha = q + + def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor: + p0 = backend.real(self.get_cmatrix()[ind, ind]) + prob = backend.convert_to_tensor([p0, 1 - p0]) + status = backend.convert_to_tensor(status) + status = backend.cast(status, rdtypestr) + eps = 1e-12 + keep = (backend.sign(status - p0 + eps) + 1) / 2 + self.post_select(ind, keep) + if with_prob is False: + return keep + else: + return keep, prob + # def product(self, other): # # self@other # gamma1 = self.get_covariance_matrix() @@ -345,7 +432,15 @@ def get_covariance_matrix(self) -> Tensor: # ) +npb = get_backend("numpy") + + class FGSTestSimulator: + """ + Never use, only for correctness testing + stick to numpy backend and no jit/ad/vmap is available + """ + def __init__( self, L: int, filled: Optional[List[int]] = None, hc: Optional[Tensor] = None ): @@ -419,14 +514,12 @@ def chemical_potential_jw(chi: Tensor, i: int, L: int) -> Tensor: return m def evol_hamiltonian(self, h: Tensor) -> None: - self.state = backend.expm(-1 / 2 * 1.0j * h) @ backend.reshape( - self.state, [-1, 1] - ) - self.state = backend.reshape(self.state, [-1]) + self.state = npb.expm(-1 / 2 * 1.0j * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) def evol_ihamiltonian(self, h: Tensor) -> None: - self.state = backend.expm(-1 / 2 * h) @ backend.reshape(self.state, [-1, 1]) - self.state = backend.reshape(self.state, [-1]) + self.state = npb.expm(-1 / 2 * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) self.orthogonal() def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: @@ -548,3 +641,25 @@ def product(self, other: "FGSTestSimulator") -> Tensor: rho = rho1 @ rho2 rho /= backend.trace(rho) return rho + + def post_select(self, i: int, keep: int = 1) -> None: + c = Circuit(self.L, inputs=self.state) + c.post_select(i, keep) + s = c.state() + s /= backend.norm(s) + self.state = s + + def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor: + p0 = self.get_cmatrix()[ind, ind] + prob = [p0, 1 - p0] + if status < p0: + self.post_select(ind, 0) + keep = 0 + else: + self.post_select(ind, 1) + keep = 1 + + if with_prob is False: + return keep + else: + return keep, prob diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 2facc03c..718f58cc 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -2,7 +2,6 @@ import pytest from pytest_lazyfixture import lazy_fixture as lf import tensorflow as tf -import optax try: import openfermion as _ @@ -43,6 +42,8 @@ def test_cmatrix(backend, highp): @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) def test_fgs_ad(backend, highp): + import optax + N = 18 def f(chi): @@ -102,3 +103,64 @@ def test_ground_state(backend, highp): np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-6) np.testing.assert_allclose(c1.entropy([0]), c.entropy([0]), atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_post_select(backend, highp): + for ind in [0, 1, 2]: + for keep in [0, 1]: + c = F(3, filled=[0, 2]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + c.evol_cp(1, -0.8) + c.evol_sp(0, 2, 0.3) + c.post_select(ind, keep) + c1 = FT(3, filled=[0, 2]) + c1.evol_hp(0, 1, 0.2) + c1.evol_cp(0, 0.5) + c1.evol_hp(1, 2, 0.3j) + c1.evol_cp(1, -0.8) + c1.evol_sp(0, 2, 0.3) + c1.post_select(ind, keep) + np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_jittable_measure(backend): + @tc.backend.jit + def get_cmatrix(status): + r = [] + c = F(3, filled=[0]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + r.append(c.cond_measure(1, status[0])) + c.evol_cp(1, -0.8) + r.append(c.cond_measure(2, status[1])) + r.append(c.cond_measure(1, status[3])) + c.evol_sp(0, 2, 0.3) + c.evol_hp(2, 1, 0.2) + c.evol_hp(0, 1, 0.8) + return c.get_cmatrix(), tc.backend.stack(r) + + def get_cmatrix_baseline(status): + r = [] + c = FT(3, filled=[0]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + r.append(c.cond_measure(1, status[0])) + c.evol_cp(1, -0.8) + r.append(c.cond_measure(2, status[1])) + r.append(c.cond_measure(1, status[3])) + c.evol_sp(0, 2, 0.3) + c.evol_hp(2, 1, 0.2) + c.evol_hp(0, 1, 0.8) + return c.get_cmatrix(), np.array(r) + + status = np.array([0.2, 0.83, 0.61, 0.07]) + m, his = get_cmatrix(tc.backend.convert_to_tensor(status)) + m1, his1 = get_cmatrix_baseline(status) + np.testing.assert_allclose(m, m1, atol=1e-5) + np.testing.assert_allclose(his, his1, atol=1e-5) From de45e8b83414703526f02f54db1211bdeaadced8 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 1 Sep 2023 16:38:33 +0800 Subject: [PATCH 026/139] add expectation for fgs --- README.md | 2 ++ tensorcircuit/fgs.py | 78 ++++++++++++++++++++++++++++++++++++++++++-- tests/test_fgs.py | 36 ++++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b548913..089cd0ac 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,8 @@ We also have [Docker support](/docker). - Support **analog/digital hybrid simulation** (time dependent Hamiltonian evolution, **pulse** level simulation) with neural ode modes. + - Support **Fermion Gaussian state** simulation with expectation, entanglement, measurment, ground state, real and imaginary time evolution. + - Support **qudits simulation**. - Support **parallel** quantum circuit evaluation across **multiple GPUs**. diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index f35fd595..ea54e26e 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -58,6 +58,10 @@ def __init__( :type L: int :param filled: the fermion site that is fully occupied, defaults to None :type filled: Optional[List[int]], optional + :param alpha: directly specify the alpha tensor as the input + :type alpha: Optional[Tensor], optional + :param hc: the input is given as the ground state of quadratic Hamiltonian ``hc`` + :type hc: Optional[Tensor], optional :param cmatrix: only used for debug, defaults to None :type cmatrix: Optional[Tensor], optional """ @@ -109,7 +113,7 @@ def fermion_diagonalization_2( alpha = backend.adjoint(u)[:, :L] # c' = u@c # e_k (c^\dagger_k c_k - c_k c^\dagger_k) - return (es, u, alpha) + return es, u, alpha @staticmethod def wmatrix(L: int) -> Tensor: @@ -141,7 +145,10 @@ def get_alpha(self) -> Tensor: def get_cmatrix(self) -> Tensor: if self.cmatrix is not None: return self.cmatrix - return self.alpha @ backend.adjoint(self.alpha) + else: + cmatrix = self.alpha @ backend.adjoint(self.alpha) + self.cmatrix = cmatrix + return cmatrix def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor: m = self.get_cmatrix() @@ -209,6 +216,7 @@ def evol_hamiltonian(self, h: Tensor) -> None: # e^{-i/2 H} h = backend.cast(h, dtype=dtypestr) self.alpha = backend.expm(-1.0j * h) @ self.alpha + self.cmatrix = None def evol_ihamiltonian(self, h: Tensor) -> None: r""" @@ -221,6 +229,7 @@ def evol_ihamiltonian(self, h: Tensor) -> None: h = backend.cast(h, dtype=dtypestr) self.alpha = backend.expm(h) @ self.alpha self.orthogonal() + self.cmatrix = None def orthogonal(self) -> None: q, _ = backend.qr(self.alpha) @@ -329,6 +338,45 @@ def get_covariance_matrix(self) -> Tensor: m = self.get_cmatrix_majorana() return -1.0j * (2 * m - backend.eye(self.L * 2)) + def expectation_2body(self, i: int, j: int) -> Tensor: + """ + expectation of two fermion terms + convention: (c, c^\dagger) + for i>L, c_{i-L}^\dagger is assumed + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :return: _description_ + :rtype: Tensor + """ + return self.get_cmatrix()[i][j] + + def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: + """ + expectation of four fermion terms using Wick Thm + convention: (c, c^\dagger) + for i>L, c_{i-L}^\dagger is assumed + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param k: _description_ + :type k: int + :param l: _description_ + :type l: int + :return: _description_ + :rtype: Tensor + """ + e = ( + self.expectation_2body(i, j) * self.expectation_2body(k, l) + - self.expectation_2body(i, k) * self.expectation_2body(j, l) + + self.expectation_2body(i, l) * self.expectation_2body(j, k) + ) + return e + def post_select(self, i: int, keep: int = 1) -> None: """ post select (project) the fermion state to occupation eigenstate @@ -620,6 +668,32 @@ def get_cmatrix_majorana(self) -> Tensor: return cmatrix + def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: + s = "" + if i < self.L: + s += str(i) + "" + else: + s += str(i) + "^ " + if j < self.L: + s += str(j) + "" + else: + s += str(j) + "^ " + if k < self.L: + s += str(k) + "" + else: + s += str(k) + "^ " + if l < self.L: + s += str(l) + "" + else: + s += str(l) + "^ " + op = openfermion.FermionOperator(s) + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + return ( + npb.reshape(npb.adjoint(self.state), [1, -1]) + @ m + @ npb.reshape(self.state, [-1, 1]) + )[0, 0] + def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor: rm = quantum.reduced_density_matrix(self.state, subsystems_to_trace_out) # type: ignore return quantum.entropy(rm) diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 718f58cc..2906e410 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -164,3 +164,39 @@ def get_cmatrix_baseline(status): m1, his1 = get_cmatrix_baseline(status) np.testing.assert_allclose(m, m1, atol=1e-5) np.testing.assert_allclose(his, his1, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_exp_4body(backend): + c = F(4, filled=[0, 2]) + c.evol_hp(0, 1, 0.3) + c.evol_hp(2, 3, 0.3) + c.evol_sp(0, 3, 0.5) + c.evol_sp(0, 2, 0.9) + c.evol_cp(0, -0.4) + + c1 = FT(4, filled=[0, 2]) + c1.evol_hp(0, 1, 0.3) + c1.evol_hp(2, 3, 0.3) + c1.evol_sp(0, 3, 0.5) + c1.evol_sp(0, 2, 0.9) + c1.evol_cp(0, -0.4) + + np.testing.assert_allclose( + c.expectation_4body(0, 4, 1, 5), c.expectation_4body(0, 4, 1, 5), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 1, 4, 5), c.expectation_4body(0, 1, 4, 5), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 4, 2, 6), c.expectation_4body(0, 4, 2, 6), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 2, 3, 1), c.expectation_4body(0, 2, 3, 1), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 1, 4, 6), c.expectation_4body(0, 1, 4, 6), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(1, 0, 6, 7), c.expectation_4body(1, 0, 6, 7), atol=1e-5 + ) From 12de36cf3729d1d28e923bae8e1aa8906be5edd7 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Sat, 2 Sep 2023 10:52:11 +0800 Subject: [PATCH 027/139] add entanglement negativity --- CHANGELOG.md | 2 ++ tensorcircuit/quantum.py | 39 +++++++++++++++++++++++++++++++++++++++ tests/test_quantum.py | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2a51e70..45893f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ - Add fermion Gaussian state simulator in `fgs.py` +- Add `partial_transpose` and `entanglement_negativity` method in `quantum.py` + ### Changed - move ensemble module to applications/ai (breaking changes) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index dd9f11ab..8459051c 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -39,6 +39,7 @@ from .cons import backend, contractor, dtypestr, npdtype, rdtypestr from .backends import get_backend from .utils import is_m1mac, arg_alias +from .gates import Gate Tensor = Any Graph = Any @@ -1790,6 +1791,44 @@ def truncated_free_energy( return energy - renyi / beta +@op2tensor +def partial_transpose(rho: Tensor, transposed_sites: List[int]) -> Tensor: + rho = backend.reshape2(rho) + rho_node = Gate(rho) + n = len(rho.shape) // 2 + left_edges = [] + right_edges = [] + for i in range(n): + if i not in transposed_sites: + left_edges.append(rho_node[i]) + right_edges.append(rho_node[i + n]) + else: + left_edges.append(rho_node[i + n]) + right_edges.append(rho_node[i]) + rhot_op = QuOperator(out_edges=left_edges, in_edges=right_edges) + rhot = rhot_op.eval_matrix() + return rhot + + +@op2tensor +def entanglement_negativity(rho: Tensor, transposed_sites: List[int]) -> Tensor: + rhot = partial_transpose(rho, transposed_sites) + es = backend.eigvalsh(rhot) + rhot_m = backend.sum(backend.abs(es)) + return (backend.log(rhot_m) - 1.0) / 2.0 + + +@op2tensor +def log_negativity(rho: Tensor, transposed_sites: List[int], base: str = "e") -> Tensor: + rhot = partial_transpose(rho, transposed_sites) + es = backend.eigvalsh(rhot) + rhot_m = backend.sum(backend.abs(es)) + een = backend.log(rhot_m) + if base in ["2", 2]: + return een / backend.cast(backend.log(2.0), rdtypestr) + return een + + @partial(op2tensor, op_argnums=(0, 1)) def trace_distance(rho: Tensor, rho0: Tensor, eps: float = 1e-12) -> Tensor: """ diff --git a/tests/test_quantum.py b/tests/test_quantum.py index 609111ad..88ff1b12 100644 --- a/tests/test_quantum.py +++ b/tests/test_quantum.py @@ -364,6 +364,26 @@ def test_expectation_quantum(backend): np.testing.assert_allclose(exp1, exp2, atol=1e-5) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_negativity(backend, highp): + c = tc.DMCircuit(2) + c.h(0) + c.cnot(0, 1) + c.depolarizing(0, px=0.1, py=0.1, pz=0.1) + dm = c.state() + np.testing.assert_allclose( + tc.quantum.log_negativity(dm, [0], base="2"), 0.485427, atol=1e-5 + ) + np.testing.assert_allclose( + tc.quantum.partial_transpose(tc.quantum.partial_transpose(dm, [0]), [0]), + dm, + atol=1e-6, + ) + np.testing.assert_allclose( + tc.quantum.entanglement_negativity(dm, [1]), -0.33176, atol=1e-5 + ) + + @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_tn2qop(backend): nwires = 6 From 4428206143e34df46749d5965735574d77fc8a27 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Sat, 2 Sep 2023 11:07:22 +0800 Subject: [PATCH 028/139] add some docs --- tensorcircuit/applications/README.md | 3 +++ tensorcircuit/quantum.py | 32 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/tensorcircuit/applications/README.md b/tensorcircuit/applications/README.md index c63ef6cf..202e06cf 100644 --- a/tensorcircuit/applications/README.md +++ b/tensorcircuit/applications/README.md @@ -1,3 +1,6 @@ +Code implementation in this submodule `applications` are not very well maintained and extensively tested. There are indeed many interesting pieces, but try on your own risk. + + ## Differentiable Quantum Architecture Search In `applications`, framework and relevant applications of DQAS are implemented, mainly in `vags.py` and `dqas.py`. diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 8459051c..7cfabee4 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1793,6 +1793,16 @@ def truncated_free_energy( @op2tensor def partial_transpose(rho: Tensor, transposed_sites: List[int]) -> Tensor: + """ + _summary_ + + :param rho: density matrix + :type rho: Tensor + :param transposed_sites: sites int list to be transposed + :type transposed_sites: List[int] + :return: _description_ + :rtype: Tensor + """ rho = backend.reshape2(rho) rho_node = Gate(rho) n = len(rho.shape) // 2 @@ -1812,6 +1822,16 @@ def partial_transpose(rho: Tensor, transposed_sites: List[int]) -> Tensor: @op2tensor def entanglement_negativity(rho: Tensor, transposed_sites: List[int]) -> Tensor: + """ + _summary_ + + :param rho: _description_ + :type rho: Tensor + :param transposed_sites: _description_ + :type transposed_sites: List[int] + :return: _description_ + :rtype: Tensor + """ rhot = partial_transpose(rho, transposed_sites) es = backend.eigvalsh(rhot) rhot_m = backend.sum(backend.abs(es)) @@ -1820,6 +1840,18 @@ def entanglement_negativity(rho: Tensor, transposed_sites: List[int]) -> Tensor: @op2tensor def log_negativity(rho: Tensor, transposed_sites: List[int], base: str = "e") -> Tensor: + """ + _summary_ + + :param rho: _description_ + :type rho: Tensor + :param transposed_sites: _description_ + :type transposed_sites: List[int] + :param base: whether use 2 based log or e based log, defaults to "e" + :type base: str, optional + :return: _description_ + :rtype: Tensor + """ rhot = partial_transpose(rho, transposed_sites) es = backend.eigvalsh(rhot) rhot_m = backend.sum(backend.abs(es)) From a687ee531689d0b5db0480a652c78aff8e7528e6 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Sat, 2 Sep 2023 17:20:03 +0800 Subject: [PATCH 029/139] add entanglement_entropy shortcut --- tensorcircuit/quantum.py | 6 ++++++ tests/test_quantum.py | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 7cfabee4..9a47ebbe 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1582,6 +1582,12 @@ def trace_product(*o: Union[Tensor, QuOperator]) -> Tensor: return backend.trace(prod) +@op2tensor +def entanglement_entropy(state: Tensor, cut: Union[int, List[int]]): + rho = reduced_density_matrix(state, cut) + return entropy(rho) + + def reduced_density_matrix( state: Union[Tensor, QuOperator], cut: Union[int, List[int]], diff --git a/tests/test_quantum.py b/tests/test_quantum.py index 88ff1b12..13d06354 100644 --- a/tests/test_quantum.py +++ b/tests/test_quantum.py @@ -364,6 +364,18 @@ def test_expectation_quantum(backend): np.testing.assert_allclose(exp1, exp2, atol=1e-5) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_ee(backend): + c = tc.Circuit(3) + c.h(0) + c.cx(0, 1) + c.cx(1, 2) + s = c.state() + np.testing.assert_allclose( + tc.quantum.entanglement_entropy(s, [0, 1]), np.log(2.0), atol=1e-5 + ) + + @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_negativity(backend, highp): c = tc.DMCircuit(2) From 7f4001c32c8e8955ab7947521869cc98ddc45e5e Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Sat, 2 Sep 2023 20:54:42 +0800 Subject: [PATCH 030/139] fix mypy --- tensorcircuit/quantum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 9a47ebbe..1a4a84d8 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1583,7 +1583,7 @@ def trace_product(*o: Union[Tensor, QuOperator]) -> Tensor: @op2tensor -def entanglement_entropy(state: Tensor, cut: Union[int, List[int]]): +def entanglement_entropy(state: Tensor, cut: Union[int, List[int]]) -> Tensor: rho = reduced_density_matrix(state, cut) return entropy(rho) From 71178f0449f8ab971deb72ac7ee102e3499933a9 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 4 Sep 2023 10:13:17 +0800 Subject: [PATCH 031/139] doc prettify --- README.md | 14 ++++++++++++++ tensorcircuit/fgs.py | 8 ++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 089cd0ac..4174bdae 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,20 @@ c.cx(range(n-1), range(1, n)) c.expectation_ps(z=[0, n-1], reuse=False) ``` +- Density matrix simulator and quantum info quantities + +```python +c = tc.DMCircuit(2) +c.h(0) +c.cx(0, 1) +c.depolarizing(1, px=0.1, py=0.1, pz=0.1) +dm = c.state() +print(tc.quantum.entropy(dm)) +print(tc.quantum.entanglement_entropy(dm, [0])) +print(tc.quantum.entanglement_negativity(dm, [0])) +print(tc.quantum.log_negativity(dm, [0])) +``` + ## Install diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index ea54e26e..c4919f7c 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -247,7 +247,7 @@ def hopping(chi: Tensor, i: int, j: int, L: int) -> Tensor: def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: r""" - The evolve Hamiltonian is :math:`chi c_i^\dagger c_j +h.c.` + The evolve Hamiltonian is :math:`\chi c_i^\dagger c_j +h.c.` :param i: _description_ :type i: int @@ -323,10 +323,10 @@ def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]: ) def get_cmatrix_majorana(self) -> Tensor: - """ + r""" correlation matrix defined in majorana basis - convention: gamma_0 = c0 + c0^\dagger - gamma_1 = i(c0 - c0^\dagger) + convention: :math:`gamma_0 = c_0 + c_0^\dagger` + :math:`gamma_1 = i(c_0 - c_0^\dagger)` :return: _description_ :rtype: Tensor From e7ff994a71993c19380fd11f62940dfc29088a0f Mon Sep 17 00:00:00 2001 From: PeilinZHENG Date: Tue, 5 Sep 2023 11:30:15 +0800 Subject: [PATCH 032/139] Fix the typos in classical_shadows.ipynb --- docs/source/tutorials/classical_shadows.ipynb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/tutorials/classical_shadows.ipynb b/docs/source/tutorials/classical_shadows.ipynb index 9b53f860..e6776482 100644 --- a/docs/source/tutorials/classical_shadows.ipynb +++ b/docs/source/tutorials/classical_shadows.ipynb @@ -30,21 +30,21 @@ { "cell_type": "markdown", "source": [ - "Let's first briefly review the classical shadows in Pauli basis. For an $n$-qubit quantum state $\\rho$, we randomly perform Pauli projection measurement on each qubit and obtain a snapshot like $\\{1,-1,-1,1,\\cdots,1,-1\\}$. This process is equivalent to apply a random unitary $U$ to $\\rho$ and measure in computational basis to obtain $|b\\rangle=|s_1\\cdots s_n\\rangle,\\ s_j\\in\\{0,1\\}$:\n", + "Let's first briefly review the classical shadows in Pauli basis. For an $n$-qubit quantum state $\\rho$, we randomly perform Pauli projection measurement on each qubit and obtain a snapshot like $\\{1,-1,-1,1,\\cdots,1,-1\\}$. This process is equivalent to apply a random unitary $U_i$ to $\\rho$ and measure in computational basis to obtain $|b_i\\rangle=|s_{i1}\\cdots s_{in}\\rangle,\\ s_{ij}\\in\\{0,1\\}$:\n", "$$\n", - "\\rho\\rightarrow U\\rho U^{\\dagger}\\xrightarrow{measure}|b\\rangle\\langle b|,\n", + "\\rho\\rightarrow U_i\\rho U_i^{\\dagger}\\xrightarrow{measure}|b_i\\rangle\\langle b_i|,\n", "$$\n", - "where $U=\\bigotimes_{j=1}^{n}u_j$, $u_i\\in\\{H, HS^{\\dagger}, \\mathbb{I}\\}$ correspond to the projection measurements of Pauli $X$, $Y$, $Z$ respectively. Then we reverse the operation to get the equivalent measurement result on $\\rho$:\n", + "where $U_i=\\bigotimes_{j=1}^{n}u_{ij}$, $u_{ij}\\in\\{H, HS^{\\dagger}, \\mathbb{I}\\}$ correspond to the projection measurements of Pauli $X$, $Y$, $Z$ respectively. Then we reverse the operation to get the equivalent measurement result on $\\rho$:\n", "$$\n", - "\\rho\\xrightarrow{measure}U^{\\dagger}|b\\rangle\\langle b| U.\n", + "\\rho\\xrightarrow{measure}U_i^{\\dagger}|b_i\\rangle\\langle b_i| U_i.\n", "$$\n", "Moreover, we perform $N$ random measurements and view their average as a quantum channel:\n", "$$\n", - "\\mathbb{E}\\left[U^{\\dagger}|b\\rangle\\langle b|U\\right]=\\mathcal{M}(\\rho),\n", + "\\mathbb{E}\\left[U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i\\right]=\\mathcal{M}(\\rho),\n", "$$\n", "we can invert the channel to get the approximation of $\\rho$:\n", "$$\n", - "\\rho=\\mathbb{E}\\left[\\mathcal{M}^{-1}(U^{\\dagger}|b\\rangle\\langle b|U)\\right].\n", + "\\rho=\\mathbb{E}\\left[\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)\\right].\n", "$$\n", "We call each $\\rho_i=\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)$ a shadow snapshot state and their ensemble $S(\\rho;N)=\\{\\rho_i|i=1,\\cdots,N\\}$ classical shadows." ], @@ -58,13 +58,13 @@ "In Pauli basis, we have a simple expression of $\\mathcal{M}^{-1}$:\n", "$$\n", "\\begin{split}\n", - " \\rho_i&=\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)=\\bigotimes_{j=1}^{n}3u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}|u_{ij}-\\mathbb{I},\\\\\n", + " \\rho_i&=\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)=\\bigotimes_{j=1}^{n}\\left(3u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}|u_{ij}-\\mathbb{I}\\right),\\\\\n", " \\rho&=\\frac{1}{N}\\sum_{i=1}^{N}\\rho_i\\ .\n", "\\end{split}\n", "$$\n", "For an observable Pauli string $O=\\bigotimes_{j=1}^{n}P_j,\\ P_j\\in\\{\\mathbb{I}, X, Y, Z\\}$, we can directly use $\\rho$ to calculate $\\langle O\\rangle=\\text{Tr}(O\\rho)$. In practice, we will divide the classical shadows into $K$ parts to calculate the expectation values independently and take the median to avoid the influence of outliers:\n", "$$\n", - "\\langle O\\rangle=\\text{median}\\{\\langle O_{(1)}\\rangle\\cdots\\langle O_{(K)}\\rangle\\},\n", + "\\langle O\\rangle=\\text{median}\\{\\langle O_{(1)}\\rangle,\\cdots,\\langle O_{(K)}\\rangle\\},\n", "$$\n", "where\n", "$$\n", @@ -248,7 +248,7 @@ { "cell_type": "markdown", "source": [ - "If ``measurement_only=True`` (default ``False``), the outputs of ``shadow_snapshots`` are snapshot bit strings $b=s_1\\cdots s_n,\\ s_j\\in\\{0,1\\}$, otherwise the outputs are snapshot states $\\{u_{j}^{\\dagger}|s_j\\rangle\\langle s_j| u_j\\ |j=1,\\cdots,n\\}$. If you only need to generate one batch of snapshots or generate multiple batches of snapshots with different ``nps`` or ``r``, jit cannot provide speedup. JIT will only accelerate when the same shape of snapshots are generated multiple times." + "If ``measurement_only=True`` (default ``False``), the outputs of ``shadow_snapshots`` are snapshot bit strings $\\{b_i=s_{i1}\\cdots s_{in}\\ |i=1,\\cdots,N,\\ s_{ij}\\in\\{0,1\\}\\}$, otherwise the outputs are snapshot states $\\{u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}| u_{ij}\\ |i=1,\\cdots,N,\\ j=1,\\cdots,n\\}$. If you only need to generate one batch of snapshots or generate multiple batches of snapshots with different ``nps`` or ``r``, jit cannot provide speedup. Jit will only accelerate when the same shape of snapshots are generated multiple times." ], "metadata": { "collapsed": false From e29d7366e378fa5bb72a3af7355a68052aed2d38 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 5 Sep 2023 12:38:14 +0800 Subject: [PATCH 033/139] black --- tensorcircuit/results/qem/benchmark_circuits.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tensorcircuit/results/qem/benchmark_circuits.py b/tensorcircuit/results/qem/benchmark_circuits.py index 9c6023c9..368cc828 100644 --- a/tensorcircuit/results/qem/benchmark_circuits.py +++ b/tensorcircuit/results/qem/benchmark_circuits.py @@ -16,9 +16,7 @@ generate_rb_circuits, generate_w_circuit, ) - from mitiq.interface import ( - convert_from_mitiq, - ) + from mitiq.interface import convert_from_mitiq except ModuleNotFoundError: logger.warning("mitiq is not installed, please ``pip install mitiq`` first") From b96a1b1c11df8c767e85476efd6c336bb2b3a7b9 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 5 Sep 2023 17:24:23 +0800 Subject: [PATCH 034/139] fix fgs exp_2 bug --- README.md | 2 +- tensorcircuit/fgs.py | 2 +- tests/test_fgs.py | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4174bdae..677beaa0 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ We also have [Docker support](/docker). - Support **analog/digital hybrid simulation** (time dependent Hamiltonian evolution, **pulse** level simulation) with neural ode modes. - - Support **Fermion Gaussian state** simulation with expectation, entanglement, measurment, ground state, real and imaginary time evolution. + - Support **Fermion Gaussian state** simulation with expectation, entanglement, measurement, ground state, real and imaginary time evolution. - Support **qudits simulation**. diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index c4919f7c..565d1585 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -351,7 +351,7 @@ def expectation_2body(self, i: int, j: int) -> Tensor: :return: _description_ :rtype: Tensor """ - return self.get_cmatrix()[i][j] + return self.get_cmatrix()[i][(j + self.L) % (2 * self.L)] def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: """ diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 2906e410..526c94ff 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -166,6 +166,14 @@ def get_cmatrix_baseline(status): np.testing.assert_allclose(his, his1, atol=1e-5) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_exp_2body(backend): + c = F(3, filled=[1]) + np.testing.assert_allclose(c.expectation_2body(4, 1), 1.0, atol=1e-5) + np.testing.assert_allclose(c.expectation_2body(5, 2), 0.0, atol=1e-5) + np.testing.assert_allclose(c.expectation_2body(1, 4), 0.0, atol=1e-5) + + @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_exp_4body(backend): c = F(4, filled=[0, 2]) From 7acd0c17db8e8d796f85a64d73231aade7848a80 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 13 Sep 2023 20:41:52 +0800 Subject: [PATCH 035/139] fix jax eigh ad --- CHANGELOG.md | 4 ++++ tensorcircuit/backends/jax_backend.py | 7 +++++++ tensorcircuit/backends/jax_ops.py | 26 ++++++++++++++++++++++++++ tensorcircuit/fgs.py | 22 ++++++++++++++-------- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45893f18..a4d2c684 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ - tc2qiskit now record qiskit measure with incremental clbit from 0 +### Fixed + +- Support degenerate eigenvalue for jax backend `eigh` method when using AD + ## 0.11.0 ### Added diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index c9ca0249..994f4bfc 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -156,12 +156,19 @@ def _rq_jax( return r, q +def _eigh_jax(self: Any, tensor: Tensor) -> Tensor: + from .jax_ops import adaware_eigh_jit as adaware_eigh + + return adaware_eigh(tensor) + + tensornetwork.backends.jax.jax_backend.JaxBackend.convert_to_tensor = ( _convert_to_tensor_jax ) tensornetwork.backends.jax.jax_backend.JaxBackend.svd = _svd_jax tensornetwork.backends.jax.jax_backend.JaxBackend.qr = _qr_jax tensornetwork.backends.jax.jax_backend.JaxBackend.rq = _rq_jax +tensornetwork.backends.jax.jax_backend.JaxBackend.eigh = _eigh_jax class JaxBackend(jax_backend.JaxBackend, ExtendedBackend): # type: ignore diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index efcce174..57e86609 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -145,3 +145,29 @@ def _QrGradSquareAndDeepMatrices(q: Array, r: Array, dq: Array, dr: Array) -> Ar adaware_qr.defvjp(jaxqr_fwd, jaxqr_bwd) # type: ignore adaware_qr_jit = jax.jit(adaware_qr) + + +@jax.custom_vjp +def adaware_eigh(A: Array) -> Array: + return jnp.linalg.eigh(A) + + +def jaxeigh_fwd(A: Array) -> Array: + e, v = jnp.linalg.eigh(A) + return (e, v), (A, e, v) + + +def jaxeigh_bwd(r: Array, tangents: Array) -> Array: + a, e, v = r + de, dv = tangents + eye_n = jnp.eye(a.shape[-1], dtype=a.dtype) + f = _safe_reciprocal(e[..., jnp.newaxis, :] - e[..., jnp.newaxis] + eye_n) - eye_n + middle = jnp.diag(de) + jnp.multiply(f, (v.T @ dv)) + grad_a = jnp.conj(v) @ middle @ v.T + return (grad_a,) + + +# denegerate eigev values lead nan in eigh gradients, while tf has fixed that long ago + +adaware_eigh.defvjp(jaxeigh_fwd, jaxeigh_bwd) +adaware_eigh_jit = jax.jit(adaware_eigh) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index 565d1585..b853d02e 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -26,7 +26,6 @@ def onehot_matrix(i: int, j: int, N: int) -> Tensor: # TODO(@refraction-ray): efficiency benchmark with jit -# TODO(@refraction-ray): occupation number post-selection/measurement # TODO(@refraction-ray): FGS mixed state support? # TODO(@refraction-ray): overlap? @@ -490,14 +489,21 @@ class FGSTestSimulator: """ def __init__( - self, L: int, filled: Optional[List[int]] = None, hc: Optional[Tensor] = None + self, + L: int, + filled: Optional[List[int]] = None, + state: Optional[Tensor] = None, + hc: Optional[Tensor] = None, ): if filled is None: filled = [] self.L = L - self.state = self.init_state(filled, L) - if hc is not None: + if state is not None: + self.state = state + elif hc is not None: self.state = self.fermion_diagonalization(hc, L) + else: + self.state = self.init_state(filled, L) @staticmethod def init_state(filled: List[int], L: int) -> Tensor: @@ -673,19 +679,19 @@ def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: if i < self.L: s += str(i) + "" else: - s += str(i) + "^ " + s += str(i - self.L) + "^ " if j < self.L: s += str(j) + "" else: - s += str(j) + "^ " + s += str(j - self.L) + "^ " if k < self.L: s += str(k) + "" else: - s += str(k) + "^ " + s += str(k - self.L) + "^ " if l < self.L: s += str(l) + "" else: - s += str(l) + "^ " + s += str(l - self.L) + "^ " op = openfermion.FermionOperator(s) m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() return ( From b14c67df655dc70b174173bc512b0d06ee53c2c9 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:27:35 +0100 Subject: [PATCH 036/139] CVaR is now jittable --- tensorcircuit/applications/optimization.py | 83 +++++++++++++--------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py index a579d6b8..e2609e1f 100644 --- a/tensorcircuit/applications/optimization.py +++ b/tensorcircuit/applications/optimization.py @@ -5,7 +5,6 @@ from typing import List, Callable, Any, Optional, Tuple from functools import partial -import numpy as np import tensorflow as tf import scipy.optimize as optimize @@ -161,7 +160,7 @@ def QUBO_QAOA( # Return the optimized parameters for the ansatz circuit. -def cvar_value(r: List[float], p: List[float], percent: float) -> float: +def cvar_value(r: List[float], p: List[float], percent: float) -> Any: """ Calculate the Conditional Value at Risk (CVaR) according to the measurement results. @@ -170,17 +169,17 @@ def cvar_value(r: List[float], p: List[float], percent: float) -> float: :param percent: The cut-off percentage of CVaR. :return: The calculated CVaR value. """ - sorted_indices = np.argsort(r) - p = np.array(p)[sorted_indices] - r = np.array(r)[sorted_indices] + sorted_indices = tf.argsort(r) + p = tf.cast(tf.gather(p, sorted_indices), dtype=tf.float32) + r = tf.cast(tf.gather(r, sorted_indices), dtype=tf.float32) - sump = 0.0 # The sum of probabilities. - count = 0 - cvar_result = 0.0 + sump = tf.constant(0.0, dtype=tf.float32) # The sum of probabilities. + count = tf.constant(0, dtype=tf.int32) + cvar_result = tf.constant(0.0, dtype=tf.float32) # Iterate over the sorted results and calculate CVaR. while sump < percent: - if round(sump + p[count], 6) >= percent: + if tf.math.round(sump + p[count], 6) >= percent: # Add the remaining portion of the last result that exceeds the cut-off percentage. cvar_result += r[count] * (percent - sump) count += 1 @@ -195,9 +194,7 @@ def cvar_value(r: List[float], p: List[float], percent: float) -> float: return cvar_result -def cvar_from_circuit( - circuit: Circuit, nsamples: int, Q: Tensor, alpha: float -) -> float: +def cvar_from_circuit(circuit: Circuit, nsamples: int, Q: Tensor, alpha: float) -> Any: """ Directly calculate the Conditional Value at Risk (CVaR) from a circuit. The CVaR depends on a bunch of measurements. @@ -208,27 +205,31 @@ def cvar_from_circuit( :param alpha: The cut-off percentage for CVaR. :return: The calculated CVaR value. """ - s = circuit.state() + # Get measurement results and normalize them. results = measurement_results( - s, counts=nsamples, format="count_dict_bin" - ) # Get readouts from the measurements. - results = {k: v / nsamples for k, v in results.items()} # Normalize the results. + circuit.state(), counts=nsamples, format="count_dict_bin" + ) + results = {k: v / nsamples for k, v in results.items()} + values = [] # List to store the measurement values. probabilities = [] # List to store the corresponding probabilities. + Q_tf = tf.convert_to_tensor(Q, dtype=tf.float32) - # Iterate over the measurement results and calculate the values and probabilities. for k, v in results.items(): - x = np.array([int(bit) for bit in k]) - values.append(np.dot(x, np.dot(Q, x))) + binary_strings = tf.strings.bytes_split(k) + x = tf.reshape( + tf.strings.to_number(binary_strings, out_type=tf.float32), (-1, 1) + ) + xT = tf.transpose(x) + values.append(tf.squeeze(tf.matmul(xT, tf.matmul(Q_tf, x)))) probabilities.append(v) cvar_result = cvar_value(values, probabilities, alpha) - # Calculate the CVaR using the cvar_value function. return cvar_result -def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> float: +def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> Any: """ Calculate the Conditional Value at Risk (CVaR) from the expectation values of a quantum circuit. @@ -237,23 +238,34 @@ def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> float: :param alpha: The cut-off percentage for CVaR. :return: The calculated CVaR value. """ - prob = circuit.probability() # Get the probabilities of the circuit states. - prob /= np.sum(prob) - states = [] - # Generate all possible binary states based on the length of Q. - for i in range(2 ** len(Q)): - a = f"{bin(i)[2:]:0>{len(Q)}}" - states.append(a) + # Calculate the probability amplitudes for quantum circuit outcomes. + prob = tf.convert_to_tensor(circuit.probability(), dtype=tf.float32) + + # Generate all possible binary states for the given Q-matrix. + states = tf.constant( + [format(i, "0" + str(len(Q)) + "b") for i in range(2 ** len(Q))] + ) + + # Convert the Q-matrix to a TensorFlow tensor. + Q_tf = tf.convert_to_tensor(Q, dtype=tf.float32) values = [] + + # Calculate the cost for each binary state. for state in states: - x = np.array([int(bit) for bit in state]) - values.append(np.dot(x, np.dot(Q, x))) - # Calculate the values by taking the dot product of each state with the Q-matrix. + binary_strings = tf.strings.bytes_split(state) + x = tf.reshape( + tf.strings.to_number(binary_strings, out_type=tf.float32), (-1, 1) + ) + xT = tf.transpose(x) # the transpose + value = tf.squeeze(tf.matmul(xT, tf.matmul(Q_tf, x))) + values.append(value) + + values = tf.convert_to_tensor(values, dtype=tf.float32) + # Calculate the CVaR value using the computed values and the probability distribution. cvar_result = cvar_value(values, prob, alpha) - # Calculate the CVaR using the cvar_value function. return cvar_result @@ -265,7 +277,7 @@ def cvar_loss( alpha: float, expectation_based: bool, params: List[float], -) -> float: +) -> Any: """ Calculate the CVaR loss for a given QUBO problem using the QAOA ansatz. @@ -297,7 +309,7 @@ def cvar_loss( def QUBO_QAOA_cvar( Q: Tensor, nlayers: int, - alpha: int, + alpha: float, nsamples: int = 1000, callback: Optional[Callable[[List[float], float], None]] = None, expectation_based: bool = False, @@ -318,9 +330,10 @@ def QUBO_QAOA_cvar( :param maxiter: The maximum number of iterations for the optimization. Default is 1000. :return: The optimized parameters for the ansatz circuit. """ + tf.config.run_functions_eagerly(True) loss = partial(cvar_loss, nlayers, Q, nsamples, alpha, expectation_based) - f_scipy = scipy_interface(loss, shape=(2 * nlayers,), jit=False, gradient=False) + f_scipy = scipy_interface(loss, shape=(2 * nlayers,), jit=True, gradient=False) if init_params is None: params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) From 2fa179b699487c836a81741f10e418c268379855 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:28:01 +0100 Subject: [PATCH 037/139] modify the qubo tutorials --- .../tutorials/portfolio_optimization.ipynb | 50 ++++--- docs/source/tutorials/qubo_problem.ipynb | 130 +++++++++--------- 2 files changed, 97 insertions(+), 83 deletions(-) diff --git a/docs/source/tutorials/portfolio_optimization.ipynb b/docs/source/tutorials/portfolio_optimization.ipynb index 69d9628f..7ec25888 100644 --- a/docs/source/tutorials/portfolio_optimization.ipynb +++ b/docs/source/tutorials/portfolio_optimization.ipynb @@ -8,9 +8,11 @@ "source": [ "# Portfolio Optimization\n", "\n", + "In this tutorial, we demonstrate the transformation of financial portfolio optimization into a quadratic unconstrained binary optimization (QUBO) problem. Subsequently, we employ the Quantum Approximate Optimization Algorithm (QAOA) to solve it. We will conduct a comparative analysis between the outcomes obtained through QAOA and those derived from classical brute force searching. Additionally, we explore the potential for enhancing results by customizing the QAOA 'mixer' component.\n", + "\n", "## Introduction\n", "\n", - "Consider the following scenario: Xiaoming, an astute individual, possesses a sum of money represented by $B$ and is contemplating investing it in the stock market. The market comprises of $n$ shares, each having an identical price. Xiaoming's objective is to maximize returns while minimizing risk, taking into account the varying levels of risk tolerance among individuals. Xiaoming's personal risk tolerance is represented by $p$. In light of these considerations, the question arises: which shares should Xiaoming choose to construct an optimal portfolio?\n", + "Consider the following scenario: Xiaoming, an astute individual, possesses a sum of money represented by $B$ and is contemplating investing it in the stock market. The market contains $n$ shares, each having an identical price. Xiaoming's objective is to maximize returns while minimizing risk, taking into account the varying levels of risk tolerance among individuals. Xiaoming's personal risk tolerance is represented by $q$. In light of these considerations, the question arises: Which shares should Xiaoming choose to construct an optimal portfolio?\n", "\n", "Xiaoming's predicament falls under the purview of portfolio optimization problems. These problems are classified as Quadratic Unconstrained Binary Optimization (QUBO) problems, wherein binary numbers are utilized to represent decisions. In this case, \"1\" signifies selection, while \"0\" denotes the opposite. To address the challenge of portfolio optimization, the Quantum Approximate Optimization Algorithm (QAOA) is employed.\n", "\n", @@ -18,38 +20,50 @@ "\n", "In a simple boolean Markowitz portfolio optimization problem, we wish to solve \n", "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^T x$$\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^T x\n", + "$$\n", "\n", "subject to a constraint\n", "\n", - "$$ 1^T x = B$$\n", + "$$\n", + "1^T x = B\n", + "$$\n", "\n", "where \n", "* $n$: number of assets under consideration\n", "* $q > 0 $: risk-appetite\n", "* $\\Sigma \\in \\mathbb{R}^{n\\times n}$: covariance matrix of the assets\n", "* $\\mu\\in\\mathbb{R}^n$: mean return of the assets\n", - "* $B$: budget (i.e., total number of assets out of $n$ that can be selected)\n", + "* $B$: budget (i.e., the total number of assets out of $n$ that can be selected)\n", "\n", - "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and consider the alternative problem:\n", + "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and considering the alternative problem:\n", "\n", - "$$ \\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2$$\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2\n", + "$$\n", "\n", - "The linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be transformed into squared forms, exploiting the properties of boolean variables where $0^2=0$ and $1^2=1$. The same trick is applied on the middle term of $t(1^Tx-B)^2$. Then the function is written as\n", + "The linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be transformed into squared forms, exploiting the properties of boolean variables where $0^2=0$ and $1^2=1$. The same trick is applied to the middle term of $t(1^Tx-B)^2$. Then the function is written as\n", "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2$$\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2\n", + "$$\n", "\n", "which is a QUBO problem\n", "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q x + tB^2$$\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q x + tB^2\n", + "$$\n", "\n", "where matrix $Q$ is\n", "\n", - "$$ Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", + "$$\n", + "Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", "1 & 1-2B & 1 & \\ldots \\\\1 & 1 & 1-2B \\\\\n", - "\\vdots\\end{pmatrix}$$\n", + "\\vdots\\end{pmatrix}\n", + "$$\n", "\n", - "and we ignore the constant term $t B^2$. We can now solve this by QAOA as above.\n", + "and we ignore the constant term $t B^2$. We can now solve this by QAOA.\n", "\n", "## Set up" ] @@ -120,7 +134,7 @@ "id": "0fb1d227", "metadata": {}, "source": [ - "In this analysis, we have carefully chosen six prominent stocks: Apple Inc. (AAPL), Microsoft Corporation (MSFT), NVIDIA Corporation (NVDA), Pfizer Inc. (PFE), Levi Strauss & Co. (LEVI), and Cisco Systems, Inc. (CSCO). We acquired their historical data spanning from 09/07/2022, to 09/07/2023 from Yahoo finance. Here are the return and covariance associated with this dataset" + "In this analysis, we have carefully chosen six prominent stocks: Apple Inc. (AAPL), Microsoft Corporation (MSFT), NVIDIA Corporation (NVDA), Pfizer Inc. (PFE), Levi Strauss & Co. (LEVI), and Cisco Systems, Inc. (CSCO). We acquired their historical data spanning from 09/07/2022 to 09/07/2023 from Yahoo Finance. Here are the return and covariance associated with this dataset" ] }, { @@ -153,7 +167,7 @@ "id": "f6dc53d4-7ed0-436d-aa1f-8674c56e756e", "metadata": {}, "source": [ - "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the pauli terms and weights" + "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the Pauli terms and weights, which is similar to what we do in the [QUBO tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qubo_problem.html)." ] }, { @@ -178,7 +192,7 @@ "source": [ "## Classical method\n", "\n", - "We firstly use brutal force to calculate the cost of each combination. It will give us a clue on the performance of QAOA." + "We first use brute force to calculate the cost of each combination, which is the expectation value $x^TQx$ for each $x\\in\\{0, 1\\}^n$ ($n$ is the number of stocks). It will give us a clue about the performance of QAOA." ] }, { @@ -260,7 +274,7 @@ "source": [ "### Use QAOA\n", "\n", - "Here, a standard QAOA ansatz with 12 layers is used. This circuit will be trained for 1000 times." + "Here, a standard QAOA ansatz with 12 layers is used. This circuit will be trained for 1000 iterations." ] }, { @@ -385,7 +399,7 @@ "id": "71c7a0e0", "metadata": {}, "source": [ - "The highest probability corresponds to the best combination, thereby ensuring consistency with the classical approach.\n", + "The highest probability corresponds to the best combination, which is consistent with what we found with classical brute force search.\n", "\n", "## Use XY mixer to improve the performance\n", "\n", @@ -457,7 +471,7 @@ "id": "917c9415", "metadata": {}, "source": [ - "Compared with standard X mixer, the XY mixer gives a higher probability to measure the best result." + "Compared with the standard X mixer, the XY mixer gives a higher probability of measuring the best result." ] } ], diff --git a/docs/source/tutorials/qubo_problem.ipynb b/docs/source/tutorials/qubo_problem.ipynb index 86441d71..a4779366 100644 --- a/docs/source/tutorials/qubo_problem.ipynb +++ b/docs/source/tutorials/qubo_problem.ipynb @@ -6,33 +6,37 @@ "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", "metadata": {}, "source": [ - "# Solving portfolio optimization as a QUBO problem with QAOA\n", + "# Solving QUBO Problem using QAOA\n", "\n", "## Overview\n", "\n", - "In this tutorial we will demonstrate how to solve quadratic unconstrained binary optimization (QUBO) problems using QAOA.\n", + "In this tutorial, we will demonstrate how to solve quadratic unconstrained binary optimization (QUBO) problems using QAOA. There is a specific application for portfolio optimization and we will introduce it in another [tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/portfolio_optimization.html).\n", "\n", "## QUBO problem\n", "\n", - "### what is QUBO?\n", + "### What is QUBO?\n", "\n", - "The quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", + "Quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", "\n", - "From a computational perspective, solving a QUBO problem is generally considered NP-hard. This classification implies that solving the optimal solution to a QUBO instance is believed to be computationally challenging, and there is no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", + "From a computational perspective, solving a QUBO problem is NP-hard. This classification implies that solving the optimal solution to a QUBO instance is believed to be computationally challenging, and no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", "\n", - "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in this [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem solving. QAOA leverages inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz. The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", + "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem-solving. QAOA leverages inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz (a quantum circuit with parameters to be decided). The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", "\n", "### General Case\n", "\n", - "For the general QUBO case, we wish to minimize the cost function in the form of\n", + "For the general QUBO case, we wish to minimize a cost function of the form\n", "\n", - "$$ x^T Q x$$\n", + "$$ \n", + "x^T Q x\n", + "$$\n", "\n", "where $x\\in\\{0,1\\}^n$ and $Q\\in\\mathbb{R}^{n\\times n}$ is a real symmetric matrix.\n", "\n", "This function maps to an Ising Hamiltonian \n", "\n", - "$$\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i" ] @@ -289,14 +309,14 @@ "source": [ "## Improve the performance with CVaR\n", "\n", - " Conditional Value-at-Risk (CVaR) is a risk measure that quantifies the potential loss beyond a certain threshold (alpha), considering the tail end of the distribution. In QAOA, incorporating CVaR as an objective function allows for addressing risk-averse optimization problems effectively. By optimizing for CVaR, the algorithm focuses on minimizing the expected value of the worst-case scenario, rather than solely optimizing for the mean or expected value, which usually lead to a faster convergence to a more accurate result.\n", + "Conditional Value-at-Risk (CVaR) is a risk measure that quantifies the potential loss beyond a certain threshold (alpha), considering the tail end of the distribution. As proposed by [Barkoutsos et al. (2020)](https://arxiv.org/abs/1907.04769), incorporating CVaR as an objective function in QAOA allows for addressing risk-averse optimization problems effectively. By optimizing for CVaR, the algorithm focuses on minimizing the expected value of the worst-case scenario, rather than solely optimizing for the mean or expected value, which usually leads to faster convergence to a more accurate result.\n", "\n", - " In order to showcase the performance of CVaR, a more complicated QUBO problem is used. This QUBO problem is described as a randomly generated symmetric Q matrix. The Q matrix is:" + "To showcase the performance of CVaR, a more complicated QUBO problem is used. This QUBO problem is described as a randomly generated symmetric Q matrix. The Q matrix is:" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 86, "id": "02ec55b6", "metadata": {}, "outputs": [], @@ -319,12 +339,12 @@ "id": "76879a55", "metadata": {}, "source": [ - "Then let's define a function to brutally calculate the costs (classical methods). The results are printed below." + "Then let's define a function to classically brute-force calculate all feasible combinations of stocks and their associated cost. The results are printed below." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 87, "id": "46e9cbd9", "metadata": {}, "outputs": [ @@ -391,12 +411,12 @@ "id": "04d4ea38", "metadata": {}, "source": [ - "The QAOA with CVaR and different alpha will be run and a callback function will be used to record the parameters during the solving procedure." + "The QAOA with CVaR and three different alpha (1, 0.25, 0.1) will be run and a callback function will be used to record the parameters during the solving procedure. When alpha is $1$, the complete measurement results are accepted and the model changes to the standard QAOA." ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 88, "id": "d3b386d6", "metadata": {}, "outputs": [], @@ -440,7 +460,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 89, "id": "b3da7c48", "metadata": {}, "outputs": [], @@ -471,23 +491,13 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 92, "id": "d1f375ce", "metadata": {}, "outputs": [ { "data": { - "text/plain": [ - "Text(0, 0.5, 'loss')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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7+zZs/HnP/8ZQ4YMQUZGBvR6PZqammJ6/6OPPhqbN29GW1ub/Nj69euh0+kwYsQIVFVVAQB++eUXeDwe+Z7Dhw/j2GOPBQCsXr0a+/btw549e/Dpp5/i008/xXvvvQebzRbTWIgo8biUn4hSTkZGBp577jmMGTNGvkpKSjB06FDs3r1bvq+1tdXv+0488US89tpr+PjjjzFr1iwcd9xxePDBB2E0GrtknIEN4IIgQKsV/2e3paUFY8eOxaWXXorDhw9jwYIF2Lx5M7KysrpkLEQUPVaOiCipORwO6HQ6v8e+//57jBw50i8IRWPSpEnYt28fHnroIfmxgQMHdvh+gbZt24Yrr7wS6enpcvXopJNOgtvtxo4dO6Iej9vtxtq1a7F27Vrcd999aGhowLRp0/Dee+/F8FMRUaKxckRESW3v3r049dRT0a9fP+Tm5gIAHn74YUyaNAlPPfWUXDE655xz8NRTT0V8rV9//RVFRUW4+OKLMXjwYNx00004//zzg96vuLgYJSUlyM3NDVlVeu2112C327FixQocc8wxmDJlCp566im88sor8pRaR84++2zcdNNNKCkpQVFREa644gpotdqYwhURdQ2GIyJKan/7298waNAg7N69GzU1NQCALVu2YPLkyRg+fDj+97//4YcffsCCBQtw6NChiK/14YcfYsmSJXj66afx448/YtKkSbj//vv97nn33Xfx6aef4osvvkBNTQ0uvfTSoNex2Ww444wz0KtXL3z33Xd45513sHbtWtx4441R/1wNDQ244IIL8Pnnn2Pbtm2YO3cuLr30UmzdujXq1yCirqGB2JlNRERERGDliIiIiMgPwxERERGRAsMRERERkQLDEREREZECwxERERGRAsMRERERkQLDEREREZECwxERERGRAsMRERERkQLDEREREZECwxERERGRwv8HWlMAT8XjTSEAAAAASUVORK5CYII=", + "image/png": "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u3dvceLECfHNN99UVpu9/9Ju9LJr1y7x0UcfyZ8VCoW4ePGiePnll73etupSateuLYQQ4uabbxYARGhoqCgsLBT33nuvXKdly5ZCCCF69Ojh9fb6WwkODhaJiYli0KBBYuvWrXJwxPdccWX27Nli27ZtLutcvnxZTJo0Sf4cGhoqDAaDeOCBB7zefn8pq1evFl988YXdsZ9++kksW7aM77mCiqPgqLR32qpVKyGEEF26dJHr3HrrrcJsNou6detWeBvZreZlGo0GXbp0webNm+VjQghs3rwZcXFxXmxZ9RIWFgYAuHr1KgCgS5cu0Gq1du89MTERSUlJfO9lsHDhQqxduxZbtmyxO873XHHuuusu7NmzBz/88ANSUlKwb98+PPHEE/L5m266CXXr1rV719nZ2di9ezfftQf++usvDBo0CM2bNwcAdOjQAX369MG6desA8D1XBnfeaVxcHDIyMrB37165zubNm2GxWNCjR48KbxM3nvWy2rVrQ61WIyUlxe54SkoKWrVq5aVWVS8KhQIffPABduzYgSNHjgAAoqOjUVhYiKysLLu6KSkpiI6O9kYz/dYDDzyAzp07Oxwnx/dccZo0aYKnnnoK8+bNw9tvv41u3brhww8/hNFoxNKlS+X36ei/JXzX7nvnnXcQGhqK48ePw2w2Q6VS4dVXX8W3334LAHzPlcCddxodHY3U1FS782azGVevXq2U987giKq9hQsXol27dujTp4+3m1LtNGjQAAsWLMDgwYO5pUIlUyqV2LNnD1599VUAwIEDB9CuXTtMnDgRS5cu9XLrqo+RI0dizJgxGD16NI4cOYKOHTvigw8+wOXLl/mebyDsVvMyvV6PoqIiREVF2R2PiopCcnKyl1pVfXz00UcYNmwYBgwYgEuXLsnHk5OTERAQIHe3SfjePdOlSxdERUVh3759MJlMMJlM6N+/P5577jmYTCakpKTwPVeQK1eu4OjRo3bHjh07hpiYGACQ3yf/W1I+c+bMwTvvvIPvv/8e//77L5YvX4758+dj6tSpAPieK4M77zQ5ObnELFeVSoWaNWtWyntncORlJpMJe/fuxaBBg+RjCoUCgwYNQkJCghdb5v8++ugjjBgxAgMHDsS5c+fszu3duxdGo9Huvbdo0QKNGjXie/fAli1b0K5dO3Ts2FEu//zzD7755ht07NgRe/bs4XuuIDt37kTLli3tjrVo0QJJSUkAgLNnz+LKlSt271qn06FHjx581x4ICgqCxWKxO2Y2m6FUWn9d8j1XPHfeaUJCAiIiItC5c2e5zsCBA6FUKrF79+5KaZfXR67f6GXkyJHCYDCIhx9+WLRq1Up89tln4urVq6JOnTpeb5u/loULF4qMjAzRt29fERUVJZcaNWrIdT755BNx7tw50b9/f9G5c2exc+dOsXPnTq+33d+L7Ww1vueKK127dhVGo1FMnTpVNG3aVDz44IMiNzdXjB49Wq7z0ksviatXr4o777xTtGvXTqxcuZJTzD0sX331lbhw4YI8lf/uu+8Wqamp4p133uF7LkcJDg4WsbGxIjY2VgghxPPPPy9iY2NFw4YN3X6nv/32m9i7d6/o1q2b6NWrl0hMTORU/upennnmGXHu3DlRUFAgdu3aJbp37+71NvlzcWbcuHFynYCAAPHxxx+L9PR0kZubK37++WcRFRXl9bb7e7k+OOJ7rrhyxx13iEOHDgmDwSCOHj0qnnjiiRJ1ZsyYIa5cuSIMBoPYtGmTaN68udfb7U8lJCREzJ8/X5w7d07k5+eLU6dOiTfffFNoNBq+53KUfv36Ofxv8ldffeX2O42IiBDffPONyM7OFpmZmWLx4sUiODi4UtqruPYDEREREYFjjoiIiIjsMDgiIiIissHgiIiIiMgGgyMiIiIiGwyOiIiIiGwwOCIiIiKyweCIiIiIyAaDIyIiIiIbDI6IyOds3boV8+fP93Yz7AghMHz4cG83g4iqiNeXFWdhYWGxLRERESIkJEQAEGfPnhXx8fFV9uw33nhD7N+/v8TxqKgoodVqvf5uWFhYKr+oQUTkYzIyMir8nhqNBiaTqczXp6SkVGBriMjXeT1CY2FhYbEt0ua1W7duLbFRpVSnd+/eYtu2bSI/P1+cP39eLFiwQAQFBcnnz549K1577TWxZMkSkZWVJW9w+c4774jExESRl5cnTp8+LWbOnCnUarUAIMaNG+d0s2IhhBg+fLh8/3bt2oktW7aI/Px8odfrxaJFi+w2wfzqq6/EypUrxaRJk8Tly5eFXq8XH3/8sfwsAOKpp54SJ06cEAaDQSQnJ4sff/zR6++ehYUFAj7QABYWFha7IgVHERER4vz58+K1114TUVFRIioqSgAQTZo0ETk5OSI+Pl40a9ZMxMXFib1794ovv/xSvsfZs2dFZmameOGFF0STJk1EkyZNBADx6quviri4ONGoUSMxbNgwceXKFTF58mQBQNSoUUPMmTNHHD58WH5ejRo1BGAfHAUFBYlLly6Jn376SbRt21YMGDBAnD592m6H8a+++kpkZmaKTz75RLRs2VLccccdIjc3VzzxxBMCgOjSpYswmUxi1KhRIiYmRnTs2FE8++yzXn/3LCwsEPCBBrCwsLDYFSk4AhyPOfr888/FZ599Znesd+/eoqioSAQEBMjX/fLLL6U+a9KkSeKff/6RPzsbc2QbHD3xxBMiPT3dLlN12223iaKiIlGnTh0BWIOjs2fPCqVSKdf5/vvvxYoVKwQAMWLECJGZmSmPrWJhYfGdwjFHROR3YmNj0aFDB4wZM0Y+plAooFKpcNNNN+H48eMAgD179pS4duTIkXjuuefQtGlThISEQK1WIzs726Pnt27dGgcPHkR+fr58bOfOnVCpVGjZsiVSU1MBAEeOHIHFYpHrXLlyBe3btwcAbNq0CUlJSThz5gzWr1+P9evXY+XKlTAYDB61hYgqHqfyE5HfCQkJwaJFi9CxY0e5xMbGolmzZjh9+rRcLy8vz+66nj174ptvvsFvv/2GYcOGoVOnTpg1axa0Wm2ltPP6AeBCCCiV1v/s5ubmonPnznjwwQdx5coVzJw5EwcPHkRYWFiltIWI3MfMERH5NKPRCJVKZXds3759aNOmjV0g5I5evXohKSkJb7/9tnysUaNGpT7veseOHcMjjzyCoKAgOXvUu3dvmM1mJCYmut0es9mMLVu2YMuWLZgxYwYyMzMxcOBArFy50oNvRUQVjZkjIvJp586dQ9++fVGvXj3UqlULAPDuu++iV69e+Oijj+SM0V133YWPPvrI5b1OnjyJmJgYPPDAA2jSpAmeffZZjBgxosTzbrrpJsTGxqJWrVoOs0rffPMNCgoKsGTJErRt2xb9+/fHRx99hGXLlsldaqW544478OyzzyI2NhYxMTF4+OGHoVQqPQquiKhyMDgiIp82bdo0NG7cGKdPn4ZerwcAHD58GP369UOLFi2wfft27N+/HzNnzsTly5dd3mv16tWYP38+Pv74Yxw4cAC9evXCm2++aVfn559/xvr167F161bo9Xo8+OCDJe5jMBhw6623ombNmvjnn3/w008/YcuWLfi///s/t79XZmYm7rnnHvz+++84duwYJk6ciAcffBBHjx51+x5EVDkUsI7MJiIiIiIwc0RERERkh8ERERERkQ0GR0REREQ2GBwRERER2WBwRERERGSDwRERERGRDQZHRERERDYYHBERERHZYHBEREREZIPBEREREZENBkdERERENv4flMrniyoj9T4AAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -499,9 +509,9 @@ "source": [ "for loss in loss_list:\n", " plt.plot(loss)\n", - "plt.legend([0.1, 0.25, 1])\n", + "plt.legend([\"alpha = 0.1\", \"alpha = 0.25\", \"alpha = 1\"])\n", "plt.xlabel(\"iterations\")\n", - "plt.ylabel(\"loss\")" + "p = plt.ylabel(\"cost\")" ] }, { @@ -514,23 +524,13 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 93, "id": "f81fdeae", "metadata": {}, "outputs": [ { "data": { - "text/plain": [ - "Text(0, 0.5, 'probability of the best answer')" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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gARecD3Hm4IopijWHKD4LrBc5X+87kUhaIIgCCITmjUIccSIEZg1axbWrVuHdevWYdasWRg5cmSuz3bUIvnjHCC21sIMQVsOUKoQtIcDVJBfbL6uKeE5Zyu8qas8HSCjBJa5AyRw7n9CHGe8NqIoaIrbBcZKYLlahGqckUpgBEEQRPZkLYBuvPFGzJ49G/X19XjyySfx5JNPoq6uDh999BFuuummljjjUYdo5ndk5gCxtngzBM2bZSTFKwStGaIkfgAhAOTnGw6QojQmPOdshWet9KqS2AafWQnMzgAlCCDzn1Q4qlhzgOK7wHJZAqMQNEEQBNEcsi6B3X333bj99tsxefJk67GnnnoK33zzDe6++24888wzOT3g0YgY5wD5A44MkN8PIUUJTNFZt5a7/RwAQnlFAABZbkh4blfVDshyDJLkg865W+CB+BJY6hB0TU0DBMHbAQKMszdFY5YDdDBLYCSACIIgiEzI2gFq06YNZs+enfD4J598gqKiopwc6miHtborbA6Qny0QNTNAbE2GbAgQv4cD5FUCCwbbAABisfqE5zRNxcdz3sWmresREVVX/sd4L7YKI7sSGA97kSvPG5voAaApHPUogZEAIgiCIA4PshZAH3zwAS6++OKExy+88EL8+9//zsmhjnasQYjMAbImQ7szQLLZBubVBh8/gBAAgoFCAEAkut/zfZ948l788YGboHPu/A9guz2ZlMCamqJQFOPsvM5Z5/U5gtkNkUhCCUySDkYIOpbkSoIgCIKwyagEdsstt1jfr1y5En/6058wfPhwzJ8/HwAwePBgDB06FI8//njLnPIog80BYl1gflM46CwDJDIBZIgStwBiDlCiAPL7CwAAkUhd8ve2WvDjBVBiF1iqYYW1+w2XiQMHXyCASGOjy5Wqb4g4SmAt5wDRMlSCIAiiOWQkgG6//XbXz/v27cMJJ5yAE044wXqstrYW11xzDR588MHcnvAoxF6FYU6C9scJINNRiSlMANliR1WNUpXk4QD5fIYAamrydoAAQGCzeORkJTDBziClECr79tnvkZefj0hjI/KCQfMRHfUNYUsABYN+cBxnCaBc7QHzOmM0mrsOM4IgCOLoJSMBdMwxx7T0OVoV8SFou6NLhyj5rFUUspxYAlM05tQkCiBJzAcANDbVJn9vtqw0aQks/S4wANhXYwugYKgAQBWK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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGwCAYAAABB4NqyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACvYklEQVR4nOydd3hUZfbHP9PTCzW00BRpSlVBVBBEwYrKImJvLLZF0V1X3QVBRV0Vl7Xs7k8REV0sqCgqoFhBYwGkdwSkJRAgpE2f+f1x596505KZMEmAnM/zzEPm3vfe+06C5ss533OOAfAjCIIgCILQgDDW9wYEQRAEQRDqGhFAgiAIgiA0OEQACYIgCILQ4BABJAiCIAhCg0MEkCAIgiAIDQ4RQIIgCIIgNDhEAAmCIAiC0OAw1/cGjlVatmxJWVlZfW9DEARBEIQEyMzMZO/evdWuEwEUhZYtW7Jnz5763oYgCIIgCDWgVatW1YogEUBRUCM/rVq1kiiQIAiCIBwnZGZmsmfPnrh+d4sAqoKysjIRQIIgCIJwAiImaEEQBEEQGhwigARBEARBaHAcEwLozjvvZPv27djtdn788UdOP/30KtePHDmSDRs2YLfbWb16NcOHDw85P3PmTPx+f8hrwYIFtfkRBEEQBEE4jqh3ATRq1CimTZvG5MmT6d27N6tWrWLRokU0bdo06vr+/fszZ84cZsyYQa9evZg3bx7z5s2jW7duIesWLFhAXl6e9rrmmmvq4uMIgiAIgnCc4K/P148//uh/4YUXtPcGg8G/e/du/4MPPhh1/dtvv+2fP39+yLGCggL/v//9b+39zJkz/R9++GGN95SZmen3+/3+zMzMev3eyEte8pKXvOQlr/hfifz+rtcIkMVioU+fPixevFg75vf7Wbx4Mf379496Tf/+/UPWAyxatChi/aBBgygqKmLjxo28/PLLNGrUKOY+rFYrmZmZIS9BEARBEE5c6lUANWnSBLPZTFFRUcjxoqIi8vLyol6Tl5dX7fqFCxdyww03MGTIEB588EEGDhzIggULMBqjf9yHHnqI0tJS7SVNEAVBEAThxOaE7AP0zjvvaF+vXbuW1atX89tvvzFo0CC++uqriPVPPvkk06ZN096rjZQEQRAEQTgxqdcIUHFxMR6Ph+bNm4ccb968OYWFhVGvKSwsTGg9wPbt2zlw4AAnnXRS1PMul0treijNDwVBEAThxKdeBZDb7Wb58uUMGTJEO2YwGBgyZAgFBQVRrykoKAhZDzB06NCY60EZadG4cWP27duXnI0LgiAIgnDcU6+O7VGjRvntdrv/hhtu8Hfu3Nn/n//8x3/o0CF/s2bN/IB/1qxZ/qlTp2rr+/fv73e5XP4JEyb4TznlFP+kSZP8TqfT361bNz/gT09P9//jH//wn3nmmf62bdv6Bw8e7F+2bJl/06ZNfqvVmnQXubzkJS95yUte8jo2Xgn+/q7/Dd91113+HTt2+B0Oh//HH3/0n3HGGdq5r7/+2j9z5syQ9SNHjvRv3LjR73A4/GvWrPEPHz5cO5eSkuJfuHChv6ioyO90Ov3bt2/3//e//9UEVS18A+UlL3nJS17yktcx8Erk97ch8IWgIzMzk9LSUrKyssQPdAJjMpvx+Xz4fb763oogCIKQBBL5/V3vnaAFoT5o3KY1U5YuZMzUifW9FUEQBKEeEAEkNEhOH3ERKenp9L74Qpq2y6/v7QiCIAh1jAggoUHSY+hg7euzrr6yHnciCIIg1AcigIQGR95JHWjWvq32/vTLL8aamlqPOxIEQRDqGhFAQoPjtKHnAbDum6Xs376T1MwM+lwyrJ53JQiCINQlIoCEBkePC5T016pFX/L92+8DMOCaq2p8v6ymTTBbrUnZmyAIglA3iAASjmk6n92Py/4yntSsrKTcr3mHduSd1AGP2826b5ey7OPPcFZW0uLkjnTs2yuhe2U1a8rVjz3C3xd/xF8++h95J3VIyh4FQRCE2ueEHIYqHB1mqxWPy1Xf2wDgkgl30+LkjnQ5uz+v3DmBQ7v3HtX9Tg2kvzYX/IyjrByA5fMXctbVVzLgmpFsW/artrbz2f24esojOMorWP/t96z/dinbV67GbLEw6KZrGXTTtdjSFO9Q49atuOfN/+N/D01m3ddLqtxDbos8Wnc9hSb5rfH7/Hi9XnweD16vl4rDJRzas5dDe/ZhL43sYWEymzHbrBhNZkwWE0aTGbPFjCUlBWtqKtbUFKwpKfh8PpwVlTgrK3BWVOJyODBgwGA0YjAaMBiMGM0mTGaz9jIYjXjcbjxOJx6nC7fLhc/rxe/z4ff78fuU/mF+v7QOEwTh6PF5vHg9nnp7vgggIYQbp02l4+m9efLiP0T9BVzX5LbIA6BZ+7b86c1XeO1Pf+H31etqfL8eAQG0+vOvtGPfv/0+Z119Jd0Hn0t286YcKTrAkNtuZNg9YzEajWQ1bUKz9m0ZdNMY7KVluF0uspo0BmD7r6v5/N8zGHzr9Zx8Zl9u+dc/+Oxf/+HLV2YBkJKRTtsep9K+92nkd+tC666dSc/NiWuv9tIySosPYrHZsKWnYUtPw2yx1PizC4IgHEssfmUWC/71n3p7vgggIYS2PbqTnpNN8/bt2LFqTb3uxZaeRkpGOgB7Nm6mVedO3DnjJd566FHWLP4m4fs1aduGlqecjNftYe3XS7XjhVt/Y+svKzjp9N4MvHEMOc2baT6hgvfmsfnHX+h67ll0OecsMhrlkgoc3L2HT6a9xOovvgZg6y/Lufwv93L2NSO56E/j6NT/DFIzMmjRqSNGkylkH163h31btlH023b8Pj9GswmjyYTZYiazcWMatW5JZuNGpGZlkpqVWeVn8ro9eD0eXHY7LocDl92B2+nEaDRiS1NEky0tDWtqitb1Wonm+PB5lX99ed0efB4vPp8Xs9WK2WrFYrOKr0kQhBMaEUBCCOova1t6Wj3vBLKbNQWUSMiLN4zj+mceo+vAAdzw3BPMnfI0P73/cUL3U3v/bPlpGfbS0pBz38+Zqwig60cD4HG7+XDqc/w49yNAiRgZjEbadO9CZuNGbPr+p5A0oc/j5cOpz7FvyzaufOh+Tjq9t3au+PfdbP91FTtXrWPXug3s27INr9td5V6tqSnktmxBZuNGuOx2JZ1VUYmjshKPU0lN+bzehD5/ohiMRoxGIxgMGAyGQOrMUKvPFASh4eB111/6C0QACWEcUwKoeTMAjuw/gMtuZ+b4B7n8QSXKcvlf7mXj0gKOFB2I+35q+fvqL76KOLf26+84UnRASYHtP8CsCQ+zc9XakDV+n6/a9NuP781jz/pNdDmnP4W/7WD7ilWUFR+Me48qLruDom3bKdq2PeFrk4Xf58Mrc9IEQThBEQEkhHAsCaCc5koE6EjRfgB8XiXK0rLTSXTo05OL/nQHcx6ZEte9GrduReuup+D1eFj71XcR530eL2/c/wjdhwzk2zfm1Ei0qOxat4Fd6zbU+HpBEASh9pEyeCEEVQClpKfX806UMnOAI/uLQ45/9I9/4vP56HvZcNp07xrXvU4bOgiAbb+soKLkSNQ1O1at4ZNpLx6V+BEEQRCOD0QACSGYzMdSBEhJgZUEIkAqu9dvYvn8BQCMePDeuO7V59LhAKz+4puk7U8QBEE4fhEBJIRgMCp/JY4FAZStRYAifT6fTf8Pzko77XqeSs9h51d5n1MG9KPFyR1xVFTw68IvamWvgiAIwvGFCCAhBJNZsYXZ0o4BAaSaoAv3R5wrPVDMVzPeAOCSCXdhttli3ue8m64F4Kf3P9aaHwqCIAgNGxFAgoa+X80xEQFqHjsCBPDNrDkc3ldIbos8Bt14TdQ1rbuewsn9+uL1ePhu9ju1tldBEATh+EIEkKChF0Ap9SyATBYLmY0bAcEqsHA8TiefTHsJgMG33kCjVi0i1gwKRH9WLlxMSWFRLe1WEARBON4QASRoGE3Bvw62tPqtAstqqoyacDudMau2QBE221eswpaWyi0vPKN1jgZo1KqF1tH565lv1e6GBUEQhOMKEUCCxrGUAsvRNUGsjtl/+TtH9h+gxckduf6Zx7XPce71ozGaTGz64Sf2bd5aq/sVBEEQji9EAAkax5IAqqoCLJwjRQd47Z4/46y00/nsfoz4632kZWdxxhWXAhL9EQRBECIRASRoGM3HjgDK0rpAxzfqYvf6TfzvoUfx+XwMGH0Vt//neWxpqezZsJktP/5Sm1sVBEEQjkNEAAkaRqNOANVzGbyWAktg1tfar77j0+dfBiA/0CH669cl+iMIgiBEIgJI0DheU2B6vnn9LW2C+6G9+1j1+ZdJ35sgCIJw/CPDUAUNfQrMaDRiTU3FZbfXy160JogxSuCr4v0nnmH3hk3sWLkGn8eb7K0JgiAIJwAigAQNozE0IGhLT6s/AVTDCBAok90L3v0w2VsSBEEQTiAkBdaAGPXoQ/zlozkxx0boU2BQf2kwg8EQFEBRxmAIgiAIwtEiAqgB0e28c2jeoR3N2uVHPW80hwYE66sbdHqjHEwWMz6fj9KDB+tlD4IgCMKJjQigBoTq8dF3fNZjCo8A1VMlmFoBVlZ8UDw8giAIQq0gAqgBoU56D091qRgiPED1Mw7jaPw/giAIghAPIoAaEKrwMZqie9/1VWBQfx6g7Br0ABIEQRCERBAB1IDQIkDm6BGgiBRYfQkgiQAJgiAItYwIoAaCwWDQIkDhQkclPDWWUk8eoGxtDIZUgAmCIAi1gwigBoJBZ3yO5QE6VsrgJQUmCIIg1DYigBoIJl2Je9wCKKN+TdAlEgESBEEQagkRQA0EvbiJ5QE65lJg4gESBEEQagkRQA2EuCJAx0AVmC09jZRA+X2pCCBBEAShlhAB1EDQi5uYJugos8DqGrUJYmVpKS67o86fLwiCIDQMRAA1EEIiQLFSYGGjMOqjE3SwAkyiP4IgCELtIQKogRDiAYrVCPEYqAKTCjBBEAShLhAB1EDQi57qqsAc5RVAPQkgaYIoCIIg1AEigBoIJnM8VWDKX4fK0lKgvlJgagRISuAFQRCE2kMEUANB7++prhO0vbQMQKvGqkskAiQIgiDUBSKAGgghEaA4BZAlxRYzWlRbSBNEQRAEoS4QAdRAiMcDpIqkyoAAArCl1W0USKrABEEQhLpABFADwRRHJ2iDUTnucblwO50ApNShEdpksZDZuBEgHiBBEAShdhEB1EAwWuKIAAWO+zxenBWVQN1WgmU3awKA2+mk8khpnT1XEARBaHiIAGog6CNAMU3QgciQz+vFWVkfAkjSX4IgCELdIAKogWAM6QRddSNEr9cTjADVUSm8yWzmwjtvB+DA77vq5JmCIAhCw0UEUAMhtBN01bPA/F5fnafA/vDoXzm5X18cFRV89s9/18kzBUEQhIaLCKAGQnzT4JU1Pq8XRyAFVhcm6KHjbuH0yy/G6/Ew+4G/sXfTllp/piAIgtCwEQHUQDDG1QlaTYHVnQm6z6XDGXaXkvr6YOpzbFz6Y60+TxAEQRBABFCDIS4TtL4KTJ0HVot9gDr27cWoyQ8B8NWMN/jxvXm19ixBEARB0CMCqIFgjCcFFpgF5vcFU2C1GQG6ZMLdmC0WVi5czGfT/1NrzxEEQRCEcKKXAwknHKZ4TNC6FJinDlJgjVu3BOCL/3sdv99fa88RBEEQhHBEADUQQhohVuMB8nm8uOwOoPYGohrNJtJzcwAoP3ioVp4hCIIgCLGQFFgDIa4IkL4RYi1HgNJzcrRnVZQcqZVnCIIgCEIsjgkBdOedd7J9+3bsdjs//vgjp59+epXrR44cyYYNG7Db7axevZrhw4fHXPvvf/8bv9/P+PHjk73t4wq9ByimCdqoCiAfzsqACbqWBJA686v8cAl+n69WniEIgiAIsah3ATRq1CimTZvG5MmT6d27N6tWrWLRokU0bdo06vr+/fszZ84cZsyYQa9evZg3bx7z5s2jW7duEWtHjBhBv3792LNnT21/jGOe0GGoVXeCDokA1VInaE0AHTpcK/cXBEEQhKqodwE0YcIEXnnlFV5//XU2bNjAuHHjqKys5JZbbom6fvz48SxcuJBnn32WjRs3MnHiRFasWMHdd98dsq5ly5a88MILXHvttbjd7rr4KMc0IX2AYg1D1aXAHLWcAstQBZD4fwRBEIR6oF4FkMVioU+fPixevFg75vf7Wbx4Mf379496Tf/+/UPWAyxatChkvcFgYPbs2TzzzDOsX7++2n1YrVYyMzNDXica8ZXBqwIoOAustjpBqxGgMhFAgiAIQj1QrwKoSZMmmM1mioqKQo4XFRWRl5cX9Zq8vLxq1z/44IN4PB7+9a9/xbWPhx56iNLSUu11IqbMQlNg0QWQITALTPEA1U0KTASQIAiCUB/Uewos2fTu3Zvx48dz0003xX3Nk08+SVZWlvZq1apV7W2wnojHBG2qwyqwjEa5gKTABEEQhPqhXgVQcXExHo+H5s2bhxxv3rw5hYWFUa8pLCyscv0555xDs2bN+P3333G73bjdbtq1a8dzzz3H9u3bo97T5XJRVlYW8jrRiK8RYmAYqseLIzAKw2gyYUmxJX0/mY0VAVR2UEzQgiAIQt1TrwLI7XazfPlyhgwZoh0zGAwMGTKEgoKCqNcUFBSErAcYOnSotn727Nmcdtpp9OzZU3vt2bOHZ555hgsvvLD2PswxTkgjxDg6QbvsdnyB8vTaiAJpJuhDEgESBEEQ6p6EOkGbTCYefvhhXnvttaT5ZKZNm8asWbNYtmwZP//8M/feey/p6enMnDkTgFmzZrFnzx4efvhhAKZPn863337LhAkT+PTTTxk9ejR9+/Zl7NixABw6dIhDYb9U3W43hYWFbN68OSl7Ph6JxwOknwUG4Kq0k5KRTkp6OuVJjtSIB0gQBEGoTxKKAHm9Xv785z9jjtFHpia8++67PPDAA0yZMoWVK1fSs2dPhg0bxv79+wHIz8+nRYsW2vqCggLGjBnD2LFjWbVqFSNHjmTEiBGsW7cuaXs6ETEmMAvM51EEUG35gAwGgzYGQ1JggiAIQn2QsJL56quvGDhwIG+88UbSNvHSSy/x0ksvRT133nnnRRybO3cuc+fOjfv+7du3r/HeThRMISboqhsher0BAaRNhE/uPLC0nGxtP5ICEwRBEOqDhAXQggULeOqppzj11FNZvnw5FRUVIefnz5+ftM0JySOkEWKsFJiuCgzAEfjZJrsUXq0Aqyg5okWbBEEQBKEuSVgAvfzyy4DSwTkcv9+f1PSYkDxM8TRC1M0CA2qtGaL4fwRBEIT6JmG1EquHjHBsk5AHKCIFVjsCSOaACYIgCPXFUZXB22zJ7w8j1A5xCaCwFFhtDUSVOWCCIAhCfZOwADIajfztb39j9+7dlJeXawbjKVOmxBxgKtQ/ISbomGXwahWYB6i9KjBJgQmCIAj1TcIC6JFHHuGmm27iL3/5Cy6XSzu+du1abrvttqRuTkge8UyDN6qzwHyhHiARQIIgCMKJRsIC6IYbbmDs2LH873//08qlAVatWkXnzp2TujkhecRlgo5VBZZkASRzwARBEIT6JmEB1KpVK7Zu3Rp5I6MRi8WSlE0JyccYVyfo6I0QU5LuAZI5YIIgCEL9krAAWr9+Peecc07E8ZEjR/Lrr78mZVNC8oknAqQ2SIwwQWcktxFipswBEwRBEOqZhMvgp0yZwqxZs2jVqhVGo5Err7ySU045hRtuuIFLLrmkNvYoJAG96InVCdpgUj1AgRRYLZfBiwdIEARBqC8SjgB9/PHHXHrppZx//vlUVFQwZcoUunTpwqWXXsrixYtrY49CEojHBG2KmQJLXgQoJTMDs9UKSApMEARBqD9q1LZ56dKlXHDBBcnei1CLhJTBW+KcBVYLVWBq9MdRXoHH6UzafQVBEAQhERKOAE2ePJlBgwZJE8TjjPCoj8EY+aOPaIRYmfwqMLUCTNJfgiAIQn2SsADq378/8+fPp6SkhO+++47HHnuMIUOGkJKSUhv7E5KEKWxGW7Q0mDoLzB82CyyZnaAzpQu0IAiCcAyQsAC64IILyMnJYciQIXz22Wf07duXDz74gJKSEpYsWVIbexSSQHjpe7Ru0LFSYNbUlJi+oUTRDNAyB0wQBEGoR2rkAfJ6vfzwww8cOHCAQ4cOUVZWxogRI6QR4jFMPBEg1Rvk8yqjMBwBAQRgTUvFUVZ+1PuQOWCCIAjCsUDCEaDbb7+dt956i927d/PDDz8wbNgwli5dSt++fWnatGlt7FFIAuGCJ8ITZDBoX6tVYF63G4/bDSSvGaKUwAuCIAjHAglHgP7zn/9w4MABnnvuOV5++WUqAuMShGObCAFkji2I1FlgAM7yCsy5OUkzQmc2FhO0IAiCUP8kHAG68soreeuttxg9ejQHDhzg+++/54knnmDo0KGkpqbWxh6FJBCZAgt7rxNEagQIgmmwZHWDzmgkKTBBEASh/kk4AvTRRx/x0UcfAZCVlcU555zDH/7wBz755BN8Pp+IoGOUCBN0FSkxn27IrTPQDTolSREgmQMmCIIgHAvUyATdqFEjBg4cyKBBgxg0aBDdunXj8OHDUgV2DFOdCTqmAEpyKbzMARMEQRCOBRIWQKtXr6ZLly4cPnyY7777jldeeYVvv/2WNWvW1Mb+hCSRkAcomgBKP/oUmDU1RRNS4gESBEEQ6pMamaC//fZb1q1bVxv7EWoBg8FQbRWY+l4vfiCYAkuGCVotgXc7nJqwEgRBEIT6IGEB9PLLL4e8NxqNnHrqqezcuZOSkpJk7UtIInqx43Y4saTYIgSQKZYASmIKTErgBUEQhGOFhKvAnn/+eW655RblYqOR7777jhUrVrBr1y4GDhyY9A0KR48+3eUODCAN7wRtMCl/FbyeUAHkqEjePDCZAyYIgiAcKyQsgEaOHMmqVasAuPTSS2nXrh2dO3fm+eef54knnkj6BoWjR2+AVgVQZApMWePX9QCC5FaBBQ3QUgEmCIIg1C8JC6AmTZpQWFgIwEUXXcR7773Hli1beO211zj11FOTvkHh6AlJgWkCKDT7aTJXkwJLogdIegAJgiAI9U3CAqioqIiuXbtiNBoZNmwYX3zxBQBpaWnaEE3h2EKNAPl8PrxuZc5XrCowr8cTclw8QIIgCMKJSMIm6JkzZ/Luu++yb98+/H4/ixcvBuDMM89k48aNSd+gcPQYddEdNcIT3gjRYDRqa/SUHy4BIKtZk6PehwggQRAE4VghYQE0efJk1q5dS5s2bXjvvfdwuVyAMiH+qaeeSvoGhaNHi+64PdqYi4gqsIBICvcAFe/cBUDT/DZHvQ/VBC0pMEEQBKG+qVEn6Pfffz/i2BtvvHHUmxFqBy0F5vXi9QZSYDH6AIVXgRX/vhuA9Nwc0rKzqDxSWuN9SARIEARBOFaokQAaPHgwQ4YMoVmzZhiNoTaiW2+9NSkbE5KH1uTQ49FSXJEeoKBI0uOy2ykp2k9O82Y0aduG31fXvAGmOgdMqsAEQRCE+iZhE/TEiRP5/PPPGTJkCE2aNCE3NzfkJRx7mCyKuPF6vTFTYEZTdA8QwIEdvwPQtG3+UezBQlpWFiARIEEQBKH+STgCNG7cOG666SbefPPN2tiPUAtEiwDFmgYfVQDt3MXJZ/alabua+4AyA/4fr9uDvbSsxvcRBEEQhGSQcATIarXyww8/1MZehFpC9QB5Pd4qUmBVCaCjjwBl6Jog+v3+Gt9HEARBEJJBwgLo1VdfZcyYMbWxF6GW0Pt71F5N4Y0QjTEaIQIc2BGoBGtb8wiQ6v+R9JcgCIJwLJBwCiwlJYWxY8dy/vnns3r1atxud8j5+++/P2mbE5KDKm68nthl8EajmiaLHQFqchSl8GlZmQBUlta8ikwQBEEQkkXCAui0005j5cqVAHTv3j3knKQ2jk30ZfDVpsDC+gABHNqzF6/Hgy0tlaxmTSndfyDhPZitNgA8TlfC1wqCIAhCsklYAA0ePLg29iHUIvoxFzFN0FWkwHweL4d276Vpu3yatm1TQwFkAYKzyARBEAShPknYAyQcf2gRII8Xnyd6I0STKXYKDJRKMICm7WpmhDbbrAB4XEcXATKbLYwb+xd69jjzqO5TlxiNRiZOHM2IEf3qeyuCIAhCgBo1QuzTpw+jRo0iPz8fq9Uacu6qq65KysaE5KEvgw+aoMNmgWl9gEKHoaoc+P3ojNCWJKXAzhlwPlf/4VbOPut8rrvpgqO6V11x2WVn8Ojka3G7PfTv9wArVmyr7y0JgiA0eBKOAF199dX88MMPdOnShSuuuAKLxUK3bt0YPHgwR44cqY09CkdJSCPEGB4gUxUeIDj6ZohaBCjMNJ8oHTqcAkCrVm1p2eLo55PVBaOuPgcAi8XM7DfvJzXVVs87EgRBEBIWQA8//DD33Xcfl112GS6Xi/Hjx9O5c2feffddfv/999rYo3CU6Hv8xO4EXXUKTBuKWsMIULI8QO3anqx93bfP2Ud1r7ogLc3GpZeeAUBpaSVdurTh6advrOddCYIgCAkLoI4dO/Lpp58C4HK5SE9PB+D5559n7Nixyd2dkBTiMkGbglGiaKgRoMatW0VEj+LBHEiVHm0KrH27oAA6ve+xL4Auvvh00tNT+O23Qv4w8ikA7r7nUi68sHfE2lNPbUfjxll1vUVBEIQGScIC6PDhw2RmKj1d9uzZo5XC5+TkkJaWltzdCUkhxAStpcDCGiFWMQsM4Mj+A7jsDkwWM41atkh4DxabDZPPgPsoTNA2WwotdGmvXj37YTLVyMZWZ6jpr/feXcoXX/zKC/+aD8BrM8fTuHEWBoOByy/vx9Lv/8Gq1S+wdt2LdOtW847b0TCbTXTp0oYWLRphMkndgyAIAtTABP3dd98xdOhQ1q5dy3vvvcf06dMZPHgwQ4cO5csvv6yNPQpHib4RYiwTtPreH0MA+f1+in/fRctTTqZJ2zYU/747oT20atSS0/bnkHvuGH6eM4/S0sQnwrfN74jRaKSk5BAGg4Hs7Fy6dunBmrXLE75XMklLs+F0uvF6Q/1TGRmpXHRRHwDeeWcJAA8++DpDzu9B1675fDjvEZo2zeKUU1pr1zRvnsvX3zzJBUP/zsqVvx31vm677QLumzCCtm2bAYrH68CBI+zbd5iNG3fzw/cbWLp0PWvW7IjYfzjdu7dlyJAelJc7KC4u5eDBUoqLS/n99wNUVkp7A0EQji8SFkB33303KSkpADzxxBO43W7OOuss3n//fR5//PGkb1A4ekIaIVbjAYqVAgOlFL7lKSfTtG0+G5cUJLSH01p2xYCB/Gb5vDh9Dn99+Hb27tuV0D3U9Ndv2zdzuKSYIeddQt8+Z9erAOrYsQUrfv0ny5Zt5YKhfw8REZdddgapqTY2b96jiRmHw8X1102j4MdnOPvsrgAcPlzOv1/+jDff/JrXZ93HGWd04suvnmDYhRP55ZctANhsFsaMGchtt1/Itm37eOD+19i/vyTqnho3zuKeey7hrrsv1lJqlZVObDYzJpOJ5s1zad48l549OzB69LkAlJVVUlCwiaVL1vHdd+v4+efNOBwubDYLI0cOYNwdwxkwoGvU5/l8Pn77rZDVq3ewds1ONm3ag8ViIiMjhYyMVDIyUmjaNJsWLRvRqlVjWrZsROPGmRw5Uklxcan2qqx0YjQaMBqNGAwGTCYj6ek2MjJStT9NJiMulwe326P96XZ7dX968fl8GI1GTCZj4H4G/H5lnz6fH7/fj98vjVsFob6Z+95SZs/+ut6en7AAOnw4+C93v9/P008/ndQNCcknxAQdqxN0FY0QVYKVYIkZobMyc2ib3QqAssoy2rRuz4vT3+Hhv/+RjZvWxH2fdu06AbBjx2Y2b13PkPMu4fS+ZzNz1vSE9pNM7rrrYjIz0zjvvNOYMGEEzzzzgXZOTX+9G4j+qPz66zbuGPcy4+64iLfnfMsrr3xOebkdgKHn/41PP3uUs8/uyheLH+fGG56nT5+O/HHccJo2zQagf//ODB/eh3vHv8Jbb32j3bdFi0Y88MAVjP3jMNLTlX+kbN26l+ee/ZBZs77C5fLQpEkWLVrk0rJlI3r37shZA7py1lmdyc5O54ILenHBBb0AcDrdLF++lVNOaaWJKLfbwxdfrMTn89O4cSZNmmTRtGkWOTkZnHRSS046qSVXXnlW3N+7pk2ztc8kCELDY+2aHfX6/GPbQCEkBW0avLsKE7RRTYHFToPUtBni+UMuxWQ0UWn2MO1/z3DNuaPo1Kk7zz87m8en3s/3BfGlTtUI0I6dW1m2/HsATunUnays3Bql1I6WlBQrN940RHs/ecq1zJ//Mxs37iY7O51hwxSj8zthAghg5szFzJy5OOJ4WZmd4cMm8fH8v3Peeafx4bxHtHM7d+5nxqufM+KK/vTu3ZHZb97P1aPPZeoT73DDDYO5+Zah2GxKtd3y5Vv5x9Pv8/77P4S0Nti/v4T9+0tYtWo7CxYokTOj0Ui3bvmcc05Xzj6nGwMHdqdFi0acdVYXAH7//QCv/N9CZsz4gsLCyO9zkyZZnHpqO047rR2nntqWDh1bYLe7KC+3U17uoKLczqFD5ezZc5C9ew+xZ89BDh4sIysrlSZNsgJCKhubzYLf79eiND6fn4oKB+XlDsrL7VRUOPF6vVgsZiwWE1arBYvFhMVixmo1a18bjQa8XiXa4/X6tEiP0WjAYDBofwqCUL+sXr2jXp8vAqgBEFoGH70TtOYTqjIFVrMI0EXDRgJwMNVJSUkx4++/nkl/e55+Zw7i8Skv8+13C5k561/s/L3qBoHt2p0EwPYdWzh4cD+/bd9Eh/an0KdXP77+dkFCe0oGo0adTW5uBtu3F7Fx426GD+/DzNfv5ZG/fsVtt96B32dm3brfWLcusfYQFRUOLrl4CnPff4jhw/uwZMk6pv/zYz766Ee8Xh9PPTWXP//5SiZOuoZLLjmdSy45Xbt2yZJ1PPH4O3z++a9xP8/n87FmzQ7WrNnByy9/BiipvbPO6syBA6V8/vmvMftDARQXl/L116v5+uvVCX1OQRCE+kRKQhoAiZig40mB5bbIw5ISXzO/Tp2607FjZ7x+H4dSXbhdLhyOSh6ZeCcffPgGPp+PgecOY8b/zeehvzxNi7zWUe+TnpZB82YtAUUAAfyybCkAp/c9J669JJuxfxwGwCv/t5Cxt79ASUk5Z555CnfecQ8t8jqxZ3dORPorXux2J5dcPJmWLW5g4Ll/5YMPftD8RR6PlyeffI/evcbz448bAfj8818ZeO5fGXjuXxMSP7HYtm0fs2d/zcKFy6sUP4IgCMcrIoAaAAlNg4/RCBGg8kgpFSVKt+8m+dGFSjhq9Gef+xBeo1/rA+TzeXnh5Se49Y+X8d3SzzGZTFwwdARvzFzIRcNHRtynXSD9deBAIRUVZQBaGqxvnwFx7SWZnHZaO846qwtut4fXXlvMnj0HmXDfqwC0bq0IteKijKjpr3jx+/1RU04qGzbsYsBZf6FF3vUMu3AiS5asq/GzBEEQGhoJC6AZM2aQkZERcTwtLY0ZM2YkZVNCcglphBizCizQB8gXWwCBviN09T4gmy2FIYMvAWCvT/lFHt4HaMeOLUyafA9/vOsqflm+FLPZwi03jo/waLRrG0x/qaxeswyn00HTpnna+brij38cDsAHHxRo1Vivv/4ln376Cx6PIjjtdised+R/K8nE7/dTVFRSq88QBEE4EUlYAN14442kpqZGHE9NTeWGG25IyqaE5BKtEWJkJ+jqU2AQNEI3ya/eB3TuOReSkZ7J3n27OGJW+sTEmga/efNaHv7bOMorymjcuBmdO58Wcr59e6UCbPuOzdoxl8vJ6jW/AHUbBcrISOW66wcB8H//XRhy7o9jX8TtDn5vB557YZ3tK1EMBgNt8zty8fA/8JcHpvLcP17nDyNvJjs7N2nP6NSpO/fc9TduvnE8GRnS5VoQhGOHuE3QmZmZGAxK9URmZiYOh0M7ZzKZuOiii9i/f3+tbFI4OvQl7uGdoBs1asrhw8VxpcBAZ4RuV70AGn7hVQAsXPQB7W9R/DJVjcLweNz8/PN3DD7vYgb0H8KGDau0c/oKMD2/LFvK6X3P4fS+5zD3g1nV7ikZXHPNuWRmprFp0+4I4++REhf4g9Grc8++gJmz/lXtPY1GI5dcdDU7f9/KqtW/JH3PesxmC+Pv/jvnnnMhWVk5Ied69+rP7bdMYOn3i/l0wXus+LUg4X45FouVwYMu4vLLrqWLTshefuk1vPraND5bOLdKX1FqajoZGZmkpKRRWVlOaelh3FGG6BoMBmy2VGw2GzZrCjZbClabDZ/XR0VFGRUVZVTaK7T9WywWUlPSSUlJxWA04nTacTgcuFwOrXeQ1ZpCakoqtpRUDIDDYcfusON02qv8PijVZSaMRuVnr1aygT/iOiW6GaxIg/CKNGW92qtIvY9yTHoXCScW9fl3Om4BVFJSov3HuHnz5ojzfr+fSZMmJXVzQnIwmaKboHucdgb/fG4277w3g/1m5RdSvBGg6lJgLVu0oVfPM/H5fCz8/AP+dMflQOwIkMr3BV8qAuisIbz62jTtuJYC274lZP0vAR9Qj9NOx2q14XLVfkfiP45T0l/h0R9AExQulwuDQfEutc3vWG2F25/unsjll15DZWUF11w/pFbL+q8edSuXXHw1oPyC37hpNWvXraCk5BDnD7mMzqecynmDLuK8QRexafNa/jbpToqLiyLuYzKZufKK6zm5Y1fS0tJJTU0nPT2DFnmtQ74P3y1ZRMcOp9C+fSfuv+8xLr1kNK++Ng2j0UiH9qfQob1yrknjZmRkZEYdb2K3V3CktASvx0NqalrglV7tZ/X5fDgcdqxWK2azJeY6t9uFxWKt8l5OpwO/36/9QxAMgUaLJoxGsVMKQqK8Nec/vPra8/X2/LgF0HnnnYfBYOCrr77iqquu4tChQ9o5l8vFzp072bdvX61sUjg6jDE6Qbdvr0RVevfqz6K9Smfn6ip+4m2GOHyYEv1Ztvx7Dhwo1IahVjcN/qefv8PjcdOu7Um0atWWPXt2kp2dS6NGTQHY+XtoBGjHji0cOFBI06Z5XDz8D3z40ZtV3v9o6dv3ZHr37ojD4WLWrK8izmdlKemjwyXFbN++mX5nDuLccy5k9lsvx7znzTf+icsvvQaAtLR0Ro+6lf979dla2X/rVu244do7AXh++qN8uuA9vF6Pdv79D9+gY8fOXHLRKM4fchmndOrOv1+cyyN/H8fmLUGTddOmeUx85Hm6d4sc6gpQWLSH+Z+8zWcL51JScgiTyczll17DzTf+iU4nd+MfT1btF3S7XTgcdtLSMjCZTKSmplcpeFwuJ06nA6fLicloIj09E6vVitFoJC0tPWKt3+/HZkvRjoWLH7u9EoDU1OB8Q/16QRCOf+IWQN999x0A7du35/ffE+trItQvWgRI1wjRaDZhsyr/Q89v0wFzkZJ2qS4Fps4Ay2iUS2pWFvbS0qjrzh4wFICFi94HwGwLTIN3RaYy9FRUlLFy1c/07TOAAf2H8O7c12jXVhFqe/ftwuGwR1zz7tzXuOuOh7lz3F/ZsnU9a9etqPIZR8Ptt1+gPPPdpRw6VBZxXvXPHDlymG+XLAoIoAtiCqArR1zPDdfdBcDiL+dz/pBLueLy63jv/dc5fLg46fu//74pWK02fv5lCR9/Mifqmm3bNjL9hSm8/e4MnnzsP7Rv34np095i6tN/ZsnSLzjj9HN5+MF/kJ2dS3l5KW+/N4MjJYeotFdQWVlBaWkJGzetDhHTXq+HD+bN5suvP+HWm+5l0MDhHDy4n23bN7F9+2a2/baJwsLdlJWXUl5eitOppNgNBgPp6ZlkZeWQnZWDyWSmsrICu70Cu6MSh8OuRWbCsVisZKRnkpqWjsvpwG6vxO6wa0Z/g8GA1WrT0mgulxOHw64JJHWNzZZCSkoqNlvA+xiIhPvx4/f58Pp8eL1efD4vfvUzGwIjPTCAwaDks3T48SvfH/U+fu0y5c/AdcFoU+CYIJxAOF2O6hfVIgk3QuzSpQtt2rTh+++V1MOdd97J7bffzvr167nrrrsoKSlJeBN33nknf/7zn8nLy2PVqlXcc889/PJLbB/EyJEjeeyxx2jXrh1btmzhwQcfZMGCYCO8SZMmMXr0aNq0aYPL5WL58uU88sgj/Pzzzwnv7UQgJAIU+Ne+yWTS/kVrs6WQnZ4dWOOJfpMALrudI0UHyG7elCZtWrFrXXQB1KypMjF+89b1GM3BFEF1KTBQ0mB9+wxgwFmKAFIjVfoKMD1zP5hFt669GDRwOI/+fTp/vOsqDh5M3I9mNJpISUmhsrIi5poz+50CKNPdo6GmfkpLS/jhh6/wej2c1LGLFs3Sc/7gS7nnrr8B8Nrr05n91su0bNmGrl16Mmb0WF7699SEP0NVDL/wKnr2OBOHw87z/3q02vVFRXu4+97RTHzkn5x5xrlMmfQi3xd8xYD+gwHYtHktkx8bz77C+AfjHjlymGnTJzFtenzpcr/fT3lAFO3dm9g/vNxuF4dLDnK45GDMezudDk1sxVrjcNijCm9BEI5vEk5cP/PMM2RlKdUc3bt3Z9q0aXz22We0b9+eadOmVXN1JKNGjWLatGlMnjyZ3r17s2rVKhYtWkTTpk2jru/fvz9z5sxhxowZ9OrVi3nz5jFv3jy6deumrdm8eTN33303p556KmeffTY7duzg888/p0mTJgnv70TAZI5eBm+1BpsZNs5QIhdVdYJWKT2o/ELJaBS9Wig1NV1LOxw8eACL7jnuKkzQKj/8oKSWunXtRXZ2rhYB2rEj0num8vSzD7N9+2YaN27Go3+fXqXfIxb3/WkSH773Iyd17BJzzUknKT1+Nm6M/ks/WyeASstKWLHyR0AxQ+sZcNYQHvzzk4CSdlIjRK+9rsw1u+ySa2jSpHm1e/7DVTfxxsyFtA/MSYtFbk5jxo39CwAzZ/2LwjhFS2VlBQ//fRwfzJut7Dsgfj786E3uuXd0QuJHEAThWCJhAdS+fXvWr18PwFVXXcX8+fN55JFHuOuuuxg+fHjCG5gwYQKvvPIKr7/+Ohs2bGDcuHFUVlZyyy23RF0/fvx4Fi5cyLPPPsvGjRuZOHEiK1as4O6779bWzJkzhy+//JLt27ezfv16JkyYQHZ2NqeddlrUe57o6CNAehO03tOQm5oDVD0LTKXiUAkAGY1yop5vHPDrVFZW4HBUaukvAG8cEaD9B/axecs6TCYT/fudF6wA27E15jUORyV/n3w35eWldO/Wm7vveLja5+hJTU3ngqEjsFqtXHD+5VHXtGjRiLQ0Gx6Pl507o0eYVA/QkYCJ+bvvFgFKSwBQUio3XHcXUya9iNls4YvFH4dEepav+IFVq3/GarVy3Zg7qtzzZZdcw53jHqJN6/aMuPzaKtfedefDZGXlsHnLuoSr5Xw+Ly+89DjPT380EPW5l3+9+FjUyixBEITjhYQFkMvlIi1NMQaef/75fP755wAcOnRIiwzFi8VioU+fPixeHBwK6ff7Wbx4Mf379496Tf/+/UPWAyxatCjmeovFwtixYykpKWHVqlVR11itVjIzM0NeJxL6Ene9ByhFJ4AapeUoa+KIAJUfVn65p+dGjwA1bqwIoIOHFJFgCRigPW533CWP3/+gDEgd0H+IJoC2VxEBAtizZydPPPkAPp+Pyy8bw1VX3BjXswD6nXGuFhE7KxDlCOekk5S03s6d+/HE8ErpI0AAS39YjNfrpfMpp9Kxwyk89uhL3HzjnzAajXz08f94+tmHIr4nahTo4uEjyYsxGmTQucMZf89E7f2A/oNjDvg84/RzGXLeJXi9Xp57/u/VNruMxcefzGHcXVfxzXd1P3dNEAQh2SQsgJYuXcq0adP429/+xhlnnMGnn34KQKdOndi9O7FweJMmTTCbzRQVhZbYFhUVkZeXF/WavLy8uNZffPHFlJWV4XA4uO+++xg6dCgHD0b3Ajz00EOUlpZqrz179iT0OY51TDE6QVt1AignRfEAxZMCqzhcAkBGbk7U82rF1qFDB5TnqwIojvSXijohvt+ZA8nMzMbr9fD7ru3VXvfjz98ya/aLANx958M894/XadWqbbXXqREagFat2tI2v2PEmo4dlb9jW7fGrnbUm6ABSkoOsXrNMgBe+te7DDhrCC6Xk6effYh/vjA5pAJLZfWaZVpXbLViS0+f3mfx8F//gdFo5JNP36G8vJTGjZvRtUvPqHu6/lolkvT+h7NCKrkEQRAaMgkLoLvvvhuPx8PIkSO544472Lt3LwDDhw9n4cLIvij1xddff03Pnj0566yzWLhwIe+++25MX9GTTz5JVlaW9mrVqlUd77Z2MVoiZ4GZTGZsOm9Oti0T/NVXgQGUB1Jg6dWkwIoDRmSLLb4SeD3btm2ksHC35uXZs+d33O74BNTst17mv688g8Nhp3ev/rz2f/O5bswdMX1BVquNM884F0DzxkSLAqn+n21VCKCssAgQwHdLlTSYzZZC0f693HPfGBYu+qDKzzAzEAW6YOjl3H/vFK664gZ69+pPn95n8dijL2KxWPnm2wU8/69H+fGnb4Fg5Z2eNq3b071bb7xeD++891qVzxQEQWhIJCyAdu3axaWXXkrPnj157bXg/1AnTJjA+PHjE7pXcXExHo+H5s1DzZ7NmzensLAw6jWFhYVxra+srGTbtm389NNP3HbbbXg8Hm699dao93S5XJSVlYW8TiRCIkD6MnhdBMhsNGHzGvHHkR6pUFNgOTlRzzdu1AyAQweVCJDaAyieCjA9PxQE++xUl/7S4/f7efvdV7nl9kv4ZdkSrFYbt958L/99+X1ychpFrD+979mkpqZzoHgfW7Z9A0QXQB0DKbCqIkCaACor0Y599fVn7Nmzk4Ifv+aPd17J5s1rq/0MGzau5tvvFmIymbnk4qu5+85HeO4fr/Ps0zNJTU1n2fLvmfr0n/H5fCxZqqShzzk7UgBdeMEVAPz8yxItIicIgiDUcBp8hw4deOyxx/jf//6nRVWGDRtG165dE7qP2+1m+fLlDBkyRDtmMBgYMmQIBQUFUa8pKCgIWQ8wdOjQmOtVjEYjNputyjUnKrFM0FZraGO3FI8prhRYeXUpMM0DpPzCVSNAiaTAIJgGg9gl8FWxr3A3f3noNh6fej+HDx+kQ/tTuPH6uyPWqemv7JwS/vzgWQB07dIzQiydpAmgvTGfmZ0VmgIDKC09zHU3XcDDfx8Xcrw6Hpt6P1Mev5fZb/2bJUu/YNfu7Xi9XtauW8HEyfdoJuSfly3B6XTQqmU+Hdqfol1vNBq5YOgIgGojToIgCA2NhAXQueeey5o1azjzzDO58sortcnwPXr0YPLkyQlvYNq0adx+++3ccMMNdO7cmX//+9+kp6czc+ZMAGbNmsXUqcEqmenTpzNs2DAmTJjAKaecwqRJk+jbty8vvqj4PtLS0njiiSc488wzyc/Pp3fv3syYMYNWrVrx3nvvJby/E4GQRogefRWYIggrKsoBRQDFkwKrOHwEiJ0Ca9JYiQCpAsisM0EnwqrVyygrU54VPgMsEb78+hMmP34vAJdcNIoWOmOx2WzhrH7nAZDTqARbioey8r0YjUb6nTko5D4nJRABOqJLgdUUr9fD198u4LXX/8nEyXdzw83DuPDi07jn3muw24O9ihwOO8sCI0HOHnC+drxP7wE0bdKcI0cO88OPXx/1fgRBEE4kEhZATz31FH/729+44IILcOlSGl999RX9+vVLeAPvvvsuDzzwAFOmTGHlypX07NmTYcOGaYNV8/PzadGihba+oKCAMWPGMHbsWFatWsXIkSMZMWIE69Yp5k6v10vnzp15//332bx5M/Pnz6dx48acc845Wvl+QyNaI0R9GfyWrcr3LsVjSqgKLCNGFVjQBK38DOMdgxGO1+vhpf88ydfffMaPP30DgMVi5oknrmfAgMSijatW/8wvy5ZgNlu46cY/acd79+pPRkYWBw/uJydX2Z/Fqgi3s/oF02BNmmSRnZ2Oz+dj+/bIuVhAoFuw8j0tTYIAikY00zSgpcH0/YaGX3glAIu/mo/HIyXrgiAIehLuBH3qqacyZsyYiOP79++vcaPBl156iZdeeinqufPOOy/i2Ny5c5k7d27U9U6nk6uuuqpG+zhRCU6DD3qATOZgCmzT5rX07HEmqR4Tvnj6AAVSYCkZ6ZgsFrxhkR3VBH1Q9QDVMAUGsOjzD1n0+Yfa+yFDevDQw6MYcHZXBg18KKF7vfra85ze9xzOH3wpb7/zKtt3bObccxTBsPT7xZw1UKn8at/Rx75d0LfPAG3Aqhr92bWrGKczupjIyswBFE+ZPkJTF/zw49d4vR46duxMi7zWlFeUMeAsJRok6S9BEIRIEo4AlZSUhERkVHr16nXClY+fKARN0F68UVJgaml0iscUnGVUBfbSMrxuJRIR3gzRarWRmamU1IdXgSVqgo5GdrbSgyonp/pJ4OFs3rKOb75biNFo5JabxmM0mjg7IBK+W7qIzExl1tPJndIpLi4kNTWN3j2VqKZaAZaoAbquKCs7wqrVyviYs88eypDzLsZqtbJ12wa2bttQ5/sRBEE41klYAL399ts8/fTTNG/eHL/fj9Fo5KyzzuLZZ5/ljTfeqI09CkeJlgLTV4GZgsNQd+zYitfvxYiB3Mzoaa1wKgIz38LTYGr6y+l0UFGhVNOZLfENQo2HlBTlXqmpsQ3tJpORv/zlKs44I3I8xGuvT8fr9XL2gPMZPepWsrNzOXLkMKvXLCc9Xfl+GAzw2/ZfAegfqAZTI0BVlcCH9wCqa5Z8/wUA5wwYyrALlSioRH8EQRCik7AAevjhh9m4cSO7du0iIyOD9evX89133/HDDz/w+OOP18YehaNEHwEKLYNXRITdXkG5TxkImdc4MroXDbUSLD2sEkxLf+lKrs016AMUC5tN6eWTlhZbAJ17bneeevom/vXCHyPO7dr1m5ZSu/3W+wGl63Rqamg22O1R+gH173ceBoNBK4Hfti2xHkB1ydLvlQ7pp3bvwymduuN2u/jiy/n1shdBEIRjnYQFkNvtZuzYsXTs2JFLLrmE6667js6dO3PDDTfgiyN9ItQ9QRO0rgrMGPQAOV3OoABqEp8AUueBRQigQAXYoSgCKBkpsJSU6gVQo0ZKZaLauTmcWbNfDDHw69NfKnkt3VRWVtC0SXNOPrlbXBVgagSotLR+IkDFxUVs2BAc91Lw49f1thdBEIRjnRr1AQKlIeKCBQt477332Lq15iXKQu0TMg0+EAEym8xaZMjpdFCBEp1p2TS+LtjBFFhOyPGgATo4LFSdBl8TE3Q4wRSYNeYaVRw1bpylpbX07D+wj48/mQNAeUUZK34tICMjVACd1qMtvyxbAihztjp2jKMEPmCCTkYJfE1R02AACyT9JQiCEJMaCaBbbrmFNWvW4HA4cDgcrFmzJmaXZaH+idYI0WwMpnxcLgcVKOKkZbPowzfD0VJgYSboxo2jpMCsStQm0T5A0VAjQCkpVozG6H999dGh/Pzo409mv/kyS5Z+wf+98gxut1uLAKlDTrt3b6uV3vfvN4gmTZRBv1WlwIKDUOsv6vLtdwtxuVwUFu7ml2VL620fgiAIxzoJl8FPnjyZCRMm8MILL2jdl/v378/zzz9Pfn4+kyZNSvomhaPDFDINXqneMquiyOfD7XZTaVAEUItmrTAajdWmMysORe8F1ChKBCiZHiA1AgRKFKiiwhGxJlwAbdiwK2JNaVkJEycHu0JnZCiRoq1b99GmTRPS01NwupTP0KZ1e/z+3ezbd5DKytifob5N0AB79+3ij3ddSXl5acyeQYIgCEINBNAdd9zB7bffzttvv60dmz9/PqtXr+aFF14QAXQMYow2Dd5vAJT0F4DT7MWHH6vVRl7zVuzdFyka9MQ2QYd2gQZdJ+gkpsAgfgEUD2oE6MiRCkpKyunXrzMtW9kCz0zD4zZWmf6C+jdBq+yowdgQQRCEhkbCKTCLxcKyZcsiji9fvlyLKgjHFqGdoAMCKHDO5VIiGkaTCYdZOde27UnV3jPWPLBoJmhLoNrMnUQTNMQ2QtdMACn9hcrK7KxetQOA7t3bcOCAMmTXbrdWWQIPwTlg9S2ABEEQhOpJWADNnj2bO+64I+L42LFjeeutt5KyKSG5RDNBG8IiQHoB1C4OAaSlwBqFpsDCu0BDMALkTYIAsukiQHEJoLbN4rqvmgIrL3ewatV2AE49rZ0WCXPYLXFHgI5I5ZUgCMIxT1whm+eee0772u/3c9ttt3HBBRfw448/AmiDR6UR4rFJsBGirhO0KoBcQQFkNwUEULuTq72nlgLLydaOmc0WbYL6wUM6D1DABO1OSgosGAGK1QzxaFJgZWV2TQD16NGeJd/sosdpp2OPSwAFPEASARIEQTjmiUsA9erVK+T98uXLAejYUZmdVFxcTHFxMd26dUvy9oSjxWAwaNVS+giQ0a+cdzkjU2Dt8jtWe191HlhqdhYGoxG/z0dubmMAPB53SBoomaMwUuKIAKXWQACpEaCKcjurV+8AoFWrxpSUrAaUCFBVFWAWi4W0NGU8R32aoAVBEIT4iEsADR48uPpFwjGJaoAGxQOkzvqKFgFSBVB+fkcMBgN+vz/mfSuPlCrXGY2k52RTfuhwSBdo/bXmQB+g5ESAEkuBtW7dOK6qNr0HqLzczrZt++jYsQXZOcrnsNstbNtWGPN6Nfrj9Xq0ESCCIAjCsUuNGyEKxwcmS1DjqtEfr9ujqwILRIDMJpwmHy6Xk5SUVDp0OKXK+/q8XipKjgDBSjC1AuyQzv8DwTL4ZHiAQlNg0Zsh6gWQxWKmRYvq55vpU2CAlgbr2Uv5TJXlJo4ciT3hXW2CWFp6pNpnCYIgCPWPCKATHH0ESJ3g7vN6MQQCNFoEyGgEA/y6+icA7vvToxiNJqqiIqwSTK0A05fAg84DVFcpsDBvUDxpsHSdCRpgdUAADR6iGMLdbitmsyX6xeh6AIkBWhAE4bhABNAJjskcJQLk9WBEiQC5nA7FJxQQSv+e8QzlFWV069qL0aOq7u5dHqgESw9UgkXrAg3JHoWRWAQI4hNAkRGgHQA0bZqC0egDDOQ1jz0m5FjpASQIgiDEhwigExxV2Pi8Xs2X4/N6Q1JgBlPwr8H+/ft48aXHAbjphnvoWEUqLLwXkNoF+lB4BEjtBF1HESD1+K5dyj7iEUDBMvjQFJjBAKmpygiPFi3axLz+WOgCLQiCIMSPCKATHJOuCaKKz+PVqsCcTjtGkznk3KIv5rH0+8VYLFYe+ss/sFiip34iUmBRxmCArhN0HQugTZv2ANA2jl5AehM0wI4dRZrnJyVNEUAtqxBAWgSorKTaZwmCIAj1T40E0HXXXcfSpUvZs2cP+fn5AIwfP57LLrssqZsTak56egr3338FHTrmAUoJvEpIBMjlDBkqqg5Lfe6ff+fw4YN07NiZG6+/J+ozyg8HUmDVCqDAMNQ6S4Epxzdt3A1AmxqkwACtHD5FiwDFHhSbrZmgS6p9liAIglD/JCyAxo0bx7Rp0/jss8/IycnRBm2WlJRw7733Jnt/Qg0ZOXIAzzx7C3++71IAbQYYqCboYCdoozlodvYHBFBJySGmTZ8IwOhRt9Gta2gvKICKw6FVYI1imKDVURh1HQFSh6AmlgILzhZTjdCSAhMEQTjxSFgA3XPPPdx+++1MnTpVixYALFu2jFNPPTWpmxNqTqNGGSF/6lNg3pAUmEMTseHrln6/mM+/mIfJZOJPd/0t4hkVh4MT4Y1GI7k5SiPEyCqwZE6Dj38W2MZABCgxE3Sldkz1AXm8Ss+jVi3yY14vJmhBEITji4QFUPv27fn1118jjjudTtLT05OyKeHosQbSTmqaKFYKzOVyBo3SPl9E88OX/vMUdnsFnTp1p98ZA0POlR8qASC9UQ45OY0xmUx4vV5KSg6GrDNrnaDdR/259CXu0UZhWK1mTdCpHqDc3AxN4MQiWgTo66/X4HZ7WLt2PVBNBChLyuAFQRCOJxIWQNu3b6dnz54Rx4cNG8aGDRuSsSchCVitirFZTRmFmKC9Xu0H73Q6MOgqxcIpLT3MRx/PAeD66+4MOac3Qav+n5KSgyFdl41mk+YxOtoUmPqZVFKjRID0UaGiohIOHVK6MlcVBUpNtWmiSe8B2rZtH/ltbubqqyfh8/lIS0vXUl3hSARIEATh+CJhATRt2jReeuklRo0ahcFg4IwzzuDhhx/mySef5B//+Edt7FGoATZbIAIUSBmFR4AMulEY6i9/vzf6uIh3576Gw2Gna5ee9O0zQDuumaBzckLGYOhRewDB0Y/C0Pt/IHoKTD3mdnvweLzs3KkYsqsSQGp0yOfzUVkZmqYrKiqhsrKS4uIiIHYlWHASfEn1H0QQBEGodxIWQDNmzODBBx/k8ccfJy0tjf/973/ccccdjB8/nnfeeac29ijUgIgIkCe8DF5thBhMgXm9HqJxuOQg8z95G4Abr79bO66mwEwWM3mtFGEQUQFmC4qWox2FES6AolWBqQJIFTK//159LyBtEGqFI+b8s32FiqE6WhrMaDSRmZkNiAlaEATheKFGZfD/+9//6NSpExkZGeTl5dGmTRtee+21ZO9NOArUCFBKlAiQ1+sJmqBdwSqwaCkwlbffm4HL5aR7t9706tlPuY/bjaNc6ZXTvKVSIh4ZAQr4f9zuKoerxoPeAA1VR4BUAbQrIICq6gUUrQQ+nL37YgugrCxF/Ph8PsrLZRaYIAjC8cBRNUK02+0cOHCg+oVCnaNFgAJCKMIDpOsErXp09FGicA4dOsAnnyoRvht0XqCKkhIAmjVrqa3TY1IFUJInwUN0AaQao8MjQFX1AsrIUASQ3gAdzr59SkVZtEow1QBdVn6k2qnzgiAIwrFBwgKoWbNmvPHGG+zZswe3243H4wl5CccGVi0CpAghb1gn6Gh9gKr75T3n3VdxuVz07HEmp53aFwimwbRBqAfDewDVTgk8xJcC27mz+hRYXBGgvb8D0ZshigFaEATh+MNc/ZJQXn/9dfLz83nsscfYt2/fUac1hNpBjQCpqTCfO7wMXvna5XKEzAuriuLiIhYsep/LL72G66+9kz//9RatEizYA6huxmBAfCmweDxAcQmgKjxAIoAEQRCOPxIWQGeffTbnnHMOq1atqo39CElCFT5mkxEj/ihl8LoUWHpgXlgVKTCVOW//HxcPH0nfPgO47JJrtEqw7AzFBxOeArMksQdQIgLIblcElyqAWrVqjMlkxBul0i1aD6Bw9gU8QE2b5GGxWHC7g59HukALgiAcfyScAtu1axcGg6E29iIkEX3PHJPRH2aC1s8Cc2AMTIOvLgIEULR/L7Pf+jcA941/lLapeeCHjFSl43RxLQ5CVUVdaanSrTmeFFhh4WFcLjdms4mWLRtHvW+0LtDhlJQcwm6vwGg00rxZq5BzWQEPkAxCFQRBOH5IWADde++9PPXUU7Rt27Y29iMkCVUsAJgNVU2Djz8FpvLGmy/x/odvAHDhqefTxG7DZFTucfhwWBfoWhiDoTY3jCcF5vf72b1b2VOsNJhqgq6oIgIEsDdghG7ZMtQIrQ5ClQiQIAjC8UNcKbBDhw6FeH3S09PZtm0blZWVIakAgMaNo/8rW6hb9BEgc1gEyO/1YSCyD1C8AgjgxZefwGZL4ZKLRpFfqoxAKSk5hMcT+vdBG4ORxCqwQ4fKadeuOSaTCavVjMsV/GzhAghg5879dOiQR35+U77/PvK+8XiAQDFCd+xwCi3DjNBqCkw8QIIgCMcPcQkgmfJ+/BEaAfKH+HsMOt+6w2nHFEcfoGg8P30Szdq04YxT+wORPYBA5wFyJ8MDpHymw4fLtWOpqbaoAsiuE0C/a72AokeA4hVAsZohiglaEATh+CMuAfTGG2/U9j6EJBMaAQotgzf6ggrI5XJiMKqdoBMTQD6fj//Meo5OL/yPHKeVPXt3RqwxW5IfASors+PxeDGbTaSl2ThypEJbEy0CtKuaSrB0zQRdjQBSmyHmhQogzQQtg1AFQRCOGxL2AHk8Hpo2jfxF0qhRI+kDdAwRGQEK/mzUHkDuQLrKWM0ssKo4cvAg23PK2Zp6mJdenhpx3pzUPkDKvex2J3a7cr9wH1A0AVRdM8S4U2CqByg8AhTwAEkESBAE4fghYQEUqwLMZrPhSkKlj5Acwj1A+vSWaoD2BGZ/1TQFBlBxqAS/AUqz/ZSUR0ZANA9QUvoAKaLO4XBrAie8Eiy6B6jqCJAqgKoqg4dgBKhly+gpMDFBC4IgHD/E3QfonnvuAZSqmttuu43y8qAPw2Qyce6557Jx48bk71CoESERIGPoLDC1BN4dEEDVDUOtCmdlJW6nE4vNRnpuDi57Ych5dRp8MvsAOR0uKisVQRUeAUoJCKJoEaBY88DUKrDqIkCFRbvx+XykpqaTk9OIkpJDGAyG4CBUiQAJgiAcN8QtgO677z5AiQCNGzcuxC/icrnYsWMH48aNS/4OhRoREgEKM0GrTRA9voAAimMWWFVUHC4hJ685Gbm5HN4bKoDMVkWIJTsClEgKbNcuRQBlZaWRnZ0e4hmC+FNgbrebA8WFNG/WkgH9h7D4q/lYrTZMAQFZViaDUAVBEI4X4hZAHTp0AOCrr77iyiuvpCQwBFM4NgmNAPlDTdCBzKeaAlNngflrOMiz/JAigNIb5UScqw0PkMPhSigFVlnppLi4lCZNssjPb8qaNaECKCNOEzTArl3bad6sJQ9MeJw/3T2Rbb8pUc/yirKIFgCCIAjCsUvCHqDBgweL+DkOiIwA6VJggQiQ16eIIqMpcmBqIlQExmFk5OZGnDPXwjR4vQCKFQFSR2GoVDUTLN4IEMBL/57Kws8/YP/+fVitVrp0Pg2AkpKD1VwpCIIgHEskPAtMOD6I8ADpxI1JjQBpAihggq5pCqxESf2k52RHnLPYFEHiTnoKTLlfamr1KTCAvXsP0bt3R1q0iBRp8ZqgAXbs3MrTzzwEQOtW7ejT+yy6dD6NJd9/keCnEQRBEOoTEUAnKFZrWBm8bhq8KoC8ftUEHf8ssGiUHyoBICNaCiywD28yZoGpJminu9oIULgAKipUolR5eaECyGIxa9+reCJAenbv2cHuPTv4aP7/ErpOEARBqH8SToEJxz769BdE8QAZ1AiQ4vmpySgMPepE+PQqUmDupKTA1AhQ9SmwcAG0b98hIFIAqdEfiM8DJAiCIJwYxCWA3n//fTIzMwG4/vrrsVojp3ALxw766A8EhqHqPEBmgxoBCkuB1dgDVAJARm5OxDlLUvsAqR4gNw4tBVa9CRqUqfAAeWEpMNUAbbc78dagEaQgCIJwfBKXALrkkktIT1cGXs6cOZPs7Eivh3DsoPf/AJhiRIC8/kAE6CgaIULQA5SalRlxzhzoA1TfEaDCwhIgdgQo0fSXIAiCcHwTlwdo48aNPPnkk3z99dcYDAZGjRpFaWlp1LWzZ89O6gaFxIlIgYX1ATIblfM+AgLIeHQCyFGmNMWMLoCS5wHSR4BiCaD0dCWik2gKLB4DtCAIgnDiEJcAGjduHNOmTePiiy/G7/fz+OOP4/f7I9b5/X4RQMcA4REgszE8BRbo/OwP9wDVLAVkLysDYgggtQ9QUgWQS2uEqE+BqechdgosvAos3i7QgiAIwolFXAKooKCA/v37A0o5dadOnThw4ECtbkyoOdEiQCFl8Or0d5KTAqssDQigzIyIc9oojFpKgaXqIkD6aJAqkFSKikqU9ak2srLSKC2tBCQFJgiC0FBJuAqsffv2In6OcSIjQKGNEM1qxCcggExHaYK2lyopMFtamiamtGfVSgQoegpMjQY5ne4IQ3NlpVMTPfo0WCJdoAVBEIQTh4T7AP3+++9kZ2dz66230qVLFwDWr1/PjBkzYvqChLqlujJ41QPkRUljGgJ9gPQDUxPBWREcLZGamalVhUFtzQJzRW2EGMsArbJv3yGystLIy8tl8+Y9gESABEEQGioJR4D69OnDtm3buO+++2jUqBGNGjXivvvuY9u2bfTq1as29igkSGQKjJBGiKoA8gcEkBoBincW2LXXDuI//7krOETV68VRroig8DRY7YzC0EeAgr6f6gSQWgmm9wFlZqYBYoIWBEFoaCQsgJ5//nk+/vhj2rVrx1VXXcVVV11F+/bt+eSTT/jnP/9ZC1sUEiVaCiwkAhSY/eUzKAJInQUW7yiMxx6/jrF/HEbfvidpxzQjdGaoEVodhZHcPkDRy+CDc8BiCaDIbtBaCkwiQIIgCA2KhAVQ3759efrpp0N+oXq9Xv7xj3/Qt2/fpG5OqBlRy+CjCiDlvVoFFu8w1MaNFZGTlZWmHbOrRuis6BGg5EyDP7oUWLRxGJICEwRBaJgkLIBKS0vJz8+PON6mTRvKAlEAoX5RI0DuQNrLbAz191jMyvlgBCj+WWAmk1FLG6nREwC71gsoK2R90APkTvyD6LBYzFrKLZYJunoPkCKAmosJWhAEocGTsAB65513mDFjBqNGjaJ169a0bt2aq6++mldffZU5c+bUxh6FBFEjQEeOKFVPEY0QY0SA/HEIoOzsdO1rtYcO6FNgwQiQ0WzS7n20KTA1+gPVp8Bie4AiewFlBMScRIAEQRAaFglXgT3wwAP4/X7eeOMNzGblcrfbzb///W/++te/Jn2DQuKoEaCSknKaNMlSPEBRIkAYFQWUSAosJycogNLTdX13AqXwegGk9gCCox+FoW9y6HS6dSmwaCbo6M+K5gGSFJggCELDJGEB5Ha7uffee3nooYfo2LEjANu2bcNul18gxwqREaDQ9JYqgPxqBCiBRoh6ARQSAQp4gFJ0Jmi1BxAc/SgMVdQ5HMp9apYCU8dh5GjHgikwqQITBEFoSCScAlOx2+2sXbuWtWvXHrX4ufPOO9m+fTt2u50ff/yR008/vcr1I0eOZMOGDdjtdlavXs3w4cO1c2azmaeeeorVq1dTXl7Onj17mDVrFi1atDiqPR5PBCNASmm6wQAmQ3B0icWsCBNf4KevzQKLowosNAWm9wApAihNNw5D8/+43VFHpySC3gANQZGTkmLVvEHxlsE3bZqNKeB7kgiQIAhCwyThCFCyGTVqFNOmTWPcuHH89NNP3HvvvSxatIhTTjklasfp/v37M2fOHB566CE++eQTxowZw7x58+jduzfr1q0jLS2N3r1789hjj7Fq1Spyc3OZPn06H3/8cbXC6lggt2UeV/39L5jNFipLS3GUlVNZWsaudRtYtejLuO5hDQiPI0eCDQot5qDWtaoRIFMgBaZGgOLoAxQzAlQWmQIzJ3UMRrAHEISWuqekWKisdAbL4GMIoOLiUrxeLyaTiWbNcti375CYoAVBEBoo9S6AJkyYwCuvvMLrr78OKINXL774Ym655RaefvrpiPXjx49n4cKFPPvsswBMnDiRoUOHcvfdd3PHHXdQWlrKBRdcEHLN3XffzS+//EKbNm3YtWtXrX+mo6HHBUPocnb/qOee3ryV/dt3VnsPm035sZaXO/D5/RgNBqwBAWQwGLBYAqmpMA9QoikwvQfIEYgApegiQBZbMkvggz2AAM0DBErkRy+AYkWAfD4f+/cfoUWLRuTl5bJv3yGJAAmCIDRQapwCSwYWi4U+ffqwePFi7Zjf72fx4sXa8NVw+vfvH7IeYNGiRTHXA2RnZ+Pz+SgpKYl63mq1kpmZGfKqL2zpSlXS5oKfef/xZ/jsX/+hcNt2AE4Z0C+ue6gRIJfTjTugaSxmQ+BcULRgChNAcaTAQgSQLgIUbSCq1gU6qWMwlAiQ3+/XxJAqfFRDdCwBBMFSeNUHlClVYIIgCA2ShAVQWlpa9YvipEmTJpjNZoqKikKOFxUVkZeXF/WavLy8hNbbbDaefvpp5syZE7NP0UMPPURpaan22rNnTw0+TXKwpigpmT0bNvPDOx/w5Suz+OXDTwDo1D++FJ7qAXK5PHgCWS2bRRE7NmvQt+M3qwJI7QNU/SywnJygwInWByhN1wdIjQAdbQ8giIwAQVDoqM0Qq4sAgb4UvhFGo1G7RkzQgiAIDYuEBVBRUREzZsxgwIABtbGfpGI2m3n33XcxGAzccccdMdc9+eSTZGVlaa9WrVrV4S5DsaYqosKlM5ZvKvgZgI59e2EyV5+1VKvAnE43nkCzH0vA52MNjKbw4dciP1oEKGEPkE4AaVVgtR0BihRAWgSomlEYENoNWr//srLKo96jIAiCcPyQsAC67rrraNSoEV999RWbNm3iwQcfrHGFVXFxMR6Ph+bNm4ccb968OYWFhVGvKSwsjGu9Kn7atm3L0KFDq+xS7XK5KCsrC3nVF9ZUJa3ksgcjEoVbtlF28BC2tDTa9jy12nuERIACxVc2i/KjTrEp9/cbggLIlEAKLDvEAxQUEI6oJuiqPUD9+p3C+PGXVftMiDRBAxG9gOKJAOlTYKoAcrs9uFzVR78EQRCEE4eEBdBHH33EFVdcQatWrfjPf/7DmDFj2LlzJ/Pnz+eKK67QfpnGg9vtZvny5QwZMkQ7ZjAYGDJkCAUFBVGvKSgoCFkPMHTo0JD1qvg5+eSTOf/88zl06FCCn7L+sKQov8RdjqAA8vv9bPnxFyC+NFj0CJDyo7apESBDMPJjqKEJWh9BqSwtVZ5js2nCR+0DFKsK7MWX7uD5f97OeeedVu1zq0qBqcInkRRYXotG4v8RBEFowNTYBF1cXMzzzz9Pjx49mDBhAueffz5z585l7969TJ48mdTU1OpvAkybNo3bb7+dG264gc6dO/Pvf/+b9PR0Zs6cCcCsWbOYOnWqtn769OkMGzaMCRMmcMoppzBp0iT69u3Liy++CCjiZ+7cufTt25drr70Wk8lE8+bNad68ORaLJeoejiWsaZERIIDNqgDqd0a19wiNAAW8PxY1BaaIFp/Br6XTatoJWl8G76q0awIqNVAJpnmA3NE9QOpQ1R492lf73HATNBylAMrLlQowQRCEBkyNy+CbNWvGjTfeyE033UTbtm2ZO3cuM2bMoHXr1jz44IP069ePCy+8sNr7vPvuuzRt2pQpU6aQl5fHypUrGTZsGPv37wcgPz8/xJtSUFDAmDFjePzxx5k6dSpbtmxhxIgRrFu3DoBWrVpx+eWXA7Bq1aqQZw0aNIhvv/22ph+5TojmAQKlKgygTbfOpGZlap4blVtfepambfN5buT1WHQRIK8qgGyKyFFN0L4oKbB4ZoHFKoP3+/04yitIy84iNTODsuKDmC1VR4DUFFr37pHDdcNRI0BOpz4Fppqg40+BBQVQjnSBFgRBaMAkLICuuOIKbr75Zi688ELWr1/Pyy+/zJtvvsmRI0e0NT/88AMbNmyI+54vvfQSL730UtRz5513XsSxuXPnMnfu3Kjrd+7cicFgiPvZxxpqFZg+BQZwpOgARb/toHmHdpx0em/WfBkUcl3OHUDXcxVTerN2bcMiQEbAizUQAdJSYBBpgo5LAOmrwEKjfPayMkUABSJA5mr6AKkCqmu3eARQNBN0aBl8Yh4gfQRIDNCCIAgNjYRTYDNnzmTv3r0MGDCAXr168dJLL4WIH4C9e/fyxBNPJG2TDYloJmgVNQrUqX9oGmzo2Ju0r20Z6ZoHyOX2aBGglMAxNQLkN/i1DtCGQBl84sNQU7QxFBDZC0jzAEWpAjMajVr5ere4BFAgApSkFFhGRiotWjQCJAIkCILQEEk4AtSiRYtqZ385HA6mTJlS4001ZLQUWGXk93hzwS+cc+2oEAF08pl9aduju/Y+JT1diwC53b6gBygggIIeIHQpMOVcdVVgJpORrKzQPlBpaTZtjIRDmwgf8ACpozCi9AHSDzHNzEwjP78pv/8eOfpE+1xRTNA1SYFVVDgoL7eTkZHKySe3BMQDJAiC0BBJOAJUVlZG06ZNI443atQIj0dKiY8WNQXmdkRGJbb9sgKv20OT/NY0aqW0HjhfF/0BpZO0GgFye7zBRog2NQKkVoH5MRqNGAwGLRLkr6YPULj4gVAfkDoQVUuBqcNQo0SA9AIIqo8CRUuB2WsQAYJgGuykk5XvoQggQRCEhkfCAiiWv8Zms+FKQsO7hk5VKTBnZSU7V68FlDRY+16ncdIZffC43fy+Zj0QFgHyBiNAKaoA0lWBgRIFircKTE1/VVQ4KC1VfDPRB6JW7wHSCyeA7t3bVvnsaH2A9Ckwg8GgpdSqE0BqGkyNAFVICkwQBKHBEXcK7J577gGUap/bbruN8vJy7ZzJZOLcc89l48aNyd9hA8JgNAb7AMVIM27+8Rc69OlJp/5n0H3IQAB++ehTzBYr+ad2JSUjGAHyeHx4A32AVAGhpsACugij2aT5eKpLgakG6JKSCoxGA1lZaVG7QWseIGvsKjB9E0Wo3ggdNQKkNUK0aZ8P4hdAHTuqESAxQQuCIDQ04hZA9913H6BEgMaNGxcSLXC5XOzYsYNx48Ylf4cNCIstGBUJrwJT2VzwM8Puup2u5w7AkmLD6/Hw1YzZDLx+NKCYoNUIkMfr1zpBpwYEgpYCQxcBMqtVYFWnMLOzlRRYSUmFJrL0QsauTYTPCPk80foAhQug6lJgtmoiQPqUmn5SfDTUcRjq90lM0IIgCA2PuAVQhw4dAPjqq6+48sorY05WF2qONS2QnvL5cDuiRzF2rd2AvbRM89n8+tkXHNq9F0d5BaCkwIIeIJ/WCTolYBSOTIGZdWXwVXuA1BRYSUm5JjiqGoiqeYCipMD0fp20NBtdu+ZjMBjw+/1Rn13lMFSdAHI4XDHvoaJ6gFTEAyQIgtDwSNgDNHjwYBE/tYTq/4lmgFbxeb1s/WWF8rXPx5evzgLAUREQQPoIkM8f9AAFUkhBE7RyP5PZFHcfIFUAHTlSqUVNQj1A0VNg7qgpMGUfGzbswuFwkZZmo3375hHrVKpOgVnjNkBDMAWmIgJIEASh4RFXBOi5557j73//O5WVlTz33HNVrr3//vuTsrGGSFUGaD1rvvyWU4cMZOWCL9i/fSeAFgGyxYgAqQZh1QPk9SliR2+Crl4AhXqAIHwivBIBUifCW6roA6SmwEpLK9mwYRe9enWkW7d8fvst+hDc6kzQRyOA1DJ+QRAEoeEQlwDq1auXNkerV69eMddVl3oQqsaqGaCrFkDL5y/g0O497FoXNJ07o0SAvHoPkJoCCzRC9PqVdFe4AOrSpQ3t2zfns8+WRTxXiwDF8gBpJmi1DD52HyD1uooKJ3v2HKRXr450796W+fN/jvqZo3eCrqkAKgl5LxEgQRCEhkdcAmjw4MFRvxaSSzACVP0v5O2/rg557yhXKpn0HiCPD10ESPUABUSJXzE8G8NSYO+8+1e6d2/LKZ3+yJYte0OeofcApUb1ACkCKC28D1DUMnjluspKJ+vW/g5UXQkWLQKkb4SYiADat+9QyHsxQQuCIDQ8ajwNXkg+QQ9Q9b/Ew9F7gKwB4eH1+WOnwGJEgFq3bgwEe+ToydYEUAWVFdE8QKEpMK0PUBWNECsqHKxbp6TxquoFVJUJOtEI0IEDR0IG7EoESBAEoeERVwTo/fffj/uGV111VY0309CxVtMDqCqcmgcoDZtN+eXu9hEzBebxegArJpMJoynYB0gdEKrOydKToxNAjRsre9Q3NHQEIkAmsxlrampwFEYVJujKCgfr1ikRoM6dW2MyGfFGqUZLZgrM6/Vx4MARmjfPBUQACYIgNETiEkDhw06F2iFeE3Q0VBN0akYaJpPyC90XEgFSBFCKFgEKmKB1KTCr1YQp8HXLltEEUNAEHa0KzGV34HG7MVsspGZlVDkMNegBcrBjx34qKhykp6fQsWMLNm/eE7E+egqsZlVgoJTCqwJITNCCIAgNj7gE0C233FLb+xAI9gGK1QSxKtQUWFp6GqD8Qvf4DFoZvCqA1BSYx6d4gExmMyaz8tcgLdWi3a9Fi9yIZ+gjQKoASs8IbWhoLy0js3EjUrOyNA9QtBSY3gTt9/tZv34Xp59+Mt27t40hgJIXAYLQSjCJAAmCIDQ8xAN0DGEJDEKtSQpMjQCZDMFKPJ/frw1DVT1AqgnaHRh7YbYER0ikpQa/bhE1AhQ0QVdoHqBQAeTQ5oFlVDkKIzVMsKhpsFgdoeMtg7fHLYBKAKWXUryiSRAEQThxiCsCtHz5coYMGUJJSQkrVqyosty9T58+SdtcQ+NoUmBetxuPy0VaavBH6vVHRoA0D5DPgxkwWYNRn/SQCFDVHiAtAhQ20kI/EFUbhRE1AhQ0QQOsW6sYobvFMEKrpf3RGiGaTCZtTEe8YkYdhyEVYIIgCA2TuATQRx99hDNQyjxv3rza3E+DxpqqiAl3DQQQKFGgnHRlDIXT6cZkNgdHYaRYMRgMWFVREpj7pTYrhFBDc7gHyGg0kp2tF0BKlCo8AmQvLQVCI0DRp8EHPUBQdQTIZDJiDswri5YCA2jSRPnc1c0BU1FL4SX9JQiC0DCJSwBNmTIl6tdCcrHGmQJLTbUxZsxAPvtsWUhPG0dFBSaDIgRcLjdGk0mrAgNFBAWrwJRUktqsEEJTYHl5uRiNRq1cPCsraHY+cqRClwILHgddBCgrM9gHqJpGiBAUQJ06tcRiMeN2Bwez6ie961NgbrcHr9eLyWSicUAAJeoBEgO0IAhCw6TGHqA+ffpw3XXXcd1119G7d+9k7qnBEm8KbPToc3jl1XuYNOmakOPOikrNA+R0ekIiQKAYiVNSAr2GPJERoAxdBMhsNmlRFQhWgFVWOnG5PNWmwDIa5WrVZVWlwFTBsmvXAUpLK7FYzHTqFNqDSC+AnM5QMaVe37hxZsj76li+fBsej5fVq3fEtV4QBEE4sYh7GrxKq1atmDNnDgMGDNCGoubk5PDDDz8wevRo9uyJrOAR4kNNgVVXBab6c5o1zwk5rkSAlK9dLjdGswk/Brw+PyajgaysDG2t26uIErPOA5QRJmZatmzE/v0lQKgBGtCVwYcLIKUXUGbjYAot2jBUfSNElXXrfqd//85065avRYQgWAHmdLoj/GeVlU4yM9M0sRavANq2bR+tW93EwYOlca0XBEEQTiwSjgC9+uqrWCwWunTpQuPGjWncuDFdunTBaDTy6quv1sYeGwwWVQBVEwFSRYfeswPgLI+MAAG4PGoaK1Nb6/aEpsC8bo/WBFFFXwqvN0ADVXiAAgKoSWPtmLeaPkAqqhE6vCN0tC7Q2vMCnp9EI0AA+/eXRG26KAiCIJz4JBwBGjhwIGeddRabN2/Wjm3evJl77rmHJUuWJHVzDQ0tAlSNB0gVKuHpp4gIUCAF5fL4SbVCZmBEhdfrwRtIganNCn0+b4SYadkyKGL0BmgIendSU20hXiF1InxmEyUC5HFHRm30e1fvA0EfUPhMsGg9gFSCKbDEIkCCIAhCwybhCNCuXbu0yfB6TCYTe/fujXKFEC+aBygsBZaSkkp2djAakx4wHqtpJBVHeYUuAuTGaFL0rdutiBNVADmdTnxepQ+Q6gHyeb01igBBaCRKTYFlBSJA0XoA6a/RR4C2bt0HQNu2zcI+vzWwbw/hqIJHrRITASQIgiDEQ8IC6M9//jMvvPBCSL+fPn36MH36dB544IGkbq6hEawCCxVA06e9xf/e+JL0NEXABFNgoREbZ7k+AuTBZFEjQAEBlKEKIIcmgMwBMavMAVN66XgD5/Sl8OECyOl04wk0U4w2EDUj4AGKVgJvNpu0ga16wVJUVAJAs2bZIevjSYGpiAASBEEQ4iGuFNihQ4dC0hjp6en89NNPeNQ0itmMx+Phtddeo3HjxrFuI1SDlgKrDE2BtW93MhaLlabNWlCxY4sWqYmIAFVUYIwSAXK5FaGSnqGIGKfLoYkcc6AvkM/rJSNw3+3bizjppJYh3aBVAVR6pEI7VlHhIDs7PSR1pvYBUoVVtAow/b71ESDVcN2sWU7I+nhSYLHeC4IgCEI04hJA9957by1vQ4BgCsytS4GZTGYsgXEVqalKhCaWCdpRXkFgsLsSAQqkhZyBFFh6miJiXE4nPnUUhuYB8mn33bx5ryKAWsSOAIFSCZadnR4SiVIjQCpV9QDyer0hZe0HDijiyWazkJWVRmlpJRB9DIaKCCBBEAShJsQlgN54443a3odA9BSY2rcHIDXwdUYMD5CzIroHSIsApSsCyukKpsAsgW7NSgpMue/mTXu46KK+ISmwbN0keJVolWCqB0il6jEYoWLFbndSVlZJZmYazZpl6wRQ7AiQpMAEQRCEmnBUw1BtNhuZmZkhLyExcnOb0LJlPgajEUuKIgz0VWBq1AcgNUWJwqhCxWq1aOZfUE3Qytculwdj4JwqgNIC9wrxAAUEkNcbLINXp7Hn5eViMCg3jBUBglAPkKMseB6qHoMRTawEfUA52rGqIkDhw09FAAmCIAjxkLAASktL44UXXqCoqIiKigoOHz4c8hIS41/Pv8WM/35MTqMm2jF9FVhqik4AhaXAINQI7QjpBO3W+gA5Xd7A9amBcw58YWXwfp9PEzLbthXi8/kwm000baoYksMbIQJRJ8J7XC7cjqAIiVYFFq0Josr+/UeAUCN0VSbocMET7ywwQRAEoWGTsAD6xz/+weDBg7njjjtwOp3cdtttTJo0ib1793LDDTfUxh5PWIxGI61btSMlJZXmLZTxDz6fL0RA6FNgKWEpMAhNg0VEgAJ9gJwuT8j1TqfOBB0lBXb4cLkmRNRS+KoiQOHVaJWlwe7KHndVc8CqEkA5us+tpsCiRIDsEgESBEEQEidhAXTppZdy55138sEHH+DxeFiyZAlPPPEEDz/8MNdee21t7PGERR/dyczOAUIN0BDmAUpNw2QyhogevRFa7wFyRYkApageI1dkHyCvrg9QWZmdvXuVIauqD6jqFFj0eWAQPQIUrQmiyoFAJVhz3ZiPRCJA0dYIgiAIQjgJC6BGjRrx22+/AVBaWkqjRsovyKVLl3Luuecmd3cnOGnpwdlcGVk5QGQPoJSQFFh6RLQlngiQI1BpZbMp1yopMLUPUGQjxPJyvQBS2hpEE0CxJsI7dAIougco0RRYYBZYNQKostIZteu0IAiCIISTsAD67bffaN++PQAbN25k1KhRgBIZUoejCvGhNjYEyMhQDOThAig1LAUWHm0J8QCVB/sAub0+TJZABCjQQVkTQLoIkOoBMvl9mqG6rMxO4T5FALVooRihs7IUIRYigAJVYOHl+PpKsKr6AEVLV6kCqGm8Jmid50fSX4IgCEK8JCyAZs6cSY8ePQB46qmnuOuuu7Db7Tz//PM888wzSd/giUyaTgClZyqzrMLngIVUgaWmad2atet0Ashlt2spMJ/fEBEBsgYGn4ZUgQUEkNno1e5TXu4ISYFlZaVhNCp/VY4cqboKDIIDUaHqPkDRI0AlQM1M0CKABEEQhHhJeBjqP//5T+3rL7/8ki5dutC7d2+2bt3KmjVrkrm3E550XQosPRAB0hugISwFlpIWEQEK7wXkD0x59+gEkBoBslgCZfYuhzYFXe0DZDUqwqmiwoHP52NfIAKU16KRlv6y250hjQujVYFBmAeoiknwlVE8QFWlwKprhCgCSBAEQYiXhAVQODt37mTnzp3J2EuDIyQCFPg6PAIUXgVWVQoMwOB1A0b8BqNmgrYHhIPZrA4VdeLzKBEdtQrMGogcqc0N9RGgaP4fZW2gCixcAOkiQIl7gEqAWH2Aqm6EKAJIEARBiJcaNUIcPHgw8+fPZ+vWrWzdupX58+czZMiQZO/thEfvAUpVx1REmKD1VWDpERPbwyNAeJVojw+j1gjRESGAIlNgFpMigMrKFAG0b5/S06lFi9zqBVB6zarAqvIANWmShSkw18MW5ywwEUCCIAhCvCQsgO644w4WLlxIWVkZ06dPZ/r06ZSWlvLZZ59x55131sYeT1hSU9N1XyupLldEGXyoByjcbxNuQDb4FWHjN5qCZfBOVQApQsIVZRSGNdBQWhVAe/ceBKBFi0bk5kaOwYDoozAgOBAVovcBqqoR4sGDZVqPoiZNFF9UvLPARAAJgiAI8ZJwCuzhhx/mvvvu46WXXtKOvfDCC3z//fc8/PDDvPzyy0nd4ImM3gOkCaBwE3RYCiw8AhSRAvMFBJDBpHmA1DSRyWjB71NTYMp1agRI9QCpAqioqETrBn3yyUqTxnABFKsMPjQCFClK0qroA+Tz+SguLqV581yaNcuhqKhEUmCCIAhC0kk4ApSTk8PChQsjjn/++edkZ2dHuUKIRVpaMAKUYlNEREQZfGp4BKhqE7TRr5ibMVm0CJAqHIxGtTGirhN0oA+QLSCF1bSW1+vT0lGdu7QBQsdg6NdWlQJzR02BxY4AQaQRWkzQgiAIQrJJWAB9/PHHXHHFFRHHL7/8cj755JOkbKqhoPcA2ayKiHBX5QFKiZYCC4sAoQogsxYBUoWBQRVAOg+Q2ivIGuigqEaAIGiE7tpVEUBHYniAIlNgVfcBqqoMHiLHYVQdAQqKHoddBJAgCIIQH3GlwO655x7t6/Xr1/PII48waNAgCgoKAOjXrx8DBgzgueeeq51dnqCkhQmgCqJVgaWFfF2dCdqoCiCzBaNfNUErwsEQ+HG7XE7MHm/IdVoESCeAlFL4jnTRIkCxUmBVCaDYHqBYEZvwXkApYoIWBEEQkkxcAui+++4LeX/48GG6du1K165dtWMlJSXccsstPPHEE8nd4QmMfhSGNZCKqroKLJgCO3KkguzsdNLCTNDqKAzMFkx+5cerRYBQ+wI5SPGGC6DICNC+QAQoWhdoqKIRor4TdNQy+NgeIIADYSkwm01SYIIgCEJyiUsAdejQobb30SDRp8CsZivgj1IFFhQXRqNRG5lRVFRCdnbkbDC1E7TRYsPoU03QijDwawIoOApDe45FEUBqZRcEU2Aq+i7Q+rU2mwWz2YQnEFVylAfXuaOmwOL1AOUoexMTtCAIgpBkatQHSEgO+hSYRS1Rr2IYKkBmpnJNUVFJ4B6hESCzUREyBotVM0FXVioiwe9XftxOp10zQatYzcq5sogUWJBYESAI9SL5vF4cFcraqqfBxxJAymdrGocJ2u/3a8JIBJAgCIIQLzUSQNdffz2rV6/Gbrdjt9tZtWoV1113XbL3dsKTrqsCs5gC/pwqZoEBpGeECqCICFCgn4/RlhIsgw8IDW+g+3NFZbk2DV4lxRopgMIjQOECyO324HYrjRdj+YCqHIUR0wMUXgUWOwKkv48IIEEQBCFeEu4DdN999/HYY4/x4osv8v333wNw9tln85///IcmTZqEzAoTqiYkAmQICKCwFJi+DxBAWkAQ7Y8RAbIEuicbrTZMgbRWZaUDn8+gRYAqK8qrSIEFn692g1YJF0Dq+tzcjAghtubLb+k26Bz2bt4acU1VjRAhchyGGgHSzyHTo6bBRAAJgiAI8ZKwALrnnnu44447mD17tnZs/vz5rFu3jkcffVQEUALoGyGaDCbwxzZBu1wurFar1jsoGAEKS4EFUlkmWwrGSiU6U1npxOsxaGvsjkp8vvAIkBItCo0AHQxZE10A2cnNzYiIAH309D/56Ol/Rqy3Ws2YAyM6Ypmg1QhQ8+Y5yt4kAiQIgiAkmYRTYC1atOCHH36IOP7DDz/QokWLpGyqIWCzpWAyBfWn0WDAALgqgwLEbLZo4ytKShQxogqiWCkwa0BcmFJStRSY1+2hslIpj3c4KvH5fFWkwCq1Y2o3aJXwRogQFDHhlWCx0O+3OhN0enoKWVlpWCxqQ8foESBV+OgN0YIgCIJQFQkLoK1btzJq1KiI41dffTVbtmxJyqYaAmr6Sy8wjH4Dbl0KTF8BdjgggGxW5ZiaJopIgVkU0WNOSdNM0F6Ph8rKQIWWQxE4ESmwKBEgfTdoiB0BgkgPUCxUAeRyubWqsWj3VCvX2rRpoh2PFQF6792lbN68hx9/3BTXHgRBEAQh4RTYpEmTeOeddzj33HM1D9CAAQMYMmRIVGEkREctga+sLMdisSoRIb8hJAWmCiC320VZmSJErNYUoJLCQsWfExEBsio/UoPViiVFEUc+r1eLALlcDu2YntRAJ0S9BwgUI3ReXi4OhyuqByfWOIxYVNcEUaWoqIR27ZqTn99UOxbLAzR16rtMnfpuXM8XBEEQBKhBBOiDDz7gjDPOoLi4mBEjRjBixAiKi4s544wzmDdvXi1s8cREbYJYUVmOw6FEUYz+0CowdVq8w2HX1hgMSkpMTYHZbBZMpuCPURVAXp+BtCxlmrrX68XhUPoDuVzKfbwh0Rc/qbbICBAES+GjRX8g9jiMWFTXBFFFjTypAsjt9uD1+qq6RBAEQRDiJqEIkNls5r///S+PPfYY119/fW3tqUGgRYAqysEP2dm5GH2GkCowtQLM4bBjtyupK69XETv61FRamo2yMrsmfgB8/uCcL5/Hg1MVQO7ICJDJAGZTZBk8BLtBxxJAsSbCx/zc1TRBVAkXQLHSX4IgCIJQExKKAHk8Hq666qra2kuDIi0Q3amoLMcRiMoYfOB2BCMjagrM7rBjd6gCyIDD4aKiIjjRXU0rWa0W7VqPP1j15fV4cTr9geuV++sFkMXo177Wd4KGYCl8NAM0QEUNPUDVCaADAY9TG00ARU9/CYIgCEJNSDgFNm/ePEaMGFELW2lYqCkwu70CpyswqiLM46J2gXbYKzTzstdr1KI0qo9GFRXqzCxQIkDa1x4PbpchcL1TO6ZiDQggu90ZkWbas0cxXx86FF0AJeoBqq4JoopEgARBEITaJGET9JYtW5g4cSIDBgxg+fLlVFSEpkZeeOGFpG3uREbtAl1RWUFqYL6Xz+UJWRMSAbKr1VtGTXRUVDjJzEzTREXQ/+PHjy4C5PXi9hgwG8DrcwXuE4wAqQIoPP0F8MEHP3De4NN49ZVFUT9HrInwsQg2QaxOAJUAegEkESBBEAQheSQsgG699VZKSkro06cPffr0CTnn9/tFAMVJms4D5PIEohuusMqsqB4gA47y0AiQKirUCJBXH/5BifZ4PEbMFsDvDtwnMgUWTQAVF5dyzeh/xPwciZugE/MAtW6tlMFLBEgQBEFIJgmnwDp06BDz1bFjx4Q3cOedd7J9+3bsdjs//vgjp59+epXrR44cyYYNG7Db7axevZrhw4eHnL/iiitYtGgRxcXF+P1+evTokfCe6gJVAFVUluP2BKIb7jABFBh74XBUalVgXk8wBaaKCFVUqBEgtydUAHk9XnxepcrLjxJl0jdCtJpiC6DqUAVQWoIpsHgFkNo1WiJAgiAIQjKp12nwo0aNYtq0aUyePJnevXuzatUqFi1aRNOmTaOu79+/P3PmzGHGjBn06tWLefPmMW/ePLp166atSU9PZ+nSpTz44IN19TFqhDoGo7KyHLdPESUGb6hw0TxADjt2u5Jq9Pr0KbCA+AiLAHnCfDw+rwefTxESBmNAAEVJgYX3AIqHxKvAAh6gOFNgKhIBEgRBEJJJjQTQLbfcwpo1a3A4HDgcDtasWcOtt96a8H0mTJjAK6+8wuuvv86GDRsYN24clZWV3HLLLVHXjx8/noULF/Lss8+yceNGJk6cyIoVK7j77ru1NW+++SaPPfYYixcvrslHqzP0ESBPQADhCRUuKfoUmGqC9hi1Sq1wE7QaAXKFRZK8Hi/4lXNGo3IuWhVYzSJAiVaBxdcIUV/mDyKABEEQhOSSsACaPHky06dPZ/78+fzhD3/gD3/4A/Pnz+f5559n8uTJcd/HYrHQp0+fEKHi9/tZvHgx/fv3j3pN//79I4TNokWLYq6PF6vVSmZmZsirttH3AfL4FTFiDOvzp5mg7boUmNegS4FFrwJzhwkgn9eDavcyRRFAVZmgqyNRD1B1k+BVDhwIF0CSAhMEQRCSR8Im6DvuuIPbb7+dt99+Wzs2f/58Vq9ezQsvvMCkSZPiuk+TJk0wm80UFRWFHC8qKqJz585Rr8nLy4u6Pi8vL8FPEcpDDz3Eo48+elT3SJQ03SgML4ryMep690AwBWZ3VIZUgVUEREe4CVqLAIVVk/k8XgwGZaK62RLoB6TzAFkCHqBy3SDUeKlpGXx1Asjj8XLwYCmNGyvdrCUCJAiCICSThCNAFouFZcuWRRxfvnw5ZnPCeuqY4MknnyQrK0t7tWrVqtafqS+D9xkUARIugEKrwAIeIK8uBVYRKj7UCJDLHRRA3kC/H6MxIIDMithSokIKyfEAxRkBinMUBoSmwSQCJAiCICSThAXQ7NmzueOOOyKOjx07lrfeeivu+xQXF+PxeGjevHnI8ebNm1NYWBj1msLCwoTWx4vL5aKsrCzkVduk6UzQvsBPwURYBChVZ4LWUmCRVWDhESCnTiyo1V6mgACyWBWxk/wUWGIm6OoiQBAqgJwSARIEQRCSSI1M0Lfeeitr1qzhlVde4ZVXXmH16tXcfvvt+Hw+nnvuOe1VFW63m+XLlzNkyBDtmMFgYMiQIRQUFES9pqCgIGQ9wNChQ2OuP5bRTNAVQQFkNphC1gQjQJUhfYDKw1JgqrFYiwC5ggLIG4j0mM2qSFKO68vgk2GCVvdQHWlp1pC9V4W+EkxSYIIgCEIySThn1b17d1asWAGg9f0pLi6muLiY7t27a+v8fn/U6/VMmzaNWbNmsWzZMn7++Wfuvfde0tPTmTlzJgCzZs1iz549PPzwwwBMnz6db7/9lgkTJvDpp58yevRo+vbty9ixY7V75ubmkp+fT8uWLQE45ZRTACV6FO4fqk/SdR4gv0mJ/JiNoT+O0DJ41Z9jwG5XxEu4CVqNADnsLlAybPi8Xmy2FIxGRVzZUgzacZWjiQCpkRyr1YLFYsbt9lS5PpEI0AFJgQmCIAi1RMICaPDgwUl7+LvvvkvTpk2ZMmUKeXl5rFy5kmHDhrF//34A8vPz8fmCpVEFBQWMGTOGxx9/nKlTp7JlyxZGjBjBunXrtDWXXXYZr7/+uvb+nXfeAeDRRx9NqEqtNjGbLdhsASFQWY7frISALBECSB2FUYnTGRQnTofyPVGjKKlhfYAcjqAA8ro92uBV8JOaojxL3wlabYQYPgg1HvRenoyMFA4fjj4zTCWxFFiJ9rVEgARBEIRkUu+u5ZdeeomXXnop6rnzzjsv4tjcuXOZO3duzPvNmjWLWbNmJW1/tUFQkEBlZQUGVQCZLCHrgmXw9kBETSlndwW0QEWYCToYAQqKC5/Xq/mNTCYf1hRFLCUrBeZ2e3A63dhsFjIyUhMQQGKCFgRBEOqPeu0E3VBRBYnDYcfn80JAuFgt1pB1wRSYkv4yBhoFqRafWJ2gHfaguPB6PFq6zWz2kZqqPCNZKTBIzAcUbyNECBdAEgESBEEQkocIoHpAjQBVVirREkMMAZSqqwIDMJoUAeT1GAPXh5qg1QhQZUVoBCg18DxTDAF0NBEgCEZz4qkEi7cRIkgKTBAEQag9RADVA/oxGABGW2BMhcGI1RqMouirwADMZrWEXTEyR5qglQiQ0+7E6w4OPU3XpcBSUwMpsCTNAlOui38cRmICSFJggiAIQu1Q7x6ghkh6uhoBUpobmlJ1oic1DZfLicViwWRSfjxqDyCLxY/DDj6/KXB9aCdoNQXmdLpxVFSQnpON1xM0QetTYKCkx0xm81FHgOLtBp2aasNoVDR3fB6gEu1rp1MEkCA0BNLS0mjSpAkGg6H6xUKDwu/3U1xcTGVl4lMLoiECqB7Q9wACsKam4DX4MfkNpKamc+TIYc3/A0oKLCXFismsthYwB66PboJ2uTw4yhUB5PN6tecpEaCgAPJ5vVgsJgIebMpqMApDv4/qIkB6j1A8HqCSkgpcLjdWq0VSYIJwgmMwGLj55psZNGhQfW9FOMb55ptvmDlzZlztdqpCBFA9oO8BBGBJScHnCgiggPBRK8BcLhder4fc3CxMgXJ1g8ESuD52BMhZERid4fEEq8DMkQJITX/B0aTA4usGre7T4XCFtDeoiv37j9C6dRNJgQnCCc7NN9/MwIEDeeedd9i4cSMeT9U9xYSGh9lspnPnzowaNQqA11577ejul4xNCYmRFiaArKkp+NyKEElJVUREeAVYZmYqpoAJWhVHwQhQ5DBUR7kigHxeb0gKzGQyaQ0LfZ6gAHI43Xg8oVPk4yVeD1AiPYBUNm/eQ+vWTdiz52CN9iYIwrFPeno6gwYN4p133uHTTz+t7+0IxzDbtm0D4Oqrr+btt98+qnSYCKB6QDUlV1SWYzAasdhs2kBUNQIUXgGWkREUQOoa1UejemvCPUCglsEHqsA0AWVRBJDXq/l/4vHkxKIiTg9QIj2AVG64fhpdu+azcuVvNd6fIAjHNo0bNwZg48aN9bwT4XhA/XvSpEkTfv/99xrfRwRQPaCPAFlTFFHgVQVQQPjoJ8GDEl0JF0B6H01qqhWLLgLkVCNAHi+ZAcFlNHkDa22Uldnx6lJgNU1/QXQPkMViJjMzlUOHgoNl1UhVIhGgvXsPsXfvoRrvTRCEYx/V8CxpLyEe1L8nR2uUlzL4eiBdZ4K2piqiwYcqgJRoTUpYCbySAgsVSXZdw8P09JTQCFAgLOjTVYH5/e7A9cFeQBbT0UeAgh4g5bNccEEvNm/5L3v2ziI/v2nIHiE+A7QgCIIg1CYigOqBtLRgGbw14Pnx+APRmZRQD5A9IIBCUmCpwQoxfTdoa0gESJ0eH6wC83pDTdN6D1BZDeaAqagCqFXrJsx4bTwLF02hbdtm2GwWzj03OCA3kR5AgiAIJwJt27bF7/fTo0ePuK+58cYbOXz4cC3uSgARQPVCms4DZAlEgNxeJTqTkhpaBWbXp8DMoSZoCDVCqxEglyvoAfJ5vVrE6UhpKQAdOuRp55KZArviiv7cfPP5+Hw+tm8vAqBHj/baupp4gARBEIRjh5EjR7JhwwbsdjurV69m+PDhVa7Py8vjrbfeYtOmTXi9Xp5//vk62mn1iACqB/Rl8GoKzBUQQJoJOswDpK8CC40ABaM6agTI6fTgKFMqzLxuD6mBiNPmzTsBOPPMTgAhJuiaNkEMv3bjxt2cc/aDTH3iXQBO69Eu+Llr4AESBEEQjg369+/PnDlzmDFjBr169WLevHnMmzePbt26xbzGZrNx4MABHn/8cVatWlWHu60eEUD1QNAEXYEtkAJze1R/TsADFPjToUuBGU2hPiHlHsFxGPoI0LpvlrBt2a/88tFnmuBas3oLAKefoQggr8ejiwDVXAB98cWvfP31ap54/B169fwTBQUbWbVqOwCnndZOW1eTMnhBEBou1tSUenklwoUXXsiSJUs4fPgwxcXFzJ8/nw4dOsRcP3DgQPx+PxdddBGrVq3CbrdTUFAQVURccMEFrF+/nrKyMhYsWEBeXp52rm/fvnz++eccOHCAkpISvvnmG3r16pXQ3hNl/PjxLFy4kGeffZaNGzcyceJEVqxYwd133x3zmp07d3Lvvfcye/Zsjhw5EnNdfSBVYPWAPgJkyckFwOV2gTUY+amqCix6CixFFwFyc2jPPl6++U4A0iYoz1u2bANwGWec0QmDwaCkwExHHwHau/cQQwY/EnJs3brf8Xq9NG+eS/PmORQVlWgeILuYoAVBqAZragpP/vx1vTz7oTPOw2WP7x9q6enpTJs2jdWrV5ORkcGUKVP48MMP6dmzZ5Wdip955hnGjx9PYWEhU6dOZf78+XTq1EmrcEpLS+OBBx7g+uuvx+fz8eabb/Lss89y3XXXAZCZmcmsWbO45557MBgM3H///Xz22WecfPLJlJeXR33mmDFj+O9//1vl5xk+fDhLly6Neq5///5MmzYt5NiiRYsYMWJElfc8VhEBVA/oh6E2TW0BgNPlgPRgekurArNHSYHpxmTou0EHI0DBUlKDwaDd89eVm7HbneTmZnDyyS1DU2ClyZmtomK3O9myZR+dO7emR4/2fP75r+IBEgThhOODDz4IeX/LLbdQXFxM165dWbduXczrJk+ezOLFiwHF9Lx7926uuOIK3nvvPQCsVivjxo3jt9+UHmgvvvgiEydO1K7/+utQcTh27FhKSkoYOHBgzGaSH3/8MT/99FOVn2fPnj0xz+Xl5VFUVBRyrKioKCQydTwhAqiOMRgMWiPEyopyrQrM4VT+tRE0QYdXgaVUWQWWnm4LiQCppKSkaQNIS0uPsGLFNgYM6MoZZ3QKqQIrTbIAAli1ansMASQpMEEQqsZld/DQGefV27Pj5aSTTmLKlCmceeaZNGnSRPv/bX5+fpUCqKCgQPv68OHDbNq0iS5dumjHKioqNPEDsG/fPpo1a6a9b9asGY8//jiDBg2iWbNmmEwm0tLSyM/Pj/nM8vLymNGhhogIoDpGP+S0orIca2ASvMOlRHrCI0CqAErPCPYBSkkgAqSW3Hs8blwuJz//tJkBA7py5pmd2KSrAjuaFFgsVq/aztVXn8OpAR9QmpigBUFIgESESH0xf/58du7cye23387evXsxGo2sW7cOq9Va/cVV4HaHzj/0+/2auAKYNWsWjRs3Zvz48ezcuROn00lBQUGVzz3aFFhhYSHNmzcPOda8eXMKCwur+zjHJCKA6pj0MEGiRoDsdkXohA9DjVYFFuoBCpqgo0WA9IZrgJ9/3gwoRuj164IpsNIjFUn9nIBmhFZL4aURoiAIJxKNGjWic+fO3H777ZpoGDBgQFzX9uvXj127dgGQk5NDp06d2LBhQ9zPHjBgAHfeeScLFiwAoHXr1jRt2rTKa442BVZQUMCQIUOYPn26dmzo0KEh0azjCRFAdYy+BxAQUwBFzgILpsCUuV8pOJ0OKnUm6GgRoHSt6aLyvJ9+UgRQz57tmb1uTzAFVgsCaPXqHQB07twaq9UsjRAFQTihUCu/xo4dy759+8jPz+epp56K69qJEydy8OBBioqKeOKJJyguLmbevHlxP3vLli1cf/31LFu2jKysLJ555plqB4MebQps+vTpfPvtt0yYMIFPP/2U0aNH07dvX8aOHautmTp1Kq1ateLGG2/UjqlNIDMyMmjatCk9evTA5XIlJPhqAymDr2O0CrBAo0JLiloZpbxP0WaBhU6D15fBQ1Ag6VNg0SNAAQFkV+6/Y0cR+/eXYLVaaJlt0kZh1EYKbPfuYg4dKsNiMdO1a76YoAVBOKHw+/2MHj2aPn36sHbtWp5//nn+/Oc/x3XtX//6V6ZPn87y5cvJy8vj0ksvjUh7VcWtt95Kbm4uK1asYPbs2fzrX/9i//79Nf0ocVFQUMCYMWMYO3Ysq1atYuTIkYwYMSLE69SiRYsIH9LKlStZuXIlffv25dprr2XlypV89tlntbrXeJAIUB2jH4QKwQhQZYXyPqIKTJcCMxjA5XJgtaaQmpJGCYdCyuCje4BCU2AAP/+8hUsuOZ12Ta1J6QNUFatWbee8807jtNPaSSNEQRBOOL788suIHj76IZ07d+6MOrRz6dKlnHrqqVHvOWvWLGbNmhVy7KOPPgq5z8qVKznjjDNC1rz//vsJ7z9R5s6dy9y5c2Oev/nmmyOOHe3Q0tpCIkB1THpaeApMjYooU9ODs8BCU2PqoFGn0x44HxoBSo0RAdIPXlX5+adNALRvaqtVEzTAmkAarEeP9lIFJgiCIBwziACqY1QPUHgEqKI8IIBS0zEYDBFl8JmZoVVhaqRIFRNZWamYTCYgNAKkjsGw24MRINUH1K55alJGYVSF1hG6R3vNAyQmaEEQBKG+kRRYHRMRAUpRoiLlZWXaGpstNSQFZjAYyMgIM0trAkgRE40aZWrXR40AVQYjQL/8ogigvFybdqy2BZB+KKp4gARBaKh8++23x2xKqKEhEaA6RvPkVISmwCrLSvH5go0OgyZouxY5AaU5FgRTZGo0JTc3Q1sT1QOkS4GVlFSwadPukH0dzTT4qlBHYjRpkkWTJlmApMAEQRCE+kcEUB0THIOhCBk1BeZ02DXDc3ZWjpbOctgrtfSX1+vVIjnqQFRVTOgFkNsd2Qix0h5a5q6mwQA8Pn/INcnE6XSzaVNoXwkRQIIgCEJ9IwKojkkP8+SoESCX3aEdy81toq23O+yaAbq83KHNBgsvg8/NVe6rT39B6NwxPb/8HBRAztrRPhpqGkxFPECCIAhCfSMCqI7RGiGGpcBclcEIUE5OI+WYy4nP59X8P+XlDs0ErabA1GhKZqYiiCIEUCBSpE+BQWgEyFXLAmj1qh0h7+12V+0+UBAEQRCqQQRQHZMeow+Q2xEUN40CEaDwCrDycntEx+hwQ7ErTM1oHqCwFNiqVdtxexTPkdPjpzbRR4AqKhz4/bX7PEEQBEGoDhFAdYw+JZWem0NKRsDLc+SIJm5ycxsDoWMwQKnUcmhl8OqIi1ABFB4BSg8ru1dxuz38tlepPKttAbR6dagAEgRBEIT6RgRQHaOPAJ12/nkYTSZ2rdtA+cHDmgBqlKsMtAsKIF0KTIsAhabAVMIjQEGhFDnra/POEuU5bt9Rf66q2Lv3EMXFpYCUwAuC0LBo27Ytfr9fm4cVDzfeeCOHDx+uxV0JIAKoztFHgHoOPx+AlQsWA8G5X6oHSD8GA8IEUJgJWiUiAhQ2DFXPL+uKACg84j2ajxQXahpMDNCCIAjHLyNHjmTDhg3Y7XZWr17N8OHDq1x/xRVX8Pnnn7N//36OHDnCDz/8wAUXXBCyZtKkSfj9/pBXXQxKFQFUx6SlK4LEaLPQoU9PAFYu+hJAlwJTPEDBQahqCqxSE0UpMQSQyxWrCiwyArRsfREzNuXy8cqyiHPJRh2JISkwQRCE45P+/fszZ84cZsyYQa9evZg3bx7z5s2LmIWm59xzz+WLL77goosuok+fPnz99dfMnz+fnj17hqxbu3YteXl52uvss8+u5U8jAqjOUauy2p3eE6PRyPZfV1NSqERiVNOz6gEKzgFTx2UEjdJqCszv92O3B0WQU1fTbjQadZGiSAHk83gpdZvwums/ArRixTYADh2qfbElCMKJQVqarV5eiXDhhReyZMkSDh8+THFxMfPnz6dDhw4x1w8cOBC/389FF13EqlWrsNvtFBQURBURF1xwAevXr6esrIwFCxaQl5ennevbty+ff/45Bw4coKSkhG+++YZevXoltPdEGT9+PAsXLuTZZ59l48aNTJw4kRUrVnD33XfHvOa+++7jmWeeYdmyZWzdupVHHnmELVu2cOmll4as83g8FBUVaa+DBw/W6mcBGYVRp1gsViwWKwCdBvYHYOXCxdp5LQKUo0aAQlNgZWV2rVeQ6u0BxVeTmqr8R6uPAOnX2O2RKTCf1xvyZ23y7rtLOPnklnz00Y+1/ixBEI5/0tJslFfEnjpem2Skj4w7XZ+ens60adNYvXo1GRkZTJkyhQ8//JCePXtWWfH6zDPPMH78eAoLC5k6dSrz58+nU6dOeDzKP2LT0tJ44IEHuP766/H5fLz55ps8++yzXHfddQBkZmYya9Ys7rnnHgwGA/fffz+fffYZJ598MuXlkf+/BxgzZgz//e9/q/w8w4cPZ+nSpVHP9e/fn2nTpoUcW7RoESNGjKjynnoMBgOZmZkcOnQo5PjJJ5/Mnj17cDgcFBQU8NBDD7Fr166471sTRADVIWpFFkDr07ri8/lY/cXX2jFV8Fitikiyh6XAyssd2hq1DB6UtJI6ZiLaHDCXy4nbHZoaA50A8tWuCVrZg4dJk96q9ecIgiDUJR988EHI+1tuuYXi4mK6du3KunXrYl43efJkFi9W/gF84403snv3bq644gree+89QPk9MG7cOH777TcAXnzxRSZOnKhd//XXX4fcb+zYsZSUlDBw4EA+/fTTqM/8+OOP+emnn6r8PHv27Il5Li8vj6KiopBjRUVFIZGp6njggQfIyMjg3Xff1Y799NNP3HTTTWzatIkWLVowadIklixZQvfu3WOKuWQgAqgOUf04TrcTDPDbL79SeqBYO28P69Wjip30jMg+QGojRAj1AYXOAYtdAQZKCkz/pyAIwrFCZaWTjPSR9fbseDnppJOYMmUKZ555Jk2aNMFoVJwl+fn5VQqggoIC7evDhw+zadMmunTpoh2rqKjQxA/Avn37aNasmfa+WbNmPP744wwaNIhmzZphMplIS0sjPz8/5jPLy8trVVBUxzXXXMOkSZO4/PLLOXDggHZ84cKF2tdr1qzhp59+YufOnYwaNYrXXnut1vYjAqgOUSMyPmXMFysXfhlyXhU3KtFTYKFVYBBqLNZHgGKNwVDxaimwWm4FLQiCUAOOh6rR+fPns3PnTm6//Xb27t2L0Whk3bp1WiS/poRH7f1+vyauAGbNmkXjxo0ZP348O3fuxOl0UlBQUOVzjzYFVlhYSPPmzUOONW/enMLCwuo+DldffTWvvvoqf/jDH/jyyy+rXHvkyBE2b97MSSedVO19jwYRQHWIKkiwmPF6PKxeHBrCVAVP+PvQFFikAIoVAYrVBFFFTYF568ADJAiCcKLRqFEjOnfuzO23366JhgEDBsR1bb9+/TSPS05ODp06dUqo9HvAgAHceeedLFiwAIDWrVvTtGnTKq852hRYQUEBQ4YMYfr06dqxoUOHhkSzojF69Ghee+01Ro8ezWeffVblWlB8VR07dmT27NnVrj0aRADVIaog8Rn9bP1pGRWHS0LOh0eA1JRYUAAFI0A2WyoGgwG/3x/SXFAfAaqqCSIEU19+b+17gARBEE401MqvsWPHsm/fPvLz83nqqafiunbixIkcPHiQoqIinnjiCYqLi5k3b17cz96yZQvXX389y5YtIysri2eeeYbKysoqrznaFNj06dP59ttvmTBhAp9++imjR4+mb9++jB07VlszdepUWrVqxY033ggoaa9Zs2Yxfvx4fvrpJy2CZLfbKS1VGuQ+88wzWiStZcuWTJ48Ga/Xy5w5c2q813iQMvg6RI0AeQ1+ftVVf6nYHdE9QCEpsEAEyGg0YrMpwkifAnPrI0BpVUeAfl+7DkdFBduW/VqjzyMIgtCQ8fv9jB49mj59+rB27Vqef/55/vznP8d17V//+lemT5/O8uXLycvL49JLL41arBKLW2+9ldzcXFasWMHs2bP517/+xf79+2v6UeKioKCAMWPGMHbsWFatWsXIkSMZMWJEiNepRYsWIT6ksWPHYrFYePnllyksLNRe+ihS69atmTNnDps2beLdd9/l4MGD9OvXj+LiYmoTiQDVIT1PPw0Aq9nN2q++izgfEQGKMgrD6QyKndSUNBwOe/UmaHv0CNCeDZv5+4AL66QMXhAE4UTkyy+/jOjhYzAYtK937twZ8l5l6dKlnHrqqVHvOWvWLGbNmhVy7KOPPgq5z8qVKznjjDNC1rz//vsJ7z9R5s6dy9y5sdsT3HzzzSHvzzvvvGrvec011xz1vmqCCKA6ZODg0wFIowJ7aWRDQHuYB+jNt8aTnXMTNpsFUFJgSuPDClJT07VKsMpqTNCVFbFDniJ+BEEQhIaIpMDqkCXf/0heyyO0bGqP+i+C8AiQ2YwmfvbvL2HHjv0h66JNhA+NAMUegyEIgiAIDRmJANUh0574Bw9P6ElWVhq9e3dk+fKtIeedztAI0BUjJrN9x3osFhOFhSXayAs1UqRWgsUyQaspsPD+QoIgCEL98O2330b9B7BQ90gEqA7xeLwsXrwSgOHD+0Sc7969Zcj7vXuL2L27mO3bi0LmfTnCmiFWVDhwOk1UVFhDy+ADAqiiihSYIAiCIDRERADVMYsWrgDgwmG9I85deGFPIDg7JtwTFDwe2gvI7Tay4qe2LP8xH5MxU1uXVk0VmCAIgiA0VEQA1TELFiwHoF+/U8jNzQg5d9HFfTGZgj15whsjqgQFkBLh6dJpOC6XGb/fSLOm3bV11VWBCYIgCEJDRQRQHbN7dzFr1+7EZDIxdGhP7XjLlo3o1atjmACK3tRKPw/s1O59OPmkYOfRlnk9tK8lAiQIgiAI0REBVA+oabBhw/tqx4YHvna7dV6fGBEg1QOUlZnN/fc9BkDT5qUYDD6ys1vQrt3JgF4ASQRIEARBEPSIAKoHFixYBsCwYb21aoCLLlYE0JFAa3CXy4nPF31EheoNuvKKG2ib35Hy8hJO7ryfRo0VYXTewIsASAukyGINQxUEQRCEhooIoHpg6dL1lJfbycvLpUeP9litZi0dduDAISCyJ5Ae9Vyj3CYAfPzpK1gsPprmKc0Vzxs0HNANQ5UqMEEQhHqhbdu2+P1+evToUf3iADfeeCOHDx+uxV0JIAKoXnC5PHz55SpAKYc/55xuZGSksm/fIYqLDwJBo3M09H19fvr5Owp+/AKAxk3K8XhctGndni5demC12gAxQQuCIAhHT9euXZk7dy7bt2/H7/czfvz4+t7SUSECqJ4I+oD6cPHFyoiMBZ8t09Jbsfw/EBRHDoedf74wWesEbTb72fqbMtj04uF/0NaLB0gQBEE4WtLS0vjtt9/461//yr59++p7O0eNCKB6Qi2H79+/M1dedRYAn366TIvuVCWAfvzpW7b9tonn/jmRwsLdIdPg165dCsDgQYoPyG6vxOeTeV+CIBx/pKSk1ssrES688EKWLFnC4cOHKS4uZv78+XTo0CHm+oEDB+L3+7noootYtWoVdrudgoKCiIGqABdccAHr16+nrKyMBQsWkJeXp53r27cvn3/+OQcOHKCkpIRvvvmGXr16JbT3RFm2bBl/+ctfeOedd3A6ndVfcIwjozDqiZ0797Nhwy66dGlDfn5TXC43ixevpHXLIUDsEniAXbt+47Y/Xqa9188CW7/hZyorK2QMhiAIxzUpKaksmL+yXp49/NKeVf4jVE96ejrTpk1j9erVZGRkMGXKFD788EN69uyJ3++Ped0zzzzD+PHjKSwsZOrUqcyfP59OnTrh8Sjd/NPS0njggQe4/vrr8fl8vPnmmzz77LNcd911AGRmZjJr1izuueceDAYD999/P5999hknn3wy5eXRfZ9jxozhv//9b9Wfffhwli5dGtdnP94RAVSPLFywnC5d2gCwZMl6ysrsmsE53v/4IHQWWHlFBT8UfMX5Qy5VzkkFmCAIQq3xwQcfhLy/5ZZbKC4upmvXrqxbty7mdZMnT2bx4sWAYnrevXs3V1xxBe+99x4AVquVcePG8dtvvwHw4osvMnHiRO36r7/+OuR+Y8eOpaSkhIEDB/Lpp59GfebH/9/evQdFdZ99AP9yEwdYIgYBSbooqKCiIAQpYOKFcTTxgjYtRNNq3ql21Bbtq68aRycpaJTWGYlBjbYmDBiaarXY0HgZJfgaCRpAMfGGiIANl7XLRW7LRXjeP3w9kw2KEGGPsN/PzDN6fvvbc559RuGZc35nz2ef4cKFC51+ntLS0k5f70+eiQZoxYoVWLt2Ldzc3HD58mVER0cjOzv7sfN//vOfY/PmzRg2bBgKCgqwfv16HD9+3GhOTEwMli5dikGDBiEzMxPLly/HrVu3HrNHdZw4cRH/vXoeAODY5w8+78PGp7O7wH6ovb0dTU0tGDjwwbPAMv73mNIAcf0PEfVFTU0GvDrHX7Vjd9WIESMQGxuL4OBgODs7w9LywcoSrVbbaQOUlZWl/L26uhr5+fkYPXq0MtbQ0KA0PwBQXl4OFxcXZdvFxQVbtmzBlClT4OLiAisrK9jZ2UGr1T72mPX19Y89O2SOVF8DFBkZiR07diAmJgYBAQG4fPkyTp48iSFDhjxyfkhICD799FN89NFHmDBhAo4ePYqjR48aXT9dt24dVq5ciWXLliE4OBgNDQ04efIkbG1tTfWxuuTs2SuoqalHW1sb0tK+BgAU3HrwH+bmrWvd2ldl5YNb4O/da0R2zpeor3/wfUJsgIior2pqMqgS3ZGWlobBgwdj6dKlCA4ORnBwMIAHZ3CeRmtrq9G2iCjNFQAkJSXB398fq1atQmhoKPz9/VFZWdnpcRcuXIi6urpOY9KkSU+Vd18jasb58+clISFB2bawsJDvvvtO1q9f/8j5f/vb3yQtLc1oLCsrSz788ENlu6ysTNasWaNsOzo6isFgkKioqC7lpNFoREREo9H0+ucPChop06dP+MHxn+v2fmbMCJAVK15Tttf9z1bJOJUvW2I/fKr8GAwGo7fDw8NDkpOTxcPDQ/VcuhODBw8WEZFJkyYpY2FhYSIiEhERoXw2ERE/Pz8BIJMnTxYRkV/84hfKewYNGiT19fXK2OLFi6W6utroWBERESIPFhUJAKmtrZVf/vKXyvaLL74oIiKrVq16bL4ODg7i5eXVaQwcOLBLn72oqKjTY6n176U7v79VvQRmY2ODwMBAbNu2TRkTEZw+fRohISGPfE9ISAh27NhhNHby5EnMmzcPADB8+HAMHTpUubYKALW1tbhw4QJCQkJw8ODBDvscMGCA0dkhjUbTYU5vyc4u6DBWV3ev2/s5efKi0fahw4kY7T0e6V+k/ejciIjo8R7e+fWb3/wG5eXl0Gq1iIuL69J733nnHVRWVkKn0+G9996DXq/H0aNHu3zsgoIC/OpXv0JOTg4cHR2xfft2NDZ2vnTiaS+B2djYYMyYMQAe/N584YUX4Ofnh/r6ehQWFv7o/apF1Utgzs7OsLa2hk6nMxrX6XRGt/t9n5ubW6fzH/7ZnX1u2LABtbW1SvSHRWDFxQX4r6WzkXHmmNqpEBH1SyKCN954A4GBgbhy5Qri4+Oxdu3aLr337bffxs6dO5Gbmws3NzfMmTOnw2Wvzvz617+Gk5MTLl68iAMHDuCDDz7A3bt3f+xH6RJ3d3fk5eUhLy8P7u7uWLt2LfLy8rB///5ePW5veSYWQatt27ZtRmeVNBpNv2iCiIiod6Wnp3f4Dp+Hz3gEgJKSEqPth86dO4dx48Y9cp9JSUlISkoyGvvnP/9ptJ+8vDxMnDjRaM6RI0e6nX93PO6z9FWqngHS6/W4f/8+XF1djcZdXV1RUVHxyPdUVFR0Ov/hn93ZZ0tLS4eFYERERNR/qdoAtba2Ijc3F+Hh4cqYhYUFwsPDjW4R/L6srCyj+QAwffp0ZX5RURHKy8uN5mg0GgQHBz92n0RERGR+VF1FHxkZKQaDQRYtWiQ+Pj6yd+9eqaqqEhcXFwEgSUlJsnXrVmV+SEiItLS0yOrVq8Xb21veffddaW5ulrFjxypz1q1bJ1VVVTJnzhzx9fWV1NRUKSwsFFtb2y7lZMq7wBgMBsPco6/eBcZQJ/rFXWAAcOjQIQwZMgSxsbFwc3NDXl4eZs6cqSzm0mq1aG9vV+ZnZWVh4cKF2LJlC7Zu3YqCggLMmzfP6Aun/vSnP8He3h5//vOfMWjQIJw7dw4zZ87sF88uISIiop6hejf3rAXPADEYDIbpQqvVSnJysnh5eameC+PZDy8vL0lOThatVtvhte78/lb9m6CJiMi8VVZWAgB8fHxUzoT6gof/TvR6/VPtR/VLYEREZN4aGhpw5swZREZGAgBu3LihPBWd6CFra2v4+PggMjISZ86ceeIXPz5xfz2UFxER0Y+WmJgIAIiKilI5E3rWnTlzRvn38jQs8OBaGH2PRqNBbW0tHB0d+Z1AREQmZGdnB2dn5371hXvUM0QEer2+0zM/3fn9zTNARET0zGhsbMSdO3fUToPMABdBExERkdlhA0RERERmhw0QERERmR2uAeqERqNROwUiIiLqou783mYD9AgPC1haWqpyJkRERNRdGo3miXeB8Tb4x3B3d++VW+A1Gg1KS0vxwgsv8Bb7XsQ6mwbrbBqss2mwzqbR23XWaDQoKyt74jyeAXqMrhTvadTV1fE/mAmwzqbBOpsG62warLNp9Fadu7pPLoImIiIis8MGiIiIiMwOGyATa25uxh/+8Ac0NzernUq/xjqbButsGqyzabDOpvGs1JmLoImIiMjs8AwQERERmR02QERERGR22AARERGR2WEDRERERGaHDZAJrVixAkVFRTAYDDh//jyCgoLUTqlPe/vtt/H111+jtrYWOp0OqampGDVqlNEcW1tb7Nq1C3q9HnV1dTh8+DBcXFxUyrh/WL9+PUQE8fHxyhjr3DPc3d1x4MAB6PV6NDY24ptvvkFgYKDRnJiYGJSVlaGxsRGnTp3CiBEjVMq2b7K0tERsbCxu376NxsZG3Lp1C5s2beowj3XuvpdffhmfffYZSktLISKIiIjoMOdJdXVycsInn3yCe/fuobq6Gvv374e9vX2v5SyM3o/IyEhpamqSt956S0aPHi379u2TqqoqGTJkiOq59dU4fvy4LF68WMaMGSPjx4+Xf/3rX1JcXCx2dnbKnD179khJSYlMnTpVAgIC5KuvvpJz586pnntfjZdeeklu374teXl5Eh8fzzr3YAwaNEiKiork448/lqCgIBk2bJhMnz5dPD09lTnr1q2T6upqmTt3rowbN06OHj0qhYWFYmtrq3r+fSU2bNgg//nPf+S1114TDw8Pef3116W2tlaio6NZ56eMmTNnyubNm2XevHkiIhIREWH0elfq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", "text/plain": [ "
" ] @@ -542,9 +542,9 @@ "source": [ "for prob in prob_list:\n", " plt.plot(prob)\n", - "plt.legend([0.1, 0.25, 1])\n", + "plt.legend([\"alpha = 0.1\", \"alpha = 0.25\", \"alpha = 1\"])\n", "plt.xlabel(\"iterations\")\n", - "plt.ylabel(\"probability of the best answer\")" + "p = plt.ylabel(\"probability of the best answer\")" ] }, { From 6a12efbc42ba4718846564f92846e10f1f3f57f4 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:00:37 +0100 Subject: [PATCH 038/139] truelly jittable cvar --- tensorcircuit/applications/optimization.py | 110 +++++++++++++-------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py index e2609e1f..642ef127 100644 --- a/tensorcircuit/applications/optimization.py +++ b/tensorcircuit/applications/optimization.py @@ -162,35 +162,35 @@ def QUBO_QAOA( def cvar_value(r: List[float], p: List[float], percent: float) -> Any: """ - Calculate the Conditional Value at Risk (CVaR) according to the measurement results. + Compute the Conditional Value at Risk (CVaR) based on the measurement results. - :param r: The results showing after measurements. - :param p: Probabilities corresponding to each result. - :param percent: The cut-off percentage of CVaR. + :param r: The observed outcomes after measurements. + :param p: Probabilities associated with each observed outcome. + :param percent: The cut-off percentage for CVaR computation. :return: The calculated CVaR value. """ sorted_indices = tf.argsort(r) - p = tf.cast(tf.gather(p, sorted_indices), dtype=tf.float32) - r = tf.cast(tf.gather(r, sorted_indices), dtype=tf.float32) - - sump = tf.constant(0.0, dtype=tf.float32) # The sum of probabilities. - count = tf.constant(0, dtype=tf.int32) - cvar_result = tf.constant(0.0, dtype=tf.float32) - - # Iterate over the sorted results and calculate CVaR. - while sump < percent: - if tf.math.round(sump + p[count], 6) >= percent: - # Add the remaining portion of the last result that exceeds the cut-off percentage. - cvar_result += r[count] * (percent - sump) - count += 1 - break - else: - # Add the entire result to the CVaR calculation. - sump += p[count] - cvar_result += r[count] * p[count] - count += 1 + p_sorted = tf.cast(tf.gather(p, sorted_indices), dtype=tf.float32) + r_sorted = tf.cast(tf.gather(r, sorted_indices), dtype=tf.float32) + + # Calculate the cumulative sum of sorted probabilities. + cumsum_p = tf.math.cumsum(p_sorted) + + # Create a tensor that evaluates to 1 if the condition is met, otherwise 0. + mask = tf.cast(tf.math.less(cumsum_p, percent), dtype=tf.float32) + + # Use mask to filter and sum the required elements for CVaR. + cvar_numerator = tf.reduce_sum(mask * p_sorted * r_sorted) + + # Compute the last remaining portion that exceeds the cut-off percentage. + last_portion_index = tf.math.argmax(tf.math.greater_equal(cumsum_p, percent)) + last_portion = (percent - cumsum_p[last_portion_index - 1]) * r_sorted[ + last_portion_index + ] + + # Calculate the final CVaR. + cvar_result = (cvar_numerator + last_portion) / percent - cvar_result /= percent return cvar_result @@ -205,25 +205,51 @@ def cvar_from_circuit(circuit: Circuit, nsamples: int, Q: Tensor, alpha: float) :param alpha: The cut-off percentage for CVaR. :return: The calculated CVaR value. """ - # Get measurement results and normalize them. + # Obtain and normalize measurement results + measurement_data = circuit.state() results = measurement_results( - circuit.state(), counts=nsamples, format="count_dict_bin" + measurement_data, counts=nsamples, format="sample_int", jittable=True ) - results = {k: v / nsamples for k, v in results.items()} + n_counts = tf.shape(results)[0] - values = [] # List to store the measurement values. - probabilities = [] # List to store the corresponding probabilities. - Q_tf = tf.convert_to_tensor(Q, dtype=tf.float32) + # Initialize TensorArrays to hold probabilities and values + probabilities = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) + values = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) - for k, v in results.items(): - binary_strings = tf.strings.bytes_split(k) - x = tf.reshape( - tf.strings.to_number(binary_strings, out_type=tf.float32), (-1, 1) + # Determine the number of qubits in the circuit and generate all possible states + n_qubits = len(Q) + all_states = tf.constant([format(i, f"0{n_qubits}b") for i in range(2**n_qubits)]) + + # Convert the Q matrix to a TensorFlow tensor + Q_tensor = tf.convert_to_tensor(Q, dtype=tf.float32) + + # Loop through all possible states to calculate the value and probability of each + for state_index in tf.range(tf.shape(all_states)[0]): + state_str = all_states[state_index] + binary_values = tf.strings.bytes_split(state_str) + state_vector = tf.reshape( + tf.strings.to_number(binary_values, out_type=tf.float32), (-1, 1) + ) + + # Compute the value for this binary state + value = tf.squeeze( + tf.matmul(tf.transpose(state_vector), tf.matmul(Q_tensor, state_vector)) ) - xT = tf.transpose(x) - values.append(tf.squeeze(tf.matmul(xT, tf.matmul(Q_tf, x)))) - probabilities.append(v) + values = values.write(state_index, value) + + # Compute the probability of this state occurring + prob_of_state = ( + tf.reduce_sum(tf.cast(tf.equal(results, state_index), tf.int32)) / n_counts + ) + probabilities = probabilities.write( + state_index, tf.cast(prob_of_state, dtype=tf.float32) + ) + + # Stack TensorArrays to Tensors + probabilities = probabilities.stack() + values = values.stack() + # Calculate CVaR cvar_result = cvar_value(values, probabilities, alpha) return cvar_result @@ -250,19 +276,20 @@ def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> Any: # Convert the Q-matrix to a TensorFlow tensor. Q_tf = tf.convert_to_tensor(Q, dtype=tf.float32) - values = [] + values = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) # Calculate the cost for each binary state. - for state in states: + for idx in tf.range(tf.shape(states)[0]): + state = states[idx] binary_strings = tf.strings.bytes_split(state) x = tf.reshape( tf.strings.to_number(binary_strings, out_type=tf.float32), (-1, 1) ) xT = tf.transpose(x) # the transpose value = tf.squeeze(tf.matmul(xT, tf.matmul(Q_tf, x))) - values.append(value) + values = values.write(idx, value) - values = tf.convert_to_tensor(values, dtype=tf.float32) + values = values.stack() # Calculate the CVaR value using the computed values and the probability distribution. cvar_result = cvar_value(values, prob, alpha) @@ -330,7 +357,6 @@ def QUBO_QAOA_cvar( :param maxiter: The maximum number of iterations for the optimization. Default is 1000. :return: The optimized parameters for the ansatz circuit. """ - tf.config.run_functions_eagerly(True) loss = partial(cvar_loss, nlayers, Q, nsamples, alpha, expectation_based) f_scipy = scipy_interface(loss, shape=(2 * nlayers,), jit=True, gradient=False) From 31d47adfcd618e9d8d0b9c3c3d050e74ec40a952 Mon Sep 17 00:00:00 2001 From: Felix Xu <61252303+FelixXu35@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:53:17 +0100 Subject: [PATCH 039/139] optimized cvar --- tensorcircuit/applications/optimization.py | 71 ++++++++-------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py index 642ef127..28c5c81a 100644 --- a/tensorcircuit/applications/optimization.py +++ b/tensorcircuit/applications/optimization.py @@ -212,42 +212,28 @@ def cvar_from_circuit(circuit: Circuit, nsamples: int, Q: Tensor, alpha: float) ) n_counts = tf.shape(results)[0] - # Initialize TensorArrays to hold probabilities and values - probabilities = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) - values = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) - # Determine the number of qubits in the circuit and generate all possible states n_qubits = len(Q) all_states = tf.constant([format(i, f"0{n_qubits}b") for i in range(2**n_qubits)]) + all_binary = tf.reshape( + tf.strings.to_number(tf.strings.bytes_split(all_states), tf.float32), + (2**n_qubits, n_qubits), + ) + all_decimal = tf.range(2**n_qubits, dtype=tf.int32) # Convert the Q matrix to a TensorFlow tensor Q_tensor = tf.convert_to_tensor(Q, dtype=tf.float32) - # Loop through all possible states to calculate the value and probability of each - for state_index in tf.range(tf.shape(all_states)[0]): - state_str = all_states[state_index] - binary_values = tf.strings.bytes_split(state_str) - state_vector = tf.reshape( - tf.strings.to_number(binary_values, out_type=tf.float32), (-1, 1) - ) - - # Compute the value for this binary state - value = tf.squeeze( - tf.matmul(tf.transpose(state_vector), tf.matmul(Q_tensor, state_vector)) - ) - values = values.write(state_index, value) - - # Compute the probability of this state occurring - prob_of_state = ( - tf.reduce_sum(tf.cast(tf.equal(results, state_index), tf.int32)) / n_counts - ) - probabilities = probabilities.write( - state_index, tf.cast(prob_of_state, dtype=tf.float32) - ) + # calculate cost values + values = tf.reduce_sum(all_binary * tf.matmul(all_binary, Q_tensor), axis=1) - # Stack TensorArrays to Tensors - probabilities = probabilities.stack() - values = values.stack() + # Count the occurrences of each state and calculate probabilities + state_counts = tf.reduce_sum( + tf.cast(tf.equal(tf.reshape(results, [-1, 1]), all_decimal), tf.int32), axis=0 + ) + probabilities = tf.cast(state_counts, dtype=tf.float32) / tf.cast( + n_counts, dtype=tf.float32 + ) # Calculate CVaR cvar_result = cvar_value(values, probabilities, alpha) @@ -269,27 +255,21 @@ def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> Any: prob = tf.convert_to_tensor(circuit.probability(), dtype=tf.float32) # Generate all possible binary states for the given Q-matrix. - states = tf.constant( - [format(i, "0" + str(len(Q)) + "b") for i in range(2 ** len(Q))] + n_qubits = len(Q) + all_states = tf.constant( + [format(i, "0" + str(n_qubits) + "b") for i in range(2 ** len(Q))] + ) + all_binary = tf.reshape( + tf.strings.to_number(tf.strings.bytes_split(all_states), tf.float32), + (2**n_qubits, n_qubits), ) # Convert the Q-matrix to a TensorFlow tensor. - Q_tf = tf.convert_to_tensor(Q, dtype=tf.float32) - - values = tf.TensorArray(dtype=tf.float32, dynamic_size=True, size=0) - - # Calculate the cost for each binary state. - for idx in tf.range(tf.shape(states)[0]): - state = states[idx] - binary_strings = tf.strings.bytes_split(state) - x = tf.reshape( - tf.strings.to_number(binary_strings, out_type=tf.float32), (-1, 1) - ) - xT = tf.transpose(x) # the transpose - value = tf.squeeze(tf.matmul(xT, tf.matmul(Q_tf, x))) - values = values.write(idx, value) + Q_tensor = tf.convert_to_tensor(Q, dtype=tf.float32) - values = values.stack() + # calculate cost values + elementwise_product = tf.multiply(all_binary, tf.matmul(all_binary, Q_tensor)) + values = tf.reduce_sum(elementwise_product, axis=1) # Calculate the CVaR value using the computed values and the probability distribution. cvar_result = cvar_value(values, prob, alpha) @@ -377,7 +357,6 @@ def QUBO_QAOA_cvar( method="COBYLA", callback=callback, options={"maxiter": maxiter}, - # bounds=[(0, (2 - np.mod(i, 2))*np.pi) for i in range(2*nlayers)] ) # Perform the optimization using the COBYLA method from scipy.optimize. From df94bea2629cd3ee5da8fa551ae9203ffc7552cd Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 25 Sep 2023 16:01:40 +0800 Subject: [PATCH 040/139] update readme refs --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 677beaa0..57b908d4 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ Reference paper: https://arxiv.org/abs/2010.08561 (published in QST). For the application of Variational Quantum-Neural Hybrid Eigensolver, see [applications](/tensorcircuit/applications). -Reference paper: https://arxiv.org/abs/2106.05105 (published in PRL) and https://arxiv.org/abs/2112.10380. +Reference paper: https://arxiv.org/abs/2106.05105 (published in PRL) and https://arxiv.org/abs/2112.10380 (published in AQT). ### VQEX-MBL @@ -339,7 +339,7 @@ Reference paper: https://arxiv.org/abs/2208.02866 (published in PRL). For the numerical simulation of variational quantum algorithm training using random gate activation strategy by us, see the [project repo](https://github.com/ls-iastu/RAtraining). -Reference paper: https://arxiv.org/abs/2303.08154. +Reference paper: https://arxiv.org/abs/2303.08154 (published in PRR as a Letter). ### TenCirChem @@ -386,6 +386,8 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Zero and Finite Temperature Quantum Simulations Powered by Quantum Magic: https://arxiv.org/abs/2308.11616. +- Comparison of Quantum Simulators for Variational Quantum Search: A Benchmark Study: https://arxiv.org/abs/2309.05924. + If you want to highlight your research work here, feel free to add by opening PR. From 47fff438de1fd68a4c1e5f1f7593d85acae9f4f9 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Sat, 7 Oct 2023 16:04:26 +0800 Subject: [PATCH 041/139] add overlap in fgs --- tensorcircuit/fgs.py | 25 ++++++++++++++----------- tests/test_fgs.py | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index b853d02e..6db2025d 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -466,17 +466,20 @@ def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tens # cmatrix = backend.adjoint(self.wtransform) @ cm @ self.wtransform * 0.25 # return type(self)(self.L, cmatrix=cmatrix) - # def overlap(self, other): - # # ? - # u, v = self.get_bogoliubov_uv() - # u1, v1 = other.get_bogoliubov_uv() - # return backend.det( - # backend.adjoint(u1) @ u + backend.adjoint(v1) @ v - # ) * backend.det(backend.adjoint(v1) @ v), backend.det( - # backend.adjoint(u1) @ u + backend.adjoint(v1) @ v - # ) * backend.det( - # backend.adjoint(u1) @ u - # ) + def overlap(self, other: "FGSSimulator") -> Tensor: + """ + overlap upto a U(1) phase + + :param other: _description_ + :type other: FGSSimulator + :return: _description_ + :rtype: _type_ + """ + u, v = self.get_bogoliubov_uv() + u1, v1 = other.get_bogoliubov_uv() + return backend.sqrt( + backend.abs(backend.det(backend.adjoint(u1) @ u + backend.adjoint(v1) @ v)) + ) npb = get_backend("numpy") diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 526c94ff..6ec87653 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -208,3 +208,22 @@ def test_exp_4body(backend): np.testing.assert_allclose( c.expectation_4body(1, 0, 6, 7), c.expectation_4body(1, 0, 6, 7), atol=1e-5 ) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_overlap(backend): + def compute_overlap(FGScls): + c = FGScls(3, filled=[0, 2]) + c.evol_hp(0, 1, 1.2) + c.evol_hp(1, 2, 0.3) + c.evol_cp(0, 0.5) + c.evol_sp(0, 2, 0.3) + c1 = FGScls(3, filled=[0, 2]) + c1.evol_hp(0, 1, 0.2) + c1.evol_hp(1, 2, 0.6) + c1.evol_sp(1, 0, -1.1) + return tc.backend.abs(c.overlap(c1)) + + np.testing.assert_allclose( + compute_overlap(tc.FGSSimulator), compute_overlap(tc.fgs.FGSTestSimulator), 1e-5 + ) From 3641db966e787950febd6fdcadb3c77bd4c41b11 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 11 Oct 2023 11:18:16 +0800 Subject: [PATCH 042/139] update readme by more projects --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 57b908d4..b76ef176 100644 --- a/README.md +++ b/README.md @@ -388,6 +388,10 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Comparison of Quantum Simulators for Variational Quantum Search: A Benchmark Study: https://arxiv.org/abs/2309.05924. +- Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866. + +- Google Summer of Code 2023 Projects (QML4HEP): https://github.com/ML4SCI/QMLHEP, https://github.com/Gopal-Dahale/qgnn-hep, https://github.com/salcc/QuantumTransformers. + -If you want to highlight your research work here, feel free to add by opening PR. +If you want to highlight your research work or projects here, feel free to add by opening PR. From 126cfe73fc39795afbccf9b948607c78ccb2ef70 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 11 Oct 2023 11:21:08 +0800 Subject: [PATCH 043/139] add iteopt ref --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b76ef176..cb6313c8 100644 --- a/README.md +++ b/README.md @@ -390,6 +390,8 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866. +- Quantum imaginary time evolution and quantum annealing meet topological sector optimization: https://arxiv.org/abs/2310.04291. + - Google Summer of Code 2023 Projects (QML4HEP): https://github.com/ML4SCI/QMLHEP, https://github.com/Gopal-Dahale/qgnn-hep, https://github.com/salcc/QuantumTransformers. From eab1f598b30b2ee8c122b20e84ce70ba91a1a4e5 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 11 Oct 2023 15:38:29 +0800 Subject: [PATCH 044/139] add reduced_wavefunction --- CHANGELOG.md | 2 ++ tensorcircuit/quantum.py | 39 +++++++++++++++++++++++++++++++++++++++ tests/test_quantum.py | 25 +++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d2c684..218e93e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - Add `partial_transpose` and `entanglement_negativity` method in `quantum.py` +- Add `reduced_wavefunction` method in `quantum.py` to get reduced pure state + ### Changed - move ensemble module to applications/ai (breaking changes) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 1a4a84d8..147deffb 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1588,6 +1588,45 @@ def entanglement_entropy(state: Tensor, cut: Union[int, List[int]]) -> Tensor: return entropy(rho) +def reduced_wavefunction( + state: Tensor, cut: List[int], measure: Optional[List[int]] = None +) -> Tensor: + """ + Compute the reduced wavefunction from the quantum state ``state``. + The fixed measure result is guaranteed by users, + otherwise final normalization may required in the return + + :param state: _description_ + :type state: Tensor + :param cut: the list of position for qubit to be reduced + :type cut: List[int] + :param measure: the fixed results of given qubits in the same shape list as ``cut`` + :type measure: List[int] + :return: _description_ + :rtype: Tensor + """ + if measure is None: + measure = [0 for _ in cut] + s = backend.reshape2(state) + n = len(backend.shape_tuple(s)) + s_node = Gate(s) + end_nodes = [] + for c, m in zip(cut, measure): + rt = backend.cast(backend.convert_to_tensor(1 - m), dtypestr) * backend.cast( + backend.convert_to_tensor(np.array([1.0, 0.0])), dtypestr + ) + backend.cast(backend.convert_to_tensor(m), dtypestr) * backend.cast( + backend.convert_to_tensor(np.array([0.0, 1.0])), dtypestr + ) + end_node = Gate(rt) + end_nodes.append(end_node) + s_node[c] ^ end_node[0] + new_node = contractor( + [s_node] + end_nodes, + output_edge_order=[s_node[i] for i in range(n) if i not in cut], + ) + return backend.reshape(new_node.tensor, [-1]) + + def reduced_density_matrix( state: Union[Tensor, QuOperator], cut: Union[int, List[int]], diff --git a/tests/test_quantum.py b/tests/test_quantum.py index 13d06354..2009fbe6 100644 --- a/tests/test_quantum.py +++ b/tests/test_quantum.py @@ -498,3 +498,28 @@ def test_ps2xyz(): xyz.update({"y": []}) assert tc.quantum.ps2xyz([0, 1, 3]) == xyz assert tc.quantum.ps2xyz([0, 1, 3, 0]) == xyz + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_reduced_wavefunction(backend): + c = tc.Circuit(3) + c.h(0) + c.cnot(0, 1) + r = c.cond_measure(0) + s = c.state() + s1 = tc.quantum.reduced_wavefunction(s, [0, 2], [r, 0]) + if tc.backend.cast(r, tc.rdtypestr) < 0.5: + np.testing.assert_allclose(s1, np.array([1, 0]), atol=1e-5) + else: + np.testing.assert_allclose(s1, np.array([0, 1]), atol=1e-5) + + c = tc.Circuit(3) + c.h(0) + c.cnot(0, 1) + s = c.state() + s1 = tc.quantum.reduced_wavefunction(s, [2], [0]) + + c1 = tc.Circuit(2) + c1.h(0) + c1.cnot(0, 1) + np.testing.assert_allclose(s1, c1.state(), atol=1e-5) From 56f1590415f2e3ff50e3ab262febeb8ca49f5dd5 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 17 Oct 2023 15:52:15 +0800 Subject: [PATCH 045/139] update readme --- README.md | 2 +- README_cn.md | 2 +- docs/source/index.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb6313c8..dfd7e68a 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ We also have [Docker support](/docker). ### Status -This project is released by [Tencent Quantum Lab](https://quantum.tencent.com/) and is created and maintained by [Shi-Xin Zhang](https://github.com/refraction-ray) with current core authors [Shi-Xin Zhang](https://github.com/refraction-ray) and [Yu-Qin Chen](https://github.com/yutuer21). We also thank [contributions](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors) from the lab and the open source community. +This project is created and maintained by [Shi-Xin Zhang](https://github.com/refraction-ray) with current core authors [Shi-Xin Zhang](https://github.com/refraction-ray) and [Yu-Qin Chen](https://github.com/yutuer21). We also thank [contributions](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors) from the open source community. ### Citation diff --git a/README_cn.md b/README_cn.md index 56ac6c5c..8137eb85 100644 --- a/README_cn.md +++ b/README_cn.md @@ -123,7 +123,7 @@ pip install tensorcircuit-nightly ### 现况 -该项目由[腾讯量子实验室](https://quantum.tencent.com/)发布,由 [Shi-Xin Zhang](https://github.com/refraction-ray) 创造并维护。当前核心作者包括 [Shi-Xin Zhang](https://github.com/refraction-ray) 和 [Yu-Qin Chen](https://github.com/yutuer21)。我们也感谢来自实验室和开源社区的[贡献](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors)。 +该项目由 [Shi-Xin Zhang](https://github.com/refraction-ray) 创造并维护。当前核心作者包括 [Shi-Xin Zhang](https://github.com/refraction-ray) 和 [Yu-Qin Chen](https://github.com/yutuer21)。我们也感谢来自开源社区的[贡献](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors)。 ### 引用 diff --git a/docs/source/index.rst b/docs/source/index.rst index 9d27204d..bd055a60 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -35,7 +35,7 @@ Relevant Links TensorCircuit is created and maintained by `Shi-Xin Zhang `_ and this version is released by `Tencent Quantum Lab `_. The current core authors of TensorCircuit are `Shi-Xin Zhang `_ and `Yu-Qin Chen `_. -We also thank `contributions `_ from the lab and the open source community. +We also thank `contributions `_ from the open source community. If you have any further questions or collaboration ideas, please use the issue tracker or forum below, or send email to shixinzhang#tencent.com. From 56b44c590f79f02b95b3a1acb9fde4caaefc7278 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 18 Oct 2023 10:19:32 +0800 Subject: [PATCH 046/139] add ref in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index dfd7e68a..834e3847 100644 --- a/README.md +++ b/README.md @@ -388,6 +388,8 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Comparison of Quantum Simulators for Variational Quantum Search: A Benchmark Study: https://arxiv.org/abs/2309.05924. +- Statistical analysis of quantum state learning process in quantum neural networks: https://arxiv.org/abs/2309.14980 (Pubilshed in NeurIPS). + - Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866. - Quantum imaginary time evolution and quantum annealing meet topological sector optimization: https://arxiv.org/abs/2310.04291. From 9959e8c24fc707eaa4266083e8f10c56ac00dacc Mon Sep 17 00:00:00 2001 From: ztzhu1 Date: Tue, 31 Oct 2023 15:05:53 +0800 Subject: [PATCH 047/139] fix(qir2cirq): add a paramter 'args' for _circuit_diagram_info_ to make 'CustomizedCirqGate' work --- tensorcircuit/translation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index f300fc8a..5e8ddea2 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -138,7 +138,9 @@ def _num_qubits_(self) -> int: def _unitary_(self) -> Any: return self.uMatrix - def _circuit_diagram_info_(self) -> List[str]: + def _circuit_diagram_info_( + self, args: Optional[cirq.CircuitDiagramInfoArgs] + ) -> List[str]: return [self.name] * self.nqubit if extra_qir is not None and len(extra_qir) > 0: From da04635846b941d6af638e556dd23f6257565853 Mon Sep 17 00:00:00 2001 From: ztzhu1 Date: Tue, 31 Oct 2023 17:08:40 +0800 Subject: [PATCH 048/139] fix(qir2cirq): make 'args' variable positional arguments (*args) for compatibility --- tensorcircuit/translation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 5e8ddea2..78136967 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -139,7 +139,7 @@ def _unitary_(self) -> Any: return self.uMatrix def _circuit_diagram_info_( - self, args: Optional[cirq.CircuitDiagramInfoArgs] + self, *args: Optional[cirq.CircuitDiagramInfoArgs] ) -> List[str]: return [self.name] * self.nqubit From 12b89723a563a9a760aedea47e450bacf6eb7f4f Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 1 Nov 2023 10:37:15 +0800 Subject: [PATCH 049/139] fix doc typo --- tensorcircuit/backends/abstract_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/backends/abstract_backend.py b/tensorcircuit/backends/abstract_backend.py index 472f0081..cf6884bc 100644 --- a/tensorcircuit/backends/abstract_backend.py +++ b/tensorcircuit/backends/abstract_backend.py @@ -25,7 +25,7 @@ def copy(self: Any, a: Tensor) -> Tensor: :param a: tensor in matrix form :type a: Tensor - :return: matrix exponential of matrix ``a`` + :return: the copy tensor of ``a`` :rtype: Tensor """ raise NotImplementedError( From da19b1cf9c38e2121ad27c28280ad070874b16a3 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 02:40:18 +0000 Subject: [PATCH 050/139] docs: update README.md [skip ci] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 834e3847..df9fc06c 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,9 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. peilin
peilin

💻 ⚠️ 📖 Cristian Emiliano Godinez Ramirez
Cristian Emiliano Godinez Ramirez

💻 ⚠️ + + ztzhu
ztzhu

💻 + From 91433be7c2c38b3f492443bb9159042616d3bbba Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 02:40:19 +0000 Subject: [PATCH 051/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index b76d6a80..74aab495 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -282,6 +282,15 @@ "code", "test" ] + }, + { + "login": "ztzhu1", + "name": "ztzhu", + "avatar_url": "https://avatars.githubusercontent.com/u/111620128?v=4", + "profile": "https://github.com/ztzhu1", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 6, From 9a32bab3697148eb294fd78fc1a038c02da76def Mon Sep 17 00:00:00 2001 From: Yuxuan Yan Date: Thu, 2 Nov 2023 14:08:13 +0800 Subject: [PATCH 052/139] add SHVQE script --- examples/shvqe.py | 237 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 examples/shvqe.py diff --git a/examples/shvqe.py b/examples/shvqe.py new file mode 100644 index 00000000..fdf9d50a --- /dev/null +++ b/examples/shvqe.py @@ -0,0 +1,237 @@ +""" +Schrodinger-Heisenberg quantum variational eigensolver (SHVQE) with DQAS-style optimization. + +DQAS part is modified from: examples/clifford_optimization.py +""" + +import sys +sys.path.insert(0, "../") + +import numpy as np +import tensorflow as tf + +import tensorcircuit as tc +from tensorcircuit.applications.vqes import construct_matrix_v3 + +ctype, rtype = tc.set_dtype("complex64") +K = tc.set_backend("tensorflow") + +n = 10 # the number of qubits (must be even for consistency later) +ncz = 2 # number of cz layers in Schrodinger circuit +nlayersq = ncz + 1 # Schrodinger parameter layers + +# training setup +epochs = 1000 +batch = 1000 + +# Hamiltonian +h6h = np.load("./h6_hamiltonian.npy") # reported in 0.99 A +hamiltonian = construct_matrix_v3(h6h.tolist()) + +def hybrid_ansatz(structure, paramq, preprocess="direct", train=True): + """_summary_ + + Parameters + ---------- + structure : K.Tensor, (n//2, 2) + parameters to decide graph structure of Clifford circuits + paramq : K.Tensor, (nlayersq, n, 3) + parameters in quantum variational circuits, the last layer for Heisenberg circuits + preprocess : str, optional + preprocess, by default "direct" + + Returns + ------- + K.Tensor, [1,] + loss value + """ + c = tc.Circuit(n) + if preprocess == "softmax": + structure = K.softmax(structure, axis=-1) + elif preprocess == "most": + structure = K.onehot(K.argmax(structure, axis=-1), num=2) + elif preprocess == "direct": + pass + + structure = K.cast(structure, ctype) + structure = tf.reshape(structure, shape=[n//2, 2]) + + # quantum variational in Schrodinger part, first consider a ring topol + for j in range(nlayersq): + if j !=0 and j!=nlayersq-1: + for i in range(j%2,n,2): + c.cz(i, (i+1)%n) + for i in range(n): + c.rx(i, theta=paramq[j, i, 0]) + c.ry(i, theta=paramq[j, i, 1]) + c.rz(i, theta=paramq[j, i, 2]) + + # Clifford part, which is actually virtual + if train: + for j in range(0,n//2-1): + dis = j + 1 + for i in range(0,n): + c.unitary( + i, + (i+dis) % n, + unitary=structure[j, 0] * tc.gates.ii().tensor + + structure[j, 1] * tc.gates.cz().tensor, + ) + + for i in range(0,n//2): + c.unitary( + i, + i + n//2, + unitary=structure[n//2-1, 0] * tc.gates.ii().tensor + + structure[n//2-1, 1] * tc.gates.cz().tensor, + ) + else: # if not for training, we just put nontrivial gates + for j in range(0,n//2-1): + dis = j + 1 + for i in range(0,n): + if structure[j, 1]==1: + c.cz(i, (i+dis) % n) + + for i in range(0,n//2): + if structure[j, 1]==1: + c.cz(i, i + n//2) + + return c + +def hybrid_vqe(structure, paramq, preprocess="direct"): + """_summary_ + + Parameters + ---------- + structure : K.Tensor, (n//2, 2) + parameters to decide graph structure of Clifford circuits + paramq : K.Tensor, (nlayersq, n, 3) + parameters in quantum variational circuits, the last layer for Heisenberg circuits + preprocess : str, optional + preprocess, by default "direct" + + Returns + ------- + K.Tensor, [1,] + loss value + """ + c = hybrid_ansatz(structure, paramq, preprocess) + return tc.templates.measurements.operator_expectation(c, hamiltonian) + +def sampling_from_structure(structures, batch=1): + ch = structures.shape[-1] + prob = K.softmax(K.real(structures), axis=-1) + prob = K.reshape(prob, [-1, ch]) + p = prob.shape[0] + r = np.stack( + np.array( + [np.random.choice(ch, p=K.numpy(prob[i]), size=[batch]) for i in range(p)] + ) + ) + return r.transpose() + + +@K.jit +def best_from_structure(structures): + return K.argmax(structures, axis=-1) + + +def nmf_gradient(structures, oh): + """ compute the Monte Carlo gradient with respect of naive mean-field probabilistic model + + Parameters + ---------- + structures : K.Tensor, (n//2, ch) + structure parameter for single- or two-qubit gates + oh : K.Tensor, (n//2, ch), onehot + a given structure sampled via strcuture parameters (in main function) + + Returns + ------- + K.Tensor, (n//2 * 2, ch) == (n, ch) + MC gradients + """ + choice = K.argmax(oh, axis=-1) + prob = K.softmax(K.real(structures), axis=-1) + indices = K.transpose( + K.stack([K.cast(tf.range(structures.shape[0]), "int64"), choice]) + ) + prob = tf.gather_nd(prob, indices) + prob = K.reshape(prob, [-1, 1]) + prob = K.tile(prob, [1, structures.shape[-1]]) + + return K.real( + tf.tensor_scatter_nd_add( + tf.cast(-prob, dtype=ctype), + indices, + tf.ones([structures.shape[0]], dtype=ctype), + ) + ) # in oh : 1-p, not in oh : -p + +# vmap for a batch of structures +nmf_gradient_vmap = K.jit( + K.vmap(nmf_gradient, vectorized_argnums=1)) + +# vvag for a batch of structures +vvag_hybrid = K.jit( + K.vectorized_value_and_grad(hybrid_vqe, vectorized_argnums=(0,), argnums=(1,)), + static_argnums=(2,)) + +def train_hybrid(stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, verbose=False): + # params = K.implicit_randn([n//2, 2], stddev=stddev) + params = K.ones([n//2, 2], dtype=float) + paramq = K.implicit_randn([nlayersq, n, 3], stddev=stddev) * 2*np.pi + if lr is None: + lr = tf.keras.optimizers.schedules.ExponentialDecay(0.6, 100, 0.8) + structure_opt = K.optimizer(tf.keras.optimizers.Adam(lr)) + + avcost = 0 + avcost2 = 0 + loss_history = [] + for epoch in range(epochs): # iteration to update strcuture param + # random sample some structures + batched_stucture = K.onehot( + sampling_from_structure(params, batch=batch), + num=params.shape[-1], + ) + vs, gq = vvag_hybrid(batched_stucture, paramq, "direct") + loss_history.append(np.min(vs)) + gq = gq[0] + avcost = K.mean(vs) # average cost of the batch + gs = nmf_gradient_vmap(params, batched_stucture) # \nabla lnp + gs = K.mean(K.reshape(vs - avcost2, [-1, 1, 1]) * gs, axis=0) + # avcost2 is averaged cost in the last epoch + avcost2 = avcost + + [params, paramq] = structure_opt.update([gs, gq], [params, paramq]) + if epoch % debug_step == 0 or epoch == epochs - 1: + print("----------epoch %s-----------" % epoch) + print( + "batched average loss: ", + np.mean(vs), + "minimum candidate loss: ", + np.min(vs), + ) + + # max over choices, min over layers and qubits + minp = tf.math.reduce_min(tf.math.reduce_max(tf.math.softmax(params), axis=-1)) + if minp > 0.5: + print("probability converged") + + if verbose: + print( + "strcuture parameter: \n", + params.numpy() + ) + + cand_preset = best_from_structure(params) + print(cand_preset) + print("current recommendation loss: ", hybrid_vqe(params, paramq, "most")) + + loss_history = np.array(loss_history) + return hybrid_vqe(params, paramq, "most"), params, paramq, loss_history + + +print('Train hybrid.') +ee, params, paramq, loss_history = train_hybrid(epochs=epochs, batch=batch, verbose=True) +print('Energy:', ee) From 84c3f544c96ba745fc1edf93a3a4ba7b6d05b63e Mon Sep 17 00:00:00 2001 From: Yuxuan Date: Thu, 2 Nov 2023 09:37:32 -0700 Subject: [PATCH 053/139] reformat the SHVQE script --- examples/shvqe.py | 87 ++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/examples/shvqe.py b/examples/shvqe.py index fdf9d50a..4083fa6d 100644 --- a/examples/shvqe.py +++ b/examples/shvqe.py @@ -5,6 +5,7 @@ """ import sys + sys.path.insert(0, "../") import numpy as np @@ -16,9 +17,9 @@ ctype, rtype = tc.set_dtype("complex64") K = tc.set_backend("tensorflow") -n = 10 # the number of qubits (must be even for consistency later) -ncz = 2 # number of cz layers in Schrodinger circuit -nlayersq = ncz + 1 # Schrodinger parameter layers +n = 10 # the number of qubits (must be even for consistency later) +ncz = 2 # number of cz layers in Schrodinger circuit +nlayersq = ncz + 1 # Schrodinger parameter layers # training setup epochs = 1000 @@ -28,6 +29,7 @@ h6h = np.load("./h6_hamiltonian.npy") # reported in 0.99 A hamiltonian = construct_matrix_v3(h6h.tolist()) + def hybrid_ansatz(structure, paramq, preprocess="direct", train=True): """_summary_ @@ -54,13 +56,13 @@ def hybrid_ansatz(structure, paramq, preprocess="direct", train=True): pass structure = K.cast(structure, ctype) - structure = tf.reshape(structure, shape=[n//2, 2]) + structure = tf.reshape(structure, shape=[n // 2, 2]) # quantum variational in Schrodinger part, first consider a ring topol for j in range(nlayersq): - if j !=0 and j!=nlayersq-1: - for i in range(j%2,n,2): - c.cz(i, (i+1)%n) + if j != 0 and j != nlayersq - 1: + for i in range(j % 2, n, 2): + c.cz(i, (i + 1) % n) for i in range(n): c.rx(i, theta=paramq[j, i, 0]) c.ry(i, theta=paramq[j, i, 1]) @@ -68,36 +70,37 @@ def hybrid_ansatz(structure, paramq, preprocess="direct", train=True): # Clifford part, which is actually virtual if train: - for j in range(0,n//2-1): + for j in range(0, n // 2 - 1): dis = j + 1 - for i in range(0,n): + for i in range(0, n): c.unitary( i, - (i+dis) % n, + (i + dis) % n, unitary=structure[j, 0] * tc.gates.ii().tensor + structure[j, 1] * tc.gates.cz().tensor, ) - for i in range(0,n//2): + for i in range(0, n // 2): c.unitary( i, - i + n//2, - unitary=structure[n//2-1, 0] * tc.gates.ii().tensor - + structure[n//2-1, 1] * tc.gates.cz().tensor, + i + n // 2, + unitary=structure[n // 2 - 1, 0] * tc.gates.ii().tensor + + structure[n // 2 - 1, 1] * tc.gates.cz().tensor, ) - else: # if not for training, we just put nontrivial gates - for j in range(0,n//2-1): + else: # if not for training, we just put nontrivial gates + for j in range(0, n // 2 - 1): dis = j + 1 - for i in range(0,n): - if structure[j, 1]==1: - c.cz(i, (i+dis) % n) + for i in range(0, n): + if structure[j, 1] == 1: + c.cz(i, (i + dis) % n) - for i in range(0,n//2): - if structure[j, 1]==1: - c.cz(i, i + n//2) + for i in range(0, n // 2): + if structure[j, 1] == 1: + c.cz(i, i + n // 2) return c + def hybrid_vqe(structure, paramq, preprocess="direct"): """_summary_ @@ -118,6 +121,7 @@ def hybrid_vqe(structure, paramq, preprocess="direct"): c = hybrid_ansatz(structure, paramq, preprocess) return tc.templates.measurements.operator_expectation(c, hamiltonian) + def sampling_from_structure(structures, batch=1): ch = structures.shape[-1] prob = K.softmax(K.real(structures), axis=-1) @@ -137,7 +141,7 @@ def best_from_structure(structures): def nmf_gradient(structures, oh): - """ compute the Monte Carlo gradient with respect of naive mean-field probabilistic model + """compute the Monte Carlo gradient with respect of naive mean-field probabilistic model Parameters ---------- @@ -166,21 +170,25 @@ def nmf_gradient(structures, oh): indices, tf.ones([structures.shape[0]], dtype=ctype), ) - ) # in oh : 1-p, not in oh : -p + ) # in oh : 1-p, not in oh : -p + # vmap for a batch of structures -nmf_gradient_vmap = K.jit( - K.vmap(nmf_gradient, vectorized_argnums=1)) +nmf_gradient_vmap = K.jit(K.vmap(nmf_gradient, vectorized_argnums=1)) # vvag for a batch of structures vvag_hybrid = K.jit( K.vectorized_value_and_grad(hybrid_vqe, vectorized_argnums=(0,), argnums=(1,)), - static_argnums=(2,)) + static_argnums=(2,), +) + -def train_hybrid(stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, verbose=False): +def train_hybrid( + stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, verbose=False +): # params = K.implicit_randn([n//2, 2], stddev=stddev) - params = K.ones([n//2, 2], dtype=float) - paramq = K.implicit_randn([nlayersq, n, 3], stddev=stddev) * 2*np.pi + params = K.ones([n // 2, 2], dtype=float) + paramq = K.implicit_randn([nlayersq, n, 3], stddev=stddev) * 2 * np.pi if lr is None: lr = tf.keras.optimizers.schedules.ExponentialDecay(0.6, 100, 0.8) structure_opt = K.optimizer(tf.keras.optimizers.Adam(lr)) @@ -197,7 +205,7 @@ def train_hybrid(stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, ve vs, gq = vvag_hybrid(batched_stucture, paramq, "direct") loss_history.append(np.min(vs)) gq = gq[0] - avcost = K.mean(vs) # average cost of the batch + avcost = K.mean(vs) # average cost of the batch gs = nmf_gradient_vmap(params, batched_stucture) # \nabla lnp gs = K.mean(K.reshape(vs - avcost2, [-1, 1, 1]) * gs, axis=0) # avcost2 is averaged cost in the last epoch @@ -214,15 +222,14 @@ def train_hybrid(stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, ve ) # max over choices, min over layers and qubits - minp = tf.math.reduce_min(tf.math.reduce_max(tf.math.softmax(params), axis=-1)) + minp = tf.math.reduce_min( + tf.math.reduce_max(tf.math.softmax(params), axis=-1) + ) if minp > 0.5: print("probability converged") if verbose: - print( - "strcuture parameter: \n", - params.numpy() - ) + print("strcuture parameter: \n", params.numpy()) cand_preset = best_from_structure(params) print(cand_preset) @@ -232,6 +239,8 @@ def train_hybrid(stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, ve return hybrid_vqe(params, paramq, "most"), params, paramq, loss_history -print('Train hybrid.') -ee, params, paramq, loss_history = train_hybrid(epochs=epochs, batch=batch, verbose=True) -print('Energy:', ee) +print("Train hybrid.") +ee, params, paramq, loss_history = train_hybrid( + epochs=epochs, batch=batch, verbose=True +) +print("Energy:", ee) From 6f8e490185f02891fc76ea79c99bf22ff984fee6 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 3 Nov 2023 06:13:38 +0000 Subject: [PATCH 054/139] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index df9fc06c..e1718e30 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. ztzhu
ztzhu

💻 + Rabqubit
Rabqubit

💡 From 9898e2d77260f5e5965949ea2816c157ecedf953 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 3 Nov 2023 06:13:39 +0000 Subject: [PATCH 055/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 74aab495..ad7f098d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -291,6 +291,15 @@ "contributions": [ "code" ] + }, + { + "login": "royess", + "name": "Rabqubit", + "avatar_url": "https://avatars.githubusercontent.com/u/31059422?v=4", + "profile": "https://github.com/royess", + "contributions": [ + "example" + ] } ], "contributorsPerLine": 6, From 9b614f82033fac31354989f931a52d4b6aaa0c35 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 28 Nov 2023 16:46:54 +0800 Subject: [PATCH 056/139] add env variable for eps of entropy --- tensorcircuit/quantum.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 147deffb..383259c2 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -9,6 +9,7 @@ """ # pylint: disable=invalid-name +import os from functools import reduce, partial import logging from operator import or_, mul, matmul @@ -1503,7 +1504,7 @@ def op2tensor( @op2tensor -def entropy(rho: Union[Tensor, QuOperator], eps: float = 1e-12) -> Tensor: +def entropy(rho: Union[Tensor, QuOperator], eps: Optional[float] = None) -> Tensor: """ Compute the entropy from the given density matrix ``rho``. @@ -1541,6 +1542,11 @@ def entanglement2(param, n, nlayers): :return: Entropy on the given density matrix. :rtype: Tensor """ + eps_env = os.environ.get("TC_QUANTUM_ENTROPY_EPS") + if eps is None and eps_env is None: + eps = 1e-12 + elif eps is None and eps_env is not None: + eps = 10 ** (-int(eps_env)) rho += eps * backend.cast(backend.eye(rho.shape[-1]), rho.dtype) # type: ignore lbd = backend.real(backend.eigh(rho)[0]) lbd = backend.relu(lbd) From 3498f0a91df2193c0f767da0b33894138e3a9b6b Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 4 Dec 2023 12:06:29 +0800 Subject: [PATCH 057/139] fix requirements --- requirements/requirements-extra.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 80fff586..787c6cae 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,9 +1,9 @@ # extra dependencies for ci qiskit==0.43 -qiskit-nature +# qiskit-nature +mitiq cirq torch jupyter mthree==1.1.0 -mitiq openfermion From 0ce8afdecff92482756e771e4df1b8631bec3455 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 8 Dec 2023 19:42:11 +0800 Subject: [PATCH 058/139] add evol_gh in fgs --- tensorcircuit/fgs.py | 18 ++++++++++++++++++ tests/test_fgs.py | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index 6db2025d..dfb8b794 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -230,6 +230,19 @@ def evol_ihamiltonian(self, h: Tensor) -> None: self.orthogonal() self.cmatrix = None + def evol_ghamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-1/2 i \hat{h}}` with h generally non-Hermitian + + :param h: _description_ + :type h: Tensor + """ + # e^{-1/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(-1.0j * backend.adjoint(h)) @ self.alpha + self.orthogonal() + self.cmatrix = None + def orthogonal(self) -> None: q, _ = backend.qr(self.alpha) self.alpha = q @@ -579,6 +592,11 @@ def evol_ihamiltonian(self, h: Tensor) -> None: self.state = npb.reshape(self.state, [-1]) self.orthogonal() + def evol_ghamiltonian(self, h: Tensor) -> None: + self.state = npb.expm(-1 / 2 * 1.0j * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) + self.orthogonal() + def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: self.evol_hamiltonian(self.hopping_jw(chi, i, j, self.L)) diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 6ec87653..36bae00e 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -16,6 +16,23 @@ @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_cmatrix(backend, highp): + import openfermion + + def asymmetric_hopping(J, gamma, i, j, L): + m0 = tc.fgs.onehot_matrix(i, j, 2 * L) - tc.fgs.onehot_matrix( + j + L, i + L, 2 * L + ) + m = (J + gamma) * m0 + (J - gamma) * tc.backend.adjoint(m0) + return m / 2 + + def asymmetric_hopping_jw(J, gamma, i, j, L): + op = (J + gamma) * openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + np.conj( + J - gamma + ) * openfermion.FermionOperator(f"{str(j)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + c = tc.fgs.FGSSimulator(4, [0]) c1 = tc.fgs.FGSTestSimulator(4, [0]) c.evol_hp(0, 1, 1.2) @@ -26,6 +43,8 @@ def test_cmatrix(backend, highp): c1.evol_cp(0, -0.8) c.evol_sp(1, 0, 0.5) c1.evol_sp(1, 0, 0.5) + c.evol_ghamiltonian(asymmetric_hopping(1, 0.5, 0, 2, 4)) + c1.evol_ghamiltonian(np.array(asymmetric_hopping_jw(1, 0.5, 0, 2, 4))) c.evol_sp(1, 2, 1.5) c1.evol_sp(1, 2, 1.5) c.evol_ihamiltonian(c.chemical_potential(1.0, 1, 4)) From fc2fb0650e40a019ae18ec4cabd0a79cc2b0f041 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 15 Dec 2023 11:15:48 +0800 Subject: [PATCH 059/139] fix cu qiskit translation --- CHANGELOG.md | 2 ++ tensorcircuit/translation.py | 3 ++- tests/test_circuit.py | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 218e93e2..54e26b8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ - Support degenerate eigenvalue for jax backend `eigh` method when using AD +- Fixed `cu` gate translation from qiskit to avoid qiskit bug + ## 0.11.0 ### Added diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 78136967..866cf4c1 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -523,7 +523,8 @@ def qiskit2tc( tc_circuit.multicontrol( *idx, ctrl=ctrl_state, unitary=gates._x_matrix, name="x" ) - elif gate_name[0] == "c" and gate_name[:7] != "circuit": + elif gate_name[0] == "c" and gate_name[:7] != "circuit" and gate_name != "cu": + # qiskit cu bug, see https://github.com/tencent-quantum-lab/tensorcircuit/issues/199 for i in range(1, len(gate_name)): if (gate_name[-i] == "o") & (gate_name[-i - 1] == "_"): break diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 10a73971..cb67eb36 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1105,6 +1105,9 @@ def test_qiskit2tc(): qisc.x(3) qisc.y(3) qisc.z(3) + qisc.cu( + 5.868768495722669, 2.24809352294186, 3.59102783505607, 2.0223650288392, 1, 3 + ) qisc.cnot(0, 1) qisc.cy(0, 1) qisc.cz(0, 1, ctrl_state=0) From 0d60be4b37e64183b1be28d656a738ec7e83dc8a Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 15 Dec 2023 11:20:03 +0800 Subject: [PATCH 060/139] add refs in readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e1718e30..daaad5ea 100644 --- a/README.md +++ b/README.md @@ -400,6 +400,10 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Google Summer of Code 2023 Projects (QML4HEP): https://github.com/ML4SCI/QMLHEP, https://github.com/Gopal-Dahale/qgnn-hep, https://github.com/salcc/QuantumTransformers. +- Absence of barren plateaus in finite local-depth circuits with long-range entanglement: https://arxiv.org/abs/2311.01393. + +- Non-Markovianity benefits quantum dynamics simulation: https://arxiv.org/abs/2311.17622. + If you want to highlight your research work or projects here, feel free to add by opening PR. From 9e034d681150aa8a3957c6e88c8dd47c62650ef1 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 21 Dec 2023 10:30:13 +0800 Subject: [PATCH 061/139] fix requirements --- requirements/requirements-extra.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 787c6cae..17c1438f 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,5 +1,5 @@ # extra dependencies for ci -qiskit==0.43 +qiskit # qiskit-nature mitiq cirq From 4e615fba8c3d161a0b006e6f09c36eb5caf4cd22 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 21 Dec 2023 12:13:56 +0800 Subject: [PATCH 062/139] fix reqs --- requirements/requirements-extra.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 17c1438f..63d1824f 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -4,6 +4,6 @@ qiskit mitiq cirq torch -jupyter +# jupyter mthree==1.1.0 openfermion From e2cc48b6f7e0ba8a0849b09699e91237335ff082 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 21 Dec 2023 17:07:24 +0800 Subject: [PATCH 063/139] fix for future qiskit --- requirements/requirements-extra.txt | 1 + tensorcircuit/translation.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 63d1824f..024c584f 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,5 +1,6 @@ # extra dependencies for ci qiskit +qiskit_aer # qiskit-nature mitiq cirq diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 866cf4c1..e297113d 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -342,7 +342,7 @@ def qir2qiskit( qop = qi.Operator(gatem) try: qiskit_circ.unitary(qop, index[::-1], label=qis_name) - except ExtensionError: + except (ExtensionError, ValueError) as _: logger.warning( "omit non unitary gate in tensorcircuit when transforming to qiskit: %s" % gate_name From 9d60c64668a754886a9f45120234ed26d3191395 Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Mon, 15 Jan 2024 11:21:44 +0900 Subject: [PATCH 064/139] Update cons.py --- tensorcircuit/cons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/cons.py b/tensorcircuit/cons.py index 5c3fb78d..e7e4bccf 100644 --- a/tensorcircuit/cons.py +++ b/tensorcircuit/cons.py @@ -152,7 +152,7 @@ def set_dtype(dtype: Optional[str] = None, set_global: bool = True) -> Tuple[str raise ValueError(f"Unsupported data type: {dtype}") try: - from jax.config import config + from jax import config except ImportError: config = None # type: ignore From 0c2433cb4c962dee9ffa150a493c5c7db773f7d8 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 03:30:07 +0000 Subject: [PATCH 065/139] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index daaad5ea..46a70c2a 100644 --- a/README.md +++ b/README.md @@ -297,6 +297,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. ztzhu
ztzhu

💻 Rabqubit
Rabqubit

💡 + Kazuki Tsuoka
Kazuki Tsuoka

💻 From 7105cfb59901cf3c408a958a616ccf2ceec65d20 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 03:30:08 +0000 Subject: [PATCH 066/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index ad7f098d..4b928ff4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -300,6 +300,15 @@ "contributions": [ "example" ] + }, + { + "login": "king-p3nguin", + "name": "Kazuki Tsuoka", + "avatar_url": "https://avatars.githubusercontent.com/u/103920010?v=4", + "profile": "https://github.com/king-p3nguin", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 6, From 11fc3b6c44a97c1cce01fee49b564bee34bebbc3 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 17 Jan 2024 15:42:41 +0800 Subject: [PATCH 067/139] add 2-otoc support for fgs --- tensorcircuit/fgs.py | 176 +++++++++++++++++++++++++++++++++++++++++-- tests/test_fgs.py | 19 +++++ 2 files changed, 189 insertions(+), 6 deletions(-) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index dfb8b794..e0e36d43 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -1,7 +1,7 @@ """ Fermion Gaussian state simulator """ -from typing import Any, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple import numpy as np @@ -74,8 +74,10 @@ def __init__( _, _, self.alpha = self.fermion_diagonalization(hc, L) else: self.alpha = alpha + self.alpha0 = self.alpha self.wtransform = self.wmatrix(L) self.cmatrix = cmatrix + self.otcmatrix: Dict[Tuple[int, int], Tensor] = {} @classmethod def fermion_diagonalization( @@ -141,13 +143,35 @@ def init_alpha(filled: List[int], L: int) -> Tensor: def get_alpha(self) -> Tensor: return self.alpha - def get_cmatrix(self) -> Tensor: - if self.cmatrix is not None: + def get_cmatrix(self, now_i: bool = True, now_j: bool = True) -> Tensor: + # otoc in FGS language, see: https://arxiv.org/pdf/1908.03292.pdf + # https://journals.aps.org/prb/pdf/10.1103/PhysRevB.99.054205 + # otoc for non=hermitian system is more subtle due to the undefined normalization + # of operator and not considered here, see: https://arxiv.org/pdf/2305.12054.pdf + if self.cmatrix is not None and now_i is True and now_j is True: return self.cmatrix - else: + elif now_i is True and now_j is True: cmatrix = self.alpha @ backend.adjoint(self.alpha) self.cmatrix = cmatrix return cmatrix + elif now_i is True: # new i old j + if (1, 0) in self.otcmatrix: + return self.otcmatrix[(1, 0)] + cmatrix = self.alpha @ backend.adjoint(self.alpha0) + self.otcmatrix[(1, 0)] = cmatrix + return cmatrix + elif now_j is True: # old i new j + if (0, 1) in self.otcmatrix: + return self.otcmatrix[(0, 1)] + cmatrix = self.alpha0 @ backend.adjoint(self.alpha) + self.otcmatrix[(0, 1)] = cmatrix + return cmatrix + else: # initial cmatrix + if (0, 0) in self.otcmatrix: + return self.otcmatrix[(0, 0)] + cmatrix = self.alpha0 @ backend.adjoint(self.alpha0) + self.otcmatrix[(0, 0)] = cmatrix + return cmatrix def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor: m = self.get_cmatrix() @@ -216,6 +240,7 @@ def evol_hamiltonian(self, h: Tensor) -> None: h = backend.cast(h, dtype=dtypestr) self.alpha = backend.expm(-1.0j * h) @ self.alpha self.cmatrix = None + self.otcmatrix = {} def evol_ihamiltonian(self, h: Tensor) -> None: r""" @@ -229,6 +254,7 @@ def evol_ihamiltonian(self, h: Tensor) -> None: self.alpha = backend.expm(h) @ self.alpha self.orthogonal() self.cmatrix = None + self.otcmatrix = {} def evol_ghamiltonian(self, h: Tensor) -> None: r""" @@ -242,6 +268,7 @@ def evol_ghamiltonian(self, h: Tensor) -> None: self.alpha = backend.expm(-1.0j * backend.adjoint(h)) @ self.alpha self.orthogonal() self.cmatrix = None + self.otcmatrix = {} def orthogonal(self) -> None: q, _ = backend.qr(self.alpha) @@ -350,7 +377,9 @@ def get_covariance_matrix(self) -> Tensor: m = self.get_cmatrix_majorana() return -1.0j * (2 * m - backend.eye(self.L * 2)) - def expectation_2body(self, i: int, j: int) -> Tensor: + def expectation_2body( + self, i: int, j: int, now_i: bool = True, now_j: bool = True + ) -> Tensor: """ expectation of two fermion terms convention: (c, c^\dagger) @@ -363,7 +392,7 @@ def expectation_2body(self, i: int, j: int) -> Tensor: :return: _description_ :rtype: Tensor """ - return self.get_cmatrix()[i][(j + self.L) % (2 * self.L)] + return self.get_cmatrix(now_i, now_j)[i][(j + self.L) % (2 * self.L)] def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: """ @@ -520,6 +549,7 @@ def __init__( self.state = self.fermion_diagonalization(hc, L) else: self.state = self.init_state(filled, L) + self.state0 = self.state @staticmethod def init_state(filled: List[int], L: int) -> Tensor: @@ -621,6 +651,140 @@ def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None: def orthogonal(self) -> None: self.state /= backend.norm(self.state) + def get_ot_cmatrix(self, h: Tensor, now_i: bool = True) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(self.L): + for j in range(self.L): + op1 = openfermion.FermionOperator(f"{str(i)}") + op2 = openfermion.FermionOperator(f"{str(j)}^") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L): + op1 = openfermion.FermionOperator(f"{str(i-self.L)}^") + op2 = openfermion.FermionOperator(f"{str(j)}^") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + for i in range(self.L): + for j in range(self.L, 2 * self.L): + op1 = openfermion.FermionOperator(f"{str(i)}") + op2 = openfermion.FermionOperator(f"{str(j-self.L)}") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L, 2 * self.L): + op1 = openfermion.FermionOperator(f"{str(i-self.L)}^ ") + op2 = openfermion.FermionOperator(f"{str(j-self.L)}") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + return cmatrix + def get_cmatrix(self) -> Tensor: alpha1_jw = self.state cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) diff --git a/tests/test_fgs.py b/tests/test_fgs.py index 36bae00e..dd307b3c 100644 --- a/tests/test_fgs.py +++ b/tests/test_fgs.py @@ -59,6 +59,25 @@ def asymmetric_hopping_jw(J, gamma, i, j, L): ) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_otoc(backend, highp): + c = tc.FGSSimulator(4, [0, 1]) + c1 = tc.fgs.FGSTestSimulator(4, [0, 1]) + h = c.hopping(0.6, 1, 2, 4) + h += c.hopping(-0.8, 3, 2, 4) + h += c.chemical_potential(0.3, 2, 4) + h1 = c1.hopping_jw(0.6, 1, 2, 4) + h1 += c1.hopping_jw(-0.8, 3, 2, 4) + h1 += c1.chemical_potential_jw(0.3, 2, 4) + c.evol_hamiltonian(h) + m = c.get_cmatrix(now_i=True, now_j=False) + m0 = c1.get_ot_cmatrix(h1) + np.testing.assert_allclose(m, m0, atol=1e-5) + m = c.get_cmatrix(now_i=False, now_j=True) + m0 = c1.get_ot_cmatrix(h1, now_i=False) + np.testing.assert_allclose(m, m0, atol=1e-5) + + @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) def test_fgs_ad(backend, highp): import optax From 86026fa186dbc8f5c8f311373f6822d455fe2d4b Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 29 Jan 2024 20:40:45 +0800 Subject: [PATCH 068/139] new black --- .../source/tutorials/barren_plateaus_cn.ipynb | 4 +- docs/source/tutorials/nnvqe_cn.ipynb | 4 +- .../optimization_and_expressibility_cn.ipynb | 4 +- .../tutorials/tfim_vqe_diffreph_cn.ipynb | 4 +- examples/matprod_vmap.py | 1 + tensorcircuit/abstractcircuit.py | 1 + tensorcircuit/applications/dqas.py | 7 +-- tensorcircuit/applications/layers.py | 1 + tensorcircuit/applications/physics/fss.py | 1 + tensorcircuit/applications/utils.py | 1 + tensorcircuit/applications/vags.py | 1 + tensorcircuit/applications/vqes.py | 1 + tensorcircuit/asciiart.py | 1 + tensorcircuit/backends/abstract_backend.py | 46 +++++++++++-------- tensorcircuit/backends/cupy_backend.py | 1 + tensorcircuit/backends/jax_backend.py | 1 + tensorcircuit/backends/jax_ops.py | 1 + tensorcircuit/backends/numpy_backend.py | 1 + tensorcircuit/backends/pytorch_backend.py | 1 + tensorcircuit/backends/pytorch_ops.py | 1 + tensorcircuit/backends/tensorflow_backend.py | 1 + tensorcircuit/backends/tf_ops.py | 1 + tensorcircuit/basecircuit.py | 1 + tensorcircuit/circuit.py | 1 + tensorcircuit/cloud/utils.py | 1 + tensorcircuit/cloud/wrapper.py | 1 + tensorcircuit/compiler/__init__.py | 1 + tensorcircuit/cons.py | 1 + tensorcircuit/densitymatrix.py | 9 ++-- tensorcircuit/fgs.py | 1 + tensorcircuit/mps_base.py | 1 + tensorcircuit/mpscircuit.py | 1 + tensorcircuit/noisemodel.py | 1 + tensorcircuit/quantum.py | 1 + tensorcircuit/results/counts.py | 1 + tensorcircuit/results/readout_mitigation.py | 9 ++-- tensorcircuit/simplify.py | 1 + tensorcircuit/templates/blocks.py | 1 + tensorcircuit/templates/graphs.py | 1 + tensorcircuit/templates/measurements.py | 1 + tensorcircuit/vis.py | 1 + 41 files changed, 87 insertions(+), 33 deletions(-) diff --git a/docs/source/tutorials/barren_plateaus_cn.ipynb b/docs/source/tutorials/barren_plateaus_cn.ipynb index 4288475f..6f5a8a49 100644 --- a/docs/source/tutorials/barren_plateaus_cn.ipynb +++ b/docs/source/tutorials/barren_plateaus_cn.ipynb @@ -158,7 +158,9 @@ " dtype=\"float32\",\n", ")\n", "\n", - "e, grad = op_expectation_vmap_vvag(params, seed, n, nlayers) # 不同随机电路的 ZZ 可观测量和梯度的期望\n", + "e, grad = op_expectation_vmap_vvag(\n", + " params, seed, n, nlayers\n", + ") # 不同随机电路的 ZZ 可观测量和梯度的期望\n", "\n", "grad_var = tf.math.reduce_std(tf.math.reduce_std(grad, axis=0), axis=0)[\n", " 0, 0\n", diff --git a/docs/source/tutorials/nnvqe_cn.ipynb b/docs/source/tutorials/nnvqe_cn.ipynb index df6e0871..056990bb 100644 --- a/docs/source/tutorials/nnvqe_cn.ipynb +++ b/docs/source/tutorials/nnvqe_cn.ipynb @@ -115,7 +115,9 @@ "metadata": {}, "outputs": [], "source": [ - "def MERA(inp, n, d=1, lamb=1.0, energy_flag=False): # 对于单变量一维XXZ模型,我们固定lamb\n", + "def MERA(\n", + " inp, n, d=1, lamb=1.0, energy_flag=False\n", + "): # 对于单变量一维XXZ模型,我们固定lamb\n", " params = K.cast(inp[\"params\"], \"complex128\")\n", " delta = K.cast(inp[\"delta\"], \"complex128\")\n", " c = tc.Circuit(n)\n", diff --git a/docs/source/tutorials/optimization_and_expressibility_cn.ipynb b/docs/source/tutorials/optimization_and_expressibility_cn.ipynb index 3fdaa7a8..e09df93c 100644 --- a/docs/source/tutorials/optimization_and_expressibility_cn.ipynb +++ b/docs/source/tutorials/optimization_and_expressibility_cn.ipynb @@ -276,7 +276,9 @@ "@tf.function\n", "def entropy(v):\n", " ψ = get_state(v)\n", - " ρ_reduced = tc.quantum.reduced_density_matrix(ψ, NA) # 部分描绘出子系统A得到的降密度矩阵\n", + " ρ_reduced = tc.quantum.reduced_density_matrix(\n", + " ψ, NA\n", + " ) # 部分描绘出子系统A得到的降密度矩阵\n", " S = tc.quantum.renyi_entropy(ρ_reduced) # Renyi 纠缠熵\n", " return S" ] diff --git a/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb b/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb index eca8c1ad..14a5cbea 100644 --- a/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb +++ b/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb @@ -420,7 +420,9 @@ "\n", "Jx = np.array([1.0 for _ in range(n - 1)]) # xx 相互作用的强度 (OBC)\n", "Bz = np.array([1.0 for _ in range(n)]) # 横向场强\n", - "hamiltonian_mpo = tn.matrixproductstates.mpo.FiniteTFI(Jx, Bz, dtype=dtype) # 矩阵乘积算子\n", + "hamiltonian_mpo = tn.matrixproductstates.mpo.FiniteTFI(\n", + " Jx, Bz, dtype=dtype\n", + ") # 矩阵乘积算子\n", "hamiltonian_mpo = quoperator_mpo(hamiltonian_mpo) # 从 mpo 生成 QuOperator" ] }, diff --git a/examples/matprod_vmap.py b/examples/matprod_vmap.py index e1c6954b..bbf8f137 100644 --- a/examples/matprod_vmap.py +++ b/examples/matprod_vmap.py @@ -2,6 +2,7 @@ matrix product: a new twist rewrite matrix product in a vmap style """ + from functools import partial import numpy as np diff --git a/tensorcircuit/abstractcircuit.py b/tensorcircuit/abstractcircuit.py index 46c549c9..ac2b9116 100644 --- a/tensorcircuit/abstractcircuit.py +++ b/tensorcircuit/abstractcircuit.py @@ -1,6 +1,7 @@ """ Methods for abstract circuits independent of nodes, edges and contractions """ + # pylint: disable=invalid-name from typing import Any, Callable, Dict, List, Optional, Sequence, Union, Tuple diff --git a/tensorcircuit/applications/dqas.py b/tensorcircuit/applications/dqas.py index d139fe01..161a2c73 100644 --- a/tensorcircuit/applications/dqas.py +++ b/tensorcircuit/applications/dqas.py @@ -1,6 +1,7 @@ """ Modules for DQAS framework """ + # possibly deprecated, multiprocessing is not the recommended way to do DQAS task now, using vmap! import sys @@ -486,9 +487,9 @@ def qaoa_simple_train( if "prob_model_func" in kws: pmf = kws["prob_model_func"] del kws["prob_model_func"] - kws[ - "prob_model" - ] = pmf() # in case keras model cannot pickled for multiprocessing map + kws["prob_model"] = ( + pmf() + ) # in case keras model cannot pickled for multiprocessing map if isinstance(graph, list): def graph_generator() -> Iterator[Graph]: diff --git a/tensorcircuit/applications/layers.py b/tensorcircuit/applications/layers.py index 18f53db6..64eef546 100644 --- a/tensorcircuit/applications/layers.py +++ b/tensorcircuit/applications/layers.py @@ -1,6 +1,7 @@ """ Module for functions adding layers of circuits """ + import itertools import logging import sys diff --git a/tensorcircuit/applications/physics/fss.py b/tensorcircuit/applications/physics/fss.py index dc60d492..f0490509 100644 --- a/tensorcircuit/applications/physics/fss.py +++ b/tensorcircuit/applications/physics/fss.py @@ -1,6 +1,7 @@ """ finite size scaling tools """ + from typing import List, Tuple, Optional import numpy as np diff --git a/tensorcircuit/applications/utils.py b/tensorcircuit/applications/utils.py index 8390afce..3ca54ff2 100644 --- a/tensorcircuit/applications/utils.py +++ b/tensorcircuit/applications/utils.py @@ -2,6 +2,7 @@ A collection of useful function snippets that irrelevant with the main modules or await for further refactor """ + import logging from typing import Any, Callable, Iterator, Optional, Sequence, Tuple diff --git a/tensorcircuit/applications/vags.py b/tensorcircuit/applications/vags.py index 80e5b74a..b2b5a612 100644 --- a/tensorcircuit/applications/vags.py +++ b/tensorcircuit/applications/vags.py @@ -1,6 +1,7 @@ """ DQAS application kernels as vag functions """ + from functools import lru_cache, partial, reduce import logging import operator diff --git a/tensorcircuit/applications/vqes.py b/tensorcircuit/applications/vqes.py index ba279365..a542268b 100644 --- a/tensorcircuit/applications/vqes.py +++ b/tensorcircuit/applications/vqes.py @@ -1,6 +1,7 @@ """ VQNHE application """ + from functools import lru_cache from itertools import product import time diff --git a/tensorcircuit/asciiart.py b/tensorcircuit/asciiart.py index b63b317e..b5c9e3b4 100644 --- a/tensorcircuit/asciiart.py +++ b/tensorcircuit/asciiart.py @@ -1,6 +1,7 @@ """ Some ascii art from https://www.asciiart.eu/, have fun! """ + # pylint: disable=invalid-name import hashlib diff --git a/tensorcircuit/backends/abstract_backend.py b/tensorcircuit/backends/abstract_backend.py index cf6884bc..4a7ccecd 100644 --- a/tensorcircuit/backends/abstract_backend.py +++ b/tensorcircuit/backends/abstract_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: abstract backend """ + # pylint: disable=invalid-name # pylint: disable=unused-variable @@ -1539,16 +1540,19 @@ def wrapper(*args: Any, **kws: Any) -> Any: args, tuple( [ - self.reshape( - self.eye(self.sizen(arg), dtype=arg.dtype), - [-1] + list(self.shape_tuple(arg)), - ) - if i == argnum - else self.reshape( - self.zeros( - [self.sizen(arg), self.sizen(arg)], dtype=arg.dtype - ), - [-1] + list(self.shape_tuple(arg)), + ( + self.reshape( + self.eye(self.sizen(arg), dtype=arg.dtype), + [-1] + list(self.shape_tuple(arg)), + ) + if i == argnum + else self.reshape( + self.zeros( + [self.sizen(arg), self.sizen(arg)], + dtype=arg.dtype, + ), + [-1] + list(self.shape_tuple(arg)), + ) ) for i, arg in enumerate(args) ] @@ -1607,16 +1611,18 @@ def _first(x: Sequence[Any]) -> Any: args, collect( [ - self.reshape( - self.eye(self.sizen(v), dtype=v.dtype), - [-1] + list(self.shape_tuple(v)), - ) - if i == k - else self.reshape( - self.zeros( - [self.sizen(v), self.sizen(v)], dtype=v.dtype - ), - [-1] + list(self.shape_tuple(v)), + ( + self.reshape( + self.eye(self.sizen(v), dtype=v.dtype), + [-1] + list(self.shape_tuple(v)), + ) + if i == k + else self.reshape( + self.zeros( + [self.sizen(v), self.sizen(v)], dtype=v.dtype + ), + [-1] + list(self.shape_tuple(v)), + ) ) for i, v in enumerate(values) ] diff --git a/tensorcircuit/backends/cupy_backend.py b/tensorcircuit/backends/cupy_backend.py index 4aa58d06..11260d19 100644 --- a/tensorcircuit/backends/cupy_backend.py +++ b/tensorcircuit/backends/cupy_backend.py @@ -1,6 +1,7 @@ """ CuPy backend. Not in the tensornetwork package and highly experimental. """ + # pylint: disable=invalid-name import logging diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index 994f4bfc..581d8be7 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: jax backend """ + # pylint: disable=invalid-name from functools import partial diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index 57e86609..fcdc52a4 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any, Tuple, Sequence diff --git a/tensorcircuit/backends/numpy_backend.py b/tensorcircuit/backends/numpy_backend.py index 83ef3040..df3dc043 100644 --- a/tensorcircuit/backends/numpy_backend.py +++ b/tensorcircuit/backends/numpy_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: numpy backend """ + # pylint: disable=invalid-name import logging diff --git a/tensorcircuit/backends/pytorch_backend.py b/tensorcircuit/backends/pytorch_backend.py index 3256a44e..3214c72c 100644 --- a/tensorcircuit/backends/pytorch_backend.py +++ b/tensorcircuit/backends/pytorch_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: pytorch backend """ + # pylint: disable=invalid-name import logging diff --git a/tensorcircuit/backends/pytorch_ops.py b/tensorcircuit/backends/pytorch_ops.py index 182101fd..e801a4ca 100644 --- a/tensorcircuit/backends/pytorch_ops.py +++ b/tensorcircuit/backends/pytorch_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any diff --git a/tensorcircuit/backends/tensorflow_backend.py b/tensorcircuit/backends/tensorflow_backend.py index 632b558f..365bd521 100644 --- a/tensorcircuit/backends/tensorflow_backend.py +++ b/tensorcircuit/backends/tensorflow_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: tensorflow backend """ + # pylint: disable=invalid-name import os diff --git a/tensorcircuit/backends/tf_ops.py b/tensorcircuit/backends/tf_ops.py index 27327722..d7b6d380 100644 --- a/tensorcircuit/backends/tf_ops.py +++ b/tensorcircuit/backends/tf_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any diff --git a/tensorcircuit/basecircuit.py b/tensorcircuit/basecircuit.py index 65eac8d8..468c6a1b 100644 --- a/tensorcircuit/basecircuit.py +++ b/tensorcircuit/basecircuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: common methods for all circuit classes as MixIn """ + # pylint: disable=invalid-name from typing import Any, Dict, List, Optional, Sequence, Tuple, Union diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index e07516cb..a293e3df 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: the state simulator """ + # pylint: disable=invalid-name from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple diff --git a/tensorcircuit/cloud/utils.py b/tensorcircuit/cloud/utils.py index 296e66df..fe15a56f 100644 --- a/tensorcircuit/cloud/utils.py +++ b/tensorcircuit/cloud/utils.py @@ -1,6 +1,7 @@ """ utility functions for cloud connection """ + from typing import Any, Callable, Optional from functools import wraps import inspect diff --git a/tensorcircuit/cloud/wrapper.py b/tensorcircuit/cloud/wrapper.py index 2ae2da20..f43f9ea9 100644 --- a/tensorcircuit/cloud/wrapper.py +++ b/tensorcircuit/cloud/wrapper.py @@ -1,6 +1,7 @@ """ higher level wrapper shortcut for submit_task """ + from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import logging import time diff --git a/tensorcircuit/compiler/__init__.py b/tensorcircuit/compiler/__init__.py index 43f92b99..d5f812fe 100644 --- a/tensorcircuit/compiler/__init__.py +++ b/tensorcircuit/compiler/__init__.py @@ -2,6 +2,7 @@ Experimental module, no software agnostic unified interface for now, only reserve for internal use """ + from .composed_compiler import Compiler, DefaultCompiler, default_compile from . import simple_compiler from . import qiskit_compiler diff --git a/tensorcircuit/cons.py b/tensorcircuit/cons.py index e7e4bccf..c2ffa8f8 100644 --- a/tensorcircuit/cons.py +++ b/tensorcircuit/cons.py @@ -1,6 +1,7 @@ """ Constants and setups """ + # pylint: disable=invalid-name import logging diff --git a/tensorcircuit/densitymatrix.py b/tensorcircuit/densitymatrix.py index e70197dc..dc52fe4a 100644 --- a/tensorcircuit/densitymatrix.py +++ b/tensorcircuit/densitymatrix.py @@ -1,6 +1,7 @@ """ Quantum circuit class but with density matrix simulator """ + # pylint: disable=invalid-name from functools import reduce @@ -333,9 +334,11 @@ def apply_general_kraus( ) -> None: # incompatible API for now kraus = [ - k - if isinstance(k, tn.Node) - else Gate(backend.cast(backend.convert_to_tensor(k), dtypestr)) + ( + k + if isinstance(k, tn.Node) + else Gate(backend.cast(backend.convert_to_tensor(k), dtypestr)) + ) for k in kraus ] self.check_kraus(kraus) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py index e0e36d43..a7012701 100644 --- a/tensorcircuit/fgs.py +++ b/tensorcircuit/fgs.py @@ -1,6 +1,7 @@ """ Fermion Gaussian state simulator """ + from typing import Any, Dict, List, Optional, Tuple import numpy as np diff --git a/tensorcircuit/mps_base.py b/tensorcircuit/mps_base.py index ae05c7ad..d8234c2b 100644 --- a/tensorcircuit/mps_base.py +++ b/tensorcircuit/mps_base.py @@ -1,6 +1,7 @@ """ FiniteMPS from tensornetwork with bug fixed """ + # pylint: disable=invalid-name from typing import Any, Optional, List, Sequence diff --git a/tensorcircuit/mpscircuit.py b/tensorcircuit/mpscircuit.py index 1c6876ed..7fc4052e 100644 --- a/tensorcircuit/mpscircuit.py +++ b/tensorcircuit/mpscircuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: MPS state simulator """ + # pylint: disable=invalid-name from functools import reduce diff --git a/tensorcircuit/noisemodel.py b/tensorcircuit/noisemodel.py index 0b03d966..9a1d85ac 100644 --- a/tensorcircuit/noisemodel.py +++ b/tensorcircuit/noisemodel.py @@ -1,6 +1,7 @@ """ General Noise Model Construction. """ + import logging from functools import partial from typing import Any, Sequence, Optional, List, Dict, Tuple, Callable, Union diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 383259c2..0d57362a 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -7,6 +7,7 @@ import tensorcircuit.quantum as qu """ + # pylint: disable=invalid-name import os diff --git a/tensorcircuit/results/counts.py b/tensorcircuit/results/counts.py index 9611ee4b..a4800cc4 100644 --- a/tensorcircuit/results/counts.py +++ b/tensorcircuit/results/counts.py @@ -1,6 +1,7 @@ """ dict related functionalities """ + from typing import Any, Dict, Optional, Sequence import numpy as np diff --git a/tensorcircuit/results/readout_mitigation.py b/tensorcircuit/results/readout_mitigation.py index ef205800..d701dcc1 100644 --- a/tensorcircuit/results/readout_mitigation.py +++ b/tensorcircuit/results/readout_mitigation.py @@ -1,6 +1,7 @@ """ readout error mitigation functionalities """ + # Part of the code in this file is from mthree: https://github.com/Qiskit-Partners/mthree (Apache2) # https://journals.aps.org/prxquantum/pdf/10.1103/PRXQuantum.2.040326 @@ -811,9 +812,11 @@ def expectation( ] else: diagonal_op = [ - [1, -1] @ inv_single_qubit_cals[i] - if i in z1 - else [1, 1] @ inv_single_qubit_cals[i] + ( + [1, -1] @ inv_single_qubit_cals[i] + if i in z1 + else [1, 1] @ inv_single_qubit_cals[i] + ) for i in range(n) ] diff --git a/tensorcircuit/simplify.py b/tensorcircuit/simplify.py index 6123c8dd..1cbcfc6a 100644 --- a/tensorcircuit/simplify.py +++ b/tensorcircuit/simplify.py @@ -1,6 +1,7 @@ """ Tensornetwork Simplification """ + # part of the implementations and ideas are inspired from # https://github.com/jcmgray/quimb/blob/a2968050eba5a8a04ced4bdaa5e43c4fb89edc33/quimb/tensor/tensor_core.py#L7309-L8293 # (Apache 2.0) diff --git a/tensorcircuit/templates/blocks.py b/tensorcircuit/templates/blocks.py index eacc2b42..1e376903 100644 --- a/tensorcircuit/templates/blocks.py +++ b/tensorcircuit/templates/blocks.py @@ -1,6 +1,7 @@ """ Shortcuts for measurement patterns on circuit """ + # circuit in, circuit out # pylint: disable=invalid-name diff --git a/tensorcircuit/templates/graphs.py b/tensorcircuit/templates/graphs.py index 4b2e1c9c..e382085c 100644 --- a/tensorcircuit/templates/graphs.py +++ b/tensorcircuit/templates/graphs.py @@ -1,6 +1,7 @@ """ Some common graphs and lattices """ + # pylint: disable=invalid-name from functools import partial diff --git a/tensorcircuit/templates/measurements.py b/tensorcircuit/templates/measurements.py index aca804d9..63f5c5b7 100644 --- a/tensorcircuit/templates/measurements.py +++ b/tensorcircuit/templates/measurements.py @@ -1,6 +1,7 @@ """ Shortcuts for measurement patterns on circuit """ + # circuit in, scalar out from typing import Any diff --git a/tensorcircuit/vis.py b/tensorcircuit/vis.py index 092216b8..19834d95 100644 --- a/tensorcircuit/vis.py +++ b/tensorcircuit/vis.py @@ -1,6 +1,7 @@ """ Visualization on circuits """ + import os import subprocess from uuid import uuid4 From 0339bf17de16e52a5c41cad2a034fb4f1ff87fdb Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 9 Feb 2024 19:02:56 +0800 Subject: [PATCH 069/139] fix jax breaking changes --- CHANGELOG.md | 2 ++ tensorcircuit/backends/jax_ops.py | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e26b8b..624458e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ - Fixed `cu` gate translation from qiskit to avoid qiskit bug +- Fixed jax refactoring (0.4.24) where SVD and QR return a namedtuple instead of a tuple + ## 0.11.0 ### Added diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index fcdc52a4..2eaf2f1b 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -14,7 +14,8 @@ @jax.custom_vjp def adaware_svd(A: Array) -> Any: - return jnp.linalg.svd(A, full_matrices=False) + u, s, v = jnp.linalg.svd(A, full_matrices=False) + return (u, s, v) def _safe_reciprocal(x: Array, epsilon: float = 1e-15) -> Array: @@ -77,8 +78,8 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: @jax.custom_vjp def adaware_qr(A: Array) -> Any: - # q, r = jnp.linalg.qr(A) - return jnp.linalg.qr(A) + q, r = jnp.linalg.qr(A) + return (q, r) def jaxqr_fwd(A: Array) -> Any: From dafa300100e22e2802dc350113a9f5f87e64b5be Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 27 Feb 2024 10:37:32 +0800 Subject: [PATCH 070/139] fix qiskit<1.0 --- requirements/requirements-extra.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 024c584f..9475bddf 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,6 +1,6 @@ # extra dependencies for ci -qiskit -qiskit_aer +qiskit<1.0 +qiskit_aer<1.0 # qiskit-nature mitiq cirq From 2b7ed605ed19212d9e3dae936a477b2b09b5db00 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 11 Mar 2024 16:37:20 +0800 Subject: [PATCH 071/139] fix tf version --- requirements/requirements.txt | 2 +- tensorcircuit/applications/ai/ensemble.py | 3 +++ tests/test_ensemble.py | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 5deccf0d..97de418f 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,6 +1,6 @@ numpy scipy -tensorflow +tensorflow<2.16 # tf 2.16 with integration of keras 3 seems a disaster... tensornetwork-ng graphviz jax diff --git a/tensorcircuit/applications/ai/ensemble.py b/tensorcircuit/applications/ai/ensemble.py index 7946cb4c..d983ebf0 100644 --- a/tensorcircuit/applications/ai/ensemble.py +++ b/tensorcircuit/applications/ai/ensemble.py @@ -3,6 +3,7 @@ """ from typing import Any, List, Optional +from copy import deepcopy import tensorflow as tf import numpy as np @@ -53,10 +54,12 @@ def train(self, **kwargs: kwargus) -> None: def compile(self, **kwargs: kwargus) -> None: self.permit_train = True + for i in range(self.count): if not self.model_trained[i]: dict_kwargs = kwargs.copy() # TODO(@refraction-ray): still not compatible with new optimizer + # https://github.com/tensorflow/tensorflow/issues/58973 self.models[i].compile(**dict_kwargs) def __get_confidence(self, model_index: int, input: NDArray) -> NDArray: diff --git a/tests/test_ensemble.py b/tests/test_ensemble.py index 097789dc..92869fd8 100644 --- a/tests/test_ensemble.py +++ b/tests/test_ensemble.py @@ -2,6 +2,7 @@ import sys import tensorflow as tf import numpy as np +import pytest thisfile = os.path.abspath(__file__) modulepath = os.path.dirname(os.path.dirname(thisfile)) @@ -11,6 +12,9 @@ from tensorcircuit.applications.ai.ensemble import bagging +@pytest.mark.xfail( + int(tf.__version__.split(".")[1]) >= 16, reason="legacy optimizer fails tf>=2.16" +) def test_ensemble_bagging(): data_amount = 100 # Amount of data to be used linear_dimension = 4 # linear demension of the data From a5745a982fe3d8a3d81b8d460f6663933bf7a366 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 11 Mar 2024 16:55:40 +0800 Subject: [PATCH 072/139] pylint --- tensorcircuit/applications/ai/ensemble.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tensorcircuit/applications/ai/ensemble.py b/tensorcircuit/applications/ai/ensemble.py index d983ebf0..a9d6b0d7 100644 --- a/tensorcircuit/applications/ai/ensemble.py +++ b/tensorcircuit/applications/ai/ensemble.py @@ -3,7 +3,6 @@ """ from typing import Any, List, Optional -from copy import deepcopy import tensorflow as tf import numpy as np From b79dae4e559d8e90d9d2d7d785aeb38b2de275d2 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 11 Mar 2024 17:08:38 +0800 Subject: [PATCH 073/139] lock tf and qiskit in setup: two nonsense update with so many meaningless breaking changes, just pushing the users away... --- setup.py | 6 +++--- tensorcircuit/__init__.py | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ac6d4d57..8e176a49 100644 --- a/setup.py +++ b/setup.py @@ -19,11 +19,11 @@ include_package_data=True, install_requires=["numpy", "scipy", "tensornetwork-ng", "networkx"], extras_require={ - "tensorflow": ["tensorflow"], + "tensorflow": ["tensorflow<2.16"], "jax": ["jax", "jaxlib"], "torch": ["torch"], - "qiskit": ["qiskit"], - "cloud": ["qiskit", "mthree"], + "qiskit": ["qiskit<1.0"], + "cloud": ["qiskit<1.0", "mthree"], }, classifiers=[ "Programming Language :: Python :: 3", diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index a3993163..8b2779d5 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -55,5 +55,16 @@ except ModuleNotFoundError: pass # in case torch is not installed +try: + import qiskit + + qiskit.QuantumCircuit.cnot = qiskit.QuantumCircuit.cx + qiskit.QuantumCircuit.toffoli = qiskit.QuantumCircuit.ccx + qiskit.QuantumCircuit.fredkin = qiskit.QuantumCircuit.cswap + + # amazing qiskit 1.0 nonsense... +except ModuleNotFoundError: + pass + # just for fun from .asciiart import set_ascii From b042a745d2708b2cc571b8c9c6b352b6b7d4920f Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 15 Mar 2024 10:12:38 +0800 Subject: [PATCH 074/139] version0.12.0 --- CHANGELOG.md | 4 ++++ README.md | 14 +++++++------- tensorcircuit/__init__.py | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 624458e7..b5318889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.12.0 + ### Added - Add translation of r gate from qiskit @@ -28,6 +30,8 @@ - Fixed jax refactoring (0.4.24) where SVD and QR return a namedtuple instead of a tuple +- Fix qiskit<1.0 and tf<2.16 + ## 0.11.0 ### Added diff --git a/README.md b/README.md index 46a70c2a..cc532ff7 100644 --- a/README.md +++ b/README.md @@ -356,13 +356,13 @@ Reference paper: https://arxiv.org/abs/2303.10825 (published in JCTC). For the numerical simulation and hardware experiments with error mitigation on QAOA, see the [project repo](https://github.com/sherrylixuecheng/EMQAOA-DARBO). -Reference paper: https://arxiv.org/abs/2303.14877. +Reference paper: https://arxiv.org/abs/2303.14877 (published in Communications Physics). ### NN-VQA For the setup and simulation code of neural network encoded variational quantum eigensolver, see the [demo](/docs/source/tutorials/nnvqe.ipynb). -Reference paper: https://arxiv.org/abs/2308.01068. +Reference paper: https://arxiv.org/abs/2308.01068 (published in PRApplied). ### More works @@ -377,7 +377,7 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Variational Quantum Simulations of Finite-Temperature Dynamical Properties via Thermofield Dynamics: https://arxiv.org/abs/2206.05571. -- Understanding quantum machine learning also requires rethinking generalization: https://arxiv.org/abs/2306.13461. +- Understanding quantum machine learning also requires rethinking generalization: https://arxiv.org/abs/2306.13461 (published in Nature Communications). - Decentralized Quantum Federated Learning for Metaverse: Analysis, Design and Implementation: https://arxiv.org/abs/2306.11297. Code: https://github.com/s222416822/BQFL. @@ -385,7 +385,7 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Quantum generative adversarial imitation learning: https://doi.org/10.1088/1367-2630/acc605 (published in New Journal of Physics). -- GSQAS: Graph Self-supervised Quantum Architecture Search: https://arxiv.org/abs/2303.12381. +- GSQAS: Graph Self-supervised Quantum Architecture Search: https://arxiv.org/abs/2303.12381 (published in Physica A: Statistical Mechanics and its Applications). - Practical advantage of quantum machine learning in ghost imaging: https://www.nature.com/articles/s42005-023-01290-1 (published in Communications Physics). @@ -393,15 +393,15 @@ Reference paper: https://arxiv.org/abs/2308.01068. - Comparison of Quantum Simulators for Variational Quantum Search: A Benchmark Study: https://arxiv.org/abs/2309.05924. -- Statistical analysis of quantum state learning process in quantum neural networks: https://arxiv.org/abs/2309.14980 (Pubilshed in NeurIPS). +- Statistical analysis of quantum state learning process in quantum neural networks: https://arxiv.org/abs/2309.14980 (published in NeurIPS). -- Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866. +- Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866 (published in PRL). - Quantum imaginary time evolution and quantum annealing meet topological sector optimization: https://arxiv.org/abs/2310.04291. - Google Summer of Code 2023 Projects (QML4HEP): https://github.com/ML4SCI/QMLHEP, https://github.com/Gopal-Dahale/qgnn-hep, https://github.com/salcc/QuantumTransformers. -- Absence of barren plateaus in finite local-depth circuits with long-range entanglement: https://arxiv.org/abs/2311.01393. +- Absence of barren plateaus in finite local-depth circuits with long-range entanglement: https://arxiv.org/abs/2311.01393 (published in PRL). - Non-Markovianity benefits quantum dynamics simulation: https://arxiv.org/abs/2311.17622. diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index 8b2779d5..fb1c2e40 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.11.0" +__version__ = "0.12.0" __author__ = "TensorCircuit Authors" __creator__ = "refraction-ray" From 0565d5eac3be7916f6954f584c5362d932e09da4 Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Sun, 7 Apr 2024 05:27:21 +0900 Subject: [PATCH 075/139] allow various parameterexpressions --- requirements/requirements-extra.txt | 4 +- tensorcircuit/abstractcircuit.py | 12 ++-- tensorcircuit/translation.py | 86 ++++++++++++++--------------- tests/test_circuit.py | 41 +++++++++----- 4 files changed, 77 insertions(+), 66 deletions(-) diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 9475bddf..e5cd85a8 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,7 +1,7 @@ # extra dependencies for ci qiskit<1.0 -qiskit_aer<1.0 -# qiskit-nature +qiskit-aer<1.0 +qiskit-nature mitiq cirq torch diff --git a/tensorcircuit/abstractcircuit.py b/tensorcircuit/abstractcircuit.py index ac2b9116..2334aa39 100644 --- a/tensorcircuit/abstractcircuit.py +++ b/tensorcircuit/abstractcircuit.py @@ -4,21 +4,21 @@ # pylint: disable=invalid-name -from typing import Any, Callable, Dict, List, Optional, Sequence, Union, Tuple +import json +import logging from copy import deepcopy from functools import reduce from operator import add -import json -import logging +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import numpy as np import tensornetwork as tn from . import gates from .cons import backend, dtypestr -from .vis import qir2tex from .quantum import QuOperator from .utils import is_sequence +from .vis import qir2tex logger = logging.getLogger(__name__) @@ -756,7 +756,7 @@ def to_qiskit( :type enable_inputs: bool, defaults to False :return: A qiskit object of this circuit. """ - from .translation import qir2qiskit, perm_matrix + from .translation import perm_matrix, qir2qiskit qir = self.to_qir() if enable_instruction: @@ -887,7 +887,7 @@ def from_qiskit( n = qc.num_qubits return qiskit2tc( # type: ignore - qc.data, + qc, n, inputs, circuit_constructor=cls, diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index e297113d..fcef21d4 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -2,23 +2,26 @@ Circuit object translation in different packages """ -from typing import Any, Dict, List, Optional, Tuple, Union, Sequence -from copy import deepcopy import logging +from copy import deepcopy +from typing import Any, Dict, List, Optional, Sequence, Tuple, Union + import numpy as np logger = logging.getLogger(__name__) try: + import qiskit.quantum_info as qi + import symengine + import sympy from qiskit import QuantumCircuit + from qiskit.circuit import Parameter, ParameterExpression from qiskit.circuit.library import XXPlusYYGate + from qiskit.circuit.parametervector import ParameterVectorElement + from qiskit.circuit.quantumcircuitdata import CircuitInstruction from qiskit.extensions import UnitaryGate - import qiskit.quantum_info as qi from qiskit.extensions.exceptions import ExtensionError - from qiskit.circuit.quantumcircuitdata import CircuitInstruction - from qiskit.circuit.parametervector import ParameterVectorElement - from qiskit.circuit import Parameter, ParameterExpression except ImportError: logger.warning( "Please first ``pip install -U qiskit`` to enable related functionality in translation module" @@ -34,11 +37,10 @@ from . import gates from .circuit import Circuit -from .densitymatrix import DMCircuit2 from .cons import backend +from .densitymatrix import DMCircuit2 from .interfaces.tensortrans import tensor_to_numpy - Tensor = Any @@ -358,7 +360,7 @@ def _translate_qiskit_params( gate_info: CircuitInstruction, binding_params: Any ) -> List[float]: parameters = [] - for p in gate_info[0].params: + for p in gate_info.operation.params: if isinstance(p, ParameterVectorElement): parameters.append(binding_params[p.index]) elif isinstance(p, Parameter): @@ -367,30 +369,29 @@ def _translate_qiskit_params( if len(p.parameters) == 0: parameters.append(float(p)) continue - if len(p.parameters) != 1: - raise ValueError( - f"Can't translate parameter expression with more than 1 parameters: {p}" - ) - p_real = list(p.parameters)[0] - if not isinstance(p_real, ParameterVectorElement): - raise TypeError( - "Parameters in parameter expression should be ParameterVectorElement" - ) + # note "sym" != "sim" expr = p.sympify().simplify() - # only allow simple expressions like 1.0 * theta - if not expr.is_Mul: - raise ValueError(f"Unsupported parameter expression: {p}") - arg1, arg2 = expr.args - if arg1.is_number and arg2.is_symbol: - coeff = arg1 - elif arg1.is_symbol and arg2.is_number: - coeff = arg2 - else: - raise ValueError(f"Unsupported parameter expression: {p}") - # taking real part here because using complex type will result in a type error - # for tf backend when the binding parameter is real - parameters.append(float(coeff) * binding_params[p_real.index]) + if isinstance(expr, symengine.Expr): # qiskit uses symengine if available + expr = expr._sympy_() # sympy.Expr + + for free_symbol in expr.free_symbols: + # replace names: theta[0] -> theta_0 + # ParameterVector creates symbols with brackets like theta[0] + # but sympy.lambdify does not allow brackets in symbol names + free_symbol.name = free_symbol.name.replace("[", "_").replace("]", "") + + parameter_list = list(p.parameters) + sympy_symbols = [param._symbol_expr for param in parameter_list] + # replace names again: theta[0] -> theta_0 + sympy_symbols = [ + sympy.Symbol(str(symbol).replace("[", "_").replace("]", "")) + for symbol in sympy_symbols + ] + lam_f = sympy.lambdify(sympy_symbols, expr, modules=backend.name) + parameters.append( + lam_f(*[binding_params[param.index] for param in parameter_list]) + ) else: # numbers, arrays, etc. parameters.append(p) @@ -403,7 +404,7 @@ def ctrl_str2ctrl_state(ctrl_str: str, nctrl: int) -> List[int]: def qiskit2tc( - qcdata: List[CircuitInstruction], + qc: QuantumCircuit, n: int, inputs: Optional[List[float]] = None, is_dm: bool = False, @@ -412,19 +413,18 @@ def qiskit2tc( binding_params: Optional[Union[Sequence[float], Dict[Any, float]]] = None, ) -> Any: r""" - Generate a tensorcircuit circuit using the quantum circuit data in qiskit. + Generate a tensorcircuit circuit from the qiskit circuit. :Example: >>> qisc = QuantumCircuit(2) >>> qisc.h(0) >>> qisc.x(1) - >>> qc = tc.translation.qiskit2tc(qisc.data, 2) + >>> qc = tc.translation.qiskit2tc(qisc, 2) >>> qc.to_qir()[0]['gatef'] - h - :param qcdata: Quantum circuit data from qiskit. - :type qcdata: List[CircuitInstruction] + :param qc: A quantum circuit in qiskit. + :type qc: QuantumCircuit :param n: # of qubits :type n: int :param inputs: Input state of the circuit. Default is None. @@ -435,7 +435,7 @@ def qiskit2tc( :type circuit_params: Optional[Dict[str, Any]] :param binding_params: (variational) parameters for the circuit. Could be either a sequence or dictionary depending on the type of parameters in the Qiskit circuit. - For ``ParameterVectorElement`` use sequence. For ``Parameter`` use dictionary + For ``ParameterVectorElement`` use sequence. For ``Parameter`` use dictionary. :type binding_params: Optional[Union[Sequence[float], Dict[Any, float]]] :return: A quantum circuit in tensorcircuit :rtype: Any @@ -451,17 +451,17 @@ def qiskit2tc( if "nqubits" not in circuit_params: circuit_params["nqubits"] = n if ( - len(qcdata) > 0 - and qcdata[0][0].name == "initialize" + len(qc.data) > 0 + and qc.data[0][0].name == "initialize" and "inputs" not in circuit_params ): - circuit_params["inputs"] = perm_matrix(n) @ np.array(qcdata[0][0].params) + circuit_params["inputs"] = perm_matrix(n) @ np.array(qc.data[0][0].params) if inputs is not None: circuit_params["inputs"] = inputs tc_circuit: Any = Circ(**circuit_params) - for gate_info in qcdata: - idx = [qb.index for qb in gate_info[1]] + for gate_info in qc.data: + idx = [qc.find_bit(qb).index for qb in gate_info.qubits] gate_name = gate_info[0].name parameters = _translate_qiskit_params(gate_info, binding_params) if gate_name in [ diff --git a/tests/test_circuit.py b/tests/test_circuit.py index cb67eb36..b1d45dd6 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1,8 +1,9 @@ # pylint: disable=invalid-name -import sys import os +import sys from functools import partial + import numpy as np import opt_einsum as oem import pytest @@ -975,6 +976,7 @@ def test_qir2cirq(backend): def test_qir2qiskit(backend): try: import qiskit.quantum_info as qi + from tensorcircuit.translation import perm_matrix except ImportError: pytest.skip("qiskit is not installed") @@ -1074,9 +1076,10 @@ def test_qir2qiskit(backend): def test_qiskit2tc(): try: - from qiskit import QuantumCircuit import qiskit.quantum_info as qi + from qiskit import QuantumCircuit from qiskit.circuit.library.standard_gates import MCXGate, SwapGate + from tensorcircuit.translation import perm_matrix except ImportError: pytest.skip("qiskit is not installed") @@ -1149,26 +1152,34 @@ def test_qiskit2tc(): @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) def test_qiskit2tc_parameterized(backend): try: - from qiskit.circuit import QuantumCircuit, Parameter - from qiskit.quantum_info import Operator + from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit from qiskit.circuit.library import TwoLocal + from qiskit.quantum_info import Operator from qiskit_nature.second_q.circuit.library import UCCSD - from qiskit_nature.second_q.mappers import ParityMapper, QubitConverter + from qiskit_nature.second_q.mappers import ParityMapper except ImportError: pytest.skip("qiskit or qiskit-nature is not installed") from tensorcircuit.translation import perm_matrix mapper = ParityMapper() - converter = QubitConverter(mapper=mapper, two_qubit_reduction=True) - ansatz1 = UCCSD(2, [1, 1], converter) + ansatz1 = UCCSD(2, [1, 1], mapper) ansatz2 = TwoLocal(2, rotation_blocks="ry", entanglement_blocks="cz") ansatz3 = QuantumCircuit(1) ansatz3_param = Parameter("θ") ansatz3.rx(ansatz3_param, 0) - ansatz_list = [ansatz1, ansatz2, ansatz3] + ansatz4 = QuantumCircuit(1) + ansatz4_param = ParameterVector("φ", 3) + ansatz4.rx(2.0 * ansatz4_param[0] + 5.0, 0) + ansatz4.ry(ansatz4_param[0] * ansatz4_param[1] + ansatz4_param[2], 0) + ansatz4.rz( + np.exp(np.sin(ansatz4_param[0])) + + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), + 0, + ) + ansatz_list = [ansatz1, ansatz2, ansatz3, ansatz4] for ansatz in ansatz_list: n = ansatz.num_qubits - if ansatz in [ansatz1, ansatz2]: + if ansatz in [ansatz1, ansatz2, ansatz4]: params = np.random.rand(ansatz.num_parameters) else: params = {ansatz3_param: 0.618} @@ -1178,9 +1189,9 @@ def test_qiskit2tc_parameterized(backend): # test jit @tc.backend.jit - def get_unitary(_params): + def get_unitary(params): return tc.Circuit.from_qiskit( - ansatz, inputs=np.eye(2**n), binding_params=_params + ansatz, inputs=np.eye(2**n), binding_params=params ).state() tc_unitary = get_unitary(params) @@ -1191,10 +1202,10 @@ def get_unitary(_params): ) # test grad - def cost_fn(_params): - return tc.backend.real(tc.backend.sum(get_unitary(_params))) + def cost_fn(params): + return tc.backend.real(tc.backend.sum(get_unitary(params))) - if ansatz in [ansatz1, ansatz2]: + if ansatz in [ansatz1, ansatz2, ansatz4]: grad = tc.backend.grad(cost_fn)(tc.backend.convert_to_tensor(params)) assert np.sum(np.isnan(grad)) == 0 else: @@ -1208,8 +1219,8 @@ def cost_fn(_params): @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_qiskit_vs_tc_intialization(backend): try: - from qiskit import QuantumCircuit import qiskit.quantum_info as qi + from qiskit import QuantumCircuit except ImportError: pytest.skip("qiskit is not installed") From 908e5e7fd810720b1ef5824ad43054e7adfad19e Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Sun, 7 Apr 2024 16:46:27 +0900 Subject: [PATCH 076/139] support pytorch backend (kind of) --- tensorcircuit/translation.py | 12 +++++++++++- tests/test_circuit.py | 17 +++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index fcef21d4..17629db4 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -375,6 +375,16 @@ def _translate_qiskit_params( if isinstance(expr, symengine.Expr): # qiskit uses symengine if available expr = expr._sympy_() # sympy.Expr + if expr.is_algebraic_expr(): # numpy ufuncs are not used + lambdify_module_name = "numpy" + else: + if backend.name == "pytorch": + raise ValueError( + "pytorch backend does not support sympy lambdify with non-algebraic expressions" + ) + else: + lambdify_module_name = backend.name + for free_symbol in expr.free_symbols: # replace names: theta[0] -> theta_0 # ParameterVector creates symbols with brackets like theta[0] @@ -388,7 +398,7 @@ def _translate_qiskit_params( sympy.Symbol(str(symbol).replace("[", "_").replace("]", "")) for symbol in sympy_symbols ] - lam_f = sympy.lambdify(sympy_symbols, expr, modules=backend.name) + lam_f = sympy.lambdify(sympy_symbols, expr, modules=lambdify_module_name) parameters.append( lam_f(*[binding_params[param.index] for param in parameter_list]) ) diff --git a/tests/test_circuit.py b/tests/test_circuit.py index b1d45dd6..f395ed94 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1149,7 +1149,7 @@ def test_qiskit2tc(): np.testing.assert_allclose(qis_unitary2, qis_unitary, atol=1e-5) -@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")]) def test_qiskit2tc_parameterized(backend): try: from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit @@ -1171,11 +1171,12 @@ def test_qiskit2tc_parameterized(backend): ansatz4_param = ParameterVector("φ", 3) ansatz4.rx(2.0 * ansatz4_param[0] + 5.0, 0) ansatz4.ry(ansatz4_param[0] * ansatz4_param[1] + ansatz4_param[2], 0) - ansatz4.rz( - np.exp(np.sin(ansatz4_param[0])) - + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), - 0, - ) + if tc.backend.name != "pytorch": # pytorch backend with ufuncs is not supported + ansatz4.rz( + np.exp(np.sin(ansatz4_param[0])) + + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), + 0, + ) ansatz_list = [ansatz1, ansatz2, ansatz3, ansatz4] for ansatz in ansatz_list: n = ansatz.num_qubits @@ -1196,7 +1197,7 @@ def get_unitary(params): tc_unitary = get_unitary(params) tc_unitary = np.reshape(tc_unitary, [2**n, 2**n]) - p_mat = perm_matrix(n) + p_mat = tc.array_to_tensor(perm_matrix(n)) np.testing.assert_allclose( p_mat @ tc_unitary @ p_mat, qiskit_unitary, atol=1e-5 ) @@ -1207,7 +1208,7 @@ def cost_fn(params): if ansatz in [ansatz1, ansatz2, ansatz4]: grad = tc.backend.grad(cost_fn)(tc.backend.convert_to_tensor(params)) - assert np.sum(np.isnan(grad)) == 0 + assert tc.backend.sum(tc.num_to_tensor(np.isnan(grad))) == 0 else: # tf only supports tf tensor as input grad = tc.backend.grad(cost_fn)( From 77721d401b78785ba4a52f221f2bad7e94725ec5 Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Sun, 7 Apr 2024 21:54:12 +0900 Subject: [PATCH 077/139] use math for pytorch backend --- tensorcircuit/translation.py | 4 +--- tests/test_circuit.py | 11 +++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 17629db4..992eed39 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -379,9 +379,7 @@ def _translate_qiskit_params( lambdify_module_name = "numpy" else: if backend.name == "pytorch": - raise ValueError( - "pytorch backend does not support sympy lambdify with non-algebraic expressions" - ) + lambdify_module_name = "math" else: lambdify_module_name = backend.name diff --git a/tests/test_circuit.py b/tests/test_circuit.py index f395ed94..16bc4844 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1171,12 +1171,11 @@ def test_qiskit2tc_parameterized(backend): ansatz4_param = ParameterVector("φ", 3) ansatz4.rx(2.0 * ansatz4_param[0] + 5.0, 0) ansatz4.ry(ansatz4_param[0] * ansatz4_param[1] + ansatz4_param[2], 0) - if tc.backend.name != "pytorch": # pytorch backend with ufuncs is not supported - ansatz4.rz( - np.exp(np.sin(ansatz4_param[0])) - + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), - 0, - ) + ansatz4.rz( + np.exp(np.sin(ansatz4_param[0])) + + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), + 0, + ) ansatz_list = [ansatz1, ansatz2, ansatz3, ansatz4] for ansatz in ansatz_list: n = ansatz.num_qubits From 8738dc993dfd2a375382286e341c6519d6b760b9 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 8 Apr 2024 09:54:48 +0800 Subject: [PATCH 078/139] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5318889..3f072c9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Add support for parameter expression in qiskit translation + ## 0.12.0 ### Added From 93d1d3beec6aaae12180a5ea2e7a14f0e58463dd Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 01:57:27 +0000 Subject: [PATCH 079/139] docs: update README.md [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc532ff7..845a6750 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. ztzhu
ztzhu

💻 Rabqubit
Rabqubit

💡 - Kazuki Tsuoka
Kazuki Tsuoka

💻 + Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 From fb13030c460ae2f1ab35f47179fd169467dbed85 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 01:57:28 +0000 Subject: [PATCH 080/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 4b928ff4..2afd3367 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -307,7 +307,9 @@ "avatar_url": "https://avatars.githubusercontent.com/u/103920010?v=4", "profile": "https://github.com/king-p3nguin", "contributions": [ - "code" + "code", + "test", + "doc" ] } ], From 5c0c768ebaeb6ee82f82581cd79d37231b1709a3 Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Tue, 9 Apr 2024 09:01:33 +0900 Subject: [PATCH 081/139] fix dep warnings --- tensorcircuit/backends/jax_backend.py | 13 +++++++------ tensorcircuit/compiler/qiskit_compiler.py | 13 +++++++------ tensorcircuit/translation.py | 12 +++++------- tests/test_circuit.py | 4 +++- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index 581d8be7..f19c23ce 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -4,15 +4,16 @@ # pylint: disable=invalid-name -from functools import partial import logging import warnings +from functools import partial from typing import Any, Callable, Optional, Sequence, Tuple, Union import numpy as np -from scipy.sparse import coo_matrix import tensornetwork +from scipy.sparse import coo_matrix from tensornetwork.backends.jax import jax_backend + from .abstract_backend import ExtendedBackend logger = logging.getLogger(__name__) @@ -196,8 +197,8 @@ def __init__(self) -> None: "Jax not installed, please switch to a different " "backend or install Jax." ) - from jax.experimental import sparse import jax.scipy + from jax.experimental import sparse try: import optax @@ -419,7 +420,7 @@ def searchsorted(self, a: Tensor, v: Tensor, side: str = "left") -> Tensor: return jnp.searchsorted(a, v, side) def tree_map(self, f: Callable[..., Any], *pytrees: Any) -> Any: - return libjax.tree_map(f, *pytrees) + return libjax.tree_util.tree_map(f, *pytrees) def tree_flatten(self, pytree: Any) -> Tuple[Any, Any]: return libjax.tree_util.tree_flatten(pytree) # type: ignore @@ -630,7 +631,7 @@ def is_sparse(self, a: Tensor) -> bool: return isinstance(a, sparse.BCOO) # type: ignore def device(self, a: Tensor) -> str: - dev = a.device() + dev = a.devices() return self._dev2str(dev) def device_move(self, a: Tensor, dev: Any) -> Tensor: @@ -757,7 +758,7 @@ def wrapper( gs = list(gs) for i, (j, g) in enumerate(zip(argnums_list, gs)): if j not in vectorized_argnums: # type: ignore - gs[i] = libjax.tree_map(partial(jnp.sum, axis=0), g) + gs[i] = libjax.tree_util.tree_map(partial(jnp.sum, axis=0), g) if isinstance(argnums, int): gs = gs[0] else: diff --git a/tensorcircuit/compiler/qiskit_compiler.py b/tensorcircuit/compiler/qiskit_compiler.py index e54dd1a4..1f946359 100644 --- a/tensorcircuit/compiler/qiskit_compiler.py +++ b/tensorcircuit/compiler/qiskit_compiler.py @@ -2,8 +2,8 @@ compiler interface via qiskit """ -from typing import Any, Dict, Optional import re +from typing import Any, Dict, Optional from ..abstractcircuit import AbstractCircuit from ..circuit import Circuit @@ -71,7 +71,7 @@ def _get_positional_logical_mapping_from_qiskit(qc: Any) -> Dict[int, int]: positional_logical_mapping = {} for inst in qc.data: if inst[0].name == "measure": - positional_logical_mapping[i] = inst[1][0].index + positional_logical_mapping[i] = qc.find_bit(inst[1][0]).index i += 1 return positional_logical_mapping @@ -95,16 +95,17 @@ def _get_logical_physical_mapping_from_qiskit( for inst in qc_after.data: if inst[0].name == "measure": if qc_before is None: - logical_q = inst[2][0].index + logical_q = qc_after.find_bit(inst[2][0]).index else: for instb in qc_before.data: if ( instb[0].name == "measure" - and instb[2][0].index == inst[2][0].index + and qc_before.find_bit(instb[2][0]).index + == qc_after.find_bit(inst[2][0]).index ): - logical_q = instb[1][0].index + logical_q = qc_before.find_bit(instb[1][0]).index break - logical_physical_mapping[logical_q] = inst[1][0].index + logical_physical_mapping[logical_q] = qc_after.find_bit(inst[1][0]).index return logical_physical_mapping diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 992eed39..c6ca1e0e 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -17,11 +17,10 @@ import sympy from qiskit import QuantumCircuit from qiskit.circuit import Parameter, ParameterExpression - from qiskit.circuit.library import XXPlusYYGate + from qiskit.circuit.exceptions import CircuitError + from qiskit.circuit.library import HamiltonianGate, UnitaryGate, XXPlusYYGate from qiskit.circuit.parametervector import ParameterVectorElement from qiskit.circuit.quantumcircuitdata import CircuitInstruction - from qiskit.extensions import UnitaryGate - from qiskit.extensions.exceptions import ExtensionError except ImportError: logger.warning( "Please first ``pip install -U qiskit`` to enable related functionality in translation module" @@ -311,9 +310,8 @@ def qir2qiskit( # Error can be presented if theta is actually complex in this procedure. exp_op = qi.Operator(unitary) index_reversed = [x for x in index[::-1]] - qiskit_circ.hamiltonian( - exp_op, time=theta, qubits=index_reversed, label=qis_name - ) + gate = HamiltonianGate(data=exp_op, time=theta, label=qis_name) + qiskit_circ.append(gate, index_reversed) elif gate_name == "multicontrol": unitary = backend.numpy(backend.convert_to_tensor(parameters["unitary"])) ctrl_str = "".join(map(str, parameters["ctrl"]))[::-1] @@ -344,7 +342,7 @@ def qir2qiskit( qop = qi.Operator(gatem) try: qiskit_circ.unitary(qop, index[::-1], label=qis_name) - except (ExtensionError, ValueError) as _: + except (CircuitError, ValueError) as _: logger.warning( "omit non unitary gate in tensorcircuit when transforming to qiskit: %s" % gate_name diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 16bc4844..81f20762 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1078,6 +1078,7 @@ def test_qiskit2tc(): try: import qiskit.quantum_info as qi from qiskit import QuantumCircuit + from qiskit.circuit.library import HamiltonianGate from qiskit.circuit.library.standard_gates import MCXGate, SwapGate from tensorcircuit.translation import perm_matrix @@ -1090,7 +1091,8 @@ def test_qiskit2tc(): zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) exp_op = qi.Operator(zz) for i in range(n): - qisc.hamiltonian(exp_op, time=np.random.uniform(), qubits=[i, (i + 1) % n]) + gate = HamiltonianGate(exp_op, time=np.random.uniform()) + qisc.append(gate, [i, (i + 1) % n]) qisc.fredkin(1, 2, 3) qisc.cswap(1, 2, 3) qisc.swap(0, 1) From 3a748305ca123ab074055f18cf63aa0afbf7bf5f Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Tue, 9 Apr 2024 09:49:09 +0900 Subject: [PATCH 082/139] fix test --- tensorcircuit/backends/jax_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index f19c23ce..33be28fd 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -631,7 +631,7 @@ def is_sparse(self, a: Tensor) -> bool: return isinstance(a, sparse.BCOO) # type: ignore def device(self, a: Tensor) -> str: - dev = a.devices() + (dev,) = a.devices() return self._dev2str(dev) def device_move(self, a: Tensor, dev: Any) -> Tensor: From be721a24e1fe617c31499c223d6ec9213975cebd Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 9 Apr 2024 16:45:13 +0800 Subject: [PATCH 083/139] fix some bug when qiskit or cirq is not installed --- tensorcircuit/results/qem/qem_methods.py | 3 ++- tensorcircuit/translation.py | 1 + tests/test_torchnn.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tensorcircuit/results/qem/qem_methods.py b/tensorcircuit/results/qem/qem_methods.py index 7328b3bb..68199e49 100644 --- a/tensorcircuit/results/qem/qem_methods.py +++ b/tensorcircuit/results/qem/qem_methods.py @@ -14,7 +14,6 @@ logger = logging.getLogger(__name__) import numpy as np -import cirq try: from mitiq import zne, ddd @@ -205,6 +204,8 @@ def dd_rule(slack_length: int, spacing: int = -1) -> Any: return dd_sequence if isinstance(rule, list): + import cirq + gates = [] for i in rule: gates.append(getattr(cirq, i)) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 992eed39..70276c58 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -27,6 +27,7 @@ "Please first ``pip install -U qiskit`` to enable related functionality in translation module" ) CircuitInstruction = Any + QuantumCircuit = Any try: import cirq diff --git a/tests/test_torchnn.py b/tests/test_torchnn.py index 6acb7b17..88549248 100644 --- a/tests/test_torchnn.py +++ b/tests/test_torchnn.py @@ -14,7 +14,7 @@ try: import torch except ImportError: - pytest.skip("torch is not installed") + pytest.skip("torch is not installed", allow_module_level=True) @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")]) From a7dc3cb13b512eefd6debcce596a109a8a6a99e3 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Tue, 9 Apr 2024 17:27:50 +0800 Subject: [PATCH 084/139] give specific reason on disable tf2.16+ --- tests/test_keras.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_keras.py b/tests/test_keras.py index 187a316e..3564f828 100644 --- a/tests/test_keras.py +++ b/tests/test_keras.py @@ -129,6 +129,9 @@ def qf(inputs, param): def test_keras_layer_inputs_dict(tfb): + # https://github.com/tensorflow/tensorflow/issues/65306 + # keras3 for tf2.16+ fails to accept complex valued input for keras layers + # which is vital for quantum applications n = 3 p = 0.1 K = tc.backend From 7bd91c0d0e54bcd3bee4cded970c4fc9f1cadca1 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Wed, 10 Apr 2024 14:24:23 +0800 Subject: [PATCH 085/139] warning to info with no cirq --- tensorcircuit/translation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 42a2fe57..73b973b6 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -31,7 +31,7 @@ try: import cirq except ImportError: - logger.warning( + logger.info( "Please first ``pip install -U cirq`` to enable related functionality in translation module" ) From 229b018fdbe6d1fe582a49d21563392b6a48e7b3 Mon Sep 17 00:00:00 2001 From: Gopal Dahale Date: Wed, 29 May 2024 23:49:40 +0530 Subject: [PATCH 086/139] vqe noisyopt --- examples/vqe_noisyopt.py | 194 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 examples/vqe_noisyopt.py diff --git a/examples/vqe_noisyopt.py b/examples/vqe_noisyopt.py new file mode 100644 index 00000000..8fa06bd3 --- /dev/null +++ b/examples/vqe_noisyopt.py @@ -0,0 +1,194 @@ +""" +VQE with finite measurement shot noise +""" + +from functools import partial +import numpy as np +from scipy import optimize +import optax +import tensorcircuit as tc +from tensorcircuit import experimental as E +from noisyopt import minimizeCompass, minimizeSPSA +from tabulate import tabulate + +seed = 42 +np.random.seed(seed) + +K = tc.set_backend("jax") +# note this script only supports jax backend + +n = 6 +nlayers = 4 + +result = { + "Algorithm / Optimization": ["Without Shot Noise", "With Shot Noise"], + "Gradient Free": [], + "Gradient based": [], +} + +# We use OBC 1D TFIM Hamiltonian in this script + +ps = [] +for i in range(n): + l = [0 for _ in range(n)] + l[i] = 1 + ps.append(l) + # X_i +for i in range(n - 1): + l = [0 for _ in range(n)] + l[i] = 3 + l[i + 1] = 3 + ps.append(l) + # Z_i Z_i+1 +w = [-1.0 for _ in range(n)] + [1.0 for _ in range(n - 1)] + + +def generate_circuit(param): + # construct the circuit ansatz + c = tc.Circuit(n) + for i in range(n): + c.H(i) + for j in range(nlayers): + for i in range(n - 1): + c.rzz(i, i + 1, theta=param[i, j, 0]) + for i in range(n): + c.rx(i, theta=param[i, j, 1]) + return c + + +def ps2xyz(psi): + # ps2xyz([1, 2, 2, 0]) = {"x": [0], "y": [1, 2], "z": []} + xyz = {"x": [], "y": [], "z": []} + for i, j in enumerate(psi): + if j == 1: + xyz["x"].append(i) + if j == 2: + xyz["y"].append(i) + if j == 3: + xyz["z"].append(i) + return xyz + + +@partial(K.jit, static_argnums=(2)) +def exp_val(param, key, shots=1024): + # expectation with shot noise + # ps, w: H = \sum_i w_i ps_i + # describing the system Hamiltonian as a weighted sum of Pauli string + c = generate_circuit(param) + if isinstance(shots, int): + shots = [shots for _ in range(len(ps))] + loss = 0 + for psi, wi, shot in zip(ps, w, shots): + key, subkey = K.random_split(key) + xyz = ps2xyz(psi) + loss += wi * c.sample_expectation_ps(**xyz, shots=shot, random_generator=subkey) + return K.real(loss) + + +@K.jit +def exp_val_analytical(param): + param = param.reshape(n, nlayers, 2) + c = generate_circuit(param) + loss = 0 + for psi, wi in zip(ps, w): + xyz = ps2xyz(psi) + loss += wi * c.expectation_ps(**xyz) + return K.real(loss) + + +# 0. Exact result + +hm = tc.quantum.PauliStringSum2COO(ps, w, numpy=True) +hm = K.to_dense(hm) +e, v = np.linalg.eigh(hm) +exact_gs_energy = e[0] +print("==================================================================") +print("Exact ground state energy: ", exact_gs_energy) +print("==================================================================") + +# 1.1 VQE with numerically exact expectation: gradient free + +print(">>> VQE without shot noise") + + +r = minimizeSPSA( + func=exp_val_analytical, + x0=np.random.uniform(size=[n * nlayers * 2]), + niter=6000, + paired=False, +) + +print(r) +print(">> Converged as (Gradient Free) :", exp_val_analytical(r.x)) +result["Gradient Free"].append(exp_val_analytical(r.x)) + +# 1.2 VQE with numerically exact expectation: gradient based + +exponential_decay_scheduler = optax.exponential_decay( + init_value=1e-2, transition_steps=500, decay_rate=0.9 +) +opt = K.optimizer(optax.adam(exponential_decay_scheduler)) +param = K.implicit_randn([n, nlayers, 2], stddev=0.1) # zeros stall the gradient +exp_val_grad_analytical = K.jit(K.value_and_grad(exp_val_analytical)) +for i in range(1000): + e, g = exp_val_grad_analytical(param) + param = opt.update(g, param) + if i % 100 == 99: + print(e) + +print(">> Converged as (Gradient based):", exp_val_grad_analytical(param)[0]) +result["Gradient based"].append(exp_val_grad_analytical(param)[0]) + +# 2.1 VQE with finite shot noise: gradient free + +print("==================================================================") +print(">>> VQE with shot noise") + + +rkey = K.get_random_state(42) + + +def exp_val_wrapper(param): + param = param.reshape(n, nlayers, 2) + global rkey + rkey, skey = K.random_split(rkey) + # maintain stateless randomness in scipy optimize interface + return exp_val(param, skey, shots=1024) + + +r = minimizeSPSA( + func=exp_val_wrapper, + x0=np.random.uniform(size=[n * nlayers * 2]), + niter=6000, + paired=False, +) +print(r) +print(">> Converged as (Gradient Free) :", exp_val_wrapper(r["x"])) +result["Gradient Free"].append(exp_val_wrapper(r["x"])) + +# 2.2 VQE with finite shot noise: gradient based + +exponential_decay_scheduler = optax.exponential_decay( + init_value=1e-2, transition_steps=500, decay_rate=0.9 +) +opt = K.optimizer(optax.adam(exponential_decay_scheduler)) +param = K.implicit_randn([n, nlayers, 2], stddev=0.1) # zeros stall the gradient +exp_grad = E.parameter_shift_grad_v2(exp_val, argnums=0, random_argnums=1) +rkey = K.get_random_state(42) + +for i in range(1000): + rkey, skey = K.random_split(rkey) + g = exp_grad(param, skey) + param = opt.update(g, param) + if i % 100 == 99: + rkey, skey = K.random_split(rkey) + print(exp_val(param, skey)) + +# the real energy position after optimization +print(">> Converged as (Gradient based):", exp_val_analytical(param)) +result["Gradient based"].append(exp_val_analytical(param)) + +print("==================================================================") +print(">>> Benchmark") +print(">> Exact ground state energy: ", exact_gs_energy) +print(tabulate(result, headers="keys")) From 6eec70232d2ba67b79f9ef9db5cc37a4e8b1ca9a Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 30 May 2024 13:03:50 +0900 Subject: [PATCH 087/139] update quantum.py --- tensorcircuit/quantum.py | 621 +++++++++++++++++++-------------------- 1 file changed, 306 insertions(+), 315 deletions(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 0d57362a..67a14b25 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -10,10 +10,10 @@ # pylint: disable=invalid-name -import os -from functools import reduce, partial import logging -from operator import or_, mul, matmul +import os +from functools import partial, reduce +from operator import matmul, mul, or_ from typing import ( Any, Callable, @@ -28,20 +28,19 @@ ) import numpy as np -from tensornetwork.network_components import AbstractNode, Node, Edge, connect -from tensornetwork.network_components import CopyNode -from tensornetwork.network_operations import get_all_nodes, copy, reachable -from tensornetwork.network_operations import get_subgraph_dangling, remove_node - -try: - import tensorflow as tf -except ImportError: - pass +from tensornetwork.network_components import AbstractNode, CopyNode, Edge, Node, connect +from tensornetwork.network_operations import ( + copy, + get_all_nodes, + get_subgraph_dangling, + reachable, + remove_node, +) -from .cons import backend, contractor, dtypestr, npdtype, rdtypestr from .backends import get_backend -from .utils import is_m1mac, arg_alias -from .gates import Gate +from .cons import backend, contractor, dtypestr, npdtype, rdtypestr +from .gates import Gate, num_to_tensor +from .utils import arg_alias Tensor = Any Graph = Any @@ -1162,318 +1161,310 @@ def quimb2qop(qb_mpo: Any) -> QuOperator: return qop -try: +def heisenberg_hamiltonian( + g: Graph, + hzz: float = 1.0, + hxx: float = 1.0, + hyy: float = 1.0, + hz: float = 0.0, + hx: float = 0.0, + hy: float = 0.0, + sparse: bool = True, + numpy: bool = False, +) -> Tensor: + """ + Generate Heisenberg Hamiltonian with possible external fields. + Currently requires tensorflow installed - def _id(x: Any) -> Any: - return x + :Example: - if is_m1mac(): - compiled_jit = _id - else: - compiled_jit = partial(get_backend("tensorflow").jit, jit_compile=True) - - def heisenberg_hamiltonian( - g: Graph, - hzz: float = 1.0, - hxx: float = 1.0, - hyy: float = 1.0, - hz: float = 0.0, - hx: float = 0.0, - hy: float = 0.0, - sparse: bool = True, - numpy: bool = False, - ) -> Tensor: - """ - Generate Heisenberg Hamiltonian with possible external fields. - Currently requires tensorflow installed + >>> g = tc.templates.graphs.Line1D(6) + >>> h = qu.heisenberg_hamiltonian(g, sparse=False) + >>> tc.backend.eigh(h)[0][:10] + array([-11.2111025, -8.4721365, -8.472136 , -8.472136 , -6. , + -5.123106 , -5.123106 , -5.1231055, -5.1231055, -5.1231055], + dtype=float32) + + :param g: input circuit graph + :type g: Graph + :param hzz: zz coupling, default is 1.0 + :type hzz: float + :param hxx: xx coupling, default is 1.0 + :type hxx: float + :param hyy: yy coupling, default is 1.0 + :type hyy: float + :param hz: External field on z direction, default is 0.0 + :type hz: float + :param hx: External field on y direction, default is 0.0 + :type hx: float + :param hy: External field on x direction, default is 0.0 + :type hy: float + :param sparse: Whether to return sparse Hamiltonian operator, default is True. + :type sparse: bool, defalts True + :param numpy: whether return the matrix in numpy or tensorflow form + :type numpy: bool, defaults False, + + :return: Hamiltonian measurements + :rtype: Tensor + """ + n = len(g.nodes) + ls = [] + weight = [] + for e in g.edges: + if hzz != 0: + r = [0 for _ in range(n)] + r[e[0]] = 3 + r[e[1]] = 3 + ls.append(r) + weight.append(hzz) + if hxx != 0: + r = [0 for _ in range(n)] + r[e[0]] = 1 + r[e[1]] = 1 + ls.append(r) + weight.append(hxx) + if hyy != 0: + r = [0 for _ in range(n)] + r[e[0]] = 2 + r[e[1]] = 2 + ls.append(r) + weight.append(hyy) + for node in g.nodes: + if hz != 0: + r = [0 for _ in range(n)] + r[node] = 3 + ls.append(r) + weight.append(hz) + if hx != 0: + r = [0 for _ in range(n)] + r[node] = 1 + ls.append(r) + weight.append(hx) + if hy != 0: + r = [0 for _ in range(n)] + r[node] = 2 + ls.append(r) + weight.append(hy) + ls = tf.constant(ls) + weight = tf.constant(weight) + ls = get_backend("tensorflow").cast(ls, dtypestr) + weight = get_backend("tensorflow").cast(weight, dtypestr) + if sparse: + r = PauliStringSum2COO_numpy(ls, weight) + if numpy: + return r + return backend.coo_sparse_matrix_from_numpy(r) + return PauliStringSum2Dense(ls, weight, numpy=numpy) - :Example: - >>> g = tc.templates.graphs.Line1D(6) - >>> h = qu.heisenberg_hamiltonian(g, sparse=False) - >>> tc.backend.eigh(h)[0][:10] - array([-11.2111025, -8.4721365, -8.472136 , -8.472136 , -6. , - -5.123106 , -5.123106 , -5.1231055, -5.1231055, -5.1231055], - dtype=float32) - - :param g: input circuit graph - :type g: Graph - :param hzz: zz coupling, default is 1.0 - :type hzz: float - :param hxx: xx coupling, default is 1.0 - :type hxx: float - :param hyy: yy coupling, default is 1.0 - :type hyy: float - :param hz: External field on z direction, default is 0.0 - :type hz: float - :param hx: External field on y direction, default is 0.0 - :type hx: float - :param hy: External field on x direction, default is 0.0 - :type hy: float - :param sparse: Whether to return sparse Hamiltonian operator, default is True. - :type sparse: bool, defalts True - :param numpy: whether return the matrix in numpy or tensorflow form - :type numpy: bool, defaults False, - - :return: Hamiltonian measurements - :rtype: Tensor - """ - n = len(g.nodes) - ls = [] - weight = [] - for e in g.edges: - if hzz != 0: - r = [0 for _ in range(n)] - r[e[0]] = 3 - r[e[1]] = 3 - ls.append(r) - weight.append(hzz) - if hxx != 0: - r = [0 for _ in range(n)] - r[e[0]] = 1 - r[e[1]] = 1 - ls.append(r) - weight.append(hxx) - if hyy != 0: - r = [0 for _ in range(n)] - r[e[0]] = 2 - r[e[1]] = 2 - ls.append(r) - weight.append(hyy) - for node in g.nodes: - if hz != 0: - r = [0 for _ in range(n)] - r[node] = 3 - ls.append(r) - weight.append(hz) - if hx != 0: - r = [0 for _ in range(n)] - r[node] = 1 - ls.append(r) - weight.append(hx) - if hy != 0: - r = [0 for _ in range(n)] - r[node] = 2 - ls.append(r) - weight.append(hy) - ls = tf.constant(ls) - weight = tf.constant(weight) - ls = get_backend("tensorflow").cast(ls, dtypestr) - weight = get_backend("tensorflow").cast(weight, dtypestr) - if sparse: - r = PauliStringSum2COO_numpy(ls, weight) - if numpy: - return r - return backend.coo_sparse_matrix_from_numpy(r) - return PauliStringSum2Dense(ls, weight, numpy=numpy) - - def PauliStringSum2Dense( - ls: Sequence[Sequence[int]], - weight: Optional[Sequence[float]] = None, - numpy: bool = False, - ) -> Tensor: - """ - Generate dense matrix from Pauli string sum. - Currently requires tensorflow installed. - - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :param numpy: default False. If True, return numpy coo - else return backend compatible sparse tensor - :type numpy: bool - :return: the tensorflow dense matrix - :rtype: Tensor - """ - sparsem = PauliStringSum2COO_numpy(ls, weight) - if numpy: - return sparsem.todense() - sparsem = backend.coo_sparse_matrix_from_numpy(sparsem) - densem = backend.to_dense(sparsem) - return densem - - # already implemented as backend method - # - # def _tf2numpy_sparse(a: Tensor) -> Tensor: - # return get_backend("numpy").coo_sparse_matrix( - # indices=a.indices, - # values=a.values, - # shape=a.get_shape(), - # ) - - # def _numpy2tf_sparse(a: Tensor) -> Tensor: - # return get_backend("tensorflow").coo_sparse_matrix( - # indices=np.array([a.row, a.col]).T, - # values=a.data, - # shape=a.shape, - # ) - - def PauliStringSum2COO( - ls: Sequence[Sequence[int]], - weight: Optional[Sequence[float]] = None, - numpy: bool = False, - ) -> Tensor: - """ - Generate sparse tensor from Pauli string sum. - Currently requires tensorflow installed - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :param numpy: default False. If True, return numpy coo - else return backend compatible sparse tensor - :type numpy: bool - :return: the scipy coo sparse matrix - :rtype: Tensor - """ - # numpy version is 3* faster! - - nterms = len(ls) - # n = len(ls[0]) - # s = 0b1 << n - if weight is None: - weight = [1.0 for _ in range(nterms)] - if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): - weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) - # rsparse = get_backend("numpy").coo_sparse_matrix( - # indices=np.array([[0, 0]], dtype=np.int64), - # values=np.array([0.0], dtype=getattr(np, dtypestr)), - # shape=(s, s), - # ) - rsparses = [ - get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore - for i in range(nterms) - ] - rsparse = _dc_sum(rsparses) - # auto transformed into csr format!! +def PauliStringSum2Dense( + ls: Sequence[Sequence[int]], + weight: Optional[Sequence[float]] = None, + numpy: bool = False, +) -> Tensor: + """ + Generate dense matrix from Pauli string sum. + Currently requires tensorflow installed. - # for i in range(nterms): - # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore - rsparse = rsparse.tocoo() - if numpy: - return rsparse - return backend.coo_sparse_matrix_from_numpy(rsparse) - def _dc_sum(l: List[Any]) -> Any: - """ - For the sparse sum, the speed is determined by the non zero terms, - so the DC way to do the sum can indeed bring some speed advantage (several times) + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :param numpy: default False. If True, return numpy coo + else return backend compatible sparse tensor + :type numpy: bool + :return: the tensorflow dense matrix + :rtype: Tensor + """ + sparsem = PauliStringSum2COO_numpy(ls, weight) + if numpy: + return sparsem.todense() + sparsem = backend.coo_sparse_matrix_from_numpy(sparsem) + densem = backend.to_dense(sparsem) + return densem + + +# already implemented as backend method +# +# def _tf2numpy_sparse(a: Tensor) -> Tensor: +# return get_backend("numpy").coo_sparse_matrix( +# indices=a.indices, +# values=a.values, +# shape=a.get_shape(), +# ) + +# def _numpy2tf_sparse(a: Tensor) -> Tensor: +# return get_backend("tensorflow").coo_sparse_matrix( +# indices=np.array([a.row, a.col]).T, +# values=a.data, +# shape=a.shape, +# ) + + +def PauliStringSum2COO( + ls: Sequence[Sequence[int]], + weight: Optional[Sequence[float]] = None, + numpy: bool = False, +) -> Tensor: + """ + Generate sparse tensor from Pauli string sum. + Currently requires tensorflow installed + + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :param numpy: default False. If True, return numpy coo + else return backend compatible sparse tensor + :type numpy: bool + :return: the scipy coo sparse matrix + :rtype: Tensor + """ + # numpy version is 3* faster! + + nterms = len(ls) + # n = len(ls[0]) + # s = 0b1 << n + if weight is None: + weight = [1.0 for _ in range(nterms)] + if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): + weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) + # rsparse = get_backend("numpy").coo_sparse_matrix( + # indices=np.array([[0, 0]], dtype=np.int64), + # values=np.array([0.0], dtype=getattr(np, dtypestr)), + # shape=(s, s), + # ) + rsparses = [ + get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore + for i in range(nterms) + ] + rsparse = _dc_sum(rsparses) + # auto transformed into csr format!! + + # for i in range(nterms): + # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore + rsparse = rsparse.tocoo() + if numpy: + return rsparse + return backend.coo_sparse_matrix_from_numpy(rsparse) - :param l: _description_ - :type l: List[Any] - :return: _description_ - :rtype: Any - """ - n = len(l) - if n > 2: - return _dc_sum(l[: n // 2]) + _dc_sum(l[n // 2 :]) - else: - return sum(l) - PauliStringSum2COO_numpy = partial(PauliStringSum2COO, numpy=True) +def _dc_sum(l: List[Any]) -> Any: + """ + For the sparse sum, the speed is determined by the non zero terms, + so the DC way to do the sum can indeed bring some speed advantage (several times) - def PauliStringSum2COO_tf( - ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None - ) -> Tensor: - """ - Generate tensorflow sparse matrix from Pauli string sum - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :return: the tensorflow coo sparse matrix - :rtype: Tensor - """ - nterms = len(ls) - n = len(ls[0]) - s = 0b1 << n - if weight is None: - weight = [1.0 for _ in range(nterms)] - if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): - weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) - rsparse = tf.SparseTensor( - indices=tf.constant([[0, 0]], dtype=tf.int64), - values=tf.constant([0.0], dtype=weight.dtype), # type: ignore - dense_shape=(s, s), - ) - for i in range(nterms): - rsparse = tf.sparse.add(rsparse, PauliString2COO(ls[i], weight[i])) # type: ignore - # very slow sparse.add? - return rsparse + :param l: _description_ + :type l: List[Any] + :return: _description_ + :rtype: Any + """ + n = len(l) + if n > 2: + return _dc_sum(l[: n // 2]) + _dc_sum(l[n // 2 :]) + else: + return sum(l) - @compiled_jit - def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: - """ - Generate tensorflow sparse matrix from Pauli string sum - - :param l: 1D Tensor representing for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type l: Sequence[int] - :param weight: the weight for the Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[float], optional - :return: the tensorflow sparse matrix - :rtype: Tensor - """ - n = len(l) - one = tf.constant(0b1, dtype=tf.int64) - idx_x = tf.constant(0b0, dtype=tf.int64) - idx_y = tf.constant(0b0, dtype=tf.int64) - idx_z = tf.constant(0b0, dtype=tf.int64) - i = tf.constant(0, dtype=tf.int64) - for j in l: - # i, j from enumerate is python, non jittable when cond using tensor - if j == 1: # xi - idx_x += tf.bitwise.left_shift(one, n - i - 1) - elif j == 2: # yi - idx_y += tf.bitwise.left_shift(one, n - i - 1) - elif j == 3: # zi - idx_z += tf.bitwise.left_shift(one, n - i - 1) - i += 1 - - if weight is None: - weight = tf.constant(1.0, dtype=tf.complex64) - return ps2coo_core(idx_x, idx_y, idx_z, weight, n) - - @compiled_jit - def ps2coo_core( - idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int - ) -> Tuple[Tensor, Tensor]: - dtype = weight.dtype - s = 0b1 << nqubits - idx1 = tf.cast(tf.range(s), dtype=tf.int64) - idx2 = (idx1 ^ idx_x) ^ (idx_y) - indices = tf.transpose(tf.stack([idx1, idx2])) - tmp = idx1 & (idx_y | idx_z) - e = idx1 * 0 - ny = 0 - for i in range(nqubits): - # if tmp[i] is power of 2 (non zero), then e[i] = 1 - e ^= tf.bitwise.right_shift(tmp, i) & 0b1 - # how many 1 contained in idx_y - ny += tf.bitwise.right_shift(idx_y, i) & 0b1 - ny = tf.math.mod(ny, 4) - values = ( - tf.cast((1 - 2 * e), dtype) - * tf.math.pow(tf.constant(-1.0j, dtype=dtype), tf.cast(ny, dtype)) - * weight - ) - return tf.SparseTensor(indices=indices, values=values, dense_shape=(s, s)) # type: ignore -except (NameError, ImportError): - logger.info( - "tensorflow is not installed, and sparse Hamiltonian generation utilities are disabled" +PauliStringSum2COO_numpy = partial(PauliStringSum2COO, numpy=True) + + +def PauliStringSum2COO_tf( + ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None +) -> Tensor: + """ + Generate tensorflow sparse matrix from Pauli string sum + + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :return: the tensorflow coo sparse matrix + :rtype: Tensor + """ + nterms = len(ls) + n = len(ls[0]) + s = 0b1 << n + if weight is None: + weight = [1.0 for _ in range(nterms)] + if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): + weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) + rsparse = tf.SparseTensor( + indices=tf.constant([[0, 0]], dtype=tf.int64), + values=tf.constant([0.0], dtype=weight.dtype), # type: ignore + dense_shape=(s, s), + ) + for i in range(nterms): + rsparse = tf.sparse.add(rsparse, PauliString2COO(ls[i], weight[i])) # type: ignore + # very slow sparse.add? + return rsparse + + +def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: + """ + Generate tensorflow sparse matrix from Pauli string sum + + :param l: 1D Tensor representing for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type l: Sequence[int] + :param weight: the weight for the Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[float], optional + :return: the tensorflow sparse matrix + :rtype: Tensor + """ + n = len(l) + one = num_to_tensor(0b1, dtype="int64") + idx_x = num_to_tensor(0b0, dtype="int64") + idx_y = num_to_tensor(0b0, dtype="int64") + idx_z = num_to_tensor(0b0, dtype="int64") + i = num_to_tensor(0, dtype="int64") + for j in l: + # i, j from enumerate is python, non jittable when cond using tensor + if j == 1: # xi + idx_x += tf.bitwise.left_shift(one, n - i - 1) + elif j == 2: # yi + idx_y += tf.bitwise.left_shift(one, n - i - 1) + elif j == 3: # zi + idx_z += tf.bitwise.left_shift(one, n - i - 1) + i += 1 + + if weight is None: + weight = tf.constant(1.0, dtype=tf.complex64) + return ps2coo_core(idx_x, idx_y, idx_z, weight, n) + + +def ps2coo_core( + idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int +) -> Tuple[Tensor, Tensor]: + dtype = weight.dtype + s = 0b1 << nqubits + idx1 = tf.cast(tf.range(s), dtype=tf.int64) + idx2 = (idx1 ^ idx_x) ^ (idx_y) + indices = tf.transpose(tf.stack([idx1, idx2])) + tmp = idx1 & (idx_y | idx_z) + e = idx1 * 0 + ny = 0 + for i in range(nqubits): + # if tmp[i] is power of 2 (non zero), then e[i] = 1 + e ^= tf.bitwise.right_shift(tmp, i) & 0b1 + # how many 1 contained in idx_y + ny += tf.bitwise.right_shift(idx_y, i) & 0b1 + ny = tf.math.mod(ny, 4) + values = ( + tf.cast((1 - 2 * e), dtype) + * tf.math.pow(tf.constant(-1.0j, dtype=dtype), tf.cast(ny, dtype)) + * weight ) + return tf.SparseTensor(indices=indices, values=values, dense_shape=(s, s)) # type: ignore + # some quantum quatities below From 1b297d5fdcfc9db0842229629de27127ec08a2e5 Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 30 May 2024 13:42:24 +0900 Subject: [PATCH 088/139] update quantum.py & test --- tensorcircuit/quantum.py | 43 +++++++++++++++++++--------------------- tests/test_quantum.py | 7 ++++--- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 67a14b25..33fe8163 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1245,8 +1245,8 @@ def heisenberg_hamiltonian( r[node] = 2 ls.append(r) weight.append(hy) - ls = tf.constant(ls) - weight = tf.constant(weight) + ls = num_to_tensor(ls) + weight = num_to_tensor(weight) ls = get_backend("tensorflow").cast(ls, dtypestr) weight = get_backend("tensorflow").cast(weight, dtypestr) if sparse: @@ -1332,22 +1332,18 @@ def PauliStringSum2COO( # s = 0b1 << n if weight is None: weight = [1.0 for _ in range(nterms)] - if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): - weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) + weight = num_to_tensor(weight) # rsparse = get_backend("numpy").coo_sparse_matrix( # indices=np.array([[0, 0]], dtype=np.int64), # values=np.array([0.0], dtype=getattr(np, dtypestr)), # shape=(s, s), # ) - rsparses = [ - get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore - for i in range(nterms) - ] + rsparses = [backend.numpy(PauliString2COO(ls[i], weight[i])) for i in range(nterms)] # type: ignore rsparse = _dc_sum(rsparses) # auto transformed into csr format!! # for i in range(nterms): - # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore + # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) rsparse = rsparse.tocoo() if numpy: return rsparse @@ -1389,6 +1385,8 @@ def PauliStringSum2COO_tf( :return: the tensorflow coo sparse matrix :rtype: Tensor """ + import tensorflow as tf + nterms = len(ls) n = len(ls[0]) s = 0b1 << n @@ -1409,7 +1407,7 @@ def PauliStringSum2COO_tf( def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: """ - Generate tensorflow sparse matrix from Pauli string sum + Generate sparse matrix from Pauli string sum :param l: 1D Tensor representing for a Pauli string, e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` @@ -1429,41 +1427,40 @@ def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: for j in l: # i, j from enumerate is python, non jittable when cond using tensor if j == 1: # xi - idx_x += tf.bitwise.left_shift(one, n - i - 1) + idx_x += backend.left_shift(one, n - i - 1) elif j == 2: # yi - idx_y += tf.bitwise.left_shift(one, n - i - 1) + idx_y += backend.left_shift(one, n - i - 1) elif j == 3: # zi - idx_z += tf.bitwise.left_shift(one, n - i - 1) + idx_z += backend.left_shift(one, n - i - 1) i += 1 if weight is None: - weight = tf.constant(1.0, dtype=tf.complex64) + weight = num_to_tensor(1.0, dtype="complex64") return ps2coo_core(idx_x, idx_y, idx_z, weight, n) def ps2coo_core( idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int ) -> Tuple[Tensor, Tensor]: - dtype = weight.dtype s = 0b1 << nqubits - idx1 = tf.cast(tf.range(s), dtype=tf.int64) + idx1 = num_to_tensor(backend.arange(s), dtype="int64") idx2 = (idx1 ^ idx_x) ^ (idx_y) - indices = tf.transpose(tf.stack([idx1, idx2])) + indices = backend.transpose(backend.stack([idx1, idx2])) tmp = idx1 & (idx_y | idx_z) e = idx1 * 0 ny = 0 for i in range(nqubits): # if tmp[i] is power of 2 (non zero), then e[i] = 1 - e ^= tf.bitwise.right_shift(tmp, i) & 0b1 + e ^= backend.right_shift(tmp, i) & 0b1 # how many 1 contained in idx_y - ny += tf.bitwise.right_shift(idx_y, i) & 0b1 - ny = tf.math.mod(ny, 4) + ny += backend.right_shift(idx_y, i) & 0b1 + ny = backend.mod(ny, 4) values = ( - tf.cast((1 - 2 * e), dtype) - * tf.math.pow(tf.constant(-1.0j, dtype=dtype), tf.cast(ny, dtype)) + num_to_tensor(1 - 2 * e) + * ((num_to_tensor(-1.0j) ** num_to_tensor(ny))) * weight ) - return tf.SparseTensor(indices=indices, values=values, dense_shape=(s, s)) # type: ignore + return backend.coo_sparse_matrix(indices=indices, values=values, shape=(s, s)) # type: ignore # some quantum quatities below diff --git a/tests/test_quantum.py b/tests/test_quantum.py index 2009fbe6..63ff755e 100644 --- a/tests/test_quantum.py +++ b/tests/test_quantum.py @@ -1,13 +1,13 @@ # pylint: disable=invalid-name -from functools import partial import os import sys +from functools import partial import numpy as np import pytest -from pytest_lazyfixture import lazy_fixture as lf import tensornetwork as tn +from pytest_lazyfixture import lazy_fixture as lf thisfile = os.path.abspath(__file__) modulepath = os.path.dirname(os.path.dirname(thisfile)) @@ -312,7 +312,8 @@ def test_extract_from_measure(backend): np.testing.assert_allclose(r, 1, atol=1e-5) -def test_heisenberg_ham(tfb): +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_heisenberg_ham(backend): g = tc.templates.graphs.Line1D(6) h = tc.quantum.heisenberg_hamiltonian(g, sparse=False) e, _ = tc.backend.eigh(h) From 45c5b6e17b29cd1f51cd07bbd32e54e54808b24c Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 30 May 2024 14:05:31 +0900 Subject: [PATCH 089/139] fix: fix failed test --- tests/test_templates.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_templates.py b/tests/test_templates.py index 25f22b08..79e2b176 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -1,7 +1,8 @@ # pylint: disable=invalid-name -import sys import os +import sys + import numpy as np import pytest from pytest_lazyfixture import lazy_fixture as lf @@ -160,10 +161,6 @@ def test_operator_measurement(backend): ) dense = tc.array_to_tensor(np.kron(tc.gates._x_matrix, np.eye(2))) sparse = tc.quantum.PauliString2COO([1, 0]) - if tc.backend.name == "jax": - sparse = tc.backend.coo_sparse_matrix( - sparse.indices, sparse.values, sparse.shape - ) for h in [dense, sparse, mpo]: From 846715af3eca8f0b737a367ddd689a2b4aa50896 Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 30 May 2024 15:15:20 +0900 Subject: [PATCH 090/139] chore: change example --- examples/hamiltonian_building.py | 91 ++++++++++++++++++++++++++++---- tensorcircuit/quantum.py | 2 - 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/examples/hamiltonian_building.py b/examples/hamiltonian_building.py index e00c6a7e..91ce33a7 100644 --- a/examples/hamiltonian_building.py +++ b/examples/hamiltonian_building.py @@ -3,36 +3,86 @@ """ import time + +import jax import numpy as np import quimb +import scipy +import tensorflow as tf +import torch + import tensorcircuit as tc +tc.set_dtype("complex128") nwires = 20 -# tc outperforms quimb in large nwires +# tc with numpy backend outperforms quimb in large nwires + +print("--------------------") +# 1.1 tc approach for TFIM (numpy backend) -# 1. tc approach for TFIM +tc.set_backend("numpy") +print("hamiltonian building with tc (numpy backend)") +print("numpy version: ", np.__version__) +print("scipy version: ", scipy.__version__) g = tc.templates.graphs.Line1D(nwires, pbc=False) -time0 = time.time() -h1 = tc.quantum.heisenberg_hamiltonian( +time0 = time.perf_counter() +h11 = tc.quantum.heisenberg_hamiltonian( g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True, numpy=True ) -time1 = time.time() +time1 = time.perf_counter() + +print("tc (numpy) time: ", time1 - time0) +print("--------------------") + +# 1.2 tc approach for TFIM (jax backend) + +tc.set_backend("jax") +print("hamiltonian building with tc (jax backend)") +print("jax version: ", jax.__version__) + +g = tc.templates.graphs.Line1D(nwires, pbc=False) +time0 = time.perf_counter() +h12 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (jax) time: ", time1 - time0) +print("--------------------") + +# 1.3 tc approach for TFIM (tensorflow backend) + +tc.set_backend("tensorflow") +print("hamiltonian building with tc (tensorflow backend)") +print("tensorflow version: ", tf.__version__) + +g = tc.templates.graphs.Line1D(nwires, pbc=False) +time0 = time.perf_counter() +h13 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (tensorflow) time: ", time1 - time0) +print("--------------------") -print("tc time: ", time1 - time0) # 2. quimb approach for TFIM -builder = quimb.tensor.tensor_gen.SpinHam() +print("hamiltonian building with quimb") +print("quimb version: ", quimb.__version__) + +builder = quimb.tensor.SpinHam1D() # spin operator instead of Pauli matrix builder += 4, "Z", "Z" builder += -2, "X" -time0 = time.time() +time0 = time.perf_counter() h2 = builder.build_sparse(nwires) h2 = h2.tocoo() -time1 = time.time() +time1 = time.perf_counter() print("quimb time: ", time1 - time0) @@ -43,4 +93,25 @@ def assert_equal(h1, h2): np.testing.assert_allclose(h1.data, h2.data, atol=1e-5) -assert_equal(h1, h2) +# numpy +assert_equal(h11, h2) + +# jax +scipy_coo = scipy.sparse.coo_matrix( + ( + h12.data, + (h12.indices[:, 0], h12.indices[:, 1]), + ), + shape=h12.shape, +) +assert_equal(scipy_coo, h2) + +# tensorflow +scipy_coo = scipy.sparse.coo_matrix( + ( + h13.values, + (h13.indices[:, 0], h13.indices[:, 1]), + ), + shape=h13.shape, +) +assert_equal(scipy_coo, h2) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 33fe8163..eb3d6637 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1247,8 +1247,6 @@ def heisenberg_hamiltonian( weight.append(hy) ls = num_to_tensor(ls) weight = num_to_tensor(weight) - ls = get_backend("tensorflow").cast(ls, dtypestr) - weight = get_backend("tensorflow").cast(weight, dtypestr) if sparse: r = PauliStringSum2COO_numpy(ls, weight) if numpy: From 313ddd39a8d4acb77fb20927e171d2af3d0d1f9c Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 30 May 2024 15:21:38 +0900 Subject: [PATCH 091/139] lint: fix lint --- tensorcircuit/quantum.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index eb3d6637..9662e97b 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -37,7 +37,6 @@ remove_node, ) -from .backends import get_backend from .cons import backend, contractor, dtypestr, npdtype, rdtypestr from .gates import Gate, num_to_tensor from .utils import arg_alias From 0366583144590a7c2dea89524c062bc3f5b9ac54 Mon Sep 17 00:00:00 2001 From: Gopal Dahale Date: Thu, 30 May 2024 12:35:38 +0530 Subject: [PATCH 092/139] Added compass. Kept inital parameters same for all --- examples/vqe_noisyopt.py | 69 ++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/examples/vqe_noisyopt.py b/examples/vqe_noisyopt.py index 8fa06bd3..2c59026b 100644 --- a/examples/vqe_noisyopt.py +++ b/examples/vqe_noisyopt.py @@ -9,7 +9,7 @@ import tensorcircuit as tc from tensorcircuit import experimental as E from noisyopt import minimizeCompass, minimizeSPSA -from tabulate import tabulate +from tabulate import tabulate # pip install tabulate seed = 42 np.random.seed(seed) @@ -20,10 +20,14 @@ n = 6 nlayers = 4 +# initial value of the parameters +initial_value = np.random.uniform(size=[n * nlayers * 2]) + result = { "Algorithm / Optimization": ["Without Shot Noise", "With Shot Noise"], - "Gradient Free": [], - "Gradient based": [], + "SPSA (Gradient Free)": [], + "Compass Search (Gradient Free)": [], + "Adam (Gradient based)": [], } # We use OBC 1D TFIM Hamiltonian in this script @@ -113,14 +117,26 @@ def exp_val_analytical(param): r = minimizeSPSA( func=exp_val_analytical, - x0=np.random.uniform(size=[n * nlayers * 2]), + x0=initial_value, niter=6000, paired=False, ) print(r) -print(">> Converged as (Gradient Free) :", exp_val_analytical(r.x)) -result["Gradient Free"].append(exp_val_analytical(r.x)) +print(">> SPSA converged as:", exp_val_analytical(r.x)) +result["SPSA (Gradient Free)"].append(exp_val_analytical(r.x)) + +r = minimizeCompass( + func=exp_val_analytical, + x0=initial_value, + deltatol=0.1, + feps=1e-3, + paired=False, +) + +print(r) +print(">> Compass converged as:", exp_val_analytical(r.x)) +result["Compass Search (Gradient Free)"].append(exp_val_analytical(r.x)) # 1.2 VQE with numerically exact expectation: gradient based @@ -128,16 +144,16 @@ def exp_val_analytical(param): init_value=1e-2, transition_steps=500, decay_rate=0.9 ) opt = K.optimizer(optax.adam(exponential_decay_scheduler)) -param = K.implicit_randn([n, nlayers, 2], stddev=0.1) # zeros stall the gradient +param = initial_value.reshape((n, nlayers, 2)) # zeros stall the gradient exp_val_grad_analytical = K.jit(K.value_and_grad(exp_val_analytical)) for i in range(1000): e, g = exp_val_grad_analytical(param) param = opt.update(g, param) if i % 100 == 99: - print(e) + print(f"Expectation value at iteration {i}: {e}") -print(">> Converged as (Gradient based):", exp_val_grad_analytical(param)[0]) -result["Gradient based"].append(exp_val_grad_analytical(param)[0]) +print(">> Adam converged as:", exp_val_grad_analytical(param)[0]) +result["Adam (Gradient based)"].append(exp_val_grad_analytical(param)[0]) # 2.1 VQE with finite shot noise: gradient free @@ -145,7 +161,7 @@ def exp_val_analytical(param): print(">>> VQE with shot noise") -rkey = K.get_random_state(42) +rkey = K.get_random_state(seed) def exp_val_wrapper(param): @@ -158,13 +174,26 @@ def exp_val_wrapper(param): r = minimizeSPSA( func=exp_val_wrapper, - x0=np.random.uniform(size=[n * nlayers * 2]), + x0=initial_value, niter=6000, paired=False, ) print(r) -print(">> Converged as (Gradient Free) :", exp_val_wrapper(r["x"])) -result["Gradient Free"].append(exp_val_wrapper(r["x"])) +print(">> SPSA converged as:", exp_val_wrapper(r["x"])) +result["SPSA (Gradient Free)"].append(exp_val_wrapper(r["x"])) + +r = minimizeCompass( + func=exp_val_wrapper, + x0=initial_value, + deltatol=0.1, + feps=1e-2, + paired=False, +) + +print(r) +print(">> Compass converged as:", exp_val_wrapper(r["x"])) +result["Compass Search (Gradient Free)"].append(exp_val_wrapper(r["x"])) + # 2.2 VQE with finite shot noise: gradient based @@ -172,9 +201,9 @@ def exp_val_wrapper(param): init_value=1e-2, transition_steps=500, decay_rate=0.9 ) opt = K.optimizer(optax.adam(exponential_decay_scheduler)) -param = K.implicit_randn([n, nlayers, 2], stddev=0.1) # zeros stall the gradient +param = initial_value.reshape((n, nlayers, 2)) # zeros stall the gradient exp_grad = E.parameter_shift_grad_v2(exp_val, argnums=0, random_argnums=1) -rkey = K.get_random_state(42) +rkey = K.get_random_state(seed) for i in range(1000): rkey, skey = K.random_split(rkey) @@ -182,13 +211,13 @@ def exp_val_wrapper(param): param = opt.update(g, param) if i % 100 == 99: rkey, skey = K.random_split(rkey) - print(exp_val(param, skey)) + print(f"Expectation value at iteration {i}: {exp_val(param, skey)}") # the real energy position after optimization -print(">> Converged as (Gradient based):", exp_val_analytical(param)) -result["Gradient based"].append(exp_val_analytical(param)) +print(">> Adam converged as:", exp_val_analytical(param)) +result["Adam (Gradient based)"].append(exp_val_analytical(param)) print("==================================================================") print(">>> Benchmark") print(">> Exact ground state energy: ", exact_gs_energy) -print(tabulate(result, headers="keys")) +print(tabulate(result, headers="keys", tablefmt="github")) From 856c6500df9f067a8be3798f1df48a07aa329171 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 30 May 2024 15:51:05 +0800 Subject: [PATCH 093/139] jit the paulistrsum --- examples/hamiltonian_building.py | 19 ++++++++++++-- requirements/requirements-extra.txt | 2 +- tensorcircuit/quantum.py | 39 ++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/examples/hamiltonian_building.py b/examples/hamiltonian_building.py index 91ce33a7..80385265 100644 --- a/examples/hamiltonian_building.py +++ b/examples/hamiltonian_building.py @@ -9,14 +9,12 @@ import quimb import scipy import tensorflow as tf -import torch import tensorcircuit as tc tc.set_dtype("complex128") nwires = 20 -# tc with numpy backend outperforms quimb in large nwires print("--------------------") @@ -51,6 +49,14 @@ time1 = time.perf_counter() print("tc (jax) time: ", time1 - time0) + +time0 = time.perf_counter() +h12 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (jax) time (after jit): ", time1 - time0) print("--------------------") # 1.3 tc approach for TFIM (tensorflow backend) @@ -67,6 +73,15 @@ time1 = time.perf_counter() print("tc (tensorflow) time: ", time1 - time0) + +time0 = time.perf_counter() +h13 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (tensorflow) time (after jit): ", time1 - time0) + print("--------------------") diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index e5cd85a8..63e1f992 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -4,7 +4,7 @@ qiskit-aer<1.0 qiskit-nature mitiq cirq -torch +torch==2.2.2 # jupyter mthree==1.1.0 openfermion diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 9662e97b..a2c54bb6 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1330,12 +1330,21 @@ def PauliStringSum2COO( if weight is None: weight = [1.0 for _ in range(nterms)] weight = num_to_tensor(weight) + ls = num_to_tensor(ls) # rsparse = get_backend("numpy").coo_sparse_matrix( # indices=np.array([[0, 0]], dtype=np.int64), # values=np.array([0.0], dtype=getattr(np, dtypestr)), # shape=(s, s), # ) - rsparses = [backend.numpy(PauliString2COO(ls[i], weight[i])) for i in range(nterms)] # type: ignore + global PauliString2COO_jit + if backend.name not in PauliString2COO_jit: + PauliString2COO_jit[backend.name] = backend.jit( + PauliString2COO, jit_compile=True + ) + rsparses = [ + backend.numpy(PauliString2COO_jit[backend.name](ls[i], weight[i])) # type: ignore + for i in range(nterms) + ] rsparse = _dc_sum(rsparses) # auto transformed into csr format!! @@ -1372,6 +1381,7 @@ def PauliStringSum2COO_tf( ) -> Tensor: """ Generate tensorflow sparse matrix from Pauli string sum + [deprecated] :param ls: 2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` @@ -1416,19 +1426,27 @@ def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: :rtype: Tensor """ n = len(l) + l = backend.cast(l, dtype="int64") one = num_to_tensor(0b1, dtype="int64") idx_x = num_to_tensor(0b0, dtype="int64") idx_y = num_to_tensor(0b0, dtype="int64") idx_z = num_to_tensor(0b0, dtype="int64") i = num_to_tensor(0, dtype="int64") - for j in l: - # i, j from enumerate is python, non jittable when cond using tensor - if j == 1: # xi - idx_x += backend.left_shift(one, n - i - 1) - elif j == 2: # yi - idx_y += backend.left_shift(one, n - i - 1) - elif j == 3: # zi - idx_z += backend.left_shift(one, n - i - 1) + # for j in l: + for j in range(n): + oh = backend.onehot(l[j], 4) + s = backend.left_shift(one, n - i - 1) + oh = backend.cast(oh, dtype="int64") + idx_x += oh[1] * s + idx_y += oh[2] * s + idx_z += oh[3] * s + + # if j == 1: # xi + # idx_x += backend.left_shift(one, n - i - 1) + # elif j == 2: # yi + # idx_y += backend.left_shift(one, n - i - 1) + # elif j == 3: # zi + # idx_z += backend.left_shift(one, n - i - 1) i += 1 if weight is None: @@ -1436,6 +1454,9 @@ def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: return ps2coo_core(idx_x, idx_y, idx_z, weight, n) +PauliString2COO_jit = {"numpy": PauliString2COO} + + def ps2coo_core( idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int ) -> Tuple[Tensor, Tensor]: From f0d561b21c1b72943014ac87ff763e0ddbaac0d5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 08:12:29 +0000 Subject: [PATCH 094/139] docs: update README.md [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 845a6750..dbdfb554 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. ztzhu
ztzhu

💻 Rabqubit
Rabqubit

💡 - Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 + Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 💡 From 14609aa7b9da6f2edc05d47f280d313bf9b91b38 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 08:12:30 +0000 Subject: [PATCH 095/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2afd3367..fb02e2fa 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -309,7 +309,8 @@ "contributions": [ "code", "test", - "doc" + "doc", + "example" ] } ], From 05f6c445af3d110a3f0507f615464bb47cfa4626 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 30 May 2024 16:32:49 +0800 Subject: [PATCH 096/139] lint the example --- examples/vqe_noisyopt.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/vqe_noisyopt.py b/examples/vqe_noisyopt.py index 2c59026b..8bd18948 100644 --- a/examples/vqe_noisyopt.py +++ b/examples/vqe_noisyopt.py @@ -4,12 +4,11 @@ from functools import partial import numpy as np -from scipy import optimize import optax -import tensorcircuit as tc -from tensorcircuit import experimental as E from noisyopt import minimizeCompass, minimizeSPSA from tabulate import tabulate # pip install tabulate +import tensorcircuit as tc +from tensorcircuit import experimental as E seed = 42 np.random.seed(seed) From d554eb3ece84ab04b00babf60096f5ece17b62ab Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 08:34:29 +0000 Subject: [PATCH 097/139] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dbdfb554..224e1a67 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. ztzhu
ztzhu

💻 Rabqubit
Rabqubit

💡 Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 💡 + Gopal Ramesh Dahale
Gopal Ramesh Dahale

💡 From ebca718f989bc854aa8ee20b7748033014697a52 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 08:34:30 +0000 Subject: [PATCH 098/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index fb02e2fa..3fec6727 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -312,6 +312,15 @@ "doc", "example" ] + }, + { + "login": "Gopal-Dahale", + "name": "Gopal Ramesh Dahale", + "avatar_url": "https://avatars.githubusercontent.com/u/49199003?v=4", + "profile": "https://gopal-dahale.github.io/", + "contributions": [ + "example" + ] } ], "contributorsPerLine": 6, From 54bd507be65708e9a97a05556fc94e826b8c260e Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Thu, 30 May 2024 16:42:00 +0800 Subject: [PATCH 099/139] fix non tensor input --- tensorcircuit/quantum.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index a2c54bb6..23bb926c 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1426,7 +1426,8 @@ def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: :rtype: Tensor """ n = len(l) - l = backend.cast(l, dtype="int64") + l = num_to_tensor(l, dtype="int64") + # l = backend.cast(l, dtype="int64") one = num_to_tensor(0b1, dtype="int64") idx_x = num_to_tensor(0b0, dtype="int64") idx_y = num_to_tensor(0b0, dtype="int64") From f0c1c80259cfdf1d51c932a1d19dbd50da408550 Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Fri, 31 May 2024 19:28:55 +0900 Subject: [PATCH 100/139] chore: add example --- examples/cotengra_setting_bench.py | 142 +++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 examples/cotengra_setting_bench.py diff --git a/examples/cotengra_setting_bench.py b/examples/cotengra_setting_bench.py new file mode 100644 index 00000000..2ffee840 --- /dev/null +++ b/examples/cotengra_setting_bench.py @@ -0,0 +1,142 @@ +""" +Optimization for performance comparison with different cotengra settings. +(random layouts averaged). +""" + +import itertools +import sys +import warnings + +import cotengra as ctg +import networkx as nx +import numpy as np + +sys.path.insert(0, "../") +import tensorcircuit as tc + +try: + import kahypar +except ImportError: + print("kahypar not installed, please install it to run this script.") + exit() + + +# suppress the warning from cotengra +warnings.filterwarnings( + "ignore", + message="The inputs or output of this tree are not ordered." + "Costs will be accurate but actually contracting requires " + "ordered indices corresponding to array axes.", +) + +K = tc.set_backend("jax") + + +def generate_circuit(param, g, n, nlayers): + # construct the circuit ansatz + c = tc.Circuit(n) + for i in range(n): + c.H(i) + for j in range(nlayers): + c = tc.templates.blocks.QAOA_block(c, g, param[j, 0], param[j, 1]) + return c + + +def trigger_cotengra_optimization(n, nlayers, d): + g = nx.random_regular_graph(d, n) + + # define the loss function + def loss_f(params, n, nlayers): + + c = generate_circuit(params, g, n, nlayers) + + # calculate the loss function, max cut + loss = 0.0 + for e in g.edges: + loss += c.expectation_ps(z=[e[0], e[1]]) + + return K.real(loss) + + params = K.implicit_randn(shape=[nlayers, 2]) + + # run only once to trigger the compilation + K.jit( + K.value_and_grad(loss_f, argnums=0), + static_argnums=(1, 2), + )(params, n, nlayers) + + +# define the cotengra optimizer parameters +methods_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#drivers + "greedy", + "kahypar", + "labels", + # "spinglass", # requires igraph + # "labelprop", # requires igraph + # "betweenness", # requires igraph + # "walktrap", # requires igraph + # "quickbb", # requires https://github.com/dechterlab/quickbb + # "flowcutter", # requires https://github.com/kit-algo/flow-cutter-pace17 +] + +optlib_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#optimization-library + "optuna", # pip install optuna + "random", + # "baytune", # pip install baytune + # "nevergrad", # pip install nevergrad + # "chocolate", # pip install git+https://github.com/AIworx-Labs/chocolate@master + # "skopt", # pip install scikit-optimize +] + +post_processing_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#slicing-and-subtree-reconfiguration + (None, None), + ("slicing_opts", {"target_size": 2**28}), + ("slicing_reconf_opts", {"target_size": 2**28}), + ("reconf_opts", {}), + ("simulated_annealing_opts", {}), +] + + +def get_optimizer(method, optlib, post_processing): + if post_processing[0] is None: + return ctg.HyperOptimizer( + methods=method, + optlib=optlib, + minimize="flops", + parallel=True, + max_time=30, + max_repeats=30, + progbar=True, + ) + else: + return ctg.HyperOptimizer( + methods=method, + optlib=optlib, + minimize="flops", + parallel=True, + max_time=30, + max_repeats=30, + progbar=True, + **{post_processing[0]: post_processing[1]}, + ) + + +if __name__ == "__main__": + # define the parameters + n = 20 + nlayers = 15 + d = 3 + + for method, optlib, post_processing in itertools.product( + methods_args, optlib_args, post_processing_args + ): + print(f"method: {method}, optlib: {optlib}, post_processing: {post_processing}") + tc.set_contractor( + "custom", + optimizer=get_optimizer(method, optlib, post_processing), + contraction_info=True, + preprocessing=True, + debug_level=2, # no computation + ) + trigger_cotengra_optimization(n, nlayers, d) + print("-------------------------") From 13b543ac5a2e98de91c0f88c25ffc6764f826a76 Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Fri, 31 May 2024 19:29:49 +0900 Subject: [PATCH 101/139] chore: comment change --- examples/cotengra_setting_bench.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/cotengra_setting_bench.py b/examples/cotengra_setting_bench.py index 2ffee840..662a8b73 100644 --- a/examples/cotengra_setting_bench.py +++ b/examples/cotengra_setting_bench.py @@ -1,6 +1,5 @@ """ Optimization for performance comparison with different cotengra settings. -(random layouts averaged). """ import itertools From 9827b394961b7606021203bee8931a97645224fe Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Mon, 3 Jun 2024 14:41:24 +0900 Subject: [PATCH 102/139] feat: add more settings for cotengra benchmark example --- examples/cotengra_setting_bench.py | 70 ++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/examples/cotengra_setting_bench.py b/examples/cotengra_setting_bench.py index 662a8b73..3143cc18 100644 --- a/examples/cotengra_setting_bench.py +++ b/examples/cotengra_setting_bench.py @@ -41,17 +41,16 @@ def generate_circuit(param, g, n, nlayers): return c -def trigger_cotengra_optimization(n, nlayers, d): - g = nx.random_regular_graph(d, n) +def trigger_cotengra_optimization(n, nlayers, graph): # define the loss function def loss_f(params, n, nlayers): - c = generate_circuit(params, g, n, nlayers) + c = generate_circuit(params, graph, n, nlayers) # calculate the loss function, max cut loss = 0.0 - for e in g.edges: + for e in graph.edges: loss += c.expectation_ps(z=[e[0], e[1]]) return K.real(loss) @@ -60,12 +59,28 @@ def loss_f(params, n, nlayers): # run only once to trigger the compilation K.jit( - K.value_and_grad(loss_f, argnums=0), + loss_f, static_argnums=(1, 2), )(params, n, nlayers) +# define the benchmark parameters +n = 10 +nlayers = 15 + # define the cotengra optimizer parameters +graph_args = { + "1D lattice": nx.convert_node_labels_to_integers( + nx.grid_graph((n, 1)) + ), # 1D lattice + "2D lattice": nx.convert_node_labels_to_integers( + nx.grid_graph((n // 5, n // (n // 5))) + ), # 2D lattice + "all-to-all connected": nx.convert_node_labels_to_integers( + nx.complete_graph(n) + ), # all-to-all connected +} + methods_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#drivers "greedy", "kahypar", @@ -79,10 +94,10 @@ def loss_f(params, n, nlayers): ] optlib_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#optimization-library - "optuna", # pip install optuna - "random", + # "optuna", # pip install optuna + "random", # default when no library is installed # "baytune", # pip install baytune - # "nevergrad", # pip install nevergrad + "nevergrad", # pip install nevergrad # "chocolate", # pip install git+https://github.com/AIworx-Labs/chocolate@master # "skopt", # pip install scikit-optimize ] @@ -95,47 +110,56 @@ def loss_f(params, n, nlayers): ("simulated_annealing_opts", {}), ] +minimize_args = [ # https://cotengra.readthedocs.io/en/main/advanced.html#objective + "flops", # minimize the total number of scalar operations + "size", # minimize the size of the largest intermediate tensor + "write", # minimize the sum of sizes of all intermediate tensors + "combo", # minimize the sum of FLOPS + α * WRITE where α is 64 +] + -def get_optimizer(method, optlib, post_processing): +def get_optimizer(method, optlib, post_processing, minimize): if post_processing[0] is None: return ctg.HyperOptimizer( methods=method, optlib=optlib, - minimize="flops", + minimize=minimize, parallel=True, max_time=30, - max_repeats=30, + max_repeats=128, progbar=True, ) else: return ctg.HyperOptimizer( methods=method, optlib=optlib, - minimize="flops", + minimize=minimize, parallel=True, max_time=30, - max_repeats=30, + max_repeats=128, progbar=True, **{post_processing[0]: post_processing[1]}, ) if __name__ == "__main__": - # define the parameters - n = 20 - nlayers = 15 - d = 3 - - for method, optlib, post_processing in itertools.product( - methods_args, optlib_args, post_processing_args + for graph, method, optlib, post_processing, minimize in itertools.product( + graph_args.keys(), + methods_args, + optlib_args, + post_processing_args, + minimize_args, ): - print(f"method: {method}, optlib: {optlib}, post_processing: {post_processing}") + print( + f"graph: {graph}, method: {method}, optlib: {optlib}, " + f"post_processing: {post_processing}, minimize: {minimize}" + ) tc.set_contractor( "custom", - optimizer=get_optimizer(method, optlib, post_processing), + optimizer=get_optimizer(method, optlib, post_processing, minimize), contraction_info=True, preprocessing=True, debug_level=2, # no computation ) - trigger_cotengra_optimization(n, nlayers, d) + trigger_cotengra_optimization(n, nlayers, graph_args[graph]) print("-------------------------") From ed378cb78a2c889c2bb8e3c0c72f3e0f47c28621 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Mon, 3 Jun 2024 15:31:40 +0800 Subject: [PATCH 103/139] improve cotengra benchmark example --- examples/cotengra_setting_bench.py | 31 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/examples/cotengra_setting_bench.py b/examples/cotengra_setting_bench.py index 3143cc18..d1b3f1b7 100644 --- a/examples/cotengra_setting_bench.py +++ b/examples/cotengra_setting_bench.py @@ -48,10 +48,7 @@ def loss_f(params, n, nlayers): c = generate_circuit(params, graph, n, nlayers) - # calculate the loss function, max cut - loss = 0.0 - for e in graph.edges: - loss += c.expectation_ps(z=[e[0], e[1]]) + loss = c.expectation_ps(z=[0, 1, 2], reuse=False) return K.real(loss) @@ -65,8 +62,8 @@ def loss_f(params, n, nlayers): # define the benchmark parameters -n = 10 -nlayers = 15 +n = 12 +nlayers = 12 # define the cotengra optimizer parameters graph_args = { @@ -84,7 +81,7 @@ def loss_f(params, n, nlayers): methods_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#drivers "greedy", "kahypar", - "labels", + # "labels", # "spinglass", # requires igraph # "labelprop", # requires igraph # "betweenness", # requires igraph @@ -94,26 +91,26 @@ def loss_f(params, n, nlayers): ] optlib_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#optimization-library - # "optuna", # pip install optuna - "random", # default when no library is installed + "optuna", # pip install optuna + # "random", # default when no library is installed # "baytune", # pip install baytune - "nevergrad", # pip install nevergrad + # "nevergrad", # pip install nevergrad # "chocolate", # pip install git+https://github.com/AIworx-Labs/chocolate@master # "skopt", # pip install scikit-optimize ] post_processing_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#slicing-and-subtree-reconfiguration (None, None), - ("slicing_opts", {"target_size": 2**28}), - ("slicing_reconf_opts", {"target_size": 2**28}), + # ("slicing_opts", {"target_size": 2**28}), + # ("slicing_reconf_opts", {"target_size": 2**28}), ("reconf_opts", {}), ("simulated_annealing_opts", {}), ] minimize_args = [ # https://cotengra.readthedocs.io/en/main/advanced.html#objective - "flops", # minimize the total number of scalar operations - "size", # minimize the size of the largest intermediate tensor - "write", # minimize the sum of sizes of all intermediate tensors + # "flops", # minimize the total number of scalar operations + # "size", # minimize the size of the largest intermediate tensor + # "write", # minimize the sum of sizes of all intermediate tensors "combo", # minimize the sum of FLOPS + α * WRITE where α is 64 ] @@ -125,7 +122,7 @@ def get_optimizer(method, optlib, post_processing, minimize): optlib=optlib, minimize=minimize, parallel=True, - max_time=30, + max_time=60, max_repeats=128, progbar=True, ) @@ -135,7 +132,7 @@ def get_optimizer(method, optlib, post_processing, minimize): optlib=optlib, minimize=minimize, parallel=True, - max_time=30, + max_time=60, max_repeats=128, progbar=True, **{post_processing[0]: post_processing[1]}, From b5aee2e0772ea875c594929f0724a251c964917d Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Tue, 11 Jun 2024 02:48:04 +0900 Subject: [PATCH 104/139] change: add stabilizer simulation example --- examples/stabilizer_simulation.py | 162 ++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 examples/stabilizer_simulation.py diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py new file mode 100644 index 00000000..8daa2abc --- /dev/null +++ b/examples/stabilizer_simulation.py @@ -0,0 +1,162 @@ +import numpy as np +import stim + +import tensorcircuit as tc + +np.random.seed(0) + +tc.set_dtype("complex128") + +clifford_one_qubit_gates = ["h", "x", "y", "z", "s"] +clifford_two_qubit_gates = ["cnot"] +clifford_gates = clifford_one_qubit_gates + clifford_two_qubit_gates + + +def genpair(num_qubits, count): + choice = list(range(num_qubits)) + for _ in range(count): + np.random.shuffle(choice) + x, y = choice[:2] + yield (x, y) + + +def random_clifford_circuit_with_mid_measurement(num_qubits, depth): + c = tc.Circuit(num_qubits) + for _ in range(depth): + for j, k in genpair(num_qubits, 2): + c.cnot(j, k) + for j in range(num_qubits): + getattr(c, np.random.choice(clifford_one_qubit_gates))(j) + measured_qubit = np.random.randint(0, num_qubits - 1) + sample, p = c.measure_reference(measured_qubit, with_prob=True) + # Check if there is a non-zero probability to measure "0" for post-selection + if (sample == "0" and p > 0.0) or (sample == "1" and p < 1.0): + c.mid_measurement(measured_qubit, keep=0) + c.measure_instruction(measured_qubit) + return c + + +def convert_tc_circuit_to_stim_circuit(tc_circuit): + stim_circuit = stim.Circuit() + for instruction in tc_circuit._qir: + gate_name = instruction["gate"].name + qubits = instruction.get("index", []) + if gate_name == "x": + stim_circuit.append("X", qubits) + elif gate_name == "y": + stim_circuit.append("Y", qubits) + elif gate_name == "z": + stim_circuit.append("Z", qubits) + elif gate_name == "h": + stim_circuit.append("H", qubits) + elif gate_name == "cnot": + stim_circuit.append("CNOT", qubits) + elif gate_name == "s": + stim_circuit.append("S", qubits) + else: + raise ValueError(f"Unsupported gate: {gate_name}") + for measurement in tc_circuit._extra_qir: + qubit = measurement["index"] + stim_circuit.append("M", qubit) + return stim_circuit + + +# ref: https://quantumcomputing.stackexchange.com/questions/16718/measuring-entanglement-entropy-using-a-stabilizer-circuit-simulator +def get_binary_matrix(z_stabilizers): + N = len(z_stabilizers) + binary_matrix = np.zeros((N, 2 * N)) + r = 0 # Row number + for row in z_stabilizers: + c = 0 # Column number + for i in row: + if i == 3: # Pauli Z + binary_matrix[r, N + c] = 1 + if i == 2: # Pauli Y + binary_matrix[r, N + c] = 1 + binary_matrix[r, c] = 1 + if i == 1: # Pauli X + binary_matrix[r, c] = 1 + c += 1 + r += 1 + + return binary_matrix + + +def get_bipartite_binary_matrix(binary_matrix, cut): + N = len(binary_matrix) + cutMatrix = np.zeros((N, 2 * cut)) + + cutMatrix[:, :cut] = binary_matrix[:, :cut] + cutMatrix[:, cut:] = binary_matrix[:, N : N + cut] + + return cutMatrix + + +# ref: https://gist.github.com/StuartGordonReid/eb59113cb29e529b8105?permalink_comment_id=3268301#gistcomment-3268301 +def gf2_rank(matrix): + n = len(matrix[0]) + rank = 0 + for col in range(n): + j = 0 + rows = [] + while j < len(matrix): + if matrix[j][col] == 1: + rows += [j] + j += 1 + if len(rows) >= 1: + for c in range(1, len(rows)): + for k in range(n): + matrix[rows[c]][k] = (matrix[rows[c]][k] + matrix[rows[0]][k]) % 2 + matrix.pop(rows[0]) + rank += 1 + for row in matrix: + if sum(row) > 0: + rank += 1 + return rank + + +# ref: https://quantumcomputing.stackexchange.com/questions/27795/exact-probabilities-of-outcomes-for-clifford-circuits-with-mid-circuit-measureme +def simulate_stim_circuit_with_mid_measurement(stim_circuit): + simulator = stim.TableauSimulator() + + for instruction in stim_circuit.flattened(): + if instruction.name == "M": + for t in instruction.targets_copy(): + expectaction = simulator.peek_z(t.value) + desired = 0 + if expectaction == -1: + desired = 1 + simulator.postselect_z(t.value, desired_value=desired) + else: + c = stim.Circuit() + c.append(instruction) + simulator.do_circuit(c) + + return simulator.current_inverse_tableau() ** -1 + + +if __name__ == "__main__": + num_qubits = 10 + depth = 8 + + tc_circuit = random_clifford_circuit_with_mid_measurement(num_qubits, depth) + print(tc_circuit.draw(output="text")) + + stim_circuit = convert_tc_circuit_to_stim_circuit(tc_circuit) + + # Entanglement entropy calculation using stabilizer formalism + stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) + zs = [stabilizer_tableau.z_output(k) for k in range(len(stabilizer_tableau))] + binary_matrix = get_binary_matrix(zs) + cut_matrix = get_bipartite_binary_matrix(binary_matrix, num_qubits // 2) + custom_entropy = (gf2_rank(cut_matrix.tolist()) - num_qubits // 2) * np.log(2) + print("Stim Entanglement Entropy:", custom_entropy) + + # Entanglement entropy calculation using TensorCircuit + state_vector = tc_circuit.wavefunction() + assert np.linalg.norm(state_vector) > 0 + state_vector /= np.linalg.norm(state_vector) + baseline_entropy = tc.quantum.entanglement_entropy(state_vector, num_qubits // 2) + print("TensorCircuit Entanglement Entropy:", baseline_entropy) + + np.testing.assert_allclose(custom_entropy, baseline_entropy, atol=1e-8) From 053641eb666b2d25991b42e2640d9b875a6d6747 Mon Sep 17 00:00:00 2001 From: king-p3nguin Date: Tue, 11 Jun 2024 03:11:54 +0900 Subject: [PATCH 105/139] change: add comments --- examples/stabilizer_simulation.py | 65 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py index 8daa2abc..1c97fc57 100644 --- a/examples/stabilizer_simulation.py +++ b/examples/stabilizer_simulation.py @@ -56,8 +56,8 @@ def convert_tc_circuit_to_stim_circuit(tc_circuit): else: raise ValueError(f"Unsupported gate: {gate_name}") for measurement in tc_circuit._extra_qir: - qubit = measurement["index"] - stim_circuit.append("M", qubit) + qubits = measurement["index"] + stim_circuit.append("M", qubits) return stim_circuit @@ -65,31 +65,26 @@ def convert_tc_circuit_to_stim_circuit(tc_circuit): def get_binary_matrix(z_stabilizers): N = len(z_stabilizers) binary_matrix = np.zeros((N, 2 * N)) - r = 0 # Row number - for row in z_stabilizers: - c = 0 # Column number - for i in row: - if i == 3: # Pauli Z - binary_matrix[r, N + c] = 1 - if i == 2: # Pauli Y - binary_matrix[r, N + c] = 1 - binary_matrix[r, c] = 1 - if i == 1: # Pauli X - binary_matrix[r, c] = 1 - c += 1 - r += 1 - + for row_idx, row in enumerate(z_stabilizers): + for col_idx, col in enumerate(row): + if col == 3: # Pauli Z + binary_matrix[row_idx, N + col_idx] = 1 + if col == 2: # Pauli Y + binary_matrix[row_idx, N + col_idx] = 1 + binary_matrix[row_idx, col_idx] = 1 + if col == 1: # Pauli X + binary_matrix[row_idx, col_idx] = 1 return binary_matrix def get_bipartite_binary_matrix(binary_matrix, cut): N = len(binary_matrix) - cutMatrix = np.zeros((N, 2 * cut)) + bipartite_binary_matrix = np.zeros((N, 2 * cut)) - cutMatrix[:, :cut] = binary_matrix[:, :cut] - cutMatrix[:, cut:] = binary_matrix[:, N : N + cut] + bipartite_binary_matrix[:, :cut] = binary_matrix[:, :cut] + bipartite_binary_matrix[:, cut:] = binary_matrix[:, N : N + cut] - return cutMatrix + return bipartite_binary_matrix # ref: https://gist.github.com/StuartGordonReid/eb59113cb29e529b8105?permalink_comment_id=3268301#gistcomment-3268301 @@ -122,15 +117,16 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): for instruction in stim_circuit.flattened(): if instruction.name == "M": for t in instruction.targets_copy(): - expectaction = simulator.peek_z(t.value) - desired = 0 - if expectaction == -1: - desired = 1 - simulator.postselect_z(t.value, desired_value=desired) + expectaction_value = simulator.peek_z(t.value) + desired_measurement_outcome = 0 + if expectaction_value == -1: # zero probability to measure "0" + desired_measurement_outcome = 1 + simulator.postselect_z( + t.value, + desired_value=desired_measurement_outcome, + ) else: - c = stim.Circuit() - c.append(instruction) - simulator.do_circuit(c) + simulator.do(instruction) return simulator.current_inverse_tableau() ** -1 @@ -148,15 +144,16 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) zs = [stabilizer_tableau.z_output(k) for k in range(len(stabilizer_tableau))] binary_matrix = get_binary_matrix(zs) - cut_matrix = get_bipartite_binary_matrix(binary_matrix, num_qubits // 2) - custom_entropy = (gf2_rank(cut_matrix.tolist()) - num_qubits // 2) * np.log(2) - print("Stim Entanglement Entropy:", custom_entropy) + bipartite_matrix = get_bipartite_binary_matrix(binary_matrix, num_qubits // 2) + stim_entropy = (gf2_rank(bipartite_matrix.tolist()) - num_qubits // 2) * np.log(2) + print("Stim Entanglement Entropy:", stim_entropy) # Entanglement entropy calculation using TensorCircuit state_vector = tc_circuit.wavefunction() assert np.linalg.norm(state_vector) > 0 + # Normalize the state vector because mid-measurement operation is not unitary state_vector /= np.linalg.norm(state_vector) - baseline_entropy = tc.quantum.entanglement_entropy(state_vector, num_qubits // 2) - print("TensorCircuit Entanglement Entropy:", baseline_entropy) + tc_entropy = tc.quantum.entanglement_entropy(state_vector, num_qubits // 2) + print("TensorCircuit Entanglement Entropy:", tc_entropy) - np.testing.assert_allclose(custom_entropy, baseline_entropy, atol=1e-8) + np.testing.assert_allclose(stim_entropy, tc_entropy, atol=1e-8) From 15aa34ad0bfe42d4c85e833544c5bb674817696d Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 13 Jun 2024 10:10:32 +0900 Subject: [PATCH 106/139] fix: fix entropy inconsistency --- examples/stabilizer_simulation.py | 61 ++++++++++++------------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py index 1c97fc57..d957a6f9 100644 --- a/examples/stabilizer_simulation.py +++ b/examples/stabilizer_simulation.py @@ -7,8 +7,8 @@ tc.set_dtype("complex128") -clifford_one_qubit_gates = ["h", "x", "y", "z", "s"] -clifford_two_qubit_gates = ["cnot"] +clifford_one_qubit_gates = ["H", "X", "Y", "Z", "S"] +clifford_two_qubit_gates = ["CNOT"] clifford_gates = clifford_one_qubit_gates + clifford_two_qubit_gates @@ -22,42 +22,32 @@ def genpair(num_qubits, count): def random_clifford_circuit_with_mid_measurement(num_qubits, depth): c = tc.Circuit(num_qubits) + operation_list = [] for _ in range(depth): for j, k in genpair(num_qubits, 2): c.cnot(j, k) + operation_list.append(("CNOT", (j, k))) for j in range(num_qubits): - getattr(c, np.random.choice(clifford_one_qubit_gates))(j) + gate_name = np.random.choice(clifford_one_qubit_gates) + getattr(c, gate_name)(j) + operation_list.append((gate_name, (j,))) measured_qubit = np.random.randint(0, num_qubits - 1) sample, p = c.measure_reference(measured_qubit, with_prob=True) # Check if there is a non-zero probability to measure "0" for post-selection - if (sample == "0" and p > 0.0) or (sample == "1" and p < 1.0): + if (sample == "0" and not np.isclose(p, 0.0)) or ( + sample == "1" and not np.isclose(p, 1.0) + ): c.mid_measurement(measured_qubit, keep=0) - c.measure_instruction(measured_qubit) - return c + operation_list.append(("M", (measured_qubit,))) + return c, operation_list -def convert_tc_circuit_to_stim_circuit(tc_circuit): +def convert_operation_list_to_stim_circuit(operation_list): stim_circuit = stim.Circuit() - for instruction in tc_circuit._qir: - gate_name = instruction["gate"].name - qubits = instruction.get("index", []) - if gate_name == "x": - stim_circuit.append("X", qubits) - elif gate_name == "y": - stim_circuit.append("Y", qubits) - elif gate_name == "z": - stim_circuit.append("Z", qubits) - elif gate_name == "h": - stim_circuit.append("H", qubits) - elif gate_name == "cnot": - stim_circuit.append("CNOT", qubits) - elif gate_name == "s": - stim_circuit.append("S", qubits) - else: - raise ValueError(f"Unsupported gate: {gate_name}") - for measurement in tc_circuit._extra_qir: - qubits = measurement["index"] - stim_circuit.append("M", qubits) + for instruction in operation_list: + gate_name = instruction[0] + qubits = instruction[1] + stim_circuit.append(gate_name, qubits) return stim_circuit @@ -118,13 +108,8 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): if instruction.name == "M": for t in instruction.targets_copy(): expectaction_value = simulator.peek_z(t.value) - desired_measurement_outcome = 0 - if expectaction_value == -1: # zero probability to measure "0" - desired_measurement_outcome = 1 - simulator.postselect_z( - t.value, - desired_value=desired_measurement_outcome, - ) + if expectaction_value != -1: # non-zero probability to measure "0" + simulator.postselect_z(t.value, desired_value=0) else: simulator.do(instruction) @@ -133,12 +118,14 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): if __name__ == "__main__": num_qubits = 10 - depth = 8 + depth = 20 - tc_circuit = random_clifford_circuit_with_mid_measurement(num_qubits, depth) + tc_circuit, op_list = random_clifford_circuit_with_mid_measurement( + num_qubits, depth + ) print(tc_circuit.draw(output="text")) - stim_circuit = convert_tc_circuit_to_stim_circuit(tc_circuit) + stim_circuit = convert_operation_list_to_stim_circuit(op_list) # Entanglement entropy calculation using stabilizer formalism stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) From ca943aa81c7ac7157658f939e8dff5479d241c4b Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 13 Jun 2024 10:26:03 +0900 Subject: [PATCH 107/139] feat: allow tracing out any list of qubits in stim example --- examples/stabilizer_simulation.py | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py index d957a6f9..f87cb866 100644 --- a/examples/stabilizer_simulation.py +++ b/examples/stabilizer_simulation.py @@ -67,14 +67,12 @@ def get_binary_matrix(z_stabilizers): return binary_matrix -def get_bipartite_binary_matrix(binary_matrix, cut): +def get_cut_binary_matrix(binary_matrix, cut): N = len(binary_matrix) - bipartite_binary_matrix = np.zeros((N, 2 * cut)) - - bipartite_binary_matrix[:, :cut] = binary_matrix[:, :cut] - bipartite_binary_matrix[:, cut:] = binary_matrix[:, N : N + cut] - - return bipartite_binary_matrix + new_indices = [i for i in range(N) if i not in set(cut)] + [ + i + N for i in range(N) if i not in set(cut) + ] + return binary_matrix[:, new_indices] # ref: https://gist.github.com/StuartGordonReid/eb59113cb29e529b8105?permalink_comment_id=3268301#gistcomment-3268301 @@ -107,8 +105,9 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): for instruction in stim_circuit.flattened(): if instruction.name == "M": for t in instruction.targets_copy(): - expectaction_value = simulator.peek_z(t.value) - if expectaction_value != -1: # non-zero probability to measure "0" + expectaction_value = simulator.peek_z(t.value) # 1, 0, -1 + # there is a non-zero probability to measure "0" if expectaction_value is not -1 + if expectaction_value != -1: simulator.postselect_z(t.value, desired_value=0) else: simulator.do(instruction) @@ -117,8 +116,12 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): if __name__ == "__main__": - num_qubits = 10 - depth = 20 + # Number of qubits + num_qubits = 8 + # Depth of the circuit + depth = 10 + # index list that is traced out to calculate the entanglement entropy + cut = [i for i in range(num_qubits // 2)] tc_circuit, op_list = random_clifford_circuit_with_mid_measurement( num_qubits, depth @@ -131,8 +134,8 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) zs = [stabilizer_tableau.z_output(k) for k in range(len(stabilizer_tableau))] binary_matrix = get_binary_matrix(zs) - bipartite_matrix = get_bipartite_binary_matrix(binary_matrix, num_qubits // 2) - stim_entropy = (gf2_rank(bipartite_matrix.tolist()) - num_qubits // 2) * np.log(2) + bipartite_matrix = get_cut_binary_matrix(binary_matrix, cut) + stim_entropy = (gf2_rank(bipartite_matrix.tolist()) - len(cut)) * np.log(2) print("Stim Entanglement Entropy:", stim_entropy) # Entanglement entropy calculation using TensorCircuit @@ -140,7 +143,8 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): assert np.linalg.norm(state_vector) > 0 # Normalize the state vector because mid-measurement operation is not unitary state_vector /= np.linalg.norm(state_vector) - tc_entropy = tc.quantum.entanglement_entropy(state_vector, num_qubits // 2) + tc_entropy = tc.quantum.entanglement_entropy(state_vector, cut) print("TensorCircuit Entanglement Entropy:", tc_entropy) + # Check if the entanglement entropies are close np.testing.assert_allclose(stim_entropy, tc_entropy, atol=1e-8) From 596582f28f6249d55bfbd8949cf225ac3714addb Mon Sep 17 00:00:00 2001 From: Kazuki Tsuoka Date: Thu, 13 Jun 2024 10:37:04 +0900 Subject: [PATCH 108/139] fix: fix cut inconsistency --- examples/stabilizer_simulation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py index f87cb866..aa50e821 100644 --- a/examples/stabilizer_simulation.py +++ b/examples/stabilizer_simulation.py @@ -69,8 +69,8 @@ def get_binary_matrix(z_stabilizers): def get_cut_binary_matrix(binary_matrix, cut): N = len(binary_matrix) - new_indices = [i for i in range(N) if i not in set(cut)] + [ - i + N for i in range(N) if i not in set(cut) + new_indices = [i for i in range(N) if i in set(cut)] + [ + i + N for i in range(N) if i in set(cut) ] return binary_matrix[:, new_indices] @@ -117,11 +117,11 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): if __name__ == "__main__": # Number of qubits - num_qubits = 8 + num_qubits = 10 # Depth of the circuit - depth = 10 + depth = 30 # index list that is traced out to calculate the entanglement entropy - cut = [i for i in range(num_qubits // 2)] + cut = [i for i in range(num_qubits // 3)] tc_circuit, op_list = random_clifford_circuit_with_mid_measurement( num_qubits, depth @@ -134,8 +134,8 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) zs = [stabilizer_tableau.z_output(k) for k in range(len(stabilizer_tableau))] binary_matrix = get_binary_matrix(zs) - bipartite_matrix = get_cut_binary_matrix(binary_matrix, cut) - stim_entropy = (gf2_rank(bipartite_matrix.tolist()) - len(cut)) * np.log(2) + cur_matrix = get_cut_binary_matrix(binary_matrix, cut) + stim_entropy = (gf2_rank(cur_matrix.tolist()) - len(cut)) * np.log(2) print("Stim Entanglement Entropy:", stim_entropy) # Entanglement entropy calculation using TensorCircuit From 38fa725e20f233b10ea6cede3b584745b7d15903 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 14 Jun 2024 13:53:42 +0800 Subject: [PATCH 109/139] decrease the measurement probability --- examples/stabilizer_simulation.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py index aa50e821..699983bf 100644 --- a/examples/stabilizer_simulation.py +++ b/examples/stabilizer_simulation.py @@ -31,14 +31,15 @@ def random_clifford_circuit_with_mid_measurement(num_qubits, depth): gate_name = np.random.choice(clifford_one_qubit_gates) getattr(c, gate_name)(j) operation_list.append((gate_name, (j,))) - measured_qubit = np.random.randint(0, num_qubits - 1) - sample, p = c.measure_reference(measured_qubit, with_prob=True) - # Check if there is a non-zero probability to measure "0" for post-selection - if (sample == "0" and not np.isclose(p, 0.0)) or ( - sample == "1" and not np.isclose(p, 1.0) - ): - c.mid_measurement(measured_qubit, keep=0) - operation_list.append(("M", (measured_qubit,))) + if np.random.uniform() < 0.2: + measured_qubit = np.random.randint(0, num_qubits - 1) + sample, p = c.measure_reference(measured_qubit, with_prob=True) + # Check if there is a non-zero probability to measure "0" for post-selection + if (sample == "0" and not np.isclose(p, 0.0)) or ( + sample == "1" and not np.isclose(p, 1.0) + ): + c.mid_measurement(measured_qubit, keep=0) + operation_list.append(("M", (measured_qubit,))) return c, operation_list @@ -117,9 +118,9 @@ def simulate_stim_circuit_with_mid_measurement(stim_circuit): if __name__ == "__main__": # Number of qubits - num_qubits = 10 + num_qubits = 12 # Depth of the circuit - depth = 30 + depth = 24 # index list that is traced out to calculate the entanglement entropy cut = [i for i in range(num_qubits // 3)] From be7135490dd8a34d5386c4240a5552c284f120e2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 05:55:33 +0000 Subject: [PATCH 110/139] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 224e1a67..d4bf0753 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,7 @@ TensorCircuit is open source, released under the Apache License, Version 2.0. Rabqubit
Rabqubit

💡 Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 💡 Gopal Ramesh Dahale
Gopal Ramesh Dahale

💡 + Chanandellar Bong
Chanandellar Bong

💡 From 6bf45fd9ffdfd63a6193f9f1ed7a4a096b07e57f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 05:55:34 +0000 Subject: [PATCH 111/139] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 3fec6727..a625ed92 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -321,6 +321,15 @@ "contributions": [ "example" ] + }, + { + "login": "AbdullahKazi500", + "name": "Chanandellar Bong", + "avatar_url": "https://avatars.githubusercontent.com/u/75779966?v=4", + "profile": "https://github.com/AbdullahKazi500", + "contributions": [ + "example" + ] } ], "contributorsPerLine": 6, From 3bcda9a3eb964c3ea7cd44d24401998eb9e26767 Mon Sep 17 00:00:00 2001 From: refraction-ray Date: Fri, 14 Jun 2024 13:57:05 +0800 Subject: [PATCH 112/139] update --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index d4bf0753..c46b54c7 100644 --- a/README.md +++ b/README.md @@ -143,13 +143,6 @@ pip install tensorcircuit[tensorflow] Other optional dependencies include `[torch]`, `[jax]`, `[qiskit]` and `[cloud]`. -For the nightly build of tensorcircuit with new features, try: - -```python -pip uninstall tensorcircuit -pip install tensorcircuit-nightly -``` - We also have [Docker support](/docker). ## Advantages From 8e0c9ff340ee11a5774c33de9e4583c1232383ee Mon Sep 17 00:00:00 2001 From: abhinavd Date: Thu, 21 Nov 2024 15:08:19 -0800 Subject: [PATCH 113/139] Add option to not always normalise --- tensorcircuit/quantum.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index 23bb926c..b6ed4eab 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -1645,6 +1645,7 @@ def reduced_density_matrix( state: Union[Tensor, QuOperator], cut: Union[int, List[int]], p: Optional[Tensor] = None, + normalize: bool = True, ) -> Union[Tensor, QuOperator]: """ Compute the reduced density matrix from the quantum state ``state``. @@ -1658,6 +1659,7 @@ def reduced_density_matrix( :type p: Optional[Tensor] :return: The reduced density matrix. :rtype: Union[Tensor, QuOperator] + :normalize: if True, returns a trace 1 density matrix. Otherwise does not normalize. """ if isinstance(cut, list) or isinstance(cut, tuple) or isinstance(cut, set): traceout = list(cut) @@ -1700,7 +1702,9 @@ def reduced_density_matrix( rho = backend.reshape( rho, [2 ** (freedom - len(traceout)), 2 ** (freedom - len(traceout))] ) - rho /= backend.trace(rho) + if normalize: + rho /= backend.trace(rho) + else: w = state / backend.norm(state) @@ -1715,7 +1719,9 @@ def reduced_density_matrix( rho = w @ backend.adjoint(w) else: rho = w @ backend.diagflat(p) @ backend.adjoint(w) - rho /= backend.trace(rho) + if normalize: + rho /= backend.trace(rho) + return rho From 58835a31971b07f8a7ec566d714916386b187397 Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Fri, 18 Apr 2025 15:48:45 +0800 Subject: [PATCH 114/139] Update LICENSE --- LICENSE | 265 ++++++++++++++------------------------------------------ 1 file changed, 64 insertions(+), 201 deletions(-) diff --git a/LICENSE b/LICENSE index d6456956..253d6ac1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,202 +1,65 @@ +Tencent is pleased to support the open source community by making tensorcircuit available. - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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 - - http://www.apache.org/licenses/LICENSE-2.0 - - 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. +Copyright (C) 2025 THL A29 Limited, a Tencent company. All rights reserved. + +tensorcircuit is licensed under the Apache License Version 2.0. + + +Terms of the Apache License Version 2.0: +-------------------------------------------------------------------- +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS From 4e6c1fd32004920bf27e11aa7958ea4066db4e15 Mon Sep 17 00:00:00 2001 From: mac Date: Tue, 29 Apr 2025 21:02:45 -0700 Subject: [PATCH 115/139] Add parametric waveform control and TQASM export support --- tensorcircuit/__init__.py | 3 +- tensorcircuit/abstractcircuit.py | 9 +++ tensorcircuit/basecircuit.py | 3 + tensorcircuit/circuit.py | 85 +++++++++++++++++++++++++++ tensorcircuit/waveforms.py | 85 +++++++++++++++++++++++++++ tests/test_parametric_waveform.py | 54 +++++++++++++++++ tests/test_waveform_types_to_tqasm.py | 48 +++++++++++++++ 7 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 tensorcircuit/waveforms.py create mode 100644 tests/test_parametric_waveform.py create mode 100644 tests/test_waveform_types_to_tqasm.py diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index fb1c2e40..8092ec39 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -24,8 +24,9 @@ ) # prerun of set hooks from . import gates from . import basecircuit +from . import waveforms from .gates import Gate -from .circuit import Circuit, expectation +from .circuit import Circuit, expectation, Param from .mpscircuit import MPSCircuit from .densitymatrix import DMCircuit as DMCircuit_reference from .densitymatrix import DMCircuit2 diff --git a/tensorcircuit/abstractcircuit.py b/tensorcircuit/abstractcircuit.py index 2334aa39..7c2d119d 100644 --- a/tensorcircuit/abstractcircuit.py +++ b/tensorcircuit/abstractcircuit.py @@ -79,6 +79,14 @@ class AbstractCircuit: mpogates = mpogates gate_aliases = gate_aliases + def __init__(self, nqubits: int, *args, **kwargs): + self._nqubits = nqubits + self._qir = [] + self._extra_qir = [] + self.inputs = None + self.circuit_param = {} + self.is_mps = False + def apply_general_gate( self, gate: Union[Gate, QuOperator], @@ -114,6 +122,7 @@ def apply(self: "AbstractCircuit", *index: int, **vars: Any) -> None: gate_dict = { "gatef": gatef, "index": index, + "target": list(index), "name": localname, "split": split, "mpo": mpo, diff --git a/tensorcircuit/basecircuit.py b/tensorcircuit/basecircuit.py index 468c6a1b..cc9c5d7d 100644 --- a/tensorcircuit/basecircuit.py +++ b/tensorcircuit/basecircuit.py @@ -40,6 +40,9 @@ class BaseCircuit(AbstractCircuit): is_mps = False + def __init__(self, nqubits: int, *args, **kwargs): + super().__init__(nqubits, *args, **kwargs) + @staticmethod def all_zero_nodes(n: int, d: int = 2, prefix: str = "qb-") -> List[tn.Node]: l = [0.0 for _ in range(d)] diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index a293e3df..1bf1ead5 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -60,6 +60,11 @@ def __init__( ``max_singular_values`` and ``max_truncation_err``. :type split: Optional[Dict[str, Any]] """ + super().__init__( + nqubits=nqubits, inputs=inputs, mps_inputs=mps_inputs, split=split + ) + self.calibrations = [] + self.inputs = inputs self.mps_inputs = mps_inputs self.split = split @@ -111,6 +116,43 @@ def __init__( # self._qcode += str(self._nqubits) + "\n" self._qir: List[Dict[str, Any]] = [] self._extra_qir: List[Dict[str, Any]] = [] + + def add_calibration( + self, name: str, parameters: List[str], instructions: List[Dict] + ) -> None: + self.calibrations.append({ + "name": name, + "parameters": parameters, + "instructions": instructions + }) + + + def to_tqasm(self) -> str: + qasm_lines = [] + qasm_lines.append("OPENQASM 3;") + qasm_lines.append(f"qubit[{self._nqubits}] q;") + + for gate in self._qir: + gname = gate["name"] + targets = ", ".join(f"q[{i}]" for i in gate["target"]) + qasm_lines.append(f"{gname} {targets};") + + for cal in getattr(self, "calibrations", []): + pname = ", ".join(cal["parameters"]) + qasm_lines.append(f"\ndefcal {cal['name']}({pname}) {{") + for inst in cal["instructions"]: + if inst["type"] == "frame": + qasm_lines.append(f" frame {inst['frame']} = newframe({inst['qubit']});") + elif inst["type"] == "play": + args_str = ", ".join(str(x) for x in inst["args"]) + wf_type = inst["waveform_type"] + qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") + qasm_lines.append("}") + + return "\n".join(qasm_lines) + + def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": + return DefcalBuilder(self, name, parameters) def replace_mps_inputs(self, mps_inputs: QuOperator) -> None: """ @@ -998,3 +1040,46 @@ def expectation( else: den = 1.0 return num / den + +class Param: + def __init__(self, name: str): + self.name = name + +class DefcalBuilder: + def __init__(self, circuit, name: str, parameters: List["Param"]): + self.circuit = circuit + self.name = name + self.parameters = parameters + self.instructions = [] + + def new_frame(self, frame_name: str, param: "Param"): + self.instructions.append({ + "type": "frame", + "frame": frame_name, + "qubit": param.name, + }) + return self + + def play(self, frame_name: str, waveform: Any, start_time: int = None): + if not hasattr(waveform, "__dataclass_fields__"): + raise TypeError("Unsupported waveform type") + + waveform_type = waveform.qasm_name() + args = list(waveform.__dict__.values()) + if start_time is not None: + args = [start_time] + args + + self.instructions.append({ + "type": "play", + "frame": frame_name, + "waveform_type": waveform_type, + "args": args, + }) + return self + + def build(self): + self.circuit.add_calibration( + name=self.name, + parameters=[p.name for p in self.parameters], + instructions=self.instructions, + ) \ No newline at end of file diff --git a/tensorcircuit/waveforms.py b/tensorcircuit/waveforms.py new file mode 100644 index 00000000..7bafc93e --- /dev/null +++ b/tensorcircuit/waveforms.py @@ -0,0 +1,85 @@ +from typing import List, Union +from dataclasses import dataclass + +ParamType = Union[float, str] + +__all__ = [ + "Gaussian", + "GaussianSquare", + "Drag", + "Constant", + "Sine", + "Cosine", + "CosineDrag", + "Flattop", +] + +@dataclass +class Gaussian: + amp: ParamType + duration: int + sigma: ParamType + def qasm_name(self) -> str: + return "gaussian" + +@dataclass +class GaussianSquare: + amp: ParamType + duration: int + sigma: ParamType + width: ParamType + def qasm_name(self) -> str: + return "gaussian_square" + +@dataclass +class Drag: + amp: ParamType + duration: int + sigma: ParamType + beta: ParamType + def qasm_name(self) -> str: + return "drag" + +@dataclass +class Constant: + amp: ParamType + duration: int + def qasm_name(self) -> str: + return "constant" + + +@dataclass +class Sine: + amp: ParamType + frequency: ParamType + duration: int + def qasm_name(self) -> str: + return "sine" + + +@dataclass +class Cosine: + amp: ParamType + frequency: ParamType + duration: int + def qasm_name(self) -> str: + return "cosine" + + +@dataclass +class CosineDrag: + amp: ParamType + duration: int + phase: ParamType + alpha: ParamType + def qasm_name(self) -> str: + return "cosine_drag" + + +@dataclass +class Flattop: + amp: ParamType + width: ParamType + duration: int + def qasm_name(self) -> str: + return "flattop" diff --git a/tests/test_parametric_waveform.py b/tests/test_parametric_waveform.py new file mode 100644 index 00000000..83bb3eca --- /dev/null +++ b/tests/test_parametric_waveform.py @@ -0,0 +1,54 @@ +import sys +import os + +# Add the directory containing your module to Python's search path +module_path = "/Users/mac/tensorcircuit" +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device +import re + +print("✅ TEST FILE LOADED") + +def test_parametric_waveform(): + qc = Circuit(2) + + param0 = Param("param0") + param1 = Param("param1") + + builder = qc.calibrate("my_gate", [param0, param1]) + builder.new_frame("f0", param0) + builder.play("f0", waveforms.CosineDrag(10, 0.2, "0.5*PI", 0.01)) + builder.new_frame("f1", param1) + builder.play("f1", waveforms.CosineDrag(20, 0.01, "0", 0)) + builder.build() + + tqasm_code = qc.to_tqasm() + print(tqasm_code) + + assert "OPENQASM 3;" in tqasm_code + assert "defcal my_gate(param0, param1)" in tqasm_code + assert "frame f0 = newframe(param0);" in tqasm_code + assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code + assert "frame f1 = newframe(param1);" in tqasm_code + assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code + assert re.search(r"defcal my_gate\([^\)]*\)\s*\{", tqasm_code) + + return + + + device_name = "tianxuan_s1" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=8192, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + print(rf) + + +test_parametric_waveform() diff --git a/tests/test_waveform_types_to_tqasm.py b/tests/test_waveform_types_to_tqasm.py new file mode 100644 index 00000000..f2587bfe --- /dev/null +++ b/tests/test_waveform_types_to_tqasm.py @@ -0,0 +1,48 @@ +import sys +import os + +# Add the directory containing your module to Python's search path +module_path = "/Users/mac/tensorcircuit" +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, waveforms + +def test_waveform_types_to_tqasm_(): + test_cases = [ + (waveforms.CosineDrag, [10, 0.2, "PI/2", 0.01], "cosine_drag"), + (waveforms.Gaussian, [0.5, 20, 5], "gaussian"), + (waveforms.GaussianSquare, [0.5, 20, 5, 10], "gaussian_square"), + (waveforms.Drag, [0.4, 30, 10, 0.2], "drag"), + (waveforms.Flattop, [1.0, 5, 20], "flattop"), + (waveforms.Constant, [0.7, 15], "constant"), + (waveforms.Sine, [0.3, "2*PI", 10], "sine"), + (waveforms.Cosine, [0.6, "PI", 8], "cosine"), + ] + + failed = False + + for waveform_class, args, expected_name in test_cases: + qc = Circuit(1) + p = Param("q0") + + builder = qc.calibrate("test_gate", [p]) + builder.new_frame("f0", p) + builder.play("f0", waveform_class(*args)) + builder.build() + + qasm = qc.to_tqasm() + print(f"--- {expected_name} ---\n{qasm}\n") + + if f"play(f0, {expected_name}(" not in qasm: + print(f"❌ FAILED: waveform {waveform_class.__name__} expected '{expected_name}', but not found in QASM output.") + failed = True + else: + print(f"✅ PASSED: waveform {expected_name}") + + if failed: + raise AssertionError("Some waveform QASM outputs were incorrect.") + else: + print("All waveform QASM outputs passed.") + +if __name__ == "__main__": + test_waveform_types_to_tqasm_() \ No newline at end of file From d09396d8917ad590ceb100bb0a173f60fc4dbd28 Mon Sep 17 00:00:00 2001 From: mac Date: Tue, 29 Apr 2025 21:14:04 -0700 Subject: [PATCH 116/139] Update waveform classes with to_args methods --- tensorcircuit/circuit.py | 2 +- tensorcircuit/waveforms.py | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index 1bf1ead5..470a70fb 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -1065,7 +1065,7 @@ def play(self, frame_name: str, waveform: Any, start_time: int = None): raise TypeError("Unsupported waveform type") waveform_type = waveform.qasm_name() - args = list(waveform.__dict__.values()) + args = waveform.to_args() if start_time is not None: args = [start_time] + args diff --git a/tensorcircuit/waveforms.py b/tensorcircuit/waveforms.py index 7bafc93e..7f6484a7 100644 --- a/tensorcircuit/waveforms.py +++ b/tensorcircuit/waveforms.py @@ -21,6 +21,8 @@ class Gaussian: sigma: ParamType def qasm_name(self) -> str: return "gaussian" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma] @dataclass class GaussianSquare: @@ -30,6 +32,8 @@ class GaussianSquare: width: ParamType def qasm_name(self) -> str: return "gaussian_square" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma, self.width] @dataclass class Drag: @@ -39,6 +43,8 @@ class Drag: beta: ParamType def qasm_name(self) -> str: return "drag" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma, self.beta] @dataclass class Constant: @@ -46,7 +52,8 @@ class Constant: duration: int def qasm_name(self) -> str: return "constant" - + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration] @dataclass class Sine: @@ -55,7 +62,8 @@ class Sine: duration: int def qasm_name(self) -> str: return "sine" - + def to_args(self) -> List[ParamType]: + return [self.amp, self.frequency, self.duration] @dataclass class Cosine: @@ -64,7 +72,8 @@ class Cosine: duration: int def qasm_name(self) -> str: return "cosine" - + def to_args(self) -> List[ParamType]: + return [self.amp, self.frequency, self.duration] @dataclass class CosineDrag: @@ -74,7 +83,8 @@ class CosineDrag: alpha: ParamType def qasm_name(self) -> str: return "cosine_drag" - + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.phase, self.alpha] @dataclass class Flattop: @@ -83,3 +93,5 @@ class Flattop: duration: int def qasm_name(self) -> str: return "flattop" + def to_args(self) -> List[ParamType]: + return [self.amp, self.width, self.duration] From 5293c5567a2092559f82b71c32accea1fbc1a7ce Mon Sep 17 00:00:00 2001 From: walterxu Date: Wed, 30 Apr 2025 13:41:51 +0800 Subject: [PATCH 117/139] revise syntax mismatches. --- experiments/rabi.py | 59 +++++++++++++++++++++++++ tensorcircuit/backends/numpy_backend.py | 3 +- tensorcircuit/circuit.py | 6 +-- tensorcircuit/cloud/tencent.py | 4 +- tests/test_parametric_waveform.py | 23 ++++++---- 5 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 experiments/rabi.py diff --git a/experiments/rabi.py b/experiments/rabi.py new file mode 100644 index 00000000..7a830639 --- /dev/null +++ b/experiments/rabi.py @@ -0,0 +1,59 @@ +import sys +import os + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices +import re + +print("✅ TEST FILE LOADED") +set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") +set_provider("tencent") +ds = list_devices() +print(ds) + +def test_parametric_waveform(): + qc = Circuit(2) + + param0 = Param("param0") + param1 = Param("param1") + + builder = qc.calibrate("my_gate", [param0, param1]) + builder.new_frame("f0", param0) + builder.play("f0", waveforms.CosineDrag(10, 0.2, "0.5*PI", 0.01)) + builder.new_frame("f1", param1) + builder.play("f1", waveforms.CosineDrag(20, 0.01, "0", 0)) + builder.build() + + tqasm_code = qc.to_tqasm() + tqasm_code = tqasm_code + '\nmygate q[0], q[1]' + print(tqasm_code) + + assert "TQASM 0.2;" in tqasm_code + assert "defcal my_gate param0, param1" in tqasm_code + assert "frame f0 = newframe(param0);" in tqasm_code + assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code + assert "frame f1 = newframe(param1);" in tqasm_code + assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code + assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) + + + #tc.cloud.apis.set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") + #tc.cloud.apis.set_provider("tencent") + device_name = "tianji_m2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=8192, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + print(rf) + + +test_parametric_waveform() diff --git a/tensorcircuit/backends/numpy_backend.py b/tensorcircuit/backends/numpy_backend.py index df3dc043..87052275 100644 --- a/tensorcircuit/backends/numpy_backend.py +++ b/tensorcircuit/backends/numpy_backend.py @@ -214,7 +214,8 @@ def imag(self, a: Tensor) -> Tensor: def cast(self, a: Tensor, dtype: str) -> Tensor: with warnings.catch_warnings(): - warnings.simplefilter("ignore", np.ComplexWarning) + #warnings.simplefilter("ignore", np.ComplexWarning) + warnings.simplefilter("ignore", DeprecationWarning) if isinstance(dtype, str): return a.astype(getattr(np, dtype)) return a.astype(dtype) diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index 470a70fb..69df3042 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -129,8 +129,8 @@ def add_calibration( def to_tqasm(self) -> str: qasm_lines = [] - qasm_lines.append("OPENQASM 3;") - qasm_lines.append(f"qubit[{self._nqubits}] q;") + qasm_lines.append("TQASM 0.2;") + qasm_lines.append(f"QREG q[{self._nqubits}];") for gate in self._qir: gname = gate["name"] @@ -139,7 +139,7 @@ def to_tqasm(self) -> str: for cal in getattr(self, "calibrations", []): pname = ", ".join(cal["parameters"]) - qasm_lines.append(f"\ndefcal {cal['name']}({pname}) {{") + qasm_lines.append(f"\ndefcal {cal['name']} {pname} {{") for inst in cal["instructions"]: if inst["type"] == "frame": qasm_lines.append(f" frame {inst['frame']} = newframe({inst['qubit']});") diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index fc37460a..2dfb11fa 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -213,7 +213,9 @@ def c2qasm(c: Any, compiling: bool) -> str: s = c.qasm() # nq = c.num_qubits else: - s = c.to_openqasm() + s = c.to_tqasm() + '\nmy_gate q[0], q[1];' + print(s) + #s = c.to_openqasm() # nq = c._nqubits # s = _free_pi(s) # tQuk translation now supports this # if measure is not None: # ad hoc partial measurement diff --git a/tests/test_parametric_waveform.py b/tests/test_parametric_waveform.py index 83bb3eca..7a830639 100644 --- a/tests/test_parametric_waveform.py +++ b/tests/test_parametric_waveform.py @@ -2,14 +2,18 @@ import os # Add the directory containing your module to Python's search path -module_path = "/Users/mac/tensorcircuit" +module_path = ".." sys.path.insert(0, module_path) from tensorcircuit import Circuit, Param, gates, waveforms -from tensorcircuit.cloud.apis import submit_task, get_device +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices import re print("✅ TEST FILE LOADED") +set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") +set_provider("tencent") +ds = list_devices() +print(ds) def test_parametric_waveform(): qc = Circuit(2) @@ -25,20 +29,21 @@ def test_parametric_waveform(): builder.build() tqasm_code = qc.to_tqasm() + tqasm_code = tqasm_code + '\nmygate q[0], q[1]' print(tqasm_code) - assert "OPENQASM 3;" in tqasm_code - assert "defcal my_gate(param0, param1)" in tqasm_code + assert "TQASM 0.2;" in tqasm_code + assert "defcal my_gate param0, param1" in tqasm_code assert "frame f0 = newframe(param0);" in tqasm_code assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code assert "frame f1 = newframe(param1);" in tqasm_code assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code - assert re.search(r"defcal my_gate\([^\)]*\)\s*\{", tqasm_code) + assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) - return - - - device_name = "tianxuan_s1" + + #tc.cloud.apis.set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") + #tc.cloud.apis.set_provider("tencent") + device_name = "tianji_m2" d = get_device(device_name) t = submit_task( circuit=qc, From 8df9d40142d8176d298eecfbe7061c50ff1da70e Mon Sep 17 00:00:00 2001 From: walterxu Date: Wed, 30 Apr 2025 13:55:38 +0800 Subject: [PATCH 118/139] test pass --- tests/test_parametric_waveform.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_parametric_waveform.py b/tests/test_parametric_waveform.py index 7a830639..66948262 100644 --- a/tests/test_parametric_waveform.py +++ b/tests/test_parametric_waveform.py @@ -18,8 +18,8 @@ def test_parametric_waveform(): qc = Circuit(2) - param0 = Param("param0") - param1 = Param("param1") + param0 = Param("a") + param1 = Param("b") builder = qc.calibrate("my_gate", [param0, param1]) builder.new_frame("f0", param0) @@ -33,10 +33,10 @@ def test_parametric_waveform(): print(tqasm_code) assert "TQASM 0.2;" in tqasm_code - assert "defcal my_gate param0, param1" in tqasm_code - assert "frame f0 = newframe(param0);" in tqasm_code + assert "defcal my_gate a, b" in tqasm_code + assert "frame f0 = newframe(a);" in tqasm_code assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code - assert "frame f1 = newframe(param1);" in tqasm_code + assert "frame f1 = newframe(b);" in tqasm_code assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) From a57c36ff7df4552c74f34b2d097d1953ff752a94 Mon Sep 17 00:00:00 2001 From: walterxu Date: Wed, 30 Apr 2025 14:02:16 +0800 Subject: [PATCH 119/139] rabi base --- experiments/rabi.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/experiments/rabi.py b/experiments/rabi.py index 7a830639..66948262 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -18,8 +18,8 @@ def test_parametric_waveform(): qc = Circuit(2) - param0 = Param("param0") - param1 = Param("param1") + param0 = Param("a") + param1 = Param("b") builder = qc.calibrate("my_gate", [param0, param1]) builder.new_frame("f0", param0) @@ -33,10 +33,10 @@ def test_parametric_waveform(): print(tqasm_code) assert "TQASM 0.2;" in tqasm_code - assert "defcal my_gate param0, param1" in tqasm_code - assert "frame f0 = newframe(param0);" in tqasm_code + assert "defcal my_gate a, b" in tqasm_code + assert "frame f0 = newframe(a);" in tqasm_code assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code - assert "frame f1 = newframe(param1);" in tqasm_code + assert "frame f1 = newframe(b);" in tqasm_code assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) From 354ef45d5287c51cb6e29e706eb85d5fc902d621 Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Wed, 30 Apr 2025 15:34:12 +0800 Subject: [PATCH 120/139] rabi --- experiments/rabi.py | 86 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/experiments/rabi.py b/experiments/rabi.py index 66948262..47839a99 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -1,5 +1,6 @@ import sys import os +import matplotlib.pyplot as plt # Add the directory containing your module to Python's search path module_path = ".." @@ -15,7 +16,7 @@ ds = list_devices() print(ds) -def test_parametric_waveform(): +def test_parametric_waveform(t): qc = Circuit(2) param0 = Param("a") @@ -23,26 +24,11 @@ def test_parametric_waveform(): builder = qc.calibrate("my_gate", [param0, param1]) builder.new_frame("f0", param0) - builder.play("f0", waveforms.CosineDrag(10, 0.2, "0.5*PI", 0.01)) - builder.new_frame("f1", param1) - builder.play("f1", waveforms.CosineDrag(20, 0.01, "0", 0)) + builder.play("f0", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) + builder.new_frame("f1", param0) + builder.play("f1", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) builder.build() - tqasm_code = qc.to_tqasm() - tqasm_code = tqasm_code + '\nmygate q[0], q[1]' - print(tqasm_code) - - assert "TQASM 0.2;" in tqasm_code - assert "defcal my_gate a, b" in tqasm_code - assert "frame f0 = newframe(a);" in tqasm_code - assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code - assert "frame f1 = newframe(b);" in tqasm_code - assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code - assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) - - - #tc.cloud.apis.set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") - #tc.cloud.apis.set_provider("tencent") device_name = "tianji_m2" d = get_device(device_name) t = submit_task( @@ -53,7 +39,65 @@ def test_parametric_waveform(): enable_qos_qubit_mapping=False, ) rf = t.results() - print(rf) + return rf + +data = { + '00': [], + '01': [], + '10': [], + '11': [] +} +for i in range(1,5): + result = test_parametric_waveform(i) + print(i, result['00'], result['01'], result['10'], result['11']) + + for key in data: + data[key].append(result[key]) + + +plt.figure(figsize=(10, 6)) + +colors = ['blue', 'green', 'red', 'purple'] +marker_size = 4 + +# for idx, (state, values) in enumerate(data.items()): +# plt.plot( +# range(1, 5), +# values, +# marker='o', +# markersize=marker_size, +# linestyle='-', +# linewidth=1.2, +# color=colors[idx], +# label=state +# ) + +# plt.xlabel('Parameter i') +# plt.ylabel('Counts') +# plt.title('State Distribution by Parameter') +# plt.legend() +# plt.grid(True, alpha=0.3) + + +# 子图 +for idx, (state, values) in enumerate(data.items()): + plt.subplot(2, 2, idx+1) + + plt.plot( + range(1, 5), + values, + marker='o', + markersize=4, + linestyle='-', + linewidth=1.2, + color=colors[idx] + ) + + plt.xlabel('Parameter i') + plt.ylabel('Counts') + plt.title(f'State {state}') + plt.grid(True, alpha=0.3) -test_parametric_waveform() +plt.tight_layout() +plt.show() \ No newline at end of file From a14b7dd6477fa7429f6cd79d273c26985fbf73f1 Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Fri, 6 Jun 2025 16:40:03 +0800 Subject: [PATCH 121/139] add rabi test --- experiments/rabi.ipynb | 3185 ++++++++++++++++++++++++++++++++ experiments/rabi.py | 132 +- tensorcircuit/cloud/tencent.py | 2 +- 3 files changed, 3253 insertions(+), 66 deletions(-) create mode 100644 experiments/rabi.ipynb diff --git a/experiments/rabi.ipynb b/experiments/rabi.ipynb new file mode 100644 index 00000000..76cc10b7 --- /dev/null +++ b/experiments/rabi.ipynb @@ -0,0 +1,3185 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import os\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Add the directory containing your module to Python's search path\n", + "module_path = \"..\"\n", + "sys.path.insert(0, module_path)\n", + "\n", + "from tensorcircuit import Circuit, Param, gates, waveforms\n", + "from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices\n", + "import re" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ TEST FILE LOADED\n", + "[tencent::tianji_m2, tencent::tianji_m1v15s4, tencent::tianji_m1v15s2, tencent::tianxuan_s2v20s2, tencent::simulator:tc, tencent::tianji_m2v15s3, tencent::tianxuan_s2, tencent::tianji_m1v15s1, tencent::tianji_s2, tencent::tianji_m2v14s4, tencent::tianxuan_s2v20s1, tencent::tianji_s2v6, tencent::tianji_m2v16s1, tencent::tianji_m2v14s2, tencent::tianji_m1v15s3, tencent::tianxuan_s1, tencent::tianji_m1, tencent::tianji_s2v7]\n" + ] + } + ], + "source": [ + "shots_const = 1000\n", + "\n", + "print(\"✅ TEST FILE LOADED\")\n", + "set_token(\"\")\n", + "set_provider(\"tencent\")\n", + "ds = list_devices()\n", + "print(ds)\n", + "\n", + "# TQASM 0.2;\n", + "# QREG a[1];\n", + "# defcal rabi_test a {\n", + "# frame drive_frame = newframe(a); \n", + "# play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); } \n", + "# rabi_test a[0];\n", + "# MEASZ a[0];" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_parametric_waveform_circuit(t):\n", + " qc = Circuit(2)\n", + "\n", + " param0 = Param(\"a\")\n", + "\n", + " builder = qc.calibrate(\"rabi_test\", [param0])\n", + " builder.new_frame(\"drive_frame\", param0)\n", + " builder.play(\"drive_frame\", waveforms.CosineDrag(t, 0.2, 0.0, 0.01))\n", + "\n", + " builder.build()\n", + " \n", + " tqasm_code = qc.to_tqasm()\n", + "\n", + " print(tqasm_code)\n", + " return qc\n", + "\n", + "\n", + "def run_circuit(qc):\n", + " device_name = \"tianji_m2\" \n", + " d = get_device(device_name)\n", + " t = submit_task(\n", + " circuit=qc,\n", + " shots=shots_const,\n", + " device=d,\n", + " enable_qos_gate_decomposition=False,\n", + " enable_qos_qubit_mapping=False,\n", + " )\n", + " rf = t.results()\n", + " return rf\n", + "\n", + "\n", + "\n", + "def exp_rabi():\n", + " result_lst = []\n", + " for t in range(1, 400, 2):\n", + " qc = gen_parametric_waveform_circuit(t)\n", + " result = run_circuit(qc)\n", + " result['duration'] = t\n", + " result_lst.append(result)\n", + " return result_lst\n", + "\n", + "\n", + "\n", + "def draw_rabi(result_lst):\n", + " data = {\n", + " 'duration': [],\n", + " '0': [],\n", + " '1': []\n", + " }\n", + " \n", + " for result in result_lst:\n", + " data['0'].append(int(result['0']) / shots_const)\n", + " data['1'].append(int(result['1']) / shots_const)\n", + " data['duration'].append(result['duration'])\n", + "\n", + "\n", + " \n", + "\n", + " plt.figure(figsize=(10,6))\n", + " plt.plot(data['duration'], data['0'], 'b-o', label='State |0>')\n", + " plt.plot(data['duration'], data['1'], 'r--s', label='State |1>')\n", + "\n", + "\n", + " plt.title('Rabi Oscillation Experiment')\n", + " plt.xlabel('Duration (dt)')\n", + " plt.ylabel('Probability')\n", + " plt.grid(alpha=0.3)\n", + " plt.legend()\n", + " plt.tight_layout()\n", + "\n", + "\n", + " plt.savefig('rabi.png', dpi=300)\n", + " plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(247, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(247, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(249, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(249, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(251, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(251, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(253, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(253, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(255, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(255, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(257, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(257, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(259, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(259, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(261, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(261, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(263, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(263, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(265, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(265, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(267, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(267, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(269, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(269, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(271, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(271, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(273, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(273, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(275, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(275, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(277, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(277, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(279, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(279, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(281, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(281, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(283, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(283, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(285, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(285, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(287, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(287, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(289, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(289, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(291, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(291, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(293, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(293, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(295, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(295, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(297, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(297, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(299, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(299, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(301, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(301, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(303, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(303, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(305, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(305, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(307, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(307, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(309, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(309, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(311, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(311, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(313, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(313, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(315, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(315, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(317, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(317, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(319, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(319, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(321, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(321, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(323, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(323, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(325, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(325, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(327, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(327, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(329, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(329, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(331, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(331, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(333, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(333, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(335, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(335, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(337, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(337, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(339, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(339, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(341, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(341, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(343, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(343, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(345, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(345, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(347, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(347, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(349, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(349, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(351, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(351, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(353, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(353, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(355, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(355, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(357, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(357, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(359, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(359, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(361, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(361, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(363, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(363, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(365, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(365, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(367, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(367, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(369, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(369, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(371, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(371, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(373, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(373, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(375, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(375, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(377, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(377, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(379, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(379, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(381, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(381, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(383, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(383, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(385, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(385, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(387, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(387, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(389, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(389, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(391, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(391, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(393, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(393, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(395, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(395, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(397, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(397, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(399, 0.2, 0.0, 0.01));\n", + "}\n", + "TQASM 0.2;\n", + "QREG q[2];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(399, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJOCAYAAABBfN/cAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAADkAElEQVR4nOzdeXwTdf4/8Nc0vbgLtOVqS7lvkHIJWAEFwQPBciiIgrviiVzL6urKKcp6oMX7p/sFVNSVxYjnoohUijcgolIqp4FSKKXc0JYm8/vjw7RJmmOSJplJ5vV8PPJIMpm0H5gmM+/P8X5LsizLICIiIiIiIqKgiNK6AURERERERESRjIE3ERERERERURAx8CYiIiIiIiIKIgbeREREREREREHEwJuIiIiIiIgoiBh4ExEREREREQURA28iIiIiIiKiIGLgTURERERERBREDLyJiIiIiIiIgoiBNxERhYUDBw5AkiQ888wzXvddsGABJEkKQav8N3jwYAwePLjyufLvW7lyZeW2YPw7cnJyIEkScnJyAvpzjSA9PR1TpkzRuhlERBSGGHgTEVHArVy5EpIkVd6io6PRokULTJkyBQUFBVo3r5pPPvkEI0aMQOPGjREfH4/27dtjzpw5OH78uNZN89vLL7/sEMTrweDBgx3+LuxvHTt21Lp5EWHnzp1YsGABDhw4oHVTiIjITrTWDSAiosi1aNEitGrVCqWlpfj++++xcuVKbN68Gb/99hvi4+OD9nsfffRR/OMf/1C175w5c7B06VL06NEDDz30EBo1aoRt27bhxRdfxH/+8x9s2LABHTp0CHgbv/jii4D/THsvv/wyEhMTq43QXnnllbhw4QJiY2OD+vvdSUlJwZIlS6ptb9CggQat8U1+fj6iovQ9ZrFz504sXLgQgwcPRnp6utbNISKiSxh4ExFR0Fx77bXo3bs3AODOO+9EYmIinnzySXz00UcYP3580H5vdHQ0oqO9n+LeffddLF26FDfffDPefvttmEymytemTJmCIUOGYNy4cdi2bZuqn+cLrQLfqKiooHZ6eNOgQQNMmjRJs9/vK1mWUVpailq1aiEuLk7r5hARUZjSd7ctERFFlMzMTADA3r17K7eVl5dj3rx56NWrFxo0aIA6deogMzMTGzdudPtznnvuObRs2RK1atXCoEGD8Ntvvzm8rnZt9MKFC9GwYUO89tprDkE3APTt2xcPPfQQfv31V6xZs6Zy++7duzFmzBg0bdoU8fHxSElJwS233IJTp045vH/VqlXo27cvateujYYNG+LKK690GOV2XuOt1ooVK3DVVVchOTkZcXFx6Ny5M1555RWHfdLT0/H777/j66+/rpzKrfwud2u8//vf/6JXr16oVasWEhMTMWnSpGrLAqZMmYK6deuioKAAo0ePRt26dZGUlIQ5c+bAarX6/G9x5cKFC+jYsSM6duyICxcuVG4vKSlBs2bNMGDAgMrfpbRn3759GD58OOrUqYPmzZtj0aJFkGXZ4efabDZkZ2ejS5cuiI+PR5MmTXD33XfjxIkT1f7vbrjhBnz++efo3bs3atWqhf/3//5f5Wv2MwiUJRWbN2/G9OnTkZSUhISEBNx9990oLy/HyZMncfvtt6Nhw4Zo2LAhHnzwwRq3a/Pmzejbty/i4+PRunVrvPnmmw7tGTduHABgyJAhlcee6/mJiLTHwJuIiEJGWXfasGHDym2nT5/Gv//9bwwePBhPPvkkFixYgGPHjmH48OHYvn17tZ/x5ptv4vnnn8f999+Phx9+GL/99huuuuoqHD161Ke27N69G/n5+Rg1ahTq16/vcp/bb78dgFgDDohOguHDh+P777/HAw88gJdeegl33XUX9u3bh5MnT1a+b+HChbjtttsQExODRYsWYeHChUhNTcVXX33lUxtdeeWVV9CyZUs88sgjWLp0KVJTU3HffffhpZdeqtwnOzsbKSkp6NixI9566y289dZb+Oc//+n2Z65cuRLjx4+HyWTCkiVLMHXqVJjNZlxxxRUO/y4AsFqtGD58OBo3boxnnnkGgwYNwtKlS/Haa6+par/VakVxcXG127lz5wAAtWrVwhtvvIE9e/Y4tPn+++/HqVOnsHLlSodOEqvVihEjRqBJkyZ46qmn0KtXL8yfPx/z5893+L133303/v73v2PgwIFYtmwZ7rjjDrz99tsYPnw4Ll686LBvfn4+JkyYgGHDhmHZsmW47LLLPP6bHnjgAezevRsLFy7EjTfeiNdeew1z587FyJEjYbVa8cQTT+CKK67A008/jbfeesvvdu3Zswdjx47FsGHDsHTpUjRs2BBTpkzB77//DkAsI5g+fToA4JFHHqk89p06dVJxZIiIKKhkIiKiAFuxYoUMQP7yyy/lY8eOyQcP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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "data = exp_rabi()\n", + "draw_rabi(data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/experiments/rabi.py b/experiments/rabi.py index 47839a99..824cfc3d 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -10,30 +10,45 @@ from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices import re +shots_const = 1000 + print("✅ TEST FILE LOADED") -set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") +set_token("") set_provider("tencent") ds = list_devices() print(ds) -def test_parametric_waveform(t): +# TQASM 0.2; +# QREG a[1]; +# defcal rabi_test a { +# frame drive_frame = newframe(a); +# play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); } +# rabi_test a[0]; +# MEASZ a[0]; + +def gen_parametric_waveform_circuit(t): qc = Circuit(2) param0 = Param("a") - param1 = Param("b") - builder = qc.calibrate("my_gate", [param0, param1]) - builder.new_frame("f0", param0) - builder.play("f0", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) - builder.new_frame("f1", param0) - builder.play("f1", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) + builder = qc.calibrate("rabi_test", [param0]) + builder.new_frame("drive_frame", param0) + builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) + builder.build() + + tqasm_code = qc.to_tqasm() + + print(tqasm_code) + return qc + +def run_circuit(qc): device_name = "tianji_m2" d = get_device(device_name) t = submit_task( circuit=qc, - shots=8192, + shots=shots_const, device=d, enable_qos_gate_decomposition=False, enable_qos_qubit_mapping=False, @@ -41,63 +56,50 @@ def test_parametric_waveform(t): rf = t.results() return rf -data = { - '00': [], - '01': [], - '10': [], - '11': [] -} -for i in range(1,5): - result = test_parametric_waveform(i) - print(i, result['00'], result['01'], result['10'], result['11']) - - for key in data: - data[key].append(result[key]) - -plt.figure(figsize=(10, 6)) - -colors = ['blue', 'green', 'red', 'purple'] -marker_size = 4 - -# for idx, (state, values) in enumerate(data.items()): -# plt.plot( -# range(1, 5), -# values, -# marker='o', -# markersize=marker_size, -# linestyle='-', -# linewidth=1.2, -# color=colors[idx], -# label=state -# ) - -# plt.xlabel('Parameter i') -# plt.ylabel('Counts') -# plt.title('State Distribution by Parameter') -# plt.legend() -# plt.grid(True, alpha=0.3) - - -# 子图 -for idx, (state, values) in enumerate(data.items()): - plt.subplot(2, 2, idx+1) - - plt.plot( - range(1, 5), - values, - marker='o', - markersize=4, - linestyle='-', - linewidth=1.2, - color=colors[idx] - ) + +def exp_rabi(): + result_lst = [] + for t in range(1, 4, 2): + qc = gen_parametric_waveform_circuit(t) + result = run_circuit(qc) + result['duration'] = t + result_lst.append(result) + return result_lst + + + +def draw_rabi(result_lst): + data = { + 'duration': [], + '0': [], + '1': [] + } - plt.xlabel('Parameter i') - plt.ylabel('Counts') - plt.title(f'State {state}') - plt.grid(True, alpha=0.3) + for result in result_lst: + data['0'].append(int(result['0']) / shots_const) + data['1'].append(int(result['1']) / shots_const) + data['duration'].append(result['duration']) + + + + + plt.figure(figsize=(10,6)) + plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') + plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + + plt.title('Rabi Oscillation Experiment') + plt.xlabel('Duration (dt)') + plt.ylabel('Probability') + plt.grid(alpha=0.3) + plt.legend() + plt.tight_layout() + + + plt.savefig('rabi.png', dpi=300) + plt.show() -plt.tight_layout() -plt.show() \ No newline at end of file +data = exp_rabi() +draw_rabi(data) diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index 2dfb11fa..888d3923 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -213,7 +213,7 @@ def c2qasm(c: Any, compiling: bool) -> str: s = c.qasm() # nq = c.num_qubits else: - s = c.to_tqasm() + '\nmy_gate q[0], q[1];' + s = c.to_tqasm() + '\nrabi_test q[0];' print(s) #s = c.to_openqasm() # nq = c._nqubits From 1e393311533c1400847add4e1d9ccbb15ffeee2d Mon Sep 17 00:00:00 2001 From: ruan-prog <1696257014@qq.com> Date: Wed, 9 Jul 2025 11:40:47 +0800 Subject: [PATCH 122/139] Update rabi.py --- experiments/rabi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experiments/rabi.py b/experiments/rabi.py index 824cfc3d..192ad193 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -33,9 +33,10 @@ def gen_parametric_waveform_circuit(t): builder = qc.calibrate("rabi_test", [param0]) builder.new_frame("drive_frame", param0) - builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.01)) + builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) builder.build() + qc.add_calibration(builder, ['q[0]']) //'rabi_test q[0]' tqasm_code = qc.to_tqasm() From 001136b1f1cdcbb6483d0d18c2c7294ef8f2bc30 Mon Sep 17 00:00:00 2001 From: ruan-prog <1696257014@qq.com> Date: Wed, 9 Jul 2025 11:42:36 +0800 Subject: [PATCH 123/139] Update rabi.py --- experiments/rabi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experiments/rabi.py b/experiments/rabi.py index 192ad193..1423ccd1 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -27,7 +27,7 @@ # MEASZ a[0]; def gen_parametric_waveform_circuit(t): - qc = Circuit(2) + qc = Circuit(1) param0 = Param("a") From cc8e3eeb4caac98882529d00d2a3b991a4c60451 Mon Sep 17 00:00:00 2001 From: ruan-prog <1696257014@qq.com> Date: Wed, 9 Jul 2025 11:57:38 +0800 Subject: [PATCH 124/139] Update circuit.py --- tensorcircuit/circuit.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index 69df3042..d9c1ff53 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -64,6 +64,7 @@ def __init__( nqubits=nqubits, inputs=inputs, mps_inputs=mps_inputs, split=split ) self.calibrations = [] + self.calibration_invokes = [] self.inputs = inputs self.mps_inputs = mps_inputs @@ -117,7 +118,7 @@ def __init__( self._qir: List[Dict[str, Any]] = [] self._extra_qir: List[Dict[str, Any]] = [] - def add_calibration( + def def_calibration( self, name: str, parameters: List[str], instructions: List[Dict] ) -> None: self.calibrations.append({ @@ -126,6 +127,15 @@ def add_calibration( "instructions": instructions }) + def add_calibration( + self, name: str, parameters: List[str], instructions: List[Dict] + ) -> None: + self.calibration_invokes.append({ + "name": name, + "parameters": parameters, + "instructions": instructions + }) + def to_tqasm(self) -> str: qasm_lines = [] @@ -149,6 +159,10 @@ def to_tqasm(self) -> str: qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") qasm_lines.append("}") + for cal in getattr(self, "calibration_invokes", []): + pname = ", ".join(cal["parameters"]) + qasm_lines.append(f"\n {cal['name']} {pname};") + return "\n".join(qasm_lines) def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": @@ -1078,8 +1092,8 @@ def play(self, frame_name: str, waveform: Any, start_time: int = None): return self def build(self): - self.circuit.add_calibration( + self.circuit.def_calibration( name=self.name, parameters=[p.name for p in self.parameters], instructions=self.instructions, - ) \ No newline at end of file + ) From f4bfba16d5fc499455b4e7c3ecdadc96d9f92202 Mon Sep 17 00:00:00 2001 From: ruan-prog <1696257014@qq.com> Date: Wed, 9 Jul 2025 11:58:47 +0800 Subject: [PATCH 125/139] Update tencent.py --- tensorcircuit/cloud/tencent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index 888d3923..029e2486 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -213,7 +213,7 @@ def c2qasm(c: Any, compiling: bool) -> str: s = c.qasm() # nq = c.num_qubits else: - s = c.to_tqasm() + '\nrabi_test q[0];' + s = c.to_tqasm() print(s) #s = c.to_openqasm() # nq = c._nqubits From 95f1ab430298d1cd19980180169ea4bf8c7a5b37 Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Wed, 9 Jul 2025 12:06:49 +0800 Subject: [PATCH 126/139] update --- experiments/draw_rabi.py | 35 + experiments/rabi.ipynb | 2703 +++++---------------------------- experiments/rabi.png | Bin 0 -> 97857 bytes experiments/rabi.py | 2 +- experiments/rabi_grpc.sh | 16 + nohup.out | 2467 ++++++++++++++++++++++++++++++ tensorcircuit/circuit.py | 5 +- tensorcircuit/cloud/config.py | 2 +- 8 files changed, 2891 insertions(+), 2339 deletions(-) create mode 100644 experiments/draw_rabi.py create mode 100644 experiments/rabi.png create mode 100644 experiments/rabi_grpc.sh create mode 100644 nohup.out diff --git a/experiments/draw_rabi.py b/experiments/draw_rabi.py new file mode 100644 index 00000000..0c135b75 --- /dev/null +++ b/experiments/draw_rabi.py @@ -0,0 +1,35 @@ + +import csv +import matplotlib.pyplot as plt + +data = { + 'duration': [], + '0': [], + '1': [] +} +total_shots = 1000 + + +with open('rabi_data.csv') as f: + reader = csv.DictReader(f) + for row in reader: + data['duration'].append(float(row['duration'])) + data['0'].append(int(row['count0'])/total_shots) + data['1'].append(int(row['count1'])/total_shots) + + +plt.figure(figsize=(10,6)) +plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') +plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + +plt.title('Rabi Oscillation Experiment') +plt.xlabel('Duration (dt)') +plt.ylabel('Probability') +plt.grid(alpha=0.3) +plt.legend() +plt.tight_layout() + + +plt.savefig('rabi.png', dpi=300) +plt.show() \ No newline at end of file diff --git a/experiments/rabi.ipynb b/experiments/rabi.ipynb index 76cc10b7..820735a4 100644 --- a/experiments/rabi.ipynb +++ b/experiments/rabi.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 5, + "execution_count": 22, "metadata": {}, "outputs": [], "source": [ @@ -21,15 +21,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, + "execution_count": 23, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ TEST FILE LOADED\n", - "[tencent::tianji_m2, tencent::tianji_m1v15s4, tencent::tianji_m1v15s2, tencent::tianxuan_s2v20s2, tencent::simulator:tc, tencent::tianji_m2v15s3, tencent::tianxuan_s2, tencent::tianji_m1v15s1, tencent::tianji_s2, tencent::tianji_m2v14s4, tencent::tianxuan_s2v20s1, tencent::tianji_s2v6, tencent::tianji_m2v16s1, tencent::tianji_m2v14s2, tencent::tianji_m1v15s3, tencent::tianxuan_s1, tencent::tianji_m1, tencent::tianji_s2v7]\n" + "[tencent::tianji_m2, tencent::tianji_m1v15s4, tencent::tianji_m1v15s2, tencent::tianxuan_s2v20s2, tencent::tianji_m2v16s1, tencent::simulator:tc, tencent::tianji_m2v15s3, tencent::tianxuan_s2, tencent::tianji_s2, tencent::tianji_m2v14s4, tencent::tianxuan_s2v20s1, tencent::tianji_m1v15s1, tencent::tianji_s2v6, tencent::tianji_m1v15s3, tencent::tianji_m2v14s2, tencent::tianji_m1, tencent::tianxuan_s1, tencent::tianji_s2v7]\n" ] } ], @@ -37,7 +39,7 @@ "shots_const = 1000\n", "\n", "print(\"✅ TEST FILE LOADED\")\n", - "set_token(\"\")\n", + "set_token(\"xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=\")\n", "set_provider(\"tencent\")\n", "ds = list_devices()\n", "print(ds)\n", @@ -53,12 +55,12 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def gen_parametric_waveform_circuit(t):\n", - " qc = Circuit(2)\n", + " qc = Circuit(1)\n", "\n", " param0 = Param(\"a\")\n", "\n", @@ -70,7 +72,7 @@ " \n", " tqasm_code = qc.to_tqasm()\n", "\n", - " print(tqasm_code)\n", + " # print(tqasm_code)\n", " return qc\n", "\n", "\n", @@ -84,8 +86,8 @@ " enable_qos_gate_decomposition=False,\n", " enable_qos_qubit_mapping=False,\n", " )\n", - " rf = t.results()\n", - " return rf\n", + " rs = t.results()\n", + " return rs\n", "\n", "\n", "\n", @@ -134,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -142,3010 +144,1038 @@ "output_type": "stream", "text": [ "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(247, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(247, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(249, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(249, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(251, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(251, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(253, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(253, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(255, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(255, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(257, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(257, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(259, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(259, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(261, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(261, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(263, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(263, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(265, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(265, 0.2, 0.0, 0.01));\n", - "}\n", - "rabi_test q[0];\n", - "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(267, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(267, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(269, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(269, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(271, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(271, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(273, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(273, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(275, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(275, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(277, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(277, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(279, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(279, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(281, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(281, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(283, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(283, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(285, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(285, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", - "\n", - "defcal rabi_test a {\n", - " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(287, 0.2, 0.0, 0.01));\n", - "}\n", - "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(287, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(289, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(289, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(291, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(291, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(293, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(293, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(295, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(295, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(297, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(297, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(299, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(299, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(301, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(301, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(303, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(303, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(305, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(305, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(307, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(307, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(309, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(309, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(311, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(311, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(313, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(313, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(315, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(315, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(317, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(317, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(319, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(319, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(321, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(321, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(323, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(323, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(325, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(325, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(327, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(327, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(329, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(329, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(331, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(331, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(333, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(333, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(335, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(335, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(337, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(337, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(339, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(339, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(341, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(341, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(343, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(343, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(345, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(345, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(347, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(347, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(349, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(349, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(351, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(351, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(353, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(353, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(355, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(355, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(357, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(357, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(359, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(359, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(361, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(361, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(363, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(363, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(365, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(365, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(367, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(367, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(369, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(369, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(371, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(371, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(373, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(373, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(375, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(375, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(377, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(377, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(379, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(379, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(381, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(381, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(383, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(383, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(385, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(385, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(387, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(387, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(389, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(389, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(391, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(391, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(393, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(393, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(395, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(395, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(397, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(397, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(399, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", "}\n", + "rabi_test q[0];\n", "TQASM 0.2;\n", - "QREG q[2];\n", + "QREG q[1];\n", "\n", "defcal rabi_test a {\n", " frame drive_frame = newframe(a);\n", - " play(drive_frame, cosine_drag(399, 0.2, 0.0, 0.01));\n", + " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", "}\n", "rabi_test q[0];\n" ] }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Fails at fetching url: http://111.230.11.154/cloud/quk/task/detail. Try again.\n" + ] + }, + { + "ename": "ValueError", + "evalue": "{\"code\": 0, \"status\": \"502 Bad Gateway\", \"desc\": \"\\u672a\\u77e5\\u9519\\u8bef\", \"Contents\": [\"\\u672a\\u77e5\\u5f02\\u5e38\", \"\\u5982\\u9700\\u5e2e\\u52a9\\u8bf7\\u7acb\\u5373\\u81f4\\u75358000\\u70ed\\u7ebf\\u6216\\u4f01\\u4e1a\\u5fae\\u4fe1 8000\\u52a9\\u624b\\uff08IT\\u4e1a\\u52a1\\uff09 \\uff0c7x24\\u5c0f\\u65f6\\u4e3a\\u60a8\\u670d\\u52a1\"], \"version\": \"3.0.30.217\"}", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/tencent.py:361\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(task, device, token, prettify)\u001b[0m\n\u001b[1;32m 360\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 361\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresult\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m \u001b[43mr\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtask\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m:\n\u001b[1;32m 362\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcounts\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m r[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtask\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresult\u001b[39m\u001b[38;5;124m\"\u001b[39m]:\n", + "\u001b[0;31mKeyError\u001b[0m: 'task'", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[21], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[43mexp_rabi\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m draw_rabi(data)\n", + "Cell \u001b[0;32mIn[20], line 37\u001b[0m, in \u001b[0;36mexp_rabi\u001b[0;34m()\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m400\u001b[39m, \u001b[38;5;241m2\u001b[39m):\n\u001b[1;32m 36\u001b[0m qc \u001b[38;5;241m=\u001b[39m gen_parametric_waveform_circuit(t)\n\u001b[0;32m---> 37\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mrun_circuit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mqc\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 38\u001b[0m result[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mduration\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m t\n\u001b[1;32m 39\u001b[0m result_lst\u001b[38;5;241m.\u001b[39mappend(result)\n", + "Cell \u001b[0;32mIn[20], line 28\u001b[0m, in \u001b[0;36mrun_circuit\u001b[0;34m(qc)\u001b[0m\n\u001b[1;32m 20\u001b[0m d \u001b[38;5;241m=\u001b[39m get_device(device_name)\n\u001b[1;32m 21\u001b[0m t \u001b[38;5;241m=\u001b[39m submit_task(\n\u001b[1;32m 22\u001b[0m circuit\u001b[38;5;241m=\u001b[39mqc,\n\u001b[1;32m 23\u001b[0m shots\u001b[38;5;241m=\u001b[39mshots_const,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 26\u001b[0m enable_qos_qubit_mapping\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 27\u001b[0m )\n\u001b[0;32m---> 28\u001b[0m rs \u001b[38;5;241m=\u001b[39m \u001b[43mt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresults\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m rs\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\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[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:431\u001b[0m, in \u001b[0;36mTask.results\u001b[0;34m(self, format, blocked, mitigated, calibriation_options, readout_mit, mitigation_options)\u001b[0m\n\u001b[1;32m 429\u001b[0m tries \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 430\u001b[0m s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate()\n\u001b[0;32m--> 431\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresults\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mblocked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmitigated\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 432\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mitigated \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 433\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\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[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:419\u001b[0m, in \u001b[0;36mTask.results\u001b[0;34m(self, format, blocked, mitigated, calibriation_options, readout_mit, mitigation_options)\u001b[0m\n\u001b[1;32m 417\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcompleted\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m TaskUnfinished(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mid_, s)\n\u001b[0;32m--> 419\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdetails\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresults\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 420\u001b[0m r \u001b[38;5;241m=\u001b[39m counts\u001b[38;5;241m.\u001b[39msort_count(r) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 421\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\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[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:336\u001b[0m, in \u001b[0;36mTask.details\u001b[0;34m(self, blocked, **kws)\u001b[0m\n\u001b[1;32m 333\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapis\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_task_details\n\u001b[1;32m 335\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m blocked \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[0;32m--> 336\u001b[0m dt \u001b[38;5;241m=\u001b[39m \u001b[43mget_task_details\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;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[43mkws\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 337\u001b[0m dt\u001b[38;5;241m.\u001b[39mupdate(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmore_details)\n\u001b[1;32m 338\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m dt\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/apis.py:402\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(taskid, token, prettify)\u001b[0m\n\u001b[1;32m 399\u001b[0m provider \u001b[38;5;241m=\u001b[39m device\u001b[38;5;241m.\u001b[39mprovider\n\u001b[1;32m 401\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m provider\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtencent\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m--> 402\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtencent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_task_details\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtask\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprettify\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 403\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m provider\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mlocal\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 404\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m local\u001b[38;5;241m.\u001b[39mget_task_details(task, device, token, prettify) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/tencent.py:398\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(task, device, token, prettify)\u001b[0m\n\u001b[1;32m 396\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 397\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[0;32m--> 398\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(dumps(r))\n\u001b[1;32m 400\u001b[0m \u001b[38;5;66;03m# make the return at least contain the following terms across different providers\u001b[39;00m\n\u001b[1;32m 401\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;124;03m'id': 'd947cd76-a961-4c22-b295-76287c9fdaa3',\u001b[39;00m\n\u001b[1;32m 403\u001b[0m \u001b[38;5;124;03m'state': 'completed',\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[38;5;124;03m'111': 131}\u001b[39;00m\n\u001b[1;32m 416\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n", + "\u001b[0;31mValueError\u001b[0m: {\"code\": 0, \"status\": \"502 Bad Gateway\", \"desc\": \"\\u672a\\u77e5\\u9519\\u8bef\", \"Contents\": [\"\\u672a\\u77e5\\u5f02\\u5e38\", \"\\u5982\\u9700\\u5e2e\\u52a9\\u8bf7\\u7acb\\u5373\\u81f4\\u75358000\\u70ed\\u7ebf\\u6216\\u4f01\\u4e1a\\u5fae\\u4fe1 8000\\u52a9\\u624b\\uff08IT\\u4e1a\\u52a1\\uff09 \\uff0c7x24\\u5c0f\\u65f6\\u4e3a\\u60a8\\u670d\\u52a1\"], \"version\": \"3.0.30.217\"}" + ] + } + ], + "source": [ + "\n", + "data = exp_rabi()\n", + "draw_rabi(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJOCAYAAABBfN/cAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAADkAElEQVR4nOzdeXwTdf4/8Nc0vbgLtOVqS7lvkHIJWAEFwQPBciiIgrviiVzL6urKKcp6oMX7p/sFVNSVxYjnoohUijcgolIqp4FSKKXc0JYm8/vjw7RJmmOSJplJ5vV8PPJIMpm0H5gmM+/P8X5LsizLICIiIiIiIqKgiNK6AURERERERESRjIE3ERERERERURAx8CYiIiIiIiIKIgbeREREREREREHEwJuIiIiIiIgoiBh4ExEREREREQURA28iIiIiIiKiIGLgTURERERERBREDLyJiIiIiIiIgoiBNxERhYUDBw5AkiQ888wzXvddsGABJEkKQav8N3jwYAwePLjyufLvW7lyZeW2YPw7cnJyIEkScnJyAvpzjSA9PR1TpkzRuhlERBSGGHgTEVHArVy5EpIkVd6io6PRokULTJkyBQUFBVo3r5pPPvkEI0aMQOPGjREfH4/27dtjzpw5OH78uNZN89vLL7/sEMTrweDBgx3+LuxvHTt21Lp5EWHnzp1YsGABDhw4oHVTiIjITrTWDSAiosi1aNEitGrVCqWlpfj++++xcuVKbN68Gb/99hvi4+OD9nsfffRR/OMf/1C175w5c7B06VL06NEDDz30EBo1aoRt27bhxRdfxH/+8x9s2LABHTp0CHgbv/jii4D/THsvv/wyEhMTq43QXnnllbhw4QJiY2OD+vvdSUlJwZIlS6ptb9CggQat8U1+fj6iovQ9ZrFz504sXLgQgwcPRnp6utbNISKiSxh4ExFR0Fx77bXo3bs3AODOO+9EYmIinnzySXz00UcYP3580H5vdHQ0oqO9n+LeffddLF26FDfffDPefvttmEymytemTJmCIUOGYNy4cdi2bZuqn+cLrQLfqKiooHZ6eNOgQQNMmjRJs9/vK1mWUVpailq1aiEuLk7r5hARUZjSd7ctERFFlMzMTADA3r17K7eVl5dj3rx56NWrFxo0aIA6deogMzMTGzdudPtznnvuObRs2RK1atXCoEGD8Ntvvzm8rnZt9MKFC9GwYUO89tprDkE3APTt2xcPPfQQfv31V6xZs6Zy++7duzFmzBg0bdoU8fHxSElJwS233IJTp045vH/VqlXo27cvateujYYNG+LKK690GOV2XuOt1ooVK3DVVVchOTkZcXFx6Ny5M1555RWHfdLT0/H777/j66+/rpzKrfwud2u8//vf/6JXr16oVasWEhMTMWnSpGrLAqZMmYK6deuioKAAo0ePRt26dZGUlIQ5c+bAarX6/G9x5cKFC+jYsSM6duyICxcuVG4vKSlBs2bNMGDAgMrfpbRn3759GD58OOrUqYPmzZtj0aJFkGXZ4efabDZkZ2ejS5cuiI+PR5MmTXD33XfjxIkT1f7vbrjhBnz++efo3bs3atWqhf/3//5f5Wv2MwiUJRWbN2/G9OnTkZSUhISEBNx9990oLy/HyZMncfvtt6Nhw4Zo2LAhHnzwwRq3a/Pmzejbty/i4+PRunVrvPnmmw7tGTduHABgyJAhlcee6/mJiLTHwJuIiEJGWXfasGHDym2nT5/Gv//9bwwePBhPPvkkFixYgGPHjmH48OHYvn17tZ/x5ptv4vnnn8f999+Phx9+GL/99huuuuoqHD161Ke27N69G/n5+Rg1ahTq16/vcp/bb78dgFgDDohOguHDh+P777/HAw88gJdeegl33XUX9u3bh5MnT1a+b+HChbjtttsQExODRYsWYeHChUhNTcVXX33lUxtdeeWVV9CyZUs88sgjWLp0KVJTU3HffffhpZdeqtwnOzsbKSkp6NixI9566y289dZb+Oc//+n2Z65cuRLjx4+HyWTCkiVLMHXqVJjNZlxxxRUO/y4AsFqtGD58OBo3boxnnnkGgwYNwtKlS/Haa6+par/VakVxcXG127lz5wAAtWrVwhtvvIE9e/Y4tPn+++/HqVOnsHLlSodOEqvVihEjRqBJkyZ46qmn0KtXL8yfPx/z5893+L133303/v73v2PgwIFYtmwZ7rjjDrz99tsYPnw4Ll686LBvfn4+JkyYgGHDhmHZsmW47LLLPP6bHnjgAezevRsLFy7EjTfeiNdeew1z587FyJEjYbVa8cQTT+CKK67A008/jbfeesvvdu3Zswdjx47FsGHDsHTpUjRs2BBTpkzB77//DkAsI5g+fToA4JFHHqk89p06dVJxZIiIKKhkIiKiAFuxYoUMQP7yyy/lY8eOyQcP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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJOCAYAAABBfN/cAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAADiyElEQVR4nOzdd3gU5doG8Ht2IQkdQhIIJCH0IjVBkBIpgqCIaEBURMGjWBECRz3iJ9XCsaABCx49BxBRj4p7EBUbCBK7ghSlQyAYQiiht5Dd+f54mWR3s2U22d2Znbl/17XXbGZnkxcmm5nnLc8jybIsg4iIiIiIiIhCwqJ1A4iIiIiIiIiMjIE3ERERERERUQgx8CYiIiIiIiIKIQbeRERERERERCHEwJuIiIiIiIgohBh4ExEREREREYUQA28iIiIiIiKiEGLgTURERERERBRCDLyJiIiIiIiIQoiBNxERRYS9e/dCkiS88MILfo+dMWMGJEkKQ6sqrm/fvujbt2/p18q/b9GiRaX7QvHvWLNmDSRJwpo1a4L6fc0gNTUVY8eO1boZREQUgRh4ExFR0C1atAiSJJU+qlSpgsaNG2Ps2LHIz8/XunnlfPrppxg8eDDq16+PmJgYtGrVCg8//DCOHj2qddMq7LXXXnMJ4vWgb9++Lr8Xzo82bdpo3TxD2LJlC2bMmIG9e/dq3RQiInJSResGEBGRcc2aNQtNmzbF+fPn8dNPP2HRokX47rvv8McffyAmJiZkP/eJJ57AY489purYhx9+GHPmzEGnTp3wj3/8A7GxsVi/fj1eeeUV/Pe//8WqVavQunXroLfxq6++Cvr3dPbaa68hLi6u3AjtlVdeiXPnziEqKiqkP9+bpKQkzJ49u9z+OnXqaNCawGzfvh0Wi77HLLZs2YKZM2eib9++SE1N1bo5RER0CQNvIiIKmWuuuQZdu3YFANx9992Ii4vDs88+i+XLl2PkyJEh+7lVqlRBlSr+L3Hvvfce5syZg5tvvhnvvPMOrFZr6Wtjx45Fv379cNNNN2H9+vWqvl8gtAp8LRZLSDs9/KlTpw5Gjx6t2c8PlCzLOH/+PKpVq4bo6Gitm0NERBFK3922RERkKBkZGQCA3bt3l+4rLi7GtGnTkJ6ejjp16qBGjRrIyMjA6tWrvX6fl156CU2aNEG1atXQp08f/PHHHy6vq10bPXPmTNSrVw9vvPGGS9ANAN26dcM//vEPbN68GUuXLi3dv3PnTgwfPhwNGzZETEwMkpKScMstt+DEiRMu71+yZAm6deuG6tWro169erjyyitdRrnd13irtXDhQvTv3x8JCQmIjo5Gu3btMH/+fJdjUlNT8eeff+Lbb78tncqt/Cxva7w//PBDpKeno1q1aoiLi8Po0aPLLQsYO3Ysatasifz8fNxwww2oWbMm4uPj8fDDD8Nutwf8b/Hk3LlzaNOmDdq0aYNz586V7i8qKkJiYiJ69uxZ+rOU9uzZsweDBg1CjRo10KhRI8yaNQuyLLt8X4fDgezsbFx22WWIiYlBgwYNcO+99+LYsWPl/u+uu+46fPnll+jatSuqVauGf/3rX6WvOc8gUJZUfPfdd5gwYQLi4+NRt25d3HvvvSguLsbx48dxxx13oF69eqhXrx4effTRSrfru+++Q7du3RATE4NmzZph8eLFLu256aabAAD9+vUrPfdcz09EpD0G3kREFDbKutN69eqV7jt58iT+/e9/o2/fvnj22WcxY8YMHD58GIMGDcKGDRvKfY/Fixdj3rx5ePDBBzFlyhT88ccf6N+/PwoLCwNqy86dO7F9+3YMGzYMtWvX9njMHXfcAUCsAQdEJ8GgQYPw008/4aGHHsKrr76Ke+65B3v27MHx48dL3zdz5kzcfvvtqFq1KmbNmoWZM2ciOTkZ33zzTUBt9GT+/Plo0qQJHn/8ccyZMwfJycl44IEH8Oqrr5Yek52djaSkJLRp0wZvv/023n77bfzf//2f1++5aNEijBw5ElarFbNnz8a4ceNgs9nQu3dvl38XANjtdgwaNAj169fHCy+8gD59+mDOnDl44403VLXfbrfjyJEj5R5nzpwBAFSrVg1vvfUWdu3a5dLmBx98ECdOnMCiRYtcOknsdjsGDx6MBg0a4LnnnkN6ejqmT5+O6dOnu/zce++9F4888gh69eqFuXPn4s4778Q777yDQYMG4eLFiy7Hbt++HbfeeisGDhyIuXPnonPnzj7/TQ899BB27tyJmTNn4vrrr8cbb7yBqVOnYujQobDb7XjmmWfQu3dvPP/883j77bcr3K5du3ZhxIgRGDhwIObMmYN69eph7Nix+PPPPwGIZQQTJkwAADz++OOl575t27YqzgwREYWUTEREFGQLFy6UAcgrV66UDx8+LO/fv19eunSpHB8fL0dHR8v79+8vPbakpES+cOGCy/uPHTsmN2jQQP7b3/5Wui83N1cGIFerVk3+66+/Svf//PPPMgB50qRJpfumT58u+7vELVu2TAYgv/TSSz6Pq127tpyWlibLsiz//vvvMgD5ww8/9Hr8zp07ZYvFIt94442y3W53ec3hcJQ+79Onj9ynT59y/76FCxf6/HecPXu23M8cNGiQ3KxZM5d9l112mcv3V6xevVoGIK9evVqWZVkuLi6WExIS5Pbt28vnzp0rPe7TTz+VAcjTpk0r3TdmzBgZgDxr1iyX79mlSxc5PT293M9y16dPHxmAx8e9997rcuyUKVNki8Uir127Vv7www9lAHJ2drbLMUp7HnroodJ9DodDHjJkiBwVFSUfPnxYlmVZzsnJkQHI77zzjsv7v/jii3L7mzRpIgOQv/jii3Ltb9KkiTxmzJjSr5Xf80GDBrmc2x49esiSJMn33Xdf6b6SkhI5KSnJ5ZxUpF1r164t3Xfo0CE5Ojpa/vvf/166T/m/Us4vERHpA0e8iYgoZAYMGID4+HgkJydjxIgRqFGjBpYvX46kpKTSY6xWa+l6Z4fDgaKiIpSUlKBr165Yv359ue95ww03oHHjxqVfd+vWDd27d8eKFSsCatupU6cAALVq1fJ5XK1atXDy5EkAZQnAvvzyS5w9e9bj8cuWLYPD4cC0adPKJeIKRmmwatWqlT4/ceIEjhw5gj59+mDPnj3lprur8dtvv+HQoUN44IEHXNZ+DxkyBG3atMFnn31W7j333Xefy9cZGRnYs2ePqp+XmpqKr7/+utwjKyvL5bgZM2bgsssuw5gxY/DAAw+gT58+paO57saPH1/6XJIkjB8/HsXFxVi5ciUAMY2+Tp06GDhwoMsoe3p6OmrWrFluWUPTpk0xaNAgVf8eALjrrrtczm337t0hyzLuuuuu0n1WqxVdu3Z1+X8KtF3t2rUrXa4BAPHx8WjdurXq/3siItIOk6sREVHIvPrqq2jVqhVOnDiBBQsWYO3atR4TVL311luYM2cOtm3b5jK9tmnTpuWObdmyZbl9rVq1wgcffBBQ25SAWwnAvTl16hQSEhJK2zN58mS8+OKLeOedd5CRkYHrr78eo0ePLg3Kd+/eDYvFgnbt2gXUHrW+//57TJ8+HT/++GO54P/EiRMBZwfft28fAHjM3N6mTRt89913LvtiYmIQHx/vsq9evXrl1iR7U6NGDQwYMMDvcVFRUViwYAEuv/xyxMTEYOHChR47LiwWC5o1a+ayr1WrVgDKljbs3LkTJ06cKD2P7g4dOuTytaffO19SUlJcvlbOQXJycrn9zv9PgbbL/ecAgf3fExGRdhh4ExFRyHTr1q00q/kNN9yA3r17Y9SoUdi+fTtq1qwJQCQhGzt2LG644QY88sgjSEhIKF1r7JyELdiUda+bNm3yesy+fftw8uRJlyB6zpw5GDt2LD7++GN89dVXmDBhAmbPno2ffvrJZSQ/FHbv3o2rrroKbdq0wYsvvojk5GRERUVhxYoVeOmll+BwOEL68wGUS0IXSl9++SUA4Pz589i5c2fAAbHC4XAgISEB77zzjsfX3TsSnGcVqOHt/8TTftkpuVqg7fL2c2S3hG1ERKQ/DLyJiCgslGC6X79+eOWVV0rrbC9duhTNmjWDzWZzGdF0T46l2LlzZ7l9O3bsCLhmcatWrdCqVSssW7YMc+fO9TjlXMkYfd1117ns79ChAzp06IAnnngCP/zwA3r16oXXX38dTz31FJo3bw6Hw4EtW7b4TcoVqE8++QQXLlzA8uXLXUY/PWWAVzutvUmTJgBEQrH+/fu7vLZ9+/bS18Nt06ZNmDVrFu68805s2LABd999NzZv3lxuRN/hcGDPnj2lo9yA+H0AUPo70bx5c6xcuRK9evUKOKgOpVC0KxjLGYiIKPi4xpuIiMKmb9++6NatG7Kzs3H+/HkAZaN4zqN2P//8M3788UeP32PZsmUuZa5++eUX/Pzzz7jmmmsCbs+0adNw7Ngx3HfffeXKYa1btw7PPvss2rdvj+HDhwMQGdhLSkpcjuvQoQMsFgsuXLgAQIzsWywWzJo1q9wIdGVHJj39X504cQILFy4sd2yNGjXKZST3pGvXrkhISMDrr79e+m8AgM8//xxbt27FkCFDKtXmirh48SLGjh2LRo0aYe7cuVi0aBEKCwsxadIkj8e/8sorpc9lWcYrr7yCqlWr4qqrrgIAjBw5Ena7HU8++WS595aUlKj6fwqFULSrRo0aAKDZv4mIiDzjiDcREYXVI488gptuugmLFi3Cfffdh+uuuw42mw033ngjhgwZgtzcXLz++uto164dTp8+Xe79LVq0QO/evXH//ffjwoULyM7ORv369fHoo48G3JbbbrsNv/76K+bOnYstW7bgtttuQ7169bB+/XosWLAA9evXx9KlS1G1alUAwDfffIPx48fjpptuQqtWrVBSUoK3334bVqu1NDhv0aIF/u///g9PPvkkMjIykJmZiejoaPz6669o1KgRZs+eXeH/u6uvvhpRUVEYOnQo7r33Xpw+fRpvvvkmEhISUFBQ4HJseno65s+fj6eeegotWrRAQkJCuRFtAKhatSqeffZZ3HnnnejTpw9uvfVWFBYWYu7cuUhNTfUa7FbUiRMnsGTJEo+vjR49GgDw1FNPYcOGDVi1ahVq1aqFjh07Ytq0aXjiiScwYsQIXHvttaXviYmJwRdffIExY8age/fu+Pzzz/HZZ5/h8ccfL52q3adPH9x7772YPXs2NmzYgKuvvhpVq1bFzp078eGHH2Lu3LkYMWJEUP+daoSiXZ07d4bVasWzzz6LEydOIDo6urTuOxERaUjDjOpERGRQSpmlX3/9tdxrdrtdbt68udy8eXO5pKREdjgc8jPPPCM3adJEjo6Olrt06SJ/+umn8pgxY+QmTZqUvk8pt/X888/Lc+bMkZOTk+Xo6Gg5IyND3rhxo8vPUFNOzNmyZcvkgQMHyvXq1ZOjo6PlFi1ayH//+99Ly1Ep9uzZI//tb3+TmzdvLsfExMixsbFyv3795JUrV5b7ngsWLJC7dOkiR0dHy/Xq1ZP79Okjf/3116WvV7Sc2PLly+WOHTvKMTExcmpqqvzss8/KCxYskAHIubm5pccdPHhQHjJkiFyrVi0ZQOnPci8npnj//fdL2xsbGyvfdtttLmXbZFmU76pRo0a5f6va/29f5cSU969bt06uUqWKS4kwWRbluC6//HK5UaNG8rFjx1zas3v3bvnqq6+Wq1evLjdo0ECePn16uVJusizLb7zxhpyeni5Xq1ZNrlWrltyhQwf50UcflQ8cOFB6TJMmTeQhQ4Z4bL+3cmLuv+fK/4f774+3/7/KtMv990iWZfnNN9+UmzVrJlutVpYWIyLSCUmWmZGDiIiIIs/YsWOxdOlSjzMjiIiI9IRrvImIiIiIiIhCiIE3ERERERERUQgx8CYiIiIiIiIKIa7xJiIiIiIiIgohjngTERERERERhRADbyIiIiIiIqIQqqJ1A8LN4XDgwIEDqFWrFiRJ0ro5REREREREFIFkWcapU6fQqFEjWCy+x7RNF3gfOHAAycnJWjeDiIiIiIiIDGD//v1ISkryeYzpAu9atWoBEP85tWvX1rg15TkcDhw+fBjx8fF+e01IGzxH+sdzpH88R/rHc6R/PEf6xvOjfzxH+qf3c3Ty5EkkJyeXxpi+mC7wVqaX165dW7eB9/nz51G7dm1d/nIRz1Ek4DnSP54j/eM50j+eI33j+dE/niP9i5RzpGYJs35bT0RERERERGQADLyJiIiIiIiIQoiBNxEREREREVEIMfAmIiIiIiIiCiEG3kREREREREQhxMCbiIiIiIiIKIQYeBMRERERERGFEANvIiIiIiIiohDSNPBeu3Ythg4dikaNGkGSJCxbtszve9asWYO0tDRER0ejRYsWWLRoUcjbSURERERERFRRmgbeZ86cQadOnfDqq6+qOj43NxdDhgxBv379sGHDBmRlZeHuu+/Gl19+GeKWEhEREREREVVMFS1/+DXXXINrrrlG9fGvv/46mjZtijlz5gAA2rZti++++w4vvfQSBg0aFKpmEhEREREREVWYpoF3oH788UcMGDDAZd+gQYOQlZXl9T0XLlzAhQsXSr8+efIkAMDhcMDhcISknZXhcDggy7Iu20YCz5H+8RzpH8+R/vEc6R/Pkb7x/Ogfz5H+6f0cBdKuiAq8Dx48iAYNGrjsa9CgAU6ePIlz586hWrVq5d4ze/ZszJw5s9z+w4cP4/z58yFra0U5HA6cOHECsizDYmHuOz3iOdI/niP94znSP54j/eM50jeeH/3jOdI/vZ+jU6dOqT42ogLvipgyZQomT55c+vXJkyeRnJyM+Ph41K5dW8OWeeZwOCBJEuLj43X5y0U8R5GA50j/eI70j+dI/3iO9I3nR/94jvRP7+coJiZG9bERFXg3bNgQhYWFLvsKCwtRu3Ztj6PdABAdHY3o6Ohy+y0Wiy5PHgBIkqTr9hHPUSTgOdI/niP94znSP54jfeP50T+eI/3T8zkKpE0RFXj36NEDK1ascNn39ddfo0ePHhq1iIiIiIzIbgdycoCCAiAxEcjIAKxWrVtFRESRStNug9OnT2PDhg3YsGEDAFEubMOGDcjLywMgponfcccdpcffd9992LNnDx599FFs27YNr732Gj744ANMmjRJi+YTERGRAdlsQGoq0K8fMGqU2Kamiv1EREQVoWng/dtvv6FLly7o0qULAGDy5Mno0qULpk2bBgAoKCgoDcIBoGnTpvjss8/w9ddfo1OnTpgzZw7+/e9/G76UmN0OrFkDvPee2NrtWreIiIjImGw2YMQI4K+/XPfn54v9DL6JiKgiNJ1q3rdvX8iy7PX1RYsWeXzP77//HsJW6YvNBkyc6HoDkJQEzJ0LZGZq1y4iIiK9qug0cbtdXHM93ZrIMiBJQFYWMGwYp50TEVFg9LdCnUpHuCdNAoYPZ687ERGRWpWZJp6TU/6a60yWgf37xXGcjUZERIGIqORqZmCzARMmxKOgwHufCHvdiYiIylOmibuPWCsd1kuX+p4tVlCg7ud8/DFw++2uQXrjxsA99wAtWzIZGxERlcfAW0dsNmDkSAmyLPk91rnXvW/f0LeNiIhIzwKZJg54noqemKjuZ2Vnl9+Xnw9Mn172NZeFERGRM0411wnXGwb/gbdCbe88ERGRkamdJv70096nomdkiIA5GLgsjIiInDHw1omyGwb1QTdQ1jvvvtasuJhrz4iIyDzUdkRPn14+QP/rL5FT5eGHgSuvDE57lJH3rCxeg4mIiFPNdSPQkWtJEr3yGRmeM59bra4Xek55IyIio7LbgcLCyn8f5ynkMTHA+fOV+35cFkZERAoG3jqhdl2ZQpZF7/zTTwMzZpRf0+beu642sQwRBUFeHnDkiPfX4+KAlJTwtYfIwDx1PgfD+fPA2LGAh8qmAeOyMCIiYuCtE8q6svx8WVVyNcBzchdvmAmdKEzy8oDWrX0PlcXEANu3M/gmqiRvWcyDQZKA5cuD872cl4VVpL44ERFFPq7x1gmrVUwFBwBJ8nwHcd11lfsZzlPeiChEjhzxPz/1/HnfI+JE5JevLObBIMtAUVHlv09srGjr0qUVry9ORESRjyPeOpKZCXzwgYwJE2QUFJR1gScnA3PmAJMnB+fncMobkQ4UFADr13t/ndPRiXzyl8U8WGJjgWPHKh7gFxUBAwZ4fo3LwIiIzIOBt85kZgI9ehzG9u0JKCy0lE5FC+YNRmGh6H3n9DYiDWVmivID3nA6OpFXdjuwalV4ftbEiSKXiiR5Dr6zsoB69YA33wz8Os1lYERE5sGp5jpktYrsp7feKrZWa3BHqSdN4vQ2Is35CroBTkcn8sJmE9ewp54K7c+RJDHj7P/+T4xIN27s+npyMvDRR8BLLwHTpgF79wIrV4oR8kAoy8Befpllx4iIjIwj3hEi0Kzn/nB6G1EAmKWcSBcCTaZmtQIOh/fja9YETp8uP5otXcpxmp0tvkdmphiR9pUYzWoVj4quC580SSwrY+lPIiJjYuAdIcqynqu74XCv4+2O09uIVFKTpTwqSkQEiYnA1q3haxuRiQSSTE0JnCdPBl54wXtg/dZbYutejiwpSQTdzgGwMhvNl8rOTvvrL1EqVLk2M+s5EZFxcKp5hHDNeu76mvL1zJnAu+8Cq1cDZ8+K6W++MMs5kQpqspQXF4uyA+npwOjR4WkXkckEkuskKUnM6HruOc/TxJXXMzPFY+9ece1UrqG5uRUbdQ7W7LTsbGY9JyIyGo54R5DMTHGjoKZnHgAaNFD3fZnlnCjMoqL8r/EmIgBlta8/+kjd8U88IZKhKSPFaqeJ+xvNViPQ2Wn+cFkYEZFxMPCOMGpuIBRqe94TE8tubPx9TyJS6ckngaZNgYsXgfh4YNcuYMoUoFo1YOpUsaCTiHyy2cp3Nvtz1VXlr1/BCqz9UWanjRjhPQt6ILgsjIjIOBh4RyC1NxD+et4lSbx+5IiYzuY+is4EL2RazsnUKrpme+rUsufR0eJDWFwMnDunPuj29bOZ0I0MLtBEaso1LSMjtO3yx9vstORkkTwtPz+wfjfnZWHh6DwgIqLQYOBtYP563mUZ6NQJuOmm8u/l9DYyDfeM5QUF/mtsB+rChYq9z9d6cdb5JgMLJJEaUD4LudZ8zU6z28sC8EBGxLksjIgosjHwNjhvPe+KTz/1/D5ObyNTUJOxPJyWLAHathUj3f6StCl1vhl4kwEFkkgN8J7rREveZqdVdDp6sMuKEhmemlKgSUnhaw+ZHgNvE3Duef/4Y3Fzogant5HhqclYHk5t2wLNm4vCw0QmpnZ0d/x4UX4r0vKS+OsUdxcbK0bK7fbI+ncSaUZtKdCPPkKVqCjxIUtIYGc2hRTLiZmE1SpuTJYuDfy9nN5GFCYTJ4oe+O3btW4JkabUju4OHy46hiMxGHUuY5aVJfa5lwtVFBUBAwawvBiRaipLgVqGDkXcoEGwXH65CNTz8sLTPjIljnibSKBT9xRbtgBr1kTeiAIRAN9TzSqaOC1ULBagpAT44Qd1xzu3n8nWKEJ5qqqhNjmo1onUKkuZjt63r/i3+BsBZ/4VohDytIRLzXR1XntJJQbeJlLRkeunnhIPZjqniJOXJ6Zvh2I6eSDrsdVq3hxYuxZYuVLd8c4/l8nWKAJ5KhemXGuUddDu9JZILViUZWFr1gAjR4pRbnfu+Ve8jZATURComa7Oay8FgFPNTaSyiVmUnnZlmpvdLm4Q3ntPbO32yraQKMhCuYa7bVsgLU1sg2XhQrHdsSPw9yo99UQRQikX5j7Cq1xrALGG211SknFHfK1W8fAUdCuU/Csvv8zrLpGLvDxg/XrxCMaMNjX3ELz2UgA44m0i/qbu+ePc0+5wiDqkrP1NphcXJ3q8fV2co6PFtqJlxYgimKep5ID3cmHO15qWLcW+v/1NrHF2LstlVGpnp02aBMyZI2HGjGjceWdo20QUdp6meBcUAMePi+d167qOKBUUiKQPlb3OOgfseluORhGPgbeJqClhMnw48NFH3r+H0tPO2t9kajExIuAGxPSy7dv9rwEDfK81D9Z0dSId8TaVfNw432uZlWvN/v3i66lTRWIxMwhkdlp+PjBuXF3UqSN7nJZPFJG0LPVZ2Wsx14STDwy8TcZbCZPkZLFe7sIF34G3L6z9TYYUFSWiB+e7YfcLZ0qKugspL7ZkIspUcvdO3vx8YPp09d/nyivNE3QDgc1Ok2UJkiRj8mQJN97I6y4ZhN5KfarFNeHkBwNvE3Ku6+089c9qFWu1K4O1v8kQlMRpAHuniSrAbvc9lTwQmzeLIN4sM6nUzE5zJssSr7tEehDImnDeV5gSA2+TUkqYuKvsOnAFa3+TZvLygEOHUKWoCDh0qGLfQ0mcRkQVUtHylZ4cP26+ZUzeZqf5osxWM/oaeCKiSMWs5uRC6WkHypcpCaRsSWUzqBNVyKVpXpbLL0fcoEGw3H671i0iMqVgdr4qncBZWebK4p2ZCezdC7z0krrjX3kF6NdPTMtXqo8QkZslS4B168RjyZLgfM+tW4OXSZ0MjYE3laP0tDdu7Lq/cWPggw/EiLi3IFySxHpxJWstUVhF6rqwYHBO+EaksUA6Xy0q7kSclzGZidUKPPSQ7+su4Do9zb30J1FECHYpMG+UGW3BLAc6ejSQns4kqeQXA2/ySOlp/+absnv5V14R2cznzvU8DV25KcjO5jQ3ooAoJcl8iY4GPv20rKf+l1+A+vXFay+9xGQtpCvKsiU1M6Vq1oTqjNxmXMbkayaaCLpdd5p1hgBFMCUpWXo6A1gyNAbe5JXVKqatKTdEX30ltpmZwA03lD++bl1zrcEjnQhXL3koKSXJlKDa02PHDmDIkLKe+ssvB0aNEu9ft45BN+mKEiyqyRVy6pS4dqhh1mVM3maiuQfdCrPOEKAIFa7ZapwZRhpjcjXy65prgNdfBz7/vOwmasMGsZ0xA/jjD3FD0Ls3g24Ks1DU+tTqwqy2JJmzm28GXn4Z+PlnwOFQN2eXKEwyM4HrrweWL/d9nHJdsVrFr7G3GVVJSeZexuRckeSjj8QsNH/MOEOAyIWvKiVxcZBjYiCZdYkahR0Db/Krf39Ryjg3Vwy6HT8upqHXqAE88giwc6cIvFeuBM6eBapX17rFZBoV7SV3vhC7i6TyYY0bA//6F9Cli+gNKygQH1BF3bq+648ThZhSWGDUKODdd30fq0yLdi+hxWVMZZwrkqgJvM06Q4AMKju7rGP8yBGxnsIfX1VKUlIgb92Kozt2IDY2FpbCQtHDVVwcrBaXx1F3U2PgTX7VrClGGVatEqPeeXli//XXiyC7Y0dxL5+XJ44ZOlTb9hL5ZYRyYXl54t8RSMdDTAzXglPYnDsnVkEAYmWEv8AbEPfRS5e6ltBKShL325xRVaas9KcMWfY83Tw2VnRm2O3ssCAdyMsTwbInapeJZWSUXbvXrw9Ou1JSUBITAyQkiFljO3f6bmdF15/fdBPw2GPsADc5Bt6kyjXXiKB6yRJgzx6xT1n7LUkiCH/lFTGlkIE3URhUZLT//HkxT9XbtDuiIPr1V+DiRTHq2qmTuvcMGwa88IL4NS0oEO9lXerylDX0I0YAkuQ5+C4qAgYMEAH63LnsuCANhWJZmJKU1Nf3rMjockWWfanx11+R3+FPlcbAm1Spcuk3RRm9AIAJE8RWWcf3yiti3VnfvmIGLG+WSJfMPs3LubeeI+AUQt9/L7a9ewNXXqmM0Ppfw+08nZq8y8wEPvhAxoQJMgoKvF9slfJiTH5KmglF8jQlKam30WlAP53L6eli3SaZHgNv8stmAyZNKr//wIGyi3lJibhxOnas7L6eveykG76Sq5jZ+fPipoX/HxQC330ntr16uY/Qcg13sGRmAj16HMaWLQm45RYLiorKHyPL4v84K0vMKAA4o4AMIlSj096oGWX35I03XEe7fU27V34Or8uGxMCbfLLbgYkTPY9QKBfze+4RU9rcj2EvO+mGEdZ0E0UQhwP44QfxvHdvsVVKYk2cyDXcwWS1ioenoFuhlBd7+mngzTfL//+zk5x0Tw+z1dxH2QsK/Cdjc2+3mmn3nI1mWAy8yaecHNcLtDtZBo4e9f6acy87e9SJiMxhyxaRYL9GDdf13c4lsTjiGjxqy4ZNn15+HzvJSbf0OFvNfZTdVzI2oKzdJ06I3rFjx/yPmHM2mmEx8CafKlsDVOllz8nhmj0KgVAlVyGiSlGmmV9xRVmOEAXXcAdfZcqGsZOcdCsSZqupme7+3nuipuJVVwHPPReedpEuMfAmn4JVA7SyATyRRykpwObNwMmTLrsdDgeKiopEXc6EBPYaE4WJ3S46WpcsEV/37Klte8yirLyY56Vh/rCTnCiEWrcW2/XrK/YBJcNg4E0+VfZirghWAE8G5y/hyIULQHR02deyDNx2mxjRfuQRoEsXEWQ7HCg5dKisLqcRVTTJC1GI2Gzl12/Pnw907swpzKHmK3ldINhJThQCl10mpv4cOwYcPKh1a0hDDLzJJ3+ZaGUZqF/fc3I15RilRAyRT5Wp87l9u6hdpCQkSUoKfvv0xlMplYICsbAWAHJzgalTNWkamY/NJq4T7teBo0e5fjhcvCWvCwQ7ySkk4uJEp/mFC1q3RBvR0SL43rgR2LZN69aQhgw6FETBpFzMGzd23Z+UJOp2v/GG+FopCeNMloHhw8X0Nbs99G2lCBaMOp9KQhKzSEkR69+Ux5AhYgbAbbcBd9whOiJ8iY4Wwfr69Z4feXnh+XdQRPNX/QIQ64d5DQi9zExg717gpZcCe58kAcnJ7CSnEElJKVvbfOWVZWtRzKRLF7Hdvl3bdpCmGHiTKsrFfPVq4N13xTY3V+z3FpgrsrOBfv2A1FQxKkJEYaCMiK9bV/Z46CHxWkYG8Omn4vl11wHp6Z4frVsz+Ca/1FS/UNYPU+hZrUCDBoG/j3XUKaRWrRLbK68sy1RuJkqSOI54mxqnmpNqvjLROpeI+fhjcQF3x5IlVI7zmu6tW7VtixF5yrb68svAhg1AfLz/aX8saUJulORpzqXA1K4L5vrh8Alkynjt2sDChbwuU5A5X99PnQJWrBDPO3QQfwz8TT03UkWSvDygenXx/M8/xXrvkhLvxxvp304uGHhT0Fit4ibs9ts9v86SJeSiMmu6qWI6dxZDYc2aicW3RAHwlDwtKQkYN07d+7l+OHzUJEatUQM4cwZo145BNwWZr+v7zTeLbXS0mHnl7Q+DXup2V5b7/0VRUfljrFbRq9m2rZiGb5R/O5XDwJuCKpAphyxZYnLBWNNNgbFYgH37xA3P+vVat4YiiLfkafn5wPTpTLKpN/4SowJiHfg99wC//CLOXWysNm0lA1Jzfb9wQQTdeq/TXVlq/i/sdvHB3LpVfBAZdBsW13hTUHHKIZHOOZdjI1LBX/I0T4k1FcprXD8cfr4Soy5dKmYqtG8POBzAV19p00YiukTpgFi5Utt2UEhxxJuCSu1Uwi1bgDVrxAgIb8aIwsR5zd26dere4772nlPgTEfNTKajR4GZM4FnnnFdtpmUJIJuTmXWhnP+Fed1+cp195prgD/+EMtvb7lF27YSmdoNNwCPPy4yEbvPSON11zAYeFNQqVlXBgBPPSUeSUliOhxvyigomJDEu4quqR892vVrpVY6bwJMQ+0MpWbNygK6f/4T6N6dnat64Csx6jXXAM8/D3zxhRj5tnAeJFWEc6cuwGSpFTF1qvfXeN01DAbeFFS+1pV5wkznVGlLlpSVJlF6hR0ObdukR8FaU89M56ajdibTmTPA2bNAnTrAI48wiIsEvXqJJGuHDwOzZ4uv2VlCfjkH2gUF4gauuFjbNhkZr7uGwcsiBZ2/ut7OlMA8K0usIyQKWNu2Ym1UWhovSkQhoMxk8raWW5KA5GTg3Dnxdc+eDLojxaefll17n3gC6NdPzHS12TRtFumZMnsqPV08rruOQTeRSrw0UkhkZgJ79wKrV4uLuS/Omc6JiEhflJlMnjgnT/vhB/G8d++wNIsqSclU7z4RRpmJxuCbPGJFEm1s3SrWfq9fLzo/KCJxqjmFjLKujJnOyaO4OLFuiRdwIt1TZjKNGuWaPC02FnjjDeDGG4GHHhL7GHjrn5pM9VlZIjEbp52bkPuabWfBWr9tlpwswbrXcc63wjXfEYuBN4Wc2vWBao8jg0hJERcOXxd398ReRKSZzEygQQNxT96mDbBtG3DllWJ/bi5w4ABQtSpw+eVat5T8UZOpXpmJ5i0xGxlURRNx+uOcjwUwT6buUNzrnD8vPpzu+W1I9xh4U8j5y3QuSeL1jIzwt400lpLi/WKhppfYLD3mRDpw7pwIxgAx9XzQIJEN+8wZ4Pvvxf70dKBaNe3aSOpwJhp5Faqp5Eo+FjPyda9TURwBj0gMvCnkfGU6d14fyOlsJrV4sZju0KsXUL162X5/vcQAe3mJwmjXLvH3u25dYOBAUT5szx7g88+B774Tx/TqpWkTSSW1M8y2bAHWrGGmcyJdY9bziMHAm8JCWR84caLr9LakJBF0s5SYSdntwP33ixpEW7a4TkMDQtNLbFZqZhBER4ut8yJed5xlYFo7doht69ai03TECOC554DXXgN27hSv9eihXftIPX8z0RRPPSUeSUmiA53XaoNyXtPNGtzhxXw3psLAm8ImM1Mkavn738UFvFs3kQWXvegmtm2bCLpr1ABatdK6NcamdgYBUHZMSYlY4HnuHPDuuyLi4iwD09q+XWyVj2r9+mK7enXZMQ89JIJyBmj65msmmidKpvOlS3luDSdUa7qdscPWO/drM/PbGBoDbworqxW46SZxwf/rLwbdprdundimpfGXIRzUziBwPqZfP2DFCpE569ZbQ9c20j1lxLtVK1Fq6rHHyh9z8CADtEjhbSaaJ8x0bmChWNMdFSX+SChrGthh6xtn95kG63hT2HXsKLYHDvgefCMT+O03sU1P17Yd5N1VV4ntqlXatoM0p4x4t2zpuxQVIAI0uz1sTaMKyswE9u4VsxaeeML3sc6ZzonQooXY/v3vohPd+bFzJzBkiOhUT0tjUEl0CUe8Kexq1SpLyrNxY9l9PZmQMuLNwFu/lA/o2rXAxYuiXhSZkjLifeoUS1EZidUqzhMznVNAdu0S0yAmTQIaN9a6NcbBNd+GxhFv0kSnTmK7caO27SANlZQAv/8unnftqm1byLsOHcTIxSOP8EbAxI4eBYqKxHO104wZoEUWtZnO1R5HBlbl0rhd794MuoNNWfOtzB5YskTrFlEQccSbNNG5M/C//zHwNrVt20TSrpo1mVhNzywW4NNPtW4FaUyZZp6cDDRtqu49DNAii79M55IkXs/ICH/bSAfq1gWOHwfuugv49lsx4t2zJ7B+PddwB5vzmm81I+BMXhcxGHiTJjjibVLOJUtKSoB33gEKC4ENG8Q+Xrz1x/mcecJzZgrOidUYoBmTr0znkiS22dlMrGZax4+L7X/+U7bv2WfFIyZG9M7xWhB8niqSfPUVMGUK0KaNuI/idThiMPAmTSiB95YtQHGxSIBJBqemZAkv3vrCc0aXONfwZoBmXN4ynScliXPKTPXk0fnzIjDkdSA03LOeN2wI5OaK3s20NO3aRQHjGm/SRJMmQJ06IlfT1q1at4bCQk3JEuXiTfqg9pzl5IjphuvXi2CdDMe9hrcSoLkv70xKYimxSKdkOh80SHx9553iHp/n1KCUqcwUORo1Av71L9b7jkAc8SZNSJIoK5aTI6abKyPgRBSBnC/+HAE3JOep5orMTFHTOSdHJFJLTBQDMBzpjnxWK9CnD/Dll2JWGs+pgXmayuxs61YGeERBwsCbNNOpU1ngrbDbeRNHFNE45dBwHA5RlhcQU82dKaWoyHiUc63MdiADO3kSeP99YPBgoF8/rVtDaly8KCrD5OcDN96odWtIJQbepBn3BGs2m+d1ZXPncopbxHJOzMU1BUQRKS8PuHBB5OJo0kTr1lC4OAfesly2fp8MaMUK4LnnxMlm4B0ZNm0CuncX2eaHDRMVSEj3GHiTZjp3FtuNG4GPPgJuuql8htz8fJHAh2sGI5CaxFxEpHvKNPMWLTgDyUxatBD38qdOAQcPsjycoa1eLbacvhI5OnYEqlcX2ea3bQPatdO6RaQCu0dIM5ddJnrQjxwB7r7bc1kaZV9WlpiGThFETWIuItI9T+u7yfiio8tqtnO6uYFdvCjW+AEc7Y4kVasC3bqJ5z/8oG1bSDWOeJNmPv9cjJ6UlJSVh/REloH9+8V1gZ2xOuKvvnNBQfjaQkQhYbcDq1eLOcYxMeJrjnqbR+vWwO7dIvDm9deg1q0DzpwBYmOBDh3Kv65kPfdXVjIuLnRtpPLy8oBmzYA1a4Dly8uXFWNtb11i4E2asNnEFHJPo9zeMI7TETXTyCtSnJ0Xb31Rc8NFhuKc4HLHDuBf/4pHQYEIvP/7X+C775h3w0xatxbLfznibSDuneZLlohtp07Ahg3lAzZ/Wc8BBnnh5n4P9skn4uGMFUZ0iYE3hZ3dLpKoBRJ0A1xfpitqppEXF6v7XkuWAG3biue8eOuL+w0Xy8oYWvkElxYArn+omXfDXJjZ3GB8dZqvXg2kp3sO2FJSeG3WEzX3YKwwoksMvCnscnJcM5f7I0kiu3lGRujaRBpq27b8FCnSD+cbLk45NCzvs5BcU1kr2a2zskQiXU47NzYG3gbDgM1cnKvJcGBDFxh4U9hVZMp4djZv8Ig052nK4f79wB13iDqw48eLOrBHjpQdw4u97gU6C4l5N8xDCbxzc0VJuehobdtDRAFwnqHGqee6wMCbwi7QKeM33igu+GvWiFFvBuBEGnIeAc/LA3r1KhtBeeUV8XDGi73uBToLScG8G8bXsCFQq5YoKbZ7NysWEUUszmTQBZYTo7DLyBBTxyXJ+zGxsUD//uK5zQaMGiWqXKSmiq8pQvhLsMZpyZEtkGmLpFsVDaCZd8P4JInTzYmIgoWBN4Wd1Sqy4gLlg29JEo+77hJ5PtwpiX0YfEcImw2oW1c8X7hQlC1xfnAklEhzgQbQkgQkJzPvhlkw8CYiCg7NA+9XX30VqampiImJQffu3fHLL7/4PD47OxutW7dGtWrVkJycjEmTJuE8S91EnMxMkRW3cWPX/UlJwPvvA++953m9obIvK0usSySdKy4WRdqjo4FbbxVJ1JwfDLqJNKfMQlJD6Sxl3g3z8BR42+1i+dd774ktr8dERP5pGni///77mDx5MqZPn47169ejU6dOGDRoEA4dOuTx+HfffRePPfYYpk+fjq1bt+I///kP3n//fTz++ONhbjkFQ2YmsHevGNl+912xzc0F4uN9rzd0TuxDGlGyW/sSEwPs2iWed+vGrDxmtnUrsH69eOTlad0acmO1AnPmeHvVtQc0KYmlxMzGPfC22cSyr379uAyMSBNq7sFIlzRNrvbiiy9i3LhxuPPOOwEAr7/+Oj777DMsWLAAjz32WLnjf/jhB/Tq1QujRo0CAKSmpuLWW2/Fzz//HNZ2U/BYreWz4qpdb8jEPhpyzm49Zgzwxx9A8+Yi+06/fsALL4gLw8yZ4vjevbVtL2nLU2ZVtUOsFBbK6LXFAjgcZfsTEx24914JrVpZkJjIBJdm5Bx4eys7x/ruEYIlIY3BvcLI1q2u11nSLc0C7+LiYqxbtw5Tpkwp3WexWDBgwAD8+OOPHt/Ts2dPLFmyBL/88gu6deuGPXv2YMWKFbj99tu9/pwLFy7gwoULpV+fPHkSAOBwOOBwvrvQCYfDAVmWddm2cGnQAFAzGaNBAwe0+G/iObokKQlo3BjSvn2QADimToVl7FjIv/4KuW1bIDoa0nffidd69EA4TxbPUZg4HIFPmzp/Ho5Dh+Bo1IjnSEf+/W8JgISHH5YxaJCMggKgYUMZrVsfQsOG8bA4nWieMv0Ix9+65s0BwIKiImD8ePlS0O2pvruMrCxg6FCZnTOX6O5alJQkgrRPPoFlwgTIcXGQP/sMLh/wuDhxnF7aHGK6O0dqJSWVdWCrvBY7HI6IPK96P0eBtEuzwPvIkSOw2+1oIKKsUg0aNMC2bds8vmfUqFE4cuQIevfuDVmWUVJSgvvuu8/nVPPZs2djpjLq5uTw4cO6XBvucDhw4sQJyLIMi0XzJfiaaN0aSEyMx8GDFshy+dTnkiQjMdGB1q0Pw8uqhJDiOSpjyc9HwqlTkKtUwaG+fRHfoAGshYU4tnw5ivv0geWDD1D1119R3Lo15DCeLJ6j8KhSVISKjIsUFRWh+NAhniON2e3Azz9HYds2K778sjYAYNiwI2jWzI527co+RxYLz5FehetvXaNG8ThwwIqCAu/lSGRZwv79wCefHEPPnsUha0sk0eW1KCYGtdavRw0A5wYPxklPuVa0uLnSiC7PUYAsAOKjoyE5DTS6k6OjcQSAIwLPrd7P0alTp1QfG1F1vNesWYNnnnkGr732Grp3745du3Zh4sSJePLJJzF16lSP75kyZQomT55c+vXJkyeRnJyM+Ph41K5dO1xNV83hcECSJMTHx+vylytc5s0DRo4UQbZr8C3mt82dKyExMUGTtvEcOVm/XmxbtUJCcjLw/PNw1KuHuv36AdWqAQkJQIcOYW8Wz1GYtGoFOSYGUoCdmLGxsXAkJPAchZndLnJjFBSI9AtvvikhP7/s72tUlIwDB+rjiivE1/wc6V84zpHNBhw96qP+p5t16+pi6FAuSQB0+hmSZUgrVwIAYkaOREyCNvdSeqHLcxSohATI27ZB9lW6My4OcRGa0Fbv5ygmgPX2mgXecXFxsFqtKCwsdNlfWFiIhg0benzP1KlTcfvtt+Puu+8GAHTo0AFnzpzBPffcg//7v//zeDKio6MR7SGpk8Vi0eXJAwBJknTdvnBQ1opNnOiaaK12bQkLFwKZmepvAkKB5+iSrVsBAFK7dpAsFsDHso9w4zkKg9TUCq0zs1gsgMXCcxRGNlv5v6fuiosljBwpuazT5TnSv1CeI5tNdIJ7qjLizTPPWLB4sSgbyvXeOvwMnT8PjB0LfPUVLAMGuE4zNyndnaOKSE0VD4PS8zkKpE2aBd5RUVFIT0/HqlWrcMMNNwAQPRqrVq3C+PHjPb7n7Nmz5f5x1ktdqnIgVwWKCJmZwLBhYoTmnXeAf/9bDJ7yQq4jFy4AdeoAl10mslU797bOmSNeGzZMpKqPi2P5MCNKSeF51TlvCbG8ycoSH1tJ2/5N0pjdLjprKnJ7xWRrOuJ+bQaAG28Uj61beW02qrw8oLAQ+PVXUTLo1ltdX+d514SmU80nT56MMWPGoGvXrujWrRuys7Nx5syZ0iznd9xxBxo3bozZs2cDAIYOHYoXX3wRXbp0KZ1qPnXqVAwdOrQ0ACdjUbKep6SIwPvnn4EzZ4AaNbRuGQEAHn8cmDJFZDNv3dpzptT588VWyWbNP/REYRNo8ORcrvHKK0PbNtK3nBzfMyR8EcnWyjpxeIumkbw879dmBa/NxuPpvL/wgusxUVGiVzYxUXzNQDwsNA28b775Zhw+fBjTpk3DwYMH0blzZ3zxxRelCdfy8vJcRrifeOIJSJKEJ554Avn5+YiPj8fQoUPx9NNPa/VPoDBp2hRo0gTYt0/cDAwerHWLqJQkASdP+r6wA+L1I0f4h50ojCoaPLFcI1X2d8C5E8e9bCiFyZEjvDabkZrzXlwMXHdd2dfsgAkLzZOrjR8/3uvU8jVr1rh8XaVKFUyfPh3Tp08PQ8tITyQJuOoqYMEC4JtvGHgT6RJrxOpORYMnZRCEzCtYvwPsxAkz56nll/KwEPnFDpiw0DzwJlKrf38ReK9apXVLCADw1VfA+PHAkCG6SqpGGkpJcU225okynU2n9TiNJtDgSZJEadiMjNC0hyJHRob4XcjPr9g6bwU7ccJIzdRyItIMA2+KGP37i+3vvwNFRUBsrLbtMb1Nm4CdO8VdGZHCU7I15xGYI0fEw+FAFeWDnJDAXvYQCSR4UpKpZWeLNbnsGzE3q1VkJh8xQvxuOP/+KF/Xry+ux55+t9iJowE1U4yJSDP6y8lO5EViItC2rbjAP/kksGaNSBxEGtmyRWwvu0zbdpC+KSMw6ekuD8vllyNu0CBYLr9cvJ6Xp3VLDUkJntRISmIWanKVmSl+Jxo3dt2flAR89BHwxhvia08Z8GUZGD5crPHmtZqIiIE3RRCbTSRqAcSITL9+omShzaZlq0zszz/FloE3+RJIch8KCSV4qlnTdX9SEjBzJvDuu8Dq1aLiDINucpeZCezdK35H3H9XvAXmCl6riYjKcKo5RQRvdWjz80WP+syZQMuWYlQ8I4OlS0JOlstGvNu149Q2Ip3LzAT+8x9gxQrgb38TaRn4t5LUUkp7epKZKUqG5eQAH38sgm13rOtNRMQRb4oAvurQKvumTwdGjWLPetjk5QGnTwNVq4oeDyWbtS/MZk2kqR07xHb0aBFEMeimYLFaRUfO0qWeX1eu1VlZnHauO7w2G4+aezLSBEe8SfcCrUPLnvUwUEa7W7USwXcg2ayJKOyKi8X0YEAsqScKNn/Xatb11pElS0TSHIDXZiNyvycrKBA3xMXF3t/DDpiwYOBNuhdoDVBZFolesrLE9DeO6gSJc2bqnTuBNm2AZs2A9evFvrg4IC1Nu/YRkVe7d4uRxpo1Wd6JQkPttZp1vXWgbVter43OvcLIzp3lB0eyskRP2NixYs0mO2BCjoE36V5FbhLZsx5k3mqDbtsGfPKJeB4TI3pY+YebSHe2bxfb1q09Z6Amqiy112p2/IRQXBwQFcWRTSrPPRDPywOuu07cKK9YATzwgGtgzpkQIcHAm3QvkDq07tizHiSBZKbmH2oi3dm2TWw5zZxCxd+1mnW9Q8R5NhoADBkC/O9/QKdOwCOPAHXruvZ2MKAi98GUQ4eAbt1cj+FgSkgw8CbdU+rQjhghLtyBBN/sWSfSmJLkxVfHDUdgQs55xJsoFNRcq7OzufwrqLzNRgOAjRtFJkUGUOSOgymaYeBNEUGpFTpxorpEa+xZJ9IJL4n3HA4HioqKEBsbC0tCAi/uIcbAm8LB27W6Xj3g3/9mwtOgcB7h3rqVARRRBGHgTRHDuVZoQYHIEzFjhnjNuWddWb/InnUinXBfWwYAFy5A/vlnkeDnr7/KkvR5wqmRlcbAm8LF+Vr90kvA8uXA8OEMuoPC1wg3EekeA2+KKFara7K09u3L96wnJYmgmxd5Ip3asQPSFVegviwDv/wCdOzofyo6p0pW2JEjQFGReN6ypbZtIXNQrtWHD4vAe8MGrVtkEGqmCBORblm0bgBRZWRmAnv3ivwhANC5s6hVy6CbSMeaNwesVliOHwe+/lr9VEmqEGW0OzkZqFFD27aQuaSni+2mTcDFi9q2hYhIawy8KeJZrcCtt4rne/cCFv5WE+lbfj7QowcAQFq2TNu2mACnmZNWmjYF6tQR1a3+/FPr1hARaYshChnCZZcBVasCx48D+/Zp3RoDiosDoqN9H8PM1KTGpTWK0qX679LXX2vcIONj4E1akSSRxgHwncaBiMgMGHiTIURFifXeAPD779q2xZBSUoC//10879ABWLeu/INrcEkNrlEMOwbepCVlurl74G23A2vWAO+9J7Z2e7hbRmRSSplPXziYEhJMrkaG0aWLCLrXrwduvFHr1hiAc8kSALjmGjGtoG5d8TUzTRNFBAbepCVlxHvdurJ9NpvnxKhz5zJHS9AxgCJ3nsp8yrK4ed6/H3jmGeC223iPFwIMvMkwunQRW/cRb7u9rARZYqKo7c0yY36oKVnCTNNEuldSAuzeLZ4z8CYtKIH3xo3i93H5cmDECNcyoIBI/TBihKgDzuC7kpYsAdq2Fc/ZSU6eeCrzOXo0MHu2GMGaMkWbdhkcp5qTYXgKvG02IDUV6NcPGDVKbFNTxX7yQc10YGaaJtIVT1N3c3NFNulq1URWc6Jwa9kSqFkTOHcO2LJFjHS7B91A2b6sLE4790rtFOGMDNHjkZbGoJvUGzFCbFesAM6c0bYtBsURbzKMTp1EIpcDB4DCQuD779mrTmQInCrpl7epu7ffLp63bMmKD6QNi0V0jOfkAP/9r+vvqDtZFjNdc3JEHXByo0wRfuMN4OmngZ49gZdfdj2GI9xUUfXri2zFLVsCP/wgvnbG361KY+BNhlGzJtCqlbgm/fab7151SRK96sOGcdo5kW499ZTILcCLvU82m+dOxr/+ErMGAaBePTGKyL93pIW0NBFMq01+WlAQ2vZEtJQUsf42Lg5o3LhsLj9RZeTlAW3aiNmMf/4JeCr1ySWGlcb+bzIUZbr5smXqe9WJSIeefRa4915OlfTDbvfeyejs22+5zIa0o8SGSqI/fxITQ9cWQ2jbVowe3HST1i0ho+ASw7Bg4E2GogTemzerO5696kRhpnaN4i23cHq5Cjk5vjsZnSnLbBh8U7gVFYltbq7v4yRJ5CLIyAh9m4iIwo1TzclQlMB7/351x7NXnSjMLq1RdBw6hKKiIsTGxsLivviYU8tVC6TzkMtsSAs2GzB5sv/jJElss7P5u+nT6dPAJ58A7dqJ5DZEFDEYeJOhKIH3gQNiTeOxY56PkySReIi96kQaSEkBkpJQcugQkJDgOevXzz8Dq1aJNd7KB5vKCbTzkMmrKJzULoUAxDU5O5tJT/364w9RpqVxY/XTXYhIFxh4k6GsXSt6yu1230E3wF51n+LigKgooLjY+zHMNE2hNHeuqItltzPw9iEjQwQsgd5/c5kNhYPapRCtW4t8Trwmq7Bli9i2a6dtO4goYFzjTYahZPb1V/8zMZGlxPxKSQE+/hi46irg+uuBdevKP5jZkkKpZ0+x/eEHbduhY3a7CGz69Qv8vVxmQ+GgtoPn2DEG3aox8CaKWBzxJkNQM51NGQl/8UUG3R7l5blmq0xIAJ57ruw/letuKZyUwPvHHwGHg0Wo3Xiq260Gl9lQOKnt4Dl8WEywiooKbXsMQQm827bVth1kTlu3lj3nfWHAGHiTIaiZzqaMhOfkADffHPo2RZS8PDHXz1cpCdZvpHDJywNKSsTv3IkTwEcfAc2bl71u8ou9t7rdiuuuAz79VATZzsdwmQ2Fm7IUIj/f8++r8jspy8DevUCrVmFtXmTiiDeFglJxxF9JsdGjy57zvjBgHEIgQwhkveLq1aFrR8Ri/UbSC6UTqHv3st/JkSOB9PSyR+vW4jgT8je7R5KAjRuBDz8UuZecJSVxmQ2Fl9Uq0jUAZUG2QvlauWfftSt87YpYp08D+/aJ5wy8KZguVRwpXU64ZIn/9/C+MGAc8SZDCGS94pYtgJJMmYh0JpBOIBP2svub3aNkLY+LEyOIOTmiYzIxUYw+cqSbwi0zU3T4uC+NULKYv/uuiCV37tSsiZFj2zaxTUgA6tfXti1kPCkppryuhhMDbzIENdPZkpKAunWBzZuBNWvEIBoRUSRRO7unoEAE2SwZRnqQmSlqx3vqCPr1V3EMR7xVaNkSWL4cOHlS65YQUQUw8CZDUKazjRjhe13j2rUi8F69moE3EUUetbN7mLWc9MZbR1CLFmLLEW8V6tQBhg7VuhVEVEFc402GoUxn87WuUSm7s2ZN2JtHRFRpyuwebyQJSE5m1nKKHC1bii1HvInI6Bh4k6FkZop1jatXi3Vjq1cDubllyYSuvFJst20DXntNBOD+6n4TEemFc7Iqd8xaTpFIGfHeuxe4eFHTpujfvHmiysOZM1q3hIgqgFPNyXB8rWtcvRqoWlVc3B98UOxLShI3ssz0SxRBTFxLdNgwMeP0xAnX/UqyKv4to0iSmAhUrw6cPSuCb2UE3JTy8lyzRBcUAMePi+fFxSJDHQB89ZVIrmayv31EkY6BN5mGt9q3+fliv6nL7Kip3xgTI44j0gMT1xL99lsRdNerB3zwAXD4MLOWU+SSJDHqvWmTWOdt2sBbKaXor6oDAFx9tdia7G8fhZGa+8KoKNE5tH592Xv4u+gTA28yBV+1b2VZXPizssRIkilvXJX6jfn5on7jFVcAFreVKPyDSuGg5mLvzmTlxd5/X2yHDwcGDNC2LUTB0LKlCLyd13nb7SYrh6emlKI7k/3tozBS7guVGRgFBWJ0qri47JjiYuC668q+ZkeQXwy8yRTU1r7NyTFx+R2lfmOPHlq3hMzM/WK/davr6LbJXbwolngCwM03a9sWomBxz2xus3mu+81lYURh5FzXe/1616DbE3YE+cXAm0whkNq3RKQx54s9ASgb/fviC+DoUTExwLSdhGQ4zpnNuSyMiIyKWc3JFFj71o/Nm4G2bYEZM7RuCRG5sdmA1FRRDvHZZ8W+c+eA5cs1bRZR0Cgj3jt2+F4WBohlYaxGQkSRiCPeZApK7dv8fM8XdEkSrxu29q2vTKkA8OWXosbaN98A11/P9dxEOuFt9O/MGY7+kXEoI9579wIOh/fjuCyMiCIZA28yBaX27YgRIsj2FHwbtvZtIJlSc3KA9HQmyCDSAV9JIRWmTgpJhuFcUkwNLgsjokjEqeZkGpmZYnSocWPX/bVqGXzUqDKZUolIM4EkhSSKZEpJMbVMuyyMiCIaA28ylcxMMZVt9Wrg/vvFvmbNDBx0E0U6pbyYLwatMc+kkGQmzZuLbfXq3o+RJCA52aDLwtT8rXNn0L99REbFqeZkOlarWBvWrh0wfz6wcWNZnVAi0hn38mIA8PTTwB9/ALNmicWhBs1JwKSQZBY2G7BypXjubbq5JImtYZeFOf+tGzRIbF94AWjYsOyYunVdP/AG/dtHOqR0DPmaQcmOIL8YeJNpJSQAXbsCv/0mSvTceafWLSIij9zLixUWivTHAJCWpk2bwsD0SSHJFLwlEHSXlCSCbkPPUEtJEevflI7GceOA2rW1bRMRUL4TvLAQuPZa0Qv2/fdA1arsCFKBU83J1K65Rmw//1zbdhBRAFq1Elsl+DYoJSmkJ4Yf/SNTUJNAEBC/7zt2GDzoVvz5p9gmJzPoJn1JSRGd3WlpwODBopPIbhfbtDQG3Sow8CZTUwLvr78GSkq0bQsRqaTUHjJ44A2IQGPBgvL7k5IMnhSSTMFfAkGFkkjQFA4eBKpVA9q317olRN5JEtCmjXi+dau2bYkgDLzJ1Lp1A+rVEyWtn3oKWLNGdN4RkY4pI947d2rbjjCJihLbpk2Bd98VySFzcxl0U+QLJDGgST7uYt796dPAO+9o3RIi39q2FVsG3qpxjTeZ2scfl+WJmDlTPJKSxPROw9zUqkmI4Y4JMkjPlMB7+3YxFKbMuzYoZSnMTTcBt96qbVuIgimQxIC7doWuHbpjsYhRASI9u+EGcdPct6/4Oi/PdylargFn4E3m5S2hS36+2G+YaZxKQowhQ0Qm6EcfBa68UgzzK5gplSKJUvD3+HHg6FFDdxI5HMCXX4rnytIYIqNQk0CwZk3g1CkTjXgTRYobbxQPQATdrVv7z3q+fbup7y8ZeJMp+UroogygZWUBw4YZJHGRwyGCbosFmDTJtTwJUaSpVk0E31WrGj7wXrcOOHxY5K7p1Uvr1hAFl5JAcMQIcd11viYrE1lGjxalP00x4n34MNC/P9CxI/D22+KaTRQJjhzxP7Py/HlxnIkDb36iyZT8JXRRErnk5ISvTSH1wQdi26cPg24yhh07gC1bRA+7gSnTzAcMEP0MREaTmSlmmDVu7LpfSSA4cqT42hQj3n/8IR4//cSgmyJDfj6wciVw8qTWLYkIHPEmU1Kb0CWQxC+64r7OpnZt4KqrgN69gfXrOZWcIp/B13Xb7aLj7+23xdeDBmnbHqJQyswUM8xycsR1NzFRTEO3WsV9PQDs3QtcvGjwDqg//hBbZjSnSDF4sPi99Vb7klww8CZTUpvQJZDEL7rha53NqlUigxzX2RDpls0mlsI4z8qZOROIjzdI3gkiD6zWshxNzhITxeqSc+dE8K1UEzQkpYY3A2+KFG3bisA7N1frlkQEzmMhU1ISungbNJMkIDlZHBdxAllnQxSpNmwALr9cJAo0ECXpo/tSmIMHxX6bTZt2EWnFYinLp2j4dd7KiPdll2nbDiK1lJJiDLxVYeBNpqQkdAG8B9/Z2QZJrEZkRDVqAL/9JrKPORxatyYo/CV9BETSR7s9rM0i0pwyym3odd6yzBFvijzt2oktA29VGHiTaXlL6BIdbaBSYkRGlZoqesbOngUOHNC6NUFhuqSPRCqZYsT7wAFRItFqNXzSSDIQjngHhGu8ydScE7ps2CAqbZWUiAzCRKRjVasCzZqJIbAdO8TakQhn+KSPRBVk2BFv50SoO3eKv2kWS9nINxOhkt61aiV+Z0+dEiNXFy54PzYmxtDlP9Vg4E2mpyR06dsXePVV0aO+erUIyIlIx1q1Kgu8+/fXujWVZuikj0SVYMgRb1+JUNPTxZaJUEnvYmKApk2B3buBt97ynf2QHUkMvImcXX21uLB/+WWEBd7OveZbt2rbFqJwadUK+OwzwwyDKUkf8/M9r/OWJPF6RCZ9JKoE5V4+N9dAJcUCSYRq8mCFdO7xx8U2I0NMG3X+fc3LE2ukVq4U00ndE/uaLBhn4E3kZNAg4LXXgK++0rolAfDVa05kZK1aie2OHeVr17uLgIu7kvRxxIjyrylJIJn0kczIVCXFiCKFct3t3Fl8/fnnwN13A717i4tVcbGYjabcn86YUf57mGxWBwNvIif9+gFVqogZM7t3A82ba90iFdT0mrvjOhsygjZtRPBdp47/zqcIubhnZgLTp5e/P0lKEvcxTPpIZqSUFNu8WcxKY+BNpDFfgz7ffQd07QpERYng2xeTzepgVnMiJ7VqAb16iecvvwy89x6wZo1ByvcsWSJKL61bFxEBCJFPeXlA7driQ3rNNYaqXa/cpwwYALz7rsg5kZvLoJvMTVnnbZCVJUSRTc2gj7+g24Q44k3kRikvptT5BsRo09y5EX7j27YtkJamdSuIKs/gyyu+/lpsR48Gbr1V27YQ6YUyyh3RCdaYj4XI1Bh4Ezmx2cQIk7v8fLHuculS4IYbwt4sInJWkeUVEaKoCPjtN/GcZQ2JykT8iLfBOwyJyD9ONSe6xG4HJk70/JqSYTgryyDTzolIl1avFn9v2rYtm31DRKLENQD8/nuELgEzcIchEanDwJvokpwc4K+/vL8uy6IiQk5O+NpEROaiTDMfOFDbdhDpic0G3H67eF5YKBKhpqaK/YbGRKhEhsLAm+iSgoLgHkdEpJbdLkbx/vc/8XX//po2h0g3bDax1Mv92qssATNc8M1EqESGxTXeRJckJgb3uLCJiwOio4ELF7wfw15zItdkRjqq622ziWUuzjNuHnhABOMRndCRqJKUJWDKci9nsizq22dlAcOGGai+PROhkpH4KylmsvtTBt5El2RkiOzl+fmeL/KSJF7PyACOHg1/+7xKSQEefhh4+mngssuAxYvLH6OjIINIM6NHlz3XSV1vZTTP/W9OQUFZQkcG32RWgSwB69s3bM0iorg4cR31lbcgJgb45hsxOOTr+5jo/pSBN9ElVqsoGTZihAiynW+EJUlss7N10qvuXJJEloF33hHPlZTrJvtDRhQwpa63Rp8TZWr5uHEmG80jCgCXgBHpVEqK6LxW7kU98XQvumAB8NFHwOTJwFVXhbaNOsTAm8hJZqYYYXKf9tm4cVkdb4dDu/YB8F2S5OmnxUMno3lEIaGmp13HPE0t94SjeWR2EbsEjMgMUlICv8/87jtgxQqgQwdTBt5MrkbkJjMT2LtXzI6pV0/smz9fR9M91ZQkUUbziIxI6WlXEhC5P5Ys0bqFXilTy/0F3c44mkdmpSwBU2aduZMkIDlZHKd7cXFivasvJlvvSibUp4/Yfvuttu3QCEe8iTywWkW5kptuAt54A/jiC+C667RuFRGVqkhPu8Z8JYryhaN5ZFa+loApdLMEzJO8PFTZsQOIjQUsFtFDsGoVcPnl4o9B3bquH3AuEyOjUwLv334DzpwBatTQtj1hxsCbyIfrrhOB96efAi+/7L3XnYjIH3+Jotw5J3QkMitvS8AA4IUXXGej2e3ic1ZQIOLZjAwNg/K8PEht2yLO0wy1X38VyR65LIzMJjVV/L7n5QE//AAMHKh1i8KKU82JfOjfXyRj3LcP2LJF69YQUSQLZMq47hI6EmlIWQK2ejXw7rtA795i/6FDZcfYbOKevl8/YNQosU1N1bDO95EjkLgsjKg8E08354g3kQ81aoiL9xdfiOlu/foBDRqI3GZERIEIZMp4UpIIunWTW4JIY1ZrWZLBqCiRo+ndd4FnngGWLfNcli8/P4Rl+Zyri3jC5AxE5eXliR4xAPjss/IfTIMvt2DgTeRHUpLYvvmmeAAWJCbGY948cUEnIp1RW180zEmMlERR+fne13nHxgIffCACDI50E3k2ZAhQu7bI+j9vHvDkk2Euy+eruojCXyI1IrNx/9xs2ACkp7seY/DlFwy8iXyw2YD//Kf8/oMHLRg5MkS96ERUORWtLxpizomi3ClTy99805QVVogCEhMj7tdXrwYmTfJ9bEjK8qmpLlJcHKQfRmQQgVTlMWjgzTXeRF74ykAsy+IuOStLHBdWymieLyxJQmaXkgKkpZU9du8G3n9ffC7S0jS7qGdmAvfdV35/UhI78ojUstlE0B0IzvwmIq1pHni/+uqrSE1NRUxMDLp3745ffvnF5/HHjx/Hgw8+iMTERERHR6NVq1ZYsWJFmFpLZuIvA7EsS6W96GGljObdfbf4etiw8nWMDTxNh6hCnn8eeO45kU1YYxcuiO1tt4k1qqtXA7m5DLqJ1FA6xQPFsnxEpDVNp5q///77mDx5Ml5//XV0794d2dnZGDRoELZv346EhIRyxxcXF2PgwIFISEjA0qVL0bhxY+zbtw9169YNf+PJ8NT2jmvSi56SAhw+LJ737y9G8IjIuw4dRNC9eTMwfLimTfnxR7G9+WZg6FBNm0IUcViWj4gilaaB94svvohx48bhzjvvBAC8/vrr+Oyzz7BgwQI89thj5Y5fsGABioqK8MMPP6Bq1aoAgFQlMx5RkKntHdesF33TJrHt2FGjBhBFkPbtxfaPPzRtxvHjwNat4vkVV2jaFKKIZKiyfFwWRmQqmgXexcXFWLduHaZMmVK6z2KxYMCAAfhRGQ5ws3z5cvTo0QMPPvggPv74Y8THx2PUqFH4xz/+AauXv6gXLlzABWVeH4CTJ08CABwOBxwORxD/RcHhcDggy7Iu22Y2vXoBSUnSpQzEUrnXJUlGUhLQq5eMsJ8uWQYefRTSpk2Q27dH+Bugb/wc6V/Yz1G7drAAkP/4A3KIf6bdLkblCgpEx1xGRtlNv7i8WdC8uYz69TX42xEAfo70z4znqEEDQO1KyaQkGS++KOOGG4J8mXQ4KrRW0/H220CbNmU74uLEcLyJzp/emPEzpBmVnxuHw+HymdD7OQqkXZoF3keOHIHdbkcD8Re0VIMGDbBt2zaP79mzZw+++eYb3HbbbVixYgV27dqFBx54ABcvXsT06dM9vmf27NmYOXNmuf2HDx/GeX+Z9TTgcDhw4sQJyLIMi0XzJfimN2NGNMaNqwtJkt2CbxmyDAwefAaffFKM7t2Lw9+bfsMN4lFSAhw6FOYfrm/8HOlfuM+RJTERCQCwcycO7dsHVKsWkp/z2WfRmDq1NgoKyv4gJCba8eSTJzFkyAV8800NALXQufN5HDp0IiRtCBZ+jvTPjOeodWsgMTEeBw9aPHaKAzIACb16XcD77x+D1Rr8S2SVoiJUZJy6KCEBJUqNUgWv35oy42dIK2o/N0VFRShx+lzo/RydOnVK9bERVU7M4XAgISEBb7zxBqxWK9LT05Gfn4/nn3/ea+A9ZcoUTJ48ufTrkydPIjk5GfHx8ahdu3a4mq6aw+GAJEmIj4/X5S+X2dx5J1CnjoxJkyS3NWXiYv/mmzXx5puiV/2ll2QmR9IJfo70L+znKD4ecv36kI4eRUJREdClS9B/hM0GjBsnlauEcPCgBePG1cUHH8jYtEn87ejXL9pjLhM94edI/8x6jubNA0aORLlOcfG1eH7xYhQSE0P0GWvVCnJMDKQAB3BiY2MBnX/uzcasnyFNqPjcyDExiG3VyuVzovdzFOOv0pATzQLvuLg4WK1WFBYWuuwvLCxEw4YNPb4nMTERVatWdZlW3rZtWxw8eBDFxcWIiooq957o6GhER0eX22+xWHR58gBAkiRdt89sRowAbrxRTB39+GMgO1v0pjvLz5cwcqQUvnJA338PVK0q1q1Wrx6GHxh5+DnSv7Cfo/btgW+/hWXrVlEEOIjsdlFP2Fv5QUkCJk+WcGm1E3r0sCASfjX5OdI/M56jESNE+b2JE10TrSUlScjKAv7+d2DXLgkWi6cR8SBITRXVQw4dAq68Ejh3TtXbLBYLIuKDbzJm/AxpQvncHDlStu+tt0RPWno68MYbkOLiIHmoyqPncxRImzRrfVRUFNLT07Fq1arSfQ6HA6tWrUKPHj08vqdXr17YtWuXy1z6HTt2IDEx0WPQTRQsVqtYp7l0qefXlZvtsNX1fuQRoHt30RNAROq89hqwb5+o4xVk/ssPAvv3AydOiFnuzIlIVDmZmcDevaIcn3NZvnvuEa8XFQHHjoWwASkpQN26IuiOjhaJ0nxhIjUi8blJSyt7TJok9q9fL5KiGLwUrqZTzSdPnowxY8aga9eu6NatG7Kzs3HmzJnSLOd33HEHGjdujNmzZwMA7r//frzyyiuYOHEiHnroIezcuRPPPPMMJkyYoOU/g0yi7Mbacw+6cmOdkwP07RvChjgcoiQSwLt3okC0axeybx1IpuXLLweqRNRCLyJ9slrLX29r1hQJ2AoLgd27ga5dQ9iADRvEtmNH0TPvPJIHMaBUVFSE2NhYWBISDB9UEAUsNRWYMkUE4fXqad2akNP00n/zzTfj8OHDmDZtGg4ePIjOnTvjiy++KE24lpeX5zJ8n5ycjC+//BKTJk1Cx44d0bhxY0ycOBH/+Mc/tPonkInopq733r3A6dNAVJTIMkNEmgukrGDjxmJmjC7LGxEZQIsWYQq8f/9dbDt3FkG1e2DtcIgkUQkJnGJO5Elenlg7AgBbtpR/Xcn8bxCa97mPHz8e48eP9/jamjVryu3r0aMHfvrppxC3iqg83dT1Vup3X3YZh82IAuFwALNmiRkj//mPmCYaJBkZ4t5AlB/0fex774mZMXPnhiknBJHJNG8uUqHs3h3iH3TmjJhm3rlziH8QkQHl5YkBJF9JCmNigK1b/S/liBDsfiNSSbmxliTPd9WSBCQni+NCSgm8Oc2cKDAWC7BggUg//scfQf3WVqsIpNXKzxed/DZbUJtBRBCBNwDs2hXiH5SdLWagXVoiSUQBOHLEd9ANiNfdlnBEMgbeRCo531i7B9/SpWXf2dlhmD7KwJsocHl5InlLcrL4esUK8bXyyMur9I/IzBTLPGvV8n9s2BMyEplIixZiG/IRb0DMPKtWLQw/iIgiHQNvogBkZgIffCCjYUOHy/5GjRC6UmJKwKA8fvlF7K9WLWgBA5GhKdPZ0tOBH34Q+2bPFl8rj9atgxZ8d+smnl97re9jnRMyElHwKCPeYQm8iSi0tm1DlU2bDHHPy8CbKECZmcCvvx7GqlUONG4s9mVnhzDoVgIG5bF/v3jtgQeCGjAQGVYYp7PJsrg3AIBevdS9J+QJGYlMRhnxzs9XXWI7cC+9BHTqJMoUElHIWG6/HXGDBsFy+eURf8/LwJuoApQSJtdfL77+7rsQ/SATrn8himS5uaJ2cFSUKBumRsgTMhKZTGwsUKeOeL5nT4h+yK+/iqVfJ06E6AcQUTkRfs/LwJuoEvr0Edtvvw3iN3WeWr51axC/MRGF2rp1YtuxI9C/v5KQ0fOxYUvISGQykhSG6eZKDW9mNCcilSoUeK9evTrY7SCKSErgvXGjGOWqNPep5aNHB+GbElG4/Pab2KanuydkdD0urAkZiUxImW4ekszmZ88C27eL5wy8iUilCgXegwcPRvPmzfHUU09hv7LelMiEGjYEWrUS6zq//z4I31DN1HIi0i1lxLtrV7FVMp0r+SAUSUkhTMhIRMEf8XaejbZ0KeBwAPXqAQcOGCLpE1HYxcUZpj63WlUq8qb8/Hy8/fbbeOuttzBz5kz0798fd911F2644QZERUUFu41EunbllcCOHWK6+XXXad0aItKKLJcF3unpZfszM4Fhw0T28oICsaY7I4Mj3UShFNRa3spsNPeO8WPHynrZYmLEKHhKShB+IJEJpKSIz4yyZnvrVsPP9KzQiHdcXBwmTZqEDRs24Oeff0arVq3wwAMPoFGjRpgwYQI2btwY7HYS6VZI1nkTUcTZswc4fhyIjgYuu8z1NSUh4623ii2DbqLQCmotbyY6JQqNlBQgLU082rbVujUhV+nkamlpaZgyZQrGjx+P06dPY8GCBUhPT0dGRgb+/PPPYLSRSNeUwHvdOmDBAmDNGqC4WGzfe09s7XYNG0hkdmqms8XEiOMqQVnf3bGjyGpORNpRRrz37QMuXtS2LUREQCUC74sXL2Lp0qW49tpr0aRJE3z55Zd45ZVXUFhYiF27dqFJkya46aabgtlWIl369VcxeuVwAHfdBfTrB1SvLrajRoltaipgs4WoAUEIGIgMTZnOtm5d2ePzz8te//TToEwRdV/fTUTaadRIXB5LSrj8migihKmTXEsVWuP90EMP4b333oMsy7j99tvx3HPPoX379qWv16hRAy+88AIaNWoUtIYS6ZHNBowYIdZ2OnMf4c7PF8cFLZnSkiVlU3Li4rimjMiflJTyn5N+/YDVq4HNm4EhQyr9I5wzmhORtiwWoFkzYMsWMd1cGQEnIp1yX/N9icPhQFFREWJjY2FJSIjoe94KBd5btmzByy+/jMzMTERHR3s8Ji4ujmXHyNDsdmDixPJBtyeyLMoHZWWJJEuVXt/Ztq1YD0NEFZOXB/TqJQLvf/8buPpqkfns+HHxet26IguaMy+dXHa7yPHw00/i6y5dQtpyIlJJCbz/+1+x/INJDYl0zlMnucOBkkOHgIQE0aMWwSoUeE+fPh09e/ZElSquby8pKcEPP/yAK6+8ElWqVEEfZfErkQHl5AB//aX+eFkG9u8X7+vb18tByjQbX0lcInyaDZHm3DMU796tbpjaQ9Zim010wDn/Lbj+emDePJYKI9KSzSZyrADAwoXikZQEzJ3LzyYRaaNC3Qb9+vVDUVFRuf0nTpxAv379Kt0ookhQUBCC9zmvRR04UMxP/+IL17WpLFdCVDlqMhR74pa1WFlq4t4Bd+CA2B+yvA5E5JPy2Tx92nW/suyLn00i0kKFRrxlWYYkSeX2Hz16FDVq1Kh0o4gigfss1KC9LyUFiI0Fvv5afD1/Pke4iXTG11KToC8tISLVQvLZ5Gw0qiCHw4Hi4mKtmxHRHA4HLl68iPPnz8OiwVTzqlWrwhqkC3lAgXfmpbk5kiRh7NixLuu77XY7Nm3ahJ49ewalYUR6l5Ehpq3l56tb5y1J4viMDBXfXCnF17AhL+REOuRvqYmqpSVEFHRB+2zm5bkmeZo8GXjmGaB2beDll4H69V170pnolNwUFxcjNzcXDodD66ZENFmW4XA4cOrUKY8Dv+FQt25dNGzYsNI/P6DAu06dOgDEf0CtWrVQrVq10teioqJwxRVXYNy4cZVqEFGksFrFWrERI0RQrSb4zs5W2cO+aZPYduhQmSYSUYioXWpS0SUpRFQxQflsuueBcHbyJDBmjMecD0QKWZZRUFAAq9WK5ORkTUZqjUKWZZSUlKBKlSphD7xlWcbZs2dx6NAhAEBiRae7XhJQ4L1w4UIAQGpqKh5++GFOKyfTy8wUJcLckytZra4lxapWFVlVVSd02bxZbDt2DFpbiSh41F57K3mNJqIABeWzqSYPhJLzgYE3eVBSUoKzZ8+iUaNGqF69utbNiWhaBt4ASgeaDx06hISEhEpNO69Q98v06dMZdBNdkpkJ7N0rqhK9+67Ynj0rtvPni2MuXgR69AjgmyqBN0e8iXRJWWri7R5AkoDkZJVLS4goaPx9NgGRRsVud+0gJwom+6VfrqioKI1bQsGgdJ5cvHixUt9H9Yh3WloaVq1ahXr16qFLly4+exzWr19fqUYRRRqrtfxasb59xWPhQuCXX4AVK4C77lLxzWSZgTeRzjkvNXGnXB5VLy0hoqBRswysqAgYMIDlxSj0tFqTTMEVrPOoOvAeNmxYaTK1G264ISg/nMgMhgwRgfenn6oMvE+cEGvHLBagbduQt4/IdNRkKPbELWuxstTkllvErBZFUpIIunkzT6QNb8vA3CnlxZYu5eeViEJPdeA9ffp0j8+JyLfrrgOmTxfVwS5cAJyKAXhWt664UzhxAnBKYEhEQZKSIpIiOWcsBkS2pePHxfPNm4EtW4D+/YErrxT7PGQtvvpqoKREPH/1VaBdOzHVlSPdRNrKzBQlw9asAUaOFKPc7lj6jygySZKE3NxcpKamat2UgFSojjcRqdeli0jiUlAAzJsnRsMSE1XcnF+qIkBEIZCSEpSkSL/9Jm7ek5KABx4IQruIKGisVvHwFHQrWPqP9MxuF7+bBQUq7x0r6fDhw5g2bRo+++wzFBYWol69eujUqROmTZuGXr16ARBB7//+97+AZ0CnpqYiKysLWVlZQW+3LMuYPn063nzzTRw/fhy9evXC/Pnz0bJly6D/rMpQHXjXq1dP9fz2Il9/4YhMRpLEKFhBAfDoo2X7ubaMKPL9/LPYXnGFtu0gIs9Y+o8ilc1WfrlEqO8dhw8fjuLiYrz11lto1qwZCgsLsWrVKhw9ejQ0PzBInnvuOcybNw9vvfUWmjZtiqlTp2LQoEHYsmULYmJiAAB5eXlI0bgKgerAOzs7O4TNIDIumw1Ytar8fq9rywYPBhwO4KWXgMsuC1s7ichNcTGwbRvQsCGQkODxECXw7t49jO0iItUqVF5MTR4It5wPRMFks4l7RPfkgKHMS3D8+HHk5ORgzZo16NOnDwCgSZMm6NatW+kxytTuG2+8sfT1vXv3Yvfu3Zg8eTJ++uknnDlzBm3btsXs2bMxYMAAAEDfvn2xb98+TJo0CZMmTQIgRqkB4LvvvsOUKVPw22+/IS4uDjfeeCNmz56tuoKWLMvIzs7GE088gWHDhgEAFi9ejAYNGmDZsmW45ZZbAAB9+vRBgwYNMGbMGNxyyy2oV69eJf/HAqc68B4zZkwo20FkSHa76K30xOPaspISsSDtwgWu7ybS2o03inIEr78O3Huvx0MYeBPpm1JeLD/fc4ZzSRKvu5T+U/JAfPstcMcdIvfKypWuNco85Hwg8kaWRalZNex2YMIEz7+vyr3jxIkiM7+aaefVq/sur6eoWbMmatasiWXLluGKK64oTart7Ndff0VCQgIWLlyIwYMHl9a0Pn36NK699lo8/fTTiI6OxuLFizF06FBs374dKSkpsNls6NSpE+655x6MGzeu9Pvt3r0bgwcPxlNPPYUFCxbg8OHDGD9+PMaPH4+FCxf6bzSA3NxcHDx4sDTIB4A6deqge/fu+PHHH0sD77Vr1+Ltt9/GvHnzMGnSJFx//fUYM2aMy78j1FQH3idPnkTt2rVLn/uiHEdkdjk55TOqJiMPcbiU1EkGsB/4/T9A164AcnNF0F2jBhBhCSOIDKd9exF4b9rk8eW//gIOHBA3PunpYW4bEamipryYx9J/KSllI96XX84POVXK2bNAzZrB+V6yLK4/alMBnT4tbiv9qVKlChYtWoRx48bh9ddfR1paGvr06YNbbrkFHTt2BADEx8cDAOrWrYuGDRuWvrdTp07o1KlT6ddPPvkk/ve//2H58uUYP348YmNjYbVaUatWLZf3zZ49G7fddlvpuu+WLVti3rx56NOnD+bPn186TdyXgwcPAgAaNGjgsr9BgwalrwFAcnIyHn/8cTz++OP45ZdfsHjxYowdOxZVqlTBbbfdhrFjx6J9+/b+/6MqIaA13gUFBUhISEDdunU9rveWZRmSJJUWjScyO/c1Y8nIw3a0RjW4TV9zH0xLSgI2bBDP2atOpA3lJsJL4P3TT2LboYMYUSAiffJWXiw6Gnj3XR9TdpXrcOfOIW4hkT4MHz4cQ4YMQU5ODn766Sd8/vnneO655/Dvf/8bY8eO9fq+06dPY8aMGfjss89QUFCAkpISnDt3Dnl5eT5/3saNG7Fp0ya88847pftkWYbD4UBubi7ahqisbrdu3dCtWze8+OKLmDJlCl588UWsXLkSG5TPfIioDry/+eYbxMbGAgBWr14dsgYRGYn72rI4HCkfdHuyfXtZ73pMjPiawTdReF3q4cemTWXz+5wwsRpR5FDKi+XkAL//DkyeDFy86DbF3B0DbwqS6tXFyLMaa9cC117r/7gVK8qqXfr72YGIiYnBwIEDMXDgQEydOhV33303pk+f7jPwfvjhh/H111/jhRdeQIsWLVCtWjWMGDECxcXFPn/W6dOnce+992LChAnlXlObCE0ZQS8sLESi0413YWEhOnv57G7fvh1vv/02lixZghMnTmDcuHG46667VP28ylAdeCuL7N2fE5F3/taWqXL+vKg3zMCbKLxatwaqVgVOngT27Su3/IPru4kii9UqSob17QssWQKsXy+SWDmncHAu3zSouAbqVa8OiYE3VZIkqZvuDQBXX60uL8HVV4en9ny7du2wbNmy0q+rVq1abnbz999/j7Fjx5YmXTt9+jT27t3rckxUVFS596WlpWHLli1o0aJFhdvXtGlTNGzYEKtWrSoNtE+ePImff/4Z999/f+lxR44cwX//+1+8/fbbWLduHQYOHIh//vOfuOGGG1RNaQ8GS0XfeOzYMbzwwgu46667cNddd2HOnDksI0bkRllbBqhLbEFEOlK1qqgFCJSbbl5SAqxbJ54z8CaKPDffLLbvv1+2z2YT/Wv9+gGjRgH1f/sKqfVOwraljSZtJHPyde+ofO0xL0ElHT16FP3798eSJUuwadMm5Obm4sMPP8Rzzz1Xmi0cEJnNV61ahYMHD+LYsWMAxNpsm82GDRs2YOPGjRg1ahQcDofL909NTcXatWuRn5+PI0dErqN//OMf+OGHHzB+/Hhs2LABO3fuxMcff4zx48erbrckScjKysJTTz2F5cuXY/PmzbjjjjvQqFEjl1rj3bt3x/z58zF8+HDs378fn3/+OW655ZawBd1ABQPvtWvXIjU1FfPmzcOxY8dw7NgxzJs3D02bNsXatWuD3UaiiKasLWvcWOuWEFHAPKzzttuBRYtEspwaNYBKdNQTkUZGjhTbNWuA+fOBWbNEAjb3hKj7D1gxYqQFNlvYm0gm5u3eMSkpNKXEAJHVvHv37njppZdw5ZVXon379pg6dSrGjRuHV155pfS4OXPm4Ouvv0ZycjK6dOkCAHjxxRdRr1499OzZE0OHDsWgQYOQlpbm8v1nzZqFvXv3onnz5qVJ2jp27Ihvv/0WO3bsQEZGBrp06YJp06ahUaNGAbX90UcfxUMPPYR77rkHl19+OU6fPo0vvvjCJaj+7LPP8Oeff+LRRx91mZIeTpIsBz4BtkOHDujRowfmz59fmn7dbrfjgQcewA8//IDNmzcHvaHBcvLkSdSpUwcnTpzQZfZ1h8OBQ4cOISEhARZLhSckUAhV9BzZ7cC/H1iPe9+oQGbUdesAtz9g5B0/R/oXMefos89E0H311UB6Omy28gmakpLE6EQoboS0FDHnyMR4jirOZgNuvRXwtgRVggPypfEpZWpvbm5go4w8P/oXqnN0/vx55ObmomnTppUaUXVe+pCYKJYwhqnylW7IsoySkhJUqVKlNLm3JEnIzc0trSsear7OZyCxZYV+w3bt2oW///3vLjXPrFYrJk+ejF27dlXkWxIZntUKOM14IaJIMGQI7I9OwZpT6Zg0CRg+vPyIWH6+GCnjiBhRZLDZxGfWV96njzEMf6IdBuBryDKwf78IgIjCSclLcOutYmu2oNtoVCdXc5aWloatW7eidevWLvu3bt3qUsONiFy5lRgkIj3Ly8M3HxzB888DhYfEri5OLx9BHPYjpTTheVaWyJrMGyMi/bLbxawVf/M907EOjVCA0ygrvuxeIpSIKBCqA+9NTuvbJkyYgIkTJ2LXrl244lIdlZ9++gmvvvoq/vnPfwa/lURGEReHYksMohwqSooRkXby8mBv0Rr9L55Hfy+HnEMMWmN7afCtjIj17RvOhhJRIHJyys9acZeAQjRCARyQsBkdSvdrtCyUiNxMnz4ddevW1boZAVMdeHfu3BmSJMF5Sfijjz5a7rhRo0bhZiVVJBG5SknBW49vR8xTj+N2vCMKNa5c6Xu+W0wMEBcXvjYSEeyFR2C96LuDrBrOozdysA1tAYgR8IIClv0j0rOCAiAZeYjDEa/HtMUWAMAOtMIZ1Cxd4+2z5jcRhc2MGTO0bkKFqA68c3NzQ9kOItO47JoU/P2pB1FYvTn+npUBaf58Uafbm7g41vAmCrPffwe6qjjuXYwufX4OMdhg2Q6An1civUq15GE7WqMavHesXbx0e7wBnUNavomIzEV14N2kSZNQtoPINNLSgHVVe+Cnsz2Q2RxolgIG1kQ646svzJtqOI9uzY6AgTeRfnVrdgRWH0E3AFRFCQDgEOIxOGE9Hn4Y6N81DvxsE1FlVCi5mmLLli3Iy8tDsds02euvv75SjSIyspgYEXz//DPw449As2Zat4iI3FV0dQdHxIj0LZDP6AS8ggmFrwCPAJgaA2zfzo5yIqqwCgXee/bswY033ojNmze7rPtWaqvZ7fbgtZDIaL7/HnclHMUu9MRPP8XhttvEbtZqJNKPLl38H0NEJnL+vJgKw8CbiCqoQnW8J06ciKZNm+LQoUOoXr06/vzzT6xduxZdu3bFmjVrgtxEIoN5+WWM+2QY7sW/8NVXwHvvAbNmAampQL9+wKhRYpuayrrARFphpxcREREFU4VGvH/88Ud88803iIuLg8VigcViQe/evTF79mxMmDABv//+e7DbSWQcP/0kNrgCO3aIQNuT/HxgxAhg6VIgMzOM7SMiIiIi0ilJkpCbm4vU1FStmxKQCo142+121KpVCwAQFxeHAwcOABAJ2LZv3x681hEZTUEBsG8f7LDgF3TzeahSuS8rS0xDJ6IwiosTCRmIiIjCLS8PWL/e+yMvLyQ/9vDhw7j//vuRkpKC6OhoNGzYEIMGDcL3339feowkSVi2bFnA3zs1NRXZ2dnBa6wTm82Gq6++GvXr14ckSdiwYUNIfk5lVWjEu3379ti4cSOaNm2K7t2747nnnkNUVBTeeOMNNGOmKCKv7N//CCuAP9Aep1HL7/GyDOzfL9Z+9+0b8uYRkSIlBdi+He/MPYI5LwK3d92KSb+N9v8+IiKiysjLA1q3FnkFvIkJTbK/4cOHo7i4GG+99RaaNWuGwsJCrFq1CkePHg3qzwm2M2fOoHfv3hg5ciTGjRvn8Zi8vDykaJyjoUIj3k888QQcDgcAYNasWcjNzUVGRgZWrFiBefPmBbWBRBHPqdfy0BsfAwB2oQW6YD26YD2S4b/XsqAg1I0konJSUrCyKA2/Iw3oneF/BDwmpuLp0IkoPDibhfTuyBHfQTdQluwviI4fP46cnBw8++yz6NevH5o0aYJu3bphypQppRWrlKndN954IyRJKv169+7dGDZsGBo0aICaNWvi8ssvx8qVK0u/d9++fbFv3z5MmjQJkiSVJuQGgO+++w4ZGRmoVq0akpOTMWHCBJw5cyagtt9+++2YNm0aBgwY4PWYMWPGoH379nj++edRoNGNdYUC70GDBiHz0qLTFi1aYNu2bThy5AgOHTqE/v37B7WBRBFN6bVMTwfS05H49WIAwHDYsB7pWI90bEdrv8F3YmI4GktE7jZtEtvUK8UIONatE4+ffwaiosSLNpvYx1JDRPqX4vZZXrcOWLJE61aRWZw54/3hL9iuyPcNQM2aNVGzZk0sW7YMFy5c8HjMr7/+CgBYuHAhCgoKSr8+ffo0rr32WqxatQq///47Bg8ejKFDhyLv0pR4m82GpKQkzJo1CwUFBaWB7+7duzF48GAMHz4cmzZtwvvvv4/vvvsO48ePr+j/hFcffPAB7rnnHrz//vtITk7Gtddei/fffx/nK/P/HqAKBd7O9u/fj/379yM2Ntal94KIoKrXshrOIw6eey0lCUhOFqXFiCi8SkqAP/8Uzzt2hLhhT0sTj27dgK5dxYunTol9DLqJIoPzZzktTVxkOaOFwqFmTe+P4cMr/n1TUz1/zwBUqVIFixYtwltvvYW6deuiV69eePzxx7FJ6YEGEB8fDwCoW7cuGjZsWPp1p06dcO+996J9+/Zo2bIlnnzySTRv3hzLly8HAMTGxsJqtaJWrVpo2LAhGjZsCACYPXs2brvtNmRlZaFly5bo2bMn5s2bh8WLFwc9II6Pj8eECRPw22+/YfPmzejYsSMefvhhJCYm4r777sNPl5Ifh1KFAu+SkhJMnToVderUQWpqKlJTU1GnTh088cQTuHjxYrDbSGRKSj9WdjZLGxFpYccO4MIFce/StKmHA664Qmx//jms7SKiSsrPB95/v2xE0NMo+Lp1GNNhHdKwDl/N5owWMofhw4fjwIEDWL58OQYPHow1a9YgLS0NixYt8vm+06dP4+GHH0bbtm1Rt25d1KxZE1u3bi0d8fZm48aNWLRoUeloe82aNTFo0CA4HA7k5uYG8V/mqm3btvjnP/+Jffv24bHHHsOCBQswePDgkP08RYWSqz300EOw2Wx47rnn0KNHDwCixNiMGTNw9OhRzJ8/P6iNJDKjpCQRdLOUGJE2lE7+Dh0Ai6du6u7dxZaBN5G+5eW5rod96y1g3jygRw/glVfESHZKSrnAunov4PfNwOoTwNWMuSkYTp/2/lplRln27q34e93ExMRg4MCBGDhwIKZOnYq7774b06dPx9ixY72+5+GHH8bXX3+NF154AS1atEC1atUwYsQIFBcX+/xZp0+fxr333osJEyaUey2UidD279+Pd955B2+//TZyc3Nx00034c477wzZz1NUKPB+99138d///hfXXHNN6b6OHTsiOTkZt956KwNvogpISgKGDQNefRWoVg3YsweoUqFPKBEFgxJ4d+zo5QAl8N64ETh3TnxwiUhffGWI/vFHkYPFS4bozp3FVqeViSgS1agRWd8XQLt27VzKh1WtWhV2tzq333//PcaOHYsbb7wRgAio97p1BkRFRZV7X1paGrZs2YIWLVqEpO3OTp06hY8++giLFy/Gt99+i549e2Ly5Mm46aabULt27ZD/fKCCgXd0dLTHguVNmzZFlJJshohUe+NfQJe7AIcDeOMNcQ//119iyQ4RacNv4J2SIu7MmzQBjh1j4E2kR4FkiPYSeP/+e2iaRqQnR48exU033YS//e1v6NixI2rVqoXffvsNzz33HIYNG1Z6XGpqKlatWoVevXohOjoa9erVQ8uWLWGz2TB06FBIkoSpU6eWVsByft/atWtxyy23IDo6GnFxcfjHP/6BK664AuPHj8fdd9+NGjVqYMuWLfj666/xyiuvqG57UVER8vLycODAAQDA9u3bAcBlPfkNN9yAPXv24Pbbb8ebb76J5s2bV/a/LGAVWuM9fvx4PPnkky4Z7y5cuICnn346JFnoiIyua1cxw6hqVaBtW7Fv82Zt20Rkdn4Db0kSd+TLlgGNGoWrWUQUJh06iI95YSEwfz6wZg3gNmBHFHxqSt6FINlfzZo10b17d7z00ku48sor0b59e0ydOhXjxo1zCYLnzJmDr7/+GsnJyejSpQsA4MUXX0S9evXQs2dPDB06FIMGDUJaWprL9581axb27t2L5s2blyZl69ixI7799lvs2LEDGRkZ6NKlC6ZNm4ZGAV5Tly9fji5dumDIkCEAgFtuuQVdunTB66+/XnrMa6+9hj179mDWrFmaBN1AACPemW4LTVeuXImkpCR06tQJgFgc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koTs7GzrMSO+lhh468T777+P6dOnY86cOdi3bx/S09MxePBglJSUaN20kHX99dejsLDQ+vXll19a75s2bRr+/e9/44MPPsDWrVvxv//9D1lZWRq21vguX76M9PR0LF261On9L730El599VW8/vrr2LVrFxo1aoTBgwejvLzces6ECRNw+PBhbNy4EZ9++im++OILPPDAA4H6FQzPUx8BwJAhQ+xeV6tWrbK7n33kX1u3bsUjjzyCr776Chs3bsTVq1dx++234/Lly9ZzPL2/VVdXY9iwYaisrMSOHTvwz3/+EytWrMCzzz6rxa9kKGr6BwAmT55s9zp66aWXrPexf/zLbDZj4cKF2Lt3L/bs2YOBAwdixIgROHz4MAC+fvTAUx8BfA3pye7du/HGG28gLS3N7rghX0sy6UKvXr3kRx55xPpzdXW13Lx5c3nBggUatip0zZkzR05PT3d63/nz5+UGDRrIH3zwgfVYfn6+DEDeuXNngFoY2gDIa9eutf5ssVjk5ORk+S9/+Yv12Pnz5+XIyEh51apVsizL8pEjR2QA8u7du63nrF+/XpYkST516lTA2h4qHPtIlmX5/vvvl0eMGOHyMeyjwCspKZEByFu3bpVlWd3723/+8x85LCxMLioqsp6zbNkyOSYmRq6oqAjsL2Bwjv0jy7J86623ylOnTnX5GPZP4DVr1kx+8803+frRMaWPZJmvIT0pKyuT27dvL2/cuNGuX4z6WuKMtw5UVlZi7969yMzMtB4LCwtDZmYmdu7cqWHLQtuxY8fQvHlzXHvttZgwYQIKCgoAAHv37sXVq1ft+uu6665Damoq+0sjJ06cQFFRkV2fNG3aFL1797b2yc6dOxEbG4uePXtaz8nMzERYWBh27doV8DaHqry8PCQmJqJjx454+OGHcfbsWet97KPAu3DhAgAgLi4OgLr3t507d6JLly5ISkqynjN48GBcvHjRbkaJ6s+xfxTvvvsu4uPjccMNN2DmzJm4cuWK9T72T+BUV1dj9erVuHz5MjIyMvj60SHHPlLwNaQPjzzyCIYNG2b3mgGMey0K17oBBJw5cwbV1dV2fzgAkJSUhO+++06jVoW23r17Y8WKFejYsSMKCwsxb9483HLLLTh06BCKiooQERGB2NhYu8ckJSWhqKhImwaHOOX/3dlrSLmvqKgIiYmJdveHh4cjLi6O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w4YNWLBgAYYPH4777rsPgFg63adPHyxcuBBt2rRBSUkJZs+erer527dvj5ycHNx5552QJAnPPPNMrRno1q1b44svvsDdd9+NyMhIxMfH13qeJ598EmPHjkW3bt2QmZmJf//738jJybHLkF4XgwcPxh/+8AdUV1fDZDIBAB577DH07dsXixYtwogRI/D5559jw4YNtdp84sQJHDhwAGazGU2aNEFkZCQAkbDtz3/+c73aRURE5E+c8SYiIgqgDRs2ICUlBa1bt8aQIUOwZcsWvPrqq1i3bp01EAWAt956C1VVVejRoweys7Ptsny78/LLL6NZs2a46aabcOedd2Lw4MHo3r273Tnz58/HyZMn0bZtW5dLtEeOHIklS5Zg0aJFuP766/HGG2/g7bffRv/+/ev8uwPA0KFDER4ebhfA9+nTB8uXL8eSJUuQnp6O//73v7UGGkaPHo0hQ4ZgwIABSEhIwKpVqwAAO3fuxIULFzBmzJh6tYuIiMifJNl2AxkRERGRny1duhSffPIJPv/883o/17hx45Ceno5Zs2b5oGVERET+waXmREREFFAPPvggzp8/j7KyMjRp0qTOz1NZWYkuXbpg2rRpPmwdERGR73HGm4iIiIiIiMiPuMebiIiIiIiIyI8YeBMRERERERH5EQNvIiIiIiIiIj9i4E1ERERERETkRwy8iYiIiIiIiPyIgTcRERERERGRHzHwJiIiIiIiIvIjBt5EREREREREfsTAm4iIiIiIiMiPGHgTERERERER+dH/By9hj+f04sliAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -3155,15 +1185,20 @@ } ], "source": [ - "\n", - "data = exp_rabi()\n", "draw_rabi(data)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -3181,5 +1216,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/experiments/rabi.png b/experiments/rabi.png new file mode 100644 index 0000000000000000000000000000000000000000..57da7ca1963bafc27d6161622da1e1402513f9e6 GIT binary patch literal 97857 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 z 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 literal 0 HcmV?d00001 diff --git a/experiments/rabi.py b/experiments/rabi.py index 1423ccd1..142007f6 100644 --- a/experiments/rabi.py +++ b/experiments/rabi.py @@ -36,7 +36,7 @@ def gen_parametric_waveform_circuit(t): builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) builder.build() - qc.add_calibration(builder, ['q[0]']) //'rabi_test q[0]' + qc.add_calibration('rabi_test', ['q[0]']) tqasm_code = qc.to_tqasm() diff --git a/experiments/rabi_grpc.sh b/experiments/rabi_grpc.sh new file mode 100644 index 00000000..7e3e6b0b --- /dev/null +++ b/experiments/rabi_grpc.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +echo "duration,count0,count1" > rabi_data.csv + +for t in $(seq 1.0 2.0 400.0); do + formatted_t=$(printf "%.1f" $t) + ./GRPCtest 127.0.0.1:2023 60GmonTa 15 1000 1 "TQASM 0.2;\\QREG a[1];\\defcal rabi_test a {frame drive_frame = newframe(a); \\play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); \\} rabi_test a[0];\\MEASZ a[0];" > tmp.log + + count0=$(grep -A1 'key: "0"' tmp.log | grep 'value:' | awk '{print $NF}') + count1=$(grep -A1 'key: "1"' tmp.log | grep 'value:' | awk '{print $NF}') + + echo "$t,$count0,$count1" >> rabi_data.csv + echo "已采集 duration=$t 的数据: 0: $count0 , 1: $count1" + + rm tmp.log +done \ No newline at end of file diff --git a/nohup.out b/nohup.out new file mode 100644 index 00000000..9027e401 --- /dev/null +++ b/nohup.out @@ -0,0 +1,2467 @@ +[W 2025-06-06 18:35:36.833 ServerApp] A `_jupyter_server_extension_points` function was not found in notebook_shim. Instead, a `_jupyter_server_extension_paths` function was found and will be used for now. This function name will be deprecated in future releases of Jupyter Server. +[I 2025-06-06 18:35:36.834 ServerApp] jupyter_lsp | extension was successfully linked. +[I 2025-06-06 18:35:36.838 ServerApp] jupyter_server_terminals | extension was successfully linked. +[I 2025-06-06 18:35:36.841 ServerApp] jupyterlab | extension was successfully linked. +[I 2025-06-06 18:35:36.845 ServerApp] notebook | extension was successfully linked. +[I 2025-06-06 18:35:37.209 ServerApp] notebook_shim | extension was successfully linked. +[I 2025-06-06 18:35:37.250 ServerApp] notebook_shim | extension was successfully loaded. +[I 2025-06-06 18:35:37.252 ServerApp] jupyter_lsp | extension was successfully loaded. +[I 2025-06-06 18:35:37.253 ServerApp] jupyter_server_terminals | extension was successfully loaded. +[I 2025-06-06 18:35:37.255 LabApp] JupyterLab extension loaded from /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/jupyterlab +[I 2025-06-06 18:35:37.255 LabApp] JupyterLab application directory is /Library/Frameworks/Python.framework/Versions/3.10/share/jupyter/lab +[I 2025-06-06 18:35:37.255 LabApp] Extension Manager is 'pypi'. +[I 2025-06-06 18:35:37.258 ServerApp] jupyterlab | extension was successfully loaded. +[I 2025-06-06 18:35:37.260 ServerApp] notebook | extension was successfully loaded. +[I 2025-06-06 18:35:37.261 ServerApp] Serving notebooks from local directory: /Users/yuanhe/tensorcircuit +[I 2025-06-06 18:35:37.261 ServerApp] Jupyter Server 2.12.5 is running at: +[I 2025-06-06 18:35:37.261 ServerApp] http://V_ANYUHE-MC0:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.261 ServerApp] http://127.0.0.1:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.261 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). +[C 2025-06-06 18:35:37.265 ServerApp] + + To access the server, open this file in a browser: + file:///Users/yuanhe/Library/Jupyter/runtime/jpserver-11002-open.html + Or copy and paste one of these URLs: + http://V_ANYUHE-MC0:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 + http://127.0.0.1:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.523 ServerApp] Skipped non-installed server(s): bash-language-server, dockerfile-language-server-nodejs, javascript-typescript-langserver, jedi-language-server, julia-language-server, pyright, python-language-server, python-lsp-server, r-languageserver, sql-language-server, texlab, typescript-language-server, unified-language-server, vscode-css-languageserver-bin, vscode-html-languageserver-bin, vscode-json-languageserver-bin, yaml-language-server +[I 2025-06-06 18:35:51.929 ServerApp] Kernel started: 49917d1f-ff43-4a11-89a9-94bf2d206d7d +[I 2025-06-06 18:35:52.390 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:37:08.420 ServerApp] 302 GET / (@10.96.56.35) 0.34ms +[I 2025-06-06 18:37:08.426 JupyterNotebookApp] 302 GET /tree? (@10.96.56.35) 0.37ms +[W 2025-06-06 18:37:17.452 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:19.121 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.88ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:30.322 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:38.188 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:37:51.836 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:38:16.849 ServerApp] Kernel interrupted: 49917d1f-ff43-4a11-89a9-94bf2d206d7d +[I 2025-06-06 18:38:21.911 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:e26a9209-3bbf-4db4-b22f-5a2bbb453850 +[W 2025-06-06 18:38:36.795 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.95ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:38:42.885 ServerApp] 302 GET / (@10.96.56.35) 0.35ms +[I 2025-06-06 18:38:42.891 JupyterNotebookApp] 302 GET /tree? (@10.96.56.35) 0.42ms +[W 2025-06-06 18:38:44.357 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.93ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:39:55.928 ServerApp] User 8a3ac88ad2984ca1a9015545763aa000 logged in. +[I 2025-06-06 18:39:55.929 ServerApp] 302 POST /login?next=%2Ftree%3F (8a3ac88ad2984ca1a9015545763aa000@10.96.56.35) 1.14ms +[I 2025-06-06 18:40:10.278 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:42:10.243 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:44:10.275 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:46:10.308 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:48:10.338 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:50:00.936 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:50:00.950 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:50:00.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:51:06.475 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:52:18.733 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:52:59.140 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:52:59.141 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:52:59.148 ServerApp] Replaying 16 buffered messages +[I 2025-06-06 18:53:37.941 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:53:37.952 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:53:37.952 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:54:34.164 ServerApp] 302 GET / (@10.96.56.17) 0.31ms +[I 2025-06-06 18:54:34.180 JupyterNotebookApp] 302 GET /tree? (@10.96.56.17) 0.38ms +[I 2025-06-06 18:55:01.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:55:03.755 ServerApp] User c83a602e3b2b49ab938fe23884616702 logged in. +[I 2025-06-06 18:55:03.755 ServerApp] 302 POST /login?next=%2Ftree%3F (c83a602e3b2b49ab938fe23884616702@10.96.56.17) 0.78ms +[I 2025-06-06 18:55:14.530 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:57:38.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:165040ce-03f4-44cf-ad52-8baf106e91c8 +[I 2025-06-06 19:10:19.624 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 19:10:23.602 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:11:47.415 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:27:29.684 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:27:29.685 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:28:53.494 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:44:21.186 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:44:21.187 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:45:45.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:01:27.156 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:01:27.157 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:02:50.982 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:36:48.118 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:36:48.118 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:38:41.939 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:53:34.081 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:53:34.082 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:54:57.927 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:10:08.085 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:10:08.085 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:11:31.935 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:27:36.142 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:27:36.143 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:28:59.964 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:44:29.143 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:44:29.144 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:45:52.962 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:11:12.266 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:11:12.267 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:12:36.094 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:29:10.872 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:29:10.872 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:30:34.694 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:46:25.940 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:46:25.940 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[W 2025-06-06 22:47:55.940 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-06 22:48:00.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:13:39.608 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:13:39.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:15:33.427 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:30:16.059 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:30:16.060 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:31:39.886 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:56:47.677 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:56:47.677 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:58:41.510 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:13:43.477 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:13:43.477 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:15:07.326 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:31:37.153 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:31:37.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:33:00.980 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:47:38.096 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:47:38.096 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:49:01.918 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:14:31.482 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:14:31.483 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:16:25.337 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:31:42.282 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:31:42.282 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:33:06.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:47:43.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:47:43.929 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:49:07.753 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:58:44.349 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:58:44.350 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:00:08.169 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:14:46.790 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 02:14:46.791 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:16:10.617 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:38:57.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 02:40:21.808 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:11:24.434 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:11:24.436 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:12:48.265 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:28:20.248 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:28:20.249 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:29:44.071 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:45:04.969 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:45:04.970 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:46:28.793 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:01:15.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:01:15.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:02:39.806 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:19:18.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:19:18.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:20:42.666 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:37:13.963 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:37:13.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:38:37.798 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:56:42.180 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:56:42.181 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:58:06.005 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:12:31.225 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:12:31.226 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 05:14:01.226 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 05:14:06.229 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:28:57.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:28:57.332 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:30:21.155 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:57:53.539 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:57:53.540 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:59:47.379 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:16:33.320 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:16:33.320 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:17:57.141 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:33:49.999 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:33:49.999 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:35:13.823 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:59:11.973 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:59:11.974 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:00:35.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:16:51.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:16:51.987 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:18:15.806 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:35:25.686 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:35:25.687 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:36:49.509 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:58:22.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:58:22.891 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:59:46.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:15:27.488 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 08:15:27.489 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:16:51.309 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:34:00.188 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 08:34:00.201 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:35:54.309 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:00:49.218 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:00:49.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:02:13.039 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:19:12.732 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:19:12.732 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:20:36.556 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:37:40.318 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:37:40.318 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:39:04.139 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:59:29.541 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:59:29.542 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:00:53.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:16:22.231 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 10:16:22.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:17:46.051 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:32:53.211 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 10:32:53.212 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:34:17.032 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:08:41.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:08:41.761 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:10:35.578 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:27:19.697 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:27:19.698 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:28:43.517 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:45:40.860 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:45:40.861 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:47:04.688 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:01:27.545 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:01:27.545 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:02:51.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:18:18.700 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:18:18.700 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:19:42.524 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:34:03.435 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:34:03.436 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:35:27.280 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:46:37.059 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:46:37.059 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:48:00.879 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:04:23.710 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:04:23.710 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:05:47.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:21:34.852 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:21:34.852 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:22:58.672 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:47:14.061 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:47:14.062 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:49:07.892 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:05:43.730 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:05:43.730 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:07:07.555 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:23:28.433 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:23:28.433 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:24:52.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:40:49.050 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:40:49.050 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:42:12.895 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:05:16.299 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:05:16.299 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:06:40.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:22:19.293 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:22:19.293 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:23:43.114 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:40:45.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:40:45.973 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:42:09.796 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:06:05.097 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:06:05.097 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:07:28.917 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:23:09.644 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:23:09.644 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:25:03.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:41:49.729 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:41:49.729 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:43:13.553 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:07:00.089 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:07:00.089 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:08:23.910 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:23:07.768 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:23:07.768 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:24:31.594 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:40:50.739 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:40:50.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:42:14.564 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:51:41.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:51:41.549 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:53:05.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:09:11.095 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 18:09:11.096 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:10:34.906 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:40:27.685 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 18:40:27.685 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:42:21.497 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:20:18.158 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:20:18.159 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:21:41.986 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:37:33.558 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:37:33.558 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:38:57.384 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:53:27.356 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:53:27.356 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:54:51.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:10:11.161 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:10:11.162 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 20:11:41.162 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 20:11:46.163 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:26:14.204 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:26:14.204 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 20:27:44.205 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 20:27:49.208 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:42:17.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:42:17.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:43:41.040 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:09:39.832 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 21:09:39.833 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:11:33.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:41:42.294 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 21:41:42.294 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:43:06.114 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:12:00.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:12:00.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 22:13:30.984 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 22:13:35.986 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:29:43.721 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:29:43.721 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:31:07.544 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:47:46.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:47:46.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:49:10.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:13:36.152 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:13:36.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:14:59.972 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:29:46.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:29:46.210 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:31:10.031 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:45:38.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:45:38.875 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:47:02.694 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:13:03.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:13:03.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:14:57.080 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:31:29.816 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:31:29.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:32:53.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:48:33.510 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:48:33.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:49:57.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:58:36.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:58:36.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:00:00.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:16:43.902 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:16:43.903 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:18:07.731 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:34:39.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:34:39.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:36:03.377 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:50:27.280 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:50:27.281 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:51:51.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:16:48.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:16:48.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:18:12.285 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:32:54.196 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:32:54.197 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:34:18.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:56:27.904 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:56:27.904 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:58:21.730 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:14:04.897 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:14:04.899 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:15:28.724 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:33:45.311 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:33:45.312 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:35:09.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:49:38.931 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:49:38.932 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:51:02.750 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:05:36.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:05:36.601 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:07:00.420 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:22:12.427 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:22:12.428 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:23:36.252 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:38:34.419 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:38:34.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:39:58.242 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:54:41.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:54:41.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:56:05.043 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:12:39.911 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:12:39.911 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:14:03.731 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:29:26.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:29:26.886 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:30:50.725 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:57:20.757 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:57:20.757 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:58:44.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:18:22.900 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:18:22.901 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:19:46.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:36:30.562 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:36:30.562 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:37:54.391 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:53:42.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:53:42.653 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:55:06.476 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:10:33.267 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:10:33.267 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:11:57.089 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:26:20.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:26:20.874 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:27:44.698 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:43:58.879 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:43:58.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:45:22.701 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:02:23.533 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:02:23.534 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:03:47.356 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:21:04.205 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:21:04.205 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:22:28.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:39:03.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:39:03.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:40:27.803 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:55:08.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:55:08.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:56:32.475 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:18:26.225 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:18:26.226 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:19:50.050 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:36:18.797 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:36:18.798 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:37:42.620 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:54:59.804 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:54:59.805 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:56:23.627 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:20:21.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:20:21.820 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:21:45.644 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:36:50.989 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:36:50.990 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:38:14.811 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:54:07.695 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:54:07.695 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:55:31.552 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:23:01.868 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 11:23:01.869 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:24:55.707 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:46:14.668 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 11:46:14.669 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 11:47:44.668 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-08 11:47:49.673 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:04:18.858 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:04:18.859 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:05:42.678 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:21:48.563 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:21:48.564 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:23:42.385 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:40:45.823 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:40:45.823 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:42:09.649 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:59:10.526 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:59:10.526 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:00:34.350 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:24:07.419 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:24:07.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:25:31.237 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:41:34.008 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:41:34.009 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:42:57.830 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:58:47.578 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:58:47.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:00:11.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:25:06.709 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 14:25:06.710 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:26:30.527 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:43:06.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 14:43:06.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:45:00.825 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:08:56.164 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:08:56.165 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:10:19.991 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:26:08.822 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:26:08.823 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:27:32.644 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:44:06.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:44:06.421 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:45:30.246 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:00:03.768 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:00:03.769 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:01:27.590 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:26:22.959 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:26:22.960 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:27:46.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:42:23.007 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:42:23.007 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:43:46.833 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:01:02.707 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:01:02.708 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:02:26.533 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:28:20.207 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:28:20.208 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:29:44.024 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:45:43.282 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:45:43.283 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:47:07.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:01:30.984 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:01:30.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:02:54.796 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:28:19.340 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:28:19.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:30:13.160 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:45:15.687 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:45:15.688 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:46:39.516 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:02:33.411 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:02:33.412 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:03:57.234 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:30:20.609 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:30:20.609 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:31:44.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:59:42.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:59:42.785 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:01:06.604 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:30:18.936 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 20:30:18.937 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:32:12.757 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:49:16.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 20:49:16.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 20:50:46.530 ServerApp] WebSocket ping timeout after 90002 ms. +[I 2025-06-08 20:50:47.996 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:05:10.669 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:05:10.670 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:06:34.491 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:32:27.142 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:32:27.142 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:33:50.961 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:49:55.605 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:49:55.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:51:19.432 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:08:20.107 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:08:20.107 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 22:09:50.109 ServerApp] WebSocket ping timeout after 90002 ms. +[I 2025-06-08 22:09:55.109 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:32:23.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:32:23.381 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:33:47.204 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:49:29.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:49:29.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:50:52.869 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:05:32.828 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:05:32.828 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:06:56.648 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:32:30.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:32:30.516 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:34:24.340 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:50:37.471 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:50:37.471 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:52:01.297 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:07:04.098 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:07:04.099 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:08:27.920 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:36:14.687 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:36:14.688 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:38:08.514 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:52:49.482 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:52:49.482 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:54:13.307 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:09:46.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:09:46.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:11:09.854 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:34:29.864 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:34:29.865 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:36:23.699 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:51:42.312 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:51:42.313 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:53:06.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:09:11.301 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:09:11.302 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:12:20.541 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:26:44.538 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:26:44.539 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:28:08.360 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:44:28.172 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:44:28.173 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:45:51.992 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:01:18.261 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:01:18.262 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-09 03:02:48.263 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-09 03:02:53.266 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:18:49.628 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:18:49.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:20:13.460 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:35:25.377 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:35:25.378 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:36:49.224 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:51:40.538 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:51:40.539 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:53:04.386 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:13:23.765 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:13:23.766 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:15:17.592 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:30:53.284 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:30:53.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:32:17.107 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:46:55.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:46:55.960 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:48:19.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:03:11.577 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:03:11.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:04:35.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:19:03.356 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:19:03.357 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:20:27.180 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:34:49.908 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:34:49.909 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:36:13.739 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:52:43.421 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:52:43.421 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:54:07.247 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:18:10.133 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:18:10.134 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:19:33.960 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:36:12.807 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:36:12.808 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:37:36.630 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:52:44.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:52:44.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:54:08.446 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:10:58.294 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:10:58.296 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:12:22.115 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:29:08.957 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:29:08.957 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:30:32.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:47:46.589 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:47:46.590 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:49:10.406 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:19:42.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 08:19:42.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:21:36.176 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:55:18.221 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 08:55:18.222 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:57:17.584 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:18:58.605 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:18:58.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:20:22.431 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:20:56.685 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:21:36.152 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:165040ce-03f4-44cf-ad52-8baf106e91c8 +[I 2025-06-09 09:51:11.265 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:53:36.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:20:16.614 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:20:16.615 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:21:40.432 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:36:24.652 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:36:24.653 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:37:48.474 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:52:17.625 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:52:17.626 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:53:41.441 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:22:37.598 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:22:37.598 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:24:01.412 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:39:56.971 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:39:56.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:41:20.787 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:47:48.628 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:47:48.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:49:02.792 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:49:02.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:49:02.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:50:26.620 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:06:38.190 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:06:38.191 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:08:02.058 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:25:50.415 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:25:50.415 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:27:14.240 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:41:53.724 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:41:53.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:43:17.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:31:58.913 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 13:31:58.914 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:33:22.738 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:49:05.361 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 13:49:05.361 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:50:29.175 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:05:11.342 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:05:11.343 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:06:35.157 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:25:22.706 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:25:22.707 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-09 14:26:52.706 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-09 14:26:57.708 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:43:04.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:43:04.454 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:44:28.264 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:00:00.434 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:00:00.435 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:01:24.245 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:22:36.901 ServerApp] 302 GET / (@10.96.56.32) 3.44ms +[I 2025-06-09 15:22:36.907 JupyterNotebookApp] 302 GET /tree? (@10.96.56.32) 1.65ms +[I 2025-06-09 15:23:47.599 ServerApp] User 463021115425478faae79675b159db20 logged in. +[I 2025-06-09 15:23:47.600 ServerApp] 302 POST /login?next=%2Ftree%3F (463021115425478faae79675b159db20@10.96.56.32) 5.47ms +[I 2025-06-09 15:24:01.964 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:26:01.906 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:26:02.613 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:30:02.664 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:32:03.667 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:34:03.696 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:36:03.724 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:38:03.752 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:40:03.780 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:42:03.838 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:43:03.252 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:44:04.682 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:46:05.677 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:48:06.702 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:50:07.690 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:58:18.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 16:25:25.268 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 16:41:38.843 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:00:04.309 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:26:27.017 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:43:00.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:49:54.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 18:16:45.519 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 18:24:44.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 19:08:32.774 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:12:32.875 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:18:32.941 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:23:50.318 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 19:49:54.155 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:08:35.216 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:41:00.315 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:57:53.355 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:15:11.037 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:42:45.258 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:59:40.832 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 22:17:30.444 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 22:44:06.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:01:06.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:20:27.670 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:28:28.484 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:45:08.910 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:01:44.554 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:19:02.882 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:44:50.403 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:01:13.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:19:52.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:47:23.384 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:03:12.090 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:20:49.489 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:38:04.163 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:56:03.810 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:13:49.563 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:29:49.092 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:47:56.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 04:07:56.445 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 04:26:13.013 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 04:27:43.015 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-10 04:51:33.393 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:09:14.998 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:26:16.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:44:31.068 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:01:33.785 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:19:49.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:38:29.504 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:56:57.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 07:15:20.583 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 07:16:50.585 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-10 07:32:13.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 07:49:27.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 07:50:57.464 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-10 08:02:26.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:20:28.460 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:37:18.979 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:54:07.928 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 09:20:05.513 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 09:38:41.108 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:22:02.714 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:38:43.330 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:43:40.746 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 10:57:39.550 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 11:00:09.551 ServerApp] WebSocket ping timeout after 119994 ms. +[I 2025-06-10 11:08:53.019 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:10:53.062 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:12:53.118 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:14:53.151 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:16:53.196 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:18:53.719 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:20:54.753 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:22:55.164 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:23:20.070 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:24:55.212 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:26:55.274 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:40:56.837 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:49:51.131 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:55:41.766 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 12:07:26.215 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 13:02:00.801 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 16:10:22.117 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-10 16:10:22.143 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 16:10:22.143 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-11 10:08:45.978 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-11 10:13:07.204 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-11 10:13:07.205 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 11:55:51.065 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 11:55:51.117 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 11:55:51.118 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:40:32.807 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:40:32.836 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 15:40:32.837 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:41:56.663 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:00:15.116 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:00:15.116 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:01:38.938 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:02:25.953 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:02:25.954 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:12:07.023 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:12:07.040 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:12:07.041 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:35:26.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:35:26.847 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:35:26.847 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:37:20.667 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:38:36.286 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:38:36.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:40:00.110 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:56:36.745 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:56:36.746 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:59:00.569 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:15:47.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:15:47.886 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-12 17:18:17.887 ServerApp] WebSocket ping timeout after 119996 ms. +[I 2025-06-12 17:18:22.889 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:32:19.930 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:32:19.930 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:34:13.749 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:49:52.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:49:52.601 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:51:16.455 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:05:59.425 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:05:59.426 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:08:23.242 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:23:17.552 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:23:17.552 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:26:41.381 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:30:42.866 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:30:42.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:33:36.686 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:34:43.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:34:43.184 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:36:07.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:49:20.581 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:49:20.584 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:50:44.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:50:44.422 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:50:44.422 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:52:38.249 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:08:10.786 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:08:10.787 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:11:34.606 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:27:07.249 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:27:07.250 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:30:01.067 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:31:47.951 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:31:47.952 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:34:41.770 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:50:32.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:50:32.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:53:26.818 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:07:53.931 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:07:53.932 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:10:47.756 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:25:12.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:25:12.993 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:28:36.821 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:43:17.284 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:43:17.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:46:11.112 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:00:49.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:00:49.242 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:02:13.065 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:16:58.115 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:16:58.115 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:19:51.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:35:34.669 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:35:34.670 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:38:28.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:54:07.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:54:07.602 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:59:01.445 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:14:04.650 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:14:04.652 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:16:58.469 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:31:22.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:31:22.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:32:46.446 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:48:11.429 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:48:11.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:51:05.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:07:13.496 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:07:13.496 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:10:37.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:26:34.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:26:34.220 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:29:28.037 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:46:24.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:46:24.184 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:49:18.007 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:03:54.417 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:03:54.418 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:06:48.238 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:21:24.023 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:21:24.023 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:22:47.839 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:38:07.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:38:07.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:40:31.286 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:56:12.937 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:56:12.937 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:59:36.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:13:57.302 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:13:57.303 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:15:21.145 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:30:29.423 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:30:29.424 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:32:53.241 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:47:47.371 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:47:47.371 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:50:41.192 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:05:35.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:05:35.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:08:47.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:23:12.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:23:12.339 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:26:36.168 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:43:10.303 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:43:10.319 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:46:04.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:01:31.254 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:01:31.254 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:02:55.084 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:17:47.289 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:17:47.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:20:11.108 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:35:13.256 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:35:13.257 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:38:37.079 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:53:22.280 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:53:22.281 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:56:16.104 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:12:30.046 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:12:30.047 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:15:53.876 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:31:39.868 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:31:39.868 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:35:03.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:50:17.055 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:50:17.056 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:53:10.878 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:08:20.751 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:08:20.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:11:14.585 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:19:50.191 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:19:50.191 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:22:44.047 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:38:25.132 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:38:25.133 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:41:18.954 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:57:15.141 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:57:15.142 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:00:08.970 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:14:49.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:14:49.348 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:17:43.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:20:55.826 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:20:55.826 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:23:49.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:38:10.974 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:38:10.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:41:04.790 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:55:42.122 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:55:42.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:58:35.965 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:12:55.278 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:12:55.279 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:15:49.126 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:21:36.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:21:36.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:26:30.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:41:33.014 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:41:33.014 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:45:09.597 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:01:41.471 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:01:41.471 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:04:05.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:20:28.956 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:20:28.957 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:27:53.057 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:34:42.096 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:34:42.097 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:37:35.919 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:54:15.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:54:15.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:57:33.232 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:11:33.576 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:11:33.576 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:12:57.400 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:22:45.622 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:22:45.622 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-13 09:26:15.623 ServerApp] WebSocket ping timeout after 119962 ms. +[I 2025-06-13 09:26:20.625 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:37:32.085 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:37:32.086 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:52:01.962 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:52:01.987 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:52:01.987 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:24:43.645 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:24:43.654 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 10:24:43.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:47:17.956 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:47:17.971 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 10:47:17.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:04:17.315 ServerApp] 302 GET / (@10.96.56.21) 4.14ms +[I 2025-06-13 11:04:18.612 ServerApp] 302 GET / (@10.96.56.21) 0.36ms +[I 2025-06-13 11:22:42.235 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:22:42.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 11:22:42.248 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:55:53.872 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:55:53.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 11:55:53.885 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:57:47.702 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:12:22.016 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 12:12:22.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:15:15.849 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:30:01.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 12:30:01.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:12:31.919 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:27:57.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:27:57.602 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:29:51.429 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:45:01.632 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:45:01.633 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:46:25.465 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:52:07.510 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:52:07.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:55:31.330 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 14:11:33.180 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 14:11:33.181 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 15:29:24.216 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 15:29:24.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 15:29:24.241 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:05:56.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:05:56.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 17:05:56.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:57:52.485 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:57:52.524 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 17:57:52.525 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:59:46.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:15:52.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:15:52.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:18:46.083 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:33:47.348 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:33:47.349 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:40:11.162 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:55:36.668 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:55:36.669 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:59:30.505 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:15:13.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:15:13.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:18:07.505 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:33:07.913 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:33:07.914 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:36:44.561 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:52:02.704 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:52:02.705 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:54:56.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:58:32.509 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:58:32.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:01:26.331 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:15:45.518 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:15:45.519 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:19:09.369 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:34:13.738 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:34:13.739 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:37:37.562 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:52:42.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:52:42.585 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:55:06.405 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:09:34.373 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:09:34.374 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:10:58.188 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:26:17.442 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:26:17.442 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:29:11.271 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:43:44.706 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:43:44.706 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:46:38.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:01:07.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:01:07.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:04:01.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:19:35.783 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:19:35.783 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:20:59.603 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:36:01.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:36:01.512 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:38:55.335 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:53:32.748 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:53:32.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:54:56.572 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:09:16.891 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:09:16.892 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:12:40.713 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:27:13.759 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:27:13.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:30:07.579 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:45:01.763 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:45:01.764 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:47:25.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:04:16.648 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:04:16.648 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:09:10.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:25:29.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:25:29.818 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:28:53.641 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:44:21.699 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:44:21.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:47:45.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:02:45.699 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:02:45.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:05:39.534 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:22:26.569 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:22:26.570 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:25:20.567 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:41:21.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:41:21.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:44:15.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:01:10.411 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:01:10.411 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:04:04.232 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:07:47.345 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:07:47.345 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:10:41.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:26:46.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:26:46.878 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:30:10.698 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:44:43.644 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:44:43.644 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:47:37.462 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:02:07.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:02:07.516 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:05:01.336 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:21:55.001 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:21:55.002 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:26:48.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:41:38.124 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:41:38.125 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:44:31.945 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:47:36.948 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:47:36.949 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:50:30.766 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:06:50.230 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:06:50.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:09:44.057 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:25:15.485 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:25:15.486 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:32:09.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:47:09.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:47:09.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:50:03.291 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:06:31.670 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:06:31.671 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:09:55.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:26:18.444 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:26:18.444 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:29:12.264 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:45:13.406 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:45:13.407 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:47:37.250 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:48:20.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:48:20.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:51:14.713 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:06:22.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:06:22.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:09:16.709 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:23:55.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:23:55.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 06:27:55.287 ServerApp] WebSocket ping timeout after 119878 ms. +[I 2025-06-14 06:28:00.288 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:42:44.005 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:42:44.005 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:45:37.828 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:49:33.594 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:49:33.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:52:27.417 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:09:26.529 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:09:26.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:10:50.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:26:27.533 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:26:27.534 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:29:21.347 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:43:49.231 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:43:49.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:46:13.062 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:50:21.012 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:50:21.012 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:53:14.862 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:08:47.779 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:08:47.780 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:12:11.602 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:27:11.856 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:27:11.857 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:30:35.680 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:46:17.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:46:17.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:49:11.275 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:51:45.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:51:45.380 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:54:39.243 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:56:01.608 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:56:01.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:58:25.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:13:32.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:13:32.241 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:16:56.069 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:33:34.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:33:34.406 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:36:28.227 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:51:18.540 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:51:18.541 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:54:12.370 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:08:36.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:08:36.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:11:30.336 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:20:44.050 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:20:44.068 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:24:07.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:38:35.996 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:38:35.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:41:52.494 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:52:35.920 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:52:35.921 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:55:29.746 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:10:21.013 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:10:21.014 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:13:44.893 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:30:11.567 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:30:11.569 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:33:05.407 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:47:57.407 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:47:57.408 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:50:51.227 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:53:36.346 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:53:36.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:56:30.167 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:13:02.315 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:13:02.316 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:14:26.156 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:29:22.351 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:29:22.351 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:32:16.183 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:46:40.740 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:46:40.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:49:34.565 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:54:21.638 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:54:21.638 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:36:15.486 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:51:01.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 13:51:01.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:54:25.163 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:55:41.696 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 13:55:41.696 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:58:35.526 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:13:13.659 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:13:13.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:16:07.500 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:30:42.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:30:42.464 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:36:06.287 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:52:48.354 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:52:48.355 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:55:12.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:56:20.211 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:56:20.211 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:59:44.046 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:14:11.934 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:14:11.934 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:15:35.753 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:31:35.042 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:31:35.042 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:33:28.868 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:48:46.377 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:48:46.378 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:52:40.219 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:57:37.321 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:57:37.321 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:04:31.148 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:19:51.607 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:19:51.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 16:23:51.607 ServerApp] WebSocket ping timeout after 119994 ms. +[I 2025-06-14 16:23:56.609 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:38:53.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:38:53.247 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:40:47.070 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:52:28.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:52:28.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:54:52.474 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:58:24.306 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:58:24.306 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:59:48.122 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:14:22.245 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:14:22.245 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:17:46.076 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:33:07.000 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:33:07.001 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:36:00.823 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:50:45.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:50:45.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:53:39.800 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:58:36.012 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:58:36.013 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:01:29.825 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:16:18.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:16:18.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:17:42.811 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:33:09.795 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:33:09.795 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:34:33.604 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:50:16.586 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:50:16.587 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:52:10.402 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:06:54.599 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:06:54.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:09:48.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:24:56.621 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:24:56.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 19:28:56.623 ServerApp] WebSocket ping timeout after 119899 ms. +[I 2025-06-14 19:29:01.624 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:43:22.737 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:43:22.738 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:47:46.564 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:03:32.723 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:03:32.723 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:07:01.103 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:21:57.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:21:57.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:25:51.610 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:40:39.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:40:39.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:42:03.168 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:56:40.474 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:56:40.475 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:01:04.294 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:16:26.445 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:16:26.445 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:19:50.283 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:34:47.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:34:47.997 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:37:41.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:53:00.371 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:53:00.371 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:55:54.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:11:45.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:11:45.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:14:39.127 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:29:00.683 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:29:00.683 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:32:24.526 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:47:36.542 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:47:36.543 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:51:00.365 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:05:57.386 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:05:57.387 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:08:51.206 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:25:10.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:25:10.537 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:28:04.358 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:42:49.159 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:42:49.161 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:45:43.009 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:00:22.397 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:00:22.399 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:02:46.236 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:18:25.218 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:18:25.220 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:19:49.037 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:34:43.314 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:34:43.314 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:37:37.141 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:52:22.334 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:52:22.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:53:46.153 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:09:56.269 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:09:56.270 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-15 01:11:26.269 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-15 01:11:31.270 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:19:28.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:19:28.752 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:22:40.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:37:19.348 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:37:19.349 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:40:13.175 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:47:52.032 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:47:52.033 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:50:45.907 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:05:05.944 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:05:05.945 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:08:21.788 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:23:19.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:23:19.248 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:26:43.068 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:42:50.730 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:42:50.730 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:45:44.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:47:03.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:47:03.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:49:27.616 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:05:00.946 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:05:00.946 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:06:24.772 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:21:12.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:21:12.929 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:24:06.755 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:38:40.677 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:38:40.677 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:41:34.510 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:48:50.394 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:48:50.394 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:51:44.213 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:07:58.236 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:07:58.238 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:11:22.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:25:56.603 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:25:56.603 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:31:36.169 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:46:52.437 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:46:52.437 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:49:46.276 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:04:45.485 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:04:45.485 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:07:39.308 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:24:24.246 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:24:24.247 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:27:25.750 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:42:05.691 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:42:05.692 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:44:59.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:01:45.664 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:01:45.664 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:04:42.477 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:20:24.580 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:20:24.580 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:23:48.417 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:38:36.659 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:38:36.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:42:00.489 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:59:02.891 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:59:02.892 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:01:26.715 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:16:02.702 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:16:02.703 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:19:26.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:34:55.626 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:34:55.627 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:37:49.457 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:46:21.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:46:21.620 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:49:15.454 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:05:11.540 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:05:11.541 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:08:05.375 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:22:27.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:22:27.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:25:51.325 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:40:45.623 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:40:45.623 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:43:39.586 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:00:46.879 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:00:46.880 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:03:10.743 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:19:02.764 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:19:02.765 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:23:11.487 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:37:28.746 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:37:28.746 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:39:52.568 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:47:09.501 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:47:09.502 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:50:06.895 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:05:43.545 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:05:43.546 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:08:37.381 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:25:17.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:25:17.961 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:28:41.784 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:44:22.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:44:22.486 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:49:46.308 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:59:55.190 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:59:55.190 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:02:49.010 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:19:07.127 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:19:07.128 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:22:00.985 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:36:20.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:36:20.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:39:14.156 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:48:15.242 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:48:15.242 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:51:09.086 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:05:32.199 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 12:05:32.199 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:47:55.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:49:28.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 12:49:28.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:50:52.283 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:07:41.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:07:41.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:10:35.254 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:26:09.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:26:09.584 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:29:33.423 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:44:22.700 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:44:22.700 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:47:16.533 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:50:22.693 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:50:22.693 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:53:16.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:08:14.723 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:08:14.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:11:08.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:26:05.459 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:26:05.459 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:29:29.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:44:14.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:44:14.348 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:47:08.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:51:27.230 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:51:27.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:54:21.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:09:47.127 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:09:47.128 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:12:40.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:28:41.869 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:28:41.870 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:31:53.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:48:22.007 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:48:22.008 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:49:45.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:52:25.168 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:52:25.169 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:53:48.984 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:09:35.961 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:09:35.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:10:59.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:25:36.021 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:25:36.022 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:28:59.841 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:44:21.237 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:44:21.237 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:48:15.086 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:53:20.578 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:53:20.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:58:20.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:12:50.820 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:12:50.821 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:14:14.635 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:31:09.838 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:31:09.839 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:34:03.658 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:43:19.798 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:43:19.798 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:46:13.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:54:28.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:54:28.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:57:22.593 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:01:41.791 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:01:41.792 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:04:35.606 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:19:01.739 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:19:01.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:24:25.554 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:40:48.555 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:40:48.556 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:43:42.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:59:10.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:59:10.820 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:02:04.647 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:12:58.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:12:58.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:19:52.572 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:34:55.132 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:34:55.133 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:37:48.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:53:26.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:53:26.986 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:56:20.809 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:11:40.032 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:11:40.032 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-15 20:13:10.036 ServerApp] WebSocket ping timeout after 90003 ms. +[I 2025-06-15 20:13:14.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:27:31.323 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:27:31.323 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:30:55.144 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:46:31.084 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:46:31.085 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:49:24.902 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:05:05.887 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:05:05.887 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:07:59.722 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:23:55.831 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:23:55.831 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:26:49.657 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:41:32.412 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:41:32.413 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:46:26.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:01:52.770 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:01:52.770 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:05:00.406 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:20:23.839 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:20:23.839 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:23:52.752 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:40:06.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:40:06.819 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:43:30.649 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:58:05.745 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:58:05.745 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:00:29.560 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:15:00.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:15:00.528 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:18:24.384 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:34:05.998 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:34:05.999 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:38:59.817 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:53:39.090 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:53:39.090 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:56:32.915 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:11:05.302 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:11:05.302 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:14:29.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:29:19.051 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:29:19.051 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:32:42.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:48:48.049 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:48:48.050 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:51:41.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:06:25.202 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:06:25.202 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:09:51.055 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:24:28.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:24:28.627 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:27:22.445 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:42:03.594 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:42:03.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:44:27.435 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:59:09.631 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:59:09.631 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:02:03.451 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:18:13.614 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:18:13.614 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:21:37.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:36:21.801 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:36:21.801 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:39:15.640 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:54:02.939 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:54:02.939 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:56:57.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:12:23.028 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:12:23.028 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:13:46.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:25:50.074 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:25:50.075 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-16 03:29:20.074 ServerApp] WebSocket ping timeout after 119912 ms. +[I 2025-06-16 03:29:21.451 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:43:00.506 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:43:00.506 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:45:54.345 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:01:38.927 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:01:38.927 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:04:02.742 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:18:26.837 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:18:26.837 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:20:20.654 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:35:22.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:35:22.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:37:46.783 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:53:24.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:53:24.656 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:54:48.490 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:10:37.771 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:10:37.772 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:12:01.588 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:28:17.798 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:28:17.799 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:31:11.617 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:45:30.319 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:45:30.319 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:48:24.153 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:04:34.227 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:04:34.227 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:07:28.053 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:23:27.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:23:27.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:28:51.116 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:43:17.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:43:17.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:46:11.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:00:44.433 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:00:44.434 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:03:08.267 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:18:06.269 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:18:06.270 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:20:00.084 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:35:13.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:35:13.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:37:37.382 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:53:27.727 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:53:27.727 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:56:21.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:11:13.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:11:13.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:14:37.627 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:31:09.769 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:31:09.770 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:34:59.775 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:49:33.719 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:49:33.720 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:52:27.548 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:08:44.597 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:08:44.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:10:08.413 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:24:27.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:24:27.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:26:51.686 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:36:42.341 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:36:42.342 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:39:36.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:46:57.393 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:46:57.395 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:57:03.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:57:03.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:57:03.536 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:58:57.349 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 10:02:38.490 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 10:02:38.491 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:08:07.891 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:08:07.919 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:08:07.920 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:10:01.748 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:25:01.289 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:25:01.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:26:25.117 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:41:20.314 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:41:20.314 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:51:36.834 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:51:36.846 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:51:36.847 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:53:30.687 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:10:19.291 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:10:19.291 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:11:43.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:26:23.357 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:26:23.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:27:47.177 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:43:03.949 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:43:03.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:44:33.275 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:00:25.277 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:00:25.277 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:03:19.097 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:07:44.042 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:07:44.042 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:21:53.429 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:21:53.438 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:21:53.438 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:23:47.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:35:35.258 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:35:35.258 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:55:35.702 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:55:35.758 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 15:55:35.758 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:57:29.587 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:59:13.446 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 15:59:13.446 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:00:59.692 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:00:59.728 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:00:59.728 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:15:46.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:15:46.738 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:15:46.738 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:17:40.558 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:32:14.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:32:14.382 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:33:38.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:48:07.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:48:07.209 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:51:31.024 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:08:13.014 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:08:13.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:11:36.857 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:26:31.242 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:26:31.243 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:29:55.063 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:46:21.385 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:46:21.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:49:35.246 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:04:19.866 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:04:19.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:07:13.695 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:16:15.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:16:15.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:19:39.127 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:33:58.542 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:33:58.542 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:36:52.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:51:45.179 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:51:45.179 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:54:53.903 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:09:04.108 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:09:04.108 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:11:57.937 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:26:48.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:26:48.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:30:12.176 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:44:46.580 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:44:46.580 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:47:40.399 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:02:25.186 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:02:25.187 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-16 21:07:55.186 ServerApp] WebSocket ping timeout after 119886 ms. +[I 2025-06-16 21:08:00.187 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:22:40.161 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:22:40.161 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:25:33.985 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:40:24.889 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:40:24.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:43:48.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:58:09.414 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:58:09.415 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:01:03.249 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:15:36.201 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:15:36.202 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:18:30.040 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:32:53.790 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:32:53.791 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:34:47.646 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:51:15.693 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:51:15.694 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:53:39.845 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:09:08.493 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:09:08.494 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:12:32.323 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:29:25.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:29:25.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:32:19.449 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:46:43.703 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:46:43.705 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:49:37.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:04:31.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:04:31.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:07:25.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:22:48.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:22:48.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:24:12.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:40:28.103 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:40:28.104 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:42:51.927 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:58:45.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:58:45.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:02:09.798 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:17:49.583 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:17:49.583 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:21:13.425 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:35:44.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:35:44.183 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:38:38.029 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:45:12.030 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:45:12.030 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:48:05.846 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:04:29.024 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:04:29.024 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:06:52.848 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:22:51.841 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:22:51.841 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:26:15.660 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:41:33.153 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:41:33.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:44:26.978 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:59:08.487 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:59:08.489 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 03:02:08.514 ServerApp] WebSocket ping timeout after 90011 ms. +[I 2025-06-17 03:02:13.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:17:09.353 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:17:09.353 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:20:08.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:36:57.194 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:36:57.194 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:40:21.018 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:55:08.061 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:55:08.062 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:58:01.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:13:37.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:13:37.875 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:17:01.696 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:33:06.047 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:33:06.051 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:36:29.883 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:52:36.427 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:52:36.428 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:55:43.621 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:02:00.106 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:02:00.106 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:04:53.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:19:40.035 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:19:40.036 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:23:03.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:38:00.710 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:38:00.711 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:40:24.545 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:55:44.625 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:55:44.626 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:59:08.450 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:03:07.590 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:03:07.590 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:06:01.415 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:20:53.372 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:20:53.372 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:22:17.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:37:46.340 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:37:46.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:40:10.159 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:55:30.595 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:55:30.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:58:24.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:03:53.397 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:03:53.397 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:07:19.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:22:57.168 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:22:57.169 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:25:50.994 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:41:46.975 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:41:46.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:44:40.819 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:01:07.950 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:01:07.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:04:01.778 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:04:57.011 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:04:57.013 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:07:50.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:16:13.212 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:16:13.213 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:19:37.038 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:35:38.401 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:35:38.401 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:39:02.223 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:47:23.458 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:47:23.458 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:50:17.303 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:06:11.290 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:06:11.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 09:09:11.291 ServerApp] WebSocket ping timeout after 119890 ms. +[I 2025-06-17 09:09:15.699 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:24:09.358 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:24:09.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:29:33.193 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:45:06.149 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:45:06.149 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:47:59.980 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:03:05.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:03:05.961 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:05:59.780 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:07:13.724 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:07:13.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:09:37.550 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:26:26.872 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:26:26.872 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:29:50.693 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:44:13.666 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:44:13.666 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:49:07.491 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:05:37.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:05:37.517 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:08:31.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:24:19.335 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:24:19.336 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:27:13.172 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:43:16.088 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:43:16.088 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:46:09.911 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:00:29.281 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:00:29.282 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:03:23.108 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:08:06.162 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:08:06.162 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:10:59.987 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:25:22.568 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:25:22.569 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:29:16.385 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:44:44.561 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:44:44.562 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:30:38.395 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:44:57.959 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 13:44:57.959 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:46:21.776 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:03:23.984 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:03:23.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:04:47.810 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:08:58.123 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:08:58.124 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:11:51.942 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:27:46.810 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:27:46.810 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:31:10.632 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:47:21.067 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:47:21.078 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:50:14.887 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:05:33.400 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:05:33.400 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:08:27.237 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:10:09.683 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:10:09.683 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:11:33.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:27:21.703 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:27:21.703 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:30:18.026 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:45:18.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:45:18.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:48:12.820 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:02:56.489 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:02:56.490 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:05:20.347 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:10:46.115 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:10:46.115 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:14:10.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:29:53.802 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:29:53.802 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:32:47.623 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:48:11.323 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:48:11.337 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:51:05.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:06:47.224 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:06:47.225 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:09:11.038 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:11:48.125 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:11:48.125 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:14:41.946 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:30:52.082 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:30:52.083 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:33:45.915 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:48:42.862 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:48:42.863 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:50:06.680 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:05:13.909 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:05:13.910 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:07:03.821 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:12:52.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:12:52.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:14:16.473 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:28:58.633 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:28:58.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:31:52.455 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:46:37.006 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:46:37.006 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:48:30.827 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:04:08.002 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:04:08.002 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:07:31.819 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:22:11.130 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:22:11.130 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:23:34.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:38:13.060 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:38:13.061 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:41:06.922 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:55:36.437 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:55:36.437 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:00:30.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:17:10.759 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:17:10.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:20:34.575 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:34:59.122 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:34:59.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:36:22.952 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:39:27.290 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:39:27.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:42:21.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:57:10.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:57:10.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:00:34.957 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:14:25.756 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:14:25.756 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:17:49.330 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:32:01.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:32:01.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:35:47.691 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:51:25.480 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:51:25.480 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:54:19.304 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:10:01.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:10:01.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 22:13:31.464 ServerApp] WebSocket ping timeout after 119996 ms. +[I 2025-06-17 22:13:32.810 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:28:16.189 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:28:16.189 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:31:40.010 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:46:34.430 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:46:34.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:49:28.248 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:05:33.749 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:05:33.749 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:08:27.570 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:23:42.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:23:42.511 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:27:06.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:43:49.369 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:43:49.369 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:46:13.193 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:01:01.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:01:01.208 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:04:25.048 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:19:14.357 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:19:14.357 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:20:38.178 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:35:39.417 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:35:39.417 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:38:33.245 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:53:02.714 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:53:02.714 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:54:26.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:08:48.766 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:08:48.767 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:11:42.590 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:26:30.478 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:26:30.478 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:28:54.296 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:43:29.586 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:43:29.586 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:46:23.408 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:01:16.698 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:01:16.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:04:10.534 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:20:07.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:20:07.761 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:23:46.422 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:37:53.406 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:37:53.407 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:40:47.235 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:56:38.841 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:56:38.842 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:59:32.673 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:14:14.671 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:14:14.671 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:19:08.501 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:34:09.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:34:09.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:37:02.866 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:52:38.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:52:38.974 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:55:32.790 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:02:28.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:02:28.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:05:22.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:14:41.876 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:14:41.876 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:17:35.697 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:33:00.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:33:00.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:36:24.087 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:50:50.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:50:50.537 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:57:14.724 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:13:13.431 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:13:13.432 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:16:07.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:30:49.257 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:30:49.257 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:33:43.083 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:48:21.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:48:21.487 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:51:29.733 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:06:48.054 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:06:48.055 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:09:41.902 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:25:56.855 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:25:56.856 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:31:20.691 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:46:30.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:46:30.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:49:54.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:05:37.502 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:05:37.503 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:10:31.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:25:04.451 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:25:04.451 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:27:58.274 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:42:42.275 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:42:42.276 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:45:36.115 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:54:47.248 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:54:47.249 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:57:41.112 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:12:13.194 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:12:13.195 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:15:07.014 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:31:42.296 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:31:42.297 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:37:06.122 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:51:28.698 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:51:28.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:54:22.540 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:09:45.442 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:09:45.442 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:12:39.270 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:27:28.725 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:27:28.725 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:30:22.570 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:44:55.052 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:44:55.052 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:24:01.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:24:01.671 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:24:01.672 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:25:55.487 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:28:02.262 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:28:02.263 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:38:45.593 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:38:45.609 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:38:45.609 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:40:39.424 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:52:43.850 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:52:43.851 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:02:16.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:02:16.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:02:16.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:04:10.116 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:18:45.159 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:18:45.160 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:20:08.983 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:34:47.295 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:34:47.296 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:37:11.111 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:52:14.277 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:52:14.277 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:53:38.096 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:09:03.283 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 13:09:03.283 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:10:57.103 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:26:47.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 13:26:47.465 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:34:56.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:34:56.825 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 15:34:56.825 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:36:50.641 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:51:32.138 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 15:51:32.139 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:12:18.357 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:12:18.385 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 17:12:18.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:51:55.611 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:51:55.634 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 17:51:55.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:53:49.452 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:08:16.181 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:08:16.182 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:09:39.998 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:25:58.237 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:25:58.238 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:27:22.076 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:44:01.016 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:44:01.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-18 18:45:31.016 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-18 18:45:36.017 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:00:34.448 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:00:34.452 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:03:58.284 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:18:36.520 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:18:36.521 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:20:00.333 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:35:31.534 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:35:31.535 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:38:25.344 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:52:58.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:52:58.512 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:59:52.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:15:51.015 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 20:15:51.015 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:19:51.462 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:34:57.213 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 20:34:57.213 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:43:56.745 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:00:00.867 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:00:00.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:19:24.743 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:34:19.429 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:34:19.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:35:43.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:51:17.116 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:51:17.117 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:58:14.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:13:57.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:13:57.972 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:16:51.795 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:31:17.948 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:31:17.948 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:36:41.772 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:51:44.126 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:51:44.127 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:13:16.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:27:46.384 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 23:27:46.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:33:14.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:48:21.926 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 23:48:21.927 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:53:15.757 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:07:42.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:07:42.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 00:09:12.879 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-19 00:09:17.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:24:42.087 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:24:42.087 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:28:05.912 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:43:03.479 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:43:03.480 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:50:27.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:06:07.734 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:06:07.739 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:19:01.566 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:34:01.011 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:34:01.011 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:37:24.841 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:50:26.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:50:26.548 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:55:25.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:10:12.358 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:10:12.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:17:06.191 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:34:06.599 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:34:06.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:37:00.592 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:52:00.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:52:00.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 02:55:30.963 ServerApp] WebSocket ping timeout after 119986 ms. +[I 2025-06-19 02:55:35.964 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:10:21.171 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:10:21.171 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:19:44.990 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:34:56.229 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:34:56.229 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:37:50.052 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:38:44.066 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:38:44.066 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:41:38.225 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:56:36.851 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:56:36.851 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 04:00:06.852 ServerApp] WebSocket ping timeout after 119899 ms. +[I 2025-06-19 04:00:11.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:15:15.835 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:15:15.836 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:18:39.684 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:33:53.977 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:33:53.978 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:39:58.304 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:54:43.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:54:43.549 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:01:37.383 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:17:55.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:17:55.406 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:32:49.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:39:49.658 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:39:49.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:42:43.508 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:57:40.403 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:57:40.403 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:00:34.221 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:15:37.273 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:15:37.274 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:18:01.095 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:32:56.222 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:32:56.223 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:34:50.035 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:40:51.346 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:40:51.346 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:43:45.166 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:58:08.634 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:58:08.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:01:02.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:15:38.502 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 07:15:38.503 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:26:32.332 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:41:46.942 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 07:41:46.943 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:44:40.759 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:00:05.121 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:00:05.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:03:16.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:18:42.991 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:18:42.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:20:06.804 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:23:58.970 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:23:58.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:26:52.788 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:41:29.977 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:41:29.978 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:50:23.835 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:05:22.134 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:05:22.135 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:08:15.954 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:24:50.010 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:24:50.010 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:27:43.851 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:42:36.974 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:42:36.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 09:46:06.975 ServerApp] WebSocket ping timeout after 119914 ms. +[I 2025-06-19 09:46:07.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:51:44.943 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:51:44.943 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:52:24.522 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:52:24.532 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:52:24.532 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 11:59:53.761 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 11:59:53.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 11:59:53.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:01:47.600 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:17:20.450 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:17:20.451 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:21:14.274 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:35:45.035 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:35:45.036 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:37:08.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:52:45.827 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:52:45.827 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 13:39:02.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 13:54:21.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 13:54:21.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-24 18:25:47.453 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-24 18:25:47.574 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-24 18:25:47.575 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-25 12:30:17.576 ServerApp] WebSocket ping timeout after 1829994 ms. +[I 2025-06-25 12:30:22.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 13:22:31.091 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-25 13:22:31.091 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-25 13:47:01.090 ServerApp] WebSocket ping timeout after 1079993 ms. +[I 2025-06-25 13:47:06.090 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 14:12:47.395 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-25 14:12:47.396 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 17:45:11.236 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +Task exception was never retrieved +future: .wrapper() done, defined at /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py:1086> exception=WebSocketClosedError()> +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1088, in wrapper + await fut +tornado.iostream.StreamClosedError: Stream is closed + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1090, in wrapper + raise WebSocketClosedError() +tornado.websocket.WebSocketClosedError +Task exception was never retrieved +future: .wrapper() done, defined at /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py:1086> exception=WebSocketClosedError()> +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1088, in wrapper + await fut +tornado.iostream.StreamClosedError: Stream is closed + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1090, in wrapper + raise WebSocketClosedError() +tornado.websocket.WebSocketClosedError diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index d9c1ff53..597552a3 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -128,12 +128,11 @@ def def_calibration( }) def add_calibration( - self, name: str, parameters: List[str], instructions: List[Dict] + self, name: str, parameters: List[str] ) -> None: self.calibration_invokes.append({ "name": name, - "parameters": parameters, - "instructions": instructions + "parameters": parameters }) diff --git a/tensorcircuit/cloud/config.py b/tensorcircuit/cloud/config.py index 5ad31e81..ca8928a2 100644 --- a/tensorcircuit/cloud/config.py +++ b/tensorcircuit/cloud/config.py @@ -1 +1 @@ -tencent_base_url = "https://quantum.tencent.com/cloud/quk/" +tencent_base_url = "http://111.230.11.154/cloud/quk/" From 01ad8687a8416dad7f669892c1646ed86f3abd98 Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Tue, 15 Jul 2025 09:10:00 +0800 Subject: [PATCH 127/139] Create README.mk --- experiments/README.mk | 129 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 experiments/README.mk diff --git a/experiments/README.mk b/experiments/README.mk new file mode 100644 index 00000000..7e28e08c --- /dev/null +++ b/experiments/README.mk @@ -0,0 +1,129 @@ +# 在 Tensorcircuit 中使用参数化波形完成 Rabi 实验 + +## 下载安装 +``` +git clone https://github.com/ruan-prog/tensorcircuit.git +cd tensorcircuit +git checkout rabi_test + +cd experiments +pip install -r requirements.txt +``` + +## 代码实现 + +在 rabi.py 文件中修改代码 +``` +vim rabi.py +``` + +#### 1. 配置量子云服务 + +```python +set_token("your_api_token") # 需替换为真实的量子云服务令牌 +``` + +#### 2. 自定义参数化波形 + + +```python +def gen_parametric_waveform_circuit(t): + """ + 参数: + t : 脉冲持续时间(dt) + + 返回: + Circuit: 包含自定义波形的量子电路 + """ + qc = Circuit(1) + + param0 = Param("a") + + builder = qc.calibrate("rabi_test", [param0]) + builder.new_frame("drive_frame", param0) + builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + qc.add_calibration('rabi_test', ['q[0]']) + + tqasm_code = qc.to_tqasm() + + print(tqasm_code) + return qc +``` + + +#### 3. 在量子设备中执行电路 + +通过以下输出获取可用的设备名称 +```python +ds = list_devices() +``` + +在其中一台设备上执行电路 +```python +def run_circuit(qc): + """ + 参数: + qc (Circuit): 待执行量子电路 + + 返回: + rf(Dict): 测量结果统计 + """ + device_name = "tianji_m2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + return rf +``` + +#### 4. Rabi 参数扫描 + +定义扫描周期,遍历不同的脉冲长度 +```python +def exp_rabi(): + result_lst = [] + for t in range(1, 400, 2): + qc = gen_parametric_waveform_circuit(t) + result = run_circuit(qc) + result['duration'] = t + result_lst.append(result) + return result_lst +``` + +#### 5. 绘制 Rabi 结果图 + +绘制 0/1 态的结果分布 +```python +def draw_rabi(result_lst): + data = { + 'duration': [], + '0': [], + '1': [] + } + + for result in result_lst: + data['0'].append(int(result['0']) / shots_const) + data['1'].append(int(result['1']) / shots_const) + data['duration'].append(result['duration']) + + plt.figure(figsize=(10,6)) + plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') + plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + plt.title('Rabi Oscillation Experiment') + plt.xlabel('Duration (dt)') + plt.ylabel('Probability') + plt.grid(alpha=0.3) + plt.legend() + plt.tight_layout() + + plt.savefig('rabi.png', dpi=300) + plt.show() +``` From 5dcf1286d20d3051fafa370cd4284ea79f7f50f5 Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Tue, 15 Jul 2025 09:10:32 +0800 Subject: [PATCH 128/139] Rename README.mk to README.md --- experiments/{README.mk => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename experiments/{README.mk => README.md} (100%) diff --git a/experiments/README.mk b/experiments/README.md similarity index 100% rename from experiments/README.mk rename to experiments/README.md From ae25c78bed866a5b3b644344f1d92cc0a76041ef Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Tue, 15 Jul 2025 09:12:51 +0800 Subject: [PATCH 129/139] Update README.md --- experiments/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/experiments/README.md b/experiments/README.md index 7e28e08c..c22ec332 100644 --- a/experiments/README.md +++ b/experiments/README.md @@ -2,10 +2,8 @@ ## 下载安装 ``` -git clone https://github.com/ruan-prog/tensorcircuit.git +git clone https://github.com/tencent-quantum-lab/tensorcircuit.git cd tensorcircuit -git checkout rabi_test - cd experiments pip install -r requirements.txt ``` From f8fc17b464467520edb020f35f04769e7d132bfc Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Tue, 15 Jul 2025 09:13:38 +0800 Subject: [PATCH 130/139] Create requirements.txt --- experiments/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 experiments/requirements.txt diff --git a/experiments/requirements.txt b/experiments/requirements.txt new file mode 100644 index 00000000..7664be2d --- /dev/null +++ b/experiments/requirements.txt @@ -0,0 +1,2 @@ +matplotlib==3.8.2 +tensorcircuit==0.12.0 From 52dfa0f6e41d2d2d865d72fb1e74914f5b92da18 Mon Sep 17 00:00:00 2001 From: tencentqlab Date: Wed, 16 Jul 2025 11:07:26 +0800 Subject: [PATCH 131/139] Update config.py --- tensorcircuit/cloud/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorcircuit/cloud/config.py b/tensorcircuit/cloud/config.py index ca8928a2..5ad31e81 100644 --- a/tensorcircuit/cloud/config.py +++ b/tensorcircuit/cloud/config.py @@ -1 +1 @@ -tencent_base_url = "http://111.230.11.154/cloud/quk/" +tencent_base_url = "https://quantum.tencent.com/cloud/quk/" From fecb2498a5269ad27e46e614ddbbf51cc81f622d Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Thu, 28 Aug 2025 16:55:39 +0800 Subject: [PATCH 132/139] add to_tqasm test --- tests/01_test_gate.py | 49 ++++++++++++++++++++ tests/02_test_param_pulse.py | 59 ++++++++++++++++++++++++ tests/03_test_gate_pulse_mix.py | 60 ++++++++++++++++++++++++ tests/04_test_custom_chip.py | 82 +++++++++++++++++++++++++++++++++ tests/05_test_multi_measure.py | 60 ++++++++++++++++++++++++ 5 files changed, 310 insertions(+) create mode 100644 tests/01_test_gate.py create mode 100644 tests/02_test_param_pulse.py create mode 100644 tests/03_test_gate_pulse_mix.py create mode 100644 tests/04_test_custom_chip.py create mode 100644 tests/05_test_multi_measure.py diff --git a/tests/01_test_gate.py b/tests/01_test_gate.py new file mode 100644 index 00000000..0ba2cfda --- /dev/null +++ b/tests/01_test_gate.py @@ -0,0 +1,49 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_gate_circuit(t): + qc = Circuit(2) + qc.h(0) + qc.cnot(0, 1) + + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + print(rf) + +qc = gen_gate_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file diff --git a/tests/02_test_param_pulse.py b/tests/02_test_param_pulse.py new file mode 100644 index 00000000..cc212f1f --- /dev/null +++ b/tests/02_test_param_pulse.py @@ -0,0 +1,59 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_parametric_waveform_circuit(t): + qc = Circuit(2) + + param0 = Param("a") + +# 需根据以下定义的方式,修改代码 + builder = qc.calibrate("basic_pulse", [param0]) + frame = builder.new_frame("drive_frame", param0) + builder.play(frame, waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + + qc.add_calibration(builder, [0]) + + # print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + print(rf) + +qc = gen_parametric_waveform_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file diff --git a/tests/03_test_gate_pulse_mix.py b/tests/03_test_gate_pulse_mix.py new file mode 100644 index 00000000..c7568fea --- /dev/null +++ b/tests/03_test_gate_pulse_mix.py @@ -0,0 +1,60 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_gate_pulse_mix_circuit(t): + qc = Circuit(2) + + param0 = Param("a") + + builder = qc.calibrate("basic_pulse", [param0]) + frame = builder.new_frame("drive_frame", param0) + builder.play(frame, waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + + qc.add_calibration(builder, [0]) + + qc.i(0) + qc.x(0) + + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + print(rf) + +qc = gen_gate_pulse_mix_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py new file mode 100644 index 00000000..87aa398a --- /dev/null +++ b/tests/04_test_custom_chip.py @@ -0,0 +1,82 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + +def gen_custom_chip_circuit(t): + qc = Circuit(2) + +# 需添加 MapQubits(user_addr, chip_addr),对应 #pragram的qubits.mapping +# 需添加 GridQubit(left_user_addr, right_user_addr),对应 #pragram的qubits.coupling + +# 以下是两种映射方式 + qc.map_qubits([4,9,8,14]) + qc.map_qubits([4,9,8,14], [3,2,1,0]) + + + qc.i(0) + qc.cnot(0) + + # print(qc.to_tqasm()) + return qc + + + +def gen_custom_chip_circuit(t): + qc = Circuit(2) + +# 需添加 MapQubit(user_addr, chip_addr),对应 #pragram的qubits.mapping +# 需添加 GridQubit(left_user_addr, right_user_addr),对应 #pragram的qubits.coupling + + + qc.MapQubit(0, 4) + qc.MapQubit(1, 9) + qc.MapQubit(2, 8) + qc.MapQubit(3, 14) + + qc.GridQubit(0, 1) + qc.GridQubit(0, 2) + qc.GridQubit(1, 3) + + qc.i(0) + qc.cnot(0) + + # print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + print(rf) + +qc = gen_gate_pulse_mix_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file diff --git a/tests/05_test_multi_measure.py b/tests/05_test_multi_measure.py new file mode 100644 index 00000000..989f891a --- /dev/null +++ b/tests/05_test_multi_measure.py @@ -0,0 +1,60 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_multi_measure_circuit(t): + qc = Circuit(6) + + qc.h(0) + qc.cnot(0, 1) + + # 参数门在 to_tqasm 中的转换丢失了参数 + # qc.rxx(0, 5, theta=1.04632) + +# 需添加测量指令 + qc.measure(0, 1) + qc.cz(0, 1) + qc.measure(0, 1) + + + # print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() # 需返回 multi_results + print(rf) + +qc = gen_multi_measure_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file From df229f47f90c1f025946b4be86038dc40152c20c Mon Sep 17 00:00:00 2001 From: walterxu Date: Tue, 2 Sep 2025 10:42:16 +0800 Subject: [PATCH 133/139] revise to cloud 3rd phase. --- tensorcircuit/circuit.py | 71 ++++++++++++++++------ tensorcircuit/cloud/abstraction.py | 51 ++++++++++++++++ tensorcircuit/cloud/tencent.py | 97 ++++++++++++++++++++++++++++-- tests/01_test_gate.py | 3 +- tests/02_test_param_pulse.py | 3 +- tests/03_test_gate_pulse_mix.py | 3 +- tests/04_test_custom_chip.py | 52 ++++++---------- tests/05_test_multi_measure.py | 4 +- 8 files changed, 222 insertions(+), 62 deletions(-) diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index 597552a3..f90dc404 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -128,23 +128,23 @@ def def_calibration( }) def add_calibration( - self, name: str, parameters: List[str] + self, builder: DefcalBuilder, parameters: List[str] ) -> None: self.calibration_invokes.append({ - "name": name, - "parameters": parameters + "name": builder.name, + "parameters": parameters, + "pos": len(self._qir) }) - def to_tqasm(self) -> str: + def to_tqasm(self, pragma: str) -> str: qasm_lines = [] + if pragma: + qasm_lines.append(pragma) + qasm_lines.append("TQASM 0.2;") - qasm_lines.append(f"QREG q[{self._nqubits}];") - for gate in self._qir: - gname = gate["name"] - targets = ", ".join(f"q[{i}]" for i in gate["target"]) - qasm_lines.append(f"{gname} {targets};") + qasm_lines.append(f"QREG q[{self._nqubits}];") for cal in getattr(self, "calibrations", []): pname = ", ".join(cal["parameters"]) @@ -158,12 +158,42 @@ def to_tqasm(self) -> str: qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") qasm_lines.append("}") + + # 先把 calibration_invokes 按 pos 分组,并保留同 pos 内的插入顺序 + from collections import defaultdict + cals_by_pos = defaultdict(list) for cal in getattr(self, "calibration_invokes", []): - pname = ", ".join(cal["parameters"]) - qasm_lines.append(f"\n {cal['name']} {pname};") + # pos 记录的是加入时的 len(self._qir) + pos = cal.get("pos", len(self._qir)) + cals_by_pos[pos].append(cal) + + # 交错输出:在第 i 个门之前输出所有 pos == i 的校准 + for i, gate in enumerate(self._qir): + for cal in cals_by_pos.get(i, []): + # print(cal) + pname = ", ".join(cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + # print(gate) + gname = gate["name"] + gname = gname.upper() + if gname == "CNOT": + gname = "CX" + targets = ", ".join(f"q[{idx}]" for idx in gate["index"]) + if (gname == "RX") or (gname == "RY") or (gname == "RZ"): + theta = gate["parameters"]["theta"] + qasm_lines.append(f"{gname} ({theta}) {targets};") + else: + qasm_lines.append(f"{gname} {targets};") + + # 收尾:把 pos == len(self._qir) 的校准放在最后 + for cal in cals_by_pos.get(len(self._qir), []): + # print(cal) + pname = ", ".join(cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + return ("\n".join(qasm_lines)) - return "\n".join(qasm_lines) - def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": return DefcalBuilder(self, name, parameters) @@ -1057,7 +1087,11 @@ def expectation( class Param: def __init__(self, name: str): self.name = name - + +class Frame: + def __init__(self, name: str): + self.name = name + class DefcalBuilder: def __init__(self, circuit, name: str, parameters: List["Param"]): self.circuit = circuit @@ -1066,14 +1100,15 @@ def __init__(self, circuit, name: str, parameters: List["Param"]): self.instructions = [] def new_frame(self, frame_name: str, param: "Param"): + frame = Frame(frame_name) self.instructions.append({ "type": "frame", - "frame": frame_name, + "frame": frame, "qubit": param.name, }) - return self + return frame - def play(self, frame_name: str, waveform: Any, start_time: int = None): + def play(self, frame: Frame, waveform: Any, start_time: int = None): if not hasattr(waveform, "__dataclass_fields__"): raise TypeError("Unsupported waveform type") @@ -1084,7 +1119,7 @@ def play(self, frame_name: str, waveform: Any, start_time: int = None): self.instructions.append({ "type": "play", - "frame": frame_name, + "frame": frame.name, "waveform_type": waveform_type, "args": args, }) diff --git a/tensorcircuit/cloud/abstraction.py b/tensorcircuit/cloud/abstraction.py index b94e2a69..10403e6f 100644 --- a/tensorcircuit/cloud/abstraction.py +++ b/tensorcircuit/cloud/abstraction.py @@ -380,6 +380,57 @@ def resubmit(self) -> "Task": from .apis import resubmit_task return resubmit_task(self) + + @partial(arg_alias, alias_dict={"format": ["format_"], "blocked": ["wait"]}) + def m_results( + self, + format: Optional[str] = None, + blocked: bool = True, + mitigated: bool = False, + calibriation_options: Optional[Dict[str, Any]] = None, + readout_mit: Optional[rem.ReadoutMit] = None, + mitigation_options: Optional[Dict[str, Any]] = None, + ) -> counts.ct: + """ + get task results of the qjob + + :param format: unsupported now, defaults to None, which is "count_dict_bin" + :type format: Optional[str], optional + :param blocked: whether blocked to wait until the result is returned, defaults to False, + which raise error when the task is unfinished + :type blocked: bool, optional + :param mitigated: whether enable readout error mitigation, defaults to False + :type mitigated: bool, optional + :param calibriation_options: option dict for ``ReadoutMit.cals_from_system``, + defaults to None + :type calibriation_options: Optional[Dict[str, Any]], optional + :param readout_mit: if given, directly use the calibriation info on ``readout_mit``, + defaults to None + :type readout_mit: Optional[rem.ReadoutMit], optional + :param mitigation_options: option dict for ``ReadoutMit.apply_correction``, defaults to None + :type mitigation_options: Optional[Dict[str, Any]], optional + :return: count dict results + :rtype: Any + """ + if not blocked: + s = self.state() + if s != "completed": + raise TaskUnfinished(self.id_, s) + r = self.details()["multi_results"] + r = counts.sort_count(r) # type: ignore + else: + s = self.state() + tries = 0 + while s != "completed": + if s in ["failed"]: + err = self.details().get("err", "") + raise TaskFailed(self.id_, s, err) + time.sleep(0.5 + tries / 10) + tries += 1 + s = self.state() + r = self.m_results(format=format, blocked=False, mitigated=False) + + return r # type: ignore @partial(arg_alias, alias_dict={"format": ["format_"], "blocked": ["wait"]}) def results( diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index 029e2486..e2428b3e 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -19,6 +19,84 @@ logger = logging.getLogger(__name__) +class Topology: + def __init__(self, device: Device) -> None: + topology = device.topology() + + self._qubits = list(set(num for row in topology for num in row)) + self._qubit_pairs = topology + + self._used_chip_qubits = [] + self._used_user_qubits = [] + self._used_user_pairs = [] + + def map_qubits(self, chip_addrs: Optional[List[int]], user_addrs: List[int] = None) -> None: + """ + Map chip address to user address, and remove other unused chip addresses. + """ + if user_addrs is None: + user_addrs = range(len(chip_addrs)) + if len(user_addrs) != len(chip_addrs): + raise ValueError("user_addrs and chip_addrs should have the same length") + for addr in chip_addrs: + if addr not in self._qubits: + raise ValueError(f"chip_addr {addr} not in the device") + + self._used_chip_qubits = chip_addrs + self._used_user_qubits = user_addrs + self._used_user_pairs = [e for e in self._qubit_pairs if e[0] in chip_addrs and e[1] in user_addrs] + + def map_qubit(self, chip_addr: int, user_addr: int) -> None: + if chip_addr not in self._qubits: + raise ValueError(f"chip_addr {chip_addr} not in the device") + try: + subscript = self._used_chip_qubits.index(chip_addr) + if self._used_user_qubits[subscript] != user_addr: + raise ValueError(f"chip_addr {chip_addr} is already mapped to user_addr {self._used_user_qubits[subscript]}") + except ValueError: # not found, so add it. + self._used_chip_qubits.append(chip_addr) + self._used_user_qubits.append(user_addr) + return + + def pair_qubit(self, user_addr1: int, user_addr2: int, dual: bool = True, add_remove: bool = True) -> None: + original_pair = (user_addr1, user_addr2) + + def update_pairs(user_addr1: int, user_addr2: int, add_remove: bool = True): + if add_remove: + if original_pair in getattr(self, "_used_user_pairs", []): + return + self._qubit_mapping = getattr(self, "_used_user_pairs", []) + [original_pair] + else: + try: + self._qubit_mapping = getattr(self, "_used_user_pairs", []) - [original_pair] + except ValueError: + raise ValueError(f"Qubit pair {user_addr1}-{user_addr2} does not exist to remove") + update_pairs(user_addr1, user_addr2, add_remove) + if dual: + update_pairs(user_addr2, user_addr1, add_remove) + return + + def pragmam(self) -> str: + lines = [] + if self._used_chip_qubits == [] or self._used_user_qubits == []: + return None + if len(self._used_user_pairs) == 0: + raise ValueError("No qubit pairs are defined, please use pair_qubit to define qubit pairs") + + pragma = "#pragma qubits.mapping [" + for c, u in zip(self._used_chip_qubits, self._used_user_qubits): + pragma += f"[{u}, {c}], " + pragma = pragma[:-2] + "]" + lines.append(pragma) + + pragma = "#pragma qubits.coupling []" + for u1, u2 in getattr(self, "_used_user_pairs", []): + pragma += f"[{u1}, {u2}], " + pragma = pragma[:-2] + "]" + lines.append(pragma) + + return "\n".join(lines) + def tencent_headers(token: Optional[str] = None) -> Dict[str, str]: if token is None: token = "ANY;0" @@ -133,6 +211,7 @@ def submit_task( enable_qos_gate_decomposition: bool = True, enable_qos_initial_mapping: bool = False, qos_dry_run: bool = False, + topology: Optional[Topology] = None, **kws: Any ) -> List[Task]: """ @@ -211,10 +290,14 @@ def c2qasm(c: Any, compiling: bool) -> str: else: if isinstance(c, QuantumCircuit): s = c.qasm() + lang = "OPENQASM" # nq = c.num_qubits else: - s = c.to_tqasm() - print(s) + prag = None + if topology is not None: + prag = topology.praggam() + s = c.to_tqasm(prag) + lang = "TQASM" #s = c.to_openqasm() # nq = c._nqubits # s = _free_pi(s) # tQuk translation now supports this @@ -227,13 +310,12 @@ def c2qasm(c: Any, compiling: bool) -> str: # slist.append("") # s = "\n".join(slist) s = _replace_rz_to_st(s) - return s # type: ignore + return s, lang # type: ignore if is_sequence(circuit): source = [c2qasm(c, compiling) for c in circuit] # type: ignore else: - source = c2qasm(circuit, compiling) - lang = "OPENQASM" + source, lang = c2qasm(circuit, compiling) if len(device.name.split("?")) > 1: device_str = device.name @@ -363,6 +445,10 @@ def get_task_details( r["task"]["results"] = r["task"]["result"]["counts"] else: r["task"]["results"] = r["task"]["result"] + if "multi_results" in r["task"]: + for i, res in enumerate(r["task"]["multi_results"]): + if "counts" in res: + r["task"]["multi_results"][i] = counts.sort_count(res["counts"]) if "optimization" in r["task"]: if ( "pairs" in r["task"]["optimization"] @@ -413,4 +499,5 @@ def get_task_details( '101': 135, '110': 128, '111': 131} + 'multi_results': [{'000': 123, '001': 126, ...}, {...}, ...] """ diff --git a/tests/01_test_gate.py b/tests/01_test_gate.py index 0ba2cfda..c196d07b 100644 --- a/tests/01_test_gate.py +++ b/tests/01_test_gate.py @@ -46,4 +46,5 @@ def run_circuit(qc): print(rf) qc = gen_gate_circuit(1.0) -result = run_circuit(qc) \ No newline at end of file +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/02_test_param_pulse.py b/tests/02_test_param_pulse.py index cc212f1f..15441fde 100644 --- a/tests/02_test_param_pulse.py +++ b/tests/02_test_param_pulse.py @@ -56,4 +56,5 @@ def run_circuit(qc): print(rf) qc = gen_parametric_waveform_circuit(1.0) -result = run_circuit(qc) \ No newline at end of file +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/03_test_gate_pulse_mix.py b/tests/03_test_gate_pulse_mix.py index c7568fea..a3887598 100644 --- a/tests/03_test_gate_pulse_mix.py +++ b/tests/03_test_gate_pulse_mix.py @@ -57,4 +57,5 @@ def run_circuit(qc): print(rf) qc = gen_gate_pulse_mix_circuit(1.0) -result = run_circuit(qc) \ No newline at end of file +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py index 87aa398a..c25584ba 100644 --- a/tests/04_test_custom_chip.py +++ b/tests/04_test_custom_chip.py @@ -7,7 +7,7 @@ sys.path.insert(0, module_path) from tensorcircuit import Circuit, Param, gates, waveforms -from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties, Topology import re # from dotenv import load_dotenv @@ -24,52 +24,34 @@ def gen_custom_chip_circuit(t): qc = Circuit(2) -# 需添加 MapQubits(user_addr, chip_addr),对应 #pragram的qubits.mapping -# 需添加 GridQubit(left_user_addr, right_user_addr),对应 #pragram的qubits.coupling - -# 以下是两种映射方式 - qc.map_qubits([4,9,8,14]) - qc.map_qubits([4,9,8,14], [3,2,1,0]) - - qc.i(0) qc.cnot(0) # print(qc.to_tqasm()) - return qc - - - -def gen_custom_chip_circuit(t): - qc = Circuit(2) - -# 需添加 MapQubit(user_addr, chip_addr),对应 #pragram的qubits.mapping -# 需添加 GridQubit(left_user_addr, right_user_addr),对应 #pragram的qubits.coupling - - - qc.MapQubit(0, 4) - qc.MapQubit(1, 9) - qc.MapQubit(2, 8) - qc.MapQubit(3, 14) - - qc.GridQubit(0, 1) - qc.GridQubit(0, 2) - qc.GridQubit(1, 3) - - qc.i(0) - qc.cnot(0) - - # print(qc.to_tqasm()) - return qc + return qc, tp def run_circuit(qc): device_name = "tianji_s2" d = get_device(device_name) +# 以下是两种映射方式 + tp = Topology(d) + tp.map_qubits([4,9,8,14]) + tp.map_qubits([4,9,8,14], [3,2,1,0]) + + tp.map_qubit(0, 4) + tp.map_qubit(1, 9) + tp.map_qubit(2, 8) + tp.map_qubit(3, 14) + + tp.pair_qubit(0, 1) + tp.pair_qubit(0, 2) + tp.pair_qubit(1, 3, False) t = submit_task( circuit=qc, shots=shots_const, device=d, + topology = tp, enable_qos_gate_decomposition=False, enable_qos_qubit_mapping=False, ) @@ -78,5 +60,5 @@ def run_circuit(qc): rf = t.results() print(rf) -qc = gen_gate_pulse_mix_circuit(1.0) +qc = gen_custom_chip_circuit(1.0) result = run_circuit(qc) \ No newline at end of file diff --git a/tests/05_test_multi_measure.py b/tests/05_test_multi_measure.py index 989f891a..6d760fc6 100644 --- a/tests/05_test_multi_measure.py +++ b/tests/05_test_multi_measure.py @@ -54,7 +54,9 @@ def run_circuit(qc): # print(qc.to_tqasm()) # n = qc._nqubits rf = t.results() # 需返回 multi_results + rf = t.m_results() # 需返回 multi_results print(rf) qc = gen_multi_measure_circuit(1.0) -result = run_circuit(qc) \ No newline at end of file +result = run_circuit(qc) +print(result) \ No newline at end of file From b0a1fc6cc044ce0f527747183f477cde2a7ef016 Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Tue, 2 Sep 2025 16:04:26 +0800 Subject: [PATCH 134/139] update --- tensorcircuit/circuit.py | 17 +++++++++-------- tensorcircuit/cloud/__init__.py | 1 + tensorcircuit/cloud/tencent.py | 7 +++++-- tests/01_test_gate.py | 5 ++++- tests/02_test_param_pulse.py | 12 ++++++++++-- tests/03_test_gate_pulse_mix.py | 2 +- tests/04_test_custom_chip.py | 24 +++++++++++++----------- 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index f90dc404..044541e4 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -128,7 +128,7 @@ def def_calibration( }) def add_calibration( - self, builder: DefcalBuilder, parameters: List[str] + self, builder: "DefcalBuilder", parameters: List[str] ) -> None: self.calibration_invokes.append({ "name": builder.name, @@ -137,21 +137,22 @@ def add_calibration( }) - def to_tqasm(self, pragma: str) -> str: + def to_tqasm(self, pragma: Optional[str]= None) -> str: qasm_lines = [] - if pragma: - qasm_lines.append(pragma) qasm_lines.append("TQASM 0.2;") + if pragma: + qasm_lines.append(pragma) + qasm_lines.append(f"QREG q[{self._nqubits}];") for cal in getattr(self, "calibrations", []): pname = ", ".join(cal["parameters"]) - qasm_lines.append(f"\ndefcal {cal['name']} {pname} {{") + qasm_lines.append(f"defcal {cal['name']} {pname} {{") for inst in cal["instructions"]: if inst["type"] == "frame": - qasm_lines.append(f" frame {inst['frame']} = newframe({inst['qubit']});") + qasm_lines.append(f" frame {inst['frame'].name} = newframe({inst['qubit']});") elif inst["type"] == "play": args_str = ", ".join(str(x) for x in inst["args"]) wf_type = inst["waveform_type"] @@ -171,7 +172,7 @@ def to_tqasm(self, pragma: str) -> str: for i, gate in enumerate(self._qir): for cal in cals_by_pos.get(i, []): # print(cal) - pname = ", ".join(cal.get("parameters", [])) + pname = ", ".join(f"q[{x}]" for x in cal.get("parameters", [])) qasm_lines.append(f"{cal['name']} {pname};") # print(gate) @@ -189,7 +190,7 @@ def to_tqasm(self, pragma: str) -> str: # 收尾:把 pos == len(self._qir) 的校准放在最后 for cal in cals_by_pos.get(len(self._qir), []): # print(cal) - pname = ", ".join(cal.get("parameters", [])) + pname = ", ".join(f"q[{x}]" for x in cal.get("parameters", [])) qasm_lines.append(f"{cal['name']} {pname};") return ("\n".join(qasm_lines)) diff --git a/tensorcircuit/cloud/__init__.py b/tensorcircuit/cloud/__init__.py index 56d5a724..eb14f9d6 100644 --- a/tensorcircuit/cloud/__init__.py +++ b/tensorcircuit/cloud/__init__.py @@ -3,3 +3,4 @@ from . import wrapper from .wrapper import batch_expectation_ps from .apis import submit_task +from .tencent import Topology diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index e2428b3e..a639b54b 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -40,6 +40,8 @@ def map_qubits(self, chip_addrs: Optional[List[int]], user_addrs: List[int] = No raise ValueError("user_addrs and chip_addrs should have the same length") for addr in chip_addrs: if addr not in self._qubits: + print(addr) + print(self._qubits) raise ValueError(f"chip_addr {addr} not in the device") self._used_chip_qubits = chip_addrs @@ -89,7 +91,7 @@ def pragmam(self) -> str: pragma = pragma[:-2] + "]" lines.append(pragma) - pragma = "#pragma qubits.coupling []" + pragma = "#pragma qubits.coupling [" for u1, u2 in getattr(self, "_used_user_pairs", []): pragma += f"[{u1}, {u2}], " pragma = pragma[:-2] + "]" @@ -295,8 +297,9 @@ def c2qasm(c: Any, compiling: bool) -> str: else: prag = None if topology is not None: - prag = topology.praggam() + prag = topology.pragmam() s = c.to_tqasm(prag) + print(s) lang = "TQASM" #s = c.to_openqasm() # nq = c._nqubits diff --git a/tests/01_test_gate.py b/tests/01_test_gate.py index c196d07b..76566aff 100644 --- a/tests/01_test_gate.py +++ b/tests/01_test_gate.py @@ -27,6 +27,8 @@ def gen_gate_circuit(t): qc.h(0) qc.cnot(0, 1) + print(qc.to_tqasm()) + return qc @@ -43,7 +45,8 @@ def run_circuit(qc): # print(qc.to_tqasm()) # n = qc._nqubits rf = t.results() - print(rf) + # print(rf) + return rf qc = gen_gate_circuit(1.0) result = run_circuit(qc) diff --git a/tests/02_test_param_pulse.py b/tests/02_test_param_pulse.py index 15441fde..5eabe93a 100644 --- a/tests/02_test_param_pulse.py +++ b/tests/02_test_param_pulse.py @@ -27,6 +27,13 @@ def gen_parametric_waveform_circuit(t): param0 = Param("a") + # builder = qc.calibrate("basic_pulse", [param0]) + # builder.new_frame("drive_frame", param0) + # builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + # builder.build() + # qc.add_calibration('basic_pulse', ['q[0]']) + # 需根据以下定义的方式,修改代码 builder = qc.calibrate("basic_pulse", [param0]) frame = builder.new_frame("drive_frame", param0) @@ -36,7 +43,7 @@ def gen_parametric_waveform_circuit(t): qc.add_calibration(builder, [0]) - # print(qc.to_tqasm()) + print(qc.to_tqasm()) return qc @@ -53,7 +60,8 @@ def run_circuit(qc): # print(qc.to_tqasm()) # n = qc._nqubits rf = t.results() - print(rf) + # print(rf) + return rf qc = gen_parametric_waveform_circuit(1.0) result = run_circuit(qc) diff --git a/tests/03_test_gate_pulse_mix.py b/tests/03_test_gate_pulse_mix.py index a3887598..00ce1f94 100644 --- a/tests/03_test_gate_pulse_mix.py +++ b/tests/03_test_gate_pulse_mix.py @@ -54,7 +54,7 @@ def run_circuit(qc): # print(qc.to_tqasm()) # n = qc._nqubits rf = t.results() - print(rf) + return rf qc = gen_gate_pulse_mix_circuit(1.0) result = run_circuit(qc) diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py index c25584ba..07692d61 100644 --- a/tests/04_test_custom_chip.py +++ b/tests/04_test_custom_chip.py @@ -7,7 +7,8 @@ sys.path.insert(0, module_path) from tensorcircuit import Circuit, Param, gates, waveforms -from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties, Topology +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +from tensorcircuit.cloud.tencent import Topology import re # from dotenv import load_dotenv @@ -24,11 +25,12 @@ def gen_custom_chip_circuit(t): qc = Circuit(2) - qc.i(0) - qc.cnot(0) + qc.cnot(0, 2) + # qc.cnot(1, 3) + # qc.cnot(0, 3) # print(qc.to_tqasm()) - return qc, tp + return qc def run_circuit(qc): @@ -36,17 +38,17 @@ def run_circuit(qc): d = get_device(device_name) # 以下是两种映射方式 tp = Topology(d) - tp.map_qubits([4,9,8,14]) - tp.map_qubits([4,9,8,14], [3,2,1,0]) + # tp.map_qubits([6,3,4,1]) + # tp.map_qubits([6,3,4,1], [3,2,1,0]) - tp.map_qubit(0, 4) - tp.map_qubit(1, 9) - tp.map_qubit(2, 8) - tp.map_qubit(3, 14) + tp.map_qubit(0, 6) + tp.map_qubit(1, 3) + tp.map_qubit(2, 4) + tp.map_qubit(3, 1) tp.pair_qubit(0, 1) tp.pair_qubit(0, 2) - tp.pair_qubit(1, 3, False) + tp.pair_qubit(1, 3) t = submit_task( circuit=qc, shots=shots_const, From f5e75c3818416ed910321a796ab2fdf91a4af511 Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Tue, 2 Sep 2025 16:59:14 +0800 Subject: [PATCH 135/139] update --- tensorcircuit/__init__.py | 3 +- tensorcircuit/circuit.py | 51 ++-------------------------------- tensorcircuit/cloud/tencent.py | 5 ++-- tensorcircuit/pulse.py | 50 +++++++++++++++++++++++++++++++++ tests/04_test_custom_chip.py | 3 +- 5 files changed, 58 insertions(+), 54 deletions(-) create mode 100644 tensorcircuit/pulse.py diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index 8092ec39..57646d0f 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -26,7 +26,8 @@ from . import basecircuit from . import waveforms from .gates import Gate -from .circuit import Circuit, expectation, Param +from .circuit import Circuit, expectation +from .pulse import Param from .mpscircuit import MPSCircuit from .densitymatrix import DMCircuit as DMCircuit_reference from .densitymatrix import DMCircuit2 diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index 044541e4..a389f7eb 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -17,6 +17,7 @@ from .quantum import QuOperator, identity from .simplify import _full_light_cone_cancel from .basecircuit import BaseCircuit +from .pulse import DefcalBuilder, Param, Frame Gate = gates.Gate Tensor = Any @@ -128,7 +129,7 @@ def def_calibration( }) def add_calibration( - self, builder: "DefcalBuilder", parameters: List[str] + self, builder: DefcalBuilder, parameters: List[str] ) -> None: self.calibration_invokes.append({ "name": builder.name, @@ -1084,51 +1085,3 @@ def expectation( else: den = 1.0 return num / den - -class Param: - def __init__(self, name: str): - self.name = name - -class Frame: - def __init__(self, name: str): - self.name = name - -class DefcalBuilder: - def __init__(self, circuit, name: str, parameters: List["Param"]): - self.circuit = circuit - self.name = name - self.parameters = parameters - self.instructions = [] - - def new_frame(self, frame_name: str, param: "Param"): - frame = Frame(frame_name) - self.instructions.append({ - "type": "frame", - "frame": frame, - "qubit": param.name, - }) - return frame - - def play(self, frame: Frame, waveform: Any, start_time: int = None): - if not hasattr(waveform, "__dataclass_fields__"): - raise TypeError("Unsupported waveform type") - - waveform_type = waveform.qasm_name() - args = waveform.to_args() - if start_time is not None: - args = [start_time] + args - - self.instructions.append({ - "type": "play", - "frame": frame.name, - "waveform_type": waveform_type, - "args": args, - }) - return self - - def build(self): - self.circuit.def_calibration( - name=self.name, - parameters=[p.name for p in self.parameters], - instructions=self.instructions, - ) diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index a639b54b..16419f18 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -78,7 +78,7 @@ def update_pairs(user_addr1: int, user_addr2: int, add_remove: bool = True): update_pairs(user_addr2, user_addr1, add_remove) return - def pragmam(self) -> str: + def pragma(self) -> str: lines = [] if self._used_chip_qubits == [] or self._used_user_qubits == []: return None @@ -297,9 +297,8 @@ def c2qasm(c: Any, compiling: bool) -> str: else: prag = None if topology is not None: - prag = topology.pragmam() + prag = topology.pragma() s = c.to_tqasm(prag) - print(s) lang = "TQASM" #s = c.to_openqasm() # nq = c._nqubits diff --git a/tensorcircuit/pulse.py b/tensorcircuit/pulse.py new file mode 100644 index 00000000..a09ddac6 --- /dev/null +++ b/tensorcircuit/pulse.py @@ -0,0 +1,50 @@ +from typing import List, Dict, Any + + +class Param: + def __init__(self, name: str): + self.name = name + +class Frame: + def __init__(self, name: str): + self.name = name + +class DefcalBuilder: + def __init__(self, circuit, name: str, parameters: List["Param"]): + self.circuit = circuit + self.name = name + self.parameters = parameters + self.instructions = [] + + def new_frame(self, frame_name: str, param: "Param"): + frame = Frame(frame_name) + self.instructions.append({ + "type": "frame", + "frame": frame, + "qubit": param.name, + }) + return frame + + def play(self, frame: Frame, waveform: Any, start_time: int = None): + if not hasattr(waveform, "__dataclass_fields__"): + raise TypeError("Unsupported waveform type") + + waveform_type = waveform.qasm_name() + args = waveform.to_args() + if start_time is not None: + args = [start_time] + args + + self.instructions.append({ + "type": "play", + "frame": frame.name, + "waveform_type": waveform_type, + "args": args, + }) + return self + + def build(self): + self.circuit.def_calibration( + name=self.name, + parameters=[p.name for p in self.parameters], + instructions=self.instructions, + ) diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py index 07692d61..be431e2b 100644 --- a/tests/04_test_custom_chip.py +++ b/tests/04_test_custom_chip.py @@ -23,8 +23,9 @@ print(ds) def gen_custom_chip_circuit(t): - qc = Circuit(2) + qc = Circuit(3) + # qc.h(0) qc.cnot(0, 2) # qc.cnot(1, 3) # qc.cnot(0, 3) From 20323966222b8551ceecc1dfcbd8b5df4dc6a2ef Mon Sep 17 00:00:00 2001 From: v_anyuhe Date: Tue, 2 Sep 2025 17:02:12 +0800 Subject: [PATCH 136/139] upadte --- tensorcircuit/cloud/tencent.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index 16419f18..c89514d0 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -40,8 +40,6 @@ def map_qubits(self, chip_addrs: Optional[List[int]], user_addrs: List[int] = No raise ValueError("user_addrs and chip_addrs should have the same length") for addr in chip_addrs: if addr not in self._qubits: - print(addr) - print(self._qubits) raise ValueError(f"chip_addr {addr} not in the device") self._used_chip_qubits = chip_addrs From 93d23b899d9a299c7a0e7838b35388518e7fdbac Mon Sep 17 00:00:00 2001 From: walterxu Date: Tue, 2 Sep 2025 17:18:25 +0800 Subject: [PATCH 137/139] revise some bugs. --- tensorcircuit/cloud/tencent.py | 10 +- tests/04_test_custom_chip.py | 18 +- tests/circuit.py | 1129 ++++++++++++++++++++++++++++++++ 3 files changed, 1144 insertions(+), 13 deletions(-) create mode 100644 tests/circuit.py diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index c89514d0..9fc8bd02 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -44,7 +44,8 @@ def map_qubits(self, chip_addrs: Optional[List[int]], user_addrs: List[int] = No self._used_chip_qubits = chip_addrs self._used_user_qubits = user_addrs - self._used_user_pairs = [e for e in self._qubit_pairs if e[0] in chip_addrs and e[1] in user_addrs] + inherited_pairs = [e for e in self._qubit_pairs if e[0] in chip_addrs and e[1] in chip_addrs] + self._used_user_pairs = [(user_addrs[chip_addrs.index(e[0])], user_addrs[chip_addrs.index(e[1])]) for e in inherited_pairs] def map_qubit(self, chip_addr: int, user_addr: int) -> None: if chip_addr not in self._qubits: @@ -59,16 +60,15 @@ def map_qubit(self, chip_addr: int, user_addr: int) -> None: return def pair_qubit(self, user_addr1: int, user_addr2: int, dual: bool = True, add_remove: bool = True) -> None: - original_pair = (user_addr1, user_addr2) - def update_pairs(user_addr1: int, user_addr2: int, add_remove: bool = True): + original_pair = (user_addr1, user_addr2) if add_remove: if original_pair in getattr(self, "_used_user_pairs", []): return - self._qubit_mapping = getattr(self, "_used_user_pairs", []) + [original_pair] + self._used_user_pairs = getattr(self, "_used_user_pairs", []) + [original_pair] else: try: - self._qubit_mapping = getattr(self, "_used_user_pairs", []) - [original_pair] + self._used_user_pairs = getattr(self, "_used_user_pairs", []) - [original_pair] except ValueError: raise ValueError(f"Qubit pair {user_addr1}-{user_addr2} does not exist to remove") update_pairs(user_addr1, user_addr2, add_remove) diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py index be431e2b..aba58e2a 100644 --- a/tests/04_test_custom_chip.py +++ b/tests/04_test_custom_chip.py @@ -40,16 +40,18 @@ def run_circuit(qc): # 以下是两种映射方式 tp = Topology(d) # tp.map_qubits([6,3,4,1]) - # tp.map_qubits([6,3,4,1], [3,2,1,0]) + tp.map_qubits([6,3,4,1], [3,2,1,0]) - tp.map_qubit(0, 6) - tp.map_qubit(1, 3) - tp.map_qubit(2, 4) - tp.map_qubit(3, 1) + # tp.map_qubit(6, 0) + # tp.map_qubit(3, 1) + # tp.map_qubit(4, 2) + # tp.map_qubit(1, 3) - tp.pair_qubit(0, 1) - tp.pair_qubit(0, 2) - tp.pair_qubit(1, 3) + # tp.pair_qubit(0, 1) + # tp.pair_qubit(0, 2) + # tp.pair_qubit(1, 3) + pragma = tp.pragma() + print(qc.to_tqasm(pragma=pragma)) t = submit_task( circuit=qc, shots=shots_const, diff --git a/tests/circuit.py b/tests/circuit.py new file mode 100644 index 00000000..8c393b7e --- /dev/null +++ b/tests/circuit.py @@ -0,0 +1,1129 @@ +""" +Quantum circuit: the state simulator +""" + +# pylint: disable=invalid-name + +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple +from functools import reduce +from operator import add + +import numpy as np +import tensornetwork as tn +import quantum_compiler + +from . import gates +from . import channels +from .cons import backend, contractor, dtypestr, npdtype +from .quantum import QuOperator, identity +from .simplify import _full_light_cone_cancel +from .basecircuit import BaseCircuit + +Gate = gates.Gate +Tensor = Any + + +class Circuit(BaseCircuit): + """ + ``Circuit`` class. + Simple usage demo below. + + .. code-block:: python + + c = tc.Circuit(3) + c.H(1) + c.CNOT(0, 1) + c.RX(2, theta=tc.num_to_tensor(1.)) + c.expectation([tc.gates.z(), (2, )]) # 0.54 + + """ + + is_dm = False + + def __init__( + self, + nqubits: int, + inputs: Optional[Tensor] = None, + mps_inputs: Optional[QuOperator] = None, + split: Optional[Dict[str, Any]] = None, + ) -> None: + """ + Circuit object based on state simulator. + + :param nqubits: The number of qubits in the circuit. + :type nqubits: int + :param inputs: If not None, the initial state of the circuit is taken as ``inputs`` + instead of :math:`\\vert 0\\rangle^n` qubits, defaults to None. + :type inputs: Optional[Tensor], optional + :param mps_inputs: QuVector for a MPS like initial wavefunction. + :type mps_inputs: Optional[QuOperator] + :param split: dict if two qubit gate is ready for split, including parameters for at least one of + ``max_singular_values`` and ``max_truncation_err``. + :type split: Optional[Dict[str, Any]] + """ + super().__init__( + nqubits=nqubits, inputs=inputs, mps_inputs=mps_inputs, split=split + ) + self.calibrations = [] + self.calibration_invokes = [] + + self.inputs = inputs + self.mps_inputs = mps_inputs + self.split = split + self._nqubits = nqubits + + self.circuit_param = { + "nqubits": nqubits, + "inputs": inputs, + "mps_inputs": mps_inputs, + "split": split, + } + if (inputs is None) and (mps_inputs is None): + nodes = self.all_zero_nodes(nqubits) + self._front = [n.get_edge(0) for n in nodes] + elif inputs is not None: # provide input function + inputs = backend.convert_to_tensor(inputs) + inputs = backend.cast(inputs, dtype=dtypestr) + inputs = backend.reshape(inputs, [-1]) + N = inputs.shape[0] + n = int(np.log(N) / np.log(2)) + assert n == nqubits or n == 2 * nqubits + inputs = backend.reshape(inputs, [2 for _ in range(n)]) + inputs = Gate(inputs) + nodes = [inputs] + self._front = [inputs.get_edge(i) for i in range(n)] + else: # mps_inputs is not None + mps_nodes = list(mps_inputs.nodes) # type: ignore + for i, n in enumerate(mps_nodes): + mps_nodes[i].tensor = backend.cast(n.tensor, dtypestr) # type: ignore + mps_edges = mps_inputs.out_edges + mps_inputs.in_edges # type: ignore + ndict, edict = tn.copy(mps_nodes) + new_nodes = [] + for n in mps_nodes: + new_nodes.append(ndict[n]) + new_front = [] + for e in mps_edges: + new_front.append(edict[e]) + nodes = new_nodes + self._front = new_front + + self.coloring_nodes(nodes) + self._nodes = nodes + + self._start_index = len(nodes) + # self._start = nodes + # self._meta_apply() + + # self._qcode = "" # deprecated + # self._qcode += str(self._nqubits) + "\n" + self._qir: List[Dict[str, Any]] = [] + self._extra_qir: List[Dict[str, Any]] = [] + self._mapping = True + + def def_calibration( + self, name: str, parameters: List[str], instructions: List[Dict] + ) -> None: + self.calibrations.append({ + "name": name, + "parameters": parameters, + "instructions": instructions + }) + + def add_calibration( + self, name: str, parameters: List[str] + ) -> None: + self.calibration_invokes.append({ + "name": name, + "parameters": parameters, + "pos": len(self._qir) + }) + + + def to_tqasm(self) -> str: + qasm_lines = [] + qasm_lines.append("TQASM 0.2;") + + for cal in getattr(self, "calibrations", []): + pname = ", ".join(cal["parameters"]) + qasm_lines.append(f"\ndefcal {cal['name']} {pname} {{") + for inst in cal["instructions"]: + if inst["type"] == "frame": + qasm_lines.append(f" frame {inst['frame']} = newframe({inst['qubit']});") + elif inst["type"] == "play": + args_str = ", ".join(str(x) for x in inst["args"]) + wf_type = inst["waveform_type"] + qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") + qasm_lines.append("}") + + qasm_lines.append(f"QREG q[{self._nqubits}];") + + # 先把 calibration_invokes 按 pos 分组,并保留同 pos 内的插入顺序 + from collections import defaultdict + cals_by_pos = defaultdict(list) + for cal in getattr(self, "calibration_invokes", []): + # pos 记录的是加入时的 len(self._qir) + pos = cal.get("pos", len(self._qir)) + cals_by_pos[pos].append(cal) + + # 交错输出:在第 i 个门之前输出所有 pos == i 的校准 + for i, gate in enumerate(self._qir): + for cal in cals_by_pos.get(i, []): + # print(cal) + pname = ", ".join(cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + # print(gate) + gname = gate["name"] + gname = gname.upper() + if gname == "CNOT": + gname = "CX" + targets = ", ".join(f"q[{idx}]" for idx in gate["index"]) + if (gname == "RX") or (gname == "RY") or (gname == "RZ"): + theta = gate["parameters"]["theta"] + qasm_lines.append(f"{gname} ({theta}) {targets};") + else: + qasm_lines.append(f"{gname} {targets};") + + # 收尾:把 pos == len(self._qir) 的校准放在最后 + for cal in cals_by_pos.get(len(self._qir), []): + # print(cal) + pname = ", ".join(cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + print("\n".join(qasm_lines)) + # print(f"before processing : line = {len(qasm_lines)}") + + return quantum_compiler.process("\n".join(qasm_lines), self._mapping) + + def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": + return DefcalBuilder(self, name, parameters) + + def replace_mps_inputs(self, mps_inputs: QuOperator) -> None: + """ + Replace the input state in MPS representation while keep the circuit structure unchanged. + + :Example: + >>> c = tc.Circuit(2) + >>> c.X(0) + >>> + >>> c2 = tc.Circuit(2, mps_inputs=c.quvector()) + >>> c2.X(0) + >>> c2.wavefunction() + array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], dtype=complex64) + >>> + >>> c3 = tc.Circuit(2) + >>> c3.X(0) + >>> c3.replace_mps_inputs(c.quvector()) + >>> c3.wavefunction() + array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], dtype=complex64) + + :param mps_inputs: (Nodes, dangling Edges) for a MPS like initial wavefunction. + :type mps_inputs: Tuple[Sequence[Gate], Sequence[Edge]] + """ + mps_nodes = mps_inputs.nodes + mps_edges = mps_inputs.out_edges + mps_inputs.in_edges + ndict, edict = tn.copy(mps_nodes) + new_nodes = [] + for n in mps_nodes: + new_nodes.append(ndict[n]) + new_front = [] + for e in mps_edges: + new_front.append(edict[e]) + old = set(id(n) for n in self._nodes[: self._start_index]) + j = -1 + for n in self._nodes[: self._start_index]: + for e in n: + if e.is_dangling(): + j += 1 + self._front[j] = new_front[j] + else: + if (id(e.node1) in old) and (id(e.node2) in old): + pass + else: + j += 1 + if id(e.node2) == id(n): + other = (e.node1, e.axis1) + else: # id(e.node1) == id(n): + other = (e.node2, e.axis2) + e.disconnect() + new_front[j] ^ other[0][other[1]] + j += 1 + self._front += new_front[j:] + self.coloring_nodes(new_nodes) + self._nodes = new_nodes + self._nodes[self._start_index :] + self._start_index = len(new_nodes) + + # TODO(@refraction-ray): add noise support in IR + # TODO(@refraction-ray): unify mid measure to basecircuit + + def mid_measurement(self, index: int, keep: int = 0) -> Tensor: + """ + Middle measurement in z-basis on the circuit, note the wavefunction output is not normalized + with ``mid_measurement`` involved, one should normalize the state manually if needed. + This is a post-selection method as keep is provided as a prior. + + :param index: The index of qubit that the Z direction postselection applied on. + :type index: int + :param keep: 0 for spin up, 1 for spin down, defaults to be 0. + :type keep: int, optional + """ + # normalization not guaranteed + # assert keep in [0, 1] + if keep < 0.5: + gate = np.array( + [ + [1.0], + [0.0], + ], + dtype=npdtype, + ) + else: + gate = np.array( + [ + [0.0], + [1.0], + ], + dtype=npdtype, + ) + + mg1 = tn.Node(gate) + mg2 = tn.Node(gate) + # mg1.flag = "post-select" + # mg1.is_dagger = False + # mg1.id = id(mg1) + # mg2.flag = "post-select" + # mg2.is_dagger = False + # mg2.id = id(mg2) + self.coloring_nodes([mg1, mg2], flag="post-select") + mg1.get_edge(0) ^ self._front[index] + mg1.get_edge(1) ^ mg2.get_edge(1) + self._front[index] = mg2.get_edge(0) + self._nodes.append(mg1) + self._nodes.append(mg2) + r = backend.convert_to_tensor(keep) + r = backend.cast(r, "int32") + return r + + mid_measure = mid_measurement + post_select = mid_measurement + post_selection = mid_measurement + + def depolarizing2( + self, + index: int, + *, + px: float, + py: float, + pz: float, + status: Optional[float] = None, + ) -> float: + if status is None: + status = backend.implicit_randu()[0] + g = backend.cond( + status < px, + lambda: gates.x().tensor, # type: ignore + lambda: backend.cond( + status < px + py, # type: ignore + lambda: gates.y().tensor, # type: ignore + lambda: backend.cond( + status < px + py + pz, # type: ignore + lambda: gates.z().tensor, # type: ignore + lambda: gates.i().tensor, # type: ignore + ), + ), + ) + # after implementing this, I realized that plain if is enough here for jit + # the failure for previous implementation is because we use self.X(i) inside ``if``, + # which has list append and incur bug in tensorflow jit + # in terms of jax jit, the only choice is jax.lax.cond, since ``if tensor``` paradigm + # is not supported in jax jit at all. (``Concrete Tensor Error``) + self.any(index, unitary=g) # type: ignore + return 0.0 + # roughly benchmark shows that performance of two depolarizing in terms of + # building time and running time are similar + + # overwritten now, deprecated + def depolarizing_reference( + self, + index: int, + *, + px: float, + py: float, + pz: float, + status: Optional[float] = None, + ) -> Tensor: + """ + Apply depolarizing channel in a Monte Carlo way, + i.e. for each call of this method, one of gates from + X, Y, Z, I are applied on the circuit based on the probability + indicated by ``px``, ``py``, ``pz``. + + :param index: The qubit that depolarizing channel is on + :type index: int + :param px: probability for X noise + :type px: float + :param py: probability for Y noise + :type py: float + :param pz: probability for Z noise + :type pz: float + :param status: random seed uniformly from 0 to 1, defaults to None (generated implicitly) + :type status: Optional[float], optional + :return: int Tensor, the element lookup: [0: x, 1: y, 2: z, 3: I] + :rtype: Tensor + """ + + # px/y/z here not support differentiation for now + # jit compatible for now + # assert px + py + pz < 1 and px >= 0 and py >= 0 and pz >= 0 + + def step_function(x: Tensor) -> Tensor: + r = ( + backend.sign(x - px) + + backend.sign(x - px - py) + + backend.sign(x - px - py - pz) + ) + r = backend.cast(r / 2 + 1.5, dtype="int32") + # [0: x, 1: y, 2: z, 3: I] + + return r + + if status is None: + status = backend.implicit_randu()[0] + r = step_function(status) + rv = backend.onehot(r, 4) + rv = backend.cast(rv, dtype=dtypestr) + g = ( + rv[0] * gates.x().tensor # type: ignore + + rv[1] * gates.y().tensor # type: ignore + + rv[2] * gates.z().tensor # type: ignore + + rv[3] * gates.i().tensor # type: ignore + ) + self.any(index, unitary=g) # type: ignore + return r + + def unitary_kraus2( + self, + kraus: Sequence[Gate], + *index: int, + prob: Optional[Sequence[float]] = None, + status: Optional[float] = None, + name: Optional[str] = None, + ) -> Tensor: + # dont use, has issue conflicting with vmap, concurrent access lock emerged + # potential issue raised from switch + # general impl from Monte Carlo trajectory depolarizing above + # still jittable + # speed is similar to ``unitary_kraus`` + def index2gate2(r: Tensor, kraus: Sequence[Tensor]) -> Tensor: + # r is int type Tensor of shape [] + return backend.switch(r, [lambda _=k: _ for k in kraus]) # type: ignore + + return self._unitary_kraus_template( + kraus, + *index, + prob=prob, + status=status, + get_gate_from_index=index2gate2, + name=name, + ) + + def unitary_kraus( + self, + kraus: Sequence[Gate], + *index: int, + prob: Optional[Sequence[float]] = None, + status: Optional[float] = None, + name: Optional[str] = None, + ) -> Tensor: + """ + Apply unitary gates in ``kraus`` randomly based on corresponding ``prob``. + If ``prob`` is ``None``, this is reduced to kraus channel language. + + :param kraus: List of ``tc.gates.Gate`` or just Tensors + :type kraus: Sequence[Gate] + :param prob: prob list with the same size as ``kraus``, defaults to None + :type prob: Optional[Sequence[float]], optional + :param status: random seed between 0 to 1, defaults to None + :type status: Optional[float], optional + :return: shape [] int dtype tensor indicates which kraus gate is actually applied + :rtype: Tensor + """ + # general impl from Monte Carlo trajectory depolarizing above + # still jittable + + def index2gate(r: Tensor, kraus: Sequence[Tensor]) -> Tensor: + # r is int type Tensor of shape [] + l = len(kraus) + r = backend.onehot(r, l) + r = backend.cast(r, dtype=dtypestr) + return reduce(add, [r[i] * kraus[i] for i in range(l)]) + + return self._unitary_kraus_template( + kraus, + *index, + prob=prob, + status=status, + get_gate_from_index=index2gate, + name=name, + ) + + def _unitary_kraus_template( + self, + kraus: Sequence[Gate], + *index: int, + prob: Optional[Sequence[float]] = None, + status: Optional[float] = None, + get_gate_from_index: Optional[ + Callable[[Tensor, Sequence[Tensor]], Tensor] + ] = None, + name: Optional[str] = None, + ) -> Tensor: # DRY + sites = len(index) + kraus = [k.tensor if isinstance(k, tn.Node) else k for k in kraus] + kraus = [gates.array_to_tensor(k) for k in kraus] + kraus = [backend.reshapem(k) for k in kraus] + if prob is None: + prob = [ + backend.real(backend.trace(backend.adjoint(k) @ k) / k.shape[0]) + for k in kraus + ] + kraus = [ + k / backend.cast(backend.sqrt(p), dtypestr) for k, p in zip(kraus, prob) + ] + if not backend.is_tensor(prob): + prob = backend.convert_to_tensor(prob) + prob_cumsum = backend.cumsum(prob) + l = int(prob.shape[0]) # type: ignore + + def step_function(x: Tensor) -> Tensor: + if l == 1: + r = backend.convert_to_tensor(0.0) + else: + r = backend.sum( + backend.stack( + [backend.sign(x - prob_cumsum[i]) for i in range(l - 1)] + ) + ) + r = backend.cast(r / 2.0 + (l - 1) / 2.0, dtype="int32") + # [0: kraus[0], 1: kraus[1]...] + return r + + if status is None: + status = backend.implicit_randu()[0] + status = backend.convert_to_tensor(status) + status = backend.real(status) + prob_cumsum = backend.cast(prob_cumsum, dtype=status.dtype) # type: ignore + r = step_function(status) + if get_gate_from_index is None: + raise ValueError("no `get_gate_from_index` implementation is provided") + g = get_gate_from_index(r, kraus) + g = backend.reshape(g, [2 for _ in range(sites * 2)]) + self.any(*index, unitary=g, name=name) # type: ignore + return r + + def _general_kraus_tf( + self, + kraus: Sequence[Gate], + *index: int, + status: Optional[float] = None, + ) -> float: + # the graph building time is frustratingly slow, several minutes + # though running time is in terms of ms + sites = len(index) + kraus_tensor = [k.tensor for k in kraus] + kraus_tensor_f = [lambda _=k: _ for k in kraus_tensor] + # must return tensor instead of ``tn.Node`` for switch` + + def calculate_kraus_p(i: Tensor) -> Tensor: + # i: Tensor as int of shape [] + newnodes, newfront = self._copy() # TODO(@refraction-ray): support reuse? + # simply reuse=True is wrong, as the circuit is contracting at building + # self._copy seems slower than self._copy_state, but anyway the building time is unacceptable + lnewnodes, lnewfront = self._copy(conj=True) + kraus_i = backend.switch(i, kraus_tensor_f) + k = gates.Gate(kraus_i) + kc = gates.Gate(backend.conj(kraus_i)) + # begin connect + for ind, j in enumerate(index): + newfront[j] ^ k[ind + sites] + k[ind] ^ kc[ind] + kc[ind + sites] ^ lnewfront[j] + for j in range(self._nqubits): + if j not in index: + newfront[j] ^ lnewfront[j] + norm_square = contractor(newnodes + lnewnodes + [k, kc]).tensor + return backend.real(norm_square) + + if status is None: + status = backend.implicit_randu()[0] + + import tensorflow as tf # tf only implementation + + weight = 1.0 + fallback_weight = 0.0 + fallback_weight_i = 0 + len_kraus = len(kraus) + for i in tf.range(len_kraus): # breaks backend agnostic + # nested for and if, if tensor inner must come with for in tensor outer, s.t. autograph works + weight = calculate_kraus_p(i) + if weight > fallback_weight: + fallback_weight_i = i + fallback_weight = weight + status -= weight + if status < 0: + # concern here, correctness not sure in tf jit, fail anyway in jax jit + break + # placing a Tensor-dependent break, continue or return inside a Python loop + # https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/common_errors.md + + if ( + status >= 0 or weight == 0 + ): # the same concern, but this simple if is easy to convert to ``backend.cond`` + # Floating point error resulted in a malformed sample. + # Fall back to the most likely case. + # inspired from cirq implementation (Apcache 2). + weight = fallback_weight + i = fallback_weight_i + kraus_i = backend.switch(i, kraus_tensor_f) + newgate = kraus_i / backend.cast(backend.sqrt(weight), dtypestr) + self.any(*index, unitary=newgate) # type: ignore + return 0.0 + + def _general_kraus_2( + self, + kraus: Sequence[Gate], + *index: int, + status: Optional[float] = None, + with_prob: bool = False, + name: Optional[str] = None, + ) -> Tensor: + # the graph building time is frustratingly slow, several minutes + # though running time is in terms of ms + # raw running time in terms of s + # note jax gpu building time is fast, in the order of 10s.!! + # the typical scenario we are talking: 10 qubits, 3 layers of entangle gates and 3 layers of noise + # building for jax+GPU ~100s 12 qubit * 5 layers + # 370s 14 qubit * 7 layers, 0.35s running on vT4 + # vmap, grad, vvag are all fine for this function + # layerwise jit technique can greatly boost the staging time, see in /examples/mcnoise_boost.py + sites = len(index) + kraus_tensor = [k.tensor if isinstance(k, tn.Node) else k for k in kraus] + kraus_tensor = [gates.array_to_tensor(k) for k in kraus_tensor] + + # tn with hole + newnodes, newfront = self._copy() + lnewnodes, lnewfront = self._copy(conj=True) + des = [newfront[j] for j in index] + [lnewfront[j] for j in index] + for j in range(self._nqubits): + if j not in index: + newfront[j] ^ lnewfront[j] + ns = contractor(newnodes + lnewnodes, output_edge_order=des) + ntensor = ns.tensor + # ns, des + + def calculate_kraus_p(i: int) -> Tensor: + # i: Tensor as int of shape [] + # kraus_i = backend.switch(i, kraus_tensor_f) + kraus_i = kraus_tensor[i] + dm = gates.Gate(ntensor) + k = gates.Gate(kraus_i) + kc = gates.Gate(backend.conj(kraus_i)) + # begin connect + for ind in range(sites): + dm[ind] ^ k[ind + sites] + k[ind] ^ kc[ind] + kc[ind + sites] ^ dm[ind + sites] + norm_square = contractor([dm, k, kc]).tensor + return backend.real(norm_square) + + prob = [calculate_kraus_p(i) for i in range(len(kraus))] + eps = 1e-10 + new_kraus = [ + k / backend.cast(backend.sqrt(w) + eps, dtypestr) + for w, k in zip(prob, kraus_tensor) + ] + pick = self.unitary_kraus( + new_kraus, *index, prob=prob, status=status, name=name + ) + if with_prob is False: + return pick + else: + return pick, prob + + def general_kraus( + self, + kraus: Sequence[Gate], + *index: int, + status: Optional[float] = None, + with_prob: bool = False, + name: Optional[str] = None, + ) -> Tensor: + """ + Monte Carlo trajectory simulation of general Kraus channel whose Kraus operators cannot be + amplified to unitary operators. For unitary operators composed Kraus channel, :py:meth:`unitary_kraus` + is much faster. + + This function is jittable in theory. But only jax+GPU combination is recommended for jit + since the graph building time is too long for other backend options; though the running + time of the function is very fast for every case. + + :param kraus: A list of ``tn.Node`` for Kraus operators. + :type kraus: Sequence[Gate] + :param index: The qubits index that Kraus channel is applied on. + :type index: int + :param status: Random tensor uniformly between 0 or 1, defaults to be None, + when the random number will be generated automatically + :type status: Optional[float], optional + """ + return self._general_kraus_2( + kraus, *index, status=status, with_prob=with_prob, name=name + ) + + apply_general_kraus = general_kraus + + @staticmethod + def apply_general_kraus_delayed( + krausf: Callable[..., Sequence[Gate]], is_unitary: bool = False + ) -> Callable[..., None]: + def apply( + self: "Circuit", + *index: int, + status: Optional[float] = None, + name: Optional[str] = None, + **vars: float, + ) -> None: + kraus = krausf(**vars) + if not is_unitary: + self.apply_general_kraus(kraus, *index, status=status, name=name) + else: + self.unitary_kraus(kraus, *index, status=status, name=name) + + return apply + + @classmethod + def _meta_apply_channels(cls) -> None: + for k in channels.channels: + if k in ["depolarizing", "generaldepolarizing"]: + is_unitary = True + else: + is_unitary = False + setattr( + cls, + k, + cls.apply_general_kraus_delayed( + getattr(channels, k + "channel"), is_unitary=is_unitary + ), + ) + doc = """ + Apply %s quantum channel on the circuit. + See :py:meth:`tensorcircuit.channels.%schannel` + + :param index: Qubit number that the gate applies on. + :type index: int. + :param status: uniform external random number between 0 and 1 + :type status: Tensor + :param vars: Parameters for the channel. + :type vars: float. + """ % ( + k, + k, + ) + getattr(cls, k).__doc__ = doc + + def is_valid(self) -> bool: + """ + [WIP], check whether the circuit is legal. + + :return: The bool indicating whether the circuit is legal + :rtype: bool + """ + try: + assert len(self._front) == self._nqubits + for n in self._nodes: + for e in n.get_all_dangling(): + assert e in self._front + return True + except AssertionError: + return False + + def wavefunction(self, form: str = "default") -> tn.Node.tensor: + """ + Compute the output wavefunction from the circuit. + + :param form: The str indicating the form of the output wavefunction. + "default": [-1], "ket": [-1, 1], "bra": [1, -1] + :type form: str, optional + :return: Tensor with the corresponding shape. + :rtype: Tensor + """ + nodes, d_edges = self._copy() + t = contractor(nodes, output_edge_order=d_edges) + if form == "default": + shape = [-1] + elif form == "ket": + shape = [-1, 1] + elif form == "bra": # no conj here + shape = [1, -1] + return backend.reshape(t.tensor, shape=shape) + + state = wavefunction + + def get_quoperator(self) -> QuOperator: + """ + Get the ``QuOperator`` MPO like representation of the circuit unitary without contraction. + + :return: ``QuOperator`` object for the circuit unitary (open indices for the input state) + :rtype: QuOperator + """ + mps = identity([2 for _ in range(self._nqubits)]) + c = Circuit(self._nqubits) + ns, es = self._copy() + c._nodes = ns + c._front = es + c.replace_mps_inputs(mps) + return QuOperator(c._front[: self._nqubits], c._front[self._nqubits :]) + + quoperator = get_quoperator + # both are not good names, but for backward compatibility + + get_circuit_as_quoperator = get_quoperator + get_state_as_quvector = BaseCircuit.quvector + + def matrix(self) -> Tensor: + """ + Get the unitary matrix for the circuit irrespective with the circuit input state. + + :return: The circuit unitary matrix + :rtype: Tensor + """ + mps = identity([2 for _ in range(self._nqubits)]) + c = Circuit(self._nqubits) + ns, es = self._copy() + c._nodes = ns + c._front = es + c.replace_mps_inputs(mps) + return backend.reshapem(c.state()) + + def measure_reference( + self, *index: int, with_prob: bool = False + ) -> Tuple[str, float]: + """ + Take measurement on the given quantum lines by ``index``. + + :Example: + + >>> c = tc.Circuit(3) + >>> c.H(0) + >>> c.h(1) + >>> c.toffoli(0, 1, 2) + >>> c.measure(2) + ('1', -1.0) + >>> # Another possible output: ('0', -1.0) + >>> c.measure(2, with_prob=True) + ('1', (0.25000011920928955+0j)) + >>> # Another possible output: ('0', (0.7499998807907104+0j)) + + :param index: Measure on which quantum line. + :param with_prob: If true, theoretical probability is also returned. + :return: The sample output and probability (optional) of the quantum line. + :rtype: Tuple[str, float] + """ + # not jit compatible due to random number generations! + sample = "" + p = 1.0 + for j in index: + nodes1, edge1 = self._copy() + nodes2, edge2 = self._copy(conj=True) + for i, e in enumerate(edge1): + if i != j: + e ^ edge2[i] + for i in range(len(sample)): + if sample[i] == "0": + m = np.array([1, 0], dtype=npdtype) + else: + m = np.array([0, 1], dtype=npdtype) + nodes1.append(tn.Node(m)) + nodes1[-1].get_edge(0) ^ edge1[index[i]] + nodes2.append(tn.Node(m)) + nodes2[-1].get_edge(0) ^ edge2[index[i]] + nodes1.extend(nodes2) + rho = ( + 1 + / p + * contractor(nodes1, output_edge_order=[edge1[j], edge2[j]]).tensor + ) + pu = rho[0, 0] + r = backend.random_uniform([]) + r = backend.real(backend.cast(r, dtypestr)) + if r < backend.real(pu): + sample += "0" + p = p * pu + else: + sample += "1" + p = p * (1 - pu) + if with_prob: + return sample, p + else: + return sample, -1.0 + + # TODO(@refraction-ray): more _before function like state_before? and better API? + + def expectation( + self, + *ops: Tuple[tn.Node, List[int]], + reuse: bool = True, + enable_lightcone: bool = False, + noise_conf: Optional[Any] = None, + nmc: int = 1000, + status: Optional[Tensor] = None, + **kws: Any, + ) -> Tensor: + """ + Compute the expectation of corresponding operators. + + :Example: + + >>> c = tc.Circuit(2) + >>> c.H(0) + >>> c.expectation((tc.gates.z(), [0])) + array(0.+0.j, dtype=complex64) + + >>> c = tc.Circuit(2) + >>> c.cnot(0, 1) + >>> c.rx(0, theta=0.4) + >>> c.rx(1, theta=0.8) + >>> c.h(0) + >>> c.h(1) + >>> error1 = tc.channels.generaldepolarizingchannel(0.1, 1) + >>> error2 = tc.channels.generaldepolarizingchannel(0.06, 2) + >>> noise_conf = NoiseConf() + >>> noise_conf.add_noise("rx", error1) + >>> noise_conf.add_noise("cnot", [error2], [[0, 1]]) + >>> c.expectation((tc.gates.x(), [0]), noise_conf=noise_conf, nmc=10000) + (0.46274087-3.764033e-09j) + + :param ops: Operator and its position on the circuit, + eg. ``(tc.gates.z(), [1, ]), (tc.gates.x(), [2, ])`` is for operator :math:`Z_1X_2`. + :type ops: Tuple[tn.Node, List[int]] + :param reuse: If True, then the wavefunction tensor is cached for further expectation evaluation, + defaults to be true. + :type reuse: bool, optional + :param enable_lightcone: whether enable light cone simplification, defaults to False + :type enable_lightcone: bool, optional + :param noise_conf: Noise Configuration, defaults to None + :type noise_conf: Optional[NoiseConf], optional + :param nmc: repetition time for Monte Carlo sampling for noisfy calculation, defaults to 1000 + :type nmc: int, optional + :param status: external randomness given by tensor uniformly from [0, 1], defaults to None, + used for noisfy circuit sampling + :type status: Optional[Tensor], optional + :raises ValueError: "Cannot measure two operators in one index" + :return: Tensor with one element + :rtype: Tensor + """ + from .noisemodel import expectation_noisfy + + if noise_conf is None: + # if not reuse: + # nodes1, edge1 = self._copy() + # nodes2, edge2 = self._copy(conj=True) + # else: # reuse + + # self._nodes = nodes1 + if enable_lightcone: + reuse = False + nodes1 = self.expectation_before(*ops, reuse=reuse) + if enable_lightcone: + nodes1 = _full_light_cone_cancel(nodes1) + return contractor(nodes1).tensor + else: + return expectation_noisfy( + self, + *ops, + noise_conf=noise_conf, + nmc=nmc, + status=status, + **kws, + ) + + +Circuit._meta_apply() +Circuit._meta_apply_channels() + + +def expectation( + *ops: Tuple[tn.Node, List[int]], + ket: Tensor, + bra: Optional[Tensor] = None, + conj: bool = True, + normalization: bool = False, +) -> Tensor: + """ + Compute :math:`\\langle bra\\vert ops \\vert ket\\rangle`. + + Example 1 (:math:`bra` is same as :math:`ket`) + + >>> c = tc.Circuit(3) + >>> c.H(0) + >>> c.ry(1, theta=tc.num_to_tensor(0.8 + 0.7j)) + >>> c.cnot(1, 2) + >>> state = c.wavefunction() # the state of this circuit + >>> x1z2 = [(tc.gates.x(), [0]), (tc.gates.z(), [1])] # input qubits + >>> + >>> # Expection of this circuit / + >>> c.expectation(*x1z2) + array(0.69670665+0.j, dtype=complex64) + >>> tc.expectation(*x1z2, ket=state) + (0.6967066526412964+0j) + >>> + >>> # Normalize(expection of Circuit) / Normalize() + >>> c.expectation(*x1z2) / tc.backend.norm(state) ** 2 + (0.5550700389340034+0j) + >>> tc.expectation(*x1z2, ket=state, normalization=True) + (0.55507004+0j) + + Example 2 (:math:`bra` is different from :math:`ket`) + + >>> c = tc.Circuit(2) + >>> c.X(1) + >>> s1 = c.state() + >>> c2 = tc.Circuit(2) + >>> c2.X(0) + >>> s2 = c2.state() + >>> c3 = tc.Circuit(2) + >>> c3.H(1) + >>> s3 = c3.state() + >>> x1x2 = [(tc.gates.x(), [0]), (tc.gates.x(), [1])] + >>> + >>> tc.expectation(*x1x2, ket=s1, bra=s2) + (1+0j) + >>> tc.expectation(*x1x2, ket=s3, bra=s2) + (0.7071067690849304+0j) # 1/sqrt(2) + + :param ket: :math:`ket`. The state in tensor or ``QuVector`` format + :type ket: Tensor + :param bra: :math:`bra`, defaults to None, which is the same as ``ket``. + :type bra: Optional[Tensor], optional + :param conj: :math:`bra` changes to the adjoint matrix of :math:`bra`, defaults to True. + :type conj: bool, optional + :param normalization: Normalize the :math:`ket` and :math:`bra`, defaults to False. + :type normalization: bool, optional + :raises ValueError: "Cannot measure two operators in one index" + :return: The result of :math:`\\langle bra\\vert ops \\vert ket\\rangle`. + :rtype: Tensor + """ + if bra is None: + bra = ket + if isinstance(ket, QuOperator): + if conj is True: + bra = bra.adjoint() + # TODO(@refraction-ray) omit normalization arg for now + n = len(ket.out_edges) + occupied = set() + nodes = list(ket.nodes) + list(bra.nodes) + # TODO(@refraction-ray): is the order guaranteed or affect some types of contractor? + for op, index in ops: + if not isinstance(op, tn.Node): + # op is only a matrix + op = backend.reshape2(op) + op = gates.Gate(op) + if isinstance(index, int): + index = [index] + noe = len(index) + for j, e in enumerate(index): + if e in occupied: + raise ValueError("Cannot measure two operators in one index") + bra.in_edges[e] ^ op.get_edge(j) + ket.out_edges[e] ^ op.get_edge(j + noe) + occupied.add(e) + nodes.append(op) + for j in range(n): + if j not in occupied: # edge1[j].is_dangling invalid here! + ket.out_edges[j] ^ bra.in_edges[j] + # self._nodes = nodes1 + num = contractor(nodes).tensor + return num + + else: + # ket is the tensor + if conj is True: + bra = backend.conj(bra) + ket = backend.reshape(ket, [-1]) + ket = backend.reshape2(ket) + bra = backend.reshape2(bra) + n = len(backend.shape_tuple(ket)) + ket = Gate(ket) + bra = Gate(bra) + occupied = set() + nodes = [ket, bra] + if normalization is True: + normket = backend.norm(ket.tensor) + normbra = backend.norm(bra.tensor) + for op, index in ops: + if not isinstance(op, tn.Node): + # op is only a matrix + op = backend.reshape2(op) + op = gates.Gate(op) + if isinstance(index, int): + index = [index] + noe = len(index) + for j, e in enumerate(index): + if e in occupied: + raise ValueError("Cannot measure two operators in one index") + bra[e] ^ op.get_edge(j) + ket[e] ^ op.get_edge(j + noe) + occupied.add(e) + nodes.append(op) + for j in range(n): + if j not in occupied: # edge1[j].is_dangling invalid here! + ket[j] ^ bra[j] + # self._nodes = nodes1 + num = contractor(nodes).tensor + if normalization is True: + den = normket * normbra + else: + den = 1.0 + return num / den + +class Param: + def __init__(self, name: str): + self.name = name + +class DefcalBuilder: + def __init__(self, circuit, name: str, parameters: List["Param"]): + self.circuit = circuit + self.name = name + self.parameters = parameters + self.instructions = [] + + def new_frame(self, frame_name: str, param: "Param"): + self.instructions.append({ + "type": "frame", + "frame": frame_name, + "qubit": param.name, + }) + return self + + def play(self, frame_name: str, waveform: Any, start_time: int = None): + if not hasattr(waveform, "__dataclass_fields__"): + raise TypeError("Unsupported waveform type") + + waveform_type = waveform.qasm_name() + args = waveform.to_args() + if start_time is not None: + args = [start_time] + args + + self.instructions.append({ + "type": "play", + "frame": frame_name, + "waveform_type": waveform_type, + "args": args, + }) + return self + + def build(self): + self.circuit.def_calibration( + name=self.name, + parameters=[p.name for p in self.parameters], + instructions=self.instructions, + ) From 38a74c851b15ef4c85b0760c6f039e047b79bf65 Mon Sep 17 00:00:00 2001 From: walterxu Date: Tue, 2 Sep 2025 17:55:45 +0800 Subject: [PATCH 138/139] multi_measure. --- tensorcircuit/circuit.py | 23 + tests/05_test_multi_measure.py | 6 +- tests/circuit.py | 1129 -------------------------------- 3 files changed, 26 insertions(+), 1132 deletions(-) delete mode 100644 tests/circuit.py diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index a389f7eb..f510142f 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -66,6 +66,7 @@ def __init__( ) self.calibrations = [] self.calibration_invokes = [] + self.measz_invokes = [] self.inputs = inputs self.mps_inputs = mps_inputs @@ -136,6 +137,14 @@ def add_calibration( "parameters": parameters, "pos": len(self._qir) }) + + def measz(self, *index: int) -> None: + self.measz_invokes.append({ + "name": "measz", + "index": index, + "pos": len(self._qir) + }) + return def to_tqasm(self, pragma: Optional[str]= None) -> str: @@ -169,8 +178,18 @@ def to_tqasm(self, pragma: Optional[str]= None) -> str: pos = cal.get("pos", len(self._qir)) cals_by_pos[pos].append(cal) + measz_by_pos = defaultdict(list) + for m in getattr(self, "measz_invokes", []): + # pos 记录的是加入时的 len(self._qir) + pos = m.get("pos", len(self._qir)) + measz_by_pos[pos].append(m) + # 交错输出:在第 i 个门之前输出所有 pos == i 的校准 for i, gate in enumerate(self._qir): + for m in measz_by_pos.get(i, []): + targets = ", ".join(f"q[{idx}]" for idx in m["index"]) + qasm_lines.append(f"MEASZ {targets};") + for cal in cals_by_pos.get(i, []): # print(cal) pname = ", ".join(f"q[{x}]" for x in cal.get("parameters", [])) @@ -188,6 +207,10 @@ def to_tqasm(self, pragma: Optional[str]= None) -> str: else: qasm_lines.append(f"{gname} {targets};") + for m in measz_by_pos.get(len(self._qir), []): + targets = ", ".join(f"q[{idx}]" for idx in m["index"]) + qasm_lines.append(f"MEASZ {targets};") + # 收尾:把 pos == len(self._qir) 的校准放在最后 for cal in cals_by_pos.get(len(self._qir), []): # print(cal) diff --git a/tests/05_test_multi_measure.py b/tests/05_test_multi_measure.py index 6d760fc6..f314e7f4 100644 --- a/tests/05_test_multi_measure.py +++ b/tests/05_test_multi_measure.py @@ -32,12 +32,12 @@ def gen_multi_measure_circuit(t): # qc.rxx(0, 5, theta=1.04632) # 需添加测量指令 - qc.measure(0, 1) + qc.measz(0, 1) qc.cz(0, 1) - qc.measure(0, 1) + qc.measz(0, 1) - # print(qc.to_tqasm()) + print(qc.to_tqasm()) return qc diff --git a/tests/circuit.py b/tests/circuit.py deleted file mode 100644 index 8c393b7e..00000000 --- a/tests/circuit.py +++ /dev/null @@ -1,1129 +0,0 @@ -""" -Quantum circuit: the state simulator -""" - -# pylint: disable=invalid-name - -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple -from functools import reduce -from operator import add - -import numpy as np -import tensornetwork as tn -import quantum_compiler - -from . import gates -from . import channels -from .cons import backend, contractor, dtypestr, npdtype -from .quantum import QuOperator, identity -from .simplify import _full_light_cone_cancel -from .basecircuit import BaseCircuit - -Gate = gates.Gate -Tensor = Any - - -class Circuit(BaseCircuit): - """ - ``Circuit`` class. - Simple usage demo below. - - .. code-block:: python - - c = tc.Circuit(3) - c.H(1) - c.CNOT(0, 1) - c.RX(2, theta=tc.num_to_tensor(1.)) - c.expectation([tc.gates.z(), (2, )]) # 0.54 - - """ - - is_dm = False - - def __init__( - self, - nqubits: int, - inputs: Optional[Tensor] = None, - mps_inputs: Optional[QuOperator] = None, - split: Optional[Dict[str, Any]] = None, - ) -> None: - """ - Circuit object based on state simulator. - - :param nqubits: The number of qubits in the circuit. - :type nqubits: int - :param inputs: If not None, the initial state of the circuit is taken as ``inputs`` - instead of :math:`\\vert 0\\rangle^n` qubits, defaults to None. - :type inputs: Optional[Tensor], optional - :param mps_inputs: QuVector for a MPS like initial wavefunction. - :type mps_inputs: Optional[QuOperator] - :param split: dict if two qubit gate is ready for split, including parameters for at least one of - ``max_singular_values`` and ``max_truncation_err``. - :type split: Optional[Dict[str, Any]] - """ - super().__init__( - nqubits=nqubits, inputs=inputs, mps_inputs=mps_inputs, split=split - ) - self.calibrations = [] - self.calibration_invokes = [] - - self.inputs = inputs - self.mps_inputs = mps_inputs - self.split = split - self._nqubits = nqubits - - self.circuit_param = { - "nqubits": nqubits, - "inputs": inputs, - "mps_inputs": mps_inputs, - "split": split, - } - if (inputs is None) and (mps_inputs is None): - nodes = self.all_zero_nodes(nqubits) - self._front = [n.get_edge(0) for n in nodes] - elif inputs is not None: # provide input function - inputs = backend.convert_to_tensor(inputs) - inputs = backend.cast(inputs, dtype=dtypestr) - inputs = backend.reshape(inputs, [-1]) - N = inputs.shape[0] - n = int(np.log(N) / np.log(2)) - assert n == nqubits or n == 2 * nqubits - inputs = backend.reshape(inputs, [2 for _ in range(n)]) - inputs = Gate(inputs) - nodes = [inputs] - self._front = [inputs.get_edge(i) for i in range(n)] - else: # mps_inputs is not None - mps_nodes = list(mps_inputs.nodes) # type: ignore - for i, n in enumerate(mps_nodes): - mps_nodes[i].tensor = backend.cast(n.tensor, dtypestr) # type: ignore - mps_edges = mps_inputs.out_edges + mps_inputs.in_edges # type: ignore - ndict, edict = tn.copy(mps_nodes) - new_nodes = [] - for n in mps_nodes: - new_nodes.append(ndict[n]) - new_front = [] - for e in mps_edges: - new_front.append(edict[e]) - nodes = new_nodes - self._front = new_front - - self.coloring_nodes(nodes) - self._nodes = nodes - - self._start_index = len(nodes) - # self._start = nodes - # self._meta_apply() - - # self._qcode = "" # deprecated - # self._qcode += str(self._nqubits) + "\n" - self._qir: List[Dict[str, Any]] = [] - self._extra_qir: List[Dict[str, Any]] = [] - self._mapping = True - - def def_calibration( - self, name: str, parameters: List[str], instructions: List[Dict] - ) -> None: - self.calibrations.append({ - "name": name, - "parameters": parameters, - "instructions": instructions - }) - - def add_calibration( - self, name: str, parameters: List[str] - ) -> None: - self.calibration_invokes.append({ - "name": name, - "parameters": parameters, - "pos": len(self._qir) - }) - - - def to_tqasm(self) -> str: - qasm_lines = [] - qasm_lines.append("TQASM 0.2;") - - for cal in getattr(self, "calibrations", []): - pname = ", ".join(cal["parameters"]) - qasm_lines.append(f"\ndefcal {cal['name']} {pname} {{") - for inst in cal["instructions"]: - if inst["type"] == "frame": - qasm_lines.append(f" frame {inst['frame']} = newframe({inst['qubit']});") - elif inst["type"] == "play": - args_str = ", ".join(str(x) for x in inst["args"]) - wf_type = inst["waveform_type"] - qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") - qasm_lines.append("}") - - qasm_lines.append(f"QREG q[{self._nqubits}];") - - # 先把 calibration_invokes 按 pos 分组,并保留同 pos 内的插入顺序 - from collections import defaultdict - cals_by_pos = defaultdict(list) - for cal in getattr(self, "calibration_invokes", []): - # pos 记录的是加入时的 len(self._qir) - pos = cal.get("pos", len(self._qir)) - cals_by_pos[pos].append(cal) - - # 交错输出:在第 i 个门之前输出所有 pos == i 的校准 - for i, gate in enumerate(self._qir): - for cal in cals_by_pos.get(i, []): - # print(cal) - pname = ", ".join(cal.get("parameters", [])) - qasm_lines.append(f"{cal['name']} {pname};") - - # print(gate) - gname = gate["name"] - gname = gname.upper() - if gname == "CNOT": - gname = "CX" - targets = ", ".join(f"q[{idx}]" for idx in gate["index"]) - if (gname == "RX") or (gname == "RY") or (gname == "RZ"): - theta = gate["parameters"]["theta"] - qasm_lines.append(f"{gname} ({theta}) {targets};") - else: - qasm_lines.append(f"{gname} {targets};") - - # 收尾:把 pos == len(self._qir) 的校准放在最后 - for cal in cals_by_pos.get(len(self._qir), []): - # print(cal) - pname = ", ".join(cal.get("parameters", [])) - qasm_lines.append(f"{cal['name']} {pname};") - - print("\n".join(qasm_lines)) - # print(f"before processing : line = {len(qasm_lines)}") - - return quantum_compiler.process("\n".join(qasm_lines), self._mapping) - - def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": - return DefcalBuilder(self, name, parameters) - - def replace_mps_inputs(self, mps_inputs: QuOperator) -> None: - """ - Replace the input state in MPS representation while keep the circuit structure unchanged. - - :Example: - >>> c = tc.Circuit(2) - >>> c.X(0) - >>> - >>> c2 = tc.Circuit(2, mps_inputs=c.quvector()) - >>> c2.X(0) - >>> c2.wavefunction() - array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], dtype=complex64) - >>> - >>> c3 = tc.Circuit(2) - >>> c3.X(0) - >>> c3.replace_mps_inputs(c.quvector()) - >>> c3.wavefunction() - array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], dtype=complex64) - - :param mps_inputs: (Nodes, dangling Edges) for a MPS like initial wavefunction. - :type mps_inputs: Tuple[Sequence[Gate], Sequence[Edge]] - """ - mps_nodes = mps_inputs.nodes - mps_edges = mps_inputs.out_edges + mps_inputs.in_edges - ndict, edict = tn.copy(mps_nodes) - new_nodes = [] - for n in mps_nodes: - new_nodes.append(ndict[n]) - new_front = [] - for e in mps_edges: - new_front.append(edict[e]) - old = set(id(n) for n in self._nodes[: self._start_index]) - j = -1 - for n in self._nodes[: self._start_index]: - for e in n: - if e.is_dangling(): - j += 1 - self._front[j] = new_front[j] - else: - if (id(e.node1) in old) and (id(e.node2) in old): - pass - else: - j += 1 - if id(e.node2) == id(n): - other = (e.node1, e.axis1) - else: # id(e.node1) == id(n): - other = (e.node2, e.axis2) - e.disconnect() - new_front[j] ^ other[0][other[1]] - j += 1 - self._front += new_front[j:] - self.coloring_nodes(new_nodes) - self._nodes = new_nodes + self._nodes[self._start_index :] - self._start_index = len(new_nodes) - - # TODO(@refraction-ray): add noise support in IR - # TODO(@refraction-ray): unify mid measure to basecircuit - - def mid_measurement(self, index: int, keep: int = 0) -> Tensor: - """ - Middle measurement in z-basis on the circuit, note the wavefunction output is not normalized - with ``mid_measurement`` involved, one should normalize the state manually if needed. - This is a post-selection method as keep is provided as a prior. - - :param index: The index of qubit that the Z direction postselection applied on. - :type index: int - :param keep: 0 for spin up, 1 for spin down, defaults to be 0. - :type keep: int, optional - """ - # normalization not guaranteed - # assert keep in [0, 1] - if keep < 0.5: - gate = np.array( - [ - [1.0], - [0.0], - ], - dtype=npdtype, - ) - else: - gate = np.array( - [ - [0.0], - [1.0], - ], - dtype=npdtype, - ) - - mg1 = tn.Node(gate) - mg2 = tn.Node(gate) - # mg1.flag = "post-select" - # mg1.is_dagger = False - # mg1.id = id(mg1) - # mg2.flag = "post-select" - # mg2.is_dagger = False - # mg2.id = id(mg2) - self.coloring_nodes([mg1, mg2], flag="post-select") - mg1.get_edge(0) ^ self._front[index] - mg1.get_edge(1) ^ mg2.get_edge(1) - self._front[index] = mg2.get_edge(0) - self._nodes.append(mg1) - self._nodes.append(mg2) - r = backend.convert_to_tensor(keep) - r = backend.cast(r, "int32") - return r - - mid_measure = mid_measurement - post_select = mid_measurement - post_selection = mid_measurement - - def depolarizing2( - self, - index: int, - *, - px: float, - py: float, - pz: float, - status: Optional[float] = None, - ) -> float: - if status is None: - status = backend.implicit_randu()[0] - g = backend.cond( - status < px, - lambda: gates.x().tensor, # type: ignore - lambda: backend.cond( - status < px + py, # type: ignore - lambda: gates.y().tensor, # type: ignore - lambda: backend.cond( - status < px + py + pz, # type: ignore - lambda: gates.z().tensor, # type: ignore - lambda: gates.i().tensor, # type: ignore - ), - ), - ) - # after implementing this, I realized that plain if is enough here for jit - # the failure for previous implementation is because we use self.X(i) inside ``if``, - # which has list append and incur bug in tensorflow jit - # in terms of jax jit, the only choice is jax.lax.cond, since ``if tensor``` paradigm - # is not supported in jax jit at all. (``Concrete Tensor Error``) - self.any(index, unitary=g) # type: ignore - return 0.0 - # roughly benchmark shows that performance of two depolarizing in terms of - # building time and running time are similar - - # overwritten now, deprecated - def depolarizing_reference( - self, - index: int, - *, - px: float, - py: float, - pz: float, - status: Optional[float] = None, - ) -> Tensor: - """ - Apply depolarizing channel in a Monte Carlo way, - i.e. for each call of this method, one of gates from - X, Y, Z, I are applied on the circuit based on the probability - indicated by ``px``, ``py``, ``pz``. - - :param index: The qubit that depolarizing channel is on - :type index: int - :param px: probability for X noise - :type px: float - :param py: probability for Y noise - :type py: float - :param pz: probability for Z noise - :type pz: float - :param status: random seed uniformly from 0 to 1, defaults to None (generated implicitly) - :type status: Optional[float], optional - :return: int Tensor, the element lookup: [0: x, 1: y, 2: z, 3: I] - :rtype: Tensor - """ - - # px/y/z here not support differentiation for now - # jit compatible for now - # assert px + py + pz < 1 and px >= 0 and py >= 0 and pz >= 0 - - def step_function(x: Tensor) -> Tensor: - r = ( - backend.sign(x - px) - + backend.sign(x - px - py) - + backend.sign(x - px - py - pz) - ) - r = backend.cast(r / 2 + 1.5, dtype="int32") - # [0: x, 1: y, 2: z, 3: I] - - return r - - if status is None: - status = backend.implicit_randu()[0] - r = step_function(status) - rv = backend.onehot(r, 4) - rv = backend.cast(rv, dtype=dtypestr) - g = ( - rv[0] * gates.x().tensor # type: ignore - + rv[1] * gates.y().tensor # type: ignore - + rv[2] * gates.z().tensor # type: ignore - + rv[3] * gates.i().tensor # type: ignore - ) - self.any(index, unitary=g) # type: ignore - return r - - def unitary_kraus2( - self, - kraus: Sequence[Gate], - *index: int, - prob: Optional[Sequence[float]] = None, - status: Optional[float] = None, - name: Optional[str] = None, - ) -> Tensor: - # dont use, has issue conflicting with vmap, concurrent access lock emerged - # potential issue raised from switch - # general impl from Monte Carlo trajectory depolarizing above - # still jittable - # speed is similar to ``unitary_kraus`` - def index2gate2(r: Tensor, kraus: Sequence[Tensor]) -> Tensor: - # r is int type Tensor of shape [] - return backend.switch(r, [lambda _=k: _ for k in kraus]) # type: ignore - - return self._unitary_kraus_template( - kraus, - *index, - prob=prob, - status=status, - get_gate_from_index=index2gate2, - name=name, - ) - - def unitary_kraus( - self, - kraus: Sequence[Gate], - *index: int, - prob: Optional[Sequence[float]] = None, - status: Optional[float] = None, - name: Optional[str] = None, - ) -> Tensor: - """ - Apply unitary gates in ``kraus`` randomly based on corresponding ``prob``. - If ``prob`` is ``None``, this is reduced to kraus channel language. - - :param kraus: List of ``tc.gates.Gate`` or just Tensors - :type kraus: Sequence[Gate] - :param prob: prob list with the same size as ``kraus``, defaults to None - :type prob: Optional[Sequence[float]], optional - :param status: random seed between 0 to 1, defaults to None - :type status: Optional[float], optional - :return: shape [] int dtype tensor indicates which kraus gate is actually applied - :rtype: Tensor - """ - # general impl from Monte Carlo trajectory depolarizing above - # still jittable - - def index2gate(r: Tensor, kraus: Sequence[Tensor]) -> Tensor: - # r is int type Tensor of shape [] - l = len(kraus) - r = backend.onehot(r, l) - r = backend.cast(r, dtype=dtypestr) - return reduce(add, [r[i] * kraus[i] for i in range(l)]) - - return self._unitary_kraus_template( - kraus, - *index, - prob=prob, - status=status, - get_gate_from_index=index2gate, - name=name, - ) - - def _unitary_kraus_template( - self, - kraus: Sequence[Gate], - *index: int, - prob: Optional[Sequence[float]] = None, - status: Optional[float] = None, - get_gate_from_index: Optional[ - Callable[[Tensor, Sequence[Tensor]], Tensor] - ] = None, - name: Optional[str] = None, - ) -> Tensor: # DRY - sites = len(index) - kraus = [k.tensor if isinstance(k, tn.Node) else k for k in kraus] - kraus = [gates.array_to_tensor(k) for k in kraus] - kraus = [backend.reshapem(k) for k in kraus] - if prob is None: - prob = [ - backend.real(backend.trace(backend.adjoint(k) @ k) / k.shape[0]) - for k in kraus - ] - kraus = [ - k / backend.cast(backend.sqrt(p), dtypestr) for k, p in zip(kraus, prob) - ] - if not backend.is_tensor(prob): - prob = backend.convert_to_tensor(prob) - prob_cumsum = backend.cumsum(prob) - l = int(prob.shape[0]) # type: ignore - - def step_function(x: Tensor) -> Tensor: - if l == 1: - r = backend.convert_to_tensor(0.0) - else: - r = backend.sum( - backend.stack( - [backend.sign(x - prob_cumsum[i]) for i in range(l - 1)] - ) - ) - r = backend.cast(r / 2.0 + (l - 1) / 2.0, dtype="int32") - # [0: kraus[0], 1: kraus[1]...] - return r - - if status is None: - status = backend.implicit_randu()[0] - status = backend.convert_to_tensor(status) - status = backend.real(status) - prob_cumsum = backend.cast(prob_cumsum, dtype=status.dtype) # type: ignore - r = step_function(status) - if get_gate_from_index is None: - raise ValueError("no `get_gate_from_index` implementation is provided") - g = get_gate_from_index(r, kraus) - g = backend.reshape(g, [2 for _ in range(sites * 2)]) - self.any(*index, unitary=g, name=name) # type: ignore - return r - - def _general_kraus_tf( - self, - kraus: Sequence[Gate], - *index: int, - status: Optional[float] = None, - ) -> float: - # the graph building time is frustratingly slow, several minutes - # though running time is in terms of ms - sites = len(index) - kraus_tensor = [k.tensor for k in kraus] - kraus_tensor_f = [lambda _=k: _ for k in kraus_tensor] - # must return tensor instead of ``tn.Node`` for switch` - - def calculate_kraus_p(i: Tensor) -> Tensor: - # i: Tensor as int of shape [] - newnodes, newfront = self._copy() # TODO(@refraction-ray): support reuse? - # simply reuse=True is wrong, as the circuit is contracting at building - # self._copy seems slower than self._copy_state, but anyway the building time is unacceptable - lnewnodes, lnewfront = self._copy(conj=True) - kraus_i = backend.switch(i, kraus_tensor_f) - k = gates.Gate(kraus_i) - kc = gates.Gate(backend.conj(kraus_i)) - # begin connect - for ind, j in enumerate(index): - newfront[j] ^ k[ind + sites] - k[ind] ^ kc[ind] - kc[ind + sites] ^ lnewfront[j] - for j in range(self._nqubits): - if j not in index: - newfront[j] ^ lnewfront[j] - norm_square = contractor(newnodes + lnewnodes + [k, kc]).tensor - return backend.real(norm_square) - - if status is None: - status = backend.implicit_randu()[0] - - import tensorflow as tf # tf only implementation - - weight = 1.0 - fallback_weight = 0.0 - fallback_weight_i = 0 - len_kraus = len(kraus) - for i in tf.range(len_kraus): # breaks backend agnostic - # nested for and if, if tensor inner must come with for in tensor outer, s.t. autograph works - weight = calculate_kraus_p(i) - if weight > fallback_weight: - fallback_weight_i = i - fallback_weight = weight - status -= weight - if status < 0: - # concern here, correctness not sure in tf jit, fail anyway in jax jit - break - # placing a Tensor-dependent break, continue or return inside a Python loop - # https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/common_errors.md - - if ( - status >= 0 or weight == 0 - ): # the same concern, but this simple if is easy to convert to ``backend.cond`` - # Floating point error resulted in a malformed sample. - # Fall back to the most likely case. - # inspired from cirq implementation (Apcache 2). - weight = fallback_weight - i = fallback_weight_i - kraus_i = backend.switch(i, kraus_tensor_f) - newgate = kraus_i / backend.cast(backend.sqrt(weight), dtypestr) - self.any(*index, unitary=newgate) # type: ignore - return 0.0 - - def _general_kraus_2( - self, - kraus: Sequence[Gate], - *index: int, - status: Optional[float] = None, - with_prob: bool = False, - name: Optional[str] = None, - ) -> Tensor: - # the graph building time is frustratingly slow, several minutes - # though running time is in terms of ms - # raw running time in terms of s - # note jax gpu building time is fast, in the order of 10s.!! - # the typical scenario we are talking: 10 qubits, 3 layers of entangle gates and 3 layers of noise - # building for jax+GPU ~100s 12 qubit * 5 layers - # 370s 14 qubit * 7 layers, 0.35s running on vT4 - # vmap, grad, vvag are all fine for this function - # layerwise jit technique can greatly boost the staging time, see in /examples/mcnoise_boost.py - sites = len(index) - kraus_tensor = [k.tensor if isinstance(k, tn.Node) else k for k in kraus] - kraus_tensor = [gates.array_to_tensor(k) for k in kraus_tensor] - - # tn with hole - newnodes, newfront = self._copy() - lnewnodes, lnewfront = self._copy(conj=True) - des = [newfront[j] for j in index] + [lnewfront[j] for j in index] - for j in range(self._nqubits): - if j not in index: - newfront[j] ^ lnewfront[j] - ns = contractor(newnodes + lnewnodes, output_edge_order=des) - ntensor = ns.tensor - # ns, des - - def calculate_kraus_p(i: int) -> Tensor: - # i: Tensor as int of shape [] - # kraus_i = backend.switch(i, kraus_tensor_f) - kraus_i = kraus_tensor[i] - dm = gates.Gate(ntensor) - k = gates.Gate(kraus_i) - kc = gates.Gate(backend.conj(kraus_i)) - # begin connect - for ind in range(sites): - dm[ind] ^ k[ind + sites] - k[ind] ^ kc[ind] - kc[ind + sites] ^ dm[ind + sites] - norm_square = contractor([dm, k, kc]).tensor - return backend.real(norm_square) - - prob = [calculate_kraus_p(i) for i in range(len(kraus))] - eps = 1e-10 - new_kraus = [ - k / backend.cast(backend.sqrt(w) + eps, dtypestr) - for w, k in zip(prob, kraus_tensor) - ] - pick = self.unitary_kraus( - new_kraus, *index, prob=prob, status=status, name=name - ) - if with_prob is False: - return pick - else: - return pick, prob - - def general_kraus( - self, - kraus: Sequence[Gate], - *index: int, - status: Optional[float] = None, - with_prob: bool = False, - name: Optional[str] = None, - ) -> Tensor: - """ - Monte Carlo trajectory simulation of general Kraus channel whose Kraus operators cannot be - amplified to unitary operators. For unitary operators composed Kraus channel, :py:meth:`unitary_kraus` - is much faster. - - This function is jittable in theory. But only jax+GPU combination is recommended for jit - since the graph building time is too long for other backend options; though the running - time of the function is very fast for every case. - - :param kraus: A list of ``tn.Node`` for Kraus operators. - :type kraus: Sequence[Gate] - :param index: The qubits index that Kraus channel is applied on. - :type index: int - :param status: Random tensor uniformly between 0 or 1, defaults to be None, - when the random number will be generated automatically - :type status: Optional[float], optional - """ - return self._general_kraus_2( - kraus, *index, status=status, with_prob=with_prob, name=name - ) - - apply_general_kraus = general_kraus - - @staticmethod - def apply_general_kraus_delayed( - krausf: Callable[..., Sequence[Gate]], is_unitary: bool = False - ) -> Callable[..., None]: - def apply( - self: "Circuit", - *index: int, - status: Optional[float] = None, - name: Optional[str] = None, - **vars: float, - ) -> None: - kraus = krausf(**vars) - if not is_unitary: - self.apply_general_kraus(kraus, *index, status=status, name=name) - else: - self.unitary_kraus(kraus, *index, status=status, name=name) - - return apply - - @classmethod - def _meta_apply_channels(cls) -> None: - for k in channels.channels: - if k in ["depolarizing", "generaldepolarizing"]: - is_unitary = True - else: - is_unitary = False - setattr( - cls, - k, - cls.apply_general_kraus_delayed( - getattr(channels, k + "channel"), is_unitary=is_unitary - ), - ) - doc = """ - Apply %s quantum channel on the circuit. - See :py:meth:`tensorcircuit.channels.%schannel` - - :param index: Qubit number that the gate applies on. - :type index: int. - :param status: uniform external random number between 0 and 1 - :type status: Tensor - :param vars: Parameters for the channel. - :type vars: float. - """ % ( - k, - k, - ) - getattr(cls, k).__doc__ = doc - - def is_valid(self) -> bool: - """ - [WIP], check whether the circuit is legal. - - :return: The bool indicating whether the circuit is legal - :rtype: bool - """ - try: - assert len(self._front) == self._nqubits - for n in self._nodes: - for e in n.get_all_dangling(): - assert e in self._front - return True - except AssertionError: - return False - - def wavefunction(self, form: str = "default") -> tn.Node.tensor: - """ - Compute the output wavefunction from the circuit. - - :param form: The str indicating the form of the output wavefunction. - "default": [-1], "ket": [-1, 1], "bra": [1, -1] - :type form: str, optional - :return: Tensor with the corresponding shape. - :rtype: Tensor - """ - nodes, d_edges = self._copy() - t = contractor(nodes, output_edge_order=d_edges) - if form == "default": - shape = [-1] - elif form == "ket": - shape = [-1, 1] - elif form == "bra": # no conj here - shape = [1, -1] - return backend.reshape(t.tensor, shape=shape) - - state = wavefunction - - def get_quoperator(self) -> QuOperator: - """ - Get the ``QuOperator`` MPO like representation of the circuit unitary without contraction. - - :return: ``QuOperator`` object for the circuit unitary (open indices for the input state) - :rtype: QuOperator - """ - mps = identity([2 for _ in range(self._nqubits)]) - c = Circuit(self._nqubits) - ns, es = self._copy() - c._nodes = ns - c._front = es - c.replace_mps_inputs(mps) - return QuOperator(c._front[: self._nqubits], c._front[self._nqubits :]) - - quoperator = get_quoperator - # both are not good names, but for backward compatibility - - get_circuit_as_quoperator = get_quoperator - get_state_as_quvector = BaseCircuit.quvector - - def matrix(self) -> Tensor: - """ - Get the unitary matrix for the circuit irrespective with the circuit input state. - - :return: The circuit unitary matrix - :rtype: Tensor - """ - mps = identity([2 for _ in range(self._nqubits)]) - c = Circuit(self._nqubits) - ns, es = self._copy() - c._nodes = ns - c._front = es - c.replace_mps_inputs(mps) - return backend.reshapem(c.state()) - - def measure_reference( - self, *index: int, with_prob: bool = False - ) -> Tuple[str, float]: - """ - Take measurement on the given quantum lines by ``index``. - - :Example: - - >>> c = tc.Circuit(3) - >>> c.H(0) - >>> c.h(1) - >>> c.toffoli(0, 1, 2) - >>> c.measure(2) - ('1', -1.0) - >>> # Another possible output: ('0', -1.0) - >>> c.measure(2, with_prob=True) - ('1', (0.25000011920928955+0j)) - >>> # Another possible output: ('0', (0.7499998807907104+0j)) - - :param index: Measure on which quantum line. - :param with_prob: If true, theoretical probability is also returned. - :return: The sample output and probability (optional) of the quantum line. - :rtype: Tuple[str, float] - """ - # not jit compatible due to random number generations! - sample = "" - p = 1.0 - for j in index: - nodes1, edge1 = self._copy() - nodes2, edge2 = self._copy(conj=True) - for i, e in enumerate(edge1): - if i != j: - e ^ edge2[i] - for i in range(len(sample)): - if sample[i] == "0": - m = np.array([1, 0], dtype=npdtype) - else: - m = np.array([0, 1], dtype=npdtype) - nodes1.append(tn.Node(m)) - nodes1[-1].get_edge(0) ^ edge1[index[i]] - nodes2.append(tn.Node(m)) - nodes2[-1].get_edge(0) ^ edge2[index[i]] - nodes1.extend(nodes2) - rho = ( - 1 - / p - * contractor(nodes1, output_edge_order=[edge1[j], edge2[j]]).tensor - ) - pu = rho[0, 0] - r = backend.random_uniform([]) - r = backend.real(backend.cast(r, dtypestr)) - if r < backend.real(pu): - sample += "0" - p = p * pu - else: - sample += "1" - p = p * (1 - pu) - if with_prob: - return sample, p - else: - return sample, -1.0 - - # TODO(@refraction-ray): more _before function like state_before? and better API? - - def expectation( - self, - *ops: Tuple[tn.Node, List[int]], - reuse: bool = True, - enable_lightcone: bool = False, - noise_conf: Optional[Any] = None, - nmc: int = 1000, - status: Optional[Tensor] = None, - **kws: Any, - ) -> Tensor: - """ - Compute the expectation of corresponding operators. - - :Example: - - >>> c = tc.Circuit(2) - >>> c.H(0) - >>> c.expectation((tc.gates.z(), [0])) - array(0.+0.j, dtype=complex64) - - >>> c = tc.Circuit(2) - >>> c.cnot(0, 1) - >>> c.rx(0, theta=0.4) - >>> c.rx(1, theta=0.8) - >>> c.h(0) - >>> c.h(1) - >>> error1 = tc.channels.generaldepolarizingchannel(0.1, 1) - >>> error2 = tc.channels.generaldepolarizingchannel(0.06, 2) - >>> noise_conf = NoiseConf() - >>> noise_conf.add_noise("rx", error1) - >>> noise_conf.add_noise("cnot", [error2], [[0, 1]]) - >>> c.expectation((tc.gates.x(), [0]), noise_conf=noise_conf, nmc=10000) - (0.46274087-3.764033e-09j) - - :param ops: Operator and its position on the circuit, - eg. ``(tc.gates.z(), [1, ]), (tc.gates.x(), [2, ])`` is for operator :math:`Z_1X_2`. - :type ops: Tuple[tn.Node, List[int]] - :param reuse: If True, then the wavefunction tensor is cached for further expectation evaluation, - defaults to be true. - :type reuse: bool, optional - :param enable_lightcone: whether enable light cone simplification, defaults to False - :type enable_lightcone: bool, optional - :param noise_conf: Noise Configuration, defaults to None - :type noise_conf: Optional[NoiseConf], optional - :param nmc: repetition time for Monte Carlo sampling for noisfy calculation, defaults to 1000 - :type nmc: int, optional - :param status: external randomness given by tensor uniformly from [0, 1], defaults to None, - used for noisfy circuit sampling - :type status: Optional[Tensor], optional - :raises ValueError: "Cannot measure two operators in one index" - :return: Tensor with one element - :rtype: Tensor - """ - from .noisemodel import expectation_noisfy - - if noise_conf is None: - # if not reuse: - # nodes1, edge1 = self._copy() - # nodes2, edge2 = self._copy(conj=True) - # else: # reuse - - # self._nodes = nodes1 - if enable_lightcone: - reuse = False - nodes1 = self.expectation_before(*ops, reuse=reuse) - if enable_lightcone: - nodes1 = _full_light_cone_cancel(nodes1) - return contractor(nodes1).tensor - else: - return expectation_noisfy( - self, - *ops, - noise_conf=noise_conf, - nmc=nmc, - status=status, - **kws, - ) - - -Circuit._meta_apply() -Circuit._meta_apply_channels() - - -def expectation( - *ops: Tuple[tn.Node, List[int]], - ket: Tensor, - bra: Optional[Tensor] = None, - conj: bool = True, - normalization: bool = False, -) -> Tensor: - """ - Compute :math:`\\langle bra\\vert ops \\vert ket\\rangle`. - - Example 1 (:math:`bra` is same as :math:`ket`) - - >>> c = tc.Circuit(3) - >>> c.H(0) - >>> c.ry(1, theta=tc.num_to_tensor(0.8 + 0.7j)) - >>> c.cnot(1, 2) - >>> state = c.wavefunction() # the state of this circuit - >>> x1z2 = [(tc.gates.x(), [0]), (tc.gates.z(), [1])] # input qubits - >>> - >>> # Expection of this circuit / - >>> c.expectation(*x1z2) - array(0.69670665+0.j, dtype=complex64) - >>> tc.expectation(*x1z2, ket=state) - (0.6967066526412964+0j) - >>> - >>> # Normalize(expection of Circuit) / Normalize() - >>> c.expectation(*x1z2) / tc.backend.norm(state) ** 2 - (0.5550700389340034+0j) - >>> tc.expectation(*x1z2, ket=state, normalization=True) - (0.55507004+0j) - - Example 2 (:math:`bra` is different from :math:`ket`) - - >>> c = tc.Circuit(2) - >>> c.X(1) - >>> s1 = c.state() - >>> c2 = tc.Circuit(2) - >>> c2.X(0) - >>> s2 = c2.state() - >>> c3 = tc.Circuit(2) - >>> c3.H(1) - >>> s3 = c3.state() - >>> x1x2 = [(tc.gates.x(), [0]), (tc.gates.x(), [1])] - >>> - >>> tc.expectation(*x1x2, ket=s1, bra=s2) - (1+0j) - >>> tc.expectation(*x1x2, ket=s3, bra=s2) - (0.7071067690849304+0j) # 1/sqrt(2) - - :param ket: :math:`ket`. The state in tensor or ``QuVector`` format - :type ket: Tensor - :param bra: :math:`bra`, defaults to None, which is the same as ``ket``. - :type bra: Optional[Tensor], optional - :param conj: :math:`bra` changes to the adjoint matrix of :math:`bra`, defaults to True. - :type conj: bool, optional - :param normalization: Normalize the :math:`ket` and :math:`bra`, defaults to False. - :type normalization: bool, optional - :raises ValueError: "Cannot measure two operators in one index" - :return: The result of :math:`\\langle bra\\vert ops \\vert ket\\rangle`. - :rtype: Tensor - """ - if bra is None: - bra = ket - if isinstance(ket, QuOperator): - if conj is True: - bra = bra.adjoint() - # TODO(@refraction-ray) omit normalization arg for now - n = len(ket.out_edges) - occupied = set() - nodes = list(ket.nodes) + list(bra.nodes) - # TODO(@refraction-ray): is the order guaranteed or affect some types of contractor? - for op, index in ops: - if not isinstance(op, tn.Node): - # op is only a matrix - op = backend.reshape2(op) - op = gates.Gate(op) - if isinstance(index, int): - index = [index] - noe = len(index) - for j, e in enumerate(index): - if e in occupied: - raise ValueError("Cannot measure two operators in one index") - bra.in_edges[e] ^ op.get_edge(j) - ket.out_edges[e] ^ op.get_edge(j + noe) - occupied.add(e) - nodes.append(op) - for j in range(n): - if j not in occupied: # edge1[j].is_dangling invalid here! - ket.out_edges[j] ^ bra.in_edges[j] - # self._nodes = nodes1 - num = contractor(nodes).tensor - return num - - else: - # ket is the tensor - if conj is True: - bra = backend.conj(bra) - ket = backend.reshape(ket, [-1]) - ket = backend.reshape2(ket) - bra = backend.reshape2(bra) - n = len(backend.shape_tuple(ket)) - ket = Gate(ket) - bra = Gate(bra) - occupied = set() - nodes = [ket, bra] - if normalization is True: - normket = backend.norm(ket.tensor) - normbra = backend.norm(bra.tensor) - for op, index in ops: - if not isinstance(op, tn.Node): - # op is only a matrix - op = backend.reshape2(op) - op = gates.Gate(op) - if isinstance(index, int): - index = [index] - noe = len(index) - for j, e in enumerate(index): - if e in occupied: - raise ValueError("Cannot measure two operators in one index") - bra[e] ^ op.get_edge(j) - ket[e] ^ op.get_edge(j + noe) - occupied.add(e) - nodes.append(op) - for j in range(n): - if j not in occupied: # edge1[j].is_dangling invalid here! - ket[j] ^ bra[j] - # self._nodes = nodes1 - num = contractor(nodes).tensor - if normalization is True: - den = normket * normbra - else: - den = 1.0 - return num / den - -class Param: - def __init__(self, name: str): - self.name = name - -class DefcalBuilder: - def __init__(self, circuit, name: str, parameters: List["Param"]): - self.circuit = circuit - self.name = name - self.parameters = parameters - self.instructions = [] - - def new_frame(self, frame_name: str, param: "Param"): - self.instructions.append({ - "type": "frame", - "frame": frame_name, - "qubit": param.name, - }) - return self - - def play(self, frame_name: str, waveform: Any, start_time: int = None): - if not hasattr(waveform, "__dataclass_fields__"): - raise TypeError("Unsupported waveform type") - - waveform_type = waveform.qasm_name() - args = waveform.to_args() - if start_time is not None: - args = [start_time] + args - - self.instructions.append({ - "type": "play", - "frame": frame_name, - "waveform_type": waveform_type, - "args": args, - }) - return self - - def build(self): - self.circuit.def_calibration( - name=self.name, - parameters=[p.name for p in self.parameters], - instructions=self.instructions, - ) From d35e13aeca2c89d2486134aeae2d40896a74111a Mon Sep 17 00:00:00 2001 From: walterxu Date: Tue, 2 Sep 2025 18:30:40 +0800 Subject: [PATCH 139/139] multi --- tensorcircuit/cloud/abstraction.py | 3 +-- tests/05_test_multi_measure.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tensorcircuit/cloud/abstraction.py b/tensorcircuit/cloud/abstraction.py index 10403e6f..be07790c 100644 --- a/tensorcircuit/cloud/abstraction.py +++ b/tensorcircuit/cloud/abstraction.py @@ -416,8 +416,7 @@ def m_results( s = self.state() if s != "completed": raise TaskUnfinished(self.id_, s) - r = self.details()["multi_results"] - r = counts.sort_count(r) # type: ignore + r = self.details()["multi_result"] else: s = self.state() tries = 0 diff --git a/tests/05_test_multi_measure.py b/tests/05_test_multi_measure.py index f314e7f4..0370f89b 100644 --- a/tests/05_test_multi_measure.py +++ b/tests/05_test_multi_measure.py @@ -53,9 +53,9 @@ def run_circuit(qc): ) # print(qc.to_tqasm()) # n = qc._nqubits - rf = t.results() # 需返回 multi_results + # rf = t.results() # 需返回 multi_results rf = t.m_results() # 需返回 multi_results - print(rf) + return rf qc = gen_multi_measure_circuit(1.0) result = run_circuit(qc)