{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Import libraries"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now implement deep Q-learning, from the [2015 paper](https://www.nature.com/articles/nature14236) paper of Mnih et al."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import gym\n",
"import numpy as np\n",
"import random\n",
"import math\n",
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"\n",
"\n",
"env = gym.make('CartPole-v0')\n",
"\n",
"low = env.observation_space.low\n",
"high=env.observation_space.high\n",
"\n",
"input_dim = env.observation_space.shape[0]\n",
"output_dim = env.action_space.n\n",
"\n",
"discount_factor = 0.99 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Import Keras and define the neural network"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, instead of the Q-table, we will implement a neural network to approximate the Q-function.\n",
"The network will have the state of the environment as an input and the Q-values associated with each action as output.\n",
"Define a neural network with _inputdim_ input neurons, _outputdim_ output neurons and an hidden layer of 64 neurons. Use a ReLU activation function in the hidden layer and a linear one in the output layer."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"import keras as K\n",
"\n",
"model = K.Sequential()\n",
"model.add(............)\n",
"model.add(............)\n",
"\n",
"opt = ...........\n",
"model.compile(loss='mse', optimizer=opt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define the memory that we need to store the samples"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For the algorithm to work, we need a memory to store many (state, action, reward, next_state) tuples, and then we will use them for the neural network training.\n",
"It strongly helps to sample a random batch of _batch_size_ samples from the memory, to avoid correlated samples during the training.\n",
"The _sample()_ function should receive the number of samples requested and it should output _n_ random samples from the memory. \n",
"**Note:** if n is higher than the number of samples in the memory, just output everything in the memory until that moment."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"class Memory:\n",
" samples = []\n",
"\n",
" def __init__(self, capacity):\n",
" self.capacity = capacity\n",
"\n",
" def add(self, sample):\n",
" self.samples.append(sample) \n",
"\n",
" if len(self.samples) > self.capacity:\n",
" self.samples.pop(0)\n",
"\n",
" def sample(self, n):\n",
" ...............\n",
" \n",
"capacity=100000\n",
"memory=Memory(capacity)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Deep Q-network algorithm"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To train the neural network, we need to work with a supervised learning approach. We want the neural network to approximate the optimal Q-function which is, following the Bellman equation:\n",
"$$Q^{new}(s_t,a_t)=Q^{old}(s_t,a_t)+\\alpha (r_t+\\gamma \\underset{a}{max} Q^{old}(s_{t+1},a_t) -Q^{old}(s_t,a_t))$$\n",
"You can notice that the optimal Q-function is then:\n",
"$$Q^{*}(s_t,a_t)=r_t+\\gamma \\underset{a}{max} Q^{old}(s_{t+1},a_t)$$\n",
" \n",
"So, for the training, you just need an x array containing each of the _batchsize_ samples, and an y array with all entry $Q^{old}(s_{0},a)$ except for the one corresponding to the action that the agent took, which will be $y[a]=r_t+\\gamma \\underset{a}{max} Q^{old}(s_{t+1},a_t)$\n",
"\n",
"**Example**\n",
"If the first sample is ($s_0$, $a=1$, $r_0$, $s_1$), I will have:\n",
"$$ x[0]=s_0$$\n",
"$$ y[0]=[Q^{old}(s_{0},a=0), r_0+\\gamma \\underset{a}{max} Q^{old}(s_{1},a)]$$\n",
"\n",
"You can estimate $Q^{old}(s,a)$ with the neural network."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"batch_size = 64\n",
"discount_factor = 0.99\n",
"\n",
"def DQN_update(): \n",
" batch = memory.sample(batch_size)\n",
" len_batch = len(batch)\n",
"\n",
" states = np.array([ o[0] for o in batch ])\n",
" states_ = np.array([ (np.zeros(input_dim) if o[3] is None else o[3]) for o in batch ])\n",
"\n",
" prediction = .............\n",
" prediction_ = ..............\n",
"\n",
" x, y = np.zeros((len_batch, input_dim)), np.zeros((len_batch, output_dim))\n",
"\n",
" for i in range(len_batch):\n",
" state = batch[i][0]; action = batch[i][1]; reward = batch[i][2]; state_ = batch[i][3]\n",
"\n",
" target = prediction[i]\n",
" if state_ is None:\n",
" target[action] = reward\n",
" else:\n",
" target[action] = ..............\n",
"\n",
" x[i]=state\n",
" y[i]=target\n",
"\n",
" model.fit(x, y, batch_size=64, epochs=1, verbose=0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Define learning and exploration rates"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"min_eps=0.01 \n",
"max_eps=1 \n",
"gamma=0.02\n",
"\n",
"def get_explore_rate(episode):\n",
" return ..................."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Rule for selecting an action"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This function is very similar to the Q-table case, but now you will predict the Q-values of each action by employing the _predict()_ function of your keras model."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def select_action(state, episode):\n",
" explore_rate = get_explore_rate(episode)\n",
" \n",
" if random.random() < explore_rate:\n",
" return env.action_space.sample()\n",
" else:\n",
" return ................"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simulation"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Episode: 0 Total reward: 15.0\n",
"Episode: 1 Total reward: 19.0\n",
"Episode: 2 Total reward: 10.0\n",
"Episode: 3 Total reward: 15.0\n",
"Episode: 4 Total reward: 12.0\n",
"Episode: 5 Total reward: 10.0\n",
"Episode: 6 Total reward: 18.0\n",
"Episode: 7 Total reward: 13.0\n",
"Episode: 8 Total reward: 21.0\n",
"Episode: 9 Total reward: 23.0\n",
"Episode: 10 Total reward: 14.0\n",
"Episode: 11 Total reward: 29.0\n",
"Episode: 12 Total reward: 41.0\n",
"Episode: 13 Total reward: 11.0\n",
"Episode: 14 Total reward: 8.0\n",
"Episode: 15 Total reward: 10.0\n",
"Episode: 16 Total reward: 12.0\n",
"Episode: 17 Total reward: 38.0\n",
"Episode: 18 Total reward: 21.0\n",
"Episode: 19 Total reward: 21.0\n",
"Episode: 20 Total reward: 31.0\n",
"Episode: 21 Total reward: 14.0\n",
"Episode: 22 Total reward: 11.0\n",
"Episode: 23 Total reward: 13.0\n",
"Episode: 24 Total reward: 12.0\n",
"Episode: 25 Total reward: 13.0\n",
"Episode: 26 Total reward: 16.0\n",
"Episode: 27 Total reward: 12.0\n",
"Episode: 28 Total reward: 13.0\n",
"Episode: 29 Total reward: 11.0\n",
"Episode: 30 Total reward: 18.0\n",
"Episode: 31 Total reward: 10.0\n",
"Episode: 32 Total reward: 11.0\n",
"Episode: 33 Total reward: 14.0\n",
"Episode: 34 Total reward: 17.0\n",
"Episode: 35 Total reward: 15.0\n",
"Episode: 36 Total reward: 13.0\n",
"Episode: 37 Total reward: 24.0\n",
"Episode: 38 Total reward: 9.0\n",
"Episode: 39 Total reward: 11.0\n",
"Episode: 40 Total reward: 15.0\n",
"Episode: 41 Total reward: 11.0\n",
"Episode: 42 Total reward: 13.0\n",
"Episode: 43 Total reward: 10.0\n",
"Episode: 44 Total reward: 14.0\n",
"Episode: 45 Total reward: 11.0\n",
"Episode: 46 Total reward: 12.0\n",
"Episode: 47 Total reward: 10.0\n",
"Episode: 48 Total reward: 15.0\n",
"Episode: 49 Total reward: 10.0\n",
"Episode: 50 Total reward: 14.0\n",
"Episode: 51 Total reward: 11.0\n",
"Episode: 52 Total reward: 9.0\n",
"Episode: 53 Total reward: 10.0\n",
"Episode: 54 Total reward: 16.0\n",
"Episode: 55 Total reward: 8.0\n",
"Episode: 56 Total reward: 11.0\n",
"Episode: 57 Total reward: 12.0\n",
"Episode: 58 Total reward: 12.0\n",
"Episode: 59 Total reward: 10.0\n",
"Episode: 60 Total reward: 12.0\n",
"Episode: 61 Total reward: 17.0\n",
"Episode: 62 Total reward: 8.0\n",
"Episode: 63 Total reward: 8.0\n",
"Episode: 64 Total reward: 10.0\n",
"Episode: 65 Total reward: 9.0\n",
"Episode: 66 Total reward: 11.0\n",
"Episode: 67 Total reward: 16.0\n",
"Episode: 68 Total reward: 34.0\n",
"Episode: 69 Total reward: 9.0\n",
"Episode: 70 Total reward: 10.0\n",
"Episode: 71 Total reward: 10.0\n",
"Episode: 72 Total reward: 12.0\n",
"Episode: 73 Total reward: 11.0\n",
"Episode: 74 Total reward: 12.0\n",
"Episode: 75 Total reward: 10.0\n",
"Episode: 76 Total reward: 10.0\n",
"Episode: 77 Total reward: 11.0\n",
"Episode: 78 Total reward: 13.0\n",
"Episode: 79 Total reward: 11.0\n",
"Episode: 80 Total reward: 9.0\n",
"Episode: 81 Total reward: 9.0\n",
"Episode: 82 Total reward: 10.0\n",
"Episode: 83 Total reward: 9.0\n",
"Episode: 84 Total reward: 10.0\n",
"Episode: 85 Total reward: 12.0\n",
"Episode: 86 Total reward: 10.0\n",
"Episode: 87 Total reward: 9.0\n",
"Episode: 88 Total reward: 10.0\n",
"Episode: 89 Total reward: 10.0\n",
"Episode: 90 Total reward: 17.0\n",
"Episode: 91 Total reward: 17.0\n",
"Episode: 92 Total reward: 45.0\n",
"Episode: 93 Total reward: 125.0\n",
"Episode: 94 Total reward: 69.0\n",
"Episode: 95 Total reward: 47.0\n",
"Episode: 96 Total reward: 57.0\n",
"Episode: 97 Total reward: 61.0\n",
"Episode: 98 Total reward: 83.0\n",
"Episode: 99 Total reward: 41.0\n",
"Episode: 100 Total reward: 51.0\n",
"Episode: 101 Total reward: 37.0\n",
"Episode: 102 Total reward: 57.0\n",
"Episode: 103 Total reward: 53.0\n",
"Episode: 104 Total reward: 47.0\n",
"Episode: 105 Total reward: 124.0\n",
"Episode: 106 Total reward: 70.0\n",
"Episode: 107 Total reward: 108.0\n",
"Episode: 108 Total reward: 83.0\n",
"Episode: 109 Total reward: 191.0\n",
"Episode: 110 Total reward: 53.0\n",
"Episode: 111 Total reward: 67.0\n",
"Episode: 112 Total reward: 83.0\n",
"Episode: 113 Total reward: 65.0\n",
"Episode: 114 Total reward: 76.0\n",
"Episode: 115 Total reward: 47.0\n",
"Episode: 116 Total reward: 72.0\n",
"Episode: 117 Total reward: 94.0\n",
"Episode: 118 Total reward: 200.0\n",
"Episode: 119 Total reward: 200.0\n",
"Episode: 120 Total reward: 108.0\n",
"Episode: 121 Total reward: 62.0\n",
"Episode: 122 Total reward: 53.0\n",
"Episode: 123 Total reward: 94.0\n",
"Episode: 124 Total reward: 57.0\n",
"Episode: 125 Total reward: 200.0\n",
"Episode: 126 Total reward: 138.0\n",
"Episode: 127 Total reward: 117.0\n",
"Episode: 128 Total reward: 60.0\n",
"Episode: 129 Total reward: 133.0\n",
"Episode: 130 Total reward: 67.0\n",
"Episode: 131 Total reward: 200.0\n",
"Episode: 132 Total reward: 103.0\n",
"Episode: 133 Total reward: 75.0\n",
"Episode: 134 Total reward: 155.0\n",
"Episode: 135 Total reward: 200.0\n",
"Episode: 136 Total reward: 200.0\n",
"Episode: 137 Total reward: 125.0\n",
"Episode: 138 Total reward: 161.0\n",
"Episode: 139 Total reward: 195.0\n",
"Episode: 140 Total reward: 200.0\n",
"Episode: 141 Total reward: 200.0\n",
"Episode: 142 Total reward: 193.0\n",
"Episode: 143 Total reward: 193.0\n",
"Episode: 144 Total reward: 195.0\n",
"Episode: 145 Total reward: 200.0\n",
"Episode: 146 Total reward: 200.0\n",
"Episode: 147 Total reward: 200.0\n",
"Episode: 148 Total reward: 200.0\n",
"Episode: 149 Total reward: 200.0\n",
"Episode: 150 Total reward: 200.0\n",
"Episode: 151 Total reward: 200.0\n",
"Episode: 152 Total reward: 200.0\n",
"Episode: 153 Total reward: 200.0\n",
"Episode: 154 Total reward: 195.0\n",
"Episode: 155 Total reward: 200.0\n",
"Episode: 156 Total reward: 200.0\n",
"Episode: 157 Total reward: 200.0\n",
"Episode: 158 Total reward: 200.0\n",
"Episode: 159 Total reward: 200.0\n",
"Episode: 160 Total reward: 200.0\n",
"Episode: 161 Total reward: 200.0\n",
"Episode: 162 Total reward: 200.0\n",
"Episode: 163 Total reward: 200.0\n",
"Episode: 164 Total reward: 200.0\n",
"Episode: 165 Total reward: 200.0\n",
"Episode: 166 Total reward: 200.0\n",
"Episode: 167 Total reward: 200.0\n",
"Episode: 168 Total reward: 200.0\n",
"Episode: 169 Total reward: 200.0\n",
"Episode: 170 Total reward: 200.0\n",
"Episode: 171 Total reward: 200.0\n",
"Episode: 172 Total reward: 200.0\n",
"Episode: 173 Total reward: 200.0\n",
"Episode: 174 Total reward: 200.0\n",
"Episode: 175 Total reward: 200.0\n",
"Episode: 176 Total reward: 200.0\n",
"Episode: 177 Total reward: 200.0\n",
"Episode: 178 Total reward: 200.0\n",
"Episode: 179 Total reward: 200.0\n",
"Episode: 180 Total reward: 200.0\n",
"Episode: 181 Total reward: 200.0\n",
"Episode: 182 Total reward: 200.0\n",
"Episode: 183 Total reward: 200.0\n",
"Episode: 184 Total reward: 200.0\n",
"Episode: 185 Total reward: 200.0\n",
"Episode: 186 Total reward: 200.0\n",
"Episode: 187 Total reward: 200.0\n",
"Episode: 188 Total reward: 200.0\n",
"Episode: 189 Total reward: 200.0\n",
"Episode: 190 Total reward: 200.0\n",
"Episode: 191 Total reward: 200.0\n",
"Episode: 192 Total reward: 200.0\n",
"Episode: 193 Total reward: 200.0\n",
"Episode: 194 Total reward: 200.0\n",
"Episode: 195 Total reward: 200.0\n",
"Episode: 196 Total reward: 200.0\n",
"Episode: 197 Total reward: 200.0\n",
"Episode: 198 Total reward: 200.0\n",
"Episode: 199 Total reward: 200.0\n",
"Episode: 200 Total reward: 200.0\n",
"Episode: 201 Total reward: 200.0\n",
"Episode: 202 Total reward: 200.0\n",
"Episode: 203 Total reward: 200.0\n",
"Episode: 204 Total reward: 200.0\n",
"Episode: 205 Total reward: 200.0\n",
"Episode: 206 Total reward: 200.0\n",
"Episode: 207 Total reward: 200.0\n",
"Episode: 208 Total reward: 200.0\n",
"Episode: 209 Total reward: 200.0\n",
"Episode: 210 Total reward: 200.0\n",
"Episode: 211 Total reward: 200.0\n",
"Episode: 212 Total reward: 200.0\n",
"Episode: 213 Total reward: 200.0\n",
"Episode: 214 Total reward: 200.0\n",
"Episode: 215 Total reward: 200.0\n",
"Episode: 216 Total reward: 200.0\n",
"Episode: 217 Total reward: 200.0\n",
"Episode: 218 Total reward: 200.0\n",
"Episode: 219 Total reward: 200.0\n",
"Episode: 220 Total reward: 200.0\n",
"Episode: 221 Total reward: 200.0\n",
"Episode: 222 Total reward: 200.0\n",
"Episode: 223 Total reward: 200.0\n",
"Episode: 224 Total reward: 200.0\n",
"Episode: 225 Total reward: 200.0\n",
"Episode: 226 Total reward: 200.0\n",
"Episode: 227 Total reward: 200.0\n",
"Episode: 228 Total reward: 200.0\n",
"Episode: 229 Total reward: 200.0\n",
"Episode: 230 Total reward: 200.0\n",
"Episode: 231 Total reward: 200.0\n",
"Episode: 232 Total reward: 200.0\n",
"Episode: 233 Total reward: 200.0\n",
"Episode: 234 Total reward: 200.0\n",
"Episode: 235 Total reward: 200.0\n",
"Episode: 236 Total reward: 200.0\n",
"Episode: 237 Total reward: 200.0\n",
"Episode: 238 Total reward: 200.0\n"
]
}
],
"source": [
"max_episodes = 1000\n",
"max_t = 250\n",
"combo_goal = 100\n",
"timesteps_goal= 195\n",
"\n",
"combo = 0\n",
"R=[]\n",
"\n",
"\n",
"for episode in range(max_episodes):\n",
" state = env.reset()\n",
" cumulative_reward = 0 \n",
" for t in range(max_t): \n",
" #self.env.render()\n",
" action = select_action(state, episode)\n",
" next_state, reward, done, info = env.step(action)\n",
" if done:\n",
" if (t >= 150): \n",
" combo += 1\n",
" else: \n",
" combo = 0\n",
" next_state = None\n",
" memory.add( (state, action, reward, next_state) )\n",
" DQN_update() \n",
" state = next_state\n",
" cumulative_reward += reward\n",
" if done:\n",
" break\n",
"\n",
" print('Episode: {}'.format(episode), 'Total reward: {}'.format(cumulative_reward))\n",
" R.append(cumulative_reward)\n",
" if combo > combo_goal:\n",
" break"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD8CAYAAAB+UHOxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJztvXmYXGWd9/35nVp6S2fppElCFpJAwiqEEDAKIg4jIvqIqOO4Di7Pg87o9ejo8/o6+s6oozOvzijO66PiwIjC6ODyoAPOoIDIMioQQwghISQkIStJp5NOp/dazrnfP85Sp6pOdVV1dXdVUr/PdeWq6rNU3QdO3d/zW28xxqAoiqI0H1a9B6AoiqLUBxUARVGUJkUFQFEUpUlRAVAURWlSVAAURVGaFBUARVGUJkUFQFEUpUlRAVAURWlSVAAURVGalHi9BwAwb948s2zZsnoPQ1EU5aTiqaeeOmqM6Z7o+Q0hAMuWLWPDhg31HoaiKMpJhYjsreV8dQEpiqI0KSoAiqIoTYoKgKIoSpOiAqAoitKkqAAoiqI0KWUFQESWiMjDIvKciGwVkY9527tE5EERecF7neNtFxH5hojsFJHNIrJmqi9CURRFqZ5KLIAs8EljzHnAOuAjInIe8GngIWPMSuAh72+A1wMrvX83AbdM+qgVRVGUmilbB2CMOQQc8t4Pisg2YBFwPXCVd9gdwCPA/+1tv9O4a00+ISKzRWSh9zmKclIwnMpyx+N7SGcd3nHpUhbMai06ZiSd5VdbDnPDxYsQkaL92w8PMjiWYe2yrmDbi0eH+fnTB5nREuP9ly8nEXOfwWzH8L3fvcjAaIY3XnQ6q+Z3Buf8ftdRnth1rKJxnzW/kzdddDo/f/oAL/YOV3nVSj1YtaCTN154el2+u6pCMBFZBlwMPAnMD03qh4H53vtFwP7QaQe8bXkCICI34VoILF26tMphK8rU8viuY/zDr7YDkIxb/MVVZxUd89C2I3ziJ8+wZukcls3rKNr//z20gz1HR7jvY68Ktt35+B6+97s9AFy2fC6rl8wG4Mndx/jSf24DYFfvMN96d85z+um7n2Vf3wgRGpOHMWAJXLR4Fn/542cAyp6j1J83Xnh64wuAiMwA7gY+bowZCD/xGGOMiFS1urwx5lbgVoC1a9fqyvRKQ5Gxndz7bPTt6R+TyjqR+9NZh7Sdv28sY0d+xxO7j2EJrFsxl22HB4LtB/tH2dc3wt+88Tw+cMXyccf8+51Hede/PMm3Ht4JwN1//kouOWPOuOcozU1FWUAiksCd/H9ojPmZt7lHRBZ6+xcCR7ztB4ElodMXe9sU5aTBNrlJ33aiJ3jbcY/J2NH7HQOOky8eYbHI2rl9T+zu44JFs1i7rIs9R4cDoXhyt+v6efmKLspx8dI5JGMWd288SFsixoWLZ5U9R2luKskCEuC7wDZjzM2hXfcCN3rvbwTuCW3/My8baB1wQv3/ysmGHZq4w2IQxt9cWgAM2QIBSIcEwP+OsYzNpv39rFsxl3MWdOIYeKFnCIAnd/cxqy3BuQtmlh1zWzLGRUtmYTuGtcvmBPEFRSlFJXfI5cB7gT8SkU3ev+uALwOvFZEXgD/2/ga4D9gN7ARuA/5i8oetKFOLE5r0CyfxwmNK7bcdkyckkC8AGc+y2LjvOGnbYd2KLs5e4AZ/n/fcQE+8eIxLl3VhWZU589etmJv3qijjUUkW0G+BUnff1RHHG+AjNY5LUepK+KG+0I0TbC9jARiTLyQAadvBEvdc23MBPfeSO9lfvGQOM9sStMQtth8e5Pc7j7L32AgfuHx833+Y15xzGt9+ZBevXjXhDsFKE9EQ7aAVpdEIT/ol5vfANRT25eftL2EBtCfjDKWygeUwnHL9/TPbEsQsYdX8Ttbv6eOh549wxtx2/vTSJUWfXYo1S+fwzOeuYUaL/rSV8qiTUFEiqCQIbAIXUOkYQJQAtCVj3ud6MYCsTSImxDw3z+ols9l84AR7jw3zpTdfQGsiVtXYdfJXKkXvFKVp6B9JE49ZFU2QlQSBnSALqHSQuPDcVNahIxmjl5xwjGVsWuO5Sf6zbziXt69dwpyOBIvntJcdq6JMFLUAlKbhz3+wkS/cu7WiY33fvSUUPcXnjnFfS7qASloA8bzzxjI2LaGn/NZEjJctnqWTvzLlqAAoTcOx4RTHR9IVHetP3Mm4NY4AlKsDiBAA26G90AWUcWhL6k9RmX70rlOaBtsxlJjLI48FSMSssmmgJQWgZBDYFYBsqA4g7AJSlOlCBUBpGhxT2p1TfKxnAcSssmmgpQWiOA00lScAoRhAlYFeRZkMVACUpsG1ACoTAP+hvhILIFuNCyhr014UA3BoTehPUZl+9K5TmgbbMVQ4/weTeyIuJUUj1wqidB2AY3LpouDGAKLSQNUCUOqBCoDSNDimGgsg5wIq5Tbyt5eqA/C/Knx+OuvQniiMATi0aAxAqQMqAErTEFWZO96x4LqAymcBlU4DDb9mbQfHQHtLPPgbIJWx1QWk1AW965SmwTETcAGNKwDua6k6AP8z/PP9tQE6orKA1AWk1AEVAKVpiMrKKYXtGGKW256hVBDYlEkDLXQB+Z1Ak3GLmCWhGIAGgZX6oHed0jTYjinZ1qHoWGOIiSsApUQjWBCmzIIx/u5CAdA6AKXeqAAoTYNTRSGY4xgsC3eiLunicV/LuoC8V381sGTMIm4JtuNgjFEXkFI3VACUpsE2Ji8lc9xjHVwLQMZLAy1TB1CQJZQKWQBxS8jYhrQXGFYXkFIPKlkS8nYROSIiW0LbfhxaHWyPiGzyti8TkdHQvu9M5eAVpRqqyQJyjMGyhHisdAwgyAIqEyQudAG1xC3iXnB5LONuUwtAqQeVtIP+PvBN4E5/gzHmT/33IvI14ETo+F3GmNWTNUBFmSzcOoDKjvWDwJZI+VYQ41QCQ84F5GcBhWMAKW/xdxUApR5UsiTkYyKyLGqft2D824E/mtxhKcrk41YCVxcEjo+TBRQUgpWLAdgFWUCxWBADUAtAqSe1Oh5fBfQYY14IbVsuIk+LyKMi8qoaP19RJgXjPf1XmgbqBoEFK5SuGfWZUN4FFFgA4RhAzA0uj2V9C0BjAMr0U+uKYO8E7gr9fQhYaow5JiKXAP8uIucbYwYKTxSRm4CbAJYuXVrjMBRlfILJuIpK4HJB4GBR+GwZF1BQCOZO9m4Q2G0yN+a7gDQNVKkDE37sEJE48Bbgx/42Y0zKGHPMe/8UsAtYFXW+MeZWY8xaY8za7u7uiQ5DUSrCn4QrrQS2jVcIVkEQuFQvoKAOoNACiOUKwdQFpNSTWuzOPwaeN8Yc8DeISLeIxLz3K4CVwO7ahqgoteNPwtW5gNxU0NJB4PJrAkMuRlCYBpp1nJwFoC4gpQ5UkgZ6F/A4cLaIHBCRD3q73kG++wfgSmCzlxb6f4APG2P6JnPAijIR/KfxyiuBKRsE9h/8q7UAWsIxAM0CUupIJVlA7yyx/X0R2+4G7q59WIoyufgTf4m5uohwEHiiFkCpZnBuGqgXA8j6LiC1AJTpR+86pSlwghhAdUHgcS2AMnUAgQuosBlc0AoiZwHoegBKPVABUJqC6l1AXiHYOM3gckHg8dcDKHIBJfxCMEcLwZS6ogKgNAW5ybiy4x3HYJW1AKpzAYWbwSW8GMCoBoGVOqJ3ndIU+L7/qiqBvVYQ5RaEiVoPwIQWn3FCLiBLIB4LxQA0DVSpIyoASlPgVGkB2F4QOD5OJXDgAooQgPAp2VAQOBl3f3LhGEDcEhIx/Skq04/edUpTEMQAqugGGhPyVu4qxIzjAgrHDcKtIJLeRO83gxvLOPr0r9QNFQClKai2ECzoBlrBimBRdQBh0XBCMYCkl+2TiHnN4LK6ILxSP/TOU5qCaltBOA4VBIHd16huoCbKBZR1aIn7FoAVFIJpCqhSL1QAlKagMCOnHOEgsDFEFoONtyh8ON3UKREDcNcD0AXhlfqhd57SFPhzdLUuoLgl7t8R5wUWQIQ4RMcA7LwYgB8E1hiAUi9UAJSmoGoXkHHrACxfACIm+fEWhDFO8XHpbM4CSMS8ZnBZFQClfqgAKE1B4fKM5SiyAMZ5yk/bTlF9Qfh77AgXUMzym8GpC0ipH3rnKU1BYWfOSo63RIiN4wIKbyoUCCdKAEJpoOEFYXQxGKVeqAAoTYE/gRtTWTWwYwwxi5wAlMn1L4wDhIPG4V5AYQtAYwBKvVEBUJqC8IRciRHgu4DGswDCAlCYCRRVCZwKCUDcjwFkHFrUBaTUCb3zlKYg7KKpJA7gGPJdQFExgNCcXxgIdipJA/XqANrUAlDqhAqA0hTk5eVXIACBBSDlg8AAmYJq4DzBCbWhSHiCEgvHAFQAlDpRyZKQt4vIERHZEtr2eRE5KCKbvH/Xhfb9lYjsFJHtIvK6qRq4olRDeH6u2AVUzgIIxwAKLIC8AHGoYjhm5SwAgJGMtoJQ6kcld973gWsjtn/dGLPa+3cfgIich7tW8PneOd/2F4lXlHoSlZY5Ho5xu4GOLwC59+O5gGxPfWzHBBN/POa+GoNmASl1o6wAGGMeAypd2P164EfGmJQx5kVgJ3BZDeNTlEkhKitnPIosgDJB4HRBEDhfcNzXrGOIeRO/LwSgawEo9aMW2/OjIrLZcxHN8bYtAvaHjjngbVOUupLXnbMCF1BlFkA4DTRfAExEzMF2nGDi911BoKuBKfVjonfeLcCZwGrgEPC1aj9ARG4SkQ0isqG3t3eCw1CUyojKyhkPNwjM+EHgcbKA7Ih9WS+wDPkWQItaAEqdmJAAGGN6jDG2McYBbiPn5jkILAkdutjbFvUZtxpj1hpj1nZ3d09kGIpSMc5EsoAqCAL7lb3FdQDFaadRMQBQF5BSPyYkACKyMPTnDYCfIXQv8A4RaRGR5cBKYH1tQ1SU2gnPz5W5gKjIBeTn9RdVAkdYHK4FkJ8FBNAaVxeQUh/i5Q4QkbuAq4B5InIA+BxwlYisBgywB/gQgDFmq4j8BHgOyAIfMcbYUzN0RamcCdUBhCyA6JbPuAKQirAAwt1AIyyA/BiAWgBKfSgrAMaYd0Zs/u44x/8d8He1DEpRJpuqs4BMfiuIqHMcY4IVvsZPAzUYY4LiMtAsIKUxUNtTaQqqzgJyymcBGUNOAAorgQsEwD8/OgagP0OlPuidpzQFUUs0ljs+JuVbQfgxgHS2sBI4XwB8F1JUHYD2AlLqhQqA0hRU4wIyxmC8ILD/pF5qRbBkCQsgfHiUBaAxAKURUAFQmoL8IHCZY/2ndXEXhQ9vC2MMQRpocR1AfhpoYAFEZAFpO2ilXuidpzQF1VgAvljkLQhTwgXU4vXxGa8OwCkbA1ALQKkPKgBKU5AXBC5jAvjenHAQODoNdJw6gIJF4X0XUSxwAYXrAFQAlPqgAqA0BWEPTVkXkMm5gMZLA7UdcgIwXiVwlAXguYIsgUTIGlCU6UQFQGkKqnIBBf56CSbsKAvAGEN70n16H83k1zsWtoLwYwSFFkBrIoaICoBSH1QAlKagmvUAfLGwQkHgKLeRYwydrXFEYHAsW7Qv/H2BBVCQBqr+f6WeqAAoTUF40i9XCJwLAkvgqinVCiJuWcxoiRcLQEEMIPeZuUXhQfsAKfVF7z6lKajGBRRYAJbgp+tHWgCOQQRmtiYYGMvk76swBqAWgFJPVACUpqCaZnDhILA/UZdaEcwSobM1ZwHYjuGHT+4NVgizxD3OjwH4LiU/BqBrASj1RAVAaQomFgQmsABKuYAs3wIYdS2AjfuO89mfb+HJ3e4qqvGYVcICcF/btAhMqSN69ylNQXj+LpcGGtQBhCyAUkHgQgsgnXVP9rOCkjGLbLgOIJZfCKYuIKWeqAAoTUE1zeDCQWC/GVx0GqgbJ+hsjTOYci0AvyI45QlBIiY4RmMASmOiAqA0BeFJP8qfHyZcB+A/sUeJhm0MlkBnayIvBgCQzroWgO8CyoY+M/yqraCVeqJ3n9IUVJMG6scILBnfAvBdQDPbXBeQCTV9811ByaIYQH4zOG0DodSTsgIgIreLyBER2RLa9o8i8ryIbBaRn4vIbG/7MhEZFZFN3r/vTOXgFaVSqsoCCj2tB2mgBef4LaNFhM7WBLZjGEnbQbaPnwWUiEmkBeDHADQLSKknlVgA3weuLdj2IHCBMeZCYAfwV6F9u4wxq71/H56cYSpKbeS5gMrFAEKVwEEhmF0oAO5rzAsCg1sN7Ad700EMwMI2YHvbi2MAaoQr9aPs3WeMeQzoK9j2gDHGL318Alg8BWNTmhhjDDt6Bift88IWQKUuoJgl+E07C+MGduAmcmMAAINjmUA8/CBwPGbhOOP3AlKUejEZjx8fAH4Z+nu5iDwtIo+KyKtKnSQiN4nIBhHZ0NvbOwnDUE4lnt7fzzVff4znDw9M6PwjA2OMpHPtGcLNOqupAxCvI6hdtOJXrlrYtwAGxrI5F1AQAxCyJXoBzWlPsHBW64SuT1Emg5oEQEQ+C2SBH3qbDgFLjTEXA58A/k1EZkada4y51Riz1hiztru7u5ZhKKcg/SNpAI4PZ8ocGc1bv/N7vvPIruDv/EKw8c8NB4HBdfMUdHsOrAi3FYTvAsoUBYETvgVQkAZqWcJvPnkV77xs6QSuTlEmhwkLgIi8D3gj8G7jrYBtjEkZY455758CdgGrJmGcSpPhP0kXrrVbKX1DaY4Op4O/q+kG6k/2YXdNodUQFomZgQsoG1gKOReQYIfqAMJrAc/pSJKIaQxAqR8TuvtE5FrgU8CbjDEjoe3dIhLz3q8AVgK7J2OgSnPhT5iFSy1WStYxZLK5c528NNAKXUChvj2FQWAnLwjsCsDAWIaMnR8DSBTUAYTXAlaUehMvd4CI3AVcBcwTkQPA53CzflqAB73FLJ7wMn6uBP5WRDKAA3zYGNMX+cGKMg45V0oZf00JwpMuVLcofNi/D9EWgC8SIuRlAfmi4ReC5eoA8peEVJRGoKwAGGPeGbH5uyWOvRu4u9ZBKYo/wU7EBeQXZKVD1oNdQgzG++6wC6hwHCbkAmpPxohZwuBYho4W9yflf3e8oA5ALQClkVAHpNKQZGtwAflzfZ4LyJhgQi/rAioMAlvFQWD/OyxxM4X8RWHsgiygRMzK6wWkFoDSSKgAKA2J7zLJTMAF5D+tZwosAP/pu9IFYQILQEqngfrH+B1BfeHyBSLoBmrnt4JQlEZA70alIQksgAm4gPzJNhMK3NoOQcZNOaMiKghcZAEEMQBfABJeGmj+gfGY4ITqAPzmcorSCKgAKA1JkAWUnYAA+AFkO98F5BdhlbUAgiCw+3d0IZj76ruJWhMWqaxT1DTObQWhMQClMVEBUBqSqKf4SolKIXWMCSyA8mmg7ms4CFw4DCfUCgIgYVlkbCeIAfgkYha2rVlASmOiAqA0JHYtLqASMYBEEAMo890mygVUohWEd0wi7tYKFFoAcUvyLAD/MxWlEVABUBqSIAYwgSCwHXGu6wKy8vaXwvfvW3lB4IJCMH/ZyFB3z4zt5MUAYpbfR8iNAViSO15RGgEVAKUh8Z+wJ5IGGriPnAILIFZhGmglQeBCF1DMImObPKHwJ3zHswA0A0hpNPSOVBqSqEm8UiJjAKEsoIpdQFYVLqCYkLGdvJiFiBC3ct1A1f+vNBoqAEpDUlsdQLELyA5lAZVzAZmIVhDFQWD3VfIsACfvs2MiWCIY4wqaZgApjYYKgNKQ1FIJXDIIHFgAFWYBjRMENgVWgu8Cyha4gPz9advWGgCl4SjbC0hR6kEtvYDC6/LuOTrMP/16B2MZO2jbXG5FMDuiDqCwG2hhuwjfBZQNiY7lBYHBbQ2hFoDSaKgFoDQktXQDDccAnth9jH/f9BJ7j43kXECVtoIITe6F6Z1BFlDIBZR1Ci2AnACkso7GAJSGQwVAaUhqWQ8g5z4yjGXctsyjGbsKF1C+eycZs4Lmbj7+Z/itIOIxIZMtsACEUHtoR7OAlIZD70ilIfFdPxNxAfkTuO0YRjwBAEJpoOOfX7geQCJCAPzP8F1AyZhFxslvBRGzJPiMtFoASgOiAqA0JHYNLqCwaAyncgvD+0/gTpksoMI6gGTcyusrBOFUUe+zY1JUB+CngYLrAtIYgNJoqAAoDUmuF9DELQCAobGQAFQYAyisA0jGy7uA/KUfMwUuILUAlEamIgEQkdtF5IiIbAlt6xKRB0XkBe91jrddROQbIrJTRDaLyJqpGrxy6lJTFlBIAAbzLIDKegEFrSC8yb0lwgIwRVlA7k9pNORyiomQ9ERnJJNVAVAajkotgO8D1xZs+zTwkDFmJfCQ9zfA63EXg18J3ATcUvswlWajll5A4ZTNwZAFYFmCJdV3A40OAnufGWQBuW/GMrnjRIT2ZG694LjWASgNRkUCYIx5DChc3P164A7v/R3Am0Pb7zQuTwCzRWThZAxWaR6CGMCEXEC5c8IuIL8yt1wlsF3Q5yfKBWQ7JSyAdMgCsNz1giF/wXhFaRRqiQHMN8Yc8t4fBuZ77xcB+0PHHfC25SEiN4nIBhHZ0NvbW8MwlFORWrKAwi6goZALKGa5AlCJC8hf6xeig8CFvYD8TqNjIReQJdDmCcDAaEZdQErDMSlBYOPa1FXZ6saYW40xa40xa7u7uydjGMopRFRL52rPBRgcywTvLUuwrMoWhQ9P1slYLGjp7GMKXEC+r380TwCEDs8FpN1AlUakljuyx3fteK9HvO0HgSWh4xZ72xSlYmrqBWSXsAAqdAG5FkBIAOLuzyTsBiqsFfAn9zwBCLmAQFcDUxqPWgTgXuBG7/2NwD2h7X/mZQOtA06EXEWKUhG1xQCig8CVuoAKWzdHC4D7GgSB4/5yk7nPCbuAAA0CKw1HRc3gROQu4CpgnogcAD4HfBn4iYh8ENgLvN07/D7gOmAnMAK8f5LHrDQB/lN8YRO2is4NzfCpbDgv380CKtsKwpi8gK0vACnbBtyGcoWposmIyT3sAgK1AJTGoyIBMMa8s8SuqyOONcBHahmUotTSC6iwdbNPzMqt0DUejmPylm70J3ffAth+eJDeoRQQCgJH+PctkXwLQAVAaTC0HbTSkPjZPxNxAWVKWA1W4AIaXwDSdm75SCh2Ab3/e+uDrJ/covARAmC5RWSu1aEWgNJ4qAAoDUlQCTwBF1CpIK8fBC4XAxhOZZnRkvtpJGPuU7wvLCdGM4GFEKwIFjG5x0QQzw00mMpqFpDScOgdqTQkta0IVkIAKqwEHhzL0OktHgPFFkDadoKCrygLwNcCv47AdwOpBaA0GioASkOS6wVkyk7YxedGi4ZVYRroUKEF4AuAbXsN33ILv4SXhPRpS8S873P/9lNBNQagNBoqAEpDEn6KL+XTr+RcyPXp8S2Aci6gwbEsna1hF5CXBZR1ilpC+HN6eHJvTeQ/8fv9gNQCUBoNFQClIbHzBKA6N1DhE/7cjhYgt0BLuSDw4FiWGa0RFkDWIZW1844Nt4vw8QXA3xdYAFoHoDQYKgBKQxLuAVStABRaAF0dSSDnAiq3IMzgWCZYQB7cTB5wBaASC6Al4R4f0xiA0uCoACgNiW1P3AVUaAH4AhCzKOsCMsaMEwNw8grL3M8sjgG0xr0YgLfJLwbTLCCl0dA7UmlIsl5HTqjeAsjYTl4e/9wZIQugjAtoNGPjGPJdQLHSLqDCdtCQe+K3ClxAagEojYYKgNKQ2I4JfOkTiQH450LYAihfCOb3DgoHgRMhF1B4wRcI1QHEwkHg/CKxNs0CUhoUFQClIcnmCUD1WUB+BS5AV3s4BgDjLTHgC0B+IVjOBVRYmRxVBxC4gLzv72jRLCClMVEBUBoS2zFBPn2hBfDe7z7Jtx7eWfpc2+2977tl5s9sBdwnc98CMMZwzdcf5cd/2Jd3rr9+wMwShWCpTAkBsIqzgPwJ378OtQCURkMFQGlIso4TZNMUCsDmAyd4oWdwnHPdds7+k/uiOW18732X8oYLTw9aQYykbXb0DLH1pYG8c/31A8IxgJa8IHBBDMD7BYVdQP64C9NAYxoEVhoM7QWkNCT5FkB4JS43S6cwGyf/XId4TFy3TMqdwC8/ax7gTtiOMRwfSQNuX58wUTGA/CBwtAUQiygECyqBPReQ1gEojYY+kigNSbaEC2g047ZjKMzHLzw3ZknwVB4OCMc8F9DxYXfi7x/JF4ChiBiAZQlxS0rUAfhN4XIWR1thJXBCs4CUxkQFQGk4HMdgDJFZQP4EPb4FYIhbEsQAWkIBWvFcQH2eBdBfYAEMeDGAcDM48BaGj7QAcu/jgeBEu4A0BqA0GhN2AYnI2cCPQ5tWAH8DzAb+B9Drbf+MMea+CY9QaTr8Sl5fAMItoQc8ARjPAsjYhphlkYy557XEcxaAmwVkOD7sCsBAgQAEMYCW/J9GMm6ViAHkJnVXcOxQFpAnAJoFpDQoExYAY8x2YDWAiMRwF37/Oe4SkF83xnx1UkaoNB1+Ja+fPx9OvfQn6MKJOP98h7glOJ4F4D+RA0EWUJ8nAP2eJRB8/liWjmSsaLJOxqxxs4AgVwwWZAFpN1ClwZksF9DVwC5jzN5J+jylifH7ALXGi7OA/DTN8VxAfgzAd8nkWQBeJXA4CLz5QD8f+tcNZGynqBGcj+8CKq4DyL1PFLiAiiuB1eOqNBaTdUe+A7gr9PdHRWSziNwuInMm6TuUJqHQAgi7gIYqcAHZjrukYxADyLMA3EIw3wJwDNyz6SXu39rD0aEUQ6lskf8fXAsgZVdmAbT4WUBF7aDLXrqiTCs135IikgTeBPzU23QLcCaue+gQ8LUS590kIhtEZENvb2/UIUqTUhgDSOdZAOWDwIV1AC3xYhdQOPtn2yG3FmAkbTMwliny/0M4CFzYDjr33rc4CheEWdrVzodevYJXrzptnKtWlOlnMp5JXg9sNMb0ABhjeowxtjHGAW4DLos6yRhzqzFmrTFmbXd39yQMQzlVsAsEIM8FlKo0C8giEReScSvIxgE3EBuOAUBOAEbTtmcBjCcABd1AQ5+dLIgBhGsE/ur157JgVmu5S1eUaWUyBOCdhNw/IrIwtO8GYMskfIfSRPgWQFtEFlAuDbR0EDhXB2DlPf1DLg30+EiaOe2rq7+BAAAcvElEQVSuq+e4Zw2MZuyi1cB8/CBwqToAKE4DtTToqzQ4NVUCi0gH8FrgQ6HN/yAiqwED7CnYpyhl8dcCaI1oBeEHgcePAbhZQJYleUVg4K8H4FoAy+d1cHxff7BvJG0znMoG/fvDJOMWqTIuoMIsIJ3/lUanJgEwxgwDcwu2vbemESlNj58F1BYRAxgKuYCMMXnuneB8u7QFEPMWhT8+kuaKlfPYGBKA0XSWoVQ26N4ZJhm3ghYUrQmLsYyDCHnfHwhA3E8DVQVQGhvtBaQ0HONlAflBYHCFIZzi6ZN1DPGY8MfnncaZ3R15+0SEwbEsGduwfG7+Pt8CiAwCh+oAZrYmGMukiiZ4Pw20LZlfCawojYoKgNJw+DGAZMwiERNGMzm3ix8EBtcNFCUAtuNWAt9w8eKifZbAsaEUAAtmtdKWiAWf3zecxjGUtAD8OoBZbQmODKby/P+QswCSsRgiFO1XlEZDM5OVhsO3AGKWMKMlHgR+IRcDgNKZQFnHIVHCAR+zhOG0O+F3dSSZ1ZbL+e/1hKGjpVhUwjEAP0hcOL/7a/7GYkLCsjTvX2l49BZVGg7fAojHhBmt8bxJPywGpQLBthcDiCL8VD6nI8ns9kQQrO0d9AQgIgjc4vcCyji0JmIk41bRE34y7v4dt4Srzz2Ni5dqDaTS2KgLSGk4bC8IHLMsOlsSQeAX3BhAqZx8Hz8GEEV4zu6e0cLMtgTzZ7ZybCjN0SG3NiDSBRTLfWdna5zWuBVYKj6+BRC3hFvec0nlF6wodUItAKXh8IO+ccu3AHICMJTKMtdb5L1ULYDtVGYBzJ2RZN3yLl69qpu2ZCywAKKCwIlQHUBLPEZLIlaU5+/HAOLa80c5SVALQGk4wjGAma1xXuofA9w2zkOpLMvmtXPoxFhJF1DWqwSOIlikJRmjPRnnE9ecDcCjO3oDAWgvEQPw20En4xatCavo+30XUExX/lJOEvRRRWk4ghiAHwT2XEBDafd13owWYJwgsO2UtAB8A8D/DJ+2ZIy+4dIWQNJz+YykbVriFq3xWFGhV9gFpCgnAyoASsMRtgA6WxNBENgPAM/tcCfv8S2A8V1A82Yk87a3J2P4Lv2oGIAvCv0jGVoSFi2J4iBwzgWkAqCcHKgAKA1HzgKwmNHqWgDGGPYeGwFg0Wy3qdp4MYBSQeBYIAD5FkB7IjfpdySLXUCL57QDueKz1nhUDKB4gXhFaWRUAJSGI5cFJHS2xsnYhlTW4dfbekjGLK5c5XaPjbIAjDFeM7joW9vfPDfCBeQTZQEsm9cevE/GfQsg/5jFXe0smt2mFcDKSYMGgZWGI1wH0OlNxgNjGR547jCXnzWXriALqFgAfDdOKTeM8fZ3R7iAwJ3cExEVXEu7cgKQiwHkf8e7L1vKOy5dUu7yFKVhUAtAaTgKYwAAT+05zv6+UV573gKSXoO38OpcvYMpjg2lgkZypdwwJ7xF4Od1RlsAUQFgcFf1Os07pyUeozVRLACWJZHioSiNit6tSsORVwfgTci/2noYgKvPPS3o/5MKdQn9xE828eEfPBWIRykL4Ji3EExRDMATgPYI/7/PGXNdK6AlbjF/ZitzC6wIRTnZUBeQ0nDYJmwBuLfocy8N0NkaZ/7M1uApPhVqEnfoxBg7jwwFNQOlLIDjngD4xWQ+/rq9pSwAgKVdHfxhz3GScYtPXXt20frAinKyoRaA0nDYBVlAALuPDgeZOH6P//A6AQOeKNzvWQqlLIDjI54FUOgC8tYeiAoA+ywLWQCtiRiz2osXj1eUkwkVAKXhyOZVAruTrO0YFs9pA3ICEH4C99tF3PfsIffcEr74WlxAS30BSJQ+RlFOJmoWABHZIyLPisgmEdngbesSkQdF5AXvVdsiKhVje0/24RgAwKLZrgCICMmYFWQBpbMOoxmbZMxi60vuAu+l2kGvPcO9FWcWrPvbXiYIDLBqficAs9v0yV85NZgsC+A1xpjVxpi13t+fBh4yxqwEHvL+VpSKCCwArx20j28BgNeeOeuQtZ2gUnjtstxzRqkYwHffdym//sSVRbn6bV4MYDwX0LkLZ/LvH7mcK86aV+UVKUpjMlUuoOuBO7z3dwBvnqLvUU5Bwpk8iZgVLA7vxwDAzdf//a6jnP+5+9nRMwTAFStzE3OpSuCZrQnOOq2zaLtvAURVAYdZvWR2UQWwopysTIYAGOABEXlKRG7yts03xhzy3h8G5k/C9yhNQjgGADCjxXW5FFoAzx8eJJV12LTfXdh9VWhiL1UJXAq/DmA8C0BRTjUm426/whhzUEROAx4UkefDO40xRkRM4UmeWNwEsHTp0kkYhnKqEM4CAtdff3QoxZICC8DnxaOuBTCrPcGSrjb2941W3ZCtvYIsIEU51ajZAjDGHPRejwA/By4DekRkIYD3eiTivFuNMWuNMWu7u7trHYZyCuFbAP4cPqM1zoyWODPbcpNzeDH4F48OA6575/yFswAYTUc3iitFJXUAinKqUZMAiEiHiHT674FrgC3AvcCN3mE3AvfU8j1Kc2E7DnFLgkDtrLYEi+fkN1kLWwC7ez0BaIuzbkUXAMPpLNXgB5s7W1UAlOah1rt9PvBz74cZB/7NGPMrEfkD8BMR+SCwF3h7jd+jNBHZgiUdP/W6c0jb+U/0LSEB8HP7O1sTvPcVy2hNxLhhzaKqvnPZ3Ha++icX8brzF9QwckU5uahJAIwxu4GLIrYfA66u5bOV5iVr5wvAyxbPKjqmJZFvvFriZvCICO+4rPqYkojwtksWVz9YRTmJ0UpgpeEYy9hBa4ZSJL1KX98rNLMtoX34FaVKVACUhmM0bect0BKFHwQ+s3sGQNAyQlGUylEBUBqOkbQ9bk8eyAWBL1o8GyAvQ0hRlMpoagG4+cEd/OKZl+o9DKWA4XQ2SMssRUvcoi0RY9V8tQAUZaI09WPTnY/v4fKz5vHfLjq93kNRQoxWYAG87ZLFnH/6zGDFMBUARameprUAxjI2/SOZqguGlKlnuAIBePmKubzv8uVBX391ASlK9TStABwZSAHRFaPPHx7gy798HmOKOlgo08BoBS4gn3nesoxqAShK9TStAPQMuksHjmSKBeD+LT1859FdwdKDyvRSSRDYx1/YZab26FeUqmlaATh8whWAsQgLYMRrI9A/ogJQD0YqSAP16Z7RwlvWLOLKVdpPSlGqpWkdpz0DvgVQ3DPG7yNzfCTNMjqmdVzNjjGGkXSWjgpdQJYl3Pz21VM8KkU5NWlaC8AXgKgYwEjK3dbMFkAqa/PN37xAKju9QfJU1sExVGwBKIoycZpYAEoHgYdSngtoND2tY2ok1r/Yx1cf2MH6F/um9XtHvP8flcYAFEWZOE0rAIcHckHgwmwffxI6Pty8FoBv/QyNVddWuVb8+EulLiBFUSZO0wrAEU8AjHHdDmGGgyCwawHsPDLI73Yend4B1pl+LwNqeJrrJHyLTF1AijL1NKUAGGM4PDAW9JMpdAMFMQBvErz5wR38Xz99ZnoHWWdOeOI3nJpeC2BYXUCKMm00pQAMjGUZyzgsm+uuMVtYC+DHAI57bpD9faP0jTRXPCBwAU2zAPguoEoLwRRFmThNKQC9XhHYGXPdFM8iC6DABXSwf5SxjMNYRNHYqYpfBDdS5dKKtTKqFoCiTBsTFgARWSIiD4vIcyKyVUQ+5m3/vIgcFJFN3r/rJm+4k8PRIXdiXzynDSgWAN8N0T+SYTiVpc9bcvB4E1kBQQwgNb2ipy4gRZk+arGzs8AnjTEbvYXhnxKRB719XzfGfLX24U0N/oS+eI7rAhoNPdlnbIe0FxQ+PpLmYP9osO/4cIaFs9qmcaT140SdXECjvguoRV1AijLVTPhXZow5BBzy3g+KyDagupW464S/iPii2e5kHnZz+AHgmCX0j2Q4cHwk2NdMdQH1cgEFdQBlloRUFKV2JiUGICLLgIuBJ71NHxWRzSJyu4jMKXHOTSKyQUQ29Pb2TsYwKubYkFsEFuUC8lNAF8xsZSiV5cWjIQGY5Mrg/X0jDdtwzhe7oWl2AY1oGqiiTBs1C4CIzADuBj5ujBkAbgHOBFbjWghfizrPGHOrMWatMWZtd/f0NPI6PpymZ2CMvuE0s9oSdLa6BlDYBeQ/8S7yxGHrSydy509yDOBd//IEX3tg+6R+5mThi910p4GOpLPELKEl3pT5CYoyrdTkaBWRBO7k/0NjzM8AjDE9of23Af9R0wgniXTW4U9vfZy2ZJzFc9qY25EMnjJHwhaA98S7eHYb64EtB0+waHYbB/tHJ9UCSGVt9veNcuD4aPmDp5mxjB0Ux02/ANi0J2KIyLR+r6I0I7VkAQnwXWCbMebm0PaFocNuALZMfHiTx23/tZsdPUO80DNI31Caro4kbZ6fOZze6buATvfiAzt6hljR3UFbIhakhU4GPSdcN5Qfj2gkwm6p4emOAaQqbwWtKEpt1GIBXA68F3hWRDZ52z4DvFNEVgMG2AN8qKYRTgJZ2+HbD++kNWExkrZ54cgga5bOCQQgygI487RcG+gV8zrYeWQoKAybDF464T759w2nJu0zJwvf0unqSE57GuhIxqZDM4AUZVqoJQvot0CUnX7fxIczMYZSWVrjFvFYtEFz4Pgow2mb11+wgF9uOczRoTRzZ7QQj1kkY1aeAPgxgAsXz+Znf/FKBseyrFk6m/V7jk+qC8hfkKZvqPEsAN/SOX12Kzt6hqb1u0dS2UCYFUWZWk76SFvWdrjm5kf5xkMvFO1zHMNYxmb3UXcSe805pwX75na4a8m2JWP5LiDviXdGS5w1S+fw6lXddLYmmNOeqMoFlM46ZG2n5H7fAhhO2w1XYey7gE6f1UY665AZ5zomm2qWg1QUpTZOegH4w57jvHRijGcPnijad9t/7eaqf3yE7YddAbhqVTeWZ7N0+QKQiOXXAQS9aPInoTntyaqygN512xP87X88l7cta+cm00P9Y8H2vjrEAcYTJ78K2M+EGpkmN9BQKsvAWEaLwBRlmjjpBeDB59yko719I0X7Nu47zuGBMe595iXmdiQ5bWZrUMk7d4YrAO3JGKOZ3GToV74WNiOb1Z4o6QJynPz1BMYyNk/v72fjvuN52z/8g438yXceJ2s7HDqRy/45Ns1uoN29Q5z3uft5umB8Pn4VsF8oNzQNgeBjQynWfulBtr40wMxWFQBFmQ5OagEwxvDAc4cBONA3il0wEe/qHQZg26EBzuyeAcAZXgfQrpALaDTPArBpTVjErPzwxpz2BP2jmaLFY8YyNlf+48Pc8siuYNvOI0PYjmHXkeFAHHb3DvHrbT1s2t/PnY/v5aX+MWa1JQA4NomB4J6BMV72uft5Yvexksc8sr2XdNbhmf39kfuPDqeIW8L8ma3A9KSCbnlpgLGMw59fdSafet05U/59iqKc5ALw/OFBDhwf5aLFs0jbDj/dsJ81X3yQg/2jZG2HvceGg2P9rB6/A+jcjhbAdwGFYwBZZkS4IOa0J7Edw2DBZPjLLYc4cHyUn208EGzbfngQcAvM/JXHfvjkPhIx4dJlc/jaA9vZe2yYCxbNBFwX0OBYhnV//xD3bDpY9rrf/731fOEXWyP3rX+xj8FUlj+Ms5SjLw57jhVbTQBP7+vnvNNnBv8dpkMAnj80AMCHrlzBUk+kFUWZWk5qAejqSPK/rlnFB65YDsCtj+2mbzjNvz25l/3HR8nYJnAnrJjnWgDL57mTy7zOkAWQVwlsR/ain9PuHt9zYixv+78+vheAF44M8eJRV3C29wwG+3f1DjGatvnphv1ce8FCvvYnq8k6huG0zQWnzwJcAXh0Ry+HB8b4P0/lhMRxDP/tf/+W7zyasy4GxjI8uqOX+549xHMvDbD2S7/m+cMDwf7NB/qD743CcQzr97jisC/CbTaWsdm0r5+XL+8K0jGnIxV0++FB5s9sYbb331lRlKnnpBaA+TNb+egfreSSM9x2Q7u9CfjHf9jPNu+J8q2XLAZyFsCfXrqUb71rDad1uu6NtkQsrxfQUCobmYXyijPnYgncvfEg//2ODbzve+u5/bcvsnFfPx/0BOhjP3qaq/7xYR7b0cv8ma6FsevIEL945iUGxrK8d90ZLJ3bzv+8eiUAq+Z3kogJx4bTPLDVjWU8vusY3/zNC1zz9UdZv6ePZw+e4LbHdpPKumPcsKcPx7iL2v/Tr3dwdCjF9367JxjnMwfcYLjv/ipke88g/SMZkjErz0Ly2bjvOGnbYd2KuXS0xIL/JpXw0w37ufafHgt6LVXDtsODnLNgZtXnKYoycU6JaNvCWW0kYkLGNlx+1lx+t/MY3/zNTgA+8pqzOLN7Bq9a6fYbmtWW4A0X5oqV20MWgDGGIwNjkS6g02e38cfnzue2/9qN7RgscX3pV5w1j09es4rHdx1j84ETWAKOgbesWcSDW3vY1TvM0/uPc/b8Ti5d5grVTVeuYHZ7gtddsICv/Op5ek6M8fD2I5yzoJPnDw/y1Qd2APCZnz0LuNXCH/nhRvb1jbBqfici7lrGD3gB8HueOchnrjuXGa1xtnjZULt7hzDG8IMn9nLzgzuwHcMXrj+fl7zso9eeP58Ht/ZgOyYv3vHk7j5EYO2yriDt1c+M2t83wgfv+AM3XLyYfX0j7O4d4s4PXkZLPMbhE2N84RfPMZTK8nf3bePmt6+O/H911/p9/HTDfu74wGV0troxkIztsOvIEFeunFfd/3hFUWripLYAfGKWsMTr7f/Ja87moiWzee7QAPNmtDBvRgvvWXcGiRJFYm3JOANecPf+rT08c+AE116wIPLY96w7A9sxXLasi3s/egV/e/35fP/9l9KejPP3b3kZ3373Gj51rRvAPHfBTFacNoNfbjnEloMDvOcVZwT9bRIxi3e//AxmtMTp6kjy6209DI5l+cvXrmLejCTtyRiL57Sx++gw61Z0sXxeB7/edoQdPUP8x+ZDXHpGF/NmuBbGOy9byljG4Yfr97Krd4iRtM3qJbMZTtv87X88x1/fs5VzF85kSVc7f/PvW7nlkV1cuaqbV545l7TtBDEKcAXwke1HOP/0mcxqSwSusOFUFmMMf3PPFnb0DPGVXz3PXev38eSLfdzyyC5OjGT4+I+fJmM7vOXiRfxs40F+v+to0X+//X0jfOEXW9m4r5+veSIHsOfoMGnb4ZyFndX+r1cUpQZOCQsA3OyenoExLlw0i7+/4QLe9M3fsaK7o+x5a8+Yw13r9/Hgcz18/t6tnLOgkxtfuSzy2CvOmsdnrjuH11+wkCVd7VywaFawb/WS2axeMpuM7SDAmy9exLbDAzyzv591K7p425rFkZ85d0aS5w8PsnxeB1ed3c0/vO1CLBFePDrMF37xHK87fwEXLp7FnqMj9A6l+PIvn2fdii66Z7bwn5sP8bGrV9IzMMY3f7OT/Z5P/y1rFrFpfz/f+90eXrVyHt9//2Xs6xvhdf/0GAJ88frzgyZ0e48Ns+/YCF/+1fO8fHkXzxw4wZfefAFAYAn99T1b+cZvdtI7mOKznqWxcFYrd288yP/+zU7+5b9eJJW1+cpbL+S6ly1kw97j/D8/38IvP/4q7tn0Enc+voePXb2KWx/bhSXC6y9YwJ2P72H1ktk8sfsY9291M7nOnq8uIEWZTk4ZAfjIa87iLWvGiMcszj99Fje//SK6vafk8XjDhQv54n8+x//80dOksg7ffs+aktaCZQk3XXnmuJ+XiFl86NXuMR+68kxetmjWuBaIn430xesvoCUe44/OmQ/AZcuzHB/J8NZLFjOzNcElZ3SRsR0yWYe3XrKY/pEMrzxzLgtmtfKFN53Pa7/+KHet388bL1zINect4G/ucbOE/vurVhCzhOXzOrjl3WsQcTOhLM8a2XF4kNt/t4d9fSM8s7+f1Utm867LlgLQmsiN+RUr5nLWaTN4/+XLgpYbFy6ezfzOFkYyNm+7ZDFrlrouri+++QJuvH09V3zlYXoHU7QmLP7HnRtIxISv/slFvOac0zg8MMbHf7wJEXjDyxaybG4H5yxQC0BRphMpzGuvB2vXrjUbNmyo2/f/v/dt458f2827X76Uv7vhZdP63Rv29LHt0ADvfcWymj7nga2H6RlM8Z6Xu5P3BZ+7n3mdLTz8yauwrOKWTbZjOOevf0ncshjN2Pzzey9h84F+3nbJEpbPy1lOtz62i3MXzgxiKJXyr4/vYeO+flbOn8G7LlvKPz+2m9eeNz8QiVTW5juP7OaiJbO46uzTxv8wRVEiEZGnjDFrJ3y+CgAcGRzj2w/v4i9fuyoozjrZ+cETe1na1c6Vq0pP3N95dBebD/SzbsVc/qxGAVIUZfpRAVAURWlSahWAUyILSFEURakeFQBFUZQmZcoEQESuFZHtIrJTRD49Vd+jKIqiTIwpEQARiQHfAl4PnIe7TOR5U/FdiqIoysSYKgvgMmCnMWa3MSYN/Ai4foq+S1EURZkAUyUAi4D9ob8PeNsURVGUBqFuQWARuUlENojIht7e3noNQ1EUpWmZKgE4CCwJ/b3Y2xZgjLnVGLPWGLO2u7u6KlNFURSldqakEExE4sAO4Grcif8PwLuMMZHLWIlIL7C3hq+cBxS3n2wOmvnaQa9fr7+5r/9sY8yEm2hNSTM4Y0xWRD4K3A/EgNtLTf7e8TWZACKyoZZquJOZZr520OvX69frr+X8KesGaoy5D7hvqj5fURRFqQ2tBFYURWlSThUBuLXeA6gjzXztoNev19/c1HT9DdENVFEURZl+ThULQFEURamSk1oAmrHhnIjsEZFnRWSTnwEgIl0i8qCIvOC9zqn3OCcLEbldRI6IyJbQtsjrFZdvePfDZhFZU7+RTw4lrv/zInLQuwc2ich1oX1/5V3/dhF5XX1GPXmIyBIReVhEnhORrSLyMW97U9wD41z/5NwDxpiT8h9ueukuYAWQBJ4Bzqv3uKbhuvcA8wq2/QPwae/9p4Gv1Huck3i9VwJrgC3lrhe4DvglIMA64Ml6j3+Krv/zwP+KOPY873fQAiz3fh+xel9Djde/EFjjve/ErS86r1nugXGuf1LugZPZAtCGczmuB+7w3t8BvLmOY5lUjDGPAX0Fm0td7/XAncblCWC2iCycnpFODSWuvxTXAz8yxqSMMS8CO3F/JyctxphDxpiN3vtBYBtuX7GmuAfGuf5SVHUPnMwC0KwN5wzwgIg8JSI3edvmG2MOee8PA/PrM7Rpo9T1NtM98VHPxXF7yOV3Sl+/iCwDLgaepAnvgYLrh0m4B05mAWhWrjDGrMFda+EjInJleKdx7cCmSe1qtuv1uAU4E1gNHAK+Vt/hTD0iMgO4G/i4MWYgvK8Z7oGI65+Ue+BkFoCyDedORYwxB73XI8DPcc27Ht/M9V6P1G+E00Kp622Ke8IY02OMsY0xDnAbORP/lLx+EUngTn4/NMb8zNvcNPdA1PVP1j1wMgvAH4CVIrJcRJLAO4B76zymKUVEOkSk038PXANswb3uG73DbgTuqc8Ip41S13sv8GdeJsg64ETITXDKUODTvgH3HgD3+t8hIi0ishxYCayf7vFNJiIiwHeBbcaYm0O7muIeKHX9k3YP1DvKXWOE/DrcqPgu4LP1Hs80XO8K3Aj/M8BW/5qBucBDwAvAr4Gueo91Eq/5LlwTN4Prz/xgqevFzfz4lnc/PAusrff4p+j6/9W7vs3eD35h6PjPete/HXh9vcc/Cdd/Ba57ZzOwyft3XbPcA+Nc/6TcA1oJrCiK0qSczC4gRVEUpQZUABRFUZoUFQBFUZQmRQVAURSlSVEBUBRFaVJUABRFUZoUFQBFUZQmRQVAURSlSfn/AXX6D0pdtnLkAAAAAElFTkSuQmCC\n",
"text/plain": [
"