mlx-examples/gan/playground.ipynb
2024-07-26 16:36:29 +03:00

479 lines
66 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Import Library"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import mnist"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import mlx.core as mx\n",
"import mlx.nn as nn\n",
"import mlx.optimizers as optim\n",
"\n",
"from tqdm import tqdm\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GAN Architecture"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generator 👨🏻‍🎨"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def GenBlock(in_dim:int,out_dim:int):\n",
" \n",
" return nn.Sequential(\n",
" nn.Linear(in_dim,out_dim),\n",
" nn.BatchNorm(out_dim),\n",
" nn.ReLU()\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"class Generator(nn.Module):\n",
"\n",
" def __init__(self, z_dim:int = 10, im_dim:int = 784, hidden_dim: int =128):\n",
" super(Generator, self).__init__()\n",
" # Build the neural network\n",
" self.gen = nn.Sequential(\n",
" GenBlock(z_dim, hidden_dim),\n",
" GenBlock(hidden_dim, hidden_dim * 2),\n",
" GenBlock(hidden_dim * 2, hidden_dim * 4),\n",
" GenBlock(hidden_dim * 4, hidden_dim * 8),\n",
"\n",
"\n",
" nn.Linear(hidden_dim * 8,im_dim),\n",
" nn.Sigmoid()\n",
" )\n",
" \n",
" def __call__(self, noise):\n",
"\n",
" return self.gen(noise)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Generator(\n",
" (gen): Sequential(\n",
" (layers.0): Sequential(\n",
" (layers.0): Linear(input_dims=100, output_dims=128, bias=True)\n",
" (layers.1): BatchNorm(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
" (layers.2): ReLU()\n",
" )\n",
" (layers.1): Sequential(\n",
" (layers.0): Linear(input_dims=128, output_dims=256, bias=True)\n",
" (layers.1): BatchNorm(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
" (layers.2): ReLU()\n",
" )\n",
" (layers.2): Sequential(\n",
" (layers.0): Linear(input_dims=256, output_dims=512, bias=True)\n",
" (layers.1): BatchNorm(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
" (layers.2): ReLU()\n",
" )\n",
" (layers.3): Sequential(\n",
" (layers.0): Linear(input_dims=512, output_dims=1024, bias=True)\n",
" (layers.1): BatchNorm(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
" (layers.2): ReLU()\n",
" )\n",
" (layers.4): Linear(input_dims=1024, output_dims=784, bias=True)\n",
" (layers.5): Sigmoid()\n",
" )\n",
")"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gen = Generator(100)\n",
"gen"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def get_noise(n_samples, z_dim):\n",
"\n",
" return np.random.randn(n_samples,z_dim)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Discriminator 🕵🏻‍♂️"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def DisBlock(in_dim:int,out_dim:int):\n",
" \n",
" return nn.Sequential(\n",
" nn.Linear(in_dim,out_dim),\n",
" nn.LeakyReLU(negative_slope=0.2)\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"class Discriminator(nn.Module):\n",
"\n",
" def __init__(self,im_dim:int = 784, hidden_dim:int = 128):\n",
" super(Discriminator, self).__init__()\n",
"\n",
" self.disc = nn.Sequential(\n",
" DisBlock(im_dim, hidden_dim * 4),\n",
" DisBlock(hidden_dim * 4, hidden_dim * 2),\n",
" DisBlock(hidden_dim * 2, hidden_dim),\n",
"\n",
" nn.Linear(hidden_dim,1),\n",
" )\n",
" \n",
" def __call__(self, noise):\n",
"\n",
" return self.disc(noise)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Discriminator(\n",
" (disc): Sequential(\n",
" (layers.0): Sequential(\n",
" (layers.0): Linear(input_dims=784, output_dims=512, bias=True)\n",
" (layers.1): LeakyReLU()\n",
" )\n",
" (layers.1): Sequential(\n",
" (layers.0): Linear(input_dims=512, output_dims=256, bias=True)\n",
" (layers.1): LeakyReLU()\n",
" )\n",
" (layers.2): Sequential(\n",
" (layers.0): Linear(input_dims=256, output_dims=128, bias=True)\n",
" (layers.1): LeakyReLU()\n",
" )\n",
" (layers.3): Linear(input_dims=128, output_dims=1, bias=True)\n",
" )\n",
")"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"disc = Discriminator()\n",
"disc"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Model Training 🏋🏻‍♂️"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"# Set your parameters\n",
"criterion = nn.losses.binary_cross_entropy\n",
"n_epochs = 200\n",
"z_dim = 64\n",
"display_step = 500\n",
"batch_size = 128\n",
"lr = 0.00001"
]
},
{
"cell_type": "code",
"execution_count": 197,
"metadata": {},
"outputs": [],
"source": [
"gen = Generator(z_dim)\n",
"mx.eval(gen.parameters())\n",
"gen_opt = optim.Adam(learning_rate=lr)\n",
"\n",
"disc = Discriminator()\n",
"mx.eval(disc.parameters())\n",
"disc_opt = optim.Adam(learning_rate=lr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Losses"
]
},
{
"cell_type": "code",
"execution_count": 198,
"metadata": {},
"outputs": [],
"source": [
"def disc_loss(gen, disc, real, num_images, z_dim):\n",
" noise = mx.array(get_noise(num_images, z_dim))\n",
" fake_images = gen(noise)\n",
" \n",
" fake_disc = disc(fake_images)\n",
" \n",
" fake_labels = mx.zeros((len(fake_images),1))\n",
" fake_loss = nn.losses.binary_cross_entropy(fake_disc,fake_labels,with_logits=True)\n",
" \n",
" real_disc = disc(real)\n",
" real_labels = mx.ones((len(real),1))\n",
" real_loss = nn.losses.binary_cross_entropy(real_disc,real_labels,with_logits=True)\n",
"\n",
" disc_loss = (fake_loss + real_loss) / 2\n",
"\n",
" return disc_loss"
]
},
{
"cell_type": "code",
"execution_count": 199,
"metadata": {},
"outputs": [],
"source": [
"def gen_loss(gen, disc, num_images, z_dim):\n",
"\n",
" noise = mx.array(get_noise(num_images, z_dim))\n",
" fake_images = gen(noise)\n",
" \n",
" fake_disc = disc(fake_images)\n",
"\n",
" fake_labels = mx.ones((fake_images.size(0),1))\n",
" \n",
" gen_loss = nn.losses.binary_cross_entropy(fake_disc,fake_labels,with_logits=True)\n",
"\n",
" return gen_loss"
]
},
{
"cell_type": "code",
"execution_count": 200,
"metadata": {},
"outputs": [],
"source": [
"train_images, _, test_images, _ = map(\n",
" mx.array, getattr(mnist, 'mnist')()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 201,
"metadata": {},
"outputs": [],
"source": [
"def batch_iterate(batch_size:int, ipt:list):\n",
" perm = mx.array(np.random.permutation(len(ipt)))\n",
" for s in range(0, ipt.size, batch_size):\n",
" ids = perm[s : s + batch_size]\n",
" yield ipt[ids]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### show batch of images"
]
},
{
"cell_type": "code",
"execution_count": 202,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAUkAAAFICAYAAADd1gwNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACX60lEQVR4nOy992+cWXan/1TOOVcxB5GicupR556R2x6PPV4H7Ngwdm0Y2AX2f1qsscB60+xixmv7O7Fn2p2mk1o5MpPFYuWc8/eHxr1dVGCrWyJVpN4HINQtFkv1Xr7vueee8Dmqfr/fR0FBQUHhkaif9wdQUFBQGGYUI6mgoKCwC4qRVFBQUNgFxUgqKCgo7IJiJBUUFBR2QTGSCgoKCrugGEkFBQWFXVCMpIKCgsIuKEZSQUFBYRe0T/pClUq1l5/jQPFtm5SUNfwKZQ2fHmUNn54nWUPFk1RQUFDYBcVIKigoKOyCYiQVFBQUdkExkgoKCgq7oBhJBQUFhV1QjKSCgoLCLihGUkFBQWEXFCOpoKCgsAuKkVRQUFDYBcVIKigoKOzCE7clPgl6vR6j0YjBYMDlcqHX69Hr9eh0uke+vl6v02g06PV6dDod+v0+3W6XXq9Hq9WiVqs9sm1IvG7wTwUFBYW94JkaSY/Hw+joKOFwmEuXLuHz+QgGg7hcLvka0Tfa7/fZ2NhgbW2NVqtFuVym3W5TqVRoNBokEgmWlpZot9sP/TudTodqtUqn06FWq9FqtZ7lZSgoKChInomRVKvVqFQqLBYLHo+HYDDI9PQ0wWCQSCSC1+uVrx1srjeZTKhUKprNJsVikXa7TalUol6vA5DNZh9pADudDlqtlna7Lb1I4YEqXqXCoxD3qEajQa/XP/T9fr8vvwQqlYp+v7/jvhL/3+v15P8rfHtUKhVarRaVSiV/R+K/+/2+PGEKBn8fD/6+9oqnNpJarZZgMIjVauXVV1/le9/7Hm63myNHjmC1WjGbzTte3+/35c3n9XrRarV0Oh2azSb9fp9Wq0Wn06FSqZDL5eTNKH4GoNlsUigUqNfr3Lt3j3g8TiKRYHl5mU6nQ6vVUm5eBYlarSYUCuFyuZidneW1117DZDKhVn8Zkm82mzQaDRqNBrlcjk6ng8lkQqfTUS6XSafTtFotGo0G7XabeDxOPB6n2+3Sbrfp9Xq022263e5zvtKDh9vt5uTJk9jtdvx+P1arFafTic/no1arcePGDXK5nHx9tVollUrRaDRIJpNUKpU9/4xPbSQ1Gg1erxefz8fJkye5dOkSJpNpx034qN0ZwOFwYLfbv/bfGPQ++/0+9XqdXC5HtVrF6/WyvLzMnTt3iMVi1Ot1Op2OcsMqSFQqFS6Xi4mJCb7zne/wt3/7tzgcDjQaDSqVinK5LL82NzdpNps4HA5MJhOJRILV1VUajQaFQoFGo4FWq5XhoUajQbfblV8K3wybzcaJEycIBALMzMzg9/sJhULMzMyQy+X453/+Z6LRqHx9Lpfj/v37lMtlSqXSwTCSBoOBY8eOMTc3x8zMDAaDQbrPT8Kg0Xzc9x/8f61Wi9lsRq1WMzk5iclkwul04nQ6KRaL3L59m0KhQK1Wo1arPdX1PW/UajWBQAC3243D4SAUCtHpdFhZWaFYLNJsNqUX/jj0ej1+vx+j0Sj/ThxrtFotHo8Hq9VKq9WSybStrS1qtdq+3Yh7Sb/fp1gssr29TTKZlJ6JzWZDr9ej1Wrl2gQCAelJ6vV61Go1Go2GdrtNrVaj3W7j8/mYnJyk3W5TLpdpNptsbW2Ry+Uol8tkMhnlJDOA0+kkGAxiMBiw2WzodDosFgsWiwW/38/Zs2dxOBwEg0Hsdjt2ux2VSoXRaGRqagqHwyHfq1KpEAqFyOfzFItF0un0nn/+pzaSVquV73//+/ze7/0eJpMJi8Wy56KeOp1OeqFut5tut0u9XqdcLrO1tcV/+S//hcXFRaLR6IE3khqNhuPHj3Pq1Cnm5+e5dOkStVqNf/iHf+DOnTtks9mvfShtNhuvvfYawWBQ/p1arZbG4dy5c0xMTFAoFEilUqRSKX7+858TjUZZWlo68Eay1+tJAxkIBKS3qNVq0el0sgLDZrPhdruBrzaRSCTC/Pz8jjhYt9ul0+lQr9dJp9OUy2U++OADlpaWWFpaolAoPDLh+KISiUS4dOkSTqeT6elpnE4no6OjjIyMyBixRqNBrVbv+LJarbz88ss7PHQRD06lUty/f5/bt2/v+ed/ZtltEXQVgVWRcBkMroobT7wevrxosSji+4Nfu/178KURAeTN3mw2CYVCVCoVisUiiURi3wK8e4FKpcJgMGCxWLDb7Xi9XhqNBuFwmHK5jNlsxmKxfK2RjEQiBAKBHe+r0+kwGAz4/X68Xu+OUq1IJEK/3yebzZJMJg98rFcch2u1GtlsFp1Oh9frlWGhwYTBIFrtzkdk8PpFgtFkMhEMBqlUKmQyGXQ6Hb1e74U8fqtUKumBC288FAoRDodxuVyEQiHp3FitVvr9Pu12m3a7TbVa3bG5qNVqdDqdNJhWq1V+r9FoPLa08Fnz1Eay2Wxy584dzGYz4+PjTE9P02w2icVi1Go1Op0OnU5Hei5i8YRx6/f70v3WarXyuC5qLp/UK9VqtfJm/eEPf0gmk+HHP/4xsViMdrv9tUfSYUasnVgzq9XKH/7hH/L666/TarVoNpu7/rxOp8PtdmMwGICvkmfiy+l0AmA2m2WCw263UyqV+PWvf43ZbCabzbK8vPy1/9awE4vF+PWvf00oFEKtVjMxMYHVasVms33j9zIYDLjdbux2O6+//jonTpzAYrFw+/ZtGePsdDp7cBXDi9lsZmRkBJvNxvnz55mZmWF0dJRTp05hNBoxm81otVqKxaI8pWxtbVEqlfj8889ZW1uT72UwGBgdHcVut/MHf/AHvPXWW89l9MRTG8lut0smkyEajWK1WhkZGaFWq5HJZKhWqzQaDVqt1g632mKxoNPppNHS6/X0ej10Oh3dbleWaOj1+h0P9KBH+iAivmaxWJieniYQCBAMBuWu/nWxz4OA8NK1Wi0TExNP9T4P0uv10Gg0mM1mTCaTjFEuLy9z9+5d+f2DTrVaZWNjg2azSTabxePxyE36wQQh8NCJRtyPgNzw+/2+LHW7efMmZrOZZrP5kFd62BFepMvlwuVyMT8/z+nTpwkEAkxPT6PVauU9nM/nyWaz5PN5VldXyeVy/O53v+PWrVvy/cxmM0eOHMHn83Hq1KmH/j1xAt3rk+JTG8lGo8HVq1fZ3t7m3r17XL16lVarJdP09Xpd3jDiITMYDDtuPL1ej91ul56kOAaazWZ0Oh0ej0fuQiaTCZvNxsjICAaDQR6VBGq1GovFglqtxu124/f7ZXBdlBMdJLrdLisrK7RaLdLptLw+nU6HRqPB5XLh8Xjk2j3qwex0OuTzeRqNBtVq9bFxWrfbTTgclp68TqcjEAgwPz+PVqvl5s2be325e06lUmFtbY10Oo1WqyUQCDA6OsrY2Jh8Tb/fJ5PJUCqV8Hg8TExMoNfrMRgMaDQafD7fjtpfYEcNptFoxGg0vlBGcnR0lPHxcYLBIC+//DIej4fZ2VlCoRBWqxW1Wk25XOaTTz4hkUiwsbHBxsYG1WpVVqp8kySM0WjktddeQ6/Xs7i4yJUrV/bMa38mRvLKlSuoVCocDgcul4tut0ur1aLb7coOmkEe9ASFByhuMq1WK5MKFouF2dlZnE6nLDUSR0KNRoNOp9vxfhqNBqvVisFgwOv1EgwG0Wq1ZDKZA3n06Xa7LC4usrKywtbWFq1WS3p6er2emZkZjhw5gl6vx+l0PjJOU6/XWV1dpVAokE6nH3szzs7OYjKZMJvNcrMKhUIsLCzQarX2LQa0l5TLZSqVChqNhrW1NfR6PXNzcxw/flzeR91ulzt37rC1tcXRo0d54403sFgsOBwOjEYjR48exePxyNeLWKa4H180I6lSqRgfH+fNN99kYmKCH/7wh3i93odyC8VikZ///OfcuHGD9fV1Njc3dxTqfxMnxmQy8dZbb3H06FH+6Z/+iRs3bgyvkYSvLq7ZbFKpVGQw9kmLbPv9Po1GA41GQ6fTQaPRyI4aUbxbqVSoVCrk83lKpRI2mw2Hw4Hf75elHCaTCfjqphUlM/1+n9XV1Wdxqc8F0Z9eLpeJxWLyIdRqtbRaLSqVCnq9HqvV+sgjsShRqVQqFAoF8vn8I/8dvV5PMBjE4XDIGLFYy8P0wIsMtThdFAoFYrHYDiOZz+eld7O6uorRaJSbr91uZ2RkRBpElUolEzWijKperx/Ik8s3QaVSYTab5X0zMTFBOBzGaDSi0Wio1+u0Wi0KhQLb29vE43G2trbIZrMPJWkehdFolDFNn8/30PeFndjrMNAz7d0WR2vgG+0OooQH2LH7iK/t7W00Go38cjqdfPjhh7hcLr773e8yPz+P3+9nfHxcZiPVajVTU1O89dZb3Lp1i5s3bx7YciBR9hCPxykUCjuMlhAREce9RyE6mcSD/Lgdd3l5mXw+TyQSwePxYLFY9uyanjf9fp9ms0mr1WJlZYVoNLpDV6DZbEqNgPX1dbnmOp2OarWKz+fD4XBIYyk6cvL5PFtbW7LY/DCj1+sZGRnB5XLx8ssv88Mf/lBuJt1ul0QiQTqd5qOPPuIf/uEfKBaL5HI52bn0dbjdbv76r/+a8+fP43Q6n9u88GdqJAd7Wr/Nzz6OBzOq9XodnU5HsVgkmUzi9/sfWQZjNptlqcFhSDq0Wq09FfPI5XIUi0VsNtsLUb4iAv7C83sUQkQFvipJKZVKtFotqR3wYP2kML6HFRGzNpvNeDweGQbzer2o1Wra7TatVot8Pk8qlSIajbK4uPjE9bbi9GI0GgkGg4yOjj70GnH6rFQqe15x8UyN5H7RaDTY3t6mUCjwySefkEwm+c53vsPs7OyObh+j0SiLzkWiQxHBeDxms5lAIIDf7z8U8cdniU6nIxgMyqSh1+uVCUL46uT0ItxbMzMzvP3227jdbubm5nC73UxNTaFWq8nn81y7do1sNsvvfvc77t27x9bW1kN5id2w2+34fD7Gx8d3dIkNUqvV+MUvfsEHH3zA5ubmnnrtB9JItttt8vk85XKZxcVFSqUS4XBYej/iRhWlHSJ+p9FoDnRh+V4jkj+i0kDhK7RaLW63G7fbjcfjwW63y2qCF8lAAoRCIS5dukQwGOTIkSM7pBArlYrUUfjXf/1Xrl279o3f32w2EwwGH2pwGKTVanH16lV+8YtffNvLeGL2/UkQN5vJZMJgMDx2pxhE1DiWSiVKpZIMkGu1WlmJr9frpZsvFrbVaslaTUVK7esxmUz4fD48Ho+sVRWqK4VC4YU4gj+IiLE5nU4uXLjAyMgIU1NTOzQKOp0Om5ubbG9vs7W1dSgTNiqVCpvNJhs2AoEAXq9XNiisra2xsrJCLBbjypUrpNPpHeo9T/L+drsdo9HI/Pw8b775JuFwWDY6CETrcSKRoFgsPstLfCz7biT1ej1TU1NStEGUCuyGMJJLS0usrKzQaDQoFouyTtDr9WI0Gmk0GrIUQ6VSUa/XZTZcZNsVI/l47HY7ExMT+Hw+qfWZy+VYWVkhHo8fyBKqp8VqtTIxMcHIyAh/9md/xsLCAna7HavVKu/bdrvNzZs3uXz5Mrdv3z6U66RWq6WI9szMjCzLU6vV9Ho9Pv/8c/7X//pfpNNp7t69+0TZ60E0Gg2BQACfz8f3vvc9/uN//I/YbLaHnKhMJsN7770ns+X7wb4ZSVEDabPZCIVCMivm8Xh2/bnBjKPI0DabTUqlEmq1mpGREVm28mBhuTCSlUpFGfOwC6Im0mKxyJIOUb4lyq7K5fKh9JAehwjPCDEGkfEX3o5KpZJVGaVSiXQ6TTKZPNTrZDKZsNvtO5oZ4Mtns1arkUqlZHnPk8YgxWnQaDQSiUSIRCKyv1uU9MGXCTQhyi30PL9JnPNp2Dcj6XA4GBsbIxQK8Vd/9VcsLCyg0+meKEEgDF+1WpX1Z+12G7VaLQufRd2kUBPpdrusra3x3nvvyQVVjOTDaLVaJicnCQQCHDlyRIo+VKtVWq0Wi4uLfPrpp7Jr6UVArVbj8XhwOBy88sor/PVf/zVut5vx8fEdyZpCocCNGzdIpVJ88MEHfPbZZ9Tr9UMZlhCSfXNzc7LvfZBsNsvi4qKsjXxSfD4fr7zyCj6fj7feeov5+fkdOgPwpRFOp9OkUimuXLnCz372M5LJJNls9pld327sm5EUPZ1CXHNhYUF+75voSX6T15fLZRKJhFSbVngYUXQfCARwuVxSkbtUKlGr1cjlciSTSdlBddgR9aYWiwWn00kkEuHYsWM7EjXwVQlKIpFge3ub7e1tEonEc/70e4cYzyJK6gaNpCijehKJuAdroC0WC2NjY3Kdjx8//sifE/diKpVic3OTVCr1TK9vN/bNSNrtdmZnZ4lEIg+NdNgLVCoVPp+Pubk5otEom5ubUi5L8Si/MgZms5mFhQXOnj3L/Py8jO3euXOHRCLB5uYmjUbjoVkjhxGbzSZFXs+dO8fU1BSzs7MyMSgMQ6lUkio277///qE3kPBluGx2dpY33njjW5eImUwm5ubmpEr8+Pi4HPVis9nw+/2P/Ller8fa2hofffQRS0tL+36i2TcjabPZmJ6eJhQK7ZuR9Hq9HDlyBEA+/Ery5kuEnqTJZGJhYYE33ngDl8uF0WikXC5z584dlpeX2djYeGFCFWKUQCgU4g//8A85c+aMVMEXJ5Rer0epVGJra4v79+/zwQcfsL29/dhi9MOCRqNhZmaG119//Wu1Xh+HyWTi1KlTTE5O8sYbb/Daa689pCP7KPr9Puvr63zwwQdkMpnDayQHOxIajQa1Wk32Xn7dIg0mbwb//3EM6iSOjY3R7XY5ffo0+XyeRCJBqVSi2Wwe2DbFZ4Fer5c1fw6HQ8rqN5tNqtUq8XicaDRKqVR6IQzkgwgNz8F60cFW216vh16vx+v1yv7ver0u594cNnq9HltbW1y/fh2Xy8XIyIhcG5VKxcTEBN/97nd3PW47HA4WFhYIh8NSuWq3Z7nX61Gr1eRMq2w2S7lc3vewz74ZSdHeVS6XSaVSsu7KarVKGf1H8Sg9v90Qrxc738jICLlcjmPHjpHNZvnNb37DvXv35FHysGYivw6bzcbCwgLBYJCpqSlCoZAUKEkmk3z++edcvXr1UD7wj2NwIwdkElB8T/zZ6/XodDrYbDYuXrxIoVBgZWVF1gYmEolDd1+1Wi1+/etfs7q6yiuvvMLf/u3fSqFitVrNH//xH/PKK6/s+nyKWK8QyP46Z6fZbLK5uUkul+PevXssLi5KEe/9ZF+NZKVSwWAwkM1mUavVUkRAHPsGaxwHGbxRhejpk7jpRqNRBttrtZocPJTJZKhUKs+tYf55ItbLYDDIvltR0lGr1SgWixQKBYrFIqVS6Xl/3H2l2+3K0bJizKwodXlQs1Qcw8WAtcG+ZDGxU8Rxn8eD/awRozx0Oh0TExOykFsIadvt9ocKvwWDo3dFTkCcJkUJ0KNUprrdrkzWlEol6vX6cznV7JuR3N7e5te//jUGg4F//dd/xWQy4fF48Pl8WK1WRkdHZcP84CyLBw1Zv9/HYDDgcrnQ6XQ4nc4dMc4HB5nDl8ZSVO+//PLLjIyM8MEHH7C4uPhCZGwHETNxpqenuXTpkqxNA1haWuJnP/sZsVhsX7OHw0KpVOLKlStyIFi9XmdkZITjx4/Lk45KpZIi0M1mk4mJCdrttjxuZzIZKUu3urpKsVhkbW2NaDS6qwLTsCOGb5XLZemkeDwezp49SyAQkM/yo4jFYty4cYNKpUI8HqdarZLJZMhkMiwsLPAf/sN/eGTSJpfL8X/+z//h5s2brK6uPrewz74ZyUKhQKFQ2PF3YsSCy+Xi6NGjUqfvcYstEIo/QiB2sOj0wTEN/X4frVaL0+mUxsFut7OysnKoNBKfFFFT6vP5OHbsGCMjI9IDSCaTfPLJJ/JheNFoNBpsbGxgNBpZXFzEbrej0Wg4evTojnCQGIcKSIUa0faayWSIxWLk83msVqssMBfdIQe1ukLomYr7ot/vS7k4QIpcP+p0VigUuHPnjpyZnc/nWV9fZ2Njg+9+97v85V/+5SONZKVS4fLly/zud7/b24v7Gp6rikG9Xiebzcq4l9FoZHNz82uHMhmNRllwGggEsNvteDweIpEIRqNxR0/pIKImUKVSMTIywszMDMVikVQq9UIUSos4cCgUIhAIyF5c0ckgjtqVSuXAejzPgm63y+bmJhqNhmw2S6FQwGazEQgEMJvNcobLoDK+CP9YLBZ8Ph9ms5l2u02xWMRiseD1ekmlUty8efPAZ8Lr9TqJRIJqtcr777/PvXv3dm0xjkaj3Lp1i2q1SiKRoFaroVKpCIVCMoEzzDzXTyek9FUqFaurqztutt3QaDRS2cfr9WK32zl58iRvvfUWXq9XduE86uf8fj9ut5v5+XnOnj1LMpmkWq2+EEYSkLNHJiYm5Npls1kqlYpsrRO97i8qnU6H27dvs7KygsVi4Ve/+hUul4uLFy8SDoc5evQoc3Nzct7SYJZW9HX3+31mZmbodrscPXqUlZUVrl27xurq6oE3kpVKRRq6e/fu7ZiV/ShEmEEkvQApFBKJRIZelu+5GslB2bJvEhsUwp6iREOMeFhfX6dWqxEOh4EvjwBi6Ji4iUUQXgjyirERhxmRqBFD1QZLMPr9PsVikXQ6TT6f3yEm+6IyqBMgEoWdTkeKfIhkoNFoxOVySU0CscZCKV6r1dLr9XA6nfj9foLBICMjI+j1evL5/IE1lqIKAPhWJw6xNna7HbPZ/JBxFXoB29vbQ+G8DLef+xhE73an05FlF7lcjtu3bxMMBsnlckxMTDA9Pc3k5KT0PAc9Vb/fz6lTp7Db7Xz22WffaFLbQUOv1zM+Po7T6eT111/nj/7oj+S8lmq1yqeffsq1a9e4c+cOxWKRZrP5wiW0HkTcX+12m2q1ilarJZfLSUVuMYwtHA7jcDh4+eWXpbrVxMSE3HhFz7M4oqvVapLJJP/4j/+4Y3zqi4Ro9Jibm2N0dPQhT/LmzZv85Cc/IRaLEYvFntOn/IoDaSThq3EP4mGu1Wqk02nK5TIbGxtotVo8Hg+tVmvH/G748pdkMpnwer0UCoWhj4k8LRqNRmZsQ6EQY2Nj8ogoxv+ur6+TSqVemB7tr0OccsSGDDw0fsBqtZLJZHA6nYTDYekZdbvdHWEjs9ksY5Tz8/NSLf9FxmQy4XQ6d5T/iNNLNpvl9u3bpNPpoWj4OHTWoVKp8PHHH7O4uCir8z0eD0eOHNkRp3S5XBw5coRut/tEwr8HGaHhOT4+LqfZNRoNtra2yOVy3L17V3qRh60Iei9ptVokk0mKxSLvvvsud+/e5dSpU/R6Pex2O+FweEd5msFgwOfz0ev1dlRkvIg4nU45p1un09Hr9WRHzfr6OmtraxSLxaFoZjh0RrJarfLFF1+g1WoxGAw4HA7Gx8eZnJzcYSQdDgcOh4NqtfpCGMnx8XHm5+cJBAKy+Hlzc5NEIsHS0hKLi4vP+2MeOFqtFplMBpVKRTqdRqvVUigUiEQi+P1+qaok0Ov1eDweut2uVH5/EVGpVDgcDkZHR2VsXJRPCZWfaDRKtVp93h8VeA5GUmhA6nQ6/H4/gUBAjooVSYRKpUKj0aBUKsl2xm8TIG6329RqNZrN5o7j9ouCmO4nBnyNjIxgsVhk8fPi4qIcqKbw7RlMZBSLRdbX12m32zvkAAVPUr1xWBHPvNVq3SFiLNTNq9WqrLQYphPNc5lxE4lEcDqdvP322/zhH/6hDIZ3u12uXbvG+vo6W1tb3Lp1i1KpxMbGxhMXN4vMmVarpdFokM1mpQjB415/WNHr9djtdgKBAKdOneI73/mObA9dW1vjpz/9KZubm2Qymef9UQ88nU5H1lf+67/+K5OTk1y4cIFQKPS8P9rQYLFYePnllxkfH+eVV15hbm5OPqvNZpN4PM7S0hKpVEoxkkJ8NxKJMDo6itFoxGQyybiE6PNMp9OYzWbK5fITl+kI70mr1coZGaIkY5BOpyMHyg/TL+RZYjAYcDqduFwuKbtfLpdpNBpy185ms0NRZnEYEH3a9XqdZrN5aO+rb4sYh+Hz+XaMwYCvRIyLxSK1Wm2oStD23Uja7Xb+/M//nPPnzxMOh2Xngjhuz83NEYlEqFarvPnmm1QqFZaXlykWi0+0cGq1Gr1ej1arZXp6momJiYfmZQBsbW1JzcTDKuQwMzPDn/zJnxAOhwkGg1KkYGNjg83NTcrl8qEdN/C8sFgsRCIRgsHgIxsaXmT0er3sdHO73Tu+1+12SSQSLC8vk06nh2qD2XcjaTQaOXXqFG+++ab8u0Hj5/f7d/RxCpEBETf7OkOpVqvluM9wOEwgEHjkv5PP51laWpLK24cRr9fL+fPn8fv9suSkWq3KwnGhwqTw7BDeu+j7fpAXWfR50JO0WCw7Tne9Xk82NZTL5aFao6HPbot6R1FK8SR6kmLS3YMK6EIctVarcf/+fVlEPixZtGeB6M82Go34fD7cbrcMjne7XQqFAtFolHQ6rRjIZ4hWq5VjV48dO0YoFHrIEJRKJW7dukUikSCfzz/HT/t80Gg0suNL6DO0Wi0KhQK5XE7OLR82oeehN5I6nU4Gv5904QaLxgcRLn0qleLy5cv86le/olarfaPpbsOOWq2WYgORSEQKgKjVatmhtLi4SDQaPVTX/TwRozD0ej2jo6NcvHgRt9v9kFBLJpPho48+IhaLHeoOr8eh0+mIRCJMTU3JZ7Ner8tStJWVFSmJ9kIbSTEjJJvNYjAYdrQLPopHiep+k+mK/X5fzo+u1WpsbW2xvb1NJpOh0WjIHt3DgEhaidY4ERdTqVRStCKdTpNOpykWi0os8ikZjH8LsZBBdSVx3BbjHur1uhyNelhDPI9Cq9Wi1+uluPPgs16r1VhbWyMejw9tM8O+G8l6vc6VK1fodrtMT08zMzODVqvdkel61mQyGS5fvkwmk+HDDz9kZWWFeDx+qDKQGo0Gg8GA3W7nD/7gD3j77bfxer24XC5ZYB+Px3n33Xf56KOPpAK3wrfHaDQSDAax2+289tprzM7OMjc3RzgclmIXYtxqvV4nGo3y8ccfE4vFXii9TrvdzujoKJOTkw+FwDY2NvjP//k/s7a2NrRCz/tuJLvdLtlsllgsJntexe4ivr5uLMPjEG76YN9tr9eTisjJZFK2PA1bwerTIo58BoOBcDgs2zCFeEA+n5drkE6nh+o4c9AQY0aMRqMssRobG2N2dlZOAxVeZL/fl7ODSqUSmUyGbDb7nK9gfzEYDLjdblwul9RJEM9otVqVx+xhZd+NZK1W49NPP2VpaYlr164xMjIi1VRMJhPBYFDeeMFg8InFJ+r1OqVSiUajQSwWkxP/UqkUmUyG27dvS/GLYrF46OTAjEYjo6Oj+Hw+qakpRCzE1LlyuazEIZ8SlUrF0aNHOXr0KF6vlxMnTmC325mZmcHn82Gz2WQHiYh3f/zxx3zxxRcsLS0dqiThkzI7O8vf/M3fEAwGZX4hn8/LjXvYE4j7biQbjQbXr1+X/ZtOpxOn08mRI0dwOBwcO3aMsbExRkdHHzus/HHvm8vlKBQKXL9+XRrGe/fuyQmA7Xb7wMrnfx3CgxSbzGBdqIiHVatVxUg+JSqViqmpKS5dukQ4HObixYtSeHew5Kfdbss1v3btGj/5yU8ol8tDoWqz34yPj/Mnf/Insjay3+9TKpVkAksxko9BCJuKnVXMBen3+ySTSdbW1qTkGTw8u+ZByuUyhUKBarXK6uqqHCAvlETEDJLDaCDhyyLmubk5RkZGHirUFWvdaDSG/oY8CIh7S6VSkcvl6PV6Up+zXC6Tz+ep1WqynXZ1dVUayMMU4tkNMcrCYDA8chpiJpPh/v37RKPRoVfBf+4zbprNJvl8nmQyiUql4rPPPpMdON9E1l3EH4X+36Aw76AAwWHF5/Pxgx/8gJmZGbxe747vdbtdqtXq0EhPHWT6/T5bW1t8+umnpNNpIpEIPp9Pdo9tbm7yxRdfkMlk5Gui0Sjb29typOqLgBAb9vl8hEKhHV52r9djcXGRn/3sZ3JWzjDz3Mc3PI0MvMJXaDQaOT1So9HQ6/VoNpvU63VyuRzlcplqtTr0u/awI7LVhUKBbDZLPB6Xa1qv19ne3mZ7e5tsNksymZSTJ1/kda/VaiQSCZnR73a7JJNJMpkMpVJp6DeOoS8mV3gyhMK41Wql2WxitVq5c+cOv/3tb0mn03z88cckEgkqlcqhDTnsF/l8nkajQSKRkCNoTSYTWq2WarVKLpej1WqRy+VkLe6LRq/XI5lMylHS169flxqavV6PaDTK1taWnKk0zChG8pAgJNBKpRIGgwGNRkM0GuWTTz4hk8nIOK3C0yPqHnO5HFtbW8/74wwl/X6fSqVCpVIhm81y79695/2RvjWKkTwkZLNZfv3rX+N2u7FarRiNRlZWVtjY2FCy2goKT4Gq/4Rnr8MsTvtN+bbH1b1cQyHsMViI3+12ZcnTsB2xh3ENDxrKGj49T7KGiid5SBA96goKCs+WJ/YkFRQUFF5EHi29o6CgoKAAKEZSQUFBYVcUI6mgoKCwC4qRVFBQUNgFxUgqKCgo7IJiJBUUFBR2QTGSCgoKCrugGEkFBQWFXVCMpIKCgsIuKEZSQUFBYRcUI6mgoKCwC4qRVFBQUNiFJ1YBUuSVvkKRqHp6lDV8epQ1fHqeZA0VT1JBQUFhFxQjqaCgoLALipFUUFBQ2AXFSCooKCjsgmIkFRQUFHZBMZIKCgoKu6AYSQUFBYVdUKYlKigoDD0P1nbu5/xCxUgqKCgMJTqdDp/Ph9lsZmFhgdnZWUqlEhsbG1QqFZaWlkin03v+ORQjqaCgMJQYDAbGxsbw+/381V/9Ff/m3/wbotEov/nNb4jH45RKpcNtJFUqlfzS6/XY7Xa0Wi1qtRqVSoXJZMJms6HRaB77Hv1+n1arRafToVgskkwm6Xa79Hq9fXXHFQ4ORqMRq9WKWq1Gq9WiUqnkPdNut6lUKnS7Xfr9vnIPPSdUKhVqtRqj0UgoFCIcDuNyuTAajWg0GjqdDq1Wa99+P8/FSGo0GlQqFTqdTrrUL730Ena7HYPBgE6nY3p6mpdeegm9Xi9/bjAu0e/36fV6pNNpyuUyH3zwAf/7f/9vKpUK1WqVbrf7PC5NYUgRD57f7+fUqVNyE9br9VSrVWq1Gtlsltu3b1OpVOTmq7D/6HQ6jEYjfr+fN954g7m5OWZmZgBoNBpsb28Ti8WoVqv78nn2zUgKr1GtVmMwGNBoNBgMBoxGIx6Ph3A4jNPpxGg0otfrmZ6eZmFhAYPB8NDOLt6n2+3idrspFousra1ht9sBaLfbtFotxaN8BIMevNisxJ+Cfr9Ps9k8VBuNXq9Hr9fjdDoJBoNYLBYcDgd6vZ5KpUKlUkGr1RKNRgEol8vyvlPYXzQaDUajEbPZjNfrlb8v4e1Xq9V9dYT23EiKB9JqteJ2u7Hb7Zw4cQKv10sgEJALEA6HpfFUq9XYbDZarRaVSoW1tTVKpZK8me12OxMTE5hMJkwmE36/nwsXLtDr9chkMnz22WekUilSqdS+xCwOAiKUYTabMZlMuFwujhw5gtVqJRKJ4HK5UKvVaDQaUqkUP/3pT9nc3KTdbh94Y6nT6XjllVc4efIkIyMjnDx5Um7GGo2GdrtNu92mVCpx8eJFCoUC77zzDrdu3aLValGv1xVjuY+43W6OHDnC+Pg4ExMTRCIRAHK5HLFYjLt37xKLxSgWi/vyefbFSGo0GsxmM8FgEK/XyyuvvMLU1BSTk5PMzMw8Urqp2WxSrVYplUqsrKyQSCRIp9NkMhkCgQBqtRqn08nExAQOh4O5uTlcLheJRIJSqYTRaKTRaChGki9/B1qtFo1GIz2okZERLly4gM/n48SJE4yMjKDVatHpdCwvL/Ppp58Sj8fp9XoH3khqtVqOHz/O97//fYLBIPPz8+h0uodeV6/XOXHiBLlcjmg0ytraGiqVinq9/hw+9YuLzWZjYmKC8fFxaTNyuRyFQoFsNsvGxgbxeJxms7kvn2fPjKQ4EkciEbxeL+FwmBMnTuB0OpmZmcHv92Oz2Xb8TL/fp1ar0Ww22d7e5v79+xSLRW7fvk02m6VUKlEqlchkMvKordfrsVqtANjtdmq1GmazGaPRiFb7YifvhRdvNpuZn5/H5XIRCATw+Xx4vV4WFhaw2Wx4PB5MJpNMZpjNZsbGxigUCsTjcZLJ5PO+lKdCpVLhcDgIBoM4nU7U6kf3UIhr7/V6HD9+nFqtRjQa5caNGzSbTdrtNr1eb58//YuH0WjE5/PhdrvR6XT0+32q1SrpdJpSqUS/399XTcw9syJqtRq9Xs/Jkyc5c+YMR44c4Xvf+x5ms1kecx6MhfV6PbLZLNlslo8//pj/83/+j3xQa7WajDHq9Xo+//xznE4nTqeTQCCA2WwmEAgA4HQ6sdlsj/QWXiSE0fN4PPzgBz9gfn6e6elpJicnpdc4mOUVvwuXy8WZM2dwOBx8/PHHpFKpA33cVKvVBAIBjh49Kk82j0Kn0+FyubDZbPzgBz/gpZde4r333iORSFAsFikWi7RarX3+9C8eDoeDqakpgsEgRqORfr9PNptlZWWFeDxOt9uVVTD7wZ4YSXGsM5vN+Hw+wuEwgUBAJmYE/X6fbrdLp9OhUqnQbDbZ2toinU6zvb1NKpWS3uOga93r9TAYDLTbbfr9Pmq1esfD3mq1qNVqL2x2Uhg8k8mE0+nE5/Ph8/nw+/14PJ5dvSn48ven1WplHPOgM+iJiM0ZkAav0+nQ7XbR6/U4HA4Zu/X5fDidTsxmM81mk3K5/Dwv49BjMBjQarXYbDbp6Gg0Gnq9HpVKhVQqRaFQ2Pcyvz0xkna7ndOnT+Pz+fje977Hq6++isVi2VHOA1/GHev1OrFYjN/85jek02nu3btHPB4nn88Ti8XodDq02+0dP2cymRgfHycQCBAKhfB4PNIrrdfr3Lp1i8uXL+9bYHdYELur0WhEp9MxPz/PW2+9hd/v5+LFiwSDQcxmM51OR+7Cj8pud7tdyuUyhUKBRqNxoL1I+NIYvvPOOySTSSwWCx6Ph263SzKZpFKpkM/nyWazTE5O8qMf/YhAIIDX6yUUCjEyMsLExARms5lyuUyj0Xjel3Mo0Wq1TE5OEgwGOX/+PGfPnsVqtaLT6ajValy7do2f/vSn8nfVbDb3LfSxJ0ZSr9dLAzY2NsbY2Jj83uADJzKHuVyOO3fusLW1xd27d4lGo7sW8+p0OpxOpzwaCe9UFJen02mZdHhREDFgEeYwGAwEAgEWFhbw+XwEg0FpHISRFEb1waOLWMdGo3Hgkzbw5cljfX2dRqOB0+kkFArR6XRYX1+nVCqRSCTY3t7mxIkTvP7665hMJrxeLxaLRXo1jUbjhY9x7yUiERsKhQgEAvj9foxGI81mk2azSSqVYmlpiUajQaPR2Ndne09+641Gg2g0Sr1eZ3FxEZfLJb/X6/Wo1+u0222i0SgbGxskk0lu3rxJPp+nWCw+1kCK4nO/38+ZM2cIh8N4PB4AEokEy8vLrK6uUigUXriOCYPBgM/nw2KxcPHiRWZnZxkZGeHYsWM7agG3t7fZ3t7G7XazsLCAxWLBYrFgMBjke4kwiPg66PR6PfL5PJ1Oh0wmQyKRoN/vS0+5XC7LpOHKygrtdhu3200gEMDhcDA7O4vFYuHevXvP+1IOLcJIijUXpVnxeJxisUgmk6FWq8kQ236yZ0Zyc3OTfD7PnTt3sFgs8nviRq1Wq9y8eZMrV65Qr9dJp9NfuwA6nU4maM6dO0ckEsHn8wGwvb3N+++/L+unXrRCcqPRSCQSIRAI8Bd/8Re8/fbb0kus1Wrcu3ePXC7H5cuXuXLlCtPT03g8Hnw+HwaDYYeRBGSY4zCsoQj853I54KvOLXFt4s9qtcrS0hLVapX5+XngyyTg0aNHZYxdYW8Y9CSdTidarVZWuSSTSVKpFNVq9bmcDvfESPZ6PRqNBmq1mq2tLVmiA18+fKVSiUajQTKZpFqtyu6Or3sgRTzJ6/XicrlwOp0ygy36bqvVKp1O51A83E+C2WzGbDbj9/uZm5sjEAjg8XjQarW0221qtRrFYlHWmjYaDVl7JkqlDkNy5kl40Cg+iEajwWQyYTab0Wq1z/U08mD447AiumusVqvsrnE4HMCXz3QqlWJra0uW/jwP9sRIdjodeXR+5513+PDDD+X3xFGu3+/TaDRkAPbrjnUqlYpIJMKpU6eYm5tjbm4On88njWStViMej5NKpV6oMo1wOMzs7CxTU1P8+Z//OcFgkGAwCECpVGJzc5NYLMaPf/xjFhcXuXTpEm+//TY+n4+RkRHMZvOuIiIvEgaDgUgkwujoqNzYRSvcfnrVovNp0Egf1pOR0WhkZGQEj8fD2bNneeWVV7BarahUKkqlEp9++il3795lbW3tcBnJfr8vy2+e1mCJ0h6tVovT6ZRlLCaTCb1eT7vdlt05+93T+TwRSRqr1SrbO0X4QavVUq/XZeG96FTK5XKoVCpZ2iKy4IJBT0sIiBzGB/NBRMmUTqeTyRqxLr1ej2azua+qM6IEC776XRyW0MeD6HQ6bDYbDodDJmNFPLJWq5HP50mn09Rqtef2GYc2XafRaOQCnj59WvZnnzt3DovFQqPRIBaLcf36dba2trh+/TrXr1+Xii6HGa1WuyNJ84d/+Ie43W7cbjcqlYrLly+ztrbGxsYG165do9PpyHrV06dPMzU1JQ2kSqXa4a10Oh1qtRrJZJJYLPZC1AZaLBbsdjtjY2McPXqUiYkJ3G43AJlMhitXrkj9wr1GpVLhdrtlL71KpaLT6bC9vX0ofxdut5vXX399R6lVKpVifX2djY0NlpaW2NjY2DfFn0cxtEZSlLJYLBYWFhaYmpri/PnznD9/XvZkl0olbty4wY0bN6RReLCm8jCi0WjkznvkyBEuXrwoy34ajQYrKyt8/PHHLC0t8dlnn2G1WvnhD3/I5OQkk5OTsvddIAylOAE0m00KhQK5XO6F6Fs2Go04nU48Hg9jY2OMjo7KsrJyuczq6iqJRGJf1kKIwYjfkVqtptlsksvlDqWRtFqtLCwsMD4+LpOItVqN1dVV2aOdyWSe62ccKiOpUqlwuVwyQTMxMYHH4+H06dOEw2F8Pp+8cUTcxm634/V6KRaL2Gw2ms3moanvexCxaTgcDi5cuMDIyAjj4+O0Wi0KhQJra2sUi0WuXr0qpe17vZ7sIHE6nRgMBlkHKbKFOp1OdjZ0u1151CmXyy9EfFcYJa/XK4VdRXnQ9vY2mUyGQqGw7xuwx+NhdnaWdrstwybDiqikAJ7o2RMJx0AgQCQSIRQKYTKZ6Pf7ckRDLBbbNxGL3RgqI6nRaBgdHZX1fd/73vdwOBxMTk7uUC6Hr2KVfr9fGsb19XWq1SrZbPZQGkmz2UwkEiEcDvNnf/ZnnDx5EkB6j//tv/03YrEYa2trJJNJeXzWarUycygSEsIAtNttKXYsZOoajYbsbDiMcbBBxPF2ZmaGsbExrFYrWq2WeDzO1tYW9+/fZ2Njg3K5vO8P7MjICD/60Y9otVpcv359qOs0NRoNer3+iVsGRbnP1NQU8/PzUg6t2+2STqe5du2a7Ih63gyFkdRqtVgsFinXPjY2Rjgcxuv1YrfbHyp2Fv23ote2Xq8TDoeZmpqiUqlIl73Vakk9xGazKZMRBw0hc+Z0OhkdHSUcDuN2u7HZbBQKBfL5PJlMRn4JZW2xu4uEhN1uR6/Xy8qCZDJJq9WS9aciCSY8yMetlUh0GAwGTCbTDtGIarUq9ReH2cCK9k2tVovb7Zb3m0iYFItFEokE+XxeqpTv9fWIhI3D4ZClXA6H40B0+2i1WgwGwxPV14qQgt/vx+12y9+DKBYvl8sUi0U5SuN5MxQr73a7uXjxIj6fj7feeosTJ05gtVplvd+Dhc46nU622NntdprNJi+//DJ/8id/QrFY5Pr162SzWWKxmLzRV1dXZcnRMCz8k6JSqaQoxdmzZ/mrv/or3G43o6OjaDQaGX+MRqPcv3+fXC4nPR6tVrtDYPfEiROydzsWi/FP//RP1Go1/vqv/5rp6WlWVla4du0a6+vrj93BhXHUarVMT09z4sQJjEajlL377LPPuHnzJu12e6j7vg0GA7Ozs3g8Ht5++21++MMfYrVacTgctFotrl27xm9+8xui0SiVSmXPZdK0Wi12ux2z2cxrr73G22+/jd/vl1qKw24khWEX8nK7ed0qlYr5+Xn+6I/+iJGRESwWC91ul3g8LvUb7t+/T6VSGYqY+FCsvMFgIBwOE4lEmJubY2FhYUeMY9ADFA+dKAsSBlQU35ZKJTqdDqlUCr1eLwVnBwVkD1Jpi1qtlmo+Igwhim273S75fJ61tTW5GQwaNxGSEGMLvF6vXAOh+C5uRFFOlUwmyWQyD8UiHxzcptfrcbvdTE5OYjabcTgcqFQqVldX0Wq1Q++xC8/c7/czOjrKzMyM9IZFYnBtbY1CoUCn09mz6xFrKrQshVL83NycPEE9KEAyjIjTiIiB74YIcUxOTkrvvd/vU6lUyOVyssZ6WKpUhsJIilo00bg+uMiNRkP2Y4uvRyGOkwLhfZ06dYp8Ps+JEycolUrcuXOHZDIp66+G1ViK7g+TycSrr77K+fPnmZqakmMtPv30U2KxGNeuXePmzZuPTbKIzUbEG+PxuIxbiol0wjiIrLbYaOBLRSebzYbJZJK6nTMzM3i9XkZGRpienqbZbLK6uipl7er1+lDNh1GpVNJLa7fb1Ot17Ha7HA/g9XqBL5sgqtUqhUKBTCZDKpXaMzEFoeU5MTHB/Py8NI42m42zZ89KvYNSqUShUBj6BFqpVJKJlscluEQtqpiO6vV6cTgc0ksW9c4iNDYsDI2RHOy+Gdw1G40Gd+/eZWtrS9ZOPWoBRQeJ3W7n6NGjeDweRkZGCIVCsvMkn8/z85//nDt37rCxsTHUCZ7BUQuvvPIKf/Znf4Zer5d1ZB988AHXrl1jY2OD9fX1R8YAB70/URGQSqW4efMmqVRKxuUG9RWLxSLlclkqBdntdoLBID6fj4WFBVnXNj09jclkwmq1kkwmWV1dJZ/PUy6Xh+KINIi4Do/HQ71ep1AoYLPZGBsbk0dulUpFs9mkWCySy+WkkdyrzyM8/JmZGf74j/8Yl8vF9PQ0NpsNl8uFw+GgVqs9t8z6N0VskLshQjVGo1EaSdHxJUrPhK6sYiQfoN1uk8/n0Wq13L9/H71ej1arxWg0ykmIW1tbstn9UYiuCKvVKo+CRqNR7sg2mw2VSsXo6KhM6MRiMSnXNmzHQ41GI2W6xLGr3W6TSCRIJBJkMhmy2Sy1Wu2xSRKj0YjX68Xr9UotT3EsEkkgjUYjM94Wi4VIJILRaJTB82AwKAWTRZWBy+XCZDLRarVIJBIyExyLxYYiG/kgGo2G8fFx5ufnpeqP1WqV+oUmk0lm9G/duiU7lJ4WUQwuVODFqBEhJWiz2Thx4oT0IO12uyyDqdVqpFIpbt26JZVwDjIibDQ9PY3X6yUSicjx0aJOVyR9hs1xGQojWalUuHPnDiaTiXg8Lo/KoVCIarUqRwjstluJzKDFYmFxcRGPx0Oz2ZTGUmjUqVQqjh8/jsfjIZvNUiwWicViQ+f9GI1GRkdH8fv9+Hw+bDYb6+vrfP7558RiMW7evMni4uKuWVev18u5c+cYHR2ViRWbzSaV4sUYh3A4DEAkEuF73/sezWaTt99+m263i8fjwe12y5iZECTQ6XQsLS1x7do1otEo7733HtFodCgfZr1ez+///u/zV3/1V7LSQaPRyLrIVqtFPp/n7t27/P3f/z2bm5tsbGw81b8pjpYi9ik8p6NHj+Jyubh48aLcdNxut+wwA2Qh/5UrV/iv//W/kkgknvrzPE9EhYXP5+NHP/oRx44dY3Z2VirkCyNZr9elsLHiST5At9ulWq1KT6lSqci4WKPRkH3HtVrta4O5orRFSLLlcjlsNhsWi0V2qqjVarxer9SiHMZBV4NHExG/AqQXLG48EfR+FA6HQ/a6iySWKEgXsV/hsYujt8vlotfrSc/abrfvUHGCL6cKVioVMpmMHBSWy+UoFotDUfz7IOK4HQgEZOJKeDZarZZSqUStVpMJm1Qq9bWb5mAYYzCcMfjfgyVGQpZOlG+JeKioQADkutdqNbLZrFTAyWQyQ7eJfxN0Op2sHAiFQoyOjko5tGFPSMEQGclKpYJaraZer6PT6TAYDKysrNDpdMhmszQajSeaWdNqtYjFYmQyGdRqNcvLy4yOjvLaa6/J1rNwOMzZs2dRq9XS+xFKL8Pm6gtUKhV+v59XXnmFYrGIxWJhe3tbino8ylAeOXKEl19+WV63yCqKljvxQAu9T5PJhM/n2yF0kclk5BptbGzIrLiIlaXTaer1upRhG7awBXw1YG5jY0PW1woBZ+HtiUoJcewVsnuPQvyc0WjccVIRNb0OhwO9Xi89Va/Xi9vtluVYer1eHvPF5tfpdCgUCtRqNd555x0++ugjtre35RC8YY9JPgqxkUxPT/PGG2/IiamDbZ8CoScZDAax2WxDJd83FEZSZLeBp94xRVkMfHnjRaNRjh49ysjIiNRRFPO6ReHuL3/5SxKJxNArcdtsNmw2m/Sms9ks+XyefD7/SOM0OzvLmTNndozXFUrkg9MRRUxTPPyCXq9HLBYjHo8Tj8f54osvpHBvNBrdhyt+Nojykkwmg8FgwGq1YjAY5JoJr1wYvsFk1qMQR2Oz2YzX68VqtcoxyS6XSxrAcDiMyWSS3rzgQe9JyAdWq1U5Qvndd9+VKjjDuPE8CWITFuI0wWCQkZERKR7y4GtNJpOsQhgmhsJI7hUiSL+5ucmHH36Ix+Oh0WgwOTmJXq/H5XIxMjLCK6+8Qjgc5s6dO1K37nnfmK1WSw5gv3//vnzwHA4H/X4fh8Mhj8eP83j8fr9s5XzUsUYYx2KxSLVaJZfLEYvF5EbR6/VYXV1lfX1dFuTv5mENK51Oh1u3bu0wbk6nk7fffpuxsTEZavD7/bzxxhtyxEOhUHjkfWA0GjEYDFgsFvl78fv98gEXnU1CFPpBr0kMWhP3p6hvXVpaIp/Pc+/ePdk1NUyxuSdFJKvGxsbweDwcP36cqakp6U0PMqg8tbq6yu3bt9nc3Hzuz98gh9pICtm0XC7H6uoqNpuNfD7PsWPHOH78OK+88gpOp5O/+Iu/IJ1O8z//5/9ka2tLFpw/T+r1upwzLAapBQIBjhw5Ih9Ks9n8UGZ7UPpM1Ec+CvGaTqdDIpEgnU5z/fp1fvvb30qvvt/vs7W1RSKRkPWFTyKQPGy0223ee+89PvroI2m0RkdHmZiYwOfzyTjt1NQUP/rRj2i32zJOCTy0voNep8fjkUf2wZIrQB4ZH9ygxKTGbDbL+vo69+7dI5vN8tlnn5HJZCgWizJBedCMpGhRNRqNnDx5kpMnT3L8+HHOnDmDyWR66H7sdrvUajUKhQJXr17lvffekzmFYeFQG0lhQERJBXyZpBEBZFGgK7wzEVPar17dr/vsorVPBPAbjYYsMi+XyzuOJY86wtlsNrxerywkFxnEVqsls9W9Xk/2KSeTSdLp9A4jKbxMoQ500B5aQavVktctjGA2myWdTkt1JFGbOpjYgYcN1YMlPSKUoVKpZDeXOEILZXNxT4npfysrK2SzWaLRKLFYTGa0hzG7+00Rm7OIMbrdbtnK+iBCF1b8LgqFguz9HxYOtZEUiONzvV7n008/5fbt27RaLebm5rBarYTDYYLBIEePHmVxcZFsNsvq6upz7XIQD1e32+Xzzz/n7t27sghXlDp9XT/v66+/zr//9/8eu90uZ9lEo1GWl5dxuVycPHmSXq/H1atX+eSTT9jY2ODu3bs7dnFhXIZdsOJJ6Xa7NBoNcrkcH374IalUijNnznDhwgXpAalUKrmBAA+dKgaz2MIzEh6kiK93Oh2pHLS1tSVnyS8tLVGpVFheXpYbkkjM7EeP+F4j4rtms5mFhQXeeustec8+is3NTf7+7/+era0tbty4wdbW1p62gX4bnruRfJQHtBeIYlVRqpJOp6lWq1LJRmhT2mw2qtXqUJQmiJIQoe4jMrMitvZ1s2nC4bB8YMW6ii4O0eUgMtibm5skEgmKxeKBO05/E4SxbzabJBIJdDodo6OjNBoNmfUWxm+3e/PBURfitcL7b7fbsiQqlUoRjUZJpVLcvn2bUqnEysrKcxeT3QsGi+eFJ6nX6x/KVguPu1Qqsbi4yMbGhpyIOGw8FyMpjn9CXVt4eZ1Oh0qlsmfHDb1ez8LCAqFQiLNnzxKJRNDpdLLEaH19nbW1Ncrl8lAaCuFddjod2Ta4G6LNc3AtnU4n4+PjmM1m2UIYjUbldQ/TDr6XNJtN7t27J8cyrK6u4nK5pLCE2WyWdapWq1UKFYsY2mAVRq/XI5fLUa1WyefzJJNJGSYR8TZR3iPk6YbRGDwLBnv7Rbfbg/R6Pe7evcv9+/e5d+8e6+vrT1Sb+rzYdyMpArsajQaPxyOVtfP5vPR6Go3GjgTEs0Kn03H06FGOHz/O8ePHCQaDtFotVlZWyOVyRKNRNjY26Ha7QxU4FgwOWHuSujnRAyvWURRVj4yM0Ov1KJfLFAoFtre3D3RHx7eh1WqxvLyMSqVic3OTa9euEQ6H+e53vyu7jMSAqkAgACBFRETZ1eB7ra2tkUqliMfjLC8vU61WicfjD8XXDkPIYjdMJpNs9xwUnBGI0NfS0hK/+MUv2NraYnNzc6hHU+yrkVSr1RgMBkZHR7Hb7UxNTTE9PS29mUqlIudEP6ubaXAKnsPhkLVaTqcTlUpFt9ulWCzKPuhhyGw/LaL3XSQjBo/lQiSj0+kM7c69n4ijd6lUQqfTsbi4KAvKhXSZqOsTQs6iI0zQ7XbZ3t6W95E4Zh/0+OI3QRyxhVBHJBKR7aziqN3r9ahWqzuSkel0eigdkkH2zUiKOJrL5eLSpUscOXKEhYUFTpw4QTab5YsvviCVSlEul4nFYsDT77oitiRGQPh8Pi5cuMD58+dxOBxoNBqazSabm5tEo1Gy2exzz2o/LSqVCpvNhtVqxel0SoMpjuZmsxmj0Ui9Xh/KFsLngdDUTKfTrK+vy3ZNcc+KOkeRUBDJLIHw8EXNn7iHhjFks1cITdHp6Wl+8IMfMD4+LoVQBO12m+3tbfL5PDdu3ODjjz+m1WoN/X24b0ZyUB7K7/dLkQWv10u3293Rn/ysELub2WzG4/HIbhsx00WU2RSLRRkzOsgGEpD92SaT6ZH1e8KzrNfrNBoNGQt+kREJMpF0gYcVfACpkSkMocJXiA1FCES7XC5ZKQBfbSRCx1UU0B8ET3vfjKQQbY1EIpw8eZKzZ89iMBioVCpEo1F++ctfsrm5yfr6+lMrh4sb3O/3EwgEmJiY4Pd+7/fw+XzMzs5is9mk6y/mKt+/f594PP4Mr/j5oFarcblcRCIR/H6/7A55cAPK5XJ88MEHsu1QYSdC13Swn3+w7lZhJ6J8avBLhHlEjW06neYXv/gFd+/e5c6dOwdmHffNSAolEPEAj42NSXEG0Yol2t6edvGExySGDY2NjXH8+HF8Ph8+nw+j0Uij0ZBjU0V2dz+Gz+81osbP6XRitVofWypUq9VYXl5mc3NzKOXNhgFhEA+Ct/O8EZ6k+BqsixReZLVa5c6dO1y+fJlCoaAYyQcRvayDhaVCCVoU3X7TIlKhHGKxWGT8UcQ9TSYTx44dY25ujmAwSCgUwmAwyL7cWCzGysqKLPQVUm2HmX6/T6FQoFgssrq6yvLyMrFYbKgziwoHA5EcFeLQzWZThtBSqRSLi4tEo1GSyeSBm+e+b0bSYDBIySihkl2r1WR8YnB8w5OiVqsJhUIEg0Epr2Y2m6Wg54ULFzh9+rQcGtZoNLh27RpbW1t88cUX/Pa3v6VUKrG9vT10rVDPggePhv1+n1QqxfLyMjdu3ODatWskEgnFU1J4aoxGIw6HQyrW1+t1GR+Px+O88847xONxNjY2yOfzB+pZ29fjtiitEJ7koCLL1NQUJpPpG2k6arVaKVElemnNZrOcdWM2m3c00AulEaHTJ/7uoGe0H0TEZAeD5uJPIfhRKpVkcbSCwrNgsNxMzHYXo1mENsBB7EvfNyPpdDo5ceIE4XBYjhJwuVxYLBZ8Ph9+v/8b1ylqNBo52kAIp4paTI1GQz6f5/bt26yurvLrX/9adkOUSiXK5TK5XE4GlQ8TarX6odIfoZUZi8W4cuUKm5ubQ196oXAwEFUAQkUfvrzf0uk0lUqF69ev88EHH8hJnAeNfTOSQnVGDDrqdDpSaUWtVjMzM/OQsXpw1vagLmK/35etjeI9HpzTnU6nSafTxGIxbt++TSaToVQqSZXzw2YcYWfv7OCuLmr4KpUK6XSaYrGoHLMVnjmD6lWitE48hwe17XXfjOTW1hb/8i//gtvtZnNzUyZSjEaj7N1Wq9VMTk4SCoVky1y73aZardLpdIhEIoTDYfmwt9tt7t+/T6VSkaosrVZLzgRZXl5mfX2dTCZDLBaTHRPDpjLyLBGTAc+ePcvExAQajYZWq8X6+jqFQoEbN25w48YNmSxTUHha+v0+6XSaGzduEI1G2d7exmQyye6azc3NA3nMFuybkUwkErz77rvY7XbK5TLhcBi73Y7dbpfeoV6vZ2RkBKvVSq1Wk50QmUyGZrMph5nX63WZjV5fX98xSqBWq7G0tEShUGBtbY319XXZi31Qf0nfBLVaTSQS4dixYwQCAVk4LrL49+/f5+7du4d2k1B4PmSzWbLZLACfffbZju8d9Odu34ykOO7V63Xi8TiNRgOz2SyHUAFyBu/a2hqFQoFEIkGr1ZKTE0ulEltbW7RaLYrFIo1Gg9XVVfnLgS/LikRJj1Dzedri9IOECJiXy2UpJtztdsnlcnISpYLCXnLYnrV9NZJiHOq1a9dku9xgJ4hKpeKf/umf0Ol0MtEg4mmDg6oG/+7BbPhgH+2wqvnsJf1+n3w+z/b2NhaLRQo4LC8vc+fOHRKJxKG7iRUU9pJ9VQESdXuiP1bh2TM4GdDhcLC9vS1HAxQKBWXtFRS+Iar+E7oVw6DUPSx8W09sP9ZQrVYTDodlW6LH45Gx23K5TLlcHooj9zCv4UFBWcOn50nWUDGS3wLl5nx6lDV8epQ1fHqeZA2frTaZgoKCwiFDMZIKCgoKu6AYSQUFBYVdeOKYpIKCgsKLiOJJKigoKOyCYiQVFBQUdkExkgoKCgq7oBhJBQUFhV1QjKSCgoLCLihGUkFBQWEXFCOpoKCgsAuKkVRQUFDYBcVIKigoKOyCYiQVFBQUdkExkgoKCgq7oBhJBQUFhV1QjKSCgoLCLjzxjBtFzfgrFEXop0dZw6dHWcOnR1EmV1BQUHhKFCOpoKCgsAuKkVRQUFDYBcVIKigoKOyCYiQVFBQUduGJs9sKCgpPhlqtRq1WYzQa0Wq16PV6dDodrVaLcrlMt9ul2+3S6/We90dVeAIUI6mg8AzR6XQYjUYcDgfnz5/H7/czMzPD1NQUS0tL/PSnPyWbzZJMJqlUKs/74yo8AftqJJ+0PksZ4KhwUNFoNOj1eqxWK5OTk4yPj3Pu3DlOnz6Nx+Ph448/ptPpkM/nn/dHVXhC9tRIajQaAoEALpcLq9WK1+tFr9fjdrvlUUSn09HpdKjVarTbbVKpFMVikVKpRCqVkkeUdru9lx9VQeGZEA6HOXPmDH6/n4sXLxIKhYhEIuh0OkZGRviTP/kT0uk0n332GWtra2SzWWKxmHL0HmL2zEiqVCo0Gg1jY2PMzMwQDodZWFjAbrczMzODy+XCbDZjsVio1+ukUimq1So3btxgfX2djY0Nbt68SblcptlsKkZS4UAwNjbG97//fQKBABcuXMDr9aJWq1GpVExMTBAOhymXyzidTm7cuMHt27eJx+OKkRxi9sRI6vV6XC4XJpOJyclJZmdn8Xq9BAIBjEYj/X6farVKrVYjk8nQ6/XodDoAuN1uer0eOp2OXq9HqVRCo9GQz+epVCqUy+W9+MgvNHq9Hq1WKz17rVaLxWJBq9ViMpkwGo3ytd1ul1qtRrPZRKPRoNVqabVaZLNZms0mrVZL/i4PO8IR0Gg02Gw2TCYToVAIv9+Px+PBaDSi0Wjk69VqtVzfXq/3Qq3VQWZPjKTT6eT1118nGAzy9ttvc/bsWdRqNRqNhkajweLiIrlcjq2tLaLRKC6Xi1OnTmG325mdneWll16iXq9TLpfJ5/P89re/ZXNzk+vXr3P9+nV6vZ4St3xGqNVqPB4Pdrsdm81GIBDAZrOxsLCAy+ViYmKC8fFx+fpWq8WtW7eIx+NYLBbsdjvpdJqf/exnbG9vk06nyeVyz/GK9g+tVovVasVkMnHhwgUmJyc5c+YMFy5ckKekQfr9vnQIMpkMW1tb5HI55V4ecvbESOp0Ouk5BoNBgsEg7Xaber1Oo9GgWCySSqXY2tpiZWUFn8/HyMgIKpUKtVqNzWbDYrHg8XhwOByMjo7S7/dZX19Hr9fT6XSU4/e3RJSnCC9Iq9XicDhwOp24XC6CwSB2u52JiQm8Xi8zMzNMTk6iUqlQqVQ0Gg3q9Tp6vR6bzYbb7cZiseB0Osnn82i1h79gQqyfSNBYLBaCwSCjo6MEAgEcDgcGgwG1emcZcrfbpdFoUKvVqNVqVCoV2u22YiSHnD0zkoFAgHA4TLVaZWlpic3NTb744guKxSL3798nn89TLBYpFosYjUbW19ex2WycOXOGyclJRkZGOHbsGHq9ngsXLrCwsIBOpwMgl8tx//59Go3GXnz8Q4lGo0GtVhMKhQiFQtjtdsbGxrBYLExPT+P3+zEajdhsNhkuMRgMqFQqNjc30Wg0GAwG+v0+DodDHjHdbjcajQa32002myWTyTzvS91zfD4fgUCAQCDA2bNncbvdLCwsEIlE8Hg86PX6HZUcoiZyY2ODf/3XfyWZTPLpp5+yurpKtVpVjOSQs2cxSbfbjcfjodFosLW1xY0bN/jnf/5nCoUCW1tbD9WI3bt3D71eTy6XY3Z2lrNnzzI1NYXNZmN+fh6NRkM2myWRSBCNRllbW1OM5BMyGDvz+XzMzs4SCAQ4d+4cTqeT+fl5QqGQfE2/36fdbtPpdEgmk6RSKXQ6HVarFY1GI4+Sdrsdl8tFo9HAZrNhNpsPvSepUqlkGGJycpJLly7h8/kYHR3F7XY/8mfEETuZTPL+++8Ti8W4e/cuyWRynz+9wrdhT+7oVqtFPp/HYrHIh6dWq1EulymXy48NVvd6PTKZjEwimM1m3G43p06dwuVy4XQ6OXnyJBaLhXv37qHT6ahUKjSbzb24jAOP2WyWCbTR0VFsNhvT09NMTU3hcDgIh8OYTCYZIxNx4GazSTabpdFokMlkyOfz+P1+Tp8+jcViwWQyodPpKBQKRKNR+ZVIJKjVas/7sp8pJpMJp9OJwWAgHA7L+sfJyUnpTdrtdgwGw46f6/f7MjFz//59VlZWWFlZYX19nVwup2zwA4jwhcFgQKvVYrPZ8Hg8sltJq9XKTbtYLLK5uUmr1dq3z7dnRnJra4t2u00wGMTj8VAoFEilUpRKpcfGEzudDsvLy6ytrXH37l0+++wzwuEw/+k//ScWFhYYGxtjenqamzdvcv/+fba2tlhfX1eM5GPweDwcP36cQCDA22+/zdjYGIFAAL/fT7/fp9vt0ul0SKVSJJNJotEot2/fplAocPv2bfL5PNVqlWq1yrlz5xgZGUGn0+FwOLBYLCwvL/Pee+8Ri8W4evUqiURiX2/e/cDlcnH06FH8fj+XLl1idHSUUChEMBhEp9NhMplkKGOQbrdLuVymWq3yL//yL/z4xz+mWq2STqflA6/wpWeu1WplyMZisTA1NcW5c+cwm82ytlqs5f379/npT3968I1kp9OhVCphMBhwuVx0u11UKhVms5lOp0OlUnlsXVin06HT6VAul9FqtRgMBjKZDNlsFp/Ph8vlkse8SqXy0A7+IiMSXxaLBYPBQCAQYGRkBL/fTyAQwOv1YjQa6Xa7tFotSqUSzWaTWCxGPp9na2uL7e1tSqUSmUyGUqkkd3hRuqJSqSgWi5TLZeLxONvb27LGtdVq0e12n/cyPBNMJhN6vR6v18vIyAg+n49QKEQgEJAJRVGxMYjYeIQ3XiqVSKfTpNNpms0mjUZDqYkEWW6m0+mwWCzodDpCoRAOh4OxsTHC4bA8Ser1egDq9fpDm9G+fNa9eNNKpcKNGzew2+2YzWYCgQChUIi33nqLXC7H559/TiKR2PU9xE3W6/V47733WF9f5/XXXycUCuHxeDh37hyhUEjGKfv9/gsdAFer1ej1ekwmE2+88QYLCwtMTExw6tQpeew2GAwsLS2xvLxMNpvlzp07lMtl6eHX63W5gfV6PdRqNRcvXuT8+fOMjo4yPT0NwE9+8hOuX79OLBZjZWWFZrNJoVCg2+0eit+BTqfj2LFjTE5OcuzYMS5duiTLo4TxfFzstVQqsb29TT6f5+OPPyaRSPDFF19QKpUUUYsB/H4/oVAIt9vN/Pw8drudkydPMjIygtlsxm63yxbPfr9PLBaT99x+n1b2xEi2223S6bQsc+j1ephMJsLhMEajcUdx8uMQSinlcploNEq73eb48eOoVCqMRiOhUAj4Mu4mMomH4QH9tqhUKimuIIzj2NgYx44dQ6fT0W636Xa7FItFlpeXicfjfP755xSLRTKZzI5EmigLMpvNhMNhTp06JWspq9Uqq6urfPLJJxQKBdLp9KFad7VajVarxefzMTU1xZEjRzhx4gQmk0l60o+j3+/TaDRkaGl5eZloNEoqlVJCQiDLyFQqFVarVZ5wjhw5Ih2fyclJ+XpxX4l7N5VKUSgU9n2j2RMj2e12qdfrdLtdbt68KeNauVyOarVKoVB44vdqtVpsbGyQz+eZnp5mbGwMjUbDxMQEHo+HkZERlpaWaDQaVCqVQ/XAPgniiB0KhXjzzTfx+/28/PLLzM3NoVaricVi1Go1bt26RSaTYXFxkfv371Mul0kmkzQaDbkzGwwGLBYLLpeLV199lVAoxJkzZxgbG6NcLvPOO++QzWa5d+8euVyOer1+KNbbYDBgMBjwer1yQzh16hQTExNEIhEMBgMajeYhA9nr9WR8MR6PUygUuH//Pl988QX5fJ67d+9SKBS+0f1+GBG6DVarlZmZGZxOJ+Pj44yNjWGz2aT3aLFYaDab0kY0Gg2plnTlyhU2NjaoVCr7Hs/dEyPZ6/Wo1WrU63Vu3LjB8vKyNGLiKPektFot1tbW0Gg0Mmg+MjLC66+/Tr/fZ3R0VCaGXsSaMxEXCwaD/Pmf/7msMfV4PGxvb3Pv3j3i8Tg//vGPWVpaIpfLyS6PB0MURqMRt9vN+Pg4f/qnf8r8/DxOpxOHw8H169f5+c9/TiwW486dO4eqHtJgMOBwOJienuYv//IviUQijI+P4/V60Wg0sj73QXq9Hs1mk3q9zv3791lfX+eLL77gF7/4hbz/O53OC3dPPojdbmdycpJgMMgPfvAD2cMeCoWk5y688EajQTabZX19nUKhwPXr18lkMly5coX19XV5wtxP9rSoTdTbCW/l28asBtu5ms0mnU5nR3eOx+Oh0+mQTqf34CqGk0EPMhKJMD8/j9frxWazUa/XSSQSbG5uynq8dDpNpVKh0Wg89iYzmUwEg0H8fj8OhwOr1SpDJ6lUinQ6LXu0DwM6nQ6NRoPL5ZJF9h6PB7fbLY/Xj0oUiB71arXK9vY2lUqFpaUl1tfXicfj1Ov1r73fhXcqjHC326VSqRyaxBd81cAg4o5+v59gMIjT6USv18sEolD5ErHxbDYra6mFsSwWi88t5r3nlb/CQD6LxEqr1aJSqVCr1ej3+2i1WsbGxjh58iR3795lY2PjUN1kj0PEH3U6Hd/97nf50Y9+hMfjYW5uDp1Ox/Xr19nc3OTatWv87Gc/o1Qqkc/naTabu65PMBjk5Zdflp6Uz+fjzp07LC4ucuPGDW7evEkmkzkURlKj0WC32zEajSwsLHD27FnGxsaYn5/H4/FIA/oo8vk8iUSCra0t3n33XTKZDDdv3mR7e5tGo0G1Wt1VX0CUu4gaYqfTSaVSkWGQw4DIHRgMBk6cOMHf/M3f4Ha7ZYVFs9mkUqmQSqW4cuUKuVxOysfVajWKxaJ0ikQ75/N6tvfcSIp6vGdBr9eTGUJxAxqNRqxWq2yhexEQRlLE0aamprBarRiNRnq93o7ynK2tLWq12q7HPrHjW61WfD4fHo9HrmelUiGRSJDNZimXy4eiWFzU5lmtVhkvCwaD+Hw+LBbLjsSiOMX0+306nQ7dbpdCoUAmk5G1pel0mkQiQSqVeuy/Jzx/Ufoi+uVtNhsulwuj0cjGxga1Wu1QCLio1WoZZ/R4PITDYVmUr1arKZfLFAoFstks29vbZDIZ1tfXZbXEMIXODncP2SFFp9MxMTGBy+VicnISv99Pt9tlY2ODUqnEu+++y8cff0w6nZYJtMfdcFqtlvHxcTweD9/5znd48803MZvN1Ot11tfX+d3vfsf/9//9f+Tz+UNhIPV6vUxO/dEf/RFTU1NMTk7KjcZsNu94faVSIZPJUC6XuX37NtlslrW1NTY3NykWizs8n8dhs9lkWGhubg673S6Pn2azGZvNJjUl19fXSafTB1a5XK1WYzAYMJlMfPe73+XUqVMsLCzIulJxT/7ud7/j448/lmtYrVZJpVIy5DAsBhIUI3kg0Wq1+P1+wuGwjB8KJfdUKsWtW7f4/PPPZWHzbqjVanw+HxMTE8zOzrKwsADA+vo6+Xyee/fu8emnnx6aGr/BdtcLFy5w5swZfD4ffr//ka9vNptkMhlSqRSffvop0WiU1dVV1tbWZLx9twdapVJhMplwuVxEIhHOnz+P1+vl9OnTRCIRjEYjFotFllUJlaCDbCTFRnTixAkuXbqE1+uVjSSlUolCocDVq1f5l3/5F+r1uow3DitDYSTF8Wewu0P0zAIyBjYxMcHExIRsCRPHF/Ezogd0mHahvUAYybGxMZxOJyqVinq9ztramixk/jqjZjAYZBvYqVOnOHr0KKOjo7K29YsvvmB7e5vNzc1DcfwTCM1SIY7rdDofqtsVotDNZpPV1VU+++wzMpkMS0tLpFIpcrkcrVZr1/UVUmo6nY6jR4/KkQ5CnX8wOSS60ebm5tDr9VQqFba2tvZ6KfYE0XvtcDhkDFKj0ZBIJKhUKly+fJlkMsnq6qoMLVit1h297t+0AmavGQojOTh+U4x1CIfDzM3NoVKpKBQKtNttLly4wNmzZ6WcV6/Xk7V94ufb7faheqgfhV6vZ2pqilOnThEMBuUaffbZZ6yvr7O9vf21HqTVauXIkSP4/X6+//3vc/HiRSlMEo1G+X//7/9x9+5dMpnMUO/y3xSv18vLL79MOBxmenqaUCj0yPrHbDZLNpvl888/58c//jH5fJ5YLCaTMl+3JqI91GKx8NZbb/HXf/3XcuMXSaHBzLndbue1115jfn6e7e1trl69eiDvYaEl6/f7GR0dZXx8nEQiwdLSEvF4nH/8x39kZWVFzrIymUwEAgG0Wi25XE7Gz4dJA+C5GEkRyDaZTJhMJgwGgwzqiqFhou9YpVJhs9nodDp4vV5pENVqNf1+H6vVitvtxufzEYlEpNpQu92m1WodSnHewez2YAZWiBHv9gCLtRdJH1E2ZDQaKZfLxGIxtra2yGazFIvFQ6NWYzabZS92IBDA5/PJ+2gQUWomlPOTyaTUPm00Gk90P4nfj9PplF6juL9NJtMjy4rUajUmkwmr1Sp7lQ8iBoNBCm0LaT1R3iRUwEqlktSctdlsjI6OyvtY1J4OkxjxvhtJURqg0+lYWFjg1KlTuN1ujh8/Lt10s9mMwWCQLYdiwRwOxw5hAbVazalTp5iZmZHvlc1m+eyzz0gmk8RiMba3t2WG8rAjlMZ3EwEQ8lOhUEj2wguxkCtXrvB//+//JZPJcP/+fQqFwqFQq9FqtRw9epSpqSlOnz7NpUuXcDqdeDyeHa8TnWKVSoXf/OY3vP/++8TjcaLRKK1W64m8GzHHxu128/rrrzM6OsqxY8dkL/Ljfjc6nQ673U6/33+itt1hJRgM8qMf/YjJyUlmZmYAKJfLbGxskEgkpArYuXPnOHv2LD6fj2PHjtHv9/nf//t/y9DGMHVzPRcjqdfrpUrNzMwMwWCQc+fO4XA4sNvtmEymr32ffr8vBVCFUohWqyWZTLK9vQ1AoVBAq9XKbNmwLPqzQMRtBq9L6HA+iZG0Wq2EQiHC4TB6vZ5ms0kymeTWrVsUCgXy+fxQHXm+LUJw2OPxMD4+zujoKKOjo1gslh3rJErVms0mtVqNaDQqBUB2U616EBEnF1oFExMTO5RsdvucojzoeSjdPCvMZjPT09PMzs5is9nkutbrdWq1mlQECwQCUsbv9OnTdLtdPvzwQ2w2G5VKZajK+fbVSKpUKiwWC2fPniUcDnPu3DkuXLggyyOEh/k4xG7earVko7v4mU6nI+ezaDQaSqUS169fly109+/fp16vf+1x9CBQq9X4/PPPicfjdDodOYbhtddeY3Z2Vs4RarVa1Ot1AKnZNzc3x9zcHBMTE3Jkw/3798lkMly7dk3GhQ76GsGXcdfp6WmcTidvvvkmZ8+eJRgMylo98SCK/upMJsPVq1dlcbgowP8mm2swGGR+fp5wOMyFCxcYHx8nGAx+7c+J1kZRoXBQN3QRix0MG/h8Pi5cuEC5XGZiYoJKpcL8/Dzz8/NYLBb0er28T4eRfTOSopjWbDZz7tw5FhYWOHHiBKdPn95xw+6GaAUrl8tsbm7SbrdxOp2YzWYcDgeBQACNRsORI0fo9Xqy13t5eVlKsz1J0H3YqdfrXL58mdu3bxOJRHjjjTcwm8288sorlMtl7t27x/LysmxDhC+Pc3q9nrm5Od5++22Zeez3+9y/f5/r16+zurpKPp8/NHFcq9XKiRMnCIfDvP7663znO995pAZksVhkY2ODlZUVfvrTnxKPx9na2vpWZTiBQEB2LQmh4ie5t+v1OouLi2xsbBzo9loxjthqtQJfeuherxe73U6v1+PVV1+Vzo3JZJIxcsVIghTXdLlcBAIBIpGIjC/udhMJsQyhdh6NRqlUKsRiMdrttuy28Xq9jI6OYjQapSSbzWZjbGyMXq/H0aNHyefzrK+vS53Kg2osRbmESqUim82yubmJxWKRSitCIk0ohatUKkKhkPyemGezvb1NvV5na2tLxosOU+zWaDQyOjrK5OQkTqfzISUfUSaVy+VYX1+XI16FF/5NEEk0p9Mpy4selRiCnZJ+IsFYrValwMNhiAMPMtitJNoMxRqLSZPDzL4ZSfGAjo6Ocv78ec6dO/fQVLlHIaTSCoUC77zzDr/5zW+o1Wqk02k6nY40smNjYxw9epRQKMQf//EfMzo6SiQSYWJigmQySSQSIZVK8dOf/pQbN27IHtuDSK/Xo1qtUq/XuXPnDr/61a8YHx/n+9//Pj6fj9/7vd9jbm6Ozz//nHq9jk6n44033iASiXD27FnOnDnD2tqa9JouX77M2tqavJEPC263m9///d/n6NGj2Gy2h2KQIlt9584dfv7zn0sNyG8qxyWEVkQ87uLFi7hcLmw222N/RhjKSqUilcsLhQKVSuVQxIIHabfblMtlGSar1+ssLy+zsrLC5OQkf/qnfzrUA+T27ZOJdiWj0Sh7Oh80kA8WlIqAbyaTIZfLsb29TTQapV6vk8vldtzIQshT1LjZ7XY8Ho+cCR0Oh9FqtVJYAJBCGQcRkbQplUokEgnMZjPVahWDwSCTMqFQCJ/PJ7PZg/2z/X5f9hyLWTaHDSEe7Ha7H5mkERtNPp+XReJCweebIMrZrFarrNAQ5S+PQ8TGxXgH0foo6gQPKqKEZzCWK8ryhAxarVYjmUwSj8ex2+10u13FSMJXsmntdlsuosjGihKdRqPBZ599xtLSEsVikUQisWNhxVH5UR5PLpfj1q1bbG9vo9VqCQaDnD59muPHj6PVaqWeXTweJxwOc/PmTX73u98NVT3WN6Xf77OxsUG1WuXevXtUq1VZUjE6OsrFixcZGRlBo9EwMjKCxWKh3W6zvLzM3bt3uXHjhpxv86Ig5LkKhQK//OUvWVtb4+rVq3KO+zcxkCIjbTQaOXbsGNPT05w4cUJOqHyckWy32ywuLpJKpbh+/Trvv/8+lUqFZDJJvV4nm80+q8vdd0qlEl988cWO5FMqlWJtbU1Kyg2Gdex2O+12e6hnVe2bkRSeoSh4brfb8iaDL29e8QB/8sknJJNJlpaWZIZW9Mk+rrhZqJ8Xi0UMBoP0Iv1+P263m0gkQq/XY2FhAZPJRD6fR6PRHPgkhRiSls1m0el0+P1+RkZGWFhYkJP+AJlpXFtbY2trS9b/xePx5/nx9x2hJl4ul7lx4wbXrl1jfX1dzkn6JohkpF6vJxKJcPToUamyLdb7Ue/Z7XZla97ly5f5+c9/fmiO2EIYZVAMRcwZLxQK3Lx5k1wuh9/vx+/3y9k/w+yo7JuRbDab5HI5AN555x1WV1dljaNw0Wu1GlevXmVxcZFSqUSpVJItSk+aaGm322QyGRqNBjdv3qTX6zE1NUUwGJSisjqdjq2tLcbHxymXy6TT6QN/k7ZaLXK5nJxmWKvVMJlMMnkgOpSazSalUkm21x1G7Ha7TKAIyTcR2qlUKkSjUSkjF4/Hn3jsh1hHMW/baDTKo/X58+eZm5sjHA4/1oMcnFK5uroqTz6H6fdQKpW4evXqjnhsoVAgHo9Tq9VoNpuoVCo5wsHn89HpdOTM92KxOFSF5LCPRrJerxOLxWQdmNlslnO0O52OzO7dvn2baDS6Q8cPnnzIV6vVIhqNolarKRQK3Lp1i4sXL/LSSy9hMpmYnp5mZmZGzpYeHId6UBFJiFgsJqW9SqUSarUal8u1o+WrVqvJgUqHKUkziM/n48iRI8zMzGA2m3dUUOTzeRlmEKVST2KkxKlHq9UyPz/PSy+9hNPpZGxsDKvVyrFjx6SBfJyR7HQ6FItFstks165d46OPPpKVFoeFTCbDr3/96x35hsHGh16vh0qlwu/3c/z4ccbGxuScoHw+TzabHbpZVfsakxRxSZHBs1gsmM1m+fAKteKnPQKLX4rQ+SsWi5RKJRlY1+v18kun0w1Vdf+3QfRii5nQdrtddiANXpvodhK6iUI96bDIoAl0Oh1Wq1X2SQ+ugUjaiPnuj9soxM+J9liNRiN1BkZGRhgdHcVms0lNSFEU/SjEvS+SkCKTXSqVvlZq7aAhTiuPQ3Qk2Ww2KXIsqgmEDRi2xNW+p5SE8Wo0GjSbzR291b1e75kWlZbLZRkjuXbtGplMhoWFBYLBoIwlHXQjKW66sbEx/u7v/k6WQkUikYdaFFUqlVQNErWTwKER1BVYrVYikQg+n++hDi7xexebiAhDDBqqwdED4+PjnDp1CqvVSjAYxGazcfToUebn52XSRjRJPA5RCxmNRvnlL39JPB7nzp07JJPJF2pQmFgno9HIkSNHeP311+UkT1HDPIzz259L3l1MPBNe5V4hvIVKpUIul8NsNstjtejpfdSo0IOE6CAROolTU1MEAgEsFot8zeBkRKPRiMfjkXV8pVLp0MxVEYje6UcVcwsBCp1OJ4/Pg/qFYgMRHSEul4uJiQnsdjvj4+PYbDamp6efqJNGHDFbrZZsFRXx0Hw+P9RdJnuBUEfS6/WyQ06UXiWTSVlLOWwMb3HSM0YcscTDoNfrsdlslMvlXevZhh2Px0MwGJTGUfTAD9JsNllfX6dSqchpgJFIhIsXLxKPx/nwww8plUrP6QqePWIC4YPhBgCn08nx48cJBoOkUimOHDkiQzJCrkyv1zM7OyuV36empmSSRq/X43K5HlnjC19VaTQaDTnxb3V1VRrHzz//nGKx+ELO4tZoNHK2j9vtxm63k0qlZLfTsN6DL4SRHGyLEjeziFuJwP5BRKggTU1NScEKt9v90APcbDZZWVkhnU5z6tQpxsfHCYVCXLhwgXg8LhMYhwHhCT7OSAq5PRGKmZubY2tri1gshk6nk6LPr776KnNzc1LUeTBD/jhEzL1er1Mqlbh//z7JZJLPPvuMK1euyAFtB73s7NsijKTH45FVAQCbm5usra0N7YnmUBtJIeorpuGJsg1A9pGKcbcHEZEMyOfzskBXPMhi0mE2myWXy7G0tEQikcDn8zE7Owt8mQVWqVT4fD6cTietVuvAxyZFfFuoRYmk1INGTihoC+/R6XTKCYpitMXgWJCvQ4SQkskky8vLsiYwk8lIL6lerx+qBNm3YfD+VKlUdDodKcY7jEdtOMRGUjz84XCYhYUFzp07JwPv8KV3VSgUKJfLQ5dN+ybkcjna7TYul2tHvBUgHo/z8ccfE4/H+Zd/+Re2t7cxm80sLCxgNBo5efIklUqFTz/9lHg8TjqdJhqNHvgHWdQiVioVqXItpOIEBoOBo0ePSuPW6XRkcfjgrKUniVeLjG6r1eLKlSv8wz/8gxTNEA//N6n1fZEQAiubm5tDuzZDayQH680Ga6y+zusbHMDkcrnkPGUh5qtWq6VE/4M9pgeRTqcj2+kevI56vU4ymSSZTJLL5WSPdrvdRq/XYzQa6ff7mM1mzGbzgc/0C4SRLJVK5PN5GX8WSvfwVQb7WTOoNZDNZg9lT/y3RTybRqNRPtuD7crDytAZSVGWITom4Eu9v2azKVWid8NisXD69Gkp9HnmzBmZrNDr9VJAI51Oy17w3eq6DhKDhfcqlYp4PM57771HOp2WPe+Dc3DE68ScoFKpdCiM5ObmJtVqldu3bxOPx/F6vfzBH/wB586dk0mdb8qjNmnheQLyWG6326VOp1DIV/gSUfozOTlJOBw+MPfa0BlJUfcnlGzEgyw0JavV6q6en6htGx0d5ezZs7z88svodDqpfCM8r3K5TDabla2PB50Hj8hCIWh5eVmq24gH/cHicaH1KVr4DjpCaTyRSFCr1fB6vRw7doxTp04BPDKhsxuifOpRRlJ8ifk1ItFTqVQObEJwr9Bqtfh8PkZHR7Hb7fLvh/0kN1RGUqPREA6H8Xq9zM7O8tJLL6HRaCgWi1KUQLQvCqk0cbNbrVYcDgc2m43jx4/jdrsZHR2VXRCieP369etsbW1x8+ZNCoUC1Wp1aGMh3wbRoig2lG63i06nY3R0FKvVytTUFG63G6PRKJNX6XSatbU1MpnMgY9HDiKmHjYaDX71q18Rj8flrJvBOe27IbLVzWZTGl2BxWIhEAig0+lktvzWrVtS6eawTJp8FoiNxGq1YrVa5UTO69evD3296NAZSTH58OzZs/zwhz/EZDLJrgQRZM/n89y9e5d6vS5FB0KhENPT0+h0OllELIL1ImtbKBR47733uHz5Muvr64ey46HX6+0Y3Snij2fOnGFsbIwTJ04QDAZlsqFWq7G5ucmdO3dkNviwIAwbQDQaRavVMjs7y1tvvSVbDL/O2xMVAsVikcuXL+8YrSBCOiaTiWg0KuO+iURC3qsKX4UldDqd1Nu8ffs2d+7cYXt7e08bSp4FQ2Uk4audW0xXg6/iPeLPXq+Hz+ej0WhIIynEdIVhFOUFrVZLzsTJ5XLE43EymQyVSmXo2p+eFnEt4qa02+1MTk6i0WgYGxsjEolgt9tRqVQ0m02y2axcCxGrPWwIz1gk6QqFAtvb25hMpq+dLAlfCsbmcjmq1apUTxIYjUZSqRQGg0EaUpEYO0z31dMihKCdTicmkwmdTkej0ZA97MO+mQyVkex2u2xtbcmMsxjuHolE5CKLr4WFhR11gVqtdocsVr/fp1AokMvlWFxc5Kc//anUqEylUrIk46Az2HIoYo1iHc6fPy/r/6anp3E4HNIzTyaTvP/++yQSCdbX1w+d0MLjSCQSvPvuu0/cjir0J4WS+SDFYpHr16+jUqnkJnPYNt5ngd/v5+TJkwQCAYLBIFarVaoxCVGLYWaojGS/36daraLVakmn02xvb0tdRBFbExPWHqW4MliM2u/3KZfL8vgjlKBFj+hhYTCpIIQUADmqYm5uTiq1i951kbiKxWLyuHMYNownYTfh5m9Kp9N5IdsLvyl6vR6v1ytbZjUaDY1Gg0KhcCCclaEzkqL4Vsz/MBgMOBwODAYDJpNpV7WVB9+rWq3KoWFizMGw71rfFCFYGovF+NnPfsbIyAjz8/NEIhHUajVerxf4MrZWKBS4e/cud+/eJZFI8Omnn8r5LgoKe4XRaJSCKoOJReF9D7vnPXRGUoxhyOVysp/4actShv2X8DQMtsO9//77+Hw+qfRjtVpxuVx0Oh3ZGvfFF1/wq1/9SrYqDntmUeHgo9Vqsdvt0ki2Wi1ZQD7sXiQMmZF8HIfZyD0rRCa30Whw+fJlCoWCnD3e7XbJZDLUajXu3r0rJ/MdxkSNwvAh9D3FifCgcSCMpMLXU61WuXv3Lmq1muvXr8uZ5iJ7K5I6zWaTRqMhWzMVFPYan8/HSy+9hNlsJpPJHLhWTcVIHhKEAQSUI7TCUCFEkPV6vWwvPki5AcVIKigo7ClCuq7RaPDJJ5+wvr7OysrKgQmjKUZSQUFhTxF6AY1Gg83NTRYXF8lkMs/7Yz0xipFUUFDYU1ZWVvjv//2/0+l0uHHjBslkklKpdGA8SVX/CT/pYVCHeVZ821+usoZfoazh03NQ1lC0FAOyLvLBCZXPiyf5DIonqaCgsKcMJhUPIk/sSSooKCi8iCiqoAoKCgq7oBhJBQUFhV1QjKSCgoLCLihGUkFBQWEXFCOpoKCgsAuKkVRQUFDYBcVIKigoKOyCYiQVFBQUdkExkgoKCgq7oBhJBQUFhV1QjKSCgoLCLihGUkFBQWEXnlgFSJGo+oqDIlE1zChr+PQoa/j0PMkaKp6kgoKCwi4oRlJBQUFhFxQjqaCgoLALipFUUFBQ2AXFSCooKCjsgmIkFRQUFHZBMZIKCgoKu6BMS1RQGEIGaxmVWX3PF8VIKih8Q9RqNWq1Go1Gg8FgAKBer9Nut7/xe2k0GrRaLQaDgWAwiNFoxGw2YzKZ5GuazSaLi4tkMplndg0KT45iJBUUviEajQadToder8dutwPQ7Xa/tZE0GAw4nU6OHTuG2+3G7/fjdrvla0qlEsViUTGSzwnFSCoo7IJWq8VoNKLRaDCbzWi1WiwWCxaLBaPRiNvtRqVSsb29TalUolarUSwW6XQ6NJtNer3eQ++pUqnQ6/VotVo8Hg/BYBCXy8Xs7CwulwuXy4XD4aDZbFIqldBqtUor4XNEMZIKCrtgt9sZHR3FarUyMzOD0+lkZGSESCSCzWZjdHQUlUrF4uIi8Xic+/fv8/HHH1Mqldje3qZWqz30nmq1Gr/fj8Ph4MKFC7z99ts4nU4mJyexWCxotVo0Gg3b29tcvnyZYrH4HK5cQaAYyUOGSqWSXof4b5VKJb2Rwe/3ej36/T69Xk9+dbvd5/nxnztifXQ6HRqNBrvdjtvtxuFwEA6H8Xg8jI+PMzY2ht1uZ3x8HJVKRbfbxWw2U61W8Xg8qNVqCoXCjrUVa63RaLBYLDidToLBIFNTUzgcDiKRCCaTiW63S6/XQ6/X0263abVaSvLmOaIYyUOCWq3ecSw0GAyYTCZsNhs2m40TJ07gdruxWq1YLBbq9TqpVIpGo8HW1hb5fJ5YLMbS0tILayj1ej0ulwuTycTFixeZnZ3F7XYTiUQwGo14PB6MRqNcU3FkBohEIrhcLux2O4FAgHK5zNraGsVikVQqRSaToVwuk0gkMBgMfPe73+XUqVNMTU0xOjqKXq+n1+tRrVZZXl5mc3OT1dVVfvOb35DP50kkEs95dV5cFCN5SBAJAJ1Oh9PpxGq1YrfbCQaD+Hw+fvCDHzA+Po7H48Hj8VAsFllaWqJUKnHjxg2i0SgqlYrV1dUX1khqtVocDgdut5tXX32VN954A4fDQSAQQKPRoFY/uqxYpVLh9XoBcLvdjI6OUq1WWV1dpVAosLS0xMrKCplMhkqlgslk4syZM3z3u9+Vnmqv16NWq9FsNllbW+PKlSssLy/z6aefUi6X6XQ6+7kUCgMMrZEUGUThGWk0GqrVKtVqFa1Wi9VqlbEbtVqN1+tlZGQEjUYDfFlbFo1GSSQSNJtNisXiI4PoBx2z2YzZbMbpdDI7O4vNZsPj8eBwODCbzTgcDmksrVYr8GW2tN1u43Q6MZlMHDlyBI/Hg8FgoNVqUSgUWF1dpVKpPOer2x9EGY7H4+H06dP4/X7GxsbkGqrV6h2JExGWaLfbVKtVOp2OLAESWW+9Xo/b7cZoNNLv97Hb7RQKBXw+HzqdjpGREaxWqywharVaJJNJSqUSy8vL3Llzh2Qy+djkz0FArJnFYpFrEQqF5ElHXPvX0e/3yWazZLNZyuUym5ub36qS4NsytEZSlFeIhTWZTGxubrK5uYnVamViYgKTyYTJZEKn0/HSSy/xR3/0RxiNRgA6nQ4///nPeeedd8hms3KXPmy4XC5GRkaYnJzkT//0TwkGg0QiEZl1ValUqNVqDAYDarWafD5PMpnEaDQSDofR6XRMTk7S6/U4efIkMzMzbG5u8t//+39/YYykXq/HbDYzPj7On/7pn8qYo9/vl+s3SLvdptlsyge2VqsRj8cpFotMTk5y6tQpzGYzo6Oj9Pt9pqen6fV61Ot1CoUCANPT03g8Hvk7ajQa3L9/n3g8zocffsi7775Lp9Oh3W4f2HikWDu/38+pU6fw+XxcunSJkZER3G63vEcf/JlB+v0+3W6Xy5cvc+3aNZaWlshms3Id94OhM5IGgwGtVovT6SQUCsmHWRTXqlQqrFYrY2NjGI1GaSTD4TB+v18ayXa7jd1ux2KxUK1WH3tUOoio1Wp53YFAgLGxMSKRCF6vF5fLhdFoRK1W02q1qNVq9Pt9+ZXL5cjn85jNZlqtFgaDAYfDgclkkju+KDt5UTAajTidTtxuNx6PB7fbLU8vAmHk2u025XKZUqlEqVSSRjKRSFAul9HpdLhcLnQ6HbCz3AfA6XSi0+kwmUyo1WppBBqNBtlsllQqRbFYfGRW/CAgkoRqtRq73Y7ZbGZkZISRkRF8Ph/BYFDWgbpcLoCHPOUHN6Zutys3/0KhgNFoRKfTyQTXXjNUT4JWq2VycpJQKMTx48e5dOkSFosFm82GTqejWCxSLBall6nT6eSR2+Fw4PF45M3Y6XTw+XwEAgFardahMpImk4mXXnqJcDjMhQsXuHjxIkajURY2i/iXiG3V63UajQadTodWq0Wr1ZKGwW6382//7b/l/Pnz9Pt9/H4/lUpFPuSHHZVKxfj4OOfPn2d6epqpqSn8fv+Oo2C/36dSqfD555+TTCa5e/cu9+7do16vk8lk6HQ6cn3NZjN2u13ebyqViomJCUZHR5mcnOTtt9/G4XDI9280GlQqFWKxGB999BHLy8tsbGw8l7V4FhgMBnw+Hzabje9973ucOHECn8/H5OQkJpNJJr/0ej3wpQGs1+s7KgD0ej0Wi0V6lWq1mqmpKdxuNxaLhU8++QSj0ShjvHvNUBlJtVqN0+kkHA4zOzvLxYsXsVgsctdtNBo0Gg00Go30lgZLWuArd12r1WIymWT84zAZSeE5T09Pc+zYMc6dO0e326VcLlOv18nn86yvr3P79m0++OADKpUKlUplR/Bfp9Nhs9lwu9288sornDhxAkCGMAa9qMOO0+lkbGyMcDiMw+HAYrHI7wkPvNVqEYvF2NjY4MaNG3zxxRc0Gg3K5fKuiS4R4qjVaphMJmkABJ1Oh1qtRqlUku9fKpX29HqfJQ8+ezqdDrvdjsvlYm5uju985zu4XC7C4TAajUaGDkQ5lCi673a7OzzDwecbwOFwYLPZiMViOJ1OyuXyvh25n6uRFG612WwmHA5js9l48803OX78OBMTE5jNZvR6/Q7DJwzeowzkYUev12O1WvH7/Zw8eZITJ07gcDiIxWLkcjmuXr1KoVDg7t27xGIxmQhotVoPHUtErNfn88kETrfbfaHWU2A0GmX5zoObQ6FQYGtri2Qyyccff8zy8jLb29ty03nccU+tVmOxWNDr9YyNjbGwsMDY2NhDHno8HueLL75gc3NTxjUbjcaeXeuzQKPRoNfrMRqNTE5O4nA4sFqtsqJiamoKu93OqVOn8Pv9dLtdYrEYzWaTZDJJrVajVqtRrVZpNptkMhna7bZcT6fTKYvtT5w4gcvlkskwkY/Q6XTk8/l9MZTP1Uiq1WpZdnH06FH8fj+XLl3i4sWLaLVaaSAHjeSL5OE8iMFgwO12EwqFOHv2LBcuXCCVShGNRllZWeEnP/kJ8Xicra0tstms3K0f917hcFi2xIkY5YtmJFUqFSaTCa/Xi8PheOj+yuVy3Lp1i2g0ygcffMDi4qL0LndDo9Fgs9lkQuj48eMEg0F5zBTEYjE+/PBD4vE4sViMfD7/zK/xWSNOaS6XiwsXLjA+Pk4gECAUCuF0Opmbm5MtnGq1mmQyyfr6OoVCgWvXrpFOp8lms/K4LAyoMJSBQICJiQlZAaBWq3E4HBiNRqxWK9PT0xiNRhYXF/fnevflX3kAUdrjdrvxer34fD7m5ubw+Xy43W75/Ud5iiqVasfD/yJ5k8LjDofDWCwWGaddWlpic3OTbDYrPZEHj4DCa7fb7bIk6OjRo7IkRRST37t3j83NTarV6nO6yv1HeJI2m+2hsEy326XZbNJsNnf1HB9Er9fj9/txuVyyVtXhcMj3F+8nis1zudy+lrU8DUajEb/fj8fjYWRkhPHxcZn0MplMsiRKeIpbW1vcuXOHYrEoa0cLhQKlUkm+rt1u02636fV6VCoVstksVqtV/p1gUFxkv0Jo+24kRauX6Gp47bXX8Pv9nD17FrvdLpM0uxm+Xq8njyQGg+GF8S4DgQBvvvkm4XCYQCCATqfj7t27/I//8T/I5/OsrKw8UrJrMMN67Ngxzp49y8TEBG+//TY2m414PM7t27f56KOP+L//9/9SKpXIZrPP6Sr3H7/fz8LCgoxfDyKy2Q/GdHdDrVZjs9l4+eWXmZyc5MKFC5w6dUqejrrdrtzQFhcXuXr1KuVy+cBsTF6vl5deeolQKMTbb7/NzMyMPOU1Gg0SiQT1ep07d+4QjUZZXl7m448/pl6vU6/X6XQ6O2KQnU5nRwWG8DA7nQ7VanWH567VarHb7VQqlX2rwNhXIynKAywWC1arFZ/Px9jYGD6fT3pHu9Htdul0OjLY3e/3pa7foxAe55Mcjw4CItlitVrlRlKpVIjH45RKJbkjw1eeoyi2F/Exn8/HyMgIoVBIZhrX1tZIp9PE43E2Njao1+vP+Ur3F1FHOhj/Fgz2wYs4+G73kjCEFosFn89HKBTC7XZjs9nka4S3NOhR1Wq1A1M0bjAY8Hg80pt0u93y2ez1evKatre3iUajsr652Ww+du2EbRCF/eLPBwv5B43pfrFvRtJgMGCxWLDb7bz66quMjIxw5swZTp48+cgd/EH6/T6bm5sy+xeNRgH43ve+x/z8/CNfX6vVyOVylMvlA3MD7kaj0SCdTqPX6+UNV6lUSCaT1Ot1ecQWdWSiRU70bnu9XqamppiamqJcLvOrX/2KcrnM9evXiUajbG1tHZgj37Mkn8+zuLiI2+1mbGxsh+Ct3W5nZmYGg8GAy+UimUzSarUeu04jIyOcOnWKcDjMq6++KltB4avC6HK5zPvvv8/169e5c+cOtVrtoWPlMBMIBHjjjTcIBoNS93JtbY2lpSW2t7d57733ZIeMqCd9XFH84AY1Pz9PKBTC7/czMTGB1+tlYWEBj8cjY7nlcpl79+4Ri8UOX3ZbtBK63W4WFhY4cuQIc3NzTExMPHFMMZPJcP/+fTKZDHfu3EGj0XDixIlHGkn4stWrWq1Sr9cPhSfZbrcplUrYbDZ5RBEtl4MepE6nk4IMMzMz+P1+fu/3fo+RkRHZu3337l3+8R//ka2tLa5fv87W1pb00l80KpUKiUSCfr9PJBLZ8T2TyUQoFKLdbmO1WuVx+XFG0uv1curUKSKRCPPz8zveb7Bw/O7du3zwwQfkcrlHVh8MM4OJVovFQr/fJ5lMcuvWLVZXV/nVr35FOp1+omdOrVaj0+kwm81MTU0xPz/P1NQUp0+fxmq1EggEZIMIfOkoxGIxtra29u3Es6dGUqVSyfKAkZERzp07h9vt5sSJEzKr+nWJl0ajwcrKCoVCgStXrnD16lX5vjabDZPJ9NgjUrValR0Mh0G0oVqtsrGxQbfblbV3rVYL+Mo46vV6Tp06xcTEBMFgkNnZWcxmMzqdjkqlwubmJoVCgWg0yt27d8nlcpRKJRknetHo9/s0Gg2KxSJms/khYyUqCur1OjMzM7TbbaLRqDzJwJdx9tHRUTweDydOnGB2dhav1ys90sFup8XFRdLptPw9iLDRQULcazqdbkfypN/vy/i3wWDYURwueuD1er3MS4jsv9frxWq1cvLkSUZGRvD7/TidTqlqBV/1y4vi+/0U/dhTI6lWq4lEIoyMjPDKK6/wd3/3dzgcDrlQD8YbHkW5XOa3v/2tDHBfv36d6elp/uIv/oJIJILT6dzx+sH3y+VyrK+vy2DxQSeXy3H9+nUymQzb29uEQiEajQb9fl8Kgdjtdv7gD/6A3//938fpdBIIBGi326ysrJDNZvnZz37GL3/5SxmKaLfb+9beNaxUq1Xi8TgGg+Gh+0Q0M5hMJr7zne/g9/v54IMP2NraksZNr9dz/vx5Tp06xezsLBcuXMBsNss4pPAgY7EY//zP/8z29jY3btwgHo9LQ3KQEGrtj2rSUKlUGI1GLBaLvK8cDgehUAi9Xi+f/5mZGaanp2XRucVikaVoojQQkO8vusVqtZqsjxQOwp5f716+uUqlwmAwYLPZsNvt0vt71CQ4sduK0ohmsyk1D2OxGNvb2xQKBRl7E4WrDxbnipKNRqMhRS3E0fSgI1q4xIiAfD4vjxxCyFVIb3k8HqkdWalUZGImmUySzWblGr3IxlHQbrep1WpywxlEpVLJ4mmv10uj0ZAbv8jQiiN5OBzG6/VisVh2GJBms0mr1aJcLpNKpUilUtRqtQPtuYs2QuHpmc1mXC4XjUaDyclJnE6n3ByE3Jxer8dms2E0GhkZGSEYDGK326Uaknj+hUC06G1XqVS0223ZcddoNGSXzn6w50ZSKDl7vV5504gLFzekcKVbrRbLy8skEgnW19e5cuUKhUKB27dvk8vlaDQaMoB+5MgRJiYmcDgcO/7Ner3OvXv3yGazUnyg2+0eCiPZbrdlDdm1a9eoVCqsr6/T7/exWq0sLCwQCASYnJwkEAjImy2fz/OTn/yEzz//XAbTxU2ugGwJtNlsj/VOLBYLFy5c4NixY0xOTvKd73xHzqDR6/W8/vrrzM7OYjKZsFqt8qQkZL5EmdXly5dJJpOUy+V9vspnh5CIE7N+dDod09PTeL1e6vU6ly5d2lHWMyjoIeobhTiN2DxE2VmlUpFSdUKPQKvVUiqVSKVSbG9vk0gkSKfT+5Zk3HMjKZScB4Ov8JXnCF8aSSG8kMvliMViLC4u8sUXX+yYFSI06EwmE263G6fTiV6v32EAO50OuVxO3ojfpAB42On3+1JMIZVKYTKZKJVK9Pt92bkkiqIHM7StVov19XXu3bt3qEqinhXiQa1Wq/KI+GCsXKvV4vf75ffMZjONRoNcLodWq5UiFg+ejHq9HuVymUwmQyaTkSrlB5lerycL7EXcUJwWe70eExMTO9ZBtBHDV8dnsUmXy2Wy2SzVapVEIkE+n0elUuH3+1Gr1fLZbTQalEolqU+wn62b+3bcFkZSuOCifKVarZLP57l//z7FYpEbN26wsbFBKpUiHo/LdiWVSsXo6CjT09OynMVutz/U5tVqtdja2mJ9fZ1cLncoDUKj0eD27dtsbW3J2Fi1WuXOnTskEgkWFhZwu91ylIDH4+Fv/uZveOONN7hx4wY3b96kVquRSqUORaz2aRDFy3fv3qXRaPDLX/6SUCjEsWPHGBkZeegBV6lUuFwuNBqN7CxRq9UyCSnes16vy4Tj559/zrVr14jFYgemYHw3tre3effdd2U3kRB99ng8MjQxeGqsVqsy/i20BNLptCwa39rakmVVYhM6d+4cRqNRHrXv3LnD+++/z+rq6r7X8e55CZDwJAf180QmtVgskkwmiUaj/PznPyeRSMgq/QeNm1qtZnR0lJdffpmpqSkZc3sQYSSXl5fJ5/OHxoscpNlscvv2beCrmG6lUuHu3btYLBbOnDlDIBBgdHRUtnr+u3/37+h0Ovyv//X/t3d2T2mcXxz/LiwKwgIqCIKImoTa2KRpEtN0Jpmm01600/tOe9W/q9e9+d30pp02U3ORtmkzzauJaEJEE0UCLG8Lu7y/+bvIPKeYWLQxkQX3M+PkxsFls3ue8zznnO/3fyTxJUnSkQ+SwIvWMibkajab4Xa7IQgCPB4PALySBTHB2JefT+CfwmGlUqFneWFhAb///nvfHPuIoojr16/DarViamoKdrsdU1NTmJmZIQ/x9lpBJpNBOBxGsVhENBqlXsdwOEztV81mE06nExaLBV6vl3aMwIvt/ePHj/Hzzz9DUZRD19p8q0GSrdJPnz5FtVolDxZ26JpKpeggmynZdJo8EASBWof+bSSJiaOyBt1+ZbeXjS1A0WgUKysrqNVqcLlcVGk1GAxwu92Ym5ujBnRZlpHNZvsiwzkIrGiQSCTQaDTw+PFjmizx+Xy7Tn/s1pnBFvd6vU5dCKwFrR8CJPBiARBFEYVCAa1WCxaLBbIs06ADs1ZhZDIZRKNROiZiBVlZlkmHE3hR/GFmdXq9nlrdisUinVd2o+f5rQbJRqOBhw8fIhKJQBAEXLt2jaTqa7UaJEkimaRSqURl/t3gOI7Ub9pFS3f7m+xM8ii++LVaDTdu3MDi4iIuXrwIg8EAp9OJkydPYnh4GB988AEmJiYQjUYxMTEBURRx48YNrK2tdfvSu44sy1hcXMTAwACSySSuX7+Ojz76CF9//TUsFsuOvr2XaT+DA4BSqYRgMIilpSXEYrG+CZAAaFFljeCsZYeNyr68mLTbULAaQbtVbqPRwODgIHw+H44fPw6fzwej0YharYZgMIhEIoFQKEQZ52F3Bbz1TLJQKKDZbKJYLKJSqVCQrNfrkCQJ2Wx2z89hN55t3Vkv1b/9TdY+1M+Z5L/RarWQz+fpIJxNkvh8Phr/GhsbQ6PRgNfrhV6vp8bdTpMkRwFWkGg2m8jlchgcHCRR3U4zw+1nkQyWTR5mq8ph0Ww23/iWlxV/2DGaTqejTJJlnd3y+3nrQZIFxFKpRG0PrIK4n2ZQJs5gNBphs9lIV+7fgmS9Xqdzzl71CTko7P6GQiF8//33cDqdiEQi8Pl8mJmZwfT0NNxuN65cuUJBwOFwIBqNIhQKHdlzSpPJBI/Hg6GhIQQCAXg8Hprl/q/SXEajEbOzs9Dr9bh37x5EUXyLV967sLYgQRBw5swZfPLJJ3C5XABeZPb37t3D48ePqU7RDd564YbpxL0urELOrFPZA/tvkzqNRgO5XG5fGWq/ws50WSY5MjICm80GSZIgCAJOnDhBmoClUgnr6+t0NnRYQqZqxGAwUNeEx+OB1+slcQWmb7pfBgYGaOZ7bW1tT/Wgo0q71sDk5CTm5ubo/a5UKtjc3MSTJ0+6Kt2nKo+b3bBarfj000/h9/tx+vRp0kU8SmK7B6VarWJtbQ35fB5ms5mmI44dOwae5zE5OUntLMvLyygWiz0/EfJfcLvdcLvdcLlcmJ+fJ6fO4eFhjI+P0/P2X2ifYe4nf6U3jcVioeEHp9MJo9FI7WmRSATpdBqyLHfVDlr1QXJkZATffvstLl++TAIOndAeyFcplUq4d+8eeJ4n4dOZmRmMj4/DZrPRFEmtVsOtW7eQy+Voprvf4TgOMzMzuHTpEvx+Pz7//HPq92NTM68j7to+VbLXM3uUsdvt5Pw5MTEBs9mMVCqFlZUVbGxsIB6PI51Od7WVT/VBcq8VmZ2/sab0ra2tQxt87xVYEaHRaJBNg8lkQiqV2jFBMjw8TJVFSZJUb0j1OrQLEbNdycjICPWTWiyWHYXB9oos68BgFVbm9aLX68kvvp3dKr0aL2BFRJatj4+Pw2QykQ5sJpNRjYyc6oMkO2NMp9Mk2MAeOqbwXC6Xcfv2bfz0008QRRGRSKTLV61Otre3EQ6HkUgkcOzYMRgMBoyPj+PcuXOYmprC+++/D47jsLGxge+++w75fL7bl/zGYX42JpMJExMTsFqtmJ+fx7lz53ao0DCYJqmiKAgGg9R0ns/nSfbParXuENfV6AzHcXC73fD7/Zibm8OXX34Jt9sNs9mMcrmMaDSKv/76i6ra3Ub1QRIAtVK0jzayf2u1GsrlMuLxOB4+fEjNpxq7w5SiDQYDtra20Gq1MDc3B57nMTw8jOPHjwPAnlYavQjblQiCALPZDJfLRZkM0zR8uQ+SWYUoikLiCizLcbvd8Hq9NDqnsX/MZjNZQPh8PoyNjVH/dKFQQDKZRCqVUsWuUPVBUq/Xw2KxwG63v9JA3mw2sbm5iWg0itXVVSQSCRQKBe2B3QeFQgHBYBCiKOLUqVOYnp4m1aZcLgeHwwGHw0Eeyb0M+15WqxWBQAAff/wxqV6bzWayDGBV7HaePXuGhYUFZLNZPHr0CNlslsRVBEHAxMQEyaNp7A3zrhkfH8fp06cxMzNDIjX5fJ4UmdbX17tesGGoPkhyHAeLxbJDEo1lkvV6Hc+fP8fKygqZWanhpvYChUIBoVAI6XSaRhR5niehAmbwxM7iehmdToeRkRF4PB6cO3cOX331Fex2O3lDdzoz3NzcxI8//oh0Ok2WAWfOnMHo6CjMZjM8Hg+cTuehOff1Mkybkykqvfvuu+RF3mq1aLQxHo9ja2tLNTtC1f7PMte5oaGhV1Z3JkHF5mOj0Siy2WzXD3h7CSaFzzyAyuUyTCYTjEYjjEYjxsfHIUkSydf1MjqdjlrIjh07RnYWnYoqtVoNjUYDHMfB4XDQPQGAQCCAEydOUJFrN0c/ZvjFfNA1QGfggiBgcnKSjMSYotLW1hbC4TCi0aiqOitUGySNRiMcDgecTucrLRRMxEJRFDx69Ah//vknJElS1Y1VO/V6HblcDtvb25AkiXT82Fby/PnzZP2wubnZ043QAwMDuHLlCr755huS9erUHM6yGkVRwPM8Tp06BYPBgPPnz2NsbIxsfQcGBmC1Wnd8FlvAq9UqWfQelquf2hkaGsKFCxfg9/tx6dIlnD17lma+ZVnGjRs3sLCwgGQyqaojM9UGSYPBQO0Yu2WSbM64WCwin8/3jSPiYcKET9kPU4zX6/UwmUyUcfU6HMdBEAS4XC7a7u0Fm9NmSkCsGu52u0n8md2r9mBbr9dpAZdlGfl8noQcjjKsaDY6OkoZpNlsRqvVIquVbDaLZDKpOgto1QZJ1l4xOTn5im4kE8xQFIVGEPvFx+awYIGQZUXMZwToTyUlvV5PKjV7odPpYLVaYTKZSF9Sr9fD6XSSLmr7wt0ufrG2toa7d+8iHo/jt99+QzQahSRJb/OrqR5mGet0OvHhhx/izJkzcLlc4DgO+XweKysrEEUR6+vrlEWq6V1WbZA0mUzwer20crfD/HCq1WpfVF+7AWumZlkRa6wGdi5CamjBeBPsFtg6we4Lq4LvBdtmZ7NZckJkfk1HHdZsLwgC/H4/AoEAPWvlchmRSATxeBypVAqFQqHLV/sqqguSbPvicDgwOztLbRrtAgG5XI5W61Qq1eUr7k0sFgsCgQBcLhcpcbebVoVCIYRCISSTSVWt6q9Dq9VCNBrFgwcPMDw8TBJxB6VarSKbzaJarWJzcxPpdBqPHj1CMBgkT20NkG2s3++nM9xMJgNJkrCxsYG///4boiiq1vtHdUGS53nqo5qfnycFGwAUKDOZDK5du4ZIJLLDJF5j/9hsNszPz8Pr9ZIEfzabJafKO3fuYGlpSVVnQ69Ls9nE6uoq/vjjDwQCAdo2HxSWBWWzWSwsLGB5eRmiKOLp06c0vqgBOJ1OXLhwARMTExgdHQXP84jH41haWsKTJ09w9epVpFIp1XYBqC5IsnlXZkPJzoCAna0/hUKBhDg1OqPT6UhSn+d56PV6eL1eeL1e0k/kOA7lchmiKCKVStGccj/QarUgSRIikQh4nidLi/20ArV/BhPQZUrbsiwjHA4jl8shHo+TXa8a5o3VAHuXh4aG4HK54HA4qFOlVCohnU5Txq1mcWJVBUl2U3meJ5FdQRBoa8Qk3xVFgSiKSCQSh+6c1ouYTCacPn0aTqcTdrsdNpsNfr8fn332GUZHRyEIAgAgEong119/RSwW66u2lUajgcXFRaytrcFut+OXX34h9SP24r5sefwylUoFGxsbkGUZuVyOXu5kMknb7mKx2FcWxgeFeVr5/X5cvnwZo6OjsNvt2N7eRiwWw/379xGPx1EsFlVXrGlHVUES+KeJ3GAw0A/wTxbJWn/K5bKqVx810G574XQ6SUR2ZGQEPp8PXq8XNpuN7qmiKHj+/DlEUeyrySXWC5rP55HNZpHJZGC1WmE0GlEsFknSrBPlcpmyRuahXalUkMvlaGut1pe8G7SL6QqCAKfTieHhYXqfy+UyZd5q70xRVZDkeR6zs7OYnp7G7OzsK/1szL83mUwil8tp2+09cLvdCAQCGBsbwxdffEETIqy1hed5lEolPHnyBPF4HLdu3cLy8jJkWe67DJ0tspVKhXyx7969S/dhr97JRqOBTCaDSqWCSqWCcrm8w+BKzS95N+B5Hu+88w6mp6fx3nvvQRAEDA4O0nGFoijIZrOQZVn1iY6qgqRer8f09DTm5+dJNZvRrjOXy+WgKErf9PC9LUZHR3H27Fn4fD5cuXIF09PT9EKzs91isYjV1VWsrKzgwYMHCIfDfZVFMtj3rtVqdGSj1mpqP6DX6zEzM4P5+XkEAgGYzWYMDAzs8LySZbmjhbRaUEWQZKn50NAQxsbGSJtPp9PRCt1qtSCKIikW90v/3tuEyXwVi0XaDhYKBSiKgnK5jHQ6TaOdq6urEEVR9au6Rm/AGvJdLhcEQQDHcajVaohGo8jn80gkEuSgqvYsXBVBkud5WK1W2O12nDx5EhcvXiSFFgCUogeDQfzwww+qbTpVG+VyGYlEAoODg6hUKmi1WojFYjTZcP/+fUiShMXFRWxubpJ6uYbGQdHpdPB4PDh58iSJWMiyjNu3b2NjYwPBYBDJZJKcBdSMKoJkJ5iaCttqp1Ip5HI5LePZB+2z7clkEjabDbFYDLFYDMlkEvF4nLzPtUVH403Cdoesws1xHL3L7HlTe8GGoYogyQ5yW60WlpaWYLPZMDU1hbNnz6JQKODq1auIRCK4efMmnj59SjJWGp2RJAnBYBBra2uIRCKwWCy03WaV2Xq93pc2DRrqo9FoIJ1OIxaLQVGUbl/OvlFFkNze3ka1WgXHcUgmk3j27BnMZjO1+qyurmJ5eRnr6+uQJKknVh81wHQiAWBjY6O7F6NxJGkvFDabTRQKBeTz+Z4qDqoiSDIajQbC4TAqlQqePXuGUCiEcrmMW7duIZFIaAFSQ6NHqNVquHnzJhRFgclkgtVqhaIouHPnDuLxOGmZ9gLc9j6v9LBsMXU63Y4fADTFoJZ+tNe9Bs1a9B+0e3hw1H4P2Qgsx3Gku9CL77LqgmQvoPaHsxfQ7uHB0e7hwXmjQVJDQ0PjKKLb+1c0NDQ0ji5akNTQ0NDogBYkNTQ0NDqgBUkNDQ2NDmhBUkNDQ6MDWpDU0NDQ6IAWJDU0NDQ6oAVJDQ0NjQ5oQVJDQ0OjA/8H1mjMJE12Q9IAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 400x400 with 16 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for X in batch_iterate(16, train_images):\n",
" fig,axes = plt.subplots(4, 4, figsize=(4, 4))\n",
"\n",
" for i, ax in enumerate(axes.flat):\n",
" img = mx.array(X[i]).reshape(28,28)\n",
" ax.imshow(img,cmap='gray')\n",
" ax.axis('off')\n",
" break"
]
},
{
"cell_type": "code",
"execution_count": 203,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"0it [00:00, ?it/s]\n"
]
},
{
"ename": "TypeError",
"evalue": "'bool' object is not callable",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[203], line 28\u001b[0m\n\u001b[1;32m 23\u001b[0m disc_opt\u001b[38;5;241m.\u001b[39mupdate(disc, D_grads)\n\u001b[1;32m 25\u001b[0m \u001b[38;5;66;03m# Update gradients\u001b[39;00m\n\u001b[0;32m---> 28\u001b[0m G_loss,G_grads \u001b[38;5;241m=\u001b[39m \u001b[43mG_loss_grad\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdisc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mz_dim\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 30\u001b[0m \u001b[38;5;66;03m# Update optimizer\u001b[39;00m\n\u001b[1;32m 31\u001b[0m gen_opt\u001b[38;5;241m.\u001b[39mupdate(gen, G_grads)\n",
"File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/mlx/nn/utils.py:34\u001b[0m, in \u001b[0;36mvalue_and_grad.<locals>.wrapped_value_grad_fn\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[38;5;129m@wraps\u001b[39m(fn)\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapped_value_grad_fn\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m---> 34\u001b[0m value, grad \u001b[38;5;241m=\u001b[39m \u001b[43mvalue_grad_fn\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrainable_parameters\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 35\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m value, grad\n",
"File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/mlx/nn/utils.py:28\u001b[0m, in \u001b[0;36mvalue_and_grad.<locals>.inner_fn\u001b[0;34m(params, *args, **kwargs)\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21minner_fn\u001b[39m(params, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 27\u001b[0m model\u001b[38;5;241m.\u001b[39mupdate(params)\n\u001b[0;32m---> 28\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
"\u001b[0;31mTypeError\u001b[0m: 'bool' object is not callable"
]
}
],
"source": [
"batch_size = 8\n",
"cur_step = 0\n",
"mean_generator_loss = 0\n",
"mean_discriminator_loss = 0\n",
"test_generator = True # Whether the generator should be tested\n",
"gen_loss = False\n",
"error = False\n",
"\n",
"D_loss_grad = nn.value_and_grad(disc, disc_loss)\n",
"G_loss_grad = nn.value_and_grad(gen, gen_loss)\n",
"\n",
"\n",
"for epoch in range(n_epochs):\n",
" \n",
" # Dataloader returns the batches\n",
" for real in tqdm(batch_iterate(batch_size, train_images)):\n",
"\n",
" # Flatten the batch of real images from the dataset\n",
" \n",
" D_loss,D_grads = D_loss_grad(gen, disc, real, batch_size, z_dim)\n",
"\n",
" # Update optimizer\n",
" disc_opt.update(disc, D_grads)\n",
" \n",
" # Update gradients\n",
" \n",
" \n",
" G_loss,G_grads = G_loss_grad(gen, disc, batch_size, z_dim)\n",
" \n",
" # Update optimizer\n",
" gen_opt.update(gen, G_grads)\n",
" \n",
" # Update gradients\n",
"\n",
" \n",
"\n",
" # # Keep track of the average discriminator loss\n",
" # mean_discriminator_loss += disc_loss.item() / display_step\n",
"\n",
" # # Keep track of the average generator loss\n",
" # mean_generator_loss += gen_loss.item() / display_step\n",
"\n",
" # ### Visualization code ###\n",
" # if cur_step % display_step == 0 and cur_step > 0:\n",
" # print(f\"Step {cur_step}: Generator loss: {mean_generator_loss}, discriminator loss: {mean_discriminator_loss}\")\n",
" # fake_noise = get_noise(cur_batch_size, z_dim, device=device)\n",
" # fake = gen(fake_noise)\n",
" # show_tensor_images(fake)\n",
" # show_tensor_images(real)\n",
" # mean_generator_loss = 0\n",
" # mean_discriminator_loss = 0\n",
" # cur_step += 1\n"
]
}
],
"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.10.10"
}
},
"nbformat": 4,
"nbformat_minor": 2
}