{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Qubit mapping and routing\n", "\n", "**Download this notebook - {nb-download}`mapping_example.ipynb`**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this tutorial we will show how the problem of mapping from logical quantum circuits to physically permitted circuits is solved automatically in TKET. The basic examples require only the installation of pytket, ```pip install pytket```." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a wide variety of different blueprints for realising quantum computers, including the well known superconducting and ion trap devices. Different devices come with different constraints, such as a limited primitive gate set for universal quantum computing. Often this limited gate set accommodates an additional constraint, that two-qubit gates can not be executed between all pairs of qubits." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In software, typically this constraint is presented as a \"connectivity\" graph where vertices connected by an edge represents pairs of physical qubits which two-qubit gates can be executed on. As programmers usually write logical quantum circuits with no sense of architecture (or may want to run their circuit on a range of hardware with different connectivity constraints), most quantum software development kits offer the means to automatically solve this constraint. One common way is to automatically add logical ```SWAP``` gates to a Circuit, changing the position of logical qubits on physical qubits until a two-qubit gate can be realised. This is an active area of research in quantum computing and a problem we discuss in our paper \"On The Qubit Routing Problem\" - arXiv:1902.08091." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In TKET this constraint is represented by the ```Architecture``` class. An Architecture object requires a coupling map to be created, a list of pairs of qubits which defines where two-qubit primitives may be executed. A coupling map can be produced naively by the integer indexing of nodes and edges in some architecture." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pytket.architecture import Architecture\n", "from pytket.circuit import Node" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import networkx as nx\n", "from typing import List, Union, Tuple" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def draw_graph(coupling_map: List[Union[Tuple[int, int], Tuple[Node, Node]]]):\n", " coupling_graph = nx.Graph(coupling_map)\n", " nx.draw(coupling_graph, labels={node: node for node in coupling_graph.nodes()})" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "simple_coupling_map = [(0, 1), (1, 2), (2, 3)]\n", "simple_architecture = Architecture(simple_coupling_map)\n", "draw_graph(simple_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively we could use the `Node` class to assign our nodes - you will see why this can be helpful later. Lets create an Architecture with an identical graph:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "node_0 = Node(\"e0\", 0)\n", "node_1 = Node(\"e1\", 1)\n", "node_2 = Node(\"e2\", 2)\n", "node_3 = Node(\"e3\", 3)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "id_coupling_map = [(node_0, node_1), (node_1, node_2), (node_2, node_3)]\n", "id_architecture = Architecture(id_coupling_map)\n", "draw_graph(id_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also create an ID with an arbitrary-dimensional index. Let us make a 2x2x2 cube:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "node_000 = Node(\"cube\", [0, 0, 0])\n", "node_001 = Node(\"cube\", [0, 0, 1])\n", "node_010 = Node(\"cube\", [0, 1, 0])\n", "node_011 = Node(\"cube\", [0, 1, 1])\n", "node_100 = Node(\"cube\", [1, 0, 0])\n", "node_101 = Node(\"cube\", [1, 0, 1])\n", "node_110 = Node(\"cube\", [1, 1, 0])\n", "node_111 = Node(\"cube\", [1, 1, 1])" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "cube_coupling_map = [\n", " (node_000, node_001),\n", " (node_000, node_010),\n", " (node_010, node_011),\n", " (node_001, node_011),\n", " (node_000, node_100),\n", " (node_001, node_101),\n", " (node_010, node_110),\n", " (node_011, node_111),\n", " (node_100, node_101),\n", " (node_100, node_110),\n", " (node_110, node_111),\n", " (node_101, node_111),\n", "]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAAHzCAYAAACe1o1DAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAvPVJREFUeJzs3XdUVOfWx/HvUASxoiJNEA2iRo3YWwxq7MJgpSsQjUTTTHK9ibnxTTfVJFdzYzBRQaWJioK9d8WGJXaNiFQBRRSUOu8fXueG2GmHgf1Zy7XCzJlzfqM5w55nn/M8Ko1Go0EIIYQQQohS0lM6gBBCCCGE0G1SUAohhBBCiDKRglIIIYQQQpSJFJRCCCGEEKJMpKAUQgghhBBlIgWlEEIIIYQoEykohRBCCCFEmUhBKYQQQgghykQKSiGEEEIIUSZSUAohhBBCiDKRglIIIYQQQpSJFJRCCCGEEKJMpKAUQgghhBBlIgWlEEIIIYQoEykohRBCCCFEmUhBKYQQQgghykQKSiGEEEIIUSZSUAohhBBCiDKRglIIIYQQQpSJFJRCCCGEEKJMpKAUQgghhBBlIgWlEEIIIYQoEykohRBCCCFEmUhBKYQQQgghykQKSiGEEEIIUSZSUAohhBBCiDKRglIIIYQQQpSJFJRCCCGEEKJMpKAUQgghhBBlIgWlEEIIIYQoEykohRBCCCFEmUhBKYQQQgghykQKSiGEEEIIUSZSUAohhBBCiDKRglIIIYQQQpSJFJRCCCGEEKJMpKAUQgghhBBlYqB0ACGEKG85eYXEZ+aQX1hMLQM97BrXoY6RfNwJIURFkU9YIUS1cCHtFiGxCWw/d42E67lo/vKcCrBtZEL/1k3x7mFLK/N6SsUUQohqSaXRaDRP3kwIIaqmq9dz+TDqJLsvZqCvp6Ko+NEfafef72vfhFmjOmDTyKQSkwohRPUlBaUQQmeFH0rg4+hTFBZrHltI/p2+ngoDPRWfqtvh0c22AhMKIUTNIAWlEEIn/bz9At9vOl/m/fxjsANv9G9VDomEEKLmkru8hRAVxs7ODmdn53Lb344dO1CpVKhUKt4c4EBeyoUy7/P7TeeJOJRQDunK37Rp07Tvt27dukrHEUKIR5KCUgihcxr1caex83sYNLTQPlZ4+zo3dgSRGjqDhB/GceVrZ+5eOfFU+/u/6FNcvZ770Oe+/PJL1Go15ubmqFQqPvnkk/J4C0RHR9O5c2eMjY2xtbXl448/prCwsMQ248ePZ8mSJfTt27dcjimEEBVFCkohhM4xsnOkbvv+6Nf+393ahZmJZB9YTtGtTGqZNX+m/RUWa/gw6uRDn/voo484dOgQnTp1KlPmv1q/fj0jR46kYcOGzJ07l5EjR/LFF1/w5ptvltiuS5cu+Pj40LJly3I7thBCVASZNkgIoTMS/zuKWPyQG3BqWdjT7O0w9GvXI+fsHvKSvn7q/RYVa9h9MYOL125h37TklEKXL1/Gzs6OjIwMzMzMyvYG/usf//gHL7zwAps2bcLA4N7HcP369Zk1axZvv/02bdq0KZfjCCFEZZERSiFECUlJSUycOBErKyuMjIxo0aIFU6ZMIT8/H4BPPvkElUr1wOuCgoJQqVTEx8c/8NymTZtwdHTE2NiY559/npUrVz6wTVZWFtOmTcPGxgYjIyPs7e355ptvKC4u1m6z5UzaI3PrGZmUGLF8Vvp6KpYeePBaSjs7u1Lv82FOnz7N6dOnmTx5sraYBJg6dSoajYbly5eX6/GEEKIyyAilEEIrOTmZ7t27k5WVxeTJk2nTpg1JSUksX76c3NxcatWq9cz7vHDhAu7u7rz22mv4+vqyaNEixo0bx4YNGxg0aBAAubm5ODk5kZSUREBAALa2tuzbt48ZM2aQkpLCTz/9BEDc1axyfLclFRVr2H7+Gp/QrsKOARAXFwdA165dSzxuZWVFs2bNtM8LIYQukYJSCKE1Y8YMUlNTiY2NLVHwfPbZZ5R2hrHz58+zYsUKRo8eDcDEiRNp06YN77//vrag/OGHH7h06RJxcXG0anVvCp+AgACsrKz47rvveO+99zBtakla9t0yvsPHS8jMJSevsEKXaUxJSQHA0tLygecsLS1JTk6usGMLIURFkZa3EAKA4uJiVq1ahYuLywOjZ8BD29xPw8rKilGjRml/rl+/PhMmTCAuLo7U1FQAIiMj6du3L6ampmRkZGj/DBw4kKKiInbt2sWVzJzSvbFnoAHiK/g4d+7cAcDIyOiB54yNjbXPCyGELpERSiEEAOnp6WRnZ9O+ffty3a+9vf0DxaiDgwMA8fHxWFhYcOHCBU6cOPHIm16uXbtGfmHxQ58rbxV9nNq1awOQl5f3wHN3797VPi+EELpECkohxDN51EhlUVFRqfdZXFzMoEGD+Oc///nQ5x0cHLhlUDkNlVoVfJz7re6UlBRsbGxKPJeSkkL37t0r9PhCCFERpKAUQgBgZmZG/fr1+eOPPx67nampKXDvruyGDRtqH79y5cpDt7948SIajaZEIXr+/L0lE+/fQf3cc89x+/ZtBg4c+Mjj5uQVPvK58qIC7BrXqdBjODo6AnD48OESxWNycjKJiYlMnjy5Qo8vhBAVQa6hFEIAoKenx8iRI4mJieHw4cMPPH//ppznnnsOgF27dmmfy8nJITg4+KH7TU5OJioqSvtzdnY2ixcvxtHREQuLeyvduLm5sX//fjZu3PjA67OysigsLCT+4jmMNA+2ictTYyMNtfRKd/PR02rXrh1t2rRh/vz5JUZ1582bh0qlYuzYsRV6fCGEqAgyQimE0Jo1axabNm3CycmJyZMn07ZtW1JSUoiMjGTPnj00bNiQwYMHY2try8SJE5k+fTr6+vosXLgQMzMzEhIenMfRwcGBiRMncujQIczNzVm4cCFpaWksWrRIu8306dOJjo7G2dkZPz8/unTpQk5ODseOHSMyMpKOHTty8OBBmvQa89j8WXvDASjIuJfj9qnt3E08DUDDPh7/2253CDf3hmHuOQvj5i/ce7C4iD/3rsXa+hW8vb3x8/OjY8eOLFmyhCtXrpCbe29S9V27dvHFF18A95ZGbN783qo8O3bsoH///nz88cdPXJ7xu+++Q61WM3jwYDw8PPjjjz/4+eefmTRpEm3btn3sa4UQoiqSglIIoWVtbU1sbCwzZ84kJCSE7OxsrK2tGTZsGCYmJgAYGhoSFRXF1KlTmTlzJhYWFkybNg1TU1P8/f0f2GerVq2YO3cu06dP59y5c7Ro0YKIiAiGDBmi3cbExISdO3cya9YsIiMjCQ4OxsDAgPz8fIqKiqhTpw7Lli0jByP89694ZP6bu5eW+DnnxGbtf/+1oNQU3AVU6Nc1/d/Gevos+b/JbFtVl6VLl/LTTz/h6OjIrVu3uHTpknaz7du3s337dgBefPFFbUF5+/Zt4OHTAf2ds7MzK1eu5NNPP+XNN9/EzMyMDz/8kP/7v/974muFEKIqUmlKO7mcEEKUo7y8PFasWEFgYCC7du2iSZMm+Pn5MXnyZO3clPdHAc3HfoShVVv0jOui0tN/5mOlBL+DQf2mmI2aAdxbJad3y8YsmdgDgIKCAjZs2EBQUBAxMTFoNBrt6Onw4cMxNDR8YJ///Oc/CQsL4+LFiw+dEqg0cnJyuHPnDm+++SYxMTHaolUIIaoauYZSCKGoCxcuMH36dJo1a4a3tzcqlYrQ0FASExP57rvvtMXkX6Ut/4LEOd7kp/35zMcrzssl/9plGvb10T5moKdi1qgO2p8NDQ1xcXFhxYoVJCcn88MPP5CQkMDIkSOxtrbmnXfe4fjx4yX2u337dmbOnFluxSTAv/71L8zMzAgPDy+3fQohREWQEUohRKXLz89n1apVBAYGsm3bNkxNTbWjkW3atHnk627cuMGRI0fYfu4av++5jJGlA3pGJmXO883oDrh3s33ididOnCA4OJilS5dy7do1HB0d8fPzw8vL65FzaJbF+fPntdelGhgY0K9fv3I/hhBClAcpKIUQlebPP/9k/vz5LFq0iGvXrtGnTx8CAgIYO3bsM0/o/fP2C3y/6XyZM00f3JrX+9s/02tK0xIXQojqTApKIUSFKigoICYmhsDAQDZt2kSDBg2YMGECAQEBtGvXrkz7Dj+UwMfRpygs1lBU/PQfZfp6Kgz0VHymbvdUI5OPk5GRQVhYGEFBQRw9ehQzM7MSd4kLIURNIAWlEKJCXLlyhd9++40FCxaQmppKz549CQgIwM3NTXvHeHm4ej2XD6NOsvtiBvp6qscWlpriIlR6+vS1b8KsUR2waVR+OQBOnjxJcHAwS5YsqZSWuBBCVBVSUAohyk1hYSFr164lMDCQDRs2ULduXcaPH8/kyZMrfLTuQtotQmIT2H7+GgmZufz1g00FWNWvxZlty/lwXF/+MdnnUbspFwUFBWzcuJGgoCCio6PRaDSMGDFC2xKvVatWhR5fCCEqmxSUQogyS0xM5Pfff+f3338nKSmJrl27EhAQgIeHB3Xr1q30PDl5hcRn5pBfWEwtAz3sGtehjpEBL7/8MkVFRezYsaPSsmRmZmpb4keOHKFJkybalvj9ZRiFEELXSUEphCiVoqIiNmzYQGBgIGvXrqV27dp4e3sTEBBA586dlY73UCEhIfj4+HDx4kXtEpKV6e8t8Y4dO2pb4k2bNq30PEIIUV6koBRCPJPk5GQWLFjA77//TkJCAp06dSIgIAAvLy/q1aundLzHys3NxdLSkrfeeovPP/9csRzSEhdCVDdSUAohnqi4uJjNmzcTGBhIdHQ0RkZGeHh4EBAQQLdu3VCpVEpHfGqvvfYa69at4/Lly+jrP/sqO+VNWuJCiOpACkohxCOlpaWxcOFCfvvtNy5fvkyHDh0ICAjAx8eHBg0aKB2vVGJjY+nZsycbN25k8ODBSscp4X5LfOnSpaSlpUlLXAihM6SgFEKUUFxczLZt2wgMDGTVqlUYGBjg7u5OQEAAPXv21KnRyIfRaDS0a9eOjh07EhYWpnSch5KWuBBC10hBKYQAID09naCgIObPn8/Fixdp27YtAQEBTJgwAVNTU6Xjlavvv/+ejz76iJSUlCr/3qQlLoTQBVJQClGDaTQadu7cSWBgICtXrkSlUjF27FgCAgJ48cUXdX408lFSU1Np1qwZc+bMYerUqUrHeWp/b4m/8MIL+Pn54e3tLS1xIYSipKAUogbKzMwkODiY+fPnc+7cORwcHAgICMDX15fGjRsrHa9SqNVqUlJSOHTokNJRntnDWuLDhw/Hz8+PESNGSEtcCFHppKAUoobQaDTs2bOHwMBAli9fTnFxMaNHj+a1117Dycmp2o5GPsqqVasYNWoUJ06coEOHDkrHKbXMzEzCw8MJCgri8OHDNG7cuERLvKb9uwohlCEFpRDV3I0bN1iyZAmBgYGcPn2a5557jsmTJ+Pn51ej26QFBQVYW1vj4+PDDz/8oHSccvHHH39oJ06XlrgQojJJQSlENaTRaDhw4ACBgYFERERQWFjIyJEjCQgIYMCAAejp6SkdsUp49913Wbp0KUlJSRgaGiodp9wUFhaWaIkXFxdLS1wIUaGkoBSiGrl58yZLly4lMDCQkydPYmdnx6uvvsorr7yChYWF0vGqnD/++IMOHToQFRXFyJEjlY5TIaQlLoSoDFJQCqHjNBoNhw8fJjAwkLCwMPLy8nBxcSEgIIDBgwfLaOQTdOvWDUtLS6Kjo5WOUuGkJS6EqChSUAqho27dukVoaCiBgYHExcVhY2OjHY20trZWOp7O+OWXX3jrrbdITEysMaO40hIXQpQ3KSiF0DFHjx4lMDCQ0NBQcnNzGTFiBAEBAQwdOrRKrE2ta27cuIGlpSWff/4506dPVzpOpZOWuBCiPEhBKYQOyMnJITw8nMDAQA4dOoSVlRWTJk1i0qRJ2NjYKB1P53l6enL8+HFOnTpVowsoaYkLIUpLCkohqrATJ04QGBjI0qVLuXXrFkOHDiUgIIARI0ZgYGCgdLxqY/PmzQwePJgDBw7Qo0cPpeMorrCwkE2bNhEUFMTq1aulJS6EeCIpKIWoYnJzc1m2bBmBgYEcOHAACwsLJk6cyKRJk7Czs1M6XrVUVFREixYtGDZsGIGBgUrHqVKuX7+ubYkfOnSIxo0b4+XlhZ+fH506darRI7pCiP+RglKIKuL06dMEBgayePFisrKyGDRoEAEBAajV6mo1R2JVNXPmTObMmUNKSgomJiZKx6mSTp06pW2Jp6am0qFDB21L3NzcXOl4QggFSUEphILu3r3L8uXLCQwMZM+ePZiZmfHKK6/w6quv8txzzykdr0a5dOkS9vb2LF26FG9vb6XjVGl/b4kXFRVpW+LOzs7SEheiBpKCUggFnD17lvnz5xMcHMz169cZMGAAAQEBjBw5Un4ZK6hfv37o6+uzdetWpaPoDGmJCyFACkohKk1eXh5RUVH8+uuv7Ny5k8aNG+Pn58fkyZNxcHBQOp4AgoOD8fPz4/Lly3K9ailIS1yImksKSiEq2MWLF5k/fz6LFi0iIyODl156iYCAAEaPHo2xsbHS8cRf5OTkYGFhwXvvvccnn3yidBydJS1xIWoeKSiFqAD5+fmsXr2awMBAtm7diqmpKb6+vkyePJm2bdsqHU88xqRJk9iyZQt//vmnLFtZDqQlLkTNIAWlEOXozz//5LfffmPRokWkpaXRu3dvXnvtNcaOHUvt2rWVjieewt69e3nxxRfZunUrAwYMUDpOtXL69GmCg4NZvHixtMSFqGakoBSijAoKClizZg2BgYFs2rSJ+vXrM378eAICAmjfvr3S8cQz0mg0tGnThm7durF06VKl41RLhYWFbN68maCgIFatWkVRURHDhg3TtsSNjIyUjiiEeEZSUApRSleuXOH3339nwYIFpKSk0KNHDwICAnB3d5d5DHXc119/zaeffkpqaioNGjRQOk61dv36dSIiIggKCuLgwYM0atRI2xLv3LmztMSF0BFSUArxDAoLC1m/fj2//vor69evp27dunh7exMQEICjo6PS8UQ5SU5OxsbGhnnz5jF58mSl49QYf2+Jt2/fXtsSt7CwUDqeEOIxpKAU4ikkJiayYMECfv/9dxITE+nSpQsBAQF4enpSt25dpeOJCjBixAgyMzM5cOCA0lFqHGmJC6F7pKAU4hGKiorYuHEjgYGBrFmzhtq1a+Pl5UVAQABdunRROp6oYMuXL2fcuHGcPn1a7sxXkLTEhdANUlAK8TcpKSna0cgrV67QsWNHXnvtNby8vKhfv77S8UQlycvLw9ramldeeYVvv/1W6TiC/7XElyxZQkpKirTEhahCpKAUAiguLmbLli0EBgayevVqatWqhYeHBwEBAXTv3l1GQWqot99+m4iICK5evYqhoaHSccR/SUtciKpHCkpRo6WlpbFo0SJ+++03/vzzT9q3b09AQAA+Pj40bNhQ6XhCYceOHaNTp05ER0fj4uKidBzxENISF6JqkIJS1DjFxcVs376dwMBAVq1ahb6+Pm5ubgQEBNCrVy/5BSRK6Ny5M82bNycqKkrpKOIJ/t4Sb9euHX5+fvj4+EhLXIgKJgWlqDEyMjIICgoiMDCQixcv0qZNGwICApgwYQKNGjVSOp6ooubOncu7775LUlISTZs2VTqOeAoPa4kPHToUPz8/XFxcpCUuRAWQglJUaxqNhl27dhEYGMiKFSsAGDt2LAEBAfTt21dGI8UTZWZmYmVlxddff80777yjdBzxjG7cuKFticfGxmJqaqptiXfp0kU+A4QoJ1JQimrp+vXrBAcHM3/+fM6ePUurVq0ICAjA19eXJk2aKB1P6Bg3NzfOnDnDiRMnpADRYWfOnNFOnC4tcSHKlxSUotrQaDTs27ePX3/9lcjISIqLixk1ahQBAQH0799fCgFRauvXr2f48OEcOnSIrl27Kh1HlFFhYSFbtmzRtsQLCwulJS5EGUlBKXReVlYWS5YsITAwkFOnTtGyZUsmT56Mv7+/XPMmykVRURHNmzfH1dWV//znP0rHEeVIWuJClA8pKIVO0mg0xMbGEhgYSEREBAUFBbi6uhIQEMDLL7+Mnp6e0hFFNfPhhx8yb948UlJSMDY2VjqOqADSEhei9KSgFDolOzubpUuXEhgYyIkTJ7Czs+PVV1/F398fS0tLpeOJauz8+fO0bt2asLAwPDw8lI4jKpC0xIV4dlJQCp1w+PBhAgMDCQ0NJS8vD2dnZ1577TUGDRqEvr6+0vFEDdG3b19q167Npk2blI4iKom0xIV4OlJQiirr1q1bhIWFERgYyNGjR7GxsWHSpElMnDgRa2trpeOJGmjhwoVMmjSJ+Ph4bG1tlY4jKtn9lviSJUtITk7WtsS9vb2lQyJqPCkoRZUTFxdHYGAgISEh5ObmMnz4cAICAhg2bJiMRgpF3bp1CwsLC2bMmMFHH32kdByhkKKiIm1LPCoqSlriQiAFpagicnJyiIiIIDAwkIMHD2JlZcXEiROZNGmSjASJKsXf359du3Zx4cIFuflLcOPGDZYtW0ZQUBAHDhzA1NQUT09P/Pz86Nq1q7TERY0hBaVQ1MmTJwkMDGTJkiXcunWLIUOGEBAQgLOzMwYGBkrHE+IBu3btwsnJiR07duDk5KR0HFGFnD17VnuXeHJyMs8//7z2LnFpiYvqTgpKUenu3LnDsmXLCAwMZP/+/Zibm2tHI1u0aKF0PCEeS6PR0KpVK1588UWCgoKUjiOqoL+3xAsKCkq0xGXaKVEdSUEpKs2ZM2cIDAwkODiYrKwsBg4cyGuvvYZarcbQ0FDpeEI8tS+//JJZs2aRmppKvXr1lI4jqrCsrCztXeLSEhfVmRSUokLdvXuXFStWEBgYyO7duzEzM8Pf359XX30Ve3t7peMJUSpXr16lefPm/Pbbb0ycOFHpOEJHSEtcVGdSUIoKce7cOebPn09wcDCZmZn079+fgIAARo4cKXdAimphyJAh5OTksGfPHqWjCB0jLXFRHUlBKcpNXl4eUVFRBAYGsmPHDho1aoS/vz+TJ0/GwcFB6XhClKuIiAg8PDw4e/YsrVu3VjqO0FHSEhfVhRSUoswuXbrE/PnzWbRoEenp6fTt25eAgADGjBkj37RFtXX37l0sLS157bXX+Oqrr5SOI6oBaYkLXSYFpSiVgoICVq9eTWBgIFu2bKFhw4b4+voyefJknn/+eaXjCVEp3njjDVauXElCQoJMcyXKzcNa4kOGDMHPzw+1Wi1f1EWVJAWleCaXL1/mt99+Y+HChaSlpdG7d28CAgIYN24ctWvXVjqeEJXqyJEjdO3albVr1zJ8+HCl44hq6O8t8YYNG2pb4t26dZOWuKgypKAUT1RYWMiaNWsIDAxk48aN1KtXj/HjxxMQEECHDh2UjieEYjQaDR07dqR169ZERkYqHUdUc+fOndO2xJOSkmjbtq22JW5lZVVpOXLyConPzCG/sJhaBnrYNa5DHSMZoa/ppKAUj5SQkMDvv//OggULSE5Opnv37gQEBODu7k6dOnWUjidElfDTTz/xz3/+k+TkZJo0aaJ0HFEDFBUVsXXrVm1LPD8/v8Jb4hfSbhESm8D2c9dIuJ7LXwsHFWDbyIT+rZvi3cOWVuYyN2tNJAWlKKGoqIh169YRGBjI+vXrMTExwcfHh4CAABwdHZWOJ0SVk56ejpWVFbNnz+att95SOo6oYbKysrRrie/fv7/cW+JXr+fyYdRJdl/MQF9PRVHxo0uG+8/3tW/CrFEdsGlkUqZjC90iBaUAICkpiQULFvD7779z9epVOnfuzGuvvYanpyd169ZVOp4QVdro0aO5fPkycXFxSkcRNVh5t8TDDyXwcfQpCos1jy0k/05fT4WBnopP1e3w6Gb7zMcVukkKyhqsqKiITZs2ERgYyJo1azA2NsbT05OAgAC6du2qdDwhdMaaNWtwcXHh6NGjdOrUSek4ooYrj5b4z9sv8P2m82XO8o/BDrzRv1WZ9yOqPj2lA4jKl5KSwpdffslzzz3H8OHDiY+PZ+7cuSQnJ/Pbb79JMSnEMxo6dCgWFhYsWrRI6SiiBrGzs8PZ2fmBx/X19Rk8eDChoaGkpKQwb948srKycHd3x9LSkqlTp3Lw4EH+Pp60Y8cOVCoVKpWKNwc4kJdyocwZv990nohDCWXeT0X46aeftO9XpVKRkZGhdCSdJgVlDVFcXMzmzZsZO3Ystra2fPnll/Tv35/9+/cTFxfHlClTqF+/vtIxhdBJBgYGjB8/npCQEPLy8pSOI4RWw4YNmTx5Mvv27ePs2bNMmTKF6OhoevToQbt27fj2229JTk4u8ZpGfdxp7PweBg0ttI8V3r7OjR1BpIbOIOGHcVz52pm7V048VYb/iz7F1eu5D33uyy+/RK1WY25ujkql4pNPPin1e70vIiICHx8fWrVqhUqlol+/fg/dbujQoSxZsoRRo0aV+ZhCCspq79q1a3zzzTe0atWKwYMHc/bsWX744QeSk5NZtGgRPXv2lHnMhCgH/v7+XL9+nejoaKWjCPFQrVu3ZtasWVy5coWNGzfi6OjIxx9/jI2NDcOHD2f79u0AGNk5Urd9f/Rr/+9u7cLMRLIPLKfoVia1zJo/03ELizV8GHXyoc999NFHHDp0qFwvFZk3bx6rV6/GxsYGU1PTR27Xpk0bfHx8eOGFF8rt2DWZTBxVDWk0GrZv305gYCBRUVHo6enh5ubG4sWL6d27txSQQlSAtm3b0rNnTxYtWsS4ceOUjiPEI91viQ8ePJibN29q7xL/8qd5ABQ/5AacWhb2NHs7DP3a9cg5u4e8pK+f+nhFxRp2X8zg4rVb2DctOaXQ5cuXsbOzIyMjAzMzs7K9sf9asmQJ1tbW6Onp0b59+3LZp3gyGaGsRjIyMpg9ezatW7fm5Zdf5vjx49p2xuLFi+nTp48Uk0JUoFdeeYWNGzeSlJSkdBRRRSUlJTFx4kSsrKwwMjKiRYsWTJkyhfz8fAA++eSTh35OBwUFoVKpiI+Pf+C5TZs24ejoiLGxMc8//zwrV658YJusrCymTZuGjY0NRkZG2Nvb880331CvXj1effVV9u7di+vUmY/MrWdkUmLE8lnp66lYeuDBaynt7OxKvc9HsbGxQU9PypvKJn/jOk6j0bBr1y68vb2xtrbmww8/pGvXruzYsYMzZ84wbdo0GjVqpHRMIWoEd3d3jIyMWLx4sdJRRBV0f4GI8PBw3N3dmTNnDuPHj2fnzp3k5j78GsMnuXDhAu7u7gwbNoyvvvoKAwMDxo0bx+bNm7Xb5Obm4uTkxNKlS5kwYQJz5syhT58+zJgxg3fffVe73cUbhWV+j49SVKxh+/lrFbZ/oTxpeeuo69evs3jxYubPn8+ZM2do1aoVX375JX5+frJahxAKqV+/PmPGjGHRokV88MEH0hEQJcyYMYPU1FRiY2NLzKbx2WefPXDH9dM6f/48K1asYPTo0QBMnDiRNm3a8P777zNo0CAAfvjhBy5dukRcXBytWt2bwicgIAArKyu+++473nvvPUybWpKWfbeM7/DxEjJzyckrlGUaqykZodQhGo2GvXv3MmHCBKytrfnnP/9Jhw4d2Lp1K2fPnuUf//iHFJNCKOyVV17hwoUL7N27V+koogopLi5m1apVuLi4PHRqttJ++bCysipxl3L9+vWZMGECcXFxpKamAhAZGUnfvn0xNTUlIyND+2fgwIEUFRWxa9curmTmlO6NPQMNEF8JxxHKkK8JOiArK4ulS5cSGBjIH3/8QYsWLfj444/x9/fH3Nxc6XhCiL9wcnLCzs6ORYsW8eKLLyodR1QR6enpZGdnl/tNIvb29g8Uow4ODgDEx8djYWHBhQsXOHHixCNverl27Rr5hcXlmutRKus4ovJJQVlFaTQaDh48SGBgIOHh4eTn5+Pq6srs2bMZOHCgXHAsRBWlp6eHn58f33//Pf/+979l6VLxTB41UllUVFTqfRYXFzNo0CD++c9/PvR5BwcHbhlUzu+UWpV0HFH5pKCsYrKzswkJCSEwMJDjx4/TvHlz/vWvf/HKK69gaWmpdDwhxFPw8/Pj008/Zfny5fj5+SkdR1QBZmZm1K9fnz/++OOx292fNzErK4uGDRtqH79y5cpDt7948SIajaZEIXr+/L0lE+/fQf3cc89x+/ZtBg4c+Mjj5uRV3A0596kAu8Z1Kvw4QhnyVaGKOHLkCJMnT8bKyoo33niD5s2bs3btWi5dusS//vUvKSaF0CHNmzdnwIABshSj0NLT02PkyJHExMRw+PDhB56/f1POc889B8CuXbu0z+Xk5BAcHPzQ/SYnJxMVFaX9OTs7m8WLF+Po6IiFxb2Vbtzc3Ni/fz8bN2584PVZWVlkZWWxankE+gW3S/8Gn4JtYxO5Iacak39ZBd2+fZuwsDACAwM5cuQIzZo1Y/r06UycOJFmzZopHU8IUQb+/v74+Phw8eJF7O3tlY4jqoBZs2axadMmnJycmDx5Mm3btiUlJYXIyEj27NlDw4YNGTx4MLa2tkycOJHp06ejr6/PwoULMTMzIyHhwXkcHRwcmDhxIocOHcLc3JyFCxeSlpZW4svM9OnTiY6OxtnZGT8/P7p06UJ2djYbN25k165dGBoacufOHZoP8n1s/qy94QAUZNzLcfvUdu4mngagYR+P/223O4Sbe8Mw95yFcfN7q9Do66no79D0gX0uWbKEK1euaKdN2rVrF1988QUA48ePp3nze6vy7Nixg/79+/Pxxx8/cXnGXbt2aQvy9PR0cnJytPt86aWXeOmllx77elE6Nb6gzMkrJD4zh/zCYmoZ6GHXuE6Ff4M6duwYgYGBhISEcPv2bYYPH050dDTDhg3DwKDG/5MIUS2MHj2aBg0aEBQUpP1lJmo2a2trYmNjmTlzJiEhIWRnZ2Ntbc2wYcMwMTEBwNDQkKioKKZOncrMmTOxsLBg2rRpmJqa4u/v/8A+W7Vqxdy5c5k+fTrnzp2jRYsWREREMGTIEO02JiYm7Ny5ky+//JKlS5eycOFCNBoNGo0Gc3NzXn/9dXx8fNgbd4bxmx8+Egpwc/fSEj/nnPjfXJd/LSg1BXcBFfp1/7fsYVGxBp+etg/sc8GCBezcuVP78/bt27VLQL744ovagvL27Xujp0/Trdu2bRuffvppicdmzrw3afvHH38sBWUFUWlKO/mVDruQdouQ2AS2n7tGwvVc/voXoAJsG5nQv3VTvHvY0sq89CsD/FVubi4REREEBgYSGxuLpaUlEydOZNKkSdoTRghRvbz22musXbuW+Ph49PX1lY4jaqiTJ08SGhpKWFgYV65coVmzZnh5eeHl5cULL7ygvf7y/iig+diPMLRqi55xXVR6z/7/bUrwOxjUb4rZqBnAvdHJ3i0bs2Rij1K/h3/+85+EhYVx8eJFjIyMSr2fv7p79y63b9/m22+/5bvvviM9PV2m3iuDGjUcdvV6Lh9GnWT3xQz09VQUPWS9Ug1w5XouS2KvELQ/nr72TZg1qgM2jUxKdcw//viDwMBAlixZQnZ2NoMHD2blypU4OztjaGhYxnckhKjKXnnlFQIDA9myZUuJESMhKtqVK1cICwsjNDSUkydPYmpqyrhx4/D29ubFF1987Ewhacvvjahb+P6IkWWrZzpucV4u+dcu02TE/1bgMdBTMWtUh9K9kf/avn07M2fOLLdiEuDXX3/lnXfeKbf91XQ1ZoQy/FACH0eforBY89BC8lH09VQY6Kn4VN0Oj24PDtc/zJ07d4iMjCQwMJB9+/Zhbm7OK6+8wquvvkqLFi1K+xaEEDpGo9HQvn17OnToQHh4uNJxRDWXmZlJZGQkISEh7NmzB2NjY1xdXfHy8mLo0KHUqlXrsa+/ceMGR44cYfu5a/y+5zJGlg7oGZVuMOWvvhndAfen/P1Zma5evcq5c+e0Pzs5OclATxnUiILy5+0X+H7T+TLv5x+DHXij/6O/rZ05c4b58+cTHBzMjRs3ePnllwkICMDV1fWJJ7IQonr6/vvv+eijj0hOTqZRo0ZKxxHVTE5ODjExMYSEhLBhwwbtnJPe3t6MHDmSevVKd9lWef3enD64Na/3l5vSaoIqMW2QnZ0dzs7O5ba/HTt2oFKptH++DF5bLvv9ftN5Ig6VvMsuLy+P0NBQnJyceP7551m6dCmTJk3iwoULbNmyhXHjxlV4MTly5Ejtey3vVRiEEGUzfvx4CgsLCQsLUzqKqCYKCgpYv34948ePx9zcHE9PT9LT0/nhhx9ITk5mw4YNjB8/vtTFJMAb/Vvx9egOGBnooa/3bMtC6uupMDLQ45vRHaSYrEGqREFZUd54ZzoWrv/AoKGF9rHC29e5sSOI1NAZJPwwjitfO3P3yomn3uf/RZ/i6vVczp8/zz/+8Q+sra3x9vZGpVLh6elJnTp1mDNnDqNHjy6XXyALFiygbdu2GBsba+/m+7t33nmHJUuW0KZNmzIfTwhRvszNzRkxYoTMSSnKRKPRsH//ft544w2sra0ZPnw4hw4d4v333+fixYscOHCAN998s1yX4/XoZsuWd5zo3bIxwJMLS829ZRV7t2zMlnecqmSbW1Scal1QntW3w6Rdf/Rr/+9bWmFmItkHllN0K5NaZs9+d3VBYRGD/7WI1q1bs2jRInx9fTl79iy9evUiLCyMwYMHM3fuXGxtbfHy8irTdVOBgYFMmjSJdu3aMXfuXHr16sVbb73FN998U2I7JycnfHx8ZF1vIaoof39/jhw5wokTT//lVQiA06dP89FHH/Hcc8/Ru3dvoqKimDBhAkeOHOHMmTPMnDlTOxl6RbBpZMKSiT3YPO0lxvdoTvPGJvy9rFQB9bhD/qktbHizD0sm9ij1jaxCd1WJayjt7Oxo3749a9asKZf9aac++MukqvcV5+WiKS5Cv3Y9cs7uIWPV1w/d7knesr/JVO/RGBsbk5SURIsWLZg8eTI///wzcO/bpJOTE5cvXy7VlCF37tzBxsaGnj17lvh78fHxYdWqVVy9elW7RNd9/fr1IyMj44lLewkhKldBQYF2qpYff/xR6TiiiktMTNTeoX3s2DEaNGjA2LFj8fb25qWXXlJ8CqqHzd986vhRevTowc6dO2Wexxqq1COUSUlJTJw4ESsrK4yMjGjRogVTpkwhPz8fgE8++eShi9wHBQWhUqmIj49/4LlNmzbh6OiIsbExzz//PCtXrnxgm6ysLKZNm4aNjQ1GRkbY29vzzTffUFxc/OCbe8jwvJ6RSYkRy9LQ11ORbdYRY2NjAFavXk1BQQFTp07VbqNSqZgyZQqJiYns37//mY+xfft2MjMzS+wT4PXXXycnJ4e1a8vnulAhRMUzNDTEx8eHpUuXaj8jhfir69ev89tvv9GvXz9sbW2ZOXMm9vb2rFy5krS0NH7//Xf69++veDEJUMfIgHZWDehka0o7qwbUMTKga9euWFhYEB0drXQ8oZBSFZTJycl0796d8PBw3N3dmTNnDuPHj2fnzp3a5ZOe1YULF3B3d2fYsGF89dVXGBgYMG7cODZv/t9M/Lm5uTg5ObF06VImTJjAnDlz6NOnDzNmzODdd999YJ/FzzA90LMoKtaw/fw17c9xcXHUqVOHtm3bltiue/fu2uef1f3XdO3atcTjXbp0QU9Pr1T7FEIox9/fn4yMjHLrxAjdd+fOHZYtW8bIkSOxsLDgtddew9DQULt8YmRkJKNGjSrXuRcrip6eHi4uLqxevZoq0PgUCijVxOYzZswgNTWV2NjYEgXPZ599Vur/kc6fP8+KFSsYPXo0ABMnTqRNmza8//77DBo0CIAffviBS5cuERcXR6tW96bvCQgIwMrKiu+++4733nsPGxsb7uQXlSrDs0jIzCUnr5A6RgakpKRgbm7+wIjs/SWikpOTn3n/KSkp6Ovr07RpybVPa9WqRePGjUu1TyGEctq3b0+3bt1YtGiR9nNO1DyFhYVs27aNkJAQoqKiuHXrFt26dePbb7/F3d39qZYWrKpcXV357bffOHv27AMDLKL6e+YRyuLiYlatWoWLi8sDo2fAQ9vcT8PKyopRo0Zpf65fvz4TJkwgLi6O1NRUACIjI+nbty+mpqZkZGRo/wwcOJCioiLtYvCp2XdKleFZaID4zBzg3rfMh32DvN8Sv3Pn2fPcuXPnkdMNGRsbl2qfQghl+fv7s379elJSUpSOIiqRRqMhNjaWt99+m2bNmjFkyBD279/Pe++9x7lz5zh48CDTpk3T6WISYMCAAZiYmEjbu4Z65oIyPT2d7Ozscp/v0N7e/oFi1MHBAUB7veWFCxfYsGEDZmZmJf4MHDgQgGvX7rWhC4sqZ7g9v/DedZu1a9cmLy/vgefv3r2rff5Z1a5d+5HXWt29e7dU+xRCKMvDwwMDAwOWLFmidBRRCc6dO8fHH3+Mg4MDPXv2ZNmyZXh6enLo0KESz1UXtWvXZvDgwVJQ1lAVtpb3o0Yqi4pK346+vwLAP//5z4c+f//ENNAv3Sjps6plcK8et7S0ZPv27Wg0mhLv+/4ohJWV1TPv29LSkqKiIq5du1ai7Z2fn09mZmap9imEUJapqSmjR49m0aJFTJ8+vdQdHVF1JScnEx4eTmhoKEeOHKFevXqMGTOGefPmVZmbaiqSWq1m4sSJD/zuEtXfMxeUZmZm1K9f/4lT09yf0iYrK4uGDRtqH79y5cpDt7948eIDBdn58/eWfbKzswPgueee4/bt29oRyUexqF/xo3cqwK5xHQAcHR35/fffOXPmDM8//7x2m9jYWO3zz+r+aw4fPszw4cO1jx8+fJji4uJS7VMIoTx/f3/CwsKIjY2lZ8+eSscR5SArK4uVK1cSEhLC9u3bMTQ0ZMSIEXzwwQeMGDGiRnWURowYAcDatWvx9/dXOI2oTM/c8tbT02PkyJHExMRw+PDhB56/f1PO/YlW71/XCPfWHA0ODn7ofpOTk4mKitL+nJ2dzeLFi3F0dMTC4t5KN25ubuzfv5+NGzc+8PqsrCwKCwsBqF2r4r8BNmtoRB2je/W4q6srhoaG/PLLL9rnNRoNv/76K9bW1vTu3fuZ9z9gwAAaNWrEvHnzSjw+b948TExMtCetEEK3DBgwAFtbWxYuXKh0FFEGd+/eZcWKFYwZMwYLCwsmTZqERqPht99+IzU1lZUrVzJ27NgaVUwCNG3alF69eknbuwYqVct71qxZbNq0CScnJyZPnkzbtm1JSUkhMjKSPXv20LBhQwYPHoytrS0TJ05k+vTp6Ovrs3DhQszMzEhISHhgnw4ODkycOJFDhw5hbm6unTbhr8uVTZ8+nejoaJydnfHz86NLly7k5ORw8uRJli9fTnx8PE2aNNFu/7B5KAGy9t5bvaYg416O26e2czfxNAAN+3j8b7vdIdzcG/bAxOea4iLObFvBmIPz8PPzY+jQoUybNo3vvvuOgoICunXrxqpVq9i9ezchISElWhxBQUH4+/uzaNEi/Pz8Hvl3XLt2bT7//HNef/11xo0bx5AhQ9i9ezdLly7lyy+/pFGjRo/7JxJCVFH6+vr4+vry008/8dNPP2FiIiuK6IqioiJ27NhBSEgIK1asIDs7m86dO/Pll1/i4eGBtbW10hGrBFdXVz799FPu3LlT4wrqmqxUBaW1tTWxsbHMnDmTkJAQsrOzsba2ZtiwYdoPR0NDQ6Kiopg6dSozZ87EwsKCadOmYWpq+tBh8PvrVE+fPp1z587RokULIiIiGDJkiHYbExMTdu7cyaxZs4iMjGTx4sXUr18fBwcHPv30Uxo0aFBin4+ah/Lm7qUlfs458b+5Lv9aUGoK7gIq9OuWXJFGpafP1MEdiF4yH7VaTdOmTfH29uatt95i9erVBAUF0apVK5YuXYqXl1eJ196+fRvgqe7mmzp1KoaGhsyePZvo6GhsbGz48ccfefvtt5/4WiFE1eXn58fnn3/OypUr8fHxUTqOeAyNRsORI0cIDQ0lPDyclJQUWrZsydtvv42np6dMj/MQarWa999/n61bt+Ls7Kx0HFFJqsTSi+Xt/tKLTq9/S7xhMzS16qDSe/Y2eErwOxjUb4rZqBnax/T1VPRu2ZglE3sAcOzYMYKDg1m6dCkZGRl06dIFPz8/PD09ady48QP7dHNzIz4+noMHD5b+Df7NrVu3yMvLw9XVlZs3b8rSi0LogP79+6NSqdi2bZvSUcRDXLhwgdDQUEJDQzl//jxNmzbF3d0db29vunfvLjdUPYZGo6F169b069eP+fPnKx1HVJJSL72oC3b+559c+cmL/LQ/n/m1xXm55F+7TMO+JUcPDPRUzBrVQfuzo6MjP/74I0lJSaxatQobGxveeecdLC0tGTNmDDExMRQUFAD3TrIdO3bwxRdflO2N/c348eMxMzNj37595bpfIUTF8ff3Z/v27Vy+fFnpKOK/UlNT+fe//0337t1xcHDg+++/p2fPnmzYsIGkpCTmzJlDjx49pJh8ApVKhVqtJiYm5qHLIovqqVqOUN64cYMjR44AsP3cNZZcMkTPqHyuU/pmdAfcu9k+dpv09HRCQ0MJCgri2LFjNG3aFB8fH/z8/OjQocNjX1saJ06c0M7BWbduXblzVAgdkJOTg6WlJe+88w6ffvqp0nFqrOzsbFauXEloaChbt25FX1+fYcOG4e3tjbOzs1zjWkq7du3CycmJ2NhY7TLEonqrlgXl3/28/QLfbzpf5v1MH9ya1/vbP9Nr/t4S79y5s7Yl/tcbiIQQNc+rr77K5s2b+fPPP9HTq9YNoyolLy+P9evXExoaSkxMDHfv3sXJyQkvLy/Gjh0rNz2Wg8LCQszNzZkyZUq5d+VE1VQjCkqA8EMJfBx9isJiDUWPuFnnYfT1VBjoqfhM3e6JI5OPk5+fz/r16wkKCmLNmjWoVCpcXFy0d4kbGhqWet9CCN20b98++vTpw5YtW3j55ZeVjlOtFRcXs2vXLkJCQli+fDlZWVl07NgRb29vPDw8sLGxUTpitePr68vRo0c5efKk0lFEJagxBSXA1eu5fBh1kt0XM9DXUz22sLz/fF/7Jswa1QGbRuXX9qjslrgQomrSaDS0bduWLl26EBISonScakej0XDs2DFCQ0MJCwsjKSkJOzs7vLy88PLyol27dkpHrNZWrFjB2LFjuXTpEi1btlQ6jqhgNaqgvO9C2i1CYhPYfv4aCZm5lPwL0FBwPQW3vu14fXAH7JvWq9As0hIXomb75ptv+OSTT0hJSSmxqpgovT///FN7h/aZM2do0qQJ7u7ueHl50atXL7mpppLcunWLJk2a8O2338p0dzVAjSwo/yonr5D4zBzyC4upZaBHEyMNtlbmfPPNN0ybNq3SckhLXIiaKTk5GRsbG3755RcCAgKUjqOzrl27xrJlywgJCeHAgQPUqVOHkSNH4u3tzcCBA+UzVCHDhg0jPz+frVu3Kh1FVLAaX1A+zLBhw8jLy1NsfjhpiQtRszg7O5Oenk5sbKzSUXTKrVu3WLVqFaGhoWzevBmVSsXQoUPx8vJCrVZTp04dpSPWePPmzePNN98kPT0dU1PTJ79A6Cy5rfAh1Go1u3bt4saNG4oc38zMjLfffpu4uDji4uLw8vJi8eLFvPDCC3Tp0oW5c+eSkZGhSDYhRPnz9/fn4MGDnDp1SukoVV5+fj4xMTF4eHhgbm7OhAkTuH37Nj///DMpKSnExMTg6ekpxWQV4eLiQlFRERs2bFA6iqhgMkL5EImJidjY2BASEvLA0olKkZa4ENVXfn4+VlZW+Pn58f333ysdp8opLi5mz549hIaGEhkZyfXr12nfvj3e3t54enrSvHlzpSOKx+jatSv29vaEh4crHUVUICkoH6FLly60atWqSp4A0hIXovqZNm0aYWFhJCYmyhfE/zpx4gQhISGEhYVx9epVbG1t8fT0xNvbWz7rdMhnn33G7NmzSU9Pp1atWkrHERVECspH0JUTQO4SF6J6OH78OI6OjqxevRq1Wq10HMXEx8cTFhZGaGgof/zxB40aNcLNzQ0vLy/69OkjE8DroGPHjtGpUyc2b97MwIEDlY4jKogUlI+gayeAtMSF0H2dO3fG1taWVatWKR2lUmVkZBAZGUlISAh79+6ldu3auLq64u3tzeDBg6v0l3rxZBqNhubNmzNy5EjmzJmjdBxRQaSgfIT7J4Crqytz585VOs4zkZa4ELrp559/5p133iEpKYmmTZsqHadC5eTksHr1akJDQ9m4cSMajYbBgwfj5eXFyJEjqVu3rtIRRTl64403WLNmDZcvX5Z5QKspKSgf44033iAmJob4+HidPQGkJS6E7rh+/TqWlpZ89dVXvPvuu0rHKXcFBQVs3ryZkJAQVq1aRW5uLr169cLb25tx48ZV+yK6Jtu0aRNDhgzh+PHjvPDCC0rHERVACsrHuH8CHDt2jI4dOyodp0ykJS6EbnBzc+P06dOcPHlSZ7/I/pVGo2Hfvn2EhoaybNkyMjIyaNu2rfYObVmSr2bIz8+nSZMmTJ8+nZkzZyodR1QAKSgfIy8vDzMzs2p3AkhLXIiqa8OGDQwbNoyDBw/SrVs3peOU2qlTp7R3aMfHx9OsWTM8PT3x8vKiY8eO1aJYFs/G3d2dP//8k0OHDikdRVQAKSifwM3NjcuXL1fbE0Ba4kJULUVFRTRv3hy1Ws0vv/yidJxnkpCQQHh4OCEhIZw4cYKGDRsybtw4vL296du3r9yhXcOFhITg4+NDYmIi1tbWSscR5UzO7idwdXXl8OHDJCUlKR2lQjg6OvLjjz+SlJTEqlWrsLW15d1338XKyooxY8YQExNDQUGB0jGFqDH09fXx9fUlNDSUO3fuKB3nia5fv05gYCBOTk40b96cjz/+mDZt2rBq1SpSU1OZP38+Tk5OUkwKhg0bhr6+PmvWrFE6iqgAMkL5BNevX6dp06b85z//ISAgQOk4lUJa4kIo68KFCzg4OBAaGoqnp6fScR6Qm5tLTEwMISEhbNiwgaKiIgYOHIiXlxejRo2ifv36SkcUVVT//v0xMTFh7dq1SkcR5UwKyqfQv39/ateuzbp165SOUumkJS6EMvr27YuxsTGbN29WOgoAhYWFbN26lZCQEKKiorh9+zbdu3fH29sbNzc3LCwslI4odMCPP/7IjBkzyMjIkKmhqhkpKJ/Cjz/+yAcffEBmZmaNPQHkLnEhKteiRYuYOHEi8fHx2NraKpJBo9EQGxtLaGgoERERXLt2DQcHB7y9vfHy8sLe3l6RXEJ3Xbp0CXt7e1asWMHo0aOVjiPKkRSUT0FOgJIe1RL39fWV+cWEKCe3b9/GwsKC999/v9JnmTh79iwhISGEhoby559/Ymlpqb1Du3PnznKHtiiT9u3b07VrV4KCgpSOIsqRFJRPqV27dnTr1k1OgL+RlrgQFcff35+dO3dy8eLFCr+pJSkpSXuHdlxcHA0aNGDMmDF4e3vj5OSEvr5+hR5f1Bwffvgh8+fPJy0tTf6/qkakoHxKM2bM4LfffpMT4BGkJS5E+du9ezcvvfQS27dvp1+/fuW+/xs3brBixQpCQ0PZsWMHtWrVwtnZGS8vL4YPH46xsXG5H1OIAwcO0KtXL3bv3s2LL76odBxRTqSgfEpyAjy99PR0wsLCCAoKIi4uTlriQpSSRqPBwcGB3r17ExwcXC77vHPnDmvXriUkJIR169ZRUFDAgAED8Pb2ZvTo0TRo0KBcjiPEoxQXF2NpaYmvry/ffvut0nFEOZGC8inJCVA6x48fJygoSNsS79SpE35+fnh5eUlLXIin8OWXX/Lll1+Smppa6ul4ioqK2LZtG6GhoaxcuZLs7Gy6du2Kl5cXHh4eWFpalnNqIR5v0qRJ7N69m3PnzikdRZQTKSifgZwApfewlrizszP+/v7SEhfiMRITE7G1tWX+/PlMmjTpqV+n0Wg4fPgwISEhREREkJqair29vXYN7datW1dgaiEeLyYmBrVazdmzZ+X/xWpCCspnEB0djaurq5wAZSQtcSGezdChQ8nOzmbfvn1P3Pb8+fOEhoYSGhrKhQsXMDc3x8PDA29vb7p27Sp3aIsqITc3lyZNmvDpp58yffp0peOIciAF5TPIzc2lcePGfPbZZ3IClJPjx49r7xJPT0+XlrgQDxEREYGHhwdnzpyhTZs2DzyfkpJCREQEISEhHD58mHr16jFmzBi8vLzo378/BgYGCqQW4vFcXV25fv06u3fvVjqKKAdSUD4jtVrNjRs35AQoZwUFBdqWeExMjLYl7ufnx7Bhw6QlLmq0u3fvYmVlxeTJk/n6668BuHnzJitXriQ0NJRt27ZhYGDA8OHD8fb2ZsSIEdSuXVvh1EI83oIFC5g8eTKpqamYmZkpHUeUUcVObFYNubq6sm/fPtLT05WOUq0YGhqiVqtZuXIlycnJfP/998THx+Pq6oq1tTXvvvsuJ06cUDqmEIowNjbGy8uLoKAgli9fztixYzE3N2fixIkUFRURGBhIamoqUVFRjB07VopJoROcnZ3RaDQ1clnj6khGKJ9RWloalpaWLFq0CF9fX6XjVHvSEhc1XVFRETt37mTOnDmsXr0agE6dOuHt7Y27uzvNmjVTOKEQpderVy8sLS1ZuXKl0lFEGUlBWQpyAlQ+aYmLmkSj0RAXF0dISAjh4eEkJyfTsmVLbt++TceOHdm0aZPSEYUoF19//TWff/45mZmZMpG+jpOWdymo1Wo2btzI3bt3lY5SY0hLXNQEly5d4vPPP6dt27Z06dKFJUuWMHr0aPbv38/FixeZMWMGO3bsICMjQ+moQpQLtVpNbm4u27ZtUzqKKCMZoSyFU6dO0b59e9auXcvw4cOVjlOjSUtc6Lq0tDQiIiIIDQ0lNjaWunXrMmrUKLy8vBg4cGCJO7TT09Oxtrbmu+++4+2331YwtRDlQ6PR0KpVKwYOHMivv/6qdBxRBlJQloJGo8He3p5BgwbJCVBFSEtc6JLs7GxWrVpFSEgIW7ZsQU9Pj2HDhuHt7Y2LiwsmJiaPfO2YMWO4ePEix44dkzklRbXw7rvvEhERwdWrV9HTk8aprpJ/uVJQqVSo1WpiYmIoLi5WOo5AWuKi6svPz2f16tW4u7tjbm6Or68vd+/e5ZdffiE1NZXo6Gjc3d0fW0wC+Pv7c+LECeLi4iopuRAVS61Wk5yczNGjR5WOIspARihLaceOHfTv359Dhw7RtWtXpeOIR5CWuFBScXExu3fvJiQkhOXLl3Pjxg1eeOEFvL298fDwwNbW9pn3WVhYiI2NDWPHjmXu3LkVkFqIylVYWEjTpk15/fXX+fzzz5WOI0pJCspSKigowNzcnDfeeIPPPvtM6TjiCaQlLiqLRqPhxIkThISEEBYWRmJiIs2bN8fLywsvLy/at29f5mO8//77/PbbbyQnJ8udsaJaGD9+PCdOnOD48eNKRxGlJAVlGfj4+HDy5Ek5AXTM39cSNzMzw8fHBz8/P1lLXJTa5cuXCQsLIyQkhNOnT9O4cWPc3d3x8vKid+/e5Xq949mzZ2nbti0RERG4ubmV236FUEpkZCRubm5cvnwZOzs7peOIUpCCsgyWLVuGu7u7nAA6TFrioizS09NZtmwZoaGh7Nu3DxMTE0aOHIm3tzeDBg2q0JHv3r1706BBA9avX19hxxCismRnZ9OkSRNmz57Nm2++qXQcUQpSUJbBzZs3MTMzkxOgGpCWuHhat2/fZvXq1YSEhLBp0yZUKhVDhgzBy8sLV1dX6tSpUyk5fvvtNwICAkhISJDVckS1MGTIEIqLi9m8ebPSUUQpSEFZRoMHD0aj0cgJUI1IS1z8XUFBARs3biQ0NJTVq1eTm5tLnz598Pb2ZuzYsZiZmVV6puzsbCwsLPjoo4/48MMPK/34QpS3//znP0ybNo2MjAwaNGigdBzxjKSgLCM5Aao3aYnXXMXFxezbt4+QkBAiIyPJzMykXbt2eHt74+npWSUuc5kwYQL79+/n/PnzMiel0HkJCQk0b96csLAwPDw8lI4jnpEUlGV0/wQIDw/H3d1d6TiigkhLvOY4efIkoaGhhIWFceXKFWxsbPD09MTb25sOHTpUqcJt+/btDBgwgF27dtG3b1+l4whRZp07d6ZNmzaEhoYqHUU8Iykoy0GnTp14/vnnCQkJUTqKqATSEq9+rly5QlhYGKGhoZw8eZJGjRoxbtw4vLy8ePHFF6vs6h3FxcXY29vTr18/Fi5cqHQcIcrsk08+4aeffiI9PV2+qOsYKSjLwccff8ycOXO4du2anAA1jLTEdVdmZiaRkZGEhISwZ88eateujVqtxtvbmyFDhlCrVi2lIz6Vzz77jG+//ZbU1FTq1q2rdBwhyuTo0aN06dKFrVu3MmDAAKXjiGdQNb926xi1Wk1WVha7d+9WOoqoZB07duSHH34gKSmJ1atXY2dnx3vvvYeVlRWjR48mOjqagoICpWOK/8rJySEsLAwXFxcsLCx44403qFu3LosXLyYtLY3w8HBcXFx0ppgE8PX1JTc3l8jISKWjCFFmnTp1wtramujoaKWjiGckI5TlQKPR0KxZM8aNG8dPP/2kdByhMGmJVy0FBQVs2bKFkJAQVq1aRU5ODr169cLLy4tx48Zhbm6udMQyGzRoEHl5eezatUvpKEKU2dSpU9mwYQOXLl2qUtcsi8eTgrKcTJkyhY0bN8oJIEqQlrgyNBoN+/fvJzQ0lGXLlpGenk6bNm3w9vbGy8uLli1bKh2xXIWGhuLt7c358+dp1aqV0nGEKJMNGzYwbNgwTpw4QYcOHZSOI56SFJTl5P4JcPLkyXJZq1dUL3KXeOU4ffo0ISEhhIaGEh8fj7W1NZ6ennh5eeHo6Fhtv+zduXMHS0tLXn/9db788kul4whRJnl5eTRp0oQPPviAf/3rX0rHEU9JCspycv8EmDFjhkwyLB5LWuLl6+rVq4SHhxMSEsLx48dp2LAhY8eOxdvbm759+6Kvr690xEoxZcoUYmJiuHLlSo15z6L6GjduHAkJCcTGxiodRTwlKSjL0dixY0lMTOTAgQNKRxE6QlripXP9+nWWL19OaGgou3btwsjICBcXF7y8vBg2bBhGRkZKR6x0Bw8epEePHqxfv56hQ4cqHUeIMlmyZAkTJkwgOTkZS0tLpeOIpyAFZTlavHgxvr6+cgKIZ1ZQUMCGDRu0LXFAWuJ/c+fOHWJiYggNDWXdunUUFRXx8ssv4+3tzahRo6hfv77SERWl0Wjo0KED7dq1IyIiQuk4QpRJZmYmTZs25ddff+XVV19VOo54ClJQlqOMjAzMzc3lBBBlkpGRQWhoaImWuLe3N35+fnTs2LHScuTkFRKfmUN+YTG1DPSwa1yHOkYGlXZ8gMLCQrZt20ZISAgrV67k9u3bdO/eHS8vL9zd3bGwsKjUPFXd7Nmz+fDDD0lJSaFRo0ZKxxGiTJycnKhfv772S7ao2qSgLGcvvfQSDRo0kBNAlIu/t8QdHR3x8/PD29u7QlriF9JuERKbwPZz10i4nstfPxxUgG0jE/q3bop3D1tamdcr9+PDvZG2gwcPEhoaSkREBGlpaTg4OGjX0Ja7mB8tLS0Na2trfvrpJ9544w2l4whRJrNnz+ajjz4iIyODOnXqKB1HPIEUlOVMTgBRESq6JX71ei4fRp1k98UM9PVUFBU/+mPh/vN97Zswa1QHbBqZlOnY9507d057h/alS5ewtLTEw8MDb29vOnfuXG3v0C5vI0eO5OrVqxw5ckTpKEKUyYULF3BwcCAqKoqRI0cqHUc8gRSU5ez+CbBq1SpcXV2VjiOqoYyMDO1d4kePHi1zSzz8UAIfR5+isFjz2ELy7/T1VBjoqfhU3Q6PbrbPfFyApKQkIiIiCAkJ4ejRo9SvX5+xY8fi5eVFv3795G7lUli9ejUjR47k2LFjlXqJhBAV4fnnn6dnz56yVr0OkIKyArRt25bevXuzYMECpaOIau7EiRPalvi1a9e0LXEvLy/MzMye+Pqft1/g+03ny5zjH4MdeKP/07Wis7KyWLFiBaGhoWzfvh1DQ0OcnZ3x8vJixIgRGBsblzlPTVZQUECzZs3w9PSUlbuEzvvggw9YuHAhKSkp8gWzipO1vCuAWq0mJiaGoqIipaOIasDOzg5nZ+eHPvfCCy8we/ZsEhMTiY6OpmXLlkyfPh0rKytGjRrF6tWrH1hLfMeOHahUKlQqFW8OcCAv5UKZM36/6TwRhxIe+fzdu3dZsWIFo0ePxtzcXHvT2u+//05aWhorVqxgzJgxFVJMTps2Tft+69atW+77r2oMDQ0ZP348S5cuJT8/X+k4QpSJWq0mPT1d5qPUAVJQVgA5AURlMzQ0xMXFhRUrVpCcnMwPP/xAQkICI0eOxNramnfeeYfjx4+XeE2jPu40dn4Pg4b/u1O68PZ1buwIIjV0Bgk/jOPK187cvXLiqTL8X/Qprl7P1f5cVFTEli1beOWVV2jatCljx45l7dq1FBcX06ZNGyZNmsQrr7xCw4YNS/We582bx7hx47C1tUWlUuHn5/fQ7caPH8+SJUvo27dvqY6ji/z9/cnMzJSbA4XO69GjB2ZmZqxevVrpKOIJpKCsAD179qRJkyZER0crHUXUQE2aNOHNN9/kyJEjHD9+nPHjxxMaGoqjoyOdOnVi+fLlABjZOVK3fX/0a//vbu3CzESyDyyn6FYmtcyaP9NxC4s1zIg6yeHDh3nnnXdo1qwZgwYNYteuXdoVgHx9ffnll19o2bIlXl5ehIeHl/p9fvPNN2zbto127dphYPDo6Yy6dOmCj49PtVu/+3HatWtHt27dWLRokdJRhCgTfX19nJ2d5fepDpCCsgLICSCqioe1xH8LXQFA8UNuwKllYU+zt8OwDphPvW4jn+lYRcUa9lzMoNfQUYSGhuLm5kZsbCw7duzg4MGDvP7668yfP59XX32VmJgY+vbty/Tp00t9acjOnTvJyMhg/fr1NXJlnCd55ZVXWL9+PcnJyUpHEaJMXF1dOXv2LOfPl/16b1FxpKCsIK6urpw5c4YLF8p+fZrQPUlJSUycOBErKyuMjIxo0aIFU6ZM0V7T9sknnzx0GpygoCBUKhXx8fEPPLdp0yYcHR0xNjbm+eefZ+XKlQ9sk5WVxbRp07CxscHIyAh7e3u++eYb9PX1tS3x0W9+8sjcekYmJUYsn5mmmPGfzCcpKYl///vfdO/enejoaAoKCpg6dap2M5VKxZQpU0hMTGT//v2lOlTz5s1lKqHH8PDwoFatWixZskTpKEKUycCBAzE2NpZLOKo4KSgryKBBgzAyMpIToAZKTk6me/fuhIeH4+7uzpw5cxg/fjw7d+4kNzf3yTt4iAsXLuDu7s6wYcP46quvMDAwYNy4cWzevFm7TW5uLk5OTixdupQJEyYwZ84c+vTpw4wZM3j33Xe1251OK12Gp6LS49Jd4xIt6Li4OOrUqUPbtm1LbNq9e3ft86L8NWzYkFGjRrFo0SJkMg+hy+rUqcPAgQOl61fFVe46ajXIX0+Av/4yF9XfjBkzSE1NJTY2lq5du2of/+yzz0r9i/38+fPau6QBJk6cSJs2bXj//fcZNGgQAD/88AOXLl0iLi5Ou5pMQEAAVlZWfPfdd7z33nuYNrUkLftuGd/h4yVk5pKTV6hdpjElJQVzc/MHRhPvr3cvLdmK88orrxAWFsaBAwfo1auX0nGEKDW1Ws1rr71GZmYmjRs3VjqOeAgZoaxAarWa3bt3k5mZqXQUUUmKi4tZtWoVLi4uJYrJ+0rbor0/DdB99evXZ8KECcTFxZGamgpAZGQkffv2xdTUlIyMDO2fgQMHUlRUxK5du7iSmVO6N/YMNED8X45z586dh17jeH+KoDt37lR4pppqwIAB2NrayqTQQuc5OztTXFzM2rVrlY4iHkEKygp0/wRYt26d0lFEJUlPTyc7O5v27duX637t7e0fKEYdHBwAtNdbXrhwgQ0bNmBmZlbiz8CBAwG4du0a+YXF5ZrrUf56nNq1a5OXl/fANnfv3tU+LyqGnp4efn5+REREkJNT8V8mhKgolpaW2muyRdUkBWUFsrKyolu3bnICiAc8aqSyLJPhFxcXM2jQIDZv3vzQP2PGjKGWQeWc8n89jqWlJampqQ+0+1NSUoB754moOH5+fty6dYsVK1YoHUWIMnF1dWXDhg3aL6OiapGCsoLdPwEeNkIjqh8zMzPq16/PH3/88djtTE1NgXt3Zf/VlStXHrr9xYsXHyjI7k+hYWdnB8Bzzz3H7du3GThw4EP/2NraYte4Tine1bNRQYnjODo6kpuby5kzZ0psd3/if0dHxwrPVJO1aNGCfv36yZyUQuep1WpycnLYsWOH0lHEQ0hBWcHUajW3b9+WE6CG0NPTY+TIkcTExHD48OEHnr9fFD733HMA7Nq1S/tcTk4OwcHBD91vcnIyUVFR2p+zs7NZvHgxjo6OWFjcW+nGzc2N/fv3s3Hjxgden5WVRWHhvRtlzOtX7FrZto1NtDfkwL0vVYaGhvzyyy/axzQaDb/++ivW1tb07t27QvOIezfn7Nixgz///FPpKEKUWrt27WjRooV0/aooucu7grVv3x47Ozuio6MZMmSI0nFEJZg1axabNm3CycmJyZMn07ZtW1JSUoiMjGTPnj00bNiQwYMHY2try8SJE5k+fTr6+vosXLgQMzMzEhIeXBPbwcGBiRMncujQIczNzVm4cCFpaWklRp2mT59OdHQ0zs7O+Pn50aVLF3Jycjh58iTLly8nPj6eJk2a0MmmIY9bTDFr773Vawoy7uW4fWo7dxNPA9Cwj8f/ttsdws29YZh7zsK4+b2VcPT1VPR3aFpif82aNWPatGl89913FBQU0K1bN1atWsXu3bsJCQlBX19fu21QUBD+/v4sWrTokUsp3hcTE6NdTrKgoIATJ07wxRdfAPe+yN1fnUfAmDFjeP311wkKCuKzzz5TOo4QpaJSqVCr1Sxfvpz//Oc/Mg9tFSMFZQW7fwKsXLmSn3/+WU6AGsDa2prY2FhmzpxJSEgI2dnZWFtbM2zYMExMTIB7a29HRUUxdepUZs6ciYWFBdOmTcPU1BR/f/8H9tmqVSvmzp3L9OnTOXfuHC1atCAiIqLElxQTExN27tzJrFmziIyMZPHixdSvXx8HBwc+/fRTGjRoAMDAtuY8fBz0npu7l5b4OefE/+a6/GtBqSm4C6jQr2uqfayoWINPT9sH9vn1119jampKYGAgQUFBtGrViqVLl+Ll5VViu9u3bwP/m1LocVasWFFiRDcuLk47p2WzZs2koPwLExMT3N3dCQ4O5pNPPkFPT5pTQjep1Wr+/e9/c/ToUbp06aJ0HPEXKo3MeFvhtm7dysCBAzly5AidO3dWOo6o4Xbs2EH//v0xH/sRhlZt0TOui0pP/8kv/JuU4HcwqN8Us1EzgHujk71bNmbJxB6lzubm5kZ8fDwHDx4s9T7+Licnhzt37vDmm28SExOjLVprmv3799O7d282b96svfNfCF1TUFBA06ZNeeutt/j000+VjiP+Qr6mVoKXXnqJBg0ayHUfokpJW/4FiXO8yU979uvqivNyyb92mYZ9fbSPGeipmDWqQ6nzaDQaduzYoW1bl5d//etfmJmZER4eXq771TU9e/akdevWMiel0GmGhoYMHz5cfp9WQTJCWUk8PT05d+4cR48eVTqKqOFu3LjBkSNH2H7uGr/vuYyRpQN6RiZl3u83ozvg3u3BdrfSzp8/r70u1cDAgH79+ikbSEHffPMNH3/8MSkpKdqZBoTQNREREXh4eHDlyhVsbaveZ05NJQVlJQkPD8fT05OEhARsbGyUjiMEAD9vv8D3m86XeT/TB7fm9f725ZBIVKSUlBRsbGyYO3cuU6ZMUTqOEKVy8+ZNmjRpwk8//cTrr7+udBzxX9LyriRDhw7FwMCAmJgYpaMIofVG/1Z8PboDRgZ66Os92w1j+noqjAz0+GZ0BykmdYSlpSVDhw6VOSmFTmvQoAH9+vWTtncVIwVlJWnYsCFOTk5yAogqx6ObLVvecaJ3y8YATywsNcX3VvPp3bIxW95xqpJtbvFor7zyCocOHXri5PtCVGVqtZrt27dz8+ZNpaOI/5KCshKp1Wq2bdtGdna20lGEKMGmkQlLJvZg87SXGN+jOc0bm/D3slIFNG9sQovCqxSs/j+C/Lpi06js116KyuXs7EyTJk1klFLoNLVaTUFBwUMXchDKkGsoK9Hly5dp2bIly5YtY9y4cUrHEeKxcvIKic/MIb+wmFoGetg1rkMdIwMOHTpE9+7d2bBhg0zWr6OmTZtGWFgYiYmJGBoaKh1HiFJxdHSkffv2LF269MkbiwonI5SVqEWLFnTo0EHa3kIn1DEyoJ1VAzrZmtLOqoF2OcWuXbvStm3bRy4TKao+f39/rl27xrp165SOIkSpqdVq1q5dS0FBgdJRBFJQVjpXV1fWrl1LYWGh0lGEKBWVSoWvry9RUVFy/ZKO6tixI507d5Y5KYVOU6vVZGVlsXfvXqWjCKSgrHRqtZobN27ICSB0mo+PD/n5+URGRiodRZSSv78/a9euJS0tTekoQpRK586dsbKykq5fFSEFZSXr0qULlpaWcgIInWZtbc3AgQOl7a3DvLy80NfXl+vPhM7S09PDxcWF1atXI7eDKE8KykomJ4CoLnx9fdmzZw+XLl1SOooohUaNGjFy5EgWLlwon0VCZ6nVav78809Onz6tdJQaTwpKBajVai5dusTZs2eVjiJEqY0cOZJ69eqxZMkSpaOIUvL39+f06dMcOnRI6ShClMqAAQOoU6eOdP2qACkoFTBgwABMTExYvXq10lGEKDUTExPc3NxYvHgxxcXFSscRpTBo0CCsra3l5hyhs4yNjRkyZIgUlFWAFJQKqF27NoMHD5YTQOi8CRMmcPnyZfbs2aN0FFEK+vr6+Pr6Eh4ezp07d5SOI0SpqNVqYmNjSU1NVTpKjSYFpUJcXV05cOCA3GEpdNqLL75IixYt5OYcHebv78/NmzeJiopSOooQpTJ8+HBUKhVr1qxROkqNJgWlQkaMGAHA2rVrFU4iROnp6ekxYcIEIiMjyc3NVTqOKAV7e3v69u0rbW+hs8zMzOjdu7d0/RQmBaVC5AQQ1cWECRO4deuWjHDpMH9/f7Zt28aVK1eUjiJEqajVajZv3ixfbBUkBaWC1Go1mzZtkmuXhE5r2bIlffv2lba3Dhs3bhwmJibybyh0lqurK3fv3mXLli1KR6mxpKBUkFqt5s6dO2zdulXpKEKUia+vL1u2bCExMVHpKKIU6tati5ubG4sWLZI79oVOcnBwoHXr1tL1U5AUlApq3bo1rVq1kumDhM4bN24cxsbGsuqKDvP39yc+Pp6dO3cqHUWIUlGr1cTExMiXIoVIQakglUqFq6urnABC59WvX59Ro0axePFiWXVFR7344ovY29uzaNEipaMIUSpqtZpr164RGxurdJQaSQpKhanVatLS0mSlCqHzJkyYwJkzZzh8+LDSUUQpqFQq/P39Wb58OTdv3lQ6jhDPrFevXjRu3Fja3gqRglJhcgKI6mLgwIFYWVnJjR06bMKECeTl5bFs2TKlowjxzPT19XF2dpbfpwqRglJhBgYGjBgxQk4AofP09fXx8fEhLCyMvLw8peOIUmjWrBmDBw+WOSmFznJ1deX06dNcvHhR6Sg1jhSUVYBareaPP/7gzz//VDqKEGXi6+vL9evXZcJ+Hebv78+BAwc4c+aM0lGEeGaDBg3CyMiImJgYpaPUOFJQVgGDBw+mVq1aMkopdN7zzz9P165dpe2tw9RqNaampgQFBSkdRYhnVrduXV5++WX5faoAKSirgHr16jFgwAA5AUS14Ovry7p160hPT1c6iigFY2NjvL29Wbx4MYWFhUrHEeKZqdVqdu/ezfXr15WOUqNIQVlFuLq6smvXLm7cuKF0FCHKxNPTE5VKRWhoqNJRRCn5+/uTmprKhg0blI4ixDNzdnamqKiIdevWKR2lRpGCsoq4fwKsX79e6ShClEnjxo1xdnaWtrcO69SpEx07diwxJ2VOXiGnkm8Sl3CDU8k3ycmT0UtRNVlbW9O1a1fp+lUyA6UDiHuaNWtGly5diI6OxsvLS+k4QpSJr68vI0eO5OTJk3To0EHpOOIZ3Z+T8oOvfuL9iMMcSLhFwvVc/jplvQqwbWRC/9ZN8e5hSyvzekrFFeIBrq6ufPvtt+Tl5WFkZKR0nBpBRiirELVazfr168nPz1c6ihBlMmzYMBo3bszixYuVjiJK4er1XPYZdcbc/2eWHUvlyt+KSQANcOV6LktirzDop12MXxDL1eu5SsQV4gFqtZpbt27JUqKVSArKKkStVpOdnc2uXbuUjiJEmdSqVQsvLy+WLl0qN3bomPBDCQz8cSeHr94CQIPqsdsXFd8rNff9mcnAH3cSfiihwjMK8SQdOnSgefPm0vauRFJQViEdO3bExsaG1atXKx1FiDLz9fUlNTWVzZs3Kx1FPKWft1/gg5UnySss1haKT6uoWENeYTEfrDzJz9svVFBCIZ6OSqVCrVYTHR2NRvNs/y+L0pGCsgqRE0BUJ507d6Zdu3Zyc46OCD+UwPebzpfLvr7fdJ4IGakUClOr1Vy9epVjx44pHaVGkIKyinF1dSUhIYETJ04oHUWIMlGpVPj6+rJq1SqysrKUjlNt2NnZ4ezsXG7727FjByqVCs/uzbnytTN5KeUzuvh/0aeq5DWVI0eORKVSoVKpaN++vdJxRAV66aWXqF+/vrS9K4kUlFWMk5MT9erVkxNAVAs+Pj4UFBSwbNkypaOIJ2jY243Gzu9h0NCixOPFd2+TuX4uV//tRcLsMaSGziAv9cnrJBcWa/gw6uQDj9++fZuPP/6YoUOH0qhRI1QqVbmtyrNgwQLatm2LsbExrVq1Yu7cuQ9s884777BkyRLatGlTLscUVVetWrUYPny4/D6tJFJQVjG1atVi2LBhcgKIasHS0pLBgwdL27sKS/zvKKJRc0fqtu+Pfu3/Tf+j0RRzLfJTck7vpF4XZ0z7+VOce5O00BkUXE967H6LijXsvpjBxWu3SjyekZHBZ599xpkzZ+jYsWO5vY/AwEAmTZpEu3btmDt3Lr169eKtt97im2++KbGdk5MTPj4+mJubl9uxRdWlVqs5evQoiYmJSkep9qSgrILUajWHDx8mKenxH9hC6AJfX1/27dvHhQtyo0ZVtOVM2iOfyz27l7ykMzQeMY2GL3pRr4sz5l5foVLpkbXnySsh6eupWHqg5LWUlpaWpKSkcOXKFb777rsy5we4c+cO//rXvxgxYgTLly/n1VdfZfHixXh7e/P555/LCmQ12NChQzEwMCAmJkbpKNWeFJRV0LBhw9DX12fNmjVKRxGizFxdXalfvz5LlixROopikpKSmDhxIlZWVhgZGdGiRQumTJminXP2k08+QaV6cHqeoKAgVCoV8fHxDzy3adMmHB0dMTY25vnnn2flypUPbJOVlcW0adOwsbHByMgIe3t7vvnmG4qLi7XbxF3NemTu3HN70avTEJPWvbWP6Zs0wKRtX+5cOICmsOCx77uoWMP289dKPGZkZISFhcUjXlE627dvJzMzk6lTp5Z4/PXXXycnJ4e1a9eW6/GE7jA1NeWll16S2VMqgRSUVVCjRo3o27evnACiWqhduzZubm4sXry4RCFTUyQnJ9O9e3fCw8Nxd3dnzpw5jB8/np07d5KbW7qbVi5cuIC7uzvDhg3jq6++wsDAgHHjxpWYoik3NxcnJyeWLl3KhAkTmDNnDn369GHGjBm8++67ANzOKyQt++4jj5Ofdola5s+hUpX8VVHL0gFNQd4T294ACZm5Fb5MY1xcHABdu3Yt8XiXLl3Q09PTPi9qJrVazbZt28jOzlY6SrUmSy9WUa6urrz//vvcvn2bunXrKh1HiDLx9fXl999/Z9euXfTr10/pOJVqxowZpKamEhsbW6Lg+eyzz0o9Pdj58+dZsWIFo0ePBmDixIm0adOG999/n0GDBgHwww8/cOnSJeLi4mjVqhUAAQEBWFlZ8d133/Hee++RrV//sccpun0DI5sH74Q2qGv63+czoandY/ehAeIzc2hn1eAZ3+XTS0lJQV9fn6ZNm5Z4vFatWjRu3Jjk5OQKO7ao+tRqNdOmTWPTpk2MHTtW6TjVloxQVlEuLi7k5+ezadMmpaMIUWZ9+vThueeeq3E35xQXF7Nq1SpcXFweGD0DHtrmfhpWVlaMGjVK+3P9+vWZMGECcXFxpKamAhAZGUnfvn0xNTUlIyND+2fgwIEUFRWxa9cu8gsfP2KsKcxHpW/44BP6tbTPP40nHaes7ty5Q61atR76nLGxMXfu3KnQ44uqrUWLFnTo0EFudq1gUlBWUc899xzt2rWTE0BUCyqVigkTJrB8+XJycnKUjlNp0tPTyc7OLvf5Du3t7R8oRh0cHAC011teuHCBDRs2YGZmVuLPwIEDAbh27Rq1DB7/K0BlUAtN0UOukyzK1z7/NJ50nLKqXbu29nrUv7t79y61a9eu0OOLqk+tVrN27VpZCrYCSUFZhanVatasWUNRUZHSUYQoswkTJnD79u2H3jxS0z1qpLIs535xcTGDBg1i8+bND/0zZswY7BrXeew+9OuaUnT7+gOPF96+8d/nGz8xhwqeeJyysrS0pKioiGvXSt4AlJ+fT2ZmJlZWVhV6fFH1qdVqrl+/zr59+5SOUm1JQVmFqdVqMjMz2b9/v9JRhCgzOzs7nJycalTb28zMjPr16/PHH388djtT03vXJP59RaErV648dPuLFy8+cP3l+fP3lk20s7MD7nU5bt++zcCBAx/6x9bWlls3Mqij/+iitVbTluSnXUKjKdmyzk8+h8rQCMNG1o99XwC2jU2oY1Sxl+s7OjoCcPjw4RKPHz58mOLiYu3zoubq2rUrFhYWcrNrBZKCsgrr3r07TZs2lba3qDZ8fX3Ztm0bV69eVTpKpdDT02PkyJHExMQ8UOwA2qLwueeeA2DXrl3a53Jych5ZfCcnJxMVFaX9OTs7m8WLF+Po6KidksfNzY39+/ezcePGEq+9ceMGc+fOZcCAAVhbW5Nx9uAj85u06UNxTha55/43qlOUe5Pcs3uobd8dlcFDrq/86/srLqLo6gl27dpVoXf4DxgwgEaNGjFv3rwSj8+bNw8TExNGjBhRYccWukFPTw8XFxdWr15d6pvhxOOpNPI3W6VNmjSJ3bt3c+7cOaWjCFFmt27dwsLCgo8++ogZM2YoHadSJCUl0bVrV7Kzs5k8eTJt27YlJSWFyMhI9uzZQ8OGDSkoKMDe3p7c3FymT5+Ovr4+CxcupHbt2hw5coTLly9rRx7t7OwwMjLi2rVrvPbaa5ibm7Nw4UJOnTrFunXrGDJkCHBv2qC+ffty4sQJfHx80NPT48CBA5w5cwaNRsOLL77IhAkTKDZuyGsT3DD3nIVx8xdKZNcUF5G69J8UZCRQv/to9E3qc+voWgqz07H0/RHDxs2022as+ZGcP7Zi/doCDBr+bxUa1boviD9xgJYtW+Lr68uECRNYs2YNWVlZJCcnM2/ePEaPHk2nTp0AePPNN2nQ4N4d4UFBQfj7+7No0SL8/Pwe+/f8yy+/8PrrrzN27FiGDBnC7t27Wbx4MV9++SUffvjhA9v369ePjIyMJ44ei+pjzZo1uLi4cPr0adq2bat0nGpHpg2q4lxdXVmwYAHnzp2jdevWSscRokzq1avH6NGjCQ4O5oMPPij1Xc66xNramtjYWGbOnElISAjZ2dlYW1szbNgwTExMADA0NCQqKoqpU6cyc+ZMLCwsmDZtGqampvj7+z+wz/vrVE+fPp1z587RokULIiIitMUkgL6+PtOnT+ezzz4jODgYjUaDgYEBdnZ2jB8/no8++ghDQ0N27NgBgJ7eg/8WKj19mrp9Sta2hdw6EoOmMI9aFq0wH/FOiWISQFNwB5WBEXrG966X1NdT0btlY4Lj9rJnzx6CgoL47rvv+PjjjzEyMiIvL0/72pUrV2qvrfXx8dEWlLdv3wbuXSP5JFOnTsXQ0JDZs2cTHR2NjY0NP/74I2+//fYTXytqhpdffhkTExOio6OloKwAMkJZxeXm5tKkSRM+/fRTpk+frnQcIcps8+bNDB48mAMHDtCjRw+l41QrhYWFbN++nbCwMFauXMnNmzd54YUX8PDwwMPDgxYtWjzwmh07dtC/f3+sxs1Ez7INesZ1UenpP/Oxr87xoW77AZgOeAUAIwM9trzjhE0jE+02OTk5rFy5kqCgILZt20adOnUYN24cfn5+9O3bFz29kldhubm5ER8fz8GDj27LP6tbt26Rl5eHq6srN2/elBHKGmbUqFFcu3aNvXv3Kh2l2pFrKKs4ExMTBg0aJNdRimrj/rV7NenmnIpUXFzM3r17eeONN7C2tmbw4MHs2rWLN998k1OnTnH8+HFmzJjx0GLyr5IjPydxjjf5aX8+c4b89CtoCvOo33OM9rHP1O1KFJMAderUYfz48WzdupX4+Hjef/997WT3zz33HJ988gl//nnv+BqNhh07dvDFF188c57HGT9+PGZmZnK3bw2lVqvZv38/aWmPXsNelI6MUOqABQsWMHnyZFJTUzEzM1M6jhBlNmPGDAIDA0lJScHIyEjpODpHo9Fw7NgxwsLCiIiIICEhAWtra9zd3fH09KRLly5PfTnBjRs3OHLkCACrjiUSnVwHPSOTJ7zq8aYPbs3r/e2faluNRsOePXsIDg4mIiKC27dv4+TkhJ+fH2PHji33lcJOnDihnV6obt269OzZs1z3L6q2a9euYWFhwe+//84rr7yidJxqRQpKHZCWloalpSWLFi3C19dX6ThClNnZs2dp27YtkZGRshTaMzh37hxhYWGEh4dz7tw5GjduzLhx4/D09OTFF198oGVcGuGHEvg4+hSFxRqKip/+14O+ngoDPRWfqdvh3s22VMfOyckhKipK2xKvXbs2Y8eOxc/PDycnp3J5f0L06dMHMzMzVq1apXSUakUKSh3Rq1cvrKysWLFihdJRhCgXPXr0oGnTpsTExCgdpUpLSEggPDyc8PBw4uLiqFevHqNGjcLT05OXX34ZQ8PHT91TGlev5/Jh1El2X8xAX0/12MLy/vN97Zswa1SHB9rcpZWQkMCSJUsICgri4sWLNG/eXHuX+P1ploQojW+++YZPP/2UzMxMWUWpHElBqSO+/vprvvjiCzIyMjA2NlY6jhBl9ssvv/DWW2+RlJSEubn5k19Qg6SlpREZGUl4eDh79+7F2NgYZ2dnPD09GT58eKV9BlxIu0VIbALbz18jITOXv/6yUHFv0vL+Dk3x6WmLfdN6FZJBo9Gwb98+goKCiIiI4NatW/Tt2xc/Pz/GjRtHvXoVc1xRfd3vkMTExODs7Kx0nGpDCkodcfr0adq1a8fatWsZPny40nGEKLPr169jaWnJ119/zTvvvKN0HMVlZWWxcuVKwsPD2bp1K3p6egwePBhPT09cXV0VL5xy8gqJz8whv7CYWgZ62DWuU+Er4Pxdbm4uUVFRBAcHs2XLFmrXrs2YMWPw8/OjX79+0hIXT0Wj0dC6dWv69evH/PnzlY5TbUhBqSM0Gg2tWrVi4MCB/Prrr0rHEaJcjB07lkuXLhEXF6d0FEXk5OQQExNDeHg469evp6CgACcnJzw9PRkzZgyNGz95reya6urVq9qW+IULF7C1tdW2xO3tn+6GIFFz/eMf/yAkJISkpCT5IlJOpKDUIe+++y4RERFcvXpVTgBRLcTExKBWqzl+/DgvvPDCk19QDeTl5bFx40bCw8NZvXo1ubm5dO/eHU9PT9zc3LCyslI6ok7RaDTs37+f4OBgwsPDyc7O5sUXX9S2xOvXr690RFEF7dq1CycnJ5kPtxxJVaJD1Go1ycnJHD16VOkoQpSLoUOHYmZmVu3npCwqKmLLli1MmjQJCwsLXF1dOXnyJP/617+4dOkSsbGxTJs2TYrJUlCpVPTu3ZvAwEBSU1MJDQ3FxMSEV199FQsLC8aPH8+WLVsqdC1xoXt69+5No0aNZI7nciQjlDqkoKAAc3Nz3njjDT777DOl4whRLqZNm0Z4eDiJiYkYGFSf1WDvj5yFh4ezbNky0tLSaNmyJZ6ennh4eNC+fXulI1ZriYmJ2pb4+fPnsbGxYcKECfj6+tKqVSul44kqYMKECcTFxXHy5Emlo1QLUlDqGB8fH06ePMnx48eVjiJEuYiLi6Nz586sWbOGESNGKB2nTDQaDcePH9dO83PlyhWsrKxwd3fHw8ODbt261Yj1y6sSjUZDbGwsQUFBhIeHc/PmTfr06YOvry9ubm7adcNFzbNixQrtddwtW7ZUOo7Ok4JSx0RGRuLm5sbly5exs7NTOo4QZabRaOjYsSNt2rRh2bJlSscplfPnzxMeHk5YWBhnz56lcePGjB07Fg8PD/r27Yu+/rOvjS3K3507d1i9ejVBQUFs3ryZWrVqMXr0aPz8/BgwYID8O9Uwt27dokmTJnz77be8/fbbSsfReVJQ6pjs7GyaNGnC7NmzefPNN5WOI0S5mD17Nh9++CGpqamYmpoqHeepXL16lYiICMLCwjh69Ch169bVTjg+cODACplwXJSfpKQkli5dSlBQEGfPnqVZs2balriDg4PS8UQlGTZsGHl5eWzbtk3pKDpPCkodNGTIEIqLi9m8ebPSUYQoF6mpqTRr1oyff/6Z1157Tek4j5Senk5kZCRhYWHs2bMHIyOjEhOOy6obukej0XDw4EGCgoIICwvj5s2b9O7dG19fX9zd3aUlXs3NmzePN998k/T0dJ35MltVSUGpg/7zn/8wbdo0MjIy5MNOVBsjRozg+vXr7N+/X+koJdy8eZOoqCjCwsLYunUrQIkJx2Vamurj7t27REdHExQUxMaNG6lVqxajRo3Cz8+Pl19+WVri1VBiYiI2NjaEhITg5eWldBydJgWlDkpISKB58+aEh4fj7u6udBwhysWyZctwd3fn3Llzirccc3NzWbNmDWFhYaxbt46CggJeeukl7YTjTZo0UTSfqHjJycnalviZM2ewtrZm/Pjx+Pr60qZNG6XjiXLUpUsXWrVqRXh4uNJRdJoUlDqqU6dOPP/884SEhCgdRYhycffuXSwsLHjjjTf44osvKv34+fn5bNq0ibCwMFavXk1OTg7dunXTTjhubW1d6ZmE8jQaDYcOHdK2xLOysujZsyd+fn64u7vTsGFDpSOKMvrss8+YPXs26enp1KpVS+k4OksKSh31ySef8O9//5tr167Jxf+i2ggICGDDhg1cvny5UlaDKioqYufOnYSFhbFixQpu3LjB888/r50rUpbwE3919+5dYmJiCAoKYsOGDRgaGjJy5Ej8/PwYNGiQtMR11LFjx+jUqRObN29m4MCBSsfRWVJQ6qijR4/SpUsXtm7dyoABA5SOI0S52LdvH3369KnQ/6/vz0sYFhbGsmXLSE1NpUWLFnh4eODp6UmHDh0q5LiieklJSdG2xE+fPo2VlZW2Jd62bVul44lnoNFoaN68Oa6ursydO1fpODpLCkodpdFosLGxYezYsfz0009KxxGiXGg0Glq3bk2vXr3KdTlGjUbDyZMnCQsLIzw8nPj4eCwtLXFzc8PT05Pu3bvLhOOiVDQaDUeOHCEoKIjQ0FBu3LhBjx498PX1xcPDQ+4c1hFvvPEGMTExxMfHy2dBKUlBqcOmTp3Khg0buHTpkpwAotr44osv+Prrr0lNTaVu3bpl2tfFixe1ReTp06cxNTVl7NixeHp68tJLL0mLUpSrvLy8Ei1xAwMDXF1dtS3x6rS0aHWzadMmhgwZwrFjx+jYsaPScXSSFJQ6bMOGDQwbNoyTJ0/KusCi2rhy5Qp2dnYEBQXh6+v7zK9PTExk2bJlhIWFcfjwYerUqcPIkSPx9PRk0KBBctG9qBSpqamEhISwaNEiTp06haWlpbYl/vzzzysdT/xNXl4eZmZmTJ8+nZkzZyodRydJQanD8vLyaNKkCTNmzODDDz9UOo4Q5eb+9ZNPu3pFeno6K1asICwsjN27d1OrVi2GDx+Op6cnI0aMwMTEpCLjCvFIGo2Go0ePalvi169fp1u3bvj5+eHh4UGjRo2Ujij+y93dnT///JNDhw4pHUUnSUGp48aOHUtiYiIHDhxQOooQ5SY4OBg/Pz/i4+Np3rz5Q7fJzs4mKiqK8PBw7apRAwcOxNPTk5EjR8qk/6LKycvLY+3atQQFBbFu3Tr09fW1LfHBgwdLS1xhISEh+Pj4kJiYKNOElULFz8shKpSrqyuxsbGkpKQoHUWIcjNmzBhMTExYunRpicfv3LlDZGQkY8aMoWnTpvj5+ZGTk8PcuXNJSUlhw4YN+Pr6SjEpqiQjIyNGjx5NdHQ0SUlJfPXVV5w5c4YRI0ZgY2PD9OnTOXXqlNIxa6xhw4ahr69PTEyM0lF0koxQ6rjMzEyaNm3Kr7/+yquvvqp0HCHKzYQJEzhw4AB//PEHmzdvJjw8nFWrVnH79m26dOmCp6cn7u7uNGvWTOmoQpSaRqMhLi5O2xLPzMyka9eu2pZ448aNlY5Yo/Tv35/atWuzbt06paPoHCkoqwEnJyfq168v36pEtVFUVMRPP/3EP/7xD+rVq8etW7do27atdsLxVq1aKR1RiHKXn5+vbYmvXbsWfX19XFxc8PPzY+jQodISrwQ//vgjH3zwAZmZmWWeZaKmkYKyGpg9ezYfffQRGRkZ1KlTR+k4QpSKRqPh4MGDhIeHExERQUpKCvr6+nTo0IHg4GA6dOgg02OJGiMtLY3Q0FCCgoI4ceIE5ubm+Pj44OfnJ7N6VKBLly5hb2/PihUrGD16tNJxdIoUlNXAhQsXcHBwYNWqVbi6uiodR4hn8scff2jnivzzzz+xsLDQTjgeHR3NvHnzSElJwdjYWOmoQiji2LFjBAUFERISQkZGBl26dMHPzw9PT09piVeA9u3b07VrV4KCgpSOolOkoKwm2rZtS+/evVmwYIHSUYR4okuXLhEeHk5YWBinTp3C1NSUMWPG4OnpiZOTk3bC8XPnztGmTRsiIiJwc3NTOLUQysrPz2fdunXalrhKpSrREjc0NFQ6YrXw4YcfMn/+fNLS0mTxg2cgBWU18cEHH7Bw4UJtm1CIqiYpKUk74fihQ4eoU6cOrq6ueHp6Mnjw4EdOON6rVy8aNWrE2rVrKzmxEFVXenq6tiV+7NgxmjZtio+PD76+vrzwwgtKx9NpBw4coFevXuzatYu+ffsqHUdnSEFZTezbt48+ffqwd+9eevfurXQcIYB7sxAsX76csLAwdu3ahaGhYYkJx5/mmt9ff/2VN954g8TERCwsLCohtRC65dixYwQHB7N06VIyMjLo1KkTfn5+eHl50aRJE6Xj6Zzi4mIsLS2ZMGEC3333ndJxdIbMQ1lN9OjRAzMzM6Kjo5WOImq4W7dusWTJEoYPH46FhQWvv/46RkZGLFy4kLS0NKKionBzc3vqG8jc3d0xMDAgJCSkgpMLoZscHR358ccfSUpKYtWqVdjZ2fHee+9hZWWlnfeyoKBA6Zg6Q09PDxcXF/l9+oxkhLIaeeWVVzhw4ACnT59WOoqoYe7cucO6desICwtj7dq13L17lxdffBEPDw/GjRtH06ZNy7R/Nzc3zp07x/Hjx8spsRDVW3p6OmFhYQQFBREXF4eZmRne3t74+fnRsWNHpeNVedHR0bi6unL27Flat26tdBydIAVlNbJq1SpGjRrF+fPnZZ4+UeEKCgrYsmULYWFhrFq1ilu3btG5c2c8PDxwd3fH1ta23I61Zs0aXFxciIuLw9HRsdz2K0RNcOLECW1L/Nq1azg6Ompb4mZmZkrHq5Jyc3Np0qQJn376KdOnT1c6jk6QgrIaycnJoXHjxsyaNYt3331X6TiiGiouLmb37t2EhYWxfPlyMjMzadOmjXbVmor6Jl9QUECzZs3w8vLixx9/rJBjCFHdFRQUsGHDBoKCgoiJiUGj0TBixAj8/PwYPnz4I2+Mq6lcXV3JzMxkz549SkfRCVJQVjPOzs7cvn2bHTt2KB1FVBMajYbDhw9rJxxPSkqiefPmeHh44OHhQceOHStlwvF3332XpUuXkpSUJNOjCFFGGRkZhIWFERwczJEjR2jSpIm2JS5dgHsWLFjAq6++SlpamozkPgUpKKuZ3377jSlTppCWliYT3ooyOXXqFOHh4YSHh3Px4kXMzc1xc3PDw8ODXr16VfqqNcePH8fR0ZHo6GhcXFwq9dhCVGcnT57UtsTT0tLo2LGjtiVe1uufdVlaWhqWlpYsXLgQPz8/peNUeVJQVjMpKSlYWVmxePFixo8fr3QcoWP+/PNPIiIiCAsL4+TJkzRs2JAxY8bg4eFBv379FF9L2NHREXt7e5YvX65oDiGqo4KCAjZu3EhQUBDR0dFoNBqGDx+On58fI0aMqJEt8V69emFpacnKlSuVjlLlSUFZDfXo0QNbW1siIyOVjiJ0QEpKinbC8djYWExMTHB1dcXDw4MhQ4ZgZGSkdEStH3/8kQ8++ICUlBQaNWqkdBwhqq3MzEzCw8MJCgri8OHDNG7cGG9vb3x9fenUqVOldyiU8tVXX/HFF1+QmZkpy78+gcxDWQ2p1Wo2bNhAXl6e0lFEFZWZmclvv/3GgAEDsLa2Zvr06ZibmxMWFsa1a9cIDQ1FrVZXqWISwMvLi6KiIsLDw5WOIkS11rhxY15//XUOHTrEyZMn8ff3JyIigi5dutCxY0d++OEH0tLSlI5Z4VxdXcnNzWXbtm1KR6nyZISyGjp58iQvvPACGzZsYMiQIUrHEVXErVu3WL16NeHh4WzcuJHi4mIGDBiAp6cno0aNwtTUVOmIT8XFxYX09HQOHDigdBQhapTCwkI2bdpEUFAQq1evpqioiOHDh+Pr64uzs3OV+wJaHjQaDa1ateLll18mMDBQ6ThVmhSU1ZBGo6Fly5YMHz6c//znP0rHEQq6e/cu69atIzw8nDVr1nDnzh169+6Np6cn48aNw9zcXOmIz2z58uWMGzdOJhwWQkHXr1/XtsQPHTpEo0aN8PLyws/Pj86dO1erlvi7775LeHg4iYmJ6OlJY/dRpKCspqZNm8aKFStISEioVie2eLKCggK2bt1KeHg4UVFRZGdn4+joqJ0rsnnz5kpHLJO7d+9iaWnJlClTmDVrltJxhKjxTp8+TXBwMEuWLCElJYX27dvj5+eHt7c3FhYWSscrsx07dtC/f38OHjxIt27dlI5TZUlBWU1t27aNl19+maNHj9KpUyel44gKVlxczN69ewkLCyMyMpKMjAwcHBzw9PTEw8ODNm3aKB2xXE2ZMoU1a9YQHx+Pvr6+0nGEENxriW/evJmgoCBWrVpFUVERw4YNw9fXFxcXF51tiRcUFGBubs7rr7/O559/rnScKksKymqqoKAAMzMzpk2bxieffKJ0HFEBNBoNR48eJSwsjIiICBITE7GxscHDwwNPT08cHR2r7ej0gQMH6NWrF5s3b2bgwIFKxxFC/M2NGzeIiIggKCiI2NhYTE1NtS3xLl266Nxnk4+PDydPnuT48eNKR6mypKCsxry8vDh79ixHjx5VOoooR2fOnCEsLIzw8HAuXLhA06ZNGTduHJ6envTq1atGXOOj0Who06YN3bt3Z8mSJUrHEUI8xpkzZwgODmbx4sWkpKTQrl07fH198fHxwdLSUul4TyUyMhI3NzcuX76MnZ2d0nGqJCkoq7Hw8HA8PT1JSEjAxsZG6TiiDOLj4wkPDycsLIwTJ07QoEEDRo8ejaenJ/3791d8wnElzJo1iy+//JLU1FTq1aundBwhxBMUFhayZcsWbUu8oKCAoUOH4ufnh4uLS5We5zE7O5smTZrw/fff89Zbbykdp0qSgrIay8rKwszMjH//+99MnTpV6TjiGaWmpmonHD9w4AC1a9dGrVbj6enJ0KFDdfZ6pPJy9epVmjdvzoIFC/D391c6jhDiGdy4cYNly5YRFBTEgQMHMDU1xcPDAz8/P7p161YlW+JDhgyhqKiILVu2KB2lSpKCspobOHAgBgYGbNiwQeko4incuHGDFStWEBYWxo4dO9DX12fo0KF4enri4uJC3bp1lY5YpQwcOJDCwkJ27NihdBQhRCmdPXtW2xJPTk6mbdu2+Pn54ePjg5WVldLxtP7zn/8wbdo00tPTadiwodJxqpzqf7FVDefq6sq2bdvIzs5WOop4hNu3bxMaGoqLiwvm5uYEBASgUqmYP38+qampREdH4+npKcXkQ/j6+rJz507i4+OVjiKEKKU2bdrw1VdfkZCQwMaNG3F0dOTjjz/GxsaG4cOHs2zZMu7evat0TFxcXCgsLJQBmkeQgrKac3FxoaCggI0bNyodRfxFXl4eq1atwt3dnaZNm+Lt7U1mZiazZ88mKSmJLVu2MHHiRFmv+glGjx5NnTp15MYcIaoBfX19Bg8eTGhoKCkpKcybN4+srCzc3d21c8/GxsaiVGPV1tYWR0dHoqOjFTl+VSct7xqgY8eOvPDCC/JLV2GFhYVs27aN8PBwVq5cyc2bN+nYsaN2wnG5c7B0/Pz82Lt3L+fPn6+S110JIcrm3LlzLF68mMWLF5OYmEibNm20LXFra+tKzfLJJ5/w008/kZ6ejqGhYaUeu6qTgrIGmDlzJv/5z3+4du1ajbwbWEnFxcXs27eP8PBwIiMjuXbtGq1atdJOON62bVulI+q87du3M2DAAPbs2UOfPn2UjiOEqCBFRUVs27aNoKAgVq5cSX5+PoMGDcLPzw9XV1dq165d4RmOHj1Kly5d2LJlCz1fdCI+M4f8wmJqGehh17gOdYxq7u9YKShrgEOHDtG9e3d27NiBk5OT0nGqPY1GQ1xcHOHh4YSHh3P16lWaNWuGh4cHHh4e1W6dW6UVFxfTsmVLBg8ezPz585WOI4SoBDdv3iQyMpKgoCD27t1LgwYNtHeJ9+jRo8I+Y8+nZjNwyqfUdejJHT0T/lpAqQDbRib0b90U7x62tDKvWdOZSUFZAxQXF9OsWTM8PT2ZPXu20nGqrbNnz2rnijx//jxmZmaMGzcODw8P+vTpUyMmHFfKzJkzmTNnDqmpqZUySiGEqDrOnz/P4sWLCQ4OJjExEQcHB/z8/Bg/fjzNmjUrl2NcvZ7Lh1En2X0xA5WmGI3q0Z/n+noqioo19LVvwqxRHbBpZFIuGao6KShriNdee40tW7Zw4cIFGR0rR1euXCEiIoKwsDCOHTtG/fr1GTVqFJ6enrz88styiUEluXDhAg4ODoSFheHh4aF0HCGEAoqKiti+fbu2JX737l1tS3zkyJGl/rIZfiiBj6NPUVisoaj46UsmfT0VBnoqPlW3w6ObbamOrUukoKwh1q1bx4gRIzh9+rRct1dGaWlpREZGEhYWxr59+6hduzYuLi54eHgwbNiwKr3aQ3XWp08f6tevz/r165WOIoRQWHZ2trYlvmfPHurXr4+7uzt+fn706tXrqQdWft5+ge83nS9znn8MduCN/q3KvJ+qTArKGuLu3bs0btyYmTNn8sEHHygdR+fcuHGDqKgowsLC2LZtG3p6egwdOhQPDw/UarUs/VcFzJ8/nylTpnD16tUqNRmyEEJZFy9e1E6cnpCQQKtWrbQt8cctSxx+KIEPVp4stxzfjO6AezUeqZSLumoIY2NjhgwZIvNnPYOcnBzCw8NxdXXF3NycSZMmUVxczK+//kpaWhoxMTF4e3tLMVlFuLm5YWhoSGhoqNJRhBCVyM7ODmdn50c+b29vz+eff87ly5fZunUrPXv25IsvvqB58+baeS9zc3O12+/YsQOVSoVn9+Zc+dqZvJQL5ZLz/6JPcfV67pM3rGTTpk1DpVKhUqnKtICGFJQ1iFqt5sCBA6SlpSkdpcrKy8vTrkzTtGlTPD09uXbtGt999x1JSUls3bqVV199VSYcr4IaNmyIq6srwcHBik18LISouv6/vTuPq7rOHj/+uvciKBqCiGziirih4ajouIQ2ommGaO6yKXnv1Dd/6ZSVTU5qM86YjTMtM3VBWVxR3NE0zRCtjFwwtUxFQ2QXFJFFtnt/f5B3RBYV0Mtyno+Hf/D5vO/7cy4F9/A+70WpVPLss8+ydu1a0tLSWL16NYWFhcyaNQs7Ozvmzp3Lt99+a/j9YTlkKtbjX8fE0q5cP7o7uWTt+4RrH80k8Z8vkrZxEYVp8Q98folOzzs7Ko545ubm8t577/Hcc8/Rpk0bFAoFYWFhtX6/n332GVOmTKFDhw4oFAoCAgIqbefr68u6desYPnx4rZ4nCWUT8vzzzwOwd+9eI0dSv5SUlBhOprGzs2PChAn8/PPPvPvuu1y5coVjx47x2muvYW9vb+xQxQP4+/tz7tw54uLijB2KEKIes7CwYM6cOcTExBAfH8+CBQs4ePAgw4YNw0f9/wAw6+hGK9eRqFr8rwql1+vIiFxK3s8xPNV/PFYjZqPLv0X6xkUU30iu9pmlOj1H4zOJz7hd7npmZibLli3j/PnzPP3003X2HlesWMHXX39N7969q10g2r9/f3x8fOjSpUutnicJZRNiY2PDkCFDpOzN/zYcnzdvHo6Ojnh6ehITE8Orr77KTz/9xI8//siiRYvo3LmzsUMVj2D06NHY2dkRHh5u7FCEEA1E165dWbp0KVeuXOHrr7/GyrXq/Zrzf/mWwuTzWD8/H8thM3mq/3hsZ/4dhUJJ9jcPnm6jUipY/31iuWv29vakpqZy9epVVq5cWev3c1dMTAyZmZns27cPMzOzOuu3KpJQNjETJkzgwIEDFBQUGDuUJ06v13P69GneeustOnfuzNChQ9mxYwc+Pj4cP36cS5cu8f7779OrVy9jhypqyMTEhFmzZrFx40aKioqMHY4QogrJyckEBgbi4OCAmZkZnTt35uWXXzb83C5ZsqTSldhhYWEoFAoSEhIq3Dtw4ABubm40b96cXr16sX379gptsrOzmT9/Pk5OTpiZmeHs7MyKFSvQ6XQolUpGjhyJyrZrlXHnX/gWZUtLzLsPMVxTmbfGvOdwCi59j76kuNr3XarTE30xo9w1MzMz7OzsqnhFzXXs2PGJbhMoCWUT4+XlRUFBAYcOHTJ2KE/MxYsXWbp0Kb169aJfv36sWbOGcePGERMTQ2JiIv/85z8ZMGCA7M/ZSPj7+xv+KhdC1D8pKSm4u7sTERHBtGnT+Pjjj/H19SUmJqbc4phHcenSJaZNm8bYsWP5+9//jomJCVOmTOHgwYOGNvn5+Xh4eLB+/Xr8/Pz4+OOPGTp0KIsWLeJPf/oTALmFJaTn3KnyOUXplzG17Yrivo3NTe1d0BcXPrDsDZCYlU9eYUmN3md9JrsuNzHdu3fHxcWFXbt2VbsqrqFLTEw0bDgeFxfHU089xcSJE/nXv/7FH/7wB5o1a2bsEMVj0qdPH/r160d4eDgTJkwwdjhCiPssWrSItLQ0YmNjGTBggOH6smXLaryg7uLFi2zbto1JkyYBEBgYSI8ePXjrrbfw9PQEYNWqVVy+fJm4uDi6dSvbE1Kj0eDg4MDKlSt5/fXXyVFZVPuc0tybmDm5Vrhu0srqt/tZ0K5TtX3ogYSsPHo7tH7Ed1m/yQhlE+Tl5UVUVBQ6nc7YodSpjIwM/vOf/zBs2DA6duzIX/7yF7p27cq2bdtIT08nPDyc5557TpLJJsDf3589e/aQlZVl7FCEEPfQ6XTs3LmTF154oVwyeVdNK0UODg5MnDjR8LWFhQV+fn7ExcWRlpYGQGRkJMOHD8fKyorMzEzDv1GjRlFaWsqRI0coKqn+c1FfUoRCVclniMrUcP9hPOg5DZEklE2Ql5cX6enpHD9+3Nih1Fp2djahoaGMGTMGBwcH5s+fT+vWrVm3bp3hRJtJkybJ+c5NzMyZM9Hr9WzatMnYoQgh7nH9+nVycnJwda04ylcbzs7OFZJRFxcXAMN8y0uXLrF//35sbGzK/Rs1ahRQNihhalJ9WqQwMUVfWsk8ydIiw/2H8aDnNERS8m6Cfv/732Ntbc3u3bsZNGiQscN5ZPn5+URFRREREcEXX3xBcXExHh4e/Pe//2XSpEm0bdvW2CEKI7OxsWHcuHGsXbuWV1991djhCCEeUVUjlaWlpTXuU6fT4enpyZtvvlnpfRcXF6ytW1bbh6qVFaW5NypcL8m9+dt96wfGoQA6PeA5DZEklE2QiYkJzz//PLt37+Zvf/ubscN5KEVFRXz55ZdERESwa9cu8vLycHd3Z8WKFUyZMgVHR0djhyjqGT8/PyZPnsz58+fl/Hoh6gkbGxssLCw4d+5cte2srMrmJGZnZ2NpaWm4fvXq1Urbx8fHo9fryyWiFy+WncHdqVMnoGx7oNzcXMOIZFVsLZpT1fEfpu26cCfpJ/R6XbmFOUUpF1A0M6NZmwd/FnWwNqelWeNLvxrfmKt4KBMmTODcuXNcuXLF2KFUqbS01HAyjZ2dHV5eXpw5c4Z33nmHy5cvExsby/z58yWZFJUaP348VlZWsielEPWIUqnE29ubqKgoTpw4UeH+3UU5XbuWbd1z5MgRw728vLwqf55TUlLYsWOH4eucnBzWrl2Lm5ubYUueqVOncuzYMb788ssKr8/OzqakpIQzZ86gyEqoMn7zHkPR5WWTf+E7w7XS/Fvk//INLZzdUZhUP0dfpVQw0qVdtW0aqsaXIouHMnr0aExNTYmKiuK1114jr7CEhKw8ikp0mJoo6WTd0ih/Qen1er7//nsiIiLYsmULaWlpdOnShVdeeYXp06fX+bwb0XiZmZkxY8YM1q1bx9/+9jdUKpWxQxJCAMuXL+fAgQN4eHigVqvp2bMnqampREZG8s0332Bpacno0aPp0KEDgYGBLFy4EJVKRUhICDY2NiQmJlbo08XFhcDAQI4fP46trS0hISGkp6cTGhpqaLNw4UJ2797N+PHjCQgIoH///uTl5REXF8fWrVtxdXXl5MmTtHFyrjJ28+5DMXXoTtYXH1GceQ2VuQW3T+1Fr9dhOWxWubaZe/5F3rlDOP5xDSaWtkDZPpQ+gztU6PfTTz8lOzublJQUAKKiokhKSgJg3rx5tG5dtiI8LCyM2bNnExoaWuVRindFRUXx448/AlBcXMyZM2f461//CpStpejbt2+1r39UklA2Ua1atWLYuMmsOZ3D9pXRJN7I597NGhRAhzbmjOzejlmDOtDN9qmquqo1vV7PmTNniIiIICIigoSEBBwcHJgxYwbTp09n4MCBskekqBF/f3/++9//cujQIUaPHm3scIQQgKOjI7GxsSxevJgNGzaQk5ODo6MjY8eOxdzcHIBmzZqxY8cOXnnlFRYvXoydnR3z58/HysqK2bNnV+izW7dufPLJJyxcuJALFy7QuXNnNm/ezJgxYwxtzM3NiYmJYfny5URGRhIeHo5KpaK4uJjS0lLatGnDtm3bsLCwwNPTE6Wy4ueOQqmi3dSlZH8dwu2TUehLCjG164bt8wtoZt2+XFt9cQEKEzOUzcvmS6qUCoZ0sca5XcXP0w8//LBcOX/79u2Gjdl9fHwMCWVubi7AQx0FvG3btnIjunFxcYZjadu3b1/nCaVCX9NNn0SDde1GPu/sOMvR+Ez0ulIUyqpHblRKBaU6PcOd27J8Yh+c2pjXWRyXLl0iIiKCTZs2cf78eaytrZk8eTLTp09n+PDhMqIkak2v19OrVy9+97vfsWHDBmOHI4QwsoKCArZs2UJQUBDfffcdtra2zJkzh7lz5xqO2j18+DAjR47EYcpilPY9UDZvVe3nZFWufexDK9dnsXp2DgBmJkq+WuBRq8/RqVOnkpCQwA8//FDjPu6Xl5dHQUEB8+bNIyoqypC0PioZoWxiIo4n8t7unyjRlf0d8aAfktLf2n13JYtR/4phqVdvpg+sOFz/sJKSkgwbjp88eZJWrVoxceJEPvzwQzw9PWWPSFGnFAoF/v7+LFu2jJycHCwsqt+0WAjROP30008EBQWxdu1asrOz8fT0JDIyEi8vL0xNK9/qJyXyfQDs/P+FmX23R3pe0fWr6EsKsRj8ouHaMq/etUom9Xo9hw8fZv369TXuozJ//vOf+eijjwBo2bLmq89lhLIJ+TT6Eh8euFjrft4Y7cKrIx/+h+v69ets3bqVTZs2cfToUczMzBg/fjzTp0/n+eeflz0ixWOVlJREhw4dCA4OJjAw0NjhCCGekIKCArZu3YpWq+Xbb7/FxsbGMBp5d9FPZW7evMnJkycB2Hk6id0pLVGa1a46t3B0d/5vZNVzM43p4sWLhnmpJiYmjBgxokb9SELZREQcT+Tt7WfrrL8Vk/owrZqRylu3brFz5042bdrEV199BZQtBJo+fTre3t4yUiSeqNGjR3Pnzp1yK0aFEI3T+fPnCQoKIjw8nJs3b/KHP/wBtVqNt7d3laOR1bm3sne3avcwVEoFJkoFy7x6V/t52VhIQlnPdOrUCVdXV/bs2VMn/d2dC3JXTYbuK1PZXJD8/Hz27t3Lpk2b+OKLLygqKuKZZ55h+vTpTJ48+YlsOO7m5mZY1fb888/X2fdRNGwbNmzAx8eHy5cv06VLF2OHI4SoY3fu3GHbtm1otVqOHj1K27ZtmT17NnPnzjWc210b9649uLu2oCqPc+1BfSb7UDYRlkOmYj3+dUws7cpd193JJWvfJ1z7aCaJ/3yRtI2LKEyLf2B/JTo97+w4S1FREXv37sXHxwdbW1umTp1KYmIiQ4YMwcbGhtjYWEJDQw0ry2pKp9PxwQcf0LlzZ5o3b07fvn0rPVZv+fLlrFu3Tk7LEeV4e3vTqlUr1q1bZ+xQhBB16JdffuH111+nffv2+Pj4YGJiwqZNm0hKSuKDDz6ok2QSwKmNOesCB3Fw/jP4DupIR2tz7l8DrgA6WpvjO6gjXy14hnWBg5pMMgkyQlnv1PUI5frtX+D74vPYzlhO847ltwjQ63Wkr3+LooxfsRg0CVULC27HfUFJznXsA/79UDv+5215m8wr5+jVq5dhm5/FixezdetW5s+fT7du3QgLC+P48eNER0czbNiwGr2PRYsW8Y9//IO5c+cycOBAdu3aZRgNnT59eoX2df19FA3fnDlziImJIT4+XrahEqIBKywsZPv27Wi1WmJiYrC2tiYgIAC1Wm04v/tJqC/7N9cXklDWM3WdCAX8LZTwd+dUmlDmnT9K5q4VtPV+m5Y9yhK90vxbpGjVNO86ABuvhdV3rivFRZnOP2cOxtXVFYVCwQ8//MCgQYNYuXIlb7zxBlBWinB1daVdu3Z899131fdZieTkZDp37oxarebTTz8Fyla7eXh48Ouvv5KQkFBhiyFJKMX9YmJiGDFiBEeOHGH48OHGDkcI8YguXrxIcHAwYWFhZGZmGjZGnzRpEs2bNzd2eE2elLzrQHJyMoGBgTg4OGBmZkbnzp15+eWXKSoqAmDJkiWVjoiEhYWhUChISEiocO/AgQO4ubnRvHlzevXqZdjg9F7Z2dnMnz8fJycnzMzMcHZ2ZsWKFeh0OkObuGvZVcadf+FblC0tMe8+xHBNZd4a857DKbj0PfqS4urfuFJFobUzffr0Mby/rVu3olKpUKvVhmbNmzcnMDCQY8eOce3ater7rMSuXbsoLi7mlVdeMVxTKBS8/PLLJCUlcezYsUfuUzQ9w4cPp1OnTnIUoxANSFFREZs3b+bZZ5+le/fuhISE4Ovry/nz5zl8+DAzZ86UZLKekISyllJSUnB3dyciIoJp06bx8ccf4+vrS0xMDPn5+TXq89KlS0ybNo2xY8fy97//HRMTE6ZMmcLBgwcNbfLz8/Hw8GD9+vX4+fnx8ccfM3ToUBYtWsSf/vQnAHILS0jPuVPlc4rSL2Nq27XcAfcApvYu6IsLKb6R/MBYE7PyySssMXwdFxeHi4tLhVXc7u7uAJw+ffqBfd4vLi6Oli1b0rNnz0r7rO38TNE0KJVK/Pz82LJlS41/NoUQT0Z8fDxvvvkm7du3Z/r06ZSUlLBu3TqSk5NZtWoVPXr0MHaI4j5Nt9hfRxYtWkRaWhqxsbEMGDDAcH3ZsmXUdDbBxYsX2bZtG5MmTQIgMDCQHj168NZbb+Hp6QnAqlWruHz5MnFxcYZJxxqNBgcHB1auXMnrr79Ojqr6rXlKc29i5lTxbGyTVla/3c+Cdp2q7UMPJGTl0duh7Fio1NTUSo+Eunvt7jmljyI1NRVbW9sKo7y16VM0TX5+fixbtoydO3cyc+ZMY4cjhLhHUVERu3btQqvVcujQISwtLfH390etVtOrVy9jhyceQEYoa0Gn07Fz505eeOGFcsnkXTWd+O/g4MDEiRMNX1tYWODn50dcXBxpaWkAREZGMnz4cKysrMjMzDT8GzVqFKWlpRw5coSiEl1VjwBAX1KEQlXJyTQqU8P9h3HvcwoKCjAzM6vQ5m5JoqCg4KH6vNfj6FM0TV27dmXYsGFS9haiHrly5Qpvv/02Tk5OTJ06lTt37hAeHk5KSgr//ve/JZlsIGSEshauX79OTk4Orq4VR/lqw9nZuUIyenflWkJCAnZ2dly6dIkzZ85gY2NTaR8ZGRm4mVT/94LCxBR9aSXzJEuLDPcfhuk9z2nRogWFhYUV2ty5c8dw/1E9jj5F0+Xv749GoyE5ORlHxwfvZCCEqHvFxcXs3r0brVbLwYMHad26NX5+fqjV6jr/TBVPhiSUT0BVI5WlpaU17lOn0+Hp6cmbb75Z6X0XFxesras/k1PVyorS3BsVrpfk3vztvvUD41AAne55jr29PcnJFedepqamAmWjr4/K3t6e6Oho9Hp9ue9lbfoUTdeUKVOYN28eGzZsqPLnRwjxePz6668EBwcTEhJCeno6v//97wkLC2PKlCmYmzedPRsbI0koa8HGxgYLCwvOnTtXbTsrq7I5idnZ2VhaWhquX716tdL28fHxFZKnixfLzuDu1KkTUFa6y83NZdSoUdU+29aiOelV3DNt14U7ST+h1+vKLcwpSrmAopnZQ+1D2cHavNy+W25ubkRHR5OTk1NuYU5sbKzh/qNyc3Nj9erVnD9/vlzpozZ9iqardevWeHt7Ex4ezsKFC2VPSiEes+LiYvbs2YNWq+XAgQM89dRT+Pr6otFo6NOnj7HDE3VE5lDWglKpxNvbm6ioKE6cOFHh/t1FOXcPob/3HOG8vLwq53GlpKSwY8cOw9c5OTmsXbsWNzc37OzKTrqZOnUqx44d48svv6zw+uzsbEpKylZe93OyrDJ+8x5D0eVlk3/hf3tDlubfIv+Xb2jh7I7CpJL5lfe+P10phVdOsX//fsNo6+TJkyktLSUoKMjQrrCwkNDQUAYNGoSTk1O1fVZmwoQJNGvWjP/+97//e7Zez+eff46joyNDhgyp5tVCVOTv78/PP//MyZMnjR2KEI3W1atXeffdd+nYsSOTJk0iOzubNWvWkJKSwqeffirJZCMjI5S1tHz5cg4cOGDYYLVnz56kpqYSGRnJN998g6WlJaNHj6ZDhw4EBgaycOFCVCoVISEh2NjYkJiYWKFPFxcXAgMDOX78OLa2tobSQGhoqKHNwoUL2b17N+PHjycgIID+/fuTl5fH2bNn2bp1KwkJCbRt25ZRPW2pavmBefehmDp0J+uLjyjOvIbK3ILbp/ai1+uwHDarXNvMPf8i79whHP+4BhNLWwAUShW3Tu5h7Gdv4ODggK+vL/7+/kyZMoVFixaRkZGBs7Mz4eHhJCQksGbNmnJ9LlmyhKVLlxIdHc2IESOq/B63b9+e+fPns3LlSoqLixk4cCA7d+7k6NGjbNiwocKm5kI8iKenJ/b29oSHh1e6oE4IUTMlJSXs3bsXrVbL/v37adWqFT4+Pmg0Gp5++mljhyceI0koa8nR0ZHY2FgWL17Mhg0byMnJwdHRkbFjxxrmgzRr1owdO3bwyiuvsHjxYuzs7Jg/fz5WVlbMnj27Qp/dunXjk08+YeHChVy4cIHOnTuzefNmxowZY2hjbm5OTEwMy5cvJzIykrVr12JhYYGLiwtLly6ldeuybXza/3aOqFJZsaynUKpoN3Up2V+HcPtkFPqSQkztumH7/AKaWbcv11ZfXIDCxAxl87L5kiqlgiFdrFm7/GtOnjxJWFgYQUFBrFixgoEDBzJixAjWrl1LdnY2ffv2Zc+ePTzzzDPl+szNzUWhUBhGXavzj3/8AysrK7RaLWFhYXTr1o3169fL1i+iRlQqFT4+PoSEhPDPf/4TU9OHW4AmhKhcYmIiq1evNoxADhw4kODgYKZNm0arVq2MHZ54AuToxUbu8OHDjBw5Eocpi1Ha90DZvBUK5aOP6F372IdWrs9i9ewcAMxMlHy1wKPcwfeFhYVERUURFhbGvn37aNasGd7e3gQEBODp6VlhJNHd3Z2OHTsSGRlZuzd5j7vl/t/97neGRFaIyvz000+4urqyffv2ctt0CSEeTklJCfv27UOr1bJv3z7Mzc2ZNWsWGo2Gfv36GTs88YTJHMomIiXyfZI+nkVR+pVHfm3R9avoSwqxGPyi4doyr97lkkkAMzMzJk+ezJ49e0hKSuKvf/0rZ8+eZezYsXTo0IG3336b8+fPA2XzQn/88UeWLVtWuzd2nxEjRmBjY1OjIx5F09K7d2/69+8ve1IK8YiSkpJYsmQJnTt3xsvLi7S0ND7//HNSU1P5/PPPJZlsomSEspG7efOmYeHBztNJ7E5pidKsdlszLBzdnf8b6fxQbfV6vaEkvnHjRm7evMmgQYMICAhg2rRphhXwdSU2Npbbt28DZavwZc6OqM4nn3zCn/70J1JSUqrc01UIUbbN3f79+9Fqtezdu5cWLVowc+ZMNBoN/fv3N3Z4oh6QhLKJiTieyHu7f6JEp6dU9/D/6VVKBSZKBcu8ejNtYIcaPfvekvj+/fsxMTGptiQuxOOWmZmJvb09q1atYt68ecYOR4h6Jzk5mTVr1rB69WquXbtGv3790Gg0zJw5k6eeesrY4Yl6RBLKJujajXze2XGWo/GZqJSKahPLu/eHO7dl+cQ+FcrcNZWamsqGDRsICwvjp59+wt7eHl9fXwICAujZs2edPEOIh+Ht7U1SUlKlW38J0RSVlpZy4MABtFote/bswczMjBkzZqDRaBgwYIDs3SoqJQllE3Yp/TYbYhOJvphBYlY+9/6PoKBs0/KRLu3wGdwB53aP5y/Rykri7u7uBAQEMH369DoviQtxvx07djBp0iTOnTtH7969jR2OEEaTkpJCSEgIq1ev5urVqzz99NNoNBpmzZpV7qAKISojCaUAIK+whISsPIpKdJiaKOlk3bLcCThPQmFhIXv27DGsEjcxMWHChAmGkriJiexyJepeUVERDg4OzJkzhw8++MDY4QjxROl0Og4ePIhWq2X37t2Ympoyffp0NBoN7u7uMhopHpoklKJeSktLY8OGDYSGhpYrifv7+5c7flGIujBv3jy2bdtGYmKi/OEimoS0tDRCQkIIDg4mISGBPn36oNFo8PHxMexjLMSjkIRS1Gt6vZ5Tp04ZSuI3btyQkriocydOnGDgwIHs27eP5557ztjhCPFY6HQ6Dh06hFarZdeuXTRr1oxp06ahVqsZPHiwjEaKWpGEUjQY95fEVSpVuVXiMrIkakqv1+Pq6krfvn3ZtGmTscMRok7dPbo3ODiYK1eu0Lt3b8NopPxRLuqKJJSiQZKSuKhrH3zwAe+99x5paWlS8hMNnk6n4+uvv0ar1bJz505MTEyYOnUqarWaIUOGyGikqHOSUIoGTUrioq6kpKTg5OTE559/zty5c40djhA1kpGRQVhYGMHBwcTHx9OzZ080Gg2+vr60adPG2OGJRkwSStFoVFYSv7tKfPTo0VISFw/03HPPkZeXx9GjR40dihAPTa/XEx0djVarZceOHSiVSqZMmYJGo2Ho0KEyGimeCEkoRaN0tyQeFhbGuXPnsLOzM2ycLiVxUZWNGzcya9Ys4uPj6dq1q7HDEaJamZmZhIWFERQUxKVLl+jevTsajQY/Pz+sra2NHZ5oYiShFI2aXq8nLi6OsLAwNmzYwI0bNxg4cKChJC4lIHGv/Px87OzsWLBgAUuXLjV2OEJUoNfriYmJQavVsn37dgAmT56MRqNh+PDhMhopjEYSStFkFBYWsnfvXsLCwvjiiy+kJC4q9dJLL3Ho0CEuX76MUqk0djhCAJCVlUV4eDhBQUFcuHABFxcX1Go1/v7+tG3b1tjhCSEJpWia0tPTDavE7y2J+/v7y/F7TdzRo0d55plnOHz4MB4eHsYORzRher2eo0ePotVq2bp1K3q9nhdffBGNRoOHh4eMRop6RRJK0aRJSVzcT6/X4+zsjIeHByEhIcYORzRBN27cYO3atQQFBXH+/HmcnZ1Rq9UEBARgY2Nj7PCEqJQklEL8Rkri4q6lS5fy4YcfkpaWRsuWLY0djmgC9Ho93377LVqtlsjISHQ6HRMnTkSj0TBixAiZfiHqPUkohaiElMSbtl9//ZUuXbqwbt06fHx8jB2OaMRu3rzJunXr0Gq1/Pzzz3Tp0gW1Ws3s2bNp166dscMT4qFJQilENaQk3nR5eHhgamrKwYMHjR2KaGT0ej3Hjh1Dq9WyZcsWSkpK8Pb2RqPR8Oyzz8popGiQJKEU4iFJSbxpCQkJ4aWXXiIxMZH27dsbOxzRCGRnZ7N+/Xq0Wi3nzp2jc+fOzJ07l9mzZ2NnZ2fs8ISoFUkohaiB9PR0Nm7cSGhoKGfPnpWSeCOUk5ODnZ0df/nLX3j77beNHY5ooPR6PbGxsWi1WjZv3kxRURETJkxAo9EwatQoGY0UjYYklELUgl6v5/Tp04aSeFZWFgMGDCAgIIAZM2ZISbyBmzVrFqdOneLnn3+WLVrEI7l16xYbNmxAq9Vy5swZOnbsyNy5c5kzZw729vbGDk+IOicJpRB1pKioyFAS37t3LyqVCi8vLwICAhgzZoyUxBugAwcOMGbMGGJjY3F3dzd2OKKe0+v1HD9+HK1WS0REBIWFhbzwwgtoNBo8PT1RqVTGDlGIx0YSSiEeg8pK4j4+PgQEBEhJvAEpLS2lY8eOTJgwgf/85z/GDkfUUzk5OWzcuBGtVsvp06fp0KEDL730EnPmzMHR0dHY4QnxREhCKcRjJCXxhu/tt98mKCiI1NRUzMzMjB2OqEdOnDiBVqtl06ZNFBQUMH78eDQaDWPGjJHRSNHkSEIpxBMiJfGG6fz58/Tq1YutW7fy4osvGjscYWS3b99m48aNBAUFcerUKdq3b89LL71EYGCg7AYgmjRJKIUwgvtL4ra2toZV4q6ursYOT9zH3d0dOzs7du/ebexQhJGcOnUKrVbLxo0byc/PZ9y4cWg0GsaOHSujkUIgCaUQRlVdSXz69OlYW1sbO0QB/Oc//2H+/PkkJyfL6SVNSG5uLps2bSIoKIgTJ07g6OhIYGAgL730Ek5OTsYOT4h6RRJKIeqJoqIivvjiC0NJXKlUSkm8nsjKysLe3p6VK1fy2muvGTsc8ZidPn0arVbLhg0byM3NZezYsWg0GsaNGyc/h0JUQRJKIeqhjIwMQ0n8zJkz2NraGlaJS0ncOCZNmkRCQgKnTp0ydijiMcjLyyMiIoKgoCB++OEHHBwcCAwMJDAwkI4dOxo7PCHqPUkohajn7i2JZ2Zm0r9/f8MqcSmJPzm7du3C29ubM2fO0KdPH2OHI+rImTNn0Gq1rF+/ntu3bzNmzBg0Gg3jx4+X0UghHoEklEI0EPeXxBUKhaEk/txzz8mH32NWVFSEo6Mj/v7+fPjhh8YOR9RCfn4+mzdvJigoiO+//x47OzvD3MhOnToZOzwhGiRJKIVogKQkbhyvvfYamzdvJikpSRL4BujcuXNotVrWrVvHrVu3GD16NBqNhhdeeIFmzZoZOzwhGjRJKIVo4KQk/uScOnWK/v37s3fvXsaNG2fscMRDKCgoYMuWLQQFBfHdd99ha2vLnDlzeOmll+jSpYuxwxOi0ZCEUohGorqS+JgxY2QEpg7o9Xr69u1Lr1692Lx5s7HDEdX4+eef0Wq1rF27luzsbEaNGoVGo8HLywtTU1NjhydEoyMJpRCN0N2SeFhYGD/++KOhJO7v7y8LSmrpww8/5N133yU1NRUrKytjhyPuUVBQwNatWwkKCuKbb77BxsbGMBrp7Oxs7PCEaNQkoRSikTt9+jTh4eGsX79eSuJ1IDU1lfbt2/PZZ5+hVquNHY6g7HjMoKAgwsPDuXnzJn/4wx9Qq9V4e3vLaKQQT4gklEI0EUVFRezbt4+wsDD27NmDQqHghRdeMKwSl5L4wxs3bhy3bt3i22+/NXYoTdadO3fYtm0bQUFBHDlyhLZt2zJ79mzmzp1Lt27djB2eEE2OJJRCNEHXr183lMRPnz5Nu3btDKvEpST+YBEREcyYMYOLFy9K8vKE/fLLLwQHBxMeHk5WVhYjR45ErVYzceJEzMzMjB2eEE2WJJRCNHH3l8R/97vfGUribdu2NXZ49VJBQQH29vbMmzeP999/39jhNHqFhYVs374drVZLTEwM1tbWBAQEoFarcXFxMXZ4QggkoRRC/EZK4o9GrVbz5Zdf8uuvv6JUKo0dTqN08eJFgoODCQsLIzMzEw8PD9RqNZMmTaJ58+bGDk8IcQ9JKIUQFUhJ/MG+/fZbhg0bxtdff83IkSONHU6jUVRUxI4dO9BqtURHR9OmTRv8/f1Rq9X06NHD2OEJIaogCaUQolpSEq+cXq/HxcWFoUOHEhYWZuxwGrz4+HiCg4MJDQ3l+vXrDB8+HLVazeTJk2U0UogGQBJKIcRDkZJ4Re+//z4rVqwgLS2NVq1aGTucBqeoqIhdu3ah1Wo5dOgQlpaWhtHIXr16GTs8IcQjkIRSCPHIrl+/zqZNmwgLCyMuLs5QEvf396dv377GDu+JSUhIoHPnzoSHh+Pn52fscBqMK1euEBQURGhoKBkZGQwdOhS1Ws2UKVNo0aKFscMTQtSAJJRCiFr58ccfDSXx69ev069fPwICApg5c2aTKImPHDkSlUrFV199ZexQ6rXi4mJ2796NVqvl4MGDtG7dGj8/P9RqNa6ursYOTwhRS5JQCiHqRHFxsaEkHhUVhUKhYPz48QQEBDB27NhGWxIPDQ0lMDCQq1ev4uTkZOxw6p1ff/2V4OBgQkJCSE9P5/e//z1qtZqpU6dibm5u7PCEEHVEEkohRJ27vyRuY2NjWCXe2Erit2/fxs7Ojj//+c+88847xg6nXiguLmbPnj1otVoOHDjAU089ha+vL2q1utH99xdClJGEUgjxWDWFkrivry8//PADv/zyCwqFwtjhGM3Vq1cNo5GpqakMGjQIjUbD1KlTadmypbHDE0I8RpJQCiGeiMZcEv/qq6/w9PTk2LFjDB482NjhPFElJSXs3bsXrVbL/v37adWqFT4+Pmg0Gp5++mljhyeEeEIkoRRCPHGNrSReWlpKp06dGD9+PJ999pmxw3kiEhMTWb16NWvWrCElJYWBAwei0WiYNm2abKEkRBMkCaUQwqgaS0n8nXfe4bPPPiM1NbXRbsRdUlLCvn370Gq17Nu3D3Nzc2bNmoVGo6Ffv37GDk8IYUSSUAoh6oXi4mL2799vKIkDDaokfuHCBXr06MGWLVuYMmWKscOpU0lJSYbRyKSkJPr3749Go2H69Ok89dRTxg5PCFEPSEIphKh3MjMzDWeJ3y2Jz5o1i4CAgHo9L2/w4MG0bduWPXv2GDuUWistLWX//v1otVr27t1LixYtmDlzJhqNhv79+xs7PCFEPSMJpRCiXru/JO7m5mYoidvY2Bg7vHI+++wz5s2bR3JyMra2tsYOp0aSk5NZs2YNq1ev5tq1a/Tr1w+NRsOMGTOwsLAwdnhCiHpKEkohRINwf0lcr9cbSuLjxo2rFyXxGzduYG9vzz/+8Q8WLFhg7HAeWmlpKQcOHECr1bJnzx7MzMyYMWMGGo2GAQMGNOmtkIQQD0cSSiFEg5OZmWlYJX7q1Kl6VRKfPHky8fHxnD592qhxPIyUlBRCQkJYvXo1V69e5emnn0aj0TBr1iwZjRRCPBJJKIUQDdqZM2cMJfGMjAyjl8SjoqLw8vLi9OnTRk9uK6PT6Th48CBarZbdu3djamrK9OnT0Wg0uLu7y2ikEKJGJKEUQjQK9aUkXlxcjKOjIz4+PqxateqJPPNhpKWlERISQnBwMAkJCfTp0weNRoOPjw+tW7c2dnhCiAZOEkohRKNj7JL4ggUL2LhxI0lJSTRr1oy8whISsvIoKtFhaqKkk3VLWpqZPPY4dDodhw4dQqvVsmvXLkxMTJg2bRoajYbBgwfLaKQQos5IQimEaNSMURI/ffo07qO8mPGX/5JQ2JLEG/nc+4tWAXRoY87I7u2YNagD3Wzrdi/H9PR0QkNDCQ4O5sqVK/Tu3dswGmllZVWnzxJCCJCEUgjRRFRWEn/++ecNJXFTU9M6ec61G/m8s+MsR+MzQa8DhbLKtiqlglKdnuHObVk+sQ9Obcxr/FydTkd0dDRarZadO3eiUqmYOnUqarWaIUOGyGikEOKxkoRSCNHk3F8Sb9u2raEk7ubmVuN+I44n8t7unyjR6SnVPfyvVpVSgYlSwVKv3kwf2OGRnpmRkUFYWBjBwcHEx8fTs2dPNBoNvr6+tGnT5lHfghBC1IgklEKIJu3s2bOEh4ezbt06MjIyePrppw0l8Xbt2j10P59GX+LDAxdrHc8bo114dWS3atvo9XrDaOSOHTtQKpVMnjwZjUbDsGHDZDRSCPHESUIphBCUlcS//PJLwsLC2L179yOVxCOOJ/L29rN1FsuKSX2YVslIZWZmJmFhYQQFBXHp0iW6d++ORqPBz88Pa2vrOnu+EEI8KkkohRBNRqdOnXB1dX3gWdtZWVmGkvjJkyerLIkfPnyYkSNHGr628/8XZvbVjy4+DDMTJV8t8MCpjTl6vZ6YmBi0Wi3bt28H4MUXX0Sj0fDMM8880dFIb29vdu3aBUDv3r05d+7cE3u2EKJ+q3q2uBBCNFHW1ta8+uqrnDhxgjNnzuDv78+mTZvo168fbm5u/Pvf/yYjI8PQ3nLIVKzHv46JpV25fnR3csna9wnXPppJ4j9fJG3jIgrT4h/4/BKdnje2nGLVqlX07NmTkSNHcurUKZYvX86VK1dwcnJixowZmJubM2jQIA4ePFir9/u3v/0NLy8vbG1tUSgULFmypNJ2CxYsYN26dfTo0aNWzxNCND6SUAohRDX69OnDhx9+SFJSElFRUTg7O/Pmm2/i6OjIm0v+AYBZRzdauY5E1eJ/2//o9ToyIpeS93MMT/Ufj9WI2ejyb5G+cRHFN5KrfWapTk/s1Vu8+8Gn9OvXj+joaH755Rdef/113njjDVatWsWsWbP46KOPUKlUjBs3jm+++abG7/Hdd9/l+PHj9OvXr9p2Hh4e+Pj4YGtrW+NnCSEap8e/s64QQjQCzZo1Y/z48YwfP95QEv9gZ2yV7fN/+ZbC5PO09X6blj2GAWDeczgpWjXZ32zExmthtc9ToGfeR1tYMW2A4doPP/xAREQEK1eu5I033gDAz88PV1dX3nzzTb777rsavbdff/2VTp06kZmZaZTjKoUQDZ+MUAoh6rXk5GQCAwNxcHDAzMyMzp078/LLL1NUVATAkiVLKp1HGBYWhkKhICEhocK9AwcO4ObmRvPmzenVq5dhbuK9srOzmT9/Pk5OTpiZmeHs7MyKFSvQ6XSGkriV8++qjDv/wrcoW1pi3n2I4ZrKvDXmPYdTcOl79CXF1b5vPQq+v3a73LWtW7eiUqlQq9WGa82bNycwMJBjx45x7dq1avusSqdOnWr0OiGEuEtGKIUQ9VZKSgru7u5kZ2ejVqvp0aMHycnJbN26lfz8/BptRn7p0iWmTZvGH//4R/z9/QkNDWXKlCns378fT09PAPLz8/Hw8CA5ORmNRkOHDh347rvvWLRoEampqfz73/8mt7CE9Jw7VT6nKP0yprZdUdy3sbmpvQu5p/dTfCMZ03adqo01MSufvMISwzGNcXFxuLi4YGFhUa6du7s7UHZCj5OT06N+S4QQotYkoRRC1FuLFi0iLS2N2NhYBgz4X+l32bJl1HSDiosXL7Jt2zYmTZoEQGBgID169OCtt94yJJSrVq3i8uXLxMXF0a1b2aptjUaDg4MDK1eu5PXXXydHZVHlMwBKc29i5uRa4bpJK6vf7mfBAxJKPZCQlUdvh9YApKamYm9vX6Hd3WspKSnV9ieEEI+LlLyFEPWSTqdj586dvPDCC+WSybtqul2Og4MDEydONHxtYWGBn58fcXFxpKWlARAZGcnw4cOxsrIiMzPT8G/UqFGUlpZy5MgRikp01T5HX1KEQtWs4g2VqeH+w7j3OQUFBZiZmVVo07x5c8N9IYQwBhmhFELUS9evXycnJwdX14qjfLXh7OxcIRl1cXEBICEhATs7Oy5dusSZM2eqXKCSkZGBm0n1f48rTEzRl1YyT7K0yHD/YZje85wWLVpQWFhYoc2dO3cM94UQwhgkoRRCNGhVjVSWlpbWuE+dToenpydvvvlmpfddXFywtm5ZbR+qVlaU5t6ocL0k9+Zv9x98so0C6HTPc+zt7UlOrrjlUGpqKlA2+iqEEMYgCaUQol6ysbHBwsLigaexWFmVzUnMzs7G0tLScP3q1auVto+Pj0ev15dLRC9eLDuD++5q565du5Kbm8uoUaOqfbatRXPSq7hn2q4Ld5J+Qq/XlVuYU5RyAUUzM5q1cay2b4AO1uaGBTkAbm5uREdHk5OTU25hTmxsrOG+EEIYg8yhFELUS0qlEm9vb6Kiojhx4kSF+3cX5XTt2hWAI0eOGO7l5eURHh5eab8pKSns2LHD8HVOTg5r167Fzc0NO7uyk26mTp3KsWPH+PLLLyu8Pjs7m5KSEgD6OVlWGb95j6Ho8rLJv/C/vSFL82+R/8s3tHB2R2FSyfzKe6iUCka6tCt3bfLkyZSWlhIUFGS4VlhYSGhoKIMGDZIV3kIIo5ERSiFEvbV8+XIOHDiAh4cHarWanj17kpqaSmRkJN988w2WlpaMHj2aDh06EBgYyMKFC1GpVISEhGBjY0NiYmKFPl1cXAgMDOT48ePY2toSEhJCeno6oaGhhjYLFy5k9+7djB8/noCAAPr3709eXh5nz55l69atJCQk0LZtW0b1tKXytBXMuw/F1KE7WV98RHHmNVTmFtw+tRe9XoflsFnl2mbu+Rd55w7h+Mc1mFiWnUJTqtPjM7hDuXaDBg1iypQpLFq0iIyMDJydnQkPDychIYE1a9aUa7tkyRKWLl1KdHQ0I0aMqPb7vG7dOq5evUp+fj5Qlpz/9a9/BcDX15eOHTtW+3ohhJCEUghRbzk6OhIbG8vixYvZsGEDOTk5ODo6MnbsWMzNzYGyE2x27NjBK6+8wuLFi7Gzs2P+/PlYWVkxe/bsCn1269aNTz75hIULF3LhwgU6d+7M5s2bGTNmjKGNubk5MTExLF++nMjISNauXYuFhQUuLi4sXbqU1q3LtvFp36YsBqWy4jxOhVJFu6lLyf46hNsno9CXFGJq1w3b5xfQzLp9ubb64gIUJmYom5fNl1QpFQzpYo1zu6cq9Lt27VoWL17MunXruHnzJn379mXPnj0888wz5drl5uaiUCgMo67VWbNmDTExMYavo6OjiY6OBmDYsGGSUAohHkihr+lmbkII0cQdPnyYkSNH4jBlMUr7Hiibt0KhVD1yP9c+9qGV67NYPTsHADMTJV8t8MDpt4S1Jtzd3enYsSORkZE17uN+t2/fprCwkAkTJnDr1q0Hzm8VQjQdModSCCFqKSXyfZI+nkVR+pVHfm3R9avoSwqxGPyi4doyr961SiZzcnL48ccfWbZsWY37qIyvry82NjY1PjNcCNF4yQilEELU0M2bNzl58iQAO08nsTulJUqzmieCAAtHd+f/RjrXRXh17syZM2RkZADQqlUrBg8ebOSIhBD1hSSUQghRRyKOJ/Le7p8o0ekp1T38r1aVUoGJUsEyr95MG9jhwS8QQoh6RhJKIYSoQ9du5PPOjrMcjc9EpVRUm1jevT/cuS3LJ/apVZlbCCGMSRJKIYR4DC6l32ZDbCLRFzNIzMrn3l+0Cso2LR/p0g6fwR0qXc0thBANiSSUQgjxmOUVlpCQlUdRiQ5TEyWdrFuWOwFHCCEaOkkohRBCCCFErci2QUIIIYQQolYkoRRCCCGEELUiCaUQQgghhKgVSSiFEEIIIUStSEIphBBCCCFqRRJKIYQQQghRK5JQCiGEEEKIWpGEUgghhBBC1IoklEIIIYQQolYkoRRCCCGEELUiCaUQQgghhKgVSSiFEEIIIUStSEIphBBCCCFqRRJKIYQQQghRK5JQCiGEEEKIWpGEUgghhBBC1IoklEIIIYQQolYkoRRCCCGEELUiCaUQQgghhKgVSSiFEEIIIUStSEIphBBCCCFqRRJKIYQQQghRK5JQCiGEEEKIWpGEUgghhBBC1IoklEIIIYQQolYkoRRCCCGEELUiCaUQQgghhKgVSSiFEEIIIUStSEIphBBCCCFqRRJKIYQQQghRK5JQCiGEEEKIWpGEUgghhBBC1IoklEIIIYQQolYkoRRCCCGEELUiCaUQQgghhKgVSSiFEEIIIUStSEIphBBCCCFq5f8DBAs8VaWyEvIAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "cube_architecture = Architecture(cube_coupling_map)\n", "draw_graph(cube_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To avoid that tedium though we could just use our SquareGrid Architecture:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from pytket.architecture import SquareGrid" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAAHzCAYAAACe1o1DAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAwwNJREFUeJzs3WdYVFfXBuBn6E1UEBGVIlZEsIsN6VUE1GCvMfYSjUqMDfBVrLFGjRpLomIvIL0jYI/YUBFUmtIUpQvMzPl++DERQemcGVj3dfHDKXseTZhZs8/ee3EYhmFACCGEEEJILYmxHYAQQgghhIg2KigJIYQQQkidUEFJCCGEEELqhApKQgghhBBSJ1RQEkIIIYSQOqGCkhBCCCGE1AkVlIQQQgghpE6ooCSEEEIIIXVCBSUhhBBCCKkTKigJIYQQQkidUEFJCCGEEELqhApKQgghhBBSJ1RQEkIIIYSQOqGCkhBCCCGE1AkVlIQQQgghpE6ooCSEEEIIIXVCBSUhhBBCCKkTKigJIYQQQkidUEFJCCGEEELqhApKQgghhBBSJ1RQEkIIIYSQOqGCkhBCCCGE1AkVlIQQQgghpE6ooCSEEEIIIXVCBSUhhBBCCKkTKigJIYQQQkidUEFJCCGEEELqhApKQgghhBBSJ1RQEkIIIYSQOqGCkhBCCCGE1AkVlIQQQgghpE6ooCSEEEIIIXVCBSUhhBBCCKkTKigJIYQQQkidUEFJCCGEEELqhApKQgghhBBSJ1RQEkIIIYSQOpFgOwAhpHYKirlIfF+AEi4fUhJi0FKWh7w0/UoTQghpfPTpQ4gIic/Iw+nbyQiLy0RydiGYL+7jANBQkoNJ97aYbKCBrqot2IpJCCGkmeEwDMNU/TBCCJtSsgux+spjRCa8g7gYBzz+t39ty+437NIG7qP1oK4k14hJCSGENEdUUBIi5M7eTYaLVyy4fOa7heTXxMU4kBDjwM1eFxMGajRgQkIIIc0dFZSECLE/wuKxI/BFncdZYdkNi0y61kMiQgghpCLa5U2aHQ6HA1dX1yof5+rqCg6H0/CBvuHs3WS47jiApC124H7MqPHz00+vQtIWOyRtsYPz7Mk4dze5AVIKh6tXr4LD4Qh+7t27x3YkQghpVqigJKQGtLS0wOFwsHjx4gr3hYeHg8Ph4OLFi3V+nZTsQrh4xdZ5HAnljlC2Ww7FQaOx3isWKdmFgvu8vLzQr18/yMjIQENDAy4uLuByuXV6vRs3bmD48OGQk5NDu3btsGTJEuTn59dpzGfPnsHa2hoKCgpQUlLC1KlTkZWVVe4xAwYMwMmTJzFnzpw6vRYhhJDaoYKSNDtFRUVYu3ZtncY4cuQI3r59W0+JKlp95TG4NVgv+S3icq2g0MsEMpr64PIZrL7yGADg5+cHR0dHtGrVCvv27YOjoyM2btxYaaFcXQ8ePICZmRkKCwuxc+dO/PTTTzh8+DCcnJxqPWZqaipGjBiBhIQEuLu7Y8WKFfDx8YGFhQVKSkoEj+vYsSOmTJmCIUOG1Pq1CCGE1B4dG0SaBT6fj5KSEsjIyEBGRqZOY+nq6iIuLg5btmzB3r176ynhf+Iz8hCZ8K7ex+XxGUQmvENCZh5WrFgBfX19BAYGQkLi89uAoqIi3N3d8fPPP6NHjx41Hn/16tVo3bo1wsPDoaioCODzjO7s2bMRGBgIS0vLGo/p7u6OgoIC/Pvvv9DQ+LyxaNCgQbCwsMCJEydoRpIQQoQEzVASkRIeHo4BAwZARkYGnTt3xqFDhypd68jhcLBo0SKcPn0aurq6kJaWhr+/v+C+r9dQRkVFYeDAgeXG/RYtLS1Mmzat2rOUMTExsLGxgaKiIhQUFGBmZoZbt25VeFxsbCxMTU3RU0MFqfun42P0WYDhVzpm0ct7SD/ljOTfxyJ5pxMyL7iiJCupyiziYhzsOh+Gp0+fYs6cOYJiEgAWLFgAhmFqdck+NzcXQUFBmDJliqCYBIBp06ZBQUEB58+fr/GYAHDp0iXY2dkJikkAMDc3R7du3Wo9JiGEkPpHM5REZMTExMDa2hpqampwc3MDj8fDhg0boKKiUunjQ0NDcf78eSxatAht2rSBlpZWpY97/PgxLC0toaKiAldXV3C5XLi4uEBVVfWbWdasWYN//vmnylnK2NhYGBoaQlFREc7OzpCUlMShQ4dgbGyMiIgIGBgYAADS09NhYmICLpeLDkYTkMMVR/4Df3AkpCqMmf8kFO+9d0FGux9aGc8AU1qMvBg/ZJxyhtrMvZBo9e3cPD6DkBu3AXxed/il9u3bo2PHjoiJifnm87/l8ePH4HK5FcaUkpJCnz59ajXmmzdvkJmZWWFM4PMspa+vb43HJIQQ0jCooCQiw8XFBeLi4oiOjkb79u0BAOPGjYOOjk6lj4+Li8Pjx4/Rs2fP7467fv16MAyDyMhIwUzY2LFjoaen983naGtrY+rUqThy5Ah+++03qKmpVfq4tWvXorS0FFFRUdDW1gbwedaue/fucHZ2RkREBABg69atyMrKQlhkNGb6fEBLAAp6ZnhzqPwlXX5JET4EHYJCb0so2/y33lFBzwxvDs9Dzs3z5W6vTGZ6OgBUmllNTa1Wa0PT0tK+O2ZkZGS9j5mdnY3i4mJIS0vXeGxCCCH1iy55E5HA4/EQHBwMR0dHQTEJAF26dIGNjU2lzzEyMqqymOTxeAgICICjo2O5y6o6OjqwsrL67nPXrl0LLpeLLVu2fHPswMBAODo6CopJ4HMxNGnSJERFRSE3NxcA4Ovri8GDB0NFW1fQTlFcriXkdY3LjfnpdQz4xQWQ72kEXmGO4AccMUi374ZPyY++mxkA+NxiAKi0EJORkUFRUVGVY3yt7DmNOeaXjyGEEMIumqEkIiEzMxNFRUXo0qVLhfsquw0AOnXqVOW4WVlZKCoqQteuFQ/97t69+3cvq5bNUh4+fBirVq2qdOzCwkJ07969wn06Ojrg8/lISUmBrq4ukpKSYGBggBJu+TWTkkodyv259MPn2cOMM6srzcSRrrrNIkfic4FWXFxc4b5Pnz5BVla2yjG+Vvacxhzzy8cQQghhFxWUpMlqjGJjzZo1OHnyJLZu3QpHR8c6jyclUcVFg/9vbKVstxziCq0r3M3hVH3Roex5aWlpUFdXL3dfWloaBg0aVM20/ym7LF12mfrrMb+cVa6vMZWUlOhyNyGECAm65E1EQtu2bSEjI4OEhIQK91V2W3WpqKhAVlYW8fHxFe6Li4ur8vmdO3fGlClTcOjQoQqFj4qKCuTk5Cod5/nz5xATExMUdJqamoiPj4eWsjy+3K9emv2m3PMkWn8ussTlW0JWq0+FHxlN/SozS6l8nrn19PTEl51X3759i9TUVPTp06fKMb7Wq1cvSEhIVOhQU1JSggcPHtRqzA4dOkBFRaXSrjd37typ1ZiEEEIaBhWURCSIi4vD3NwcV69eLbdpJCEhAX5+fnUa18rKClevXkVy8n+tCZ89e4aAgIBqjVG28Wbbtm0Vxra0tISnpycSExMFt2dkZMDDwwPDhw8XHLFja2uLW7duIfbhfWgofb5szSvMQUFseLkxZTv1A0daDjk3zoPhVexqwyvMqTKvvGJLcDgcuLu7Q1VVFZMnT8bx48exdetWcDgc/PDDD9X6e3+pZcuWMDc3x6lTp5CXlye4/eTJk8jPz6/14eZjx46Ft7c3UlJSBLeFhITgxYsXdTownRBCSP2igpKIjLIjfYYNG4Zt27Zh8+bNMDIyQq9eveo0rpubGwDA0NAQW7duxaZNm2BiYgJdXd1qPb9slvLBgwcV7tu4cSMkJCQwfPhwuLu7Y9u2bRg6dCiKi4vLFaDOzs5QVlaGtbU1ODEXkXfnMtJProSEYvkjkcSk5aBsuQDFqU+RduJn5Nw4h7wH/vhw/STeHluCnCiP72YVF+NgsklfXLx4ERwOB3JycoiOjsaPP/6IvXv3QlFREfv378fVq1fx8eNHJCYmgsPhYMaMGVX+O2zatAnZ2dkwMjLCn3/+ibVr12LRokWwtLSEtbV1ucdyOBwYGxtXOebq1ashJycHExMT7Nu3D5s3b4aTkxP09PQwc+bMKp9PCCGkcVBBSURG//794efnh9atW2PdunU4evQoNmzYADMzszp1v9HX10dAQABUVFSwfv16HDt2DG5ubhg9enS1x1i7di3ExcUr3K6rq4vIyEj06tULmzdvhpubGzQ1NREWFiY4gxL4vF4wLCwM+vr6uHXlGHLuekK+lykUB9hXGFNe1xiqEzZCXEEZObcv40PwYRQ+vQ4pVW3I61t8NyePz2DKYA2MGTMGly9fRuvWrZGeno727dtj7NixcHJygp+fH0aPHg1lZWU4ODgAAEpLS8u1OqxMv379EBwcDFlZWSxbtgyHDx/GrFmzKhyUXtbb+1tHLX1JXV0dERER6Ny5M1atWoVt27bB1tYWQUFBtH6SEEKECIf5chEVISLI0dERsbGxla6DFFVTj97GjVfvwatDP+/006sAPg8qY9eCIy4JSVl5DNVWxslZBlU+99WrVwgJCcHBgwcFh5LLycnByMgI5ubmMDc3h56eXoUORdXh6+sLOzs7PHz48LtnfdZESUkJcnNzcfbsWSxevBh3796t9EB0QgghDYNmKIlI+frcwfj4ePj6+lbr8qkoWWfdBXxuKer6fa/4zTOk7p2Md17bISHGgfvo6hVw2tramD17tmBm8N9//4WLiwtKS0uxevVq9O7dG2pqaoL1l1+ucaxKWFgYJkyYUG/FJPC5SFVRUcHixd8/1J0QQkjDoBlKIlLU1NQwY8YMaGtrIykpCQcPHkRxcTFiYmIqPUtSFH348AGjRo3Cs5LWaGE2r9bjFKcngP/p8+VlcVlF7JrvgPEDNap4VtWKiopw48YNBAUFITg4GPfv3wfDMOjevTvMzc1hYWEBY2NjtGzZss6vVV1ZWVl4+PCh4M8GBgZo0aJFo70+IYQ0d1RQEpEyc+ZMhIWFIT09HdLS0hgyZAjc3d3Rr18/tqPVizdv3sDKygrp6enw8fHB3UIl7Ah8UedxV1p2x0KTyg+Ar6v3798jNDQUwcHBCA4OxqtXryAmJoZBgwbBwsIC5ubmGDx4MKSkKvYlJ4QQ0jRQQUmIkHj+/Lmg3WNAQAB69OgBADh7NxkuXrHg8pkarakUF+NAQoyDDfa69TIzWV2vXr0SFJchISHIzs4WrL8sKzB79epVq/WXhBBChBMVlIQIgTt37sDW1hbt2rWDv78/OnbsWO7+lOxCrL7yGJEJ7yAuxvluYckBAwYcDOggj12TBkFdqep2jA2Fz+cjJiZGUGBGRkaiuLgYqqqqgs095ubmFf6+hBBCRAsVlISwLDAwEGPGjEHv3r1x7do1KCkpffOx8Rl5OH07GWEvMpH8vhBf/vJyAGgoy2G4dmsc+XUaxlsbYd++fQ2evyaKiooQHR0tKDC/XH9ZNnvZ2OsvCSGE1B0VlISwyMPDA9OnT4eVlRXOnz8PObnqzyYWFHOR+L4AJVw+pCTEoKUsD3lpCQCfD2vfunUrkpOT0aZNm4aKX2fv3r1DWFgYgoODERQUhNevX0NcXByDBg0SzF7S+ktCCBF+VFASwpI9e/Zg6dKlmD59Oo4cOQJJScl6G/vdu3fQ0NDAqlWrsH79+nobt6GVrb8MCgpCaGgosrOzIS8vLzj/0sLCArq6urT+khBChAwVlIQ0MoZhsGbNGmzevBnOzs7YsmVLgxRIixYtwvnz55GUlARZWdl6H7+h8Xg8PHjwQHA8UVRUFK2/JIQQIUUFJSGNiMvlYt68eTh69Ch27NiB5cuXN9hrvXr1Cl27dsX+/fsxb17tz7MUFmXrL8sKzJiYGDAMgx49eghmL42MjGj9JSGEsIAKSkIaSVFRESZOnAgfHx8cO3YMU6dObfDXHDduHO7fv4+4uLhKe42Lsnfv3gnOvwwKCkJiYqJg/WXZBh8DAwNaf0kIIY2ACkpCGsHHjx9hb2+Pe/fu4dKlS7CxsWmU17179y4GDRqEixcvYuzYsY3ymmx5+fJlufMvP3z4IFh/WVZg0vpLQghpGFRQEtLA3r59C2tra6SmpsLHxwdDhgxp1Nc3MTFBYWEhbt261WyKKR6PV+78y7L1l+3atSu3/rJDhw5sRyWEkCaBCkpCGtCLFy9gZWUFLpeLgIAA9OzZs9Ez+Pr6YuTIkYiIiMCIESMa/fWFQWFhoeD8y6CgIMTExAAAdHR0BMWlsbExFBUVWU5KCCGiiQpKQhrIvXv3YGtrizZt2iAgIADq6uqs5GAYBvr6+tDS0sK1a9dYySBsvrX+0sDAQLDBx8DAoF6PciKEkKaMCkpCGkBwcDBGjx6NXr16wdvbG8rKyqzm+fvvvzFjxgzExsayMksqzBiGqXD+5YcPH6CgoFDu/MuePXs2myUDhBBSU1RQElLPzp07h6lTp8Lc3BwXLlyAvLw825FQUlICbW1tWFpa4tixY2zHEWpl6y+/PP+ypKREsP7SwsICZmZmtP6SEEK+QAUlIfXojz/+wJIlSzB58mQcO3ZMqC6Z7tixA6tXr0ZiYiLat2/PdhyRUVhYiKioKMEGny/XX5btHjcyMqL1l4SQZo0KSkLqAcMwWL9+PTZu3IhffvkF27dvh5iYGNuxysnNzYW6ujrmzZuHrVu3sh1HZGVlZZVbf5mUlCRYf/nl+ZfC9GWCEEIaGhWUhNQRj8fDggULcPjwYWzbtg0rV65kO9I3/frrr/jzzz+RkpJCM2r1gGGYcudffrn+0tjYWLCDnNZfEkKaOiooCamDT58+YdKkSfDy8sJff/2FGTNmsB3pu96+fQstLS24u7tjxYoVbMdpcng8Hu7fv1/u/MuSkhKoqamVO/+SlhwQQpoaKigJqaWcnBw4ODjg9u3bOH/+PEaNGsV2pGr58ccfERgYiFevXlFbwgb25frLoKAgPHjwAADQs2fPcudftmjRgt2ghBBSR1RQElILaWlpsLGxQVJSEry9vTFs2DC2I1Xb06dPoauri7///hvTpk1jO06zUrb+MigoCEFBQUhOToaEhES58y8HDRpE6y8JISKHCkpCaighIQGWlpYoLi5GQEAAevXqxXakGrOzs0NSUhIePXpEa/tY8uX6y7LzLz9+/ChYf1m2wUdHR4f+GxFChB4VlITUwP3792FjY4PWrVsjICAAmpqabEeqlevXr8PIyAi+vr6wsbFhOw7Bf+svy86/jI6OLrf+suz8S1p/SQgRRlRQElJNoaGhcHR0RI8ePeDr64s2bdqwHanWGIbB4MGDIScnh7CwMLbjkEoUFhYiMjJSsMHny/WXX55/SesvCSHCgApKQqrh4sWLmDx5MoyNjXHp0iUoKCiwHanOLl68CCcnJ9y9excDBgxgOw6pQlZWFkJCQgSXyL9cf1lWYNL6S0IIW6igJKQKf/75JxYsWIAJEybgxIkTTWZnNI/HQ/fu3dG/f3+cO3eO7TikBhiGQUJCQrnzLz9+/IgWLVqUO/+S1l8SQhoLFZSEfAPDMHBzc4Obmxt+/vln7Ny5U+i639TVwYMHsWjRIsTHx0NbW5vtOKSWeDwe/v33X8Hs5Y0bN1BSUoL27duXO/9STU2N7aiEkCaKCkpCKsHj8bB48WIcPHgQ7u7uWLVqVZOc6SkqKoKmpibGjRuHP/74g+04pJ4UFBQgKipKsMHn4cOHAABdXV1BcUnrLwkh9YkKSkK+UlxcjClTpuDy5cs4fPgwZs2axXakBrVhwwZs2bIFycnJIr3RiHxbZmZmufMvU1JSICEhgcGDBwt2kA8cOJDWXxJCao0KSkK+kJubi9GjR+PGjRs4e/YsHBwc2I7U4N69ewcNDQ38+uuvcHFxYTsOaWBl6y/LZi9DQ0ORk5MjWH9ZtsGnR48eTXJWnhDSMKigJOT/ZWRkwMbGBq9evcK1a9dgaGjIdqRGs3jxYpw9exZJSUmQk5NjOw5pRFwuV7D+suz8y9LSUsH6y7LzL2n9JSHke6igJATAq1evYGlpicLCQvj7+0NfX5/tSI3q9evX6NKlC/bt24cFCxawHYewqKCgoNz5l1+uvyybvRwxYgStvySElEMFJWn2Hj58CGtra7Ro0QIBAQHo1KkT25FYMWHCBNy7dw9xcXEQFxdnOw4REhkZGQgNDRXsIC9bfzlkyBDBBp9BgwZBQkKC7aiEEBZRQUmatYiICNjb26Nr167w9fVF27Zt2Y7Emn///RcDBgzAhQsX8MMPP7AdhwghhmEQHx8vKC7DwsIE6y9NTEwEBSatvySk+aGCkjRbly9fxqRJk2BoaIjLly/TJTwApqamyM/Px+3bt6kgIFX6cv1l2fmXpaWl6NChQ7nzL9u1a8d2VEJIA6OCkjRLR44cwbx58+Dk5IS///4b0tLSbEcSCv7+/rCxsUF4eDiMjIzYjkNETNn6y7Id5I8ePQIA9OrVS7DBZ8SIEU2idSkhpDwqKEmzwjAMNm3ahHXr1mHRokXYs2dPk+t+UxcMw6B3795QV1eHj48P23GIiMvIyCjXfzw1NbXc+suy8y9p/SUhoo8KStJs8Pl8/Pzzz/jjjz/wv//9D2vWrKHLupX4559/MH36dDx58gS6urpsxyFNRNn6yy/Pv8zNzYWiomK58y+7d+9Ov5eEiCAqKEmzUFxcjOnTp+PChQs4ePAg5syZw3YkoVVSUoLOnTvD3Nwcx48fZzsOaaK4XC7u3bsnOJ7o6/WXZedf0vpLQkQDFZSkycvLy8OYMWMQGRkJDw8PjBkzhu1IQu/333/Hb7/9htevX6NDhw5sxyHNQEFBAa5fvy4oMMvWX+rp6Qk299D6S0KEFxWUpEnLysqCra0tXrx4AU9PTxgbG7MdSSTk5uZCQ0MDc+bMwbZt29iOQ5qh9PT0cudfpqamQlJSstz5l7T+khDhQQUlabISExNhaWmJ3Nxc+Pv7o0+fPmxHEimrVq3CgQMHkJKSgpYtW7IdhzRjDMPgxYsX5c6/LFt/+eX5l7T+khD2UEFJmqRHjx7B2toacnJyCAwMhLa2NtuRRM7bt2+hpaWFTZs2YeXKlWzHIUTgy/WXQUFBuHnzJkpLS9GxY8dy51+qqqqyHZWQZoMKStLkREZGYtSoUdDW1oafnx99qNTBrFmz4O/vj9evX0NKSortOIRUKj8/v9z5l48fPwbw3/pLCwsLGBoa0vpLQhoQFZSkSfHy8sL48eMxZMgQXL16FYqKimxHEmnPnj1Dz549cfz4ccyYMYPtOIRUS3p6ernzL9+8eVNu/aWFhQUGDBhA6y8JqUdUUJIm4+jRo5gzZw7GjBmDkydPQkZGhu1ITYK9vT1evXqFx48f0/o0InLK1l+WzV5+vf6y7PzLbt260f/fhNQBFZRE5DEMgy1btmD16tWYP38+9u3bB3FxcbZjNRmRkZEYMWIEfHx8YGtry3YcQuqEy+Xi7t27guOJytZfqqurC9ZempmZ0VIZQmqICkoi0vh8Pn755Rfs2bMHrq6uWL9+Pc0y1DOGYTBkyBDIyMggPDyc7TiE1Kv8/HzB+ZdBQUF48uQJAEBfX7/c+Zfy8vIsJyVEuFFBSURWSUkJZs6ciTNnzmD//v2YP38+25GarMuXL2Ps2LG4ffs2Bg0axHYcQhrMt9ZfDh06VFBg0vpLQiqigpKIpPz8fPzwww8ICwvD6dOn8cMPP7AdqUnj8Xjo0aMH+vTpgwsXLrAdh5BGwTAM4uLiyp1/mZeXh5YtWwrOv7SwsEDXrl3pyghp9qigJCLn3bt3GDlyJJ49e4arV6/C1NSU7UjNwqFDh7BgwQK8ePECnTt3ZjsOIY2ubP1l2Qafmzdvgsvl0vpLQkAFJRExSUlJsLKywocPH+Dn54d+/fqxHanZKCoqgqamJpycnLB//3624xDCurL1l2UF5tfrL8vOv6T1l6Q5oIKSiIzY2FhYWVlBSkoKgYGB6NKlC9uRmp3//e9/cHd3R3JyMlRUVNiOQ4hQSUtLK7f+8u3bt4L1l2XHE/Xv318k1l8WFHOR+L4AJVw+pCTEoKUsD3lp4c9N2EMFJREJ0dHRsLOzg6amJvz8/KCmpsZ2pGbp/fv30NDQwMqVK+Hq6sp2HEKEFsMweP78ueB4oi/XX5qamgoukQvT+sv4jDycvp2MsLhMJGcX4svigANAQ0kOJt3bYrKBBrqqtmArJhFSVFASoeft7Q0nJycYGBjA09MTLVu2ZDtSs7ZkyRJ4eHggOTkZcnJybMchRCSUlpZWOP+Sy+VCQ0Oj3PrLtm3bNnq2lOxCrL7yGJEJ7yAuxgGP/+2yoOx+wy5t4D5aD+pK9B5APqOCkgi1EydO4KeffoK9vT08PDyo+40QeP36Nbp06YK9e/di4cKFbMchRCTl5eWVO/8yNjYWANC7d+9y51829Je2s3eT4eIVCy6f+W4h+TVxMQ4kxDhws9fFhIEaDZiQiAoqKInQ2r59O5ydnTF79mwcPHiQut8IkYkTJ+LOnTuIi4sTifVghAi7ytZfSklJCc6/tLCwQP/+/ev1ffCPsHjsCHxR53FWWHbDIpOu9ZCIiDIxtgMQ8jU+n48VK1bA2dkZ69atw6FDh6iYFDIrV67Eq1evcPnyZbajECJUOBxOtdYXu7q6lls7qaamhilTpuDEiRNITU3F06dPsWPHDrRo0QJbt26FgYEB2rRpgzFjxuDAgQOIj49HXeaDzt5NhuuOA0jaYgfux4waPz/99CokbbFD0hY7OM+ejHN3k2udRdg9ePAAHA5H8HPx4kW2IwklKiiJUCktLcX06dOxc+dO7Nu3Dxs2bBCaBevkP/369YOZmRm2b99epw81Qsh/tLS0wOFwsGTJEujo6GDx4sXw8vLC+/fvsW/fPnz8+BHPnj3Dzz//jG7dukFLSwuzZs3C2bNnkZmZWe3XSckuhItXbJ3zSih3hLLdcigOGo31XrFIyS4U3Ofl5YV+/fpBRkYGGhoacHFxAZfLrdPr3bhxA8OHD4ecnBzatWuHJUuWID8/v9bj3blzBwsWLED//v0hKSn5zc8aTU1NnDx5EqtXr671azUHVFASoVFQUAAHBwecO3cOZ86cwaJFi9iORL5j5cqVuHfvHiIiItiOQojQKCoqwtq1a+s0xpEjR/D27VvBnyUlJdGrVy8An4/uys7Ohre3N0aPHo3bt29j4sSJUFVVRZ8+fbBy5UoEBASgsLDwW8Nj9ZXH4NZgveS3iMu1gkIvE8ho6oPLZ7D6ymMAgJ+fHxwdHdGqVSvs27cPjo6O2LhxIxYvXlzr13rw4AHMzMxQWFiInTt34qeffsLhw4fh5ORU6zF9fX3x119/gcPhQFtb+5uPa926NaZMmQILC4tav1ZzQIufiFB4//497Ozs8PjxY/j4+NAvrgiwtLSEvr4+tm3bBmNjY7bjEMIaPp+PkpISyMjI1HnjoK6uLuLi4rBlyxbs3bu30se0aNECI0eOxMiRIwEAb9++Fay/9PDwwI4dOyAlJYVhw4YJNviUrb+Mz8hDZMK7OmWsDI/PIDLhHRIy87BixQro6+sjMDBQsMZaUVER7u7u+Pnnn9GjR48aj7969Wq0bt0a4eHhUFRUBPB5Rnf27NkIDAyEpaVljcecP38+fv31V8jKymLRokV48aLu60mbM5qhJKxLSUmBoaEhEhISEB4eTsWkiOBwOFi5ciX8/Pzw+PFjtuMQUmfh4eEYMGAAZGRk0LlzZxw6dKjCWkfg8//7ixYtwunTp6GrqwtpaWn4+/sL7vt6DWVUVBQGDhxYbtxv0dLSwrRp0yrMUn5LTEwMZs2ahYULF+LSpUvo0aMHPDw8sH37digoKGDz5s0wMDBA69at0bZtW/ToqIzU/dPxMfoswPArHbPo5T2kn3JG8u9jkbzTCZkXXFGSlVRlFnExDnadD8PTp08xZ86cchv2FixYAIZharX+MDc3F0FBQZgyZYqgmASAadOmQUFBAefPn6/xmACgqqoKWVnZWj2XVEQFJWHV06dPMXToUBQWFiI6OhoDBgxgOxKpgfHjx0NdXR07duxgOwohdRITEwNra2u8f/8ebm5umDVrFjZs2ICrV69W+vjQ0FAsW7YM48ePx549e6ClpVXp4x4/fgxLS0tkZmbC1dUVM2fOhIuLC65cufLNLGvWrAGXy8WWLVu+mzk2NhaGhoZ4+PChYBPj69evMXPmTBgYGMDLywvZ2dnw9PQEj8fDhw8fIN/bGi0GOKDgSShy73lVGDP/SSgyL7iBIyWLVsYz0HLoeJS8S0HGKecqN+/w+AxCbtwGgArv5e3bt0fHjh0RExPz3TEq8/jxY3C53ApjSklJoU+fPrUak9Q/uuRNWHPz5k3Y2dmhQ4cO8Pf3R/v27dmORGpIUlISy5Ytg7OzMzZt2oSOHTuyHYmQWnFxcYG4uDiio6MF70Xjxo2Djo5OpY+Pi4vD48eP0bNnz++Ou379ejAMg8jISGhofD6vcezYsdDT0/vmc7S1tTF16lQcOXIEv/322zc7g61duxalpaWIiooSrAGcNm0aunfvDmdnZ0REREBSUhJhYWEoLCxEWGQ0Zvp8AANAQc8Mbw7NKTcev6QIH4IOQaG3JZRt/lvvqKBnhjeH5yHn5vlyt1cmMz0dACrNrKamVq1Z16+lpaV9d8zIyMgaj0nqH81QElb4+fnBzMwMPXv2xPXr16mYFGE//fQT5OXlsWfPHrajEFIrPB4PwcHBcHR0LPde1KVLF9jY2FT6HCMjoyqLSR6Ph4CAADg6OgqKSQDQ0dGBlZXVd5+7du3a785S8ng8BAYGwtHRsdyGEjU1NUyaNAlRUVHIzc0F8HnzyeDBg6GirStopygu1xLyusblxvz0Ogb84gLI9zQCrzBH8AOOGKTbd8On5EffzQwAfG4xAEBaWrrCfTIyMigqKqpyjK+VPac+xyT1jwpK0uhOnjwJe3t7WFhYIDAwEK1atWI7EqmDFi1aYP78+Th06BBycnLYjkNIjWVmZqKoqAhdunSpcF9ltwFAp06dqhw3KysLRUVF6Nq14qHf3bt3/+5zy2YpDx8+LJih+3rswsLCSsfR0dEBn89HSkoKACApKQldu3ZFCbf8mklJpQ7l/lz64fPsYcaZ1UjdO7ncz6fXMZ+LyypwJD4XfcXFxRXu+/TpU63WLJY9pz7HJPWPCkrSqH7//XdMmzYN06ZNw6VLl+iNoIlYsmQJiouLv7vZgJCmpDHeu8rWUm7durVexpOSqOIj///PlFW2W462EzZW/BlT9XFI4gqtAaDSIjgtLa1WV6PKLnXX55ik/lFBSRoFwzBwdnbGihUr8Ntvv+Gvv/6iln1NiJqaGqZOnYrdu3dXOotAiDBr27YtZGRkkJCQUOG+ym6rLhUVFcjKyiI+Pr7CfXFxcVU+v3PnzpgyZQoOHTpUoZhSUVGBnJxcpeM8f/4cYmJiUFdXB/D5YO74+HhoKcvjy/3qpdlvyj1PovXnwk1cviVktfpU+JHR1K8ys3Tbz5ff7927V+72t2/fIjU1FX369KlyjK/16tULEhISFcYsKSnBgwcPajUmqX9UUJIGx+Vy8eOPP2L79u3YvXs33N3dqftNE7R8+XKkpaXBw8OD7SiE1Ii4uDjMzc1x9erVcptGEhIS4OfnV6dxrayscPXqVSQn/9ea8NmzZwgICKjWGGUbb7Zt21ZhbEtLS3h6eiIxMVFwe0ZGBjw8PDB8+HDBETu2tra4desWYh/eh4aSHACAV5iDgtjwcmPKduoHjrQccm6cB8Or2NWmOpe8u/TQQY8ePXD48GHweDzB7QcPHgSHw8EPP/xQrb/3l1q2bAlzc3OcOnUKeXl5gttPnjyJ/Pz8Oh1uTuoPTRGRBlVYWIjx48fD398fp0+fxqRJk9iORBqIjo4O7O3tsWPHDkyfPh1iYvR9lYgOV1dXBAYGYtiwYZg/fz54PB7++OMP9OrVCw8ePKj1uG5ubvD394ehoSEWLFgALpeLffv2QVdXF48eVb3JpWyW8u+//65w38aNGxEUFIThw4djwYIFkJCQwKFDh1BcXFyuAHV2dsbJkydhbW0NfeuJyMv4hNwYf0goqqA0q0DwODFpOShbLsA7751IO/Ez5HVGQEyuJbi5WShKuAuZjjpQspz/zaziYhyYdGuLAdu3w97eHpaWlpgwYQKePHmCP/74Az/99FO5XfOJiYno1KkTpk+fjhMnTnz332HTpk0YOnQojIyMMGfOHKSmpuL333+HpaUlrK2tyz2Ww+HAyMgI4eHh3x0zKSkJJ0+eBPDfjOrGjRsBfJ7VnTp16nefT8qjgpI0mOzsbNjb2+PBgwfw9vauclcjEX0rV66EoaEhfH19YWdnx3YcQqqtf//+8PPzw4oVK7Bu3Tqoq6tjw4YNePbsGZ4/f17rcfX19REQEIBffvkF69evR8eOHeHm5oa0tLRqFZTA51nKU6dOlZvxAz531YmMjMRvv/2GzZs3g8/nw8DAAKdOnYKBgYHgcWpqaggLC8PixYtx68oxcCXlodDHBhIKSnjvV74bj7yuMcQVlJBz6yJybl8GeKUQV1CGtLou5PW/33SCx2cwZbAGurTVxeXLl+Hm5obFixdDRUUFq1evxvr168s9vqwP97eORfpSv379EBwcjF9//RXLli1DixYtMGvWLGzevLnWY75+/Rrr1q0rd1vZn42MjKigrCEOwzB1b+hJyFdSU1NhbW2N9PR0+Pr6YtCgQWxHIo2AYRgMGzYMkpKS1OObNAmOjo6IjY2tdB2kqJp69DZuvHoPXh36eaefXgXweVAZuxYccUlIyspjqLYyTs4yqPrJ/+/AgQNwdnbGy5cvoaqqWussXyr7Mvvw4cPvnvVZE2WHwkdHR8PR0REXLlyo1aX7po6uSZF69/z5cwwbNgx5eXmIioqiYrIZKWvHeP36ddy+fZvtOITUyNfnGcbHx8PX17fJ9ap3H60HCbG6r2MvfvMMqXsn453XdkiIceA+umYFXFhYGJYsWVJvxWTZmBMmTKi3YhL43KlHRUUFjo6O9TZmU0QzlKRe3blzB7a2tmjXrh38/f2pc0ozxOPxoKOjA319/Vr17SWELWpqapgxYwa0tbWRlJSEgwcPori4GDExMZWeJSnK9njfw67o77dS/J7i9ATwP32+vCwuq4hd8x0wfqBGFc8STfn5+bh165bgz/r6+mjbti2LiYQTFZSk3gQEBGDs2LHo3bs3rl27BiUlJbYjEZYcPnwY8+bNw4sXL755MDQhwmbmzJkICwtDeno6pKWlMWTIELi7u6Nfv35sR6tXL1++hJGREWT6O4Lbs/JOQDWx0rI7FprQ73lzRwUlqRceHh6YPn06rK2tce7cOcjJybEdibDo06dP0NTUxJgxY3Dw4EG24xBC/t/r169hZGQEWVlZhIeHIyK1FC5eseDymRqtqRQX40BCjIMN9rpNdmaS1AytoSR1tmfPHkyePBmTJ0/G5cuXqZgkkJGRwZIlS3DixAlkZmayHYcQgs/H5JiYmEBKSgqhoaFQU1PDhIEaCF5mhKHaygA+F4rfxXxu3zhEWxnBy4yomCQCVFCSWmMYBqtXr8bSpUvh7OyM48ePQ1JSku1YREjMnz8f4uLi2L9/P9tRCGn2UlJSYGJiAnFxcYSFhaFDh//6eKsryeHkLAMELR2BqQaa0FSWw9dlJQeAprIcjNqL4c2ReZjbrQTqSjR5QP5Dl7xJrXC5XMybNw9Hjx7F77//jl9++YXtSEQI/fzzzzh16hSSk5MhLy/PdhxCmqU3b97AyMgIPB4PERER0NCoelaxoJiLxPcFKOHyISUhBi1lechLS4DP50NPTw9dunSBp6dnI6QnooIKSlJjRUVFmDBhAnx9fXHs2DE6/JV8U2JiIrp06YLdu3dj0aJFbMchpNlJS0uDkZERiouLERERAS0trTqPeezYMcyaNQvPnj1Djx496h6SNAlUUJIa+fjxI+zt7XHv3j1cunQJNjZ13yFImrZJkybh5s2biI+Ph4QENecipLGkp6fDxMQE+fn5CA8PR+fOnetl3OLiYmhpaWHUqFE4fPhwvYxJRB+toSTV9vbtW4wYMQJPnjxBSEgIFZOkWlauXInExERcunSJ7SiENBuZmZkwMzNDbm4uQkND662YBABpaWksWbIE//zzDzIyan+WJWlaaIaSVMuLFy9gZWUFLpeLgIAA9OzZk+1IRIRYWFjgw4cPuHv3LjicunfoIIR8W1ZWFkxNTfHu3TuEh4eje/fu9f4aHz58gLq6OpYtW4b//e9/9T4+ET00Q0mqdO/ePQwbNgyysrK4ceMGFZOkxlauXIl///0XYWFhbEchpEl7//49zM3NkZWVhbCwsAYpJgGgdevW+Omnn3DgwAEUFBQ0yGsQ0UIFJfmu4OBgmJiYoEuXLoiMjIS6ujrbkYgIsrCwQO/evbF9+3a2oxDSZGVnZ8Pc3BxpaWkICQlp8A0zS5cuRU5ODo4fP96gr0NEAxWU5JvOnTsHW1tbGBoaIjg4GMrKymxHIiKKw+Fg5cqV8Pf3x6NHj9iOQ0iT8+HDB1haWiIlJQUhISHQ1dVt8NfU0tKCk5MTdu7cCS6X2+CvR4QbFZSkUn/88QcmTpyI8ePHw9PTk84QJHU2btw4qKurY8eOHWxHIaRJycnJgZWVFV6/fo2QkBDo6ek12muvWLECr1+/xpUrVxrtNYlwok05pByGYbB+/Xps3LgRy5cvx7Zt2yAmRt87SP3YvXs3Vq5ciVevXtHyCULqQW5uLqysrPD8+XOEhoaib9++jZ7B1NQU+fn5uH37Nm26a8aoUiACPB4P8+bNw8aNG7Ft2zbs2LGDiklSr3766ScoKChg9+7dbEchROTl5eXBxsYGz549Q1BQECvFJPB5093du3cRGRnJyusT4UAzlAQA8OnTJ0yaNAleXl7466+/MGPGDLYjkSZqzZo12Lt3L1JSUtCqVSu24xAikgoKCmBjY4OHDx8iKCgIgwYNYi0LwzDQ09NDp06dcO3aNdZyEHbR9BNBTk4OrK2t4e/vj6tXr1IxSRrU4sWLUVJSgkOHDrEdhRCRVFhYCDs7O8TExMDf35/VYhL4vOluxYoV8Pb2xrNnz1jNQthDM5TNXFpaGmxsbJCUlAQfHx8MHTqU7UikGZg9eza8vb2RmJgIaWlptuMQIjIKCwsxatQo3L59G/7+/hg+fDjbkQB8bsfYqVMn2Nra4q+//mI7DmEBzVA2YwkJCRg2bBiysrIQGRlJxSRpNCtWrEBGRgZOnz7NdhRCRManT5/g6OiIW7duwdfXV2iKSeBzO8aff/4ZJ0+eRHp6OttxCAuooGym7t+/j2HDhkFKSgo3btxAr1692I5EmpHu3bvD3t4e27dvB5/PZzsOIUKvuLgYo0ePRlRUFHx8fDBixAi2I1Uwd+5cSElJYd++fWxHISyggrIZCg0NhbGxMbS0tBAVFQVNTU22I5FmaOXKlXj+/Dl8fHzYjkKIUCsuLsbYsWMRHh6Oa9euwdjYmO1IlWrVqhVmz56NgwcPIj8/n+04pJHRGspm5uLFi5g8eTJMTExw8eJFKCgosB2JNGPDhg2DuLg4rl+/znYUQoRSSUkJnJycEBAQAC8vL1haWrId6buSkpLQuXNn7Ny5E0uWLGE7DmlENEPZjBw8eBDjxo3D2LFj4eXlRcUkYd3KlSsRGRmJW7dusR2FEKFTWlqKCRMmwN/fH1euXBH6YhIANDU1MX78eOzatYvaMTYzVFA2AwzDwNXVFQsWLMCSJUtw6tQpSElJsR2LENjb26Nbt27Yvn0721EIESpcLheTJk2Ct7c3Ll26BBsbG7YjVduKFSuQmJiIS5cusR2FNCK65N3E8Xg8LF68GAcPHsTmzZvx66+/UmssIlSOHDmCuXPnIi4uDl27dmU7DiGs43K5mDp1Ki5evIiLFy/CwcGB7Ug1Zm5ujo8fP+Lu3bv0mdNM0AxlE1ZcXIwJEybg0KFD+Ouvv7Bq1Sr6xSZCZ+rUqWjbti1+//13tqMQwjoej4cZM2bgwoULOHfunEgWk8DnWcp///0XERERbEchjYRmKJuo3NxcODo64ubNmzh79qzIvimR5sHd3R0bNmxAUlISVFVV2Y5DCCt4PB5+/PFHnD59GmfOnIGTkxPbkWqNYRjo6+tDU1MT3t7ebMchjYBmKJugjIwMGBsb4/79+wgMDKRikgi9+fPnQ0JCAn/88QfbUQhhBZ/Px+zZs3Hq1CmcOnVKpItJ4L92jD4+Pnj69CnbcUgjoBnKJubVq1ewtLREYWEh/P39oa+vz3YkQqpl2bJl+Oeff5CcnAx5eXm24xDSaPh8PubOnYujR4/i5MmTmDx5MtuR6kVJSQk6deoEa2trHD16lO04pIHRDGUT8uDBAwwdOhRiYmK4ceMGFZNEpCxduhQ5OTk4duwY21EIaTQMw2DhwoU4evQojh8/3mSKSQCQkpLCzz//jFOnTiEtLY3tOKSBUUHZRISHh8PIyAgdO3ZEVFQUtLS02I5ESI2UnV+3c+dOOr+ONAsMw2Dx4sX4888/8ddff2H69OlsR6p3c+fOhbS0NLVjbAaooGwCLl++DGtrawwaNAhhYWFo27Yt25EIqZWVK1ciMTERFy9eZDsKIQ2KYRgsW7YM+/fvx+HDh/Hjjz+yHalBtGzZUtCOMS8vj+04pAFRQSniDh8+DCcnJzg6OsLb2xstWrRgOxIhtdanTx9YWFhg27ZtoOXdpKliGAYrVqzAnj17cPDgQcyePZvtSA1q6dKlyM/Pp+UsTRwVlCKKYRj873//w9y5c7FgwQJ4eHhAWlqa7ViE1NnKlSsRExOD0NBQtqMQUu8YhsGqVauwc+dO7Nu3D/PmzWM7UoNTV1endozNAO3yFkF8Ph9LlizB/v378b///Q9r1qyhA8tJk8EwDPr16wdVVVX4+/uzHYeQesMwDNauXQt3d3fs2rULS5cuZTtSo3nw4AH69u2LM2fOYMKECWzHIQ2ACkoRU1xcjOnTp+PChQs4ePAg5syZw3YkQuqdh4cHJk+ejAcPHqB3795sxyGkXri4uGDDhg3YsWMHli9fznacRmdhYYHs7Gzcu3ePJkGaICooRUheXh7GjBmDyMhIeHh4YMyYMWxHIqRBlJaWomvXrjA0NMTJkyfZjkNInW3YsAEuLi7YunUrnJ2d2Y7DisDAQFhZWSE0NBQmJiZsxyH1jApKEZGZmYmRI0fixYsX8PLygpGREduRCGlQe/bswfLly/Hq1StoaGiwHYeQWnN3d8eaNWuwadMmrF69mu04rGEYBn369EGHDh3g6+vLdhxSz2hTjgh4/fo1hg8fjpSUFERERFAxSZqFWbNmQVFREbt372Y7CiG1tm3bNqxZswZubm7NupgE/mvH6OfnhydPnrAdh9QzKiiF3KNHjzBs2DDw+XzcuHEDffr0YTsSIY1CQUEBCxYswJEjR/Dhwwe24xBSYzt37sSvv/6KdevWYf369WzHEQrjx49Hhw4d8Pvvv7MdhdQzKiiFWGRkJEaMGIF27dohOjoa2trabEcipFEtXrwYpaWl+PPPP9mOQkiNlC3Z+O233+Dm5sZ2HKEhJSWFpUuX4vTp03j79i3bcUg9ooJSSHl6esLS0hL9+/dHeHg4VFVV2Y5ESKNTVVXF9OnTsXfvXhQXF7Mdh5Bq2b9/P5YuXQpnZ2ds2rSJdjR/Zfbs2ZCRkaF2jE0MFZRC6OjRoxgzZgzs7Ozg6+sLRUVFtiMRwprly5cjIyMDp06dYjsKIVX6888/sWjRIvzyyy/YsmULFZOVaNmyJebOnUvtGJsYKiiFCMMw2Lx5M3766SfMnTsXZ8+epe43pNnr1q0bHBwcsH37dvD5fLbjEPJNf/31F+bPn48lS5Zgx44dVEx+x5IlS1BQUICjR4+yHYXUEyoohQSfz8eyZcuwevVquLq6Yv/+/RAXF2c7FiFCwdnZGXFxcfD29mY7CiGVOn78OObMmYOFCxdi9+7dVExWQV1dHRMnTsSuXbtQWlrKdhxSD+gcSiFQUlKCmTNn4syZMzhw4ECz6O1KSE0NHz4cABAVFcVyEkLK++effzBjxgzMnTsXBw4coGKymh4+fIg+ffrAw8MDEydOZDsOqSMqKFmWn5+PsWPHIjw8HKdPn8YPP/zAdiRChJKXlxccHBxw48YNDBkyhO04hAAATp8+jalTp2LWrFk4dOgQxMTowl9NWFlZISsrC//++y8V4iKOCkoWvXv3DiNHjsSzZ89w9epVmJqash2JEKHF5/Ohq6sLHR0dXL58me04hODcuXOYNGkSpk2bhqNHj1IxWQtBQUGwtLRESEgIfQaKOCooWZKUlAQrKyt8+PABfn5+6NevH9uRCBF6f/31F+bMmYPnz5+jW7dubMchzdjFixcxYcIETJo0CcePH6c177XEMAz69u0LNTU1+Pn5sR2H1AF9nWLBkydPMGzYMJSWliI6OpqKSUKqacqUKVBVVaUuG4RVV65cwcSJEzF+/HgqJuuorB2jv78/tWMUcVRQNrLo6GgYGhqiTZs2iI6ORpcuXdiORIjIkJGRwZIlS/D3338jIyOD7TikGfL09MS4ceMwduxY/P3331RM1oPx48ejY8eO2LFjB9tRSB1QQdmIvL29YW5ujt69eyMiIgLt2rVjOxIhImfevHmQkJCgLhuk0Xl7e8PJyQmOjo44deoUJCQk2I7UJEhKSmLp0qXw8PDAmzdv2I5DaokKykZy4sQJODo6wsbGBv7+/mjZsiXbkQgRSa1bt8acOXNw4MAB5Ofnsx2HNBP+/v4YO3Ys7Ozs4OHhQcVkPZs9ezZkZWWxd+9etqOQWqKCsoExDINt27Zh5syZmDVrFi5cuAAZGRm2YxEi0pYuXYrc3NxyXTYKirmIfZuDmOQPiH2bg4JiLosJSVMSFBQER0dHWFlZ4ezZs5CUlGQ7UpOjqKiIuXPn4s8//0Rubi7bcUgt0C7vBsTn87Fy5Urs3LkT69atg5ubG52zRUg9mTp1KiIfxmPa/44g4sU7JGcX4ss3Mw4ADSU5mHRvi8kGGuiq2oKtqESEhYSEwM7ODmZmZrh06RK1w21Ab968gZaWFrZu3YpffvmF7TikhqigbCClpaX48ccfcfr0aezduxeLFi1iOxIhTUZKdiEW/3MDDzKKIQYGfHz7i5q4GAc8PgPDLm3gPloP6kpyjZiUiLLw8HDY2trCyMgIV65coatLjWD69OkICwvDy5cvaSZYxFBB2QAKCgrg5OSE4OBgnDx5EuPHj2c7EiFNxtm7yXDxigWXz4DHr/7bl7gYBxJiHLjZ62LCQI0GTEiagsjISFhbW2PYsGHw9PSErKws25GahcePH0NfXx+nTp3C5MmT2Y5DaoAKynr2/v172NnZ4cmTJ7hy5QrMzc3ZjkRIk/FHWDx2BL6o8zgrLLthkUnXekhEmqLo6GhYWVnBwMAA165dg5wczWo3Jmtra2RkZOD+/fu0TEyE0KacepSSkgJDQ0O8fPkSYWFhVEwSkcDhcODq6lrl41xdXVl9cz97NxmuOw4gaYsduB9rfgZl+ulVSNpih6QtdnCePRnn7iY3QErh8ODBA3A4HMHPxYsX2Y4kMm7dugUbGxsMHDgQXl5eVEyyYOXKlXjw4AFCQkLYjkJqgArKevL06VMMHToUhYWFiIqKwoABA9iOREiD09LSAofDweLFiyvcFx4eXm/FTEp2IVy8Yus8joRyRyjbLYfioNFY7xWLlOxCAJ97Mk+ZMgVdu3YFh8OBsbFxnV8LAJ49ewZra2soKChASUkJU6dORVZWVp3GfPPmDcaNG4dWrVpBUVERDg4OePXqVbnHaGpq4uTJk1i9enWdXqu5uXPnDqysrNCnTx9cu3YN8vLybEdqlkxNTdGnTx866FzEUEFZD27evAlDQ0O0bt0aN27coB7DRKQUFRVh7dq1dRrjyJEjePv2bT0lqmj1lcfg1mC95LeIy7WCQi8TyGjqg8tnsPrKYwDAwYMH4enpCXV1dbRu3brOrwMAqampGDFiBBISEuDu7o4VK1bAx8cHFhYWKCkpqdWY+fn5MDExQUREBFavXg03NzfExMTAyMgI79+/FzyudevWmDJlCiwsLOrl79Ic/Pvvv7C0tESvXr3g4+MDBQUFtiM1WxwOBytXrkRAQAAePXrEdhxSTVRQ1pGvry/MzMygq6uL69evo3379mxHIqRKfD4fnz59AvC5nWFdDmnW1dUFj8fDli1b6iteOfEZeYhMeFejDTjVweMziEx4h4TMPJw8eRI5OTkIDQ2tt99hd3d3FBQUIDQ0FEuWLMHq1atx/vx5PHz4ECdOnKjVmAcOHEB8fDy8vb3h7OyMZcuWITAwEGlpadTfvA5iYmJgYWGBHj16wM/PDy1a0BFTbHNycoK6ujr9fy1CqKCsg5MnT8Le3h6WlpYICAhAq1at2I5Empnw8HAMGDAAMjIy6Ny5Mw4dOlTpWkcOh4NFixbh9OnT0NXVhbS0NPz9/QX3fb2GMioqCgMHDiw37rdoaWlh2rRp1Z6ljImJgY2NDRQVFaGgoAAzMzPcunWrwuNiY2NhamqKnhoqSN0/HR+jzwIMv9Ixi17eQ/opZyT/PhbJO52QecEVJVlJVWYRF+Pg1K1kqKurQ0ysft8OL126BDs7O2ho/Lej3NzcHN26dcP58+drNebFixcxcOBADBw4UHBbjx49YGZmVusxm7uHDx/C3NwcXbp0QUBAABQVFdmORPC5HeOyZcvg4eGB1NRUtuOQamj2BWVtu2v8/vvvmDZtGqZPn46LFy/SkRKk0cXExMDa2hrv37+Hm5sbZs2ahQ0bNuDq1auVPj40NBTLli3D+PHjsWfPHmhpaVX6uMePH8PS0hKZmZlwdXXFzJkz4eLigitXrnwzy5o1a8DlcqucpYyNjYWhoSEePnwIZ2dnrFu3Dq9fv4axsTFu374teFx6ejpMTEzw4MEDdDCagBYDHFDwJBS597wqjJn/JBSZF9zAkZJFK+MZaDl0PErepSDjlHOVm3d4fAZhLzK/+5jaePPmDTIzMytdSz1o0CDExMTUeEw+n49Hjx59c8yXL18iLy+vVnmbqydPnsDc3BxaWloICAiglrhC5qeffoK8vDy1YxQRzbIZaXxGHk7fTkZYXGaNu2swDINff/0V27dvx2+//YZNmzbRsQaEFS4uLhAXF0d0dLTgMu24ceOgo6NT6ePj4uLw+PFj9OzZ87vjrl+/HgzDIDIyUjC7NnbsWOjp6X3zOdra2pg6dSqOHDmC3377DWpqapU+bu3atSgtLUVUVBS0tbUBANOmTUP37t3h7OyMiIgIAMDWrVuRlZWFsMhozPT5gJYAFPTM8ObQnHLj8UuK8CHoEBR6W0LZ5r+NQQp6ZnhzeB5ybp4vd3tlkt8XoqCYC3np+ns7TEtLA4BK/x3U1NSQnZ2N4uLiGnVdKXvOt8YEgLdv36J79+61TN28PH36FKampujYsSOCgoLqbe0sqT8tWrTAvHnzcPDgQaxdu5Zmj4Vcs5qhTMkuxNSjt2Gx+zpO3k5C0lfFJAAwAJKyC3HydhIsdl/H1KO3BTtBS0tLMXPmTGzfvh27d++Gu7s7FZOEFTweD8HBwXB0dCy35q9Lly6wsbGp9DlGRkZVFpM8Hg8BAQFwdHQsd6lWR0cHVlZW333u2rVrvztLyePxEBgYCEdHR0ExCXwuhiZNmoSoqChBD19fX18MHjwYKtq6gt9RcbmWkNc1Ljfmp9cx4BcXQL6nEXiFOYIfcMQg3b4bPiVXvaCfAZD4vqDKx9VEUVERAFRaMJZ1Wyl7DJtjNlfPnz+Hqakp1NTUEBwcDCUlJbYjkW9YsmQJioqKcOTIEbajkCo0mxnKL7trAKhygX/Z/TdevYf5rgisse6K85uXIiAgAKdPn8akSZMaPDMh35KZmYmioiJ06dKlwn2V3QYAnTp1qnLcrKwsFBUVoWvXiod+d+/eHb6+vt98btks5eHDh7Fq1apKxy4sLKx0Bk1HRwd8Ph8pKSnQ1dVFUlISDAwMUMItv2ZSUqlDuT+Xfvi8ZjPjTOXH43Ckq3eG4NevU1dlS2CKi4sr3Fe2Gaqmy2QaYszm6MWLFzA1NUWbNm0QHBwMZWVltiOR72jfvj0mT56M3bt3Y8mSJdSOUYg1i4KyLt01eP/f3m29dxwK8lvD29u7ypkaQoRRYxQba9aswcmTJ7F161Y4OjrWeTwpiSouovx/oy9lu+UQV6h4yZLDqd5FmCpfp4bKLkGXXfr+UlpaGpSUlGp0uRuA4DnfGhMAnTJRhYSEBJiYmKBVq1YICQmBiooK25FINSxfvhwnTpwQnBdLhFOt30WbY3eNgtQ4fFSqfH1aU0DdNURH27ZtISMjg4SEhAr3VXZbdamoqEBWVhbx8fEV7ouLi6vy+Z07d8aUKVNw6NChCoWPiooK5OTkKh3n+fPnEBMTg7q6OoDPB3PHx8dDS1keX757lGa/Kfc8idafCzdx+ZaQ1epT4UdGU7/KzACgqVS/3VA6dOgAFRUV3Lt3r8J9d+7cQZ8+fWo8ppiYGPT09Cod8/bt29DW1qbjbr7j1atXMDExQYsWLRAaGgpVVVW2I5Fq6tWrF2xsbLB9+3ZQt2jhxcoayqbSXQMAvLy80K9fP8jIyEBDQwMuLi7gcqu3U7wygYGBmDVrFnr16gVxcfFv7sStKequ0bSIi4vD3NwcV69eLXdUT0JCAvz8/Oo0rpWVFa5evYrk5P9aEz579gwBAQHVGqNs4822bdsqjG1paQlPT08kJiYKbs/IyICHhweGDx8uWHRva2uLW7duIfbhfWj8f7HHK8xBQWx4uTFlO/UDR1oOOTfOg+FV/L3jFeZUmbc0+y30e3bH0qVLERoaWm8fWGPHjoW3tzdSUlIEt4WEhODFixdwcnKq1Zg//PAD7t69W66ojIuLQ2hoaK3HbA4SExNhYmICWVlZhIaGol27dmxHIjW0YsUKPHr0CMHBwWxHId9Q64KSumsAfn5+cHR0RKtWrbBv3z44Ojpi48aNlRbK1eXh4QEPDw+0bNmy3i5fUXeNpsnV1RVcLhfDhg3Dtm3bsHnzZhgZGaFXr151GtfNzQ0AYGhoiK1bt2LTpk0wMTGBrq5utZ5fNkv54MGDCvdt3LgREhISGD58ONzd3bFt2zYMHToUxcXF5QpQZ2dnKCsrw9raGpyYi8i7cxnpJ1dCQrH8JUoxaTkoWy5AcepTpJ34GTk3ziHvgT8+XD+Jt8eWICfK47tZxcU4sNTrAH19fRw7dgxmZmZ49uwZ7t27h3HjxmHt2rW4fv16uedUtzXj6tWrIScnBxMTE+zbtw+bN2+Gk5MT9PT0MHPmzHKP1dLSqtaXxwULFqBz584YOXKkYHOghYUFVFVVsXz58iqf3xwlJyfDxMQEkpKSCAsLo2UBIsrExAT9+vXD9u3b2Y5CvqFGBSV11yjfXWPFihXQ19dHYGAgZs+ejb179+K3337DoUOH8Pz581qN7+7ujtzcXERHR6N37971kpm6azRN/fv3h5+fH1q3bo1169bh6NGj2LBhA8zMzAS7fmtDX18fAQEBUFFRwfr163Hs2DG4ublh9OjR1R5j7dq1EBcXr3C7rq4uIiMj0atXL2zevBlubm7Q1NREWFgYDAwMBI9TU1NDWFgY9PX1cevKMeTc9YR8L1MoDrCvMKa8rjFUJ2yEuIIycm5fxofgwyh8eh1SqtqQ1//+lyMen8GacYbo06eP4AxHhmFQUFCACxcuYNOmTZgxYwb27duHxMRE5OfnC/JVRV1dHREREejcuTNWrVqFbdu2wdbWFkFBQRXWTxYUFFRrzBYtWiA8PBwjRozAxo0bsW7dOvTu3RsRERG0HrASqampMDExAYfDQVhYGDp06FD1k4hQ4nA4WLFiBYKCgvDw4UO245BKcJhqXt/R1dXFixcvcOHCBTg6OoLD4cDFxaXcOsqoqCgsW7YMjx8/RocOHeDs7Iy0tDS4ubmVu4ykpaWFXr16QVVVFR4eHnj58qXgW2N4eDhMTExw4cIF/PDDD4LnxMTEYPXq1YiOjgafz4eBgQE2bdqEwYMHl8sZGxuLxYsXIzL6BhhpBSj0sYGEghLe++1Fh3lHIdHqv3UzRS/vIefmeZRkvAQ4YpBR10Ur45mQUtEUPCb99Ofdqu0m/1f4iotxYK3GxYHFDti/fz8WLFgguO/t27fo0KED/ve//9V5BtfOzg5Pnjwpd3mwNgYNGgTg89qtL1lZWeHly5cV1tx9678BEQ2Ojo6IjY2tdB2kqJp69DZuvHpfpy+I6adXAXweVMauBUdcEpKy8hiqrYyTswwqfXxycjKuXbsGLy8vhIWFobS0FFpaWkhMTMSZM2cwbty4eumu8/TpU+jq6sLb2xsjR46s83jA5yOaPnz4gOjoaDg6OjbL3+W3b9/CyMgIpaWliIiIgKamZtVPIkKNy+Wic+fOGDFiBE6ePMl2HPKVar8bUneN//D4DEJufH7dr7tWtG/fHh07dqxVJ4yGQN01mravzx2Mj4+Hr69vtS7JihL30XqQEKv75r7iN8+Quncy3nlth4QYB+6jv31Yu4aGBhYuXIiAgAC8e/cO58+fh6ysLCQlJTFx4kSoq6tj3rx58PX1FVy5qY2wsDAMGTKk3opJ4PP7sYqKSr3stBdFaWlpMDExQXFxMcLCwqiYbCIkJCSwbNkynD17ttzaZCIcqn3Nev369VXe35y6a2SmpwP4dieMhlwbWhPUXaNp09bWxowZM6CtrY2kpCQcPHgQUlJScHZ2ZjtavVJXksOk7pI4HlvxDMbqam32E/ifPl+yFpdVxAZ7XahXc3e3oqIinJyc4OTkhNLSUkRHR8PLywuenp44dOgQ5OXlYWlpCQcHB4wcORJt2rSpdq6FCxdi4cKFtfo7fUuXLl0QFBQk+LO+fvV2uzcFGRkZMDU1RUFBASIiIqp1/ioRHbNmzYKbmxv27NmDHTt2sB2HfKFednk3x+4afO7nD7Zvda0Qlo4V1F2jabO2tsaZM2ewePFi7Nu3DwMHDsT169crPZhclEVGRmL7PEcov4mu9RjS7boIjhNaM9UG4wdqVP2kSkhKSsLY2Bg7d+5EQkICYmNjsXbtWqSnp2PmzJlQVVWFoaEhtm/fXq2jlhqCgoICzM3NBT9t27ZlJUdjy8zMhKmpKXJychAWFobOnTuzHYnUs7J2jIcPH0ZOTtWnOJDGUy8FZVXdNb7ny+4alR3YW93uGgCQlJSErl271qi7RureyeV+Pr2OqdZRIxyJzwXat7pWCEvHCuqu0bQdP34ciYmJ+PTpE3JycuDv749+/fqxHateRUdHw9bWFgYGBoj8cy22jNGDtIQYxGt4CVxcjANpCTFsHaOHhSaVdxOqKQ6Hg549e2LVqlW4ceMG3r59i8OHD0NJSQkuLi7o0aOH4EpKVFQUeDxevbwuqejdu3cwNzdHdnY2wsLCmtyXKvKfJUuW4NOnTzh8+DDbUcgXhKKXd9layq1bt9bLeDXprtF2wsaKP2Oq3kxT1pXjW10rhOVoCuquQUTZrVu3YGNjgwEDBsDLywtycnKYMFADwcuMMFT7c8u8qgrLsvuHaisjeJlRrWcmq6Ndu3aYNWsWPD098e7dO3h5eWHEiBH4559/YGhoiHbt2mHGjBm4fPmyYMc4qbv379/D3NwcGRkZCA0NpSU8TZyamhqmTJmCPXv2oKSkhO045P/VS0HZHLtrSLf9fPn9664Vb9++RWpqaq06YTQE6q5BRNWdO3dgZWWFPn364Nq1a5CXlxfcp64kh5OzDBC0dASmGmhCU1kOX5eVHACaynKYaqCJ4GUjcHKWQbXXTNYHOTk5jBo1SnDe7s2bNzF79mzcu3cPY8eORZs2bTBy5EgcOnRIaNZci6IPHz7AwsICb968QWhoKHR0mm43M/Kf5cuX482bNzh79izbUcj/q5eCsjl212ij2g7a2to4fPhwuctYBw8eBIfDEaojOqi7BhE19+7dg6WlJfT09ODj4wMFBYVKH9dVtQVc7XURscIET1yt4LN4OK7MHwqfxcPxxNUKEStM4Gqviy5t2f3SJCYmhsGDB8Pd3R1PnjxBQkICtmzZgsLCQixcuBAdOnTAwIED8b///Q+PHj2i9nLV9PHjR1haWiI5ORkhISHVPnyfiD5dXV3Y2tpix44d9PsiJKp9DmWFJ351DuWjR49gYGCAtm3bYsGCBeByudi3bx9UVVUrvEGWnUPp7e1dbswZM2bg77//BoBy56bFxsbCwMAArVq1woIFCyAhIYFDhw7hzZs3iIiIEByInJaWBj09PfD5fOhbT8TjjE/IjfEHR0IKpVmJ5c6hLIgNxzvvnZBsow55nREQk2sJbm4WihLuQqajDpQs5wOo/BxKMHwUPvRHlv8BAJ+PFxk/fjw+ffqE/fv3Y9asWeXWdiQmJqJTp06YPn06Tpw48d1/10ePHsHL6/MxR6dOnUJGRoagA0bv3r0xatSocv+OZeN/T15eHvr27Yu8vM+HsUtKSmLnzp3g8Xh48OBBhQOR6RxKwqb79+/DzMwMOjo68Pf3F3xhbKqys7Ph5+cHLy8v+Pn5IS8vD5qamrC3t4e9vT1GjBgBKSkptmMKnZycHFhaWiI+Ph6hoaFCc1WINJ6yzyp/f/8qNwCTRsDUEgDGxcWl3G0RERFM//79GSkpKUZbW5v5888/GRcXF+brl9HU1GRGjhxZYcz4+HhGXFycAcBcuHCh3H33799nrKysGAUFBUZOTo4xMTFhbty4UWGMR48eMUZGRoy0jAwj3kKZaWk4hVG2WcIAYDrMO8porvIW/KhOdGdkOvVjONLyDEdCipFopcbI65kz7WbsFjxGWr0XI63eq9zzNFd5M48SMxkvLy/GzMyMkZCQYAAwYmJijL6+PnP+/HkmPz9fkOnx48cMAGbVqlVV/rseP36cAVDpz/Tp08s9tk2bNszgwYOrHJNhGCYlJYX54YcfGEVFRUZBQYGxs7Nj4uPjK31sWFhYpf8NCGloMTExTOvWrZlBgwYxHz9+ZDtOoysuLmYCAwOZhQsXMurq6gwARlFRkRk/fjzj4eHBfPjwge2IQiE3N5cZMmQI06pVK+bff/9lOw5hCZ/PZ/r378+Ym5uzHYUwDFPrGUpR0FjdNfh8Pu7cuQNPT094eXnh6dOnkJaWhrm5ORwcHPDu3Tts2rQJL1++hKqq6nderfqouwZpah49egRTU1N06tQJQUFBaNWqFduRWMUwDB4+fAgvLy94eXnh33//hYSEBEaMGCGYvWyOZyzm5+fDxsYGjx8/RnBwcKVNG0jzce7cOUyYMAH3799H37592Y7TrDXpgjIluxDmuyJQ/NUxQjWRfnoVilOeAABkOw+E+kQ3BC8z+u7i/vj4eFy7dg2enp6IiooCn8+HmpoaFi1aBHt7e+jq6oLDqVvXj/379+P06dO4ceNGncb50oMHD8r9QlJBSRrLkydPYGJiAg0NDQQHB6N169ZsRxI6qampglaQoaGhKCkpgZ6enqC4HDBgQL20ghRmBQUFsLW1RUxMDIKCgsr1fyfNE5fLRdeuXTFs2DCcOnWK7TjNWpMuKAHg7N1krLr8uNbPL05PKNddY9d8hxodO/L+/Xv4+PjAy8sL/v7+KCgogLa2Nuzt7eHg4IDhw4dDQqLaDYsaVH5+Pm7duiX4s76+frM5EJmw5+nTpzA2NkaHDh0QEhICJSUltiMJvby8PAQGBsLLywve3t7Izs5Gu3btMGrUKNjb28PMzKzJnS9bWFgIOzs73L17FwEBARg6dCjbkYiQ2Lt3L3755Re8evWqXHMV0riafEEJAH+ExWNH4Is6j7PSsnudDkT+9OkTwsLCBJew3r59i9atW8PW1hYODg6wsrJq8hsQCPnS8+fPYWxsDFVVVYSGhkJZWZntSCKHy+Xixo0bglaQCQkJkJOTg6WlJezt7TFy5EiR/2JYVFQEe3t73Lx5E/7+/hg+fDjbkYgQyc/Ph4aGBmbOnInff/+d7TjNVrMoKIHPM5UuXrHg8pkarakUF+NAQoyDDfa69XogMp/Px/379wXrLh89egQpKSmYmJgILmF17Nix3l6PEGHz4sULGBsbQ1lZGaGhoRVOGyA1xzAM4uLiBF9ay5bEDBkyRPC+0qNHjzovuWlMnz59gqOjIyIjI+Hr6wsjIyO2IxEhtGbNGuzduxcpKSnNfv01W5pNQQl8XlO5+spjRCa8g7gY57uFJcPngSMmDsMubeA+Wq/BD0R+/fq1YH1UREQEuFwu+vXrBwcHB9jb26N3794i9SFAyPckJCTAyMgIrVq1QlhYmMjPoAmrzMxMwZKbwMBAFBYWomvXroLicujQoUKz5KYyxcXFGDNmDMLCwuDj4wMTExO2IxEhlZaWBi0tLfzvf/+Ds7Mz23GapWZVUJaJz8jD6dvJCHuRieT3hfjyH4ADQENZDoUJd5H7rw+e3Q5r9IXuHz58gL+/Pzw9PeHn54fc3FxoaGgIPgSMjIzoXDoisl6+fAljY2MoKCggPDy83k4+IN9XVFSE0NBQeHp64tq1a0hPT4eSkhJGjhwJe3t7WFlZCVXXrJKSEowdOxbBwcG4du0azM3N2Y5EhNxPP/0EPz8/vH79mj4jWdAsC8ovFRRzkfi+ACVcPqQkxKClLA95aQncuHEDw4YNw7Vr12BnZ8davpKSEkRERAguYSUnJ0NRURE2NjZwcHCAjY0NTe8TkfH69WsYGRlBVlYW4eHhUFNTYztSs8Tn83Hv3j3B+8rjx48hJSUFU1NT2NvbY9SoUawuuSktLYWTk5PgwHc6tJpUx7Nnz9CzZ0+cOHEC06dPZztOs9PsC8rvGTp0KKSkpBAeHs52FADlz6Xz9PTE/fv3ISEhASMjI8HsZVn3HEKETWJiIoyNjSEpKYnw8HB06NCB7Ujk/5UtufH09ERERAR4PB5rS25KS0sxceJEXLt2DVeuXIGtrW2jvC5pGkaNGoXExEQ8evSIlok1Mioov+Py5csYO3Ys7ty5g4EDB7Idp4KUlJRy59KVlpZCX19fcCRRv379mvy5dEQ0JCcnw9jYGBwOBxEREbThTIiVLbnx8vKCr68vcnNzoa6uLvjSamxs3GCXE7lcLiZNmoSrV6/i0qVL5VrNElIdERERMDY2hp+fH6ytrdmO06xQQfkdPB4PPXr0QL9+/XDu3Dm243xXbm4uAgIC4OXlBR8fH3z48AHt27cXfAiYmJhARkaG7ZikGUpNTYWRkREYhkF4eDidEydCSkpKEBkZKTiNIikpCS1atIC1tbVgyU19nRvK5XIxdepUXLx4ERcuXICjo2O9jEuaF4ZhYGBggBYtWiAkJITtOM0KFZRVOHjwIBYtWoSEhASRaXNWWlqK6OhoeHp6wtPTE69fv4aCggKsrKwE59LReX+kMbx58wbGxsYoLS1FREQENDU12Y5EaolhGDx+/Fiw7vLu3bsQFxeHoaGh4Itr586dazU2j8fDjBkzcObMGZw7dw5jx46t5/SkOTl//jzGjx+Pf//9F/369WM7TrNBBWUVCgsLoampiUmTJmHPnj1sx6kxhmEQGxsrWHd5584diImJYfjw4YL1UV261P6wdkK+JS0tDcbGxigqKkJERITIfCEj1fPmzRt4e3vDy8sLISEhKC4uRs+ePQXvK4MGDarWkhs+n48ff/wRJ0+exJkzZzBu3LhGSE+aMi6Xi27dumHw4MHw8PBgO06zQQVlNbi6umL79u1ISUkR+bZwaWlp8Pb2hqenJ4KDg1FcXAwdHR3Bh4CBgQGtuyR1lp6eDhMTE+Tn5yM8PLzWM1dENOTn5yMoKEjQCvLdu3dQVVWFnZ0d7O3tYW5uDjm5imf58vl8zJkzB8ePH8epU6cwceJEFtKTpmjfvn1YtmwZXr58SVdGGgkVlNWQmZkJTU1NrFu3DqtXr2Y7Tr0pKCgo1w/4yw8BBwcHmJmZVfohQMj3ZGZmwsTEBB8/fkRERATNgDczPB4PN2/eFFwaj4uLg6ysLCwsLGBvbw87OzuoqqqCz+dj/vz5OHLkCP755x9MmTKF7eikCSkoKIC6ujqmT5+OXbt2sR2nWaCCsprmzZuHq1evIikpCdLS0mzHqXdffgh4enrixYsXkJWVFfQDtrOzo24mpEpZWVkwNTXFu3fvEBERgW7durEdibAsLi5OcCTRjRs3wDAMBg0aBAC4c+cOjh07hhkzZrAbkjRJa9euxe7du5GSkoLWrVuzHafJo4Kyml68eIEePXrgyJEjmDVrFttxGlxcXJxgZ+fX/YAdHBzQvXt3OuOLlPPu3TuYmZkhIyMD4eHh6NGjB9uRiJDJysqCj48PNm7ciJcvXwIAOnfuLNjUM3z4cKFuBUlES0ZGBjQ0NODm5oZVq1axHafJo4KyBkaPHo24uDg8efKkWa0z/LIfcEBAAIqKitC1a1fBusuhQ4dCXFyc7ZiERdnZ2TAzM8Pbt28RFhaGnj17sh2JCCGGYfDLL79g9+7d+OOPP6CtrS1oBfn27Vu0bt26XCtIRUVFtiMTETd79mz4+Pjg9evXTfLqojChgrIGoqOjMXz4cHh7e2PkyJFsx2FFUVERQkJCBB8CGRkZUFZWFiy+t7S0hIKCAtsxSSP68OEDzM3NkZycjLCwMPTq1YvtSEQIMQwDZ2dn7NixAwcOHMD8+fMF9/H5fNy/f1+w7vLhw4eQlJSEiYmJoBUknV9KauP58+fQ0dHBsWPHMHPmTLbjNGlUUNaQsLVjZBOfz8edO3cE6y6fPn0KaWlpmJmZwcHBAaNGjaJezU3cx48fYWFhgdevXyM0NBT6+vpsRyJCiGEYrF69Glu2bMHevXuxePHi7z4+KSlJsO4yPDwcXC4Xffr0EVwV6du3Ly25IdVmb2+Ply9f4smTJ/T/TQOigrKGhL0dI5sSEhIEHwKRkZHg8/kYNGiQYN2lrq4u/TI3ITk5ObC0tERCQgJCQkLQp08ftiMRIcQwDNatW4dNmzZh586dWLZsWY2en5OTU64V5MePH9GhQ4dyXcDoUib5nsjISIwYMQK+vr6wsbFhO06TRQVlDfF4PHTv3h0DBgzA2bNn2Y4jtN6/fw9fX194eXnB398f+fn56NSpk6C4HD58OCQlJdmOSWopNzcXVlZWeP78OUJCQqgbBfkmNzc3wVm+K1asqNNYpaWliIyMFFwVSUxMhIKCAqytrWFvbw9bW1vqAkYqYBgGgwcPhry8PEJDQ9mO02RRQVkLBw4cwOLFi0WqHSObiouLERYWJlgf9ebNG7Ru3Rq2trawt7eHtbU1Lb4XIXl5ebC2tkZsbCyCg4MxYMAAtiMRIbVx40asW7cOmzdvrvddtl92AfPy8sLt27cFXcDKZi+7du1ar69JRNfFixfh5OSEe/fuoX///mzHaZKooKyFwsJCaGhoYPLkySLZjpFNDMPg/v37giOJvl58b29vD3V1dbZjkm/Iz8+Hra0tHj58iKCgIMF5goR8bcuWLfjtt9+wceNGrFmzpsFfr6wLmJeXF4KDg/Hp0yfo6OgI3lcMDAzoNIpmjMfjoVu3bhg0aBDOnDnDdpwmiQrKWnJxccHvv/+O5ORkkW/HyKbExERcu3YNXl5egsX3ffv2FSy+79OnD627FBIFBQUYOXIk7t+/j8DAQAwePJjtSERIbd++Hc7OznB1dYWLi0ujv35BQQGCg4Ph6ekJb29vZGVlQUVFRdAFzNzcHPLy8o2ei7Br//79+Pnnn5GQkAAtLS224zQ5VFDWUlNtx8imjx8/wt/fH56envD19UVubi7U1dUF6y6NjIwgJSXFdsxmqbCwEHZ2drh79y4CAgIwdOhQtiMRIbVr1y788ssvWLt2LTZs2MD6F0Iej4fbt28LLo0/e/YMMjIyMDc3F3QBo9MomoeCggJoaGhg6tSp2L17N9txmhwqKOugqbdjZFNJSQmuX78uWHyfnJwMRUVFWFtbw8HBATY2NtRKq5EUFRXB3t4eN2/ehJ+fHwwNDdmORITUvn37sGTJEqxatQru7u6sF5OViY+PF5xGERUVJTiNouyqCJ1G0bStX78eO3fupHaMDYAKyjqIi4uDjo4O/vrrL/z4449sx2myGIbBo0ePBMXlv//+CwkJCYwYMUKwPoo2RzWMT58+wcHBAVFRUfD19YWRkRHbkYiQOnDgABYuXIiVK1di69atIlGUfe80Cnt7exgaGtJpFE1MRkYGNDU14eLigt9++43tOE0KFZR15OjoiBcvXjS7doxsSk1NFay7DA0NRUlJCfT09AQzDP3796f/FvWguLgYo0ePRnh4OHx8fGBiYsJ2JCKkDh8+jLlz52LZsmX4/fffRaKY/FpxcTHCw8MFGwbfvHmDli1bwtbWFg4ODrC2tkbLli3Zjknqwdy5c+Hl5YXExES6uliPqKCsI2rHyK68vDwEBATA09MTPj4++PDhA9q3b49Ro0bB3t4epqamkJGRYTumyCkuLsYPP/yA4OBgXLt2Debm5mxHIkLq6NGj+Omnn7B48WLs2bNHJIvJrzEMg5iYGMG6y5iYGEhISMDY2Fgwe6mpqcl2TFJLdHWxYVBBWUcMw2Do0KGQkZFBWFgY23GaNS6Xi+joaHh6esLT0xOvXr2CvLw8rKys4ODgAFtbW7Rp04btmEKvpKQETk5OCAgIgJeXFywtLdmORITUiRMn8OOPP2LevHnYv39/kygmK5OcnCy4KhIWFobS0lL07t1bUFz269eProqIGLq6WP+ooKwHly5dwg8//IC7d+/SIc9CgmEYPH36VLDusuzQ42HDhgkujdOhxxWVlpZi/Pjx8PHxwdWrV6lNGfmmU6dOYdq0aZg9ezYOHjzYbD6Uc3NzBV+26KqI6IqKioKhoSFdXaxHVFDWA2rHKPzS09Ph7e0NT0/PCoceOzg4YNCgQc3+0OPS0lJMmjQJnp6euHz5Muzs7NiORITUmTNnMGXKFMycOROHDx9uNsXk10pLSxEdHS344vrlVRF7e3uMHDmSrooIKbq6WP+ooKwnZe0YX758SQemCrmCggIEBQXBy8sL165dw7t379C2bVvBDIO5uTnk5OTYjtmouFwuJk+ejCtXruDixYuwt7dnOxIRUufPn8fEiRMxbdo0HD16tNkWk19jGAbPnj0TrLu8desWOBwOhg4dKvji2q1bN7Zjki/Q1cX6RQVlPSlrxzhlyhQ6MFWE8Hg83Lp1SzDDEBcXB1lZWVhYWAgOPVZVVWU7ZoPi8XiYOnUqLly4gPPnz2P06NFsRyJC6tKlSxg/fjwmTpyIEydONPtZ/e9JT0+Hj48PvLy8EBQUhKKiInTv3l2w7nLIkCH078cyurpYv6igrEdl7RjpwFTRFRcXJ5hhiI6OBgAMHjxYsO6yR48eTWrjAY/Hw4wZM3DmzBmcO3cOY8eOZTsSEVJXr16Fk5MTnJyccPLkSSqGaqCwsBAhISGCqyIZGRlo06YNRo4cCQcHB1hYWEBBQYHtmM1S2dXFhIQEOs+4jqigrEeZmZnQ0NCgA1ObiKysLPj4+MDT0xOBgYEoLCxE165dBTMMQ4cOhYSEBNsxa43H42HWrFk4deoUPDw8MG7cOLYjESF17do1jB07FqNHj8bp06dF+v97tvH5fNy5c0fwxTU2NhbS0tIwMzODvb09Ro0ahfbt27Mds9kou7o4efJk7Nmzh+04Io0KynpGB6Y2TUVFRQgNDYWnpyeuXbuG9PR0KCsrC2YYLC0tRWqGgc/n46effsLff/+NU6dOYeLEiWxHIkLK19cXo0ePxqhRo3DmzBnqHFPPXr58KWgFGRkZCR6PhwEDBgiuiujp6TWpqyLCyMXFBTt27EBKSgqUlJTYjiOyqKCsZ3RgatPH5/Nx9+5dwbpLUZth4PP5mDt3Lo4ePYp//vkHU6ZMYTsSEVIBAQFwcHCAjY0Nzp8/T8VkA8vOzoafnx+8vLzg5+eHvLw8aGpqCq6KjBgxAlJSUmzHbHIyMzOhqamJdevWYfXq1WzHEVlUUDYAOjC1eXn58qXg8lXZDMPAgQMFOzt79eolNDMMDMNgwYIFOHToEE6cOIFp06axHYkIqeDgYNjZ2cHS0hIXL16kQqaRlZSUIDw8XPDekpKSgpYtW8LGxgb29vawsbFBq1at2I7ZZMybNw9Xr15FYmIinSNaS1RQNoCyA1N9fHxga2vLdhzSiLKzs+Hr6yuYYcjPz0enTp0EMwyGhoaszfIwDINFixbhwIEDOHbsGGbOnMlKDiL8QkNDMXLkSJiamuLy5cu0fIdlDMPg4cOHguLy33//hYSEBEaMGCF4b6ENJXXz4sUL9OjRA0eOHMGsWbPYjiOSqKBsAAzDYMiQIZCTk0NoaCjbcQhLiouLER4eDk9PT3h5eeHNmzdo1aoVbG1tBTMMioqKjZKFYRgsXboUe/fuxZEjR/DTTz81yusS0RMREQFbW1sYGhri6tWrNFsjhFJTUwWtIENDQ1FSUgI9PT1BcTlgwAC6OlYLo0ePxvPnzxEbG0v/frVABWUDKTsw9d69e+jfvz/bcQjLGIbB/fv3BTMMDx48gKSkJIyNjeHg4IBRo0ZBQ0OjwV57+fLl2LVrF/7880/MnTu3QV6HiL7IyEjY2NhgyJAh8PLygqysLNuRSBXy8vIQGBgILy8veHt7Izs7G+3atcOoUaPg4OAAU1NT+u9YTTdu3MCwYcNw7do16hRWC1RQNhAej4du3bph0KBBOHPmDNtxiJBJSkoS7OwMDw8Hl8tF3759Besu+/TpUy/rLhmGgbOzM3bs2IH9+/djwYIF9ZCeNEU3btyAlZUVBg4cCG9v72bXLaop4HK5uHHjhmDDYEJCAuTk5GBpaSloBdm2bVu2Ywq1oUOHQlJSEhEREWxHETlUUDag/fv34+eff0ZCQgK1YyTflJOTI9jZ6evri5ycHHTs2FFQXBobG9dqQwTDMPjtt9+wdetW7N27F4sXL26A9KQpuH37NiwsLNC3b1/4+vpCXl6e7UikjhiGETRq8PT0xM2bNwEAQ4YMEby3dO/eXWg2DAqLK1euYMyYMbh9+zYGDRrEdhyRQgVlA6J2jKSmSktLcf36dcGHQFJSElq0aCHY2Wlra1utLkwMw2DdunXYtGkTdu3ahaVLlzZ8eCKS7t69C3Nzc+jr68PPz0+kzlMl1ZeZmSloBdkUGzXUFx6Phx49eqBv3744f/4823FEChWUDWz9+vXYuXMntWMkNcYwDB4/fizY1HPv3j2Ii4sLdnY6ODh8c2eni4sLNmzYgB07dmD58uWNnJyIivv378PMzAw6OjoICAhAixYt2I5EGkFljRqUlJTKNWpozv8v/Pnnn1i4cCHi4+Ohra3NdhyRQQVlA8vIyICmpiZcXV2xatUqtuMQEfbmzRvBzs6QkBCUlJSgV69ego4aZTs7N2zYABcXF2zduhXOzs5sxyZC6sGDBzA1NUW3bt0QGBjYaCcOEOHC5/Nx7949wYbBx48fQ0pKCqampoJGDR07dmQ7ZqMqKiqChoYGJkyYgH379rEdR2RQQdkIqB0jqW9lOzs9PT3h4+OD7OxsqKmpoWPHjrh79y7c3Nywfv16tmMSIfXo0SOYmpqiU6dOCAoKogOyicDr168FGwYjIiLA4/HQv39/waXx3r17N4t1l25ubti2bRuSk5OhrKzMdhyRQAVlI4iLi0OPHj3oMGnSILhcLqKjo7F27VpERUUBAOTl5WFpaQkHBweMHDkSbdq0YTklERZPnjyBiYkJNDQ0EBwcTEtxyDd9+PAB/v7+gg2Dubm5UFdXFxSXtd0wKAqysrKgoaGBNWvWYO3atWzHEQlUUDYSBwcHJCQk4MmTJ83i2x1pXDt27MDKlSuxfv16jB8/XrCp5/bt2+BwOBg2bJhg3WXXrl3ZjktY8uzZMxgbG6N9+/YICQmBkpIS25GIiCgpKRFsGPTy8qqwYdDGxqbJ/f+0YMECXLp0CUlJSXTAfzVQQdlIIiMjMWLECGrHSOrdrl278Msvv2DNmjX43//+V+4LS3p6Ory9veHl5YWgoCB8+vQJPXr0EBSXBgYGEBcXZzE9aSxxcXEwNjaGiooKQkNDadaa1FrZhsGy4vLu3bsQFxeHoaGhYPayc+fObMess/j4eHTv3h2HDh3C7Nmz2Y4j9KigbCTUjpE0hL179+Lnn3/GqlWr4O7u/t3Z74KCAgQHB8PLywvXrl1DVlYW2rZtCzs7O9jb28PCwoIOs26i4uPjYWRkBCUlJYSFhUFFRYXtSKQJefPmjeCLa0hICIqLi6GrqysoLgcNGiSyrQzHjh2L2NhYPH36VGT/Do2FCspGdPHiRTg5OVE7RlIv9u/fj0WLFmHlypXYunVrjZZS8Hg83L59W3Ak0fPnzyEjIwMLCws4ODjAzs4OqqqqDZieNJaXL1/CyMgILVq0QHh4OP13JQ0qPz8fQUFBglaQ7969g6qqKuzs7ODg4AAzMzOR+uJ68+ZNDB06FJ6enrC3t2c7jlCjgrIRlbVjNDAwgIeHB9txiAj7888/MX/+fCxbtgy///57ndflvnjxQnD5Kjo6GgzDwMDAQHAkkY6ODq39FUGvX7+GkZERZGVlER4eDjU1NbYjkWaEx+Ph5s2bgveWuLg4yMrKwsLCAvb29iLzxXX48OEQExPD9evX2Y4i1KigbGRl7RhfvnwJTU1NtuMQEXTkyBHMmTMHP//8M3bt2lXvhV5WVhZ8fX3h6emJgIAAFBYWokuXLoJ1l9RRQzQkJSXByMgIUlJSCA8PR/v27dmORJq5uLg4wZFEN27cEJkvrlevXsXo0aNx69YtGBgYsB1HaFFB2cgKCgqgoaGBadOmYdeuXWzHISLm2LFjmDVrFhYuXIh9+/Y1+Jvvp0+fEBISIphhSE9Ph7KyMkaOHAl7e/tm31FDWCUnJ8PY2BgcDgcRERHN7mBqIvzKvrh6eXkhICAABQUF6Ny5s2Dd5fDhw4Xmiyufz0ePHj3Qu3dvXLhwge04QosKShasW7cOu3btonaMpEb+/vtvzJw5E3PnzsWBAwca/Zv8lx01PD098eTJE0hJScHMzEzwIUCzYOxLTU2FsbExeDweIiIioKGhwXYkQr7r06dPCA0NFXxxTUtLQ+vWrQVfXK2srFjv5HTo0CEsWLAAL168aBI72BsCFZQsoHaMpKZOnTqFadOm4aeffsKff/4pFLsNX716JfgAuH79Ong8HgYMGCC4fKWnpyeUl6+asrdv38LY2BjFxcWIiIiAlpYW25EIqRE+n4/79+8L3lsePnwISUlJmJiYCFpBsvElqaioCJqamhg3bhz++OMPAEBBMReJ7wtQwuVDSkIMWsrykJcWjllVNlBByZI5c+bA29sbr1+/pnaM5Ls8PDwwdepUzJgxA0eOHBGKYvJr2dnZ8PPzg5eXF/z8/JCXlwctLS3BzOWIESMgKSnJdswmLT09HcbGxigsLER4eDi0tbXZjkRInSUlJQmKy/DwcHC5XPTp00fwxbVv376N9sV1w4YN2H74FBbs9MCtpDwkZxfiywKKA0BDSQ4m3dtisoEGuqo2r+VAVFCy5Pnz59DR0cHx48cxY8YMtuMQIXXu3DlMmjQJU6dOxbFjx4SymPxa2exY2ZFEqampaNmyJWxtbeHg4ABra2u0bNmS7ZhNSmZmJoyNjZGbm4vw8HB06dKF7UiE1LucnJxyrSA/fvyIjh07YtSoUXBwcICxsXGDTdCkZBdixfl/cTspFxwwYPDtIlZcjAMen4FhlzZwH60HdSXROSapLqigZJGDgwNevnyJx48f06VBUsHFixcxYcIETJo0CcePHxfJjjYMwyAmJkYwwxATEwMJCQkYGxvDwcEBo0aNotMO6igrKwsmJibIzs5GeHg4unXrxnYkQhpcaWkpIiMjBWu6ExMToaCgAGtra9jb28PW1hbKysr18lpn7ybDxSsWXD4DHr/6JZO4GAcSYhy42etiwsCmv5aZCkoWlbVj9PX1hY2NDdtxiBC5cuUKxo0bh3HjxuGff/4RyWKyMsnJyYJjQ8LDw1FaWoo+ffoIjiRqzMtXTcG7d+9gamqKzMxMhIeHo0ePHmxHIqTRMQyD2NhYQXF5584diImJYfjw4YL3ltrO2v8RFo8dgS/qnHGFZTcsMula53GEGRWULGIYBoMHD4aCggJCQkLYjkOEhKenJ3744QeMHTsWp06dEpqjM+obm5evmoLs7GyYmZnh7du3CAsLQ8+ePdmOREi1cTgcuLi4wNXV9buPc3V1hZubG2pSqqSlpQlaQQYHB+PTp0/Q0dERrOk2MDCo1pf0s3eTseryY+Q/CsZ7393oMO8oJFrV7CD29NOrUJzyBADQd5gp7kc13c964V+Q1YRxOBysWLECoaGhuH//PttxiBDw9vaGk5MTHB0dm3QxCQAtW7bE+PHjcfr0aWRmZiIkJARjx46Fn58frK2toaKignHjxuHUqVPIzs5mO65Q+fDhAywsLJCamoqQkBAqJkmzoqWlBQ6Hg8WLF1e4r+wQ/9atW+PatWt49+4drl69isGDB+PYsWMYNmwY2rdvj1mzZsHT0xMFBQWVvkZKdiFcvGLrJa+Eckco2y1HVidLpGQXCm4/d+4cpkyZgq5du4LD4cDY2LheXu/Zs2ewtraGgoIClJSUMHXqVGRlZdXL2N9DBSXLxowZg06dOmHHjh1sRyEs8/X1xdixYzFq1Ch4eHg06WLya5KSkjA1NcXu3bvx6tUrPHr0CM7OzkhMTMTUqVPRtm1bmJiYCO5vznJycmBlZYXExESEhISgV69ebEcipMaKioqwdu3aOo1x5MgRvH379ruPkZeXh4ODA44dO4a0tDRER0dj5syZuHnzJhwdHdGmTRuMGjUKR44cQVpamuB5q688BrcG6yW/R1yuFRR6mUBKQw+rrzwW3H7w4EF4enpCXV293s6kTk1NxYgRI5CQkAB3d3esWLECPj4+sLCwQElJSb28xrdQQckycXFx/PLLLzh//jySkpLYjkNYEhAQgDFjxsDGxgZnzpxp1kfscDgc6OnpYe3atbhz5w5SU1Oxf/9+yMrK4tdff0Xnzp3Rq1cvrFmzBrdv3wafz2c7cqPJzc2FtbU1EhISEBwcDH19fbYjEVJtfD4fnz59AgDIyMjU6Uuzrq4ueDwetmzZUu3niIuLY+jQodiyZQuePn2KFy9eYNOmTcjNzcW8efPQvn17DB48GCv/9zsiE97VaANOdfD4DCIT3iEhMw8AcPLkSeTk5CA0NLTemkK4u7ujoKAAoaGhWLJkCVavXo3z58/j4cOHOHHiRL28xrdQQSkEZs6ciZYtW2L37t1sRyEsCA4OhqOjIywsLHD+/HlISUmxHUmodOjQAXPnzoWvry/ev3+PS5cuoX///vjzzz8xePBgdOjQAXPmzIGPjw+KiorYjttg8vLyYGNjg2fPniEoKAh9+/ZlOxJppsLDwzFgwADIyMigc+fOOHToEFxdXStsqONwOFi0aBFOnz4NXV1dSEtLw9/fX3Df1+sno6KiMHDgwHLjfouWlhamTZtWrVlKAIiJiYGNjQ0UFRWhoKAAMzMzvH//Hr/88gsiIiKQmZmJf/75B4qKitizexeSd4xB6v7p+Bh9FmAq/9Ja9PIe0k85I/n3sUje6YTMC64oyfr+xJC4GAenbiUDANTV1ev9KLhLly7Bzs6u3OHv5ubm6NatG86fP1+vr/U1KiiFgLy8PBYsWIAjR47gw4cPbMchjSg0NBSjRo2CqakpLl68SMVkFRQUFDBmzBj8/fffyMjIQEREBCZPnoywsDDY2dmhTZs2GD16NE6cONEoa4YaS35+PmxtbfHkyRMEBQWhf//+bEcizVRMTAysra3x/v17uLm5YdasWdiwYQOuXr1a6eNDQ0OxbNkyjB8/Hnv27Plm96bHjx/D0tISmZmZcHV1xcyZM+Hi4oIrV658M8uaNWvA5XKrnKWMjY2FoaEhHj58CGdnZ6xbtw6vX7+GsbExbt++DQBQVlaGhYUFHjx4AKYoF4qDf0CLAQ4oeBKK3HteFcbMfxKKzAtu4EjJopXxDLQcOh4l71KQccoZ3I8Z38zC4zMIe5H53by19ebNG2RmZmLAgAEV7hs0aBBiYmIa5HXLNJ9FWkJu0aJF2LZtGw4fPoxff/2V7TikEYSHh8POzg5GRka4dOkS7WiuIQkJCYwYMQIjRozA9u3b8fz5c8GxIT/++CM4HA6GDh0qODZEWM5nrGm7toKCAtjZ2eHhw4cIDAzEwIEDGzEtIeW5uLhAXFwc0dHRgsu048aNg46OTqWPj4uLw+PHj6vcOLZ+/XowDIPIyEjB7NrYsWOhp6f3zedoa2tj6tSpOHLkCH777TeoqalV+ri1a9eitLQUUVFRgg5S06ZNQ/fu3eHs7IyIiAgAwNatW5GVlQW1ab9Dqn13AICCnhneHJpTbjx+SRE+BB2CQm9LKNv8tzFIQc8Mbw7PQ87N8+Vu/1ry+0IUFHPrvU1j2RrQyv4d1NTUkJ2djeLi4gb7rKEZSiGhqqqKadOmYc+ePQ2+cJawLzIyEiNHjsTw4cNx5coVyMjIsB1JpHE4HOjo6ODXX3/FjRs3kJaWhsOHD0NJSQkuLi7o3r07evTogV9//RXR0dHg8XiNmi8+Iw+uXrEw2h6GXq4BGLkvCqMP3sDIfVHo5RoAo+1hcPWKRXxGXrnnFRYWwt7eHv/++y/8/f0xePDgRs1NyJd4PJ5gic6Xa/66dOnyzbOUjYyMqiwmeTweAgIC4OjoWO5SrY6ODqysrL773LVr1353lpLH4yEwMBCOjo7l2pGqqalh0qRJiIqKQm5uLoDPGyN79xsoKCYBQFyuJeR1jcuN+el1DPjFBZDvaQReYY7gBxwxSLfvhk/Jj76bmQGQ+L7y3eV1Ubbkp7KCsewzpiGXBVFBKUSWL1+OtLQ0eHh4sB2FNKDo6GjY2Nhg8ODBuHr1KmRlZdmO1OSoqqoKjgV59+4dPD09MXz4cJw4cQLDhw+HmpoafvzxR1y9evWbx4bUh5TsQkw9ehsWu6/j5O0kJH3V+xf4/OGSlF2Ik7eTYLH7OqYevY2U7EIUFRXBwcEBt27dgq+vL4YOHdpgOQmpjszMTBQVFVV6SPi3Dg7v1KlTleNmZWWhqKgIXbtWPPi7e/fulTzjP2WzlIcPHy63S/vLsQsLCysdR0dHB3w+HykpKQA+9w3vqKVd4XGSSh3K/bn0w+c1mxlnViN17+RyP59ex3wuLqtQwq3/zYRlnyXFxcUV7ivbDNWQnzd0yVuI9OjRA6NGjcKOHTswffp06hjSBN28eRPW1tYYOHAgrl27Bjm55tHjlU1ycnKCA415PB7u3Lkj6DN+/PhxyMjIwNzcHA4ODrCzs0O7du3q5XW/bNcGoModo2X333j1Hua7ItD6VTAeRUfD19cXhoaG9ZKJkMbWGF+Y16xZg5MnT2Lr1q1wdHSs01hi1fnY/f9D1pXtlkNcoeJxPxxO1XN1UhL1P59Xdqm7ssI6LS0NSkpKDbq0imYohcyKFSsQGxuLgIAAtqOQenb79m1YWVmhb9++8Pb2pmKSBeLi4hgyZEi5Y0M2btyInJwczJ07F+3bt8eQIUOwefNmxMbG1qg7x5f+CIvHqsuPUczl1/joER6fQXEpD+kappi790q9HXZMSF21bdsWMjIySEhIqHBfZbdVl4qKCmRlZREfH1/hvri4uCqf37lzZ0yZMgWHDh2qUEypqKhATk6u0nGeP38OMTExqKurAwA0NTWRkZqIr2vK0uw35f4s0fpz4SYu3xKyWn0q/Mhofv84Lw4ALWX5Kv9eNdWhQweoqKjg3r17Fe67c+cO+vTpU++v+SUqKIWMoaEhBg0ahO3bt7MdhdSje/fuwcrKCvr6+vD19YW8fP2/mTR1lR0zUpnKji/5lq5du2L58uW4fv06MjIycOLECbRv3x6bNm1Cr1690LVrV8GxIlwut1pjnr2bDNcdB5C0xe67uz2/Jf30KiRtHYWkLXY4tGUdzt1NrvEYouLjx4/gcDiCH2rwINzExcVhbm6Oq1evljuqJyEhAX5+fnUa18rKClevXkVy8n//vz979qzakytlG2+2bdtWYWxLS0t4enoiMTFRcHtGRgY8PDwwfPhwKCoqAgBsbW1x5/ZttMr/7+gfXmEOCmLDy40p26kfONJyyLlxHgyv4vtCVZe8NZTl6n1DTpmxY8fC29tbcBkfAEJCQvDixQs4OTk1yGuWoYJSyFA7xqbn/v37sLCwQM+ePeHn5wcFBQW2IzU7VbVq43A4CA8Px7Rp03Dp0iW8e/cOPj4+MDc3x9mzZ2FsbCzYOHfx4kXk5eVV8ir1166trFWb4qDRWO8VW65dm5eXF/r16wcZGRloaGjAxcWl2sVuZQIDAzFr1iz06tUL4uLi3zzWpSbi4uKwbNkyDB06FDIyMuBwOOU+zMvIy8vj5MmT2LVrV51fkzQOV1dXcLlcDBs2DNu2bcPmzZthZGRU545Nbm5uAD5PqmzduhWbNm2CiYkJdHV1q/X8slnKBw8eVLhv48aNkJCQwPDhw+Hu7o5t27Zh6NChKC4uLleAOjs7Q1lZGc9P/Ibc6DPIuX0Z6SdXQkJRpdx4YtJyULZcgOLUp0g78TNybpxD3gN/fLh+Em+PLUFO1Lf3QYiLcWDSrS0A4Pr169i4cSM2btyIrKwsJCUlCf58/fr1cs+rbmvG1atXQ05ODiYmJti3bx82b94MJycn6OnpYebMmeUeq6WlVS+/72WooBRCo0ePRqdOnfD777+zHYXU0YMHDwSHyvr5+aFFixZsRxJZjdWqDfi8I9LW1hZ//vknUlNTcefOHcyfPx8PHjyAk5MT2rRpAxsbGxw8eBBv3vx3Oay+2rWVtWqT0dQHl88I2rX5+fnB0dERrVq1wr59++Do6IiNGzdWWihXl4eHBzw8PNCyZct669Zx8+ZN7N27F3l5ed88Tgb43HJzypQpdV73RhpP//794efnh9atW2PdunU4evQoNmzYADMzszqdVqGvr4+AgACoqKhg/fr1OHbsGNzc3DB69Ohqj7F27VqIi4tXuF1XVxeRkZHo1asXNm/eDDc3N2hqaiIsLAwGBgaCx6mpqSEsLAz6evr4ePMC8u55Qr6XKRQH2FcYU17XGKoTNkJcQRk5ty/jQ/BhFD69DilVbcjrW3wzI4/PYMrgzzvZQ0NDsW7dOqxbtw6ZmZlITEwU/Dk0NFTwnPz8fEG+qqirqyMiIgKdO3fGqlWrsG3bNtja2iIoKKjC+smCgoJqjVldHKa2i4RIg/rjjz+wdOlSvHz5EpqammzHIbXw6NEjmJqaolOnTggKCkKrVq3YjiRy+Hw+SkpKavRB5erqCjc3t3LrH7W0tKCgoIC4uDjMnz8fe/fuFdwXHh4OExMTXLhwAT/88EOV479+/RpeXl7w8vJCREQEeDwe+vfvjxGjxuPyp8/Ho+Q/CsZ7393oMO8oJFqp1uBv/PmSNwC0m1z+GJTgZSPgYDIYkpKSuHfvnqBt3dq1a+Hu7o6nT5+iR48eNXotAHj79i1UVFQgKSkJOzs7PHnypNLZxJrIzs6GpKQkWrRogR07dmDlypV4/fr1N2dDEhMT0alTJ2zfvh0rVqyo02sTdjg6OiI2NrbSdZCiaOrR27jx6n2d2y+mn14F8HlQGbsWEpJSGK6jjpOzDKp+4hd8fX0FZ9F+71zOmnj69Cl0dXXh7e2NkSNH1suYNEMppGbOnPm5BdSePWxHIbXw5MkTmJmZQVNTE4GBgc2+mGwqrdpu3bqFTp064eeff0ZISAiysrKwdetWpKSkYNeG35D6R/23agM+XybbdT4MT58+xZw5c8r1QF6wYAEYhsHFixerHKcy7du3r/fe8UpKSjQb34R9fZZhfHw8fH19m9QGMvfRepAQ4wh2dNdF8ZtnSN07GVme2+A+uuYFYVhYGCZMmFBvxWTZmEOGDKm3YhKgY4OEVlk7xj179mD9+vXNviARJU+fPoWpqSk6duyIoKAgtG5d8ViJ5qSsVZuamhrc3NzA4/GwYcMGqKioVPr40NBQnD9/HosWLUKbNm2qbNWmoqIiWNfl4uICVdVvzwiuWbMG//zzD7Zs2VJulvJrZa3aFBUV4ezsDElJSRw6dAjGxsaIiIgQXCYrLi7Gjh07wOVyoWE6Bbk8ceQ/8AdHomILzfwnoXjvvQsy2v3QyngGmNJi5MX4IeOUM9Rm7v3uTCaPzyDkxucWcV+3VWvfvj06duzY4G3VCCmjra2NGTNmQFtbG0lJSTh48CCkpKTg7OzMdrR6I8MrgOSjKyju6VCncVqb/QT+p8+XrJfb9Ye6Us1P92iITboLFy7EwoUL63VMKiiF2KJFi7B9+3YcOnSI2jGKiOfPn8PU1BRqamoIDg6GkpIS25FY1xxatYVFRmOmzwe0RMO0agOAzPR0AN9uq1adWVdC6oO1tTXOnDmD9PR0SEtLY8iQIXB3d6/0YHJRlJycDEtLS3z8+BGzxk/F6ce5tR5Lut3nA99XWnbHQpPKD39vKuiStxBr164dtWMUIXFxcTAxMYGKigqCg4OhrKzMdiTWNYdWbYMHD4aKtq6gA05DtGoDAD73c/eLb7VVa8iWaoR86fjx40hMTMSnT5+Qk5MDf39/9OvXj+1Y9eLZs2cYNmwYiouLERUVhU2TDLFljB6kJcQgXq1Tz/8jLsaBtIQYto7Ra/LFJEAFpdD75ZdfkJaWhjNnzrAdhXxHfHw8TExMoKSkhJCQkG9ezm1umkOrtq5du1Zoo9YQrdo4Ep8LyW+1VaMWnoTUzd27d2FoaIhWrVohOjpa8B41YaAGgpcZYaj250mCqgrLsvuHaisjeJkRxg/U+O7jmwq65C3kdHR0YGdnhx07dmDatGnUjlEIvXz5EiYmJmjZsiVCQ0PRtm1btiOJNFFr1QZUo41aPbRqK3teWlqaoLNHmbS0NAwaNKiaaQkhXwsJCYGjoyP09PTg7e1dYbmSupIcTs4yQHxGHk7fTkbYi0wkvy/El1t2OPh8aLlJt7aYMlgDXdo2r41pVFCKgJUrV8LIyAgBAQGwtrZmOw75wqtXr2BiYgJ5eXmEhoZ+d0NIcyQKrdq+PIeubOyatGqLj4+HlrI8OIDgw6WqVm21Id328+X3e/fulSse3759i9TUVMyZM+dbTyWEfMfly5cxceJEmJqa4uLFi9/tZNZVtQVc7XXhCl0UFHOR+L4AJVw+pCTEoKUs32AdcEQBXfIWAYaGhhg4cCC1JRMyiYmJMDExgYyMDMLCwur1gNimojm0art16xZiH96Hxv/v3myIVm0A0KWHDnr06IHDhw+Dx+MJbj948CA4HE61ztAkhJR39OhRODk5YcyYMfD09KxRW1x5aQnotm+Jvhqtodu+ZbMuJgGaoRQJZe0Yx48fj5iYGPTt25ftSM1ecnIyTExMICkpidDQ0HrrMNIUubq6IjAwEMOGDcP8+fPB4/Hwxx9/oFevXpW2SasuNzc3+Pv7w9DQEAsWLACXy8W+ffugq6uLR//X3t3H1Xj/fwB/nU4plWYl1qaEaAnbmLGRiuTeagyzsrnbCEOrMFmYNTe5mZtRGKvcDFNh6W4qdzNrGn2b0A+dGFFoIemcc/3+8K2vVinOqeuc0+v5ePR4fJ1znc/15mt5dV3v6/M+W/NDLmVXKX/44YdK7y1evBiJiYno1asXfHx8oK+vj9DQ0CpHtUVERGDAgAHoPOADFOU9xD/pcdA3s0Tprfvlx5WNass/uBLXt82AiUNv6Bm/APk/t1Cc/TuMWjrA3H1KtbWWjWt7c/lyDBs2DO7u7hg9ejT+85//YN26dZg4cWKFp+bLNgr/6KOPsG3btqf+OZw9exb79+8H8DjoFxYWYvHixQCA1157DUOHDi0/tmwLp5o2Pi8sLMTatWsBAMePHwfweFhD06ZN0bRpU0ybNu2pnyeqD8uWLcPs2bMxZcoUrF27tsopO/QMBNIKpaWlQuvWrYUxY8aIXUqDJ5PJhDZt2gitW7cWZDKZ2OVohV9++UV44403hEaNGglt27YVNm/eLHz++eeCkZFRheMACFOnTq1yDQBCUFBQhddSU1OFrl27Co0aNRLatGkjbNy4UQgKChL+/a2tVatWwuDBgyutefHiRUEqlQoAhD179lR47/Tp00L//v0FU1NTwdjYWHB1dRVOnDhRaY2zZ88Kzs7OgqGRkSBtYiG84OQlWAz8TAAgvDJ5i9BqzsHyrxYfBAtGrbsIEkMTQaLfSNBvaiWYdHITXvp4dfkxhtYdBUPrjhU+12rOQeFi3j+CIAhCVFSU8PrrrwuGhoZCy5YthcDAQOHRo0cVasrIyBAACHPmzKn6/5AnbN26VcDju/WVvj766KMKxzZr1kzo0aNHjWtevny52jVbtWpV7fHLly+vcW0iVSmVSsHf318AIHz55ZeCUqkUuySdwNGLWmTt2rWYNWsWLl26VGGrFKo/165dg7OzM+RyOVJTUzkWUwW6NqoNUM+4tidHtUmkBjBobIJ32lg807i27777DgEBAfi///s/tfX11sWoNkEQUFBQgNzcXHTp0oWjF6nOyeVyTJ48GVu2bMG3336Lzz77TOySdAZ7KLUIxzGK6/r163B1dUVpaSmSk5MZJp9BQxjVBjwxrk1FZaPa8vcvh76e5JnHtSUnJ+Ozzz5T60NidTGqrbCwEJaWljqzhyFptocPH2LkyJHYtm0bIiIiGCbVjFcotUxgYCC+/fZb5ObmchxjPbpx4wZcXFxw//59pKamVtjwmmpmZWVVaVRbSUkJ0tPTdWa6Rpldv8swZ1/Gc3++5EZ2+ag2aWMzrJryrs7uYyeXy5GSklL+6/bt2/PuC9WJoqIieHh44MSJE9izZw+GDBkidkk6h4FSy9y4cQOtWrXCV199pVNzUzVZXl4eXF1dUVhYiNTU1Go35KbqjRs3DsnJyZVGtenqlal1yRcRknBB5XUawrg2orp269YtDBo0CBcuXMDBgwfh5OQkdkk6iYFSC02cOBGHDh3C5cuX0ahRI7HL0Wm3bt2Cq6srbt++jZSUFLRv317skkhL7PpdhqD9mZArhWfqqZTqSaCvJ8GiYY46e2WSqL48OZc7Li4Or7/+utgl6SwGSi107tw5dOjQAdu2bcNHH30kdjk6Kz8/H3369MHNmzeRkpKCV199VeySSMvk3n6AL6IycDQ7H1I9yVODpZ4EUArAqy8I2PRJH1j/d19LIno+WVlZ6NevH/T19ZGYmMi7S3WMgVJLDR06FFeuXMHZs2c5jrEOFBQUoG/fvrh+/TqSk5PRoUMHsUsiLVabcW0u7S0Ru2YuDB/ewbFjx8QqlUgnpKWlYcCAAbCyskJ8fDz3Cq4HDJRaKjU1FS4uLoiLi0P//v3FLken3LlzB3379kVubi6Sk5PRsWNHsUsiHfK0cW0xMTHw8PDAsWPH0LNnT5ErJdJOhw8fxrvvvlvtXG6qGwyUWkoQBLz11lto2rQpEhMTxS5HZ9y9exdubm64cuUKkpOT0anTs23XQqQKpVKJjh07ws7Ornx6DRHVXtlcbldXV/z000/PNEqRVMN9KLWURCKBv78/kpKSkJ6eLnY5OqGwsBDu7u64fPkyfvnlF4ZJqnd6enoICAjAgQMHkJmZKXY5RFqlbC63p6cn9u/fzzBZz3iFUovJ5XK0a9cOPXv2RGRkpNjlaLV//vkH/fv3R1ZWFn755Red3c6GNN+jR4/Qtm1b9O3bt8Y53ET0GOdyi49XKLWYvr4+Zs2ahV27diE3N1fscrRWUVERBg4ciHPnziEpKYlhkkTVqFEjzJo1C9u3b4dMJhO7HCKNJggCAgICMHv2bMyfPx/r169nmBQJA6WWGz9+PMzMzLB69WqxS9FK9+7dw6BBg/Cf//wHCQkJ6Nq1q9glEWHSpEkwNTXFqlWrxC6FSGPJ5XJMmjQJy5cvx+rVq7Fo0SLueiIiBkotZ2pqiilTpiAsLAx3794Vuxytcv/+fQwePBhnzpxBfHw83nrrLbFLIgIANGnSBFOnTsWmTZtw+/Ztscsh0jgPHz7EqFGjsG3bNoSHh2PGjBlil9TgMVDqgGnTpuHRo0fYtGmT2KVojQcPHmDo0KE4ffo04uLi0KNHD7FLIqrgs88+g0KhwPr168UuhUijFBUVYfDgwYiNjUV0dDS8vb3FLonAh3J0xsSJExEXF4dLly5xHGMNiouLMWzYMPz666+Ii4tDr169xC6JqEo+Pj7Ys2cPcnJyYGzMyTlET87lPnDgAHr37i12SfRfvEKpI3x9fXHt2jXs2rVL7FI02sOHD+Hh4YETJ04gNjaWYZI0mp+fH27fvo2tW7eKXQqR6HJzc+Hk5ASZTIbU1FSGSQ3DK5Q6ZMiQIZDJZDhz5gwbk6tQUlICDw8PpKam4ueff4arq6vYJRHV6IMPPsDJkydx8eJF6Ovri10OkSiysrLg7u4OqVTKudwailcodYifnx8yMjKQkJAgdikap6SkBMOHD0dKSgoOHDjAMElaIyAgAFeuXMGePXvELoVIFGlpaejVqxfMzMxw/PhxhkkNxSuUOoTjGKv26NEjjBgxAgkJCdi/fz/c3d3FLonomfTv3x95eXlIT0/n3QdqUMrmcnfs2BE///wz53JrMF6h1CESiQR+fn5ISkrCn3/+KXY5GqG0tBSjRo1CfHw8oqOjGSZJK82ePbt8eyuihiIqKgoDBw5Ez549kZSUxDCp4XiFUsdwHOP/lJaW4oMPPsD+/fsRFRWFwYMHi10S0XMpu/tgamqK5ORkscshqnPff/89Jk2ahPfffx/h4eHcvUQL8AqljuE4xsfkcjk+/PBD7N+/Hz/99BPDJGk1iUSC2bNnIyUlBadOnRK7HKI6tXz5ckyYMAGffPIJtm/fzjCpJXiFUgfdu3cP1tbWmDBhAkJCQsQup97J5XJ4e3tj79692LNnDzw8PMQuiUhlCoUCDg4O6NSpE3766SexyyFSO0EQMGfOHCxbtgzz58/HwoUL2TOsRXiFUgc9OY6xsLBQ7HLqlUKhwMcff4w9e/Zg165dDJOkM6RSKfz9/REVFYXz58+LXQ6RWpXN5V62bBnncmspBkodNX36dJSUlCAsLEzsUuqNQqHA+PHjsWvXLuzcuRPDhw8XuyQitfL29kaLFi0a5J0H0l2cy60bGCh1lJWVFby8vPDtt9/i0aNHYpdT55RKJSZOnIjIyEhERkbi/fffF7skIrUzMjLCzJkzER4ejuvXr4tdDpHKnpzLHRUVxbncWoyBUod9/vnnuHbtGn788UexS6lTSqUSn376KcLDwxEeHo7Ro0eLXRJRnZk8eTKMjIywevVqsUshUkl+fj769OmDtLQ0xMfHY+jQoWKXRCrgQzk6TtfHMSqVSvj4+CAsLAzbtm3D2LFjxS6JqM7Nnj0bGzZsgEwmQ9OmTcUuh+iZ5ebmwt3dHbdv30Z8fDxef/11sUsiFfEKpY4rG8eoi5NzBEHAtGnTEBYWhi1btjBMUoMxc+ZMlJSUYOPGjWKXQvTMsrKy0LNnTxQXF+PYsWMMkzqCVyh1nCAI6NatG8zNzXVqxrcgCJgxYwbWrl2LzZs3Y8KECWKXRFSvJk2ahAMHDuDKlSswMjISuxyiWklLS8PAgQPRokULxMfH45VXXhG7JFITXqHUcRKJBP7+/khMTNSZcYyCIMDX1xdr165FaGgowyQ1SP7+/rh58ybCw8PFLoWoVpKTk+Hq6go7OzscOXKEYVLH8AplAyCXy2FnZwcnJydERESIXY5KBEGAv78/VqxYgfXr18PHx0fskohEM2LECJw5cwZZWVmQSqVil0NUraioKIwePRouLi7Yt28fTExMxC6J1IxXKBsAXRnHWDZFYcWKFVi7di3DJDV4s2fPRnZ2NqKiosQuhaha33//PUaMGAFPT08cOHCAYVJH8QplA6Ht4xgFQUBgYCCCg4OxatUqzJw5U+ySiDRCnz59UFRUhFOnTunkTg6k3ZYvX46AgABMnjwZ69at45V0HcYrlA2Eto9jDAoKQnBwMEJCQhgmiZ4we/ZspKWlITk5WexSiMoJgoDZs2cjICAAgYGB+O677xgmdRyvUDYg169fR6tWrRAcHAw/Pz+xy6m1RYsWISgoCEuXLkVAQIDY5RBpFEEQ0KVLFzRv3hzx8fFil0MEhUKByZMnY/Pmzbyj1IAwUDYw48ePR0JCAi5duoRGjRqJXU6Nvv766/Jb3XPnzhW7HCKNtHPnTowZMwZ//PEHunTpInY51ICVlJRgzJgxiImJwffff8/9gRsQBsoGJjMzEx07dkR4eLjGz0xdsmQJ5s6di6+++gqBgYFil0OkseRyOdq3b4+33noLu3btErscaqCKiorg6emJ48ePY/fu3Ryl2MAwUDZAgwcPxtWrV/Hnn39qbBN/WSN3UFAQFixYIHY5RBpv/fr1+Oyzz3DhwgW0bdtW7HKogcnPz8fAgQNx4cIFHDhwAL179xa7JKpnfCinAfLz88PZs2eRlJQkdilVWrVqVXkjd1BQkNjlEGmFcePGwcLCAitWrBC7FGpgcnNz4eTkBJlMhpSUFIbJBopXKBsgTR7H+O2332LmzJmYO3cuvv76a429gkqkiRYvXoyvv/4aOTk5aN68udjlUAOQlZUFd3d36OnpITExEe3atRO7JBIJr1A2QBKJBH5+fkhMTMSZM2fELqfcunXrMHPmTPj7+zNMEj0HHx8fSKVSrFmzRuxSqAFIS0uDk5MTzMzMcPz4cYbJBo5XKBuosnGMvXv31ohZwBs2bICPjw98fX0REhLCMEn0nHx9fbF161bIZDI0adJE7HJIRyUnJ2PYsGFwdHREbGwszM3NxS6JRMYrlA1U2TjGnTt3ij6OMSwsDD4+PpgxYwbDJJGKZs2ahXv37mHTpk1il0I6Kjo6GgMGDMA777yDpKQkhkkCwEDZoI0fPx6mpqai3h7bsmULPv30U0ybNg2rVq1imCRSkbW1NT788EOsXLkSjx49Ersc0jFbt27F8OHD4eHhgQMHDsDU1FTskkhDMFA2YE2aNMHkyZMRGhoqyjjGbdu2YdKkSZgyZQrWrFnDMEmkJgEBAbh27Rq2b98udimkQ0JCQjB+/HhMmjQJO3bs0IrhGFR/GCgbuOnTp+Phw4f1fnssIiKi/BvTunXrGCaJ1KhDhw4YOnQoli1bBqVSKXY5pOUEQcCcOXPg7++PwMBAbNiwgXO5qRI+lEP1Po5xx44d8Pb2xrhx4xAWFgY9Pf5cQ6RuJ06cQM+ePREdHY13331X7HJIS3EuN9UWAyWVj2OMiIiAl5dXnZ7rxx9/xJgxYzB27Fhs2bKFYZKoDjk5OUGhUOD48eO8C0DPjHO56VkwUBIAYNCgQbh27VqdjmPcs2cPPvjgA4wZMwZbt27lLROiOnbw4EEMHToUR44cgZOTk9jlkBYpm8t97Ngx7N69G8OGDRO7JNJwDJQE4PGeYn369EFCQgL69eun9vX37duHkSNHYtSoUQgPD2eYJKoHSqUSnTt3hq2tLQ4ePCh2OaQl8vPzMWjQIJw/fx779++Hs7Oz2CWRFmCgJACPm67ffPNNNGvWDPHx8WpdOyYmBiNGjMCIESMQEREBfX19ta5PRNULDw/HRx99hIyMDHTs2FHsckjD5ebmwt3dHbdv30ZcXBzeeOMNsUsiLcFASeV27tyJMWPG4MyZM+jcubNa1jxw4ED5nmU7duxgmCSqZ6WlpWjbti1cXFw0YioWaa7z58+jX79+nMtNz4VPRFC5999/HzY2NggJCVHLerGxsRgxYgSGDh2K7du3M0wSicDAwAC+vr7YsWMHcnJyxC6HNNQff/yBXr16oUmTJpzLTc+FgZLKPTmO8erVq+Wv3y+RI/PvQqTL7iDz70LcL5HXuFZcXBw8PT0xcOBA7Ny5EwYGBnVZOhE9xcSJE2FmZoaVK1eKXQppoOTkZLi6uqJt27Y4evQoXnnlFbFLIi3EW95UQVFREaytrTHqk5mw6vU+ks/fhOz2Azz5l0QCwMbcGK72zfFhdxu0a9GkwhqJiYkYOnQo3N3dsXfvXk5TINIAQUFBCAkJgUwmg4WFhdjlkIaIjo7GqFGj4OzsjH379nGUIj03BkqqIPf2A7y/fB9u4EVIJYDiKX87pHoSKJQCnOyaIdizE6zNjfHLL79gyJAh6NOnD/bt2wdDQ8P6K56IqpWfnw8bGxvMnj0bQUFBYpdDGmDr1q2YOHEiRowYgfDwcH6/JpUwUFK5Xb/LELQ/E3KF8qlB8t+kehLo60nwQXt9LPv0XTg7OyMqKgpGRkZ1VywRPbPp06dj586dyMnJgYmJidjlkIhCQkLg7++PTz/9FOvXr+dWbqQyBkoCAKxLvoiQhAsqr2Nx7QSOh81nmCTSQFeuXIGdnR1WrVqF6dOni10OiUAQBMydOxdLly7FvHnz8NVXX3GKEqkFH8qpQxKJBAsWLKjxuAULFoj6H/Su32VYEPIdcpYMgfxu3jN//sb2OchZMgQ5S4bg3IlExGTcrIMqNcPdu3chkUjKv9T1RDxRfbC1tcWoUaOwYsUKlJaWil0O1TOFQoFPPvkES5cuxcqVK7F48WKGSVIbBkoNZWtrC4lEUuVVhJSUFEgkEuzdu1fl8+TefoCg/Zkqr6Nv0RIWQz6H2Vue+HJ/JnJvPwDweHa3l5cX2rVrB4lEAhcXF5XPderUKfj4+KBr164wMDBQ2zfEu3fv4pNPPoGlpSVMTEzg6uqK06dPVzjGxMQEERERWLVqlVrOSVTfAgICkJOTg927d4tdCtWjkpISjBo1Clu3bsUPP/yAWbNmiV0S6RgGyjpUXFyMwMBAldbYtGkT/v77bzVVVNkXURmQK1XvepAaN4VpR1cYteoMuVLAF1EZAIANGzYgJiYG1tbWePHFF1U+D/B4f8vNmzdDIpGgTZs2allTqVRi8ODB2LFjB6ZNm4Zly5bh5s2bcHFxwcWLF8uPMzAwgJeXFzw8PNRyXqL69tprr2HAgAFYunQp2PHUMBQVFWHw4ME4ePAg9u3bh7Fjx4pdEukgBko1UyqVePjwIQDAyMhIpc28HR0doVAosGTJEnWVV8HFvCIczc6HQg2B8kkKpYCj2fnIvlmEiIgIFBYW4vDhw3j55ZfVsv6UKVNQWFiItLQ0tc0d37t3L06cOIFt27YhKCgIU6dORUpKCqRSKZ+IJZ0ze/ZsZGRk4NChQ2KXQnUsPz8fffv2xe+//474+HgMGzZM7JJIRzFQViMlJQVvvvkmjIyM0LZtW4SGhlbZ6yiRSDBt2jRs374djo6OMDQ0RFxcXPl7/+6hPHbsGLp161Zh3erY2tpi7Nixtb5KmZ6ejoEDB8LMzAympqbo27cvTp48Wem4zMxM9OnTBx1sLHF1/Ue4e3wXICirXLP4/9JwIzIAshXDIVv5Pm7uWYBHt2qetiHVkyDypAzW1tbQ01PvX7MWLVqgcePGal1z7969aNGiBd57773y1ywtLTFy5EjExMSgpKRErecjEpOzszO6d++OpUuXil0K1aGrV6+id+/eyMnJQUpKCpydncUuiXQYZ+FVIT09HQMGDICVlRUWLlwIhUKBRYsWwdLSssrjDx8+jN27d2PatGlo1qwZbG1tqzwuIyMD7u7usLS0xIIFCyCXyxEUFIQWLVpUW8u8efMQHh6OJUuWYM2aNdUel5mZCScnJ5iZmSEgIAAGBgYIDQ2Fi4sLUlNT0b17dwDAjRs34OrqCrlcjlecR6NQLsW9P+Mg0a+8+fi9/xxGwcFVMGrTBU1dPoZQWoKi9EPIiwyA1bg10G9afd0KpYDkCzexAI7VHqNJ0tPT0aVLl0rh96233kJYWBguXLiATp06iVQdkXpJJBLMnj0b7733Hk6ePIkePXqIXRKp2fnz5+Hu7g6JRIJjx45xlCLVOQbKKgQFBUEqleL48ePlt2lHjhwJBweHKo8/f/48MjIy0KFDh6eu++WXX0IQBBw9ehQ2NjYAgOHDhz81qLRp0wbe3t7YtGkT5s6dCysrqyqPCwwMRGlpKY4dO1beVzh27FjY29sjICAAqampAIClS5fi1q1bSD56HON+voMXAJh26otroZ9UWE/5qBh3EkNh+po7LAb+78Eg0059cS1sMgp/3V3h9arICh7gfokcJoaa/9fs+vXr6N27d6XXy/68//77bwZK0invvvsu7O3tsXTpUkRFRYldDqnRH3/8gQEDBqB58+ZISEjgKEWqF7zl/S8KhQJJSUnw8PCo0PNnZ2eHgQMHVvkZZ2fnGsOkQqFAfHw8PDw8ysMkADg4OKB///5P/WxgYCDkcnm1vZQKhQIJCQnw8PCo8JCKlZUVxowZg2PHjuGff/4B8PiBlh49esCyjWP5OEWp8QswcXSpsObDy+lQltyHSQdnKB4Uln9BogfDl9vjoezsU2sGAAHAlYL7NR6nCYqLi6ucElG2n2ZxcXF9l0RUp/T09ODv74+YmBhkZWWJXQ6pSUpKSvlc7iNHjjBMUr1hoPyXmzdvori4GHZ2dpXeq+o1AGjdunWN6966dQvFxcVV3nawt7d/6mfLrlKGhYXh+vXrVa794MGDKtdxcHCAUqlEbm4uACAnJwft2rXDI3nFnkkD84rfdErvPO7ZzNv5Ba6u+bDC18PL6Y/DZS38+zyaqnHjxlX2SZY9YKXunk0iTeDl5QUrKyssX75c7FJIDaKjozFgwAD06NEDSUlJnNlO9Urz70VqgfoIG/PmzUNERASWLl2qli1rGunX8LPEf7cTsRjyOaSmlbf7kUhq97NIjefREFZWVlWG9bLX1PWEOpEmMTQ0xMyZMzFv3jwsWrSIV7O0WNlc7uHDhyMiIoJzuaneace/9vWoefPmMDIyQnZ2dqX3qnqttiwtLdG4ceMKexqWOX/+fI2fb9u2Lby8vBAaGlop+FhaWsLY2LjKdbKysqCnpwdra2sAQKtWrXDx4kXYWpjgyefVS29fq/A5/Rcf9w5KTV5AY9vXK30ZtepcY80A0MrcuFbHie3111/H6dOnoVRWvKL622+/wdjYGO3btxepMqK69emnn8LY2BirV68WuxR6TitWrMD48eMxadIk7Ny5k2GSRMFA+S9SqRRubm6Ijo6usFVPdna2Snu2SaVS9O/fH9HR0ZDJZOWvnzt3DvHx8bVao+zBm2XLllVa293dHTExMbhy5Ur563l5edixYwd69eoFMzMzAMCgQYNw8uRJZJ45DZv/hj3Fg0Lcz0ypsGbj1l0gMTRG4YndEBTySrXU5pZ36e2/0aF9W4wfPx47duyAXF55HU0xYsQI5OXlYd++feWv5efnY8+ePRg6dCi/QZPOMjMzw5QpU7Bx40bcuXNH7HLoGZTN5fbz88O8efOwYcMGSKVSscuiBoq3vKuwYMECJCQkoGfPnpgyZQoUCgXWrVuHjh074s8//3zudRcuXIi4uDg4OTnBx8cHcrkca9euhaOjI86erfkhl7KrlD/88EOl9xYvXozExET06tULPj4+0NfXR2hoKEpKSioE0ICAAERERGDAgAHoPOADFOU9xD/pcdA3s0Tprf89QKNnaAwLdx/kH1yJ69tmwMShN/SMX4D8n1sozv4dRi0dYO4+pdpapRLApePLKL77NmJjY7F161YAwKVLl9CzZ0+0bdsWH374YYUHkiQSCZydnZGSkvLUP4ecnBxEREQAANLS0sp//8DjK7De3t7lx5Ztm1TTRJARI0agR48eGDduHP766y80a9YM3333HRQKBRYuXPjUzxJpuxkzZmDVqlXYsGEDvvjiC7HLoVpQKBSYMmUKNm3ahJUrV3KUIomOgbIKXbt2xaFDh+Dn54f58+fD2toaixYtwrlz51R6GrJz586Ij4+Hr68vvvzyS7Rs2RILFy7E9evXaxUogcdXKSMjI6FQKCq87ujoiKNHj2Lu3Ln45ptvoFQq0b17d0RGRpbvQQk87hVMTk7G9OnTcTLqe8gNTGD6+kDom5qj4FDFfS5NHF0gNTVH4cm9KPxtH6AohdTUAobWjjDp/PQJNQoBCBzVG5EFv1eYGVxaWooTJ07gxIkT2L59O3r16oV+/frhnXfeKa+vJpcvX8b8+fMrvFb2a2dn5wqB8t69e3jppZdqXFMqlSI2Nhb+/v5Ys2YNiouL0a1bN2zbtq3Gh6aItN1LL72Ejz/+GN9++y1mzZrFh9A0XElJCT788ENER0dj27Zt+Oijj8QuiQgSgcNca83DwwOZmZlV9kFqK+8tv+HEpQKVxi/e2D4HUCpgOTwQEqkBDBqb4J02FoiY0L3K4wVBwIULF5CUlISkpCQcPny4fFsjV1dXDB8+HG5ubmjfvn2lyUTPoqioCObm5li9ejWmTp363Ov8u/aCggLk5uaiS5cuWL58Ofz8/NSyNpGYsrOzYW9vj/Xr12Py5Mlil0PVuHfvHjw9PXH06FHs3r2boxRJY7CHshr/3nfw4sWLiI2NhYuLizgF1ZFgz07Q13v+0Fam5No5XF3zIfL3L4e+ngTBntVvAi6RSGBvb4+pU6ciKioKBQUFGDNmDDp16gSlUolZs2bh1VdfRatWrcr7L/Py8p65prI92CZNmqTKb62CwsJCWFpaokuXLmpbk0gT2NnZYfjw4QgJCal0B4Q0Q0FBAfr27YvffvuNc7lJ4/AKZTWsrKzw8ccfo02bNsjJycGGDRtQUlKC9PR0nRthtet3Gebsy3juz5fcyIby4T0AgLSxGVZNeRejutnU8Knq3b9/H0eOHCm/glnWDtCpUyf069cPbm5u6N27N0xMTJ77HM9LLpdX6PFs3759hY3qibTZH3/8gTfffBM//vgjRo4cKXY59ISrV6/C3d0d+fn5iI+PxxtvvCF2SUQVMFBWY9y4cUhOTsaNGzdgaGiIt99+G8HBwTp7ZWpd8kWEJFxQeR1/d3tMda16A/jnlZeXh19++QVJSUlITEzE1atXYWBggLfffrs8YL755pvQ12dLMJGq3NzccOfOHaSlpanUckLqUzaXGwASExO5jRlpJAZKKrfrdxmC9mdCrhSeqadSqieBvp4Ei4Y5qnRlsjaq6780MzODq6trecBUtf+SqKFKTEyEu7s7EhMT4ebmJnY5Dd7p06cxYMAAWFpaIj4+Hi1bthS7JKIqMVBSBbm3H+CLqAwczc6HVE/y1GBZ9r6TXTMEe3aCtQibmMvlcqSlpZUHzBMnTqC0tBTW1tZwc3ODm5sb+vbtixYtWtR7bUTaSBAEdO3aFRYWFkhMTBS7nAYtJSUFw4YNQ4cOHfDzzz9zlCJpNAZKqtLFvCJs/02G5As3ISt4gCf/kkgA2FgYw7V9c3j1sIFd8yZilVmJJvdfEmmL3bt3Y9SoUUhLS0PXrl3FLqdBio6OxujRo9G7d2/s27cPpqamYpdE9FQMlFSj+yVyXCm4j0dyJRrp68HWwgQmhtrRr8j+S6Jnp1AoYG9vjy5dulTYR5bqx7Zt2zBhwgTO5SatwkBJDQb7L4lqb+PGjZg6dSrOnz8POzv1PmhH1VuxYgX8/Pzw6aefYv369RylSFqDgZIaLPZfElWvuLgYtra28PT0xMaNG8UuR+cJgoAvvvgCS5YswRdffIHFixfzB1vSKgyURP/F/kuiioKDg7Fo0SJcuXKlViNM6fk8OZd7xYoV8PX1FbskomfGQElUDfZfUkN3584d2NjYYPr06QgODha7HJ1UUlICLy8vREVFYcuWLZzLTVqLgZKoFth/SQ2Vn58fNm/eDJlMBjMzM7HL0Smcy026hIGS6Dmw/5IaimvXrqF169YIDg6Gn5+f2OXojIKCAgwaNAjnzp3DgQMH4OzsLHZJRCphoCRSA/Zfki4bP3484uLicPnyZW5howZPzuWOi4vT2ZG+1LAwUBLVAfZfki45d+4cHB0dsWnTJkyYMEHscrTahQsX0K9fPwCcy026hYGSqI6x/5J0gaenJ86dO4e//voLenp6YpejlTiXm3QZAyVRPWP/JWmjkydP4u2338a+ffvg6ekpdjlap2wut4ODA2JjYzmXm3QOAyWRyNh/SdrC2dkZJSUl+PXXX3k1/RnExMRg1KhRnMtNOo2BkkjDsP+SNFVsbCwGDx6MlJQUPpVcS9u2bcPEiRPx3nvvcS436TQGSiINxv5L0iSCIOC1115Dy5YtERsbK3Y5Gm/lypX4/PPP8cknn+C7777jXG7SaQyURFqkuv7Lli1bws3NDf369WP/JdWpyMhIeHt748yZM+jcubPY5WgkQRAwb948fPPNN5zLTQ0GAyWRFnta/2VZwHRycmLPFqlNaWkp7Ozs4OTkhMjISLHL0TgKhQI+Pj4ICwvjXG5qUBgoiXTIjRs3cPjw4Sr7L8sCJvsvSVVr167FrFmzkJ2dDVtbW7HL0RhPzuXevHkzPv74Y7FLIqo3DJREOqqm/suygMn+S3pW9+/fR6tWrfDBBx9g7dq1YpejEe7du4f33nsPR44cwY8//oh3331X7JKI6hUDJVEDwf5LUqeFCxdi6dKlyMnJgaWlpdjliOrJudz79++Hi4uL2CUR1TsGSqIG6t69ezh69Gj57fGMjAwA7L+k2ikoKICNjQ38/PywcOFCscsRDedyEz3GQElEANh/Sc9uxowZiIyMhEwma5Ab73MuN9H/MFASUSXsv6TayMnJQdu2bbFixQrMmDFD7HLqVdlc7mbNmiEhIYFzuanBY6Akohqx/5Kq4+3tjSNHjiA7OxsGBgZil1MvOJebqDIGSiJ6Zuy/pDIZGRno3LkzwsPD4e3tLXY5da5sLreTkxOioqL4d5zovxgoiUhl7L9s2IYMGYIrV67g7Nmz0NPTE7ucOvPDDz9gwoQJ8PT0RGRkJOdyEz2BgZKI1Ir9lw3P0aNH0bt3bxw4cABDhgwRu5w6wbncRE/HQElEdYr9l7pPEAT07NkTUqkUR48eFbsctXpyLvfcuXPx9ddf8wchoiowUBJRvWL/pW6KiYmBh4cHjh8/jnfeeUfsctTiybncISEh+Pzzz8UuiUhjMVASkajYf6kblEolOnbsiHbt2iEmJkbsclRWUlICb29v7Nu3j3O5iWqBgZKINAb7L7Xb1q1bMX78eGRmZqJDhw5il/PcOJeb6NkxUBKRxmL/pXZ59OgR2rRpg379+mHr1q1il/NcOJeb6PkwUBKR1mD/peZbsWIF5s6di0uXLmnd9Jhr167B3d0dt27d4lxuomfEQElEWov9l5qnqKgINjY2GD9+PFasWCF2ObV24cIFuLu7QxAEzuUmeg4MlESkE9h/qTkCAwOxevVqyGQymJubi11OjTiXm0h1DJREpJPYfymemzdvolWrVpg3bx4CAwPFLuepUlNTMXToULz66quIjY1Fs2bNxC6JSCsxUBJRg8D+y/rl4+ODvXv3IicnB40bNxa7nCrt378fI0eOhJOTE/bt24cmTZqIXRKR1mKgJKIGif2XdevSpUto164d1q5dCx8fH7HLqYRzuYnUi4GSiBo89l/WjdGjR+PUqVO4cOGCRgXzsrnckyZNwoYNGziXm0gNGCiJiP6F/ZfqkZ6eji5dumDnzp0YPXq02OVAEAQEBgYiODiYc7mJ1IyBkoioBuy/fH5l+zqePn1a1PCmUCgwdepUhIaGci43UR1goCQiekbsv6y9w4cPo2/fvoiPj4e7u7soNZTN5f7pp5+wefNmjBs3TpQ6iHQZAyURkQrYf/l0giDgrbfeQpMmTXD48OF6P/+Tc7l37doFDw+Peq+BqCFgoCQiUqMn+y8TExPx66+/Nvj+y7179+L999/HqVOn0K1bt3o7b0FBAQYPHoy//voLMTExcHV1rbdzEzU0DJRERHWorP8yMTERSUlJDbL/UqFQwMHBAZ07d8bevXvr5Zxlc7lv3ryJuLg4dO3atV7OS9RQMVASEdWjsv7LsoDZUPovw8LCMHnyZGRlZdX5nOwn53InJCTA3t6+Ts9HRAyURESiebL/MjExEcnJyTrbf/nw4UPY2tpi2LBhCAsLq7PzpKeno3///mjWrBni4+NhbW1dZ+ciov9hoCQi0hC63n+5ZMkSBAUF4cqVK7CyslL7+qmpqRg2bBjs7e05l5uonjFQEhFpKF3rv7x79y5sbGzg4+ODJUuWqHXtsrncvXr1QlRUFOdyE9UzBkoiIi2hC/2Xs2fPxsaNGyGTyfDCCy+oZc3w8HCMHz8eHh4e2L59O+dyE4mAgZKISAtpa//l9evXYWtri6+++goBAQHlr98vkeNKwX08kivRSF8PthYmMDGsORivWrUKvr6+nMtNJDIGSiIiHaBN/ZeTJk3CwYMHkXgqA3vT85B8/iZktx/gyX+MJABszI3hat8cH3a3QbsWFW9hC4KA+fPn4+uvv8acOXMQHBysUcGZqKFhoCQi0kGa3H+Z+kcmRi6PQuPWb0CqJ4FCWf0/Q2XvO9k1Q7BnJ1ibG1eYy718+XL4+fnVY/VEVBUGSiKiBqCm/ks3Nzd069atzvsvd/0uQ9D+TJSUygGJXq0/J9WTQF9PgvmD7HFg9Vzs3buXc7mJNAgDJRFRA1Ob/ks3NzfY29ur9TbyuuSLCEm4oPI6Rcd3YIvv+5zLTaRBav/jIRERaRyJRIIFCxbUeNyCBQvKw6FEIoG9vT2mTp2K6OhoFBQU4Ndff4W/vz/u3LkDX19fODg4wMbGBuPGjcP27duRl5enUp27fpdhQch3yFkyBPK7z77Wje1zkLNkCHKWDEHx3xdR8koXlerRdE2bNoVEIoFEIsG0adPELoeoRgyUREQNlK2tLSQSCWbNmoUePXogMDAQqampuH37NpYsWYKrV6/i8OHD8PLywksvvYTOnTvD19cXsbGxuHfvXq3Pk3v7AYL2Z6pcr75FS1gM+Rxmb3niy/2ZyL39AADw448/wsvLC+3atYNEIoGLi4vK5zp16hR8fHzQtWtXGBgYqOVK7fXr1zFnzhy4urqiSZMmkEgkSElJqfLYsLAwREREqHxOovrCQElEpMWKi4sRGBio0hqbNm3C33//Xf5rU1NTdO/eHQCwYsUKXL9+Hdu3b0fXrl2xZ88eDB48GObm5nB2dsZXX32FX3/9FXK5vNr1v4jKgPwpD97UltS4KUw7usKoVWfIlQK+iHr8oNGGDRsQExMDa2trvPjiiyqfBwBiY2OxefNmSCQStGnTRi1rnj9/HkuXLsW1a9fQqVOnpx47cuRIeHl5qeW8RPWBgZKISMsolUo8fPgQAGBkZKTSgzSOjo5QKBRPnVzz0ksvYcyYMdi6dStkMhmysrKwatUqvPjiiwgJCcE777wDCwsLeHh4YN26dcjKykJZe/7FvCIczc5/6pPcz0OhFHA0Ox/ZN4sQERGBwsJCHD58GC+//LJa1p8yZQoKCwuRlpaGfv36qWXNrl27oqCgABcuXICvr69a1iTSFAyUREQiSUlJwZtvvgkjIyO0bdsWoaGhFXody5T10W3fvh2Ojo4wNDREXFxc+Xv/7qE8duwYunXrVmHd6tja2mLs2LGVrlJW588//8TMmTMxd+5cJCUloWvXrti0aVOl/ksrKytYWVnBoWUzXF3/Ee4e3wUIyirXLP6/NNyIDIBsxXDIVr6Pm3sW4NGtnBprkepJEHlSBmtra+jpqfefsxYtWqBx48ZqXbNJkyYwNzdX65pEmkJz53MREemw9PR0DBgwAFZWVli4cCEUCgUWLVoES0vLKo8/fPgwdu/ejWnTpqFZs2awtbWt8riMjAy4u7vD0tISCxYsgFwuR1BQ0FM3NJ83bx7Cw8OxZMkSrFmzptrjMjMz4eTkBDMzMwQEBMDAwAChoaGYNm0aUlNTERgYiHv37iEmJgaTJk3Co0ePYPz6IEjNLHHvzzhI9BtVWvPefw6j4OAqGLXpgqYuH0MoLUFR+iHkRQbAatwa6Detvm6FUkDyhZtYAMdqjyGi+sFASUQkgqCgIEilUhw/frz8Nu3IkSPh4OBQ5fHnz59HRkYGOnTo8NR1v/zySwiCgKNHj8LGxgYAMHz48Kf27LVp0wbe3t7YtGkT5s6dCysrqyqPCwwMRGlpKY4dO1beVzh27FjY29sjICAAqampMDU1RVpaGoqLi5F89DjG/XwHAgDTTn1xLfSTCuspHxXjTmIoTF9zh8XA6eWvm3bqi2thk1H46+4Kr1dFVvAA90vktRrTSER1h7e8iYjqmUKhQFJSEjw8PCr0/NnZ2WHgwIFVfsbZ2bnGMKlQKBAfHw8PD4/yMAkADg4O6N+//1M/GxgYCLlcXm0vpUKhQEJCAjw8PCo8pGJlZYUxY8bg2LFj+OeffwA8fqClR48esGzjWD5OUWr8AkwcXSqs+fByOpQl92HSwRmKB4XlX5DowfDl9ngoO/vUmgFAAHCl4H6NxxFR3eKPdERE9ezmzZsoLi6GnZ1dpfeqeg0AWrduXeO6t27dQnFxMdq1a1fpPXt7e8TGxlb72bKrlGFhYZgzZ06Vaz948AD29vaV3nNwcIBSqURubi4cHR2Rk5OD7t2745G8Ys+kgfkrFX5deudxz2bezi+qrEliaFxtvU/693mIqP4xUBIRaQF1PyBSlXnz5iEiIgJLly5VyxSaRvo13AT775PgFkM+h9S08nY/klqOZqzxPERU5xgoiYjqWfPmzWFkZITs7OxK71X1Wm1ZWlqicePGuHjxYqX3zp8/X+Pn27ZtCy8vL4SGhpbvQ/nk2sbGxlWuk5WVBT09PVhbWwMAWrVqhYsXL8LWwgQSoPy2d+ntaxU+p//i415NqckLaGz7es2/wSpIANhamDzXZ4lIffhjHRFRPZNKpXBzc0N0dHSFrXqys7Nx6NAhldbt378/oqOjIZPJyl8/d+4c4uPja7VG2YM3y5Ytq7S2u7s7YmJicOXKlfLX8/LysGPHDvTq1QtmZmYAgEGDBuHkyZPIPHMaNuaPb1srHhTifmZKhTUbt+4CiaExCk/shqCovDG64kFhjfXaWBjzgRwiDcD/ComIRLBgwQIkJCSgZ8+emDJlChQKBdatW4eOHTvizz//fO51Fy5ciLi4ODg5OcHHxwdyuRxr166Fo6Mjzp6t+SGXsquUP/zwQ6X3Fi9ejMTERPTq1Qs+Pj7Q19dHaGgoSkpKKgTQgIAAREREYMCAAeg84AMU5T3EP+lx0DezROmt/z1Ao2doDAt3H+QfXInr22bAxKE39IxfgPyfWyjO/h1GLR1g7j6l2lqlehK4tm+OI0eO4MiRIwAe93rev38fixcvBgD07t0bvXv3Lv+MRCKBs7NztSMPy+Tk5JSPPkxLSyv//QOPr8B6e3uXH+vi4oLU1NTyzdyfpmyNzMzHoygjIiJw7NgxAFB54hGRmBgoiYhE0LVrVxw6dAh+fn6YP38+rK2tsWjRIpw7dw5ZWVnPvW7nzp0RHx8PX19ffPnll2jZsiUWLlyI69ev1ypQAo+DTWRkJBQKRYXXHR0dcfToUcydOxfffPMNlEolunfvjsjIyAq3yK2srJCcnIzp06fjZNT3kBuYwPT1gdA3NUfBoYr7XJo4ukBqao7Ck3tR+Ns+QFEKqakFDK0dYdL56RNqFEoBXj1sEPndHixcuLDCe/PnzwfweHumskBZNn+8um2RnnT58uXyNf69prOzc4VAee/ePbz00ks1rvnkGmW+//778v/NQEnaTCLU5kcqIiKqFx4eHsjMzKyyD1JbeW/5DScuFag0fvHG9jmAUgHL4YGQSA1g0NgE77SxQMSE7jV/+L9iY2MxZMgQnDlzpsZZ2rVVVFQEc3NzrF69GlOnTlXLmgBw+/ZtKJVKWFpaYurUqVi3bp3a1iaqC+yhJCISSXFxcYVfX7x4EbGxsXBxcRGnoDoS7NkJ+nqSmg+sQcm1c7i65kPk718OfT0Jgj2fLRQmJydj9OjRaguTAHDkyBG88sormDRpktrWBB5v41Td1CQiTcQrlEREIrGyssLHH3+MNm3aICcnBxs2bEBJSQnS09Or3EtSm+36XYY5+zKe+/MlN7KhfPj4lrW0sRlWTXkXo7rZ1PAp7ZWamorS0lIAgLW1dZX7fxJpEgZKIiKRjBs3DsnJybhx4wYMDQ3x9ttvIzg4GF26dBG7tDqxLvkiQhIuqLyOv7s9prpWvQE8EYmDgZKIiOrNrt9lCNqfCblSeKaeSqmeBPp6Eiwa5qjTVyaJtBUDJRER1avc2w/wRVQGjmbnQ6oneWqwLHvfya4Zgj07wdq8duMYiah+MVASEZEoLuYVYftvMiRfuAlZwQM8+Y+RBI83LXdt3xxePWxg17yJWGUSUS0wUBIRkejul8hxpeA+HsmVaKSvB1sLE07AIdIiDJREREREpBLuQ0lEREREKmGgJCIiIiKVMFASERERkUoYKImIiIhIJQyURERERKQSBkoiIiIiUgkDJRERERGphIGSiIiIiFTCQElEREREKmGgJCIiIiKVMFASERERkUoYKImIiIhIJQyURERERKQSBkoiIiIiUgkDJRERERGphIGSiIiIiFTCQElEREREKmGgJCIiIiKVMFASERERkUoYKImIiIhIJQyURERERKQSBkoiIiIiUgkDJRERERGphIGSiIiIiFTCQElEREREKmGgJCIiIiKVMFASERERkUoYKImIiIhIJQyURERERKQSBkoiIiIiUgkDJRERERGphIGSiIiIiFTCQElEREREKmGgJCIiIiKVMFASERERkUoYKImIiIhIJQyURERERKSS/weq54p4gwXUCQAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "alternative_cube_architecture = SquareGrid(2, 2, 2)\n", "draw_graph(alternative_cube_architecture.coupling)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The current range of quantum computers are commonly referred to as Noisy-Intermediate-Scale-Quantum devices i.e. NISQ devices. The impact of noise is a primary concern during compilation and incentivizes producing physically permitted circuits that have a minimal number of gates. For this reason benchmarking in this area is often completed by comparing the final number of two-qubit (or particularly SWAP gates) in compiled circuits." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However it is important to remember that adding logical SWAP gates to minimise gate count is not the only way this constraint can be met, with large scale architecture-aware synthesis methods and fidelity aware methods amongst other approaches producing viable physically permitted circuits. It is likely that no SINGLE approach is better for all circuits, but the ability to use different approaches where best fitted will give the best results during compilation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Producing physically valid circuits is completed via the `MappingManager` class, which aims to accommodate a wide range of approaches." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import MappingManager" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `MappingManager` object requires an `Architecture` object at construction." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "mapping_manager = MappingManager(id_architecture)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All mapping is done through the `MappingManager.route_circuit` method. The `MappingManager.route_circuit` method has two arguments, the first a Circuit to be routed (which is mutated), the second a `List[RoutingMethodCircuit]` object that defines how the mapping is completed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Later we will look at defining our own `RoutingMethodCircuit` objects, but initially lets consider one thats already available." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import LexiLabellingMethod, LexiRouteRoutingMethod" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "lexi_label = LexiLabellingMethod()\n", "lexi_route = LexiRouteRoutingMethod(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `lexi_route` object here is of little use outside `MappingManager`. Note that it takes a lookahead parameter, which will affect the performance of the method, defining the number of two-qubit gates it considers when finding `SWAP` gates to add." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "from pytket import Circuit, OpType\n", "from pytket.circuit import display" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also look at which logical qubits are interacting." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "from pytket.utils import Graph" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "q[0]\n", "\n", "q[0]\n", "\n", "\n", "\n", "q[1]\n", "\n", "q[1]\n", "\n", "\n", "\n", "q[0]--q[1]\n", "\n", "\n", "\n", "\n", "q[2]\n", "\n", "q[2]\n", "\n", "\n", "\n", "q[0]--q[2]\n", "\n", "\n", "\n", "\n", "q[3]\n", "\n", "q[3]\n", "\n", "\n", "\n", "q[0]--q[3]\n", "\n", "\n", "\n", "\n", "q[1]--q[2]\n", "\n", "\n", "\n", "\n", "q[1]--q[3]\n", "\n", "\n", "\n", "\n", "q[2]--q[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By running the `MappingManager.route_circuit` method on our circuit `c` with the `LexiLabellingMethod` and `LexiRouteRoutingMethod` objects as an argument, qubits in `c` with some physical requirements will be relabelled and the qubit graph modified (by the addition of SWAP gates and relabelling some CX as BRIDGE gates) such that the qubit graph is isomorphic to some subgraph of the full architecture." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mapping_manager.route_circuit(c, [lexi_label, lexi_route])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The graph:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "e1[1]\n", "\n", "e1[1]\n", "\n", "\n", "\n", "e0[0]\n", "\n", "e0[0]\n", "\n", "\n", "\n", "e1[1]--e0[0]\n", "\n", "\n", "\n", "\n", "e2[2]\n", "\n", "e2[2]\n", "\n", "\n", "\n", "e1[1]--e2[2]\n", "\n", "\n", "\n", "\n", "e3[3]\n", "\n", "e3[3]\n", "\n", "\n", "\n", "e2[2]--e3[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The resulting circuit may also change if we reduce the lookahead parameter." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, LexiRouteRoutingMethod(1)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also pass multiple `RoutingMethod` options for Routing in a ranked List. Each `RoutingMethod` option has a function for checking whether it can usefully modify a subcircuit at a stage in Routing. To choose, each method in the List is checked in order until one returns True. This will be discussed more later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can aid the mapping procedure by relabelling qubits in advance. This can be completed using the `Placement` class." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "from pytket.placement import Placement, LinePlacement, GraphPlacement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default ```Placement``` assigns logical qubits to physical qubits as they are encountered during routing. ```LinePlacement``` uses a strategy described in https://arxiv.org/abs/1902.08091. ```GraphPlacement``` is described in Section 7.1 of https://arxiv.org/abs/2003.10611. Lets look at how we can use the ```LinePlacement``` class.`" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "line_placement = LinePlacement(id_architecture)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "line_placement.place(c)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that one qubit remains unplaced in this example. `LexiRouteRoutingMethod` will dynamically assign it during mapping." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Different placements will lead to different selections of SWAP gates being added. However each different routed circuit will preserve the original unitary action of the full circuit while respecting connectivity constraints." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mapping_manager.route_circuit(c, [lexi_label, lexi_route])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The graph:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "e0[0]\n", "\n", "e0[0]\n", "\n", "\n", "\n", "e1[1]\n", "\n", "e1[1]\n", "\n", "\n", "\n", "e0[0]--e1[1]\n", "\n", "\n", "\n", "\n", "e2[2]\n", "\n", "e2[2]\n", "\n", "\n", "\n", "e0[0]--e2[2]\n", "\n", "\n", "\n", "\n", "e1[1]--e2[2]\n", "\n", "\n", "\n", "\n", "e3[3]\n", "\n", "e3[3]\n", "\n", "\n", "\n", "e2[2]--e3[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, small changes to the depth of lookahead or the original assignment of `Architecture` `Node` can greatly affect the resulting physical circuit for the `LexiRouteRoutingMethod` method. Considering this variance, it should be possible to easily throw additional computational resources at the problem if necessary, which is something TKET is leaning towards with the ability to define custom `RoutingCircuitMethod` objects." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To define a new `RoutingMethodCircuit` method though, we first need to understand how it is used in `MappingManager` and routing. The `MappingManager.route_circuit` method treats the global problem of mapping to physical circuits as many sequential sub-problems. Consider the following problem." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "from pytket import Circuit" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "from pytket.placement import place_with_map" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 0)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ = Circuit(4).CX(0, 1).CX(1, 2).CX(0, 2).CX(0, 3).CX(2, 3).CX(1, 3).CX(0, 1)\n", "naive_map = {\n", " circ.qubits[0]: node_0,\n", " circ.qubits[1]: node_1,\n", " circ.qubits[2]: node_2,\n", " circ.qubits[3]: node_3,\n", "}\n", "place_with_map(circ, naive_map)\n", "Graph(circ).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So what happens when we run the following?" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "SWAP\n", "\n", "\n", "cluster_15\n", "\n", "SWAP\n", "\n", "\n", "cluster_16\n", "\n", "BRIDGE\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(15, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(6, 0)->(15, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(15, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 0)->(16, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(12, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 2)\n", "\n", "2\n", "\n", "\n", "\n", "(12, 1)->(16, 2)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(13, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(14, 0)->(16, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 0)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 1)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 2)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mapping_manager.route_circuit(circ, [lexi_route])\n", "Graph(circ).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sequential mapping typically works by partitioning the circuit into two, a first partition comprising a connected subcircuit that is physically permitted, a second partition that is not. Therefore, the first thing `MappingManager.route_circuit` does is find this partition for the passed circuit, by iterating through gates in the circuit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will construct the partitions ourselves for illustrative purposes. Lets assume we are routing for the four qubit line architecture (qubits are connected to adjacent indices) \"simple_architecture\" we constructed earlier." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_first_partition = Circuit(4).CX(0, 1).CX(1, 2)\n", "place_with_map(circ_first_partition, naive_map)\n", "Graph(circ_first_partition).get_DAG()" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(2, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 0)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = Circuit(4).CX(0, 2).CX(0, 3).CX(2, 3).CX(1, 3).CX(0, 1)\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that there are gates in the second partition that would be physically permitted, if they were not dependent on other gates that are not." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next step is to modify the second partition circuit to move it closer being physically permitted. Here the `LexiRouteRoutingMethod` as before will either insert a SWAP gate at the start of the partition, or will substitute a CX gate in the first slice of the partition with a BRIDGE gate." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The option taken by `LexiRouteRoutingethod(1)` is to insert a SWAP gate between the first two nodes of the architecture, swapping their logical states. How does this change the second partition circuit?" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "SWAP\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 0)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = (\n", " Circuit(4).SWAP(0, 1).CX(1, 2).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", ")\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Leaving the full circuit as:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "SWAP\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "CX\n", "\n", "\n", "cluster_15\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 1)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(12, 0)->(15, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 1)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(14, 0)->(15, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "full_circuit = (\n", " Circuit(4).CX(0, 1).CX(1, 2).SWAP(0, 1).CX(1, 2).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", ")\n", "place_with_map(full_circuit, naive_map)\n", "Graph(full_circuit).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After a modification is made the partition is updated." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first partition:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "SWAP\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_first_partition = Circuit(4).CX(0, 1).CX(1, 2).SWAP(0, 1).CX(1, 2)\n", "place_with_map(circ_first_partition, naive_map)\n", "Graph(circ_first_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second partition:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(2, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(4, 0)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(8, 1)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 0)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = Circuit(4).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This pattern of modification and updating the partition is repeated until the partition has reached the end of the circuit, i.e. the back side of the partition has no gates in it. Also note that the process of updating the partition has been simplified for this example with \"physically permitted\" encapsulating two-qubit gate constraints only - in the future we expect other arity gates to provide constraints that need to be met. Also note that any modification to the second circuit can willfully modify the qubit labelling and a token swapping network will be automatically added to conform to the new labelling." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now enough about how `MappingManager` works to add our own `RoutingMethodCircuit`. While `LexiRouteRoutingMethod` is implemented in c++ TKET, giving it some advantages, via lambda functions we can define our own `RoutingMethodCircuit` in python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A python defined `RoutingMethodCircuit` requires three arguments. The first is a function that given a Circuit (the circuit after the partition) and an Architecture, returns a bool (determining whether the new circuit should be substituted in a full routing process), a new Circuit (a modification of the original circuit such as an added SWAP) a Dict between qubits reflecting any relabelling done in the method, and a Dict between qubits giving any implicit permutation of qubits (such as by adding a SWAP). For some clarity (we will write an example later), lets look at an example function declaration." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "from typing import Dict" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "def route_subcircuit_func(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " return ()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first return is a bool which detemrines if a given `RoutingMethodCircuit` is suitable for providing a solution at a given partition. `MappingManager.route_circuit` accepts a List of of `RoutingMethod` defining how solutions are found. At the point the partition circuit is modified, the circuit is passed to `RoutingMethodCircuit.routing_method` which additionally to finding a subcircuit substitution, should determine whether it can or can't helpfully modify the partition boundary circuit, and return True if it can. The first `RoutingMethodCircuit` to return True is then used for modification - meaning the ordering of List elements is important." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The third argument sets the maximum number of gates given in the passed Circuit and the fourth argument sets the maximum depth in the passed Circuit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`LexiRouteRoutingMethod` will always return True, because it can always find some helpful SWAP to insert, and it can dynamically assign logical to physical qubits. Given this, lets construct a more specialised modification - an architecture-aware decomposition of a distance-2 CRy gate. Lets write our function type declarations for each method:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_decomp(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " return (False, Circuit(), {}, {})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Where do we start? Lets define a simple scope for our solution: for a single gate in the passed circuit (the circuit after the partition) that has OpType CRy, if the two qubits it's acting on are at distance 2 on the architecture, decompose the gate using BRIDGE gates." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first restriction is to only have a single gate from the first slice - we can achieve this by setting both the maximum depth and size parameters to 1." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second restriction is for the gate to have OpType CRy and for the qubits to be at distance 2 - we can check this restriction in a `distance2_CRy_check` method." ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_check(circuit: Circuit, architecture: Architecture) -> bool:\n", " if circuit.n_gates != 1:\n", " raise ValueError(\n", " \"Circuit for CRy check should only have 1 gate, please change parameters of method declaration.\"\n", " )\n", " command = circuit.get_commands()[0]\n", " if command.op.type == OpType.CRy:\n", " # Architecture stores qubits under `Node` identifier\n", " n0 = Node(command.qubits[0].reg_name, command.qubits[0].index)\n", " n1 = Node(command.qubits[1].reg_name, command.qubits[1].index)\n", " # qubits could not be placed in circuit, so check before finding distance\n", " if n0 in architecture.nodes and n1 in architecture.nodes:\n", " # means we can run the decomposition\n", " if architecture.get_distance(n0, n1) == 2:\n", " return True\n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `distance2_CRy_check` confirms whether the required restrictions are respected. Given this, if the `distance2_CRy_decomp` method is called we know where to add the decomposition." ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_decomp(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " worthwhile_substitution = distance2_CRy_check(circuit, architecture)\n", " if worthwhile_substitution == False:\n", " return (False, Circuit(), {}, {})\n", " command = circuit.get_commands()[0]\n", " qubits = command.qubits\n", " # Architecture stores qubits under `Node` identifier\n", " n0 = Node(qubits[0].reg_name, qubits[0].index)\n", " n1 = Node(qubits[1].reg_name, qubits[1].index)\n", "\n", " # need to find connecting node for decomposition\n", " adjacent_nodes_0 = architecture.get_adjacent_nodes(n0)\n", " adjacent_nodes_1 = architecture.get_adjacent_nodes(n1)\n", " connecting_nodes = adjacent_nodes_0.intersection(adjacent_nodes_1)\n", " if len(connecting_nodes) == 0:\n", " raise ValueError(\"Qubits for distance-2 CRy decomp are not at distance 2.\")\n", " connecting_node = connecting_nodes.pop()\n", " c = Circuit()\n", "\n", " # the \"relabelling map\" empty, and the permutation map is qubit to qubit, so add here\n", " permutation_map = dict()\n", " for q in circuit.qubits:\n", " permutation_map[q] = q\n", " c.add_qubit(q)\n", " # rotation, can assume only parameter as CRy\n", " angle = command.op.params[0]\n", " c.Ry(angle, qubits[1])\n", " # distance-2 CX decomp\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " # rotation\n", " c.Ry(-1 * angle, qubits[1])\n", " # distance-2 CX decomp\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", "\n", " # the \"relabelling map\" is just qubit to qubit\n", " return (True, c, {}, permutation_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before turning this into a `RoutingMethod` we can try it ourselves." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CRy(0.6)\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(2, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(8, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test_c = Circuit(4)\n", "test_c.CRy(0.6, 0, 2)\n", "place_with_map(test_c, naive_map)\n", "Graph(test_c).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, our circuit has one CRy gate at distance two away." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "print(distance2_CRy_check(test_c, id_architecture))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our method returns True, as expected! We should also test cases where it returns errors or False." ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n" ] } ], "source": [ "test_c_false = Circuit(4)\n", "test_c_false.CRy(0.4, 0, 1)\n", "place_with_map(test_c_false, naive_map)\n", "print(distance2_CRy_check(test_c_false, id_architecture))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error reached!\n" ] } ], "source": [ "test_c_error = Circuit(4)\n", "test_c_error.CRy(0.6, 0, 2)\n", "test_c_error.CRy(0.4, 0, 1)\n", "place_with_map(test_c_error, naive_map)\n", "try:\n", " distance2_CRy_check(test_c_error, id_architecture)\n", "except ValueError:\n", " print(\"Error reached!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Does the decomposition work?" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "test_c = Circuit(4)\n", "test_c.CRy(0.6, 0, 2)\n", "place_with_map(test_c, naive_map)\n", "decomp = distance2_CRy_decomp(test_c, id_architecture)\n", "display.render_circuit_jupyter(decomp[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Great! Our check function and decomposition method are both working. Lets wrap them into a `RoutingMethodCircuit` and try them out." ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import RoutingMethodCircuit" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "cry_rmc = RoutingMethodCircuit(distance2_CRy_decomp, 1, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use our original `MappingManager` object as it is defined for the same architecture. Lets try it out on a range of circumstances." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we pass it a full CX circuit without `LexiRouteRoutingMethod`, we should find that `MappingManager` throws an error, as none of the passed methods can route for the given circuit." ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error reached!\n" ] } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "place_with_map(c, naive_map)\n", "try:\n", " mapping_manager.route_circuit(c, [cry_rmc])\n", "except RuntimeError:\n", " print(\"Error reached!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we can add `LexiRouteRoutingMethod` on top:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "place_with_map(c, naive_map)\n", "mapping_manager.route_circuit(c, [cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However as there are no CRy gates our new method is unused. We can add one:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CRy(0.6, 0, 2)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This time we can see our decomposition! If we reorder the methods though `LexiRouteRoutingMethod` is checked first (and returns True), so our new method is unused. The order is important!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, lets see what happens if the gate is not at the right distance initially." ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CRy(0.6, 0, 3)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Above a SWAP gate is inserted by `LexiRouteRoutingMethod` before anything else." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For anyone interested, a simple extension exercise could be to extend this to additionally work for distance-2 CRx and CRz. Alternatively one could improve on the method itself - this approach always decomposes a CRy at distance-2, but is this a good idea?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Also note that higher performance solutions are coded straight into the TKET c++ codebase. This provides advantages, including that Circuit construction and substitution is unnecessary (as with python) as the circuit can be directly modified, however the ability to produce prototypes at the python level is very helpful. If you have a great python implementation but are finding some runtime bottlenecks, why not try implementing it straight into TKET (the code is open source at https://github.com/Quantinuum/tket)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides the `LexiRouteRoutingMethod()` and the `LexiLabellingMethod()` there are other routing methods in pytket, such as the `AASRouteRoutingMethod()` and the corresponding `AASLabellingMethod()`, which are used to route phase-polynomial boxes using architecture-aware synthesis. Usually circuits contain non-phase-polynomial operations as well, so it is a good idea to combine them with the `LexiRouteRoutingMethod()`, as in the following example:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import AASRouteRoutingMethod, AASLabellingMethod\n", "from pytket.circuit import PhasePolyBox, Qubit\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = Circuit(3, 3)\n", "n_qb = 3\n", "qubit_indices = {Qubit(0): 0, Qubit(1): 1, Qubit(2): 2}\n", "phase_polynomial = {(True, False, True): 0.333, (False, False, True): 0.05}\n", "linear_transformation = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])\n", "p_box = PhasePolyBox(n_qb, qubit_indices, phase_polynomial, linear_transformation)\n", "c.add_phasepolybox(p_box, [0, 1, 2])\n", "c.CX(0, 1).CX(0, 2).CX(1, 2)\n", "display.render_circuit_jupyter(c)\n", "nodes = [Node(\"test\", 0), Node(\"test\", 1), Node(\"test\", 2)]\n", "arch = Architecture([[nodes[0], nodes[1]], [nodes[1], nodes[2]]])\n", "mm = MappingManager(arch)\n", "mm.route_circuit(\n", " c,\n", " [\n", " AASRouteRoutingMethod(1),\n", " LexiLabellingMethod(),\n", " LexiRouteRoutingMethod(),\n", " AASLabellingMethod(),\n", " ],\n", ")\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case the order of the methods is not very relevant, because in each step of the routing only one of the methods is suitable. In the first part of the circuit the mapping is done without inserting swaps by the AAS method; in the second part one swap gate is added to the circuit." ] } ], "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.11.2" } }, "nbformat": 4, "nbformat_minor": 2 }