{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "20cb7206-4444-4c15-a3c5-9cc29abbef98",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7afc13a8-b53c-48a3-93ac-8e08543cfeed",
   "metadata": {},
   "source": [
    "## Linear Classification with gradient descent\n",
    "\n",
    "### Exercise 1\n",
    "The objective of this exercise is to build a simple linear classifier on a linearly separable problem. To this end we propose a toy dataset generated according to two gaussian (one class by gaussian)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d78f9a97-ec6b-4420-ac1e-bba32d2597c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(42)\n",
    "dataset = list(zip(np.random.randn(50,2)*0.2 + [0.5, -0.5], np.ones(50))) \\\n",
    "               + list(zip(np.random.randn(50,2)*0.4 + [-0.5, 0.5], np.zeros(50)))\n",
    "X, Y = np.array([x for (x, _) in dataset]), np.array([y for (_, y) in dataset]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "bada2da2-cbb0-49f7-9bb0-72b7d733467a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7c3690a07560>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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Z88efelLX9JvfvMblZWV6dOf/rT+8z//U/369cv6nAsuuED//d//nfbYF77wBS1atMjLpQIA8nByk850tNmtoMGNEzdutrl3czvKboB40fBq/d8MAWLYMy5JngYvV199tXbt2qUVK1bo3Xff1XXXXacZM2bokUceyfm8G264QXfccUfq/b59+3q5TACADW7cpN0IGrw88txTbk1dLjRALBWeBS+vvPKKli9frr/85S8699xzJUnf/e53NXnyZN1zzz2qra3N+ty+ffuqurpn/QIAAN5x6yZdCK+OPBfKbmYp1wkpr4qKw8az8QAPPPCAZs+erbfffjv12HvvvaeKigo99thj+uQnP5nxeRdccIE2bdoky7JUXV2tSy65RLfddlvW7Et7e7va29tT78diMdXV1TEeAAA85OdQwGSb/3zZiULa/HvF7gmpMM4uyicQ4wFaWlo0ePDg9C921FEaMGCAWlpasj7vs5/9rIYOHara2lq9/PLLuvXWW7VlyxYtXbo04/ULFizQ/PnzXV07ACA3P7cs8k2btiRd+aE6H1aWm5MuvG4XFYeN48zLnDlzdNddd+W85pVXXtHSpUv14IMPasuWLWkfGzx4sObPn6+bbrrJ1td77rnndOGFF2rr1q06+eSTu32czAsAlKZM2YnOsmUqnGSN3MowFWMopNuKnV3zNPMye/ZsXXvttTmvOemkk1RdXa0333wz7fH33ntPe/bscVTPMnbsWEnKGryUl5ervLzc9ucDAIRDMjvxvee26jvP/m+3j2fKaDjZjnFz68a0mURB37ZyHLwMGjRIgwYNyntdQ0OD9u7dq7Vr12r06NGSElmUeDyeCkjsaGpqkiTV1Pj/jwUA8I7d3/Q7XzfwmHL9Ys2OjJ+va8+XFZtbsm7b3PjwOn15wqk6ceAxGnxshd4+cFhffKT7tbtS136w2+DHXIJ4QiobL4ZMus2zmpfTTz9dkyZN0g033KBFixbp3Xff1c0336wrr7wyddJo586duvDCC/XQQw9pzJgx2rZtmx555BFNnjxZxx9/vF5++WV9+ctf1vnnn6+zzjrLq6UCAHyW6zf9zrUff9t9QL9Ys0MtsfYcn+19yYzGn//6Vt62+9959rXUY2WR3OMNvvPs/+oXa7br3y49w9aNPKgnpLryYsikFzzt8/Lzn/9cN998sy688MJUk7r77rsv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uummm2w/5+6779Z9992nRYsWafXq1TrmmGM0ceJEHTpUWHtmAAAQHhHLsgodlpnT4sWLNXPmTO3duzfndZZlqba2VrNnz9ZXvvIVSVJbW5uqqqq0ePFiXXnllba+XiwWU2Vlpdra2hSNRgtdPgAAKAIn9+/A1Lw0NzerpaVFEyZMSD1WWVmpsWPHqrGxMevz2tvbFYvF0t4AAEB4BSZ4aWlpkSRVVVWlPV5VVZX6WCYLFixQZWVl6q2urs7TdQIAAH85Cl7mzJmjSCSS8+3VV1/1aq0ZzZ07V21tbam3119/vahfHwAAFJejDruzZ8/Wtddem/Oak046qUcLqa6uliS1traqpub9mRCtra0aOXJk1ueVl5ervLw89X6yhIftIwAAzJG8b9spxXUUvAwaNEiDBg3q2aryqK+vV3V1tVauXJkKVmKxmFavXu3oxNK+ffskie0jAAAMtG/fPlVWVua8xrPZRjt27NCePXu0Y8cOdXR0qKmpSZJ0yimnqF+/fpKkYcOGacGCBfrkJz+pSCSimTNn6t///d916qmnqr6+Xrfddptqa2s1depU21+3trZWr7/+uo499lhFIgzH6olYLKa6ujq9/vrrnNgyAK+XWXi9zMLrVTyWZWnfvn2qra3Ne61nwcu8efP04IMPpt4fNWqUJOkPf/iDLrjgAknSli1b1NbWlrrma1/7mg4cOKAZM2Zo7969Ou+887R8+XJVVKSPIc+lrKxMH/jAB9z5S5S4aDTKf1aD8HqZhdfLLLxexZEv45LkeZ8XmIdeOWbh9TILr5dZeL2CKTBHpQEAAOwgeEE35eXluv3229NOcSG4eL3MwutlFl6vYGLbCAAAGIXMCwAAMArBCwAAMArBCwAAMArBCwAAMArBC/Stb31L48aNU9++fdW/f39bz7EsS/PmzVNNTY2OPvpoTZgwQa+99pq3C0XKnj17dPXVVysajap///66/vrrtX///pzPueCCC7oNUr3xxhuLtOLScv/99+vEE09URUWFxo4dqzVr1uS8/rHHHtOwYcNUUVGhM888U88880yRVgrJ2eu1ePHibv+PnDRShTsIXqDDhw/rM5/5jKMZUnfffbfuu+8+LVq0SKtXr9YxxxyjiRMn6tChQx6uFElXX321Nm3apBUrVuipp57S888/rxkzZuR93g033KBdu3al3u6+++4irLa0PProo5o1a5Zuv/12rVu3TmeffbYmTpyoN998M+P1q1at0lVXXaXrr79e69ev19SpUzV16lRt3LixyCsvTU5fLynRbbfz/6Pt27cXccWQJFnAET/96U+tysrKvNfF43Grurra+va3v516bO/evVZ5ebn1i1/8wsMVwrIsa/PmzZYk6y9/+Uvqsd/+9rdWJBKxdu7cmfV548ePt2655ZYirLC0jRkzxvriF7+Yer+jo8Oqra21FixYkPH6yy+/3JoyZUraY2PHjrW+8IUveLpOJDh9vez+nIS3yLzAsebmZrW0tGjChAmpxyorKzV27Fg1Njb6uLLS0NjYqP79++vcc89NPTZhwgSVlZVp9erVOZ/785//XAMHDtSIESM0d+5cHTx40OvllpTDhw9r7dq1af83ysrKNGHChKz/NxobG9Oul6SJEyfyf6kIevJ6SdL+/fs1dOhQ1dXV6bLLLtOmTZuKsVx04tlgRoRXS0uLJKmqqirt8aqqqtTH4J2WlhYNHjw47bGjjjpKAwYMyPnv/9nPflZDhw5VbW2tXn75Zd16663asmWLli5d6vWSS8bu3bvV0dGR8f/Gq6++mvE5LS0t/F/ySU9er9NOO00PPPCAzjrrLLW1temee+7RuHHjtGnTJoYCFxGZl5CaM2dOt6Kyrm/Z/nPCH16/ZjNmzNDEiRN15pln6uqrr9ZDDz2kX//619q2bZuLfwsg3BoaGjRt2jSNHDlS48eP19KlSzVo0CD98Ic/9HtpJYXMS0jNnj1b1157bc5rTjrppB597urqaklSa2urampqUo+3trZq5MiRPfqcsP+aVVdXdysmfO+997Rnz57Ua2PH2LFjJUlbt27VySef7Hi96G7gwIHq1auXWltb0x5vbW3N+tpUV1c7uh7u6cnr1VXv3r01atQobd261YslIguCl5AaNGiQBg0a5Mnnrq+vV3V1tVauXJkKVmKxmFavXu3oxBLS2X3NGhoatHfvXq1du1ajR4+WJD333HOKx+OpgMSOpqYmSUoLQFGYPn36aPTo0Vq5cqWmTp0qSYrH41q5cqVuvvnmjM9paGjQypUrNXPmzNRjK1asUENDQxFWXNp68np11dHRoQ0bNmjy5MkerhTd+F0xDP9t377dWr9+vTV//nyrX79+1vr1663169db+/btS11z2mmnWUuXLk29f+edd1r9+/e3nnzySevll1+2LrvsMqu+vt565513/PgrlJxJkyZZo0aNslavXm298MIL1qmnnmpdddVVqY///e9/t0477TRr9erVlmVZ1tatW6077rjDeumll6zm5mbrySeftE466STr/PPP9+uvEFq//OUvrfLycmvx4sXW5s2brRkzZlj9+/e3WlpaLMuyrH/5l3+x5syZk7r+xRdftI466ijrnnvusV555RXr9ttvt3r37m1t2LDBr79CSXH6es2fP9/63e9+Z23bts1au3atdeWVV1oVFRXWpk2b/PorlCSCF1jTp0+3JHV7+8Mf/pC6RpL105/+NPV+PB63brvtNquqqsoqLy+3LrzwQmvLli3FX3yJeuutt6yrrrrK6tevnxWNRq3rrrsuLdhsbm5Oew137NhhnX/++daAAQOs8vJy65RTTrG++tWvWm1tbT79DcLtu9/9rnXCCSdYffr0scaMGWP9+c9/Tn1s/Pjx1vTp09OuX7JkifXBD37Q6tOnj3XGGWdYTz/9dJFXXNqcvF4zZ85MXVtVVWVNnjzZWrdunQ+rLm0Ry7IsHxM/AAAAjnDaCAAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGIXgBQAAGOX/A7qKcJuP1+9pAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(X[Y==1][:, 0],X[Y==1][:, 1])\n",
    "plt.scatter(X[Y==0][:, 0],X[Y==0][:, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73bf306f-2fd6-42df-a72b-91bd83e9f3f2",
   "metadata": {},
   "source": [
    "## 1. Linear Function and loss \n",
    "**Question 1**:Create a function `affine` taking as parameters $w$ (2 dim vector), $b$ (scalars) and $x$ (2 dim vector) that return $$w^{\\intercal}x  + b$$ \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7f9e6e0d-946d-4b85-8213-6bed2e928b0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def affine(w, b, x):\n",
    "    raise NotImplementedError('Implement the function')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc6a1694-80fa-4adf-a16e-0c19bc3fa1f2",
   "metadata": {},
   "source": [
    "**Question 2:** Compute the equation of the line  such that $w^{\\intercal}x  + b = 0$ and then draw it for $w_1 = 1$, $w_2 = 2$ and $b=1$. The function should return parameters $c$ and $d$ of $y = cx + d$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f345dcde-30ad-4e9c-a9dd-bc5fa41e8eb0",
   "metadata": {},
   "outputs": [
    {
     "ename": "NotImplementedError",
     "evalue": "Implement the function",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNotImplementedError\u001b[0m                       Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mline_param\u001b[39m(w, b):\n\u001b[1;32m      2\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mNotImplementedError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mImplement the function\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m----> 3\u001b[0m c, d \u001b[38;5;241m=\u001b[39m \u001b[43mline_param\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(d, c)\n\u001b[1;32m      5\u001b[0m plt\u001b[38;5;241m.\u001b[39mscatter(X[Y\u001b[38;5;241m==\u001b[39m\u001b[38;5;241m1\u001b[39m][:, \u001b[38;5;241m0\u001b[39m],X[Y\u001b[38;5;241m==\u001b[39m\u001b[38;5;241m1\u001b[39m][:, \u001b[38;5;241m1\u001b[39m])\n",
      "Cell \u001b[0;32mIn[5], line 2\u001b[0m, in \u001b[0;36mline_param\u001b[0;34m(w, b)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mline_param\u001b[39m(w, b):\n\u001b[0;32m----> 2\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mNotImplementedError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mImplement the function\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "\u001b[0;31mNotImplementedError\u001b[0m: Implement the function"
     ]
    }
   ],
   "source": [
    "def line_param(w, b):\n",
    "    raise NotImplementedError('Implement the function')\n",
    "c, d = line_param([1, 2], 1)\n",
    "print(d, c)\n",
    "plt.scatter(X[Y==1][:, 0],X[Y==1][:, 1])\n",
    "plt.scatter(X[Y==0][:, 0],X[Y==0][:, 1])\n",
    "plt.grid()\n",
    "rrange = np.arange(-1.5, 1.5, 0.01)\n",
    "plt.plot(rrange, rrange * c + d)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbe0d389-6efa-43c9-9365-bd858c0a65fd",
   "metadata": {},
   "source": [
    "**Question 3**: Create a function `affine_grad` taking as parameters $w$ (2 dim vector), $b$ (scalars) and $x$ (2 dim vector) returning the gradient w.r.t $w$ and $b$ : $$(\\nabla_{w}w^{\\intercal}x  + b,\\nabla_{b}w^{\\intercal}x  + b) $$ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9d0251c4-a659-40ab-92b6-5cc863f93422",
   "metadata": {},
   "outputs": [],
   "source": [
    "def affine_grad(w, b, x):\n",
    "    raise NotImplementedError('Implement the function')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ddf8493-f471-437b-8078-2578f69c6219",
   "metadata": {},
   "source": [
    "## Hinge loss: forward and gradient\n",
    "Create two functions that compute respectivelly the Hinge Loss and its derivative (in x) .\n",
    "\n",
    "$$\\text{Hinge loss} = \\max(0, 1 - y \\times x)$$\n",
    "\n",
    "!!! This is the formula of the hinge loss if $y\\in \\{-1,1\\}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "305bd201-a3ac-4513-8efa-862cff1db673",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hinge_loss(x, y):\n",
    "    raise NotImplementedError('Implement the function')\n",
    "\n",
    "def hinge_loss_grad(x, y):\n",
    "    raise NotImplementedError('Implement the function')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d21957d-6c04-4e8d-bb0e-99bf8634f626",
   "metadata": {},
   "source": [
    "## 2. Gradient descent\n",
    "\n",
    "\n",
    "Consider the function $f_{w, b}$ such that $f_{w, b}(x) = \\max(0, 1 - y \\times (w^{\\intercal}x  + b))$. We want to train such function using SGD on parameters (w,b). \n",
    "\n",
    "**Question 1**: Complete the training loop below:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c0131d0f-4c4e-4a2b-a30f-e6b35b201e6b",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (1676911043.py, line 14)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Cell \u001b[0;32mIn[8], line 14\u001b[0;36m\u001b[0m\n\u001b[0;31m    o_pred =\u001b[0m\n\u001b[0m             ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "n_epoch = 20\n",
    "w = [0.1, 0.1]\n",
    "b = 0.1\n",
    "learning_rate = 1e-3\n",
    "\n",
    "for epoch in range(n_epoch):\n",
    "    loss_values = []\n",
    "    shuffled_index = np.arange(len(X))\n",
    "    np.random.shuffle(shuffled_index)\n",
    "    \n",
    "    for i in shuffled_index:\n",
    "        x, y = X[i], Y[i]\n",
    "        raise NotImplementedError('Implement the function')\n",
    "        o_pred = \n",
    "        loss = \n",
    "        \n",
    "        loss_values.append(loss)\n",
    "        \n",
    "        loss_grad =\n",
    "        w_grad, b_grad = \n",
    "\n",
    "        # update w and b according to the gradients\n",
    "        w = \n",
    "        b =\n",
    "    print(f'The loss for the epoch {epoch} is {np.mean(loss_values)}')\n",
    "    loss_values = []\n",
    "\n",
    "    c, d = line_param(w, b)\n",
    "    \n",
    "    plt.scatter(X[Y==1][:, 0],X[Y==1][:, 1])\n",
    "    plt.scatter(X[Y==0][:, 0],X[Y==0][:, 1])\n",
    "    plt.grid()\n",
    "    rrange = np.arange(-1.5, 1.5, 0.01)\n",
    "    plt.plot(rrange, rrange * c + d)\n",
    "    plt.ylim([-2, 2])\n",
    "    \n",
    "    plt.show()\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53256d74-c2a0-4d69-936c-79b2577a58a5",
   "metadata": {},
   "source": [
    "**Question 2** Compute the final accuracy (number of correct classification on number of data points)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c54045ee-de23-46f3-88cc-01d07fcefb23",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ee4355ab-aa5d-478f-a07a-e3c055724251",
   "metadata": {},
   "source": [
    "**Question 3** With minimal changes (hyper-parameters) can you improve accuracy? If yes, apply those changes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ddd351d8-fb91-489e-b916-eedca9ff1e94",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "61e716e0-6e10-4935-a337-342729124c50",
   "metadata": {},
   "source": [
    "## 3. Non linearly separable problem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "0865edcf-469f-4120-b012-3ac1f3bb1e2c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7f1e809bb290>"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjkAAAGdCAYAAADwjmIIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfvElEQVR4nO3dfXwTdbY/8E9aaEuBtEChabHL86JdKkWwpairC9VWUOSKu4Du8rCIP1FUwAdg7wKLeAWE67IqitcFwauIyPqAqF0RRUULuEAVBLnSrYDYFGmlgRYKJPP7I0xo2kwyM5lJZiaf9+vVV206SWYaS07P95zztQmCIICIiIjIYuKifQJEREREemCQQ0RERJbEIIeIiIgsiUEOERERWRKDHCIiIrIkBjlERERkSQxyiIiIyJIY5BAREZEltYj2CUSDx+PBjz/+iLZt28Jms0X7dIiIiEgGQRBw8uRJZGZmIi4udJ4mJoOcH3/8EVlZWdE+DSIiIlLhyJEjuOSSS0IeF5NBTtu2bQF4f0h2uz3KZ0NERERyuFwuZGVl+d7HQ4nJIEdcorLb7QxyiIiITEZuqQkLj4mIiMiSGOQQERGRJTHIISIiIktikENERESWxCCHiIiILIlBDhEREVkSgxwiIiKyJAY5REREZEkxOQyQTMrjBg59AZyqAtqkA10GAXHx0T4rIiIyKAY5ZA77NgAlMwDXjxdvs2cCxYuA7OHROy8iIjIsLleR8e3bAKwb6x/gAICr0nv7vg3ROS8iIjI0BjlkbB63N4MDIcA3L9xWMtN7HBERUSMMcsjYDn3RPIPjRwBcR73HERERNcIgh4ztVJW2xxERUcxgkEPG1iZd2+OIiChmMMghY+syyNtFBZvEATbA3tl7HBERUSMMcsjY4uK9beIAmgc6F74uXsh5OURE1IyuQc6nn36Km2++GZmZmbDZbHjrrbdC3mfLli244oorkJiYiJ49e2LVqlXNjlm2bBm6du2KpKQk5OfnY8eOHdqfPBlH9nDgdy8B9gz/2+2Z3tvlzsnxuIGKz4A9672f2ZFFRGRpug4DrKurQ9++ffHHP/4Rt956a8jjKyoqMGzYMNx999145ZVXsHnzZtx5553IyMhAUVERAOC1117D9OnTsXz5cuTn52Pp0qUoKirCgQMH0KlTJz0vh6Ipezhw6TD1E485TJCIKObYBEEINIBE+yey2fDmm29ixIgRksfMmDED7777Lvbu3eu7bfTo0Thx4gRKSkoAAPn5+bjyyivxzDPPAAA8Hg+ysrJw3333YebMmbLOxeVyISUlBbW1tbDb7eovisxBHCbYbNbOheUuJdkgIiKKGqXv34aqySktLUVhYaHfbUVFRSgtLQUAnD17Fjt37vQ7Ji4uDoWFhb5jAmloaIDL5fL7oBjBYYJERDHLUEGO0+lEerp/K3B6ejpcLhdOnz6N48ePw+12BzzG6XRKPu6CBQuQkpLi+8jKytLl/MmAOEyQiChmGSrI0cusWbNQW1vr+zhy5Ei0T4kihcMEiYhilqF2IXc4HKiq8n+zqaqqgt1uR6tWrRAfH4/4+PiAxzgcDsnHTUxMRGJioi7nTAbHYYJERDHLUJmcgoICbN682e+2TZs2oaCgAACQkJCA/v37+x3j8XiwefNm3zFEfjhMkIgoZuka5Jw6dQplZWUoKysD4G0RLysrw+HDhwF4l5HGjh3rO/7uu+/Gv//9bzzyyCP49ttv8eyzz2LdunWYNm2a75jp06fjhRdewOrVq7F//35MnjwZdXV1mDBhgp6XQmbFYYJERDFL1+Wqf/3rX/jNb37j+3r69OkAgHHjxmHVqlWorKz0BTwA0K1bN7z77ruYNm0a/va3v+GSSy7B3//+d9+MHAAYNWoUfvrpJ8yZMwdOpxO5ubkoKSlpVoxM5CMOEww4J2ch28eJiCwqYnNyjIRzcmKUx61+mKCRnoOIKEYpff82VOExka7i4oFu1+j3+JyqTERkKIYqPCYyLXGqctOZPK5K7+37NkTnvIiIYhiDHKJwcaoyEZEhMcghChenKhMRGRKDHKJwcaoyEZEhMcghChenKhMRGRKDHKJwcaoyEZEhMcghChenKhMRGRKDHCItiFOV7Rn+t9szvbdzTg4RUcRxGCCRVrKHA5cOkz/xmNORiYh0xSCHSEtypypzOjIRke64XEUUaZyOTCbj9ggoLa/G22VHUVpeDbcn5rY8JJNiJocokkJOR7Z5pyNfOoxLV2QIJXsrMe+dfaisPeO7LSMlCXNvzkZxn4wg9ySKPmZyiCKJ05HJREr2VmLyy7v8AhwAcNaeweSXd6Fkb2WUzoxIHgY5RJHE6chkEm6PgHnv7Au2IxvmvbOPS1dkaAxyiCKJ05HJJHZU1DTL4DQmAKisPYMdFTWROykihRjkEEUSpyOTSRw7KR3gqDmOKBoY5BBFEqcjk0l0apuk6XFE0cAghyjSOB2ZTCCvW3tkpCQFyzkiIyUJed3aR/K0iBRhCzlRNCidjkwUYfFxNsy9ORuTX94FG/yHHoiBz9ybsxEfJxUGEUUfMzlE0SJOR865zfuZAQ4ZTHGfDDz3+yvgSPFfknKkJOG531/BOTlkeMzkkDLcb4kophT3ycD12Q7sqKjBsZNn0Kmtd4lKrwyO2yNE7LnI+hjkkHzcb4koJsXH2VDQo4Puz6P1dGW1ARMDLeuwCYIQc5OcXC4XUlJSUFtbC7vdHu3TMQdxv6Vmo8Eu/OKzYJaIwiBOV5b4F0bx8pjagInbWBib0vdv1uRQaCH3W4J3vyWPO5JnJZ/HDVR8BuxZ7/1s1PMkilFaT1dWux0Ft7GwHgY5FJqZ91vatwFY2gdYfRPwj4nez0v7cKdvIgPRcrqy2oCJ21hYE4McCs2s+y2JS2xNAzRXpfd2BjpEhqDldGW1ARO3sbAmBjkUmhn3WzL7EhtRDNFyurLagInbWFgTgxwKzYz7LZl5iY0oxmg5XVltwKTkfm6PgNLyarxddhSl5dVcwjIwtpBTaOJ+S+vGAlKzT42235JZl9iIYpCW05XFgMlZeyZgHtcG7zDDpgGT3Pv9XHcWVy/6iN1XJsFMDsljtv2W1CyxsQuLKGq0mq4sBkyA5Ba4AQMmOfcb3jcD965h95WZcE4O5+QoY5aJxx63t4vKVYnAdTk2b4A2dY/3/DnokMgQtBrEp/WcnNnDLsP8d/dLFieLmZ6tMwZzcKCOlL5/RyTIWbZsGRYvXgyn04m+ffvi6aefRl5eXsBjr7vuOnzyySfNbh86dCjeffddAMD48eOxevVqv+8XFRWhpKRE1vkwyIkRvgGGQMAEuJiB4qBDIkvScuLxjooajHlhW8j7vjppYESmQ8cqpe/futfkvPbaa5g+fTqWL1+O/Px8LF26FEVFRThw4AA6derU7Pg33ngDZ8+e9X1dXV2Nvn374re//a3fccXFxXjxxRd9XycmJup3EWRO4hJbwAzNQu/3Q3Zh2bxdWJcOM2bGiogkqd2OItD92H1lTroHOU8++SQmTZqECRMmAACWL1+Od999FytXrsTMmTObHd++vX8x2Nq1a5GcnNwsyElMTITD4dDvxMkasod7AxSpJTYlXVjdronIKROR8WjZ5k6Ro2vh8dmzZ7Fz504UFhZefMK4OBQWFqK0tFTWY6xYsQKjR49G69at/W7fsmULOnXqhN69e2Py5Mmorq7W9NzJQuLivQFKzm3ez40zMuzCIiIZtGxzp8jRNcg5fvw43G430tP9O13S09PhdDpD3n/Hjh3Yu3cv7rzzTr/bi4uL8dJLL2Hz5s1YtGgRPvnkE9x4441wuwN3wzQ0NMDlcvl9EAEw56BDIoo4tV1bFF2GbiFfsWIFcnJymhUpjx49GsOHD0dOTg5GjBiBjRs34ssvv8SWLVsCPs6CBQuQkpLi+8jKyorA2ZMpmHHQIRFFhVZt7hQ5utbkpKWlIT4+HlVV/qn+qqqqkPU0dXV1WLt2LR599NGQz9O9e3ekpaXh4MGDGDJkSLPvz5o1C9OnT/d97XK5GOiQlxkHHRIZiFYt32ZR3CcD12c7YuqazUzXICchIQH9+/fH5s2bMWLECACAx+PB5s2bMWXKlKD3ff3119HQ0IDf//73IZ/nhx9+QHV1NTIyAkfRiYmJ7L4iaXK6sIioGbWzaMxObdcWRZ7uc3Jee+01jBs3Ds8//zzy8vKwdOlSrFu3Dt9++y3S09MxduxYdO7cGQsWLPC73zXXXIPOnTtj7dq1frefOnUK8+bNw8iRI+FwOFBeXo5HHnkEJ0+exJ49e2QFM5yTQwGZZdAhkQGU7K3E5Jd3SU2XUrx8E2sZIVLHcHNyRo0ahZ9++glz5syB0+lEbm4uSkpKfMXIhw8fRlycf2nQgQMHsHXrVnzwwQfNHi8+Ph5ff/01Vq9ejRMnTiAzMxM33HAD5s+fz2wNhUfswiKioNweAfPe2RdsuhTmvbMP12c7ZAUqcjJCSoMgBk0EcFsHZnKIiBQqLa/WbPqvnIwQAEXLYrG6jBYLlL5/G7q7ioiIjEer6b+hMkIAMPONPZj8svxNMcWgyQibaLo9AkrLq/F22VGUllfD7Ym5nELU6b5cRURE1qLV9N8dFTWSG14C3kDnRP05ye81XRbTehktHMwmGQMzOWQcHjdQ8RmwZ733syfwcEciii6tpv+Gu8+TAKCy9gx2VNQAkBc0NT5eL0bKJsU6ZnLIGPZtkGjhXhT5Fm52WRkOi0iNRZz+O/nlXVLTpWRN/9VqnycxWDLCJppGyiYRgxwygn0bLgzja/LPgqvSe/vvXopcoGOkYIsAMO1vVOL036avjUPBayNmhJy1ZwIGBXKJwZIRNtFUkk3irB39Mcih0PTMbHjc3qAi2N89JTO9O4nrnU0xUrBFAKQ7b8S0P0fpR1e4039DZYQEAKnJLVFbfy7gvxA2eIMqcVksVNDU9Hg9RCObxEynNAY5FJzemY1DX/g/djMC4DrqPU7PGTYeN/DOAzBEsCWXxZfVmPY3h3Cn/4bKCAGQvSym1TJaOCKdTWKmMzgGOSQtEpmNU1Whj2l6nB5v7p8uAU4HK0aMULAlVwwsqzHtHztCZYSULItpsYwWjkhmk5jpDI1BDgUWqWWkNunKjtPjzd3jBrY/K+9YuUGZnmJkWc0IRaQUOcEyQkqXxaK5iWaksknMdMrDFvJYFqxlW8kyUji6DPIGKcGaUe2dvceJb+5Nz0t8c9+3Qd05HPoCOH1C3rFygzK9hAw+4Q0+LdB+b4QiUjIOMQi6JbczCnp0CPnGrfR4LYnZJEeK//+bjpQkzbIrRmmXNzpmcmJVqIyImmUkNeLivc+5biwg9XdP8ULvZ70yS3KvoVV7b7AVTUapYYoAIxSREqmldzaJmU55mMmJRXIyIkqXkcKRPdy7xGJv8teNPfPi0ouemSW515B/d/QLeyMVfBqAmPYHmuf5IlVEGsu4JUH49MwmMdMpDzM5sUZurc39Zd4gw1UpcazN+32tMhvZw71ZGKmCYj3f3MUlM8lrhTeL8+uHlD+21iIZfBpAtItIYxU7doyPmU55GOTEGrkZkSPb5S0jaZnZiIuXXmLR88096JLZBTf/LfpZHEBGQKZx8GkA0SwijUVKOnY4nyV6jNAubwZcroo1SjIicpaRIkVJgbIaktfaGfjd/xqnW0kMyABILuJoHXwaQDSLSGOJnF3B572zD2fPe/C3D/8P/edvwpgXtuGBtWUY88I2XL3oI+7LFEGRKHA2O5sgCDG30OpyuZCSkoLa2lrY7fZon05kVXwGrL4p9HFFj3uzIm3Sgax8b2Yn2kPnfK3TQMC/W7QIvMwyYC9g4Xhnb4BjlICMTKe0vBpjXtgW8rg2iS1wquF8s9vF0JNvsJEVSxk1pe/fDHJiLcjxuIGlfYLXn9jiAMFz8WsjDZnjm/tFRgnIjHIeFLa3y47igbVlYT2GWAuydcZgy77RUvQoff9mTU6skVN/0jjAAbwBxbo/GGPZJlSBciwJVsMUKTEweTmWaNGJw0nUZCSsyYlFUvUnkvUuF7zzgDGGzIlv7jm3eQOcQ18EHmhoZsEGNRqFXsMZKWrEjh0t8i+xPp+FjIGZnFjVNCNy0gl88J/B73O6Bvh+K9D92sicYyhaZBGMuNRihuyIkXaPj2Fa12IE69hRKtbns5AxMMiJZY2XOzY/Ju8+FZ8ZI8iR3L/pwtLawHuA3kODBy1SwcQV44EOPaIT9JhlX6oYmrxsVHrNspGaTdS+dUvU1J2T9RgZEvNZYqlAloyBQQ55yf13xgj/HgXNIlyw7Vnvh1QGJFiQtOXxi19HMoNipuxIDE1eNqJQs2yW3X4F2rVOUB1MBJpN1L9LO1y7+GPJ4XONBZrPYvUBgwzgjIlBDnl1uRrAYpnHRVnILEIjgTIgcoKkYPdvSqslLzNlR2Js8rKRyJllM+XVXWi8C4OaYCLQruChlrJSk1ti4a05zZ5HyYBBM7J6AGdmLDwmr27XAK3aBT+mVfvov7kCwIH3FBwcYGduJUFSqJ29923wtuSvvgn4x0Tv56V91BXdmik7ovdwRpIUavdpAGi6zZQYTIQ7qE9q+FxqcktMK/wldv75+mZv6nIHDGq1N1ak99wSA7imr4lWP3MKDzM55BUXD9z8lLeeRYrSrQ30KOr1uIGv1ym8U5MMiOIgQSKDonX9jJmyI3J3j4/2spoFqelaurDYiXnv7MP12Y6wllGUbrMRKijTsuU80hmVUAGcVj9zUo+ZHLooe7h3Fk7bJv8YtM1UPiNHywxHY4e+AOqPq7uvGNyoDRIaB0ch62cgnf2RYrbsiJG2/bAgqYyE2q6lxsFEuJRssyE3KAu35TwaGRUlARxFBzM5ZhKJdmcthu3p2SEUzlKNGNzI2XU82P0BfepnzJgdEf9/+X6rt/POBm/dlhGWNU0sWEbi+mxH0N2nQ4n0/Bq5QVk4Led6Z1SkioojFcCRegxyzCKSs1PkTNKVCrj07hBSlYVpsjO3nKnPwe4P6Fc/I2ZHAr7WBt264tt3m5zvYuPN9TEROUW64cyyifT8GnHAoFRQJm4DEajlXC49l8SCBZyRCOAoPFyuMgOjTZYNthSlJMOhRsglnaYkMiCSU59l3l/P+pns4cDUvcC4jcDIFd7PU/cYM2Aw2v+bJie3SPf6bEfAAuBgSQobpOfXKD1HJYW94oBB8RyanhMQuOVcCb0yKqGWwH6uawg6IVqrnzmpx0yO0RltdkqopaiBk+U9jtplJ6VZmGAZkKZLc9XlwM4XgZOVoe8fcskrQPZHCSPsSxWK0f7ftAAlGYlABcA/1zXg3jW7fceKtAom1Bb2Sg0YdGhUFKxHRkXOEtj8d/dj9rBs3LumeVZNq585hYdBjtHJzYxEYrsFOW9qcjufwukQklzS6Qzc8DjQuoP8eqKmwcSvH5JXj2TG+hmtmWmuj0kozUgEmmXzXJxNl2Ai3Fk3SruylNBjSUxuwNmudYKuARyFh0GO0cnNeLw+Frj5aX2XNOS8qdUfB5I7APU10CXDIdJrN3IlGRQz1s9oyUxzfUxCi4yEHsGEVoW9gYIyLQTbc0ttRkVJwHlLbmfdAjgKD4Mco5Ob8Th9Qv+9jeS+WV0+Ctj2HHTPcBhhSUevYMsMzDTXxyS0ykhoHUxEctaNWloviSkNOPUK4Cg8ESk8XrZsGbp27YqkpCTk5+djx44dkseuWrUKNpvN7yMpyf9/NkEQMGfOHGRkZKBVq1YoLCzEd999p/dlaMPj9rba7lnv/RxqjorSQluls1mUkPtm1XtobM1PEYOtnNu8n2MhwAHMN9fHBCJRpKuGWVqli/tkYOuMwXh10kD8bXQuXp00EFtnDFa1ZCQGnCwqNjfdg5zXXnsN06dPx9y5c7Fr1y707dsXRUVFOHbsmOR97HY7KisrfR+HDh3y+/4TTzyBp556CsuXL8f27dvRunVrFBUV4cwZg88iUDMgT6z9kCXMzqVQlLypmalDiNTx+39T4i3Z6nVJOpDaOsGRkhS1PZ7M1CqtZFBhqMcxYsBJytgEQdB1Y4/8/HxceeWVeOaZZwAAHo8HWVlZuO+++zBz5sxmx69atQpTp07FiRMnAj6eIAjIzMzEgw8+iIceeggAUFtbi/T0dKxatQqjR48OeU4ulwspKSmora2F3W5Xf3FKSHUlib8uoTIc+zYA79wPnP459HONXOHNKujBdx1AwKUos2dqlAxcjMRwRjMIOMOpc2zUJenISLtauz0Crl70UchltK0zBlvuTZ+bbxqL0vdvXWtyzp49i507d2LWrFm+2+Li4lBYWIjS0lLJ+506dQpdunSBx+PBFVdcgccffxy/+tWvAAAVFRVwOp0oLCz0HZ+SkoL8/HyUlpYGDHIaGhrQ0NDg+9rlcmlxefJp0WqbPRxItAP/e0vo59OzBsLKxbZKBi5Gcjij0cVyXZKOjFTjoUdhr1no2RVG+tM1yDl+/DjcbjfS0/3fdNPT0/Htt98GvE/v3r2xcuVKXH755aitrcWSJUswaNAgfPPNN7jkkkvgdDp9j9H0McXvNbVgwQLMmzdPgytSSatW227X6DubRS4rvqkp2YpCz20rzMoIReCkK71n3USakkyZkQJOUsZw3VUFBQUoKCjwfT1o0CBcdtlleP755zF//nxVjzlr1ixMnz7d97XL5UJWVlbY5yqbVq22RprNYqU3NSWZNoAD8ChmNc1qpLVOBGzA8VMNKC2vNk2Gg0tQsUPXICctLQ3x8fGoqvJ/866qqoLD4ZD1GC1btkS/fv1w8OBBAPDdr6qqChkZF/9nrKqqQm5ubsDHSExMRGJiooor0IiWrbZWXi6KFqVbUXAAHsUwMatRsrcSD63/ynSBQrhDDclcdO2uSkhIQP/+/bF582bfbR6PB5s3b/bL1gTjdruxZ88eX0DTrVs3OBwOv8d0uVzYvn277MeMOK1bbdm5pC0lmTYOwCMKuadTyd7KgPdTsu+V0j2y5JC7N5gWz6UXPX4uVqb7ctX06dMxbtw4DBgwAHl5eVi6dCnq6uowYcIEAMDYsWPRuXNnLFiwAADw6KOPYuDAgejZsydOnDiBxYsX49ChQ7jzzjsBADabDVOnTsVjjz2GXr16oVu3bpg9ezYyMzMxYsQIvS9HHT2Wmay0XBRtegy14wA8sii104+VLBHptZxkhqGGwXCZTTndg5xRo0bhp59+wpw5c+B0OpGbm4uSkhJf4fDhw4cRF3cxofTzzz9j0qRJcDqdaNeuHfr3748vvvgC2dnZvmMeeeQR1NXV4a677sKJEydw9dVXo6SkpNnQQEPhMpNxKd1s0wjF30QR1LhI9/jJBsWBQrAlortf3oVphb3QNa31hU1Gz+LeNdLH/vGqrrg+26Gq/scsQw0D4TKbOrrPyTGiqMzJEVl5toqZr03J/B+rzwqimCDVXdT09p/rGjD/3f1BA5tA/jY6F7fkdvbN2JF7/zgbIGcFRk0Go7S8GmNe2BbyuFcnDTRUJifUz9DKc4qaMtScHArAqstMZp8boyTTxqwcmZzUssfwvhnY8FWl4oAmEHH6cagloqbklpioyWDosVt5JJh9mS2aGORQ+KwyN0bJ/B8rzgqimCC17FFZewbPf1oR9uM3DRT0WvoJVv8jlaUy61BDMy+zRRuDHAqPFtOcjURJps2qWTmyrGBFw1oIFCjouZ+VVP1PsOJcMw41NNPeYUbDIMdqIl0Xo9U0ZyLSndKlI6UCBQqhloi0IGYw5Bbnmm2rBrMusxkBgxwriUZdDOfGEJmGHssZ/zn0MtSePgdAQEH3NAxsUhMSbIlIK53aJilubTfTVg1mXWYzAl2HAVIEiXUxTbMqYl3Mvg36PK8eM2b05nEDFZ8Be9Z7P3vc0T4joojQcjnDBqBdckus2PpvPPPxQTzzcTnuWLEdVy/6qNkwQHGJyJEi//nlvF/b4F2KyuvWXlFxrhlJ/QwdKUlsHw+CmRwriGZdjNIZM9Fm9i4wojBotXQkZhN+rj/X7HtSXU9Nl4i+P16PpR/+H4DAmYlnxvRDu9aJ+HCfEys+/z7gOQAXMxixUJxb3CcDgy9Nx/+Wfo9DNfXo0j4ZfyjoioQWzFdIYZBjBdGsizHSpqGhWKULjEglcdnj7pd3hfU4jpQknD7nxokAQU6wrqemS0S9HW1CFgAX9OiAK7u1D3lcLBTnBiqq/vvWCsMWTBsBgxwr0LsuJlQxsxnmxlitC4wMSap12Uiuz3YgNbllwAAlkIyUJMwelo12rRN81+XxCLhjxXbJ+8id2yK3AFjOcVYvzuXEY3UY5FiBnnUxcpd3jD43hl1gpDOz7Cu0o6JGVoAz5Tc9cVXPtIBBx9tlR2U9l5ylIbkFwKGOs3Jxrtr9woiFx9ag9S7nIqXFzOLcmJzbvJ+NEuAA7AIjXandlTsa5Nak9Epvg4IeHQK+aRp1aUiqODelVUtMLeyF67MdET0frVi9qFpPDHKsQKyLAdA80FFZFxNyeQfe5R2zdCaZsQuMTCHUX9mA969st9z9CnSmRYAiLg0F+bPK1/UUacV9MrB1xmBMK/wlUlu1BACcOH0Of/3wu4CdX2YQC0XVemGQYxViXYy9SVrcnqmuoFbJ8o4Z6JXtophntr+ytQhQxKUh8fim9weiuzS0aZ8TSz/8P5w47b8sZ8TMmhxGzZyZAYMcK8keDkzdC4zbCIxc4f08dY+6wl+rLe8ozXZxlg7JFM5f2W6PgNLyarxddhSl5dURyfZoFaAYdW6L2TJrchg5c2Z0LDy2Gq32UzLq8k4421bI7QLjLB1SQO1f2dEsVNZq/yYjbo9gxR27rVxUrTcGORSYEYf8aRF8hOoC4ywdUkhN67IR2oG1ClCMtj2CVetXzLixqBEwyKHAgg75g/fr7Fu8wYKereJi5ubAe8C2Z5t/X03wIZXtMtssnUhvxkoBKf0r20jtwEYLULRg5foVI2bOjI5BDkmTWt6xxQGCxxt0bHtWv6WcQJmbZjQMPsw0S4dLaoai5K9sKy6nGInVhwJaMTDVE4McCq7x8o6YTRE8/sfosZQjtWwUkEbBh5bF1npmWbikZkhy/8q26nKKUbB+hRpjkEOhxcV736TfvEviAI2XcoIuGwURbqeXVsXWemZZzLakFmPk/JVt5eUUo2D9CokY5JA8kVzKCflcEsLt9NKi2FpulkVtpsdMS2oUkNWXU4yC9SsEMMghuSI5N0fxY2jU6RXujupysyweD/DBLHWZHqvNL4pBXE6JHNavEIcBkjyRnJuj6DFUblshJZzJ0XKzLOvHyd8PrCmjzi8iRYw6SI/IapjJIXkiOTcn5HM10nSQnxbU7qgeVvZEZj2NEecXkSpcTiHSH4MckifcpRzNnuuCgfcAvYfqNxtGzeTosLMnMuppIvk6kO64nEKkLy5XkXxabwKq6rk6A7/7X6B4gTcQMNKbechNQGUKlRGK5OtAFAXR2NOLrMkmCELM/d/jcrmQkpKC2tpa2O32aJ+O+URy0q7Zpvr6uquA5lkWmb9q4zbKyyKZ7WdDJEM09/Qi41P6/s0gh0EOaS3gnJzOQNHjwD9nha6nmbqHwQrFJKk9vcTcKIuySen7N2tyKHZEKvMRrHDZFsd6GqIAIr6nFzOhMYFBDllT03/A6qsvZFEitNeTVOGy1H5genSJEZlIRPf04t5vMYNBDlmPrI09Eb29ntS2qBNJcHsE07eiR2xPLw32frPCzztWMMgha1G6sac4m+aXxcCR7ZELOsT9wMRA59AXDHRIFasU6kZkTy8N9n6zys87VkSkhXzZsmXo2rUrkpKSkJ+fjx07dkge+8ILL+Caa65Bu3bt0K5dOxQWFjY7fvz48bDZbH4fxcXFel8GGZ2qjT0vzKZ58lJg9U3APyZ6Py/tE3r6cDj2bfA+RySfkyxHLNRtuszjrD2DyS/vQsneyiidmXLinl5S+RAbvMFEWHt6Kdn7LQAr/bxjhe5BzmuvvYbp06dj7ty52LVrF/r27YuioiIcO3Ys4PFbtmzBmDFj8PHHH6O0tBRZWVm44YYbcPToUb/jiouLUVlZ6ft49dVX9b4UMjq1G3sC3pqdxuRus6CGmG1Su7UDEUIX6gLeQl2zzJgR9/QCmk+a0mxPrzD2frPazztW6B7kPPnkk5g0aRImTJiA7OxsLF++HMnJyVi5cmXA41955RXcc889yM3NxaWXXoq///3v8Hg82Lx5s99xiYmJcDgcvo927drpfSnW4XEDFZ8Be9Z7P3vc0T4jbWi6KeWFf6hKZmr78wmZLtfhOcmSlBTqmoXue3qFsfebFX/esUDXmpyzZ89i586dmDVrlu+2uLg4FBYWorS0VNZj1NfX49y5c2jf3j9FuWXLFnTq1Ant2rXD4MGD8dhjj6FDh8AV9w0NDWhoaPB97XK5VFyNRVi5q0DzTSllbLOglJJ0uVbPSZYUsULdCNN1T68w9n6z6s/b6nTN5Bw/fhxutxvp6f5vPunp6XA6nbIeY8aMGcjMzERhYaHvtuLiYrz00kvYvHkzFi1ahE8++QQ33ngj3O7Af/0uWLAAKSkpvo+srCz1F2VmVl8m0Wpbhaa0zBCFkS4naiwihbpRIu7pdUtuZxT06KBd55K49xsAyUUxiVlVVv55W5mh965auHAh1q5dizfffBNJSRf/xxk9ejSGDx+OnJwcjBgxAhs3bsSXX36JLVu2BHycWbNmoba21vdx5MiRCF2BgcTCMknQf8ACSE6T97haZojCSJeHzarLlDFKaaGumfeD0vTcVe79FpHCaNKcrstVaWlpiI+PR1WV/1+lVVVVcDgcQe+7ZMkSLFy4EB9++CEuv/zyoMd2794daWlpOHjwIIYMGdLs+4mJiUhMTFR+AVYSK8skksP2OgM3PA607nCxTTwrH3iqr6rUtWphpMvDYuVlyhglFupOfnmX1PxsX6GumduedTl3FbOqlPy8yTh0zeQkJCSgf//+fkXDYhFxQUGB5P2eeOIJzJ8/HyUlJRgwYEDI5/nhhx9QXV2NjAxj/7JGVSwtk2QPB6bu9W50OXKF9/PUPUCfEd4ALuc27+cWCapT16qFkS5XzerLlDFMTqFuJNuetc4W6Xru4lRy8d8DGb9zuhdGk+Z036Dztddew7hx4/D8888jLy8PS5cuxbp16/Dtt98iPT0dY8eORefOnbFgwQIAwKJFizBnzhysWbMGV111le9x2rRpgzZt2uDUqVOYN28eRo4cCYfDgfLycjzyyCM4efIk9uzZIytjE5MbdFZ85p3FEorcHbCtRGpDTT23WYjUc3rc3vk7klk8bgpqBVITeN0eAVcv+kiyK8gG7xv01hmDw85AaJ1xieS5qzk3TjyODsNt0Dlq1Cj89NNPmDNnDpxOJ3Jzc1FSUuIrRj58+DDi4i4mlJ577jmcPXsWt912m9/jzJ07F3/5y18QHx+Pr7/+GqtXr8aJEyeQmZmJG264AfPnz+eSVDB6LZNYYZO7aGyzEKnnjJVlyhgnFuo2Fan9oKR2DxczLmqyHBHdy0ohqZ83GU9EtnWYMmUKpkyZEvB7TYuFv//++6CP1apVK/zzn//U6MxiiLhMouUO2Faq85DaUNPszxlLy5TUTCTanvXaPZwt26QFQ3dXkcZUdhUExDoPc4hmNxdFXSTanvUakseWbdICN+iMNVosk2iwyR1FSLS6ucgQxLZnZ+0ZqVcfjjDbnvXKuETi3Mn6mMmJRSq6CvyEuckdRVA0urnIMCKxH5ReGZeI7GVFlscgh5RjnYe5aLlMSaajd9uznkPy2LJN4eJyFSnHOg/ziUYHGRmGnvtB6T0kT9e9rMjydJ+TY0QxOSdHS77ZKyHqPDh7hShmmHmqMpmH4ebkkAXp0Y5ORKZmtIwLB/YRwCCH1JLcIypT30nBRGRYRhmSx6wSibhcxeWq8Fhh4jERWYbU9GUxh8OCZXPjchVFVjQmBRMRBaDX9GUyL7aQExGRJeg1fZnMi5kcIiIyNbHI+P29lbKO535XsYNBDhERmVagIuNQuN9V7GCQQ0REplSytxJ3v7xL9vHc7yr2MMghIiLDazr3pn+Xdpj5xh7Z9+d+V7GJQQ4RERlaoCWpNoktcKrhvOzHcHBOTkxikENERIYlNfdGboAztqALbuyTwYnHMYpBDhERGVKwuTdy3dgnwxBTmCk6OCeHiIgMKdTcm1BSW7VkkXGMY5BDRESGFO48mwlXdeUSVYxjkENERIYUzjybdsktMWVwLw3PhsyIQQ4RERlSXrf2yEhJgtJcjA3AgltzmMUhBjlERGRM8XE2zL05GwCaBTri16nJLf1uz0hJ4k7j5MPuKiIiMqziPhl47vdXNJuTI869uT7b4TckkK3i1JhNEIRwuvNMyeVyISUlBbW1tbDb7dE+HSIiCqHpxGMGM7FJ6fs3MzlERGR48XE2zrshxViTQ0RERJbEIIeIiIgsiUEOERERWRKDHCIiIrIkBjlERERkSQxyiIiIyJIY5BAREZElRSTIWbZsGbp27YqkpCTk5+djx44dQY9//fXXcemllyIpKQk5OTl47733/L4vCALmzJmDjIwMtGrVCoWFhfjuu+/0vAQiIiIyGd2DnNdeew3Tp0/H3LlzsWvXLvTt2xdFRUU4duxYwOO/+OILjBkzBhMnTsTu3bsxYsQIjBgxAnv37vUd88QTT+Cpp57C8uXLsX37drRu3RpFRUU4c+ZMwMckIiKi2KP7tg75+fm48sor8cwzzwAAPB4PsrKycN9992HmzJnNjh81ahTq6uqwceNG320DBw5Ebm4uli9fDkEQkJmZiQcffBAPPfQQAKC2thbp6elYtWoVRo8eHfKcuK0DERGR+Sh9/9Y1k3P27Fns3LkThYWFF58wLg6FhYUoLS0NeJ/S0lK/4wGgqKjId3xFRQWcTqffMSkpKcjPz5d8zIaGBrhcLr8PIiIisjZdg5zjx4/D7XYjPT3d7/b09HQ4nc6A93E6nUGPFz8recwFCxYgJSXF95GVlaXqeoiIiMg8YqK7atasWaitrfV9HDlyJNqnRERERDrTNchJS0tDfHw8qqqq/G6vqqqCw+EIeB+HwxH0ePGzksdMTEyE3W73+yAiIiJr0zXISUhIQP/+/bF582bfbR6PB5s3b0ZBQUHA+xQUFPgdDwCbNm3yHd+tWzc4HA6/Y1wuF7Zv3y75mERERBR7Wuj9BNOnT8e4ceMwYMAA5OXlYenSpairq8OECRMAAGPHjkXnzp2xYMECAMADDzyAa6+9Fv/93/+NYcOGYe3atfjXv/6F//mf/wEA2Gw2TJ06FY899hh69eqFbt26Yfbs2cjMzMSIESP0vhwiIiIyCd2DnFGjRuGnn37CnDlz4HQ6kZubi5KSEl/h8OHDhxEXdzGhNGjQIKxZswZ//vOf8ac//Qm9evXCW2+9hT59+viOeeSRR1BXV4e77roLJ06cwNVXX42SkhIkJSXpfTlERERkErrPyTEizskhIiIyH0PNySEiIiKKFgY5REREZEm61+SQ9bk9AnZU1ODYyTPo1DYJed3aIz7OFu3TIiKiGMcgh8JSsrcS897Zh8rai5ujZqQkYe7N2SjukxHFMyMioljH5SpSrWRvJSa/vMsvwAEAZ+0ZTH55F0r2VkbpzIiIiBjkkEpuj4B57+xDoNY88bZ57+yD2xNzzXtERGQQDHJIlR0VNc0yOI0JACprz2BHRU3kToqIiKgRBjmkyrGT0gGOmuOIiIi0xiCHVOnUVt50abnHERERaY3dVaRKXrf2yEhJgrP2TMC6HBsAR4q3ndzM2B5PRGReDHJIlfg4G+benI3JL++CDfALdMQQYO7N2aYOCNgeT0RkblyuigFuj4DS8mq8XXYUpeXVmnU8FffJwHO/vwKOFP8lKUdKEp77/RWmDgTYHk9EZH7M5Fic3tmI4j4ZuD7bYaklnVDt8TZ42+Ovz3aY+jqJiKyOmRwLi1Q2Ij7OhoIeHXBLbmcU9Ohg+jd+tscTEVkDgxyL4rA+9dgeT0RkDQxyLIrZCPXYHk9EZA0MciyK2Qj1xPZ4qUU3G7x1TWZvjycisjoGORbFbIR6Yns8gGaBjlXa44mIYgGDHItiNiI8Vm6PJyKKFWwht6hYGNanNyu2xxMRxRKbIAgx117jcrmQkpKC2tpa2O32aJ+Orji1l4iIrELp+zczORbHbIT+uL8VEZExMciJAeKwPtIeM2VERMbFwmMiCaH2/OL+VkRExsZMDlEAoTI03N+KiMj4mMkhakJOhoYTpYmIjI9BDlEjcvf8cro4UZqIyOgY5BA1IjdDU3OqQdbjcaI0EVH0sCbHoNiWHB1yMy/tWycgIyUJztozAbM+NninI3OiNBFR9DDIMSC2JUeP3MyLI6UVJ0oTERkcl6sMhm3J0aVkzy/ub0VEZGzM5BgI25KjT+meX5woTURkXLplcmpqanDHHXfAbrcjNTUVEydOxKlTp4Ief99996F3795o1aoVfvGLX+D+++9HbW2t33E2m63Zx9q1a/W6jIhiW3J4Qg3vk0tphkacKH1LbmcU9OjAAIeIyCB0y+TccccdqKysxKZNm3Du3DlMmDABd911F9asWRPw+B9//BE//vgjlixZguzsbBw6dAh33303fvzxR6xfv97v2BdffBHFxcW+r1NTU/W6jIiSW/TKtuTmtK5jYoaGiMj8dNmFfP/+/cjOzsaXX36JAQMGAABKSkowdOhQ/PDDD8jMzJT1OK+//jp+//vfo66uDi1aeOMxm82GN998EyNGjFB9fkbdhby0vBpjXtgW8rhXJw3kXlSNiHVMTf9HFsMR1scQEVmD0vdvXZarSktLkZqa6gtwAKCwsBBxcXHYvn277McRL0IMcET33nsv0tLSkJeXh5UrVyJUnNbQ0ACXy+X3YURKil7JS+7wPrVLV0QUAzxuoOIzYM9672ePO9pnRBrRZbnK6XSiU6dO/k/UogXat28Pp9Mp6zGOHz+O+fPn46677vK7/dFHH8XgwYORnJyMDz74APfccw9OnTqF+++/X/KxFixYgHnz5im/kAhTWvQay8Q5Qp8f/El2HROzX0TUzL4NQMkMwPXjxdvsmUDxIiB7ePTOizShKMiZOXMmFi1aFPSY/fv3h3VCgDcdNWzYMGRnZ+Mvf/mL3/dmz57t++9+/fqhrq4OixcvDhrkzJo1C9OnT/d7/KysrLDPUw9i0WvT+hIH5+T4BKq/CYV1TEQ68LiBQ18Ap6qANulAl0FAXHy0z0q+fRuAdWOBprlgV6X39t+9xEDH5BQFOQ8++CDGjx8f9Jju3bvD4XDg2LFjfrefP38eNTU1cDgcQe9/8uRJFBcXo23btnjzzTfRsmXLoMfn5+dj/vz5aGhoQGJiYsBjEhMTJb9nRCx6lSZVfxMKt1cg0pjZMyAet/f8gw3tKJkJXDpMm8DN7AGhSSkKcjp27IiOHTuGPK6goAAnTpzAzp070b9/fwDARx99BI/Hg/z8fMn7uVwuFBUVITExERs2bEBSUug3prKyMrRr185UQYwcYlsyXRSs/kYKt1cg0oEVMiCHvvAP0JoRANdR73HdrgnvucweEIpMGKjpUpNz2WWXobi4GJMmTcLy5ctx7tw5TJkyBaNHj/Z1Vh09ehRDhgzBSy+9hLy8PLhcLtxwww2or6/Hyy+/7Fcg3LFjR8THx+Odd95BVVUVBg4ciKSkJGzatAmPP/44HnroIT0ugwwm1ByhpljHRKSDSGdA9HKqStvjpFghIARMG6jpNifnlVdewZQpUzBkyBDExcVh5MiReOqpp3zfP3fuHA4cOID6+noAwK5du3ydVz179vR7rIqKCnTt2hUtW7bEsmXLMG3aNAiCgJ49e+LJJ5/EpEmT9LoMMhCldTWsYwqMm79SWCKZAdFTm3RtjwvEKgGhiQM13YKc9u3bSw7+A4CuXbv6tX5fd911IVvBi4uL/YYAUmyRW1cz5Tc9cVXPNL55B8DNXylskcqA6K3LIG8mwlWJwEGIzfv9LoPUP4cVAkKTB2rcoJNMQ+4coWnX/5LbKwTAzV9NziizXCKRAYmEuHjvUgsANPtX5cLXxQvDe+O2QkCoJFAzIAY5ZBriHCFA8p8k1t9I4NBEk9u3AVjaB1h9E/CPid7PS/t4b480MQMS7M8Ne+fwMiCRkj3cu9Rib5LFtGdqswRjhYDQ5IEadyEnU+EcIXWUbP7Krj6DiVY9RNNOmqx84Mh279dXjAe2PA5IjS0NNwMSCeL1uc8CI5YDggDUH9e2aygSS2J6M3mgxiCHTMcqc4QiWQDMzV9NKlr1EIE6aWxxgOC5+HWr9t5zOP3zxdvsmd4Ax6BFqD7BOoW0rI0Rl8TWjYVpA0KTB2oMcsiUzD5HSIsCYCVBktyibQ5NNJhoFK5KZY4aBzjAxeDmuj8BHXqYZm5KxDNj4pJYwKDKBAGhyQM1BjlEESY1tVksAJaza7rSIEks2nbWnpH6W4xDE40o0vUQQTNHTV3IJO1aDUzdE/hNzmjD486fBTZORcQzY9nDvY9ppJ+FEiYO1BjkEEVQqAJgG7wFwNdnOySzMmqCJG7+alKRrocImTlqKkgmyWjD4/ZtADZOA+qrgxykY0t3XLxx28TlMGmgxu4qoghSUgAcSDhdUmLRtiPFf0nKkZIkK3tEURDpTia1GaGm9xOXhJoGTOKSUKS7wsTzqT8u73iDdgpFnRio5dzm/WzwAAdgJocoosItAA63S8oqRdsxI9L1EGozQo3vZ7ThcYqW4C4waKcQKccghyiCwi0A1qJLyuxF2zEnkvUQddXNu6iCCtBZo2extJoaH0VLcGF2ChmtBokY5BDpQarzqX+XdmjfOgE1dWcD3i9UATC7pGJUJOoh9m0A1o+H/IyHRCZJr2JptTU+Sp9HTmYsUDDz7bvGqkHSi8kCOQY5FHP0nk8j1fk0vG8GNnxVGTTAAYIXALNLKobpWbiqZklHKpOkpFha7htmOG3fcs8nOQ246a+hA5JAwVar9sDpAHV0JtjAUhGjFZPLwCCHYoreG1RKdT5V1p7B859WBL2vnKnN7JIiXchd0il63Bs0BAtI5A6Pq6/2bk0R6g0znBofj9v70aqd/9DCppLTgOn7gRYJ0scA0sFWoABHzvmZiUl3Imd3FcUMvTeoDNb5FEr71i3xycO/kRVosUuKNCd3SadNeujOGjkbX/YZCbw+Xl73ldoNIsX9vv73liABjs37cdNfQwc4arJdwc7PTEIGmvAGctHaNDYIZnLI8tweAdv+XY2Z/9gT1nyaUEJ1PgVTU3cOOw/9LLsgmF1SpCmt5/EEK5a+4XHgg1mQnZlRU+MjlXVoKrkDcPnvvJkejzt4pkXxDKEg52c20Zi8rREGOaRYJPdcCleg5alAtNigMtx9n5Ten11SpBk99ieSKpZW+oapNACTk3Fp2RpomeSdm7PtWe9HqNqScIMUM7elm3gncgY5pIjeNS1akqqPCSacQCXcjiZ2RJHm5Bb26jWPJ1CxtNI3TKUBmJyMy7k670djoWpLVAcpxt7AUhYT70TOmhySTe+aFi2prY8JJ9AQO5+U5rRs8AaK7IgiTYk1KatvAv4x0ft5aR/pacPiEpO9yR8r9kxti0qVvmHKqfFpHICpziaEqC0JOX06EONvYClLpCdva4hBDskSznYCkeL2CCgtr8bbZUex6vMKRfUxWgQaYueT+HhynxdgRxRpTO22CtnDgal7gXEbgZErvJ+n7tG2a0bNG6aSACysbEKQImE5wVardqHPL1o8bqDiM2DPeu9nJUXCSgNNA+FyFckS7nYCepNbexOIloGG2PkUbE5O49vltI0TKRLutgp6bySpdmlM7kDEkMtbMkhlg0JNnzbqBpZazLcx6U7kNkEQovend5S4XC6kpKSgtrYWdrs92qdjCm+XHcUDa8tCHve30bm4Jbez/ifUiJram8b0qCmSKs42U9E2mVTFZ96lqVDGbYxuJ0zAN97O2rxh+rqrAFWBTqifjZmm/kp2ml34d0dppinK1670/ZuZHJLFqNsJhDObJjW5JZaNuQIDe3TQPNCQ6nxiRxTpziydMHpuVSGVdWibCZw/c2FuThhdZE2zXeJSkNGCHj02S9U706cxBjkki1G3E1Azm0YMZxbemoOreqVpf1JE0WSmThg93zClgqhv39W2i8zIWx2YeL6NVlh4TLIEK6oV/6m4sY93OF0ki4/VtHxzMjBZmok7YTQnBlGNpzRr2UWmtsA7UsyS1dMRMzkkm1RRrc0GCAKw8vPvsfLz7xXXuIRTpyJ3eWz2sMuQ1jaRdTBkfeHMvDFTrUk4tFgq02MpSGtmyurphIXHLDxWTAxKPtznxIrPv2/2fTF8kJMtCXe4oNsj4OpFH4VcRts6Y7ChAxsWJBuMFd7slRb2GnnZxYjMUODtcV/YBDXEIMWpe0zz/zcLj0l38XE25HVrj+nrygJ+X/xV+tObezD40nQktAi8KirVFSUOF5QTJFlhV24zTZGOCVZ5s1eSrTDpDtNRZYalIL0mWZsIa3JIFTkFvzV15zBwweaAk5C1HC5o5l25zTRFOiYYvcZCqUA1KU1pscN0OIPmzMosS0GRmmRtUMzkkCpyC35r6s4GzMpoPVww0K7c/bu0w85DP+PtsqOGXAIKFehpsTM6KWCGGgs9hNuBY5XMl1J6bGqqFz3b9Q2OQQ6ponQeTtM3a7lBkpLuqcYzaEr2VuLaxR8begnI6FOkY06sttuGs+zyzVvA6+Oa3x4Ly1xmWwoy2XwbrXC5ilRRshll4zdrkZ7DBc2yBKRHoEdhMEONhR7ULrvsfQtYP0HiYJnLXGYX40tBZsBMDqnSuOBXrsZv1noNFwxnCSjSHU56Bnrs1lLBLDUWWlOz7LJvA7A+QAbHj0UzX02pWQqyQveeSeiWyampqcEdd9wBu92O1NRUTJw4EadOnQp6n+uuuw42m83v4+677/Y75vDhwxg2bBiSk5PRqVMnPPzwwzh//rxel0FBiAW/7Vu3lHV84zfrUMMFAXVdUUqWgBor2VuJqxd9hDEvbMMDa8sw5oVtuHrRR7pmfUJlw9TujB6Na7GEWB2ip3SHaV/tkkxWy3wFIqfAW7Rvg7ete/VNwD8mej8v7WO+onaT0C3IueOOO/DNN99g06ZN2LhxIz799FPcddddIe83adIkVFZW+j6eeOIJ3/fcbjeGDRuGs2fP4osvvsDq1auxatUqzJkzR6/LoBCK+2Rg26xCtG+dIHmM1Ju1Hl1RapaAorW8pUegZ5alOkNS+mZvJUqWXULWLjVhtcxXOKzWvWcCugwD3L9/P7Kzs/Hll19iwIABAICSkhIMHToUP/zwAzIzMwPe77rrrkNubi6WLl0a8Pvvv/8+brrpJvz4449IT/f+4ixfvhwzZszATz/9hIQE6TfaxjgMUHvimysQeFZNsKBFy6WV0vJqjHlhW8jjXp00EAU9OviGCUplfyIxTFCrOTlGuBZL0HN37GiSs0Qi55g9670ZCDnsnU01aE5XvsF8UgGi+QbzRYMhhgGWlpYiNTXVF+AAQGFhIeLi4rB9+3b8x3/8h+R9X3nlFbz88stwOBy4+eabMXv2bCQnJ/seNycnxxfgAEBRUREmT56Mb775Bv369dPjckgGqS0fHDLerLXcmVtprY8ROpwCtb+rCfSMcC2WYMV2W7lt3nI6cJRkZqya+VIjVrv3okyXIMfpdKJTp07+T9SiBdq3bw+n0yl5v9tvvx1dunRBZmYmvv76a8yYMQMHDhzAG2+84XvcxgEOAN/XwR63oaEBDQ0Nvq9dLpfia6LQtHqzDofSCchyl7c+P3hc12vRItBjt5aGrNRuG2qa8W9XAckd5Ad0IQuVAdjigdtWmjvzpbVY7d6LMkVBzsyZM7Fo0aKgx+zfv1/1yTSu2cnJyUFGRgaGDBmC8vJy9OjRQ/XjLliwAPPmzVN9f5JPy6yMWkqySnI7l575+CD+sesHXebsSC3XKV3G07Nbi0xKzjTj9RMAwXPx5lCD/ILOh7lg5ErgVyPCOnXLidXuvShTFOQ8+OCDGD9+fNBjunfvDofDgWPHjvndfv78edTU1MDhcMh+vvz8fADAwYMH0aNHDzgcDuzYscPvmKoqb9Qb7HFnzZqF6dOn+752uVzIysqSfR5kPnKzSqGWtxpTsqeWXFL1OMP7ZmDDV5WK6nT0assnE5NTJNw4wAHkDfITC5WtWLukFzNNSLYQRUFOx44d0bFjx5DHFRQU4MSJE9i5cyf69+8PAPjoo4/g8Xh8gYscZWVlAICMjAzf4/7Xf/0Xjh075lsO27RpE+x2O7KzsyUfJzExEYmJibKfl8JnhDktcrJKwZa3mgo2Z0fN9UptUFpZewbPf1rR7PhQQZYVNisljala+pC5hYUVa5f0ZLYJyRahS3cVANx4442oqqrC8uXLce7cOUyYMAEDBgzAmjVrAABHjx7FkCFD8NJLLyEvLw/l5eVYs2YNhg4dig4dOuDrr7/GtGnTcMkll+CTTz4B4G0hz83NRWZmJp544gk4nU784Q9/wJ133onHH39c9rmxu0pfZtxVO9A5ByN2Z0ndN9T1huqEkiKnQ8qMP3/SScVn3jksao3baJ3aJKOwavdehBiiuwrwdklNmTIFQ4YMQVxcHEaOHImnnnrK9/1z587hwIEDqK+vBwAkJCTgww8/xNKlS1FXV4esrCyMHDkSf/7zn333iY+Px8aNGzF58mQUFBSgdevWGDduHB599FG9LoMUkspO6LHUoyVxeeuvmw7gmY/LQx4vFu+qvV45u7gHIqdDyggF4GQQcoqEg2ERrPaYAYso3YKc9u3b+7I2gXTt2hWNk0hZWVm+jE0wXbp0wXvvvafJOZK2jLarttIlpPg4G67q2VFWkNOpbZLs6x18aTp2HvrZ7zzC7XAKdX8jFICTAcgpEg6mOvTvAqlgpe49g+PeVRQ2MZj4/OBPhpnTonbJRknxrty5NAMXbEZN3Vm/8xh9ZXiF7+yQinFK9j6SKhK2xTUvOm5q5yrg1w8xy0CmxSCHwqK0lgXQf05LOEtmSop35V5H4wBHPI+/fvgdUpNborb+nKK/rdkhRbIH+zUWaInk+63AJwuDP9fJHzmcjkxNt72ryPqk9kkKRc8sRKglJMC7hOT2SIcWcvfUUnsd4lKWSO7CHTukKKy9j5puIpnWS95zGqEux+P2FlHvWe/97HFH+4zIJJjJIVWCBRNSIpGF0GprAznFu0pm7AQ6jxP15zCt8JdY++VhWXNy5GyRQRYWcrCfjLbvxswynE5N5oroAgY5pIrS7qBIZSG03NogVPGukhk7UrqmJWPrjMEBg6lHii9jhxRdpPXeR2YYThdqS4pgAwuJwCCHVFJaVxOpLESktzaQ2kKifeuWqKk7J+s8pIIpOR1SRhi6SCooKRwWab33kdGH02mduaKYxCCHVJEbJEz5TU9c1TMtYm++4W5toCZoCLS0lZuVil/NLUGQ0h/E2YD+XdrJv7gmOPTPpNQuv+ixvCS5PUOmfsPp5AZ43LWbNMAgR0Ox9Fe13GBi2vW/NPQu5I2FEzQ0zbqUllcHDXAAwCMAOw/9rKqd3qxDF2NeOMsvei0vRXI4nZIAj7t2kwbYXaWRkr2VuHrRRxjzwjY8sLYMY17YhqsXfYSSvZXRPjVdiMFEINHuApLbHdWYVKeYGDSIr6PbI6C0vBpvlx1FaXm1ZJeWlrVBTWnRQUZRIGdH8JKZ0p1D4vISgOY9eWEuLzXtvNIrwFHSGWaWwmgyNGZyNBDLf1XbW7VA7enzfrelJrfEgltzonrNSrY2kDu52OMRMP/d/bIyPeHUBoXKCMrtIPvrpgO4qmdHS2cUTUWL5ZdoLC9pQU19jRkKo8nwGOSEyWhbGURKyd5K3P3yroDf+7k+dMFtJMjd2kBu0HDPmt3NvicVyKqtDZKzZCY3+/PMx+V45uNy1ukYhVbLL2bc+0hNgCenMLrocf+fQ1Y+cGS7eX4upDsGOWHSai6Lmbg9Ama+sSfoMTPf2GOawC6cCcxSgaya2iC5GUGlnWGxkFE0BS2XX4yy95HcImK1AV72cOC3q4B3HwTqj1+83Z4J9BkJ/HNW8K0qOE8n5rEmJ0x61l4Y1bbyapwIka05UX8O28qrI3RG8gWqqQm3nbxxINuYktogJXU2YpZIbvjIOh2DEJdfJF85G2DvbJ7ll30bgKV9gNU3Af+Y6P28tE/gqctqA7x9G7yBTOMAJ7kD8Kv/AL54unl2qOleXHImQZOlMZMTpkjPZTGC0n8fD33QheOu6pWm89nIJ7UUNHvYZaonFzcWKJCVWxukNCOodAihFTOKpmP0uTRKKO0SU1NfI/Uc9dVA6TMyT/TCfd+5H0hKAbpebdyfr5rZSRQSMzlhCvVXtQ3eN1JrbaiodLel6AvWPXXvmt0Y3tebVZHoWZFFKpAVa4Nuye2Mgh4dAi7hKc0ISmWJ5N6fokQsHLY3WTa0Z5pneq+aLjGlnWFBn0OF0z8DLw2XzjRFm5KsGCnCICdMjVuppd4grbahotxMgFEyBnKWgjZ8VYlltwdeWnr29it0D2TVZASL+2Rg64zBeHXSQEz5TU9NnycS5LbjW072cGDqXmDcRmDkCu/nqXvMEeAAyoqIG1MS4IV8DpWMuHwVzqarFBKXqzQgNdrfqhsqDuzeAanJLYPW5bRLbomB3Y0R5MhdCmrXOkFyH6m4OKgaMCiX2m4sMUuU1609/rHrB9WTniMt5qc1G6VwWI1wusTkdobpNuDPYNtBcOsK3THI0YiSuSxmFx9nw8JbcyRbyAFgwa05hrl2JUtBjdvOm86rWXZ7v2ZzcrQKZMOZ1KzF/SNJqoussvYM7n55F569vR+GXp4ZlXMjGcLtEpMT4Ok64M9A20Fw6wrdMcjRkNy5LFZQ3CcDy39/Bf6yYR+cLmP/NS53ieb74/W+/5YuUs5Gu9YJugSy4WYEzZBRDLZ0KJry6m48AxuGXh7986UAIjGkL+RzNHoutXU7RtgOgltX6M4mCEKMLIRf5HK5kJKSgtraWtjt9mifjqmZYb8ut0fAVQs3w+lqCHpcRkoSts4YjE37nAEzDeJV6T1vJtyfqZFfk9Lyaox5YZusY5dzro9x+TqfgIB5Qy2KqEM9x6D7gL3rg8/JCWbcxuhnRyo+8xYZh2KEczUIpe/fDHIY5FhW4zf7z/7vONbv+iHkfV65Mx8Pvf6VZA2PWNuydcZgwwQOZvJ22VE8sLZM1rEZ/DkbW8DNNjtru71EqOdo2nadle/9ev14b0dVQBcyTVP3RL/OxeP2dlGFyooZ4VwNQun7N5eryJICLTfJUVpeHXMTrCNJSXdXzP6czTIvJRLbS4R6jkD1PT2uA25+KngWyCjziKw0O8mgGOSQ5UgVtsoj716cN6OO2EUmN/iMuZ9zwMyFgbcmiESXmJrnMNNGpmY6VxNikEOWIqewNRBxGaqgexqe+bg85PFGmjdjJmIXWLDOvMZi6uesdIowBWemjUzNdK4mwyCHLCXUTJxAGrdYD+zRQdW8mpihwVJKcZ8MPHt7P0x5dTek5v/F3M+Z81L0YaZ5RGY6VxPhxGOyFDXLG403zIzFCdayaTh6fujlmXhmzBUBvxeTP2e1U4SJKChmcshS0lonyjruP4dehk72xIAt1maYNxNxOiylDL08A8vj+HMGwHkpoZilGJsMh0EOWYvMP/yzM+24qqf0DumxNME6JB2XUvhzviDcKcJWZrZibDIUBjlkKcdPBR/4p+S4WJpgHZTOo+f5c0ZkpgibEYuxKUysySFLUbObN4XApRT9ifNSAEhWg8XavJSQGUR4M4gedyTPikyGQQ5ZijiHRWqxwwbvJN2Y6drRApdSIkOcl2JvUotkz4zNjAWLsUkDXK6ioIy8D1IgZtqN2zS4lBI5nJdyETOIpAEGOSRJaiduo3e+sDtKYxw9H1lWnZeitEOKGURl2IEWkG4bdNbU1OC+++7DO++8g7i4OIwcORJ/+9vf0KZNm4DHf//99+jWrVvA761btw6//e1vvSdsa/4X+KuvvorRo0fLPjdu0Bma1NYIkdqJWwtmy0IZXiQ2ZCRrUtMhxc0r5YuhDjTD7EJ+4403orKyEs8//zzOnTuHCRMm4Morr8SaNWsCHu92u/HTTz/53fY///M/WLx4MSorK33Bkc1mw4svvoji4mLfcampqUhKkl9IyiAnOLdHwNWLPuJO3NQc/1okpaQ6pMQ/mYLVG/nuCwTMIMZirVJT4fx8TcgQu5Dv378fJSUl+PLLLzFgwAAAwNNPP42hQ4diyZIlyMzMbHaf+Ph4OBwOv9vefPNN/O53v2uW/UlNTW12LGkn1NYI3Ik7hll1KYX0Ee6MJW5eGRy3AwlJl+6q0tJSpKam+gIcACgsLERcXBy2b98u6zF27tyJsrIyTJw4sdn37r33XqSlpSEvLw8rV65EqGRUQ0MDXC6X3wdJk7s1QsztEE1EymjRIZU9HJi6Fxi3ERi5wvt56h4GOAA70GTQJZPjdDrRqVMn/ydq0QLt27eH0+mU9RgrVqzAZZddhkGD/Ds2Hn30UQwePBjJycn44IMPcM899+DUqVO4//77JR9rwYIFmDdvnvILiVGcNUNEmtCqQ4oZxMDYgRaSokzOzJkzYbPZgn58++23YZ/U6dOnsWbNmoBZnNmzZ+Oqq65Cv379MGPGDDzyyCNYvHhx0MebNWsWamtrfR9HjhwJ+xyNyO0RUFpejbfLjqK0vBpuqS2eQ+CsGSLSBDuk9MWfb0iKMjkPPvggxo8fH/SY7t27w+Fw4NixY363nz9/HjU1NbJqadavX4/6+nqMHTs25LH5+fmYP38+GhoakJgYeHPGxMREye9ZhZbt3pw1Q0Sa4IwlbTUt/M/KD/HzBWCLA+qqI3qaRqIoyOnYsSM6duwY8riCggKcOHECO3fuRP/+/QEAH330ETweD/Lz80Pef8WKFRg+fLis5yorK0O7du0sH8QEI9Xu7aw9g8kv71LV7s1ZM0QUNs5Y0o5Um3if24Avnpa+n+AB1o8H4qzVZSWXri3kVVVVWL58ua+FfMCAAb4W8qNHj2LIkCF46aWXkJeX57vfwYMH8ctf/hLvvfeeX5s4ALzzzjuoqqrCwIEDkZSUhE2bNuGhhx7CQw89pKjmxkot5Hq3e3PWDBGFjTOWwhOqTbxgCrBtmTegCcg6M4UM0UIOAK+88gqmTJmCIUOG+IYBPvXUU77vnzt3DgcOHEB9fb3f/VauXIlLLrkEN9xwQ7PHbNmyJZYtW4Zp06ZBEAT07NkTTz75JCZNmqTXZRie3u3e3CGaiMLG7SrUk9Mm/tWrQQKcC8eJXVYxVsCtWybHyKyUyXm77CgeWFsW8ri/jc7FLbmd9T8hIiLSTsVnwOqbtHmskSuAnNu0eawoUfr+zV3ITY7t3kREFqZl+3cMdlkxyDE5tnsTEenE4/ZmUvas9372uCN/DnIDk+QOQLB3AnvnmOxiY5BjcmK7N9D8f2+2exMRqbRvg3eD0NU3Af+Y6P28tI/39kgS2/BDBTBDn7z4ddPvAzHbxcYgxwLEdm9Hiv+SlCMlyRS7hRMRGYrYzdR0ywRXpff2SAY6Yhs+gKABTJ8R3n2+7E3+vbdnWm6TTiVYeGzywuPG2O5NRBQmj9ubsZHcEypK7dhy2/CbDgy0WBebYVrIKfLY7k1EFCYlm15Gsh1bbhs+9/nywyCHiIhIZORNLxnAKMaaHCIiIhE3vbQUBjlEREQiud1MMdiObUYMcoiIiERyu5ksVMxrZQxyiIiIGsseznZstYwwQLERFh4TERE1xU1FlQvY5p7pzYxFKTBkkENERBQIu5mak5rDIw5QbLpbujhAMUoZMAY5REREFJpUpqZoAfDPWWgW4AAXbrMBJTO9mbEIZ8JYk0NERETBBdvq4vVx8gcoRhiDHCIiIpLmcXszOJKZGpmiMECRQQ4RERFJC7nVhUxRGKDImhwiIiKSFnYG5sKmplEYoMhMDhEREUlTlIEx1gBFBjlEREQkTe5WF7etNtwARS5XERERkTRxq4t1Y+ENdBoXGzfK1GQPB7JvNtQARQY5REREFJy41UXAicYLL2ZqDDZAkUEOERERhWbCrS4Y5BAREZE8BsvUhMLCYyIiIrIkBjlERERkSQxyiIiIyJIY5BAREZElMcghIiIiS2KQQ0RERJbEIIeIiIgsiUEOERERWRKDHCIiIrKkmJx4LAjezcVcLleUz4SIiIjkEt+3xffxUGIyyDl58iQAICsrK8pnQkREREqdPHkSKSkpIY+zCXLDIQvxeDz48ccf0bZtW9hs3m3iXS4XsrKycOTIEdjt9iifob5i6VoBXq+VxdK1Arxeq4ul61V7rYIg4OTJk8jMzERcXOiKm5jM5MTFxeGSSy4J+D273W75/7lEsXStAK/XymLpWgFer9XF0vWquVY5GRwRC4+JiIjIkhjkEBERkSUxyLkgMTERc+fORWJiYrRPRXexdK0Ar9fKYulaAV6v1cXS9UbqWmOy8JiIiIisj5kcIiIisiQGOURERGRJDHKIiIjIkhjkEBERkSXFTJDzX//1Xxg0aBCSk5ORmpoq6z6CIGDOnDnIyMhAq1atUFhYiO+++87vmJqaGtxxxx2w2+1ITU3FxIkTcerUKR2uQBml5/X999/DZrMF/Hj99dd9xwX6/tq1ayNxSZLUvAbXXXdds+u4++67/Y45fPgwhg0bhuTkZHTq1AkPP/wwzp8/r+elyKL0emtqanDfffehd+/eaNWqFX7xi1/g/vvvR21trd9xRnltly1bhq5duyIpKQn5+fnYsWNH0ONff/11XHrppUhKSkJOTg7ee+89v+/L+T2OJiXX+8ILL+Caa65Bu3bt0K5dOxQWFjY7fvz48c1ex+LiYr0vQxYl17pq1apm15GUlOR3jJVe20D/JtlsNgwbNsx3jFFf208//RQ333wzMjMzYbPZ8NZbb4W8z5YtW3DFFVcgMTERPXv2xKpVq5odo/TfgoCEGDFnzhzhySefFKZPny6kpKTIus/ChQuFlJQU4a233hK++uorYfjw4UK3bt2E06dP+44pLi4W+vbtK2zbtk347LPPhJ49ewpjxozR6SrkU3pe58+fFyorK/0+5s2bJ7Rp00Y4efKk7zgAwosvvuh3XOOfRzSoeQ2uvfZaYdKkSX7XUVtb6/v++fPnhT59+giFhYXC7t27hffee09IS0sTZs2apfflhKT0evfs2SPceuutwoYNG4SDBw8KmzdvFnr16iWMHDnS7zgjvLZr164VEhIShJUrVwrffPONMGnSJCE1NVWoqqoKePznn38uxMfHC0888YSwb98+4c9//rPQsmVLYc+ePb5j5PweR4vS67399tuFZcuWCbt37xb2798vjB8/XkhJSRF++OEH3zHjxo0TiouL/V7HmpqaSF2SJKXX+uKLLwp2u93vOpxOp98xVnptq6ur/a517969Qnx8vPDiiy/6jjHqa/vee+8J//mf/ym88cYbAgDhzTffDHr8v//9byE5OVmYPn26sG/fPuHpp58W4uPjhZKSEt8xSn9+UmImyBG9+OKLsoIcj8cjOBwOYfHixb7bTpw4ISQmJgqvvvqqIAiCsG/fPgGA8OWXX/qOef/99wWbzSYcPXpU83OXS6vzys3NFf74xz/63Sbnf+BIUnut1157rfDAAw9Ifv+9994T4uLi/P5Rfe655wS73S40NDRocu5qaPXarlu3TkhISBDOnTvnu80Ir21eXp5w7733+r52u91CZmamsGDBgoDH/+53vxOGDRvmd1t+fr7w//7f/xMEQd7vcTQpvd6mzp8/L7Rt21ZYvXq177Zx48YJt9xyi9anGjal1xrq32qrv7Z//etfhbZt2wqnTp3y3WbU17YxOf+OPPLII8KvfvUrv9tGjRolFBUV+b4O9+cnipnlKqUqKirgdDpRWFjouy0lJQX5+fkoLS0FAJSWliI1NRUDBgzwHVNYWIi4uDhs37494ucs0uK8du7cibKyMkycOLHZ9+69916kpaUhLy8PK1eulL3lvR7CudZXXnkFaWlp6NOnD2bNmoX6+nq/x83JyUF6errvtqKiIrhcLnzzzTfaX4hMWv0/V1tbC7vdjhYt/Levi+Zre/bsWezcudPvdy4uLg6FhYW+37mmSktL/Y4HvK+TeLyc3+NoUXO9TdXX1+PcuXNo37693+1btmxBp06d0Lt3b0yePBnV1dWanrtSaq/11KlT6NKlC7KysnDLLbf4/e5Z/bVdsWIFRo8ejdatW/vdbrTXVo1Qv7da/PxEMblBpxxOpxMA/N7kxK/F7zmdTnTq1Mnv+y1atED79u19x0SDFue1YsUKXHbZZRg0aJDf7Y8++igGDx6M5ORkfPDBB7jnnntw6tQp3H///ZqdvxJqr/X2229Hly5dkJmZia+//hozZszAgQMH8MYbb/geN9BrL34vWrR4bY8fP4758+fjrrvu8rs92q/t8ePH4Xa7A/7cv/3224D3kXqdGv+OirdJHRMtaq63qRkzZiAzM9PvzaC4uBi33norunXrhvLycvzpT3/CjTfeiNLSUsTHx2t6DXKpudbevXtj5cqVuPzyy1FbW4slS5Zg0KBB+Oabb3DJJZdY+rXdsWMH9u7dixUrVvjdbsTXVg2p31uXy4XTp0/j559/Dvt3Q2TqIGfmzJlYtGhR0GP279+PSy+9NEJnpC+51xuu06dPY82aNZg9e3az7zW+rV+/fqirq8PixYs1fyPU+1obv8Hn5OQgIyMDQ4YMQXl5OXr06KH6cdWK1GvrcrkwbNgwZGdn4y9/+Yvf9yL12pI2Fi5ciLVr12LLli1+BbmjR4/2/XdOTg4uv/xy9OjRA1u2bMGQIUOicaqqFBQUoKCgwPf1oEGDcNlll+H555/H/Pnzo3hm+luxYgVycnKQl5fnd7tVXttIMnWQ8+CDD2L8+PFBj+nevbuqx3Y4HACAqqoqZGRk+G6vqqpCbm6u75hjx4753e/8+fOoqanx3V9Lcq833PNav3496uvrMXbs2JDH5ufnY/78+WhoaNB0D5JIXasoPz8fAHDw4EH06NEDDoejWSV/VVUVAJj2tT158iSKi4vRtm1bvPnmm2jZsmXQ4/V6baWkpaUhPj7e93MWVVVVSV6bw+EIeryc3+NoUXO9oiVLlmDhwoX48MMPcfnllwc9tnv37khLS8PBgwej9kYYzrWKWrZsiX79+uHgwYMArPva1tXVYe3atXj00UdDPo8RXls1pH5v7XY7WrVqhfj4+LD/f/FRVMFjAUoLj5csWeK7rba2NmDh8b/+9S/fMf/85z8NU3is9ryuvfbaZp03Uh577DGhXbt2qs81XFq9Blu3bhUACF999ZUgCBcLjxtX8j///POC3W4Xzpw5o90FKKT2emtra4WBAwcK1157rVBXVyfruaLx2ubl5QlTpkzxfe12u4XOnTsHLTy+6aab/G4rKChoVngc7Pc4mpReryAIwqJFiwS73S6UlpbKeo4jR44INptNePvtt8M+33CoudbGzp8/L/Tu3VuYNm2aIAjWfG0FwfselZiYKBw/fjzkcxjltW0MMguP+/Tp43fbmDFjmhUeh/P/i+98FB1tYocOHRJ2797ta4vevXu3sHv3br/26N69ewtvvPGG7+uFCxcKqampwttvvy18/fXXwi233BKwhbxfv37C9u3bha1btwq9evUyTAt5sPP64YcfhN69ewvbt2/3u993330n2Gw24f3332/2mBs2bBBeeOEFYc+ePcJ3330nPPvss0JycrIwZ84c3a8nGKXXevDgQeHRRx8V/vWvfwkVFRXC22+/LXTv3l349a9/7buP2EJ+ww03CGVlZUJJSYnQsWNHw7SQK7ne2tpaIT8/X8jJyREOHjzo1356/vx5QRCM89quXbtWSExMFFatWiXs27dPuOuuu4TU1FRfl9sf/vAHYebMmb7jP//8c6FFixbCkiVLhP379wtz584N2EIe6vc4WpRe78KFC4WEhARh/fr1fq+j+O/YyZMnhYceekgoLS0VKioqhA8//FC44oorhF69ekU1OBcE5dc6b9484Z///KdQXl4u7Ny5Uxg9erSQlJQkfPPNN75jrPTaiq6++mph1KhRzW438mt78uRJ33sqAOHJJ58Udu/eLRw6dEgQBEGYOXOm8Ic//MF3vNhC/vDDDwv79+8Xli1bFrCFPNjPT66YCXLGjRsnAGj28fHHH/uOwYU5ISKPxyPMnj1bSE9PFxITE4UhQ4YIBw4c8Hvc6upqYcyYMUKbNm0Eu90uTJgwwS9wipZQ51VRUdHs+gVBEGbNmiVkZWUJbre72WO+//77Qm5urtCmTRuhdevWQt++fYXly5cHPDaSlF7r4cOHhV//+tdC+/bthcTERKFnz57Cww8/7DcnRxAE4fvvvxduvPFGoVWrVkJaWprw4IMP+rVcR4vS6/34448D/r8PQKioqBAEwViv7dNPPy384he/EBISEoS8vDxh27Ztvu9de+21wrhx4/yOX7dunfDLX/5SSEhIEH71q18J7777rt/35fweR5OS6+3SpUvA13Hu3LmCIAhCfX29cMMNNwgdO3YUWrZsKXTp0kWYNGmS4jcGvSi51qlTp/qOTU9PF4YOHSrs2rXL7/Gs9NoKgiB8++23AgDhgw8+aPZYRn5tpf6NEa9v3LhxwrXXXtvsPrm5uUJCQoLQvXt3v/deUbCfn1w2QYhi/y8RERGRTjgnh4iIiCyJQQ4RERFZEoMcIiIisiQGOURERGRJDHKIiIjIkhjkEBERkSUxyCEiIiJLYpBDRERElsQgh4iIiCyJQQ4RERFZEoMcIiIisiQGOURERGRJ/x+WKdsCp8+6OwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "np.random.seed(42)\n",
    "dataset = list(zip(np.random.randn(50,2)*0.2 + [0.5, 0.5], np.ones(50))) \\\n",
    "               + list(zip(np.random.randn(50,2)*0.2 + [-0.5, 0.5], np.zeros(50)))\\\n",
    "               + list(zip(np.random.randn(50,2)*0.2 + [0.5, -0.5], np.zeros(50))) \\\n",
    "               +  list(zip(np.random.randn(50,2)*0.2 + [-0.5, -0.5], np.ones(50)))\n",
    "X, Y = np.array([x for (x, _) in dataset]), np.array([y for (_, y) in dataset]) \n",
    "\n",
    "plt.scatter(X[Y==1][:, 0],X[Y==1][:, 1])\n",
    "plt.scatter(X[Y==0][:, 0],X[Y==0][:, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bd91276-3c88-4574-9ef7-543597dde6e4",
   "metadata": {},
   "source": [
    "**Question 1**: Train a linear classifier on this dataset and reports the results. Without manually transform the data explain what architecture could solve this problem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1d64cfb-a255-4924-bf39-18941486c1be",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "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.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
