Skip to content

Instantly share code, notes, and snippets.

@mtreviso
Last active February 2, 2021 11:00
Show Gist options
  • Save mtreviso/380b9c90a67e25175221f22e6ba84a18 to your computer and use it in GitHub Desktop.
Save mtreviso/380b9c90a67e25175221f22e6ba84a18 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "surprised-workstation",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import entmax\n",
"from cvxpylayers.torch import CvxpyLayer\n",
"import cvxpy as cp"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "vulnerable-person",
"metadata": {},
"outputs": [],
"source": [
"def sparsemax_fw(X, dim=-1):\n",
" max_val, _ = X.max(dim=dim, keepdim=True)\n",
" X = X - max_val # same numerical stability trick as softmax\n",
" tau, supp_size = entmax.activations._sparsemax_threshold_and_support(X, dim=dim)\n",
" return torch.clamp(X - tau, min=0)\n",
"\n",
"def cvx_sparsemax(X):\n",
" max_val, _ = X.max(dim=-1, keepdim=True)\n",
" X = X - max_val # same numerical stability trick as softmax\n",
" # batch dimension is infered by cvxpy and then broadcasted\n",
" n = X.shape[-1]\n",
" x = cp.Parameter(n)\n",
" y = cp.Variable(n)\n",
" obj = cp.sum_squares(x-y)\n",
" cons = [cp.sum(y) == 1, 0. <= y, y <= 1.]\n",
" prob = cp.Problem(cp.Minimize(obj), cons)\n",
" layer = CvxpyLayer(prob, [x], [y])\n",
" out, = layer(X)\n",
" # just to get rid of unstable negative numbers\n",
" return torch.clamp(out, min=0)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "detected-cruise",
"metadata": {},
"outputs": [],
"source": [
"batch_size = 2\n",
"n = 8"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "pediatric-honor",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[ 0.7259, -0.7018, 2.2492, 0.4574, 0.1678, -1.1111, 0.2099, -0.6585],\n",
" [ 1.0499, 1.2296, -1.2662, 0.4773, 0.2722, -0.4636, -0.4626, -0.3327]],\n",
" requires_grad=True)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X = torch.randn(batch_size, n)\n",
"X1, X2, X3 = X.clone().requires_grad_(True), X.clone().requires_grad_(True), X.clone().requires_grad_(True)\n",
"X1"
]
},
{
"cell_type": "markdown",
"id": "partial-continuity",
"metadata": {},
"source": [
"## Autograd sparsemax"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "heated-compatibility",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.4102, 0.5898, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]],\n",
" grad_fn=<ClampBackward>)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h = sparsemax_fw(X1, dim=-1)\n",
"h.retain_grad() # to save grad in .grad\n",
"h"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "engaged-delivery",
"metadata": {},
"outputs": [],
"source": [
"loss = (h ** 2).sum()\n",
"loss.backward()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "progressive-split",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [-0.1797, 0.1797, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])\n",
"tensor([[0.0000, 0.0000, 2.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.8203, 1.1797, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])\n"
]
}
],
"source": [
"print(X1.grad.data)\n",
"print(h.grad.data)"
]
},
{
"cell_type": "markdown",
"id": "blind-technical",
"metadata": {},
"source": [
"## Specialized sparsemax"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "beginning-default",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.4102, 0.5898, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]],\n",
" grad_fn=<SparsemaxFunctionBackward>)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h2 = entmax.sparsemax(X2, dim=-1)\n",
"h2.retain_grad() # to save grad in .grad\n",
"h2"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "organic-environment",
"metadata": {},
"outputs": [],
"source": [
"loss2 = (h2 ** 2).sum()\n",
"loss2.backward()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "pleased-leone",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [-0.1797, 0.1797, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])\n",
"tensor([[0.0000, 0.0000, 2.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.8203, 1.1797, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])\n"
]
}
],
"source": [
"print(X2.grad.data)\n",
"print(h2.grad.data)"
]
},
{
"cell_type": "markdown",
"id": "academic-bloom",
"metadata": {},
"source": [
"## cvxpylayers sparsemax"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "southeast-medium",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 8.6379e-09, 0.0000e+00,\n",
" 4.7698e-09, 0.0000e+00],\n",
" [4.1017e-01, 5.8983e-01, 0.0000e+00, 7.6037e-08, 9.7740e-08, 0.0000e+00,\n",
" 0.0000e+00, 1.2660e-08]], grad_fn=<ClampBackward>)"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h3 = cvx_sparsemax(X3) # no dim -> cvxlayers always get 1d or 2d inputs, so dim=-1 always\n",
"h3.retain_grad() # to save grad in .grad\n",
"h3"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "paperback-commercial",
"metadata": {},
"outputs": [],
"source": [
"loss3 = (h3 ** 2).sum()\n",
"loss3.backward() "
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "extended-taxation",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[-1.0728e-09, 1.9481e-09, 7.0073e-09, -2.7421e-09, -5.3363e-09,\n",
" 1.5065e-10, -2.0931e-09, 2.1382e-09],\n",
" [-1.7966e-01, 1.7966e-01, 1.1963e-07, -1.5928e-08, 1.5564e-07,\n",
" -1.1809e-07, -1.1841e-07, -9.3386e-08]])\n",
"tensor([[0.0000, 0.0000, 2.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.8203, 1.1797, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])\n"
]
}
],
"source": [
"print(X3.grad.data)\n",
"print(h2.grad.data)"
]
},
{
"cell_type": "markdown",
"id": "veterinary-regard",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "parental-mortality",
"metadata": {},
"source": [
"## Performance comparison"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "backed-adrian",
"metadata": {},
"outputs": [],
"source": [
"def small_net(X, prob_fn, dim=None):\n",
" h = prob_fn(X) if dim is None else prob_fn(X, dim=dim)\n",
" h.retain_grad() # to save grad in .grad\n",
" loss = (h ** 2).sum()\n",
" loss.backward()\n",
" return h"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "other-criticism",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.4102, 0.5898, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]],\n",
" grad_fn=<ClampBackward>)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"small_net(X1, sparsemax_fw, dim=-1)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "seventh-harassment",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],\n",
" [0.4102, 0.5898, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]],\n",
" grad_fn=<SparsemaxFunctionBackward>)"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"small_net(X2, entmax.sparsemax, dim=-1)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "defined-outreach",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 8.6379e-09, 0.0000e+00,\n",
" 4.7698e-09, 0.0000e+00],\n",
" [4.1017e-01, 5.8983e-01, 0.0000e+00, 7.6037e-08, 9.7740e-08, 0.0000e+00,\n",
" 0.0000e+00, 1.2660e-08]], grad_fn=<ClampBackward>)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"small_net(X3, cvx_sparsemax, dim=None)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "substantial-creator",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"import numpy as np\n",
"\n",
"def timeit(module, *args, runs=5, verbose=False, **kwargs):\n",
" t = [] # accum times\n",
" result = None # final output\n",
" has_cuda = torch.cuda.is_available()\n",
" \n",
" # prepare everything to cuda\n",
" if has_cuda:\n",
" module = module.cuda()\n",
" args = [arg.cuda() for arg in args]\n",
"\n",
" # warm up the cpu/gpu\n",
" module(*args, **kwargs)\n",
" \n",
" for _ in range(runs):\n",
" # start timer\n",
" if has_cuda:\n",
" event_start = torch.cuda.Event(enable_timing=True)\n",
" event_end = torch.cuda.Event(enable_timing=True)\n",
" event_start.record()\n",
" else:\n",
" time_start = time.perf_counter()\n",
"\n",
" # computation\n",
" result = module(*args, **kwargs)\n",
"\n",
" # stop timer\n",
" if has_cuda:\n",
" event_end.record()\n",
" torch.cuda.synchronize(GPU_ID)\n",
" elapsed_time = event_start.elapsed_time(event_end) # in ms\n",
" elapsed_time /= 1000 # in s \n",
" else:\n",
" time_end = time.perf_counter()\n",
" elapsed_time = time_end - time_start # in s\n",
"\n",
" t.append(elapsed_time)\n",
" \n",
" # Averaged elapsed time\n",
" if verbose:\n",
" print('Avg. elapsed time: {}s (+/- {:.4f})'.format(np.mean(t), np.std(t)))\n",
" return np.mean(t), result"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "increasing-antibody",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(0.025603865400000016,\n",
" tensor([[0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 8.6379e-09, 0.0000e+00,\n",
" 4.7698e-09, 0.0000e+00],\n",
" [4.1017e-01, 5.8983e-01, 0.0000e+00, 7.6037e-08, 9.7740e-08, 0.0000e+00,\n",
" 0.0000e+00, 1.2660e-08]], grad_fn=<ClampBackward>))"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import partial\n",
"sparsemax_fw_net = partial(small_net, prob_fn=sparsemax_fw)\n",
"sparsemax_sp_net = partial(small_net, prob_fn=entmax.sparsemax)\n",
"sparsemax_cvx_net = partial(small_net, prob_fn=cvx_sparsemax)\n",
"\n",
"timeit(sparsemax_fw_net, X1, dim=-1, verbose=False)\n",
"timeit(sparsemax_sp_net, X2, dim=-1, verbose=False)\n",
"timeit(sparsemax_cvx_net,X3, dim=None, verbose=False)"
]
},
{
"cell_type": "markdown",
"id": "opponent-geology",
"metadata": {},
"source": [
"## As hidden size grows"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "combined-investing",
"metadata": {},
"outputs": [],
"source": [
"from matplotlib import pyplot as plt\n",
"def plot_times(x, y1, y2, y3, xlabel='hidden size'):\n",
" to_ms = lambda z: np.array(z) * 1000\n",
" plt.plot(x, to_ms(y1), '-', label='forward-sparsemax')\n",
" plt.plot(x, to_ms(y2), '-', label='specialized-sparsemax')\n",
" plt.plot(x, to_ms(y3), '-', label='cvx-sparsemax')\n",
" plt.legend()\n",
" plt.xticks(x)\n",
" plt.xlabel(xlabel)\n",
" plt.ylabel(\"time (ms)\")\n",
" plt.tight_layout()\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "powerful-space",
"metadata": {},
"outputs": [],
"source": [
"batch_size = 4\n",
"N = [2**i for i in range(2, 20)]"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "certain-latino",
"metadata": {},
"outputs": [],
"source": [
"# it takes about 30s to run on my mac (no gpu)\n",
"t1s, t2s, t3s = [], [], []\n",
"for n in N:\n",
" X = torch.randn(batch_size, n)\n",
" \n",
" # forward-pass sparsemax\n",
" X1 = X.clone().requires_grad_(True)\n",
" t1, res1 = timeit(sparsemax_fw_net, X1, dim=-1, verbose=False)\n",
" t1s.append(t1)\n",
" \n",
" # specialzied sparsemax\n",
" X2 = X.clone().requires_grad_(True)\n",
" t2, res2 = timeit(sparsemax_fw_net, X2, dim=-1, verbose=False)\n",
" t2s.append(t2)\n",
" \n",
" # cvx sparsemax\n",
" X3 = X.clone().requires_grad_(True)\n",
" t3, res3 = timeit(sparsemax_fw_net, X3, dim=-1, verbose=False)\n",
" t3s.append(t3)\n",
" \n",
" # outputs should be close\n",
" assert torch.allclose(res1, res2)\n",
" assert torch.allclose(res2, res3)\n",
" # grads should be close\n",
" assert torch.allclose(X1.grad.data, X2.grad.data)\n",
" assert torch.allclose(X2.grad.data, X3.grad.data) "
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "accessible-christopher",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plot_times(N, t1s, t2s, t3s, xlabel='hidden size')"
]
},
{
"cell_type": "markdown",
"id": "suburban-longer",
"metadata": {},
"source": [
"## As batch size grows"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "conditional-guess",
"metadata": {},
"outputs": [],
"source": [
"B = [2**i for i in range(2, 11)]\n",
"n = 1024"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "fundamental-broadway",
"metadata": {},
"outputs": [],
"source": [
"# it takes about 30s to run on my mac (no gpu)\n",
"t1s, t2s, t3s = [], [], []\n",
"for batch_size in B:\n",
" X = torch.randn(batch_size, n)\n",
" \n",
" # forward-pass sparsemax\n",
" X1 = X.clone().requires_grad_(True)\n",
" t1, res1 = timeit(sparsemax_fw_net, X1, dim=-1, verbose=False)\n",
" t1s.append(t1)\n",
" \n",
" # specialzied sparsemax\n",
" X2 = X.clone().requires_grad_(True)\n",
" t2, res2 = timeit(sparsemax_fw_net, X2, dim=-1, verbose=False)\n",
" t2s.append(t2)\n",
" \n",
" # cvx sparsemax\n",
" X3 = X.clone().requires_grad_(True)\n",
" t3, res3 = timeit(sparsemax_fw_net, X3, dim=-1, verbose=False)\n",
" t3s.append(t3)\n",
" \n",
" # outputs should be close\n",
" assert torch.allclose(res1, res2)\n",
" assert torch.allclose(res2, res3)\n",
" \n",
" # grads should be close\n",
" assert torch.allclose(X1.grad.data, X2.grad.data)\n",
" assert torch.allclose(X2.grad.data, X3.grad.data) "
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "grave-fifteen",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAABVzElEQVR4nO3dd1iV5RvA8e/DUEQUBcW9tyCKinujmSPNzMzUHA37lWZWrjQVR5mrXLlylmVZOTIzRxrujXuguHAxlL05z++PcyQHKCqHw7g/18UFvOcd9zkez837vM9730prjRBCCJHZWFk6ACGEECIlkqCEEEJkSpKghBBCZEqSoIQQQmRKkqCEEEJkSjaWDuB5FCpUSJctW9bSYQghhHgOhw8fDtZaF354eZZOUGXLluXQoUOWDkMIIcRzUEpdSWm5DPEJIYTIlCRBCSGEyJQkQQkhhMiUsvQ1qJQkJCQQEBBAbGyspUMR2YSdnR0lS5bE1tbW0qEIkaNkuwQVEBBAvnz5KFu2LEopS4cjsjitNSEhIQQEBFCuXDlLhyNEjpLthvhiY2NxdnaW5CTShVIKZ2dnOSMXwgKyXYICJDmJdCXvJyEsI1smKCGEEFmfJCgzmDVrFtWqVaNnz54WjWPcuHFMmzbNojEIIbKnu7F3GbVrFHtu7DHbMbLdJInM4Ntvv2Xr1q2ULFnyiesmJiZiY/P8/wxaa7TWWFlZ5m+O9HoeQojMTWvN+ovrmXZoGpHxkVR3rk6j4o3Mciw5g0pn7733Hv7+/rRr147p06fz8ssv4+7uToMGDTh+/DhgPLPp3bs3jRs3pnfv3nTo0CH5MQ8PD8aPHw/AmDFjWLRoEZGRkXh5eVG7dm1q1KjBunXrALh8+TJVqlThzTffxM3NjWvXrjFp0iQqV65MkyZNOHfuXIoxRkVF0aFDB2rWrImbmxs///wzYCwdNWzYMGrUqEG9evW4cOECAH/88Qf169fHw8OD1q1bc/v27RSfx6lTp6hXrx61atXC3d0dPz8/AH744Yfk5QMGDCApKQkABwcHhg4diqurK61bt+bAgQO0aNGC8uXLs379+uTn2LRpU2rXrk3t2rXZs8f419qaNWvw8vJCa83NmzepXLkyt27dSt9/TCHEAy6HXebtzW8zevdoyuYvyy8v/ULPauYbKcrWf/J6/3GK0zfC03Wf1YvnZ+xLrqk+Pn/+fDZt2sT27dvx9vbGw8ODtWvX8s8///Dmm2/i6+sLwOnTp9m1axd58uRh8uTJ7Ny5kzJlymBjY8Pu3bsB2LlzJ/Pnz8fOzo41a9aQP39+goODadCgAZ06dQLAz8+P5cuX06BBAw4fPsyqVavw9fUlMTGR2rVrU6dOnUdi3LRpE8WLF+fPP/8EICwsLPkxR0dHTpw4wYoVK/joo4/YsGEDTZo0Yd++fSil+O6775gyZQrTp09/5HkMGjSIwYMH07NnT+Lj40lKSuLMmTP8/PPP7N69G1tbW95//31WrlzJm2++SVRUFK1atWLq1Kl06dKF0aNHs2XLFk6fPk2fPn3o1KkTLi4ubNmyBTs7O/z8/OjRoweHDh2iS5cu/Pbbb8ydO5dNmzbh7e1N0aJF0+XfWAjxoISkBBafXMyi44vIbZ2bzxt8zquVX8VKmfccJ1snKEvbtWsXv/32GwCtWrUiJCSE8HBjwuzUqRN58uQBoGnTpsyaNYty5crRoUMHtmzZQnR0NJcuXaJKlSokJCTw2Wef4ePjg5WVFdevX08+iylTpgwNGjQAjAmtS5cu2NvbJx8jJTVq1OCTTz5h+PDhdOzYkaZNmyY/1qNHj+TvQ4YMAYz3lnXv3p2bN28SHx//wP1A9z+Phg0bMmnSJAICAnjllVeoVKkS27Zt4/Dhw3h6egIQExODi4sLALly5eLFF19Mjil37tzY2tpSo0YNLl++DBhvvB44cCC+vr5YW1tz/vz55GPPnj0bNzc3GjRokBy3ECJ9Hbl9BO+93viH+dO2bFuGew6nsP0jhcfNIlsnqMed6Vha3rx5k3/29PTk0KFDlC9fnjZt2hAcHMyiRYuSz35WrlxJUFAQhw8fxtbWlrJlyybfl3P/flJz7do1XnrpJcA4BPnee+9x5MgRNm7cyOjRo/Hy8mLMmDHAg1Oq7/08aNAgPv74Yzp16sSOHTsYN25cis/jjTfeoH79+vz555+0b9+eBQsWoLWmT58+fPnll4/EZWtrm3wMKysrcufOnfxzYmIiAF9//TVFihTh2LFjGAwG7OzskrcPCAjAysqK27dvYzAYLHb9TYjsKCwujK8Pf81vfr9RPG9x5nrNpVnJZhkag/yPNqOmTZuycuVKAHbs2EGhQoXInz//I+vlypWLUqVKsXr1aho2bEjTpk2ZNm0azZoZ3wxhYWG4uLhga2vL9u3buXIlxcr0NGvWjLVr1xITE0NERAR//PEHAKVKlcLX1xdfX1/ee+89bty4gb29Pb169WLo0KEcOXIkeR/3rkf9/PPPNGzYMPn4JUqUAGD58uWpPl9/f3/Kly/Phx9+SOfOnTl+/DheXl78+uuvBAYGAnDnzp1U409JWFgYxYoVw8rKiu+//z75+lViYiL9+/fnp59+olq1asyYMSPN+xRCpE5rzV+X/qLz2s6svbCWPtX7sKbzmgxPTpDNz6Asbdy4cfTv3x93d3fs7e0f++HetGlTtm3bRp48eWjatCkBAQHJQ289e/bkpZdeokaNGtStW5eqVaumuI/atWvTvXt3atasiYuLS/Kw2sNOnDjB0KFDsbKywtbWlnnz5iU/dvfuXdzd3cmdOzc//fRT8vPo1q0bBQsWpFWrVly6dCnF/f7yyy98//332NraUrRoUT777DOcnJyYOHEiL7zwAgaDAVtbW+bOnUuZMmXS9Bq+//77dO3alRUrVvDiiy8mn7F98cUXNG3alCZNmlCzZk08PT3p0KED1apVS9N+hRCPCogIYOL+iey+vhtXZ1fmtZ5HNWfL/Z9SWmuLHfx51a1bVz/csPDMmTPyIfWM7jWALFSokKVDyXTkfSWyswRDAt+f/p55vvOwUlZ8WPtDXq/yOtZW1hlyfKXUYa113YeXyxmUEELkYCeCTjBu7zjO3z1Py1It+az+ZxTNmzlmxEqCEsnuzZwTQmR/kfGRzDo6i1VnV1E4T2G+afENXmW8LB3WAyRBCSFEDrPtyja+OPAFQdFBvF71dT70+BCHXA6WDusRkqCEECKHuBV1iy/2f8H2a9upXLAyX7f4GvfC7pYOK1WSoIQQIptLMiTx09mfmH10NgZtYEidIfSu3htbq8zdJVoSlBBCZGNnQs7gvdebUyGnaFyiMaPrj6ZkvicXss4M5EbdLKZ9+/aEhoY+dp2yZcsSHBwMQKNGz19leNmyZQwcOPC59yOEyDjRCdFMOziNHn/24GbUTaY0m8I8r3lZJjmBnEFlORs3bnyq9e9V/84qpG2HEM/PJ8CHSfsmcSPqBl0rdWVInSE45na0dFhPTc6gzCCldhaptbIICgqia9eueHp64unpmVzJPDIykn79+lGjRg3c3d2Ti87ef3b08ssvU6dOHVxdXVm4cGGKsTg4GGfmjBkzhlq1alGrVi1KlChBv379gNRbYSxdupTKlStTr1695JgelpSURN++fXFzc6NGjRp8/fXXALRo0YLBgwdTq1Yt3NzcOHDgAAAHDhygYcOGeHh40KhRo+R2IMuWLaNTp060atUKLy8vbt68SbNmzZK337lzJwCbN2+mYcOG1K5dm27duhEZGZn8mowcOZJatWpRt25djhw5Qtu2balQoQLz589Pfj1Tally8OBB3N3diY2NJSoqCldXV06ePPn0/+hCZAJB0UF8suMTPtj2AXY2dix/cTnjGo3LkskJsvsZ1F8j4NaJ9N1n0RrQbvJjV0mpncXw4cNTbGUxePBghgwZQpMmTbh69Spt27blzJkzTJgwIXl9MJYgetiSJUtwcnIiJiYGT09PunbtirOzc4oxjR8/nvHjxxMaGkrTpk0ZOHBgqq0w2rRpw9ixYzl8+DCOjo60bNkSDw+PR/bp6+vL9evXkz/Q7x96jI6OxtfXFx8fH/r378/JkyepWrUqO3fuxMbGhq1bt/LZZ58lJ94jR45w/PhxnJycmD59Om3btmXUqFEkJSURHR1NcHAwEydOZOvWreTNm5evvvqKGTNmJBe5LV26NL6+vgwZMoS+ffuye/duYmNjcXNz47333ku1ZYmnpyedOnVi9OjRxMTE0KtXL9zc3J7wJhAiczFoA7+e/5VvDn9DXFIcH9T6gP5u/cllncvSoT2X7J2gLCS1dhYptbLYunUrp0+fTt42PDycyMhItm7dyqpVq5KXFyxY8JHjzJo1izVr1gDGiuV+fn6pJigwFoHs1asXH3/8MXXq1GHOnDkptsLYv38/LVq0oHBhY0n97t27P9Dm4p7y5cvj7+/PoEGD6NChAy+88ELyY/eea7NmzQgPDyc0NJSIiAj69OmDn58fSikSEhKS12/Tpg1OTk6Asbp7//79SUhI4OWXX6ZWrVr8+++/nD59msaNGwMQHx+fXMwW/mstUqNGDSIjI8mXLx/58uUjd+7chIaGkjdv3hRblhQtWpQxY8bg6emJnZ0ds2bNSvX1EyIz8rvrx/i94/EN8qVe0Xp83uBzyjqWtXRY6SJ7J6gnnOmYS+XKlR9pZwEpt7IwGAzs27fvgTYSabFjxw62bt3K3r17sbe3p0WLFsktOFIzbtw4SpYsmTy8l1orjLVr16a4fVJSUnILkE6dOjF+/HiOHTvG33//zfz58/nll19YsmTJI8/13u+ff/45LVu2ZM2aNVy+fJkWLVokP35/245mzZrh4+PDn3/+Sd++ffn4448pWLAgbdq0SS5g+7D7W3Xc+/ne74mJiY9tWRISEkJkZCQJCQnExsamqYWJEJYWmxjLwuMLWXpyKQ65HJjYeCKdKnR65P9eVibXoMwgtXYWKbWyeOGFF5g9e3bytvc67rZp04a5c+cmL394iC8sLIyCBQtib2/P2bNn2bdv32Nj+uOPP9i6desDZwiptcKoX78+//77LyEhISQkJLB69WoArK2tk9t2jB8/nuDgYAwGA127dmXixIkptu3YtWsXjo6OODo6PtC2Y9myZanGeuXKFYoUKcI777zD22+/zZEjR2jQoAG7d+9OvnYXFRWV4lldah7XsmTAgAFMmDCBnj17Mnz48DTvUwhL2XtjL13Xd2XRiUW0L9+e9S+vp3PFztkqOUF2P4OykJTaWbz66qsptrKYNWsWH3zwAe7u7iQmJtKsWTPmz5/P6NGj+eCDD3Bzc8Pa2pqxY8fyyiuvJB/jxRdfZP78+VSrVo0qVaokd9VNzYwZM7h+/Tr16tUD/jsDSqkVRoMGDRg3bhwNGzakQIEC1KpVK8V9Xr9+nX79+mEwGAAeOBOzs7PDw8ODhISE5LOqYcOG0adPHyZOnEiHDh1SjXXHjh1MnToVW1tbHBwcWLFiBYULF2bZsmX06NGDuLg4ACZOnEjlypWf8K9hlFrLkhUrVmBra8sbb7xBUlISjRo14p9//qFVq1Zp2q8QGelO7B2mHpzKBv8NlM5XmkUvLKJBscf/38/KpN1GBslJrSxatGjBtGnTqFv3ker5WVZmfV+JnEFrzdoLa5l+eDpRCVH0d+vPu+7vkts695M3Nqeg82DvDHlTv/adFqm12zDbEJ9SaolSKlApdfK+ZU5KqS1KKT/T94Km5UopNUspdUEpdVwpVdtccQkhRFZyKewSb21+izF7xlDesTyrO65mkMcgyyaniNuwYQj62wbondPMdhhzDvEtA+YAK+5bNgLYprWerJQaYfp9ONAOqGT6qg/MM33PNnJSK4sdO3ZYOgQhsrz4pHgWn1zMouOLsLO2Y0zDMXSt1BUrZcGpA/FRsGcO7J6JTozj7zztMRToQXszHc5sCUpr7aOUKvvQ4s5AC9PPy4EdGBNUZ2CFNo437lNKFVBKFdNa3zRXfEIIkVkdvn0Y773eXAq7xItlX2R4veEUymPBywNJieD7A2z/AiJvc9qxOYOCOnHXqgzeZowroydJFLkv6dwCiph+LgFcu2+9ANOyRxKUUupd4F0w3pwphBDZRVhcGF8f/prf/H6jeN7ifOv1LU1LNrVcQFqD32bYMhaCzhBcoCbDrAaxI7A8vRqU4eM2lSlgb76bgS02i09rrZVSTz1DQ2u9EFgIxkkS6R6YEEJkMK01Gy9tZMrBKYTFhdHPtR/v1XwPe1t7ywV14yhs/hwu7yQuf1m+yf8Z8265UqeME+s7ueJWwvzlkzI6Qd2+N3SnlCoGBJqWXwdK3bdeSdMyIYTI1q5FXGPSvknsvrEbN2c3FrRZQFWnqpYL6O4V+GcCnFiNIY8zf5YYwsf+Hjjmzcv0blV5pXaJDLvfKqMT1HqgDzDZ9H3dfcsHKqVWYZwcESbXn4QQ2VmCIYEVp1Yw/9h8rJQVI+qN4PUqr2NtZW2ZgGLugs80OLAQraw4Xf5tBlxqws1LuenTqCwftalEfruMbXBotgSllPoJ44SIQkqpAGAsxsT0i1LqLeAK8Jpp9Y1Ae+ACEA30M1dcwkjaWghhOceDjuO915vzd8/TqlQrRtYfSdG8RS0TTGIcHFgEPlMhNoyQSl35NPgltp+2pV45J77r7ErVovktEprZ5itqrXtorYtprW211iW11ou11iFaay+tdSWtdWut9R3Tulpr/YHWuoLWuobW+tCT9p/ZrVixAnd3d2rWrEmXLl0oU6ZMcsWFqKgoSpUqRUJCAp6ensnTskeOHMmoUaMe2Vdq7SccHBwYMmQIrq6ueHl5ERQUBMCiRYvw9PSkZs2adO3alejoaAD69u3Le++9R/369Rk2bBj//vtvcgsODw8PIiIiAJg6dSqenp64u7szduxYwDhNvmrVqvTt25fKlSvTs2dPtm7dSuPGjalUqdITW2p8/fXX9O/fHzBW2nBzc0uOS4icIiI+gkn7JtFrYy9C40L5puU3zGw10zLJyWCAE7/CnLqweRTxRT34usJi6px4hdNRDsx8vRY/v9vAYskJsnmpo68OfMXZO2fTdZ9VnaoyvN7j67WdOnWKiRMnsmfPHgoVKsSdO3fo168f//77Ly1btmTDhg20bdsWW1tbli1bxquvvsrs2bPZtGkT+/fvf2R/P/744yPtJ8CY6OrWrcvXX3/N+PHj8fb2Zs6cObzyyiu88847AIwePZrFixczaNAgAAICAtizZw/W1ta89NJLzJ07l8aNGxMZGYmdnR2bN2/Gz8+PAwcOoLWmU6dO+Pj4ULp0aS5cuMDq1atZsmQJnp6e/Pjjj+zatYv169fzxRdfsHbt2lRbagwePJgWLVqwZs0aJk2axIIFC7C3t+AFYCEykNaarVe3Mnn/ZIJignij2hsMrDUQh1wOlgno8i7YPBpuHEUXcWNrnfl8ctiJ6PgkBjQrxyCvSjjktnx6sHwE2dA///xDt27dkssaOTk50b17d37++WdatmzJqlWreP/99wFwdXWld+/edOzYkb1795Ir16NTNlNqPwHGSt3du3cHoFevXsm1+k6ePMno0aMJDQ0lMjKStm3bJu+rW7duWFsbx7gbN27Mxx9/TM+ePXnllVcoWbIkmzdvZvPmzcn9nyIjI/Hz86N06dKUK1eOGjVqJMft5eWFUooaNWok34gcFhaWYksNKysrli1bhru7OwMGDEhumyFEdncr6haT9k1iR8AOqhSswsxWM3ErZKGeY4FnYetYOL8J8pfgUpNpDDxZiVO7o2hc0RHvTq5UdMlnmdhSkK0T1JPOdDJSp06d+Oyzz7hz5w6HDx9+oBjpiRMnKFCgQHJV8f379zNgwADA2Gjw3lnM/e0n3nzzzUeOcW9mTd++fVm7di01a9Zk2bJlD1R2uL+VxIgRI+jQoQMbN26kcePG/P3332itGTlyZPLx77l8+fIjbSzub3GRmJgI8NiWGn5+fjg4OHDjxo1neQmFyFKSDEn8ePZHZh81div4pM4n9KreCxsrC3zsRtyGHV/AkRWQy4HIJqOYENycn7cGU9wxiW971qadW9FMVw1d2m2YQatWrVi9ejUhISGAsY2Fg4MDnp6eDB48mI4dOyafxfz+++/cuXMHHx8fBg0aRGhoKPXr109ua9GpU6cU20+AsZfUr7/+ChiHAZs0aQJAREQExYoVIyEhgZUrV6Ya58WLF6lRowbDhw/H09OTs2fP0rZtW5YsWZLcTv369evJiTMtUmupERYWxocffoiPjw8hISHJcQuRHZ0OOc0bG99gysEp1ClShzWd19DXrW/GJ6e4SNj+JczygKM/kOT5Divrr6Xhzpr8fiKE91tUYOsnzWlfo1imS06Qzc+gLMXV1ZVRo0bRvHlzrK2t8fDwYNmyZXTv3p1u3boln9EEBwczYsQItm3bRqlSpRg4cCCDBw9m+fLlD+wvpfYTYDwbOnDgABMnTsTFxSW5B9OECROoX78+hQsXpn79+smTHx72zTffsH37dqysrHB1daVdu3bkzp2bM2fOJPercnBw4IcffkhOqE+SWkuNIUOG8MEHH1C5cmUWL15My5YtadasGS4uLk/12gqRmUUnRDPXdy4/nPmBgrkLMrXZVNqWbZvxH/5JiXD0e9jxJUTehuqdOVp5MCO2R3Hu9i2aVy7M2JeqU76wha6BpZG028jCHBwcks90hHnlpPeVeDY+AT5M3DeRm1E36Va5G4NrD8Yxt/mrLTxAa+P1pS1jIfgclKpPSKPP8fZ1YP2xG5QsmIcxHavTpnqRTHXGlFq7DTmDEkKI5xAUHcSXB75ky5UtVHCswIp2K/Bw8cj4QK4fMZYmurILnCqQ8Or3LAmuzqyfLpBgiGSwVyX+16ICdrYWuhH4GUiCysLk7EkIyzFoA6vPreabI98QnxTPII9B9HPth611xlZb4O5l2DYeTv4G9oWg/TR2O3ZkzIZzXAw6R+tqLozp6Epp56x3W0e2TFBa60x1+iqytqw8DC7Mw++uH957vTkWdIz6RevzecPPKZO/TMYGEX0Hdk6HAwtBWUPTT7nhNoAJW67x18kjlHG2Z0nfurSqWuTJ+8qksl2CsrOzIyQkBGdnZ0lS4rlprQkJCcHOzs7SoYhMIDYxlgXHF7Ds5DIccjkwqckkXir/UsZ+1iTEGpPSzmkQGw4ePYlrOoLvjsUxZ84RNJpPX6jM203LZ6nhvJRkuwRVsmRJAgICksv+CPG87OzsKFmypKXDEBa258YeJuydQEBkAJ0qdOLTup9S0K5gxgVgMBiH8baNh7CrULE1tBnP9tDCeC8+xeWQaF50LcrojtUoWTDrDeelJNslKFtbW8qVK2fpMIQQ2URITAhTD03lT/8/KZO/DItfWEy9YvUyNohLPsYJEDd9oWgN6LSWawXrM37DabacPkj5wnlZ0b8ezSoXzti4zCzbJSghhEgPWmvWXljL9MPTiUqIYoD7AN5xf4fc1rmfvHF6CTxjnDLu9zfkLwldFhBbrSvzfS4xb+m/WFsphr9YlbealCOXTfaruyAJSgghHnIp7BLj947n0O1D1HapzZiGY6hQoELGBRBxC7ZPgqM/QK580NobXX8AW/3CGf/NTq7diaGjezFGdahGMcc8GRdXBpMEJYQQJvFJ8Sw+sZhFJxZhZ2PH2IZjeaXSK1ipDDo7iYuAPbONX0kJUG8ANBvK5Rg7vH84wfZzQVRyceDHd+rTqEKhjInJgiRBCSEEcOjWIcbvG8+lsEu0K9uOYfWGUShPBiWBpEQ4shx2TIaoQHDtAl5jiHEow9ztF1jo408uGytGd6hGn0ZlsbXOfsN5KZEEJYTI0cLiwphxeAa/+/1OCYcSzGs9jyYlmmTMwbWGcxuN15lC/KB0Q+jxE7pEHTadvMXEP//lemgMXTxKMLJdVVzy56zbHSRBCSFyJK01f176k6kHpxIWF0Y/t378r+b/yGOTQdd0Ag7Dls/hym5wrgSv/whV2nMhKArvJQfY6RdM1aL5+GVAQ+qVc8qYmDIZSVBCiBznWvg1Ju6fyJ4be6hRqAYL2yykilOVjDn4nUvGe5lO/Q55C0OH6VC7D5GJitmbzrJk1yXsbK3x7uRKz/qlsckhw3kpkQQlhMgxEgwJLD+1nPnH5mNjZcPIeiPpXqU71lYZUHEh+g74TIUDi8DaFpoNg8YfonM58Mfxm0z68zS3w+PoVqckw9tVpZBDBk5nz6QkQQkhcoRjQcfw3uuN310/vEp7MbLeSIrkzYA6dQmxsH8+7JwB8RHg0QtafAb5i3HuVgRj1+9jn/8d3ErkZ16vOtQunYHVKTI5SVBCiGwtIj6CmUdm8su5X3Cxd2Fmy5m0Kt3K/Ac2GODEavhnAoRdg0ovQGtvKFKd8NgEZm44zbI9l3HIbcPEl93oUa801lZSP/R+kqCEENmS1potV7Yw+cBkQmJD6FmtJwM9BpLXNq/5D+6/w1ia6NZxKFYTOs+F8s3RWrPmSABfbDxLSFQcr3uWZmjbKjjlzWX+mLIgSVBCiGznZuRNJu2fxL8B/1LVqSqzW83GtZCr+Q98+zRsGQMXtoBjKXhlEbi9ClZWnL4Rztj1Jzl4+S41SxVgSd+6uJcsYP6YsjBJUEKIbCPRkMiPZ35kju8cAD6t+yk9q/XExsrMH3XhN4yliXx/hNz5oM0EqPcu2NoRFpPAjM2n+X7fFQrY5+KrrjXoVqcUVjKc90SSoIQQ2cKpkFN47/HmzJ0zNC3RlFENRlHCoYR5DxoXAbtnwp45YEiE+v+DZp+CvRMGg+bXg9f4atNZ7kbH06tBGT5pUwVH+wzuuJuFSYISQmRp0QnRzD46mx/P/oiTnRNTm0+lbZm25m0imJQAh5cZSxNFB4NbV2j1OTgZW/2cCAjj83Un8b0WSt0yBVnRuR6uxR3NF082JQlKCJFl7bi2g0n7J3Er6havVX6NwXUGkz9XfvMdUGs4+ydsHQshF6BMY2jzC5SsA8DdqHimbj7HTweu4pw3N9O71eSV2iWku/czkgQlhMhyAqMDmXxgMluubKFigYp83+57arnUMu9Brx00lia6uhcKVYYeq6Dyi6AUSQbNqoNXmfr3OSJiE+nXqBwftalEfjsZznseFklQSqkhwNuABk4A/YBiwCrAGTgM9NZax1siPiFE5pRkSGL1+dXMPDKT+KR4PvT4kL6ufbG1NmMiuOMPW73h9FrI6wIdvwaPN8Ha+PF59Opdxqw7xYnrYdQv54R3Z1eqFjXjWVwOkuEJSilVAvgQqK61jlFK/QK8DrQHvtZar1JKzQfeAuZldHxCiMzp3J1zjN87nuPBx6lfrD5jGoyhdP7S5jtgVAj4TIGDi42liZqPgEYDjbP0gJDIOL7adJZfDgVQJH9uZr5ei041i8twXjqy1BCfDZBHKZUA2AM3gVbAG6bHlwPjkAQlRI4XkxjD/GPzWXFqBfly5eOLJl/QsXxH8yWChJj7ShNFgkdvaPkZ5CsKQGKSgZX7rzJ98zmi45MY0Kw8g7wq4ZBbrpiktwx/RbXW15VS04CrQAywGeOQXqjWOtG0WgCQ4vxQpdS7wLsApUub8a8nIYTF7bm+hwn7JhAQGcDLFV/mkzqfUMCugHkOZjDA8Z/hn4kQHmC8vtTaG1yqJq9y6PIdPl93ijM3w2lSsRDjOrlS0cXBPPEIiwzxFQQ6A+WAUGA18GJat9daLwQWAtStW1ebIUQhhIWFxIQw5eAUNl7aSNn8ZVnSdgmeRT3Nd8CL240TIG6dgGK1oMt8KNc0+eHAiFgmbzzL70evU9zRjm971qadW1EZzjMzS5yTtgYuaa2DAJRSvwONgQJKKRvTWVRJ4LoFYhNCWJDWmjUX1jD90HSiE6N5r+Z7vF3jbXJbm6n1xK2TxtJEF7dBgdLQdTG4vgJWxh5MCUkGlu+5zDdb/YhPNPBBywp80LIi9rlkOC8jWOJVvgo0UErZYxzi8wIOAduBVzHO5OsDrLNAbEIIC/EP82f83vEcvn2Y2i61GdtwLOULlDfPwcKuw/YvwHcl2OWHFyYaSxPZ/JcI914MYez6k5y/HUmLKoUZ+5Ir5QplQKFZkcwS16D2K6V+BY4AicBRjEN2fwKrlFITTcsWZ3RsQoiMF5cUx3cnvuO7E99hb2OPdyNvXq74MlbKDJ1kY8Nh9zew91vQSdDwA2j6Cdj/11L9Vlgskzae4Y9jNyhZMA8Le9ehTfUiMpxnARY5T9VajwXGPrTYH6hngXCEEBZy8NZBxu8dz+Xwy7Qv156hnkMplKdQ+h/okdJEr4LX51CwbPIq8YkGluy+xKxtfiQaNIO9KvG/FhWws82AbrsiRTKQKoTIcKGxoUw/PJ21F9ZSwqEE81vPp3GJxul/IK3hzB+wdRzcuQhlm0Kb8VCi9gOr7fILZuz6k1wMiqJ1tSKM6Vid0s726R+PeCqSoIQQGUZrzQb/DUw9OJXw+HD6u/XnvZrvkccmT/of7Op+48y8a/uhUBXo8TNUbgv3DdVdD41h4obT/HXyFmWc7Vna15OWVV3SPxbxTCRBCSEyxNXwq0zYN4F9N/fhXsidMQ3HUMWpSvofKOSi8YzpzHpwKAIvzYRavZJLEwHEJSaxyMefOdsvAPDpC5V5u2l5Gc7LZCRBCSHMKiEpgWWnlrHg+AJsrWwZVX8U3Sp3w9oqnZNBVDD8OwUOLQbr3NBiJDQcCLkfvJF2+7lAvNef4nJINO3cijKqQzVKFpThvMxIEpQQwmx8A33x3uvNhdALtCnThhH1RuBin85DaAkxsO9b2PUNxEdB7TeNySlfkQdWu3YnGu8/TrP1zG3KF87Liv71aFa5cPrGItKVJCghRLoLjw9n5uGZrD6/miJ5izC71WxalGqRvgcxJMGxVcZW6+HXoUp7aD0OCj84bBibkMS8HReZ/+9FrK0UI9pVpX/jcuSyMcM0dpGuJEEJIdKN1prNVzYz+cBk7sTeoWe1ngzyGIS9bToPoV3YZqwAcfskFK8NryyEsk0eiWXrmUDGbzjFtTsxdHQvxqgO1SjmaIYJGcIsJEEJIdLFjcgbTNo/CZ8AH6o5VWOO1xxcnV3T9yC3TphKE/0DBcrAq0ugepfk0kT3XAqOwvuPU+w4F0QlFwd+fKc+jSqY4f4qYVaSoIQQzyXRkMjKMyuZ6zsXgKF1h/JGtTewsUrHj5ewAPhnEhz7Cewcoe0X4Pn2A6WJAKLjE5m7/QKLfC6Ry8aK0R2q0adRWWytZTgvK5IEJYR4ZqeCT+G915szd87QvGRzPqv/GcUdiqffAWLDYNfXsG+e8abbRoOg6ceQp+ADq2mt2XTyFhM2nOZGWCyveJRgRLuquOS3S79YRIaTBCWEeGpRCVHMOTqHH8/+iLOdM9ObT6dNmTbpV68uMR4OL4V/v4LoEKjxmrE0UYFHe8BdCIzE+49T7PQLpmrRfMzs4YFnWacUdiqyGklQQoinsv3qdibtn0RgdCCvVXmNwbUHky9XvvTZudZweh1s84Y7/lCuGbSZAMVrPbJqZFwis7f5sXjXJfLkssa7kys965fGRobzsg1JUEKINLkddZvJByaz9epWKhaoyLTm06jlUiv9DnB1H2z+HAIOQOFq8MZqqNTmgdJEYBzO++P4TSb9eZrb4XG8Vrckw16sSiEHM/WMEhYjCUoI8VhJhiR+Of8LM4/MJNGQyODag+nj2gdbK9v0OUDwBdg6Fs5uAIei0Gk21HzjgdJE95y7FcHY9SfZ538HtxL5mderDrVLF0xhpyI7kAQlhEjVuTvnGL93PMeDj9OwWEM+b/A5pfKXSp+dRwYZrzEdXgo2dtBylLE/U65HmwKGxyYwc6sfy/ZcJp+dDZO6uPG6Z2msraRHU3aWpgSllHLB2Ja9OMYuuCeBQ1prgxljE0JYSExiDPOOzWPFqRU45nbky6Zf0qFch/SZBBEfDfvmwq6ZkBANdfpCixHg8GgJJK01a45e54uNZwmJiuN1z9IMa1uFgnlzPX8cItN7bIJSSrUERgBOGLvcBgJ2wMtABVNn3Ola63AzxymEyCC7r+9mwr4JXI+8TpeKXfi4zscUsCvw/Ds2JIHvj8bSRBE3oUoHU2miyimufupGGGPXneLQlbvUKlWAJX3r4l4yHeIQWcaTzqDaA+9ora8+/IBSygboCLQBfjNDbEKIDBQcE8yUg1P469JflM1fliVtl+BZ1PP5d6z1f6WJAk9BibrGChBlGqW4elh0AtO3nOOHfVcoYJ+LKV3debVOSaxkOC/HeWyC0loPfcxjicDa9A5ICJGxDNrAGr81TD88ndjEWP5X83+8XeNtclmnwzDazePGpoH+O4zt1V9dCq5dHpmZB2AwaH49HMBXm85yNzqe3g3K8HGbKjjap9NkDJHlpPUa1GBgKRABfAd4ACO01pvNGJsQwsz8Q/3x3uvNkcAj1C1Sl88bfk55x/LPv+PQa/DPRDj+M+QpAC9OhrpvgU3KSe94QChj1p3C91oodcsUZEXnergWd3z+OESWltZZfP211jOVUm2BgkBv4HtAEpQQWVBcUhyLji9i8cnF2NvYM77ReF6u+PLzT4KICYVdM2DffOPvjT+EJh8bk1QK7kbFM3XzOX46cBXnvLmZ8VpNuniUSL+KFCJLS2uCuvduaQ98r7U+peQdJESWdODmASbsm8Dl8Mt0KN+BoXWH4pzH+fl2mhhv7GT77xSIuQvu3aHVaCiQ8pT0JINm1cGrTP37HBGxifRrVI6P2lQiv50M54n/pDVBHVZKbQbKASOVUvkAmWIuRBYSGhvKtEPTWHdxHSUdSrKgzQIaFU95okKaaQ2n18JWb7h7Cco1hxcmQLGaqW5y5Opdxq47xYnrYdQv58T4zm5UKZpOpZJEtpLWBPUWUAvw11pHK6WcgX5mi0oIkW601mzw38DUg1OJiI/gLbe3GFBzAHlsnrNx35W9sHk0XD8ELq7Q8zeo6JXiBAiA4Mg4pmw6yy+HAiiSPzezenjwknsxGc4TqUpTgtJaG5RSiUAz0/Tye46bJywhRHq4En6FCfsmsP/mfmoWrsmYhmOoXDDl+47SLNgPtoyFc39CvmLQeS7U7AFW1imunphkYOX+q0zffI7o+CQGNCvPIK9KOOSWQjbi8dI6i28J4A6c4r+hPQ38bqa4hBDPISEpgaWnlrLg2AJyWedidP3RdKvSDSv1HJW+IwNhx2Q4vAxs7Y3XmBp8ALlSb+d+8PIdxqw7xZmb4TSpWIhxnVyp6OLw7DGIHCWtf8I00FpXN2skQoh0cTTwKOP3judC6AXalGnDiHojcLF/tIxQmsVHwd5vYfc3kBgLdftD8+HgUDjVTQLDY/nyr7OsOXqd4o52zOtZmxfdispwnngqaU1Qe5VS1bXWp80ajRDimYXHh/PN4W9YfX41xfIWY06rOTQv1fzZd2hIAt+VsP0LY2miai+B1zgoVDHVTRKSDCzfc5lvtvoRn2hgYMuKvN+yAva5ZDhPPL20vmtWYExSt4A4jNPOtdba3WyRCSHSRGvN35f/ZvKBydyNu0vv6r0ZWGsg9rapD709YYfgt8VYmijoDJT0hG7LoHSDx26292IIY9ef5PztSFpUKczYl1wpV+jRyuRCpFVaE9RijDfnniAdppcrpQpgrEjhhvFaVn/gHPAzUBa4DLymtb77vMcSIju7HnmdSfsmsfP6Tqo5VWNu67m4Ors++w5v+BpLE13ygYLloNtyqN451Zl5ALfCYpm08Qx/HLtByYJ5WPRmXVpXc5HhPPHc0pqggrTW69PxuDOBTVrrV5VSuQB74DNgm9Z6slJqBMYq6sPT8ZhCZBuJhkR+OP0D3x77FoBhnsPoUbUHNlbPOJQWevW+0kRO0G4K1OmXamkigPhEA0t2X2LWNj8SDZrBXpX4X4sK2NmmPJtPiKeV1nfzUaXUj8AfGIf4ANBaP/UsPqWUI9AM6GvaRzwQr5TqDLQwrbYc2IEkKCEecTL4JN57vTl75ywtSrbgs/qfUcyh2LPtLOYu7JwB+xcYz5KafAxNPgK7x9fB2+kXxNj1p/APiqJ1tSKM6Vid0s7POKQoRCrSmqDyYExML9y37FmnmZcDgoClSqmawGFgMFBEa33TtM4toEhKGyul3gXeBShduvQzHF6IrCkqIYrZR2fz09mfcLZzZkaLGbQu3frZhtIS4+Dgd+Az1Vg/r2YPaDUKHEs+drProTFM3HCav07eooyzPUv7etKy6nPMEBTiMdJ6o256Vo2wAWoDg7TW+5VSMzEO591/PK2U0qnEshBYCFC3bt0U1xEiu9l2dRtf7P+CoOggulfpzoe1PyRfrmcoD6Q1nPrdWJoo9AqUbwltxkOxx893iktMYpGPP3O2XwDg0xcq83bT8jKcJ8zqSR11RwPfaq3vpPJ4K8Bea73hKY4ZAARorfebfv8VY4K6rZQqprW+qZQqhrF7rxA52q2oW3y5/0v+ufYPlQpWYkaLGdQsnHqdu8e6vNtYmujGESjiBr1+N5YmeoLtZwPx/uMUl0OiaedWlNEdq1OiwHOWSRIiDZ50BnUC+EMpFQscwTg0ZwdUwlibbyvwxdMcUGt9Syl1TSlVRWt9DvACTpu++gCTTd/XPc1+hchODNrAqrOrmHV0FkmGJD6q/RFvur6JrdUzVPsOOgdbx8G5jZC/BLw8z1htPJXSRPdcDYlm/IbTbD1zm/KF8/L9W/VoWin1m3OFSG9P6qi7DlinlKoENAaKAeHAD8C7WuuYZzzuIGClaQafP8bCs1bAL0qpt4ArwGvPuG8hsrSQmBBG7x7Nruu7aFS8EaMbjKZUvpTbVjxWxG3Y8SUcWWEsTeQ1Bhq8D7aPP/uJTUhi3o6LzPv3IjZWihHtqtK/cTly2TxHmSQhnkFar0H5AX7pdVCttS9QN4WHnjzeIEQ2tu/mPkbuHEl4XDij64/mtSqvPf0kiPgo2DMHds+EpDjwfBuaD4O8hR67mdaaLadvM37DaQLuxvBSzeKMal+Noo52z/GMhHh2Un9EiEwg0ZDIt77f8t2J7yjrWJb5redTxanK0+0kKRF8fzCWJoq8DdU6Qetx4FzhiZteCo7C+49T7DgXROUiDvz0TgMaVnjOJoZCPCdJUEJY2I3IGwz3GY5vkC9dKnZhRL0RT1emSGs4/zdsHQtBZ6FUfej+A5Sq98RNo+MTmbv9Aot8LpHLxorRHarRp1FZbK1lOE9YniQoISxo65WtjNkzBoM28FXTr2hfvv3T7eD6EWPNvMs7wakCvPa9sajrE4YFtdb8dfIWEzec5kZYLK94lGBE+6q45JPhPJF5pLUfVGVgHsabad2UUu5AJ631RLNGJ0Q2FZsYy7RD0/j53M+4ObsxpdkUSuV/iokQd6/AtvFw8lewd4b206BOX7B+8iy/C4ERjFt/ml0XgqlaNB8ze3jgWdbp2Z+MEGaS1jOoRcBQYAGA1vq4qfSRJCghnpJ/qD+f+nyK310/+rr25UOPD7FNQ2IBjKWJfKbBgYWgrKDpJ9D4I7DL/8RNI+MSmb3Nj8W7LpEnlzXenVzpWb80NjKcJzKptCYoe631gYdmEyWaIR4hsi2tNWsurOHL/V9ib2vPt17f0rRk07RtnBhnTEo+0yA2DGr1hJafgWOJNB13/bEbfLHxDLfD43itbkmGvViVQg65n/MZCWFeaU1QwUqpChjr76GUehW4+fhNhBD3RMRHMGHvBP66/Bf1i9bny6ZfUtg+DTe9GgzG0kTbvI0Vxyt4GUsTFXVL03HP3Ypg7PqT7PO/g1uJ/MzrVYfapQs+57MRImOkNUF9gLH+XVWl1HXgEtDLbFEJkY2cDD7J0H+HcjPqJh96fEh/t/5YP6GKA1obJz5sGQM3jkLRGtB7DVRolaZjhscm8M0WP5bvvUw+OxsmdXHjdc/SWFtJjyaRdaT1Rl1/oLVSKi9gpbWOMG9YQmR9Bm1gxakVzDwyk8L2hVn24jJqudR6wkZJcPZP2DMLAg5C/pLw8nxTaaInXyvSWvP7ket8+ddZQqLi6FGvNENfqELBvKn3dRIis0rrLL4CwJsYu93a3LsWpbX+0FyBCZGVhcSEMGrXKHbf2E3r0q0Z12gcjrkf02MpIQZ8f4S9c+COPxQsa5yZ59HriaWJ7jl1I4yx605x6MpdapUqwJK+dXEvWSBdno8QlpDWIb6NwD7SqeW7ENnZ3ht7+WzXZ2krVxQVYuzLdGAhRAdD8drQbZmxCsSThgFNwqITmL7lHD/su0IB+1xM6erOq3VKYiXDeSKLS2uCstNaf2zWSITI4hIMCczzncd3J76jnGO5x5cruuMPe+fC0ZWQGAOV2kLjD6FM4yfeZHuPwaBZffgaX206R2h0PL0blOHjNlVwtH+GiudCZEJpTVDfK6XeATbwYMv3FPtECZHT3Ii8wTCfYRwLOkbXSl0Z5jks5XJFAYdhz0w48wcoa+O1pUaDwKXqUx3veEAon687xbFrodQtUxDvzvVwLf74Nu1CZDVpTVDxwFRgFKap5qbv5c0RlBBZyZYrWxi7ZywGbWBKsym0K9fuwRUMBvDbbJz4cGU35HaExoOh3gDIX+ypjnU3Kp4pf59j1cGrOOfNzYzXatLFo8SztX0XIpNLa4L6BKiotQ42ZzBCZCWxibFMPTiVX87/YixX1HzKg32bEuPg+C+wZzYEnzPOyGv7BdR+E3I/Xbv2JIPmpwNXmbb5HBGxifRvXI7BrSuR306G80T2ldYEdQGINmcgQmQlF0Mv8um/n3Ih9AL9XPsxyGPQf+WKYkLh0BLYvwAib0GRGvDKInDtkqZaeQ87cvUuY9ed4sT1MOqXc2J8ZzeqFH26BCdEVpTWBBUF+CqltvPgNSiZZi5yFK01v/v9zuQDk7G3tWd+6/k0LtHY+GDoNdg3D44sh/hIKN8Suswzfn+GIbjgyDi++ussqw8HUCR/bmb18OAl92IynCdyjLQmqLWmLyFyrIj4CMbvHc+my5uoX6w+XzYxlSu6edx4fenk78YV3boaJz4Uc3/qYwRGxLL9bCDbzgSy0y+YhCQDA5qX58NWlcibW7rjiJwlrZUklps7ECEysxNBJxjqM5RbUbcYXHsw/V37YeW/w5iY/HdALgeo/x40+B8USHvbDK01p26Es+1MIP+cvc2xgDAAijva0bVOCfo2KkdFFwfzPCkhMrnHJiil1C9a69eUUif4b/ZeMq310/+JKEQWYtAGlp9azqwjs3Cxd2HZC99R6/ZFWNAcbp8Ah6LGtup1+kGeAmnaZ0x8ErsvBLPtrDEp3Q6PQynwKFWAoW2r0KqqC1WL5pOhPJHjPekMarDpe0dzByJEZhMcE8zoXaPZfWM3bUq2YGyusjj+2AfCA6BwVeg8F2p0A5snt624GRZjOksKZPeFYOISDeTNZU2zyoXxqlaEFlUKS/sLIR7y2ASltb7XUuN9rfXw+x9TSn0FDH90KyGyvr039jJy50gi4yP43LEW3Q6sQ8WFQZkm0HEGVGzz2OKtBoPmWEAo/5iuJ52+GQ5AaSd73qhfGq+qRahXzolcNtIsUIjUpPWqaxseTUbtUlgmRJaWYEhg7tG5LDm5hHJWeVgYcJ3K8f7G2niNP4QSdVLdNjIukV1+QWw7E8j2c4EER8ZjpaBuGSdGtquKVzUXKhR2kKE7IdLoSdeg/ge8D5RXSh2/76F8wG5zBiZERrseEcCwLe9zPOISXcMjGR4eSJ5avaDh++CUctGUa3ei2XbmNtvOBrLf/w7xSQby29nQvIoLrau50LxyYQrYS6sLIZ7Fk86gfgT+Ar4ERty3PELq8IlsIymRzXu+ZNzF1WidxNTwBF6s+R54vg15nR9c1aA5evUuW02z7s7fjgSgfOG89G1cllZVXahTpiC21jJ0J8TzetI1qDAgDOiRMeEIkYHio4g9vJwpJ+axOjfUSIIpVd+iZL3/PdCDKTw2AZ/zxqG7HecCuRudgI2Vol45J7p7lqZVVRfKFcprwSciRPYkd/6JnCcyCA4s5MLRxQzNb8uF3LnoV7Qpg7xmYGtjB8Cl4Cjj0N2ZQA5evkOiQVPQ3paWVVzwqlaEppULSR08IcxMEpTIOUIuwp7Z6GM/8Vsea74qVAh7WwfmN59KvaINOXT5LtvO+PPP2UD8g6MAqFIkH+80K0/rai7UKlUQa2kCKESGkQQlsr9rB2D3TDj7JxE2ufEu78bfCYHUdalHS+cP+enfRN47v4WI2ERyWVvRoIIzfRoZryeVckqhp5MQIkNYLEEppayBQ8B1rXVHpVQ5YBXgDBwGemut4y0Vn8jiDAY4/xfsngXX9oFdAY7V68vH4ScIigumcEIX/vXxZLu+RiGH3LRzK4pXtSI0qVhIat4JkUlY8n/iYOAMkN/0+1fA11rrVUqp+cBbwDxLBSeyqIRYOPYT7J0DIRfQjqW5UHs03tExHAv8DUNCfmJuDKBUwRoMbGm8nlSjhCNWMnQnRKZjkQSllCoJdAAmAR8r452LrYA3TKssB8YhCUqkVfQdOLgYDiyAqCDuOFbnd5fRzAwqReK1X7Bx8KMgdenj+intXytPMcc8T96nEMKiLHUG9Q0wDOMNv2Ac1gvVWieafg8ASqS0oVLqXeBdgNKlS5s3SpH53b2M3jsXfeR7rBJjOJyrLtPj32XP7eoULnyV3OXmYEsMn9YdTY9qr0kVByGykAxPUEqpjkCg1vqwUqrF026vtV4ILASoW7fuIxXWRc4Qd/UwoVunU/jqXyRhxbqkRixM7ECewjVoWc+JcjbrWH9lJRXyV2Bq86lUKljJ0iELIZ6SJc6gGgOdlFLtATuM16BmAgWUUjams6iSwHULxCYysdthMZzZ+TtFTi6kWqwveXQeltKB82V7UsfNjR+qFiaeYIbvHM7x68d5tfKrDPMcRh4bGc4TIivK8ASltR4JjAQwnUF9qrXuqZRaDbyKcSZfH2BdRscmMheDQXPyRhjbT10n6fhq2kf8SgurawTizN/FPyBvo7fpVbUMuW2sAfj78t947/FGo5nWfBpty7a18DMQQjyPzDSfdjiwSik1ETgKLLZwPMICouMT2eUXzLYzgew/e4m2MX/Rz2YTRdVdQvJV5Gb9byja6A3a3teDKTYxlikHp7D6/GrcC7nzVbOvKJmvpAWfhRAiPVg0QWmtdwA7TD/7A/UsGY+wjIC70Ww/G8jWM4Hs9Q/BKTGI93L/zTjrf8hjG01C6abQ9COcK3rBQ5McLty9wFCfoVwIvUB/t/4M9BiIrZWUIBIiO8hMZ1Aih0gyaHyvhbLtzG3+ORvI2VsRALQqGMivRTbhdmcrCo2q/jI0+hDb4rUe2YfWml/9fuWrA1+R1zYvC1ovoFGJRhn7RIQQZiUJSmSIiNgEdvoFs/XMbXacC+JOVDzWVgrPMgWY2yCclndWYX91ByTmhXpvQ4P3oWCZFPcVHh+O9x5vNl/ZTMNiDfmi6RcUylMoY5+QEMLsJEEJs7kSEpXcN+nApTskJGkc89jSskphvKo445W0B/tDX4LvccjrAq1GQ923wN4p1X0eCzrGcJ/h3I66zZA6Q+jr2hcrJb2XhMiOJEGJdJOYZODwlbtsOxvItjO3uRhkrAheycWB/k3K4VW1CLWL2mBzbCXs+BbCroJzJXhpFrh3B1u7VPdt0AaWnlzKnKNzKJK3CMvaLaNm4ZoZ9dSEEBYgCUo8N601C338+XbHRcJiErC1VjQo70yvBmVoVdWFMs55IeI27J8NPy+G2DAo3RDafQWVXwSrx58BBccE89nOz9h7cy8vlHmBsY3Gkj9X/sduI4TI+iRBieeitWbyX2dZ4ONPyyqFea1uKZpUKkS+e838gs7Dullw/GdISoBqHaHRYCjlmab977m+h5G7RhKVEMXYhmPpWqmrlCsSIoeQBCWemcGg+XzdSVbuv0qvBqUZ38nNWBVca7iyx9jq4vxfYGMHHr2g4UBwrpCmfScYEphzdA5LTi6hYoGKLH5hMRULVjTzMxJCZCaSoMQzSUwyMPTX46w5ep0Bzcsz4sWqKG2A0xuMien6IcjjBM2Hg+c74FA4zfsOiAhguM9wjgcfp1vlbgz1HCrlioTIgSRBiacWl5jEhz8d5e9Tt/n0hcp80LIi6txG2Dwa7vhDwbLQfhrU6gm5nq4j7abLm/De441CSbkiIXI4SVDiqcTEJ/Hu94fY6RfMmI7V6d+4LPhMg+0ToYgbdFsG1TqBlfXT7Tcxhq8OfMVvfr/hXtidKc2mUMIhxY4rQogcQhKUSLOI2ATeWnaIg1fuMKWrO6/VKgS/vQ0nfwX31+GlmY+dKp4av7t+DP13KP5h/rzl9hYfeHwg5YqEEJKgRNrcjYqnz9IDnL4RzqzXPXipvBUsbQ83joLXWGgy5JE6eU+itWb1+dVMOTgFB1sH5reZT6PiUq5ICGEkCUo8UWB4LL0W7+dySDQLetfBy/EmLOxhvJ/p9ZVQtcNT7zM8Ppxxe8ax5coWGhVvxKQmk6RckRDiAZKgxGMF3I2m13f7CYyIY1lfTxrF74YlAyBvIXjrbyha46n36Rvoy3Cf4QRGB0q5IiFEqiRBiVT5B0XS67v9RMYl8sNb9ah9ebFxMkTJesYzJweXp9qfQRtYcnIJc47OoWjeoixvtxz3wu5mil4IkdVJghIpOnMznN6LD6C1ZlX/WlQ/MPS5JkMExwQzcudI9t3cR9uybRnbcCz5cuUzU/RCiOxAEpR4hO+1UPosOUAeW2t+6lGOcptef67JELuv7+azXZ8RnRDNuIbjeKXSK1KuSAjxRJKgxAP2+Yfw1rKDODnkYnUne4r+3vGZJ0MkGBKYfXQ2S08upWKBiixpu4QKBdJW6kgIISRBiWTbzwXy3veHKeVkz+pmQRT89Y1nngxxLeIaw32GcyL4BK9Vfo2hnkOxs3n6e6SEEDmXJCgBwMYTNxm86iiVXRxYXX039hsmP/NkiE2XNuG911iuaEaLGbQp08ZMUQshsjNJUIJfDwcw7Ndj1C9lz3LnpeTa/fszTYa4v1xRzcI1+arZV1KuSAjxzCRB5XAr9l5mzLpTdCgHs/DG+ozvM02GOBVyilE7R+Ef5s/bNd7m/VrvS7kiIcRzkQSVg83bcZGvNp2lf/kwPo8Yj4oNf+rJEBdDLzLXdy5brmzB2c6ZBW0W0LB4QzNGLYTIKSRB5UBaa6ZtPsfc7Rf5vLwf/QMno55yMsTV8KvMOzaPP/3/xN7Wnv/V/B+9q/eWe5uEEOlGElQOYzBoxm84zbI9l1hYZjsv3PjuqSZD3Iy8yYLjC1h7YS22Vrb0detLf9f+FLArYP7ghRA5iiSoHCTJoBnx23HWH/ZnQ/GVuN3ekubJEMExwSw6vojV51cD0L1Kd95xf0cKvAohzEYSVA4Rn2hgyM++HDhxmn8LzaXInTNpmgwRGhvKklNL+OnMTyQYEni54ssMcB9AMYdiGRi9ECInkgSVA8QmJPH+yiPcPref7Y4zcYiLeuJkiIj4CL4//T0rTq8gOiGaDuU78L+a/6N0/tIZGLkQIifL8ASllCoFrACKABpYqLWeqZRyAn4GygKXgde01nczOr7sJjIukXeWH6LAlb9Yl2c+NnaFocfvqU6GiE6I5sezP7L05FLC48NpU6YN79d8n4oFK2Zw5EKInM4SZ1CJwCda6yNKqXzAYaXUFqAvsE1rPVkpNQIYAQy3QHzZRlh0An2W7KfZrWV8bLsaiqc+GSIuKY7V51az6MQi7sTeoWmJpgz0GEh15+oWiFwIISyQoLTWN4Gbpp8jlFJngBJAZ6CFabXlwA4kQT2zoIg43vrOh3fuzuAlmz2pToZIMCSw9sJaFhxbwO3o29QrWo9BHoOo5VLLMoELIYSJRa9BKaXKAh7AfqCIKXkB3MI4BCiewY3QGD5c+BcToyZSw8o/xckQSYYkNl7ayLe+3xIQGYB7YXcmNZlE/WL1LRi5EEL8x2IJSinlAPwGfKS1Dr+/P5DWWiuldCrbvQu8C1C6tFywf9iVkCjGLfiRuXFfUMg2FvXqg5MhDNrA1itbmes7F/8wf6o6VWWu11yalmgqPZqEEJmKRRKUUsoWY3JaqbX+3bT4tlKqmNb6plKqGBCY0rZa64XAQoC6deummMRyqvO3I1i88Bu+TZqFdb7CWPdanzwZQmuNT4APc3zncPbOWco7lmdGixl4lfbCSllZOHIhhHiUJWbxKWAxcEZrPeO+h9YDfYDJpu/rMjq2rOzEtVB8lgznK72KmCJ1yNV7VfJkiH039zH76GyOBx2npENJvmjyBe3LtcfaytrCUQshROoscQbVGOgNnFBK+ZqWfYYxMf2ilHoLuAK8ZoHYsqTDF25w+/u3+UDtJrLKqzi8Ohds7fAN9GX20dkcuHWAIvZFGNtwLJ0rdpYq40KILMESs/h2Aald7PDKyFiyg33HT2H/W29eVP6ENx5F/tZDOX3nDLOPzmbX9V042zkzot4IXq38Krmtc1s6XCGESDOpJJGF7d21jXJb3sZRRRP58jICy7gxdsfHbL26lfy58vNR7Y/oUbUH9rb2lg5VCCGemiSoLOrAn0updWAYEdaOXO62nOXBO9i4fgz2tva8X/N9elXvJa0vhBBZmiSorEZrjv04mnp+c9idpwob6zfnz4MjsLWypZ9bP/q59pPWF0KIbEESVFaSEMOF7/pSPHgzg4q4s9shCgK28XrV13m7xtvS+kIIka1IgsoidPhN/BZ14Q+bm6wsVRqDVSRdTK0viuYtaunwhBAi3UmCygLCr+zmu/Vv8bOTNdEqPx0rtOf9mu9TKn8pS4cmhBBmIwkqE4tJiOaH7SNZFrCV8Py2VLByZWqHiVRyktYXQojsTxJUJpRgSGDN/unMO/cTwcpAzVgbKhUbwZiXX5d6eUKIHEMSVCZi0AY2+y5m5rF5BKgEXOMSqRbckDpNhvNW8yqWDk8IITKUJKhMQGvN3nNrmLH/K84RTfmERFqFuFO06jDeesMVl3x2T96JEEJkM5KgLOzEVR+m+YzmSNJdiiUk0eZOeYpXGUWf12tTOJ+UJhJC5FySoCzEP/AEM7Z9yr/xNyiYlMQLd4tSqvwoer3ehEIOkpiEEEISVAa7FXaFGX8P4e/o89hpTZtQR8qVGcEbr7XFWRKTEEIkkwSVQcJi7vDNpo9ZH3YIDbQIz03VYkPo/tprOOXNZenwhBAi05EEZWbR8VF8u3kkvwZtJ1ppmkRaUbPQu7zW7V0KSmISQohUSYIykwRDAou2TmRVwBruWmvqxRho4NiDbv2GUiCvDOUJIcSTSIJKZwZtYLnPbFZeWMptmyTc4pPoad+O7m9OoICD9GUSQoi0kgSVjlbv/4FlJ77hqm0cFQyJvGJowhuvT6NAAUdLhyaEEFmOJKh0EBUXzaer3mAXFylGIm8nutO76yycnIpYOjQhhMiyJEE9p33ndjF+5yCu2SbSIdqBT1/+gULFKlg6LCGEyPIkQT0jrTUz1o1k1d0N2FkZ+NSuDX3e/AakmKsQQqQLSVDPICj0FsN+7c4h2zu4xytGNJ5NDTcvS4clhBDZiiSop7Rp/09MO/EFwTaaVxJKM6L3z+Sxz2fpsIQQItuRBJVGSUmJTPypL2sSfSmkNGOKvc0rbYdYOiwhhMi2JEGlwcVrJxjzV1+O547HM86OsR2+p0zJapYOSwghsjVJUI9hSEpi2YZxLA/+nShbRU/regx7exFW1taWDk0IIbI9SVCp2OyzgmVnZnDCLonSBis+r+FN63qvWDosIYTIMSRBPeTYqd0s8fmUHXkiyGsLr9s2YMjrM7HPndfSoQkhRI6S4xPUppM3Wb73MvmSjuKY9Du789wkOo+iBWUY0flbijmXsXSIQgiRI2WqBKWUehGYCVgD32mtJ5vzeOt8r/P1pskYCvtwN5cBgBqJBRjadAoeFRqb89BCCCGeINMkKKWUNTAXaAMEAAeVUuu11qfNcbyY2Bj+2NWXkGK38IhP4iOnRjSuP4QiLq7mOJwQQoinlGkSFFAPuKC19gdQSq0COgNmSVC2tjZYO4TT3bYYI179EZu8hcxxGCGEEM8oMyWoEsC1+34PAOqb62A21rbM6fEPtjL5QQghMiUrSwfwtJRS7yqlDimlDgUFBT3XviQ5CSFE5pWZEtR1oNR9v5c0LXuA1nqh1rqu1rpu4cKFMyw4IYQQGSszJaiDQCWlVDmlVC7gdWC9hWMSQghhIZnmGpTWOlEpNRD4G+M08yVa61MWDksIIYSFZJoEBaC13ghstHQcQgghLC8zDfEJIYQQySRBCSGEyJQkQQkhhMiUJEEJIYTIlJTW2tIxPDOlVBBw5Tl3c6/GUfB9vwensM7Dyx63v7Sum1bm2Kc5ZJU4sxJ5TUVmlx7v0TJa60dubM3SCSo9KKUOAWit6977/d7P96/z8LLH7S+t6z5NjOm9T3PIKnFmJfKaiszOnO9RGeITQgiRKUmCEkIIkSllqht1LWThE35PbVla95cezLFPc8gqcWYl8pqKzM5s79Ecfw1KCCFE5iRDfEIIITIlSVBCCCEypRydoJRSS5VSSaavk0qpn5RSjkqpy0qpWNPXbtO6K5VS50zrLVFK2SqlCiilflVKnVVKnVFKNbxv358opbRS6rG95E37ClRKnbxv2VTTPo8rpdYopQqYltsqpZYrpU6YjjfSTC9NSnGWUkptV0qdVkqdUkoNNi0fp5S6rpTyNX21v28bd6XUXtP6J5RSdhkVb1Zheq+dML12h0zLupleM4NSqu5967ZRSh02rX9YKdXKcpGL7CqVzyQnpdQWpZSf6XtB0/Keps+pE0qpPUqpmg/ty1opdVQpteFZYsnRCcokDojWWrthbPMxErgEOAL5ADulVANgJVAVqAHkAd4GZgKbtNZVgZrAGTB+mAMvAFfTcPxlwIsPLdsCuGmt3YHzppgAugG5tdY1gDrAAKVU2ad/ys8kEfhEa10daAB8oJSqbnrsa611LdPXRgCllA3wA/Ce1toVaAEkZFCsWU1L02t3LxmdBF4BfB5aLxh4yfTv3wf4PgNjFDnHMh79TBoBbNNaVwK2mX4H42dlc9N7cgKPTpgYjOlz8Vnk2ASllCoJVAKiTb/bAPZAQ2CS1joOsAUUoLXWG7UJcACoADQDFmNcIV5rHWra/dfAMOCJM1C01j7AnYeWbdZaJ5p+3YexuzCm/eU1xZoHiAfCn/7ZPz2t9U2t9RHTzxEY33QlHrPJC8BxrfUx0zYhWusk80ea9Wmtz2itz6Ww/KjW+obp11NAHqVU7oyNTmR3KX0mAZ2B5aaflwMvm9bdo7W+a1p+/2fVvc/YDsB3zxpLjk1QwDcYs/sGwAG4CYRhPHNqppSKAiKAE1rr/fc2UkrZAr0xfkAEAUtNp7DfKaXyKqU6A9fvfTCng/7AX6affwWiTLFeBaZprR9+I5md6azNA7j3ugw0neYvuXfqD1QGtFLqb6XUEaXUsIyOM4vQwGbTkN27T7FdV+CI6Q8pIcytiNb6punnW0CRFNZ5i/8+q8D4GTsMMDzrQXNkglJKdQQCAX+gLhAJFAfyAs5AQYxJqw3wmlLK7b7Nv8U49HICqA3M01p7YEwc44DPgDHpFOcojENrK02L6gFJpljLAZ8opcqnx7GeIiYH4DfgI611ODAP49lkLYyJc7ppVRugCdDT9L2LUsorI2PNIpporWsD7TAOmzZ70gZKKVfgK2CAuYMT4mGmUaQHRoeUUi0xJqjhpt87AoFa68PPc6wcmaCAxkAn4BzGD9e8wFLgd4wv/O+m0bx/gBiMf62ilBoLFAY+BgKAgPvOrn7FmLDKAceUUpcxnu4eUUoVfdoAlVJ9gY5AT/3fzWpvYLzmlaC1DgR2Y0ywGcJ09vgbsFJr/TuA1vq21jpJa20AFmFMomB8fXy01sFa62iMnZJrZ1SsWYXW+rrpeyCwhv9evxSZhk3WAG9qrS+aP0IhALitlCoGYPoeeO8BpZQ7xmG8zlrrENPixkAn0+fgKqCVUuqHpz1ojkxQWuuRWuuSwEsYLzxHYRy28wIOY7pAqJSqgTF5HVZKvQ20BXporQ1a61vANaVUFdNuvTAOubhorctqrcti/JCubVo3zZRSL2I8Ne5k+nC/5yrQyrROXoyTFc4+9QvwDJRSCuP1tjNa6xn3LS9232pdMF7gB/gbqKGUsjddM2sOnM6IWLMK05Bwvns/Y7xud/Ix6xcA/gRGaK13Z0iQQhitxzgxB9P3dQBKqdIY/7DvrbU+f2/le5+xps/B14F/tNa9nvqoWusc+wX8hHGShMY4w2wPUB/jBcJYjGdPS03rJgIXAV/T1xiMw1qHgOPAWqDgQ/u/DBRKQww3TccPwHiafAG4dt+x5pvWdQBWY7z+dRoYmoGvVRPT63T8vrjaY5xJdsK0fD1Q7L5tepliPQlMsfS/d2b7AsoDx0xfp4BRpuVdTO+FOOA28Ldp+WiMf0z53vflYunnIV/Z6yuVzyRnjLP3/ICtgJNp3e+Au/e9Hw+lsL8WwIZniUVKHQkhhMiUcuQQnxBCiMxPEpQQQohMSRKUEEKITEkSlBBCiExJEpQQQohMSRKUEM9IKVX2/orPadymr1KqeBrWmfOMMb2nlHrzWbYVIrORlu9CZKy+GO8Lu/GE9Z6J1nq+OfYrhCXIGZQQz8dGGXuFnVHG3mD2AEqpMUqpg8rYP2yhMnoVY2mqlab+T3mUUp6mPjrHlFIH7lWWAIorpTaZ+u9MSenASqnJytif67hSappp2Til1KdKqeLqvx5dvsrY86yMUqqwUuo3U2wHlVKNM+RVEuIZSIIS4vlUAb7VWlfD2PrkfdPyOVprT23sM5YH6Ki1/hVj5ZGeWutaGAv//gwM1lrXBFpjrF4Cxiol3TH2H+tu6jGWTCnljLHihKs29g2beP/jWusb2tSjC2ONxN+01lcw9jD7WmvtibHG5DO3QhDC3CRBCfF8run/6uL9gLEkFEBLpdR+pdQJjPUTXVPYtgpwU2t9EEBrHa7/6wO2TWsdprWOxVjWqsxD24ZhLMe1WCn1Cqa+Zg8znSG9g7FtCxiT4ByllC/G0lT5TRXqhch05BqUEM/n4VphWhlb238L1NVaX1NKjQOett39/X2eknjo/6rWOlEpVQ9jkeJXgYGYCgnfYyrkuxhj0eFI02IroIEp8QmRqckZlBDPp7RSqqHp5zeAXfyXjIJNZyev3rd+BHDvOtM5oJhSyhNAKZXPVPn9iUz7ddRabwSGADUfetwWY2Hh4fq+KtPAZmDQfevVSsvxhLAESVBCPJ9zGBsNnsHY6HKe1joU43Wfkxjbjhy8b/1lwHzTEJs1xutMs5VSx4AtpP1MKx+wQSl1HGNS/PihxxthnJDhfd9EieLAh0Bd08SK08B7T/l8hcgwUs1cCCFEpiRnUEIIITIlSVBCCCEyJUlQQgghMiVJUEIIITIlSVBCCCEyJUlQQgghMiVJUEIIITKl/wNC1EHFjS8jTgAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plot_times(B, t1s, t2s, t3s, xlabel='batch size')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment