Skip to content

Instantly share code, notes, and snippets.

@drasros
Created December 26, 2016 10:19
Show Gist options
  • Save drasros/45393f07054b8a7972494e6e0b77e8d7 to your computer and use it in GitHub Desktop.
Save drasros/45393f07054b8a7972494e6e0b77e8d7 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"https://arxiv.org/abs/1611.02163, Luke Metz et al."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from __future__ import print_function\n",
"import os\n",
"import numpy as np\n",
"import tensorflow as tf\n",
"import time\n",
"\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generate dataset\n",
"\n",
"Let's generate a dataset of 2-dimensional datapoints drawn from a gaussian mixture model of 8 gaussians, as in the original paper. \n",
"The centers of the 8 gaussians are equally spaced on 0-centered radius-2 circle in the 2-dimensional space and which variances are 0.05, covariances 0."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"angles = [2 * i * np.pi / 8 for i in range(8)]\n",
"\n",
"def get_center(angle, radius=2.):\n",
" x = radius * np.cos(angle)\n",
" y = radius * np.sin(angle)\n",
" return np.array([x, y])\n",
"\n",
"means = np.zeros((8, 2))\n",
"for i in range(8):\n",
" means[i] = get_center(angles[i])\n",
"\n",
"def sample_from_gmm(num_samples):\n",
" # draw which gaussian samples belong to\n",
" belong_to = np.random.randint(0, 8, size=num_samples)\n",
" unique, counts = np.unique(belong_to, return_counts=True)\n",
" \n",
" samples_list = [\n",
" np.concatenate((np.random.normal(means[i, 0], 0.05, size=(counts[i], 1)),\n",
" np.random.normal(means[i, 1], 0.05, size=(counts[i], 1))), axis=1)\n",
" for i in range(8)\n",
" ]\n",
" samples = np.concatenate((samples_list), axis=0)\n",
" np.random.shuffle(samples)\n",
" return samples"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# let's create a dataset with 10000 elements\n",
"num_examples = 10000\n",
"X_train = sample_from_gmm(num_examples)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x10349de10>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# let's check the distribution of the data\n",
"heatmap, xedges, yedges = np.histogram2d(X_train[:, 0], X_train[:, 1], bins=300)\n",
"extent_tr = [xedges[0], xedges[-1], yedges[0], yedges[-1]]\n",
"\n",
"plt.clf()\n",
"plt.imshow(heatmap, extent=extent_tr, origin='lower')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Model definition"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# SOME PARAMETERS FOR ARCHITECTURE AND TRAINING\n",
"\n",
"SEED_DIM = 5\n",
"BATCH = 128\n",
"train_epochs = 250\n",
"display_step = 500\n",
"unroll_steps = 1"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"tf.reset_default_graph()\n",
"if 'session' in globals():\n",
" session.close()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def create_adam_vars(vars):\n",
" # initialize variables needed for an adam optimizer\n",
" adam_vars = {}\n",
" adam_vars['b1_t'] = tf.Variable(1., dtype=tf.float32, name='beta1_pow_t')\n",
" adam_vars['b2_t'] = tf.Variable(1., dtype=tf.float32, name='beta2_pow_t')\n",
" for key in vars.keys():\n",
" mname = '%s%s' %('mom_', key)\n",
" vname = '%s%s' %('vel_', key)\n",
" adam_vars[mname] = tf.Variable(tf.zeros(tf.shape(vars[key])))\n",
" adam_vars[vname] = tf.Variable(tf.zeros(tf.shape(vars[key])))\n",
" return adam_vars\n",
"\n",
"# TODO: \n",
"# * see why slower than base tf opt ?\n",
"def adam_updates(cost, vars, adam_vars, lr=1e-4, beta1=0.5, beta2=0.999, epsilon=1e-8):\n",
" # return symbolic expression of vars_updates and and adam_vars_updates\n",
" vars_upd = {}\n",
" adam_vars_upd = {}\n",
" adam_vars_upd['mom'] = {}\n",
" adam_vars_upd['vel'] = {}\n",
" \n",
" b1_t_new = adam_vars['b1_t'] * beta1\n",
" b2_t_new = adam_vars['b2_t'] * beta2\n",
" \n",
" for key, var in vars.items():\n",
" grad = tf.gradients(cost, var)[0]\n",
" mname = '%s%s' %('mom_', key)\n",
" vname = '%s%s' %('vel_', key)\n",
" mom_new = tf.mul(beta1, adam_vars[mname]) + tf.mul((1. - beta1), grad)\n",
" vel_new = tf.mul(beta2, adam_vars[vname]) + tf.mul((1. - beta2), tf.pow(grad, 2))\n",
" lr_t = tf.mul(lr, tf.div(tf.sqrt(1. - b2_t_new), 1. - b1_t_new))\n",
" var_new = var - tf.div(tf.mul(lr_t, mom_new), tf.sqrt(vel_new) + epsilon)\n",
" \n",
" adam_vars_upd[mname] = mom_new\n",
" adam_vars_upd[vname] = vel_new\n",
" vars_upd[key] = var_new\n",
" \n",
" adam_vars_upd['b1_t'] = b1_t_new\n",
" adam_vars_upd['b2_t'] = b2_t_new\n",
" \n",
" return vars_upd, adam_vars_upd\n",
"\n",
"def check_numerics_dic(vars, message, name=None):\n",
" vars_checked = {}\n",
" for key, var in vars.items():\n",
" var_new = tf.check_numerics(var, message, name)\n",
" vars_checked[key] = var_new\n",
" return vars_checked"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# G architecture\n",
"# in_z: (BATCH, SEED_DIM)\n",
"# --- W0: (SEED_DIM, 128); b0: (128)\n",
"# g0: (BATCH, 128)\n",
"# --- W1: (128, 128); b1: (128)\n",
"# g1: (BATCH, 128)\n",
"# --- W2: (128, 2); b2: (2)\n",
"# g2: (BATCH, 2)\n",
"\n",
"def xav_range(in_dim, out_dim):\n",
" # xavier range for normal init\n",
" return np.sqrt(3. / (in_dim + out_dim))\n",
"\n",
"def fc_vars(name, in_dim, out_dim):\n",
" W_name = '%s%s' % ('W_', name)\n",
" W = tf.Variable(tf.random_normal([in_dim, out_dim], \n",
" stddev=xav_range(in_dim, out_dim)), \n",
" name=W_name)\n",
" b_name = '%s%s' % ('b_', name)\n",
" b = tf.Variable(tf.zeros([out_dim]), \n",
" name=b_name)\n",
" return {W_name: W, b_name: b,}\n",
"\n",
"def create_vars_g():\n",
" vars = {}\n",
" vars.update(fc_vars('g0', SEED_DIM, 128))\n",
" vars.update(fc_vars('g1', 128, 128))\n",
" vars.update(fc_vars('g2', 128, 2))\n",
" return vars\n",
"\n",
"def create_vars_d():\n",
" vars = {}\n",
" vars.update(fc_vars('d0', 2, 128))\n",
" vars.update(fc_vars('d00', 128, 128))\n",
" vars.update(fc_vars('d1', 128, 1))\n",
" return vars\n",
"\n",
"def generator(in_z, vars_g):\n",
" g0 = tf.nn.relu(tf.matmul(in_z, vars_g['W_g0']) + vars_g['b_g0'])\n",
" g1 = tf.nn.relu(tf.matmul(g0, vars_g['W_g1']) + vars_g['b_g1'])\n",
" g2 = tf.matmul(g1, vars_g['W_g2']) + vars_g['b_g2'] # linear\n",
" return g2\n",
"\n",
"def discriminator(in_x, vars_d):\n",
" d0 = tf.nn.relu(tf.matmul(in_x, vars_d['W_d0']) + vars_d['b_d0'])\n",
" d0 = tf.nn.relu(tf.matmul(d0, vars_d['W_d00']) + vars_d['b_d00'])\n",
" d1 = tf.sigmoid(tf.matmul(d0, vars_d['W_d1']) + vars_d['b_d1'])\n",
" return d1"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# --------------------------\n",
"# define placeholders\n",
"# --------------------------\n",
"z_rand = tf.placeholder(tf.float32, (BATCH, SEED_DIM,))\n",
"x_data = tf.placeholder(tf.float32, (BATCH, 2))\n",
"\n",
"# --------------------------\n",
"# Create variables for G, D, and their optimizers\n",
"# --------------------------\n",
"vars_g = create_vars_g()\n",
"vars_d = create_vars_d()\n",
"adam_vars_g = create_adam_vars(vars_g)\n",
"adam_vars_d = create_adam_vars(vars_d)\n",
"\n",
"# for D:\n",
"X_GENERATED = generator(z_rand, vars_g)\n",
"P_RAND_REAL = discriminator(X_GENERATED, vars_d)\n",
"P_DATA_REAL = discriminator(x_data, vars_d)\n",
"VALFUNC_D = tf.reduce_mean(tf.log(1e-6 + P_DATA_REAL) \n",
" + tf.log(1e-6 + 1. - P_RAND_REAL))\n",
"vars_upd_d, adam_vars_upd_d = adam_updates(-VALFUNC_D, vars_d, adam_vars_d)\n",
"vars_upd_d = check_numerics_dic(vars_upd_d, \"VARS_UPD_D NUMERICS\")\n",
"\n",
"op_d = tf.group(*([tf.assign(vars_d[key], vars_upd_d[key]) \n",
" for key in vars_d.keys()] \n",
" + [tf.assign(adam_vars_d[key], adam_vars_upd_d[key]) \n",
" for key in adam_vars_d.keys()]))\n",
"\n",
"# for G\n",
"x_generated = generator(z_rand, vars_g)\n",
"\n",
"vars_upd_du, adam_vars_upd_du = vars_d, adam_vars_d\n",
"# ------- UNROLL D --------------\n",
"#for i in range(unroll_steps):\n",
"# p_rand_real = discriminator(x_generated, vars_upd_du)\n",
"# p_data_real = discriminator(x_data, vars_upd_du)\n",
"# valfunc_du = tf.reduce_mean(tf.log(1e-6 + p_data_real) \n",
"# + tf.log(1e-6 + 1. - p_rand_real))\n",
"# vars_upd_du, adam_vars_upd_du = adam_updates(\n",
"# -valfunc_du, vars_upd_du, adam_vars_upd_du)\n",
"# vars_upd_du = check_numerics_dic(vars_upd_du, \"VARS_UPD_DU NUMERICS\", name='check_du')\n",
"# ------------------------------\n",
"\n",
"p_rand_realu = discriminator(x_generated, vars_upd_du)\n",
"p_rand_realu = tf.check_numerics(p_rand_realu, \"P_RAND_REALU NUMERICS\", name='check_preal')\n",
"\n",
"valfunc_g = tf.reduce_mean(tf.log(1e-6 + 1. - p_rand_realu))\n",
"valfunc_g = tf.check_numerics(valfunc_g, \"VALFUNC_G NUMERICS\", name='check_vg')\n",
"\n",
"vars_upd_g, adam_vars_upd_g = adam_updates(valfunc_g, vars_g, adam_vars_g)\n",
"vars_upd_g = check_numerics_dic(vars_upd_g, \"VARS_UPD_G NUMERICS\", name='check_updd')\n",
"\n",
"op_g = tf.group(*([tf.assign(vars_g[key], vars_upd_g[key]) \n",
" for key in vars_g.keys()]\n",
" + [tf.assign(adam_vars_g[key], adam_vars_upd_g[key]) \n",
" for key in adam_vars_g.keys()]))"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# Session and initializations\n",
"session = tf.Session()\n",
"\n",
"def init_dict_vars(dic):\n",
" init_list = [tf.initialize_variables([v]) for v in dic.values()]\n",
" op = tf.group(*init_list)\n",
" return op\n",
"\n",
"init_op_nets = tf.group(*[init_dict_vars(dic) for dic in [vars_g, vars_d]])\n",
"init_op_optim = tf.group(*[init_dict_vars(dic) for dic in [adam_vars_g, adam_vars_d]])\n",
"\n",
"# Initialize network vars first, them adam vars. \n",
"\n",
"session.run(init_op_nets)\n",
"session.run(init_op_optim)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def train_d(numeric_in):\n",
" _, valfunc_d_value = session.run([op_d, VALFUNC_D], feed_dict={\n",
" z_rand: numeric_in['z_rand'], \n",
" x_data: numeric_in['x_data'],})\n",
" return valfunc_d_value\n",
"\n",
"def train_g(numeric_in):\n",
" _, valfunc_g_value = session.run([op_g, valfunc_g], feed_dict={\n",
" z_rand: numeric_in['z_rand'], \n",
" x_data: numeric_in['x_data'],})\n",
" return valfunc_g_value\n",
"\n",
"def generate(numeric_in):\n",
" x_generated_value = session.run(x_generated, feed_dict={\n",
" z_rand: numeric_in['z_rand'],})\n",
" return x_generated_value"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"trained 500 steps G and as many D, 1000 total\n",
"g valfunc: -0.622032\n",
"d valfunc: -1.33372\n",
"trained 1000 steps G and as many D, 2000 total\n",
"g valfunc: -0.663956\n",
"d valfunc: -1.29243\n",
"trained 1500 steps G and as many D, 3000 total\n",
"g valfunc: -0.626307\n",
"d valfunc: -1.20085\n",
"trained 2000 steps G and as many D, 4000 total\n",
"g valfunc: -0.567329\n",
"d valfunc: -1.12869\n",
"trained 2500 steps G and as many D, 5000 total\n",
"g valfunc: -0.511694\n",
"d valfunc: -1.03771\n",
"trained 3000 steps G and as many D, 6000 total\n",
"g valfunc: -0.514788\n",
"d valfunc: -0.997446\n",
"trained 3500 steps G and as many D, 7000 total\n",
"g valfunc: -0.539354\n",
"d valfunc: -0.899798\n",
"trained 4000 steps G and as many D, 8000 total\n",
"g valfunc: -0.436614\n",
"d valfunc: -0.891324\n",
"trained 4500 steps G and as many D, 9000 total\n",
"g valfunc: -0.502095\n",
"d valfunc: -0.880541\n",
"trained 5000 steps G and as many D, 10000 total\n",
"g valfunc: -0.486488\n",
"d valfunc: -0.929448\n",
"trained 5500 steps G and as many D, 11000 total\n",
"g valfunc: -0.423278\n",
"d valfunc: -0.986526\n",
"trained 6000 steps G and as many D, 12000 total\n",
"g valfunc: -0.498981\n",
"d valfunc: -1.00757\n",
"trained 6500 steps G and as many D, 13000 total\n",
"g valfunc: -0.561591\n",
"d valfunc: -0.97069\n",
"trained 7000 steps G and as many D, 14000 total\n",
"g valfunc: -0.612306\n",
"d valfunc: -1.05895\n",
"trained 7500 steps G and as many D, 15000 total\n",
"g valfunc: -0.58464\n",
"d valfunc: -1.08233\n",
"trained 8000 steps G and as many D, 16000 total\n",
"g valfunc: -0.652361\n",
"d valfunc: -1.13255\n",
"trained 8500 steps G and as many D, 17000 total\n",
"g valfunc: -0.520256\n",
"d valfunc: -1.18435\n",
"trained 9000 steps G and as many D, 18000 total\n",
"g valfunc: -0.62854\n",
"d valfunc: -1.16244\n",
"trained 9500 steps G and as many D, 19000 total\n",
"g valfunc: -0.627626\n",
"d valfunc: -1.18386\n"
]
}
],
"source": [
"step = 0\n",
"t_begin = time.time()\n",
"try:\n",
" for ep in range(train_epochs):\n",
" for batch_idx in range(num_examples / (2 * BATCH)):\n",
" # for each epoch half of the examples are used for G, half for D\n",
" numeric_in_d = dict(\n",
" z_rand = np.random.normal(size=(BATCH, SEED_DIM)).astype(np.float32),\n",
" x_data = X_train[2* batch_idx * BATCH: (2 * batch_idx + 1) * BATCH],)\n",
" numeric_in_g = dict(\n",
" z_rand = np.random.normal(size=(BATCH, SEED_DIM)).astype(np.float32),\n",
" x_data = X_train[(2 * batch_idx + 1) * BATCH: (2 * batch_idx + 2) * BATCH],)\n",
" \n",
" valfunc_d_value = train_d(numeric_in_d)\n",
" valfunc_g_value = train_g(numeric_in_g)\n",
" step += 1\n",
" if step % display_step == 0:\n",
" print(\"trained %d steps G and as many D, %d total\" %(step, step * 2))\n",
" print(\"g valfunc: \" + str(valfunc_g_value))\n",
" print(\"d valfunc: \" + str(valfunc_d_value))\n",
" \n",
"except KeyboardInterrupt:\n",
" print(\"Interrupted\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generate samples and plot their distribution"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAWQAAAFdCAYAAAA0bhdFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzsvXmwXNld5/m5+fLt+yLpSU+7SqpSSaXaVIurXF6wMQaM\n2RowpoHGwzTQTcDQTEPQdMzQBE1P0EA02O0Z3BOMu4dlcAcG2m2wTePyUna5SrWqVCpJpZKedunt\n+56Z88f3nro3M2/u283M84nIeC/XezPvOb/zO7/VSSQSWCwWi6X2RGp9AhaLxWIRViBbLBZLSLAC\n2WKxWEKCFcgWi8USEqxAtlgslpBgBbLFYrGEBCuQLRaLJSREa30CfhzHGQa+AxgH1mp7NhaLxVIW\nOoD9wBcTicR0theGSiAjYfyntT4Ji8ViqQA/BvxZtheETSCP688PACNFvP0LwAfLdzYNhf1tsmN/\nn8zY3yYz+fw2U8Bn4W35lpmwCWTXTDEC7Czi7R1Fvq8ZsL9Nduzvkxn722SmoN8mpxnWOvUsFosl\nJFiBbLFYLCHBCmSLxWIJCRUVyI7j/JrjOM87jrPgOM4dx3H+ynGcI5U74vHKfXTdY3+b7NjfJzP2\nt8lMeX+bSmvITwEfBx4D3g+0Al9yHKezMoe7rzIf2xDY3yY79vfJjP1tMlPe36aiURaJROK7/Pcd\nx/knwATwMPBMJY9tsXjsBWaBxVqfiMWSlWrbkAeABDBT5eNamppFYKPWJ2Gx5KRqcciO4zjAfwCe\nSSQSZ6t1XItF2rGfbUg3mMbqBpYwUc3EkE8C9wJPVvGYFksAm8AqsFXrE7FYkqiKQHYc5xPAdwFP\nJRKJW7nf8QWUAePnONa5YCme7cAysAdoR1msw8Bd7v9WU7aUg9eAMymP5V8nreIC2RXG3wu8O5FI\nXM3vXR/Epmpayss29+9hoBe5MiJAHzCEFciW8nAf6YrjLeBTeb270nHIn0QVjj4KLDuOs8O9paq/\nFkvl6T4M7UvAOegcgY44cAnoAQZre26BRICxWp+EpYpUOsriZ5EK8hXgpu/2wxU+rsWCilS1uf/P\nQN9dMDRI+/vWaT05DC3HgHuQ6aI1j8+LUN2dm0O66c7SyFQ6DtmmZltqSDd074KohuHeJ65z+Mgy\nBx+Y5JXxBU4tPA7nl2Htmyg8HmRf7iI9MgMkIHvRFrQaxIC3qnQsSxiwAtPSwFyBjgPQ/Z3Q/b08\n+NGb/MT3/xb/+pVf5kd2foaRn5uAe9Ykg9mGhG0bMmEEEQMuVOncLc2IFciWBmQAaAH6YfoNmJmh\nf+8MnUOrTH9rg4Vntnjv7X/gqaNfg8e7oONu4ASKxAC4jcwY/Smf6yAHoMVSGaxAttSAHvKz2WYi\nQrqw9DPqfv42YAF61tn+K7fpfnKRA+/rYOvn9zHGbe67eRY6pmB+AUVdTCOB24tsyzuRC8QQBY6V\ncN4WS3asQLbUgO1AdwnvjwK7Ux7rw7PxXkBa8gxwBKY2uXx7F7Prwyx8LsaXIw/zuce/i6sre2Fy\nDbgOzCEH2hKKuLgDXAV2+Y4RB+ZLOG+LJTtWIFtqwCUkAItlAzhLslA/hIbzfqQdfztwAlpPQOQ0\nPUtn2ViPculXn2Togw7/vet7+PSpj8Lf3kFC9ijwPuAkiiO9jLTmc0jQdyMbsgmTw33MKeF7WCzJ\nhK2nnqWpMWaMzRyvc5BGfBB42X3sPBKYr7n3XwLGYWQA5nYw9ytjPJMY5sUPHWfh/BjLf94Hf/8m\nzK0i+zHAsyi6YgcyXYwAbyBH32EkjB8EVoAXgLvd45nz7UCLRbyYL2+xWIFsCRPbkTMuV0JnByqL\n8qzvsWNICEeRUHxdD9/6ayTojzL3qzPM/er98EAbrKzBwh2ITEG8DYXHX0JadjsyibifwQYKP7sX\nCeNT7uMvpZzXXcAVbJlPS7FYgWwJETcCHnOQkPYXAkqQXk7TCMlHgVdQ8SDDXcjM0APMwitf18ND\ne8DZBtNX3c9sQ/bjg+5xjyENvB04AjwXcH6teBryOaSld7iPxdxzN+dvNWdLdqxAttSICBKCjvs3\n4T7u+B5zkIAcxdNWAdbxTBOpbPk+yxzH2IETyc8lla8YRcJ8CvgmcgoecJ9bA17McLwHgdNIAB9H\nWvYHkfZ8EQn3HcgmHbTgWCweViBbasTdKMysH5kBjLAaQxrmMhKKb7iv8zMA/CQqr53KqZT7x4Fr\nKIRtGkVPBHHbveWDEe4gW3IcOQPPoSiNz/he+6Z7Kxb/sSyNjo2ysNSIN1C68pska47XkbkhWy/c\nNYLNB0GcRo66s8hRN1rwmSYTQa0iTXTFL6IF4gUkjDNxELWSKoRW4IlCT9BSx1iBbAkZY0Anark4\ng8LRQJr0A+7/q+QvkP2cQxryIdLjmFOZA1713W8DHkfa8DNIa/0l4NNkDuG7Bwnvnchkca3A890k\n2XFpaXSsQLZUgQfxYoaP4ZW6PAzsgJFvg8HH3MciSPscRpqnqR2xQHLh71wOsgdIr0lhbMjjKKrC\nsBMJ6VT8x9hAWrD/8f8LCeOH0CKSSgTZlO+QZr/Om6Dv+XCG41nqHSuQLVXgdbxIhyjSeoeQ1jgJ\nMzdh3lRbu+k+PoVCzWJIOz5KYS2XziI7dBAxkgXdBApXy0Xq8VfRYnMR2cRTsw8voMpxpjj+btSx\nxM+Q+95CeI1CulBY6gfr1LNUkAfxkj0uIucdSODOI8G4H+LLeCUtY773G6G5SOFlKAvpMh3L/ZKM\nnEVRH60k6zeHkRPxCvoee9znjWZ+DNmzT1N4XQ/bQbtRsRqypUxE8Wy8hsdRksdZtLU3AnYdTwje\nQtENW8h0cJJ051fcfU8YiCCTgXHqrSFTxBmSNfJryMyygb6bKZQ/jITzItoFzKLFqtJsQ2nlljBj\nNWRLAQy6t0sBz0VIt9n+NTBJsgb6Jp6Gtw9FJpiwthkk1MKsAcbRd/Dbg48hDd5vBkk1KVwnOdZ6\nGC0yPSjeeZHsgvkBpE0Xm1wyh80gDD9WQ7YUwBJyUPUgm7ChDYWpvYaEzQk0tG6Rbg7YieeQmiRZ\nSKwjrbLa9tERckdd+FlIuX+N3IvIuvuaDVSRrgPtHpaRCcfEQHfi2ZSjKI4a5Ig0wvgoblX9AtjE\n2p3DTxMK5DYUjmTJzTaS43Y3kQBZR9re9yFb6RbSAOfdx6+TWZObwBMMK5SuDTuoOlumqmsHyNwB\nxLBEcMumfFmgMM3VLGwryOlnajsfRL+HEc4xvBhtf2jdLfe1Qf32dmOL6NcvTSiQt5BmZsnNMsHb\n3E0kFC6h0LQ4yQJjJuA9hkVyV3MrhAQSYJlCymbILfTXyByRUQ52IhNF0PHW8Ozna8iMY2ouR1Da\ndSpzeBErqczjOU8t9UYTCuQ46am4FhViN5radiRAVkgXVD1ohzGCnHVB9uQg9lN87Gw32bPcsi2w\n89TeJr1EcrEjP+vIuTeFvod/YUvgLW53kzxdL+HtNPbg7QIWsaaJ+qUJBbIlnV14ZStBE9of1dCP\nNLVeJKzn0cK2i/wXtyUKiyP2s0VlNdh8iBKcPJIPiyRrrQPI5m7MQevIZNKCFrojyNQSx+uGbdpM\nGY4jcwfIRJHLpmyuYS4iyAxlqQVWIFuQQJjE0+JaSY6N3cIL35pHWlwbEhAm0aEFrzpaEFMUb6pY\np/a7mgTlMwVsuZ+VGsoXdx9fIV2jvoV+3xb3/izeAneD9AVrBC8j0hwzn51COb+npVBs2JuFdGFn\nMtkG0JptwtFAgsJUY5vFs40m8ATuARQV0EhVymJ4ySulskRwIaIN5BAN4gDJpUVP+56bCnj9Frp+\noOu0TH67jAS2TGjtsBpywxFFBXpKYQ5tg/ehVkmpXvs1FCWwgSek4njCJEgQ7yT/UK1ekp1gzUQb\nyY1VDXEUXpctmmMEXbMedA1N1Es+BDWOtVQbK5BzMkL5C7nspnLNMU2HjUKPN4xnk8T9DBMOVugw\nGSddEKSeUzZM9+hmDd8K+q2ukFu4mu4k5nrNIsHcS7L5opDjWqqJNVnkpI3MHvJiaadyhcc30ZZz\nFC+etSOP4+1ApgljPyy0dkQuMm3FgzCJF5WoaDaAF08dRjYovEynIVPx/Ra8qd6JFro1kk1VWwQX\nWBolPdsyiH73NdlqQltyYQVyTm7mfknBlFvY+WlBwtUvzC66jxktOWiCzaLFp4twOHUWSM+IKweF\nZriFlRGk/W4hAWsSdvrRtV/Au47+ULooMml0kBxW14J2SRMk00OwjTqVdoqPorEYrMkiKwN4RWHC\nTCvelrQLVVm7hFf2EfRdTC2K1K1pP5qYmzSOwMrEHTIXlK8n+vD0qR68qJhudI39WXxdKFyxF4Xg\nnUe7p173+Rb3+X7SuUiwoO0neaxMkD0hqBiGaDad0QrkrBQrkFvxBncL+dnvSqENz6MO0oSjKIHD\nOMfOo7ZJb6BJO4I32PegCX6L0lKILeXFFCHC/ev3A5jEkH503Yyp4Ca6xn7h2IkW5z7fY8t4Jgqj\nNQf1/hsiWEwMkN/i3Y4n+AtlCJ138whlK5CzMk6wTayTZJNAO8nFyduQwAPPhFAsXXjaTgcapEO+\n47W6xzfbykXgb9FEnSfYY38XEsJtvvfUOpstH1pIFiqlknodsxEhedErN1HSBVcLXvLILoIdsyN4\ngrGbYAViGtmlU+PAo3hjKdVUYRgls5MxH5OSsVkXw0V0bo2+a/NonqWnrAwg+9sqmgDb0IRdxvtJ\njZ14A/VyK5YhZBtcQ9vKMfe4S0gbiqK04i008W4hIX0EtbMP2oaCtKEVNOBvkLwtNfbFsNQgNrSj\n8Lly2Zb7kZDLx2nbgqJVCjF3dCEhmE9CTAcSfv7aIVuo2wqokl4Qfn/ENjKniu8i3UbcjpeSvo5X\nQ8PPdbLbhrtITzppR/NhFf1e/t+sBQnpJbxommzX01+StJDfsz6xGnJRmKLqoEkdQaUUo0hjSdVK\nHXJXHMvEdZJrNawgzX0Gad4LwCtooj3unksXGvARVBUsVbNaxnPq7SS99VBqlldYWEGml1x0k9/Q\nvk3+yR6bJPf0y4cd5K/RLxFsMiiEcTKbnM4B30Bj1OwK1lCbqVeQmcPg19T3u+/pdh/vJVlj3k7y\nd2xD33vE95j/mO142Z1RvKL55rOzMUrx86g+sAK5ZGaRZmpsZb2kT6woyfWDQUIz31jkNjynzUHU\nscLU0TVMAH/lvnYPXjHzl0mOLwYVBTJa4UXSNaPreAtOPXKQcGxzL1P7lO9U+vAShzpJ7yLSgnZX\nhtNoMTqG6jA/QLLgHMczl3WjxJQ4Wuja8JQUk3Sy5r4H93NPIzF0t3vrcz8naG5cQoty427srUAu\nmWFU6GU3Es5BWs4m0kL8+PvNGdrQJWkjWQsZRdvRLeBFtH3NlI23RnJaLcC95B/030r9D/jXKH/s\neKMwg2cGWEKLs5+Y+1iqj2QDje1ZND6M6Gh1X9uCGhMMogV9GI3RIfd/My86SVdO2lBH7zOosNFx\n9zETr2/mBWiehXH3Vh7qfeaFgDvIpBBFAydOfvGYG2gwG9tbK9IQptAgvo20qxZk402NG87khAni\nVAGv3Y2EernqNlgyE3Fv5Y7fjaJxmC3N2kTipNpjW/B6Iz7nfsYxJKSPIC3V+CyW0G7EdBB/1vcZ\nU2jMjrjHaEECdplke3gXajDwMvAoEswRNC9OIFPgfuREnKGyMfy1x2rIZWEb8BjwBNrWGaIBN8Mp\npLkam9i9aNC9Gw3gaXR5DiCbXOr7g1Kky8FlrDCuFiMUX9IzG/tI7vQSRD/BnXNiSLA+iyfQX8Lb\neRmteg5pujPua2/jjdFR9xxAgvkCEuIfTjlWO/AImgtPoPH+IPAzyHF+Bgn8borvJVhfWA25LJiU\n1XtQdIIDTi9EHnYVW5OyHEOOFUf/Oy9B4mE0wF91X3MGCWMHbd8WkIB8FxqwX3GfG0WD1u+MsdQX\nExS208mXfLTI1OiHQjBp+KnRQ08hzfnrAe+57N78KfxdqMv4NyDiQDwBnHJfsoE09W40N4IiQBoP\nqyGXlSkUinYC9vfCr78LDThDCxq0vwZ0wMFfhNY3kSA3jhIjkO9Bg9Boq19DwhikRTyGFcaW2nCC\n4NjipwkWxoZ+NHZx3/9PgReh5V3w4++SUOYdcPBd0PoUEvhfo1mEMViBXCT70RZsN96W8w7aVv0I\nMADj2+H3/2/Y30XL2OOM3dkJH3kSLf/fBLbg0nOwuYa2hNlatB8guYXRK8DnyvqNLJZgHic92eQ0\nhaVJDyM7tINCQn8aOV2fgcgpOPykXuY48ENPwO2X3Xnx0ygs0zgLGx9rsiiKqyn3dyB72hzwVeD7\nYCgB70wwuDLDx/7ikzgDcTb+Yzt/6PyyzGa/HoNVY0d+g+SCPvegAW+SOlKrcDWHPc0SBl4g3elo\nTA73oN1cHxq/qb6HHWgMv4nmRhwpI08CPw2d5+AjPw//tAWiCd7/u9N85X9z2ErEUTTROvADwOdp\njPojubECuShSBaIbZdH9CPQdhq1W+FE4+p43+JO//jE+Gf+f+L2f/FfE7m/hno+f5xeO/RFba++A\n/Q/D9TOwZVrZjyNN+SJeM9Zc3nJLfbIDOXTDHjWQLQLEjNNZgku7TuL5Qi64j21Cfxw+MAg9J+En\n2+HPgYfh03/wz7n0736bH/jrf83UynHkWzEhjI3UfSYzViCXzA7eLlm5cgXWr0DiPfD566zt6GDu\n17r5rU/8Jn1fWWRrNcrUvxjWYv/d7fDVs7Blwo4u4IUgmUlgBXHjMkX5q6NVm1zjdBhpz+Pu/V5o\nfwweuA9+IUJ7W4LHTnyJy/t2872Pfy8vf/NufuUXP0773zi0/KMvE7v6IeDvaaYay1Ygl8w00hAO\nQeIEbL0A/AN7++7hf/nY73BnZITT//Nxbv3gLn5j9bf5S36QGK9C74OwtYY8yAeRphS22hGWyhEj\nd9H3eieKHNldwD7oWIPhh+B6O9yB3uML/FrHv+Xz2z/A8J2LvKP1Drf6xlj62U5it7chYVzvi1Zh\nWIFcMoMo+2gcaQMngQvcubLBx3/uX9AeXeXR//oNPjzwOd77u19h+OQUDk+S+NIZWN9EtjdTStHS\n3HSjtPd8ilHdi8LIwpyROIXXHXsdNrpg8gVgko5PfJCTf/sNtuYdPvDtn+CBfviZgU+y/EwXW5fa\nIP40+n7NVfTeCuSSmUdbqlXk7GsDrrE+tI2L7zhC5A+2mPz/Bnnlj7t4+f2PMPTefyC+8TcwbRpQ\nbhBO04RJLCikpkUEpb2mpm5b8mON/FtdXSP8JVNNZbZ+4ATEd8HGDWCQ+PUI1zvH+GT05/np3/kP\nfDL6M3zh+7+HzfHzEI+hudRcwhisQC4D/kkxBTjQfhe0HoKn14hPXWHi/zjMxPCH4D+fZubsObxt\n2FGkIYdxYhUT+5mg+H5w+dCJQg1LrYqWL12oHkO1jldIT7psYZJhYgBlJF4ArkJbGww+yebNL3Dx\nQ+/n8p67uXnwADe/vJPlp69A/BnkBPwQ8AUUdvcylUmgCR9WIJeVTWANtobgWhSunIeNBTizBTsT\ncH0GCeN70bb0DuHVAorZCieobMeRTZJLkVaajSofrxFZRePcXUC2OmDxORLrfay93gMJePXzJ+Da\nXwLvQXHHbyIBvIbKrY6g8gRXqZ+FqDisQC47SxA7C0sO2u5fglgrXD+AV8t3ChVqMWFD1eIwsnXX\na4HvLaobj1rt46XSguLb86kBXU32Imf2ABKQ2QrMr5PkrI6vwcqbENkOc59V/f1rcaSgHEMZfFt4\nUUfjyE/jL8TVuFiBXHY20Oq+Cw2sWZTZ9yaeIH4TxWdW23Y8X4NjWoonQTgTIpbQ2F6mOCG5BfGb\nMDcBc/vxyoGaOi/gjdO9aJfSHL0ebep0RVhBttQ2NKAW8QoQLaN060mqLxwnaPxQq0YijjduwsQM\n0nrnKD46qBVVhFv2PXYb+Qn8HV9WUeTSCM2AFcg5GSW9xVE2jOMpjoTyChpoEaQp30CDuDkyjyyW\nYExPSn+69behebMOvANlMhrtOKy+lvJiTRY5iZO/8HQD4OlD9SdSQ8aMdppvaJOlftiFTFKNb+cs\nD1uoMmIEr3DWFl5T1Z1o3hkn3wCaX11IoWnM7D2rIedkguTCP6n04JUi7AL6IDoPfdt9r2lDFYVS\nixLtwq6JjYKdSh695F+dzQhkB5XufBhVN7yNFjfHdzOvN/8PkH8T2frAjqKSacHr3OEmhzjz0HIE\ndeQF/cx+s8cuvF5h1WQnlekyYpFmV0/acTsKJasE/jmRizj67S4jjdg0SjVNgG8ijfg2Uowm8ELf\nCjlOfWAFcsnM48WqLgMzsNkCs6fxmj/2AV/2vcd01V2hurbkQjpdWxqbFqCjQp+9Sf6LUxyVDjB8\nGfr6IWIWuGGkuAyR3knc1JFpHKxALit9KNY3guIor+AJZAdPY34TDcRDpHeeriRv0SzOEYuhG69v\nox8TCVQJ2knuWl0gHRvgGEWlF5n1uqnuXKkNViCXFWM789uKN1CcZQvqKu1nGhuGZqksXRQWJVQO\nZigpXG/iOYiZTNFxvMUjgsLfgjT7ToIXnvrCCuSC6cIbEB3ufdC2ap7MPcUSpJcS9NdAbla6qdzW\nudw41F8roUlKj2UeoLqiYjvBzu5B5AcJ0r678Drs1C/WxV8wg7xds4I+tCrfQkJlBE2ALdLDcmIo\nT9SSzCD6Leuh/GgExZg3lt0yN7uQw7pc9bqNkztTXQpTfrQXacdmF5nayszPdHlOrcZUdNlzHOcp\nx3H+m+M4NxzHiTuO8+FKHq863MCrPDWHtKY9aJJOotToQ8FvtQRwHcXv1gMx1FKo2ThLZmHcQeG2\n3TY0Z3KxG8+R10Ww/tiOFKNUh199Uul9SDdqkfzPaLjUtG4UPzmIN1jnUCGYDUpyaoSaSnrnLfXH\nTgo3FawhIZ+Lcbyd0xjBNuJhpARtD3iu/qioySKRSHwBFTXFcZwGi7c6hgTTsyTbgU0Bn0MomqLR\n2jL1oj6CtaxA5iCNqB7MHPVMJ7nLsF6u4PEPuZ+/THpN6lYkviZQrHJjYJ16RfM8ip7Yi4SDWdsi\nSFCMkx5VYajn7ZXZBdSSNlRT2lJZ7sMb121UP4b9DF7xoVY0t6J4dWEeQ5pz42AFctFE8LKHHkHx\nx6Dt293IqZepldFDNFqGUXVZB16q9Uk0Ac/jxa0fp/pmuCjeInAYRXscRM7zxmwSa6MsimY3Esrj\nyDxu7Ghz5PbCP1u50yoaM/AbzNRvKROFLoCFjqcI6eVoT6DQ0CU8m7MJHTXZsY01XkMqkL9AuuPo\nONpChQV/8sdt9zaCnBz16Im/h5ID+i2Wt9mFHN8X8nhtBHgKxfD7hXK2ReAQ2ilVsodjMbyGTC1+\n8vd1hFQgfxAJtjCzD3gShWx9yX1sCsVD9qOKVa/U5tSK4hyNpm1YaskNirc5Pwa8SrIgO47i/U28\n8VuEc7zeR7rieAv4VF7vrqhAdhynGzUFM1fmoOM49wMziUQibEtbgVwD/isaFDuQEL7g3l8gPy35\nEfd1YYgWCOPgttQ3ucZUG/Ag8BzwDNKOH0O+l9Q5cdb9vCMokqkxd3KV1pBPAk+jXzIB/J77+H8G\nPlbhY1eYOOom0obMF/5MoQT5ORxewaZOW5qXDTyzhJkvLxE8J4wp4xKN3Bey0nHIX6XhIjn2oYF0\nC0VKRNEAyTRIOoCjwMsBz1lhbGl2UudArjkRVK1wFwqLy5ZaXR80mLCsBreQFeak+39qFxBQ8sRR\n9/91vNz8TByn+hW5LJZ64y687jx+JknuzVe/WIFcMBvI1LCAbMdBhbhX8FZr08wxG5fyeI3F0uxc\nR/NuH8ndTjZRjPLeoDfVFSGNsggLd6HUTDMIlpAJYhuKN85UYSpG9j58qRTyWoslbOxBTrjJXC8s\nkZ1o3k2Q7qOZoxGSrayGnJU7eJrrFBLIs3hacRiiI8LKcWo/Qe6iuUxBpthVtZlGSkulOIjMgJMo\nlXqV9J3pBtl3me0o1j7cWA05K/56rYNoMMyi7DxSnutGW6pysxMNtnqr93qL2nvDJ6mvxqOl4lcW\nqkmld3jTSPkpxAnegxK1xt37W9RDqJzVkPNmAW8FXnFvw8iOvErlNIRFymdfPkL1+pJNU/vY5nma\nK5JlkfBUFzTdPYrhMMnjtJjruIHMGIYY9dBYwArkvNjl/k01UawhwbxGcQI5U5PTMbRFA5lJyqWB\nzJFZa92FCn1bLOVgHa9Sm6ET+WJykW2c5kuqQK4PrEDOizVU7jG1y8EymdvQ5MMywQNvlcp0hw5y\nhlT6mOWgCxVzslSfgxRn2VwhXUnJ19k9SfbEqu0oM/Ye5CdoHKxAzosZ5KDy1zEeJDgmshBuEzzw\nZqh+GNws4Y32iBOerXi1cZBQrBVrlM/0tEF+kRj7yLwIbEeadgzNkWyO9U7qrV6yderlzXl08YfQ\nYIhT3oLdO5EgblbBk416aYJaKaq1c2lBAsyf7FSLbhzZvm8c+SeWSG4k3IfMf8WUMAgPViDnjWnE\nOez+nfc914O051IiIRwKF/BdKLqj0vGfltqRIDgbtFKEodPajSzPmXk4iAS332SYeu5raBdaP1iB\nnDdDSHsNEroRSo+5LUYTcbCXsFnZgXZU5YwiiVEf9SAGkQ3ZmFIWSbdXdyBFqV46mgtrQ86bNjIL\n3QXkMKs2yzRKDr8lH0bxpmwHzTV9h/CaVrShCIplZKboIT1CaAh1HKkvmumKFsAw6eFot0lehbsJ\nbktusVSKPrxt+RVq628YoDrNeofQXOzC2w3eQQJ5Cu0S2knvMBR131NfWIEcSD/JpoA+0gdfF/lf\n8Aie7dliKZYLhMdJ1Yc01WJpIb850Y8E8nU8J14vyQ1Xp0nfoc4gR/xACedYfawBMpBLvv97UahN\nFJkHjDOvEEdai/sZ02gQ5uP860H2QRt1YQkjpToazZyIkz2D7nLAY33u+yeQ464T7Rz8YZtLyC+z\nG9ma56kHrIackxEkfIdJLvlXCJvAG2jQjJGfJ3uIetxyWSz5sQFcxMuCzYdupC3PIgXJZLP2EqwJ\nL6NWazvKM+n1AAAgAElEQVSKP80qYzXknJgV+iXS4yPb0JqWb4xsAvULy4dqhjpZLOUk33mxCbye\n52d2oRoXN5G9eAEvgiKbQ32F/DpfhwOrIaexDW2JUn8a08jUzyDFa80WS6NSiXkxhswUW0hZmUKC\n32/HbqU6jsbKYTXkt+lEK/oHkAPhBZKLo4wHvCf85fwsjUgH8i3UuppeJvzzosW9lVoW9M2U+61I\nSK/jxfAPIPPFJeoVqyG/zUNotf1T4KukV6oKOw6leb0t9cNR6kcTHEC1OMpZ9jWKivGvkZxQNUmw\nMK6fuWEF8ttsUt8bhh68xqqWxuZl6qe2hwlJK6QqW655uI/CkqI6gWMFHL92WIH8Ns+ji5YaYB5E\nMXUnKs0i8GqtT8JiCWAGRRnlQwvarWabh29RWI2KFbSIhZ96VgkrwPPuX4fs9rn9KH6yHvL+LZZ6\n4jHkv2mm1lseVkMG4J14a9MjwFN4MY5BXMYKY4ulEjxLujC+n+Kbt/Yijbs+sAIZ0CAwMcYnCUeN\nirupp4B2i6U8JIBHSTZZvEZyNt9hpETlU3x+EXilbGdXaazJAkiuD3AaOEty8etK8hBwjvRuHRcJ\nb1iTxVIMfcgh91qO171MclnR1DZnl1AYar51PWrd/Tx/rIacxINosMxRPWF4huB2TaYricXSKCyh\ngj+5yFXjOea+Jmh+jCAN2tAD3Ic07gdTXvsoXkndB0guWFQbmlQgtxJsVzqHtjjlFsZtpA8Gw0YF\njldORsmvU7CluThC4XbdOJV31s2S7N9ZQUkl62h++zmDp2WfIwyhhE0qkLdQ6IxfSP4E+jlyCcc9\nFG7b3aSe8umTmabe2uBYqsFVSuu4XiliJAv9OF6j1tSd6ArwT/CydGuvGDWpQDbl+N5y798PfAVd\nlHvJHgM5SeZygf3AoQzHq7fMP4MtAWoJYo3qNV8tF63IfOHn7wke34dIr11TeZpUIBsWUZuXa+4t\nhupYZLNhrZF522U6G5TCAdLb0Vjqi4PYa1hNtpNexrMXXQc/pjCRnxsE26LvkO5orzxNLpAT6ILM\n4G1XFii+K8MCwUWICmGKMNiyLKUwRbCj1lIZFpEjHlQ7Yw+aQ6skC+WgQvX3EhxstkR5G8jmhw17\ny6t7R75sULrTIox2OUthpHZAtlSW1ZT/40iYTqEyoPfiFcRPZYIwRTM1qYbcAXwXSpG+B68uxSHK\nW5XKYrFUl3W8BXET+XyWUbTQIRTx9CHf66ewArnmxFDZPgdFTBiBvESYLo7FYimVTWSWvIR2n3H3\nfjhpUoEcJ7jp4R3C09XXYmlW9lH6TrULacRjSMxF8cwT4W142uACuQttVYIwmT6XkbF/H4pweAo1\nU7RYLLVhi9JjgjtQ1p75LL+DrvrOunxpcIEM6Rc2CuxE4W2gMJhEyi1sDFKLmEiLpTbcoLQY5y4U\n9nYF7XqNLXkMKWHXSj3BitHgURYr7q0NhcPMIC34YaQZX8ezJ5n4xPEKno+DBsX1XC9MoQnWTYul\nbDjIuXc75bFM4m4XYTFXNslMb0E9yCLINrWABHQtiol0Uni3kWkyZwdaLJZkltF8GfY9tknmGubt\nhKUDUJMI5FW0TdlA1aZOAV9CURWpNuYRKrdxSKBCJ2E0i1gy00L529pbKksUmS5a0RwfcR83kVV+\nLhOWNPAmEcgGM7GGULrlkHvzr4797usGsTHJFtGCdlSW8NJJcpefZaSERdEcNz6YCOlV6oYJiyhs\ncBuynyhaGfeiokLDqBB9Kqbg0BjSqMPrkbVUiw20s7GEly5kekjNdF0leZ7HSC/DuQ2ZMfvc99fO\nlhyOZaEitJHciqkVacXtKD7R3wV3gHQb0iXqt0KbxdJsTKNkr1w4pO92ziHFazuSG7WjwQRyG17p\nzAHUHdqwioRwUJ2BvdTmp+it0XEtlmbEQeaKvRmev0B6UShjh64ODSYNBvGcL5sk/7gR93aG9H55\np6nNNmU/TWU1slhqShTYjeZ7vuygmqVUG0wa3PH9v0ByPdNOFIN8htxNFvMlioR8sRXeynUeFosl\nnQjaNZtytpskC+Muctc8vlyB88pMg2nIfgbwesFF0MV4HdmQy8U2lPVnsVjCRw/BHXw6kIJ2HK/J\nKYQhHrlBBXIEFRC5gGfEvxtdiHvLeJxbJAebmyImFoul9iyS3uU6ihocvxPlI8SQjbgNyYZSO/6U\nRoMK5G14K2M/CmF7DdmUX67gcQdRN15LMC3UWgOxhImW3C8piT7SFbAtJIgfQGOxBTU7fgcqYG8i\nqyLUYqw2qEC+g7cyzlE9W+00wbHNxdJowus+bJEki+gATlb4GPMEO/A2gX+PCg09hpS0NSSYTajs\nMdITSCpPA+2v96HV7lKtT6SMHEHbrnziK+uBV2p9ApbQsAY8V+uTAL7p+/8FPCdfbRzuDSSQr6KQ\nlqd8j5lg8b3kF+ryqPu6sDQZvVDrE7BYSmQbqiPxRq4X1phTJHcLOo5kx3ZUqOhO0JvKTgMJZNNB\n2l9yL+7eXvc91oG2zqcCPuMlwlJkRNgiRNVhJ3LmvJXrhZaCmUJlb2tFL+o8/ap7P4pMJd9KeV1q\n67Y38LqLVK+tW4PZkHegWsd70EX4LiTURoEfdV+zhndxUgmTMLZUjwkyl2a0lEaC2tYZXiLZr7OF\nFK9cxPDO3ShG+1CAQOVoIIH8CLK5voqE7na84vN3gM/7XltsIoelMYlhF+NGxd++qQ2FvOUz/+8m\nvebFTSptuqhzgbwPCV7QKvgi0oy/H5XcMyvjCPC+qp+dxWKpFf2kh6BukhyX/BCZQ++uoB23P9Ji\nk0ov3HUskPchzWbOvd+LLsIyCmP5Op5zbgb4RrVPMAcnsPWWLZYgjlN61bVl0lulJUiu4PgmweaU\nI2huXiW9nGdlqWOBPIlsf2b7MYdWuwgKr/I7Ejbc13YAR6t4jpk4gQZLrbfJd5FcotRiKTepVRfz\n4SqFz40RFGVl2CJ3nYpMwvYm6rN3hGrPjzoTyAfwugKskGwLWkNCd5PMAd2bKN251lxHoTS1jqKY\nQM0gLZVhD7VILggXKyjSohAWKDyyYYmy9J3c/kFo60RC+Rq5hXp5qbhAdhznnzuOc9lxnFXHcb7l\nOM4jxX/aDMEC5DjKrFmD7gEYOIImwweRaaML2Zb9Jo5aMkOyMD6EV8e5UtxDur1sAdsRpZLMUe0J\nHT42SC5320lwwZ9SWaO4hhL3kBT9u3QeYktIe+5G83IXki/DAe8vLxUVyI7j/Ajwe8D/jvISXwW+\n6DjOSNY3prEfXch5dIEfRQIX5NRLAFPQfRg6t8HaBoq62HTf00p5eqKNUpjG044WglzMUXnzxTS1\n18jDhElYqCSL2B1IKpvUTimKIgHsd/ZNk6SNr1yG2EkUPptA128Jafn++upDpDdILp1Ka8i/BPxR\nIpH4L4lE4hzws0hl+Fj+H/Ee4L14RaLH0Gp4GHgEek9CdyuwCVvtsDwJa3MosPsCWuVWkV2qVFYp\nbILFyM8pME3lBfIk1QxwDz9rhCcjs5nYQuO9FphED3/XoH68mjH7kbBeQPKlBc33BRTutoK05BH3\n8VUkl0wJXhPNtRc5JQ8UfIYVy9RzHKcVLTO/bR5LJBIJx3H+ByqtlIMD6AcZQhlUg8Dd0L8H1i7B\n+hiwBVsrkOgD+mD9GjLC96Dwlg73/w0Kt2MFMV/g67eQILSEj+p6zy1hIE66D2kUKWsxJGBHkZC9\nhpS5HjyTy7B7f9B97XkkuHe7n9uHsoDnkA06tR1UbiqZOj2CJGpqJPUdFHWdgw20Ys2gzJrDwANw\ncBD2DMArnTCzDrEr0DIMh7bB2hW4sYFWp+3IaeWgFSwMzjyLxRIuxvF2p3eQcB1AClwP8j91Avvh\nXfvgUByej8Pri3j11U1wwQzwDEpI2yK5jEN+hLSWxbPA15ANthNtDz4Ah55i10euMfbENa588SAT\nM6Mq0HSmBTr6IdKPQt7W0Gq2iASzteNZLJYgUmKV+3fC8jx0HYb3dkD7CLzWCZc34O5+eP8e2o/f\nxPlilLUbR+GeYXhhAq4cQzv5v0JCGaSP9lGIYK6kQJ5C+4AdKY/vIOcZ/gI6tWvI6tEFfduh4y3G\n3nGLgWmHa6v7+cDJL7F8XwenPvMIG6cXwIlDVxTaF6B7J1yfRDai00hrHsp9aIvF0qSMQmQenCgc\n3AEjMWjfDt/RDV99A16LwdoczsPgfHgfTPfA9mV4vQV6HoW1Fuh6NyyYgIMOFIDwGeCP8jqDijn1\nEonEJsplfjtn2XEcx73/zUzvE6eQqcEY2+/AY9ugK85CrJMX/+Qu5sbbuHfkNZ74R19j7EevQ+8s\nxGOw917YsxPat9B2w9iO2/EiMyyWcjFK5TtflINuyhNp1Mi0wew4bHbB2jj85TPw9KRMzx2jcGYY\nPrtF+8vLHH3oDe599Ay8FIcbm9DfApEOaOlBETygiJILFBLdVGmTxe8Dn3Yc50XgeRR10QV8Ovvb\nRpDZwXyRVRiIQd9j3JydYX3xMq2HZ/jcyHdzsOVNRh+8ycwDY8x/rR/au6FlAZYvIjvOTaQd91GY\ng82YPGwhIks2ulHUQC0rmuVDK5WPda9HdgAR6N0GkSgsdcPOwzB9FpYiEIvCSwlY2WDgySke7Bnn\n8Se+RduxNb78uffD08ehoxcGrsCNm7CxhSJ8v6TPpbugs6moQE4kEp9xY45/E33zV4DvSCQSOSTj\nHmRemEQa7hh8+Sa0TbA4vB9u7GDjdA/XtrczPdHO8OAMnftizNMJt28CczC4HW6fR1rBBloHCgm3\n6UVeUiuQLdmolxrKtYr97UC700IjlKpFP9ACnfugpVVxyMMTEH8YVtuk4G4DDu9g8KNzPPrYszw4\nd5q/Gf8+vv7ie+DiLGy7jnbzh1DkhYkQ66PQ8VFxp14ikfgk8MnC3jWHhHEMtWRyYPoloA2e/Ta4\nswu2OmiLrLL+FzHeujQC8RXYmIBYAuZn4c6aXk8/qtx0HcUw51sse7ywU7ZYLAG0I8EUVoE8DczA\nhOloMgAXRqBvyw2+6IWebbDYwcSlUf54x/fw8fGPsnJlF7w4BVyGya/D5DDyd11A7Z+26b0FxlyH\nNMriMl6wNXirzCi8dhHFBQ6x9Kf9sLkbrrwFm1dRREWfXscZZHIw8aarqKusxWKpHvOESxg7aNds\n6l4cRdbUDaS8PQI9B2Hu67B+GxiC+DthfRvLX95i+TOz8Naqoromz6HvtgcFIFxAO/Fr7mOFt2AL\nqUAOogd90S1kzjgFb2zAwHugcw427yCtehmFyqUGZbegH8smBFjCSBRt75dyvdCSRjuy1+aTiBFB\nscZBhYiOACMwOY6Uuy7gIvz9DZTTsAoMQt8AdMegexk2LiEFsJPkxqjF9cOso2pvh/FK4X0VOevm\nYe4qLPSglW8ZhZl8D8qY8dNOcnm+QunA1i+2FE6+46YTFbFpFKrpRBwg/8I/MTzB2YsWwG48+fE3\nSPguo3rJcyiT7xxSBkdgYQqufg5mv4VMoFvA42X5JnWkIa+S7MneiS7COXTxE+iHfBn9kP7OABH3\n+XMEa8/5sBNp1+VIwbY0D6NocueK8PGb1xqBQTTXqtGrsNi2SkeQJnsIyYcrePVNLiJzRDuSOzuR\nKfXrAZ9TvjoxdSSQz6Xcv+zejDAGfZ0t9ON0oh9yA62Ae5GD0PTdK5TLRbynFFrR9wh7OJUlO+O1\nPoEaMVHrE8hBB0qTeCeyIR9FNuSXUGavmXd7kJbsBHyGYZay1GKmrkwWmRhDEXWj7v930Mr2AAo/\ncdCq9zrSjAsRxq1kvxCpRCjfGrcf2cotlrASpT5FSATJh3aksCWQXJh3/z+LVxHuItoVb1EN5aiO\nNORMjLt//QNjAm+FHkRF6l8p4rPvRoVC8l39BtHicDbXC/PgzTJ8hqW+MTu+sHIXCuuqt4qGcaQd\nPwI8hydoMylrERRQUPnytfW4vGVgD5l7d+X7Q6b+HGcobCsyTXmEsR9/CrmleWgHTtb6JHJwjvoT\nxqB5/jgq0RCU1uyQLAvuAp5EO/DKzsUGEsiZmEXFhfLhUWR7DhN3oYFgaS7WgW/V+iQalDiqyPYr\nqPlFaofr+4Gn8CI3LqCoroNUuh5OA5gsDKYjyC7kNZ1EK/gg+hFPo7jCY2hlDOJ5PG36AeTIq3VQ\nu01mCS/vQFtfm14fPoaQIjOOQmZf8j0XQRrvswTvnl9FmrD/uYsoQa2ybdAaSCCbH+oWsh8Po3jk\nTuDv0QVYxbswLUgjftb3Gf4L8FrK/SNIOBcbYlMstg9eeDlFuG28leReNBdq1Y4pF7NovsZJtw0b\nk8TX0fxKvYYJ93YUr56OeayyNJBANpgfeBIJYhNlYexFxoAfQ9pNJlI9qpcIV0+6bUj7Ly4jyFIO\nmlUYg8ZdmOZDKqlzvQNVYTP3nyV3x/U3qfZ3bDAb8k4UUQH6IdeQVpxAIWz3pLy+kK2miW8OCzM0\nb4yrJZi7qHwnbUPY5kM2ulDE1CvIUW/C3XJR/e/YYALZNCnZ73usD12MRisuZJJeLJWhF21Z64lr\n1K7MZphZQxr9KsqGDNoZ30d6qvddwA/jtQDdQ3LRs/LTYCaLTWTX8ndwWEb2pCOkZ/sVwn50McNq\nM7OUlxWqk/ZbTqrdO/IgWgDyLWlbDCYXIN+iS0Mo486fWRsnuVzCSsD7LiEB3IbKLiy7x13wHXuC\nStuRG0xDBgnlNd/9LnSRUpoZ0gKcKOBzJyi+1kArcLzI91pqQ4zgiWvxuE3l62/coLDaM4t4jvce\nFGHRSbq5MpV97vveQvLjEJq3E3jjYB3JksppyQ0okFNZRav4QaQlt6GtaBxt8fzcQ3pMomGF4k0E\nMdIXBIslrDhoC58rCWKF3I6xUjiM5k4hKcubeAJ0DS0aGyj6CqSIHXP/Pw58BJkqbqDd77x7PFNu\nM5V5KmkWagKB3IHsyDfRj7yFVkKH9JXOPF9u4ljbnqV+SCABVuuQy0lKE/hbSGNuRaV3j6C5OIGE\n8m283p0mRM6wmOHYqxRXLTI/GsyGHMQGurCzyLt6AG1LHLQiGsfNBWQLO4S02Wrb4yyWMBGGMrPl\nUmJMGGwMCd8pNP+3kV/4W/VoAg15AwnjDuQlXcWrf3oHr3SeWR0XsCUvLZZ6wxT2CqIFleCdR447\nUzt9FjkAHWTSzGSurB4NLpC78bowxND2pBN5UA233ZvZnk1Su4D/3cgJ2ciM0fjfsVaMonC9arID\nmQRrzQbJu9ouvBowcaQF70MREw6yT/ciWXDAfX8ceAIJ99rQ4ALZXAgg2gmDB5HB/zb66geqcA6t\nqDh+PphB0cg0w3esFZtUf3dXi2MGsUyyiSOOxlo7WjRu4819kHK25j6/jrRjBwnsHdSqyFiDC+RV\nvPKArZAYxPO2gi7afjxv8m7Kb1ZPkL8AmiA5ZC9M9CCbW6lMEt7vWO9MU/1QvRmSd5xhYQ1v7psF\nw+QnJFCE1QH3/xtobLeiImRz1Mqh2eAC2cfWEsz5M3TiqEKcP7Sn2J+jGxUz6iRdaG0hJ6HpdlvP\n2LrMlnrDFAVKrXEMEtBXkSy4iefcM9EXfgaphjmoeQQy6yTHApuwt8t4q+FVirMft+C1s8mmYdfe\naVA8S4S/T5rFAlKMhvHMFa1I2F5Fc9T4lZ7G056vkRxtMUJyKnWU5AzgytBEAjkVB2m25WABRWws\nk2wS8RNH6ZkWS7PSRnWKH/UgoWvE2zUkTLejee93Ko8SLAY7SBbAk1Qjl6CJBXKc8PStG8ZbyS2W\nRiVK+ZSgbKyhkLZVvGzcFmAApT77i4z1EWyKu04tbONNKpAjeO1ZCqGH7N7XNooLARpAmoMVyJZG\nphoFm/rRHEwtVbDhHvtwyuMXCEeUiGhigewPIh8iP4dVP9ljaDvczyqUt4DXscVsLOFkgPoRFYNk\nb3bsb1qc77yvHk2QOh3EFsndocdQFk83cl51I+GYunLeyPG5C+7NYmkkdqHtf9jLCbQhx/M4Em09\naK6b8pmbwBu+1++mliFuQdTLslcmIugipTKOhPA+ZDYYQx7asBPFZr1ZKs9Zwi+MQaaKbWhejKA4\n411ZXn8aac09hEVTbjKB3EbwduYBvAL26+7fejAf9JJ9wFkszcQUshP3IiH7Mvn1nDS1j2tPk5ks\n1lBPLT+daDt2nvQY5Ha0zQlrqq8pjGSxWDwKnRepXalrR5NpyKk4wP3AS8AjpCduHCIchVMsljBT\nnaSJ3LSRHgXlIMWqzXc/vHO6yQVyAjU8jKO6yKnblrPUZ2H5Jtv4WGrMPpR0UWvuAd6T8lgP8DBe\nl5AO4KeqeE6F0eQC2QEeQz/DfyT/RorFUo2fuxN4sArHsdSOsE3bt8icoVpOImR3vp0G/s53vwUl\nd3wTzyyxCvxBRc6uHITtylaZBPAM0pAr7WWNolqrlWYVOFWF41hqxyM0Z3TNUfKvODgEvBOZJI2W\nHH7s3vZtfgl4DQnoe1EY3KsoPrkcbAHfKNNnWcLNfah62HSFPv95whQ7Wz3Okv699yFlajzl8Rng\na8hefDfwQqVPriw0uYbs5xOo+tMqusCnKZ8wNjTjJGpGXkcCody8A/k5KjmOWqjOTq4Ygr63gxpA\nmGYT25EteRDZjeeBVzK8N3xYgfw2G2h704EuYLmFsaV5iFMZAfAClW/IGaP+TF43UWlNUCzyLNrl\nmsiP8NSqyIUVyEmcQYkhW9TLimppJqrVHTk8XZizsxfN0w3gJNKS4+5tieQ06fqgCQRyH9rC5MM6\nVhDnYgBlNVostcT0qbyJIjwmkTlnGDn0ziFBXV80gVNvmcJK/h1DZos3UPr0XWgbVI/xyJVgifqo\naxBWRtG0Sy0P2SjsRHperkJcpXIHr4nxKLIdR5BCdQWNUVNa4HyFz6V8NIFAjiFHXb6YNi9G6NxE\nxYYcbJoyyJxTTJsri5glLIVsKsMM1fl+fqXAFKMHacUdSBBfod4WviYwWRTKIqqVbKq9rSChHMbO\nupb6Y53G7rpdzPdzgBPkL8h3k9xgYh2ZK3qQMB5xz2EfmrcdKPQt/DSBhlwME2ilfS+yRVUjC8li\naVYSyMSRr/9mDu3SRtEOOIGqOC4g8+IWEsimrsWm+567Cbv5wmrIgZgLfplqtf+21DsHSe5SbCmM\nfJJodiMnfS8StotIA+5CWvIt9+8i2uEOuu+LIUE9Vd5TrgBWIGdlHF3k+vPWWqrNAta2XmmW0Fxc\nRtE+u5Fgnka/vz+dfBMJYhONEaNymZPlwwrkQPaiZoid7i0cxastYcZslS2VYw6ZIhaQ87Ad2Y2X\nkcDt9712HZke66HRhIcVyGmYYPNhdME3qGymzzsJbitVTg7S2J59S/PRSrILrB858/xsUA9mCj/W\nqZfGFgoy30TbIofKrrLrJHck2YFsYOU8ptXcLI2Gabv0lnvfZOjVN1ZDTuMmWmlngAHoPQltqStv\nMUSAPQGPnyJZ+FZCk71Kdg/2NpqznGPYaEeRA5Z0tiPz4TCqxDhLcof3G8BttMMtx3ytDVYgBxLl\nbcEYiYJjBNYgpZkX8rFF36b6dq8W7FCoBn1kbx/kUPtNq4MSoXIxQnq7pHIySvJ8MWPUdJS+iYSw\nGbfGrtxKONpJFUetr35IWePt7c/8GSSMe5GWWWytizhwqQznVglu1/oEmoRcC/Iatc8sc8hP0O5E\nEUiFZMEWQgfJu0WTC7CMzHotpEdNLJCsNdcfViAH0o3suDNIkC6jgVeNiz2INORC6kW0Ic29EjV4\nLeUj/GFXGu8X83jdLJXNOBzP8twq+flF6m9e2H1qIONosJm6FpNIGPeiEn/7kNbcRfkjJHpJ736d\ni1bC3EnX0ohcpzw9KB3ys/n2I19HO1KYRsjt+4hSb/PCCuScXEXaMkhY3oWEcg+eKcNPqcLRf7x8\nWSa7RmGxlJtiFIcgIuTXsXoAzb1+ZL5oR+nS3e7zHb7/29zzW6He5oU1WaTRh+xTC6THH8+hPl3Z\nzAmmuEl927IsluyYSKRSs1hjqFdeLq6QvBs1Zr1FNOe2u5+1jGzgO5C/p9Kd5MuL1ZDTGEMrb3vA\nc8Pk1n4XCa/zrlxE8bQRS3Nymeq3OVvB62ZyA43DfUj4xvBqMM8jR3X9hRBaDTmNbG1frqXcbyW5\ndnKz0IW87OGunGUJIure6rEE6GWkDUfRLjaBtOYllCbdjjcX6zPiomIasuM4/8pxnG84jrPsOE7I\n3ZzZwnzaSY5r9KdsjuIle7RQHptaPbBAsDCuZFyqpTz0oaI89couZE8eRdEWLyLNeAgpCfVNJU0W\nrcBngP+zgscoE8fJvFnYT3LRkl3IXmWSR8wWahBtnwwOwQI6yBRSKC2Er+BRK2p/VW+00FwbxRny\nC2srhdTfNELp47UVacfjqD7FFbz4+RZkpqh1DHfpVEwgJxKJf5NIJP4AeK1Sxygfp8gc13geDWKT\nKXQdDYTdaNCZfn1TwJu+93UDR1M+KwI8TOnp0SMkC/8wsIna1Ncbo9S3xhhGdpBcJsBESBRLFDXW\nfQhpwqmZpaPuc3vT31pnNJNqUCKH0CrcjTzL/kImjnvzP7YEvJryGXHgm2U4lzvuzVI6lW7G2Yzc\nTLk/Q2nJGUeRIvS6e/8wXms1022kMa6jFch5cyHLc6NIC8jmELRYLB4O+ZchSN1kv4k07jEawUzh\npyCTheM4/85xnHiWW8xxnCOVOtnwsQdpzhaLJX+6gZMlfsZFGk0YQ+Ea8u8C/0+O15QhCPcLpPcn\nOw7cV/pHlxX/gLAmBIslP5ZRdES+3Ifmmmk6nE8iSa14DTiT8lj+IYYFCeREIjFNVSqkfJDwh7Ds\nQRsM49Qz268BtJV6PeA9EeBx4FmKrxpnsTQChRSTfwMlfrxFZlv0ThR2WeukrPtIVxxvAZ/K692V\njEPe4zjO/SgcoMVxnPvdW4OkeLUAjwHvTnnc1GztIf3CxJFmYIWxxRLMSdJD5LaAu93nTCfp/cAP\nA1C034QAAB+1SURBVD+IlKMJVAemvqmkU+83gZ/w3X/J/fteVBCiTtmLnHgTKIrCJI0MI3vyItpW\nbZIcBmdotqw+i6UQXic5BPVelCF7meTmDTeALyLlZpXK9r2sHhUTyIlE4qeAn6rU59eOO2jbdB8S\nxqfcx+eRbWsLT+jWY3pqo3AvMict1/pELAWxCpxA8f+H8DpHx0hWZjapfi2NymPD3gpm3b3NkFzH\nYot6qyzV2FzBLojVYB8a96W4lhzgAff/08gOvIlqpuxH17E55pat9lY0RjCP4GV69aNayUG0EL4o\nkUZmmUbZxoabSQqv351KApkkLqOdjWmhdh6FtwUtrGOoQH1jYTXkgtmJV78CVJvCdC1oxYsOuZzy\nvjiNkk1ksXiUqyHvnPvXn/G6iMwWmyTblceQLlnqQhA+rIZcMItI+5pAGlgbXqpoH8rjDwrNSWR4\nPIg9ZK+7PEh+nYEtlnpjluSQuGnSi+D3uK9pPJOUFcgFs4QcD11oNZ/Cs29NA69QurNhkeydGNZo\nRO3A0uzcjSeSDgLtMHw/tBnlZAwpKreop8alhWAFctGsIa13J9KKQRqzEaQDwFNFfvYc2Vf/anXA\ntmTnEMm1suuJLpIrstUSB1VzMyaKI6jM7SFYn4eYcZybjiELaA40HlYgF80SWqVXSO7p5Y+6mAt+\na0GMIOFuCR+r1G+ST4zabfnbkOD1l5A11duW3f/jwMOwdB1ifWgBmSVYEA+QX+fq8GOdeiWx6N56\nkHPPDJadaFt1HkVglFIEJUZ5ogX2uedhIw/KR2qZyXpiHUVIlMo2CjehJZCmG/PdN3PE/KZx9/lh\nvKiLTJjX1j9WQy4Z0w7dH4dptKZWtPUyOBReWH6W8tiLE77z2kXztJuyJNNFecPFitkhbKI0Z9Po\nIYib7mvWUTKW0eZHkAI0hOf4XkDzpP6xArlkIiTbERNIEG9HA+9WyutbkO2u1K4hhbAbpZ8aLaNe\n7Z6W0kkdr6UyRWkKQ6ZN+ihKComi2GRjtouguWP+gpSixjDrWYFcMvN4W78O1M3gfmTCiOPZlB00\nyC65z2UTyEOUt2FoR8rxrpE9isNPD8k9BS3BbCd8fQ6DWMLrRVdrYqhHnmEn2r1F0E6yHc/ebLRi\nYyacwotmMp2065/G+BahIYom5Qwa9GMoAmMCCcQe93W5mkx2kpx8UiqlNLVsRZOi8eoGlJcutHUu\n53VrNnrxFAdTmuAKngY+QPLv24t2pI1hrgArkMtIO9oKnkGTM+r+NbblOMHV34IIU0Zf4wz2yjJe\n6xNoAC4gG/Ewb9ez6DoE67cgNoJ2dWZn1+O+bolGqnNhTRZloR8VRzmKtMkBFHHxBiqqHcEbaJb6\nI4JXh9dSWUbQnHE14e6D0NKNHHz9eOazXiSIp6p/ihXEashlYRtquniN4BW7FTkmZkiOxuhH27FC\nuidYqk8U2f/tbqFymAXvDhK2AAsw+RxevYwlPA051VneGFiBXBYukmynbUF2YCOY40gYn0FC2Nhj\ndyMzRr4OtnyIoCaSQZ7vPvfxek1mqBUb1E9H8U6SM0brARMOuhfFIxsF5RxSdN5Cc+ZK4LsbCWuy\nKDstyFP8MFrpTZzyGTTwDuE5Ll7HmzhdlCccqZXMsc77qY9IAEvxbCd7YaowYRzdCVQDZhjtIE+7\n9yMo/tgkfXTS6DqkFchlowU59nqAe1CX7CfBOQlt70BmjRFk1gjSUPdTnlC3ddK73hpOU1+ak6Vw\nrlA/dtU2FCIKmh+fAd6HNw8OoO9jdpqmuFDj0tjLTVUZQHGSbwKnwOmAlmPgvA6jJ+CqCW5fBX6f\n9FTPs2iARrA25Xqgg0Ys/1hdEug37AE+ghSJz6C50YFMFe1ITEVQ5EVjzw2rIZeNaTSA3DWuLQ67\nViERh8nnofPPoTMOPI8GYlDq8mEk1O1lCT/309wZj0ZIFoqDxn47RNuh8xK0PA78EXS2oM7STwGP\nu7cfRwkjh2iUbLxsWA25LDhocg6hrdcdWJ+CO6/BsY/BsQR0vgdiMfh0FCIdEH8ImRD8TrbXgWN4\nTsByESW540ILjVKMpXY8V+sTqDFHUEREvr30TLpzJ/AAtPbAkZNwXwu8EFfpih95gvbPf431yfsh\ncQaZKl5GDr2bNLp2DFYVKwMOysZ7AgnjCYg8BXwH8JOwmIAvAE8kaH98U6+7619KKPMzJMe3Okgo\nl0sYG+fh4yRrcw/iZQ2GkUrU+ahm7ZBm4CyFNTYdQMrGEvAqbK7BxRfgReCGQ/snThJ9V4yfvfIs\nvfu/Ac4KUliedd9zL1J4GhsrkEtiD9pK3Qa+BsRh7Ofg208gzfclaHXgKAw9PsP0+waBr+NpxH+A\nzBSmJ9/9lC8BoRV40v3/GZI14hcIb3aT+U3Lzb0oAsFSG2aRgO0FHoLeTviBx6AdOn9sjZUPdPHr\nP/HrfGr8F+k7d4jowZeAjwLfjUwYNyits3V9YE0WJZFa53gKbv43mF+Cd/0YvO8heBp2/OFt/mLn\n97Pt3dPIfuYgrTWBNAAT+P4q5YsR3gS+WabPqial1I7Oxlls/HUYcBWVxXtp/8bv8MFze/nByGf5\nrbZf5m7Os/fIeVadTvg3/wx+5Szc/Lr7nnvRvJlGSswSjZgcYjXkkjA1hnfwtkMu8RjsvAc+5sD7\nWuAfQ2t0iwfXz/DTf/dxoEW+v/gLwLdI7tp7jPwdF9tQDzJDL14IkaEebW7+us3l/lxLOIgDCdav\nx/jWvZ1871e/wEvOg5xzjvIvI/+epb8aZuu5Tth+P7R3IWF8G8+UdwnZrxsPqyGXhUm0tj0KtMLt\nKKNfucmPf+Q/0X1old/+xm/w/u/8O8795Qntxi89h8J9TOWqE0hKnyfY2bYPOeX8RYemSU7lXUJa\nYKkccM+tmtrHfhQfXc8dOJqRI0hI5op7HkLmonPId3ECiELvO5j8xcc5Pvo67Yl5nr74nbzv4N+x\nut4Fmw5cPwvrH0a7ppt4i+o+1Oqp8YSyFchlIY5KbI7Djvvgh3qY+u4W/vjTP0fkvyfYuKudlxcf\nY+tXW2D2eUgcR95jw3kkkDJpcTcDnouTrAGbtjilcj3LeVSKGzU4pqU0jpC5U8dOZJozqc7zeD4L\nBykXL8NqL/HPvpdrV/cQbRtl66OtfPGHPszaqQ45wx+9G15ohdmnSe5PmSm5qv6xJouiGCO5NRNI\nsz0HM/8JTn2JrVfXmf6NSSb/Rxv82Z+w9UcRmHgJNk0VuPvw0pjXyTzA9uJpGGO+x4dRq3RDN9ra\nZeN+crdu2iQ5RK4a1OKY5eABKpeK7s9iCyOp1df8TJG8w0qtrREHVqFjDd67BZ9+ga1PvQo/9ClW\nnCg/+uefpq9vDq63w/pfo7niH/v1Ol5yYwVyUUyR7PEd5u3U580xeLUd/vAs3F6BtShM9MAr/wWi\nK/BrD0LLCvBZlLV3DGUlZcJ0TTA3QzTlfaagUTZ8ZQ2bikolFbxF5QTDpvv5laSbZD+EwUGhkdnE\nwxpeQ4ZUNsmcor+CTA3/GJYPwP/7Z9B3N/QdgQtjcCnCl//XWZZb43Dts7B6Dgn3NaSANHYZVCuQ\nC2YMaQXrvscWkcliGZiCtXa4OYlMEW4w/No1iL0Kn70M8Vfdz4ig7ddBMgvT6+5n3yZZ65ghuSj6\nMirwbYgizQJks4ugbWNjbvWycxv9PoXShbbmmahk5bwElQ9NXCO4GUICuExup/Bl0mPmdyCTRSZi\n6Hp8C2JdcOUWtPfBZB/QC+fh9vMOsZvA8gAkWlG43CwS5A8B70V1YRoPa0MumFnSB2o3clb46yFf\nQEK2HRUb+hYk5uD8LLKHJdBkb0ECdwMJ5m5ke1twP3vV/bvD/dvjfuYNJDD2ua+PIc3kiHvsGF4I\nWapd+AjacjZLLYZihDHomjSe48gjRmahP5fhcT8rAY+ZcTuMzHpzaF7ge/wxlC21AvHvgxunYSUB\nvAarPcAmrJ1HCsc6GuMT7nuvu8coRyf28GEFcsEEDcJVkreum2jQrAN/6T52D54GexTZkU066Sya\nHH1oAAcJSjMAE0jQj6HoDiNoO1FSxQKeUDYOlxn3+G+6x5kk/632MDKVNF7MZ262sL0E/RxCDubV\nLK8xzyXQmFlPeX4Zjf0oMj+8BMuzaE7sQCnpG8Ap5DdpQ+bBURTq+RYSzo2JNVmUhTU8gbmEhPa7\n0WB8A8VNDiPN+hyyQSfwQoZiyAY9iQZ8kP1tBQndXrzW6+1I+H4ACeglJNRnkObt325P4wnvWTyB\nvAdp3cYUk8oq4c3qS+UI9atjmN1OGHDQAp6abu4fN7kwtYsdJGz3uI+vIVNHDI1JE6F0Ds2RGfex\nWeTUvA9p2mtoHi3QyNTr6A0xG0gziCCBuQuZFC6j5JFMjU6X0GDLVq943f3cVffWgYTzKhrA82gC\nDCHtw6/dTWb4zGWk0S9nOHbQjiCszFOfyTCgsTJEOLpiJAjeGRRSY2UdXYsNJMQHSDZdxJAgTqAx\n24+3gzO8hjc+Z0jWtre7jzdWWy2rIZeF3chxZlhCDr04Emhxgh1L+/G81FPkLh6/hC7ZNvf+GrKz\nvY60jS00QLe5r51ALXDuwtN29vmOOYaE+ToylWTbihbKQcpfnrIdhQFm4g71K5BXqFzaeD5E0Xg0\n3ELC8gDF6W0rSKivkVloxvFs9Mu+YxreQL6OINPHOo0YMWQFclnYJFiYbeINuDjpmWjZkkEyESP7\ntnEDaeN30GRaJ3kwb/qO6f9/O+kV4EzR/WIYo/zDK0HtO5446HctN+tk3sVUg0y/7S70fQuNt+7D\ni4RYRgpJtmObaI995LeQ+5NNGgcrkMvCHTKbIvyYZo5GW71J4XGsi2Tfpm3hCf4ttE30ZzbdxHOW\nTOA5EIMWBn9diVFkC8wXE/lRCP1kjzPdIPvErhZh1MK341UNzEQPyeFi7Ugr3oWuVarCsBevg02h\nioN/7KyixaaD7CFxEM7ftnpYgVx1cq3+2/BikocorG5xK96Aj6PtXhARJGD9iSb+STeANJx5POFv\nivDny1UKn1wO4a9bnKC2dt4xgq9Dtt+uFy10PUgAj/jeE8ETA60oJM0QQZrrOMUpDkHlMnNd32s0\nc/MEK5CrSgJ5irNpG614lyVKYUIwgrSk0ZTHHyH5Upu4ZP9j5rgDSItPzWy7RebmqeViDs9x1EX5\nsrKGyZ4NGUQ7nq0+TJjyrX5G0OLZTrCW3ILG0jL6jY35wUQuGNt1hGQFYNx93ghIs7MqljVsAans\nWIEcOm6iiTOAtIxC4mDXkeDc73vMQRPJXOrtaHJeIzne+bZ7vDaSQ926qU2n39TU8FLooHDHVD6p\n6JUmgpcQZLhMurbagdf1fIR0oTyHTAaLwEUyx5SvA/+Q5Xw6ySwy+tBYSaWDRk93LidWIIeWLnJr\nI+2ka7JbJJdDTKAge6Pl9KLLPoQ0pQH3cwwTaFFoRRMsVesKOmYECQIj/POlDy+2OlWILFC+ZJQb\nFO4AWiGzyadamHCwXCwhB+0t968ZNztIF+j5EnQdr5A5u7OT4AW0jdy2bYvBCuTQcpPc2nE76dpr\nDG37HbRVB09YgjKdNpBQbUUTPlXwG+dPt/tZfkdaG9rK+wVFi3ssh8JqDPSiSdxN8KQN+n7NRIzk\n+iTgdSUfxNP6+/EW1VtII+5GpqdM18M8H4S5jmYM5SMmMjU8XSC4XoYlCCuQQ08XmbfuC6RrcVE8\nE4WxJZv4zgG8S27inq+QXhfgNoptDkpRXXTf6w/92sSLuz5L/qFyc0gTvU1wkfNOmme7G0WLj+le\nnkkz3uG+ZhsSllHSr2EXGgOX0XUMYhg46X5W6rESeC2vzPEs1cAK5NAziDTJfFlHaagxvMm4F2k7\nY3ha1SjJpopC2CLZBGCcgf3ucfaQ39AaJnsUyRzhyFyrBr2oVkQbul5jJJss+tFvfA4tgBdI1oz9\nDKHrs0jmxXwWjY/h/7+9c4/Nqj7j+OehF0ortNBaaLkJdBMUwQuKzjGibtklxl2SZZtLtkxjNM5l\nWbK4bMmy/WNMFrcZtzizGC9L5uYuWWK2OHWiQ1RUbgoD5FIQ2tJyKdcWKJTf/njOj/O+p+dt35fS\nntP3fT7JCS3vufzO6Xm/5znP77kwcBLYHw9UmIsvASOtmCCnnnaGnzDwPmq9/o8w+H8bOnlYTeET\nXn5yyFOOZuZdhlpV/nhRqgkny8pR677YOgn7cyyUs+jf4ySwARXCMsIJ2rkMzH6M+xtWEWbITUMf\n6JUMFObj6MTuFPTtJhMJjmXyMNpYLYuiwdfOKCT9uQr1I0b91ZXk3xKqDLXu1uWx7iz0AXMZ6qbw\nD5pcx/Nhf9G02TQzC72ehRbBOc5A19FZ9OEGofhGqUILAXWhbxTNhNZtO+qumoreG1H3Vg9qcUdx\nZLcYM0YLewQWDdXoK28hzEG/tF6MK1DrdQZDx+D6B0AtcDv5hahtRUXnNNmhW03BErUPagmzxYYT\n/zqabCVejCvIPj//ppDPeQmhvzfKXCifAjIH7T5zGFgTLD5KpYvkI0aMfDBBLhpOUHjixhayxWMW\n2ifuJPEB/OMIRaWGsOvwn1Ex8FQS79usQMWllWyL3PuJo77MQ2hK+iS0QBLB9mkS57ixZCb3eJrJ\nDkFrQK/1YCU3M/d9OsexNkNjLUzoAN5l6A7QRpoxQTYy2Am8TXz8r6BWsxfG42h5RFCxWJux3k2o\nRRe1eBegPs3LGRg9sYfsjLHMW/MI6lMFtSoX5nU2o8NiwodPGWH93+j5fUR2+FcXeq1z1UCpQq8h\nqAthdXCsmCI/HX+H3tbCh26kDhNkI08aUZGJ8zlG6UettWhG2Qdo9EAng0/mTSW3+6UXnfSKI1PI\no6J+oQy1j/cIfdyLUH/6YMV4JLJEP8v82Sfz+HNZTehnt69uMWJ/VSNPushPjB2wCriR+JKNG9HX\n98F81PvIbTnWEFqOUW4ClqHW5bXBz/lkuuViUrCffFmPuoA2kbuY+0w0gmEa2R2fJ6MuDND5gEVo\nO6My9DyWke1Dvo7CCk8ZYwETZGMUWEJ2nYNNqCDnk2ZdT+iiaALuDLZfGrPuW8AbaMjX2uDn4fTE\nO0boihmPCn4c15N/evAe1Ie+jzDcbAoq1N7y70XfMECt5DeCZSnhQ24NOm+wGI1PvpJi7cRcSljY\nm5En3mURjVnNxduELov1ZJdUdKi1PVSN3UuDZUvweyfwLBpLvSZm/RvQW3otKsq59j8XFfc9ZLcV\n8kxGXSubMvZxmlAkoxRq17jIv779lkMfXFcHx/Pn6GO6M91AfttNwefHKLxmsZE2TJCNPDlIYT3V\nMv3HcfVt86mVfAgVq4moQGYmtsTtsxyN240WwPlysN076Hl8hE4gRvfRgFqr24lvM9+Piu9S1J/r\nBXAdg9cL9p1bcpWedBlj6UX90pXom8V69EFDMP64Mfl9GGMdc1kYeXKOwoqU38fwy2dORsXsGCqS\nNWgXYk8Z6i7wrCW+qtsrwOuExfb7UYGeRtgNuREN46tAxS3XuZ5DRTJTAM9Efp9PdpRFG2Err6Hw\nrZR6UH97f3C89ZR6N41SwATZGCH+hlqFi8hPmGegk32ZHCHsPNKHxke3oyK8mOx6HZC7NOQJVOCi\nFvF+wkp23YRhd7XohFsN2fHVccfJDHvz7CI7vjs6iTmVweOPQYXZR2+cCpZrsZfa4sb+usYIMQMV\nVF/ucygOEFqZl6KTZNG+fOeCfW4ltBZ7g3+vRu2Ljail24omutSgdTcadNv6K6GvBo6vJ7RaG9GH\nRgf6lTiDPghOo+IKajkvQEP3MtkRc37RVO9Osi3obkJbyL8FHGfovozbKOX2RqWACbIxQvjWP3H1\nF+LIFLFcHYWrUbEFFc1M67gVjd09Syim7ahbw5f4bIZjneCOEk6e+Tq+vibHbNS63Y/GQnuRHEd8\n1b18zi8q0D6WeB46wRgXsx1H8XVZNrIxQTZGiEKL62TiLc46NOStAngNFTafZu0tZEH9yhtRK3QB\nYWjYdlTE5gATYeECOLwJ2oOa0ZMuA7kejq5DLeHJhAV6ysmdsbiQ7AiM+cH2XnjnoCI/1DXYH4xv\nOKF5RjFhgmykmJOo5etf7/sJJ+Y8DrWEvTh2ogI5nvO3d/1C6BHY1wOneqC2BW5fBAuq4ZXd8N+9\nqKXbFywngn99pEUlasluCY7TQbYLootsC/cQuf3ZmcRVeDNKGRNkI2XUoxZuJ9mhYr4Lxu7I+r6P\nXzcqkg2otXqO86VIe4/A2Wror4dln4TayVz5+b30dx9m685xwT4moEI+kXByb0pwPP8gaAiOE037\n9g+JOcG4h/N2YJQyIyLIIjIb+ClwKxpb1A78EXjIOWftB4xBOEV8HeazxFuTDhVEb7EeRaMkxqHC\n2AQndwFT4XQVi249zO03/oljTTX8a+NyaGyCtmZCF0MbocD6AvG7UfdCXNjZPNRnfTOaZFJIaKBh\nZDNSFvJ81Oy4B51mXwg8iZo5D47QMY2iINckWR+5CxJlNmHdj1qq+1HLth4VzFNwTRVnl1Sy4IYP\nWHdiCe1TroBPVKkh3dYExz9EXSR+f5WEHbbPEd9jsCf47CBh12fDuDBGJA7ZOfeSc+5u59yrzrnd\nzrl/Ao8AXxmJ4xnGQMajt3c7cDnMWwTLZtHY3MPJ8eM5XFXL1bPWcs3ytRpy3H8YFe5MQe1DJ/lm\nDth7SCcq/JsIQ/AM48IYzcSQOgrLvTWMC6QNNXsd1E6HipnQPwPqqjm2bTI7d7bQXNPGojnrKJvQ\nB/vaoHcH8YXlM9OaDWNkGRVBFpEW4AHgidE4nlHqtKPhcX3AOK2i2bEZ5AB7J8zkLXczU+hm+ek3\naNjcDZ0Opl+CTg76msTj0Yy6M+SuQWEYF5eCfMgi8jDwo0FWccAC59y2jG2mAy8CzzvnnsrvSP9m\nYLrtQrLrGBjGYDQCR+DoXqibCdIHq/bTdMshaDnHmp4buK5vAzU9XVA9EerKoX0loZ84s12VYeTL\nRga2UssnBFIp9I57BHh6iHXO95IRkWZgBbDKOXdv/of5HFoe0TAulAlo1MR4OLIFaIIV0PPV8ZRP\nrmDt6Zm8fuBWjh52UH8EOg6h/mKPr5thGIVwFQMNx33A7/PauiBBds4dYvDeO+cJLOMVaC3Buwo5\njmEMH5/R14ZGXeyCyn46d8+lvXUq067qYMnxNbTvmc36M5dA6xpUkGuxzDkjKUYqDrkZrXe4Cw1z\naxRR35xzLt86hIYxTOrQsLTpwFk4spGe5ypg4TQOLG6koaGbSd17Wf/ObFSML0W9bibIRjKMlJPs\nM2iu6VzClgyC3u1luTYyjItLPToptyr4fRp82AWLNtDDfJ55827Ytgp4Fa1j4Qiz9Axj9BmpOORn\nnXNlkWWcc87E2BhFdqJ2QB0a0tYC9MFfX4ZHV8GZffAxP+FymFCMy7EGokYS2DSyUeQ0oeLailrK\nVcAkWLkJVnYQb5P4uhk7Rm2UhgFF1zFkY9IDSDGlem22o+2PjqKxxfPQzhtT0Sy7DtR63pqxzTFM\njDMp1XsnHy7utSkyQY7G/xkhdm10cq8GTXEW9AWxHK1/9SE6vVGZ2OjSi907ubm418ZcFkYJsYew\nLdQs1Ep2qF3Si07sTWboVkqGMTKYIBslxBzUdbEfFWePr4l8MFgMIxlMkI0SItPy9TUrHOqyqB79\n4RhGhLQJclDA4kKtlFPE90Ez7NpEmY7WMd4XLIew65MLu3dyk8+1Oa9n0QI9AxDn3FDrjBoicifa\nWcQwDKPY+KZz7rnBVkibINcDn0V75uRfIskwDCO9VKG9wF4K6gHlJFWCbBiGUcoUWRyyYRjG2MUE\n2TAMIyWYIBuGYaQEE2TDMIyUYIJsGIaREopOkEVktog8KSKtItIrIttF5OciUpH02NKCiPxERN4U\nkR4R6U56PEkiIt8VkV0iclJEVovI9UmPKQ2IyDIReUFE2kXknIjckfSY0oKI/FhE3hWRYyLSJSL/\nEJGPX4x9F50gA/PRvNh7gCuAHwD3AQ8lOaiUUQH8Bfhd0gNJEhH5GvBL4GfANcD7wEsi0pDowNJB\nDbABuB/NLzdClgG/AZYCn0a/Ty+LyITh7rgk4pBF5IfAfc65lqTHkiZE5NvAr51zU5IeSxKIyGrg\nHefc94PfBW059phz7heJDi5FiMg54EvOuReSHksaCR7g+4FPOedWDbX+YBSjhRxHHVDSr+ZGNoEL\n6zq0oR4ATq2T/wA3JTUuY0xSh75FDFtjil6QRaQFeAB4IumxGKmiAa1IH+2C3oWWfzOMIQneqh4F\nVjnnNg93f2NGkEXk4WByIdfSH3Wsi8h04EXgeefcU8mMfHS4kOtjGMaweRydq/r6xdhZ2spvDsYj\nwNNDrNPqfxCRZmAF+uS6dyQHlhIKuj4GB9HWIVMj/++b7RnGoIjIb4EvAMuccxelPumYEeSgStKg\nlZI8gWW8AngPuGskx5UWCrk+BjjnzojIWuA24AU4//p5G/BYkmMz0k8gxl8Eljvn9gy1fr6MGUHO\nl8Ayfh3YBTwINOr3DJxzUX9hSSIiM4EpwGygTEQWBx/tcM71JDeyUedXwDOBML+LhkhWA88kOag0\nICI1QAtha5W5wX3S7Zzbm9zIkkdEHge+AdwB9IiIf8s66pwbVtngogt7C0K5ov5iQSfRyxIYUuoQ\nkaeBb8V8dItzbuVojydJROR+9ME9FY27/Z5zbk2yo0oeEVkOvMbAGORnnXMl8daZiyAMME44v+Oc\n+8Ow9l1sgmwYhjFWGTNRFoZhGMWOCbJhGEZKMEE2DMNICSbIhmEYKcEE2TAMIyWYIBuGYaQEE2TD\nMIyUYIJsGIaREkyQDcMwUoIJsmEYRkowQTYMw0gJ/we+/dkjz6MdMgAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x10bd22e90>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"array([[ 1.82214439, 0.29000503],\n",
" [-0.79505074, 1.56814873],\n",
" [ 1.76158881, 0.54698807],\n",
" ..., \n",
" [-0.93795604, -1.46007335],\n",
" [-1.44670177, 1.46519935],\n",
" [-1.31411076, -1.46986461]])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"num_gen_examples = 5000\n",
"# round to an entire multiple of BATCH\n",
"num_gen_examples = (num_gen_examples / BATCH ) * BATCH\n",
"x_generated_values = np.zeros((num_gen_examples, 2))\n",
"\n",
"for batch_idx in range(num_gen_examples / BATCH):\n",
" numeric_in = dict(\n",
" z_rand = np.random.normal(size=(BATCH, SEED_DIM)).astype(np.float32),)\n",
" x_generated_batch = generate(numeric_in)\n",
" x_generated_values[batch_idx * BATCH: (batch_idx+1) * BATCH] = x_generated_batch\n",
"\n",
"\n",
"heatmap, xedges, yedges = np.histogram2d(x_generated_values[:, 0], \n",
" x_generated_values[:, 1], bins=300)\n",
"\n",
"plt.clf()\n",
"plt.imshow(heatmap, extent=extent_tr, origin='lower')\n",
"plt.show()\n",
"\n",
"x_generated_values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment