Skip to content

Instantly share code, notes, and snippets.

@justheuristic
Last active February 15, 2018 11:56
Show Gist options
  • Save justheuristic/8a31871fb78620200be9f124fc961563 to your computer and use it in GitHub Desktop.
Save justheuristic/8a31871fb78620200be9f124fc961563 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"env: CUDA_VISIBLE_DEVICES=\n",
"data matrix (bach-major, 1 = EOS) \n",
" [[10 11 12 13 14 15 16 1 1 1]\n",
" [20 21 22 23 1 1 1 1 1 1]\n",
" [30 31 32 33 34 35 1 1 1 1]\n",
" [40 41 42 43 44 45 46 47 48 1]\n",
" [50 51 52 53 54 55 56 57 1 1]]\n"
]
}
],
"source": [
"%env CUDA_VISIBLE_DEVICES=\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"import numpy as np\n",
"import tensorflow as tf\n",
"\n",
"tf.reset_default_graph()\n",
"if 'sess' in globals(): sess.close()\n",
"sess = tf.InteractiveSession()\n",
"\n",
"data = np.arange(10,60, dtype='int32').reshape([5,10])\n",
"# WARNING! in current implementation there MUST be at least 1 EOS at the end\n",
"for i, len_i in enumerate([7, 4, 6, 9, 8]):\n",
" data[i, len_i:] = 1\n",
" \n",
" \n",
"print(\"data matrix (bach-major, 1 = EOS) \\n\", data)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from tf_diffbleu import compute_bleu_with_logits, compute_ngram_stats\n",
"\n",
"ref = tf.placeholder_with_default(data, [None, None], name='reference_answers')\n",
"logits = tf.get_variable('logits', [5, 25, 60]) \n",
"\n",
"smooth_bleu = compute_bleu_with_logits(logits, ref, eos=1, smoothing=1)\n",
"hard_bleu = compute_bleu_with_logits(logits, ref, eos=1, smoothing=0)\n",
"precisions, recalls = compute_ngram_stats(tf.nn.softmax(logits), ref, eos=1, n=4)\n",
"\n",
"loss = - tf.reduce_mean(smooth_bleu)\n",
"step = tf.train.AdamOptimizer(0.1).minimize(loss)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"sess.run(tf.global_variables_initializer())\n",
"sess.run(tf.assign(logits, tf.zeros_like(logits)));"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-0.071 -0.076 -0.081 -0.087 -0.094 -0.101 -0.110 -0.120 -0.131 -0.143 -0.158 -0.175 -0.196 -0.217 -0.234 -0.246 -0.259 -0.264 -0.265 -0.263 -0.263 -0.267 -0.271 -0.276 -0.281 -0.282 -0.285 -0.291 -0.299 -0.303 -0.302 -0.303 -0.304 -0.305 -0.307 -0.309 -0.311 -0.312 -0.314 -0.316 -0.317 -0.320 -0.322 -0.324 -0.327 -0.327 -0.329 -0.331 -0.335 -0.340 -0.345 -0.349 -0.355 -0.363 -0.374 -0.387 -0.404 -0.423 -0.448 -0.475 -0.506 -0.540 -0.575 -0.611 -0.647 -0.680 -0.713 -0.744 -0.772 -0.797 -0.819 -0.839 -0.858 -0.874 -0.889 -0.902 -0.914 -0.924 -0.934 -0.942 -0.949 -0.956 -0.961 -0.966 -0.971 -0.975 -0.978 -0.981 -0.983 -0.985 -0.987 -0.989 -0.990 -0.991 -0.992 -0.993 -0.993 -0.994 -0.994 -0.995 -0.995 -0.995 -0.995 -0.996 -0.996 -0.996 -0.996 -0.996 -0.996 -0.996 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.997 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 -0.998 "
]
}
],
"source": [
"for _ in range(200):\n",
" print('%.3f'%sess.run([loss, step])[0].mean(), end=' '*7)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.colorbar.Colorbar at 0x7f67104eee80>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAcwAAALYCAYAAADxdMKWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAIABJREFUeJzsvX24LFld3/v5VVV379dzzgwjgzDMjAoCYnLVBycSo0zEx+AriUYEg4J4vURFvEEJirl3HPPo1USjJOiNQTT4OhC5EfQhiIiDoiEZEdDAjIPKjDMwMzDMnHP2a79UrftH1eq9dp2q7t7n7N3V1fv7eZ56urq6ul72S3/691u/tZY55xBCCCHEZKKmL0AIIYRoAxKmEEIIMQMSphBCCDEDEqYQQggxAxKmEEIIMQMSphBCCDEDEuaSYma/ZGY/Uqz/AzO7c07nzczsM+d0ro+a2Zcd07F+3cy+7jLf+yIz+6PjuA5xcpjZY83sw2bWafpaRDuRME8Bzrn3OOeeNm2/Y/rgb13HXjP7O8Dfdc69tXh+OT+HE79vM3u6mb3dzD5pZulJn2/emNktZjYws4vFsmVmj5T2eaWZ3W1mO2Z2j5n9mJl1g9efYGa/WfyMHjWzPzezbwVwzn0CeBfw0vnemVgWJMwWYGbxvE7FlX/w27FcyPzuGfIP0F8LT89iin8IvBF4SdMXcoLc5pw7Uyybzrmr/Qtm9h+A/x14IbAJfCXwbOBNwft/BbgXeCLwGOBbgIeC138dCVNcJhJmQxTpxB8wsw+Z2afM7PX+m7KZPcvM7jOzf2lmDwC/WGz/GjN7f/HN+T1FZOSP9/lm9j4zu2BmtwErwWvPMrP7gufXmdmbzewTxTfxf29mTwX+X+CZ4Td7M+ua2U+a2b1m9oCZ/ZyZ9YJjvdLMPm5m95vZtzFBNGb2B0VE8D+K6/yvZnaueO2GIp37EjO7F/j9YvvXmdn/MrNHzOxdxXWG3FTzM3yMmf128bP6lJm9e8Kv4yuBdxfvq/s5nDGzXy5+Zh81sx+acJ//1sz+0Mw2i+cvKVKBnzKz/2Zm1wf7Zmb20iJqesTMXlt3XOfc3c65XwI+POFewuvIzOw7i2NfMLMfMbPPNLM/NrPzZnabmSXB/pP+vl5lZn9VRH7/y8z+cfDai8zsj4r7fsTM/trMnhO8/uJi28Xi8QWzXH/pXp4EfCfwzc65/+mcy5xzdwLfADzHzG4udv1C4A3Ouf1inw865343ONT/AD7TzJ541GsQAueclgYW4KPAnwOPB84B7wF+pHjtWeTRxI8BHaAHfD75N+VnkEdA31Ico1Ms9wAvB2LyD5FB6Xh/W6xHwAeAnySXahf4+8VrLwL+sHSdPw38FnAWWAfeAvxo8dpzgAeApwGr5FFaCnxmzT3/AXBfsP9vAr9SvHYDkAH/uXitBzwZ2Aa+rLivVwIfAZIZfoY/Bvxccb8x8MU117RWnPcxwbaqn8MvA/+12P8G4C+Bbwv3L34vrwP+G9ArXnsucDfw2cW1vBr44+C4GfBW8ojpicAngK+Y8rfzWUA6w99YVlzzevEz3wd+r7j+TeBDwLcU+9b+fRWvfwNwbbH+jcXv5drg/vvkka8B/xz4WPDzvQA8qXh+LfC0muu9BfjlmtdeCny05rXbOfib/L3i7+CbgCfW7P9B4Gua/gzQ0r6l8Qs4rUvxYfQdwfOvBD5SrD+r+HDrBK//HHBr6Rh3AV9SLPeXXvtjqoX5zOKDMaq4pipRbAOfETx/JvA3xfrrgR8LXnsy04UZ7v+04oPWig/xFLgheP1fkafo/HMD7ge+dIaf4a2FLD5ryu/h8cV5u3U/B3LR9YGnBNv+D+Bdwf7vBW4D/guF0IvX3kYh1uBYO/7DnFxqzwxefyPwL6dc81GE+UXB8z8FXhk8/0ng3037+6o59vuBrw3u/+7gtdXi3I8lF+YjwD8BVqZc7y3Fz/mRYPn94rUfAv6k5n2/Afx8sX6W/MvSX5B/6fwz4Bml/d8DvPC4/pe1nJ5FKdlmuT9Yv5f8w9vzSefcMHh+A/B9RcrrETN7FLiueM/jgY+Vjn1vzTmvA+51zmXTLs7MPo38A+99/rzk0dNjil0eTx4xhuec1oZZ3r8DXBNsC38mjye4D+ecK97/hJr9w5/hvwX+GnhHkUp8Vc31nC8eNydc8zVAAvxt6VzhdTwJ+Dpy6YyC7TcArwl+fp8iT1uH7w3b2HaBjQnXclQ+Eazvlc61F5xr0t8XZvatQbr2UeDpHP69PehXnHN7xeqGc26XPNr7TuCBIk3+lAnX+0bn3NXB8uxi+8PAp9e859OL13HOXXDOvdo593fIo9kPkn9xCtnk4PcuxMxImM0StqPcAHw8eF5uC7yPPO3kP0iucs5tOOfeSJ4WfUJp/+up5j7gejOr+t2Xz/kw+Qf404PznnPOnS1ef6DiHqYVy5T3HxTnqbqGjxf7lN9/f+l5eLyPAzjntp1z3++c+yxykb3CzP5h+WKKD/S/Jk+ZVl0DxfUNS9dyA4e/pHwY+Dbg7WYWHutvgZdW/N7eW76Whqn9+yraXP8T8F3F9qvI07kzFXg5537POfcVwOPIU9mvu4zrexfwRDN7RrixaIv8IuCdFed9hDyKfryZXVXsH5N/ufngZVyDOOVImM3y3ZaXwV9N3rZ124R9Xwf8czO7CcDM1s3sq8xsHfjvwMjMvsfMEjP7euCmmuP8T3LR/biZrZlZz8z+fvHaQ8B1VvRTKyK61wE/U0Sbvmz/K4r93wS82MyeZmZrwP89wz2/0MyeWux/K/BfivPApR/AbwK+2sz+YXFf30+eqv7vwT6VP0Mz+2oz+6xiny1gRJ4mrOJt5GlrT/nnkBXX8qNmtmFmNwD/grwic0zx5eXVwDvtoC/qzwOvNrPPKa7rrJn904k/oQlYXnDVy1etZ0GXiitk0t/XOvnP7mEziywv7vrcGa/3sZYXbq2Rf+nYJk+BHwnn3EfIf5a/ZmZ/r7iOp5O3g7/DOfcHxfl+3PLuN3FRdPVdwF855x4tDnUTeVvofVXnEWISEmaz/DrwDuCvyItZfrRuR+fc+4DvAF5bpPbuJm87okjdfj15hPMp8qKMN9ccJwO+lry98W/JI4vnFS+/izxyeNDMfCrvB4rre6+ZnS+u97OLY70d+JnifXdTVLZO4VeAN5BHgl3ge8PLK13r3eRdCF4LfBL4avJ2s1Gwf93P8Mnk4toib8/9WedcXaXs64rzeKp+Di8nj7b/hrzA51ddXrF6COfcLwM/Avy+mV3vnPst4MeB24qf35+TF0tV3nPF8zGFqPfI2+dcsX5X3f5HOfaUv687gZ8ib6d9kDwd+54J5w3PFQGvII/GHwa+lDw9W8c32eF+mBfN7JriOr4b+AXgV8m/BL2N/HcVfgFZI0/BPkr+N/FE8gyD558B/3HKtQtRiR18uRfzxMw+Cny7c+5dTV/LvDCzPyCviv3Fpq+ljJn9KvAmVwxeIJaPIktyO/D5zrlBw5cjWkgyfRchlh/n3Aun7yXajHPuk+TRsRCXhVKyzXEaQ/vTeM9CiCVhIVOyxSghP0Mu9Nc7536i4UsSQghxylk4YRbdHe4mHyPy48AdwPOdc5OKG4QQQogTZRHbMG8iH63lXgDLx0V9LkE1oJktluWFEKIBnHPHMtnB5XLOzF1o8gIOuNc5d+NJn2QRhfkEDo8Gcz+VfQpvKR5vB24+4Us6OVbY43E8yON4kGt5iMfxIHfyEE/jWh7kcTxUPD7I49hntenLvUJup82/q3puZ/nu63aW755gue7r1qYvgAvADzd9EcAPXzrAyYmwiMI8VTiMIR32WGWHdS5wlj0uss0GIxIiMlbZ4yoeZY99UmJGJOPHjHnOgiWEEKeXRRTmxzg8rNt1XDpOKvk3Rcgn6bgHuPEkr+nEyIgY0GWXNS6Qjzi3zaNc4Cx9esSkbLBNwoh9Vg4tDpMwhTg13FMsi8UiSuSkWMR7vQN4UjGqyQPA84GK+fNuLh7voa2yhDzCHNBlh3UMx4iEmD0ucBbDEZGxzg4bbNOnxzYbbBXjhI9IGHJcI6PNgxubvoAT4samL+AEuLHpCzghbmz6Aq6AGzl8/ZOmeBUnwcIJ0zmXmtnLyIc7891K7qx/x43zubATwkeYhiMlZp8VemxwkV1W2WON3fHSp0fCCIcxImGvdW2aNzZ9ASfEjU1fwAlwY9MXcELc2PQFiBazcMKE8Rilk6YAWhq8MEck7LNCREZMymP4FDEpm2yxzg6P4VMMimjS7xsffQxrIYQ4VjpNX8AcWUhhni6MlISUfCoHzwr7rLPDiASHEZGRMKLDkC4DVthnlT0GdMmIxkverhkx48xLQgghZkTCXFB8ynWLTRIO5iP2adgV9rmaR1hhnz49BnTHS59eU5cthBBLi4S5oHhhXuTMuOtJwoiUGIexwj5dBmyyxQ7r48UXETlFmEKIOXCaJHKa7rVVDOmwzwpwIE8vyR798XpExgXOEpOOxWo4jXIuhBDHjIS5oHhJ+kENEkass8M5zo/bMM9xnh79sSx9f04hhJgXKvoRjTOiw6j0pzigS5cBZ7hIjz5nuMgmW4xIxn05fdTpsIq0rNK0QghxuUiYLSIlHg9e4CPLPVbHw+h1GLLJ1jjaHNJhSKcY4KCjUYGEEOIKkDBbhBfmDuvjNOwua+N+nB2GnOEiK+yzx+qhJSWWMIUQx85pkshputfWkxGNI0w/4MEqe8SkxKR0GLLCPjEpO6yzxSYRWTA4wmlqbRBCiONFwmwRPsIMC3x69Nlgmw22WWVvvH6RM8SkY1nusN705QshlpDT9DVcwmwRXph+7NmIjC4DIB/IIGHEJlt8Gp+ky2Acke6wTkTW8NULIUS7kTBbxaXTeWVEh6b88m2Ww+J7X8KIVfY4w0Vi0iJ5e7CoXVMIIWZDwmw5frCCXda4yJlxm6Uf+CAiY41dDMc6O/Tpsc/K+HEgYQohroDTJJHTdK9LiW/P3GN1HEH26Y1TsIYbTw82pFO0cG6M594caNxZIYSYCQmz5YQRZtjtxHco8bOarLJHSkyH4XjuTQ3SLoQQsyNhthwfYZb7aJ7j/KHo8moeATg0UXU4C4oQQlwOqpIVLcLPp3n4V5kwYo1dUuJxNW1EFpQH7dMrWjL9PJp+Ls18SD0NoyeEECES5pISzqfp07AJI3ZZIyOiR59znCdhNB5GL5xTU9ODCSFm4TRJ5DTd66liRMI+K4cKfLoMiq4k0Xgs2g222WG9SNyuFe/tkDZ8/UIIsWhImEuKF6aX5T4rrLBPh+E4jtxgm4QRFzhLhyFAMZ9mBupuIoQQh5AwlxQvSV/gs83GeACDhNF4ejAvTWA896Zp+mkhxIyo6Ee0Hj+Szz4r423r7IyHz/NtmNfwMHC4zVPCFEKIS5Ewl5ZLi3bCricXOUOHIRkRW2wypEPCiA22+TQ+yT4rjEjGi+bTFEJUoQhTLCXhzCUdhuM+nH16DOmMi4C6DMbj0vrHjEjCFEKcaiTMU4SfvcRXw/o2y1yFKQkjugyIScfp2S02x6IdNnz9QgjRJBLmKcKLDw5k2aPPOjvjZYNt1tlhj1USRoeG3hNCiDKnSSKn6V5PPT7CLEeW1/AwXQbjNsxreJhd1g5NVB2rZ6YQ4pTTemFGpOMPfv8IuRwO5nxU+1tOPp9m+LMwsnFbpZ+cekjn0M9Oo/4IIcQSCDMmLcZEPVgMV9rS07yPEwi7lMSkOIw+Pc5zjm02xv05hRCijKpkW0TCiBX2x21v6+wQkbHNBjusj2fn0LyP9fgUbS7LfPLpcO7MPj0JUwhx6lkqYZ7j/Hhaqw5DIjLN+zgFX9Szx+q4zXKnmFvTp2klTCFEHa2XyBFo/b3GpKywzyZbXMWjXMPDREWrpZflNhtNX+ZCM6QzlqXvXhK2AY9IJEwhxKmn9cJMijbMNfY4wxZX8ygRGQN67LLONpskqvCcQPV8mkIIIQ6zFJ+SEfncGjH5DYWPqu+cxqSfkMaUFUJMRkU/LcKKJSK/mQ6HBRohaVZjpccyLnhN4hRCiKUQZl2EGSFhVhPKctpPR7IUQghYMmH6CDMUp4RZZlZZGgeyDNeFEOKA1kvkCCzFvfpIMhSlUrKTMGaLLj2SpRBCtF6YXpQdoAesFM97qPCn+s7LsrTSa56yJCVNIcSlqOinRRgHwuySCzMhF6ZPz0aNXd1ROW61l49XlY6tK/4xICvWfQGQpCmEOL20XpjlCHO1eN4tlvYIc1rV6nEds06U5cdQkpKlEEK0XphhhOlTsmGEmdCmlOxxSnNSBFkVTZajzyxYlyyFENW0XiJHoPX3GkaY7U3JlmV23MKcJmIrLZD/1BzHdz1CCNFuWi9MA2KDxIqUrBXCdIUwHVgrAqQqaR3H8crrUB9hhvu7YBFCiGpU9NMiIoMkhm4EvQhWo0KeKXQySDKIMg7qVxaWcMyiWUbYmSbVsixnFWaYknUoNSuEEDmtF6ZFEEeQJNBNYCUpIswRdFKIRxAt/Od8WVZhOrTu4mdp76zrQlL1WLVfxqWyFUKI00nrhRkZxDF0O9DrwEoHOga9AXSGkDiw1kxWUhZnKE1X2gdmk2X5uFRsrzo3HAwJsfDhuRCiIVovkSPQ+nu1QpidBHpdWO0dVMx2HMQZRAtf9VOOLn2EOW1fqJfmJFlOE6WXdMT08wghxOmg/cKMcmEmHeh2YWXloGK2k0Gc5lJdXKrE5YVZVXRT1d446diT5DjpdVfxuhBCnF5aL0wickOuAOvABkXpbPF6BgyaubTZmSSwsjjr9qs75rTj122PgRQJUwgxCVXJtgk/rM8KuSzPcNDx0ssyrn7r4hFxOCVbF12G61XSnJZunTXCDCdIkzSFEKeb9gvTR5ir5BGmF2ZKLss9WiLMSSnZSRFmVSFPeb+q99Udq1zwI1EKIepRhNkmwgjTCzPmQJY7tGCon7Isj5KSnUWYlyPPrGIfIYQ4vbRfmOU2zLPFtj1gm4Px8VpBVYRZ9fpRo8aj7BsKUylZIYTwLI8ww5RsTC7LVQ6mLFloyhHmUVOyswiwar9J75EshRDTab9EZmfhk5VT8SOv+whzs1jWi20dWnCXoaD8cPJxadukpfz+svRmeU/5/BKmEKK9mNlzzOwuM7vbzF5V8fr1ZvZOM/ugmb3LzB4/7Zjt/3IQUd2G6YW58BFmOdILI0yfGp000s+kCDKasE947rJkqx4lTSHEpXQWwSKjw0/NLAJeCzwb+Dhwh5m9xTl3V7DbTwL/2Tn3q2Z2M/DjwLdOOs3Cx15TKUeYZ8jbMTfIU7KtaMOcNSKsSplOiirD57NErXHFvhKlEKJ13AR8xDl3r3NuCNwGPLe0z+cAfwDgnLu94vVLaL8wy0U/5ZRsl5bcZSi8o6Rj61KydSnWqv3KYq0SsRBCtIYnAPcFz+8vtoV8APh6ADP7emDDzK6adNBFCKavjAhcYmRdI1uNSDdiogSyVSPrGS6xFgizLjr0g567in2nVb+WRVgnvqp9JUwhxGwki2CR0fRdKngl8FozezHwh8DHyHvw17IIt3pFODPSOGLUiRl0E/q9DmknZtDtMEpi0jgiixb9A7+cao053A/Sr5f3r1uvqnSNSvuF1EWnasMUQiwef5TCeyZPovQx4Prg+XXFtjHOuQeAbwAws3XgG5xzFycdtPXCzCIjiyNGScyg06G/0iVNslyYnYQ0jnCLPfp6QTktGooyjDbL0quSJdQLMHxPeN5JEaYQQiwOXxLni+fHL40L7wCeZGY3AA8AzwdeEO5gZo8BHnHOOeAHgV+cdt7WCzOPMGNGScKwm7Df69LpZAy6CcMkJo1j3EJHmHWFPOXosnwPVRHnpJRslTDLcg3fExb9LPLPTwjRJJ0FLKp0zqVm9jLgHeQfZK93zt1pZrcCdzjnfge4Gfh/zCwjT8l+97TjLocwo4hhkYbNU7IHEWYWR2QLH2HOmpItt2WW3191rLr2yGlyrarMFUKIduCcezvwlNK2W4L1NwNvPsoxl0OYccQoSXJhrnTHwhwWbZjOFr7qh2pZVaVk66hLyU4S5qT2TqVlhRDTWYiinznR+lvNiEhJGNJhnx67rJGQsc8KQ7qMSMgW/gO/LC0fYcLhqLI8tmz5/eWosSzKqGb/uvbORf+5CSHE/FgCYRojYgZ06bPCLgMSHPv0GIyFuegRZigwP2hAVWR5OcKskmA5ypxWHStxCiFE64XpiBiRMKDLPivsMSLG0WelJcKsiwrLOOrFVdd+WRdplvedRZaSphDiUhZiaLw50fpb9SnZwTglmxHj2GeFAZ0WCBOqU7JlQVVN91V+f50EQxGW96diHw1cIIQQZZZAmHlKdkiXPo5drBDmQUrWtUaYobDgQJCu2Ha5wpwUNdalZJWOFUKIkNYL040jTMc+sEdUCLPLkA4j4hZEmHBphBniSo9V762KGstCnFWsdW2eQghRYgH7YZ4UrRdmRlREmNAnYo+ECOgTMyAhJW5JlWxZWJ7yBNJ1768T4aRt5ehzlkIhIYQ4nSyBMK2IMCP6JOzRIQL2iRhgjIhaIsyqCNNVLJPeP+syTZAa6UcIMSOtt8jstP5W8ypZGJKwD0UbJvRxDIERbmJs1jxV7Ym+vfKkhFlV3FNX9KOBC4QQApZAmHmEGTMkKlKycRFhZgxIScnIyJg+Uk6TVEmsSpZ19zCLIOvOE5e2VaVjQdIUQpx2Wi9MV7RhDkjo0wnaMEcMGTFiRMaw6cucQl1KFi6/DbNue1XatUqWSskKIWag9RaZndbf6sHQeF36dNmjWwhzwBAjxZGRMmVe0AUglFhZmP7RqBZnWZDh+rQ0bCjNsjBDaQohxOmm9cJ045Rsh34x2o9h9DEGOEZkuMucjnt+lEUV/lp8dDlpfNlpwpzUPjnLoihTCFFD6y0yO62/1YNuJR369NhjtRCmY0hGymjBq2SrIsC6lGwYYYbbqHmc1LUk5nAUWY44lZIVQoiQJRBmGGH2SMbCTIs2zLYMjVdOhUJ10U9ZmHXHm5SOLUuySpTllKykKYQ43bRemH6kHy/MiBWMiH1GDBiQErdoaLxySrYsTKvYNkmadQMTTBNlVdumEEJUoJF+2oNzRprFDNMO0ahHNFgDZwyGA0ZplzRLyNyif+BXRZhhVBl2NZl0jPLzunbMurbNmPpU7aL/DIUQ4mRpvTAzF5FmCcNRFxuuwGAVXMRwtM9w1GGUxTi3yBFmVdtiwmFhemnW9cmcJMuqNsyqaLMsS6VjhRAipPXC9BGmpR0Y9siGuTBHw5U8wkwTsoUWJlzaLzKMMFMOR4JelOF61eACs8iyqj9mnTSFEKKC1ltkdlp/q66IMF3aJRv1GA1WIYvIhj3SUYcsSxY8woTqbiVelr47ScrBNF91opzUB/Nyokx1KxFCCE/rhZm5CJfGZKMOo2EPG6xCFuOGK5B2cQufkvWUu3tkxaOPMH1K1qdnM2YfsOCoskxQSlYIMROtt8jstP9WHbg0wg1j6Cew14Ekgn4MgxhG0WIPI1vbPzIL1r00y7KsiyynnWvaQAZluQohhGi/MDNgBPSBPWCH/K72im0jFlyYUN1PMuVSiZVlWW6zrDrupGrZ0vGtOIZZUZBbPF/s6V6EEGIuLIcwh8CAXJLbQGKwZ/m2IS0RZlWUWZZaWZa+X2Zd0c+kc5T6YVpUCNOK3ax6gCEhhAhRP8wWURVhxsBusa0VwoT6dsXyNjiwWFVatuq4Ve2bwTEtEKZVHEeyFEKIJRZmmJJd9IlKLpFYVZVqWPjjH4/SxjglwqQiugyRNIUQVbTfIjPT/lvNLJfigDwNu22HhTm0fJ+FZVr1arkQpyzLaUU+MHOUGRURZliQi4GzaokKIcQpYgmEyYEw98lTsXGxPqAlRT9UZ1ZdITYXirMsy2mp2BmEbJbLMjKIS8L00fnCR+lCCHGySJiLQFVz5LjYJpRmOcoMC34mHXSKPH3bZWyHh7L1YyWo8EcIUUf7LTIz7b9Vx3RhtuGDvuyxzAJZ1olyWjp2mix9u2UpwvQDDcGlw9YKIcQppf3CrIowI/I2zDZGmGExrG9DtDAtW9W1pO6g5YPXpGV9u6WXZYeDqTf9WAmL3AwshBBzYHmF2aaULFzqMb8xK0WDEwcvKB+wvE95FB8vzOC8MXk/Vj9JSjrhFEIIoX6YLcK3tQ056FoSFeuD4rVFFmbow7BHiS+yGfciCVOz5QbPSQcvr5f3t4PD+WFkO8X5/djvijCFEKIZYZrZdcAvA9eS6+x1zrl/b2ZXAW8EbgDuAZ7nnLsw8WA+CqoS5pB2RJihLP24537UnUtECcduLy/LUJgR+c91xORAVghxuml/2DUzTU3jMQJe4Zx7OvBM4LvN7KnADwDvdM49BXgX8INTjxRGmD4tO+6DyUGl5yJTFmaH0nSUs7RZHvP5vbj9NQghxCmnkY9C59yDzrkPFOvbwJ3AdcBzgTcUu70B+MdTD+bbMMMI0wuzDW2YYXNiGOWNZ9jyKdO6atdjuoZQmKE0w3EThBDiFNN4MG1mNwKfB7wXuNY59xDkUjWzx049gI8wBxSpzGIJI8xFFiZUR3iOvODnUIQ5x/OHaVqlZIUQdTRukfnR6K2a2Qbwm8D3Oue2zezoI5j6NkxfKQuXCrMtKdlQWuPZvSwQZljleoznDot+/Pnh8HC2QghxymlMmGaWkMvyV5xzbyk2P2Rm1zrnHjKzxwGfqD/C7fnDaA3sJogfd9gjvuCnrcIcBYMJVLZhHmM6ttylxc9fXR7GVgjRIPcUi2iKJiPMXwQ+7Jx7TbDtrcCLgZ8AXgS8peJ9BTfnD9E1YNfmcoSDQXBCYS5ySrYqwgsXP2ydHbO9wkOUZRkKU7IUYkG4sVg8727mMsooJXuymNkXA/8M+Aszez+55l5NLso3mdlLgHuB5009mG/DDNeNg36EfsSaRaYqwvQFP5GXZRbseIVFP2GQWjGOwViYqpAVQogxjQjTOffH1I8P8eVHOxgHUvTtfuXtbRFm2IYYWzFziE/JnlCEWSVLP3DCMbhZCLHkaKSfFuFcIMQqO7bAmFVdS8I+mFYVWV5hdBmet06a6lIihBBj2i9M4KBU1pfeH2FNAAAgAElEQVTL+s6Zi96ASbW0DskyeDzuQp/w+aQ5qyVMIYRYBmGGMx37EQwiDpfILniECROkVa6KPUaLVY2DIGkKIY7CElhkVpbgVr0QwyF/QmG2oOqnTljj7SdgraPIUgghxLIIsxxh+qoVP0fVggsTLpVWpSNPoEtJeUwESVMIcRSWwCKzsgS3Ggqzrg1zwYVZltahLiXhwAXhznBZJqvrUqJ0rBBCTGSJhOnHxuuTf9r7kdfbMNQP1ZHeJenYqkpZb7PyPdaZMdg2qT9m1VuEEOIUsyTCDAeT7ZN/ug9ozejrtcIKqmQrc6Zlo1VJs+LgYSFRlU/DtwshxCTUD7NNVE2IWRbmAkeYVe2JlwjMR4OhJENxuuAArnSwmjyrWbUoa4JRIYQ47SyBMMsFP2GE2ZK+mFBR9BMIbSzCqn4nXpjhlwIXHKzKwoEFJ70sUQohxJglEGbLI0yYIKyyNA8ZlcNWK6dka6p5xoO5c1iIEqUQ4nJYAovMyhLcatiG2edgxuM2zSBdUOXEQ/aalJKdof0yrLYti1NRphBCTGQJhOlTsgMOC8ULc0SrIsyZunVMqs4J07c1adlQlHVZXnUrEULMwhJYZFaW4FZ9lxL/Ce/lOCiWlkSYVbKcOPB5XcVOWPQzQZbhISRNIYSYyhII06dkBxzI04pHvyy4MMsR5njwdSpkVdXwWHXASX02C3GWpShZCiFELUswPXA4hmwf2AN2yYt/fKXsAguzymlVwjrUnlku9pklp1uRjq0Tpab2EkLMSrwASwVm9hwzu8vM7jazV1W8/kQze5eZ/ZmZfcDMvnLarS5RhJk2fSFXRmVq1KdPy9Wv09brDlhsDwdEqBtDVmPJCiFaiplFwGuBZwMfB+4ws7c45+4KdvtXwBudcz9vZk8D3gZ8xqTjLoEwW47LYDSA/i7sXoS4k2/fsjxQ7hPULflIOlxGNQcuN4QWBnQJZDFYAmnxOCAPzP03tQzoX4St87C3DYN9yI72hSQiJWFEwogOQxJGxKQM6RRb82VIBxlZiBazmBa5CfiIc+5eADO7DXguEAozA84U6+eAj0076GLe6mkiy2DUh/4O7Ba/jnQIuyVhZnDQfcYvkyLrmlyviwth+txrfNAbx59iAAx3YOsC7G7DoH8Zwszo0WeVPVbYZ5U9ugzYY5U9VtlnhT1WGZHgJEwhxPHyBOC+4Pn95BINuRV4h5m9HFgDvnzaQSXMpnHuIMLEIB3BYC+X2D6lCNNPV5YGS137bEWhj4uKxSCNDp73i128LPfJJb63A/s7eYSZHk2YMSk9+qyzwyZbbLLFCvvF2iaGY0TCPiuL3ulHCLGcvAD4JefcT5vZFwG/Cjx90hskzKZxGQwH+bqXZbJ1OJAcUgjTz8xSfqzCKh4tl2VWtGP6dTiQ5R7QKa5l2M+vbTi47AhznR3OcoGreYR1dugyICIjJaZPD5MuhWg3DVjk9o/B7R+fuMvHgOuD59dxacr124F/BOCce6+ZrZjZNc65h+sOKmE2jW/DTEcQ7eWpUosOBu/xXhx7xZUej3o+C7pqlmQZFvk4l19blhWPRztfREaXAevscI7zXMPDnOEihiMlZp8VttmQMIUQR+bmJ+SL59b3XbLLHcCTzOwG4AHg+eQRZci95GnYNxRFP71JsgQJczFwXkrzPm/p8ZgLjR1GRkRKzIiEtGgojUnpMmCNXTbZYkB3vJ9/dMvQ40kI0QjOudTMXga8gzwUeL1z7k4zuxW4wzn3O8D3A68zs39B/un7omnHlTDFiZAR0afHDut0GGK4caHPkA4JIzbZIialT++SZSRhCtEOFtQizrm3A08pbbslWL8T+AdHOeaC3qpoO76N0qddU2J2WcNhOGzc1WSDbfZYZYd1ttkAKLqaCCHEYiFhihMhI2JAlx3Wx22WK+xXLjuskxT9SUck7LHa8NULIWamZqSdZUTCFCeCjzBHJONIs8uAq3iUmJQNttlki6t4lC02gQNZRos8lKEQ4tQiYYoTwRExpMsw2BYXo/6ssQtAlyHr7OCwcVrWt2IO6I7Tt46ITGP0CSEaRsIUc2VIhz1WucgZEkY4YECXfVYwHGvscjWPsMoeA7oM6Ywfh3SbvnwhRJlTZJFTdKuiaRzGkA67rB1qs/SPXpgdhgzosssae6yOi4UkTCFEk0iYYm54YfqiHt9m2WUwrppdZY8zXCQl5iJnuMiZ4H1CCNEcEqaYGw4bt016cXYYssE2Z7jIJlusscsZLgL5AAf+PbusNXz1QohKTpFFTtGtikXAT++1zwoAhmNIhy4DznCRVfa4mkeK9s1LU7hCCNEUEqaYI3mVqyuNIDukwz4r7LDOFpv06NNlQJ8eAD36nOEiGdGhuTT9kHsaRk+IBlE/TCHmh484t9kYR5ZemCkxXQac5QI9+pcMe5CPOyuEECePhCkax48E5Nssh3To0R/3wOwyYIV9znGeLTbZZoOIbDxebXaavuIKIRpDwhSN44UZtlmusM86O6yxyxq7rLPDKnv06BOTkhIzoKtRgYRomlNkkVN0q2JRGZGQEY1lGZGxyh4OG4/84yeh9rLs02OXNc2nKYSYG60XZj7jYkZMSlSsA8VapPkVW4AjIiUiDf4cMyLW2WFAdyxUL0dJUogFovUWmZ3W32rCiC6DcSTSZYDh6NNjQHf8OCgqLkU7CGc7ucDZ8RRhj3IVFzjLLmvjPp1CCDEPlkKYq+yN27s22MZw7LDODuvj4hAJs104bJx2jckOza+5xSY7rDOgS6bMgRBiTrRemDEpPfpssM1ZLnCWC+PKSh+V9CXL1hFGmHk1bL6+zwp7rLLPioQpxCLQeovMTutv1UeYG2xzFY9yDQ+PWy99JeUO601fpjgiXpgH4twgZnRowIJ80AKlZIUQ82EJhOkjzB3OcYFr+BQRGSM67LPKDhskpE1fpjgiB/NpaoYSIcRi0HphGvlNdIEVYI18pKaVYluCph1eHI7zN6FKWSEWglM0bkjrhRlxIMweuTAjDgtTrVxNY6XH8vaj4GrWhRDiZFkKYcYcRJir5DflhRkjYTZLWZZ1j7PikDSFWCBab5HZaf2t+pRsh4OUbChMRZhNEkqxbv1KkCyFEPOj9cIMU7IS5iJiVAvzcqXpx451xXslTSHEfFgOYVrefrlqsG75Ta066Lk88oz0mdogNmW5HDIkSyEWhNZbZHZaf6uRFcKMYDWCjUKYaw56GSQOogx9tjaCl2JUeqxKz9ZRbq88DuEKIcTRWQphdiLoxrkw1yPoGKym0DPopBArGGmAstgiDgtzmvSqCnvKj0KIxlG3kvYQAUlURJgxbCR5GnbNoDeCjlNKtjnKsoypb8usIhRk2GZZjlL1CxZCnDztF6blEWUvhtUkF2ZiefeSnitSshrop0EuN8KEA1GGi1KyQohmaL0wzSCKIUmg24FeN48wu0VbZpyBRaDR8ZqgLMvjEKbjoOhHCNE4rbfI7LT/Vsv9Snrkn6X7xesOybIRyqnXOmFO6vRTJ8wISVMIMW+WT5hrHHwWe1mqI2ZDVMmxar2OUJL+eTbje4UQ4nhZPmGucyDLETBAwmyUOmmWo80y5YKfMLqULIVYGNpvkZlp/62GwlzlYPR1L8t9JMzGCNOy5XbM8LGOqgjTpwwkTSHEfGm/MP1gsj0OR5helh0kzEap64tZbtMsUxdhxlwqTXUrEaIx1A+zRfgIMxx9PSKXpQaTbZCqPpiTIsw6adZ1KxFCiPmyHMIsz+8VAztofq/GqRu4oFz8E+7vH+sqZNUHUwjRDMshzPIM0jGarmQhqBNmXV/Msgh9VWzY/3JasZAQYq603yIz0/5b9W2YYbeSsjD1udogs4z0UzVcXhhRhqPnS5RCiGZovzB94BK2YSrCXACqin3qxpKt2gaHRVkVXUqcQoj5sRzCDFOyvg2zRy5RCbNB6ipky69NS8t6NGiBEAtH+y0yM+2/VSMXZJiW9UVAHQ4HNaIBqsRY1Q5ZXvd4SdYdTwgh5sPyCLPDQV/MMMJUlWyDlKPLulF+yqL0bZj+FxdKsyxKSVOIRmm/RWam/bcatmHWRZgSZoNURZZV3UrK4vPFPqE0y+8VQoj50X5hhhGmF6Yf+SdBVbKNMmmUn1nlp5SsEGIxWB5hhoU/fl0RZoOU06ZVUaZfqpiWkpUshVgINDRei/CfuX54vF6w7itk9dnaIFVVsVV9MsuEAxXApSlZat4nhBAnQ/uF6T9Dw7SsF2aMqmQbpaqYp0qck947KSUrhGic9ltkZtp/q2FKtixMRZgLQN3IPuWinzJ1KVkNjSeEaIblEGZdhJmgCHNhqIsuj5qSlSyFEM2wPMIMI8wOijAXikkDF1xuSlYIsRC03yIzsxS36iIjiyCLjTSJiBJHFufbnITZIFWDDFS1Z87y/rqUrhBCzIfWC9NZsURGGhtpYkRJRBobWWQ4M5w+VxtmmviO+r7yPkIIcfK0XpgUssxiKyJMIyrWXWSKMBtnWoR4JRGmEKJx1A+zPTjyCDLzEWacp2TTQpqZGU4frg0zrXtJFS543XGpPIUQYr60XpjjCDMqpJkYlkRFG2aRjtXn6wJQJclZfjmT9tcvVojGab9FZqb1t+rwUaaRRRFpFBFFjiyK8ujS7NCMimJe1KVQ67ZVUY4yy+8XQoj5sRSjrObSjMjGS0xGnop1+nBdEKaJU1WwQojjw8yeY2Z3mdndZvaqitf/nZm938z+zMz+0swemXbM1keYFFLMxo8RKZARjYWpCLNJLje6lDiFaAULaBEzi4DXAs8GPg7cYWZvcc7d5fdxzr0i2P9lwOdNO27rI8xxSraQZbg4zZ3YMEeNJicJUr9DIcTM3AR8xDl3r3NuCNwGPHfC/i8AfmPaQRfwu8FR8VFkKEufolWEuThMii4nRZlCiIVmMbuVPAG4L3h+P7lEL8HMrgduBN417aCtF6aPMLNiSYmJghStupQ0zSyFP9P6YgohxInxfOA3nXNTY6vWC9NzOMoM2zBBH7qLwlGLe1QEJIS4lNv/DG5//8RdPgZcHzy/rthWxfOB75rlvEsgTKtowzyomlVKtmmmSfKowpQ4hVgoGrDIzTfli+fWX7pklzuAJ5nZDcAD5FJ8QXknM3sqcM45995ZzrtERT9RqR0zQt1KmqZqkIGqtOy091e1dep3KoSoxjmXAi8D3gF8CLjNOXenmd1qZl8T7PpN5AVBM7FkEaYFKdkDWSrCbJpp1bKT3jepG4qkKYSoxjn3duAppW23lJ7fepRjLoEw4XClbEwaRJwq+mmaqtTr5QpTKVkhFo4lscgstP5WD6pkI9KgDTM91K1EH7DzpxwJHrX9sup9EZKmEKIpWi9MH11mY2nGGEZGrAizcSa1W9alWcvvD2XpUKQpxIKxBBaZldbfalj046NMO1QxqwizWaa1X06rkg1FGXEQZQohxHxpvTDhYNCCgwjTSZYLRVU0edTosmq7EELMj9YL83AbZlwIMxu3Z6oNs2lmiTCrqEq/qgBIiIVjMYfGOxFaL8zDFbJhG2ZYJasP1WYoy7JctDMtHZuV3suU9wghxMnR6MAFZhYVc5G9tXh+o5m9t5i/7DfMbKrQwwgzKyLMlISUOJCmaI6qStdwqdpWFmtVdaykKYSYL02P9PO9wIeD5z8B/JRz7rOB88C3Tz+EHepWciDLeNyOqQ/XpqgSpTFZlJPkScW6EKJRkgVY5kRjwjSz64CvAn4h2PxlwJuL9TcA/2TacfIIMzrUhjk6FGFqpJ9mmUWas7ZVqu1SCNEcTbZh/jTwSuAsgJk9BnjUOZcVr98PPH76YcIh8XJhgguKftQXsxnqUqqToscQFzxKkkIsLEtQCTMrjUSYZvbVwEPOuQ9w+FPwyJ+I4UwlKVERXSbjlKyKfhaBy03JHrVQSAghTo6mvht8MfB1ZvZVwCqwCbwGOGtmURFlTpq/DLgdgAsPDzn/iWvJuJqUhBEJDleIMwqkKebPtIIfv9S9N4wy/aOGxxOnlXuKRTRFI8J0zr0aeDWAmT0L+D7n3AvN7I3ANwJvBF4EvKX+KDcDsHnNPpuP3SNln1HRfulwQeGP2jCbpZyWrXqswsux/ChZitPKjcXieXczl1HmFPXDbLpKtswPAK8ws7uBq4HXT39LWCEbMyRhSMKIWBFm48waYR61WlbSFELMn8aba51z76b4quSc+yjw9470/tKgBXmEybh7iYp+mqLcDaQuupwUYfrHqihTCLEQNG6R+dH6W3Xkk0V7WY7IijZM3w9TH7DNEUqzrtBnUpVsKEq/TVGmEKIZlkCYdii6HOCIx0U/iVKyjRNKMq5Yr2sAcRXrXqD6EiSEmD9LJkzHkHwE0lHRjilhNklVZFklzUn9MMuo8EeIhaL1Fpmd1t/qYWEaQyJSHMNiEAMJs0nKxT4xhyPLWSPMEEWYQohmWCJhGkMyBkTEwGhcOWvFeLJivlRVx1bJ8qiF2uXCISGEmA+tF+ZBt5JckkMo1ilkiSLMRvFyK0uyXPhTxhf9lLdNKxYSQsyVJbDIrLT+Vn2EOQJGGAOMCBjiGOEKYWrogmYot2FeTtFPWYrldk9JUwgxH1ovzLxLScSImAERfSIiYEDGiIyUDEdKfZuYODnqBiwoR5lVlH9fVTOeSJZCNI07RSP9tF6Y7lCXkpg+SSHMlBEjUkZFhJk2famnjHIfzEnp2ElVsuU+lzGTU7lCCHEyLIEwjawQ5pAOfTpFSnZYdDFxZGTTDiNOhFmHxasTppF3EqoSpiJMIcR8WQph+mm9BnTo0yMq2jJHuCAlK+bPrGPITir6CaVZjlIlTCGaJm29RWan9bcaDos3pEufHoYxwBVtmKmqZBuhauD1MDqcdXovV1qvGohdCCFOntYLM0zJ+gjTMIbjNsxY/TAbpSzHsHJ2UqVrXZWsRCnEIqEIs0W4YoCC4SUR5oghQ1Ii3JE7x4vjoWqg9ECWU51n4MrilCyFEM2wBMK0oEq2SzIW5pARg2KKL33ANkdNdxCzg5frcOT7Hephov6XQohmWAph5inZDgM6xGNhDhiRkCkl2yBV0SWBLKf8XnzTpflIsyxL/V6FaJpRvAgZvPn0hGi9MA8GLshTshE9jIgh+8UUX7FSso1SU+Azdt4E6YX1PpKkEKJhWi9MR0TmYkZZQpR2sFEPLGKYdhllCalTSrYZym2NpTTs1NodOzycrHEQZTq1Ywoh5k/7hemMLItJRwnDYRcGPXARo2GX0SghS2Oc04drY1RlUasKZatwNUvYy0QI0ShpsggaGczlLItwp1eEc0aaRliawKiDG/QwFzEadkjTDlkW4TKlZBuhLMkqWU761XgpZlwqzXAfIYSYA0shzCyLGaUJ2bBLVkSY2ahLNkrIsphMEWZzVMmyPHZBHV6UYUSZBY8gYQrRMGl8ekZfXxphulEuzHTYAxfjhl1cmuCUkm2WWYaTnfTesijhYKQ8yVIIMUdaL0yc4bIIl8YwSqDfhSyCYQKjOF+XMJvhuMZed8G28DX9WoUQc6T9wszIZ+4aWt7u2y+eD4ptmgqzGapkGVMtz7r3Z8XrZXn6bUKIxklrJ4FfPtovTD/V5YiSMC3fljKvPq2iTNW467O2YYZiDAt9wkpZv0ieQog5sHzC3AeSItr0wtQHajOUo8nyVJaTZugK2y+rupPoS5AQYs60X5jjlCwVKVkUYTZF2KXEy9KnZGcRZlmQ4exe4ZzSQohGGSkl2yJ8tBGmZP26IsxmqYowyyP8TIsww3UvzKmjBAkhxPGzBMK0g5TsyKBv+V0Ni22ZH0pNzJ2qop9w+7RfS7ndsjx/tBCicdIl0MistP9OfYQZpmUzDoSpCLM56gYsKL9WRZUsIf99KsIUQjTA8ghzxIEwvTx9+6XaMOdPuQ2zNB3m+LVZx5L1z6vEqy9EQog5sDzCDCPMGEWYi0BdhHlUYYbrasMUYqFQP8w2EXYrqRJmOFKMmC/T2jBhujD9Y5UwhRBijiyHMH2E6aXp131KVsJsjqoZSo4aYVppXRGmEAuDIsw2URZmGGFKmM1SNVOJ3x6+XoWreG1a300hhDhBlkeYProMI0y1YTaHldarosJJ4quSpSJMIUSDLI8ww5RshFKyi0JVhOm3X8mxJEshFgKlZNtEVUo2QinZRWDSMHizCq/cbUSyFEI0xBII00HqYJTBIIV+CpGDYZZvS7N8HzF/ysI8ji+i5e4pkqcQYk60X5jpCPr7sLMNnS5EUb5ceAR2tvLXRqOmr/L04SWZAD1gpViulPLYwUKIRtHg620iTWGwD7tbEBlkGZjB9sVCmHu5VMV8MfKIsgN0yWW5dgzHDWXpB3MXQog5sATCLCJMi3JZDga5MPd2YX9XEWZThML0EeaVCtNxIMuE+smnhRBzQ4Ovt4lRIczMR5rbgMFoAMMhDAeKMJvACzPh+CJMR17MtV8cVxGmEKIGM3sO8DPkX61f75z7iYp9ngfcQp67+qBz7oWTjtl+YaajA1ma5QuWF/q4ouBHRT/zp5ySXS2WK6VfHK+DBjEQQlRiZhHwWuDZwMeBO8zsLc65u4J9ngS8Cnimc+6imV0z7bjtFyZIiouIy/Iof7AH/W3YPQ/xleZQHexdyI833Id0OPffe0RKXCwJI2JSDDfeOiIZr8vm4jSwoP0wbwI+4py7F8DMbgOeC9wV7PMdwM865y4COOcennbQ5RCmWDyyFIZ92N+B7U6+bXilZa0Ots/DzoX8uKNBLuY5EpOywj49+qywzwr7xKTFWr706S3qh4gQp4UnAPcFz+8nl2jIZwOY2XvI81W3Oud+d9JBJUxxMmRZLsy9nfx5OsqLsK4Ilx9vfzs/1nAw9wgzJqVHnw222WSLDbZJGLHNBttsjKNNIU4LLf57T4AnAV8KXA/8oZl9ro84694gxPGTpUVEuQPZKG9jTrpXftxhP18G+3mEmTUTYW6wzTnOc47zdBnQYYjhGJHQpzfXaxLitPGnt+/wp7dP/AL+MXIJeq4rtoXcD7zXOZcB95jZ3cCTgffVHVTCFCeDKyLMdJi3Y0Zx3vXnSsnSXJJZmi8NpWS9MD+NT9KjP44s91lhm425XpMQp41n3LzOM25eHz//T7de0vx4B/AkM7sBeAB4PvCC0j6/VWx7Q1Hw82TgbyadV8IUJ4NzeRo2bfpCjhfDYbhx0U/CiA5DugzG7Zqr7LHGLikxGREOIyMiU1mvWEIWcaQf51xqZi8D3sFBt5I7zexW4A7n3O84537XzL7CzD5E3sP7+51zj046roQpxBFIienTY5uNcRq2R58d1kmJ6TLgLBeISRnQHS99egzoki3gh4sQy4hz7u3AU0rbbik9/z7g+2Y9poQpxBEI064+DbvCPlnR4aTDkDNcZJ0ddlljl3V2ihEbRiQSphAtRsIU4gh4YYZtlivsj1OyPqbs0eciZ7jAEIpioL1jGblBiMVCQ+MJISrxKVkvy4QRK+xzlgskjMYp2bNcoMMQYCzLiPkWKAkhjhcJU4gjkJKQktAPtvXYJ2HEBtt0GLLJFo/lExiOIR32WKXLoBBmVb9RFQKJ9tLifphHRsIU4gpxGAO67LLGBc6SkA/2v8UmA7pEZGywTUrMHquMSBjSGT+eppSWEG1G/6lCXCEZ0ViYXpZehgO6xKSss0OHIX167LE6XhwmYQrREvSfKsQVEkaYkMtyn5XxIO1emGe4SJ8eW2wSk45FK0SbUUpWCDEzofh8m+UWm6yzU4wwuz1eH9IhYTSWrCpnhWgPEqYQV4iXX1gNaziu4eFxsc86OzyGT5ES4zCGdA6lcIUQi4+EKcQVY0Vb5OGxcsPpvvyjK/YNx6TNBzQIZ9rUfJqiPSglK4S4YnzE6dssHUZENi72WWGfc5ynR58+vfGyz8p4DFohxOIgYQpxQvjin4ucGbdz+sEMgPGU02e4yA7r4zk1/b7znelTiMtjEQdfPykkTCFOCB9h+jbLPVbHs5l4Wa6yR8KI85wjIhvL0qRLIRYOCVOIE2JI51CBj+9ecjWPjKcCO8d51tk51M1kh/XpBxdCzB0JU4gTIiNmUEpXpcSssscmWxiOLgPW2B0PZeAjzx59hmTjIiE/p6YKgcSicZoG3jg9dyrEApARjefT9F1O/HRhvo+ml6mfQ3NAt5iiWsPoCdEk+u8TYo742U52WB+nYf34sinxWJir7LHPCjusF/NqOkbEpE3fgBAl1K1ECHEi+AjTF/h4eXYY0iniyDV26TBklzU6DInIxqIdTj+FEOKEkDCFmCNefKEs/RyaZ7jIGrtsssVZLrDF5qGJqhVfCtEsEqYQc8SLsk9v3HWkwxDDjbuYbLLFp/FJevTHgt1mQxNQi4VEKVkhxAlxUOXqR/JJicf9NLfZoEefhBF7rI77ZK6xy1U8So8+I5JDc2qqEEiI+aD/NCEaJpy55AJnx2lYH416YcakbLDNHqvsszJ+lDCFmA/6TxNiAfCDGxhuLMqYlIiMiIxV9lhnhxEJW2yyxSaQjyYkRJNoaDwhxNwIRwPyBT7bbIwluc4Oa+yyzg4OG7d5+qH3hBDzQcIUomG8MH2Bj48qz3GehBEbbLPGLlfzCDHpIVn6SFOIpjhNTQKtv9MoSFv5FBZQ2pKvC7GYGBnxJX+jXQbss1KM9JML1adsNf2XEPOn9cKMSYOZBPt0GYyHFfNDi+WPEqZoFz49u8UmCSMg/3t/lKvYYnM8QpAQYj60/r8tYcQK+6yzwwbbrLOD4cbzC+6wTkrMgF7TlyrEkfDzaW6zgRXPIzK22WCLTfZZYUin6csUpxz1w2wRXph+dJRznCci4zznDlUcCtE2fIQJuSx3WR0P1u4XRZhCzI/W/7fFpKywzwbbXMWjXMPDRGTjvmx9euN0lhBtwkeYvsDH/x2nxOPB2iVM0TSKMFuEb8NcZ5czXCwqCTOGdNljjS36GoNTtBI/n6aaE+AfEJIAACAASURBVIRYDKKmL+BKsWKJgJj8G0BSrEfFolpCsTzor1mIppgpwjSzVeB659xfnvD1HBkvy1CYcbB4oQrRXsp/wf65m/eFCHEJp2mkn6kRppl9LfAB4O3F888zs7ee9IUdBeNAkIowxXJipQX0ly3EfJklJfvDwE3AeQDn3AeAzzjBazoSYYSZUC1MIdpLWZCSpRBNMUtKduicu2B26B90YXJBVW2Yfl0pWbE8lP+SF+ZfUJxyNDTeYT5kZt8MxGb2ZODlwJ+c7GXNjpHfRBfoAavkolwBOhwIVIiTofx1rEpkl/uVrS66LCN5CjEPZhHm9wA/BPSB3wB+F/jXJ3lRR8GnYrvkklwnF+YquUAlTHEy1AnMOCywuoKdo54nPF9WPEqUonnUDzPAObdLLswfOvnLOTqhMFeBNQ4izC4SpjgJqiQGBwLz0rTSe670PP64Ebk0y3IWQpwkU4VpZs8AXg3cGO7vnPu7J3dZszMpwuySp2UlTHG81ImsLrq83EKdqqpY40CW4bmFECfNLCnZXwNeCfwFB7mghaEszLXi+QpKyYqToCyvKHheFtdxVLdWRbPl6FWI5lBK9jCfdM4tVL/LEAPiCLoGPYNVK4TpoOMgdhA59CVcHCOhLMsi80tZlpcjzKro0qdkJU0h5s0swrzFzH4B+H3ywh8AnHP/34ld1RGIYohjSBLoJtCLITHojCAZQZyCjUDDyYrjI5Sg77wUfisLpTlLlSs1r9UJMzy2pCnEvJhFmN8GPJW8OTAsz1sIYVoEUQeSLnR70OtCx6Dbh84A4gFYhoQpjolQYFGwuIqlqq1zlmOXzxM+lot+hGgWpWQP84XOuaec+JVcJhZB3IFkBTor0FsthFlEmrGDaAQMm75SsTyUZemFCdXChNmkWZW2La9nwTklTSHmySzC/BMz+xzn3IdP/GouA4sgTiDpQXcNehu5MDsGiStSsv3pxxFidsI2TD8I45VGmEcpENIIyWJxOE2Dr88izC8CPmBmHyVvwzTALUq3knFKtgcdL8wIulnehhkN8n2EOB7KAjyuCPMo+2VT9hFCnASzCPM5J3FiMzsL/ALwueSfAC8B7gbeCNwA3AM8zzl3YeKBYvLWVd+nZJP882sEDID9Yh8hjpWwSnaaMKdFjFWyrNr3ctpFhRDHRa0wzeyMc+4isHVC534N8Dbn3DeaWUI+5sCrgXc65/6Nmb0K+EHgByYeJSIXZq84ghfmANhDIxeIE2BahBk+ztqlpHzMsMiH0rpkKRYHDb6e8+vA1wDv49JOXw74zMs9qZmdAb7EOfdiAOfcCLhgZs8FnlXs9gbgdmYVZhhhxuSy9COwK8IUx0pVWrYsyvL+VetVxyz37QyPWZXqFULMi1phOue+pnj8jBM472cAD5vZLwH/G/CnwP8JXOuce6g474Nm9tipR6oT5jYHwlSEKY6dWQQHs4mt6lj+j7ac4q1KywrRHKepW8lUlZjZ78+y7YgkwBcAP+uc+wJghzySLH89nz4+j2/DDFOym+Ty9COwn57fpzhxqgp5yl1M4mApv1a1lI8x6X3llK0QYl5MasP0Mds1ZnYVB/+hZ4AnXOF57wfuc879afH8zeTCfMjMrnXOPWRmjwM+UX+I2wF4eHuXT+ysHkyIqelKxFwoy/JKKYszbMMMlzAKlTRPF/cUi2iKSW2YLyVPkz6evB3T/3deBF57JScthHifmX22c+5u4NnAh4rlxcBPAC8C3lJ/lJsBuObswzz26geh89DhGaR7HLRf6nNFHCtVKdTyH5lPn5apa+Msy7IqJeu4dKYScXq4sVg8727mMkqcppTspDbM1wCvMbPvcc79hxM498uBXzOzDvA35EPwxcCbzOwlwL3A86YexTicll0hv6tQmIowxbFTV9VKab1c5TppMIJylFluCy1HmOVzCSFOklkmkD4JWeKc+yDwhRUvffmRDuSbfLwwyxGmUrLiWKkbuMC/Fj7C4QrXSXKrSsl6SYYDu9cVGgkhTpr2d6AJI0w/KWY5wtTnijh2ytIMt/n1cncQuPKUrGQpFgsNjdcmggjT9cCtgEvydaVkxckQSrGqHTOMDqF6nswy5S4l5ZRseO7yeYQQ82CWbiXfXnoem9ktJ3dJR8TAxYUkvTR7xXqSv6bPFHH8VImrqotJOYU761I+bt0+QjRLStL4UoWZPcfM7jKzu4uR48qvv8jMPmFmf1YsL5l2r7PEXs82s7eZ2aeb2dOB95L3dFwMipSsS8B1Ievli+vm25SSFSdLlcgmCbPuGHXHmiRK/WELUYWZReS9Of4R8HTgBWb21Ipdb3POfUGx/OK0485S9PPNZvZNwF+QDzDwzc65Pz7a5Z8gBi4qRZiFPF2niD6VkhUnQlU0GLZB+rkrfXeQWY41rfpVEaYQM3AT8BHn3L0AZnYb8FzgrtJ+R/pHmipMM3sy8L3kgws8DfgWM3u/c273KCc6KZwv+ikLs0jJalAUcfxURXplWfpvaVmwz6Q2zFlTrhKmWCwWtB/mE4D7guf3k0u0zNeb2ZeQz5T1Cufc/ZMOOkvs9dvA/+Wceyn5wOgfAe6Y6ZLnQRREmKWULGrDFCfKpHRsVReRKsmWj1N3XKVkhThm3grc6Jz7POCd5BN+TGSWKtmbimm+cM454KfM7Lev6DKPEYeRWcTIYkbWYRh1cVHG0BJGFpNZhDN9sIjjYpokp8lv2vHC9s+6oZRnSd0KMR+aiDDvvf0e7r393km7fAy4Pnh+XbFtjHPu0eDpLwD/Ztp5Z2nDvFix7e5p75sXuTBjUosZRgkD65JFKaOoQ+qFqQ8VcezURZShyGadv3JSNFlu/1Q6Vogbbr6RG26+cfz8Pbf+YXmXO4AnmdkNwAPA84EXhDuY2eOccw8WT58LfHjaeVvfD9NZHmGmFjO0DoOoQxbl6yNLSIklTHHMlCPC8LEuhTqrMKsiTF9A5PeddjwhTjfOudTMXga8g/wf6PXOuTvN7FbgDufc7wAvN7OvA4bAI+TjmE+k/cLEyIgYWcIoShhEXbIoYxgl4wgzU0pWHDvTZAmHo8SjRphemD7C9NKUKMVisaBFPzjn3g48pbTtlmD91cCr/3/23j1Ylu2u7/v8unte+3HOuVcPHrpISqxYxISUBURgE9viYSMwQSQOBBEqEJOKU6Bgm8TBkErJCpUy2IWxY8rGjmVKdgGSgSKiVDYWGAShYpmLJQUwEpJD7hV6cJF0zzn7Na/uXvmje81eu3f3zOxzZvZMz3w/VV0z09O7p/c5M/PZv9/6rd+6yTmXEqaZvQR4WXi8c+5aDLwJHEZmEVnkI8xSmNYhjRKlZMWKWWb8EuojwUXCrBNwzvVzSZpCbIJlppV8P/BfUOR3s3K3A7ZGmDkRKQlTK8cwrRQmsVKyYo0sqmb1slsmOpyXyq3+vNKyQmyCZSLMrwVe6Zwbr/tiHoVCmIUYUzpM6JKTMy1bJuUowhSrZl4VbDX6hMuUKjT3h62LLuG6ONV8XWwXar5+ld+haGO+xcIsI8xAmCkdUhIyIpy6r4u10CRNL7VQlGHXn6ZzzUvt+p9VWlaITdEoTDP72xSf0AvgfWb2Lwik6Zz7jvVf3mIcRkZERnxFmFOKlGyulKxYC4tkGaZSQ2k2vRfrCofqOgMpyhTbRVPz811k3m/6a+Xtv6boiLCVXI0wk1KYjikdpWTFmqkbawxvfTS5TEq2aQwzPKYaYVJznBBiXTQK0zn3FgAzOwRGzrmsfBxTLM+8FfgxzDSIMLNSmEVKNibXl4pYKU2VsFVphnJclJKdNzUlXIC6qdWeEGLdLBNL/wvgy4Gz8vGAYjLoH13XRd2EvEzJpnSY0mVc1sVO6AZjmPpiEauiKsnq+pfhVl2hZN6KJU1TVMJuQRrDFNvHts7DXAfLCLPvnPOyxDl3ZmYHa7ymG1GMYcakJEzoMC5HLS+FGavoR6yYunHLus2zqHFB9Zzhz7tgq0oVJE0hbo9lTHJuZp/nH5jZ5wPD9V3SzXBEZUo2KSPMHmP6TOgwJSFXSlashXmyjMtt3kLSi7bqiidNXYWEELfFMhHmXwB+wsw+RvEJ/XSKRrZbga+SLSJMGGPEwJSElI4aF4g10CQ4L8u6CDPc5p2vKlgX3NYV/QixWZSSvcqvA5/NZU++32a5yPRWuEzJwgRjTEQETMpCIKVkxWpZdgzTf4n4XrDzRNc0JcX/fDiO2VQcJIRYN8sI81865z4P+E2/w8zeA3xe84/cHnlZJTvFmBIzwhFTyHNaRp9KyYrVUpc2rZOnl114v+m9GEam/j5cj0yr0hRis6jTD2Bmnw68BBiY2au4/HTeAbao6Ccio/hPK1KylBEmpBTNb5sK+YV4POokGe7zoouZn5KF67L0X0J55WfDgh8hxG0yL8L8Cor1wZ4C/kaw/5QbLomyTvwY5hRjQsRolpLNmZKT4chnXzpCrIJlinTCuZhemlA/tcQfG8rSS9aPX+ZcH8NUlCnEbbKoccFbzOzPOOd+6hav6UZczsNMmBAzJibCmJCSkpGRlarMFpxJiJtQV6RTJ8tQmsukZMMKW+DKH3thhClRiu1ArfECnHM/ZWZ/GvgcoB/s/1/XeWHL4so+sn4e5ohOGWFGTJmWKdl5E8aFuAnzKmSbUrJVadads1phG3NVlP5W0aUQm2KZ9TB/mGLM8kuAfwD858Cvrvm6lsZXyfq2eCO6RGW17BTKlGy66csUO8WiOZjVaSVwta9s3fnqIkwvSP8zXr6KMsX2sE/TSpaZb/FHnXP/FXDfOfcm4I8Af3C9l7U8+UyYCWO6jBgwos+EbtmAPSbXtBKxcurmX/otqTz2Apw3DaX6XPhzdY0QJE0hbptlks++q8+FmX0m8CngM9Z3STfjMiXbYUKPEf0ywnSkZKRMNQ9TrJB5oqxuvka7WilbR1NrvTDCDCNRyVKI22YZYb7DzO4Bfx14D8Un/v9Y61XdgOsp2T5WFv0UY5iJ5mGKFbOsNOH6lJB5VbLVc4VzL704q7LUe1tsln1KyS5T9PO95d2fMrN3UDRjf7jey1qePBDmmB5RKcwxU6ZM1OlHrIG6McyqLP1HqyrMpvPVjYVWxzDhekpWCHFbLFP00we+DfiPKT7Bv2Jmf9c5N1r3xS3DLCXrEiaui7k+5oyJGzN1fgxTXyxiVTTJsk6aXpQ5V9Osdeesnics+pnXa1bvbSFui2VSsv+IolnB3y4ffyPwj4GvW9dF3QTnjCxLSNMONulioz5kEZPJiDTtkGUxzinCFKsklFW1sKeuQMfLs2l6U7VKtulnNIYptg+lZK/yHzjn/lDw+BfN7LfWdUE3JXcReRaTph2Y9mDchzwinfRKYSa4XF8sYtUsU9UapmPzcl9T8/WmCNM/H45hqkpWiE2wjDDfY2Zf5Jx7N4CZfSHwa+u9rOVxuZHlMaQd3KRHPh5AFpFNemTTDnkWkyvCFCtjmZRsNUKsjknWUZWlqmRFO1DzdcDMfoPiE94B/m8z+3D5+GXAB27n8hbjygjTpR3ySZdoXKRk82mv2KeUrFg5oTTrRFfXsceLs+l88zr9KMIUYhuYF2F+9a1dxWNQjGHGMO1g0x6UESaTLi7tQJaAUrJipdRNK2mKMMN0bFOE2dTpxz8XrqcpWQqxKeY1X3/2Ni/kkckNMoOp4UYRXESQRDCKYFI+J2GKlTFvDmZd9FdN3zbR1LjAv6ZPy/pxUE0rEduBmq+3CUex8OUEGAEXFL/ViMtFMbWyl1gp1ZRsVZh1DdrnTQMJzxcK1lNdPFrTSoTYBO0XZs5iYWqxErEymsYvHyfCbOox6wkbGFTFLIS4LXZTmDESplgj1ZRsQnP059vhhY/rCKPL6nHhWpqKMMV2oXmYbaJJmMNy3xQJU6yQqgx9dFlNq1Zl6UX3KM3Xq+31VPQjxCZovzAdxaIQU2BMIcqovD8pn5MwxUqpS6E2jVPWRZt156vKtkmG1XSspCk2iyLMNpFTSHHCpTDj8v4UpWTFmmkSXLivKs1F56k7V/W+Ikwhbpv2C9NXyYYRZjiG6ZckFGJlNFW+LqqAXbQeZtPPh/M3JUohNkX7hekjzKow/filIkyxNppSsHC9S8880S2aehJKU8U+YrtQa7w2UR3DHFH8sT4q92kMU6yFm0R81Shz3jHzpHrT1xVCrJL2C9NXydYV/fgIUylZsTKaxibnHbtMZFiXkp2X4p13jBC3hzr9tAnfqjOUZsTVdKwiTHEb1LnL+SfmRZjLSlUIsUl2Q5gZl8KcUHzf+KYFKvoR62JRMasLdrpwTmbTycptGV/qPS3ErbMbwgybF4wpvnCmXI5h6stFrJqmmR5XnquYb+4ycxVZzpOmr//R+1psAZqH2SZ8lWxdStYX/OiLRayDJlFWZefCJ+YU/Vh53Oy25rBQlpKmELdK+4VZHcMMU7KqkhXrYF4fgaob/dJyrvoDDSdeFGFKlkJsjN0Rpp9a4oWpCFOsk6a+BXXRpqOIGpd9Hy5T96P3tNgSlJJtE77ox6dlvTDTYL++XMQqmTdbpC77ukw0uEzvAhrOo/e3ELfCbgizOo7phemnlegLRayKuhRsVPN8eMyjvv/q0rPG5RCD3tdiC1CnnzZRJ0xQSlasj1Bk8xYOeRxRzk3vVh4LIW6F9gsTLot+wtWRfEpWwhTroCnCbDpmmbmVy4yH+vsqZBPi1mm/MJ0LIkwH5irCdMUxQqySZWRolSeWjQibionqIkxFmWLDqDVem/ArJnlp+i8TRZhiXVSjy6b5kjQ8t+icyxQULRu1CiFWxm4I08vSP4bLClkJU6ySuqIen5Ktvs8WzalsOn/d2GgYTYZRphAbRtNK2oQX5pX77rLpuoQpVs2iKSDVtOlNzxuOxTeNaSrKFOLW2R1h+tvZX/vu8q9xCVOsmlBufhGS6nhiNRpddL7wvGHkWhWjRCnERmi/MKGUYvlNlVWfEGLFLIow4VKgN5Fb3dhoXYFPHuwTYsMoJdsqMmAEnAMPKH6lqLx/Xj6XNf60EDcilFocbNVshu9AVaVuOkj1XH6rk3JY5DZvtTAhxMrZAWGmFFI85Wpu7GG5b8RlNwMhVkCYivVyg+vSrJNZ075lhBkW/WQN5xJCrI0dEmZM8Se3byZ7QRFhDstjhFgBYco0pvgE+QgTFo+bP6owfYrWV4THSJpiK9inlOy8FW1bgk/JnlGkYT9Rbve5jDAlTLFCIq5GmAmX4kwqWyjVR9mShp+vjnEKIa5gZq81sw+Y2QfN7LvmHPdnzCw3s89bdM4diTB9ZOm/xeDqvBL1ERMrohpheqnVjWGGLErTNkWYEfURZlPDBCFumW1svm5mEfBDwJcBHwOeNrO3O+c+UDnuCPgO4N3LnHcHhBmu7yXEmnE5uCm4MeRDyM8gi66nZP39nGaJEuwPi3nq5mD6ofl8CPkF5OPiOlb0vo/IiMiJg1so0m050ew238IvRyFqeDXwIefcswBm9lbgdcAHKsd9L/B9wP+0zEl3QJhC3CIuK2SVnoF1in3ZxXUp+r/j8srtPGn6ecRhm8drRT9jmNyH9KSQp1vNcENCSo8xXSb0GNNjDFDeK7YJXSYSpmgHLwF+N3j8EQqJzjCzVwFPOef+mZlJmEKsHJdCNgI7A6x4nJ4Fzwe34fSPRV2nQmGGKddr8zAnxeulp8V15KsRZkxGnxGHnM82YPYoIt+r4g6xPG1svm5mBvwN4JvD3Yt+rn2/qRCbxGWQj4qhc5dCNoSoWz5XOdYLMpRnE9VUbFPTdS/sfFTcutVMmUpI6TPimFPu8pB7PADgAfdmshzRX8lrCfG4nL/r17h416/NO+SjwEuDx0+V+zzHwOcA7yrl+enA283sa5xz72k6qYQpxE1wGWTjIrLLR2DhRMzqsQ23TdT1n732N29eXINLy201Y5gJKQOGHHHGkzzPC/kkwBVZJqo2F1vC4Wu+gMPXfMHs8Sff9PerhzwNvMLMXgZ8HPgG4PX+SefcCfBi/9jMfhH4Tufce+e9roQpxI3Ii7ToooixZcRkdJjSZ8QBFxxzCsCQAecc0mdElwkJUxw224DyViW7+8o2puqdc5mZvQF4J8UAx5udc+83szcBTzvn3lH9EZSSFUIsQ0rCkAGnHNNlguGIybjggJyIHmPu8YCElCkdpnSY0J3ddxKm2DKccz8LvLKy740Nx37pMueUMIUQpCSM6HPGERE5KQkdpqQkOIw+I2IyDjlnyIALDrjggCGD8hixr2xjhLkuJEwhxEyYhpuNWfYY02E6m3JyyDkROSfcmY1npiSYdCn2BAlTCDFLyaYkjOlxxhEDhhxzyjGn9BhzzCkDhnSYYriZZIvCICF2HwlTCEFKQkbMmB4AhuOIMyJyjjibjWE+wf2ZLP2YpyLM/WYbW+OtCwlTCAGzytdLpnQY05tVyp5wh4icEX1yIjpMOeJsdlxGTEoyk6/a6IldQ8IUQtSSETOhyxlHszFL3yZvSoeElCPO6DBlRP/aJmHuB23s9POo7M9vKoS4ETkRY3qcczhLw15wMItFE1KOOeUOJwwZcMYRpxzjsHK6iRC7hYQphKglJ2JC0fbPj1n2GJcTSi63Q8654ICEdCbLCw42fPVCrB4JUwhRi48wp3Rm1bAdpjzJ87PpJsec8iTPc8HBFVnGqpvdGzQPUwix97hylcwMZunViIwBQ8b0SEnIiWbrZyakdJnM2utdrqF5dVMbPdFWJEwhxI2Y0mHIgBPuEJPhsFmzA8NxwAUOY8CQCd3ZWpr+Voi2ImEKIZbGp12HDGaynNIhIi+jRxgwpMeYKZ1gdc3DK2OiYndQSlYIIRrw45ThmGWfET3GdJnMhOkwHnJ3JlbJUrQdCVMIsTRekqEs/XzMezygx5gBQ+7xgJiMmGwWWZ5zuOnLF2sgyxVhCiFEDUZKh5TOlb0ZMX1GOIweY+5wQo/xrN/sOYd0mBKRV9bRvDyvENuOhCmEeGzC5cF6jInI6TPijCMyYrpMuMtDDDdbQ9NvRbXt/kQpor1ImEKIx8Y3bvfrafpFp6d0ZsK8wwkDhgwZzLYLDvaqaGQXSdP9+f+TMIUQj42fVuJlOaE7W3Q6IaXDlAFDYrJywbDj2dqbReN2IbYfCVMI8dh4YYYFPn1GHHE2W0fzmNPZUmHFGpqFLCPyTV++eAyydH80sj+/qRBibfiuPxO6s+bsA4YAHHAxS8m+mN+/IkufwhWiDUSbemEz+4tm9ptm9utm9qNm1jWzl5vZu83sg2b242YmoQvRCixokNdhWnb2GdNjRH82ZnnO4WxaSkLKARfc5SF3ecAhZ/QZ0mFSNuQTYrvYiJDM7DOB/x74bOfcxMzeBrwe+CrgB5xzP2Fmfxf4VuDvbeIahRCPR5ie7TCdLRHmW+TFZBxyTkw2W0PTC7Y4Zn+KSdpMpqKfWyEGDs0sBwbAx4AvoRAnwFuAv4KEKUQr8d19/BqaPg0LYDgicg4554izWXr2jCOgSPEKsW1s5F3pnPuYmf0A8GHgAngn8B7ggXPOD2h8BPjMTVyfEOLxCSPMcMzSTyo54GJ2f0J3tuS0n9MpxLaxqZTsPeB1wMuAh8BPAK/dxLUIIdaDjzC9LH2rvCe4T0zGEWcccs6TPM+07Bzk197UeprtQSnZ9fPlwO84554HMLOfBr4YuGdmURllPgV8tPkU7wruv7zchBDbwuV6mle/ZrpMOOScjBjDzVrm9WcjmX4bztbQdNjsdn/b6D1TbmJTbEqYHwa+yMz6wBj4MuBp4AXA1wFvA74ZeHvzKV6z7msUQqyBlIQhA045JiGd7fcroPQZ8QT36TJhSocJ3Sub21thvpyrgcEvbeYyKqRTRZhrxTn3q2b2k8B7KRZzfy/w94F/CrzVzL633PfmTVyfEGJ9+LTrKcdAIdCElIx41rzdr4BywQHnHM5kqiXCxCbZWCmac+5NwJsqu/8/4As3cDlCiFvCR5jh/T6jcvbmhD4jukyIyGfraUIhWsPhNnnxYq9R7bYQ4lbxkvS3CSmHnHOXh3SY0mfEXR7SZ0RCemXtTZMut4482x+N7M9vKoTYClKSa1NHxvToMOUOJ/QZcY8H3OFkloYdMuCEOxKm2CgSphDilrletBPO0/RjmGN6nHI8G+M85hSHMaY3k67W0xS3iYQphNg4XpjnHM4qZy84YEKXlORK9DlkcKU/bTH1RMLcGJqHKYQQt0dONBOmH7McMCxVWLR098uCXXDAKcdX1t5My8YHQqwTCVMIsXF8hBn2n+0z4pDzWb9Zf3vKMTHZldZ7YoMowhRCiNvDC9NXw0bkdJnwQj45G9O8wwkv5JP0GV0Rq9roidtCwhRCbAHFeprhWGRGPBuv9Gtr+t60vqVenxHHnM5WQ8mJyo61scY1xcqRMIUQW4kfy/RTSnwa1k9JMRwHXMxuw7U0tZ7mLZLuT6tCCVMIsZWEDQt8gc+YHhE5DpuJ8oCL2VjmGUdE5GTETMq1N4VYFRKmEGIrCYUZFvj0GTFgOLsdMCQj5iF3MdxMrOKWSBcfsitImEKIrcQX9oSy9MU/hpstQv0E9zEcETkpCWN6V1ZBEWJV7IAwiw+K4WZbsdcqW7Th6xRC3AwjI7m2nqaXZU5EQsqAITHZlS5BEfmGrlnsMq0XZkJarpLnV86bYrhy7Ty//kFxK4RoP77o55RjukwAiMm4zxOccsyIPmn7v9rawx4F861/VyWk5QTn4awAwHDlOnoHXDAgxyRMIXaEjJgR/SsFPobjlGNOOWbIgKk6/4g1sBPCHJRzse5wwl0eEuF4WJaha9FZIXYLH2F6WfopJr63rCJMsS5a/65KyGaTl5/kPi/kU7P+k0WxQIdzDjZ9mUKIFeElGUaahmNKZ7ZJmLeIUrLtwadkjzjjCe7zIj5BPJuzVbTO6uzT/6gQO45f2mtM79r6mK5cOszfCrFKWi9MA2IcHRw98vLvx9YR6AAAIABJREFUzpwuOR0csT46QuwYBqUqry8nrQWmb53ppi/g9tgRYRa/SAJ0y8ed8nFE3XK1Qoh2Uf0UW+V+VZQSp1g9OyHMiEtJVoUZI2EK0W6s4ba6z0tSshTrYWeEmXApTH8/Lp9TywIh2k4oxjqB1klS4rwV9mh1tZ0Rpo8qeyjCFGJ3qEaTVWFWpZkjUYp10Xph+uiySyHLQfm4z2W0qQhTiDZiDVv1OU8e7JM0b409moSwE8LsWCHIA4Njil/qAOi5ItKM9NkR4gbcVk5mmdfxOaRF4gw/5K5mnxCPz24IE+gZHBocW/FLHbpCoh2HlpEVYmnqCmvW+TqLXmueMMMtLPjRIIxYD60XZmxlhGlwEF0K88BBPy8jTNAfm0IsZF416rpfq+mYqjDD++ExflZmXnlerB2lZNuDT8n2rEzJRqUwc+hH0MmVkhVieeqqUDf5Ol6QEfMjTS/MCLS0l1gT7RemQWLQi2AQw2FURJUHBr28TMlqOEOIG7LuKK1uLLKOUJR10vQ/6xqeE2J1tF6YfhDTyi3qlB+XabHhN/3RKcQC6opqVnHOea8Dza9XlWRVmOHP5sExkuWtsqUpWTN7LfA3Kd4Ub3bOfX/l+T8HfDvFTNJT4L91zn1g3jl3QpiWgPUg6oH1i6jTRuUGezWxVohHo0lYqzxv0/zJuijT349qtqafqT4n9hUzi4AfAr4M+BjwtJm9vSLEH3XO/b3y+P8E+EHgK+edt/XCtKiMLntgBxAdFMKMovKjk5eRphBiSVYZZTYVEs2LMsPbUJS+d1fT+bIVX7tYiu2MMF8NfMg59yyAmb0VeB0wE6Zz7iw4/ogl8pCtF+YsJeuFeVxGmBSyZIo6FwixNIvSpKs4X5Ms6x5XZTkv5broebFHvAT43eDxRygkegUz+zbgOylKX7500UnbrxKfku0XwrQjsOPyfq+IPjURU4hlWIcsq1s1tVqXcq1GlctsVVlKmmIxzrm/45x7BfBdwP+y6Pj2R5hBE1k7KGUZlWnYMXDBLvxZIMQtcZNpJctIqWkaSN1rhVIN78eV20URpj7wt8omUrK/8S74zXfNO+KjwEuDx0+V+5p4G/DDi162/cKMKJrGDoBD4E65z8vSr/clhLgBi6LMpuf8ft9xZ54oF8nSuC7LOPiZ6mvGlZ8XO8vnvqbYPG99U/WIp4FXmNnLgI8D3wC8PjzAzF7hnPu35cOvBj646GV3Q5gdij54oTAvgDOCVj9CiPk0Ca7uuLr7dedqOm/Tc9XosinCrIuCpzXPi33EOZeZ2RuAd3I5reT9ZvYm4Gnn3DuAN5jZlwMT4D7wzYvO235hhut6HVB0X48pZtX4JUsUYQqxgKoElxHmMqnbm8hymXRsXHMOT/U5cStsZ5UszrmfBV5Z2ffG4P5fuOk52y/MuggzBh6U+1T0I8QNWKbwp2kMsunYZVOyTcVAVWlGDeepFhQJsVp2RphuAO4Q3B3DxeCOwPkIUylZIZagSWh1xy0j1uq5FsmzTpihLKvVsOE5HIuLgsRa2KN57u0XZgyua7g+5EdGdseIEiM/tEKiijCFuAFVgS06DpYTZlMP2DphNkWXfquTr6NepkKsjtYL00WFFF2/kGR+B/LEyI/ADayQqYQpxBLUiWvR8eFt0zHVccnwtcJjlp2LWSfMHFXJinXTemEWESbkA8gPIb9rZImRHxl5v3hOKVkhFtEU9c07tulxSFWWi8Yv50WWYVq2eh7H8qIXK2WPenW3X5gRuI7h+obzKdmOT8karosiTCGWoi49uuzPLTpnVLmtvt68cctwS2p+rm4MUxGmWD2tF6aLDdeBvG9kh4Ewj4y8b7iOlQtiCiHmUyewVZyzWshTfS1YLh2bMD8lqwrZjbCl00rWQeuFmRMxpcPI+lxwyCl3SMg555CR9ZnQIVOKRogF1KVIq+JxlWOXOWdVlvNSsvPGMuelZKtjmJKmWA+tF2ZGxNQ6jOhxziEnNqZjrhAmfaZ0yVUmK8QS1MnLzTm27n7T+W6Skq2Ksy4lW5Wmin7E+mm9MHNipnQZ0efcDjglJcFxbocM6TM1RZhCLE9dgU6dNKsVsk2CqpNg+DrVlOwyUWZVvoowN4pSsu0hTMmek3FikPgI0/pM6JIpwhRiCerSpL6JelWa1bRq0/keNSVbVwhU17zA31YjTCFWT+uFmRExocOIPhcGp0TEwLn1GTFgSkcpWSEW0pQedVyV5bxVSJrOuUxKNqo5riklWyfXnOsRqBCrpfXCLFKyHUbAOTEPrUNscEaHId0ywlRKVojlqMrK1Wx1wms61zJb3es2NS2oRpl+y7msopUwbxWlZNtDRlSOYcac0eWk1OM5ESNiJsQSphBLUSctL8m8clxVmvPO2VTk0xRhNs2/TLhcTaF6fF55TsIUq6f1wsxLKQ7pcgY8xIiAMxxDYIK78lEXQtSxTEq2GmHCVRk2nTc8f/W15hX6NEkzjDL9fUWYG0MRZnsoIsyEETHnJJwQl8LMGJIxJSUjY6/6NwnxSIQSC0VUFWZ4/KLzheetk/I8Wfr7Sc1WTc9mFBFmOMYpxGppvTCLCLPDkB5ndEnolcKcMGTMhAkZYyRMIeZRlxr1QxmhMPPg+GXPOS8tW5VmXfRYjTDrpKkIU6yf1gszI2LquozyPkl+QJQNiCLjPBsyyiMmDjJS9mrRNiEeiaaKVS9J337uUc4Z3p83ftk0nlmRpZVytLi8n4JLysbRETgJ89ZQSrY95HnMNOswnvaJRwfY8BibGhfjiPE0Z5qm5LmmlQixmKrEYorMTLi/qfNP3bmq55wnT+Y8Hwo0gSiGKII4KvpE+4+3H3nJg1shVkj7heki0rTDaNqH8SH5xTHWiRiNHaNJyjSbkOeqkhViPl5U1THEMB17k/P4+zeZVrJk9azFkETQsXIrTzGFWTKpWtgr1ocizPbgI0wmffLxIenwDkwjpqOU6XRMml6QKcIUYgnqJFVXGTvv56u3N9louF9JzUZRIcyuQa/cACbAuLxclSyINbADwoyYph3yaZ90dMhkeAeSiGw8JptckKddci2IKcQCmiI6H6qFIlt0nvB8i9Ktix7XSDOKILFCmH2KLfR7hkoWxFpovzBdRJ51SSdFSpZSmIwuYHIKWQeUkhViCapyCuV5k5DtcSNKgtuaOZlRVNztUsjykMvhVS9LfeRvjz3646T1wiQ1ir54Bg8NPmnFX58PrNg3suIYIcQC6qK6Osktoq73rFtwn5r7lVsrrzExGABHwD3gTnmpXS7dPl7yUoW4Ae0Xpv9wnAEPgE9S/FYPyn0j9mpQWohHo27c8FFl6UXoH8+7H0qz+py7fmlQFPkMgGPgCeAFXA2Ex8D5kpcrxA1ovzBTCil6YQ4o0jUPgNPyORUACLEEVVmGzQuWoW4psEXCXEaw7qq3vTDvUAjzRVz2LpgAF+zCN1t72KPv1/a/raoRZofiM34fRZhC3IhVpmPnRY7V5+akZOuGPsMI80ngxRTCnFBElv57QIgV035h+gjznOJD4j/rSskKcQPqKlRDaYbHLMOyUeUSm/mtvKRqStYL08tywC58s7WHPfp+bf/bKncwcXDhIM7B8uKDdVruGzvIlp10LcS+M++zUo0IF2Fcdg+IuN5JoE7AxmWOrxyUdHkhTBw4RxRlxN2MeJCSHGXEdzNIzsmOT8gGF2TdCWmcqW+BWDntF2YGTB2M8kKYZMWH6yIr9k3zvcqxC/Fo1EV3ecPmj1+GsIF7eD+MMnMu53yGrwtF+FJKs3zNjk3px0MG3SGDwQX9wyFRcs5w8JBh7yGjzhnDaMLopv8EQiyg/cLM3aUwySBLi9ZZo1KYE1ccI4RYkrBZwTLCbPp8WfB8VZyhMK2yP3gdVwozWGYssSkH8Tl3uw+503/IncOHRJ1TTgYjTnpDHiZD0mgqYd4WSsm2iJxCmOSQ5zDNAFdEltO8eE4pWSGWIIzwmsYUq8Jc9NkKRViVpRdyWJHrj6mLMHNw0GHKQXzB3c4DXjj4BC88/ARR55T+ICPqZaSdjGGktJJYPe0XZlZ+ELMcJhlEpTDzrBBo7tSEWYiFVAtzmiLMBVWtV2iKMOtKX/3SYf7WH5+CK5chca7sW5BykJxzr3ufF/Wf4zMOP0bSOSEexKS9mGEn5mHsOwMJsTraL0znIPXr+filCiJmf5leWTFeCNFMNZJsSsk2SbNKNdUairM6XSWUpXFFmLPPcgYuI2HMgHPuRA94YfwJPiMphDlN+pxHfR5an85sQrZYO0rJtomcQpJjihnLpxQftguKOSVTVPUjxCK8JP0fnmm5L5DVNWEuE2FWxymrjdzD26hy6yg+12NgSNH7LiFOz+mOThmcnnL0/An3nntI0jnh/qdSDk6gO4yJ0+4K/k2EuMoOCXPEZYuPiGJS1phiNrNyskIspirNnGsRHuWQx1IRJtQX+ITTSeqEGYp2QvHZ7uC7ksTpGd3hGQcnJxx/6iF3f+8Bnc4px59yDE5iehcd4mn/Mf4dxI1Q8/U24Zcn8A0k/YdNEaYQyxNWp4YRZVbZmgqC6qhK0qdcw+fD+9XNR5gdiq+qGLBSmKcMSmHeO35IJznj+JMxBw+7dId9klSfebF6dkCYYYQZfkCHXApTEaYQ8/Hi82JMKT5Hjxth1hX3NDUsqBOmXxXaLzdmRF6YPiU7eEA3Puf4Ux0OTvr0Lg6JpxKmWD07JEyf+vEfdP9BU4QpxHKEEWYozEVjmDcRZlN7vbrWfBmXkWU0OyZOz4oxzJMTjvsPuRc/LIXZZ3ByRHc4IZ7qj+RbY4++XndAmD6VlHJ1DMSLUlWyQiymWiGb8fhVstXz31SYcBnhTpiJMxtj4wl2PsVOUixJsSjHHubYeY6NNPdarIcdEWb1Q+7/Og07kwghFhOK0X+Ossp+uLkwPfPGO+sKg8Kq3QmFMCe4cYq7yMg7efHpjyA/AXcObsxeTXXYOHv0b70DwoSrqSS4+kG/6QdaiH2krqPPMo0LqLnvCVckCWXY9PpVacJl9sgPuxhkU9xkirtIcZaTZw4XlbIshen2KE0obo8dEGY1wvQftuqYixBiPuFnyUeSTb1k/fGLzrfMPrgeXfrj/B++U7xEXTaBcYqzDJfl5BNHbuBGZXQ5Zq/G1cTtsSPCrPsQ1/1FLISopyrLeWOYj3r+edSlZKsFSOV5skkRYeYZ+STHXUBukKfgym2f0oQbZ4/+rXdAmHD1wx6mixRdCnFz6op6lqmIXYZ5Kdk6qgI3yDNcmuPynDx1ZOaIrWwdnYMrNyFWzY4I0xOOfcxr2SWEWA3LfL6aJFl3rjAd6/dd3RwO5xyZK9ZcSCOIyvu5KzZ96sU62CFhNn3YhBDrYZk/ShcV+8w7d/jHbyBM54q407kiYZsX5UCZZLkZ1BqvrUiWQtwON5lWUm3APk+e/lxhhe31lLDDkZfTLVO7FGZGKU19/MUa2AFhhp+Mm46PCCEenaYpJp4w4/MoEWb4GlVZFltmRWrW1/nkFLLUJ/4W2aOK5B0QZkjT2IcQYnVUP1NNn7FHScUuOm85hklZDlRGlX41TbUqEetkx4UphLg51fZ0dbfLZHYWPbfsdUQUbfESIMFIiCwmtojErFj4yyBxxRY7MH38xRrYIWGq6EeIR2eeHBf9DDSnZBedY9G1RFwKs5CmWSnMKCKJIrpemg7ivKiYNc0ouz00D7Nt1MkyfE4IsTx1oqtKb5lCnnk/v+i1/f1QmgnQwYiJopgkiujERieCLtDJy/bsOVjT14EQj8GOCBOuFxfo0yLEzZi3oPOi45c5502vI0zHXo0wY4vKCNPoxlakZLPiCy2ijDDF7aAIs81IlEI8OstIsvoZe5xxyqbzhNdRGcO0hCgqUrKd2Ogk0DXoUIxfxj7CFGLF7KAwhRCPz7wK19u2UWVqictxzhXTR1zZCq9sjef3CbEOJEwhREBdH9lNEvaJLhqxO8o+spaTZW62dHyWlf1kJc3bRZ1+hBD7R7XCvNqablOEwszAZeQuJ89zUhypc4Uww+brEqZYA9GmL0AIsQ2sa3WSx2XWogAvTUeGczl57ooIM4U0KyJM34BdCDN7rZl9wMw+aGbfVfP8XzSzf2Nm7zOznzOzz1p0TkWYQogK1XZ3mzJQKG0fYUY4l5G7jMxyMtyVXrJqjbcBtrA1nplFwA8BXwZ8DHjazN7unPtAcNh7gM93zo3M7L8D/jrwDfPOK2EKIUqqgoKri7CvM+KszucM53heXRMzI2eCMXQxp3R44Hp0ME7pckGHMTEZEeAwHBH5ldvit4pw2OzWKdm2a7wa+JBz7lkAM3sr8DpgJkzn3C8Fx78b+C8XnXStwjSzNwNfDTznnPsPy31PAG8DXgY8A3y9c+5h+dz/DnwlcA58i3Pufeu8PiGEpxrJefxjL63biN28LMNruby+CTknJDzHgAPuYoxJSHmWJ/g9jnnAgFH51dZhSpfJlS0nquzpkkqYj852zsN8CfC7weOPUEi0iW8F/tmik677XfIjwFdU9v1l4Oedc68EfgH4bgAz+0rgDzjn/j3gzwE/vOZrE0JcISisma3/UZXlurc8uK1ezxSYMMbxkITnOOBZ7vLbvIgP8CKeKYX5MBBmQsqAIcec8iTP82J+nxfxCe7xgCPO6JXxqNhfzOybgM+nSMnOZa0RpnPuV8zsZZXdrwP+RHn/LcAvUkj0dcA/Kn/uX5nZXTP7NOfcc+u8RiEE1Kdiw/2hzG7jWsIGCY7L9UisjDBjIgZMyHlIQkTOAwY8oM8D+oyDCNML8y4PuctDpnToMMVwZMSM6d3C7yRWyiffBZ9617wjPgq8NHj8VLnvCmb25RRB2x93zi2cILOJMcwXewk6537PzD6t3F8NoT9a7pMwhVg7Xoh1nXw2MS8zfE2fni3GN32EOeZgFmkajhFJuXWupGQHDLnDCU/yPC/gU0zoEpGTETOhyxlHt/Q77SibSMnee02xeT74puoRTwOvKAO2j1MU87w+PMDMXkWRyfwK59ynlnnZbSj6UUGbEFvBJqeRNL3u9f0TYEKHEzrAwdxz1qVkR/TJiBnR55xDEtI5r68ee23EOZeZ2RuAd1KkJ97snHu/mb0JeNo59w7grwGHwE+YmQHPOue+dt55NyHM53yq1cw+Hfj9cv9HgXAeTG0Ifcm7gvsvLzchhLgkJWHIgFOO6TEmIp/tAxgw5B4P6DBlSoeUhJRkdn+7eKbcxDI4534WeGVl3xuD+3/ypue8jXdEtZPzzwDfAnx/efv2YP+3A28zsy8CHswfv3zNyi9UCLFbTOnMhOllaTgmdAHoM+JJnueQc4YMGNGfyXT7hPlyrgYGv1R/2G2j1nirwcx+jMJsLzCzDwNvBL6PIgT+s8CzwNcDOOf+qZl9lZn9W4ppJf/1Oq9NCLH7eGH6Ap8RfTpMicmIyRgw5JBzHMYpx5xwByhkOaKPU0pWBKy7SvYbG5768obj37DGyxFC7Bk+/eqrYc844oALDjnniDP6jDjijJiMThkqebGKJdmjWTnblnMQQoiVMaUzk6Xv9nOHEyJyjjhjwJAnuE+f0ez4EX0SUgynikRxBQlTCLGjGA4jI7oSBHWZMKLPiD5jekzoEpPhMGIyukw45JwxPVKSMnkbkxOREauN3h4jYQoh9oowPevTsAOGs9Rtlwl3OKHDlDE9xvRmch3TK/vUihnb2RpvLUiYQoi9wgvznEMMR0oyS8k6jA5T7nDCHU4455BzDmcRaJHiFfuKhCmE2CvCoh5fRdsvk7QDhrP7fUacckxCOpOln3IiAhRhCiHEbuIjTF9Bm5DSY8wT3KfDdBZhPsF9eoyBQqwXHBDNeuyKfUTCFELsFTkxOfGV+fZdxnSZcMRZ+bgo/JnQZcBwFnn2GJOSlGto2mxNTbXQ2w8kTCHE3uNTrhcccMKdWRr2goPZlJRDzsmJOOCCKR0mdGe3KZ1N/wqbQ51+hBBif3AYE7pccDAr8JnQxWGk5fJhh5zTY8yYHhcczLacaL+FuUdImEKIvScnmgkzLPDxY5odpvQYz5q0n3CHiHz2c2I/kDCFEHtPmJINU7PHnHKHE3qMOeScO5yQkhCTkRPNjt1r9miejYQphNh7fAp2GqRWfcN2vyzYIee8gE/Nin3CFK7YDyRMIYQoq1zD1Ukcl71lzznkhDt0mGI4xvQA6DHmLg9nDRCq215Uz2oephBCiHAB6oicjJiElDE9ciJ6jLnHAwYMZ2tp+rYHORE58aZ/BbFCJEwhhGjAr4t5yvGswKfLhKjUoe8OBHDG0RWx+ihU7A4SphBCNOCF6WV5ziEDhrM1Nf0C1D3GPM+Ts3FPP3dzL1BKVgghRNHV53LKiS/+ATjgYjaGeYeTK7I842h/hLlHSJhCCNGAIyIlIvyq9F1/xvSY0ilb40FEPutLO2DIEWezsU6/lmZOtHvraarTjxBCiDrC5cH8eKbv/pOSkJByzCkx2WwNTb9QddH0fceEuUdImEIIcQNyopkwfYHPkEEZPRoxGceccsj5bEqK36ZqoddqJEwhhLgBYQGQX1vzjKPZaiY9xrP7FxzQKXOWforKzrFHfRskTCGEuAE+JetlmZDSYcoT3OceDzjknGNOuccDzjmcNTUY0VdXoJYjYQohxA1wREzpMg2arkdkdJhyyDmGo8+IO5wQkzGizwUH9BnRYUpcLh3mrnUX2oOuQC1HwhRCiBXgG7GfcjxLw07oMqIPwIAhT/I8fUbBGiiXW2vRPEwhhBDLUqx20mXIgBPuAJS9ZAuRGo4BQzqkHHHGkAEXHDBkMFspRWw/EqYQQqyAKclsqS8/ZtlhOmvFPmBIwik5ESfcubJQdatRhCmEEGJZwigx7D/rC4COOeWAC445xXAk5TimX6hatAMJUwghVoAfi7RZSY/jCe7PGhn4MUw/vullmexTiNZyJEwhhHhswqrXS3x3nyEDzjnklGO6TGZp2B5jjjklI56toenvZ8TtaKOn1nhCCCEeF5+ePeNoNmbZY8yIPhkxXSbc5eFsX7gVcz1bIMw9QsIUQog1EXYC8mOWfUazlG2XyWzFkzOOArFG7S8G2kEkTCGEWBPhQtJ+ibA+Iw64mG1+fc0H3CMmm7Xei8qK261nj5oXSZhCCLEmivU0i8gyIicmo8+IF/ApeozpMOUuD3mS56/I0q+9KbaL1gvTZqvNFZtPdVzdu4Nr0Akhth6/nmYaNCZISWbrZeZEs2kmMRkx2ex7rDXsUZFv64WZkNJlMtt6jAGCPd1yoVeNBwghNk8YRT7k7myJsAfc4yF3OeeQCd3ZwtRie2i9MH2K45BzDriYNT/2689dcEBGLGEKIbaCcHmwiHz2+IwjTjnmggMmdIOm7GJbaL0wE1L6jDjijLs85C4Pichnf7k5bDboLoQQm8a3w7vg4Io8/XSSIQPG9NoTYSol2x68MI855Qnu80I+ORu5zIiZ0FUnDSHE1uAlmRMxpscFBySks8YFUzqkJO0R5h7RemH6lOwR59zjwUyYKQlj+pxzKGEKIbaGuvU0W406/bQHAyIgBjpAN7gfl5v+ThNCbA+LxiZbVCG7Z+yMMBOuCzMpn9PQuRBi81jltro/FKWkuY20Xpg+uowpfpmqMGMkTCHEpgllaQ37Ha2Upjr9tId5EaZPx0qYQojNUSfL6v0qLZHlnrEzwqwbw1RKVgixHRj1wgwf+1Z4jsuIU2wTOyFMn4rtAwfl4365z0tTCCHWw7w/yeeJsi7KzGmdLFt0qY9L64Xpo8kehSyPKH6pg3JfBwlTCAGrzzU1Fe/U3Z8nzOq4pmP11ypWQeuF6ccv+8DA4JhLYfbd5VimEGKfmTde+Djnazp3dV/11g8WNQlTadltZCeE2QF6VhNhGnScIkwh9pumCtVVnbPpNeaJNBRmWGmRo+hye9kdYVIK04rHB66IOpWSFULUR3KPe77wvNXXmBfRhqKMgvuuvJU0t5X2C9MgNuga9CI4sDJF64roMskhqk5vEkLsCXWSXIWMlinmaZIlXBVlVZ6rFLtYJa0XJhFYUmyx3wyitNhsCpayV5NrhRBV5onsUeS0rCyXHcOULNtA64VpEVgHoh5EXYh7kBjEY4jGYH7cXMIUYs9ZNL54k/OE51u2AnaZ/eEAkop+to3WC5MIolKY8QHEgzLCTIp0beSKKFMIsc8sU5xz0/MtK8tlI1BFmdtO64VpcRlh9iE6gPi4EGYcQZQX6VjTvBIh9pgmWdbJ8ybnvKkso5qfq55PstxmWi9MokthxgcQHxWyjHOIpmBjVCYrxN5z0+KcRedaNi3bVNRTR1sjzP1J4bVfJeG8kkOwO2DHxf1ZfzxFmELsKXUyi7gusOgGW/Vnms4RB7fhmkpJZZ/f2ijL7cXMXmtmHzCzD5rZd9U8/8fM7F+b2dTM/rNlztn+CNP3xvONZI8p3qNj4AJNxBRCUC+4dUSZ1dRrk3Dh+lJey0ShYhnMLAJ+CPgy4GPA02b2dufcB4LDngW+Gfgflz1v+4XpI8w+RVTphXkBnKHeeELsPU0yW4csm4QZ0yxMf9vWlGy66Quo49XAh5xzzwKY2VuB1wEzYTrnPlw+t3Qp8m4IM+Gy1Y8X5hlq9SPE3lMntjox3URQdcVC1fHKanTZJMxQmtXn2yTNreMlwO8Gjz9CIdHHYjeEWU3JxsBDLoWpCFOIPaZpzHHVUWaTMGOuS9NVNmqurS3sT9FP+4VZN4YZU6RnexRFP4owhdhj6iTm9z+qnOZNHQlfq1r40yTMughTNPN/Ab8y74CPAi8NHj9V7nss2i/Ma93XKd6XAwqJ+oI0IcQeUiezatpzGUFVh7mWkWVTata4Lsuc9kaYm+CPlZvn+6oHPA28wsxeBnwc+Abg9XNOuNQ/+G4KM+EywtQYphB7Tl161O+n5n6IC54PpdlU4DNPluGWcz0l21ZZbl/Rj3MuM7M6YVpcAAAVZklEQVQ3AO+k+Ad/s3Pu/Wb2JuBp59w7zOwLgJ8G7gFfbWZ/xTn3ufPOuxvCrBb9zFaQRsIUYq9pijD9c9TcD6kudeQXdn4UWVbnW+bsxhjmduKc+1nglZV9bwzu/xrwWTc5524I049hDqisII2KfoTYe0KphRHmTX6+Lrq8qSyrEWYozfC8YlvZCWG6xHBdIx9EZIcRUQJ5v9jnOqYIU4i9pS66vMkXQt1iusvKskmcYYTpX4PKz7VJnqqSbQ25RaSWMI46jOIeF/GAJMkZxn3GcYfUYnIZU4g9pi4irFI3d92nX8Pz1MmtSZCLxjD9OXOuyrctotw/2i9MjDSKmUQdhnGP82RAJ8kZxT0mUZfUEnLTG1CI/aYaEdY9D83rT4ayXCYNO28+ZijGMDVbfa4tKMJsDUWEGTOJukWEmQxIYscw7jGJOqRRTG6KMIXYT+YV/VTxEaXjenQ573w3iSy9NKsRJlyVZZuEuT+0XpjOjDRKmEQdRlGP8/iAJMkZxX3GUZepJRKmEHvPMinZanFPuB+uSuxRZFlXpRuK81HGWMVt0nph5pQRZtxhGPe5SCbESV5EmHGHNEo0hinEXlNXpFN3zDxZVo99VFnGwbE+HRumZKvjrW1g++ZhrovdECYJY7qMrM+5pSTmGFqfMV1SJEwh9pe6FGpMc5FPXY/XpnNWBVdX5Vqdg7lMhNkmWe4XOyPMCT2GZJzjSHCMGDChJ2EKsfc0jWFWGxKEx88TJlwv7Gl6nZtGmE0R8Dajop/WkGOlMLuMcJxjJMCQHmO6TCVMIfaYpkivuhblMpFl3TmrKdSmIqPqVq2SrTuf2DZ2QJg+wnQMMS6IiXEM6TKhQ0pHwhRir6kTWFWUYVS5bEp2kSirrxmmZavRpVKybWBnhDnGGJFwTpcYGBExJiZFjQuE2F/mRZhNclwmJbtImk2FQf4adiklq6Kf1uCISDEmJAxxnFO8HYfABGMKZK17AwohVkdThDlvW/acdXJskmS4+Z9zwfF1jQ3ENtF6YeYzYUaMiLjAiDCG5IzJSXHkVxocCyH2h6bxxEXCrFulJKRu/LJunLIqwmpa1gW3Ce2NMveDHRFmwpiEITHnJKUwUyakpKTkpEC26UsVQmyEUGheWNX1KH16tE6YdU0NFkWXTeOXYUrYi9tfSyjTNglTVbKt4bLop8uILud0MYwhE8ZMmEIZYUqYQuwf8wpywgjPy6tOmlZzu2wqtk6aCddl7SPMUJhtkuZ+sDPCHNNlyIAO/VKYERMgJS8jTCHEftKUkqVyG0aVVXHWRZhNsqzbVxdh+i3meoTZpkLF/fl+3QFhGlPfuMD1id0h5oyRgzGuTMm26c0nhFgd1WgwTMnCpQTrUrLVx03nXSTLUJoJ1yNMfx0Jii63m/YL00WkecIk6xKnA2x6iBExTB2TNGWaT8hdvOnLFEJshDpZ1i3iDMv3kg3PW200sKiBwbzGCdUxTElz29gJYWZ5wiTrYekANz3EXMQ4TRlnY9J8RO4UYQqxv9SlRutk5McTq/v8OarnbNqo3NalZavnrxvDbAsq+mkNjog072BZlzwdkE6OMGdM0wnTbEiadyRMIfaWJmFVheTFFVauVp8Pf2aZxgV1UaZPy4av6anOwxTbRuuF6VOyedojTQdMp4dARDYdkWc9sjyRMIXYa+qkCdfHEENRNkWg81Kvy8iyGmGGtLVKVkU/rSF3ES5PoEzJMj0EF0N6jst6kHdwEqYQe0rTGGaInxPpC3/8zy0awwzP35SO9Vv42k1fu22dh7k/tF6Y5IZLI5hEuGEEZwl0IhjGMI5gapDrzSfEflKXDq1GmOEczHD6SPU+1EeZ1dcLn2soCKrb7exyw9ScbAtpvzAzYELRPPbM4ARIrLg/LJ9TzwIh9pRqhFknzKZUalWc80RJw/MVafrddQua5JWtNcJU0U97yCn+v0YG5wYnVgjzvNw3tevj90KIPaGajvXC9OOVvsvPsn9VLyPNuogyOLaurWxcXoLfYPk+8OLWaL8wMwopjigk6YWpCFMIAdSnZH27zLom6nXUpWSrz1X3Vc9XirPO4YkVtTM+mNUf+VtJ+4WZU0gxjDBjivsjkzCF2GvCohvfZceHc/62qWhn3vnmCbaahq2MW1YzxJ1yC2UZNh7aelQl2x4yK1KyQwJhlinZISr6EWKvqSv6CZfcuoksl329msdXZGmXl9INNi9Ih/7I31LaL0w/hjkGLoBTis/BOUWatlhBWgixl4QhXSjKx2kSUNdXNnyushlg7upldCgk2Qd65W0UnCLl8d19a6jopz3Min4oJFkVplKyQuw51RxoaK6bWKm6Wkm4v+E85q7L0l+GF+Wg3PypfOV/a4S5P+yeMLtcjzA1gC7EnlI1lW+Ld9OOOnWLSdf9XE2ESY0wfYTZo5DlIZd1SBMeLfAVa6f9wsy4FOYFl39AKsIUQjSmZB9Vlv62Tpqucj+UZRlphhGmT8keUAgz5bIeo1ULLKnopz2EEaZ/k4XCVIQpxJ5SJ0v/F/XjRJj+tinSXDB+GUaYXphHXNZidGleUEVslLU2WTWzN5vZc2b268G+v2Zm7zez95nZT5nZneC57zazD5XP/6mlXiSn+ANnwmWUecFldJkiYQqxz1S9GVFGfHA9fZpX7odtdx7nvh/LdJdFP6Es75a3BxTC9F4XW8W6u5L/CPAVlX3vBD7HOfeHgQ8B3w1gZn8I+Hrg3we+Evg7Zrb4LSNhCiGaqAsyY7eENJtkWbc1ybUiynBKqBfmIXAM3CtvDyjGNf3sl1Yw3YLtdljrf4lz7leA+5V9P++c8wp7N/BUef9rgLc651Ln3DMUMn314hfhcqBcwhRCVJk7hFnKrKlYp1GW8yRZc2wYXfoIs0chyGOKCPOYogDIC1MR5tax6THMPwv8eHn/JcC/DJ77aLlvPj7C9OKcBvt9X0YJU4j9JGwY4GXpgLyU4axfa5Mg6wTqTeY7pocvll+9bw4sb44wvTDvAWdcjTBbI0zNw1w7ZvY/A1Pn3I8vPHge/j3tK2HDlo/+thXtpYQQa6EaYV6p21k0hhk+B9e/UKLg2LBbkBdnJcL011JNyd4FHtJSYe4PGxGmmX0L8FXAlwa7Pwp8VvD4qXJfA+8qbwfg/iNwL6L4S2dC8alIUYgpxJ5TLfbxwpw5sRSZmyfO6lZHGG02df4pH5uDxGFdsIGDI4fddbijFA4yXC/HJXmNMJ8pN7EpbkOYV+q2zey1wF8C/rhzbhwc9zPAj5rZD1KkYl8B/GrzaV9T3j4BeFmOKQYvo/K+74unEFOIvaTa7PyKMMsxxaxJlvNSsvP+CA9NV6Z2nZdy8XQUO6yXEw0y7CgnupuTH01xgyl5L8Uljtyq31svLzfPL93on2J9aB7mSjCzH6Mw2wvM7MPAG4HvoSic/rmyCPbdzrlvc879lpn9E+C3KEz3bc65JUznuJzx61eS9sJU1Y8Qe03d6iA5RWQZcZkmbSz0qYsuHVdTsXX4Y/0f7MGYKQ5LcuJuSjTIiI8yorsp+dGEbJBi3YwsyTHTn/rbxlqF6Zz7xprdPzLn+L8K/NWbvYqv7gkjTEMRphACqO+Ml1NEljNZ+ttlturJ5/xB7vJy8wVGrnB4nBN1M+JBSnI0Jb6Tkh1N4SCFXkae5MW0l1agop8WEZbHjrkaYXphKsIUYi9pijBna0fXRZjLVMlWq2ObqJ6neM2oFGZSCrNzd8L0aAKDKa6bEcU5mYp+to4dEGYYYfrJmBKmEIL6oh9zVzvjzS328d8dVWmGkeW8KDNMxxZRpgEWOeIkI+5O6fQndA7HMJjgeil5JyOLHYZTbmzL2AFh+jd1KE3japWs3nZC7DWhOP10knCrnTrSlKqlcpsHJ14mleuIyInISUjpMKVX/oGfk5KTEbXqj3wV/bQI/4YNC3+svO8LfiRMIfaSMCXrb13wuLbgZxnx+Vsvy2qKtmnM079sTkxWCnNClwl5KcysFKbpe2vr2BFh+kjSN5UNhakIU4i9ptpP1g9DLmyJ17R5IXry4EVc8LhZthFuJsxuGWHmTMhIS1m2KcLcH3ZEmE0Rph+/lDCF2FvqhHmllywsTsPWRZdVQlFWpXmV6EqEOaXLhJQpU1JiMiJciyJMVcm2iKowfd24Ikwh9p66pb0cxZSNxtVKlpWlC17Ab02ivPz56ynZIsKcMiVhWgpTEeY2skPC9IU/KcUbNowuJUwh9pbq1BLK+2ZhDzLmTw8J07Bhz9hwq3lu9rRV1uO8fM6Z12h42yZU9NMywkpZL0wfXSolK8TeUrcepqMQ1kyaTcILT+Jq9t1gm12HzdLBLjKcWVAz6xOxi+QtNsUOCFMRphCigUZhEkSYTVFi9USuckz1Z5pkWW5elhG4iEKWFuHMrsiyTaOX+8aOCNNXyoa14l6YGgsQYq+pk+ZsEek6yc07UfWk86JOLqUcXIMrU7KFMK2cQGJl7ew8aW8rKvppGWGECZfCDBsfCyH2jur4ZZiStWC7URp0kSjrpHl1DNP58UvClKwFKVmxjeyAML0QQ2HC1QhTwhRib1naP3XfE4sizqZIk5r9wV6jUKPlRJZfU2a7UNFPywjnPXkkSyH2nnBWSPiVkDsu16hccxaqZmqn5YUgY5eRuKJ5wYSUpGxcoGkl28kOCDN8w4dzLqtNlIUQe0lVmFe+GqrSXPF3RVWWefGakXNELidxGR2mdJjQKedgxmQtjTR3nx0SZjhhONyvN50Qe8sVUVGRpiu/Hpbt5POY1zCLLsGcI3YZcRlVdpiSkJLM+si2KcLcn6KfaNMX8Pg8w9WiH7/VrEPXGp7Z9AWsiWc2fQFr4plNX8AaeGbTF7A6Qmk+/OUlZblOaTrM5bMIM3FFa7wOKfEsJdu276z9YEeECfPzLm3jmU1fwJp4ZtMXsCae2fQFrIFnNn0BqyOU1ckvX48wr4gT1iLLynX4lGxERlK2yItnfWTbWvyz++xASlYIIcTm2J8q2R2IMIUQQoj1Y861L+w3s/ZdtBBCrBjn3Ea7HJjZM8DLNnkNJc86516+7hdppTCFEEKI20YpWSGEEGIJJEwhhBBiCVorTDN7rZl9wMw+aGbftenreVTM7M1m9pyZ/Xqw7wkze6eZ/baZ/XMzu7vJa7wpZvaUmf2Cmf0bM/sNM/uOcn/bf6+emf0rM3tv+Xu9sdz/cjN7d/le/HEza131uZlFZvYeM/uZ8vEu/E7PmNn/U/5//Wq5r9XvQbFZWilMM4uAHwK+Avgc4PVm9tmbvapH5kcofo+Qvwz8vHPulcAvAN9961f1eKTAdzrnPgf4I8C3l/8/rf69nHNj4Eucc68C/jDwlWb2hcD3Az/gnPuDwAPgWzd4mY/Knwd+K3i8C79TDrzGOfcq59yry32tfg+KzdJKYQKvBj7knHvWOTcF3gq8bsPX9Eg4534FuF/Z/TrgLeX9twBfe6sX9Zg4537POfe+8v4Z8H7gKVr+ewE45y7Kuz2KecwO+BLgp8r9bwH+0w1c2iNjZk8BXwX8g2D3l9Li36nEL+wV0vr3oNgcbRXmS4DfDR5/pNy3K7zYOfccFPIBXrzh63lkzOzlFNHYu4FPa/vvVaYu3wv8HvBzwP8LPHDO+eafHwE+c1PX94j8IPCXKHvSmNkLgPst/52g+H3+uZk9bWb/Tbmv9e9BsTlaNy6xp7Ry7o+ZHQE/Cfx559xZzfzZ1v1epUReZWZ3gJ8G2joUAICZ/WngOefc+8zsNeFTG7qkVfLFzrmPm9mLgHea2W9z/T3Xuveg2BxtjTA/Crw0ePxUuW9XeM7MPg3AzD4d+P0NX8+NKYtEfhL4x865t5e7W/97eZxzJ8C7KMZo75Xj6tC+9+IXA19jZr8D/DhFKvZvAXdb/DsB4Jz7eHn7CeD/pBjK2Zn3oLh92irMp4FXmNnLzKwLfAPwMxu+psehujT7zwDfUt7/ZuDt1R9oAf8Q+C3n3N8K9rX69zKzF/qqSjMbAH+SolDmF4GvKw9r1e/lnPse59xLnXP/LsXn6Becc99Ei38nADM7KDMcmNkh8KeA36Dl70GxWVrb6cfMXkvxl3AEvNk5930bvqRHwsx+DHgN8ALgOeCNFH8N/wTwWcCzwNc75x5s6hpvipl9MfDLFF9Qfo2G7wF+FfgntPf3+lyKQpGo3N7mnPvfzOzfoSg8ewJ4L/BNZTFaqzCzPwH8D865r2n771Re/09TvPcS4Eedc99nZk/S4veg2CytFaYQQghxm7Q1JSuEEEL8/+3dPYhcVRjG8f8jGIUYREijjR8QhIBJXHchYvxokkbTKCgiIggKKoiFYkAroyxrbCwifmAVFBuxECJ+BIWQFcQEN6QQRCwDClqsICvIm+KeweuSZe7iTnTC/1fdOfecuWcHhpd7h32fC8qCKUnSABZMSZIGsGBKkjSABVOSpAEsmJIkDWDB1FRLcmWSJwbMuzPJxxO4/tvrTcpJsrzR+5A0eRZMTburgCcHzt3wfzquqser6vv1LtvofUiaPAumpt08cEMLP14ASHKoBTwvJbl/9YIkc23+9a2F2rstLPlkkv1tziNJPkzySQsbXjjfxZN8mWSmHS8neTnJd0kWW9PvURjzYtvPwVXrn03yTVszCqSebXM3Jdmc5EyS7Rv6qUlaNwumpt0B4Meqmqmq55PcC+yoqpvoer0eGjXbBkhyK/AGsL+qfgJeAI5V1W66xuOvtT6xADvp+qnuAB5IMi5CbjOwWFW7gOPAY238deBwVe0Ezvb2shfY1sKNbwZmk+ypqm/pepy+QhfkfKSq+uHOkv4DFkxdbPbQpW5QVT/TJYrMtXPbgbfoiuUofWMfcKBlXH4FbOLvJJxjVfV7Va3QNVm/dsy1V6rqaDs+CVzXjm+j68sKcKQ3fx+wN8kp4BRwI7CtnTtIV/BvAV4d90dLmjzzMHWx66fAnAUuA2aAo73x+6rqh38sSnYDK72hvxj/fek3J+/PHzWgX72fAPNV9c553msrcEV7j8uBP8ZcW9KEeYepabcMbOm9Pk73+PSS9hvi7XQpKQC/AXcD80nuaGOfAU+PFifZ9S/2slbo8gngwXb8UG/8U+DRFj9FkmuSbG3n3gReBN7DO0zpf8GCqalWVb8CJ5KcTrJQVR/RxYotAV8Az7VHs6P5vwD3AIeTzNE9+ry0rT8DvLTWpQaMrzXnGeCpJEvA1b29fA68D3yd5DRdpNuWJA8Df1bVB3S/Yc4muWvtT0HShWC8lyRJA3iHKUnSABZMSZIGsGBKkjSABVOSpAEsmJIkDWDBlCRpAAumJEkDWDAlSRrgHE2anbuhRt6SAAAAAElFTkSuQmCC\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f671053c438>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=[12,12])\n",
"plt.xlabel(\"token index\")\n",
"plt.ylabel(\"batch x time\")\n",
"plt.title(\"predicted probs (token 1 means EOS)\")\n",
"plt.imshow(sess.run(tf.nn.softmax(logits)).reshape([-1, logits.shape[-1]]))\n",
"plt.colorbar()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Reference:\n",
"[10, 11, 12, 13, 14, 15, 16, 1]\n",
"Predicted:\n",
"[10, 11, 12, 13, 14, 15, 16, 1]\n",
"\n",
"Reference:\n",
"[20, 21, 22, 23, 1]\n",
"Predicted:\n",
"[20, 21, 22, 23, 1]\n",
"\n",
"Reference:\n",
"[30, 31, 32, 33, 34, 35, 1]\n",
"Predicted:\n",
"[30, 31, 32, 33, 34, 35, 1]\n",
"\n",
"Reference:\n",
"[40, 41, 42, 43, 44, 45, 46, 47, 48, 1]\n",
"Predicted:\n",
"[40, 41, 42, 43, 44, 45, 46, 47, 48, 1]\n",
"\n",
"Reference:\n",
"[50, 51, 52, 53, 54, 55, 56, 57, 1]\n",
"Predicted:\n",
"[50, 51, 52, 53, 54, 55, 56, 57, 1]\n",
"\n"
]
}
],
"source": [
"preds = sess.run(tf.argmax(logits, -1))\n",
"\n",
"for pred, ref in zip(map(list,preds), map(list,data)):\n",
" # crop EOS after first\n",
" if 1 in pred: \n",
" pred = pred[:pred.index(1) + 1]\n",
" if 1 in ref: \n",
" ref = ref[:ref.index(1) + 1]\n",
" \n",
" print(\"Reference:\") \n",
" print(ref)\n",
" print(\"Predicted:\")\n",
" print(pred)\n",
" print()\n",
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
import numpy as np
import tensorflow as tf
from collections import Counter
# Auxiliary functions for sequence masks
def infer_length(seq, eos=1, time_major=False):
"""
compute length given output indices and eos code
:param seq: tf matrix [time,batch] if time_major else [batch,time]
:param eos: integer index of end-of-sentence token
:returns: lengths, int32 vector of [batch_size]
"""
axis = 0 if time_major else 1
is_eos = tf.cast(tf.equal(seq, eos), 'int32')
count_eos = tf.cumsum(is_eos, axis=axis, exclusive=True)
lengths = tf.reduce_sum(tf.cast(tf.equal(count_eos, 0), 'int32'), axis=axis)
return lengths
def infer_mask(seq, eos=1, time_major=False, dtype=tf.bool):
"""
compute mask
:param seq: tf matrix [time,batch] if time_major else [batch,time]
:param eos: integer index of end-of-sentence token
:returns: mask, matrix of same shape as seq and of given dtype (bool by default)
"""
lengths = infer_length(seq, eos=eos, time_major=time_major)
maxlen = tf.shape(seq)[0 if time_major else 1]
mask = tf.sequence_mask(lengths, dtype=dtype, maxlen=maxlen)
if time_major:
mask = tf.transpose(mask) # [batch, len] -> [len, batch
return mask
def safe_cumprod(tensor, axis=0, exclusive=True):
transpose_permutation = None
n_dim = len(tensor.get_shape())
if n_dim > 1 and axis != 0:
if axis < 0:
axis = n_dim + axis
transpose_permutation = np.arange(n_dim)
transpose_permutation[-1], transpose_permutation[0] = 0, axis
tensor = tf.transpose(tensor, transpose_permutation)
if exclusive:
tensor = tf.concat([tf.ones_like(tensor[:1]), tensor[:-1]], axis=0)
def prod(acc, x):
return acc * x
prob = tf.scan(prod, tensor)
tensor = tf.transpose(prob, transpose_permutation)
return tensor
def soft_mask(is_eos, time_major=False):
"""
A differentiable version of sequence mask for gumbel
:param is_eos: matrix with probabilities of EOS at each tick
:type is_eos: tf matrix[time,batch] if time_major or [batch,time]
"""
axis = 0 if time_major else 1
return safe_cumprod(1 - is_eos, axis=axis, exclusive=True)
# BLEU implementation
def get_ngrams(ref, n=4):
""" return all n-grams, [batch, time - n + 1, n] """
ref_len = tf.shape(ref)[1]
ref_ngrams = tf.stack([
ref[:, i: ref_len + i - n + 1] for i in range(n)
], axis=-1)
return ref_ngrams
def count_unique_ngrams(ngrams, pad_with=1, count_dtype='int32'):
"""
returns all unique ngrams and their respective counts. CPU-only and non-differentiable
"""
assert ngrams.shape.ndims == 3, "ngrams must be int[batch, ngram_ix, token_ix_in_ngram]"
def _select_unique_ngrams(ngrams):
unique_ngrams = []
ngram_counts = []
for ngrams_for_sample in ngrams:
ngrams_ctr = Counter([tuple(ngram) for ngram in ngrams_for_sample])
unique_ngrams_i, counts_i = zip(*ngrams_ctr.most_common())
unique_ngrams.append(list(unique_ngrams_i))
ngram_counts.append(list(counts_i))
pad_ngram = tuple(pad_with for _ in ngrams[0, 0])
max_unique_ngrams = max(map(len, unique_ngrams))
for i in range(len(unique_ngrams)):
pad_size = max_unique_ngrams - len(unique_ngrams[i])
unique_ngrams[i].extend([pad_ngram] * pad_size)
ngram_counts[i].extend([0] * pad_size)
return np.array(unique_ngrams, ngrams.dtype), np.array(ngram_counts, count_dtype)
unique_ngrams, counts = tf.py_func(_select_unique_ngrams, [ngrams], [ngrams.dtype, count_dtype])
unique_ngrams.set_shape([ngrams.shape[0], None, ngrams.shape[2]])
counts.set_shape([ngrams.shape[0], None])
return unique_ngrams, counts
def soft_count_ngrams(probs, ref_ngrams):
"""
Selects probs for all ngrams in ref.
:returns: For each n-gram enumerates all it's possible positions in probs.
[batch size, num_ngrams in probs, num_ngrams in ref, token index in ngram]
float[batch_size, probs_len - n + 1, ref_len - n + 1, n]
:param probs: predicted probabilities, float[batch, time, num_units]
:param ref_ngrams: ngrams to count, int[batch, num_ngrams, n]
"""
# cast everything to [batch, time, ngram_index, token_index_in_ngram]
ngrams_shape = [tf.shape(ref_ngrams)[i] for i in range(ref_ngrams.shape.ndims)]
batch_size, num_ngrams, ngram_size = ngrams_shape
seq_len = tf.shape(probs)[1]
batch_ix = tf.tile(tf.range(0, batch_size)[:, None, None, None],
[1, seq_len - ngram_size + 1, num_ngrams, ngram_size])
time_ix = tf.tile(tf.range(0, seq_len - ngram_size + 1)[None, :, None, None] + \
tf.range(0, ngram_size)[None, None, None, :],
[batch_size, 1, num_ngrams, 1])
selector = tf.tile(ref_ngrams[:, None, :, :], [1, seq_len - ngram_size + 1, 1, 1])
# flat select [batch, num_ngrams_in_pred, num_ngrams_in_ref * ngram_size]
indices_nd = tf.stack([tf.reshape(batch_ix, [batch_size, seq_len - ngram_size + 1, -1]),
tf.reshape(time_ix, [batch_size, seq_len - ngram_size + 1, -1]),
tf.reshape(selector, [batch_size, seq_len - ngram_size + 1, -1])], axis=-1)
ngram_probs_flat = tf.gather_nd(probs, indices_nd)
# reshape back into [batch, num_ngrams_in_pred, num_ngrams_in_ref, ngram_size]
ngram_probs = tf.reshape(ngram_probs_flat,
[batch_size, seq_len - ngram_size + 1, num_ngrams, ngram_size])
return ngram_probs
def compute_ngram_stats(probs, ref, eos=1, n=4, smoothing=None):
"""
computes soft n-gram precision and recall in a differentiable way
:param probs: predicted probabilities, float[batch, time, num_units]
:param refs: reference token indices, int[batch, time]
:param smoothing: if not None, adds this value to both numerator and denominator of precision & recall
"""
ref_mask = infer_mask(ref, eos)
pred_soft_mask = soft_mask(probs[..., eos])
ref_ngrams = get_ngrams(ref, n=n)
ref_ngrams, ref_ngrams_counts = count_unique_ngrams(ref_ngrams, pad_with=eos)
# mask-out any n-gram that covers anything after first EOS
ref_ngrams_mask = tf.equal(tf.reduce_sum(tf.cast(tf.equal(ref_ngrams, eos), 'int32'), axis=-1), 0)
# dimensions: batch, prob position, ngram index, token within ngram
probs_masked = probs * pred_soft_mask[:, :, None]
ngram_token_probs_elwise = soft_count_ngrams(probs_masked, ref_ngrams)
ngram_probs_elwise = tf.reduce_prod(ngram_token_probs_elwise, axis=3)
ngram_soft_counts = tf.reduce_sum(ngram_probs_elwise, axis=1)
ref_ngrams_counts = tf.cast(ref_ngrams_counts, 'float32') * tf.cast(ref_ngrams_mask, 'float32')
# compute precision / recall
true_positive = tf.reduce_sum(tf.minimum(ngram_soft_counts, ref_ngrams_counts), -1)
all_true = tf.nn.relu(tf.reduce_sum(ref_ngrams_counts, -1))
# there are len - n + 1 ngrams; substract 1 for EOS. If there's less than N predicted, return 0.
# NOTE: this approximation is different (simpler) than what's in the original article.
all_positive = tf.nn.relu(tf.reduce_sum(pred_soft_mask, axis=1) - n)
if smoothing is not None:
true_positive += smoothing
all_positive += smoothing
all_true += smoothing
precision = true_positive / all_positive
recall = true_positive / all_true
return precision, recall
def compute_bleu_with_logits(logits, ref, eos=1, min_n=1, max_n=4, weights=None, smoothing=None):
"""
Computes differentiable BLEU with logits.
:param logits: logits for predicted probabilities, float[batch, time, num_units]
:param refs: reference token indices, int[batch, time]
:param eos: token index for EOS
:param min_n: minimum ngram length (inclusive)
:param max_n: maximum ngram length (inclusive)
:param weights: weights for ngrams, defaults to 1 / num_ngrams
:param smoothing: if not None, adds this value to numerator and denominator of all precisions.
Default smooth BLEU has smoothing=1
:returns: differentiable BLEU, float[batch_size,]
"""
if weights is None:
weights = [1. / max_n] * max_n
else:
assert np.shape(weights)[0] == (
max_n - min_n + 1), "There must be exactly as many weights as there are ngrams (%i)" % (max_n - min_n + 1)
probs = tf.nn.softmax(logits, -1)
precisions = []
for n in range(min_n, max_n + 1):
precision_n, recall_n = compute_ngram_stats(probs, ref, eos, n=n, smoothing=smoothing)
precisions.append(precision_n)
ref_len = tf.cast(infer_length(ref, eos), 'float32')
pred_soft_len = tf.reduce_sum(soft_mask(probs[..., eos]), axis=-1)
brevity_penalty = tf.minimum(1.0, tf.exp(1 - ref_len / pred_soft_len))
bleu = brevity_penalty * tf.exp(sum(w * tf.log(pr) for w, pr in zip(weights, precisions)))
return bleu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment