{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Train Variational Quantum Circuits by using f-evovaq and Qiskit" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "## 1) Training a Variational Quantum Classifier through a Memetic Algorithm" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "#### Importing modules" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import numpy as np\n", "import cupy as cp\n", "from functools import partial\n", "from sklearn.datasets import load_iris\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import log_loss, accuracy_score\n", "from sklearn.preprocessing import MinMaxScaler\n", "from qiskit.circuit.library import TwoLocal\n", "from qiskit_aer.quantum_info import AerStatevector\n", "from qiskit import QuantumCircuit\n", "from qiskit.circuit import ParameterVector\n", "from fevovaq.problem import Problem\n", "from fevovaq.GeneticAlgorithm import GA\n", "from fevovaq.HillClimbing import HC\n", "from fevovaq.MemeticAlgorithm import MA\n", "from fevovaq.tools.operators import sel_tournament, cx_uniform, mut_gaussian, sel_best" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "#### Uploading the classical data" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "iris = load_iris()\n", "\n", "# For the sake of simplicity, we consider all the four features but only two classes\n", "iris_data = iris.data[:100, :4]\n", "iris_target = iris.target[:100] # 0 or 1\n", "\n", "# Split into train and test subsets\n", "train_data, test_data, train_labels, test_labels = train_test_split(iris_data, iris_target, test_size=0.2,\n", " random_state=42)\n", "\n", "# Pre-processing\n", "scaler = MinMaxScaler(feature_range=(-np.pi, np.pi))\n", "scaler.fit(train_data)\n", "train_data = scaler.transform(train_data)\n", "test_data = scaler.transform(test_data)" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "#### Building the Variational Quantum Classifier" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def AngleEncoding(n_qubits, rotation=\"ry\"):\n", " features = ParameterVector('f', n_qubits)\n", "\n", " qc = QuantumCircuit(n_qubits, 1)\n", "\n", " for i in range(n_qubits):\n", " if rotation == \"rx\":\n", " qc.rx(features[i], i)\n", " elif rotation == \"ry\":\n", " qc.ry(features[i], i)\n", " elif rotation == \"rz\":\n", " qc.rz(features[i], i)\n", " else:\n", " raise ValueError(\"rotation must be 'rx', 'ry', or 'rz'\")\n", "\n", " return qc" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/html": [ "
┌─────────────┐ ┌────────────────────┐ »\n",
"q_0: ┤ R(f[0],π/2) ├─┤ U3(θ[2],θ[1],θ[0]) ├───────────────────────────────»\n",
" ├─────────────┤ ├────────────────────┤ »\n",
"q_1: ┤ R(f[1],π/2) ├─┤ U3(θ[5],θ[4],θ[3]) ├──────────────────■────────────»\n",
" ├─────────────┤ ├────────────────────┤ ┌─┴─┐ »\n",
"q_2: ┤ R(f[2],π/2) ├─┤ U3(θ[8],θ[7],θ[6]) ├───■────────────┤ X ├──────────»\n",
" ├─────────────┤┌┴────────────────────┴┐┌─┴─┐┌─────────┴───┴─────────┐»\n",
"q_3: ┤ R(f[3],π/2) ├┤ U3(θ[11],θ[10],θ[9]) ├┤ X ├┤ U3(θ[23],θ[22],θ[21]) ├»\n",
" └─────────────┘└──────────────────────┘└───┘└───────────────────────┘»\n",
"c: 1/═════════════════════════════════════════════════════════════════════»\n",
" »\n",
"« ┌───────────────────────┐»\n",
"«q_0: ────────────■────────────┤ U3(θ[14],θ[13],θ[12]) ├»\n",
"« ┌─┴─┐ ├───────────────────────┤»\n",
"«q_1: ──────────┤ X ├──────────┤ U3(θ[17],θ[16],θ[15]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_2: ┤ U3(θ[20],θ[19],θ[18]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_3: ───────────────────────────────────┤ X ├──────────»\n",
"« └───┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"«q_0: ─────────────────────────────────────■────────────»\n",
"« ┌─┴─┐ »\n",
"«q_1: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_2: ──────────┤ X ├──────────┤ U3(θ[32],θ[31],θ[30]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_3: ┤ U3(θ[35],θ[34],θ[33]) ├─────────────────────────»\n",
"« └───────────────────────┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐ »\n",
"«q_0: ┤ U3(θ[26],θ[25],θ[24]) ├─────────────────────────»\n",
"« ├───────────────────────┤ »\n",
"«q_1: ┤ U3(θ[29],θ[28],θ[27]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_2: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_3: ──────────┤ X ├──────────┤ U3(θ[47],θ[46],θ[45]) ├»\n",
"« └───┘ └───────────────────────┘»\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐»\n",
"«q_0: ────────────■────────────┤ U3(θ[38],θ[37],θ[36]) ├»\n",
"« ┌─┴─┐ ├───────────────────────┤»\n",
"«q_1: ──────────┤ X ├──────────┤ U3(θ[41],θ[40],θ[39]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_2: ┤ U3(θ[44],θ[43],θ[42]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_3: ───────────────────────────────────┤ X ├──────────»\n",
"« └───┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"«q_0: ─────────────────────────────────────■────────────»\n",
"« ┌─┴─┐ »\n",
"«q_1: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_2: ──────────┤ X ├──────────┤ U3(θ[56],θ[55],θ[54]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_3: ┤ U3(θ[59],θ[58],θ[57]) ├─────────────────────────»\n",
"« └───────────────────────┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐ \n",
"«q_0: ┤ U3(θ[50],θ[49],θ[48]) ├───────■──\n",
"« ├───────────────────────┤ ┌─┴─┐\n",
"«q_1: ┤ U3(θ[53],θ[52],θ[51]) ├──■──┤ X ├\n",
"« └───────────────────────┘┌─┴─┐└───┘\n",
"«q_2: ────────────■────────────┤ X ├─────\n",
"« ┌─┴─┐ └───┘ \n",
"«q_3: ──────────┤ X ├────────────────────\n",
"« └───┘ \n",
"«c: 1/═══════════════════════════════════\n",
"« "
],
"text/plain": [
" ┌─────────────┐ ┌────────────────────┐ »\n",
"q_0: ┤ R(f[0],π/2) ├─┤ U3(θ[2],θ[1],θ[0]) ├───────────────────────────────»\n",
" ├─────────────┤ ├────────────────────┤ »\n",
"q_1: ┤ R(f[1],π/2) ├─┤ U3(θ[5],θ[4],θ[3]) ├──────────────────■────────────»\n",
" ├─────────────┤ ├────────────────────┤ ┌─┴─┐ »\n",
"q_2: ┤ R(f[2],π/2) ├─┤ U3(θ[8],θ[7],θ[6]) ├───■────────────┤ X ├──────────»\n",
" ├─────────────┤┌┴────────────────────┴┐┌─┴─┐┌─────────┴───┴─────────┐»\n",
"q_3: ┤ R(f[3],π/2) ├┤ U3(θ[11],θ[10],θ[9]) ├┤ X ├┤ U3(θ[23],θ[22],θ[21]) ├»\n",
" └─────────────┘└──────────────────────┘└───┘└───────────────────────┘»\n",
"c: 1/═════════════════════════════════════════════════════════════════════»\n",
" »\n",
"« ┌───────────────────────┐»\n",
"«q_0: ────────────■────────────┤ U3(θ[14],θ[13],θ[12]) ├»\n",
"« ┌─┴─┐ ├───────────────────────┤»\n",
"«q_1: ──────────┤ X ├──────────┤ U3(θ[17],θ[16],θ[15]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_2: ┤ U3(θ[20],θ[19],θ[18]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_3: ───────────────────────────────────┤ X ├──────────»\n",
"« └───┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"«q_0: ─────────────────────────────────────■────────────»\n",
"« ┌─┴─┐ »\n",
"«q_1: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_2: ──────────┤ X ├──────────┤ U3(θ[32],θ[31],θ[30]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_3: ┤ U3(θ[35],θ[34],θ[33]) ├─────────────────────────»\n",
"« └───────────────────────┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐ »\n",
"«q_0: ┤ U3(θ[26],θ[25],θ[24]) ├─────────────────────────»\n",
"« ├───────────────────────┤ »\n",
"«q_1: ┤ U3(θ[29],θ[28],θ[27]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_2: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_3: ──────────┤ X ├──────────┤ U3(θ[47],θ[46],θ[45]) ├»\n",
"« └───┘ └───────────────────────┘»\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐»\n",
"«q_0: ────────────■────────────┤ U3(θ[38],θ[37],θ[36]) ├»\n",
"« ┌─┴─┐ ├───────────────────────┤»\n",
"«q_1: ──────────┤ X ├──────────┤ U3(θ[41],θ[40],θ[39]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_2: ┤ U3(θ[44],θ[43],θ[42]) ├────────────■────────────»\n",
"« └───────────────────────┘ ┌─┴─┐ »\n",
"«q_3: ───────────────────────────────────┤ X ├──────────»\n",
"« └───┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"«q_0: ─────────────────────────────────────■────────────»\n",
"« ┌─┴─┐ »\n",
"«q_1: ────────────■──────────────────────┤ X ├──────────»\n",
"« ┌─┴─┐ ┌─────────┴───┴─────────┐»\n",
"«q_2: ──────────┤ X ├──────────┤ U3(θ[56],θ[55],θ[54]) ├»\n",
"« ┌─────────┴───┴─────────┐└───────────────────────┘»\n",
"«q_3: ┤ U3(θ[59],θ[58],θ[57]) ├─────────────────────────»\n",
"« └───────────────────────┘ »\n",
"«c: 1/══════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────────────┐ \n",
"«q_0: ┤ U3(θ[50],θ[49],θ[48]) ├───────■──\n",
"« ├───────────────────────┤ ┌─┴─┐\n",
"«q_1: ┤ U3(θ[53],θ[52],θ[51]) ├──■──┤ X ├\n",
"« └───────────────────────┘┌─┴─┐└───┘\n",
"«q_2: ────────────■────────────┤ X ├─────\n",
"« ┌─┴─┐ └───┘ \n",
"«q_3: ──────────┤ X ├────────────────────\n",
"« └───┘ \n",
"«c: 1/═══════════════════════════════════\n",
"« "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Encode classical data in a quantum system through a FeatureMap\n",
"reps = 5\n",
"n_qubits = train_data.shape[1] # Number of qubits\n",
"\n",
"feature_map = AngleEncoding(n_qubits)\n",
"\n",
"# Define an Ansatz to be trained\n",
"ansatz = TwoLocal(num_qubits=n_qubits, entanglement='reverse_linear', rotation_blocks='u3', reps=reps,\n",
" entanglement_blocks='cx', skip_final_rotation_layer=True)\n",
"\n",
"# Put together our quantum classifier\n",
"classifier = feature_map.compose(ansatz)\n",
"\n",
"classifier.decompose().draw()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"def get_label(params, classifier, test_data, problem):\n",
" xp = problem.xp\n",
" if xp.__name__ == 'cupy':\n",
" params = xp.asnumpy(params)\n",
"\n",
" bound_circuit = classifier.assign_parameters(np.concatenate((test_data, params)))\n",
" sv = AerStatevector(bound_circuit , device='GPU')\n",
"\n",
" probs = sv.probabilities([0])\n",
" return 1 if probs[1] > 0.5 else 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Defining the cost function to be minimized"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"def cost_function(params, classifier, train_data, train_labels):\n",
" n_samples = train_data.shape[0]\n",
"\n",
" # Convert CuPy array as NumPy because Qiskit doesn't support GPU-based arrays\n",
" params = cp.asnumpy(params)\n",
" params_reshaped = np.tile(params, (n_samples, 1))\n",
" all_params_np = np.concatenate((train_data, params_reshaped), axis=1)\n",
"\n",
" preds = np.zeros(n_samples)\n",
" for i, params_inst in enumerate(all_params_np):\n",
" bound_circuits = classifier.assign_parameters(params_inst)\n",
"\n",
" sv = AerStatevector(bound_circuits , device='GPU')\n",
"\n",
" probs = sv.probabilities([0])\n",
"\n",
" preds[i] = probs[1]\n",
"\n",
" return log_loss(train_labels, preds)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"#### Setting up the problem"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"cost_func = partial(cost_function, classifier=classifier, train_data=train_data, train_labels=train_labels)\n",
"problem = Problem(n_params=ansatz.num_parameters, param_bounds=ansatz.parameter_bounds, init_range=(-cp.pi, cp.pi),\n",
" obj_function=cost_func, backend='gpu', vectorized=False)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"#### Defining a Memetic Algorithm"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"pycharm": {
"is_executing": true,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"# Define the global search method\n",
"global_search = GA(selection=sel_tournament, crossover=cx_uniform, mutation=mut_gaussian, sigma=0.2, mut_indpb=0.15,\n",
" cxpb=0.9, tournsize=5)\n",
"\n",
"# Create a neighbour of a possible solution\n",
"def get_neighbour(problem, current_solution):\n",
" xp = problem.xp\n",
" neighbour = current_solution.copy()\n",
" index = xp.random.randint(0, problem.n_params, size=1)\n",
" neighbour[index] = xp.random.uniform(-xp.pi, xp.pi, size=1)\n",
" return neighbour\n",
"\n",
"# Define the local search method\n",
"local_search = HC(generate_neighbour=get_neighbour)\n",
"\n",
"# Compose the global and local search method for a Memetic Algorithm \n",
"optimizer = MA(global_search=global_search.evolve_population, sel_for_refinement=sel_best, local_search=local_search.stochastic_var, frequency=0.1, intensity=10)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Training our VQC"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 0%| | 0/10 [00:00, ?gen/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"********** Execution #1 **********\n",
"gen nfev min max mean std\n",
"----- ------ -------- -------- -------- --------\n",
"0 10 0.448778 0.885639 0.711605 0.123813\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 10%|███ | 1/10 [00:02<00:19, 2.21s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"1 20 0.448778 0.892065 0.740525 0.143335\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 20%|██████ | 2/10 [00:04<00:16, 2.07s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"2 20 0.448778 0.884432 0.730048 0.124827\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 30%|█████████ | 3/10 [00:06<00:14, 2.04s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"3 20 0.448778 0.798723 0.699879 0.0958409\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 40%|████████████ | 4/10 [00:08<00:12, 2.02s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"4 20 0.448778 0.895857 0.661903 0.126814\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 50%|███████████████ | 5/10 [00:10<00:10, 2.02s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"5 20 0.448778 0.940913 0.758427 0.125662\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 60%|██████████████████ | 6/10 [00:12<00:08, 2.01s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"6 20 0.448778 0.821422 0.644119 0.128682\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 70%|█████████████████████ | 7/10 [00:14<00:06, 2.03s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"7 20 0.448778 0.717158 0.55156 0.0767636\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 80%|████████████████████████ | 8/10 [00:16<00:04, 2.02s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"8 20 0.43301 0.521759 0.476904 0.0321787\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 90%|███████████████████████████ | 9/10 [00:18<00:02, 2.02s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"9 20 0.383075 0.511485 0.456047 0.033578\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generations: 100%|█████████████████████████████| 10/10 [00:20<00:00, 2.03s/gen]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"10 20 0.374914 0.524138 0.441109 0.0447009\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
},
{
"data": {
"text/plain": [
" fun: array(0.37491382)\n",
" gen: 10\n",
" log: {'gen': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'nfev': [10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20], 'min': [array(0.44877768), array(0.44877768), array(0.44877768), array(0.44877768), array(0.44877768), array(0.44877768), array(0.44877768), array(0.44877768), array(0.43300969), array(0.38307533), array(0.37491382)], 'max': [array(0.88563912), array(0.89206535), array(0.88443177), array(0.79872295), array(0.89585688), array(0.94091294), array(0.82142174), array(0.7171575), array(0.5217589), array(0.51148517), array(0.52413836)], 'mean': [array(0.7116047), array(0.74052451), array(0.73004844), array(0.69987924), array(0.66190269), array(0.75842726), array(0.64411938), array(0.55156003), array(0.47690374), array(0.45604707), array(0.44110942)], 'std': [array(0.12381267), array(0.14333453), array(0.12482709), array(0.09584085), array(0.12681402), array(0.12566232), array(0.12868223), array(0.07676358), array(0.03217866), array(0.03357805), array(0.04470089)]}\n",
" nfev: 210\n",
" x: array([ 2.66756446, 1.88347094, -2.67819543, -0.86081502, 0.07447794,\n",
" -1.69281126, 0.04354438, 1.13787173, 0.87256201, 1.03553065,\n",
" 3.20766494, 0.54151417, -0.90258819, -2.6057128 , 1.68382911,\n",
" -2.19062974, -2.59953377, 0.23649704, 2.68102339, -1.58245806,\n",
" 0.29607596, 0.24048514, 2.73712106, -0.11428715, 0.62380583,\n",
" -2.59104795, 0.96932751, 0.48425987, -3.10073629, -0.08926363,\n",
" -1.35770848, 1.13112516, 0.32676846, -0.04495667, -1.88844294,\n",
" 1.42374158, 1.09768481, -0.2076989 , -0.59348811, 1.46291578,\n",
" 2.40236227, -2.64686819, 2.58232254, -2.66135108, 0.9215397 ,\n",
" 2.33880593, 2.6188431 , 3.16970774, 2.26524258, -1.72029359,\n",
" 1.8109968 , -1.40636385, 1.91533376, -2.53913955, -2.56059053,\n",
" -3.12272377, -2.05883532, -1.04306676, 2.43778751, -0.30886724])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"res = optimizer.optimize(problem, pop_size=10, max_gen=10, verbose=True, seed=42)\n",
"res"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Testing the optimal solution found"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"pycharm": {
"is_executing": true
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy on the test subset: 0.95\n"
]
}
],
"source": [
"test_preds = [get_label(res.x, classifier, feats, problem) for feats in test_data]\n",
"\n",
"test_accuracy = accuracy_score(test_labels, test_preds)\n",
"print(\"Accuracy on the test subset:\", test_accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2) QAOA trained by a CHC algorithm to solve MaxCut problem"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"#### Importing modules"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"pycharm": {
"is_executing": true,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"import networkx as nx\n",
"import numpy as np\n",
"from functools import partial\n",
"import cupy as cp\n",
"from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
"from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
"from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
"from qiskit_aer import AerSimulator\n",
"from qiskit.visualization import plot_histogram\n",
"from qiskit_optimization.applications import Maxcut\n",
"from qiskit.circuit.library import QAOAAnsatz\n",
"from fevovaq.problem import Problem\n",
"from fevovaq.CHCAlgorithm import CHC\n",
"from fevovaq.tools.operators import cx_blx_alpha\n",
"from fevovaq.tools.distances import fitness_l1"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"#### Defining the graph"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"pycharm": {
"is_executing": true,
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
" ┌─────────────┐ »\n",
" q_0: ┤ U3(π/2,0,π) ├──■────────────────────■─────────────────────■──»\n",
" ├─────────────┤┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ │ »\n",
" q_1: ┤ U3(π/2,0,π) ├┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├──┼──»\n",
" ├─────────────┤└───┘└──────────────┘└───┘└───────────────┘┌─┴─┐»\n",
" q_2: ┤ U3(π/2,0,π) ├───────────────────────────────────────────┤ X ├»\n",
" ├─────────────┤ └───┘»\n",
" q_3: ┤ U3(π/2,0,π) ├────────────────────────────────────────────────»\n",
" ├─────────────┤ »\n",
" q_4: ┤ U3(π/2,0,π) ├────────────────────────────────────────────────»\n",
" └─────────────┘ »\n",
"meas: 5/═══════════════════════════════════════════════════════════════»\n",
" »\n",
"« »\n",
"« q_0: ──────────────────■─────────────────────■────────────────────■──»\n",
"« │ │ │ »\n",
"« q_1: ──────────────────┼─────────────────────┼────────────────────┼──»\n",
"« ┌──────────────┐┌─┴─┐┌───────────────┐ │ │ »\n",
"« q_2: ┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├──┼────────────────────┼──»\n",
"« └──────────────┘└───┘└───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐»\n",
"« q_3: ──────────────────────────────────────┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├»\n",
"« └───┘└──────────────┘└───┘»\n",
"« q_4: ────────────────────────────────────────────────────────────────»\n",
"« »\n",
"«meas: 5/════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────┐ »\n",
"« q_0: ───────────────────■────────────────────■──┤ R(2.0*β[0],0) ├──■──»\n",
"« │ │ └───────────────┘┌─┴─┐»\n",
"« q_1: ───────────────────┼────────────────────┼───────────────────┤ X ├»\n",
"« │ │ └───┘»\n",
"« q_2: ───────────────────┼────────────────────┼────────────────────────»\n",
"« ┌───────────────┐ │ │ »\n",
"« q_3: ┤ R(2.0*β[0],0) ├──┼────────────────────┼────────────────────────»\n",
"« └───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ »\n",
"« q_4: ─────────────────┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├─────»\n",
"« └───┘└──────────────┘└───┘└───────────────┘ »\n",
"«meas: 5/═════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"« q_0: ──────────────────■────■─────────────────────■────■───────────────────»\n",
"« ┌──────────────┐┌─┴─┐ │ ┌───────────────┐ │ │ »\n",
"« q_1: ┤ Rz(1.0*γ[1]) ├┤ X ├──┼──┤ R(2.0*β[1],0) ├──┼────┼───────────────────»\n",
"« └──────────────┘└───┘┌─┴─┐└┬──────────────┤┌─┴─┐ │ ┌───────────────┐»\n",
"« q_2: ─────────────────────┤ X ├─┤ Rz(1.0*γ[1]) ├┤ X ├──┼──┤ R(2.0*β[1],0) ├»\n",
"« └───┘ └──────────────┘└───┘┌─┴─┐└┬──────────────┤»\n",
"« q_3: ────────────────────────────────────────────────┤ X ├─┤ Rz(1.0*γ[1]) ├»\n",
"« └───┘ └──────────────┘»\n",
"« q_4: ──────────────────────────────────────────────────────────────────────»\n",
"« »\n",
"«meas: 5/══════════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────┐ ░ »\n",
"« q_0: ──■─────────────────────■────────────────────■──┤ R(2.0*β[1],0) ├─░─»\n",
"« │ │ │ └───────────────┘ ░ »\n",
"« q_1: ──┼─────────────────────┼────────────────────┼────────────────────░─»\n",
"« │ │ │ ░ »\n",
"« q_2: ──┼─────────────────────┼────────────────────┼────────────────────░─»\n",
"« ┌─┴─┐┌───────────────┐ │ │ ░ »\n",
"« q_3: ┤ X ├┤ R(2.0*β[1],0) ├──┼────────────────────┼────────────────────░─»\n",
"« └───┘└───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ ░ »\n",
"« q_4: ──────────────────────┤ X ├┤ Rz(1.0*γ[1]) ├┤ X ├┤ R(2.0*β[1],0) ├─░─»\n",
"« └───┘└──────────────┘└───┘└───────────────┘ ░ »\n",
"«meas: 5/════════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌─┐ \n",
"« q_0: ┤M├────────────\n",
"« └╥┘┌─┐ \n",
"« q_1: ─╫─┤M├─────────\n",
"« ║ └╥┘┌─┐ \n",
"« q_2: ─╫──╫─┤M├──────\n",
"« ║ ║ └╥┘┌─┐ \n",
"« q_3: ─╫──╫──╫─┤M├───\n",
"« ║ ║ ║ └╥┘┌─┐\n",
"« q_4: ─╫──╫──╫──╫─┤M├\n",
"« ║ ║ ║ ║ └╥┘\n",
"«meas: 5/═╩══╩══╩══╩══╩═\n",
"« 0 1 2 3 4 "
],
"text/plain": [
" ┌─────────────┐ »\n",
" q_0: ┤ U3(π/2,0,π) ├──■────────────────────■─────────────────────■──»\n",
" ├─────────────┤┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ │ »\n",
" q_1: ┤ U3(π/2,0,π) ├┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├──┼──»\n",
" ├─────────────┤└───┘└──────────────┘└───┘└───────────────┘┌─┴─┐»\n",
" q_2: ┤ U3(π/2,0,π) ├───────────────────────────────────────────┤ X ├»\n",
" ├─────────────┤ └───┘»\n",
" q_3: ┤ U3(π/2,0,π) ├────────────────────────────────────────────────»\n",
" ├─────────────┤ »\n",
" q_4: ┤ U3(π/2,0,π) ├────────────────────────────────────────────────»\n",
" └─────────────┘ »\n",
"meas: 5/═══════════════════════════════════════════════════════════════»\n",
" »\n",
"« »\n",
"« q_0: ──────────────────■─────────────────────■────────────────────■──»\n",
"« │ │ │ »\n",
"« q_1: ──────────────────┼─────────────────────┼────────────────────┼──»\n",
"« ┌──────────────┐┌─┴─┐┌───────────────┐ │ │ »\n",
"« q_2: ┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├──┼────────────────────┼──»\n",
"« └──────────────┘└───┘└───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐»\n",
"« q_3: ──────────────────────────────────────┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├»\n",
"« └───┘└──────────────┘└───┘»\n",
"« q_4: ────────────────────────────────────────────────────────────────»\n",
"« »\n",
"«meas: 5/════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────┐ »\n",
"« q_0: ───────────────────■────────────────────■──┤ R(2.0*β[0],0) ├──■──»\n",
"« │ │ └───────────────┘┌─┴─┐»\n",
"« q_1: ───────────────────┼────────────────────┼───────────────────┤ X ├»\n",
"« │ │ └───┘»\n",
"« q_2: ───────────────────┼────────────────────┼────────────────────────»\n",
"« ┌───────────────┐ │ │ »\n",
"« q_3: ┤ R(2.0*β[0],0) ├──┼────────────────────┼────────────────────────»\n",
"« └───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ »\n",
"« q_4: ─────────────────┤ X ├┤ Rz(1.0*γ[0]) ├┤ X ├┤ R(2.0*β[0],0) ├─────»\n",
"« └───┘└──────────────┘└───┘└───────────────┘ »\n",
"«meas: 5/═════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« »\n",
"« q_0: ──────────────────■────■─────────────────────■────■───────────────────»\n",
"« ┌──────────────┐┌─┴─┐ │ ┌───────────────┐ │ │ »\n",
"« q_1: ┤ Rz(1.0*γ[1]) ├┤ X ├──┼──┤ R(2.0*β[1],0) ├──┼────┼───────────────────»\n",
"« └──────────────┘└───┘┌─┴─┐└┬──────────────┤┌─┴─┐ │ ┌───────────────┐»\n",
"« q_2: ─────────────────────┤ X ├─┤ Rz(1.0*γ[1]) ├┤ X ├──┼──┤ R(2.0*β[1],0) ├»\n",
"« └───┘ └──────────────┘└───┘┌─┴─┐└┬──────────────┤»\n",
"« q_3: ────────────────────────────────────────────────┤ X ├─┤ Rz(1.0*γ[1]) ├»\n",
"« └───┘ └──────────────┘»\n",
"« q_4: ──────────────────────────────────────────────────────────────────────»\n",
"« »\n",
"«meas: 5/══════════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌───────────────┐ ░ »\n",
"« q_0: ──■─────────────────────■────────────────────■──┤ R(2.0*β[1],0) ├─░─»\n",
"« │ │ │ └───────────────┘ ░ »\n",
"« q_1: ──┼─────────────────────┼────────────────────┼────────────────────░─»\n",
"« │ │ │ ░ »\n",
"« q_2: ──┼─────────────────────┼────────────────────┼────────────────────░─»\n",
"« ┌─┴─┐┌───────────────┐ │ │ ░ »\n",
"« q_3: ┤ X ├┤ R(2.0*β[1],0) ├──┼────────────────────┼────────────────────░─»\n",
"« └───┘└───────────────┘┌─┴─┐┌──────────────┐┌─┴─┐┌───────────────┐ ░ »\n",
"« q_4: ──────────────────────┤ X ├┤ Rz(1.0*γ[1]) ├┤ X ├┤ R(2.0*β[1],0) ├─░─»\n",
"« └───┘└──────────────┘└───┘└───────────────┘ ░ »\n",
"«meas: 5/════════════════════════════════════════════════════════════════════»\n",
"« »\n",
"« ┌─┐ \n",
"« q_0: ┤M├────────────\n",
"« └╥┘┌─┐ \n",
"« q_1: ─╫─┤M├─────────\n",
"« ║ └╥┘┌─┐ \n",
"« q_2: ─╫──╫─┤M├──────\n",
"« ║ ║ └╥┘┌─┐ \n",
"« q_3: ─╫──╫──╫─┤M├───\n",
"« ║ ║ ║ └╥┘┌─┐\n",
"« q_4: ─╫──╫──╫──╫─┤M├\n",
"« ║ ║ ║ ║ └╥┘\n",
"«meas: 5/═╩══╩══╩══╩══╩═\n",
"« 0 1 2 3 4 "
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# QAOA ansatz circuit\n",
"qaoa_circuit = QAOAAnsatz(hamiltonian, reps=2)\n",
"qaoa_circuit.measure_all()\n",
"qaoa_circuit.decompose(reps=3).draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Setting up the Estimator and Sampler"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"quantum_backend = AerSimulator()\n",
"\n",
"# Set the transpiler\n",
"pm = generate_preset_pass_manager(backend=quantum_backend, optimization_level=0)\n",
"\n",
"# Set the Estimator and Sampler\n",
"estimator = Estimator(quantum_backend)\n",
"sampler = Sampler(quantum_backend)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": true
}
},
"source": [
"#### Defining the cost function to be minimized"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"pycharm": {
"is_executing": true
}
},
"outputs": [],
"source": [
"def cost_function(params, circuit, hamiltonian, estimator, pm):\n",
" # Transpile the circuit to ISA circuit\n",
" params = cp.asnumpy(params)\n",
" circuit_isa = pm.run(circuit)\n",
" hamiltonian_isa = hamiltonian.apply_layout(circuit_isa.layout)\n",
" pub = (circuit_isa, [hamiltonian_isa], [params])\n",
"\n",
" # Submit the circuit to estimator and get the result\n",
" result = estimator.run(pubs=[pub]).result()\n",
"\n",
" # Extract the expectation value\n",
" cost = result[0].data.evs[0]\n",
" return cost"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Setting up the problem"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"cost_func = partial(cost_function, circuit=qaoa_circuit, hamiltonian=hamiltonian, estimator=estimator, pm=pm)\n",
"problem = Problem(n_params=qaoa_circuit.num_parameters, param_bounds=qaoa_circuit.parameter_bounds,\n",
" init_range=(0, 2* cp.pi), obj_function=cost_func, backend='gpu', vectorized=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Defining the CHC algorithm"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"optimizer = CHC(crossover=cx_blx_alpha, distance=fitness_l1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Training the QAOA circuit"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 18%|███▏ | 18/100 [00:00<00:00, 130.30nfev/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"********** Execution #1 **********\n",
"gen nfev min max mean std\n",
"----- ------ -------- -------- --------- --------\n",
"0 10 -1.01929 0.398193 -0.397485 0.404733\n",
"\n",
"1 2 -1.01929 0.398193 -0.397485 0.404733\n",
"\n",
"2 6 -1.01929 -0.180908 -0.513013 0.278676\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 32%|██████ | 32/100 [00:00<00:00, 91.84nfev/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"3 6 -1.01929 -0.374512 -0.738574 0.230201\n",
"\n",
"4 4 -1.01929 -0.499756 -0.789917 0.198326\n",
"\n",
"5 2 -1.01929 -0.559326 -0.810059 0.176906\n",
"\n",
"6 2 -1.01929 -0.559326 -0.810059 0.176906\n",
"\n",
"7 4 -1.01929 -0.5625 -0.850708 0.160571\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 56%|██████████▋ | 56/100 [00:00<00:00, 79.03nfev/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"8 6 -1.01929 -0.61084 -0.878979 0.129153\n",
"\n",
"9 4 -1.01929 -0.660889 -0.883984 0.119255\n",
"\n",
"10 2 -1.01929 -0.660889 -0.883984 0.119255\n",
"\n",
"11 8 -1.01929 -0.701172 -0.894385 0.102736\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 79%|███████████████ | 79/100 [00:00<00:00, 76.97nfev/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"12 10 -1.01929 -0.841797 -0.938281 0.0651745\n",
"\n",
"13 13 -1.01929 0.190186 -0.485571 0.35726\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 99%|██████████████████▊| 99/100 [00:01<00:00, 77.06nfev/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"14 8 -1.01929 -0.227051 -0.597925 0.29594\n",
"\n",
"15 0 -1.01929 -0.227051 -0.597925 0.29594\n",
"\n",
"16 6 -1.40649 -0.386475 -0.795483 0.271876\n",
"\n",
"17 6 -1.5061 -0.566162 -0.907983 0.307864\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fitness Evaluations: 105nfev [00:01, 80.39nfev/s] "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"18 6 -1.5061 -0.566162 -0.907983 0.307864\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
},
{
"data": {
"text/plain": [
" fun: array(-1.50610352)\n",
" gen: 19\n",
" log: {'gen': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 'nfev': [10, 2, 6, 6, 4, 2, 2, 4, 6, 4, 2, 8, 10, 13, 8, 0, 6, 6, 6], 'min': [array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.01928711), array(-1.40649414), array(-1.50610352), array(-1.50610352)], 'max': [array(0.39819336), array(0.39819336), array(-0.1809082), array(-0.37451172), array(-0.49975586), array(-0.55932617), array(-0.55932617), array(-0.5625), array(-0.61083984), array(-0.66088867), array(-0.66088867), array(-0.70117188), array(-0.84179688), array(0.19018555), array(-0.22705078), array(-0.22705078), array(-0.38647461), array(-0.56616211), array(-0.56616211)], 'mean': [array(-0.39748535), array(-0.39748535), array(-0.5130127), array(-0.73857422), array(-0.78991699), array(-0.81005859), array(-0.81005859), array(-0.85070801), array(-0.87897949), array(-0.88398438), array(-0.88398438), array(-0.89438477), array(-0.93828125), array(-0.48557129), array(-0.5979248), array(-0.5979248), array(-0.7954834), array(-0.9079834), array(-0.9079834)], 'std': [array(0.40473292), array(0.40473292), array(0.27867585), array(0.23020122), array(0.19832642), array(0.17690649), array(0.17690649), array(0.16057095), array(0.12915256), array(0.11925523), array(0.11925523), array(0.10273635), array(0.06517446), array(0.35725997), array(0.29594042), array(0.29594042), array(0.27187597), array(0.30786416), array(0.30786416)]}\n",
" nfev: 105\n",
" x: array([5.11467318, 4.10246673, 4.38589537, 3.07366605])"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"res = optimizer.optimize(problem, 10, max_nfev=100, seed=42)\n",
"res"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Testing the optimal angles found"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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7rk7p2ORGtOzZ8/g7OyMmJgY9fe3LsVuD9CECRMwadIk9aGs2rVr4/79+5gzZw4GDBgAV1dXAMDjx481CqDHjx+jbt26WT6vtbU1rK2ttdotLS1haWmp0WZubg5zc3OtddPf3Lltz/y8+rbrWm5mZgYzM+1z3LPKvSiNKavcOSaOKbt2jolj4pgKf0y6KBSKYjEmrTxytVYRkpiYqLXhzM3N1dWhp6cnXF1dcfjwYfXy2NhY/PHHHwgKCjJorkRERFQ0Fbs9QJ07d8asWbPg5uaGmjVr4tKlS1i0aBEGDx4M4FUlOmbMGMycORNeXl7w9PTElClTUKFCBXTt2tW4yRMREVGRUOwKoK+//hpTpkzBhx9+iKioKFSoUAHvv/8+pk6dql7n448/RkJCAoYNG4YXL16gSZMm2LdvH0qUKGHEzImIiKioKHYnQRtKbGwsHB0dczyJytA8Ju3Octm9uSEGzISIiExFcfruye33d7E7B4iIiIgov1gAERERkclhAUREREQmhwUQERERmRwWQERERGRyWAARERGRyWEBRERERCaHBRARERGZHBZAREREZHJYABEREZHJYQFEREREJocFEBEREZkcFkBERERkclgAERERkclhAUREREQmhwUQERERmRwWQJStuXPnQqFQYMyYMeq2pKQkhIaGwtnZGXZ2dujevTseP35svCSJiIjyiAUQZen8+fP4/vvv4efnp9E+duxY/Pbbb9i8eTOOHz+OiIgIdOvWzUhZEhER5R0LINIpPj4effv2xY8//ojSpUur22NiYrBixQosWrQILVu2RP369bFq1SqcPn0aZ8+eNWLGREREuccCiHQKDQ1FSEgIWrdurdF+8eJFpKamarTXqFEDbm5uOHPmjKHTJCIi0ouFsROgomfjxo34888/cf78ea1lkZGRsLKyQqlSpTTay5Urh8jISANlSERElD8sgEhDeHg4Ro8ejYMHD6JEiRLGToeIiKhQ8BAYabh48SKioqJQr149WFhYwMLCAsePH8dXX30FCwsLlCtXDikpKXjx4oVG3OPHj+Hq6mqcpImIiPKIe4BIQ6tWrXDlyhWNtkGDBqFGjRqYOHEiKleuDEtLSxw+fBjdu3cHANy8eRMPHjxAUFCQMVImIiLKM+4BIg329vaoVauWxj9bW1s4OzujVq1acHR0xJAhQzBu3DgcPXoU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",
"text/plain": [
"