From f39cc81873b1d5c8f4de0d432f79fab713443947 Mon Sep 17 00:00:00 2001 From: NT Date: Sun, 24 Jan 2021 18:07:14 +0800 Subject: [PATCH] updated sol example --- diffphys-code-sol.ipynb | 921 ++++++++++++++++++++++++++ resources/diffphys-sol-domain.png | Bin 0 -> 12055 bytes resources/diffphys-sol-manifolds.jpeg | Bin 0 -> 61329 bytes 3 files changed, 921 insertions(+) create mode 100644 diffphys-code-sol.ipynb create mode 100644 resources/diffphys-sol-domain.png create mode 100644 resources/diffphys-sol-manifolds.jpeg diff --git a/diffphys-code-sol.ipynb b/diffphys-code-sol.ipynb new file mode 100644 index 0000000..3e77315 --- /dev/null +++ b/diffphys-code-sol.ipynb @@ -0,0 +1,921 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "SoL-karman2d.ipynb", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "qT_RWmTEugu9" + }, + "source": [ + "# Reducing Numerical Errors with Deep Learning\n", + "\n", + "Next, we'll target numerical errors that arise in the discretization of a continuous PDE $\\mathcal P^*$, i.e. when we formulate $\\mathcal P$. This approach will demonstrate that, despite the lack of closed-form descriptions, discretization errors often are functions with regular and repeating structures and, thus, can be learned by a neural network. Once the network is trained, it can be evaluated locally to improve the solution of a PDE-solver, i.e., to reduce its numerical error. The resulting method is a hybrid one: it will always run (a coarse) PDE solver, and then improve if at runtime with corrections inferred by an NN.\n", + "\n", + "Pretty much all numerical methods contain some form of iterative process. That can be repeated updates over time for explicit solvers,or within a single update step for implicit solvers. Below we'll target iterations over time, an example for the second case could be found [here](https://github.com/tum-pbs/CG-Solver-in-the-Loop).\n", + "\n", + "In the context of reducing errors, it's crucial to have a _differentiable physics solver_, so that the learning process can take the reaction of the solver into account. This interaction is not possible with supervised learning or PINN training. Even small inference errors of a supervised NN can accumulate over time, and lead to a data distribution that differs from the distribution of the pre-computed data. This distribution shift can lead to sub-optimal results, or even cause blow-ups of the solver.\n", + "\n", + "In order to learn the error function, we'll consider two different discretizations of the same PDE $\\mathcal P^*$: \n", + "a _reference_ version, which we assume to be accurate, with a discretized version \n", + "$\\mathcal P_r$, and solutions $\\mathbf r \\in \\mathscr R$, where $\\mathscr R$ denotes the manifold of solution of $\\mathcal P_r$.\n", + "In parallel to this, we have a less accurate approximation of the same PDE, which we'll refer to as the _source_ version, as this will be the solver that our NN should later on interact with. Analogously,\n", + "we have $\\mathcal P_s$ with solutions $\\mathbf s \\in \\mathscr S$.\n", + "And after training, we'll have a _hybrid_ solver that uses $\\mathcal P_s$ in conjunction with a trained network to obtain improved solutions, i.e., solutions that are closer to the ones produced by $\\mathcal P_r$.\n", + "\n", + "```{figure} resources/diffphys-sol-manifolds.jpeg\n", + "---\n", + "height: 280px\n", + "name: diffphys-sol-manifolds\n", + "---\n", + "Visual overview of coarse and reference manifolds\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tayrJa7_ZzS_" + }, + "source": [ + "\n", + "explain coarse/ref setup...\n", + "Let's assume $\\mathcal{P}$ advances a solution by a time step $\\Delta t$, and let's denote $n$ consecutive steps by a superscript:\n", + "$\n", + "\\newcommand{\\pde}{\\mathcal{P}}\n", + "\\newcommand{\\pdec}{\\pde_{s}}\n", + "\\newcommand{\\vc}[1]{\\mathbf{s}_{#1}} \n", + "\\newcommand{\\vr}[1]{\\mathbf{r}_{#1}} \n", + "\\newcommand{\\vcN}{\\vs} \n", + "\\newcommand{\\project}{\\mathcal{T}} \n", + "\\vc{t+n} = \\pdec(\\pdec(\\cdots \\pdec( \\project \\vr{t} )\\cdots)) = \\pdec^n ( \\project \\vr{t} ) .\n", + "$\n", + "Here we assume a mapping operator $\\mathcal{T}$ exists that transfers a reference solution to the source manifold. This could, e.g., be a simple downsampling operation.\n", + "Especially for longer sequences, i.e. larger $n$, the source state \n", + "$\\newcommand{\\vc}[1]{\\mathbf{s}_{#1}} \\vc{t+n}$\n", + "will deviate from a corresponding reference state\n", + "$\\newcommand{\\vr}[1]{\\mathbf{r}_{#1}} \\vr{t+n}$. \n", + "This is what we will address with an NN in the following.\n", + "\n", + "We'll use an $L^2$-norm in the following to quantify the deviations, i.e., \n", + "$\n", + "\\newcommand{\\loss}{\\mathcal{L}} \n", + "\\newcommand{\\corr}{\\mathcal{C}} \n", + "\\newcommand{\\vc}[1]{\\mathbf{s}_{#1}} \n", + "\\newcommand{\\vr}[1]{\\mathbf{r}_{#1}} \n", + "\\loss (\\vc{t},\\project \\vr{t})=\\Vert\\vc{t}-\\project \\vr{t}\\Vert_2$. \n", + "Our learning goal is to train at a correction operator $\\corr ( \\vc{} )$ such that \n", + "a solution to which the correction is applied has a lower error than the original unmodified (source) solution: \n", + "$\\loss ( \\pdec( \\corr (\\project \\vr{t_0}) ) , \\project \\vr{t_1}) < \\loss ( \\pdec( \\project \\vr{t_0} ), \\project \\vr{t_1})$. \n", + "\n", + "The correction function \n", + "$\\newcommand{\\vcN}{\\mathbf{s}} \\newcommand{\\corr}{\\mathcal{C}} \\corr (\\vcN | \\theta)$ \n", + "is represented as a deep neural network with weights $\\theta$\n", + "and receives the state $\\vcN$ to infer an additive correction field with the same dimension.\n", + "To distinguish the original states $\\vcN$ from the corrected ones, we'll denote the latter with an added tilde\n", + "$\\newcommand{\\vctN}{\\tilde{\\mathbf{s}}} \\vctN$.\n", + "The overall learning goal now becomes\n", + "\n", + "$\n", + "\\text{argmin}_\\theta | \n", + "( \\pdec \\corr )^n ( \\project \\vr{t} )\n", + "- \\project \\vr{t}|^2\n", + "$\n", + "\n", + "A crucial bit here that's easy to overlook is that the correction depends on the modified states, i.e.\n", + "it is a function of\n", + "$\\newcommand{\\vctN}{\\tilde{\\mathbf{s}}} \\vctN$, so we have \n", + "$\\newcommand{\\vctN}{\\tilde{\\mathbf{s}}} \\newcommand{\\corr}{\\mathcal{C}} \\corr (\\vctN | \\theta)$.\n", + "These states actually evolve over time when training. They don't exist beforehand.\n", + "\n", + "**TL;DR**:\n", + "We'll train a network $\\mathcal{C}$ to reduce the numerical errors of a simulator with a more accurate reference. Here it's crucial to have the _source_ solver realized as a differential physics operator, such that it can give gradients for an improved training of $\\mathcal{C}$.\n", + "\n", + "\\\\\n", + "\n", + "---\n", + "\n", + "First, let's download the prepared data set (for details on generation & loading cf. https://github.com/tum-pbs/Solver-in-the-Loop), and let's get the data handling out of the way, so that we can focus on the _interesting_ parts..." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JwZudtWauiGa", + "outputId": "bd3a4a4d-706f-4210-ee4e-ca4e370b762d" + }, + "source": [ + "import os, sys, logging, argparse, pickle, glob, random, distutils.dir_util\n", + "\n", + "if not os.path.isfile('data-karman2d-train.pickle'):\n", + " import urllib.request\n", + " url=\"https://ge.in.tum.de/download/2020-solver-in-the-loop/sol-karman-2d-data.pickle\"\n", + " print(\"Downloading training data (73MB), this can take a moment the first time...\")\n", + " urllib.request.urlretrieve(url, 'data-karman2d-train.pickle')\n", + "\n", + "with open('data-karman2d-train.pickle', 'rb') as f: dataPreloaded = pickle.load(f)\n", + "print(\"Loaded data, {} training sims\".format(len(dataPreloaded)) )\n" + ], + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Downloading training data (73MB), this can take a moment the first time...\n", + "Loaded data, 6 training sims\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "RY1F4kdWPLNG" + }, + "source": [ + "Also let's get installing / importing all the necessary libraries out of the way. And while we're at it, we can set the random seed - obviously, 42 is the ultimate choice here 🙂" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BGN4GqxkIueM", + "outputId": "095adbf8-1ef6-41fd-938e-6cafcf0fdfdc" + }, + "source": [ + "!pip install --upgrade --quiet phiflow\n", + "%tensorflow_version 1.x\n", + "\n", + "from phi.tf.flow import *\n", + "import phi.tf.util\n", + "\n", + "import tensorflow as tf\n", + "from tensorflow import keras\n", + "\n", + "random.seed(42)\n", + "np.random.seed(42)\n", + "tf.compat.v1.set_random_seed(42)\n" + ], + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "text": [ + "\u001b[K |████████████████████████████████| 2.7MB 4.3MB/s \n", + "\u001b[?25h Building wheel for phiflow (setup.py) ... \u001b[?25l\u001b[?25hdone\n", + "TensorFlow 1.x selected.\n", + "Could not load resample cuda libraries: CUDA binaries not found at /usr/local/lib/python3.6/dist-packages/phi/tf/cuda/build/resample.so. Run \"python setup.py cuda\" to compile them\n", + "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/util.py:119: The name tf.AUTO_REUSE is deprecated. Please use tf.compat.v1.AUTO_REUSE instead.\n", + "\n", + "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/profiling.py:12: The name tf.RunOptions is deprecated. Please use tf.compat.v1.RunOptions instead.\n", + "\n", + "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/profiling.py:13: The name tf.RunMetadata is deprecated. Please use tf.compat.v1.RunMetadata instead.\n", + "\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.6/dist-packages/phi/viz/display.py:80: UserWarning: GUI is disabled because of missing dependencies: No module named 'dash_core_components'. To install all dependencies, run $ pip install phiflow[gui]\n", + " warnings.warn('GUI is disabled because of missing dependencies: %s. To install all dependencies, run $ pip install phiflow[gui]' % import_error)\n", + "/usr/local/lib/python3.6/dist-packages/phi/tf/flow.py:15: UserWarning: TensorFlow-CUDA solver is not available. To compile it, download phiflow sources and run\n", + "$ python setup.py tf_cuda\n", + "before reinstalling phiflow.\n", + " warnings.warn(\"TensorFlow-CUDA solver is not available. To compile it, download phiflow sources and run\\n$ python setup.py tf_cuda\\nbefore reinstalling phiflow.\")\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OhnzPdoww11P" + }, + "source": [ + "Now we can set up the _source_ simulation $\\newcommand{\\pdec}{\\pde_{s}} \\pdec$. \n", + "Note that we won't deal with \n", + "$\\newcommand{\\pder}{\\pde_{r}} \\pder$\n", + "below: the downsampled reference data is contained in the training data set. It was generated with a four times finer discretization. Below we're focusing on the interaction of the source solver and the NN. \n", + "\n", + "This code block and the next ones will define lots of functions, that will be used later on for training.\n", + "\n", + "The `KarmanFlow` solver below simulates a relatively standard wake flow case with a spherical obstacle in a rectangular domain, and an explicit viscosity solve to obtain different Reynolds numbers. This is the geometry of the setup:\n", + "\n", + "```{figure} resources/diffphys-sol-domain.png\n", + "---\n", + "height: 200px\n", + "name: diffphys-sol-domain\n", + "---\n", + "Domain setup for the wake flow case.\n", + "```\n", + "\n", + "The solver applies inflow boundary conditions for the y-velocity with a pre-multiplied mask (`velBCy,velBCyMask`), and then calls `super().step()` to run the _regular_ phiflow fluid solving step.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6WNMcdWUw4EP" + }, + "source": [ + "class KarmanFlow(IncompressibleFlow):\n", + " def __init__(self, pressure_solver=None, make_input_divfree=False, make_output_divfree=True):\n", + " IncompressibleFlow.__init__(self, pressure_solver, make_input_divfree, make_output_divfree)\n", + "\n", + " self.infl = Inflow(box[5:10, 25:75])\n", + " self.obst = Obstacle(Sphere([50, 50], 10))\n", + "\n", + " def step(self, fluid, re, res, velBCy, velBCyMask, dt=1.0, gravity=Gravity()):\n", + " # apply viscosity\n", + " alpha = 1.0/math.reshape(re, [fluid._batch_size, 1, 1, 1]) * dt * res * res\n", + "\n", + " cy = diffuse(CenteredGrid(fluid.velocity.data[0].data), alpha)\n", + " cx = diffuse(CenteredGrid(fluid.velocity.data[1].data), alpha)\n", + "\n", + " # apply velocity BCs, only for y velocity for now. note: content of velBCy should be pre-multiplied\n", + " cy = cy*(1.0 - velBCyMask) + velBCy\n", + "\n", + " fluid = fluid.copied_with(velocity=StaggeredGrid([cy.data, cx.data], fluid.velocity.box))\n", + "\n", + " return super().step(fluid=fluid, dt=dt, obstacles=[self.obst], gravity=gravity, density_effects=[self.infl], velocity_effects=())\n" + ], + "execution_count": 3, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "RYFUGICgxk0K" + }, + "source": [ + "We'll also define two alternative neural networks to represent \n", + "$\\newcommand{\\vcN}{\\mathbf{s}} \\newcommand{\\corr}{\\mathcal{C}} \\corr$: \n", + "\n", + "In all cases we'll use fully convolutional networks, i.e. networks without any fully-connected layers. The\n", + "inputs are: \n", + "- 2 fields with x,y velociy\n", + "- plus the Reynolds number as constant channel.\n", + "\n", + "The output is : \n", + "- a 2 component field containing the x,y velocty\n", + "\n", + "First, let's define a minimal network consisting only of three convolutional layers with ReLU activations (we're also using keras here for simplicity). The input channel dimension is defined via the `tensor_in`, then we'll go to 32 and 64 features, before reducing to 2 channels in the output. " + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "qIrWYTy6xscA" + }, + "source": [ + "def network_small(tensor_in):\n", + " return keras.Sequential([\n", + " keras.layers.Input(tensor=tensor_in),\n", + " keras.layers.Conv2D(filters=32, kernel_size=5, padding='same', activation=tf.nn.relu),\n", + " keras.layers.Conv2D(filters=64, kernel_size=5, padding='same', activation=tf.nn.relu),\n", + " keras.layers.Conv2D(filters=2, kernel_size=5, padding='same', activation=None), # u, v\n", + " ])\n" + ], + "execution_count": 4, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YfHvdI7yxtdj" + }, + "source": [ + "For flexibility (and larger-scale tests later on), let's define a _proper_ ResNet with a few more layers. This architecture is the one from the original paper, and will give a fairly good performance (`network_small` above will train faster, but give a sub-optimal performance at inference time)." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "TyfpA7Fbx0ro" + }, + "source": [ + "def network_medium(tensor_in):\n", + " l_input = keras.layers.Input(tensor=tensor_in)\n", + " block_0 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_input)\n", + " block_0 = keras.layers.LeakyReLU()(block_0)\n", + "\n", + " l_conv1 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(block_0)\n", + " l_conv1 = keras.layers.LeakyReLU()(l_conv1)\n", + " l_conv2 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_conv1)\n", + " l_skip1 = keras.layers.add([block_0, l_conv2])\n", + " block_1 = keras.layers.LeakyReLU()(l_skip1)\n", + "\n", + " l_conv3 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(block_1)\n", + " l_conv3 = keras.layers.LeakyReLU()(l_conv3)\n", + " l_conv4 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_conv3)\n", + " l_skip2 = keras.layers.add([block_1, l_conv4])\n", + " block_2 = keras.layers.LeakyReLU()(l_skip2)\n", + "\n", + " l_conv5 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(block_2)\n", + " l_conv5 = keras.layers.LeakyReLU()(l_conv5)\n", + " l_conv6 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_conv5)\n", + " l_skip3 = keras.layers.add([block_2, l_conv6])\n", + " block_3 = keras.layers.LeakyReLU()(l_skip3)\n", + "\n", + " l_conv7 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(block_3)\n", + " l_conv7 = keras.layers.LeakyReLU()(l_conv7)\n", + " l_conv8 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_conv7)\n", + " l_skip4 = keras.layers.add([block_3, l_conv8])\n", + " block_4 = keras.layers.LeakyReLU()(l_skip4)\n", + "\n", + " l_conv9 = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(block_4)\n", + " l_conv9 = keras.layers.LeakyReLU()(l_conv9)\n", + " l_convA = keras.layers.Conv2D(filters=32, kernel_size=5, padding='same')(l_conv9)\n", + " l_skip5 = keras.layers.add([block_4, l_convA])\n", + " block_5 = keras.layers.LeakyReLU()(l_skip5)\n", + "\n", + " l_output = keras.layers.Conv2D(filters=2, kernel_size=5, padding='same')(block_5)\n", + " return keras.models.Model(inputs=l_input, outputs=l_output)\n" + ], + "execution_count": 5, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ew-MgPSlyLW-" + }, + "source": [ + "Next, we're coming to two functions which are pretty important: they transform the simulation state into an input tensor for the network, and vice versa. Hence, they're the interface between _keras/tensorflow_ and _phiflow_.\n", + "\n", + "The `to_keras` function uses the `staggered_tensor` from phiflow (a 2 component tensor instead of 2 separate grids), from which we discard the outermost layer. We then add a constant channel via `tf.constant` that is multiplied by the desired Reynolds number.\n", + "\n", + "After network evaluation, we transform the output tensor back into a staggered velocity grid for phiflow. (Note: these are two _centered_ grids with different sizes, so we leave the work to the`unstack_staggered_tensor` function in `StaggeredGrid()` constructor)." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "hhGFpTjGyRyg" + }, + "source": [ + "def to_keras(fluidstate, ext_const_channel):\n", + " # drop the unused edges of the staggered velocity grid making its dim same to the centered grid's\n", + " return math.concat(\n", + " [\n", + " fluidstate.velocity.staggered_tensor()[:, :-1:, :-1:, 0:2],\n", + " tf.constant(shape=fluidstate.density.data.shape, value=1.0)*math.reshape(value=ext_const_channel, shape=[fluidstate._batch_size, 1, 1, 1]),\n", + " ],\n", + " axis=-1\n", + " )\n", + "\n", + "def to_staggered(tensor_cen, box):\n", + " return StaggeredGrid(math.pad(tensor_cen, ((0,0), (0,1), (0,1), (0,0))), box=box)\n" + ], + "execution_count": 12, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VngMwN_9y00S" + }, + "source": [ + "---\n", + "\n", + "So far so good - we also need to take care of a few more mundane tasks, e.g. the some data handling and randomization. Below we define a `Dataset` class that stores all \"ground truth\" reference data (already downsampled).\n", + "\n", + "We actually have a lot of data dimensions: multiple simulations, with many time steps, each with different fields. This makes the code below a bit more difficult to read.\n", + "\n", + "The data format for `dataPreloaded`: is `['sim_name', frame, field (dens & vel)]`, where each field has dimension `[batch-size, y-size, x-size, channels]` (this is the standard phiflow export)." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "tjywcdD2y20t" + }, + "source": [ + "class Dataset():\n", + " def __init__(self, data_preloaded, num_frames, num_sims=None, batch_size=1):\n", + " self.epoch = None\n", + " self.epochIdx = 0\n", + " self.batch = None\n", + " self.batchIdx = 0\n", + " self.step = None\n", + " self.stepIdx = 0\n", + "\n", + " self.dataPreloaded = data_preloaded\n", + " self.batchSize = batch_size\n", + "\n", + " self.numSims = num_sims\n", + " self.numBatches = num_sims//batch_size\n", + " self.numFrames = num_frames\n", + " self.numSteps = num_frames\n", + "\n", + " #with open('/Users/thuerey/temp/sol-karman-2d-data.pickle', 'rb') as f: self.dataPreloaded = pickle.load(f)\n", + " \n", + " self.dataSims = ['karman-fdt-hires-set/sim_%06d'%i for i in range(num_sims) ]\n", + " self.dataFrms = [ np.arange(num_frames) for _ in self.dataSims ] \n", + "\n", + " # constant additional per-sim channel: Reynolds numbers from data generation\n", + " ReNrs = [160000.0, 320000.0, 640000.0, 1280000.0, 2560000.0, 5120000.0]\n", + " self.extConstChannelPerSim = { self.dataSims[i]:[ReNrs[i]] for i in range(num_sims) }\n", + "\n", + " #print(format(self.dataPreloaded[self.dataSims[0]][0][0].shape )) # debugging example: check shape of a single density field\n", + "\n", + " # the data has the following shape ['sim', frame, field (dens/vel)] where each field is [batch-size, y-size, x-size, channels]\n", + " self.resolution = self.dataPreloaded[self.dataSims[0]][0][0].shape[1:3] \n", + "\n", + " # compute data statistics for normalization\n", + " self.dataStats = {\n", + " 'std': (\n", + " np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][0].reshape(-1)) for asim in self.dataSims for i in range(num_frames)], axis=-1)), # density\n", + " (\n", + " np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][1][...,0].reshape(-1)) for asim in self.dataSims for i in range(num_frames)])), # vel[0]\n", + " np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][1][...,1].reshape(-1)) for asim in self.dataSims for i in range(num_frames)])), # vel[1]\n", + " )\n", + " ),\n", + " 'ext.std': [ np.std([np.absolute(self.extConstChannelPerSim[asim][0]) for asim in self.dataSims]) ] # Re\n", + " }\n", + "\n", + " print(\"Data stats: \"+format(self.dataStats))\n", + "\n", + " # re-shuffle data for next epoch\n", + " def newEpoch(self, exclude_tail=0, shuffle_data=True):\n", + " self.numSteps = self.numFrames - exclude_tail\n", + " simSteps = [ (asim, self.dataFrms[i][0:(len(self.dataFrms[i])-exclude_tail)]) for i,asim in enumerate(self.dataSims) ]\n", + " sim_step_pair = []\n", + " for i,_ in enumerate(simSteps):\n", + " sim_step_pair += [ (i, astep) for astep in simSteps[i][1] ] # (sim_idx, step) ...\n", + "\n", + " if shuffle_data: random.shuffle(sim_step_pair)\n", + " self.epoch = [ list(sim_step_pair[i*self.numSteps:(i+1)*self.numSteps]) for i in range(self.batchSize*self.numBatches) ]\n", + " self.epochIdx += 1\n", + " self.batchIdx = 0\n", + " self.stepIdx = 0\n", + "\n", + " def nextBatch(self): \n", + " self.batchIdx += self.batchSize\n", + " self.stepIdx = 0\n", + "\n", + " def nextStep(self):\n", + " self.stepIdx += 1\n" + ], + "execution_count": 7, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "twIMJ3V0N1FX" + }, + "source": [ + "The `nextEpoch`, `nextBatch`, and `nextStep` functions will be called at training time.\n", + "\n", + "Now we need one more function that compiles the data for a mini batch to train with, called `getData` below. It returns batches of the desired size in terms of marker density, velocity, and Reynolds number.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Dfwd4TnqN1Tn" + }, + "source": [ + " # for class Dataset():\n", + "\n", + " # get one mini batch of data: [marker density, velocity, Reynolds number] all from ground truth\n", + " def getData(self, consecutive_frames, with_skip=1):\n", + " marker_dens = [\n", + " math.concat([\n", + " self.dataPreloaded[\n", + " self.dataSims[self.epoch[self.batchIdx+i][self.stepIdx][0]] # sim_key\n", + " ][\n", + " self.epoch[self.batchIdx+i][self.stepIdx][1]+j*with_skip # steps\n", + " ][0]\n", + " for i in range(self.batchSize)\n", + " ], axis=0) for j in range(consecutive_frames+1)\n", + " ]\n", + " velocity = [\n", + " math.concat([\n", + " self.dataPreloaded[\n", + " self.dataSims[self.epoch[self.batchIdx+i][self.stepIdx][0]] # sim_key\n", + " ][\n", + " self.epoch[self.batchIdx+i][self.stepIdx][1]+j*with_skip # steps\n", + " ][1]\n", + " for i in range(self.batchSize)\n", + " ], axis=0) for j in range(consecutive_frames+1)\n", + " ]\n", + " ext = [\n", + " self.extConstChannelPerSim[\n", + " self.dataSims[self.epoch[self.batchIdx+i][self.stepIdx][0]]\n", + " ][0] for i in range(self.batchSize)\n", + " ]\n", + " return [marker_dens, velocity, ext]\n" + ], + "execution_count": 8, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "bIWnyPYlz8q7" + }, + "source": [ + "After all the definitions we can finally run some code. We can define the data set with the downloaded data from the first cell:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "59EBdEdj0QR2", + "outputId": "8043f090-4e7b-4178-d2d2-513981e3905b" + }, + "source": [ + "output_dir = \"./\" # TODO create? , replaced params['train'] and params['tf']\n", + "nsims = 6\n", + "batch_size = 3\n", + "simsteps = 500\n", + "\n", + "dataset = Dataset( data_preloaded=dataPreloaded, num_frames=simsteps, num_sims=nsims, batch_size=batch_size )\n", + "#dataset.newEpoch()\n", + "#print(format(getData(dataset,1)))\n", + "#print(format(dataset.getData(1)))\n" + ], + "execution_count": 9, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Data stats: {'std': (2.2194703, (0.32598782, 0.1820292)), 'ext.std': [1732512.6262166172]}\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0N92RooWPzeA" + }, + "source": [ + "Additionally, we can define several global variables to control the training and the simulation.\n", + "\n", + "The most important and interesting one is `msteps`. It defines the number of simulation steps that are unrolled at each training iteration. This directly influences the runtime of each training step, as we first have to simulation all steps forward, and then back-propagate the gradient through all `msteps` simulation steps interleaved with the NN evaluations. However, this is where we'll receive important feedback in terms of gradients how the inferred corrections actually influence a running simulation. Hence, larger `msteps` are typically better.\n", + "\n", + "In addition we define the `source` and `reference` simulations below (note, the reference is just a placeholder for data, only the `source` simulation is actually executed). We also define the actual NN `network`. All three are initialized with the size given in the data set (`dataset.resolution`)." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EjgkdCzKP2Ip", + "outputId": "6b21bd54-15aa-4440-b274-c3a68ab244f8" + }, + "source": [ + "# one of the most crucial! how many simulation steps to look into the future while training\n", + "msteps = 4\n", + "\n", + "# this is the actual resolution in terms of cells\n", + "source_res = list(dataset.resolution)\n", + "# this is only a virtual size, in terms of abstract units for the bounding box of the domain (in practice it's important for conversions or when rescaling to physical units)\n", + "sim_len = 100.\n", + "\n", + "source = Fluid(Domain(resolution=source_res, box=box[0:sim_len*2, 0:sim_len], boundaries=OPEN), buoyancy_factor=0, batch_size=batch_size)\n", + "reference = [ Fluid(Domain(resolution=source_res, box=box[0:sim_len*2, 0:sim_len], boundaries=OPEN), buoyancy_factor=0, batch_size=batch_size) for _ in range(msteps) ]\n", + "\n", + "# velocity BC\n", + "vn = np.zeros(source.velocity.data[0].data.shape) # st.velocity.data[0] is considered as the velocity field in y axis!\n", + "vn[..., 0:2, 0:vn.shape[2]-1, 0] = 1.0\n", + "vn[..., 0:vn.shape[1], 0:1, 0] = 1.0\n", + "vn[..., 0:vn.shape[1], -1:, 0] = 1.0\n", + "velBCy = vn\n", + "velBCyMask = np.copy(vn) # warning, mask needs to be binary, 0..1, this only works if vel is also 1\n", + "\n", + "lr_in = tf.placeholder(tf.float32, shape=[]) # learning rate\n", + "Re_in = tf.placeholder(tf.float32, shape=[batch_size]) # Reynolds numbers\n", + "\n", + "source_in = phi.tf.util.placeholder_like(source)\n", + "reference_in = [ phi.tf.util.placeholder_like(source) for _ in range(msteps) ]\n", + "\n", + "network = network_small(to_keras(source_in, Re_in)) # use small network for testing\n", + "#network = network_medium(to_keras(source_in, Re_in)) # optionally switch to larger network\n", + "network.summary() \n", + "\n" + ], + "execution_count": 10, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From /tensorflow-1.15.2/python3.6/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "If using Keras pass *_constraint arguments to layers.\n", + "Model: \"sequential\"\n", + "_________________________________________________________________\n", + "Layer (type) Output Shape Param # \n", + "=================================================================\n", + "conv2d (Conv2D) (3, 64, 32, 32) 2432 \n", + "_________________________________________________________________\n", + "conv2d_1 (Conv2D) (3, 64, 32, 64) 51264 \n", + "_________________________________________________________________\n", + "conv2d_2 (Conv2D) (3, 64, 32, 2) 3202 \n", + "=================================================================\n", + "Total params: 56,898\n", + "Trainable params: 56,898\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:23: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n", + "/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:24: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AbpNPzplQZMF" + }, + "source": [ + "Now comes the **most crucial** step in the whole setup: we define the chain of simulation steps and network evaluations to be used at training time. After all the work defining helper functions, it's acutally pretty simple: we loop over `msteps`, call the simulator via `KarmanFlow.step` for an input state, and afterwards evaluate the correction via `network(to_keras())`. The correction is then added to the last simultation state in the `prediction` list (we're actually simply overwriting the last simulated step `prediction[-1]` with `velocity + correction[-1]`.\n", + "\n", + "One other important things that's happening here is normalization: the inputs to the network are divided by the standard deviations in `dataset.dataStats`. This is slightly complicated as we have to append the scaling for the Reynolds numbers to the normalization for the velocity. After evaluating the `network`, we only have a velocity left, so we can simply multiply by the standard deviation again (`* dataset.dataStats['std'][1]`)." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "D5NeMcLGQaxh" + }, + "source": [ + "prediction, correction = [], []\n", + "for i in range(msteps):\n", + " prediction += [\n", + " KarmanFlow().step(\n", + " source_in if i==0 else prediction[-1],\n", + " re=Re_in,\n", + " res=source_res[-1], # reference resolution is size in x direction\n", + " velBCy=velBCy,\n", + " velBCyMask=velBCyMask\n", + " )\n", + " ]\n", + "\n", + " correction += [\n", + " to_staggered(\n", + " network(\n", + " to_keras(prediction[-1], Re_in)/[\n", + " *(dataset.dataStats['std'][1]), # velocity\n", + " dataset.dataStats['ext.std'][0] # Re\n", + " ]\n", + " ) * dataset.dataStats['std'][1],\n", + " box=source.velocity.box\n", + " )\n", + " ]\n", + "\n", + " prediction[-1] = prediction[-1].copied_with(velocity=prediction[-1].velocity + correction[-1])\n" + ], + "execution_count": 13, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "c4yLlDM3QfUR" + }, + "source": [ + "We also need to define a loss function for training. Here, we can simply use an $L^2$ loss over the whole sequence, i.e. the iteration over `msteps`:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "K2JcO3-QQgC9" + }, + "source": [ + "loss_steps = [\n", + " tf.nn.l2_loss(\n", + " (reference_in[i].velocity.staggered_tensor() - prediction[i].velocity.staggered_tensor())\n", + " /dataset.dataStats['std'][1]\n", + " )\n", + " for i in range(msteps)\n", + "]\n", + "loss = tf.reduce_sum(loss_steps)/msteps\n" + ], + "execution_count": 14, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "E6Vly1_0QhZ1" + }, + "source": [ + "For the training, we use a standard Adam optimizer, and only run 4 epochs by default. This could (should) be increased for the larger network or to obtain more accurate results." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "PuljFamYQksW", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "e71bcaae-187c-4c10-cee8-f03bb8964af0" + }, + "source": [ + "lr = 1e-4\n", + "adapt_lr = True\n", + "resume = 0 # load existing network?\n", + "epochs = 4\n", + "\n", + "opt = tf.compat.v1.train.AdamOptimizer(learning_rate=lr_in)\n", + "train_step = opt.minimize(loss)\n", + "\n", + "tf_session = tf.Session() \n", + "scene = Scene.create(output_dir, count=batch_size, mkdir=False, copy_calling_script=False)\n", + "sess = Session(scene, session=tf_session)\n", + "tf.compat.v1.keras.backend.set_session(tf_session)\n", + "\n", + "sess.initialize_variables()\n", + "\n", + "# optional, load existing network...\n", + "if resume>0: \n", + " ld_network = keras.models.load_model(output_dir+'/nn_epoch{:04d}.h5'.format(resume))\n", + " network.set_weights(ld_network.get_weights())\n" + ], + "execution_count": 15, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/session.py:28: The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead.\n", + "\n", + "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/session.py:29: The name tf.train.Saver is deprecated. Please use tf.compat.v1.train.Saver instead.\n", + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "p8hUXJDkRQST" + }, + "source": [ + "As this setups supports an (optional) fairly accurate training with the medium sized network from above, we'll define helper function for scheduling learning rate decay. This helps to make the network converge later on in the training. The steps below (after 10,15 etc. epochs) were determined heuristically from previous runs. Feel free to experiment." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Am3hSdNgRPEh" + }, + "source": [ + "\n", + "def lr_schedule(epoch, current_lr):\n", + " lr = current_lr\n", + " if epoch == 25: lr *= 0.5\n", + " elif epoch == 20: lr *= 1e-1\n", + " elif epoch == 15: lr *= 1e-1\n", + " elif epoch == 10: lr *= 1e-1\n", + " return lr\n" + ], + "execution_count": 16, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lrALctV1RWBO" + }, + "source": [ + "Finally, we can start training! This is very straight forward now, we simply loop over the desired number of iterations, get a batch each time via `getData`, feed it into the source simulation input `source_in`, and compare it in the loss with the `reference` data for the batch.\n", + "\n", + "The setup above will automatically take care that the differentiable physics setup used here provides the right gradient information, and connects to the tensorflow network. Be warned: due to the complexity of the setup, this training can take a while..." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "m3Nd8YyHRVFQ", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "3bea702a-14d0-43a7-ebc5-25289e27c5a5" + }, + "source": [ + "current_lr = lr\n", + "steps = 0\n", + "for j in range(epochs): # training\n", + " dataset.newEpoch(exclude_tail=msteps)\n", + " if jTQtG^o0=0^l|x{zoh7?w*^9(F*{8jQK7BRdt#6P?gx8s+x+}t3WUgE3?>?DFy&Q z=>PJGp{K5;H=Ub@tBt*rHJzugn>C%il@$PB7hIV6G;LFiQ1MnUng$I$jmd$kvtwz9q*u)+ncHZoAG6{>#HB&HTBA%Gtrw#H`>aT zC(yX@0Z-SA_Qa0H!!Ir~*FRIxn?TVf%Q^Sx(?Zr}hRt&cR%Eh2P?l3^=1?_!IX%7j zeG8U83ZVbWmtIt7Q6|=b(-LOVKkq07YDh|KodJCcI92vu=_r0?w!TZ9Llv`Fuh8;n zOZi+DGWg^2mup=?9?dD?_^vHFx#JC^YVYp#nzGcbM_5(s)z4d(nsP14u+U6-n`+(H zm*crX8_Ks`azzH}7lA1WyF9NQ@9FB*lOLo%xGMEs;bIK8T^Mb>zlmj3xw}6epjA=V z8`9MkyC5dc1XH118ZPlmObpU--8mh~3PEk1BAPKX?rmM!X5;w#}< zP|~A|25rxhx6J;hFfZ?4OlZjuxvY)6ZyPVk`$cuHehxKjKY50uGaerh0)z(6fnwNi$`az%I^*}Oy_=wo3}lWaGQ-E z&IX;Q1geFN>IP)q_KHPDwMyK0nJ#^-)rN+;g0>xa*%!U49c|rbzg=*Y%q(~7aTe&B z(SvrVNHBOPIQ(}w*>Xi6n^Bptv;{d^fzthrH7ksi$t5L?o0&wYrwSl4q@N8L^xkj2 zKIhqOPngv50)*95U3h&@KPNPN zTYpun?eoSd^gz&Zz`VduI*02j>7<@zu4(0K|GC)+a=p$v;V|%G>W9#U1PvbZBkl(5 zn)&`)U;pHVFH@bDbKg_0IrmN-{(V*UeJqAtwS1`auwspKT@>z_zxf{ z_Thd4V_OKL>aV=bEz|Y`EixqndJ&c<=^4A?UxZXxr8Ng0ObNL|kFspk#p@_r;(V{l zv@^+JlO$3P`DSyj+9k`v!z8?-UO)bd;a`uG?pTXFmw0cK;`1dgjGK99bAkjcirwqo zJ0o@Yf$-cia`{91HQA$iGA9$tY=Uq0Go_gMT|u8W8OT3n1SYQS?@1r!d#}DSm$)X! zzP7nBFFoyLib3l=J-I}59Nz4={O*$bY>*_2afa77Oxc=h(Er)piPCE1Vr{>1AN_|} zut^{dPjj9OO}xUkYsO>{&2hLXq%m%ygnIw^TXWJFcjU|A`4cOB%nWLa_Kes$uUDPahneOzvwCYV|DzjNJsxWGdpOY-u=hnfVLXo==BNj_UoC zWp6TYx}iAzN-rNLOft_xMESxs!#G4{CH{dqws%?`!VWBFTzS}+t&7=9cwDI~KxJEX zC^($-p11qE0bj46H?)Vsm5c%Fzy>q_7PIiFr;gEELOfPVJOMI0&cV#*n2&AyE#eyD z9tb%gG&2h{_>KW4E^&A;=DVf=m2sMhW00HJ9p(pT-(_rAk_D~27e#n=> zly`AbNa0W&jlp_sIiG@)RKTrqS(wWkoEl>)$RQjrBlK#J5q(hMzTseU?`KcI2#K~LFBO-_ z^NDT>q8JyE7hhDGA1C7HGSTgyM5ZE&lz+ZJvVP{w4>_Z3HIje@#s``VNoH0cf=RmH z2&~}eFRS9MAnnza7X+T)2jN@;%Z;?z*>I^<*X=@zLO$Te+!KQcCpNp)`~vxlSt2kt z!!(;x*eP1zodPCI^!mT6gGWJ#ot~!xKm2ce)f13~4?NO%KbyT$Ugg`9#N@Te3o!SI zuslF>D8|pieDRe9w~2h|6P*E2tQ6<{4Bc5n#5+6-0~--q#}rdGS?rr8)7Zh+xRLrP zM*GRep(T;e#9OgjGoL(le_-o0SEdDsyGcXf$=r=f@%M)~VlRy8;9eZ!qZ(P(s zxiU_@jXetY!Yw#1T%CvaihCcJ(UdC8`s+66O z6|vc17BhAvN$+#+Z{0s25ODhPGQUI;KdNq8T~ogPMQvDorbv+Nijot-g{`R5dzPeu zATuEmvF7sM0m{#&zL=-BKhQEcr|Zrc_mS(0pb5~PivCVX3E+$(>wxvlM8Q$YPEgE*2U0ddMdJk;HMyfKfo%^g0P~ zO3Q2jkTTjwt8h_0T;^24a-=XDivRdhv6Xc2^*6aH z@GHUi;_K(1SF2c_U4}n4AZ>Lks(C$cXw|j47#BF)+I8Z0>?X&i52HJ<&_KRIql8nx zM*}zl4A6Ny;o2E+-|fxbmj7`j;U6363UIa59x{1Q_6wja&LA>(X?Q&dAJ z2ah^$ra}QdBzTdTm@gO|ZB=q>t$mHvk0&er8yBg6_C|K7NLw=IVIBjKja4+UrU)nq z-x+?1_A3*D*8h16ha-k0`CesoYLl~Krr^>gBzT}$H_cH5I>kT5pKYQYXbveS+ip<( zTreb%W&}OfK6>t?Z8eI^uk|68lB(wGS7C*cDh(cxD0`;0^5cifom_tLR{HqH3@PmF z%0C}0Bij_zky?y6q-;72t34#-Y`9EcrKDW2oJ_3BWo!^0Y3kP)v`=ElZ5SFk%o-CS zG{QG5neH1C-v4HR*|E`W-7%3n@>stHUqHn=nCI6zIFcYO#H6CfuK|UW*CtKX!C)04i7sJnPLSL@*f2lR11^ zukF)gSDtqZOTre9?|<;RRHYz5-jrjHz#Hrq=+V=|$dk(G`lQ7Ymr5fdE^%X#3vYU1 zx1|tGxvfp%g)%YtxdI82mWF+NIH*JI#Ny#^GwrzSlIIDMyT-UoMF^EZdYu)0_Rwb= zh5B~wXf;ga_;}rkXf5fogCXI2BWhKpat(6$50=aEa7-{L7XYD&mE@f2xEk*$3yW5Y zetV%Y5EkHJ8<6wnJ$aXMCCX7|W=*oCp%%~|-dD{D^r%^_B5wfqW|Ug>jdM-a1iJUbz>!Grt8$^A*l%a4 z8fHQYgPCOrvp#}6k*aD<%+9u8=p0t418Y@Ygn?qb0d~@&enrz*?Gi@Kag<)@asI9n zrBe^_Y@wzEf^+1%pYw5eod%)U)Z8`P@|!D*y*_TSAo^}~8k@OYxYGOk@1l8G0FGMO z&2QOR-!Aj}O#W8!I(jWv&Q1-tRtf!Kx62g3r$!q#X&8$rGqnuSTVPl@P~0&r2skun zqBM||vm&i7A+r0vmmJ3Y+#mB7W8-cNDd8vzl*8JzKfc4q`6ZwL9CxH7d2^p?h4h>L;^ZplHjnyGqyenS@$t{qAHu8OW%a~ z!@x~eWs|2erwQiige#kSJce$)1#a2eISqN(O?s0F+{HEYh!k<$R@H*fqQrdM6^@BY zX->?zt8{gJ);tq!G2!S5pgf@bqT$&MG6(Kp4u7=3Hz+*VxX|o4^#b})ZmY4j-pV;# zg#|Y{wKjssC;CQPC(4ydWl9c>eiuGwv1=l}-cUtB@Xm-r&t0sjUlu=wpn8iimA24n zOZDv&fr%3)r8GqI`;f%2?YR-t6SbjM$;Xicj0Aq!FQn`zEXI8u-ye>~wdT5M&miKx zw!52r6{eALF4kHe&9T?KQ-xwZq9DRNG$Elp! z#^V;V6x*NLT8B-~=cRLZ?OhdT$Gct!9baArX3#99>$KBeOWk1Sw8R?95vD8w05s^T z3bIdprna-aE$%DcM&vRvfsKh1*l|=w$@dFYNM(T?#dWe5iNmaT$ssQ|@c1j&OF!QUd0#7a!Bco`sJBvB-Q{w_V|2x508rAdu#x1Av8 zE@F4~Ny4^cfA?GHH2s7OG^KxFoU4L5gnA@3rT@T2@54mgSKNDzjmBh;r=+j~q2kdh z`DFPTppTPrZCEG?QO93x$6ix=O)(FA8lHmD4JkRrB;M{NW54a$k5N`f&_y{za%dEr z#FK8DBds+3Zm(t%eB}J5Wt&1L$d;|^FF{i|8`T2avu9fJ&`{^vP#88u@@%H{-oZjx z%e^ive~sGhx2AF$bztQuvjfAS9K!+DAMH=~y;0U1e5S5ekKDdjHf-C*W%d26#7M-} zzTTA71kx$l_Cl|iB8_}s)hT9Z^P$^K!w?KSq@ocISs2Bfp7fi(T+42f7Glbo=!X5+ zq3i4@;&&nThwb4k_xC-e0&Tk1QCEpaE|xvt3vX-7OOTX~%=d7L*akuCJ0>cq7tCGT z17Ey?5m5$~Q3g(Q9ud{Gle9yfG;*iWDbcq99zUr7K~Ih!KVh1u9rQi;x%`sfE_jOK#5Y3ezkV(k4=q-f7u7Jn{hlw^LWkirMfUyqA`A5=+JTk+|Wl%u{=TgsC+mLMlLvZh{CK1;5bqLH+o8}afiDQ zrbql8-RSV?xXV!(4!1lMP~o*IJ567YAEhHBa21AN0-;C#QcWgK1Or4IApQwpIC4)J zdY=xW#sC4tLaq|Q@J3J&6BgZF5mN<`RDaNtgc0dh*ZN#}0B7zU+4(^@aX!^@%&X{_ zH!{C-|oRv^aodH7WVyG~rikyVUv~TLsgoKPT>g6MHwO z0U4sq<9CwvmH?hcXX}ZdO9f)iM{SS-CU%CJiT6$p^E-2>@e#+U#nR#`$&Y;ZZFh-dT5HXHh3`GK% zP-?V?BKKtf({2eBd|D=~w~$xT#>|8=us{cmbe=HqEZAJ&iAia?*8ghx#?a`U_;_P9 zi(~p}l6r!ge|7dA-55kTte()eEonDNH=M2(HVQMQ`g9@n7!TuswX z8wFHB33!Dah4R6jSK#?%?c`BFP&-NolwyPI?(i`2_)6*!R8Rk3!%V1|V=0bNhZ-69 zkKfc}T^{FhGF({oH`3i$Aas;Ol-wvwnZK+X1mE3zF=H`dsoZM5eq_0SZ%w<19d2M6Toke@A~!xk6B5$lbqlI`R1zLQ-*)c z<^QS(eALcF=N%IS*Kf%Ecd9Bbe*^|iatHbHwo6bP_Qltt<3)Ur9>R%Zn-Xyt3zt5c zvu{HCX7e(ASX!7VX!x+2$T@F73>+vQy6`xPqwsi`ggV$Sia;h;fpE}+TqTOVnX(|9m1@h?Z_ zf;s=g7Emm5PfBNQqw^67IeL+qN0qysEy;su12$?lH5JzWn4o{~mc6Zu5&XLL6 z`8ObV!PqBDy~^D=q)pwoGzGXQh3zD_IgScGPBDj(-%cc~mm0^WmO_Z%4UWfwGkGg~$+SD4G#Ke$zmeU3^St+ECP%19z;H`$kN^@zsbGZB(Ts|J2a`5v&s}{kq8cCl4)lW^Y4B+a6($=b2@r-HM!HEHQ?BvP`tXv9ppBm)3SaULs%PgpA*!M{HE&rhV@GEVr6!YT3<5gvARiX ze#^X$uk$$Uihj~ZN^FW-w?YM_J>8*E;CU1JLZ8y1@ zKUvEkF!?EvZ8=iSHQrYUJIk`^lCZ3wZy-BOi`&kq;xc->nMciPGyqUuYYIkU3fH|Y z!>}0YsFOB2YuHzTSDLrK?B#0HQfD#gZ^=ImB#;>j_|e+uck`(7_09$5!e>6MRn&fx z@}=>mJuf!*FMrV|v`4iA`N3%qZ+TQCT}z+kfbXOIR+9*;2cLZm2k477JU{5@CDrU6 z3PZvxa;JpTheK832syo&V+Y=G7vzMCzp`GObvwF_HcO{SBInuikKGOlk7I^h907|C z?d#XsSiXU*21dQ+AQC;6x2b~fQzXN@xG4Q!;+P_4zEZV1ZRBQo|BBXnJ;kjLwnG3d zV<87Tmo^@*6FYvLj#2@e8WT26&*>QW3}pJe81J` z9ztCFQXy6oHOHMv-T67zS3WRT8kaxV01mmHo_5$RxA<2WZu(Ix_C%D)`B50cQa;ka zcPp`gpuXcPO*T=h&%4hC<_q}qYyCm;sIBem2VST-;&^y$no#!4DqyeSvpx-rNszV2 znJs8F>X^(*%j|$7VAp}ao9k2d=^&ZKd>zdzoGpo_X>2s#QZ>ZDfu0kRmNUH{J8ST*Ol1pS zYJBXvo@ymFa7}CD^yN^#UD52kfn?bJNic^~he@6xiPdd6k9R1+Z5BH3vc{!WHJ&XZ zvC_w{otMy?!=N#V6V_Hhx(+C=IV&usisZ=I>jdkZOw_bhFeqiG1Y~!7acPm2ecsyPE81=8FMm_o zcg6knAu++zr(EV7nb$9bzSuQ^RMct$Aw$lFWeIF6PLsqVR5T_kIokksw9WaH6s!0e zYPtF!VdkN~)!qTgOBeVsFw1sBn~$z3bt4c&@ATqc9jGD_&h`q+W2DLl03vx6+kLxy z2T4Udxp<99c1*W(UAu=af;(^{&9TLUhKU6pHv*=?(<=%oWz^~nguh!bv!tN1~VL*?`}%v9QmAljigV|;0) z)_TGH>qWm@YT%yoXY%>cQuMZ^$Hf$d(s8a&n;BsRsg>qjO4WO7?#azm>t-^mmVT3f zwrj3tpB$!vbWiqWNUYZz+ANnQmBn{oS!6EMb}PM%3lm1IdPWX`8x233@*~y<$l};H z{RzgDuk)#yu+Gd(vw^MxU*-;dBX6nFynWLurCUaQJ_-o~^(UdIei$GU_erhR2k_ba zbx5dSFTDl!z8KcvHUOrDD78G9;8wqcB0UtK@BtaOSII{{L!HT1&EhU6Gi75b%>bSh zkCuR;Q!!0*lq65);a|(m!ezJIyKx~bhc#>CmHl<17iJ%R#USBHP!V&;MAQ0K)iqzP zsaN}MteWI(qqDtEP`9Dbtv^lr*S!)Z?*JaP`K91X2izb^zr_wNL!_BI9=-MleE=aZnVGczCHPd#>sFs^y| zawl{`kna2wqfhsv9)c(xnk_m46%9+Ri4PulpnM5d zAB8{|{;VGpimq`Bn5Ez_5mzvi0A7`~ss)N4*xx@Xo(Vy+5@A(HptrEFMVqhfgd%Zb zq=^#I@k?JzQ_SUQ1xy1|sT#Lv2oJl&5RNc8wHjgU`OHQahuL&z>?eVCYorUq_D^3` zSFXh=0!UwfO%ZM>hIMXln;N$eNBTj2l7BKv|7@YZOUPvmdyKcP;2Q-rk4y&VVPPf~ z*XPbbzon)I;uqa6#~(J*aa(TQtw)-xzJwF>l$k^0e}QVD7$aYUvdFsyhQo49&)LD(fECpMJwEw1d<;JE28xVBAjV8OfcHwZpuxZ#TBNJt3THJ zFwL^Am$yoO%PhVgcqPnrbs_*bDD(XRL)1noLw1g5OeeNV;_+;2qRG&6503qE{IGXE z-##&JLgs;&X)rDJk^(zGF^@iQ8~&y+N1RQ-vS3ltkTe8fA&#wMP1J9GsB+^)vwb@H z3emisxNZq@wmd0x`zg8v@5dC0@mTZ?vATCHfHOgqMip%P#jjlOYCdOudituf$3 zjM37kj)|E^cpH22zqE#?4o?YWvIPb6%lucBzSMxVtbuI1Df^x^)lv7_cEHAFBm(Y_ zI(O~?>e76PEaQ6tInss(EfdWB$P7|f@6wma&!04 zWEbBqm}igD*@{WbL04T=u1gwAS(iR9*ghwyTU+w=f9{-0h-stnga_C#-1`J zpr_Ck8}#nt8*vS20dR|BGX)aU)ZxRJ7dbaK5<54tbepT$TwK*$+}>QA?*Y(7usq%q zcgK}^Y{5bZfeJ6XKzcIS@3jHjF+%JgTT095Pt&6mdsP3?7Olzgvd~-_WwCfm5yG&(2Du1DLD5}xXL8i+KC zN%Wy=+Y;{WIX%LKi#ta+CW<&hzB`{%X*;`@=)UON^~KrH(dqRZf!4>btONM4ceuHR zI}ZtgQ9Kx)onYoU9*esJ;EAo zs<1Ez2$aav-85{&V3?ZEb$F##Jl?5J;iDw>KU} zvwrN5iyTzNd)#9xae3W=c{v?8B=E8KDGj6%(h^->f5h?Sl;eYdWBtV`p`Y+eo<>5y zVrcr2DndIn1h>5Yp7*tThNNa^7CHJVp7QNG9pnyo5;(*7F6pVj)ED{c>j$Lv zIil!)gZSFKx}5Lu8Wgnk%wTN_1)-?myIp(XQK{e$zPy7v{wL@Ib+!eyV@Clgt-ym& z3%FvF)~5t-ucku(Jmf~_*}J?YXtV!swSNOP{{svG?u`&+*2=q4y#`@#+_ckrK^y$( z-;(_a{QQY@EnL{lqM)F^0hfP~ih^v)kbmGqbS>t}Cg1m3Qk_wljsSDn0fo;03c=Xx znMe^)_zEx+4#GzB3Jg)_?V^sow>rF{UtoBq!TAjo`gQr$P$9%#xYQES)=~qsEse}7v`s;6K>BJO$HD(z<#iT) zImge(e)){btuy+&k&;priGy}TdA(E)JI_BVJ5h1cvj!pKDb~kx7&We}|H6lo)28*y z?4278BmE#7{13rD`IOovlu~NI47z{A&i^qw|B9Kp?f zET_4EiluK&&dOkjleEyFzQ0*bHx|pX$i=EP^+2&=cWAId9O~eTQ&vH36_$WP>dl%C zT;mSWN?}>$mIjs=AG4eBkZxFqueVtlLmQKzCh39CI5K2n(%jSp&A2sOP3tTdyI45p z8z*5IB=iOy6O&Z|mnYlUpG1oTE?LkeZ8}F%nk-I1kFnUjtkdYVhI>yWZJV4(@{&+b z-jQL(FX)_~sFkSpX`ReBt)DJE>(iACVi_)^ydsPRQ0}kae7uP`3EbXhNpeo-MnirC zdvy(bXQ)zd?@!Lz*=apJRF84(+gv*rkKJh#D!QjlT3fv@T}{=rc3f%Nh(lZg)pngQ zJeWHh2zz8p1ru^L@#p9`WbqdFf^({1PN>U8FAic=JccUpGj@tumJ&+k^%YmRs1$Ml)5`BHz|jbP%VWu43GiC0FTuCp zDTYiqL+W8`kZxH%hOWirCx2g_f#&E$AeuSiGioEGGa|{NA zv$NqC_N@lcZF??&pqMA0pL(kOK-pCdTlaSVtGCQrJibu27molFVWcG_soW=P?HaJx zd?L6|we&2!RkG397{I#{YC1fy5EN05@Exb|U-E}juiSrbjJwZ!fm zQ1elsP<;pE=?HCxx$#ZrlWy32mL6Nyu0g3H^EZ6BCVF ze(03LTk<1Fm@M)a_6MiQQ4+e#?_zK4KbPJ7sE!8akqkM?6l&6ewjX_un)ihtxV5!rk{McSTa6uzF`)YfOytnb9AS4w6! zZer$;>dU8DI!gV1v^l;vdC=)zsjIV@rOOXygWiDz(;ZRx`*fXI$in3oC{vZ;p~Wvz z(w%Ehzx`h&aZT8%6VkgUTEkB1kK~X?;C#3ZRlM0??a9kV&Qi(N@NJ8C;RQOij72^l zYkU_oDAQ{T^smW{C*znMA|uG;!(=275Cs&}`2T(<^55ScTuC3@f5>b>E}Vh-QaRe% zP}N3L6Tprt;{Y&#lmJXr35ZHkK&pR~m4K`O^grs+0DuU40LEW5k5T#EF9DVAc>c`M zlU@O^QFkCz@_CE)H#HjgE&4yoOsF=1te(88Dk|5r^02mcd12@3>Ct|ejH+PvR5bK_ zZs}<)hH61&06tzm2p2Dei%;MQuZS4Guoyod2QRM}FYgg-?fBmqoL!&W+xY$`126xd z44;N|X;2KHI|St}XyU zexXn=8s-0_G5Qx80g>8Jg?$u_$v^the_`z*@9K=|#uFeU$Vn%{&q*gF%tdgZh?S%*xfx*Tde{ z&J!U2cZp8c%?Ig6C4tPYl6E&u;5N0xXT&x z%J=T?oW1Yf_ntrRtY1$*Q(ax%Roy*Z-P7xC>TVIhl9!f~1|Sdshyj1V-4c*4&1LOM(lzgB2 z&lnmP3Lt?`IAD003HKK_{HILlUl`&JrU7E=5^{22tZwFNVd3az?c{#93-GFdu@m^< zOwPf=3h;`{DZ<~E2VTE1^>2tZP8u;C4OGByJx6)>^ISaeZW#+%PC~*+MNL^+?y1yo zl`+pvoSp6AumHfp(cM)|Mx0znSC1TN?YFM@05R~u#LUfEOhx7Cz0AMj-}3*yolgGN z3>ag+m-RRKzXx#4E!@mN(-?s4rsi&D4j}#t0PtyM&aR*Z5bx=fUhdBK_&JF2T)_&0 zIN=^!{ecVavFRVU@i&i#ngqx*3^pE`iHWNf0AS34baGEKD^L!`HHcXq&21b30Fw#C z!e-Vc<{-YWJClQh(>;C%VmgrD8N^>f%xn4&nO6V6CMKqT%QrEx`WyeD7nl>Qgrtp| zv%QJW?}z`JHwSwU(00Es8t{&0?JBDV#(1C&r|g^*?lBsOe>$2fDT5g7ZIE*tP`f`c z9ICa4tR{#-emD{{H;MbcN&sS3a}!Ag5R-sd+R7R5{OB?C?&ItAvIBy$wISmjK zg7}Svo0R&WJejUeYJZjmS8eGkA@(P|+r$+_f0Q-vVW)Xdzn6b#Z6Wukd?<#mwT3oG zM+E>Vm8XrC5{NNC%;ILJeqSH3ZcssAYl(aMZyr|j`h^?5=WeL$IFkzP2XvDj){y10MrC1tb7TfE@4ugDKzy*a9|#KWl!1 zPk*FH115kgUiIi|9k33T-~cE9_TaMzh%LZ8f0d>Mtb!Dqzn}jq-2{|r2G-Xe4EO2(XZl~%e{qU| z`abXaW8j&8J7+x4&0RAa>7X<@5JTE-oUwZtDA7LF~1YsFr z0$~wh+Q=r@_1|oy2rPmc{b553(7yk$1w0KXlM7xPUI>&9N`@zZCkB||Il*$o;6=ca zxj?GKpBmm<<*yd`r%r!s0Q{>p{^UbpMS(+kh$4zY_wP9|7%;g0()YKm|7poT>T3G8 zz5lAg|6cyTQfvTou$~Hkx5l3}fWCo#fp$T^L3^N$&>Dao+5)YG_CuTQ@t@^O|88BY zze`j5T^~EJU2Oj5`AgsX7QZj^zJIu}7PD@#UjHG*-NM@)?9YINle3Sjjg_@KxfnP* zSdhy(nz1mEv$L|Z0l@uSbI$_+M+Cp;5C}ofVF zjfN9^N8bTJ)18@ztLGo`;O`>@@GXG}jx-{G44?$)Kz-N&Za@GK1*8CZKpD^gbb)7J zf3*htxhvoW_yaG1P#_$fqZ5HtAOpw&3V>3e0;mBRfp0)3&<6|y6TmFkd)9y*U>`UI zt{@Ny5(FKB3n7BQAk+{>2s?xqA`Fp&JcX!1bRotND~Kb+1L6+}frLZiAgPcnNFn4i zqz>{8(gPWROhc9+TaZJ@B^(qE4Gs^E6pjY&2^=q+7@Pu}2AmELr)o|b7`rszu7U6c_PM`qv0h9nr0cD2rLM5QeP(7$6)D;>C4TB~@v!P|sda#|x zpo`F-&r zk00$Y;Q51h4?aEUez5f50u2X^0ZjtU0L=p}3N0V)E7~;L5jr|L4Z0}09=bbv z6nY_g8~Qx@IR-8U3x*tqIYto1dyHy~QH(uI6ijMNG0bO}zL-gvUoeL-e`29v(O^kn znP3HCy~nD<`i^yijf>5Ot&Ht}9f4hh-GjY}gM>qaBZXs*^AaZqrwwNX7m7=XD}if< z8-kmQ+kv}=hloduCx>T?7minoH;A{7kAu&NuZ8c8{~o^ye~|!6Ktmu$U{4TDP(d(B zaQTq*q1Z!_M)-(Ol+c1OjIf+=g7A`voJfkujwqI>hUf<|JTU{YDzO)F zI&lZ_&qsKV1Rj|^3VT%XXoduign>kj#E&G0q@U!3l#En{)R{Dew2ky983CCnnJrlY zSu@!d3>PL0vw~UG9Q?Ta@efK= zN?uA!$^^<*%6%#rl_HftRWa2JH3~H^wKa7zbrWSWy*e6|2Zdtil?OAhKXW4Mre&w28Q9I( z-?NW%pmRub1aZ`I9B?vnT5zUwPI2LKDRRB$YUR4&=HYhbF5}+fq2e*-N#ps>i^r?N z8^PPnhrlP!7sS`dcfrri@6KPr|4V>bz)qk@U{jD*&_Xa*a7E~`kcm*1(4sK8u(5Ea z@S+HXh>1wH$g(JBrJm(#6vIGF&o#GGAp8WEEs%Wxvaj%9+U(%I(YZ$Op)`E1)T;E2JtcKV^98 z`m|mVPElSlUU5!|TFFtVMj23+Q;t{up+c+TqSBy>sH&p+UUglKP0e4eOC49;NWDn? zR6|@NT4Pp|PSZoPRSQ$gK&w#eOj}YrPJ2=3iB5n{pDwYkjc%DLl`~B<-8YjkOE%jv z7d1~X-?9+0h_l$R6tax7+_Vz1inrRb7O_sU{%Ip&lWKEdD{Gr!duFF>mv47xuWeuM zfb3xGQ0Iu_Xy@4OMCRn}G~&$Y9O}I2!tavkvhS+k`q2&IX6RPyjt4sR{T_54uRNAK zg+1SUo_lF|eeuTjcJ%J|VeonDv*9c4o974bXXe-HPvQTcrl zXzjVo^MV(sFYI0n1hWRm1s{iKht$6$efj+5$}5>y#i1CXuA$#w3%t&F1OLY6&EQ*( zw<&LL!_32a!&$?V!mlIDB6=g)BHu;cMOj7-Msr7}#~{Wy#!SYF#1_P1$N9#s#4E;E zCy*zEB^)OjCH5q7CS@d}CVM0=zI*zvHiarBCgnQSI(6c``1|rSlC-yJXCKTzjHZjG zmt~MdG7_Qi(c&o&qWVlqaw6=`7EUTQLJp2>z$>Y=ZXXDS46$%xtUwFTiRZ>@`RpC~J zRYR(Ms`qQGYZhyDYe(wj>sspt>Z=-98uA+{8s9hJH$^w2Hot7XYw>M4`Re@j=Qpcw zE3HPYvu!$ULgB=PT-JQ~%ZCzqrE!{%hjXnH5b-ld3HGSND)%{%kRRdfDRfF7v z)k8c(wZnYF^&^5K&7&ft-^L`zI>+V4`zDkoMkX~Ur@k9}Uz{?Z+MKqZKA7>Gxte`G zhcFlR1M5f9Jjs0a0{ueyBKKm`lH^kVvikDuirLD}s@v-I+RJtH^`s5hM&Ty=X5*Ih z*6_Ce_S%l~&ehM*UF_YoJ-WThU!uSI_jUHy4qOlJ4kM0;j`EK=k6TYvPUcS?POr|w z&WX+oE_g4xF10T=uDq_1uHW6z-_+kK+|J!O+}$~wxSIU-1@2ewaF*bD{xBZ^&~*U- zcNkng=>M@6{LS%uUH>Nnmq@?SAMro%AM3^6Y1{yi^A!Lzo&&)Bav}r7G$6(l1%P`O zUPBas03g)^z>VwO-PMP?yPI6l*O>-@uP%SA zLGQT{u>c@b>>f>i^fkPX|9SnfJ_RX%>GPrf1P%(1fQW>Qg8BetsKNr^AW$eAJQM-pe!~G00Hy=**a$cj zY+{JGswPN}UGUgn#AYE=ihurwuQswz#bN3ijDkw=kdTO&nueB+o`I8#n}?T=UqVt! zT1Hk*UR^^|OB;0M%*-t;t*mWq-P}Dqy}W&VLtefLef{QbSX_KUVp8(El+^5;+`NzZ z1%*WwUn;ArYijH2Tie<@I=i}idPm2`Cnmp7P0uVXudJ@EZ)|RD9~>SXpPZhZUtHen z1p%OcsP(sI|E3oRtd4{*y$;cf;%gF?X01jPnKfXk0zbeVAffB0|N0P}A6e`qgy z6aYsFsT5$w7vIpTsOk25N#&{h?l$qg%d&>*ZL}Rz#xGVqPxHDC$HCBu?-V?5xE?Ok zQM~buZ@^d5AJB7!4l(QzL68lu&^+>cyFId_cDV48RitjKt;cRQ;A){ZE^If)@w^*8 zHa#dOd|yAJ(}*w$=%*_^WbO;9=g%0;proD6sdq3^GHMF27un7H7-^>{^rUoXRLmgG z2J5Z-gQvBRp3jRMtXzwT4K?Wmcfz-Y2gRbWeEZsSY-GzPG5bMfyrg&4Kw75ECbD>| z@2uS6`}U$1amQyYpC?ItEwZHp~DDz(X4(!tYuM{|Al2l3NH+mF8lfaw@|R2PN&Tw z|3+lSm<~>!k*g|P%?0Vb^TKg2`$D;VF?YF3ErS@I-xMCyEp7iQZVUXuYd9;B+nFvVHc^HRdwCYxHdH&yi8p z)UTn3ryMU+1)@)BjF|5Lwr|%(GusFG4`ccq19U8c*yQ_1G{U!SRaM1Y(6-UkazZw3 z^`u_msfr@}mqCpf2-{wNBunO(qDH6UXyw^ja6(h-cL#*&F;}iJFE%x(cBSAjlrPl= z+eMz2F4KE3TO4;Agfnut0p31-@yDA&M+VHkwf689WVRoap+u>J9L_lv+kPLT4;UrJ zX>~px{WOfin=3#KT9lWCMS6xUJ!k9|3}#&OJqZeFrtoPTz}fBdv02y0@ugde-|wb8 zI4)X_EGQExGz&Im7hk?CJa) z-s_$8TA4Zv9;UbpIE}5pNt!1*TtBog>U?mUm{(8fpQ56}r8mVvHxi1?LpkExsp!0Ltx;u)? z`ZC49lFk0gnzn zZvqqv9=vfdXC_8ji*qLpei^+$cn9o^e?)=b=&emDLw+>3_zIQ`lb3VIdMZOAKl*7g z?bb4})HqZmm3(*DiqA|cbrrD|2ZR3to1V1z^7sG^$u)HzayzBL(Rs?c6?DhB*YLMLGbFaI3w3NIwbTt~uuN-{BxxU+UnC2MWFgIl?CNv-wyXKq zpqd1x2o_%Z1#-nqve9FAzadO3d1+yB>auey#X2pi5V#nMD zWmKK4G4eO0+PpHoUR`_fa96<+a~juNzo4|supbr8VLQ(~dwx7BU)oWbh}6o<+v3v6#MA#ZvS-7xwgr3;iKDoMupL+>Eq_qHrC z)-b|hV#*knJ?bO3_R1KUEYs|;!@7{$gz2g3$C<{bE>3t~V5i#AgIRWc7f3y5Dww*D zXpf7mP}wrtBGffvg!sC7i9Qx?TkZ%vJ0&}8%*RCf?K->zh-G&XcSmMAUtb-O z?p~;izesb*c&c_wdt7{K-!UG(txM2x2YgqcjNXe*45Cm{#c$~&F3OOC4Hgw`F!f8? zO3QZ2-EN-c%MMWVP)NJti?-f~bjB$*klWJJ(&#>xL!z|4^tb~=Uhz>rh@kJ@vrQ72 zaT<*Xs$9qumZqg^!W|xlNnEH)038RhFtP28%-brlS~b_X0EY3UINnSqG0nMiXc8B@ z+EkH$@qBZ8H+LDI@J3y}CXjzMa1q9x@r!3mv$wzeVX;MxQl7NiS@PAwO^}3q6hCg- zF_p)uaA;wo$h=d(#<1hz9xl}yPsBoSvK|uif|tdays}4jP|BQNOCd+)=&o z4{54hbq8~Jx;1o59#Of4_Gt>4|(XDm!J z5lXRgp}}S5J)mGJPlu<*M3)@~{Cl9s)YFp~w1%!bVdr!$ld4j~^VTQxow)|Z;%69k zb(}L(9H>=+j+AT?))^{4bVPal#n7-erjdfU!SQ(X+xD?j4-1Tb#TLF|lik;HNYyc6ltyqc zPECz1&NC}%Lvc+znrgidKPGM{_;tO+0Uk)>Hp$Y>qQocEqh5aiIL%#e;$U1kDjK>mDWRr!K%>hM%xO)( zh=rcpr4KK6&h(V>iV2Awi&aS>nU{8FBKp(y)_@ftN=gLfmX@3Ex=9@BQ=X;lN8@Pd z7S>7(-ZfImAq~v;En75aU&sa-4s!ARpPBCi-}V^(u3Dn~t6Xpa}w zKN6dnBGp`zb_C@K|*noiWE7^3` z<2VDsvK90M^@#HCQI$H{M>qnqYtHNJvB$`AeSS3}dF0h$+Hh2}#AG^b8&hth>Ai=1 z(E~A=OFfi_Bx>~+s?RG1GU|)Ck1kanPJSP^uO2p+!ZULry6Qp|@*PW`nWsBrj}yH; z=n?tAM{aWDGm2zS(8+(R(JsLlzuv8>+$%@wcbeV*B(NSMbWkX#-=MCibET_BPqO;$ zkNuVg5;K?8%aeThvP_3mwf03gX^})B6NXydJm@g?EuMa6`NZcqeQ_fEhiJ-Y(MmU4 z>ytk;;$c9L_Z<+)&O80#{XjCXi$p2Xo1`;EcXOQY0!0YL+)`-3DB>YSFQK7kNuhE( z0^ik3?A`B$HNSN#tDlcu$01$&D@TQ_!-q`6NjiIOYa*mq;4xYc8 zn-XE$ILS+$#Kui{%1cC&aZtdL8~S5d+2`|@t`vqsvK6k^0V~nSQ$1AL=}*Qel7z{) zo5OuUcgc4&Kwi7z^Jrda14ArK1;Yz=@KIl1d{gpmlA6X^v`DGX$@k7Dz|_oJiv#gm zS~A0m%9nuPZDB1rAw9RBy+41rqka zS=l;j2LD5LoM5qkx15kbRMl$5wQ-zX?U>TOa-@~3v!1>x0n+DH%+B1VgR>~h54iH@ zHl=b=Ue643b%du3e9!XwU-z(-oS0X?u(Zxo{Pxy*>hpDTb}I8@s;?`!FW#;7^kE*2 z2Xd_*d1ovS?7y{dgd!AuhL>|Il3^%3p^)X`7&=Hgo#WJc_Apq}@xfdjUE8>75XGTz zg-k)X^?RmIODlJPF0$Dj5b&g>#W&LUEire*>K)L>2gRdorEeXrp)+n$-gC{+^OA>W zBKU1QIo6*FZmX!1U*EFN(6p_+VPAn-` z3k*2#+EG-FvV-=g=09(=u|BX8U=r+DS)jb8gHBtQlT_a12$RVdv2Z<_<@-{Vo!+b1 z9e^<`vtuZg(XsIQOo>2*V2eR^=$93C^uQ-NXhU{|dkfB{Z&huE!X)QTx7^pb2MHdu z+vv8z$nYc~b1HBn(o#g={tSl{fTx-oyu8lqZFWQ!#z*sl$D!woW`3h=kLJakCsO|S zq{rHk%Q|Uz@etps=S_Tzs%tE|Ag1N2r(>{`pm?|_Uv zQB#)Le23k%S6#g#m^;dv8Y)GZkSVqJ7y1RcQF2OZrtzxDKPw}qkGnQNN95K>4-r_I zOs|-FUvTjW`km-jLq!p;)aEmW;vO?YfvKx!CXwYaY}ro@Fo;1WB(fC3^G(%qb}k|^ zd!|8FcOrZT^k%C$OcP7fv)K5*Vs0RD&|K0Uy93JnQrYQK$SO5+<2YPhz0AHSq*_Yh zwJY0a%MJ6)8GUFDxent=AYc$N7 zllTkvbRl!l$~LPEdVU^T;2_LN}4tV(h(j2En}KCx{icUG5C@PuTV7vSTw< zrSO1%22H<)H@gn&wI6~zaFSj90Cw9Bjq#GwlSh2JPjLNlS-u;@#-89!lo#ar2{`)C zmTco}Up7q~zlca?CwMT25tg(6_40ep_AU13(d#F9D7&V1bGNq!CMj>IA}*n0TY56%tPp3AQ=W&B?*M(6`da+(zr2@V35er@BfxKJ3?p`gcJI!J)*z-S1*> zTt~-UDL7XS{kdJYtmYM%PrE-qIJux%duSZ_sHfYw@#N&%ZsfoqKh$5yD{mWd*@uG8 zjJ^tmwx*`aBXND{hYaTYo*#Z9*OMQ`Pbf+}gI&_x3_25+HL-hBo6l)5JlAP}a;MJv zVER07v4<~I9uI2VAS6SPt7%H z-%-Vn#Om@kapFaXt8d+H-+^Is4(sDlo$DHZbNWuc8xg&Y4mq>XuC@ zLp=5Q))6WEVN*QS`=R>(6vQ$y2@aehs;*$Twp!Jx;WF^*_>zY)i^g7zO8Y?(9y@mc z?pAejYKVdpQ-h&kF3}@p=ejbluAoES9oWf!P)xoz^j1cQ^0p!9=f~&5ud~DGfPVz& z-PnKP;|Ywr$;Wg)(?ZQDEWhN5CR{{gF7wm{9 z^F^q7I+dTs`CJ3n#rgFU%nS1M@nqFwM3UHspIvt6!3f1qt%n>!#IoKt+QEkvX6Us zN$oQC2TQm};bvB)i|P9imWroSFRu9ab> z7KZ1cZSsjpr{2w@f#*1mP9FhY{I@Gjo`&3PW_I)sl+e5ENgDdEzec3n9#SV=JZ!uIvH zD@9-(OF!79CQX~_U+GFp&rouP2s%&}lHC-PzFLju)G;||9+hX;I~I}@jO_%fRfbQZIlo zmP8pQa?}(PiS+RgLTgkmA$P*LmYK95vs|oqWiFUO6mY-(ysJKQjlOUA33r=qo49G% zblvW%(-d@CyjdXE4X9jm%m{e{0}{&_A@)=YZp);s74bw-jIk72zdmGs7vky4!07(Q z8Sun#BG-xzA+gYYrFM|RFg z;O^%F)l0R?Qora_^x1^N?m(*Z=G!rTq&6YL+km38!_r#eHQDalXUFmL{+8qG@jvU0 zURA#7qO0NHEI&cZ4LJ`x8EldjiDYL-t6-&!c%mv1ox<>OSLR4CMUe5p^wK&*^a>~nmJGoY%u49xPQfeUdfl)X4zL8>d=&kH6ms;ttF-qC!-a<6HFH`b#mC6`7FAHbDBKYmB$t{XEe-5h@F9*ixAR=)qCA=iqogzlGoiBvECG|R>axPeo zI@F1`HA^40tsjZ@^VYd#Vr~*jsxrN}tf<98=U!Jn+3Wp6jna-!Kh6xDrGxnGsT83d zJpI~qD?$NVI!{(5-eMsWlQ71aw1=FTyFGWg2z;EnOOKQE%C+_g@s`Kz7bGgZ<;FGz zl8zWE-F}efIONi8E7;my0}+iAiPIqMayj?FE8(J@8Xa{aZE!>T* zpJ!!PUH*Hc=5qPNAKsR2in^;+qsMOvZ`U{~zZ4f(`eW4binO}sY=#{;&9rF}z))w# z>|zV%r5-qRa(}cm4$Kw|a1kZ*+0R&72p9BPJolI_e@piG6Z-&@4H}QSEV49%(hB*Y ztPtZ?5Soos_IZ%8S?D`T-mICjsX(CQ^DbX+&rHpMeFs~_#>Vge7A1Al~3$|QPDBV6wq zS#!hupY`$n3vc10TbshdfCGpv5zr& zw$HF8AI~P*y(1$S%6#zRBK1_yj#Whg3s{Yxc`g_r=yaf<97jFTOx)%9D$r}J3XfJq zB27c?V0nH}HoiR&^}sQQh|su3skKSVK}~^KWcLDNla#fW5c_Fg@^N47`0Ox&6&& z2|@^uXGHP#vMt97PU^-x2nSdDqkLQDX-Z}6IF6rUp4OJLXPgENm#)SsV|Yh*5M!J` z`zppU`lB`|UG9M9B7tbAzjRf~_qG;%7ODto#MvvtHR{({?pC_YDmdXSTSS|#hFmk{d)t#l`EJCL z90n+AA~WL%FI>UP>{UkZ@oPL>n4Yny%TTM0ny0vSm3#3_d%t)kvL&oiAb*ncD%?T3 z7n5C=dBw6i?UK>$bA?QIR}1`i`f|I6sq5Ki$%hYPG7`lu%wRuMr-Jx*+EhMxdH#(3 z7TK=Wnp@{Y<41hn)+()-F#|1QS5s_BXY}Q(>?wIQ@uf|W`Am;zj_?-$$ivp#NxyE` zgQ~u|PbPM~HSlNn94tuUxUBvi`V$m^G&~L?zq1%Ep`EAIKF|S9Z(WSV$QY#jKHX;i z$))|HKZy{N9Y{aDT8Q)hXB70^acsk)TwrzV57K z^7q5NbWIpXL{UUW`>p22QqGX3bkIb!HW80fcmn@zzR%JJ`3Fspzm>DtXQ-r7+u*S0 ztW)wnNS&L>Ie&Oq!YtAn2pcPZ-0)>|m!kg78nx!di*H0j!x@9sYpJ}$U+Q0x9J=U? z+w{%x(@U$qDspT#$CXw58ceOyZt!4m{Y=`6 z#K+?78yR`@y@TCFE-j7SmG4mAuBTGzk{ncSME91xOTG#}f1w<0ZjHyjh~|-ZgnQL@ zF@D58r#@H8-$95dt8K$e?WZ1@h7=21MpvMS94^KuKbS1mfBHD)8)Z3^&TU+iUclON zIer4w{XE(dw$Biy$cGw3bZJ&)ghP9le3a9#{OievOr^>_jA? zA~y^2O|k4*=p?K2WL&c{U?R}21YIOhevlF~LGd)Km4qKEY&F;l0 z)bz~psyIujfP>zml_+H+Gwod~{WoW{Wyr@|@mc~lLn*e(Qg~{d|NQ8VmCo4JsJ-$- zt*hgE>{dKQ}9x62ILZ&Wr z%tKYaa-7TPkAD^l7hyF(Uy8l5UYjzumajPdWitb5`^%0mLRprZWA!gqDu(JsZC>=T z7QL~i`l!K4{kJ{X((LVM2XgtdGFBD{m6X`6;l$C#Y^pn0H#zbRZ#=BuVV3ch3m5yVY=3@JSrZ46R;-`!I6{$me*Q~*2U6q5XEt9GLK zMO29*;iz2#xDma>7o4iW+6Krp@rMDXk2728R5uan!I|aLfBohAA7921!_Wc$Un}Jo zBp%V1=OW$ejo>#( z&p3$OjsG83LJS|X{7BOf7S+7rXG0p&T|?hkRKnO3PtqcUlzHo(jg0TVm8J14oDh~w+H*s%XG+-Tg7!k?I*jer z*-p=`1_~ixl67wH24N?b@5#3i$jUS2)uQP%d`YqoL{^lu9D~sMGS812I0`6Eq5e!RUAs`ntK9% zyg;D+$uGStt(g{yjO_ze|6(^rQT?EE2?y#}T-zCowpkF<(FEZK!!V>$VBN z`iY}NFrJmhZ|&Qll0;e;KI1S2giM^xz{0=?)xXohaU~Htw*Sy!o;pO5l6Eaf; z)1HzrRJK+M^2_hc_^8Hjl#?|c>7Gpc3ytK)op|tNS%xybc@1^*J(>ziPuT8}W?61) zRWFDWqF`QOD~QE^7nl$yMmSSQ97-D!mGFyO`C{=7I2#?)oNGy0BUpj1L&>UEHY`)q5pV22A)pB)nB0O#q7w>G~M2vUb$=v4Rs$XNQ@nAC|y)xB~{F zNklatwePsAU_`@H-k!b1Beje8pdoO;1e7wfFe)UXTR+BlE*auxyyP2}Fe{dEf*rK* zILnMt5t|K5TK3UvF7At#jn}urm6dgh@_pBxRBW816mOALSh@E(l>NNLtEY01kl^XM zKT^um#Jq8BM~hquOW<5M+Vi;sJ_g5Cy*M(uMea6!wIt2j6$e?9VwW|2$X1^4o=CQH zo?}PB@$d~66ZP{Ifv*EpyEL0~9W{1A-Xt3ls(G(%+}I9hB}YEVj_8C0xr1spwl3EQGi4UBF9tEDYO-IX`|bZ) zicEg_D?_Vg+{t4BOOVm&CM$3@mF{_0GT|-4jnB@rSN~xrks=ckg%>9Ztt-i)?l>+P zmNlz+2Dv?J8O^P=Y)Z_GSVjud?7@nM5qAD3QI4agvGALCL zY0dM@ZzP)rZk~1WU#eB7MF5Nh0tIuB%cBAPn%6z*gBxZ^W)qPLI`z?6{%>+f!?Kqs zUuX{_!Y1D`PjXrXQPC06qId0R7xV8KaT|vBTT6@H()<*`I9}oY(LwEit^ISaJ-uyBwwF|8nUVYdczQVaO1Jc;bB4sTVJ})WolC1ghQlc-l@dRl*q3n@SMPs z$ddB8o)ebQj^4)%g5n?_wv^i$J=yUzVV%O%JJ(Ii?PC9@1LW{e+>J#2Fz@ ze-5L8tfCseBSGSNQLvl5e3Gjzjweg05;iDKFxBq%tKqm@ex!1<@&n6c=Yp_iqX|Sv zx$s(=zhI!x;%dKSLWFSe0l-h{USOcPk7`4J|JttdT z>Jm+j(}4wZ)3!B-CUz0xcU?$+d_li5Zkr@b1BZ$Y^)ni1sFip0+VTuOq_8&Vz3Zm1 z+mLX)0+u|F&pHgSX24U74bkV2-0)lR3h=zqExvCuJ4>hAj9!wK&JP{;NBXct2Ievs zDgpf(q>Mc9Pr=wkl;k9=eCnIF2}$jhXOd)!`PWCV*n*A^&*S@bM)d25h%P4@Z2YG# z2wmDRCDg{IgBzq3i#ltP*^)GYwWszPH|UB~@JIM_84}bA#{QccxA-Or&|12o zAYWVYG)D`O)Ys^oZMQS(UOk`-`%z?{LvIa7@|$XiZZa09>@oa930i6hIHUQ2$UDaf^?DA4xhhr-9V zVzsD*vR9uFosrh<>eFdhGq*~o*CxLyl`(J`wYHS^Z{nGT62X&&zS@%a)kfJS6DkmO z_*G^sNVsYNdzu!QxSc9AG;`dbd-*F;?s6q{O;BoSXLi6<*M7x_K}w6IA3(}F+cl(p zZBH}i-dIL!@L}*u@_7F*-;Q(LASYs#lN=?+!@x`+SVwXP`(uervY0 z8dTr({NxUB5B!)?V5sQD(c5KxRY=A$bQT1zbV^lt-Z$moz!_LdKj@A63OnlXP|tTz zVwmtbRu)%*?is9;%f${|R|%Az!rhN*B-L>vSsV zd=h?~cHL?-%S2RpslsED+4iTZ0g%;O+DolFAk_bnQ&3LcWab!EJn6`rSwf}h%aiNk ztcgYrlftLvoVH)s)|ORXy>2OWD3X27(2Xw&03k07+1ve!ShaXfLeA!jIQQI61JOo) z&JM&<*D-eE3Tqz{BG&6rVvFMeY*T0ul~_tv>3Bh_y%oHhij5nmTVBQwgX&&Z1~#o} z4x}jN4h6D;r}>X}RfHI7wV5k>;`jzfIz;SSj^^%w1-LB3hNH#+5cVf};vNTrJ!A-H*;@fvj7wDJphi<#v_)|Od(5eJktMrn_} z9?c3U3rI^T|CaUylvYZ`LrRdDaR8ne+e1ww(d3G}9c>%5--WLpxzK3k;{f0IV0Q%B zaH8KOEqJ`(qnHY;Ob+253}9V|Em)HNL8q%L>y`%TImuVReYe2DN63dDjn4Jip!sw) zEf61hc~9(S4QVHe{xg#I$jhN%$dVMhrbqgd`Dz{P256Y?DTS0_ahzeqY#pigI!tvy z7MYxNmCTksq7BjN+Z|x8!ToIpzr8He!WmdW!aJ$0(`H#sN~4s@II-8>-=+&kabfqg zmlYuc57wDXu9m->w)hc)#Je14+(-4)+&=ybFA3;{f6saLb#zY=v&V(WDrTV(7L9ar z>)zg7%9q z-~%f4tLi&oSpWLb#djG4Z;7ge?r&xewO#u)K}TDLEbr-4M;-*6Ts+$5E%Oa8oDEG+ zt6?4y&Hln4{Lj;#g@(O{a;M%Hk6;4Pi?C%|yA=5sBogd3VpDz@w&pH*l``uq#cbQk zuC@jx@UDW~1Rsz!moz-grZC-9r&|{*&vJx0$ylX=;1n}fLxg)%$zkVc6LOx zhjX+!*q8Ck;4RyL9~D88)^PV^2uJ@WNB1I}5R$~AJjb-b zK6?VTqb^J>(hgamDltQ7A>bQ0VNUAcb#f>}y&p zLU;~tsN}6+InQW2za=6}oqr`K?iKzy($}T% zk(|NEr_mC3bn4yXP5*)mQw0J`vraj|c<=RfbYCVa*}L6Ckga>Ax%2eQGxLWJ*_$o#JwW#_Fb1d?JpD_Hg)WX;3Ki zW>s}*r>b$3IZqo0tAXgXCkgT7S(rI9wW$s`r!mrARRtEvfRmby$dBR^YVh9;8t?FF zZ`!j>&M+}=xoniAC<}}=L&X*+?6lYf^y{d~=>oJWo4RWl4=IYWvdmXR z$3kxNO^n}CBPUCjiXZGO5vDKk#1bbG_H=Uc!)dm+`E1m$X}e!xm-ewq|a?< ze}bF44hPXJ^IRf^*-cCiyz2Rnn3W$gm#S6SMkyZpAH7BuH_0 zDDLhOD5X#=#f!T;#hv2r?(Xgo();xN&Kc)B=gPQ0V8F;uvXUp+d#<_WnrpzrgtPH+ z?j?XN^qPJWS|9sA{QCU|6b)=H)1{269^+9pJ$j^J^fW#rh9q>BEoqMNarTRl8)Joz z`C|3Y7DZXHMdpAcf$jgBfBV~^f|`R%8uR3$C%kpj_Ahp+M|@0M1>X@@rQII^viU?< z_sTi9<;p)=gxl8$2+4nH5dukQ|928@`oAF>6wbi|?%ZPsT-jhFK_5v3OZw4?7T@DZ zBxs>^ks&RoaGgcPIgAkyC3g)@7~MnJ6$1ExOR=u z@|@3!j|E4ZF7u6$BrGtv)gL>hBg5+N zR7iIK{S%*KU~N$Hs-yPg{gk^`bd}{NT0js$8YTFPp z{&PrPdN#P}CsqOB4siTl74otM%W0$rYzri+3Zr_b*70nI>wTGUbh8Q3xHvixlT@`| zaXB#54XD^4NT&S5)0l7^sULk@M(c$bT-y z)bk*bXy-~D|NH0JMZe^3vM=ZMvd|P|bSDynhwjtNL(DJ{EDr%#n|j7#gVx-D1Dj1n zhHHC|h#vC^)7App)7*rMnIbkoKcdT{p<6GxI!GO*5Gp9z7QLcp@xm$plj-8aXH#U? zu^F0HaDRj4$b>aTMR{$F?Cf`>D+-!=_q{9jB@y8WgKkw5dWExB>u0PY2-~`gJq^__PUrBGn;^ZCOzqxVoB|?S1rJt*uFI0N)e17`gpDX$T zz$vC*6Ga%Lj^$qt@EcsU6|g#tP8mLD|FTdCF{QXudQ1gh1LE9Y(sZ*_R?%YUvBTKJ zDs_Msz6XgNsjK-JK?L23sr)}nq;#CNTDF4QKhz8Q5fqgByikllv1vPQqs0Ch5`8#^ z)%f>uq;zNoymS)SZPD7-z$Nk#d~dVk_6PUfZ1e&g@pYhH0WFdZ=f2y?D8zV9sOf8y z4t1YQGYfOId)OU~Mt8iS{O-VkI7%DOHvA!h%_&8$7H8lT_zwH$MCYrW4B(N%U&*yo z)|WXSIt|Jf*} zpu5P_=>x0?%R6O2@ zF%)5Fm9Htn=)Cl>fpofIOw-b%zA6@z|JT&6$|+v-vU}7snCUHUf5w8jDajK-hv(^R5>_syoW~7}1Ev1w#Bfjz~JI95g zf`NAzOh@9A#<<}oRA|RCMil1-EmNf%NiV<)k95EVs5bW=sNX!~!E?<^_Rf`ToblSb z1_zG)0j*n_)lYdh<-`_1kCVQDb*nR^>70V-BCm(+i1*^s0_T7w7JVMYaZjoi4EQ5m zlA#;bMU#pU@Q-@$!Fm=>g-+@O43>fhWbo~gQ_I_i){03NK|TgtS51L4!a8IF+qR8J z-4e%}phG=@il6rJiCz{V{Q)WU z@JYd$aq>PvEn6RA-IaFEnKHj}*G9-E3 z8%(GPhBPa@JF2ckYfq2vm1*9OQR;nFaXqSBg}QWuUrpRkM@{McPCMS`Nd%ybsSAKL z6G8Mf8TK_bPSQi+`9pV@lZUf}#r%hQ#RbgX^|-lD+UG6POM8(iRDCO4Eo!(0bur!0@;ZWHEa+t=AuZP<#3Z6zu%y zx!9LCR3CrRy4p__cv<#%o5da;EXmK@tv7{e^c8sBXJvjfQDT4G z&cByvTIs$XYcKgAG4Qa3)sIc@>03QP6UM<^i%ptkYizPezH;$8Y=g9V=SCezS4T>q zhh5T*t%Pmr^J-?bP}viUzF`(odD*iUh!jhvqj`##lzw|rA8uzvvTwUgB8?`EG%6jo z^OoQcyAu0LbzC;i_rLgeg7O5%4*T0 zE>u<}&u&N+m*kP^x&+GERqy`4c``xTY(ZM&9oXAHpx%Wd=u8I`;J|2r3a5oGLl|NQrjr`SW+d zujS~EJNtDC54)S{J}gQ((DD!iS=p%i{iCd!{W=>d)Qb-2^K}EXkot^-O6)@W$52O4 z?43_xsBYHYN#$9yZl$}qu`oU**`u$P@@mCYA-W4_>ovJcL+&>oD{o)p5A{0 z(_Z3E@h|m0q#q&gO-^}r&QpCO=hzEW98Y>4E1z`2J-DI;$k2<$^}xX!Mo2WW1rrD@hUv~)YeqPAX z^&g?ettVAL8>&K{T@w&F^j-n|ts3|YZZs%Q+R0MbdYMBb!!{>enT6I7D)a@6T;b`b z{5}?qyMaWuhVF>n_O(3<(P;i+;|P1cw9(IXt;q8jt*;hr+a;Yom@VY(i+je$6TQfJ zc^{_oroktf8)xW6@vGhr3wl3ewX>1|EE!uzdCWXTm6qV9Ci&0GfOm!C4*nc1B(__=mUEwroYo^wc`;j zRz&WD`Ha6>Q&6PxO?U$kXD88DB~=Uci3;Xb+djR?kUqwwWv(W$-^R2GgJOPT2Ox&*%h#Y!y%B8e1|lqcpSBVPJq(7 zudVOcViTr#H_3qW1A{(JAo@V~JGibjmNMmsOx$4{@w1pX;#%U#z@U8iewAVt-D066 z&rT{GLdWP97lE6Z62z|)#fY9`(~*o-O=kkUG?j4NUt1!eRZM$e5p+?$KSmjSelxgZ zBt8-r-z-xPZE8(XQPJlUR>1=qxB^WV^x(Vgv{;UxGO-oC!f{5CeI$NxyE%w2> z?W%3v&*+v_%n+JoTOZ}xg|xq;t4a_BtqAThKd-_84W#4|PmqgK%l2at_^19(K1-K) zkNXmRm{#gMU~8MSG)IK738odEAUT0*ty`RJaQ}r?D*Svgj=khM zcz}7lhxi_LmSOUYXT^ST>|(@a6RP$7mC&S0=EeZ#GoE4S{bfbwQ-$7oO`vXgD*p$h zqvYWFHb%LA;p4hSWRC=BVm~5ep{m!>QN;%A-=$ZInsGqmVh`l%1WK<%w6cnar>C)Y zU0XgDT=wP0E`42!9kfwaz*jm9?}^Hb@IAZAXUtJ)2n&c#1zqK16#(uDVC*}VTa{}! z<)uaOr=3HT)?L8{s3M1gvM$5yd9qnw*aNk`FC{tHD8{)kFGeSpAZMuYPr{E@mb2d| zIGnp(6{^*gH}RTKMtO`F*fR`3(f7-O8=JwvWhVOPDncvTA4jHP|NQ>Nf$?25Hc-cV z#eFBe@QdVxCR(;pZ`Pq5oGj8AF5JV@>07hE0E`U?dmlg zdcQti!S@6@5%&le^s0b|v=W-xHN?(=CQ-EAKeDQyY0LV3E7OQ!HJA(f)1Q<(xLk zpIXMQMDlb+*&Y~T#jI-__NE){>k@ye>`QP%ViOc{f?U0xD$IH7G$_d;oTyFGKEFNA&?6JOa&_lol=hm35oRZhCc&hLW?rkSu z9&tkpzLyU5SlAl~PW&&-Z+MRlO+kF$2(O5tT2p77VK!NVXSt*T;8i|ELaDMy?B}VH z!8C^?BVPfifSRh{d|#Tp{7UB7ZmKnOMIZ1$1K;hYrHEfkLhEQBh=Dht#Fbbp>aGGP z*NMRo$hugGj)Z7SW(j@ANEe;LYS7`~7LQS6$Il_(XrD{IL@I6CSuVsH|CCVFl_~qd zT5Z+?-&K-V;H*pgA`{qPzTZvB@T}H-&pz+=?oqzN6qmo21n>NW5AiavzaE9A;KMKF zhhai2cl&86kbiEyn9pIY{yB04}_yc2ve1?JmsBC}7-O|amob7lMd>BgbGH1yE*59p%LqLIds##!q6 zCv>OK*V!kR>|asxL+>`LT0hqU@yJL7kp1_YKOCz4y{q{HUh6-B7DsoHW)X+%tBKKf zI)yn?=U8NFZ#s}4nas<1s`}_n8I{M$xXkZzljP-(Q0&Q@r@K~}kA0LH7L;JnT~EM} z81p(}1ulgOeD~qgKhfIF0({X<)Y$buVT9l=3X42bf$#lT`mIuyoS+;q#Q(40EmG(4RWmn(xl)N&<`4XQvvMTmFt6Bp=!667e zfe!tzuRX{PCF#pOf-ZO#mG@j*YVCxC?RhG1K4~qXQ>IGDPflJv+XLhjM4b(fr2#g? zwI8KO)#ixVn0K5G8BFV2-&iK9MLL+c_*mProcEbW=I){Mps?h+To1~u?$>)Y;9(m06BwGSc2`gCg5NXFAxTYBEG@~kI+{&iJW4My_qx1 z#F2oVn%H0lM=|S#=2PFB1Ff`|8x-yLVZCUOuf(K9QG5s&ci#HRt>~5>j3RD1n`WiM znGxl_s}-E(gWM%MHPCw+ySN;uWS7l*H52)@1FFgD0exlD1qOX4r%9 zx&SI#sgHkYZ=e;*F2=)qMYg8Pc`Em+iBqVDJ`a=J`J}#kOi2o5OsMa3B+*z*z^8X# zL{P}2S1qy@8@xzrJ9-HXnv%mPDl;E8co8nM(`G^Qb5)^6pV_dMQSH5URyec8y>8td zl@$fFCU)`{*zK-*ZOVLmFhA((8d38I^V~-(EVu_!P8wCF4sS27-9BlfxD=X#6=F1_ z>L)2{e437aJO>Bytlm2xXy1F+ysZyX2o#k?qeox+k(wSd{2@7e!%Jvcy#H00N{P$L z;1q6kLZKCxr;bNM{7$!+)d1P=GVMX?FT5%*Nkl_Vio|-BTwNZr$&dPeK*H8-)(g+AnB0V%wsM3X{x) zax#7F_^m(x)~TDBLSxf$uMUrAge=^~LLKO(|5V+mhcd?a^RjoyV<%KV+r(q7bKE(L zYHI2?CB*V2s@yZr=r9LeAlF=wA1$__d^l~(Us2#q$3{O(gNJLC0dmSc`BQFq_`Uk0 zE8<(i2D7(vAyB?@MZ}x{Ompu_4s^zD*Bp6QWIQg?Q|Z6i3ZVX*Hy8>Ha^i*^&4cbi zzkILUNoJY+40VI9sS#ER16@b?Y^!pY!+GJIP3`R>dGdvSJ3^v1%1y-cEcfO+c6J$w#S(&AB*pBX{Db@}TnZ4e1 z-xY5l$ahK-fr=`Q!Urd^@sGxqd4!b7q?5eQ!+Oex1l{oBe)nAPw-(F`eTh?$4n&-_ z-z(#iWI0f7L?=FTi;VW;CCpfEtG9EsrNd7kxW~jk_=GDVB~H0H;npBrV%m2uXi@R< z3GZg|q_utaP2ProWb|Spr?uV*9racFrh}L4#uczXSA6FgSv((?+ zsCe#sxP_D%Lvfb-P)d`CC5pq;)30xa+z_ukv^%DwbO*;}-Z5(~(4d@x>Ce3i-mZIO z6IVqHqSjLa1+{B0BIDYM+OPEMJX4;Y&yUKol^_WL-cwXG6=t4LcVB0Te%viT-V?>j zd?owVSbodYLUh62zEUO~nEcWf&o5D8Sxf3SO=LQguf>=>iGII1vHQ4eG$OTGIo)RRaXG+g=VNB`A zvzb~=eTg_nxS&`H^f^8uB)HCtC0o)55ISyD9RqD-pTUzJ-UE3+_I_|T$>yggEZjyx ztbAQ|qkf);dx*1DH@m6R7l*vf({~_!La0VGlUE}CHhkO|y9FX|>7lw;<*Pz@$m@84 zj*;0xV5acVPehRJ7vG!UZ>TSZu|+~`%AcW7B1!IxQ|^P^{Df{%LztKqy_z~R#YR^2 z2UTA36`N>IzU=wpWftJ`!+t$?UWotA?*yAviZ*j8$=qU?j&r9m?2Ml zhU@$5cFK_9bWw%h4Jff&BT^h+Fyr>|w6zBt7#)ayVj=sGe|qU(vaM>+Uzz;sWXN(F z|C>BM$OwhP;h4d->8?mBwVKAA8X#Jv($(-oOgdR5u$MpgoRR^&250|ms_e|Z-)S)F zI-mf3KK-R>>>IgG)m&uSbm{IbU$OLu^WPeeQiXWXk9XBY0dud-;jG{s*U!Gs>}X4;EK`lq_ZmQ@+co$!YRk|@OsYX$D+IquuV-*Sz>ic!EN05lKPV$riJWFv@xt(?`63KOl71(D^;sV+Hgy7cgGX2U7SE57_w9$YuVP z$p!O{h`7^E*S);#4LGnWZB6*hHFn`BZ_k3}RNKMs?Zg(Lcr#dA zooqZ)h;iavI7k6}z5NHY24TR+@TSO1VW)V;$}IzXxP|62WaACh1~aW{TLncJ5f8mn z(ddh=*z%0HVu4e=X)fVpfuneiE7~lEW;^4?0up0%@iHqxAP0Ry3cHm8NSN(_8DOxF3Czzw^ z`_f82g7!xXme;fdF3$=VbZF*X4ZlrML@sdJY)L4wL+QtK*{LV93=`epo@Eb1e?S>; zt5u!Xg3&Hr5iXX|%>3_P*tfo_vXNLnke}uVys%}IXL}MQA%cSS$V&=Wcl317A&uQY zKeDSv6A-oXdVY6kldM&bByfr~HWRk9Twc;Y!+2T$jV4M_WhZBV?^$cEd;jd-eQagP z{AWl_{155K3%YB;hLHGmm!&Ep?ADq%^Kp++M#Z?h zSDr;Tx+CPbzUl58l4|Xw4sc(IvhA9BxFM}+ zCVxaa+;F@%%WL)wCRVorP7sYS%A3m80zzGM<;=V3<3At>Tx)7y7evI3>+pcl3A)irs8Cu>cCPgIoA$5xBTbe~)fwm+L zzZ&Rz~wXxdo0?raD~&xQe>pkX|wbo()HDNpqs%-`Jh^qZ-X3IF}~X zSs@O{9qix2yQfj>imen?jrxZyRGl}oBkhCJ%T7#cY8^G7sluK-I$Y-GkeNJ1 zmr+xd^3vq(GFSL@Mpd-8=7JZa6SzQW`uc**Fye9qWp>CmJ|0JGwC4jdu{EnO;U5sO zx_lMs;`j!hbo91Tbo1B!B2GN3xcOoo0CJ{e+R)+lPl9ump+{D6?+quByF zKB<=NW?ZZob;aTTmy5#t9?y-d=~LaV1rjw`-cktW!s*I)z3QBe0^9eeskzsIaf)Qi zdKr$~WCNT-?%eH(Bqu?KC(N%(O%jkRF3?m3CqZ7$=@|36H~yFP-V216yEzDi4D0>t z@kRpbko7rg|EcvzQ3jTe*rGZo@OP;sJ#csEraB-l-?g#XsH%=Y!?#w<7tnH*LmS4{9$tR`7uhajXzJIyrHOfcv$vp@@PY zAN1;=GRl(XscUjd?~mg|HSqF0__?w1hu*pUSu&9>p+&@&j0>+o@(o8XI%|e)wi$1U z>Y&e9_V!wY1fDP%jAJgC9+x!RSLO0^*SY(maJHMl?h_tf>TqkY>nhr@IHfVr;j_W9 zx;Q~$I*WlLUy!ApDY$@T)ZRWqQn2v^LNT6YDqvKwAxI}HX!|BSDAi#v)#4$3(%0pA zbe&WCzM#b{X~21QS^f%B)TFP()=t>{l&<5N&863#8+H^vMVe(f-vjAVIA+McYNV#T zg32p7raVVW$_+b;UXGt)_p!;my%v#D*S%%ti}ep37sXo>#om`OnhVAGZVbU~?;b6e zr;dy6)TRm_AbFxm*g-0-k_9b3Npo(53H zys89_=^K8MN21N6%-Za-1CLwqT@<^6ZoZumgYdtkGJU3Tcoyl;^_a5qtbqdNHDJMB zDTL(i&{NsF3bBt+Ny5`G6h`@B&o>d}O3Z63Ckdd{&xt#m{F1{w?YVare_=QwE**U# zwo!;u^Urt&^H{W5c6FYsoZgMdyGaq;iz=rhnF?@2Yb-iH@>bog{mV`NK7mBnwZ8~k zF@5d=Bwvtct$z&bkFhiCUmR31Z20s;$WF`M$a&NGOHv5_>=|Mvfh#Q$3CIB#ISZLOV0kggnL@KKnCWRF_$p$R19FdizT zaO2S@(Ak64nj-!>pMA@3AlYj&5CS}nLiaP1USeLd^uk{a?;Yn(ZqXTFT;v1>wj-N# zzj||&t&rRbHV$OoAxYM)M#Br@K~I%HsGjFSRacXO3+X8{Y^&co{mvF@EZQfIP`8PD zY6Tkrklh4C}%?g(RR6!duU2Mx2q31 z%nfhtoE)62-&`0+J#%>Gu7(strPM^_I&r6SUiJcl+wy*5qfXUb%YabBUSvdnyxHBHPhl?? zsO+y~=rMeLs|^g&K~l4SjheDlwBSr4Y^kM!FG%u@*pu}@Pwnmgi^UNti{FY?`D@vG z{f%nBC$Z&eRdwYd)n4f0B~@&no^8?k;XrH|^g`zK&VLEc=HNTSc&lSXoQT6h_KVTg z2vO91@S3x_qaY|xHH^s^)hX5)SSl?sd%-R&!%c3-VDOF>;&t=IJ1Yp7!#mfj><>u$ zeuj#WN2)zVH8T&7!{+W4bc7ZVKKZMbeHJ!+9>Tr^!gDQLyl?^?O*g(8FhW+u$hjTv zJ_MEP(S4EQS(*ikQ3t=nF3Dn@e7UNuQl3ju0ByC_zl|yKd-TU^oUOWA$B%4(oKYI2 zm3fY9bxHOyYgTEuUBmNpGJkQDJMv`Zuz0dX%dLXalp#X7A#{Rbj#`&xHtR2#4;)^V z3?Fi3j8+T7sVwLdIp^(86~! zGv1J;;3|H4elrs}r!B=X2vVg)@=O!aNPLrP8^<61as6quE7B$%i1h#xZshO0!n-bN zKS%+g_`#R#TlGLf+ReZ~Ay_QSKpyv*cNlUzt>}0iClSG_a{Q1Y%k++5PnscfhgMNW zN*K=wNH%Y7^iPXaRlytZM{s(PS+z4x+}AfYX&kONtVNt^y#@eK)Xji{zaV&Nmd3WK2wTEl)L?u*?f@nqtUO2^HDx zURHeCQgf-19%5Lh8OC>tAGTBDL-SEvQtM6pzz0ICLpGY@4HBONpn3W(?{}1kFYP!P zB6a;y1N%T<1}ktnmOv3H&fkV&5;;dIA4^#K4tz{Qw6eNS0IrtTqJVNR;gcRcjktTsu zqOmTR*cAl~NvE7Q^Bk~W6?aF&E4SEor*MYs(gr8xkSJa=RCJ#5^f7TwYTM>KsKws6 zb`Wh(Ebj)z%%u8HXtsvl9}uqk%i49cGQ(1tdHeS+mo%TIWn$*FIcVW`40QYcZFGi*K(;sP6@( zyZL{LK6MxidUu1Tp#!Pbsa$#;oN>4`Jy;uIo|D-y{Et}ouVDB8@`KFM+3>|ei{xlC z5?u}WPE4gn$b)>?tp=MIa@t;Xp9F-g2~eCpTlh4dRWZ2{C;uxvQVI>#5i0>D?6V&SR_q3x*s^Bj<`jC? zaKf=!50k5vnZb6f$d3*BIJ-FmY^xYxF`(AM-Fox;59myFPD3~6>MOp&7xF|l^5cUq zABI5g*Z>Q*X+8x$XjF#31{#NK0d<0I&^dq_VYh{x^7qGpKJ_W~ZIN@?{UJCq9XmZf zhl%_$=f6#A!2T~ISB@t=`><_GU_+fT08U*tZK+O#nMA za#Y*(-jV2b1KRmql&$^=_HeY@FfRd#oJEr-c7KcktB!pK&%L6M6^e(gRMTIuX|^wECyA~|&)s#_ z@}%C;s7~0OJFsTrKn@u{*vrEP-X+dT7>Zov-!qLRxVXbcG&_1nF^v6YacS9!kBD!HH?$?PNpf9Y_0AX-RgzN4HaKcCU`b z1>GFQD%3)x0~^65iNBHjqy z*p5FSS1xcyf%Fmi=3$bMM+1~gbEUx54Bp3i$yD9I^p%yp=-qdP0zwo6O!X00QRnM| z$DME}JL*+gCXL#IK;hSKv%(Y=U0xo;As924LU!+G=B4g@v&buJf&=i1(ID@N4U8^} zF?hk1-in+7pqkpO;eb(|hu=-zg8B*;nHF}(3xF@%2ZL3Z=T+JpZH{|`rdpjPt@2bB zeTO^s0Ex^btBgIvipb8~H6q6(-QB`O-F3@1FLlKnD`~-^i@q+lNou2)6AcY?`>wC{ zU!rYM*)IfOWu}=J*_n_oxc|PdRr1X(p5b2aW8Rp3^N~r%AaG;*lKNLl*2(NRete@- zmIM|z#WUs6fJjwS-qv8x=k2Gt8I_`DbiXSGjjx4bTW1t^DyNjw1Z)G9h$FhbzcQA9 z5UQcPI?_4ur?gVe-(%l#$?nXRSEX){-nv45jNi~E8fkpG?|}ntUbt5~o#OeaGFCw1 zgA~H18HW@X!Zrk=rnBJ9!9`}z^V8MXXC)O28MuFI=FcqK^Ua3a=l0iYXqz1URuH@f zd^8RD^2^SnM1!>_)=}3tT%F|eAXRoWUjuFNl95_~%vX-|rtljIy*!{(RI?_oc#MX| z*y62Tz;Y7;ifhRZ44z)sYgY#s6mbbLHiWk|izNzeNlcTCPU~w1xN^H&K+ zUjC*9cdJHQhum$Cs6DX zOOn&t4Z?eqmAjWhBP|^vOG9Wns48?Nk(s{WcUfZZa<^dI9& z-|ikt&z2ecdI2=CEC3c&Z(sy>8%oIE(JUJ}Z-*uv?q7 zQCpw8dB4wJa4B?IJ{zlPRj(0(6@AVG*s6{@0eav6^W+?eK%X5-^rr=*aG4LDAa+?P zMcqQd;y!xR@E_ll7mXr?3AqsDaD!v}YW`~_kP7tijF>?|GgVjYTRgb-o^ zpArD@j&o8=7V|n%##%Mq88cAgi4spS;Edxf_y;6h1nmVp(``gh)Ta9|(Qs%d>GO9% zyMPw<>hL`N}U-{|hwqXan27tfy@s3g5V zzag{*+ows(c>@&}XQiHA{_nk%#9j(g%lN=h)w4V|W74D9FxK!i(T|T)_sag4lw>6w zY$hnty;pf9eK#IrwnbN&F%={Pesb8&ghIK2_VG;dSNGvP!@e<9jo*K7RZPdzOb0Jg z4diCNzYBK+zw(fIa=deiH*;c}^c}f2N2O)ri1S67wZG|HN@JsGX;`wB^#Go%NO|DMHf!E3!VTCVtRa~|)xbPTR>p9rb|0Lv{L z1;xckDyp1m65U8+qqZBly=z3z*`GmpPmbh!ukdhE@+czE@@z=IByKl8%Uln_;Yx)_ zyHk)rb`*YqdO@$`-)lrk$UBk3;Mg`jIg=-kFv6W#5&4 z5vVav3(gj3SdI9QXcm{Ygj*Qee?(-DC3u%98zGQA2f)kR7PNMX=z~uHG5N)>FpC~^ z=&&c2T>NsYo=qTC9L4WLWS96>`bcjT+NdKg^6b5`&1~#|qe+|iWfv`lAb>&9M*XC} z$SYZ3I>1)7@Hzd@7rjy0!ZtYHQBXuG6f*b?rbiFUvc!@?dg&mE9q~-FyAdi;p3(9n zz@1gs6?QT5N9248wmHb!nrUI2LCos!{EkC~vd8-!h%Vq9oeI6h`xvkKvJ*abcS)d; zKrA`8PzQzuefQ6?k(=4|uOfZq&vO7QN*2!cjYg8GrRDYOt-2_);UI$Ub@@$m@Bt0wWf)Y8-FG|$3#8O({P0AQUCmd{?J4OJxI1YZ zN0Cn-gZXJ6Dl8I8RdU~b+V%$|n(_w}nDfq;SZ&Conq+fCFQf_w*y7ShH{sgvt!6hs z@W`D!;CpzWhJ_{a4xu{j9hr zU>aKMnmW2lO>cL$g_GsVqN%mraqXssf)r6vx_!SR8fwVo+wB}csVWQTBg$?ST!tVB z-z3DH{%J-7EE7kiv9)fuYGJFPO5K_vfZj@$P0}#%V-$~B7I4d zU}92Gx7R6y=kPMRkxhpKFzve5T0L4XI*-ZKtW2WVvIkN~jg@x``1Apz6Wo1W(`nXKFKqW~?YWaM%x;71GKf{< zYN{27$F4jBhf@=lI54hal+@)`52u3mZVEh1F#mw;8#c4-Rc>&HbbGF4ugB5PDcgWk z1ie_hL}_?MJCLfmHmY0Wnhpoa&|x-m_F<}K>Jsk&YI7^4ZbnG+*&`-%eQx8eYH^Q3 z`3sbOlrb|l)^0-i93K=-nOF55Le*ar;}ZA<;%XTfSxfh%qt9Xb(BD5@nsL)&bM0;n zogNv=h`y)N6?ISZu)~R2Ev2My1VR-;`x_gB9V(?>`l5u~2y(44a|~EuFjEFf?M#Wg zw+4IvD%IzB@|B6sWHCn$TkwV3GX9i-5Luj?P?EDhb8lpJ7})gShImO-xRc}TH38&mGjv7!+$+YYpC+ma{0zp6BVUvT^XCgWyC(XJG*{|Y1^X%GuCtdVy zr>xo3l1nRmdzw$FO`X@I4pZ{73rN#kusKbu0||ppr5}*7`|Bytl?wW6%v1^`a)itp z`0d!hEv+erx7`y*^ZW#avYl9!JtMrhW6vr*XZHrK>Wm)ghOCOo>fa=$J}gGwt2?Wv z4AaRZa#hqCIx{n7MD}VDN^A+d^a@k;C&%8|CN>VFf{G?FAs_T5rc_HIF~hb5%jaw`p!>E^;oE0e#L4@AV7wtA>f7#|ooIbHvcJ z*NO&qP9qdBkZCcwkg2`8Nx@Gb`)4`8?4^d@&G0|Q7m?is&m*tA0Z#3ZY()PQh^kr= zieZOnCN8RT66zib$jnYkkkGC#4pp%6b`c1{o;xn--a+2NId;%}$umXQoW zSAx_Z=>jeOEL8(C)w)FjGPH!l+`#6eb$8Ok`cuH9`2DI+diniJ?5i@XTQ}acc0T^- z-dYu~V$WqMTovtOvf0!6O#?Pn%jpz8m=ywZcNg#isKeH2Kl_$A|1IHXEukU*l*n2$ zWM;fh7GKflgF?g_yK+|9P0UQOdaC;XegbS^;I`7b#5kyt__ zty2uleyCx8{*lf+9gC*Rmw2J&MqW|rT#sX-kNV&vvph_Jc-eJ|}zBvlI-j9u3)GOe%_N{?9p5 z|NO703+<_DJto^ynsj^jlM-YcOFVygaqw#Jix^9jW=>+Gx9WJS>ax-A$oNxOaUtus+0 z+c_@{?fel`9ilwWeb*8cvaN}W7K-IYu#o!LI@0Vi9_>)k5gejKWXqMI=c{J&Xc4#Z z>M2Dm6_i5mye;KNz!zi|uzxNJsdb111jPv`!(1KcdJ%AZ6&CGpJutxGMJV8Mqawy9`pbs5RsCr}IF0c=}UE3iY1a~)92CQ5Zme!k&i>*-&N$~d|+`+~(X9dAp zssvA=UpGRi?8CqRl9Z%K(}I~_W)VsD5cYCNU!zg^^!05gynkFE6Oo-4r0re?CT_Tu zi%T3RnSg0CV5obFhooPA_&pOQBpxdXkcsLR376ap8;?Fw3{?6M7Cl5k`&z67xOyv0E1om@(6UX%yInAI(8- zil4ln38y=HkWTW?D%NssR=?U_O}_l(TU7@n4d$T6Fib2^?ui#V?S5Cx(f47<632JH z5dNpQeJvX2SucJ(fm{49!pFd?gR(~*WeZ)XyZI|PBSCE>nC_R|3y2Kjwou=k*LKdgkCU;J(F3{Jig(m znS@*BBiCXNNNq))lbGD2mY1$6%E|zB4tXL+sV&6(JU6nDFlC=Htp7ka)G~CAscp1K z#?L@{sa^D0&UxMR$A%r;z$ricOT~c;@x<{XFX^62uNnEy_CsOtz3NA$=pm2d&I(AL z*?L-wil0+%^o;5|;+K~5BiJ3yvit_rZ^*-%x-l>Xe-aG#?|?3=xB0JEFIFh>p4Klg zx71+(D%xPnT*H|&ciQTN0-Jhyq`UU6knvW#v~>MWz6YPO=Yb`s>%Rrm2SR7~EXZM9MA?(@2& z*xDCrx1gDvZ_%OHNfO2NQ#1j*GiYzm!clMQQBN&LkA^a3@?GLid$mxK*9pIopccvR z-YIaXii*{$4(7M33XA6{YwWWtCblosc^NP@pq-WXesu;UE2+7_-0zj=07;tRs;^$s zlByAbGjtVH*xb+AVlEH*7D`O1OS$T3u>f<@^?`TcD|Job$16NXo7m!HLsciDYO_{Y zNtd1ps`w`FbmSO=8HyW&@P(3ec}k-Ca@!81YEuNsn;v|#06xEmyFm4`;MJUlj;Om$ z?bpS`E8@;ej&aL-k~i9aScrAW7ngj44EJEu>he_n(5Ec{JP<)KgHqi!Z#tzCS6K7L zg9e$UwZ(*QzDCvx;-lhC`2pXr<0Fd3pW8etY%>JjNA<;4ot}}>@160VjaI52xsUQK zZg{Eg&coOi8cH&An{#L2&J%0q)0wUEfR%hP2b$$+q<0i=Do+nK>9rh!xW3S2%2HbY zS@rp4Q3b-VC~wtuc`12>`g2mo#%{|AhHeF$h|Ob^HgSGrNu~X7*81Do5D5er2b`|F ztDD*0L4E@DjHP`F;xs%D>%MMq1Whl$p{OdRB}k)N9`pU$qG z7C#@ry&@uJHuiN4=SSrqvxWwFA%{s?*I0cY9m|5#v5ad*1y0o-Kp*tLIIlKps(_x> z5@i}XH_5P9uc)qB#%g@?LjWME78Yl**)l#H#>I@&Kn`eFRxRHlaHCJXzr@2`6{n`Q z33=)2*8U}17e#=6CJ``yG@wu5oT2iDcRhJ3?*(rErakWAA_b%hB_(Kwsmhd7J~+H~T(G{75E^OnZ&b{ByosAL%g9xZ(3a&Q=m>vy?ilsV4KLxX_X` z$(Dd5N5ZFd-{K|CX#Iat)QfEL|BwtE#M>bz?*3 zK40Lc0O4x1AUNLU#Z)UV#DJeS=t_-W28ThpPX^oy^Y)ex)H-_^9c6I+8^-V@C=$K4 zAscu5KBVVJMnhqqiAg`AAq_q1cFkX1kY`p;`Rwh$l2?Sw=bqMJOxiP^C&tXmlpe$U zO*pD?WVJ?+BrP5vm4{&58Sj>f>TKCYJY{G6D#P$eT|(AaD*=xchz|{cUamZtE>37u*YSgg;gB9M&7#h`T+X(7dhvGXi3oo^K;;+*S7@&JEumWdto{YlAbJZgmue+l z`CF8`%O|DRi5Wow+*eA#KmdUXYl4!D&2GuOI>e3f%N(i<{YNm9Cu-t9a!!X#mWli} zn)8X;ZxO+f>6@6x_oOygeS0t%f%SaaayayK$m8?zt4i%&`)AI{wGSsnJz@?4NYUe& zLcAAe>Mre`ZzmT+Dhq2fdsEJW!v9d^P?^s=z9Myc$dVZqsRVh0v=eCUXtd;jS(n>fs>@SZ6U4J(MfQ+k?69YrS!;HGXz(97^@kQ(gDB} zrMd(R*j?=`n_q`Hd;hVq->}pN2mC*h1ENwvhrqvWsRjGQG_`R`uhY$I$cY*G|<-gzd6L|7anqm=_ z{a^KM(*J;fzOp6%_+hHYgEvlFxs+Gt*WDji-;NLfGkW|0qOQ~oWy$>J74LHjEZ)sm zb0M{;tYS)JW@0eSHC?jmGcoeEm zqRgKlwbp1x$;O1!lD`Pc`o0*6Wo%#t(OwD)DgQ(Om{K6-pYW;u^V*XIXz?3m*yRy$5#EPB3nQItP&xr ze3G_13V3uMtHxe(`E=rxT~Uvc3$cYqm|Z@Z?+U8nuL1F>Pj`6K4RyZl`u$%786YMF z#k1OdQRd zinO{*3E;`ovZ6b0viXLJv?mw4PKY}R;&2;uwkR_aEvB|jso{hcQqOza29x74eQh= z+IQo~4`>h{0V-TFkyH%8JxO|2buD?o?Z8Eh9{Vh4$ z^sHXCKiEf8rw?X#2AXe`{8umjfm>F!C|W{a9iyu7Y3+LWw2w7dFcyjTw#0EsDlz0R zYtX;vz7Wp~*y|PcXlD}=`rLURbIvdmSHs8Xy~Qo0XUj>hFza?g3mdLp*r-Y-Z^`IjEnm4F7>}mRk;O;VTnNBWPsHKJf^o`d$uI@yg zhtb!^Mmm+1tiy$9EM?y__?R6jWY`Y>aBFYL+tw>Oxph<$r;y5l>kscU{+hl@J+e#q zVFq<@Cynt~2why+_M~rVdWhu(tdv`yA=|3mLxh=0L}C_JZd{@I9~Pd$*0E?yQV8Sx z)k1TvA>DJ67H!1S1rDdnRI)Wr>l5%RA}5YgY~i^$Rm23r_LHl0ToesQLsu#4le!=ZJ|(gDv)Hrul^>y<7Q-j^4I04NaC4{VS5^S)*%g?hKhp(5&KcIG>KcnJ;H5HRUlnflk#dL4Paa2Pk`4q!;5jnDQ zf5`6rCZY&>RG_KQOFEL#AXE zsaheYROJs2?`MHm1r6_KwmF`Dz(lJ*f^wDd?eWfG_P|1~)Fgu+&CM$<`i52(+^Pws zNJLuJA|ui7=X`tQUTnx(%c?-3EW}WjKL)zEUxhd&U3iYPxdLdUT679NYBS2!ZNlU8 zF=4n6#xa%~*NgV;7(%RwQUxqLfe$}*sp>rie7^@P2ET8{wClGMiYr^VW+8ABxY|uV z9=6aEYqnc@4VuX8pMWKg<_Iu4?p|N1Ob@s{3P-BlbIKiTNU#-$+q^Dp5W4%9zgUO>F0`4uD zufz7Lyou|0C}`PHoMLghLtFa#;K}=9$d~l2v}aw1*6q+c^Mzs%waf$l6-OeAy*n~% zWHYqraW`PjGvqZgn^b>IF~_o-a`$Lq!@|ke2WdPpqC-GuNf3@ht)?p}XE9m$acK{B z9IlBf!??o#Jr~f3mXQ)lOqsp6#-AVB*?nuP44`78;Bl^$FUm0O6_xnU?2lEbhp8$1 ziptA%Gy&f7safy*Alj{b?Oe(W7c$B?rB%AR2EYm1pd2R$WF(PUP{#23O zd(-!z^jHrfz|QVtSK4grQJqV(8ve$2WTPCUMqnm(zvH|lt@by*>syTI?AExAn#OqY zRBTQYl6(vXi*k4Gmw6otZPR>r=6w#9umoufcS|(~UA(%QIsG&_5y{5ZPttG6ky#88 z$}2I<+4dZCUsJQZ;l_H=v+n(bDFimTEff!*qMfs{;dgh4R=E-p^kDRy@eEgEC zRhf;yw@~LrX>aeC`}IaV^}OSYvpyzDLzKkU&}<|z$MEP!M~iT}^2o0LMoGs(38J@_ z$>MUqPa(Jjb0a@lj-L2Xt!OMs+dAe^Ipi!1nF5*$1bdQCKxy{(ze}?$&l0UH|BOLd z3aPg627?`4zDxXYcn}^FB5;ZEa#~hexH7`VBXtw8&+79N1YoMkEmQp)0!K$PE^|;e zX~uNA_gUk|mz9$K895S(FC9?Uc#)32V*dw;0rBsDfM#p2N{#G)^r9HY>?j`W3t?&E z1gE*Uz6Yt9qVzD7R#H&jVI`t zo+0}FXl*Mhnj5Sg6MJ^ap39;13Qr)4V4=H3xv_3_<8mXdC?7ax_wB?YH2dkuiR0Ox zMCGb|c{WKI1t#~k?<)G3>pS7ZH^_MhQT(;P702;J}XsGO-%i(m|j=Z1dWXUdM3r4_-<;ESlt4Q7LPbvsV%tQtF0Wr<;WH<9%p-sR(iq;Nc0W2!2fxCDopQdcyun%tgE~1M4ii_YhT9MdWdXXTT7$%M0R(k zg3l;bR!E@U&hUXIl&8_~j1Z!|?*Wnk`S6HboRm9bBnjl5`15Wd9TGP@fG+6}P)aaM z7G+0uaw84=kPxnJu5&?<0Dj=t_Pz-nq{Ma5`~zE~$9a3$?4yk#u-6>U-<*KW zI+qt2a8ANwr3kT)N5z@%pac8S;&_e*CmW7A5+X<_5S#B1M@e*`e$B>^7LozIDp4=$ zz|YY=3fwY(8v;={nv5@HWWv|0o$MlN0#m|Hu;~T2;{!`Mi=FRV+C9Mb@ z6`JQRTYPp^dhhBK#T|(a{$aEV=Y}I}d5PO@uH0oCnBYH3>g{P**mc~4G%B^+uhG8_ zOJ2kr+=Hkiu>#Xha+u9DGF>S6YoT-_nc8Ko{_wqpShQNVECz1U!>m2kd$luH$xpMH z{_={wWC!v%Y;TgYTB@6WMytF|*>548m?gP#l#3Pjej~I*Yw3-NdN=F7{&}2AZWga{ z(~=`Ujmx7`Z~<#dU+EG|H2aP{-09mSx7&Ov#!ox5UL4Jb0GIh49|{ZJz<$&EePjPX zi9Nz3kbp3m>%q5MgW^$ZM^AM7y5mJ-tYF07xALz~rpj-ji$}avBY8}(v17U`_W-{T zQkPGU!nQ5`M4jcU0tg2E&-@?ios5*<(os3^UVtN`Bmh-pj1h0^%2Ad7P zbW~iGbS$P4xeyLFj(Y6DUdlm){;0`rZ3_9BRQ)tP@ED~PsOHpn3p&91bMI7%;l{%h zZ`xLEmsU6AG1HL7=}a9wuAt=WPN;pX(HijbVFi9xXf8kVokezN?1TF}nvUlf+WVof{Dud$v2+vfwl)QkrU zYV-}ji+@2m?({l57Knd{p+^)X3A~D%_hoQRDJO+b1Bx@~Hn=vt?|GSpeejzs-4Y3s zpHJzuP>}TRUBOFpr>vEjP2Yi2UnI?CffxhJ@}Vf}GPc+o0v}9dcV-8n_ZrC_{P*l2 zp2iELt+jBx)9Ut#^tF4CxUDDhloe*Z-rWw_!fIUpjL)IzWN|S^Hg{q9h_#^B!6waH zC78$Q8Kf8_x+`oI-f%6T@)u!5X7#ilsF2JyKe4S`{VazvCOy>lxImu;`m0N_EL)~S zb)@+p4E`dpe6Livfi=w7OFX<$ZEQE3IRnV^+#yr*zEPCw78q#t1wXL{IER5jS>$SM zu^Lf|K|%+7dEsJKWfwgLQ+mgB5bGcnNO)_r#N7ZVOP&`bWNPH-R&)0*Ii9j!>YR)G z26xYS^fq`(i?F(UZy0Kf*BI(Mta5c9KDxd)vnpYJ6*fI<5n*Qzo9qjFDiA3`z$Ew4 z12TrX-|LQC$5bX5lD{M-maZx`y7n0t)hn15ogC0(Y%PA|jK~Nr;HVako3#akmE+F= zhjGYh>(Z|;gE$P{Hw2TA(`hZ)ZE-iQYbFFMU|uEf8B3TO|BzlJQU6l3SWQ{8HhO}o zVsqBn;N`Adjo;`NQsWb!+Q}adq5D@oKK1ZNi;#fCmXFh!HA~eM@z9dN3w8&^0K2Bt zYini5QPX`Vkn$J)a^`<*;9QNAe6$n=i@G`_SK$MluS4F1c}$NWn&o(=UTV+OhOnYn zLj$J+ueh;_Q3arxNjWBOXCZa=Eb$`IccZGc0p=|6p1EStP3N^;ECyHQnX@+9PzoNN zi~+7C0PVmXGZ}@VG3ziU^m$;fI-{ZfF`BL~4o`D;5s_71N;=n)B<9d}K8+SVWd# z+4fiE%}(bzVx(Q!YT{7$6jo;L<%C8oRpTW*!U$l$n zHx0GWhKw4j0F~GWTz#phSCy`_PS&)2ykZ|C!QZM+g4ZR85f8mvg)3=+PDWtGqo}<* zaoP1*ztyvLJU12VAQ2+0z?VQ>$b=w0X?EK6+uf24Ng=;GN9zJW7+8<-()iw2+2m4% zjO|t!Rl)bpmtf;E>jkjHvzNmbH)Z%dDH0!zXj9f2cF9pB zZfv=*)s{elLDgt*-h(NmyvyMIUL``cMk8-M1S54zYpU+&T2^iA0)=9N_H_-*(Ixz} zP)TX7;9vX5zj@y;u;RXZ$IrK2*nR-o?|~eK;c~Q%$8&w8q3n3hQe1Rc%Vb^B(QW+; zjg|roxBCZXp_AG-!oBW&&~6&0>i@M$~?Sx`~axmu|B#$H8g4OVqm=U4k33 zzsbWXjJlkZ_|#Y)DF}RpndV7=itkmamh^Pa)KS~Gjdp)y!ZRll0^r0}<-f#fcDWxS)9<+d#?(za*JKaAWMM z+D-0~{_6Q(@666&(EY!@ssBOR1)_emg`leDdb9DjvkEr~M%uK+43<eO2&6en8B38K zKYht$5PzX!Y=_(b)<2R|)5`cWxgSP5qrNiCK(Q;ia6tN-4Pd=UyOZ7fPk_W23Z=Uw zaWyd)OJX@{kA-*@$G?$0DxnkkM+OESeO=ojO~DN=CoWB9!vK`JGCX5EC%rVN5IXoG zgw~}3t0pNB;Mq?3$Jz(>xv?*KqNyJA6F258=SU{;p#r*Muy8tjntcgVSSE0L&3Pll zB?Lp2+zl9XV<@7!m@thtPxnxcb?isY+7hcY5KWTC9B+Kw1I5}$!sl}OAv{1qF-yjw zHH1W!LPaY$31PqTUdEsy9@1y|O zmNfSBE;bMU40i1FJ8m@Aen(j?b)Tarl#!9%U+9?~$|8xO7}BaoD{)OpAFJ+SrXh@v zQ@Oq!zaD^5ErN(;NKlX_cQEFdgb<((Iw&nuMYni$zM-?4g7j!XXh-1U(jgT>3v6qC z&rV?3BUSA|atzR=>a$+?+dB5#m0(y9lPqAq7I++0;=91#u;;HMr#fvdo{{(+Lnd0G z_}G^hqWwOFy~4w3eGnH1=zdB6_ha$J=a*6fZyi4JdYx%Yg`r3Kw<(p#OIjQPuEb_G zxrjP(uq3ir!Qi?=#m-$5wX~wLF~u@wV+p<5AqO@=B_5)fgS%Ow!-Mg=tE}f+j$*oG z9yBRqkZyK$$#mUN@8h17fRCe&g|g-ice?&%?L-Ot0T2N&*8(H$C@BwuH_zTb0QJ>d zp|O-_51?Y@oplC&FXg+HpLO%6#KuR$1^g%SdAz0n(PJD?A`?JL)R*Ph9n0&$;3!$Y zRy;dLz&-_VAe#hc&hwr**tswibCS(JaBgzK&$)~)uZmK5Z<;@n{+N!2CJEJ63hhk! zKCA%`K2u<9cpQ*?-E@MJWkd6gSr>ak zPp9U-wI{wiQ-C|!)a$L2Pr&-J$2ooH{#kRH%P*gk5i6+9QXEtueM=ozh|v>Gf3r#SzKBkro3R+mI4K?u z>+XUy>6CFP)Xgwk>8HsuCdEyBP>T$}^r(Ky0A_9k6aG1O8N~-KH7kJidx!4OFE`vV z)s!|s+Uo_l=hn5~0Kfo(9T{7l==SAu7JDIJ+zL>i1OJ{1mR?=_<|<52-26ey^u|9u zrm(%oQpg3MwEovon?9OXQbk8r91nCOf1tv;EMvt3>GIdGm7=LqT7L06ZEJPR*FKEI zCyVnl>!1ppui$%dt<-2}p0VTlqm31Lo(f#LF#JL@wR)}-=MNiyMl3ueFaIL&t7how z>U@@L>1ned*o}ndpIS-}p z6dL$koMlJ)?Lyto|C2E`qviOamG zNGP$0#S6AldwlJ)wlA%|J*sieHh+3bETa@~_9mA2zpr$DlIfwhT8myvYv(K`?(3@m z4ljzMX7I^-(KP!}C`3sI#0t-^X|G`7L=2UXqsA!*X%dN$x5%WLwzvo5?dovDet3m=`fG!j=7 z82S*`mRjoWA~UV7jXe?<`Ae&*A8f9xKorbW@#<~Dk&@K~oT0uOofXRSk#bj3W~>GR z1zHMp6>*Jdu5U*O3oMqjlkQ{la}Vn|qGp6HCN21W|9T#$i@M=a!okRg`zs+6AFiG& zKUriJ?bg@y5;4~{b|JLvz`{d2>mxG6;`F-FKC$Nq@36|_N8~x9a+KI)1D8vL>S3(7 zIoddS@Yi-ecH_+_3yI`epW8QAB0^x5jiukXJk&U0FK4Lyh_L?|gi>s9f;K&<{+Tb5 z3Z@}-eabr#!K+~I9t_P6eJl}H+L?J!9W1O1|KPh!WQS`fE%>W&2%fu?!ak%MhTl$McBb&SiXa;m6Qs~h8?Dqd>GqbIMhz#^)*TY=2F#NTIEF;Z=&YAUk; z*Pb;vc=HBZteMGroA#j>^Nu6^Oh=|SKiFZV`K{sw6>tzSz|Bj*-+w|0+))zE#glgP z8^vlITusi_rbaOodb-LaSN2L@v)z@Qp4ZD3l>kx%^DQOblJEE(t_kk)EajjJHUU7_sQqaD-@``F!!c(sD&L4Cl;qA< z*c%#FU4oUurE{`QQ*>^dpQ$~l*vvOXA0CP`9O678NeT<^;N_?L<^-aWIeRta859?( zlApS{KlRwBZ?rhBZ)X)+0z2?Lhg+J|W>6Yag)(}h0CdyzywVWJHGbA*yx2QtA25lQ zl#7D?u#eoy5uDAiz@=C78uWg`@Omi&Ia1Akd~nx#emw!CLF4LMj|Ms3HDBD#nwo?! z04_pu;G?)bR1nOWQz&U84r?+5Ft#$Y-O|gCr@M603+F zUPtq87Y!UpO74MLTA6W2uL-FK?L+sYr837XK0RYznxef6uy3or`v3V|{09Q}U+tp6 zsc<@^RG8JV=)>6e-lKc54Z@sh+seH0QAh zkB5@qd3-K`JufF0R3%(`$b5EkrxXn5h8MQ7Wu#-65ArQ+M5x(xH^fLh7K^?-NXT>} zQpOY!=f+I*rmJnOAfWa{`fNgpY&v6@uI<6K^^Niqs=+9CEDtS&+FPgZ$hZtKc*C8t z5DAPec*Vf>8XhO6{}X@Ty&&OX%D3^eU_k_*jgZTO)u);uT{giyypmnC;^p*&1X=Qx zP6Z!@sbs5kGH#as30HQ@CEeq>C1Y=m@iP+Eanc?3-P4>++YNq_`6F4fLG_e8=WD%- zUKv03o`(A(pC9-4J~)<3%vr*de#v|9176>4aXaN^CFqnVK{XetSTA*-3!BOq<-kUTn8>Rf5kQ>mkdgE6+5zIf zUth{TP&LP7B@5r^O#@rJ_U35|8{U>q8J`O!aMh}wSW`k{EKj?StM(Z+or#=0@n&-i zOP1iYp@j^BdRvP2nkk<%04L9g297#&9+$zHXW(Eq;Ju)>W~?4S(@r@s>37~HrX@v z^$l@pjWj4|Zufj`B@1qZJENnb57Dd z0g{GCnB{$#mc%ZL|AMN|n#l*F*ZUIob60wD8!Gu*i7jx`iV-9{n?G%Xs}Tk<3K4N5 zf$wRksIl+MBqqX}uo5Dm0$OAhYZ6lc5A&yUAZ@64nS%%umb8nN!&l&5X#z{6=#oNY z!I*?%&Hl$P_1#S6A?;0V$!=KLZ$l@dQKW^2aW9=q#^loquOR~TV+u)<#jsumXaagp zuzjM{Uj&9EX4;tJZ~v&#!1*8S@yZR=6ZooHzbG3v8xev>AY74~$(yUTO?Wil;4_XO zX4%1fNk_hqY0@(2nJ=Q@XJsR5nR(~tX~tsucRxh0Xlm0bo#MHEZVl7?!J1=1m&US( zNW3OueKeo6s1RvKfUIev6*(lhl$j(|2}?4K!DPjRy%v-B)xQoZuSS6f7PZX5?6 z8*#w6PI2E8Y7>mvmC_iM$qFUfj1YtfthM|(vjs-Kt%|AmrpBYc>^E4N>r1e%=HEjh z4nY8V%mACCMANxpfo7@uM#{(5aZjtOiBSPCDZ*4Zs>%&#L@N5v9gFcz-@W@RKU1+5 z-AFLSuF!(sFQ427^YVaK0<5a|+;x-h!_&3(l((}0=E$EmvT0j?a>`VV_GNz3iL`qi z`LC2Ym4voI3sGZW*M|p7PfEr+&!cFXFi(OO}u zPhVqaO4Y+h{)^!HXjxOn0BsT+=A-sX(zXXrTf?yLwDJ+q3n4pDmh$s0NE1hca8qQZiE zSWpJ~#iLOVBCFzBr%d4-Pvx|wjzZ+Zet(HU_K$erKflU=EXI`p92>o$6GZ6J-QinY z4rMUK0EG7-Y7B?$K#o!{klkS`r4O+|Eam&G~EN1Ctt{}l9|Fyi=n|? zZlxgpB7DN{Kab%5`5x)-|HX~I2&bcc;fF?FwqKe|hPaew4Ej9sI#_)Z0lukk_CnJ# z7m90#|4)3vd}1W~l_(hkmbH*we4N|KauR5Na!x~TGvZDBB#D3l#P$adAg>|3cVEe_ zImY%Ecp};B%``BX-W?q?x~c4rY1Vo45}hvNcqZojOvuC>Jc?1+62|_D#l_s+VKm`^ zmiWHeA!)@&*A4T~8?%**Aub+8f0LI>ecZPTDrm~sgoSDIBEC(7c6;Z|ktkz-(|HS= zn+Ve*(P#Ii1IdSV_4F&CY?$y1UoraoY5w&!`?G;Bd8Ss|Ym<&m>k}#PyeS=~$g4dC z%0V9B2`>g@AGDA3)JlaO(UOY$bZ_-UJ`>wD>3U`cXFx9ELD6o7RoJws2o zo>ezLf4jcuXaA-qHMRxphZT#1J6hs&Yf?FFsrVH{;?(jW9R<+qQ0MHK2EEuv&gpnA z(`aCBP=G$qhqrJ`2~j$5PkWE*hL37dR`?Yk2-!5JVEqYnUW~92iDcxxU&ku zZm^5+4mJS(7?`h$H9CFM72J#WXnwT>@~RX@Bzv5vod1rV?ma#f@R}kq0Flfozue`R z%Ny5UqlprK*YSytIvTfn9Lxhkqkm_T+U$g*q2=9mzp{wboSV$|Ss;qN)FaY)JLE2% z#bEF`QThT4@0nTpy0Fkrr;PKny6u`xzoM8s*@zSp-XL+S`PADjLn5SMPZnTiHN8Wc zW^RM~&Q`=*Fk{briFs8x9A8D+e_Pt`-4$?d_Ek}+=h2cR#uU!DbbT_+-&2LX?r!A! z^7v-CeH>!B%j*XHB@4s~dHr3*&y>&Zf{!XPG7LA&SPm}L;Pp}dPOPSMQr>TCBpsRU z%34lnj8P4=E*`Am;s4~Kv0eWyqxqj#5ql{-z-}3Lxy)4&C)P87HxM9~HbdeUMB@D% zC;iq-ONuJUWJ4nzB8wmU8_Vfu?0h6t&FL$@gr`x2Fvhp~B;jpCDy>Q8w25suOX;A?Dn$xCBRAA0R$0mUpxSXIZSbCnBLJ4`2`CU3&%$lu2 z&e5F;YIrS9rq($U<=e85+Yqp%BW7|(&hq>7sC@y<#uLSlLw6bu+QX^u!nMECmA^uR zUtyyD&ah#r8H&{y`xE#3S^a*^l_WE19zY`6tW1mi>XUMp3dNcyX$R}@Nb^Y+N4be8 zw#jd@P-@4<>8xcL5JWX9(PRpM;>%u$wdB zmCG2TNY~Ip z9}DvwS-3lGv5@jgpG0NP&RJ#vd_Z1;y<)@39MT-j2m8tFyKcZ-V$7uOcftd^14iF>4u2q zFq_Z?ZI>7Z&@|MgnHxtA;Y8)AIDb-50INjwplnPU*VV?Gi<~4O=}QQVUzWB}H9iQ2 zIo)+KR(UJn3coYY#QdQcM)E0P)zSV*+*Hk(QW4CA-Hel-nAR?;Ak{{Y6tF~r^GPO& zmYXts*ZG-6jf^{-N?}@Pu4x>lD{f)0zBy&op$2!H`^T8QR$B92TE?(x)TWQN+9lO? z?&ekXtaQ7P>s+r401@M8g zSRMW_dXK3Y_BF~UsR_Jr$9fkn-ok=jCK~q+X~BmFRYR%(w^&&CVoHLlj#2<7~DQ# zV6N*1q4P6LCZ_bnP~t`ui@wKeIR3J`Pmc(nOK!P<{i`6tDvqCxc2gg#`*mVjtVY6< zWK}_C3x4V$UeZgJ;vJvS$N8}2M6v<>i{SA^LnRL_iib%tpJ51X@`n$ks35ga)^7e2 z3YKq6e|DJ;Y452*y};L3)O#)7-OsqSWqY43s$Lzxp;t~a;SYR_vP`3ENB3Ql%h+!v%v=_2YGCQ$v1JOQl1(2B*0pM0$ayUciMU2JDc^!T z*IS(|4k&&R@K7RD6BUo=l;(s-fvi(Gs-_Anc9(J!*da5HfWv$m0$m>a_kW#fITJM{ zycd|rB$xYih(E2qQADGnaX&H+L4sQe@@rP|W0z`e@ZluC6$+Lggz zQF#6;je$1Kz^|n|NPL*}l6aqw@xXKbXL3z`k!SJV)n%p3flHwJ&TM2_+?|HDPqQrw#mnX-2+>$?oAD~H9`Y}kvhCcXsgUvWiSN)_2l-XA zA{tWK=ND{3z+=}9K4k53Uyc;(=K?s@+;tRwoKJQL<}0@-RJi%B3w2NOi2;oNpCWH$ z)t@gbW0FvdY2$tJCr~)r1HGu-HyrbB(~fU?Nywv@EHI$8b=4&w==f62-#iZo8}0F4t#)UjShNY8 z!A@F?Hq3Dr_jc&F$Vj0fq+La?e{c_=qB6lq*L}mC385A-0}6bBtp?YR&MoY&;oy+bTtfMQ^O^9I>$plbn*U{amY; zSsz&Thi&(IKDkSFR=(I@uqiBa8}5sG?^dZzHjJZ>TN@E6_UgpX?_2^)LK-;>l>IL% zSyahx>~eJ)wOH0nG~t1E&s>&i!f-McVWn_`(DTHT#ldNDH5yOs+U2>T{_ah4N}of#jinGqv-F6z+eIq8FuKzwU==vY;h&FCpP|@#TkhM zh}ySDsW7wbfj?U-?t}c?4Qk=KRHg+bUj1j(UsVp7t-eWW8DX$SX*5Rs7mOHdk*Ws1wGY-NiaF%~ z^PEe|^r;qmN^$G?j+~=0=FL3PdfHO{X1)H^IfmHnf6VtJ{yn1mzApOX;TL*Zd@s7k zgXt)BY2BSbUR-i!wa8sV_iZUd!u;4E#bZlY`I@@5K?p*b#Ya52e|YEVPH=ScUj*|; zr{n`ty6^U+w^<&$E<=(ipFEMY)zeDywsbH-FNG(yr}lqXE~FEPVex5&>4N5q8j%69 zR<+i)8_dzcfe-e&OnuOCquKI9OQzvhzE%842e*FttRZLymrUA_S{&rf?_h(dS{??0 zXUO}X6bbw0GUd`^ihKL!B}GFeMd&{=9j+;P5ABlbz>!@Mw z9Uc5TdZUKCAIU#jvX!Ew7`+6MxC7kt8nZ;#`*B=N03c-Z4C%lRf^0%@|3kBA1w!F;lGrb2sTCvBtb1=XK32Qc^Tq0 zRWt9g+#E*sy-`)C-@liqiy>JbgM08qPTZBRQ=XfMh}1(B6c=dnxiGp>@KVPGHxu^W zqW^>Ocl$y3C62Xv-f)qrQP;yg+DFG2j?@?A++%j$fZa~aijDLuJ=S3CFR+6nahN`= zF;}335>ZoaGu@b_l}`QnYXp>oTTg@VV3)p`^u}L9{-g!YL;H~T=&2T*R4C`m`cP`q z@}+1E^SGQ|hIOf^OUXrKPt%}1@f4YCTNu+WkYe(e(PUbx4=PNVGFdX)K18=#AYT;G^-46R`qS1E0DCT3h}9NP)0nCgluJzjw- zUJk(===UHJol#BJNHr(I1iXJ-S6+BcaxMGrdLMubWC?~M;{m=aGC`wUZ|Y1zLCYA8 z+qKv5P}WplMZk@W8_c;qm2R9d_7!Q2=3xA?A|cj@jz`6M)(l9+k~xHESJp+fn9^i^ zQZ|czOqwW3XoVCu^F4re-D|YFBpD&58|N9T!YQ=*Vjeq_igaRcsLynzF<+`vQ` z+~L3HUdGxPa6u^ki(q_7xll!Ux>8G(OEqotCNmHztDn14o+F3aGZW|Zikw+Xd*J_+ zciurwcU>Mw5hGnGN-xquKza*ARJwu*5Fk_uNDWBu1Vlio0@6Wx=)Hzsr1v5nLhm3& zknYB3-{)QTop)z;X8+uoWbQpPNhbOIZf-f}dp@Tayx*TcwGmUQEWnI6=}zVl)U}U! z?-@V7u1!7D(;OmsUV0tfw8RUYP<;2`kUc@i(3m4GL*|Mnroq5Djb8PVoqj|$OTl=R z(iB3U8n*_Z3*GMAe4>Kf!zN046`yLcMAtF|@+WW%ncUkdG0RvbUBV^;D!X3BuV9l7 za4E6X7kyI$%vYwwx>_1fcTY7NENPvZoTs>saH6=IaZ^;K^JT2m5dCP0-02IdsSFWY z)9TBk#On*g{S4FUpIA9tI^5kiWiBwr`t3>G-tCs z8d!I@3&556TqY1HZ*Q+1GdMQh5y!g_u(oc}Mz|VMBEdUpH=c9m+%%i=`}^ehr(?K> zrds3^LWfm@>Q<+J;n*X8-?Pw|CTv-!i&N}9J36C2bW8t4E%IjIo=9tk9o1RVIp@k) z9Rj(I73clLf^i5c8K+YHhZMx(nc7x6dxVl4FSks^tk`njqKf;b%a~%GJu293fhW0R zA=-)R-pdzJNDTavvk%846BAr~s>wBFtr9x7_rW0yRiLZjiw+cicH(wJMsG%TAy$uZ zq~Z}mX2ewo!X)n1mXb}Gw1o{oa5g~PBQ2cg9UI}{b7{+08Q4X)u=GWMND$j|Dov`J zDSBnGLg*P)f_uLY@R?W#>wk9=V(lAcoQ~XW-12vhDUS?;95XVkeolMfu6C^V%9K{~ zoYQ$z{wOU1bbcX~VI4zY(|iqe8!0O9XSAnieK6nf-@F) z?JAK(u$~p_MTQrc@BGx4^2ClG-#Q#&iES9dQ=8GYm_r5gBgMmou0yeT78F2M*U8^N zOLVbxG;lpsJTGyw@eT`17B95Q+c~9BN1EqB+VI;Vc>5Rrvi<#gT{Iq@`n@;l?6x{f z3g_f^A6fI+WHPb}R0M9^wp!7+w({xc{qn~OCZ?6YJ z0(N##r^yAv@j>%F!q=Nn+X>J}b-ly^H*Ibt@f*C#H{#^-N-r+_dam3kSH`qb=rlFH zJ9Gue)a#!Wc>y!;-eC%d!Hx`ZTn9R4p6R}{Ier~8SM_|vBsQGRTOUNQ*|aFWkGaB2 zy-d918S^(+;&7PH4$2bGbznmZju$TW(m!)}f5-tk91#e)QgBacJBMtF%E&Jq3f*_X zr3PK+4PXQ1%WcRX_x%oS_cN}^!-;?448cgdn_9CxDES<}_0J2E0E;Z=bGi>6d?w8n4B-m395U8&vdMQO>dqSk`SrxBCAXI z;Qms(LT$)Uheq%hqP7rJ%1-dph31K(Nh%K zq(Xw1ze7mj{TTd6>)KrbOU+Cxs#g8>==j#0m88U81C^JYy=1l@Dx5#Nhu!dO?NV&P zohHNd*15F*>dpaB45-^yW0VUlCv7eDhmEE1%B2--j^vTJ>3h~Ok(oGl9 zt-0qvFL~~|V)b0kFYdQ{$=Dtg83e6<5iCd^Eghxf70(xO7^&bV)7=VVc6zM0{2u-Z z^Gvrb%eBwuptjyxb8HVv|DjlWm|q5yH8UF#;B*#PvoPUJPPR2KI7g?QK=7q>vH=^V zu;}{Ds`&jx{u({Ul3lRJK5oJvUsPz{S2%^OX1pdZ>4LVjfWkO&$=lr-5|?^q;nHIf z`Z|5pcLyyV>+G`Q>^g1xy_3K5yZW(~fZake;AwQd=CZ!Qg>H(pnDG(k>(fl~$UEdIxr!A|OxF6^$aYXaE?`mhK&PUz($}*lmWYrW2Z!4i z?1J?07U(xPz1W{Wv?X!XQrZ8K{P0v)CA#sOnNea^FdNc4_h+UN${^mjkAy_2sA_!V z``2l?YX3_K)D{E%KBC?je{b)#l~r(D^BO0MwIuE(L>v%RLAQs)kW0&wUSUmrr;FSE zPPV3(WY5gYlIpTjf2NA+P~#w0Dh)X*0zm4`g8%d+{2sqLl3}65-Tb6`Z-6T#q+>|f zczOcDnmuYbiTu^NKyUb+^fDJP4JZMV!LMXYVkcKkz=2K&(TXA?9GZUBR zBS4?74z{R118V0aM)#4^HC&Bg1B{IgdS^wzvhwL!TP0hUv#yt+wzVrh?0PM(W3-)LCMhF%9e$NbHnWTDpWv9U&gJaha{&7*vL}pxhrDOtD2;f-7kdx*oGWzs zEbfaB3Hl_T28y=L=@tgd+0kLi?~X0>`LwM9?QVHnu! zE^G|H73fQGVTLW=qQxm|*wvG)9J$(voz4T*QDmk{GfW-gGvhI0v(46@%%rt&v&5CN z_mY;QT9%^vpo_G;6KO@d-*e|<@?`@IPq5O`Mq(bB(Rbm;xWWhAVgys5XNv4kaflqk z;)G`=>>;%?cBmH)l>-WaUDw1c79L$(%d6EzkIHRt?C$@Pz~0F zhWohDx@EbE5$BbW8peL&dY%_iHHseO@H@NWJfhUP*QoOm!wd+Am^a1QXAQ|mxeBC% z=tLiU;wpYvyI;V>=(=1arC!}x(NWOL2zervd5#R_ND6!{^#pfSk3KitP<>bKvbDFQ zkllnf!@)Oh)JDu>)N}ZqlD)qDz->XHA$L;um?@LGsNSm3Rp%C)UpT>xnY&);$x;qP_I zfk}sEvL=}(yegR7_Gb*mG4URre}oma1=I@;8E(42$t}b%t0?mAj=ZK>c?0db$g}gE zD*@OGHNE-n&x6erzd#yPGS0Z<0CU(v9n45yNxt1}u~h}YlR-G1Op)|f*JR-zs<)R& zDTIT$O^_MWB^PxXS4-Jx&A251){8q-sW_wqF@Nmc+Mh{RsD~)~Hjvt#j*Y##FTgKs zv@G!Hbc1doJgp$UaE~`G|0ZUq39v6s>?}MHs;^udpgtKgUYgGe=N5?Qz{eFGjrQJ} zrSTS*2`sdkHy`RF=_5VSjktbTx@XOYkf1jCVWY5sS=Q~yi&=k^qs+Ha(0w&8-86WN zG77=wA(ZCc@{`h|a2OIpX2VrYyH=1XmctfRDAhrQ3?|`>@B@mqr?(YAfyxMo<@1Uq z)wbQhlG@AnO$(TT`ca+H(9YmpYvONxnLYy}V*QNjzMCOh=}t>%Qc~Rf(<3c(Ge?mEgH@-50~-tR<4$qp{Pr#gEZlMZ2i;roa)tu~E;+B;$CxnfV#veRM(CSo2FT8)% zBbs2$PUETAhRt!tPS`Xf&FMkwh=zemN=g&#j)M7L|7KW^`Cr_p8+k;JzcRv_UiIJK zQnV#Es`EQxVmWr z62V^YpVAy^elJEB$}99sTI)32&!hI-zx5G07RwpI5eC_nbg27!BQ8MP-=!b!A&1zP zj|>koejC`w5c@jTDh3}+1kpZML{`bCKv%5s;4i~n ztqq*NGd8O8WerR;|H9bF!|V}0HPeB96(CC!NXN#20B1d_N>AwP0lx%xALP$Zv??Oi(L=i{WDI@nTqoRC6vdf6Rm)5m#I-d~e? z{~{72KMeDWqzyn?yKAL$5~Py6YoH^hmOqMU3CYVcXEsj{`VscG@CWw~8Zhq7-@iWO zA18vpPX>RtSgz2WrE-2@6{$#V=8uC13Z0uHm7J*L_ah!jPV0f+nQk@9wYrm#uFjXS zMXI=o4n%frclKr8!&YXwoe{&is$cf7_WW_bd0vIdhTM)@7aE*oLoE*C2W&|)=Cq5e z*6BZ1F4km<20gz z8%E#q+}h zC-e1kF>=lHn4U3)fs{R4SDA-?oH`~;ARfAzFvULV_KVsMN<+EY&`O0|f?$!9M`CxOkKI5O^6 zqd{T;bhgV;(ZWk?EmSW^B#)A4s57bGXdkBRGVW)t+K*WaWD+TmhWwbepn0VTuQTrk zaczHprt+}dtK~~(_1wwNyzh=r)5}uzE_<8KQZ|)(mcbl?TyG7XXBWNIyHOv}W~OlN zkX@!rzxmw8)Sf9s+R?iiH15nuB)$!wHd{lTqEHeOtB02wI<2>6jL`cnfS^B?S`e|? z@Yy-%^0bGu{HHPFv@0F-({*^qr|uh52(!KP{fhmL-5R4?kY-apVyRb+ zltn}PGvs+7w7TX9<9jVM9gRL3twB6OM*qeY_17@Yz^*K}|I`5f+2^{GmF~l-Z{hrt zz+3r^zL|B2F`SbG)@&wPEaG`s^Z`BVJT5X++|Sn@aKZE;?i)%lgDdXuXosm$E!85+ zSLhzE&nH_(Bw7%XsyarmqB3k3FQiw7ouT6A&N)1~kdHQa4P68JqSa%XEVkcuo@Un; z*+LT6hYBaxis!J>Ay}KG%-PjWllqYN&3Ic13(iO*WoF_E_*$p22SLEr5+Ff|HR-;w zwvWRp!~tSe3ib;zbXHK6<9jQxrL-YaF=?V>NDvu)tT}g1fL_t7A;gRBRu$CdUOA7n zd!ASHE)*~pzKUN3s`WkqwPXF6C#Z7Ic8&YCvR7U_^7Idv4A`!kS&E)v9ilrwa(K@` z_0nbHmwEK&S$hcuz|8L~?42qxD<4@q=D&u=?$d93kB{)YKID4jUT$yMoK?Uk#ygOs z9^#C3ho=5Jcj(_!=|9^X8?&J4d8Iv8?X*x8DRlEIsVH@*b5l04p(47(!hkZ_`N0!> z+=I;T2t1yt8Hcz7t@lRb@lFVag_$k9=N})6_43ovg#|Kx1<{Q)5m#x2vnnB32NGy&Ut- zMXv2fxokG;l#=!*d6vM23(+@nnO4*OS4Ue3h3&~Xp9(9Wrnj}q1zJGHUldz90Vpf8ukOI<=^IuBb5jp<o!B? zx;ifrIz@inBY#roIpD{;4x#>S`~grvNUkx4{)}NJEqr$9dO|{ zuZ-r=e(IQilH!_%yB$PJK6ylX+i!{ggL_!MC`=0S!srmdM*f2cNplRu5il^@SHvs- zrdjh@iHhmC+3=v>Me?NDEN!NpcN00^#qwNkwhtSovzAg$5!$jd%8X{T;47@MB*GF$ zfg=-2v&vsaX$oiR5FX;`ArGw*9|!AmKMq{>GN%THLG6kQK+IkkI+`N+&{2+g;fF0y+6z#am%1$~_F!)!OwDE}p!`1pNnp= ze8j3Xx1)62QQ?R}=6JrfHvZn#?zls#FDz5vvV_n%^gX+@D$1a65U^)SQX|HD(qsvs$Nzu~ zg(kM%28ZuH0EgJ!-8`Gn3F10>yrMt{B&D|Q&Ka0p_rF=xvarhsbPE>lyh4+JnDyBx z&~coZSScCI6n&eA^O<|};87ukoLnm>c;hzLWO{Vx??rb~PAClKblzJtn znW$Qxc!en7J(h)Tq!PvMUnhC*+y1W1k1yC zu=L=tR!)M)sW*02iW(XSO4p=5BDUEEYEs(DECav}{vP zwZBci1tZB7jTb%>Oiy(*cH8he%ZY6vo3pH%I3K8VLb4JS}rQdH%B-TP8vzWwe-9JltbX4 z_@{z%l+-mlkdYs!!ZWXl^AImqBJGuq*^7qdgd?F(5!KGvjjO<)AI$hCGVOme+W()w JhV<9ee*kS&z$^d& literal 0 HcmV?d00001