{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "## **!!!_8_Suitability of NNF for a hyperbolic paraboloid**"
      ],
      "metadata": {
        "id": "jZ1N5GsApnP1"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import sys\n",
        "!{sys.executable} -m pip install --upgrade pyod\n",
        "\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.optim as optim\n",
        "import math\n",
        "from matplotlib.patches import Patch\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 1. Generation of the full hyperbolic paraboloid dataset with an outlier\n",
        "#    Features: x1, x2 ; target variable: y = x1^2 - x2^2\n",
        "# ------------------------------------------------------------\n",
        "x1 = np.arange(-1.0, 1.05, 0.1)\n",
        "x2 = np.arange(-1.0, 1.05, 0.1)\n",
        "X1grid, X2grid = np.meshgrid(x1, x2)\n",
        "Ygrid = X1grid**2 - X2grid**2\n",
        "\n",
        "# Inject outlier at point (x1=0, x2=0) with value y = 0.45\n",
        "mask_out = (np.abs(X1grid) < 1e-10) & (np.abs(X2grid) < 1e-10)\n",
        "Ygrid[mask_out] = 0.45\n",
        "\n",
        "points_full = np.column_stack((X1grid.ravel(), X2grid.ravel(), Ygrid.ravel()))\n",
        "labels_full = np.zeros(len(points_full), dtype=int)\n",
        "labels_full[np.where(mask_out.ravel())[0]] = 1\n",
        "\n",
        "print(\"=\"*80)\n",
        "print(\"FULL DATASET (441 points, one outlier)\")\n",
        "print(\"=\"*80)\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 2. Random removal of 90% of normal points\n",
        "# ------------------------------------------------------------\n",
        "np.random.seed(42)\n",
        "normal_indices = np.where(labels_full == 0)[0]\n",
        "n_remove = int(0.90 * len(normal_indices))\n",
        "remove_idx = np.random.choice(normal_indices, size=n_remove, replace=False)\n",
        "keep_mask = np.ones(len(points_full), dtype=bool)\n",
        "keep_mask[remove_idx] = False\n",
        "points = points_full[keep_mask]\n",
        "labels_true = labels_full[keep_mask]\n",
        "\n",
        "print(f\"Removed normal points: {n_remove}\")\n",
        "print(f\"Remaining points: {len(points)} (outliers: {labels_true.sum()})\")\n",
        "print(f\"Outlier percentage: {labels_true.sum()/len(points)*100:.2f}%\")\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 3. Data preparation for NNF: inputs (x1,x2) -> output (y)\n",
        "# ------------------------------------------------------------\n",
        "X_nnf = points[:, :2]   # x1, x2\n",
        "y_nnf = points[:, 2]    # y\n",
        "\n",
        "Q = X_nnf.shape[0]\n",
        "N_x = X_nnf.shape[1]   # 2\n",
        "N_y = 1\n",
        "\n",
        "# Scaling to [-1, 1]\n",
        "def scale_to_minus1_1(data):\n",
        "    min_val = data.min(axis=0)\n",
        "    max_val = data.max(axis=0)\n",
        "    range_val = max_val - min_val\n",
        "    range_val[range_val == 0] = 1.0\n",
        "    scaled = 2.0 * (data - min_val) / range_val - 1.0\n",
        "    return scaled, min_val, max_val\n",
        "\n",
        "X_scaled_nnf, x_min, x_max = scale_to_minus1_1(X_nnf)\n",
        "y_scaled_nnf, y_min, y_max = scale_to_minus1_1(y_nnf.reshape(-1, 1))\n",
        "\n",
        "X_tensor = torch.tensor(X_scaled_nnf, dtype=torch.float32)\n",
        "y_tensor = torch.tensor(y_scaled_nnf, dtype=torch.float32)\n",
        "\n",
        "# Index of the true outlier (zero-based)\n",
        "true_outlier_idx = np.where(labels_true == 1)[0][0]\n",
        "print(f\"The true outlier is at index {true_outlier_idx+1} (zero-based index {true_outlier_idx})\")\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 4. Calculation of hidden layer neuron count bounds using empirical formulas\n",
        "# ------------------------------------------------------------\n",
        "log2q = math.log2(Q)\n",
        "N_min = (N_y * Q) / ((1 + log2q) * (N_x + N_y))\n",
        "N_max = (N_y / (N_x + N_y)) * ((Q / N_x + 1) * (N_x + N_y + 1) + 1)\n",
        "\n",
        "print(\"\\n\" + \"=\"*50)\n",
        "print(f\"Q = {Q}, N_x = {N_x}, N_y = {N_y}\")\n",
        "print(f\"N_min = {N_min:.4f}, N_max = {N_max:.4f}\")\n",
        "print(\"=\"*50 + \"\\n\")\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 5. Testing for N from 0 to 80, collecting the list of successful N\n",
        "# ------------------------------------------------------------\n",
        "N_range = range(0, 81)  # 0 .. 80\n",
        "success = []  # N values for which the error on the outlier is maximal\n",
        "\n",
        "for N in N_range:\n",
        "    torch.manual_seed(42)  # fix for reproducibility\n",
        "\n",
        "    if N == 0:\n",
        "        # No hidden layer – simple linear regression\n",
        "        model = nn.Sequential(\n",
        "            nn.Linear(N_x, N_y)\n",
        "        )\n",
        "    else:\n",
        "        # Two-layer network with tanh\n",
        "        model = nn.Sequential(\n",
        "            nn.Linear(N_x, N),\n",
        "            nn.Tanh(),\n",
        "            nn.Linear(N, N_y)\n",
        "        )\n",
        "\n",
        "    criterion = nn.MSELoss()\n",
        "    optimizer = optim.Rprop(model.parameters(), lr=0.01)\n",
        "\n",
        "    # Training for 1000 epochs on all data\n",
        "    model.train()\n",
        "    for epoch in range(1000):\n",
        "        optimizer.zero_grad()\n",
        "        outputs = model(X_tensor)\n",
        "        loss = criterion(outputs, y_tensor)\n",
        "        loss.backward()\n",
        "        optimizer.step()\n",
        "\n",
        "    # Compute MSE for each sample\n",
        "    model.eval()\n",
        "    with torch.no_grad():\n",
        "        predictions = model(X_tensor).numpy().flatten()\n",
        "        errors = (predictions - y_scaled_nnf.flatten()) ** 2\n",
        "\n",
        "    outlier_error = errors[true_outlier_idx]\n",
        "    max_among_others = np.max(np.delete(errors, true_outlier_idx))\n",
        "    if outlier_error > max_among_others:\n",
        "        success.append(N)\n",
        "\n",
        "    if N % 10 == 0:\n",
        "        print(f\"Processed N = {N}\")\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 6. Output the list of N that satisfy the condition\n",
        "# ------------------------------------------------------------\n",
        "print(\"\\n\" + \"=\"*80)\n",
        "print(\"Values of N for which the error on the true outlier exceeds all others:\")\n",
        "print(success)\n",
        "\n",
        "# ------------------------------------------------------------\n",
        "# 7. Suitability histogram with equal bar heights (without Y-axis)\n",
        "#    Bar height reduced by half (0.5)\n",
        "# ------------------------------------------------------------\n",
        "plt.figure(figsize=(16, 4))\n",
        "N_list = list(N_range)\n",
        "# All bars have equal height = 0.5 (reduced by half)\n",
        "heights = [0.5] * len(N_list)\n",
        "colors = ['green' if n in success else 'red' for n in N_list]\n",
        "\n",
        "bars = plt.bar(N_list, heights, color=colors, width=0.8)\n",
        "plt.xlabel('Number of hidden layer neurons $N$')\n",
        "plt.ylabel('')                # remove Y-axis label\n",
        "plt.yticks([])                # remove Y-axis ticks\n",
        "plt.ylim(0, 0.7)              # small margin for the legend\n",
        "ax = plt.gca()\n",
        "ax.spines['left'].set_visible(False)   # hide left border\n",
        "ax.tick_params(left=False)             # remove ticks\n",
        "\n",
        "plt.xticks(range(0, 81, 5))\n",
        "plt.grid(axis='y', linestyle='--', alpha=0.7)\n",
        "\n",
        "# Legend\n",
        "legend_elements = [Patch(facecolor='green', label='Neural network is suitable for outlier detection'),\n",
        "                   Patch(facecolor='red', label='Neural network is not suitable for outlier detection')]\n",
        "plt.legend(handles=legend_elements, loc='upper right')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "h7yHRFrco_bM",
        "outputId": "eae0fbdb-0b7b-4ae6-9cb9-097648272f6a"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Requirement already satisfied: pyod in /usr/local/lib/python3.12/dist-packages (2.1.0)\n",
            "Requirement already satisfied: joblib in /usr/local/lib/python3.12/dist-packages (from pyod) (1.5.3)\n",
            "Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (from pyod) (3.10.0)\n",
            "Requirement already satisfied: numpy>=1.19 in /usr/local/lib/python3.12/dist-packages (from pyod) (2.0.2)\n",
            "Requirement already satisfied: numba>=0.51 in /usr/local/lib/python3.12/dist-packages (from pyod) (0.60.0)\n",
            "Requirement already satisfied: scipy>=1.5.1 in /usr/local/lib/python3.12/dist-packages (from pyod) (1.16.3)\n",
            "Requirement already satisfied: scikit-learn>=0.22.0 in /usr/local/lib/python3.12/dist-packages (from pyod) (1.6.1)\n",
            "Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /usr/local/lib/python3.12/dist-packages (from numba>=0.51->pyod) (0.43.0)\n",
            "Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.12/dist-packages (from scikit-learn>=0.22.0->pyod) (3.6.0)\n",
            "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (1.3.3)\n",
            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (0.12.1)\n",
            "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (4.62.1)\n",
            "Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (1.5.0)\n",
            "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (26.0)\n",
            "Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (11.3.0)\n",
            "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (3.3.2)\n",
            "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.12/dist-packages (from matplotlib->pyod) (2.9.0.post0)\n",
            "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.7->matplotlib->pyod) (1.17.0)\n",
            "================================================================================\n",
            "FULL DATASET (441 points, one outlier)\n",
            "================================================================================\n",
            "Removed normal points: 396\n",
            "Remaining points: 45 (outliers: 1)\n",
            "Outlier percentage: 2.22%\n",
            "The true outlier is at index 24 (zero-based index 23)\n",
            "\n",
            "==================================================\n",
            "Q = 45, N_x = 2, N_y = 1\n",
            "N_min = 2.3106, N_max = 31.6667\n",
            "==================================================\n",
            "\n",
            "Processed N = 0\n",
            "Processed N = 10\n",
            "Processed N = 20\n",
            "Processed N = 30\n",
            "Processed N = 40\n",
            "Processed N = 50\n",
            "Processed N = 60\n",
            "Processed N = 70\n",
            "Processed N = 80\n",
            "\n",
            "================================================================================\n",
            "Values of N for which the error on the true outlier exceeds all others:\n",
            "[2, 3, 4, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 19, 20, 28, 53, 63]\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 1600x400 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAABjUAAAGGCAYAAAAzegNcAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUQFJREFUeJzt3Xm8VXW9P/7XYQZlFBRQBJxREcV5hIRELVMxp8wgNcucUDHtmgOYgibldNOu3UTLq5ZzmvMVcgoVxZEQCcNulGWgKCHKWb8//LG/HjnAAc7xsPT5fDx4PNh7r/VZ7/Xen71h79dea1UVRVEEAAAAAABgNdeksQsAAAAAAACoC6EGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlEKzuixUFEXmzZvX0LUAAAAAAACfQ4tziO7du6dJk6Ufj1GnUGPevHlp3759vRUHAAAAAADwSW+88UbWW2+9pT5ep1Cjbdu2efvtt+utKAAAAAAAgMXeeeed9OjRI23btl3mcnUKNaqqqtKuXbt6KQwAAAAAAKA2VVVVy3zchcIBAAAAAIBSEGoAAAAAAAClINQAAAAAAABKoU7X1AAAAACAj6uurs7ChQsbuwwASqJ58+Zp2rTpKo8j1AAAAABghSxcuDAzZ85MdXV1Y5cCQIl06NAhXbt2Xe7FwJdFqAEAAABAnRVFkdmzZ6dp06bp0aNHmjRxdnMAlq0oisyfPz9vvvlmkqRbt24rPZZQAwAAAIA6+/DDDzN//vx07949bdq0aexyACiJ1q1bJ0nefPPNrL322it9KipROgAAAAB1tmjRoiRJixYtGrkSAMpmcRj+wQcfrPQYQg0AAAAAVtiqnA8dgM+n+vi3Q6gBAAAAAACUglADAAAAAFYTAwcOzIgRIxq7jAbz+uuvp6qqKlOmTKnzOsOHD88BBxzQYDUty/jx49OhQ4dPZZzzzjsvW2+99SptpyiKHHvssenUqdMK97kxfbI/9dGLFVFVVZU77rjjU9veivi0e1EGLhQOAAAAwCqrGvXpno6qOLdYoeWHDx+e6667LmPGjMmZZ55Zuf+OO+7IgQcemKJYsfHKbMKECfnCF76QOXPm1MsX9g3tsssua7Tn59BDD82+++5buX3eeefljjvuWG3Dgvvuuy/jx4/PhAkTssEGG6Rz586NXdISevXqlREjRiwzvBs5cmROPPHET6+oFTR8+PDMnTu33oOQqqqq3H777TVCvNW9F43BkRoAAAAAfC60atUqF110UebMmfOpb3tVLor7WbFw4cKVWq99+/aNFr60bt06a6+9dqNse2XMmDEj3bp1yy677JKuXbumWbMV/017URT58MMPG6C6ultzzTWz1lprrdIYn5XXXH304rNGqAEAAADA58LgwYPTtWvXjBkzZpnLPfbYY9l9993TunXr9OjRIyeddFLee++9yuO1naqmQ4cOGT9+fJL/d4qlm2++OQMGDEirVq1yww035K233srhhx+eddddN23atEnfvn1z4403rtA+LD4VzS9/+cv06tUr7du3z2GHHZZ58+ZVlqmurs6YMWPSu3fvtG7dOv369cstt9xSqe0LX/hCkqRjx46pqqrK8OHDc/fdd6dDhw5ZtGhRkmTKlCmpqqqqcVTLMccck69//euV27feemu22GKLtGzZMr169cq4ceNq1NqrV6+cf/75+cY3vpF27drl2GOPXWJ/Fi1alKOOOiqbbbZZZs2aVes+f/L0U7fcckv69u2b1q1bZ6211srgwYNrPD8fN2fOnBxxxBHp0qVLWrdunY033jjXXnttko+OWKmqqsrcuXMryy/e79dffz1JzdMijR8/PqNGjcrzzz+fqqqqVFVVVZ7zH//4x+nbt2/WWGON9OjRI9/97nfz7rvvLlHPHXfckY033jitWrXKkCFD8sYbb9Ra92I///nP06dPn7Rq1SqbbbZZfvrTny512eHDh+fEE0/MrFmzUlVVlV69eiVJ3n///Zx00klZe+2106pVq+y22255+umnK+st7sO9996bbbfdNi1btsxjjz1W6zZefPHF7LnnnpXeH3vssTX2s7bTpx1wwAEZPnx45fE///nPOeWUUyo9rE1tp1xaVi+W9pqrzfTp07PHHnukVatW2XzzzfPggw8uscwbb7yRQw45JB06dEinTp2y//77V+bEeeedl+uuuy533nlnZR8mTJiw3PUW+8UvflF53XTr1i0nnHBCklSerwMPPLDG8/fJXlRXV2f06NFZb7310rJly2y99da57777lujFbbfdli984Qtp06ZN+vXrlyeffLLWfpSRUAMAAACAz4WmTZvmwgsvzBVXXJG//OUvtS4zY8aM7L333jnooIPywgsv5Oabb85jjz1W+eJxRZx55pk5+eSTM3Xq1AwZMiQLFizItttum3vuuScvvfRSjj322Bx55JF56qmnVmjcGTNm5I477sjdd9+du+++OxMnTszYsWMrj48ZMybXX399rr766rz88ss55ZRT8vWvfz0TJ05Mjx49cuuttyZJpk2bltmzZ+eyyy7L7rvvnnnz5uW5555LkkycODGdO3eufFm7+L6BAwcmSSZPnpxDDjkkhx12WF588cWcd955Ofvssytf8i92ySWXpF+/fnnuuedy9tln13js/fffz8EHH5wpU6bk0Ucfzfrrr7/cfZ89e3YOP/zwHHXUUZk6dWomTJiQoUOHLvX0VGeffXZeeeWV3HvvvZk6dWquuuqqlT4l06GHHprTTjstW2yxRWbPnp3Zs2fn0EMPTZI0adIkl19+eV5++eVcd911+d///d9873vfq7H+/Pnzc8EFF+T666/P448/nrlz5+awww5b6vZuuOGGnHPOObngggsyderUXHjhhTn77LNz3XXX1br8ZZddVvmye/bs2ZXg4nvf+15uvfXWXHfddXn22Wez0UYbZciQIfnXv/5VY/0zzzwzY8eOzdSpU7PVVlstMf57772XIUOGpGPHjnn66afzm9/8Jg899NAKvTZuu+22rLfeehk9enSlh3VR11588jX3SdXV1Rk6dGhatGiRSZMm5eqrr84ZZ5xRY5kPPvggQ4YMSdu2bfPoo4/m8ccfz5prrpm99947CxcuzMiRI3PIIYdk7733ruzDLrvsstz1kuSqq67K8ccfn2OPPTYvvvhi7rrrrmy00UZJUnm+rr322hrP3ydddtllGTduXC655JK88MILGTJkSL7yla9k+vTpNZY766yzMnLkyEyZMiWbbLJJDj/88EY/Aqe+uKYGAAAAAJ8bBx54YLbeeuuce+65+e///u8lHh8zZkyOOOKIyq/NN95441x++eUZMGBArrrqqrRq1arO2xoxYkSGDh1a476RI0dW/n7iiSfm/vvvz69//evssMMOdR63uro648ePT9u2bZMkRx55ZB5++OFccMEFef/993PhhRfmoYceys4775wk2WCDDfLYY4/lZz/7WQYMGJBOnTolSdZee+0ap3XaeuutM2HChGy33XaZMGFCTjnllIwaNSrvvvtu3n777bz22msZMGBAko+OTBg0aFAlqNhkk03yyiuv5Ec/+lHlV/lJsueee+a0006r3F78q/V33303X/rSl/L+++/nkUceSfv27eu077Nnz86HH36YoUOHpmfPnkmSvn37LnX5WbNmZZtttsl2222X5P/9Gn5ltG7dOmuuuWaaNWuWrl271njs40cn9OrVKz/84Q/zne98p8bRBB988EGuvPLK7LjjjkmS6667Ln369MlTTz1V6/N/7rnnZty4cZU51Lt377zyyiv52c9+lmHDhi2xfPv27dO2bds0bdq0Ut97772Xq666KuPHj88+++yTJLnmmmvy4IMP5r//+79z+umnV9YfPXp0vvjFLy51///nf/4nCxYsyPXXX5811lgjSXLllVdmv/32y0UXXZR11llnmf1Lkk6dOqVp06Zp27btEj1clrr2orbX3Mc99NBD+eMf/5j7778/3bt3T5JceOGFld4kyc0335zq6ur8/Oc/rxxJcu2116ZDhw6ZMGFC9tprr7Ru3Trvv/9+jX341a9+tdz1fvjDH+a0007LySefXFlv++23T5J06dIlyUdHfS2rN5dccknOOOOMSiB20UUX5ZFHHsmll16a//zP/6wsN3LkyHzpS19KkowaNSpbbLFFXnvttWy22WZLHbssHKkBAAAAwOfKRRddlOuuuy5Tp05d4rHnn38+48ePz5prrln5M2TIkFRXV2fmzJkrtJ3FX6QvtmjRopx//vnp27dvOnXqlDXXXDP333//Uk+7tDS9evWqBBpJ0q1bt7z55ptJktdeey3z58/PF7/4xRr7cP3112fGjBnLHHfAgAGZMGFCiqLIo48+mqFDh6ZPnz557LHHMnHixHTv3j0bb7xxkmTq1KnZdddda6y/6667Zvr06ZVTWNXWg8UOP/zwvPfee3nggQfqHGgkSb9+/TJo0KD07ds3Bx98cK655pplXiPluOOOy0033ZStt9463/ve9/LEE0/UeVsr4qGHHsqgQYOy7rrrpm3btjnyyCPz1ltvZf78+ZVlmjVrVvkCO0k222yzdOjQodZ5+N5772XGjBk5+uijazyPP/zhD5f7PH7cjBkz8sEHH9R4rpo3b54ddthhie0u7blabOrUqenXr18l0Eg+es6rq6szbdq0Ote0olakF3XZhx49elQCjSSV8G+x559/Pq+99lratm1b2VanTp2yYMGCZfZ+eeu9+eab+etf/5pBgwatRBc+8s477+Svf/1rra+9Tz6fHz/aplu3bklSeZ8oO0dqAAAAAPC5sscee2TIkCH5/ve/X+OoguSjIwi+/e1v56STTlpivcWnR6qqqlridEe1XZT441/+JsmPfvSjXHbZZbn00ksr118YMWLECl9Au3nz5jVuV1VVpbq6ulJ/ktxzzz1Zd911ayzXsmXLZY47cODA/OIXv8jzzz+f5s2bZ7PNNsvAgQMzYcKEzJkzp3KUxor4ZA8W23ffffOrX/0qTz75ZPbcc886j9e0adM8+OCDeeKJJ/LAAw/kiiuuyFlnnZVJkyald+/eSyy/zz775M9//nN+97vf5cEHH8ygQYNy/PHH55JLLkmTJh/93vvjz+XKXFz69ddfz5e//OUcd9xxueCCC9KpU6c89thjOfroo7Nw4cK0adNmhcdc/Dxec801lSM7FmvatOkKj1cXS3uuVkSTJk3q9NpYESvSi/rYh3fffTfbbrttrdfkWHw0xcqst3i+fVo+/j6x+MiRxe8TZedIDQAAAAA+d8aOHZvf/va3S1w8t3///nnllVey0UYbLfGnRYsWST76gvLj1wKYPn16jV/kL83jjz+e/fffP1//+tfTr1+/bLDBBnn11Vfrdb8233zztGzZMrNmzVqi/h49eiRJZT8+fkRFksp1NX7yk59UAozFocaECRMq19NIkj59+uTxxx9fYv822WSTOn3pftxxx2Xs2LH5yle+kokTJ67QPlZVVWXXXXfNqFGj8txzz6VFixa5/fbbl7p8ly5dMmzYsPzqV7/KpZdemv/6r/+q3J+kxnM5ZcqUZW67RYsWS/Rt8uTJqa6uzrhx47LTTjtlk002yV//+tcl1v3www/zzDPPVG5PmzYtc+fOTZ8+fZZYdp111kn37t3zpz/9aYnnsbbwZmk23HDDtGjRosZz9cEHH+Tpp5/O5ptvXudxko+e8+eff77GRdkff/zxNGnSJJtuummSJV8bixYtyksvvVRjnNp6uCz11YvF+/DGG2/UqPEPf/hDjWX69++f6dOnZ+21115ie4uPKqptH5a3Xtu2bdOrV688/PDDS62vefPmy+xNu3bt0r1791pfeyv6fJaZUAMAAACAz52+ffvmiCOOyOWXX17j/jPOOCNPPPFETjjhhEyZMiXTp0/PnXfeWeNiyHvuuWeuvPLKPPfcc3nmmWfyne98Z4mjJ2qz8cYbV44ymDp1ar797W/n73//e73uV9u2bTNy5Miccsopue666zJjxow8++yzueKKKyoXVe7Zs2eqqqpy99135x//+Efll/AdO3bMVlttlRtuuKESYOyxxx559tln8+qrr9Y4UuO0007Lww8/nPPPPz+vvvpqrrvuulx55ZU1rhmyPCeeeGJ++MMf5stf/nIee+yxOq0zadKkXHjhhXnmmWcya9as3HbbbfnHP/5RazCQJOecc07uvPPOvPbaa3n55Zdz9913V5ZdHPScd955mT59eu65556MGzdumdvv1atXZs6cmSlTpuSf//xn3n///Wy00Ub54IMPcsUVV+RPf/pTfvnLX+bqq69eYt3mzZvnxBNPzKRJkzJ58uQMHz48O+2001KvpzJq1KiMGTMml19+eV599dW8+OKLufbaa/PjH/+4Tr1KPjpy4bjjjsvpp5+e++67L6+88kq+9a1vZf78+Tn66KPrPE6SHHHEEWnVqlWGDRuWl156KY888khOPPHEHHnkkZXraey555655557cs899+SPf/xjjjvuuMydO7fGOL169crvf//7/N///V/++c9/1mnb9dGLJBk8eHA22WSTDBs2LM8//3weffTRnHXWWUvsZ+fOnbP//vvn0UcfzcyZMzNhwoScdNJJ+ctf/lLZhxdeeCHTpk3LP//5z3zwwQd1Wu+8887LuHHjcvnll2f69OmV1+bHe/Pwww/nb3/721JPq3b66afnoosuys0335xp06blzDPPzJQpU2pcp+OzTqgBAAAAwOfS6NGjlzgdy1ZbbZWJEyfm1Vdfze67755tttkm55xzTo1z8I8bNy49evTI7rvvnq997WsZOXJknU4x9IMf/CD9+/fPkCFDMnDgwHTt2jUHHHBAfe9Wzj///Jx99tkZM2ZM+vTpk7333jv33HNP5Vft6667bkaNGpUzzzwz66yzTo3AZsCAAVm0aFEl1OjUqVM233zzdO3atfJr/OSjX6X/+te/zk033ZQtt9wy55xzTkaPHr3E6byWZ8SIERk1alT23XffOl3vol27dvn973+ffffdN5tsskl+8IMfZNy4cTUu9PxxLVq0yPe///1stdVW2WOPPdK0adPcdNNNST4KGW688cb88Y9/zFZbbZWLLrooP/zhD5e5/YMOOih77713vvCFL6RLly658cYb069fv/z4xz/ORRddlC233DI33HBDxowZs8S6bdq0yRlnnJGvfe1r2XXXXbPmmmvm5ptvXuq2jjnmmPz85z/Ptddem759+2bAgAEZP378Ch+dMHbs2Bx00EE58sgj079//7z22mu5//7707FjxxUap02bNrn//vvzr3/9K9tvv32++tWvZtCgQbnyyisryxx11FEZNmxYvvGNb2TAgAHZYIMN8oUvfKHGOKNHj87rr7+eDTfccJmnc/q4+upFkyZNcvvtt+ff//53dthhhxxzzDG54IILltjP3//+91l//fUr15U5+uijs2DBgrRr1y5J8q1vfSubbrpptttuu3Tp0iWPP/54ndYbNmxYLr300vz0pz/NFltskS9/+cuZPn16Zdvjxo3Lgw8+mB49emSbbbapdR9OOumknHrqqTnttNPSt2/f3Hfffbnrrrsq17v5PKgqPnmSMwAAAABYigULFmTmzJnp3bt3WrVq1djlAFAiy/o35J133kn79u3z9ttvV4Kg2jhSAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAVhMDBw7MiBEjGruMBvP666+nqqoqU6ZMqfM6w4cPzwEHHNBgNa0uJkyYkKqqqsydO7fBxxk/fnw6dOiwSttJkvPOOy/rrLNOqqqqcscdd6zyeJ+GT/anvnpRV7169cqll176qW1vRXzavVhZQg0AAAAAPvOGDx+eqqqqjB07tsb9d9xxR6qqqhqpqsZRX1+ef1ouu+yyjB8/vlFr+DS+tN9ll10ye/bstG/fPsnq/wXz1KlTM2rUqPzsZz/L7Nmzs88++zR2SUuoS0h46KGH5tVXX/10CloJ5513Xrbeeut6H7e2cGV178ViQg0AAAAAVl1V1af7ZyW0atUqF110UebMmVPPO798H3zwwae+zdXNwoULV2q99u3br9Zf7teXFi1apGvXrqUJ2WbMmJEk2X///dO1a9e0bNlypcZp7NdG69ats/baa6/SGI29D/WlPnrxaRBqAAAAAPC5MHjw4HTt2jVjxoxZ5nKPPfZYdt9997Ru3To9evTISSedlPfee6/yeG2/2u/QoUPlaILFp1i6+eabM2DAgLRq1So33HBD3nrrrRx++OFZd91106ZNm/Tt2zc33njjCu3D4l9t//KXv0yvXr3Svn37HHbYYZk3b15lmerq6owZMya9e/dO69at069fv9xyyy2V2r7whS8kSTp27JiqqqoMHz48d999dzp06JBFixYlSaZMmZKqqqqceeaZlXGPOeaYfP3rX6/cvvXWW7PFFlukZcuW6dWrV8aNG1ej1l69euX888/PN77xjbRr1y7HHnvsEvuzaNGiHHXUUdlss80ya9asWvf5k6efuuWWW9K3b9+0bt06a621VgYPHlzj+fm4xUelPPzww9luu+3Spk2b7LLLLpk2bVqN5a666qpsuOGGadGiRTbddNP88pe/rLEfSXLggQemqqqqcvuTFi5cmBNOOCHdunVLq1at0rNnz8pcq+20W3Pnzk1VVVUmTJhQo9a5c+dmwoQJ+eY3v5m33347VVVVqaqqynnnnZck+eUvf5ntttsubdu2TdeuXfO1r30tb7755hL1PP7449lqq63SqlWr7LTTTnnppZdqrXuxO++8M/3790+rVq2ywQYbZNSoUfnwww9rXfa8887LfvvtlyRp0qRJJYiprq7O6NGjs95666Vly5bZeuutc99991XWW9prozazZs3K/vvvnzXXXDPt2rXLIYcckr///e+Vx2s7LdmIESMycODAyuMTJ07MZZddVunh66+/vsR2ajsiZnm9qKqqylVXXZWvfOUrWWONNXLBBRfUug9vvvlm9ttvv7Ru3Tq9e/eudV/nzp2bY445Jl26dEm7du2y55575vnnn6/UNmrUqDz//POVfVj8PrOs9Rb77W9/m+233z6tWrVK586dc+CBByb56AiWP//5zznllFMq4y6tF8t6bSzuxc9//vMceOCBadOmTTbeeOPcddddtfajvgg1AAAAAPhcaNq0aS688MJcccUV+ctf/lLrMjNmzMjee++dgw46KC+88EJuvvnmPPbYYznhhBNWeHtnnnlmTj755EydOjVDhgzJggULsu222+aee+7JSy+9lGOPPTZHHnlknnrqqRUad8aMGbnjjjty99135+67787EiRNrnFZrzJgxuf7663P11Vfn5ZdfzimnnJKvf/3rmThxYnr06JFbb701STJt2rTMnj07l112WXbffffMmzcvzz33XJJk4sSJ6dy5c+UL98X3Lf7CePLkyTnkkENy2GGH5cUXX8x5552Xs88+e4nTRF1yySXp169fnnvuuZx99tk1Hnv//fdz8MEHZ8qUKXn00Uez/vrrL3ffZ8+encMPPzxHHXVUpk6dmgkTJmTo0KEpimKZ65111lkZN25cnnnmmTRr1ixHHXVU5bHbb789J598ck477bS89NJL+fa3v51vfvObeeSRR5IkTz/9dJLk2muvzezZsyu3P+nyyy/PXXfdlV//+teZNm1abrjhhqUGIMuzyy675NJLL027du0ye/bszJ49OyNHjkzy0VEB559/fp5//vnccccdef311zN8+PAlxjj99NMzbty4PP300+nSpUv222+/pR5R8Oijj+Yb3/hGTj755Lzyyiv52c9+lvHjxy/1y/qRI0fm2muvTZJKfclHpwobN25cLrnkkrzwwgsZMmRIvvKVr2T69Ok11v/ka+OTqqurs//+++df//pXJk6cmAcffDB/+tOfcuihh9a5h5dddll23nnnfOtb36rU2KNHj+WuV9denHfeeTnwwAPz4osv1phPHzd8+PC88cYbeeSRR3LLLbfkpz/96RIB1MEHH5w333wz9957byZPnpz+/ftn0KBB+de//pVDDz00p512WrbYYovKPizuwbLWS5J77rknBx54YPbdd98899xzefjhh7PDDjskSW677bast956GT16dI3n75OW99pYbNSoUTnkkEPywgsvZN99980RRxxRqaNBFAAAAABQR//+97+LV155pfj3v/9d84Hk0/2zgoYNG1bsv//+RVEUxU477VQcddRRRVEUxe233158/Cuyo48+ujj22GNrrPvoo48WTZo0qexzkuL222+vsUz79u2La6+9tiiKopg5c2aRpLj00kuXW9eXvvSl4rTTTqvcHjBgQHHyyScvdflzzz23aNOmTfHOO+9U7jv99NOLHXfcsSiKoliwYEHRpk2b4oknnqix3tFHH10cfvjhRVEUxSOPPFIkKebMmVNjmf79+xc/+tGPiqIoigMOOKC44IILihYtWhTz5s0r/vKXvxRJildffbUoiqL42te+Vnzxi1+ssf7pp59ebL755pXbPXv2LA444IAayyzuzaOPPloMGjSo2G233Yq5c+cuq0U1nrvJkycXSYrXX399messtnhfH3roocp999xzT5Gk8nzusssuxbe+9a0a6x188MHFvvvuW7ld23P+SSeeeGKx5557FtXV1Us8tni/n3vuucp9c+bMKZIUjzzySI1aFz8v1157bdG+ffvl7uPTTz9dJCnmzZtXY5ybbrqpssxbb71VtG7durj55ptrHXvQoEHFhRdeWGPcX/7yl0W3bt2Wut1PvnaKoii6d+9eXHDBBTXu23777Yvvfve7NfqwvNfGAw88UDRt2rSYNWtW5b6XX365SFI89dRTRVHUnBeLnXzyycWAAQMqt2t7PS2vz3XpRZJixIgRy9yHadOm1ai3KIpi6tSpRZLiJz/5SVEUH723tGvXrliwYEGNdTfccMPiZz/7WVEUH73m+/XrV+Pxuqy38847F0ccccRS6+vZs2eljsU+2Yu6vjZ+8IMfVG6/++67RZLi3nvvrXW7S/03pCiKt99+u0hSvP3220utuyiKwpEaAAAAAHyuXHTRRbnuuusyderUJR57/vnnM378+Ky55pqVP0OGDEl1dXVmzpy5QtvZbrvtatxetGhRzj///PTt2zedOnXKmmuumfvvv3+pp11aml69eqVt27aV2926dav8+vu1117L/Pnz88UvfrHGPlx//fWVayAszYABAzJhwoQURZFHH300Q4cOTZ8+ffLYY49l4sSJ6d69ezbeeOMkH10ketddd62x/q677prp06dXTmFVWw8WO/zww/Pee+/lgQceqFwYuy769euXQYMGpW/fvjn44INzzTXX1OkaKVtttVXl7926dUuSSs+Wti+1zY9lGT58eKZMmZJNN900J510Uh544IEVWr+uJk+enP322y/rr79+2rZtmwEDBiTJEvNo5513rvy9U6dO2XTTTZe6T88//3xGjx5dY84sPsJh/vz5darrnXfeyV//+tc69XJp82KxqVOnpkePHjWOrNh8883ToUOHFX5eVlRde1GXfWjWrFm23Xbbyn2bbbZZjdM7Pf/883n33Xez1lpr1djezJkzl/l6rct6U6ZMyaBBg1ayC/9vH+ryfH789bXGGmukXbt2tZ4Srb40a7CRAQAAAGA1tMcee2TIkCH5/ve/v8Rpe9599918+9vfzkknnbTEeotPj1RVVbXE6Y5qO63PGmusUeP2j370o1x22WW59NJL07dv36yxxhoZMWLECl9Au3nz5jVuV1VVpbq6ulJ/8tGpZ9Zdd90ayy3vQs4DBw7ML37xizz//PNp3rx5NttsswwcODATJkzInDlzKl+er4hP9mCxfffdN7/61a/y5JNPZs8996zzeE2bNs2DDz6YJ554Ig888ECuuOKKnHXWWZk0aVJ69+691PU+3rOPX/+hPvXv3z8zZ87Mvffem4ceeiiHHHJIBg8enFtuuSVNmnz02/KPz5uVubj0e++9lyFDhmTIkCG54YYb0qVLl8yaNStDhgxZ6QuxJx/Nm1GjRmXo0KFLPNaqVauVHndpljYvVkSTJk3q9DpcUXXtRX3sw7vvvptu3brVOM3bYp+8tsWKrte6detVrq+ulvWe1BCEGgAAAAB87owdOzZbb711Nt100xr39+/fP6+88ko22mijpa7bpUuXGuegnz59ep1+zf74449n//33r1xsu7q6Oq+++mo233zzldyLJW2++eZp2bJlZs2atdQQokWLFklS44iKJJXravzkJz+prDtw4MCMHTs2c+bMyWmnnVZZtk+fPnn88ceX2L9NNtkkTZs2XW6dxx13XLbccst85StfyT333LNCgUlVVVV23XXX7LrrrjnnnHPSs2fP3H777Tn11FPrPMbHLd6XYcOG1diXjz8vzZs3X6JftWnXrl0OPfTQHHroofnqV7+avffeO//617/SpUuXJB9df2KbbbZJkhoXDa9NixYtltjmH//4x7z11lsZO3Zs5SiGZ555ptb1//CHP1SCuDlz5uTVV19Nnz59al22f//+mTZt2jLn/fK0a9cu3bt3z+OPP17j+Xz88ccr13Koqz59+uSNN97IG2+8UdnPV155JXPnzq08L126dFni4udTpkyp8QV7bT1cnvroRfLRURkffvhhJk+enO233z7JR9exmTt3bo1t/e1vf0uzZs2Wev2V2vahLutttdVWefjhh/PNb36zzuN+Ul1eG41BqAEAAADA507fvn1zxBFH5PLLL69x/xlnnJGddtopJ5xwQo455pisscYaeeWVV/Lggw/myiuvTJLsueeeufLKK7Pzzjtn0aJFOeOMM5b4pXJtNt5449xyyy154okn0rFjx/z4xz/O3//+93r9grBt27YZOXJkTjnllFRXV2e33XbL22+/nccffzzt2rXLsGHD0rNnz1RVVeXuu+/Ovvvum9atW2fNNddMx44ds9VWW+WGG26o7Osee+yRQw45JB988EGNL6pPO+20bL/99jn//PNz6KGH5sknn8yVV16Zn/70p3Wu9cQTT8yiRYvy5S9/Offee29222235a4zadKkPPzww9lrr72y9tprZ9KkSfnHP/6x1C/r6+L000/PIYcckm222SaDBw/Ob3/729x222156KGHKsv06tUrDz/8cHbddde0bNkyHTt2XGKcH//4x+nWrVu22WabNGnSJL/5zW/StWvXdOjQIU2aNMlOO+2UsWPHpnfv3nnzzTfzgx/8YJl19erVK++++24efvjh9OvXL23atMn666+fFi1a5Iorrsh3vvOdvPTSSzn//PNrXX/06NFZa621ss466+Sss85K586dc8ABB9S67DnnnJMvf/nLWX/99fPVr341TZo0yfPPP5+XXnopP/zhD1eol+eee2423HDDbL311rn22mszZcqU3HDDDXUeI0kGDx5ceY1eeuml+fDDD/Pd7343AwYMqJz2ac8998yPfvSjXH/99dl5553zq1/9Ki+99FIlNEo+6uGkSZPy+uuvZ80110ynTp2Wu+366sWmm26avffeO9/+9rdz1VVXpVmzZhkxYkSNIygGDx6cnXfeOQcccEAuvvjibLLJJvnrX/9aucj3dtttl169emXmzJmZMmVK1ltvvbRt27ZO65177rkZNGhQNtxwwxx22GH58MMP87vf/S5nnHFGpTe///3vc9hhh6Vly5bp3LnzEvtQl9dGY3BNDQAAAAA+l0aPHr3EKVK22mqrTJw4Ma+++mp23333bLPNNjnnnHPSvXv3yjLjxo1Ljx49svvuu+drX/taRo4cmTZt2ix3ez/4wQ/Sv3//DBkyJAMHDkzXrl2X+iXzqjj//PNz9tlnZ8yYMenTp0/23nvv3HPPPZXTM6277roZNWpUzjzzzKyzzjo54YQTKusOGDAgixYtysCBA5N8dC2GzTffPF27dq1xVEv//v3z61//OjfddFO23HLLnHPOORk9evQSp/NanhEjRmTUqFHZd99988QTTyx3+Xbt2uX3v/999t1332yyySb5wQ9+kHHjxmWfffZZoe1+3AEHHJDLLrssl1xySbbYYov87Gc/y7XXXlvpQfLRc/7ggw+mR48eNb40/7i2bdvm4osvznbbbZftt98+r7/+en73u99VTj31i1/8Ih9++GG23XbbjBgxYrlfkO+yyy75zne+k0MPPTRdunTJxRdfnC5dumT8+PH5zW9+k8033zxjx47NJZdcUuv6Y8eOzcknn5xtt902f/vb3/Lb3/62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AAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAAAAAUApCDQAAAAAAoBSEGgAAAAAAQCkINQAAAAAAgFIQagAAAAAAAKUg1AAAAAAAAEpBqAEAAAAAAJSCUAMAAAAAACiFZnVZqCiKzJs3r6Fr+fx5552GGWfByg7zsXHqY4zVcZyVG6RhavksPk8rqyH2qT5qST6bz5PX09LHWblBVn2M1W2c1amW+hpndZozHw20eoyxuo2zOtVSX+OsTrXU1zirUy31Nc7qVEt9jbM61VJf46xOtdTXOKvz/2Hrq5bPwjirUy31Nc7qVMsnx/ks/D+tvsZZnWqpr3FWp1rqa5zVqZb6Gmd1qqW+xlmdaqnPcT5jFr+XF0WxzOWqiuUt8f8P1r59+/qpDAAAAAAAoBZvvPFG1ltvvaU+XqdQw5EaK+edd95Jjx498sYbb6Rdu3aNXc5nkh43LP1tWPrb8PS4Yelvw9LfhqfHDUt/G5b+Njw9blj627D0t+HpccPS34alvw1Pj1fO4hyie/fuadJk6VfOqNPpp6qqqjR/FbRr107/GpgeNyz9bVj62/D0uGHpb8PS34anxw1LfxuW/jY8PW5Y+tuw9Lfh6XHD0t+Gpb8NT49XXF3OGOVC4QAAAAAAQCkINQAAAAAAgFIQajSgli1b5txzz03Lli0bu5TPLD1uWPrbsPS34elxw9LfhqW/DU+PG5b+Niz9bXh63LD0t2Hpb8PT44alvw1LfxueHjesOl0oHAAAAAAAoLE5UgMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoN6D//8z/Tq1evtGrVKjvuuGOeeuqpxi7pM+G8885LVVVVjT+bbbZZY5dVar///e+z3377pXv37qmqqsodd9xR4/GiKHLOOeekW7duad26dQYPHpzp06c3TrEltLz+Dh8+fIk5vffeezdOsSU0ZsyYbL/99mnbtm3WXnvtHHDAAZk2bVqNZRYsWJDjjz8+a621VtZcc80cdNBB+fvf/95IFZdLXfo7cODAJebwd77znUaquHyuuuqqbLXVVmnXrl3atWuXnXfeOffee2/lcfN31Syvv+Zv/Ro7dmyqqqoyYsSIyn3mcP2prb/m8KpZ3mcL83fVLK+/5u+q+7//+798/etfz1prrZXWrVunb9++eeaZZyqP+yy36pbXY5/nVl6vXr2W6F1VVVWOP/74JN6D68Pyeux9eNUsWrQoZ599dnr37p3WrVtnww03zPnnn5+PX8La+3DDEGo0kJtvvjmnnnpqzj333Dz77LPp169fhgwZkjfffLOxS/tM2GKLLTJ79uzKn8cee6yxSyq19957L/369ct//ud/1vr4xRdfnMsvvzxXX311Jk2alDXWWCNDhgzJggULPuVKy2l5/U2Svffeu8acvvHGGz/FCstt4sSJOf744/OHP/whDz74YD744IPstddeee+99yrLnHLKKfntb3+b3/zmN5k4cWL++te/ZujQoY1YdXnUpb9J8q1vfavGHL744osbqeLyWW+99TJ27NhMnjw5zzzzTPbcc8/sv//+efnll5OYv6tqef1NzN/68vTTT+dnP/tZttpqqxr3m8P1Y2n9TczhVbWszxbm76pb3mc383flzZkzJ7vuumuaN2+ee++9N6+88krGjRuXjh07VpbxWW7V1KXHic9zK+vpp5+u0bcHH3wwSXLwwQcn8R5cH5bX48T78Kq46KKLctVVV+XKK6/M1KlTc9FFF+Xiiy/OFVdcUVnG+3ADKWgQO+ywQ3H88cdXbi9atKjo3r17MWbMmEas6rPh3HPPLfr169fYZXxmJSluv/32yu3q6uqia9euxY9+9KPKfXPnzi1atmxZ3HjjjY1QYbl9sr9FURTDhg0r9t9//0ap57PozTffLJIUEydOLIrio/navHnz4je/+U1lmalTpxZJiieffLKxyiytT/a3KIpiwIABxcknn9x4RX0GdezYsfj5z39u/jaQxf0tCvO3vsybN6/YeOONiwcffLBGT83h+rG0/haFObyqlvXZwvxddcv77Gb+rpozzjij2G233Zb6uM9yq255PS4Kn+fq08knn1xsuOGGRXV1tffgBvLxHheF9+FV9aUvfak46qijatw3dOjQ4ogjjiiKwvtwQ3KkRgNYuHBhJk+enMGDB1fua9KkSQYPHpwnn3yyESv77Jg+fXq6d++eDTbYIEcccURmzZrV2CV9Zs2cOTN/+9vfaszn9u3bZ8cddzSf69GECROy9tprZ9NNN81xxx2Xt956q7FLKq233347SdKpU6ckyeTJk/PBBx/UmMObbbZZ1l9/fXN4JXyyv4vdcMMN6dy5c7bccst8//vfz/z58xujvNJbtGhRbrrpprz33nvZeeedzd969sn+Lmb+rrrjjz8+X/rSl2rM1cR7cH1ZWn8XM4dXzdI+W5i/9WN5n93M35V31113ZbvttsvBBx+ctddeO9tss02uueaayuM+y6265fV4MZ/nVt3ChQvzq1/9KkcddVSqqqq8BzeAT/Z4Me/DK2+XXXbJww8/nFdffTVJ8vzzz+exxx7LPvvsk8T7cENq1tgFfBb985//zKJFi7LOOuvUuH+dddbJH//4x0aq6rNjxx13zPjx47Pppptm9uzZGTVqVHbfffe89NJLadu2bWOX95nzt7/9LUlqnc+LH2PV7L333hk6dGh69+6dGTNm5D/+4z+yzz775Mknn0zTpk0bu7xSqa6uzogRI7Lrrrtmyy23TPLRHG7RokU6dOhQY1lzeMXV1t8k+drXvpaePXume/fueeGFF3LGGWdk2rRpue222xqx2nJ58cUXs/POO2fBggVZc801c/vtt2fzzTfPlClTzN96sLT+JuZvfbjpppvy7LPP5umnn17iMe/Bq25Z/U3M4VW1rM8W5u+qW95nN/N31fzpT3/KVVddlVNPPTX/8R//kaeffjonnXRSWrRokWHDhvksVw+W1+PE57n6cscdd2Tu3LkZPnx4Ev+HaAif7HHi/xGr6swzz8w777yTzTbbLE2bNs2iRYtywQUX5IgjjkjiO7WGJNSgdBannUmy1VZbZccdd0zPnj3z61//OkcffXQjVgYr57DDDqv8vW/fvtlqq62y4YYbZsKECRk0aFAjVlY+xx9/fF566SXX2WkgS+vvscceW/l73759061btwwaNCgzZszIhhtu+GmXWUqbbrpppkyZkrfffju33HJLhg0blokTJzZ2WZ8ZS+vv5ptvbv6uojfeeCMnn3xyHnzwwbRq1aqxy/nMqUt/zeFVs6zPFq1bt27Eyj4blvfZzfxdNdXV1dluu+1y4YUXJkm22WabvPTSS7n66qsrX7izaurSY5/n6sd///d/Z5999kn37t0bu5TPrNp67H141fz617/ODTfckP/5n//JFltskSlTpmTEiBHp3r279+EG5vRTDaBz585p2rRp/v73v9e4/+9//3u6du3aSFV9dnXo0CGbbLJJXnvttcYu5TNp8Zw1nz89G2ywQTp37mxOr6ATTjghd999dx555JGst956lfu7du2ahQsXZu7cuTWWN4dXzNL6W5sdd9wxSczhFdCiRYtstNFG2XbbbTNmzJj069cvl112mflbT5bW39qYvytm8uTJefPNN9O/f/80a9YszZo1y8SJE3P55ZenWbNmWWeddczhVbC8/i5atGiJdczhVfPxzxbeg+vf8j67mb8rplu3bpUjDxfr06dP5RRfPsutuuX1uDY+z624P//5z3nooYdyzDHHVO7zHly/autxbbwPr5jTTz89Z555Zg477LD07ds3Rx55ZE455ZSMGTMmiffhhiTUaAAtWrTItttum4cffrhyX3V1dR5++OEa52+mfrz77ruZMWNGunXr1tilfCb17t07Xbt2rTGf33nnnUyaNMl8biB/+ctf8tZbb5nTdVQURU444YTcfvvt+d///d/07t27xuPbbrttmjdvXmMOT5s2LbNmzTKH62B5/a3NlClTksQcXgXV1dV5//33zd8Gsri/tTF/V8ygQYPy4osvZsqUKZU/2223XY444ojK383hlbe8/tZ2WhNzeNV8/LOF9+D6t7zPbubvitl1110zbdq0Gve9+uqr6dmzZxKf5erD8npcG5/nVty1116btddeO1/60pcq93kPrl+19bg23odXzPz589OkSc2v15s2bZrq6uok3ocbVGNfqfyz6qabbipatmxZjB8/vnjllVeKY489tujQoUPxt7/9rbFLK73TTjutmDBhQjFz5szi8ccfLwYPHlx07ty5ePPNNxu7tNKaN29e8dxzzxXPPfdckaT48Y9/XDz33HPFn//856IoimLs2LFFhw4dijvvvLN44YUXiv3337/o3bt38e9//7uRKy+HZfV33rx5xciRI4snn3yymDlzZvHQQw8V/fv3LzbeeONiwYIFjV16KRx33HFF+/btiwkTJhSzZ8+u/Jk/f35lme985zvF+uuvX/zv//5v8cwzzxQ777xzsfPOOzdi1eWxvP6+9tprxejRo4tnnnmmmDlzZnHnnXcWG2ywQbHHHns0cuXlceaZZxYTJ04sZs6cWbzwwgvFmWeeWVRVVRUPPPBAURTm76paVn/N34YxYMCA4uSTT67cNofr18f7aw6vuuV9tjB/V82y+mv+rrqnnnqqaNasWXHBBRcU06dPL2644YaiTZs2xa9+9avKMj7LrZrl9djnuVW3aNGiYv311y/OOOOMJR7zHlw/ltZj78OrbtiwYcW6665b3H333cXMmTOL2267rejcuXPxve99r7KM9+GGIdRoQFdccUWx/vrrFy1atCh22GGH4g9/+ENjl/SZcOihhxbdunUrWrRoUay77rrFoYceWrz22muNXVapPfLII0WSJf4MGzasKIqiqK6uLs4+++xinXXWKVq2bFkMGjSomDZtWuMWXSLL6u/8+fOLvfbaq+jSpUvRvHnzomfPnsW3vvUtAegKqK23SYprr722ssy///3v4rvf/W7RsWPHok2bNsWBBx5YzJ49u/GKLpHl9XfWrFnFHnvsUXTq1Klo2bJlsdFGGxWnn3568fbbbzdu4SVy1FFHFT179ixatGhRdOnSpRg0aFAl0CgK83dVLau/5m/D+GSoYQ7Xr4/31xxedcv7bGH+rppl9df8rR+//e1viy233LJo2bJlsdlmmxX/9V//VeNxn+VW3bJ67PPcqrv//vuLJLXOS+/B9WNpPfY+vOreeeed4uSTTy7WX3/9olWrVsUGG2xQnHXWWcX7779fWcb7cMOoKoqi+LSOCgEAAAAAAFhZrqkBAAAAAACUglADAAAAAAAoBaEGAAAAAABQCkINAAAAAACgFIQaAAAAAABAKQg1AAAAAACAUhBqAAAAAAAApSDUAAAAAAAASkGoAQAAAAAAlIJQAwAAAAAAKAWhBgAAn2sDBw7MiBEjGruMiqIocuyxx6ZTp06pqqrKlClTllimLjV/msusqtXtOQAAAFZfQg0AABrV8OHDU1VVlbFjx9a4/4477khVVVUjVdV47rvvvowfPz533313Zs+enS233HKlxrntttty/vnn13N1fF4MGDAgVVVVufHGG2vcf8UVV6R79+6NVBUAAAg1AABYDbRq1SoXXXRR5syZ09il1JuFCxeu1HozZsxIt27dsssuu6Rr165p1qzZSo3TqVOntG3bdqXW/bxa2eesoTRWPUVR5Lnnnku3bt1y66231nhs8uTJ6d+/f6PUBQAAiVADAIDVwODBg9O1a9eMGTNmqcv06tUrl156aY37tt5665x33nmV2wMHDsyJJ56YESNGpGPHjllnnXVyzTXX5L333ss3v/nNtG3bNhtttFHuvffeGuN8+OGHOeGEE9K+fft07tw5Z599doqiqDxeXV2dMWPGpHfv3mndunX69euXW265pcYYAwcOzAknnJARI0akc+fOGTJkSK378f777+ekk07K2muvnVatWmW33XbL008/neSjo1ZOPPHEzJo1K1VVVenVq9dS+1FdXZ3vfe976dSpU7p27VqjD4vr+fgpnd5777184xvfyJprrplu3bpl3LhxS4xZl2WW14uBAwfmpJNOWmZty3Pfffdlt912S4cOHbLWWmvly1/+cmbMmFF5/Prrr89aa62V999/v8Z6BxxwQI488sg61bm41ro8Z8vbp7psq67z95P1LGu+1LW+JLnlllvSt2/ftG7dOmuttVYGDx6c9957r9b9nT59eubNm5cf/OAHuffeezN//vzKY88++2y23XbbWtcDAIBPg1ADAIBG17Rp01x44YW54oor8pe//GWVxrruuuvSuXPnPPXUUznxxBNz3HHH5eCDD84uu+ySZ599NnvttVeOPPLIGl/UXnfddWnWrFmeeuqpXHbZZfnxj3+cn//855XHx4wZk+uvvz5XX311Xn755Zxyyin5+te/nokTJy6x7RYtWuTxxx/P1VdfXWt93/ve93Lrrbfmuuuuy7PPPpuNNtooQ4YMyb/+9a9cdtllGT16dNZbb73Mnj17iS+vP7mtNdZYI5MmTcrFF1+c0aNH58EHH1zq8qeffnomTpyYO++8Mw888EAmTJiQZ599doWXqUsvVrS2T3rvvfdy6qmn5plnnsnDDz+cJk2a5MADD0x1dXWS5OCDD86iRYty1113VdZ58803c8899+Soo46qc52La13ec7a8farrturik/Usa77Utb7Zs2fn8MMPz1FHHZWpU6dmwoQJGTp0aI3g7uMmT56cVq1a5Zhjjkm7du0qIeCCBQsydepUR2oAANC4CgAAaETDhg0r9t9//6IoimKnnXYqjjrqqKIoiuL2228vPv7f1Z49exY/+clPaqzbr1+/4txzz63cHjBgQLHbbrtVbn/44YfFGmusURx55JGV+2bPnl0kKZ588snKOn369Cmqq6sry5xxxhlFnz59iqIoigULFhRt2rQpnnjiiRrbPvroo4vDDz+8xra32WabZe7ru+++WzRv3ry44YYbKvctXLiw6N69e3HxxRcXRVEUP/nJT4qePXsuc5xP7mdRFMX2229fnHHGGTWWOfnkk4uiKIp58+YVLVq0KH79619XHn/rrbeK1q1br9AydelFXWqrbX8Wb6M2//jHP4okxYsvvli577jjjiv22Wefyu1x48YVG2ywQVFdXV2vz9ny9qmu26rr/P14PXWZL8urryiKYvLkyUWS4vXXX1/uvhZFUYwcObLYYYcdiqL4qM+HHXZYURRF8Yc//KFIUsyaNatO4wAAQENYuRP0AgBAA7jooouy5557ZuTIkSs9xlZbbVX5e9OmTbPWWmulb9++lfvWWWedJB/9sn+xnXbaqcZFyXfeeeeMGzcuixYtymuvvZb58+fni1/8Yo3tLFy4MNtss02N+5Z3Wp4ZM2bkgw8+yK677lq5r3nz5tlhhx0yderUFdjLmvuZJN26dauxT5/c7sKFC7PjjjtW7uvUqVM23XTTFVqmrr1YkdpqM3369JxzzjmZNGlS/vnPf1aO0Jg1a1blwunf+ta3sv322+f//u//su6662b8+PGVi87X53O2vH1akW3VxcfrWZH5sqye9+vXL4MGDUrfvn0zZMiQ7LXXXvnqV7+ajh071lrDs88+WzkaY+jQoRk6dGjef//9PPvss+nSpUt69OixwvsFAAD1RagBAMBqY4899siQIUPy/e9/P8OHD6/xWJMmTZY4Xc4HH3ywxBjNmzevcbuqqqrGfYvDi8VflC/Pu+++myS55557su6669Z4rGXLljVur7HGGnUasz7Utp913aeVVdderGpt++23X3r27Jlrrrkm3bt3T3V1dbbccssaF87eZptt0q9fv1x//fXZa6+98vLLL+eee+5ZoTqTuj9nS9unum6rrvN3ZefQsnretGnTPPjgg3niiSfywAMP5IorrshZZ52VSZMmpXfv3kuM9eyzz+bwww9P8tH1Opo3b57777/fRcIBAFgtCDUAAFitjB07NltvvXWNIwSSpEuXLpk9e3bl9jvvvJOZM2fWyzYnTZpU4/Yf/vCHbLzxxmnatGk233zztGzZMrNmzcqAAQNWaTsbbrhh5XoJPXv2TPLRF9tPP/10jYt617cNN9wwzZs3z6RJk7L++usnSebMmZNXX321sk91WaY+e7E0b731VqZNm5Zrrrkmu+++e5Lkscceq3XZY445Jpdeemn+7//+L4MHD64cQfBp1LlYXbe1MvO3PudLVVVVdt111+y6664555xz0rNnz9x+++059dRTayz3pz/9KXPnzq2EF82aNctXvvKV3HrrrXnxxRezzz77rNB2AQCgvgk1AABYrfTt2zdHHHFELr/88hr377nnnhk/fnz222+/dOjQIeecc06aNm1aL9ucNWtWTj311Hz729/Os88+myuuuCLjxo1LkrRt2zYjR47MKaeckurq6uy22255++238/jjj6ddu3YZNmxYnbezxhpr5Ljjjsvpp5+eTp06Zf3118/FF1+c+fPn5+ijj66XfanNmmuumaOPPjqnn3561lprray99to566yz0qRJkxVapj57sTQdO3bMWmutlf/6r/9Kt27dMmvWrJx55pm1Lvu1r30tI0eOzDXXXJPrr7/+U61zRbe1MvO3vubLpEmT8vDDD2evvfbK2muvnUmTJuUf//hH+vTps8SykydPTosWLSqn+UqSgw46KEceeWTmz5+fs846q87bBQCAhiDUAABgtTN69OjcfPPNNe77/ve/n5kzZ+bLX/5y2rdvn/PPP7/ejtT4xje+kX//+9/ZYYcd0rRp05x88sk59thjK4+ff/756dKlS8aMGZM//elP6dChQ/r375//+I//WOFtjR07NtXV1TnyyCMzb968bLfddrn//vuXen2D+vKjH/0o7777bvbbb7+0bds2p512Wt5+++0VXqY+e1GbJk2a5KabbspJJ52ULbfcMptuumkuv/zyDBw4cIll27dvn4MOOij33HNPDjjggE+1zhXd1srO3/qYL+3atcvvf//7XHrppXnnnXfSs2fPjBs3rtajLp599tlsueWWadGiReW+L37xi1m0aFEWLlzo9FMAADS6quKTJ3YFAAAoiUGDBmWLLbZY4sgeAADgs0moAQAAlM6cOXMyYcKEfPWrX80rr7yyxDVYAACAzyannwIAAEpnm222yZw5c3LRRRcJNAAA4HPEkRoAAAAAAEApNGnsAgAAAAAAAOpCqAEAAAAAAJSCUAMAAAAAACgFoQYAAAAAAFAKQg0AAAAAAKAUhBoAAAAAAEApCDUAAAAAAIBSEGoAAAAAAAClINQAAAAAAABKQagBAAAAAACUglADAAAAAAAohf8PTkdLmsneXOUAAAAASUVORK5CYII=\n"
          },
          "metadata": {}
        }
      ]
    }
  ]
}