Skip to content

Instantly share code, notes, and snippets.

@jessegrabowski
Created September 16, 2023 23:14
Show Gist options
  • Save jessegrabowski/a56921e8ca45badebd3dfdae246023b9 to your computer and use it in GitHub Desktop.
Save jessegrabowski/a56921e8ca45badebd3dfdae246023b9 to your computer and use it in GitHub Desktop.
Pytensor rewrite speed test
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "ab0c4387-f492-4e79-85a5-aaf06d8d8600",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"env: TF_CPP_MIN_LOG_LEVEL=0\n"
]
}
],
"source": [
"import jax\n",
"import numpy as np\n",
"import pytensor\n",
"import pytensor.tensor as pt\n",
"import pymc as pm\n",
"from pytensor.tensor.nlinalg import matrix_dot\n",
"import sys\n",
"from warnings import catch_warnings, simplefilter\n",
"import matplotlib.pyplot as plt\n",
"\n",
"sys.path.append('../pymc-experimental/')\n",
"from pymc_experimental.statespace import structural as st\n",
"from pymc_experimental.statespace.filters.distributions import LinearGaussianStateSpace\n",
"\n",
"from pytensor.compile.mode import JAX, FAST_RUN\n",
"\n",
"MVN_CONST = pt.log(2 * pt.constant(np.pi, dtype=\"float64\"))"
]
},
{
"cell_type": "markdown",
"id": "d73c008c-4c15-4a6f-8c8f-b0afa3cfc978",
"metadata": {},
"source": [
"# Data Generation Function"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "6e2d691e-8d40-4aec-a7e8-47338e3e5461",
"metadata": {},
"outputs": [],
"source": [
"n_timesteps = pt.iscalar('n_timesteps')\n",
"n_seasonal = pt.iscalar('n_seasonal')\n",
"# data = pt.matrix('data', shape=(None, 1))\n",
"\n",
"c = pt.zeros((1 + n_seasonal,))\n",
"d = pt.zeros((1,))\n",
"\n",
"T_trend = pt.as_tensor_variable([[1., 1.], [0., 1.]])\n",
"T_season = pt.set_subtensor(pt.eye(n_seasonal-1, k=-1)[0], -1)\n",
"T = st.block_diagonal([T_trend, T_season])\n",
"\n",
"Z_trend = pt.as_tensor_variable([[1., 0.]])\n",
"Z_season = pt.set_subtensor(pt.zeros((1, n_seasonal-1))[0, 0], 1)\n",
"Z = pt.concatenate([Z_trend, Z_season], axis=-1)\n",
"\n",
"R = pt.concatenate([pt.eye(3), pt.zeros((n_seasonal-2, 3))])\n",
"H = pt.zeros((1, 1))\n",
"Q = pt.zeros((3, 3))\n",
"\n",
"with pm.Model():\n",
" initial_trend = pm.Normal('initial_trend', sigma=[0.1, 1e-4], shape=(2,))\n",
" sigma_trend = pm.Exponential('sigma_trend', 1, shape=(2,))\n",
" seasonal_coefs = pm.Normal('seasonal', sigma=50, shape=(n_seasonal-1,))\n",
" sigma_seasonal = pm.Exponential('sigma_seasonal', 1, shape=(1, ))\n",
" sigma_MeasurementError = pm.Exponential('sigma_MeasurementError', 1)\n",
"\n",
" P0_diag = pm.Exponential('P0_diag', 1, shape=(1 + n_seasonal, ))\n",
" P0 = pm.Deterministic('P0', pt.diag(P0_diag))\n",
"\n",
" x0 = pt.concatenate([initial_trend, seasonal_coefs])\n",
" Q = pt.set_subtensor(Q[np.diag_indices(3)], pt.concatenate([sigma_trend, sigma_seasonal]))\n",
" H = pt.set_subtensor(H[0, 0], sigma_MeasurementError)\n",
" trajectory = LinearGaussianStateSpace('traj', x0, P0, c, d, T, Z, R, H, Q, steps=n_timesteps)\n",
"\n",
"f_trajectory = pm.compile_pymc([n_seasonal, n_timesteps], [trajectory[1][:, -1, None], x0, P0, c, d, T, Z, R, H, Q])"
]
},
{
"cell_type": "markdown",
"id": "a9022e7a-cb8d-4672-814b-bb0fc45c4337",
"metadata": {},
"source": [
"## Test Function\n",
"\n",
"It's a stripped down kalman filter. KF is a good test linear algebra test function, because it has it all: solve, dot and det. I'm not obsessed, you're obsessed -_-"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1e4bc807-8814-4e9d-8b0e-dcd644c45984",
"metadata": {},
"outputs": [],
"source": [
"def predict(a, P, c, T, R, Q):\n",
" a_hat = T.dot(a) + c\n",
" P_hat = matrix_dot(T, P, T.T) + matrix_dot(R, Q, R.T)\n",
" \n",
" return a_hat, P_hat\n",
"\n",
"def update(y, a, P, d, T, Z, H):\n",
" y_hat = d + Z.dot(a)\n",
" v = y - y_hat\n",
"\n",
" PZT = P.dot(Z.T)\n",
" F = Z.dot(PZT) + H\n",
"\n",
" F_inv = pt.linalg.solve(F, pt.identity_like(F), assume_a=\"pos\", check_finite=False)\n",
"\n",
" K = PZT.dot(F_inv)\n",
" I_KZ = pt.eye(Z.shape[1]) - K.dot(Z)\n",
"\n",
" a_filtered = a + K.dot(v)\n",
" P_filtered = matrix_dot(I_KZ, P, I_KZ.T) + matrix_dot(K, H, K.T)\n",
"\n",
" inner_term = matrix_dot(v.T, F_inv, v)\n",
" F_logdet = pt.log(pt.linalg.det(F))\n",
"\n",
" ll = -0.5 * (MVN_CONST + F_logdet + inner_term).ravel()[0]\n",
" \n",
" return a_filtered, P_filtered, ll\n",
"\n",
"def kalman_step(y, a, P, c, d, T, Z, R, H, Q):\n",
" a_filtered, P_filtered, ll = update(y, a, P, d, T, Z, H)\n",
" \n",
" a_hat, P_hat = predict(a=a_filtered, P=P_filtered, c=c, T=T, R=R, Q=Q)\n",
"\n",
" return a_filtered, a_hat, P_filtered, P_hat, ll\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "160853dd-5a88-405d-ad94-6dc6787e9cb2",
"metadata": {},
"outputs": [],
"source": [
"data = pt.matrix(name=\"data\")\n",
"a0 = pt.vector(name=\"a0\")\n",
"P0 = pt.matrix(name=\"P0\")\n",
"c = pt.vector(name=\"c\")\n",
"d = pt.vector(name=\"d\")\n",
"Q = pt.matrix(name=\"Q\")\n",
"H = pt.matrix(name=\"H\")\n",
"T = pt.matrix(name=\"T\")\n",
"R = pt.matrix(name=\"R\")\n",
"Z = pt.matrix(name=\"Z\")\n",
"\n",
"inputs = [data, a0, P0, c, d, T, Z, R, H, Q]\n",
"\n",
"filter_result, updates = pytensor.scan(\n",
" kalman_step,\n",
" sequences=[data],\n",
" outputs_info=[a0, None, P0, None, None],\n",
" non_sequences=[c, d, T, Z, R, H, Q],\n",
" name=\"forward_kalman_pass\",\n",
" )\n",
"\n",
"f = pytensor.function(inputs, filter_result)\n",
"\n",
"FAST_RUN._optimizer.exclude = FAST_RUN._optimizer.exclude.union(JAX._optimizer.exclude)\n",
"f2 = pytensor.function(inputs, filter_result, mode=FAST_RUN)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "3d75b6ed-389d-479d-acd5-fa371e816f0a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Subtensor{start:stop:step} [id A] 27\n",
" ├─ Scan{forward_kalman_pass, while_loop=False, inplace=all}.0 [id B] 26\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ data [id D]\n",
" │ ├─ Subtensor{start:stop:step} [id E] 25\n",
" │ │ ├─ data [id D]\n",
" │ │ ├─ ScalarFromTensor [id F] 24\n",
" │ │ │ └─ Composite{switch(le(i0, i1), i1, i2)} [id G] 23\n",
" │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ 0 [id H]\n",
" │ │ │ └─ 0 [id I]\n",
" │ │ ├─ ScalarFromTensor [id J] 22\n",
" │ │ │ └─ Shape_i{0} [id C] 0\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id K]\n",
" │ ├─ SetSubtensor{:stop} [id L] 21\n",
" │ │ ├─ AllocEmpty{dtype='float64'} [id M] 20\n",
" │ │ │ ├─ Composite{...}.5 [id N] 1\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ └─ ···\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 2 [id Q]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 2 [id Q]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id O]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ ├─ 1 [id P]\n",
" │ │ │ │ └─ 1 [id O]\n",
" │ │ │ └─ Shape_i{0} [id R] 19\n",
" │ │ │ └─ a0 [id S]\n",
" │ │ ├─ Unbroadcast{0} [id T] 18\n",
" │ │ │ └─ ExpandDims{axis=0} [id U] 17\n",
" │ │ │ └─ a0 [id S]\n",
" │ │ └─ 1 [id V]\n",
" │ ├─ SetSubtensor{:stop} [id W] 16\n",
" │ │ ├─ AllocEmpty{dtype='float64'} [id X] 15\n",
" │ │ │ ├─ Composite{...}.4 [id N] 1\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ Shape_i{0} [id Y] 14\n",
" │ │ │ │ └─ P0 [id Z]\n",
" │ │ │ └─ Shape_i{1} [id BA] 13\n",
" │ │ │ └─ P0 [id Z]\n",
" │ │ ├─ Unbroadcast{0} [id BB] 12\n",
" │ │ │ └─ ExpandDims{axis=0} [id BC] 11\n",
" │ │ │ └─ P0 [id Z]\n",
" │ │ └─ 1 [id V]\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ c [id BD]\n",
" │ ├─ d [id BE]\n",
" │ ├─ T [id BF]\n",
" │ ├─ Z [id BG]\n",
" │ ├─ H [id BH]\n",
" │ ├─ Transpose{axes=[1, 0]} [id BI] 10\n",
" │ │ └─ Z [id BG]\n",
" │ ├─ Eye{dtype='float64'} [id BJ] 9\n",
" │ │ ├─ Shape_i{1} [id BK] 8\n",
" │ │ │ └─ Z [id BG]\n",
" │ │ ├─ Shape_i{1} [id BK] 8\n",
" │ │ │ └─ ···\n",
" │ │ └─ 0 [id H]\n",
" │ ├─ Dot22 [id BL] 7\n",
" │ │ ├─ Dot22 [id BM] 6\n",
" │ │ │ ├─ R [id BN]\n",
" │ │ │ └─ Q [id BO]\n",
" │ │ └─ Transpose{axes=[1, 0]} [id BP] 5\n",
" │ │ └─ R [id BN]\n",
" │ └─ Transpose{axes=[1, 0]} [id BQ] 4\n",
" │ └─ T [id BF]\n",
" ├─ ScalarFromTensor [id BR] 3\n",
" │ └─ Composite{...}.3 [id N] 1\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id BS] 2\n",
" │ └─ Composite{...}.0 [id N] 1\n",
" │ └─ ···\n",
" └─ 1 [id K]\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=all}.2 [id B] 26\n",
" └─ ···\n",
"Subtensor{start:stop:step} [id BT] 30\n",
" ├─ Scan{forward_kalman_pass, while_loop=False, inplace=all}.1 [id B] 26\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id BU] 29\n",
" │ └─ Composite{...}.2 [id N] 1\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id BV] 28\n",
" │ └─ Composite{...}.1 [id N] 1\n",
" │ └─ ···\n",
" └─ 1 [id K]\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=all}.3 [id B] 26\n",
" └─ ···\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=all}.4 [id B] 26\n",
" └─ ···\n",
"\n",
"Inner graphs:\n",
"\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=all} [id B]\n",
" ← CGemv{no_inplace} [id BW]\n",
" ├─ *1-<Vector(float64, shape=(?,))> [id BX] -> [id L]\n",
" ├─ 1.0 [id BY]\n",
" ├─ Dot22 [id BZ]\n",
" │ ├─ Dot22 [id CA]\n",
" │ │ ├─ *2-<Matrix(float64, shape=(?, ?))> [id CB] -> [id W]\n",
" │ │ └─ *8-<Matrix(float64, shape=(?, ?))> [id CC] -> [id BI]\n",
" │ └─ Solve{assume_a='pos', lower=False, check_finite=False, b_ndim=2} [id CD]\n",
" │ ├─ Gemm{no_inplace} [id CE]\n",
" │ │ ├─ *7-<Matrix(float64, shape=(?, ?))> [id CF] -> [id BH]\n",
" │ │ ├─ 1.0 [id BY]\n",
" │ │ ├─ *6-<Matrix(float64, shape=(?, ?))> [id CG] -> [id BG]\n",
" │ │ ├─ Dot22 [id CA]\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1.0 [id BY]\n",
" │ └─ Eye{dtype='float64'} [id CH]\n",
" │ ├─ Assert{msg=Could not broadcast dimensions. Broadcasting is only allowed along axes that have a statically known length 1. Use `specify_broadcastable` to inform PyTensor of a known shape.} [id CI]\n",
" │ │ ├─ Shape_i{0} [id CJ]\n",
" │ │ │ └─ *7-<Matrix(float64, shape=(?, ?))> [id CF] -> [id BH]\n",
" │ │ └─ Eq [id CK]\n",
" │ │ ├─ Shape_i{0} [id CJ]\n",
" │ │ │ └─ ···\n",
" │ │ └─ Shape_i{0} [id CL]\n",
" │ │ └─ *6-<Matrix(float64, shape=(?, ?))> [id CG] -> [id BG]\n",
" │ ├─ Assert{msg=Could not broadcast dimensions. Broadcasting is only allowed along axes that have a statically known length 1. Use `specify_broadcastable` to inform PyTensor of a known shape.} [id CM]\n",
" │ │ ├─ Shape_i{1} [id CN]\n",
" │ │ │ └─ *7-<Matrix(float64, shape=(?, ?))> [id CF] -> [id BH]\n",
" │ │ └─ Eq [id CO]\n",
" │ │ ├─ Shape_i{1} [id CN]\n",
" │ │ │ └─ ···\n",
" │ │ └─ Shape_i{1} [id CP]\n",
" │ │ └─ *8-<Matrix(float64, shape=(?, ?))> [id CC] -> [id BI]\n",
" │ └─ 0 [id CQ]\n",
" ├─ Sub [id CR]\n",
" │ ├─ CGemv{no_inplace} [id CS]\n",
" │ │ ├─ *0-<Vector(float64, shape=(?,))> [id CT] -> [id E]\n",
" │ │ ├─ -1.0 [id CU]\n",
" │ │ ├─ *6-<Matrix(float64, shape=(?, ?))> [id CG] -> [id BG]\n",
" │ │ ├─ *1-<Vector(float64, shape=(?,))> [id BX] -> [id L]\n",
" │ │ └─ 1.0 [id BY]\n",
" │ └─ *4-<Vector(float64, shape=(?,))> [id CV] -> [id BE]\n",
" └─ 1.0 [id BY]\n",
" ← Gemm{no_inplace} [id CW]\n",
" ├─ Dot22 [id CX]\n",
" │ ├─ Dot22 [id CY]\n",
" │ │ ├─ Gemm{no_inplace} [id CZ]\n",
" │ │ │ ├─ *9-<Matrix(float64, shape=(?, ?))> [id DA] -> [id BJ]\n",
" │ │ │ ├─ -1.0 [id CU]\n",
" │ │ │ ├─ Dot22 [id BZ]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ *6-<Matrix(float64, shape=(?, ?))> [id CG] -> [id BG]\n",
" │ │ │ └─ 1.0 [id BY]\n",
" │ │ └─ *2-<Matrix(float64, shape=(?, ?))> [id CB] -> [id W]\n",
" │ └─ Transpose{axes=[1, 0]} [id DB]\n",
" │ └─ Gemm{no_inplace} [id CZ]\n",
" │ └─ ···\n",
" ├─ 1.0 [id BY]\n",
" ├─ Dot22 [id DC]\n",
" │ ├─ Dot22 [id BZ]\n",
" │ │ └─ ···\n",
" │ └─ *7-<Matrix(float64, shape=(?, ?))> [id CF] -> [id BH]\n",
" ├─ Dot22 [id DD]\n",
" │ ├─ Transpose{axes=[1, 0]} [id DE]\n",
" │ │ └─ Solve{assume_a='pos', lower=False, check_finite=False, b_ndim=2} [id CD]\n",
" │ │ └─ ···\n",
" │ └─ Dot22 [id DF]\n",
" │ ├─ Transpose{axes=[1, 0]} [id DG]\n",
" │ │ └─ *8-<Matrix(float64, shape=(?, ?))> [id CC] -> [id BI]\n",
" │ └─ Transpose{axes=[1, 0]} [id DH]\n",
" │ └─ *2-<Matrix(float64, shape=(?, ?))> [id CB] -> [id W]\n",
" └─ 1.0 [id BY]\n",
" ← CGemv{no_inplace} [id DI]\n",
" ├─ *3-<Vector(float64, shape=(?,))> [id DJ] -> [id BD]\n",
" ├─ 1.0 [id BY]\n",
" ├─ *5-<Matrix(float64, shape=(?, ?))> [id DK] -> [id BF]\n",
" ├─ CGemv{no_inplace} [id BW]\n",
" │ └─ ···\n",
" └─ 1.0 [id BY]\n",
" ← Gemm{no_inplace} [id DL]\n",
" ├─ *10-<Matrix(float64, shape=(?, ?))> [id DM] -> [id BL]\n",
" ├─ 1.0 [id BY]\n",
" ├─ Dot22 [id DN]\n",
" │ ├─ *5-<Matrix(float64, shape=(?, ?))> [id DK] -> [id BF]\n",
" │ └─ Gemm{no_inplace} [id CW]\n",
" │ └─ ···\n",
" ├─ *11-<Matrix(float64, shape=(?, ?))> [id DO] -> [id BQ]\n",
" └─ 1.0 [id BY]\n",
" ← Mul [id DP]\n",
" ├─ -0.5 [id DQ]\n",
" └─ DropDims{axis=0} [id DR]\n",
" └─ SpecifyShape [id DS]\n",
" ├─ Reshape{1} [id DT]\n",
" │ ├─ Composite{(i1 + log(i0) + i2)} [id DU]\n",
" │ │ ├─ Det [id DV]\n",
" │ │ │ └─ Gemm{no_inplace} [id CE]\n",
" │ │ │ └─ ···\n",
" │ │ ├─ 1.8378770664093453 [id DW]\n",
" │ │ └─ DropDims{axis=0} [id DX]\n",
" │ │ └─ CGemv{inplace} [id DY]\n",
" │ │ ├─ AllocEmpty{dtype='float64'} [id DZ]\n",
" │ │ │ └─ 1 [id EA]\n",
" │ │ ├─ 1.0 [id BY]\n",
" │ │ ├─ ExpandDims{axis=0} [id EB]\n",
" │ │ │ └─ Sub [id CR]\n",
" │ │ │ └─ ···\n",
" │ │ ├─ CGemv{inplace} [id EC]\n",
" │ │ │ ├─ AllocEmpty{dtype='float64'} [id ED]\n",
" │ │ │ │ └─ Assert{msg=Could not broadcast dimensions. Broadcasting is only allowed along axes that have a statically known length 1. Use `specify_broadcastable` to inform PyTensor of a known shape.} [id CM]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ 1.0 [id BY]\n",
" │ │ │ ├─ Transpose{axes=[1, 0]} [id DE]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ Sub [id CR]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ └─ 0.0 [id EE]\n",
" │ │ └─ 0.0 [id EE]\n",
" │ └─ [-1] [id EF]\n",
" └─ 1 [id EA]\n",
"\n",
"Composite{switch(le(i0, i1), i1, i2)} [id G]\n",
" ← Switch [id EG] 'o0'\n",
" ├─ LE [id EH]\n",
" │ ├─ i0 [id EI]\n",
" │ └─ i1 [id EJ]\n",
" ├─ i1 [id EJ]\n",
" └─ i2 [id EK]\n",
"\n",
"Composite{...} [id N]\n",
" ← add [id EL] 'o0'\n",
" ├─ sub [id EM]\n",
" │ ├─ sub [id EN] 't47'\n",
" │ │ ├─ add [id EO] 't9'\n",
" │ │ │ ├─ i0 [id EP]\n",
" │ │ │ └─ i1 [id EQ]\n",
" │ │ └─ i1 [id EQ]\n",
" │ └─ i8 [id ER]\n",
" └─ maximum [id ES] 't27'\n",
" ├─ add [id ET]\n",
" │ ├─ sub [id EU]\n",
" │ │ ├─ i1 [id EQ]\n",
" │ │ └─ Switch [id EV]\n",
" │ │ ├─ LT [id EW]\n",
" │ │ │ ├─ i2 [id EX]\n",
" │ │ │ └─ add [id EO] 't9'\n",
" │ │ │ └─ ···\n",
" │ │ ├─ i3 [id EY]\n",
" │ │ └─ add [id EO] 't9'\n",
" │ │ └─ ···\n",
" │ └─ i10 [id EZ]\n",
" └─ i11 [id FA]\n",
" ← add [id FB] 'o1'\n",
" ├─ sub [id FC]\n",
" │ ├─ sub [id EN] 't47'\n",
" │ │ └─ ···\n",
" │ └─ i9 [id FD]\n",
" └─ maximum [id FE] 't6'\n",
" ├─ add [id FF]\n",
" │ ├─ sub [id FG]\n",
" │ │ ├─ i1 [id EQ]\n",
" │ │ └─ Switch [id FH]\n",
" │ │ ├─ LT [id FI]\n",
" │ │ │ ├─ i17 [id FJ]\n",
" │ │ │ └─ add [id FK] 't25'\n",
" │ │ │ ├─ i1 [id EQ]\n",
" │ │ │ └─ i16 [id FL]\n",
" │ │ ├─ i15 [id FM]\n",
" │ │ └─ add [id FK] 't25'\n",
" │ │ └─ ···\n",
" │ └─ i14 [id FN]\n",
" └─ i13 [id FO]\n",
" ← add [id FP] 'o2'\n",
" ├─ sub [id FQ]\n",
" │ ├─ sub [id FR]\n",
" │ │ ├─ Switch [id FS]\n",
" │ │ │ ├─ LT [id FT]\n",
" │ │ │ │ ├─ i6 [id FU]\n",
" │ │ │ │ └─ add [id EO] 't9'\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ i7 [id FV]\n",
" │ │ │ └─ add [id EO] 't9'\n",
" │ │ │ └─ ···\n",
" │ │ └─ i1 [id EQ]\n",
" │ └─ i18 [id FW]\n",
" └─ maximum [id FE] 't6'\n",
" └─ ···\n",
" ← add [id FX] 'o3'\n",
" ├─ sub [id FY]\n",
" │ ├─ sub [id FZ]\n",
" │ │ ├─ Switch [id GA]\n",
" │ │ │ ├─ LT [id GB]\n",
" │ │ │ │ ├─ i4 [id GC]\n",
" │ │ │ │ └─ add [id EO] 't9'\n",
" │ │ │ │ └─ ···\n",
" │ │ │ ├─ i5 [id GD]\n",
" │ │ │ └─ add [id EO] 't9'\n",
" │ │ │ └─ ···\n",
" │ │ └─ i1 [id EQ]\n",
" │ └─ i12 [id GE]\n",
" └─ maximum [id ES] 't27'\n",
" └─ ···\n",
" ← add [id GF] 'o4'\n",
" ├─ Switch [id GG]\n",
" │ ├─ GT [id GH]\n",
" │ │ ├─ i20 [id GI]\n",
" │ │ └─ maximum [id FE] 't6'\n",
" │ │ └─ ···\n",
" │ ├─ add [id GJ]\n",
" │ │ ├─ maximum [id FE] 't6'\n",
" │ │ │ └─ ···\n",
" │ │ └─ i20 [id GI]\n",
" │ └─ sub [id GK]\n",
" │ ├─ maximum [id FE] 't6'\n",
" │ │ └─ ···\n",
" │ └─ i20 [id GI]\n",
" └─ i21 [id GL]\n",
" ← add [id GM] 'o5'\n",
" ├─ Switch [id GN]\n",
" │ ├─ GT [id GO]\n",
" │ │ ├─ i19 [id GP]\n",
" │ │ └─ maximum [id ES] 't27'\n",
" │ │ └─ ···\n",
" │ ├─ add [id GQ]\n",
" │ │ ├─ maximum [id ES] 't27'\n",
" │ │ │ └─ ···\n",
" │ │ └─ i19 [id GP]\n",
" │ └─ sub [id GR]\n",
" │ ├─ maximum [id ES] 't27'\n",
" │ │ └─ ···\n",
" │ └─ i19 [id GP]\n",
" └─ i21 [id GL]\n",
"\n",
"Composite{(i1 + log(i0) + i2)} [id DU]\n",
" ← add [id GS] 'o0'\n",
" ├─ i1 [id GT]\n",
" ├─ log [id GU]\n",
" │ └─ i0 [id GV]\n",
" └─ i2 [id GW]\n"
]
},
{
"data": {
"text/plain": [
"<ipykernel.iostream.OutStream at 0x7fdce6267490>"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pytensor.dprint(f)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "558d5171-55d0-479c-83a7-07d03dc5e3ab",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Subtensor{start:stop:step} [id A] 55\n",
" ├─ Scan{forward_kalman_pass, while_loop=False, inplace=none}.0 [id B] 54\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ data [id D]\n",
" │ ├─ Subtensor{start:stop:step} [id E] 53\n",
" │ │ ├─ data [id D]\n",
" │ │ ├─ ScalarFromTensor [id F] 52\n",
" │ │ │ └─ Switch [id G] 51\n",
" │ │ │ ├─ Le [id H] 50\n",
" │ │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ └─ ···\n",
" │ │ │ │ └─ 0 [id I]\n",
" │ │ │ ├─ 0 [id I]\n",
" │ │ │ └─ 0 [id J]\n",
" │ │ ├─ ScalarFromTensor [id K] 49\n",
" │ │ │ └─ Shape_i{0} [id C] 0\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id L]\n",
" │ ├─ SetSubtensor{:stop} [id M] 48\n",
" │ │ ├─ AllocEmpty{dtype='float64'} [id N] 47\n",
" │ │ │ ├─ Add [id O] 46\n",
" │ │ │ │ ├─ Switch [id P] 45\n",
" │ │ │ │ │ ├─ Gt [id Q] 44\n",
" │ │ │ │ │ │ ├─ 1 [id R]\n",
" │ │ │ │ │ │ └─ Maximum [id S] 6\n",
" │ │ │ │ │ │ ├─ Add [id T] 5\n",
" │ │ │ │ │ │ │ ├─ Sub [id U] 4\n",
" │ │ │ │ │ │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ │ └─ Switch [id V] 3\n",
" │ │ │ │ │ │ │ │ ├─ Lt [id W] 2\n",
" │ │ │ │ │ │ │ │ │ ├─ 1 [id X]\n",
" │ │ │ │ │ │ │ │ │ └─ Add [id Y] 1\n",
" │ │ │ │ │ │ │ │ │ ├─ 1 [id Z]\n",
" │ │ │ │ │ │ │ │ │ └─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ │ ├─ 1 [id X]\n",
" │ │ │ │ │ │ │ │ └─ Add [id Y] 1\n",
" │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ └─ 1 [id BA]\n",
" │ │ │ │ │ │ └─ 2 [id BB]\n",
" │ │ │ │ │ ├─ Add [id BC] 43\n",
" │ │ │ │ │ │ ├─ Maximum [id S] 6\n",
" │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ └─ 1 [id R]\n",
" │ │ │ │ │ └─ Sub [id BD] 42\n",
" │ │ │ │ │ ├─ Maximum [id S] 6\n",
" │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ └─ 1 [id R]\n",
" │ │ │ │ └─ 1 [id X]\n",
" │ │ │ └─ Shape_i{0} [id BE] 41\n",
" │ │ │ └─ a0 [id BF]\n",
" │ │ ├─ Unbroadcast{0} [id BG] 40\n",
" │ │ │ └─ ExpandDims{axis=0} [id BH] 39\n",
" │ │ │ └─ a0 [id BF]\n",
" │ │ └─ 1 [id BI]\n",
" │ ├─ SetSubtensor{:stop} [id BJ] 38\n",
" │ │ ├─ AllocEmpty{dtype='float64'} [id BK] 37\n",
" │ │ │ ├─ Add [id BL] 36\n",
" │ │ │ │ ├─ Switch [id BM] 35\n",
" │ │ │ │ │ ├─ Gt [id BN] 34\n",
" │ │ │ │ │ │ ├─ 1 [id BO]\n",
" │ │ │ │ │ │ └─ Maximum [id BP] 31\n",
" │ │ │ │ │ │ ├─ Add [id BQ] 30\n",
" │ │ │ │ │ │ │ ├─ Sub [id BR] 29\n",
" │ │ │ │ │ │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ │ └─ Switch [id BS] 28\n",
" │ │ │ │ │ │ │ │ ├─ Lt [id BT] 27\n",
" │ │ │ │ │ │ │ │ │ ├─ 1 [id X]\n",
" │ │ │ │ │ │ │ │ │ └─ Add [id BU] 26\n",
" │ │ │ │ │ │ │ │ │ ├─ Shape_i{0} [id C] 0\n",
" │ │ │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ │ │ └─ 1 [id BV]\n",
" │ │ │ │ │ │ │ │ ├─ 1 [id X]\n",
" │ │ │ │ │ │ │ │ └─ Add [id BU] 26\n",
" │ │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ │ └─ 1 [id BW]\n",
" │ │ │ │ │ │ └─ 2 [id BB]\n",
" │ │ │ │ │ ├─ Add [id BX] 33\n",
" │ │ │ │ │ │ ├─ Maximum [id BP] 31\n",
" │ │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ │ └─ 1 [id BO]\n",
" │ │ │ │ │ └─ Sub [id BY] 32\n",
" │ │ │ │ │ ├─ Maximum [id BP] 31\n",
" │ │ │ │ │ │ └─ ···\n",
" │ │ │ │ │ └─ 1 [id BO]\n",
" │ │ │ │ └─ 1 [id X]\n",
" │ │ │ ├─ Shape_i{0} [id BZ] 25\n",
" │ │ │ │ └─ P0 [id CA]\n",
" │ │ │ └─ Shape_i{1} [id CB] 24\n",
" │ │ │ └─ P0 [id CA]\n",
" │ │ ├─ Unbroadcast{0} [id CC] 23\n",
" │ │ │ └─ ExpandDims{axis=0} [id CD] 22\n",
" │ │ │ └─ P0 [id CA]\n",
" │ │ └─ 1 [id BI]\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ Shape_i{0} [id C] 0\n",
" │ │ └─ ···\n",
" │ ├─ c [id CE]\n",
" │ ├─ d [id CF]\n",
" │ ├─ T [id CG]\n",
" │ ├─ Z [id CH]\n",
" │ ├─ H [id CI]\n",
" │ ├─ Transpose{axes=[1, 0]} [id CJ] 21\n",
" │ │ └─ Z [id CH]\n",
" │ ├─ Eye{dtype='float64'} [id CK] 20\n",
" │ │ ├─ Shape_i{1} [id CL] 19\n",
" │ │ │ └─ Z [id CH]\n",
" │ │ ├─ Shape_i{1} [id CL] 19\n",
" │ │ │ └─ ···\n",
" │ │ └─ 0 [id I]\n",
" │ ├─ dot [id CM] 18\n",
" │ │ ├─ dot [id CN] 17\n",
" │ │ │ ├─ R [id CO]\n",
" │ │ │ └─ Q [id CP]\n",
" │ │ └─ Transpose{axes=[1, 0]} [id CQ] 16\n",
" │ │ └─ R [id CO]\n",
" │ └─ Transpose{axes=[1, 0]} [id CR] 15\n",
" │ └─ T [id CG]\n",
" ├─ ScalarFromTensor [id CS] 14\n",
" │ └─ Add [id CT] 13\n",
" │ ├─ Sub [id CU] 12\n",
" │ │ ├─ Sub [id CV] 11\n",
" │ │ │ ├─ Switch [id V] 3\n",
" │ │ │ │ └─ ···\n",
" │ │ │ └─ Shape_i{0} [id C] 0\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id CW]\n",
" │ └─ Maximum [id S] 6\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id CX] 10\n",
" │ └─ Add [id CY] 9\n",
" │ ├─ Sub [id CZ] 8\n",
" │ │ ├─ Sub [id DA] 7\n",
" │ │ │ ├─ Add [id Y] 1\n",
" │ │ │ │ └─ ···\n",
" │ │ │ └─ Shape_i{0} [id C] 0\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id DB]\n",
" │ └─ Maximum [id S] 6\n",
" │ └─ ···\n",
" └─ 1 [id L]\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=none}.2 [id B] 54\n",
" └─ ···\n",
"Subtensor{start:stop:step} [id DC] 62\n",
" ├─ Scan{forward_kalman_pass, while_loop=False, inplace=none}.1 [id B] 54\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id DD] 61\n",
" │ └─ Add [id DE] 60\n",
" │ ├─ Sub [id DF] 59\n",
" │ │ ├─ Sub [id CV] 11\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id DG]\n",
" │ └─ Maximum [id BP] 31\n",
" │ └─ ···\n",
" ├─ ScalarFromTensor [id DH] 58\n",
" │ └─ Add [id DI] 57\n",
" │ ├─ Sub [id DJ] 56\n",
" │ │ ├─ Sub [id DA] 7\n",
" │ │ │ └─ ···\n",
" │ │ └─ 1 [id DK]\n",
" │ └─ Maximum [id BP] 31\n",
" │ └─ ···\n",
" └─ 1 [id L]\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=none}.3 [id B] 54\n",
" └─ ···\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=none}.4 [id B] 54\n",
" └─ ···\n",
"\n",
"Inner graphs:\n",
"\n",
"Scan{forward_kalman_pass, while_loop=False, inplace=none} [id B]\n",
" ← Add [id DL]\n",
" ├─ *1-<Vector(float64, shape=(?,))> [id DM] -> [id M]\n",
" └─ dot [id DN]\n",
" ├─ dot [id DO]\n",
" │ ├─ dot [id DP]\n",
" │ │ ├─ *2-<Matrix(float64, shape=(?, ?))> [id DQ] -> [id BJ]\n",
" │ │ └─ *8-<Matrix(float64, shape=(?, ?))> [id DR] -> [id CJ]\n",
" │ └─ Solve{assume_a='pos', lower=False, check_finite=False, b_ndim=2} [id DS]\n",
" │ ├─ Add [id DT]\n",
" │ │ ├─ dot [id DU]\n",
" │ │ │ ├─ *6-<Matrix(float64, shape=(?, ?))> [id DV] -> [id CH]\n",
" │ │ │ └─ dot [id DP]\n",
" │ │ │ └─ ···\n",
" │ │ └─ *7-<Matrix(float64, shape=(?, ?))> [id DW] -> [id CI]\n",
" │ └─ Eye{dtype='float64'} [id DX]\n",
" │ ├─ Assert{msg=Could not broadcast dimensions. Broadcasting is only allowed along axes that have a statically known length 1. Use `specify_broadcastable` to inform PyTensor of a known shape.} [id DY]\n",
" │ │ ├─ Shape_i{0} [id DZ]\n",
" │ │ │ └─ *7-<Matrix(float64, shape=(?, ?))> [id DW] -> [id CI]\n",
" │ │ └─ Eq [id EA]\n",
" │ │ ├─ Shape_i{0} [id DZ]\n",
" │ │ │ └─ ···\n",
" │ │ └─ Shape_i{0} [id EB]\n",
" │ │ └─ *6-<Matrix(float64, shape=(?, ?))> [id DV] -> [id CH]\n",
" │ ├─ Assert{msg=Could not broadcast dimensions. Broadcasting is only allowed along axes that have a statically known length 1. Use `specify_broadcastable` to inform PyTensor of a known shape.} [id EC]\n",
" │ │ ├─ Shape_i{1} [id ED]\n",
" │ │ │ └─ *7-<Matrix(float64, shape=(?, ?))> [id DW] -> [id CI]\n",
" │ │ └─ Eq [id EE]\n",
" │ │ ├─ Shape_i{1} [id ED]\n",
" │ │ │ └─ ···\n",
" │ │ └─ Shape_i{1} [id EF]\n",
" │ │ └─ *8-<Matrix(float64, shape=(?, ?))> [id DR] -> [id CJ]\n",
" │ └─ 0 [id EG]\n",
" └─ Sub [id EH]\n",
" ├─ *0-<Vector(float64, shape=(?,))> [id EI] -> [id E]\n",
" └─ Add [id EJ]\n",
" ├─ *4-<Vector(float64, shape=(?,))> [id EK] -> [id CF]\n",
" └─ dot [id EL]\n",
" ├─ *6-<Matrix(float64, shape=(?, ?))> [id DV] -> [id CH]\n",
" └─ *1-<Vector(float64, shape=(?,))> [id DM] -> [id M]\n",
" ← Add [id EM]\n",
" ├─ dot [id EN]\n",
" │ ├─ dot [id EO]\n",
" │ │ ├─ Sub [id EP]\n",
" │ │ │ ├─ *9-<Matrix(float64, shape=(?, ?))> [id EQ] -> [id CK]\n",
" │ │ │ └─ dot [id ER]\n",
" │ │ │ ├─ dot [id DO]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ └─ *6-<Matrix(float64, shape=(?, ?))> [id DV] -> [id CH]\n",
" │ │ └─ *2-<Matrix(float64, shape=(?, ?))> [id DQ] -> [id BJ]\n",
" │ └─ Transpose{axes=[1, 0]} [id ES]\n",
" │ └─ Sub [id EP]\n",
" │ └─ ···\n",
" └─ dot [id ET]\n",
" ├─ dot [id EU]\n",
" │ ├─ dot [id DO]\n",
" │ │ └─ ···\n",
" │ └─ *7-<Matrix(float64, shape=(?, ?))> [id DW] -> [id CI]\n",
" └─ dot [id EV]\n",
" ├─ Transpose{axes=[1, 0]} [id EW]\n",
" │ └─ Solve{assume_a='pos', lower=False, check_finite=False, b_ndim=2} [id DS]\n",
" │ └─ ···\n",
" └─ dot [id EX]\n",
" ├─ Transpose{axes=[1, 0]} [id EY]\n",
" │ └─ *8-<Matrix(float64, shape=(?, ?))> [id DR] -> [id CJ]\n",
" └─ Transpose{axes=[1, 0]} [id EZ]\n",
" └─ *2-<Matrix(float64, shape=(?, ?))> [id DQ] -> [id BJ]\n",
" ← Add [id FA]\n",
" ├─ dot [id FB]\n",
" │ ├─ *5-<Matrix(float64, shape=(?, ?))> [id FC] -> [id CG]\n",
" │ └─ Add [id DL]\n",
" │ └─ ···\n",
" └─ *3-<Vector(float64, shape=(?,))> [id FD] -> [id CE]\n",
" ← Add [id FE]\n",
" ├─ dot [id FF]\n",
" │ ├─ dot [id FG]\n",
" │ │ ├─ *5-<Matrix(float64, shape=(?, ?))> [id FC] -> [id CG]\n",
" │ │ └─ Add [id EM]\n",
" │ │ └─ ···\n",
" │ └─ *11-<Matrix(float64, shape=(?, ?))> [id FH] -> [id CR]\n",
" └─ *10-<Matrix(float64, shape=(?, ?))> [id FI] -> [id CM]\n",
" ← Mul [id FJ]\n",
" ├─ -0.5 [id FK]\n",
" └─ DropDims{axis=0} [id FL]\n",
" └─ SpecifyShape [id FM]\n",
" ├─ Reshape{1} [id FN]\n",
" │ ├─ Add [id FO]\n",
" │ │ ├─ 1.8378770664093453 [id FP]\n",
" │ │ ├─ Log [id FQ]\n",
" │ │ │ └─ Det [id FR]\n",
" │ │ │ └─ Add [id DT]\n",
" │ │ │ └─ ···\n",
" │ │ └─ dot [id FS]\n",
" │ │ ├─ dot [id FT]\n",
" │ │ │ ├─ Sub [id EH]\n",
" │ │ │ │ └─ ···\n",
" │ │ │ └─ Solve{assume_a='pos', lower=False, check_finite=False, b_ndim=2} [id DS]\n",
" │ │ │ └─ ···\n",
" │ │ └─ Sub [id EH]\n",
" │ │ └─ ···\n",
" │ └─ [-1] [id FU]\n",
" └─ 1 [id FV]\n"
]
},
{
"data": {
"text/plain": [
"<ipykernel.iostream.OutStream at 0x7fdce6267490>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pytensor.dprint(f2)"
]
},
{
"cell_type": "markdown",
"id": "643554b7-abdd-47d9-9444-62924184e6ba",
"metadata": {},
"source": [
"# Tests"
]
},
{
"cell_type": "markdown",
"id": "283f6448-d122-4270-b704-c4b3f14d1cd9",
"metadata": {},
"source": [
"## Performance over time series length"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c65828fe-839b-4765-ab64-2c316746ba1c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.87 ms ± 75.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"8.72 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"11.5 ms ± 234 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"14.5 ms ± 377 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"19 ms ± 196 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"23.7 ms ± 152 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"31.2 ms ± 385 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"40.6 ms ± 1.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"52.2 ms ± 519 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"71.6 ms ± 2.67 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"91.1 ms ± 540 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"115 ms ± 2.75 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"152 ms ± 6.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"190 ms ± 2.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"243 ms ± 3.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"311 ms ± 5.78 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"404 ms ± 5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"515 ms ± 5.33 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"663 ms ± 4.46 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"877 ms ± 25.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
"source": [
"time_steps = np.logspace(2, 4, 10)\n",
"results = []\n",
"\n",
"for T in time_steps:\n",
" inputs_np = f_trajectory(12, int(T))\n",
" \n",
" res_now = %timeit -o f(*inputs_np)\n",
" res_PR = %timeit -o f2(*inputs_np)\n",
" results.append((res_now, res_PR))\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "f56a6cc8-6052-4da2-9619-cd4b9d8fe9da",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABIQAAAGHCAYAAADBfok/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACUGklEQVR4nOzdeXiU5dn+8e/MZF9mQhKyBxJWCWFHFJBNXHDDtdJatdZXW237WsS2am1FrLu2tf21UNvXYq2tS7VaF4qiCOKKrBKCIhAIZCFAyEz2Zeb5/fEkMxkmQIAkk+X8HEcOmue5Z+aaQJCcve77shiGYSAiIiIiIiIiIn2GNdgFiIiIiIiIiIhI11IgJCIiIiIiIiLSxygQEhERERERERHpYxQIiYiIiIiIiIj0MQqERERERERERET6GAVCIiIiIiIiIiJ9jAIhEREREREREZE+RoGQiIiIiIiIiEgfo0BIRERERERERKSPUSAkIiLSgz3zzDNYLBbWrVvnd/3gwYNMnDiRmJgYVqxYcULPed9992GxWDqyzC7TUntbH3/4wx9YtWoVFouFVatWBTymtcWLF/PMM890ae2NjY089dRTnH766cTHxxMVFcXAgQO59NJLefXVV7u0lhO1e/duLBbLMb9mWVlZR/29af3RUV/3hx56iNdee61DnktERKQ3Cgl2ASIiItKx9u3bx7nnnsv+/ft59913OfPMM4NdUpdbvnw5DofD71p2djaRkZF88skn5OTkHPPxixcvJjExkRtuuKETq/R33XXX8e9//5v58+ezaNEiwsPD2bVrF8uXL+ftt9/m8ssv77JaOsOrr75KfX299/P/+7//4+mnnw74vRo8eHCHvN5DDz3EVVddxWWXXdYhzyciItLbKBASERHpRb7++mvOOeccGhsbWb16NaNGjQp2SUExYcIEEhMT27wXrIDMMAzq6uqIjIwMuFdQUMCLL77Ivffey6JFi7zXZ8+ezc0334zH4+nKUjvFuHHj/D5fvnw5cOzfKxEREek82jImIiLSS2zatImzzjqLkJAQPvzww4Aw6MUXX+S8884jNTWVyMhIRowYwV133UV1dfVxnzsrK4uLL76YN998k3Hjxnkf/+abbwLm1rURI0YQHR3NpEmTArawrVu3jm9+85tkZWURGRlJVlYW3/rWt9izZ4/fupYtcO+//z633noriYmJJCQkcMUVV1BcXHyKXyHa3DLW1nvdunUrq1ev9m5jysrK8t53uVz85Cc/ITs7m7CwMNLT05k/f37A19FisfCjH/2IP/3pT4wYMYLw8HD+9re/tfmahw4dAiA1NbXN+1ar759sLe/hueeeY8GCBaSkpBAZGcmMGTPYuHFjwGPXrVvH3LlziY+PJyIignHjxvHSSy8FrCstLeX73/8+GRkZhIWFkZ2dzaJFi2hqavJbV1xczNVXX01sbCwOh4N58+ZRWlra9hfzBBmGweLFixk7diyRkZH069ePq666il27dvmt27hxIxdffDFJSUmEh4eTlpbGRRddxL59+wDza19dXc3f/vY37+/hzJkzAaipqfH+/kVERBAfH8/EiRN5/vnnO+Q9iIiI9BTqEBIREekFPvzwQ+677z4yMzN555132gwWvv76ay688ELmz59PdHQ0X375JY8++ihr165l5cqVx32NzZs3c/fdd3PPPffgcDhYtGgRV1xxBXfffTfvvfceDz30EBaLhTvvvJOLL76YgoICbzfM7t27GT58ON/85jeJj4+npKSEJUuWcPrpp5Ofnx/QIXLTTTdx0UUX8c9//pO9e/fy05/+lGuvvbZddQK43W6/IMNisWCz2dr12FdffZWrrroKh8PB4sWLAQgPDwfMMGHGjBns27ePn//854wePZqtW7dy7733smXLFt59912/84hee+011qxZw7333ktKSgpJSUltvuaIESOIi4tj0aJFWK1WzjvvPL8Qqi0///nPGT9+PP/3f/+H0+nkvvvuY+bMmWzcuJFBgwYB8P777zNnzhzOOOMM/vSnP+FwOHjhhReYN28eNTU13i1xpaWlTJo0CavVyr333svgwYP55JNPeOCBB9i9ezdLly4FoLa2lnPOOYfi4mIefvhhhg0bxltvvcW8efPa9bU9nu9///s888wz3HbbbTz66KOUl5dz//33M2XKFDZv3kxycjLV1dWce+65ZGdn88c//pHk5GRKS0t5//33qaysBOCTTz7h7LPPZtasWfzyl78EwG63A7BgwQL+/ve/88ADDzBu3Diqq6vJy8vzhnIiIiJ9hiEiIiI91tKlSw3AAAyHw2GUlZW163Eej8dobGw0Vq9ebQDG5s2bvfcWLlxoHPlPhIEDBxqRkZHGvn37vNc2bdpkAEZqaqpRXV3tvf7aa68ZgPH6668f9fWbmpqMqqoqIzo62vjd734X8H5+8IMf+K1/7LHHDMAoKSk55vtqqf3Ij/T0dMMwDOP99983AOP9998/5vsdOXKkMWPGjIDnf/jhhw2r1Wp8/vnnftdffvllAzCWLVvmvdbye1JeXn7Mmlu89dZbRmJiorfmhIQE4xvf+EbA17HlPYwfP97weDze67t37zZCQ0ONm266yXvttNNOM8aNG2c0Njb6PcfFF19spKamGm632zAMw/j+979vxMTEGHv27PFb98QTTxiAsXXrVsMwDGPJkiUGYPznP//xW3fzzTcbgLF06dJ2vVfD8H3dDxw4YBiGYXzyyScGYPz617/2W7d3714jMjLS+NnPfmYYhmGsW7fOAIzXXnvtmM8fHR1tfOc73wm4npuba1x22WXtrlNERKS30pYxERGRXmDu3Lk4nU7mz5+P2+1uc82uXbu45pprSElJwWazERoayowZMwDYtm3bcV9j7NixpKenez8fMWIEADNnziQqKirgeuvtYFVVVdx5550MGTKEkJAQQkJCiImJobq6us3Xnjt3rt/no0ePDnjOY3n33Xf5/PPPvR/Lli1r1+OO58033yQ3N5exY8fS1NTk/Tj//PPb3Ip29tln069fv3Y994UXXkhhYSGvvvoqP/nJTxg5ciSvvfYac+fO5Uc/+lHA+muuucavG2ngwIFMmTKF999/H4AdO3bw5Zdf8u1vfxvAr94LL7yQkpISvvrqK+/7mjVrFmlpaX7rLrjgAgBWr14NmB1HsbGxAb8/11xzTbve47G8+eabWCwWrr32Wr8aUlJSGDNmjPdrO2TIEPr168edd97Jn/70J/Lz80/odSZNmsR///tf7rrrLlatWkVtbe0p1y4iItITacuYiIhIL/DLX/6SsWPHcv/99+PxeHjuuef8tkhVVVUxbdo0IiIieOCBBxg2bBhRUVHs3buXK664ol0/FMfHx/t9HhYWdszrdXV13mvXXHMN7733Hr/85S85/fTTsdvtWCwWLrzwwjZfOyEhwe/zli1b7f3hfcyYMZ1yUPH+/fvZsWMHoaGhbd4/ePCg3+dHOxPoaCIjI7nsssu8k7EKCwu54IIL+OMf/8itt97KyJEjvWtTUlICHp+SksLmzZu9tQL85Cc/4Sc/+ckx692/fz9vvPHGcd/XoUOHSE5ObvN1T9X+/fsxDKPN5we82+AcDgerV6/mwQcf5Oc//zmHDx8mNTWVm2++mV/84hdHfQ8tfv/735ORkcGLL77Io48+SkREBOeffz6PP/44Q4cOPeX3ISIi0lMoEBIREeklFi1ahMViYdGiRXg8Hv7xj38QEmL+p37lypUUFxezatUqb1cQQEVFRafX5XQ6efPNN1m4cCF33XWX93p9fT3l5eWd/vodKTExkcjISP76178e9X5rrTt4TsaAAQP43ve+x/z589m6datfINTWQc6lpaXeMK2llrvvvpsrrriizecfPny4d+3o0aN58MEH21yXlpYGmEHd2rVr23zdU5WYmIjFYmHNmjXeALC11tdGjRrFCy+8gGEYfPHFFzzzzDPcf//9REZG+v0Za0t0dDSLFi1i0aJF7N+/39stdMkll/Dll1+e8vsQERHpKRQIiYiI9CL33XcfVquVhQsXYhgG//znPwkJCfEGE0f+oP3UU091ek0WiwXDMAJe+//+7/+Our0t2MLDw9vsRrr44ot56KGHSEhIIDs7u8Ner7KyEovFQkxMTMC9li11LaFMi+eff54FCxZ4f2/37NnDxx9/zPXXXw+YYc/QoUPZvHkzDz300DFf/+KLL2bZsmUMHjz4mFvcZs2axUsvvcTrr7/ut23sn//8Z/ve6HFqeOSRRygqKuLqq69u12MsFgtjxozht7/9Lc888wwbNmzw3jva72FrycnJ3HDDDWzevJknn3ySmpoav+2PIiIivZkCIRERkV7m3nvvxWq18stf/hLDMHj++eeZMmUK/fr145ZbbmHhwoWEhobyj3/8w7u9qDPZ7XamT5/O448/TmJiIllZWaxevZqnn36auLi4Tn/9k9HSgfLiiy8yaNAgIiIiGDVqFPPnz+eVV15h+vTp3H777YwePRqPx0NhYSHvvPMOd9xxB2ecccYJv95XX33F+eefzze/+U1mzJhBamoqhw8f5q233uLPf/4zM2fOZMqUKX6PKSsr4/LLL+fmm2/G6XSycOFCIiIiuPvuu71rnnrqKS644ALOP/98brjhBtLT0ykvL2fbtm1s2LCBf/3rXwDcf//9rFixgilTpnDbbbcxfPhw6urq2L17N8uWLeNPf/oTGRkZXH/99fz2t7/l+uuv58EHH2To0KEsW7aMt99++9S+4MDUqVP53ve+x3e/+13WrVvH9OnTiY6OpqSkhA8//JBRo0Zx66238uabb7J48WIuu+wyBg0ahGEY/Pvf/6aiooJzzz3X+3yjRo1i1apVvPHGG6SmphIbG8vw4cM544wzuPjiixk9ejT9+vVj27Zt/P3vf2fy5MkKg0REpE9RICQiItIL/eIXv8BqtXLPPffg8Xh44YUXeOutt7jjjju49tpriY6O5tJLL+XFF19k/PjxnV7PP//5T3784x/zs5/9jKamJqZOncqKFSu46KKLOv21T8aiRYsoKSnh5ptvprKykoEDB7J7926io6NZs2YNjzzyCH/+858pKCggMjKSAQMGcM455xx3VPzRDBkyhAULFrBy5Ur+85//cODAAUJDQxk6dCgPPPAACxYswGr1nwXy0EMP8fnnn/Pd734Xl8vFpEmTeOGFFxg8eLB3zaxZs1i7di0PPvgg8+fP5/DhwyQkJJCTk+PXhZOamsq6dev41a9+xeOPP86+ffuIjY0lOzubOXPmeLuGoqKiWLlyJT/+8Y+56667sFgsnHfeebzwwgsBgdXJeOqppzjzzDN56qmnWLx4MR6Ph7S0NKZOncqkSZMAGDp0KHFxcTz22GMUFxcTFhbG8OHDeeaZZ/jOd77jfa7f/e53/PCHP+Sb3/wmNTU1zJgxg1WrVnH22Wfz+uuv89vf/paamhrS09O5/vrrueeee065fhERkZ7EYhiGEewiRERERKR9Vq1axaxZs/jXv/7FVVddFexyREREpIfS2HkRERERERERkT5GgZCIiIiIiIiISB+jLWMiIiIiIiIiIn2MOoRERERERERERPoYBUIiIiIiIiIiIn2MAiERERERERERkT4mJNgFdDWPx0NxcTGxsbFYLJZglyMiIiIiIiIi0iEMw6CyspK0tDSs1mP3APW5QKi4uJjMzMxglyEiIiIiIiIi0in27t1LRkbGMdf0uUAoNjYWML84drs9yNWIiIiIiIiIiHQMl8tFZmamN/s4lj4XCLVsE7Pb7QqERERERERERKTXac8ROTpUWkRERERERESkj1EgJCIiIiIiIiLSxygQEhERERERERHpY/rcGULtYRgGTU1NuN3uYJcigs1mIyQkpF17QEVERERERETaQ4HQERoaGigpKaGmpibYpYh4RUVFkZqaSlhYWLBLERERERERkV5AgVArHo+HgoICbDYbaWlphIWFqStDgsowDBoaGjhw4AAFBQUMHToUq1U7PUVEREREROTUKBBqpaGhAY/HQ2ZmJlFRUcEuRwSAyMhIQkND2bNnDw0NDURERAS7JBEREREREenh1GrQBnVgSHejP5MiIiIiIiLSkfRTpoiIiIiIiIhIH6NASERERERERESkj1Eg1EncHoNPdh7iP5uK+GTnIdweI9glSQd55plniIuLC3YZIiIiIiIiIidNgVAnWJ5XwlmPruRbf/mUH7+wiW/95VPOenQly/NKOvV1S0tL+d///V8GDRpEeHg4mZmZXHLJJbz33nud+rqnymKx8Nprr7VrXctHTEwMY8aM4Zlnnun0+o40b948tm/f7v38vvvuY+zYsV1eh4iIiIiIiHSQhmq4z2F+NFQHu5ouoUCogy3PK+HW5zZQ4qzzu17qrOPW5zZ0Wii0e/duJkyYwMqVK3nsscfYsmULy5cvZ9asWfzwhz886ec1DIOmpqaA6w0NDadS7klbunQpJSUlbN68mXnz5vHd736Xt99+u8tev7GxkcjISJKSkrrsNUVEREREREQ6mgKh4zAMg5qGpnZ9VNY1svD1rbS1Oazl2n2v51NZ19iu5zOM9m8z+8EPfoDFYmHt2rVcddVVDBs2jJEjR7JgwQI+/fRTwAyNLBYLmzZt8j6uoqICi8XCqlWrAFi1ahUWi4W3336biRMnEh4ezpo1a5g5cyY/+tGPWLBgAYmJiZx77rkA5Ofnc+GFFxITE0NycjLXXXcdBw8e9D7/zJkzue222/jZz35GfHw8KSkp3Hfffd77WVlZAFx++eVYLBbv50cTFxdHSkoKgwcP5uc//znx8fG888473vtOp5Pvfe97JCUlYbfbOfvss9m8ebP3ns1mY/369ebviWEQHx/P6aef7n38888/T2pqqt/X66WXXmLmzJlERETw3HPP+W0Ze+aZZ1i0aBGbN2/2di+1dC0dqxaAzZs3M2vWLGJjY7Hb7UyYMIF169Yd8/2LiIiIiIiIdISQYBfQ3dU2usm5t2M6UAyg1FXHqPveOe5agPz7zycq7Pi/ReXl5SxfvpwHH3yQ6OjogPsnc97Nz372M5544gkGDRrkffzf/vY3br31Vj766CMMw6CkpIQZM2Zw880385vf/Iba2lruvPNOrr76alauXOl9rr/97W8sWLCAzz77jE8++YQbbriBqVOncu655/L555+TlJTE0qVLmTNnDjabrV31ud1uXnnlFcrLywkNDQXMgOeiiy4iPj6eZcuW4XA4eOqpp5g9ezbbt28nPj6esWPHsmrVKiZMmMAXX3wBwBdffIHL5cJut7Nq1SpmzJjh91p33nknv/71r1m6dCnh4eF+AdS8efPIy8tj+fLlvPvuuwA4HI521fLtb3+bcePGsWTJEmw2G5s2bfK+FxEREREREZHOpECoF9ixYweGYXDaaad12HPef//93i6gFkOGDOGxxx7zfn7vvfcyfvx4HnroIe+1v/71r2RmZrJ9+3aGDRsGwOjRo1m4cCEAQ4cO5Q9/+APvvfce5557Lv379wd8nT/H861vfQubzUZdXR1ut5v4+HhuuukmAN5//322bNlCWVkZ4eHhADzxxBO89tprvPzyy3zve99j5syZrFq1ijvuuINVq1Yxe/Zsdu3axYcffsiFF17IqlWruP322/1ec/78+VxxxRVt1hMZGUlMTAwhISF+9a9cufK4tRQWFvLTn/7U+/s2dOjQ475/ERERERERkY6gQOg4IkNt5N9/frvWri0o54alnx933TPfPZ1J2fHteu32aNlaZrFY2rW+PSZOnHjca+vXr+f9998nJiYmYO3OnTv9AqHWUlNTKSsrO6m6fvvb33LOOeewd+9eFixYwO23386QIUO89VRVVZGQkOD3mNraWnbu3AmYW9iefvppPB4Pq1evZvbs2QwYMIDVq1czfvx4tm/fHtAh1NbX4njaU8uCBQu46aab+Pvf/84555zDN77xDQYPHnzCryUiIiIiIiJyohQIHYfFYmnXti2AaUP7k+qIoNRZ1+Y5QhYgxRHBtKH9sVk7LrwZOnQoFouFbdu2cdlllx11ndVqHhnV+myixsbGNte2tfXsyGsej4dLLrmERx99NGBtyzk8QMA2KIvFgsfjOWqdx5KSksKQIUMYMmQI//rXvxg3bhwTJ04kJycHj8dDamqq9zyk1lq2vU2fPp3Kyko2bNjAmjVr+NWvfkVmZiYPPfQQY8eOJSkpiREjRhzzfbdHe2q57777uOaaa3jrrbf473//y8KFC3nhhRe4/PLLT/j1RERERERERE6EAqEOZLNaWHhJDrc+twEL+IVCLfHPwktyOjQMAoiPj+f888/nj3/8I7fddltAgFFRUUFcXJx3e1ZJSQnjxo0D8Dtg+kSNHz+eV155haysLEJCTv6PUmhoKG63+4QfN2TIEK688kruvvtu/vOf/zB+/HhKS0sJCQk56uHUDoeDsWPH8oc//AGLxUJOTg5paWls3LiRN998M6A7qD3CwsIC6m9PLQDDhg1j2LBh3H777XzrW99i6dKlCoRERERERESk02nKWAebk5vKkmvHk+KI8Lue4ohgybXjmZObepRHnprFixfjdruZNGkSr7zyCl9//TXbtm3j97//PZMnTwbM827OPPNMHnnkEfLz8/nggw/4xS9+cdKv+cMf/pDy8nK+9a1vsXbtWnbt2sU777zDjTfeeEIBT1ZWFu+99x6lpaUcPnz4hGq44447eOONN1i3bh3nnHMOkydP5rLLLuPtt99m9+7dfPzxx/ziF7/wm941c+ZMnnvuOWbMmIHFYqFfv37k5OTw4osvMnPmzBN6/Zb6CwoK2LRpEwcPHqS+vv64tdTW1vKjH/2IVatWsWfPHj766CM+//zzgO4kERERERERkc6gQKgTzMlN5cM7z+b5m8/kd98cy/M3n8mHd57daWEQQHZ2Nhs2bGDWrFnccccd5Obmcu655/Lee++xZMkS77q//vWvNDY2MnHiRH784x/zwAMPnPRrpqWl8dFHH+F2uzn//PPJzc3lxz/+MQ6Hw7s9rT1+/etfs2LFCjIzM72dS+01atQozjnnHO69914sFgvLli1j+vTp3HjjjQwbNoxvfvOb7N69m+TkZO9jZs2ahdvt9gt/ZsyYgdvtPqkOoSuvvJI5c+Ywa9Ys+vfvz/PPP3/cWmw2G4cOHeL6669n2LBhXH311VxwwQUsWrTohF9fRERERERE5ERZjNYHyvQBLpcLh8OB0+nEbrf73aurq6OgoIDs7GwiIiKO8gwiXU9/NkVERERERDpRnQseyTT/9zUvw5Czwdq+QU/dybEyjyOpQ0hERERERERE+q781+GPp/s+/+dV8GSueb0XUyAkIiIiIiIiIn1T/uvw0vVQWep/3VViXu/FoZACIRERERERERHpezxuWH4n/jPCWzRfW36Xua4XUiAkIiIiIiIiIn3Prg/AVXyMBQa4imDPx11WUlcKCXYBIiIiIiIiIiJd4tBO2LkSdrxn/toeVfs7t6YgUSAkIiIiIiIiIr1TnQsKPoCdzQHQ4d0n/hwxyR1eVnegQEhEREREREREegePG0o2wY6VZgC0by14mnz3raEw4EwYfDZkz4CXrjUPkG7zHCEL2NNg4JQuKr5rKRASERERERERkZ7LVezbBrZrFdSW+9+PHwxDZpshUNZZEB7ruzfnUXOaWABL8/1HwGrrrMqDSoGQiIiIiIiIiPQcjbXmQc87m7uAyvL974fbIXu6LwTql3X058qZC1c/C//9qf/oeXuaGQblzO2Ut9AdKBDqLB63+Qe0ar+533DglF6bKnaVZ555hvnz51NRURHsUkRERERERKSrGAYc+NJ3EPSej6CprtUCC6SPh8HNAVDGRLCFtv/5c+bCoJnwSKb5+TUvw5Cze/3P8Bo73xnyX4cnc+FvF8Mr/2P++mSueb2T3HDDDVgsFiwWC6GhoQwaNIif/OQnVFdXA7B7927vfYvFgsPh4Mwzz+SNN9447nO3flxMTAxjxozhmWee6bT3cjTz5s1j+/bt3s/vu+8+xo4d2+V1iIiIiIiISCerKYe8V+C1H8JvcmDxmfDOPebh0E11EJsG466Fq/4KP9sFN6+Es++BgZNPLAxq0Tr8yeobDR3qEOpo+a837z884kAqV4l5/epnO63lbM6cOSxdupTGxkbWrFnDTTfdRHV1NUuWLPGueffddxk5ciQVFRUsXryYK6+8kg0bNpCbm3vM5166dClz5syhurqaF198ke9+97ukpqZy/vnnd8p7OVJjYyORkZFERkZ2yeuJiIiIiIhIF3I3wr51vmlgRRvw+7k6JAIGTjU7gIbMhv6ngcUStHJ7A3UIHY9hQEN1+z7qXPDfn9H26eTN15bfaa5rz/MZbT3P0YWHh5OSkkJmZibXXHMN3/72t3nttdf81iQkJJCSksJpp53Ggw8+SGNjI++///5xnzsuLo6UlBQGDx7Mz3/+c+Lj43nnnXe8951OJ9/73vdISkrCbrdz9tlns3nzZu89m83G+vXrm7+kBvHx8Zx++unexz///POkpqYCvm6ml156iZkzZxIREcFzzz3HM888Q1xcHGBuH1u0aBGbN2/2di+1dC0dqxaAzZs3M2vWLGJjY7Hb7UyYMIF169ad0NdaRERERERETtHh3fD50/DCt+GxQbB0DnzwOBStBwxIyoHJP4Jr/w137obr/g1TfgRJIxQGdQB1CB1PYw08lNZBT2aYp5+37Es8np8XQ1j0Sb9aZGQkjY2Nbd5rbGzkL3/5CwChoe1vp3O73bzyyiuUl5d7H2cYBhdddBHx8fEsW7YMh8PBU089xezZs9m+fTvx8fGMHTuWVatWMWHCBL744gsAvvjiC1wuF3a7nVWrVjFjxgy/17rzzjv59a9/zdKlSwkPD/cLoObNm0deXh7Lly/n3XffBcDhcLSrlm9/+9uMGzeOJUuWYLPZ2LRp0wl9DUREREREROQk1FfB7jW+s4DKd/rfj4yHwbPMLqDBZ5sHO0unUSDUS61du5Z//vOfzJ492+/6lClTsFqt1NbW4vF4yMrK4uqrrz7u833rW9/CZrNRV1eH2+0mPj6em266CYD333+fLVu2UFZWRnh4OABPPPEEr732Gi+//DLf+973mDlzJqtWreKOO+5g1apVzJ49m127dvHhhx9y4YUXsmrVKm6//Xa/15w/fz5XXHFFm/VERkYSExNDSEgIKSkp3usrV648bi2FhYX89Kc/5bTTTgNg6NCh7fyqioiIiIiISLt5PFD6RfM2sPeh8FPwtGpasIZAxiTzAOfBZ0Pq2D5xdk93oUDoeEKjzE6d9tjzMfzjquOv+/bL5tSx9rz2CXjzzTeJiYmhqamJxsZGLr30Uv7f//t/fmtefPFFTjvtNLZv3878+fP505/+RHx8/HGf+7e//S3nnHMOe/fuZcGCBdx+++0MGTIEgPXr11NVVUVCQoLfY2pra9m500x8Z86cydNPP43H42H16tXMnj2bAQMGsHr1asaPH8/27dsDOoQmTpx4Qu+/vbUsWLCAm266ib///e+cc845fOMb32Dw4MEn/FoiIiIiIiJyhMr9zePgm0OgmoP+9/tl+aaBZU+HCHtQyhQFQsdnsbR/21ZLS5urhLbPEbKY9wd3zvi6WbNmsWTJEkJDQ0lLS2tzG1RmZiZDhw5l6NChxMTEcOWVV5Kfn09SUtIxnzslJYUhQ4YwZMgQ/vWvfzFu3DgmTpxITk4OHo+H1NRUVq1aFfC4ljN/pk+fTmVlJRs2bGDNmjX86le/IjMzk4ceeoixY8eSlJTEiBEj/B4bHX3i2+XaU8t9993HNddcw1tvvcV///tfFi5cyAsvvMDll19+wq8nIiIiIiLSpzXVQ+Envm1g+/P874fFmMFPyzawBP2f8d2FAqGOZLXBnEebp4xZ8A+Fmg+8mvNIp7XARUdHe7t22mPGjBnk5uby4IMP8rvf/a7djxsyZAhXXnkld999N//5z38YP348paWlhISEkJWV1eZjHA4HY8eO5Q9/+AMWi4WcnBzS0tLYuHEjb775ZkB3UHuEhYXhdrv9rrWnFoBhw4YxbNgwbr/9dr71rW+xdOlSBUIiIiIiIiLHYxhw8GvfNLDdH5pn77aWOtacBDb4bHNLWEhYUEqVY1Mg1NFy5pqj5ZffaR4g3cKeZoZBnTRy/mTdcccdfOMb3+BnP/sZ6enpJ/S4MWPGsG7dOs455xwmT57MZZddxqOPPsrw4cMpLi5m2bJlXHbZZd6tXzNnzuR3v/sdl19+ORaLhX79+pGTk8OLL77I73//+xOuPSsri4KCAjZt2kRGRgaxsbHHrWXkyJH89Kc/5aqrriI7O5t9+/bx+eefc+WVV57w64uIiIiIiPQJtYdh12rfNjDnXv/7Mcm+bWCDZ0F0YnDqlBOiQKgz5MyF0y4yzxSq2m9+cwyc0i0Px7r44ovJysriwQcfZPHixe1+3KhRozjnnHO49957WbZsGcuWLeOee+7hxhtv5MCBA6SkpDB9+nSSk5O9j5k1axa/+c1vmDlzpvfajBkz2LRp00l1CF155ZX8+9//ZtasWVRUVLB06VJuuOGGY9Zis9k4dOgQ119/Pfv37ycxMZErrriCRYsWnfDri4iIiIiI9EruJije4NsGVrQODI/vvi0cBk72hUDJI3v+GPiwaLjPGewqupTFMIy2DrvptVwuFw6HA6fTid3uf3hVXV0dBQUFZGdnExEREaQKRQLpz6aIiIiIiHSqir1mB9CO96BgNdQdEY4kDvdtAxs4FcJObAiSdI1jZR5HUoeQiIiIiIiISF/TUA27P/KdBXRwu//9iDgYNNN3GHRcZjCqlE6kQEhERERERESktzMMcwJYyzawwk/A3eC7b7FCxunNAdBsSB/fLY89kY4T9EBo8eLFPP7445SUlDBy5EiefPJJpk2bdtT1//jHP3jsscf4+uuvcTgczJkzhyeeeIKEhIQurFpERERERESkm6s6ALveN0OgXe+bZ9y25hgAQ5o7gLJnQGRcUMqU4AhqIPTiiy8yf/58Fi9ezNSpU3nqqae44IILyM/PZ8CAAQHrP/zwQ66//np++9vfcskll1BUVMQtt9zCTTfdxKuvvhqEdyAiIiIiIiLSTTQ1wN7PfNvASjb73w+NgqxpvrOAEob0/MOg5aQFNRD6zW9+w//8z/9w0003AfDkk0/y9ttvs2TJEh5++OGA9Z9++ilZWVncdtttAGRnZ/P973+fxx57rEPr6mPnbEsPoD+TIiIiIiISwDCgfJdvG9juNdBQ5b8mZZRvGtiAMyEkPDi1SrcTtECooaGB9evXc9ddd/ldP++88/j444/bfMyUKVO45557WLZsGRdccAFlZWW8/PLLXHTRRUd9nfr6eurr672fu1yuo64NDQ0FoKamhsjIyBN5OyKdqqamBvD9GRURERERkT6qzgkFH/hCoIo9/vej+/sOgh40C2KTg1OndHtBC4QOHjyI2+0mOdn/D2dycjKlpaVtPmbKlCn84x//YN68edTV1dHU1MTcuXP5f//v/x31dR5++GEWLVrUrppsNhtxcXGUlZUBEBUVhUXtcxJEhmFQU1NDWVkZcXFx2Gw61E1EREREpE/xuKF4k28b2N61YLh9962hZudPyzaw5FFgtQatXOk5gn6o9JGBi2EYRw1h8vPzue2227j33ns5//zzKSkp4ac//Sm33HILTz/9dJuPufvuu1mwYIH3c5fLRWbm0cflpaSkAHhDIZHuIC4uzvtnU0REREREejlnkRn+7FxpHgZde9j/fsIQ3zawrLMgPCY4dUqPFrRAKDExEZvNFtANVFZWFtA11OLhhx9m6tSp/PSnPwVg9OjRREdHM23aNB544AFSU1MDHhMeHk54ePv3SFosFlJTU0lKSqKxsfEE3pFI5wgNDVVnkIiIiIhIb9ZYC3s+gh3NIdCBbf73wx0waLpvJHy/gcGpU3qVoAVCYWFhTJgwgRUrVnD55Zd7r69YsYJLL720zcfU1NQQEuJfcssPyh196K7NZtMP4SIiIiIiItLxDAPKtvm2ge35GJrqfPctVkgb79sGlj4RbEHf4CO9TFD/RC1YsIDrrruOiRMnMnnyZP785z9TWFjILbfcApjbvYqKinj22WcBuOSSS7j55ptZsmSJd8vY/PnzmTRpEmlpacF8KyIiIiIiIiJHV1Pu2wa2cyVUlvjft6e3Ogx6JkTFB6VM6TuCGgjNmzePQ4cOcf/991NSUkJubi7Lli1j4ECz/a2kpITCwkLv+htuuIHKykr+8Ic/cMcddxAXF8fZZ5/No48+Gqy3ICIiIiIiIhLI3Qj7PvdNAyveCLTa2RISCVlTfdvA+g8HDTWSLmQxOnqvVTfncrlwOBw4nU7sdnuwyxEREREREZHeorygeRvY++Zo+HqX//2kkTCkuQtowBQIjQhOndJrnUjmoU2IIiIiIiIiIiejvhIK1vjOAirf5X8/KgEGzfJtBbMHDkISCRYFQiIiIiIiIiLt4fFA6ebmbWDvw95PwdPku28NgcwzfAFQ6liwWoNWrsixKBASEREREREROZrK0laHQb8PNQf97/fL9k0Dy5oGETqaRHoGBUIiIiIiIiIiLRrroPAT31lA+/P874fFQvZ0GDzLDILiBwWnTpFTpEBIRERERERE+i7DgIPbfdPAdn8ITbWtFlggbaw5CWzw2ZA5CWyhwapWpMMoEBIREREREZG+pfYw7FplBkA7VoJrn//9mBTfNrBBsyA6IShlinQmBUIiIiIiIiLSu7mboGi9bxpY0XowPL77tnAYOMUMgIbMhqQcsFiCV69IF1AgJCIiIiIiIr1PRaFvG1jBaqhz+t/vf5pvG9jAKRAWFZw6RYJEgZCIiIiIiIj0fA3V5vk/LSHQoa/970fEmQdBt4yEd2QEpUyR7kKBkIiIiIiIiPQ8hgGlW3zbwAo/BXeD777FBhmn+7aBpY0Dqy149Yp0MwqEREREREREpGeoOmCGPy0f1WX+9+MG+LaBZU+HyLiglCnSEygQEhERERERke6pqQH2furbBlb6hf/90GjInta8DWw2JAzWYdAi7aRASERERERERLoHw4BDO33bwArWQGO1/5qU0b6R8JlnQEh4cGoV6eEUCImIiIiIiEjw1Dlh1+rmbWDvmdPBWotO8h0EPXgWxCQFp06RXkaBkIiIiIiIiHQdjxuKN/q2ge37HAy3774tDAac6dsGlpwLVmvw6hXppRQIiYiIiIiISOdyFvm2ge1aBbWH/e8nDPVtA8s6C8Kig1KmSF+iQEhEREREREQ6VkMN7PnYFwId+NL/frgDBs3wjYSPGxCcOkX6MAVCIiIiIiIicmoMA8ryfdvA9nwM7nrffYsV0if4toGlTwCbfhwVCSZ9B4qIiIiIiMiJqz4Eu95vPgx6JVSW+N+3Z8CQ5sOgs2dAVHxw6hSRNikQEhERERERkeNzN8Letb5tYMWbAMN3PyTSPP+nZRtY4jCwWIJVrYgchwIhERERERERaVv5ruZtYO9DwQfQUOl/PznXNxJ+wGQIjQhOnSJywhQIiYiIiIiIiKm+0gx+dq40g6DDBf73oxJ8AdDgsyE2JTh1isgpUyAkIiIiIiLSV3k8ULKpeRvY+7D3M/A0+e5bQyDzTBg8y9wGljIGrNaglSsiHUeBkIiIiIiISF/iKvEdBL3rfag55H8/fpA5CWzw2ZA9DcJjg1OniHQqBUIiIiIiIiK9WWMdFH7cvA1sJZRt9b8fFguDZphdQINnQ3x2cOoUkS6lQEhERERERKQ3MQw48JVvGtjuj6CpttUCC6SN800DyzgdbKFBK1dEgkOBkIiIiIiISE9XUw67Vvm2grmK/O/HpjZvA5sFg2ZBdEJQyhSR7kOBkIiIiIiISE/jboKidc0j4VdC8QYwPL77tnDImto8DWw2JI0AiyV49YpIt6NASEREREREpCc4vMe3DWzXB1Dv9L/ff0TzNrCzYeBUCI0MTp0i0iMoEBIREREREemO6qtg94fN28Deg0M7/O9H9jO3fw0+2/xwpAenThHpkRQIiYiIiIiIdAceD+zf4tsGVvgpeBp99y02yJzk2waWNhastqCVK9KbuD0GawvKKausIyk2gknZ8disvXubpQIhERERERGRYKkq8x0EvXMlVB/wvx830JwENvhsyJ4OEY7g1CnSiy3PK2HRG/mUOOu811IdESy8JIc5ualBrKxzKRASERERERHpKk31ZudPyzaw0i3+90OjzeCnZSR8/CAdBi3SiZbnlXDrcxswjrhe6qzj1uc2sOTa8b02FFIgJCIiIiIi0lkMwzz7p2Ub2O410FjjvyZ1jG8bWOYZEBIWnFpF+hi3x2DRG/kBYRCAAViARW/kc25OSq/cPqZASEREREREpCPVVkDBajMA2rESnIX+92OSfQdBD5oFMf2DUqZIX2YYBm9tKfbbJhawBihx1rG2oJzJgxO6rrguokBIRERERETkVHjcULTBNxJ+3zow3L77tjAYMNm3DSw5V9vARLqQYRgUlteQV+RiS5GTrcVO8oqcHK5pPP6DgbLKo4dGPZkCIRERERERkRPl3OfbBrZrFdRV+N9PHObbBpY1FcKig1GlSJ/j8RgUHKomr8jJ1mIXW/Y5ySt2UlnXFLDWagFPW/vFjpAUG9EJlQafAiEREREREZHjaaiBPR81bwN7Dw5+5X8/wgGDZvq2gsUNCEqZIn2J22Ow60AVW4qc5BW5mkMgJ9UN7oC1YTYrw1NiyU13kJtuZ1S6g8H9YzjnN6spdda1eY6QBUhxmCPoeyMFQiIiIiIiIkcyDNi/1bcNbM8n4K733bdYIX2ibxtY2niw6ccrkc7S6Pawo8wMf7YWOckrdpFf7KK2MTD8CQ+xMiLVDH1y0+3kpjsYmhRLWIg1YO3CS3K49bkNWMAvFLK0ut8bD5QGBUIiIiIiIiKm6oOw8/3mkfAroarU/74js9Vh0DMgsl9w6hTp5RqaPGzfX0lekdPs/il28WWJi/omT8DayFAbI9PszZ0/ZgA0pH8MIbbA8Kctc3JTWXLteBa9ke93wHSKI4KFl+T02pHzoEBIRERERET6qqYG2LfWtw2sZDN+PQKhUZB1lu8soMShOgxapIPVNbr5srTSu91rS5GTr0oraXQHbuKKCQ/xhj8t3T/ZiTGn3MEzJzeVc3NSWFtQTlllHUmx5jax3toZ1EKBkIiIiIiI9B2Hdvo6gAo+gIYq//vJo2DwLHMb2IDJEBIenDpFeqHaBjf5JeZZPy3dP1+XVeFu42Rne0SIN/gZ2fzrwPgorJ0U0tisll45Wv5YFAiJiIiIiEjvVecyg5+dK83zgA7v9r8flejbBjZ4FsSmBKVMkd6mqr6J/GJf+JNX7GRHWVWbU736RYW26voxf83oF4lFHXmdSoGQiIiIiIj0Hh4PlGxs3ga20twS5mk1btoaCgPONMOfwbMhZTRY23fWiIi0zVnbyNZiJ1uLXM1n/jgpOFiN0Ub4kxgTzqj01mf+OEhzRCj8CQIFQiIiIiIi0rO5SnzTwHa+D7Xl/vfjB/umgWWdBeGxwalTpBc4XN1AXnHzmPdis/tnz6GaNtem2CP8xrznpjtItkd0ccVyNAqERERERESkZ2mshT0f+84CKsv3vx9uh+zpvhCoX1ZQyhTp6Q5W1fu2fDV3/xRV1La5Nj0u0hv8jEx3kJvmoH+szuDqzhQIiYiIiIhI92YYcOBLcxLYzpWw5yNoqmu1wALp433TwDImgi00aOWK9ET7XXV+wc/WYqffGPbWBiZEkZvmG/Oem+agX3RYF1csp0qBkIiIiIiIdD815bDrfd82MFeR//3YtOYOoLNh0CyIig9OnSI9jGEYlDjrzNCnedJXXrGLA5X1AWstFshOjCY3rWXal52RaQ4ckQpcewMFQiIiIiIiEnzuJtj3uW8aWNEGoNWJtCERMHCqbxtY/9PMn1ZF5KgMw2Df4VrviPe85qlf5dUNAWutFhjcP8ZvzHtOmp2YcMUGvZV+Z0VEREREJDgO7/ZtAyv4AOpd/veTcnwj4QdOgdDIoJQp0hN4PAZ7ymv8xrznFblw1jYGrLVZLQxNivEe9Jyb7mBEaixRYYoI+pKg/24vXryYxx9/nJKSEkaOHMmTTz7JtGnTjrq+vr6e+++/n+eee47S0lIyMjK45557uPHGG7uwahEREREROWH1VbB7TfNI+PegfKf//cj45nHwzSGQPS04dYp0c26PQcHBKnPSV3P3T36xi8r6poC1oTYLw1NiW5354+C0lFgiQm1BqFy6k6AGQi+++CLz589n8eLFTJ06laeeeooLLriA/Px8BgwY0OZjrr76avbv38/TTz/NkCFDKCsro6kp8A+9iIiIiIgEmccDpV/4poEVfgqeVt0K1hDImOQ7Cyh1LFj1Q6pIa01uDzsPVJtbvpo/8ktc1DS4A9aGhVgZkWonN8035n1ocgzhIfq+kkAWwzCM4y/rHGeccQbjx49nyZIl3msjRozgsssu4+GHHw5Yv3z5cr75zW+ya9cu4uNP7tA4l8uFw+HA6XRit9tPunYREREREWlD5X7zMOgd75m/Vh/wvx830DwDaPBsczR8hP5NLtKiocnD12WVbG2e9JVX7GRbiYu6Rk/A2ohQKzmpdr8zf4YkxRBqswahcukuTiTzCFqHUENDA+vXr+euu+7yu37eeefx8ccft/mY119/nYkTJ/LYY4/x97//nejoaObOncuvfvUrIiPb3k9cX19Pfb3vtHSXy9XmOhEREREROQlN9VD4SfM2sJWwf4v//bAYM/hp2QaWMDg4dYp0M/VNbr4qrfQb8/5lSSUN7sDwJzrMxshWY95HpTsY1D8Gm1UHq8vJC1ogdPDgQdxuN8nJyX7Xk5OTKS0tbfMxu3bt4sMPPyQiIoJXX32VgwcP8oMf/IDy8nL++te/tvmYhx9+mEWLFnV4/SIiIiIifZJhwMGvfdPAdn8IjTX+a1LH+qaBZUyCkLCglCrSXdQ1uskvcbG1yOkNgLbvr6TJE7hhJzYipPm8H7v3zJ/shGisCn+kgwX9UGnLEaMiDcMIuNbC4/FgsVj4xz/+gcPhAOA3v/kNV111FX/84x/b7BK6++67WbBggfdzl8tFZmZmB74DEREREZFervYw7FrtOwvIudf/fkxycwfQbPNQ6OjE4NQp0g1U1zexraR5y1fzoc87DlThbiP8iYsKNbd8pTmaz/yxMyA+6qg/E4t0pKAFQomJidhstoBuoLKysoCuoRapqamkp6d7wyAwzxwyDIN9+/YxdOjQgMeEh4cTHh7escWLiIiIiPRm7iYo3uCbBla0DoxW21hsYeYY+JYQKHkk6AdY6YMq6xrZWuxqNerdxc4DVbR1Um9CdBi56b7gJzfdQXpcpMIfCZqgBUJhYWFMmDCBFStWcPnll3uvr1ixgksvvbTNx0ydOpV//etfVFVVERMTA8D27duxWq1kZGR0Sd0iIiIiIr1SxV5zC9jOlbBrFdQ5/e8nDvdtAxs4FcKiglKmSLA4axrJK3Z6x7xvLXZRcLC6zbXJ9nC/Me+56XZS7BEKf6RbCeqWsQULFnDdddcxceJEJk+ezJ///GcKCwu55ZZbAHO7V1FREc8++ywA11xzDb/61a/47ne/y6JFizh48CA//elPufHGG496qLSIiIiIiLShoRp2f+Q7C+jgdv/7EQ4YNLN5G9jZEKdjF6TvKK9uaBX8mL/uLa9tc22aI8Ib/JgTv+wkxUZ0ccUiJy6ogdC8efM4dOgQ999/PyUlJeTm5rJs2TIGDhwIQElJCYWFhd71MTExrFixgv/93/9l4sSJJCQkcPXVV/PAAw8E6y2IiIiIiPQMhgH783zbwAo/AXeD777FChmn+7aBpY8Hqy149Yp0kbLKOt+Y9+aPYmddm2sz4yP9zvwZmWYnIUZHlEjPZDGMtnY39l4ulwuHw4HT6cRutwe7HBERERGRzlN1wNz+1bIVrGq//31Hpm8bWPYMiIwLRpUiXcIwDEpddd6Dns0zf5zsd9W3uT47MZqRafbmM38c5KY5cESFdnHVIifmRDKPoE8ZExERERGRDtLUAHs/820DK9nsfz80CrKm+UKghCE6DFp6JcMwKKqobQ5+XN6tXwerGgLWWiwwuH8MuWm+Me85aXbsEQp/pHdTICQiIiIi0lMZBpTv8m0D270GGqr816SM8m0DG3AmhGh7i/QuhmFQWF7jF/zkFTk5XNMYsNZqgaFJsd6DnkelOxiRaic6XD8aS9+jP/UiIiIiIj1JnRMKPvCFQBV7/O9HJfo6gAbNgtjk4NQp0gk8HoOCQ9W+LV9FLvKKnVTWNQWsDbFaGJYc6zfm/bQUO5FhOhtLBBQIiYiIiIh0bx43FG/ybQPbuxYMt+++NdTs/GkJgZJHgdUatHJFOorbY7DzQJUv+Gnu/qlucAesDbNZOS011nvYc266neEpsYSHKPwRORoFQiIiIiIi3Y2r2Oz+2bkSdr0PtYf97ycM8W0DyzoLwmOCU6dIB2l0e9hRVmVu+Woe976tpJLaxsDwJzzESk6andw035j3oUmxhIUoCBU5EQqERERERESCrbEW9nwEO983g6AD2/zvh9she7rZATT4bOiXFZQyRTpCQ5OH7fsryWsOfvKKXWwrcdHQ5AlYGxVmIyfVd9jzqHQHg/tHE2JT+CNyqhQIiYiIiIh0NcOAsm2+bWB7PoamulYLLJA+wbcNLH0i2PRPd+l56hrdfFla6Tfm/avSShrdRsDamPAQ/zHv6XayE2OwWTUJT6QznNR/VWprazEMg6ioKAD27NnDq6++Sk5ODuedd16HFigiIiIi0ivUlDcHQO+bv1YW+9+PTYMhzdvABs2EqPiglClysmob3OSXuLzhz5YiJ1+XVeH2BIY/jshQ86DnNIe3+2dgfBRWhT8iXeakAqFLL72UK664gltuuYWKigrOOOMMQkNDOXjwIL/5zW+49dZbO7pOEREREZGexd0I+z73TQMr3gi0+sE4JMI8/6flLKD+w8GiH4alZ6iqbyK/2OV35s/OA1W0kf0QHx1mhj6tun8y+kVi0Z93kaA6qUBow4YN/Pa3vwXg5ZdfJjk5mY0bN/LKK69w7733KhASERERkb6pvKC5C2ilORq+3uV/P2kkDJ5lbgMbMAVCI4JTp8gJcNY2srXYydYiV/OZP04KDlZjtBH+JMaEMyrd3nzYs3nmT6ojQuGPSDd0UoFQTU0NsbGxALzzzjtcccUVWK1WzjzzTPbs2dOhBYqIiIiIdFv1lbD7w+aJYO9B+S7/+5HxZgA0uPkwaHtqcOoUaafD1Q3kFfvGvOcVO9lzqKbNtamOCL8x77npDpLtCjlFeoqTCoSGDBnCa6+9xuWXX87bb7/N7bffDkBZWRl2u71DCxQRERER6TY8Hijd3LwNbCXs/Qw8jb771hDIPMMXAqWOBaumIUn3dLCq3nfYc3P3T1FFbZtrM/pFNp/3YwY/I9Mc9I8N7+KKRaQjnVQgdO+993LNNddw++23M3v2bCZPngyY3ULjxo3r0AJFRERERIKqsrT5IOj3zF9rDvrf75ftmwaWNQ0i9H+QSvez31XnG/Pe3P1T6qprc+3AhKjmM3/M7p+RaXb6RYd1ccUi0tkshtHWzs/jKy0tpaSkhDFjxmBt/n891q5di91u57TTTuvQIjuSy+XC4XDgdDrVzSQiIiIigRrroPAT31lA+/P874fFQPZ0XwgUPyg4dYq0wTAMSpx1foc95xW7OFBZH7DWYoHsxGhzy1eag5HpdkamOXBEhgahchHpCCeSeZxUhxBASkoKKSkpftcmTZp0sk8nIiIiItIxPG7Y8zFU7YeYZBg4Bay2o683DDi43TcNbPeH0NR624wF0sb6poFlTgKbfmCW4DMMg32Ha5u7fszwZ2uxi/LqhoC1VgsMSYrxG/Oek2YnJvykfyQUkR6u3d/9V1xxRbuf9N///vdJFSMiIiIickryX4fld4Kr2HfNngZzHoWcub5rtYdh1yrfWUCuff7PE5Pi6wAaNBOiE7uiepGj8ngM9pTX+M78aT742VnbGLA2xGphaHIsuWl2b/gzIjWWqDCFPyLi0+6/ERwOh/d/G4bBq6++isPhYOLEiQCsX7+eioqKEwqOREREREQ6TP7r8NL1wBEnIrhKzOtn/xLcDeZZQEXrwfD41tjCYeBkswNoyGxIyjH304gEgdtjUHCwynvQc16Rk/xiF5X1TQFrQ20WhqfENp/1Y575MzwllojQY3TFiYhwAoHQ0qVLvf/7zjvv5Oqrr+ZPf/oTNpv5F43b7eYHP/iBzuURERERka7ncZudQUeGQeC7tvJ+/8v9T/NtAxs4BcKiOrtKkQBNbg87D1R7g5+8Iif5JS5qGtwBa8NCrIxItTMq3e7d+jUsOZawEE2yE5ETd1KHSvfv358PP/yQ4cOH+13/6quvmDJlCocOHeqwAjuaDpUWERER6YUK1sDfLj7+uoFTYcw3zSDIkdH5dYm00tDk4euySr8x79tKXNQ3eQLWRobayEmz+237GpIUQ6hN4Y+IHF2nHyrd1NTEtm3bAgKhbdu24fEE/mUmIiIiItLh6lzmNLBdq83tYu0x8UYYdVXn1iUC1De5+aq00hv8bC128mVJJQ3uwJ+XosNsjGye9JWbbmdUuoNB/WOwWbVtUUQ6z0kFQt/97ne58cYb2bFjB2eeeSYAn376KY888gjf/e53O7RAEREREREAGmth71ooWA0FH0DRBjACt9UcU0xy59QmfVpdo5v8EpdvzHuRi+37K2nyBG7GiI0IITfNwagMByPTzPAnKyEaq8IfEeliJxUIPfHEE6SkpPDb3/6WkpISAFJTU/nZz37GHXfc0aEFioiIiEgf5W6E4o1mB1DBajMMctf7r4kfBNnTIessePsX5qj5Ns8RspjTxgZO6YrKpRerrm9iW4nLG/zkFTnZcaAKdxvhT1xUqN9hz7npdgbER2HRgeUi0g2c1BlCrblcLoAecx6PzhASERER6aY8Hti/xez+KfgA9nwMDVX+a2JTIXuGGQJlT4O4Ab573ilj4B8KNf/wffWz/qPnRY7DVddIfrHLe9jzliInuw5W09ZPUIkxYeZZP82HPeem20mPi1T4IyJdqtPPEGpNoYqIiIiInBTDgEM7YNcqMwDavQZqD/uviYw3g5/s6WYQlDDk6OPgc+aaoc/yO8FV7LtuT4M5jygMkmNy1jSSV+wLfrYWuyg4WN3m2mR7uLfzJzfd7P5Jtocr/BGRHuWkAqH9+/fzk5/8hPfee4+ysjKObDJyu09wL7eIiIiI9A0Vhb4OoIIPoLLE/35YjDkJLHu6+ZGcC9YTmKqUMxdOu8jsLqrab54ZNHAKWG0d+z6kRyuvbvAb855X7GRveW2ba9PjIr1n/eSmOxiZbicpNqKLKxYR6XgnFQjdcMMNFBYW8stf/pLU1FQl4SIiIiLStqoy/wDocIH/fVs4DDjD1wGUNg5soaf2mlab2VUkApRV1rG1yOUXABU769pcOyA+itx0u/fMn5FpdhJiwru4YhGRrnFSgdCHH37ImjVrGDt2bAeXIyIiIiI9Wm0F7PnIFwCV5fvft9ggfYKvAyjzDAhVt4WcOsMwKHXV+ca8N2/9Kqusb3N9dmJ085k/du/2L0fUKYaRIiI9yEkFQpmZmQHbxERERESkD2qohsJPfQFQySYwPP5rUkb5DoIeOAXCY4NSqvQehmFQVFHb3PHTHAAVOzlY1RCw1mKBwf1jvB0/uc2/xkYo/BGRvu2kAqEnn3ySu+66i6eeeoqsrKwOLklEREREuq2mBiha5wuA9q4FT6P/moShZvgzaAYMPAuiE4JTq/QKhmFQWF7jN+Y9r9hJRU1jwFqb1cLQpJjmLV9m+DMi1U50+CnP0hER6XVO6m/GefPmUVNTw+DBg4mKiiI01D9dLy8v75DiRERERCTIPG4o2ewLgAo/gcYa/zX2DDP8adkGZk8LTq3S43k8BgWHqn2HPRe5yCt2UlnXFLA2xGpheEps85h3X/gTEaoDxEVE2uOkO4REREREpBcyDDjwpS8A2r0G6pz+a6ISfR1A2dOhX/bRR8GLHIXbY7DzQJVvzHuRi63FTqobAicWh9msnJYa23zmj3ng87CUGMJDFP6IiJyskwqEvvOd73R0HSIiIiISDIYBh3c3B0CroWANVJf5rwm3Q9ZZvnOAkkYoAJIT0uj2sKOsyu+w520lldQ2BoY/EaFWRqTavcHPyHQ7w5JjCbVZg1C5iEjvddKbad1uN6+99hrbtm3DYrGQk5PD3LlzsdmU0ouIiIh0a64Ss/OnYDXs+gCchf73QyJhwJm+DqCUMWDTGSzSPvVNbr7eX+U35n1baSUNTZ6AtVFhNkam+ca856Y7GNw/mhCFPyIine6k/su+Y8cOLrzwQoqKihg+fDiGYbB9+3YyMzN56623GDx4cEfXKSIiIiInq6Ycdn/Y3AH0ARzc7n/fGgIZp/s6gDImQkh4cGqVHqWu0c2XpZW+M3+KnXxVWkmjO3AicWx4CCPT7c1n/pgf2YnR2KzqNhMRCQaLcRLz4y+88EIMw+Af//gH8fHxABw6dIhrr70Wq9XKW2+91eGFdhSXy4XD4cDpdGK324NdjoiIiEjHq68yD3/etcoMgEq3AK3/yWeB1DG+DqABkyEsOkjFSk9R09DEthKXd8x7XpGTr8uqcHsCf5xwRIZ6D3pu2fo1ID4Kq8IfEZFOdSKZx0l1CK1evZpPP/3UGwYBJCQk8MgjjzB16tSTeUoREREROVmNdbDvc18HUNF68Bwxlan/ab4OoKypENkvOLVKj1BV30R+scvvzJ+dB6poI/shPjqsOfixe7d9ZfSLxKJzpkREurWTCoTCw8OprKwMuF5VVUVYWNgpFyUiIiIix+BugpJNvg6gvZ9BU53/mn5ZzWPgZ0DWNIhNDkKh0hM4axvZWtxqzHuRk4JD1bS1j6B/bLgZ+qTZvdu+Uh0RCn9ERHqgkwqELr74Yr73ve/x9NNPM2nSJAA+++wzbrnlFubOnduhBYqIiIj0eR4PlOX7OoB2fwQNR/yfczHJvg6g7OnQb2BwapVu7XB1A3nFvuAnr9jJnkM1ba5NdUR4t3zlppvdP0n2iC6uWEREOstJBUK///3v+c53vsPkyZMJDQ0FoKmpiblz5/K73/2uQwsUERER6XMMA8p3+TqAdq+BmkP+ayLiIHuaLwRKHKZR8OLnYFW935avvCIXRRW1ba7N6BdpnvWT4WBkc/dPYowOFhcR6c1OKhCKi4vjP//5Dzt27GDbtm0YhkFOTg5Dhgzp6PpERERE+gbnPjP8aflwFfnfD42GgVN8HUApo8BqC06t0u3sd9WR1yr4yStyUuqqa3NtVkIUI9Obx7w3d//ERenYBxGRvuakAqEWQ4YMUQgkIiIicjKqD/oHQOU7/e/bwiDzDF8AlD4BbKHBqVW6DcMwKHbW+ca8FznJK3ZxoLI+YK3FAtmJ0a2CHwc5aXYckfpzJCIiJxkIXXXVVUycOJG77rrL7/rjjz/O2rVr+de//tUhxYmIiIj0GnUu2PORLwDan+d/32KFtPG+AGjAmRAaGZxapVswDIN9h2u9I963FDnZWuyivLohYK3VAkOSYnxj3jMcjEi1ExN+Sv//r4iI9GInPXZ+4cKFAdfnzJnDE088ccpFiYiIiPR4DTXm9K+WAKh4Ixhu/zXJub4AaOAUiHAEp1YJOo/HYE95zRFn/jhx1TUFrA2xWhiaHGuOec9wMDLNQU6qncgwbSEUEZH2O6lA6Gjj5UNDQ3G5XKdclIiIiEiP426EovW+AGjvZ+A+opMjfrAvAMqeDtGJwalVgsrtMSg4WEVekcsb/OQXu6isDwx/wmxWhqfEkptu93b/DE+JJSJU4Y+IiJyakwqEcnNzefHFF7n33nv9rr/wwgvk5OR0SGEiIiIi3ZrHDaVbfAHQno+hsdp/TWwaDGo1Ct6REZxaJWia3B52HKjyjXkvcpJf4qKmwR2wNizEyohUO6PS7d4zf4YlxxIWYg1C5SIi0tudVCD0y1/+kiuvvJKdO3dy9tlnA/Dee+/x/PPP6/wgERER6Z0MAw5ubw6AVkPBGqir8F8TlQBZ05pDoBkQP0ij4PuQhiYPX5dVNgc/ZvfPthIX9U2egLWRoTZy0uyMSjfHvI/KcDC4fwyhNoU/IiLSNU4qEJo7dy6vvfYaDz30EC+//DKRkZGMHj2ad999lxkzZnR0jSIiIiLBcXiP/ySwqlL/+2GxkDXVDH+yp0NSDlj1A31fUNfoZvv+Sr8x71+VVtLgDgx/YsJDyEmzNx/2bP46qH8MNqvCQhERCR6LYRhGsIvoSi6XC4fDgdPpxG63B7scERER6U4q98PuNWYH0K7VULHH/35IhDkKvqUDKHUs2DTFqbera3STX+Jqddizi+37K2nyBP4z2h4RYp710/KRZicrIRqrwh8REekCJ5J5nPS/YCoqKnj55ZfZtWsXP/nJT4iPj2fDhg0kJyeTnp5+sk8rIiIi0nVqD8Puj3zbwA586X/fGgLpE3wdQBmnQ2hEcGqVdnN7DNYWlFNWWUdSbASTsuPb3Y1TXd9EfonLN+a9yMWOA1W42wh/+kWFtgp+HIxKd5AZH4lF2wRFRKQHOKlA6IsvvuCcc87B4XCwe/dubrrpJuLj43n11VfZs2cPzz77bEfXKSIiInLqGqqh8BOz+6fgAyjZDLT+Qd8CKaN8HUADzoTw2GBVKydheV4Ji97Ip8RZ572W6ohg4SU5zMlN9Vvrqmskv9h32POWIie7DlbTVv98YkwYuemO5jN/HIzKcJDmiFD4IyIiPdZJBUILFizghhtu4LHHHiM21vePpAsuuIBrrrnmhJ5r8eLFPP7445SUlDBy5EiefPJJpk2bdtzHffTRR8yYMYPc3Fw2bdp0om9BRERE+oKmeti3rvkQ6A/M/+1p9F+TONw3BSzrLIiKD06tcsqW55Vw63MbODLPKXXWcetzG/jx7KFEhNnIK3KytdhFwcHqNp8n2R7uC36aO4CS7eEKf0REpFc5qUDo888/56mnngq4np6eTmlpaRuPaNuLL77I/PnzWbx4MVOnTuWpp57iggsuID8/nwEDBhz1cU6nk+uvv57Zs2ezf//+k3kLIiIi0ht53FCyydcBVPgpNNX6r3EMgEHTzQ6grGlgT23zqaRncXsMFr2RHxAGga8H7Mn3vg64lx4XSW7LmPcMc+JXUqy2BYqISO93UoFQREQELpcr4PpXX31F//792/08v/nNb/if//kfbrrpJgCefPJJ3n77bZYsWcLDDz981Md9//vf55prrsFms/Haa6+dcP0iIiLSSxgGlG3zdQDt/gjqnf5ropN8HUDZ06FflkbB9yKVdY3kFbl484siv21iR3NGdj9mDE8yA6B0B/HRYV1QpYiISPdzUoHQpZdeyv33389LL70EgMViobCwkLvuuosrr7yyXc/R0NDA+vXrueuuu/yun3feeXz88cdHfdzSpUvZuXMnzz33HA888MBxX6e+vp76+nrv520FWSIiItJDGAYcLvB1AO1eA9UH/NdEOMzOn5YAqP9pCoB6idoGN/klTr7Y1/JRcdQzf47mmjMGculYDUARERE5qUDoiSee4MILLyQpKYna2lpmzJhBSUkJkydP5sEHH2zXcxw8eBC3201ycrLf9eTk5KNuO/v666+56667WLNmDSEh7Sv94YcfZtGiRe1aKyIiIt2Qq7h5Cljzh3Ov//3QKBgw2RcApY4Bqy04tUqHaWjy8FVpJZv3VbBln5PN+yr4uqztaV/pcZGkxUXw+e7Dx31ebQcTERExnVQgZLfb+fDDD1m5ciUbNmzA4/EwYcIEZs+efcLPdeThfIZhtHlgn9vt5pprrmHRokUMGzas3c9/9913s2DBAu/nLpeLzMzME65TREREukhNuX8AdOiIc1+soZA5yRcApU+EEG376cma3B52HKjii71OvigyA6BtJZU0uD0BaxNjwhmT4WB0RhyjM8xpX4kx4bg9Bmc9upJSZ12b5whZgBSHOYJeRERETjAQ+uyzzygvL+eCCy4A4Oyzz2bv3r0sXLiQmpoaLrvsMv7f//t/hIeHH/e5EhMTsdlsAd1AZWVlAV1DAJWVlaxbt46NGzfyox/9CACPx4NhGISEhPDOO+9w9tlnBzwuPDy8XfWIiIhIkNRXwp6PmwOg1VC6xf++xQqpY30B0IAzISw6KKXKqfN4DAoOVXu7frbsMyd+1Ta6A9bGRYUyKt3B6FYBUIq97VHvNquFhZfkcOtzG7CAXyjUsnrhJTnYrNo+KCIiAicYCN13333MnDnTGwht2bKFm2++me985zuMGDGCxx9/nLS0NO67777jPldYWBgTJkxgxYoVXH755d7rK1as4NJLLw1Yb7fb2bLF/x+IixcvZuXKlbz88stkZ2efyFsRERGRYGmsg72f+TqAitaDcUQYkJTjC4AGToXIuKCUKqfGMAz2Ha41z/spquCLvU7yipxU1jcFrI0JDyE33e4Nfkanx5EZH3lCo97n5Kay5NrxLHoj3++A6RRHBAsvyWFOribKiYiItDihQGjTpk386le/8n7+wgsvMGnSJP7yl78AkJmZycKFC9sVCAEsWLCA6667jokTJzJ58mT+/Oc/U1hYyC233AKY272Kiop49tlnsVqt5Obm+j0+KSmJiIiIgOsiIiLSjbgboXijbxJY4Wfgrvdf0y/bfxJYTFJwapVTst9Vx+a9FWwpcrJ5n5Mt+yo4XNMYsC48xMrItFbhT0YcgxKjsXZA986c3FTOzUlhbUE5ZZV1JMWa28TUGSQiIuLvhAKhw4cP+23nWr16NXPmzPF+fvrpp7N37962HtqmefPmcejQIe6//35KSkrIzc1l2bJlDBw4EICSkhIKCwtPpEQREREJNo8H9uf5OoD2fAwNlf5rYlP9A6C4AcGpVU5aeXUDX+yr8Jv4VVZZH7Au1GbhtBR7c/Bjhj9Dk2IIsVk7rTab1cLkwQmd9vwiIiK9gcUw2j+oc+DAgfz9739n+vTpNDQ0EBcXxxtvvOE9THrLli3MmDGD8vLyTiv4VLlcLhwOB06nE7vdHuxyREREej7DgEM7fB1ABWug9oh/C0T2842CHzQTEoZoFHwP4qprJG9fc9dPUQWb9zopqqgNWGe1wLDkWPPcn8w4Rqc7OC01lvAQTX0TERHpCieSeZxQh9CcOXO46667ePTRR3nttdeIiopi2rRp3vtffPEFgwcPPrmqRUREpOeo2Os/Cayy2P9+WAwMnALZM8wQKDkXrJ3XESIdp6ahia3FLm/Xz5Z9TnYdrG5z7aD+0YxOdzAqI44xGQ5y0uxEhZ3UEFsRERHpYif0X+wHHniAK664ghkzZhATE8Pf/vY3wsJ8Y17/+te/ct5553V4kSIiIhJkVQdgd3P4s2s1HC7wv28LN0fBD5phhkBp48AWGpxapd3qm9xsK6lky76K5jN/nHxdVomnjf7xjH6RjMmIY1Tz1q/cdAf2CP0ei4iI9FQntGWshdPpJCYmBpvNv/23vLycmJgYv5Cou9GWMRERkXaorfAfBV+W73/fYoP08b4OoMxJEBoZlFKlfRrdHr7eX2We+1Nkdv98VVpJozvwn4LJ9nDzwOd0R3MAFEd8dPf9952IiIiYOm3LWAuHw9Hm9fj4+JN5OhEREQm2hhrY+6mvA6hkExge/zXJo5o7gKbDgMkQof9jpbtyewwKDlaxea+zeeJXBfnFLuqbPAFr+0WFMrp5y9eo5qlfyfaIIFQtIiIiXUmbvEVERPqipgYoWu/rANq7FjxHjAdPGOLrAMqaBtGa2tQdGYZBYXmN98yfL/Y5yStyUt3gDlgbGx7CqAyz62dMRhyj0h1k9IvEogO+RURE+hwFQiIiIn2Bxw2lX/g6gAo/gcYa/zX2DF8HUNY0cKQHp1Y5KsMwKHHW+Q58LjJHvjtrGwPWRobayE23Myo9jjGZDkalO8hKiMZqVfgjIiIiCoRERER6J8OAA1/5RsHvXgN1Tv81UYlm+NPyET9Io+C7mYNV9d6un5aPg1X1AevCbFZGpMYyuvnQ5zEZcQzuH02ITZPdREREpG0KhERERHqLw7vN7p+WUfDVZf73w+2QdZYvAErKUQDUjThrGvmiyAx/tjR3ABU76wLW2awWhiXHNp/542B0ehzDU2IJC1H4IyIiIu2nQEhERKSnqiz1nQFU8AFUFPrfD4mEAWc2B0AzIHUM2PSf/u6gqr6Jrc3bvVomfu05VBOwzmKBwf1jGJ1ujnoflRHHyDQ7EaG2Np5VREREpP30r0IREZGeoqYcdn/o6wA6+JX/fWsIZJzu6wDKOB1CwoNTq3jVNbrJL3GxZZ857WvLPic7DlRhBE57Z2BCFKPSmw98znAwMs1ObERo1xctIiIivZ4CIRERke6qvso8/LmlA6jkC6B1imAxu35aOoAGnAnhMcGqVoBGt4evSiv9Jn5t319Jkycw/Ul1RDA6w8Ho5lHvo9IdxEWFBaFqERER6YsUCImIiHQXTfXm+PeWDqCideBp8l/T/zRfB1DWWRDZLzi1Cm6Pwc4DVWzea0772rzPybYSFw1NnoC1CdFh/uFPhoOk2IggVC0iIiJiUiAkIiISLO4mKNnk6wAq/BSajjhEOG6grwMoexrEpgSl1L7O4zHYU17j7frZss9JXrGTmgZ3wFp7RIg3+GkJgVIdEVh0gLeIiIh0IwqEREREuorHA2X5vg6gPR9Bvct/TUyy/yj4fllBKbUvMwyDoora5jN/nGxpnvxVWdcUsDYqzEZuusM89DkzjtHpDgYmRCn8ERERkW5PgZCIiEhnMQwo3+XrACpYAzUH/ddEOCBrmtkBNGgGJA7TKPguVuaq8535U2R2/xyqbghYFxZiZWSavXnil9kBNKh/DDarfr9ERESk51EgJCIicjQeN+z5GKr2m507A6eA9Tjjvp1Fvg6ggg/Atc//fmg0DJzcvAVsOqSMOv5zSoc5XN3QHPpUmN0/+5yUuuoC1oVYLQxPifXb+jUsOZZQmzUIVYuIiIh0PAVCIiIibcl/HZbfCa5i3zV7Gsx5FHLm+q5VH4Tda8zwZ9dqKN/p/zy2MMiYZHb/ZE+HtPEQoklSXaGyrpG8Ipe38+eLfRXsLa8NWGe1wJCkmFbhTxynpcQSEaqgTkRERHovBUIiIiJHyn8dXroe/xHvgKvEvH7W7eZEsILVsD/Pf43FCmnjfB1AmWdAWFSXld5X1Ta4yS9xsnmvs3niVwW7DlS3uTY7MZpR6b4Dn0em2YkO1z+JREREpG/Rv35ERERa87jNzqAjwyDwXfvwN/6Xk0b6OoAGTjHPBZJOU9/k5qvSSt+5P/ucfF1WhdsT+HuWHhfpN+49N92BIzI0CFWLiIiIdC8KhERERFrb9YH/NrGjGTYHRs8zD4SO6d/5dfVRTW4PX5dVNU/8qmBLkZMvSyppcHsC1vaPDWdMhoNR6XGMznQwKt1BYkx4EKoWERER6f4UCImISN/mcUPJZvMMoN1rzElg7THqG5B7RefW1sd4PAYFh6q9XT9f7HOytdhJXWNg+BMXFWp2/bTa+pVsD9e4dxEREZF2UiAkIiJ9i2FA2TbfFLDdH0K988SfJya542vrQwzDYN/hWrPrp7n7J6/IRVV9U8DamPAQctPtjMmIY1SGgzEZcWT0i1T4IyIiInIKFAiJiEjvZhhQvqtVALQGqg/4rwm3Q9ZZzWcATYXn55kHSLd5jpDFnDY2cEpXVN9rlDrrfJ0/zWPfD9c0BqyLCLUyMs3hHfU+OiOO7IRorFaFPyIiIiIdSYGQiIj0Ps59vgCo4ANwFfnfD42CAZPNACh7GqSMAVur/yTOebR5ypgF/1CoOZSY8whYNZL8aA5V1Ztj3vc62VJkhkBllfUB60JtFkak2hmV7vB2/wxNiiHEZg1C1SIiIiJ9iwIhERHp+arKWp0B9IHZEdSaLQwyJjUHQNMhfQKEhB39+XLmwtXPmtPGWh8wbU8zw6CcuZ3zPnogZ20jeUVOv4lfRRW1AetsVgtDk2IYneFgVEYcYzIcDE+JJTxEwZqIiIhIMCgQEhGRnqf2MOz+yNcBdGCb/32LDdLHmxPAsqdD5hkQFnVir5EzF067CPZ8DFX7zTODBk7p051BNQ1N5BW5vMHPliInBQer21w7qH+02fWT7mBMpoOcVAeRYX33ayciIiLS3SgQEhGR7q++Cgo/hYLVZgBUspmA831SRkH2DDMAGjAZIuyn/rpWm7mlrA+qa3TzZWllq4lfFewoq8LTxrFKmfGR3olfozIc5KY7sEeEdn3RIiIiItJuCoRERKT7aayDfWt9HUBF68FzxPSpxOFmWJM9HQaeBdEJwam1F2h0e9i+v7J52pd57s9XpZU0ugPTnxR7RPOkL3Pr1+h0B/2ij7H9TkRERES6JQVCIiISfO5GKN7o6wAq/AzcRxxCHDew+QygGWYQFJsSnFp7OLfHYNeBKt+ZP0VO8otd1Dd5AtbGR4eZk77SzWlfozMcJNkjglC1iIiIiHQ0BUIiItL1PG4o3eLrACr8BBqq/NfEpPgOgc6eBv2yglJqT2YYBnsO1XjHvG/e52RrkZPqBnfA2tiIEPPA5/S45u4fB+lxkVgsGvcuIiIi0hspEBIRkc5nGHDgq+YAaDXs/hDqKvzXRMb7toBlz4CEIaAwot0Mw6DEWdfqzB+zA8hV1xSwNjLURm663dv1MzojjoHxUVit+nqLiIiI9BUKhEREpOMZBhwu8HUAFayB6jL/NWGxkDXV1wWUNBKs1uDU2wMdqKxnS1EFm/ea076+2FfBwaqGgHVhNisj0uxm10/z1q8hSTHYFP6IiIiI9GkKhEREpGM4i2D3Gl8I5Nzrfz8kEgac6esASh0DNv1nqD0qahqaQx8z+Nmyz0mxsy5gnc1qYXhyrLfrZ3SGg2HJsYSFKGgTEREREX/6l7iIiJyc6oNm8NMSAh3a4X/fGgoZp/s6gDImQkh4cGrtQarqm8grcjZP/KpgS5GTPYdqAtZZLDCkf0zzxK84RmU4yEm1ExFqC0LVIiIiItLTKBASEZH2qa2APR/7OoDKtvrft1ghbZwZ/mRNM7uBwqKDUmpPUdfoZmuxiy3N076+2Odk54EqjMBp7wxMiDK7ftIdjM5wMDLdQUy4/jMuIiIiIidH/5IUEZG2NVSb078KmjuASjaBccRo8uRcXwfQwCkQ4QhKqT1BQ5OH7fsrza6ffU4273OyfX8lbk9g+pPmiGBUq21fo9IdxEWFBaFqEREREemtFAiJiIipqR72fe7rANq3DjyN/msShvrGwGdNg+jE4NTaRdweg7UF5ZRV1pEUG8Gk7Ph2Hcbs9hjsKKvyTfwqcrKtxEVDkydgbWJMWKtpX+bY9/6x2lonIiIiIp1LgZCISF/lboLijbC7OQAq/BSajjio2JFpHgDdEgLZ04JTaxAszyth0Rv5lLQ6vDnVEcHCS3KYk5vqvebxGOw+VM2WImfzxK8K8opc1Da6A57TERnq7fhpCYFSHRFYLJr4JSIiIiJdS4GQiEhf4fHA/jxfB9Cej6Gh0n9NTLLZ+dOyDaxflnl6cR+zPK+EW5/bwJGbuUqdddzy3AZunpaNzWo1J34VOamsawp4jugwG7nN5/20hD8D4qMU/oiIiIhIt6BASESktzIMOPg1FKz2TQOrPey/JiLO7Pxp6QJKHNYnA6DW3B6DRW/kB4RBgPfaX9YU+F0PD7GSk2Y3p32lOxiT6SA7MaZd28tERERERIJBgZCISG9yeLevA6jgA6ja738/LMY8/LmlAyh5FFitQSm1O/F4DArLa8grdvLO1v1+28SOZvaIJM4dkczojDiGJscQatPXUURERER6DgVCIiI9mavE7Pxp6QKqKPS/HxIBmWc0B0AzIG0s2EKDUmp30eT2sPNANVuLneQVucgrdrKt2EVlfeC2r2OZOyaNS8emd1KVIiIiIiKdS4GQiEhPUn2oOQBq7gA69LX/fWsIpE/0dQBlnA6hEcGptRuob3KzvbSKvGKnNwDaVuKivo1pX2EhVkakxJIYG85728qO+9xJsX336yoiIiIiPZ8CIRGR7qzOZR7+3BIA7d9yxAKL2fXTEgBlngnhMcGoNOiq65vYVuIir8jJ1mIXecUuvt5fSZMn8DSg6DAbI9Mc5KTZyU13kJtuZ3B/c9uX22Nw1qMrKXXWtXmOkAVIcZgj6EVEREREeioFQiIi3UlDDez9tDkAWmOOhTeOGF+elOMLgAZOgch+wak1iJw1jWbHT6ttXwUHqzHaSHD6RYUyMs3ByHQ7uWkORqbZyUqIxnqUA59tVgsLL8nh1uc2YAG/UKjlEQsvydGB0SIiIiLSoykQEhEJpqYGKFrn6wDauxY8jf5r4gc3B0DTzJHwMUnBqTVIyirr2FrUuvPHyb7DtW2uTbaHm6FPuhn85KY7SHNEnPCo9zm5qSy5djyL3sj3O2A6xRHBwktymJObekrvSUREREQk2BQIiYh0JXcTlGw2D4HevQb2fAJNR4Qb9gxfB1D2NHBkBKfWLmYYBvsO17K1uDn4KXKSV+ziQGV9m+sHxEeRm243u3/SzF/7x4Z3WD1zclM5NyeFtQXllFXWkRRrbhNTZ5CIiIiI9AYKhEREOpPHA2X5vg6gPR9Bvct/TXR/M/zJmmb+Gj8ITrCjpadxewwKDlb7hT9bi104axsD1lotMLh/jLfjp+XsH0dk509Ls1ktTB6c0OmvIyIiIiLS1RQIiYh0JMOAQzuax8CvMbuAag75r4lw+MKf7OnQ/7ReHQA1uj18vb950ldz8JNf4qKmwR2wNtRmYVhyLLlp5kHPOWkORqTGEhWm/1yJiIiIiHQk/QtbRORUVRT6OoAKPoDKEv/7odHm4c/ZzSFQymiw2oJTayera3Sbk76KXeQ3H/j8VWklDe7AMe8RoVZyUlu6fswtX8OSYwkLsQahchERERGRviXogdDixYt5/PHHKSkpYeTIkTz55JNMmzatzbX//ve/WbJkCZs2baK+vp6RI0dy3333cf7553dx1SLSp1XuNzt/ClabAdDh3f73beGQOQmyZ5gBUPp4sHX+9qau5qprJL/YxdZiF1uLzIlfOw9U425jzHtsRIh3wlfLmPfsxBidxyMiIiIiEiRBDYRefPFF5s+fz+LFi5k6dSpPPfUUF1xwAfn5+QwYMCBg/QcffMC5557LQw89RFxcHEuXLuWSSy7hs88+Y9y4cUF4ByLSJ9SUw+4PfR1AB7/yv2+xQfoE3xawzEkQGhmcWjvJoap674SvrUUuthY72X2ops21iTFhjGze8mWGQA4y4yNPeNKXiIiIiIh0HothGIH/V24XOeOMMxg/fjxLlizxXhsxYgSXXXYZDz/8cLueY+TIkcybN4977723XetdLhcOhwOn04ndbj+pukWkB/G4Yc/HULUfYpLNrVvH265VX2lO/2rpACrdArT+q9ICqaObA6AZMOBMCI/tzHfRZQzDoNRVR16rMe9bi51+o9dbS4+LbHXYs/lrUmy4wh8RERERkSA4kcwjaB1CDQ0NrF+/nrvuusvv+nnnncfHH3/crufweDxUVlYSHx9/1DX19fXU1/tGFrtcrqOuFZFeJv91WH4nuIp91+xpMOdRyJnru9ZYC3s/83UAFW0A44gDj/uf5usAGjgVoo7+905P4fEYFJbXeDt/WgKg8uqGNtcPSoxmZEvw07z9q190WBdXLSIiIiIiHSFogdDBgwdxu90kJyf7XU9OTqa0tLRdz/HrX/+a6upqrr766qOuefjhh1m0aNEp1SoiPVD+6/DS9fh39gCuEvP62b8Aw2MGQHs/A/cRIUi/bF8AlDUNYv3/ruppmtwedh2sJq/IPOh5a7GT/GIXlfVNAWttVgtDk2J8277SHYxItRMTHvRj50REREREpIME/V/3R24rMAyjXVsNnn/+ee677z7+85//kJSUdNR1d999NwsWLPB+7nK5yMzMPPmCRaT787jNzqAjwyDwXVv5K//LsWm+ACh7GsQFnmPWU9Q3udle2jzmvXnS17YSF/VNgZO+wkKsjEiJZWS6w9v1MzwllojQ3jkFTURERERETEELhBITE7HZbAHdQGVlZQFdQ0d68cUX+Z//+R/+9a9/cc455xxzbXh4OOHh4adcr4j0IHs+8t8mdjRZZ8HIK8xzgBIGQw8896a6voltJeakr7wiJ3nFLr7eX0lTG5O+osNsjExzMDLd7u3+Gdw/hlCbxryLiIiIiPQ1QQuEwsLCmDBhAitWrODyyy/3Xl+xYgWXXnrpUR/3/PPPc+ONN/L8889z0UUXdUWpItITVJWZ2792vQ9fLmvfYyZ8F0Zd1bl1dSBnTaPZ8VPs2/a162A1bY0G6BcV6g1/Wjp/shKisWrMu4iIiIiIEOQtYwsWLOC6665j4sSJTJ48mT//+c8UFhZyyy23AOZ2r6KiIp599lnADIOuv/56fve733HmmWd6u4siIyNxOBxBex8iEgT1Veb0sF2rzI+yrSf+HDHd91ygsso6traa9JVX7GTf4do21ybbw83Qp9WkrzRHhCZ9iYiIiIjIUQU1EJo3bx6HDh3i/vvvp6SkhNzcXJYtW8bAgQMBKCkpobCw0Lv+qaeeoqmpiR/+8If88Ic/9F7/zne+wzPPPNPV5YtIV3I3mtO/WgKgfWvBc8SByCmjYdAM8xDoN34MlaW0fY6QxZw2NnBK59d9HIZhsO9wLVuLnX7bvg5U1re5fkB8FLnNW75Gppm/9o/VtlgRERERETkxFsNoa7NB7+VyuXA4HDidTux2e7DLEZGjMQw48JUvANr9ITRU+q+JGwCDZsGgmeZh0NGJvnveKWPgHwo1d81c/az/6Pku4PYYFBys9gt/tha7cNY2Bqy1WmBw/xhvx8/INAc5aXYckaFdWrOIiIiIiPQcJ5J5BH3KmIiIl7MIClY3h0Crocr/0Hki+5kHQA+aaX7EZx/9uXLmmqHP8jv9D5i2p8GcRzo9DGp0e/h6f/Okr+bgJ7/ERU2DO2BtqM3CsORYcpsPes5JczAiNZaoMP0VLSIiIiIinUM/bYhI8NQ5zc6fli6gg9v974dEmNu6WgKg5FFgPYGJWDlz4bSLzLOGqvabZwYNnALWjh2pXtfo9k76ahnz/lVpJQ3uwDHvEaFWclJbun7MLV/DkmMJC9GkLxERERER6ToKhESk6zTVw961vgCoeAMYrUITixXSxvkCoIxJEBpxaq9ptUH2tFN7jlZcdY3kFzeHP82dPzsOVOFuY8x7bESId8JXbrrZ/ZOdGINNk75ERERERCTIFAiJSOfxeGB/ni8A2vMxNB0xKSthqHkQ9KCZkHWWuS2sA7k9BmsLyimrrCMpNoJJ2fHtDmQOVdV7J3xtbR7zvvtQTZtrE2PCGNm85csMgRxkxkdq0peIiIiIiHRLCoREpGMd3u07A6hgNdQc8r8fneTrABo0AxwZnVbK8rwSFr6+lf0u38SuVEcECy/JYU5uqveaYRiUuurIK/Jt+dpa7KTEWdfm86bHRbY67Nn8NSk2XOGPiIiIiIj0GAqEROTU1JS3Ogh6lRkItRYabXb+tIRASSOgC4KT5Xkl3PrchoCh86XOOm55bgM3T8smxGYlr8hJfrGLQ9UNbT7PoMRoRrYEP83bv/pFh3V6/SIiIiIiIp1JgZCInJjGWij8xBcAlXyB31h3awhknO4LgNIngK1rR6W7PQaL3sgPCIPAV+lf1hT4XbdZLQxNivFt+0p3MCLVTky4/poUEREREZHeRz/piMixedxQvAl2vW8GQHvXgrvef01Sji8AGjgFwmO7vk7AWdvI5r0VvLG5+KjbvVqbPSKJ2aclMzLNzvCUWCJCO3b6mIiIiIiISHelQEhE/BkGHNrpC4B2rzHHw7dmT4dBs8wzgLJnQGxyl5fZ6PbwVWklGwsPs3FvBZv2VrDrQPUJPcfcMWlcOja9kyoUERERERHpvhQIiQhU7oeCD3zbwFz7/O+HO8zR7YNmmkFQwuAuOQeohWEYFFXUsmlvBZsKzfBnS5GT+iZPwNqBCVFkxEXy0c5DbTyTv6TYUxxpLyIiIiIi0kMpEBLpi+orzRHwLQFQWb7/fVsYZJ7hC4BSx4Ct6/66qKxrZMs+Jxv3VrCxOQA6WFUfsM4eEcLYAf0YmxnHuMw4xmTGER8dhttjcNajKyl11rV5jpAFSHGYI+hFRERERET6IgVCIn2BuxGK1vsCoH2fg6ep1QILpI42A6DsGTBgMoRFdUlpTW4P2/dXmd0/ew+zaW8FX5dVYRyR5IRYLYxItTM2M878GBBHdkI0Vmtgp5LNamHhJTnc+twGLPgdeU3L6oWX5GBr47EiIiIiIiJ9gQIhkd7IMKBsmy8A2vMRNFT5r+mX5TsIOms6RCd0SWmlzjo27T3s7f7JK3JS0+AOWJfRL9Ib/owbEMfINMcJHfo8JzeVJdeOZ9Eb+X4HTKc4Ilh4SQ5zclM75P2IiIiIiIj0RAqERHoL5z7YtdoMgApWQ9V+//tRCZA93dcFFJ/d6SXVNDTxxT6n39k/pa7A6V+x4SGMznQ0B0DmFrD+seGn/PpzclM5NyeFtQXllFXWkRRrbhNTZ5CIiIiIiPR1CoREuguP2zzXp2o/xCSb49utx+iIqa0wJ4C1hECHvva/HxJpPkdLF1ByLlitnVa+22Ow80AVmwormrt/DrN9fyWeI7Z+WS1wWoqdsQPivGf/DO4f0+bWr45gs1qYPLhrup9ERERERER6CgVCIt1B/uuw/E5wFfuu2dNgzqOQM9f8vKke9n7m2wZWvBGMVlO2LFZIG+8LgDInQcipd9kcTVllnbfrZ9PeCr7Y56SqvilgXaojwnfuT2YcozIcRIXprx4REREREZFg0k9lIsGW/zq8dD0cOQ/LVQIvXQejvwnVZbDnE2iq9V+TOMy3BSzrLIiM65QS6xrd5BWZW79apn4VVdQGrIsKszEq3cG4lslfA+JItmu0u4iIiIiISHejQEgkmDxuszOozeHozde+eMF3KSbZ1wGUPQMc6R1fksdg18Fqv6lfX5ZU0nTE3i+LBYYlxXonfo3NjGNYcqzO5xEREREREekBFAiJBFP+6/7bxI7m9Jvh9P+B/qeZSUwHKq9uMIOf5rN/Nu+twFUXuPWrf2y4t+tnbGYcozPiiAnXXyEiIiIiIiI9kX6aE+lKVQfMg6ALPjA/yne273EDzoSkEaf88vVNbrYWu/zO/iksrwlYFxFqZVR6q6lfA+JIc0Rg6eAwSkRERERERIJDgZBIZ6qtgD0fQUFzCFS29YgFFtreLnaEmOQTfmnDMNhzqMYb/GzcW0F+sZNGd+DrDe4f7T33Z2xmHMNTYgm1dd5EMhEREREREQkuBUIiHamhGgo/8XUAlWz2nwQG5vj37OnmR+YZ8Kep5gHSbQZDFnPa2MApx33pipoGb/izqXnr1+GaxoB1CdFhvqlfA8ytX47I0JN7vyIiIiIiItIjKRASORWNdbDvc982sH3rwHNECJMw1BcAZZ0F0Yn+9+c8ivHS9RhA654cD2b/kGXOI2C1+T2kocnDl6UuM/xpPvun4GB1QHlhIVZGptmbz/7px7jMODL6RWrrl4iIiIiISB+nQEjkRLiboHgjFKw2A6C9n0FTnf8aR6Y5ASx7OmRPMzt8jmG553Rea/gx94Y+S5ql3Hu91Ejg/sbruNR9OrnlNWxsDn827T1MXrGLhiZPwHNlJ0b7un8y4xiRaicsRFu/RERERERExJ/FMIx2HGDSe7hcLhwOB06nE7vdHuxypLvzeGD/luYtYGtgz8fQUOm/Jia5VQfQNOiX1e5JYG6PwVmPrqTEWYcVD5OsX5JEBWXEsdZzGh6sWC3gaeO7NC4qlDEZcX6Tv+Kiwk79PYuIiIiIiEiPdCKZhzqERFozDDi4vTkAWg27P4Taw/5rIvuZwU9LCJQ47KRHwa8tOESJ0+ww8mDlU09OwBqPATYr5KY5vOf+jM3sR1ZClLZ+iYiIiIiIyElRICR9m2HA4d1mANRyDlDVfv81YTEwcKovAErOBevJbcNqaPKwtdjJ+j2HWbf7MB/tONiuxz165WiumpB5Uq8pIiIiIiIiciQFQtKzedzmNq6q/ebWrYFTAg5gDuAq9o2BL/gAnIX+90MiYMCZzV1AMyBtLNhObgpXRU2DGf7sOcz6PYfZvLeC+jbO/jme9Liok3p9ERERERERkbYoEJKeK/91WH6nGfC0sKfBnEchZ67vWvVBX/dPwRo49LX/81hDION0XwdQxukQEn7C5RiGQcHBatY3hz/r9hxmR1lVwLp+UaFMGNiPCQPjGTcgjvkvbGS/q/5oQ+dJcUQwKTv+hOsRERERERERORoFQtIz5b8OL10PR8YorhLz+lm3m9O/Cj6A/Xn+ayxWSB3rmwI2YDKERZ9wCfVNbvKKnKzbbYY/G/Yc5lB1Q8C6Qf2jmTiwHxMHxjMhqx+DEqP9zv65b+5Ibn1uA5Yj3k3LioWX5GCz6qwgERERERER6TiaMiY9j8cNT+b6dwYdT9JIXwfQwCkQGXfCL3uoqt7b/bN+z2G+KHIGjH4PC7EyJsPBhIHxzV1A/YiPPv7kr+V5JSx6I997wDRAqiOChZfkMCc39YRrFRERERERkb5HU8akd9vzcfvCoGEXwOirzbOAYvqf0EsYhsHOA9Ws31POut1mALTrYHXAuoToMCYM7MfELHMLWG66nfCQ45xh1IY5uamcm5PC2oJyyirrSIo1t4mpM0hEREREREQ6gwIh6RkMA/Zvha/+Cxufa99jRl0FuVe0a2ldo5sv9jlZt6ec9bsPs77wMBU1jQHrhibFeMOfCQM7dvS7zWph8uCEDnkuERERERERkWNRICTdl7sR9nxkhkBfLYOKwuM/prWY5KPeOlBZ7+v+KTxMXpGTRrf/7smIUCtjMuK8HUDjB/QjLur4279EREREREREujsFQtK91FbAjnfNAOjrd6He6bsXEgGDZsGw82HVIxhV+7G0MZvLwILFnmaeFQR4PAY7DlQ1H/5czvo9h9lzqCbgcf1jw5nYfO7PxKx4clLthIVYO+udioiIiIiIiASNAiEJvsN7fF1Aez4CT5PvXlQiDJ8Dwy+CQTMhLAqAjYesjPn4Ngyg9TE7HgPA4K20H7N71S7v9C9XXavnBCwWGJ4c6z34eeLAeDLjIzts+5eIiIiIiIhId6ZASE6dx20e9Fy139ymNXAKWI9xsLLHAyUbzRDoy2VQttX/fv/TYPgFMPxCSJ8Q8Fxuj8EPNmQwunE+C0OfJY1y771SEljUeB1vb8oAtnuvR4baGJsZ13z+Tz/GDeiHIzK0I969iIiIiIiISI+jQEhOTf7rsPxO/6lf9jSY8yjkzPVda6yFgg/MLqCvlkNVqe+exQoDpjSHQBdAwuCjvlxFTQMvfr6XEmcdJUxiRf1EJlm/JIkKyohjrec0PJjbvM4cFM/5I1OYODCe01JjCbVp+5eIiIiIiIgIKBCSU5H/Orx0PRx5jo+rxLx+6R/Nz79aBjtXQmOrc3vCYmDIbHMr2NBzISo+4OlrGprIK3Lxxb4KNu9z8sW+ioCzfzxY+dST02Z535o0gEvHpp/KOxQRERERERHplRQIycnxuM3OoDYOdfZe+88P/C/b031dQFnTICTce6uhycOXpS4z+NlbwRf7nHxdVtl8JpC/ZHs4+131xy0xKTai/e9HREREREREpA9RICQnZ8/H/tvEjqbfIBh9tRkCpY4BiwW3x2DXgSo27zvg7f7ZVuyiwe0JeHiKPYLRGQ7GZMYxOsPB6PQ4YiJCOOvRlZQ669qMoyxAiiOCSdmBXUciIiIiIiIiokBITpRhwMHtsPHv7Vs+6+fsy7iIzfsq+GLTl2zeW0FekZPqBnfA2rioUEalOxiTEecNgJLtbXf5LLwkh1uf24AF/x4lS6v7NqsmhomIiIiIiIi0RYFQX3Uik8FqK6BgNex4F3asBNe+dr/Mza/u493a9wOuR4XZyE1zmF0/mXGMyXAwID6q3WPf5+SmsuTa8Sx6I58SZ533eoojgoWX5DAnN7XdNYqIiIiIiIj0NQqE+qL81zGW34ml1ZYvw56GpWUymMcNxRthx3uw8z3Ytw6MVh09tnAqEidgLd1EDDW01YjjMcwR8CvrhhBqszAi1W6GPxlxjMmIY0hSzCl38MzJTeXcnBTWFpRTVllHUqy5TUydQSIiIiIiIiLHZjEMo61jWHotl8uFw+HA6XRit9uDXU7Hak/XT/7rGC9dj4FB6yHsHsztVpbMM8wtYbWH/R7mjh9KSf+pbAgdxzvVQ/hoTw2T6j5iSeiTAH6hUMtB0Lc2zid39rV8b8YgwkOO0n0kIiIiIiIiIh3iRDIPdQj1Fsfr+gHwuKl946eEG0ZAV483HNr7GQBNobHscUzkE8tY/u06jQ3FseB9aicAbzOJWxvnszD0WdIo9z5XKQksaryOtz2TuCErXmGQiIiIiIiISDejQKgnOrITqOYQxr9uwMCgdc5juIrhpeuxXP0sDJmNe+3/EVlbCsfZUXVvw3f4R905uCv9g5xBidHkppvn/uSk2rn9pU2845rEivqJTLJ+SRIVlBHHWs9pGFhJ1aQvERERERERkW5JgVBP00YnkAcrlqN0/RiGgeflG7EaBjajqV0vUUEsAxPt5KY7GJXuYFSGg5FpdmIjQv3WLZo7kluf24CBlU89Od7rmvQlIiIiIiIi0r0pEOpJWp3/0zpmseI5atePxQIWTyMABww7/S2u477MZdPH8/s5M4+7TpO+RERERERERHomBUI9xTHO/2mP+xqv41n3eXwY/mNSKD/mZLDIwdPa/bya9CUiIiIiIiLS81iPv6RzLV68mOzsbCIiIpgwYQJr1qw55vrVq1czYcIEIiIiGDRoEH/605+6qNLgcu/+iMja0pMKgwCGjZ7MZ/ecz+9DbwJ8k8BatHz++9D/YdLg/if03DarhcmDE7h0bDqTBycoDBIRERERERHp5oIaCL344ovMnz+fe+65h40bNzJt2jQuuOACCgsL21xfUFDAhRdeyLRp09i4cSM///nPue2223jllVe6uPKut3PXzpN6nMeAYiOB7PHn0j82nJmX3cgPGudTiv9hz6Uk8IPG+cy87EYFOiIiIiIiIiK9nMUwDOP4yzrHGWecwfjx41myZIn32ogRI7jssst4+OGHA9bfeeedvP7662zbts177ZZbbmHz5s188skn7XpNl8uFw+HA6XRit9tP/U10kQ9XvMpZH91wQo9p6fr5eejPePDnP/cGPcvzSvjV61vIrNrsnQy2N2YMv5w7Suf+iIiIiIiIiPRQJ5J5BO0MoYaGBtavX89dd93ld/28887j448/bvMxn3zyCeedd57ftfPPP5+nn36axsZGQkNDAx5TX19PfX2993OX6/iHKndHtqypFH8Yf8zzfwys2Cwe77VSEri/8Tou+4Z/14/v3J8JOvdHREREREREpA8KWiB08OBB3G43ycnJfteTk5MpLS1t8zGlpaVtrm9qauLgwYOkpgZ2tzz88MMsWrSo4woPkkmD+3NP6E081PgYHgO/UKilE+h/m35EuWH37/r5RttdPy3n/oiIiIiIiIhI3xP0KWMWi39XimEYAdeOt76t6y3uvvtuFixY4P3c5XKRmZl5suUGjc1qMc//+WcD94Y+Sxrl3nstnUBzv/l9+kWHq+tHRERERERERI4paIFQYmIiNpstoBuorKwsoAuoRUpKSpvrQ0JCSEhou9slPDyc8PDwjik6yObkpsI1t/CN16cGnv9zlE4gEREREREREZEjBS0QCgsLY8KECaxYsYLLL7/ce33FihVceumlbT5m8uTJvPHGG37X3nnnHSZOnNjm+UG9kc7/EREREREREZFTFdQtYwsWLOC6665j4sSJTJ48mT//+c8UFhZyyy23AOZ2r6KiIp599lnAnCj2hz/8gQULFnDzzTfzySef8PTTT/P8888H8210OZ3/IyIiIiIiIiKnIqiB0Lx58zh06BD3338/JSUl5ObmsmzZMgYOHAhASUkJhYWF3vXZ2dksW7aM22+/nT/+8Y+kpaXx+9//niuvvDJYb0FEREREREREpMexGC2nMvcRLpcLh8OB0+nEbrcHuxwRERERERERkQ5xIpmHtYtqEhERERERERGRbkKBkIiIiIiIiIhIH6NASERERERERESkj1EgJCIiIiIiIiLSxwR1ylgwtJyh7XK5glyJiIiIiIiIiEjHack62jM/rM8FQpWVlQBkZmYGuRIRERERERERkY5XWVmJw+E45po+N3be4/FQXFxMbGwsFosl2OUEcLlcZGZmsnfv3uOOiBPpS/S9IdI2fW+IHJ2+P0Tapu8Nkbb1hu8NwzCorKwkLS0Nq/XYpwT1uQ4hq9VKRkZGsMs4Lrvd3mP/AIp0Jn1viLRN3xsiR6fvD5G26XtDpG09/XvjeJ1BLXSotIiIiIiIiIhIH6NASERERERERESkj1Eg1M2Eh4ezcOFCwsPDg12KSLei7w2Rtul7Q+To9P0h0jZ9b4i0ra99b/S5Q6VFRERERERERPo6dQiJiIiIiIiIiPQxCoRERERERERERPoYBUIiIiIiIiIiIn2MAiERERERERERkT5GgVA3snjxYrKzs4mIiGDChAmsWbMm2CWJdJiHH36Y008/ndjYWJKSkrjsssv46quv/NYYhsF9991HWloakZGRzJw5k61bt/qtqa+v53//939JTEwkOjqauXPnsm/fPr81hw8f5rrrrsPhcOBwOLjuuuuoqKjo7Lco0iEefvhhLBYL8+fP917T94b0ZUVFRVx77bUkJCQQFRXF2LFjWb9+vfe+vj+kL2pqauIXv/gF2dnZREZGMmjQIO6//348Ho93jb43pC/44IMPuOSSS0hLS8NisfDaa6/53e/K74PCwkIuueQSoqOjSUxM5LbbbqOhoaEz3nbHMaRbeOGFF4zQ0FDjL3/5i5Gfn2/8+Mc/NqKjo409e/YEuzSRDnH++ecbS5cuNfLy8oxNmzYZF110kTFgwACjqqrKu+aRRx4xYmNjjVdeecXYsmWLMW/ePCM1NdVwuVzeNbfccouRnp5urFixwtiwYYMxa9YsY8yYMUZTU5N3zZw5/7+9ew+Kqn7/AP5eFrnrcjF2QQSvibqSCKmoSOYFRpkwJjVDgZy8NCKaqWg0YoaXMp3MTLMxbLwyjdSoOQqIYAqBggZqoiaiQyBpiE7chH2+fzSenyvkz0wuue/XzM5wPp9nP+c5B57Z4Zlz9gSJXq+XzMxMyczMFL1eL8HBwS16vERPIicnR7p06SJeXl4yd+5cZZy1Qabqjz/+EA8PD4mMjJTs7GwpKiqS1NRUuXz5shLD+iBTFB8fL05OTnLgwAEpKiqSb7/9Vuzs7OTTTz9VYlgbZAoOHjwosbGxsnfvXgEg3333ndF8S9VBfX296PV6GTFihOTl5UlKSoq4urpKVFRUs5+Df4MNoTZi4MCBMmvWLKMxT09PWbx4cStlRNS8ysvLBYBkZGSIiIjBYBCdTierV69WYmpqakSj0cjmzZtFROT27dvSrl072bNnjxJTUlIiZmZmcujQIREROX/+vACQn376SYnJysoSAHLhwoWWODSiJ3L37l3p2bOnpKSkSEBAgNIQYm2QKYuJiZFhw4b97Tzrg0zVuHHjZNq0aUZjoaGhMmXKFBFhbZBpergh1JJ1cPDgQTEzM5OSkhIlZvfu3WJpaSmVlZXNcrxPA28ZawPq6uqQm5uLMWPGGI2PGTMGmZmZrZQVUfOqrKwEADg6OgIAioqKUFZWZlQHlpaWCAgIUOogNzcX9+7dM4pxdXWFXq9XYrKysqDRaDBo0CAlZvDgwdBoNKwnatNmz56NcePGYdSoUUbjrA0yZfv27YOvry8mTJgAZ2dneHt746uvvlLmWR9kqoYNG4YjR47g4sWLAICff/4Zx48fx9ixYwGwNoiAlq2DrKws6PV6uLq6KjGBgYGora01us25rTFv7QQIuHnzJhoaGqDVao3GtVotysrKWikrouYjIpg/fz6GDRsGvV4PAMrfelN1UFxcrMRYWFjAwcGhUcz995eVlcHZ2bnRPp2dnVlP1Gbt2bMHeXl5OHnyZKM51gaZsitXrmDTpk2YP38+3nvvPeTk5CA6OhqWlpYIDw9nfZDJiomJQWVlJTw9PaFWq9HQ0IAVK1Zg8uTJAPjZQQS0bB2UlZU12o+DgwMsLCzadK2wIdSGqFQqo20RaTRG9CyIiopCfn4+jh8/3mjuSerg4Zim4llP1FZdv34dc+fORXJyMqysrP42jrVBpshgMMDX1xcrV64EAHh7e+PcuXPYtGkTwsPDlTjWB5maxMRE7NixA7t27ULfvn1x5swZzJs3D66uroiIiFDiWBtELVcH/8Va4S1jbUDHjh2hVqsbdQ7Ly8sbdRmJ/uvmzJmDffv24ejRo3Bzc1PGdTodADyyDnQ6Herq6lBRUfHImBs3bjTa7++//856ojYpNzcX5eXl8PHxgbm5OczNzZGRkYHPPvsM5ubmyt8ta4NMkYuLC/r06WM01rt3b1y7dg0APzvIdC1cuBCLFy/G66+/jn79+mHq1Kl45513sGrVKgCsDSKgZetAp9M12k9FRQXu3bvXpmuFDaE2wMLCAj4+PkhJSTEaT0lJwZAhQ1opK6KnS0QQFRWFpKQkpKWloWvXrkbzXbt2hU6nM6qDuro6ZGRkKHXg4+ODdu3aGcWUlpbi7NmzSoyfnx8qKyuRk5OjxGRnZ6OyspL1RG3SyJEjUVBQgDNnzigvX19fhIWF4cyZM+jWrRtrg0zW0KFDUVhYaDR28eJFeHh4AOBnB5muqqoqmJkZ/yunVquVx86zNohatg78/Pxw9uxZlJaWKjHJycmwtLSEj49Psx7nv9LCX2JNf+P+Y+e3bt0q58+fl3nz5omtra1cvXq1tVMjeirefvtt0Wg0kp6eLqWlpcqrqqpKiVm9erVoNBpJSkqSgoICmTx5cpOPhXRzc5PU1FTJy8uTl19+ucnHQnp5eUlWVpZkZWVJv379+HhU+k958CljIqwNMl05OTlibm4uK1askEuXLsnOnTvFxsZGduzYocSwPsgURURESKdOnZTHziclJUnHjh1l0aJFSgxrg0zB3bt35fTp03L69GkBIOvWrZPTp09LcXGxiLRcHdx/7PzIkSMlLy9PUlNTxc3NjY+dp8e3ceNG8fDwEAsLCxkwYIDyOG6iZwGAJl8JCQlKjMFgkLi4ONHpdGJpaSnDhw+XgoICo3Wqq6slKipKHB0dxdraWoKDg+XatWtGMbdu3ZKwsDBp3769tG/fXsLCwqSioqIFjpLo6Xi4IcTaIFO2f/9+0ev1YmlpKZ6enrJlyxajedYHmaI7d+7I3Llzxd3dXaysrKRbt24SGxsrtbW1Sgxrg0zB0aNHm/wfIyIiQkRatg6Ki4tl3LhxYm1tLY6OjhIVFSU1NTXNefj/mkpEpHWuTSIiIiIiIiIiotbA7xAiIiIiIiIiIjIxbAgREREREREREZkYNoSIiIiIiIiIiEwMG0JERERERERERCaGDSEiIiIiIiIiIhPDhhARERERERERkYlhQ4iIiIiIiIiIyMSwIUREREREREREZGLYECIiIqI2YdmyZejfv39rp/FE0tPToVKpcPv27dZOpcWZ8rETERH9l7EhRERERM1OpVI98hUZGYkFCxbgyJEjrZ3qExkyZAhKS0uh0WiaZf220nR56aWXMG/evFbNgYiIiJ4O89ZOgIiIiJ59paWlys+JiYlYunQpCgsLlTFra2vY2dnBzs6uNdL7V+7duwcLCwvodLrWToWIiIjosfEKISIiImp2Op1OeWk0GqhUqkZjD98yFhkZifHjx2PlypXQarWwt7fHBx98gPr6eixcuBCOjo5wc3PD119/bbSvkpISTJo0CQ4ODnByckJISAiuXr2qzKenp2PgwIGwtbWFvb09hg4diuLiYmV+//798PHxgZWVFbp166bs8z6VSoXNmzcjJCQEtra2iI+Pb/IKnszMTAwfPhzW1tbo3LkzoqOj8eeffyrzX3zxBXr27AkrKytotVq89tprT3x+6+rqsGjRInTq1Am2trYYNGgQ0tPTlflt27bB3t4ehw8fRu/evWFnZ4egoCCjRl19fT2io6Nhb28PJycnxMTEICIiAuPHj1d+HxkZGVi/fr1yZdeD5zU3Nxe+vr6wsbHBkCFDjBp+RERE1PawIURERERtVlpaGn777TccO3YM69atw7JlyxAcHAwHBwdkZ2dj1qxZmDVrFq5fvw4AqKqqwogRI2BnZ4djx47h+PHjSvOjrq4O9fX1GD9+PAICApCfn4+srCzMmDEDKpUKAHD48GFMmTIF0dHROH/+PL788kts27YNK1asMMorLi4OISEhKCgowLRp0xrlXVBQgMDAQISGhiI/Px+JiYk4fvw4oqKiAACnTp1CdHQ0li9fjsLCQhw6dAjDhw9/4vP05ptv4sSJE9izZw/y8/MxYcIEBAUF4dKlS0pMVVUVPvnkE2zfvh3Hjh3DtWvXsGDBAmX+o48+ws6dO5GQkIATJ07gzp07+P7775X59evXw8/PD9OnT0dpaSlKS0vRuXNnZT42NhZr167FqVOnYG5u3uR5ISIiojZEiIiIiFpQQkKCaDSaRuNxcXHywgsvKNsRERHi4eEhDQ0NylivXr3E399f2a6vrxdbW1vZvXu3iIhs3bpVevXqJQaDQYmpra0Va2trOXz4sNy6dUsASHp6epO5+fv7y8qVK43Gtm/fLi4uLso2AJk3b55RzNGjRwWAVFRUiIjI1KlTZcaMGUYxP/74o5iZmUl1dbXs3btXOnToIHfu3Gkyj4c9vP6DLl++LCqVSkpKSozGR44cKUuWLBGRv845ALl8+bIyv3HjRtFqtcq2VquVNWvWKNv19fXi7u4uISEhylhAQIDMnTu3ydxSU1OVsR9++EEASHV19WMdHxEREbU8focQERERtVl9+/aFmdn/XdCs1Wqh1+uVbbVaDScnJ5SXlwP467aly5cvo3379kbr1NTU4Ndff8WYMWMQGRmJwMBAjB49GqNGjcLEiRPh4uKivP/kyZNGVwQ1NDSgpqYGVVVVsLGxAQD4+vo+Mu/7eezcuVMZExEYDAYUFRVh9OjR8PDwQLdu3RAUFISgoCC8+uqryvr/RF5eHkQEzz//vNF4bW0tnJyclG0bGxt0795d2XZxcVHOW2VlJW7cuIGBAwcq82q1Gj4+PjAYDI+Vh5eXl9HaAFBeXg53d/d/fExERETU/NgQIiIiojarXbt2RtsqlarJsftNC4PBAB8fH6NGzH3PPfccACAhIQHR0dE4dOgQEhMT8f777yMlJQWDBw+GwWDABx98gNDQ0Ebvt7KyUn62tbV9ZN4GgwEzZ85EdHR0ozl3d3dYWFggLy8P6enpSE5OxtKlS7Fs2TKcPHkS9vb2j1y7qX2p1Wrk5uZCrVYbzT34Jd1NnTcRaTT2oIfnH+XB9e+v87jNJCIiImp5bAgRERHRM2PAgAFITEyEs7MzOnTo8Ldx3t7e8Pb2xpIlS+Dn54ddu3Zh8ODBGDBgAAoLC9GjR49/nce5c+ceuY65uTlGjRqFUaNGIS4uDvb29khLS2uyGfUo3t7eaGhoQHl5Ofz9/Z8oX41GA61Wi5ycHGWNhoYGnD592uiLvi0sLNDQ0PBE+yAiIqK2hQ0hIiIiemaEhYVhzZo1CAkJwfLly+Hm5oZr164hKSkJCxcuxL1797Blyxa88sorcHV1RWFhIS5evIjw8HAAwNKlSxEcHIzOnTtjwoQJMDMzQ35+PgoKChAfH//YecTExGDw4MGYPXs2pk+fDltbW/zyyy9ISUnBhg0bcODAAVy5cgXDhw+Hg4MDDh48CIPBgF69ej1y3YKCgka3w/Xv3x9hYWEIDw/H2rVr4e3tjZs3byItLQ39+vXD2LFjHyvnOXPmYNWqVejRowc8PT2xYcMGVFRUGF011KVLF2RnZ+Pq1auws7ODo6PjY58TIiIialvYECIiIqJnho2NDY4dO4aYmBiEhobi7t276NSpE0aOHIkOHTqguroaFy5cwDfffINbt27BxcUFUVFRmDlzJgAgMDAQBw4cwPLly/Hxxx+jXbt28PT0xFtvvfWP8vDy8kJGRgZiY2Ph7+8PEUH37t0xadIkAIC9vT2SkpKwbNky1NTUoGfPnti9ezf69u37yHWbehKZiCAhIQHx8fF49913UVJSAicnJ/j5+T12Mwj4q4lVVlaG8PBwqNVqzJgxA4GBgUa3oS1YsAARERHo06cPqqurUVRU9NjrExERUduikn9yczgRERERmQSDwYDevXtj4sSJ+PDDD1s7HSIiInrKeIUQEREREaG4uBjJyckICAhAbW0tPv/8cxQVFeGNN95o7dSIiIioGZj9/yFERERE9KwzMzPDtm3b8OKLL2Lo0KEoKChAamoqevfu3dqpERERUTPgLWNERERERERERCaGVwgREREREREREZkYNoSIiIiIiIiIiEwMG0JERERERERERCaGDSEiIiIiIiIiIhPDhhARERERERERkYlhQ4iIiIiIiIiIyMSwIUREREREREREZGLYECIiIiIiIiIiMjH/A0IBe3QcOOGtAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 1400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(14,4))\n",
"colors = ['blue', 'orange']\n",
"names = ['Current Rewrites', 'PR Rewrites']\n",
"for i in range(2):\n",
" ax.plot(time_steps, [x[i].average for x in results], marker='o', c=f'tab:{colors[i]}', label=names[i])\n",
" ax.vlines(time_steps, ymin=[x[i].average - 1.96 * x[i].stdev for x in results], ymax=[x[i].average + 1.96 * x[i].stdev for x in results],\n",
" color=f'tab:{colors[i]}')\n",
"ax.set(xlabel='Timeseries Length', ylabel='Seconds', title='Kalman Filter Speed Tests')\n",
"ax.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "5ffc1e86-78e9-4aea-81bb-a9f972dc417a",
"metadata": {},
"source": [
"## Performance over state space size"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "2f1f9108-f98b-4e77-b9ac-447fba35ce1a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"68.4 ms ± 1.92 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"83 ms ± 673 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"299 ms ± 132 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"420 ms ± 39.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"1.26 s ± 568 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"1.8 s ± 573 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"3.54 s ± 990 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"4.46 s ± 576 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"7.51 s ± 1.68 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"8.45 s ± 974 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"12.2 s ± 1.42 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"15 s ± 2.02 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"21.8 s ± 1.77 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"26.7 s ± 1.99 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"33.5 s ± 1.29 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"36.5 s ± 2.5 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"45.6 s ± 2.8 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"46.6 s ± 3.13 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"49.2 s ± 3.35 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"1min 10s ± 7.29 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
"source": [
"matrix_sizes = np.linspace(10, 1000, 10, dtype='int')\n",
"matrix_size_results = []\n",
"n_states = []\n",
"\n",
"for N in matrix_sizes:\n",
" inputs_np = f_trajectory(N, 1000)\n",
" n_states.append(inputs_np[1].shape[0])\n",
" \n",
" res_now = %timeit -o f(*inputs_np)\n",
" res_PR = %timeit -o f2(*inputs_np)\n",
" matrix_size_results.append((res_now, res_PR))\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "adb65f0e-8510-4021-8637-56770fa52a56",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABIAAAAGHCAYAAADIlSlFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACR+0lEQVR4nOzdd3hUZd7G8e/MJJn0CQmk0UsCBJAighRpUmKh29a+u5ZVdxWxYAdcBdG1vLsqlt1FXdeuFBUpCkFZLCgQOoj0FAKEFNIzc94/JplkSCCFJJOE+3NduWbOeU75TQ5gcvsUk2EYBiIiIiIiIiIi0myZPV2AiIiIiIiIiIjULwVAIiIiIiIiIiLNnAIgEREREREREZFmTgGQiIiIiIiIiEgzpwBIRERERERERKSZUwAkIiIiIiIiItLMKQASEREREREREWnmFACJiIiIiIiIiDRzCoBERERERERERJo5BUAiIiJNyFtvvYXJZOLnn39223/s2DH69+9PYGAgK1eurNE1Z82ahclkqssyG0xp7ZV9vfzyyyQkJGAymUhISKhwTnmvvvoqb731VoPWXlRUxOuvv84FF1xAaGgo/v7+tG/fnokTJ7Jw4cIGraWm9u/fj8lkOuP3rEOHDqd9NuW/6ur7PmfOHBYtWlQn1xIREWmOvDxdgIiIiJydw4cPM2bMGI4cOcLXX3/NhRde6OmSGtyyZcuw2Wxu+zp27Iifnx/ff/89cXFxZzz/1VdfpWXLltx88831WKW7G264gc8++4xp06Yxe/ZsrFYre/fuZdmyZSxfvpzJkyc3WC31YeHChRQUFLi2//nPf/Kvf/2rwrPq3Llzndxvzpw5XHHFFUyaNKlOriciItLcKAASERFpwn799VdGjx5NUVERa9asoVevXp4uySPOP/98WrZsWWmbpwIxwzDIz8/Hz8+vQtu+ffv48MMPeeKJJ5g9e7Zr/8UXX8ytt96Kw+FoyFLrRd++fd22ly1bBpz5WYmIiEj90RAwERGRJmrTpk0MHToULy8v1q5dWyH8+fDDDxk7dixRUVH4+fnRvXt3HnroIXJycqq8docOHbj88sv54osv6Nu3r+v8L774AnAORevevTsBAQEMGDCgwpC0n3/+mWuuuYYOHTrg5+dHhw4d+N3vfseBAwfcjisd0rZ69WruuOMOWrZsSVhYGFOmTCE5Ofksv0NUOgSsss+6bds21qxZ4xqW1KFDB1d7VlYW999/Px07dsTHx4fWrVszbdq0Ct9Hk8nEn//8Z1577TW6d++O1Wrl7bffrvSex48fByAqKqrSdrO57Ee00s/w7rvvMn36dCIjI/Hz82P48OFs3Lixwrk///wzEyZMIDQ0FF9fX/r27ctHH31U4bjU1FRuv/122rRpg4+PDx07dmT27NkUFxe7HZecnMxVV11FUFAQNpuNq6++mtTU1Mq/mTVkGAavvvoqffr0wc/PjxYtWnDFFVewd+9et+M2btzI5ZdfTnh4OFarlejoaC677DIOHz4MOL/3OTk5vP32265nOGLECAByc3Ndz8/X15fQ0FD69+/P+++/XyefQUREpKlQDyAREZEmaO3atcyaNYu2bduyYsWKSoOEX3/9lUsvvZRp06YREBDAzp07mTdvHj/99BOrVq2q8h6JiYk8/PDDPProo9hsNmbPns2UKVN4+OGH+eabb5gzZw4mk4kZM2Zw+eWXs2/fPldvl/3799O1a1euueYaQkNDSUlJYf78+VxwwQVs3769Qg+QW265hcsuu4z33nuPQ4cO8cADD3D99ddXq04Au93uFlyYTCYsFku1zl24cCFXXHEFNpuNV199FQCr1Qo4w4Phw4dz+PBhHnnkEc477zy2bdvGE088wZYtW/j666/d5hNatGgR3333HU888QSRkZGEh4dXes/u3bsTEhLC7NmzMZvNjB071i10qswjjzxCv379+Oc//0lmZiazZs1ixIgRbNy4kU6dOgGwevVq4uPjGThwIK+99ho2m40PPviAq6++mtzcXNcQt9TUVAYMGIDZbOaJJ56gc+fOfP/99zz11FPs37+fBQsWAJCXl8fo0aNJTk5m7ty5xMbG8uWXX3L11VdX63tbldtvv5233nqLu+++m3nz5pGens6TTz7J4MGDSUxMJCIigpycHMaMGUPHjh155ZVXiIiIIDU1ldWrV5OdnQ3A999/z6hRoxg5ciSPP/44AMHBwQBMnz6d//znPzz11FP07duXnJwctm7d6grhREREzhmGiIiINBkLFiwwAAMwbDabkZaWVq3zHA6HUVRUZKxZs8YAjMTERFfbzJkzjVN/JGjfvr3h5+dnHD582LVv06ZNBmBERUUZOTk5rv2LFi0yAGPJkiWnvX9xcbFx8uRJIyAgwPi///u/Cp/nzjvvdDv+2WefNQAjJSXljJ+rtPZTv1q3bm0YhmGsXr3aAIzVq1ef8fP26NHDGD58eIXrz5071zCbzcb69evd9n/yyScGYCxdutS1r/SZpKenn7HmUl9++aXRsmVLV81hYWHGlVdeWeH7WPoZ+vXrZzgcDtf+/fv3G97e3sYtt9zi2tetWzejb9++RlFRkds1Lr/8ciMqKsqw2+2GYRjG7bffbgQGBhoHDhxwO+5vf/ubARjbtm0zDMMw5s+fbwDG4sWL3Y679dZbDcBYsGBBtT6rYZR9348ePWoYhmF8//33BmA8//zzbscdOnTI8PPzMx588EHDMAzj559/NgBj0aJFZ7x+QECAcdNNN1XY37NnT2PSpEnVrlNERKS50hAwERGRJmjChAlkZmYybdo07HZ7pcfs3buXa6+9lsjISCwWC97e3gwfPhyAHTt2VHmPPn360Lp1a9d29+7dARgxYgT+/v4V9pcf3nXy5ElmzJhBly5d8PLywsvLi8DAQHJyciq994QJE9y2zzvvvArXPJOvv/6a9evXu76WLl1arfOq8sUXX9CzZ0/69OlDcXGx62vcuHGVDi0bNWoULVq0qNa1L730Ug4ePMjChQu5//776dGjB4sWLWLChAn8+c9/rnD8tdde69bbqH379gwePJjVq1cDsGfPHnbu3Ml1110H4FbvpZdeSkpKCrt27XJ9rpEjRxIdHe123CWXXALAmjVrAGePoqCgoArP59prr63WZzyTL774ApPJxPXXX+9WQ2RkJL1793Z9b7t06UKLFi2YMWMGr732Gtu3b6/RfQYMGMBXX33FQw89REJCAnl5eWddu4iISFOkIWAiIiJN0OOPP06fPn148skncTgcvPvuu25Dnk6ePMlFF12Er68vTz31FLGxsfj7+3Po0CGmTJlSrV+CQ0ND3bZ9fHzOuD8/P9+179prr+Wbb77h8ccf54ILLiA4OBiTycSll15a6b3DwsLctkuHYFX3l/XevXvXy8TCR44cYc+ePXh7e1fafuzYMbft083pczp+fn5MmjTJtXLVwYMHueSSS3jllVe444476NGjh+vYyMjICudHRkaSmJjoqhXg/vvv5/777z9jvUeOHOHzzz+v8nMdP36ciIiISu97to4cOYJhGJVeH3ANa7PZbKxZs4ann36aRx55hBMnThAVFcWtt97KY489dtrPUOrvf/87bdq04cMPP2TevHn4+voybtw4nnvuOWJiYs76c4iIiDQVCoBERESaqNmzZ2MymZg9ezYOh4P//ve/eHk5/9O+atUqkpOTSUhIcPX6AcjIyKj3ujIzM/niiy+YOXMmDz30kGt/QUEB6enp9X7/utSyZUv8/Pz497//fdr28sr30KmNdu3acdtttzFt2jS2bdvmFgBVNvFyamqqKzwrreXhhx9mypQplV6/a9eurmPPO+88nn766UqPi46OBpzB3E8//VTpfc9Wy5YtMZlMfPfdd67Ar7zy+3r16sUHH3yAYRhs3ryZt956iyeffBI/Pz+3P2OVCQgIYPbs2cyePZsjR464egONHz+enTt3nvXnEBERaSoUAImIiDRhs2bNwmw2M3PmTAzD4L333sPLy8sVRJz6i/Xrr79e7zWZTCYMw6hw73/+85+nHa7maVartdLeRpdffjlz5swhLCyMjh071tn9srOzMZlMBAYGVmgrHSJXGsKUev/995k+fbrr2R44cIB169Zx4403As5wJyYmhsTERObMmXPG+19++eUsXbqUzp07n3HI2siRI/noo49YsmSJ2zCw9957r3oftIoannnmGZKSkrjqqquqdY7JZKJ37968+OKLvPXWW2zYsMHVdrpnWF5ERAQ333wziYmJvPTSS+Tm5roNZxQREWnOFACJiIg0cU888QRms5nHH38cwzB4//33GTx4MC1atOBPf/oTM2fOxNvbm//+97+u4UL1KTg4mGHDhvHcc8/RsmVLOnTowJo1a/jXv/5FSEhIvd+/Nkp7mHz44Yd06tQJX19fevXqxbRp0/j0008ZNmwY9957L+eddx4Oh4ODBw+yYsUK7rvvPgYOHFjj++3atYtx48ZxzTXXMHz4cKKiojhx4gRffvklb7zxBiNGjGDw4MFu56SlpTF58mRuvfVWMjMzmTlzJr6+vjz88MOuY15//XUuueQSxo0bx80330zr1q1JT09nx44dbNiwgY8//hiAJ598kpUrVzJ48GDuvvtuunbtSn5+Pvv372fp0qW89tprtGnThhtvvJEXX3yRG2+8kaeffpqYmBiWLl3K8uXLz+4bDgwZMoTbbruN3//+9/z8888MGzaMgIAAUlJSWLt2Lb169eKOO+7giy++4NVXX2XSpEl06tQJwzD47LPPyMjIYMyYMa7r9erVi4SEBD7//HOioqIICgqia9euDBw4kMsvv5zzzjuPFi1asGPHDv7zn/8waNAghT8iInJOUQAkIiLSDDz22GOYzWYeffRRHA4HH3zwAV9++SX33Xcf119/PQEBAUycOJEPP/yQfv361Xs97733Hvfccw8PPvggxcXFDBkyhJUrV3LZZZfV+71rY/bs2aSkpHDrrbeSnZ1N+/bt2b9/PwEBAXz33Xc888wzvPHGG66l7tu1a8fo0aOrXLr9dLp06cL06dNZtWoVixcv5ujRo3h7exMTE8NTTz3F9OnTMZvd1+qYM2cO69ev5/e//z1ZWVkMGDCADz74gM6dO7uOGTlyJD/99BNPP/0006ZN48SJE4SFhREXF+fWyyYqKoqff/6Zv/71rzz33HMcPnyYoKAgOnbsSHx8vKtXkL+/P6tWreKee+7hoYcewmQyMXbsWD744IMKAVVtvP7661x44YW8/vrrvPrqqzgcDqKjoxkyZAgDBgwAICYmhpCQEJ599lmSk5Px8fGha9euvPXWW9x0002ua/3f//0fd911F9dccw25ubkMHz6chIQERo0axZIlS3jxxRfJzc2ldevW3HjjjTz66KNnXb+IiEhTYjIMw/B0ESIiIiJSuYSEBEaOHMnHH3/MFVdc4elyREREpInSMvAiIiIiIiIiIs2cAiARERERERERkWZOQ8BERERERERERJo59QASEREREREREWnmFACJiIiIiIiIiDRzCoBERERERERERJo5L08XUN8cDgfJyckEBQVhMpk8XY6IiIiIiIiISJ0wDIPs7Gyio6Mxm8/cx6fZB0DJycm0bdvW02WIiIiIiIiIiNSLQ4cO0aZNmzMe0+wDoKCgIMD5zQgODvZwNSIiIiIiIiIidSMrK4u2bdu6so8zafYBUOmwr+DgYAVAIiIiIiIiItLsVGfKG00CLSIiIiIiIiLSzCkAEhERERERERFp5hQAiYiIiIiIiIg0c81+DiARERERERGRmrDb7RQVFXm6DBEsFgteXl7VmuOnKgqAREREREREREqcPHmSw4cPYxiGp0sRAcDf35+oqCh8fHzO6joKgERERERERERw9vw5fPgw/v7+tGrVqk56XYjUlmEYFBYWcvToUfbt20dMTAxmc+1n8lEAJCIiIiIiIgIUFRVhGAatWrXCz8/P0+WI4Ofnh7e3NwcOHKCwsBBf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y7333suKFSuYMmUKCxYsqPH9a0IBkIiIiIiIiEgdiO8Zxfzr+xFp83XbH2nzZf71/YjvGXWaM8/Oq6++it1uZ8CAAXz66af8+uuv7Nixg7///e8MGjQIcM5Xc+GFF/LMM8+wfft2vv32Wx577LFa3/Ouu+4iPT2d3/3ud/z000/s3buXFStW8Ic//KFGgU6HDh345ptvSE1N5cSJEzWq4b777uPzzz/n559/ZvTo0QwaNIhJkyaxfPly9u/fz7p163jsscfcVtcaMWIE7777LsOHDcNkMtEiJJi4uDg+/PBDRowYUaP7l9a/b98+Nm3axLFjxygoKKiylry8PP785z+TkJDAgQMH+N///sf69esr9D6qawqAREREREREROpIfM8o1s4Yxfu3Xsj/XdOH92+9kLUzRtVb+APQsWNHNmzYwMiRI7nvvvvo2bMnY8aM4ZtvvmH+/Pmu4/79739TVFRE//79ueeee3jqqadqfc/o6Gj+97//YbfbGTduHD179uSee+7BZrO5hptVx/PPP8/KlStp27Ytffv2rVENvXr1YvTo0TzxxBOYTCaWLl3KsGHD+MMf/kBsbCzXXHMN+/fvJyIiwnXOyJEjsdvtjBhR1ttn+LBh2O32WvUAmjp1KvHx8YwcOZJWrVrx/vvvV1mLxWLh+PHj3HjjjcTGxnLVVVdxySWXMHv27BrfvyZMRvkBgM1QVlYWNpuNzMxMgoODPV2OiIiIiIiINFL5+fns27ePjh074uvrW/UJ0nQ57JDqXAqeyPPAXL1Jtz3hTH8ua5J5qAeQiIiIiIiIiEgz59EAqLi4mMcee4yOHTvi5+dHp06dePLJJ91mBDcMg1mzZhEdHY2fnx8jRoxg27ZtHqxaRERERERERKRp8WgANG/ePF577TVefvllduzYwbPPPstzzz3HP/7xD9cxzz77LC+88AIvv/wy69evJzIykjFjxpCdne3BykVEREREREREmg4vT978+++/Z+LEiVx22WWAc/bs999/3zVDt2EYvPTSSzz66KNMmTIFgLfffpuIiAjee+89br/99grXLCgooKCgwLWdlZXVAJ9ERERERERERKTx8mgPoKFDh/LNN9+we/duABITE1m7di2XXnopAPv27SM1NZWxY8e6zrFarQwfPpx169ZVes25c+dis9lcX23btq3/DyIiIiIiIiIi0oh5tAfQjBkzyMzMpFu3blgsFux2O08//TS/+93vAEhNTQVwW7KtdPvAgQOVXvPhhx9m+vTpru2srCyFQCIiIiIiIiJyTvNoAPThhx/y7rvv8t5779GjRw82bdrEtGnTiI6O5qabbnIdZzKZ3M4zDKPCvlJWqxWr1VqvdYuIiIiIiIiINCUeDYAeeOABHnroIa655hoAevXqxYEDB5g7dy433XQTkZGRgLMnUFRUlOu8tLS0Cr2CRERERERERESkch6dAyg3Nxez2b0Ei8XiWga+Y8eOREZGsnLlSld7YWEha9asYfDgwQ1aq4iIiIiIiIhIU+XRAGj8+PE8/fTTfPnll+zfv5+FCxfywgsvMHnyZMA59GvatGnMmTOHhQsXsnXrVm6++Wb8/f259tprPVm6iIiIiIiISOUcdtj3HWz5xPnqsHu6oibvrbfeIiQkxNNlNGkeDYD+8Y9/cMUVV3DnnXfSvXt37r//fm6//Xb++te/uo558MEHmTZtGnfeeSf9+/cnKSmJFStWEBQU5MHKRURERERERCqxfQm81BPevhw+/aPz9aWezv315Oabb8ZkMmEymfD29qZTp07cf//95OTkALB//35Xu8lkwmazceGFF/L5559Xee3y5wUGBtK7d2/eeuutevssp3P11Ve7VhAHmDVrFn369GnwOpoyjwZAQUFBvPTSSxw4cIC8vDx+++03nnrqKXx8fFzHmEwmZs2aRUpKCvn5+axZs4aePXt6sGoRERERERGRSmxfAh/dCFnJ7vuzUpz76zEEio+PJyUlhb179/LUU0/x6quvcv/997sd8/XXX5OSksKPP/7IgAEDmDp1Klu3bq3y2gsWLCAlJYXExESuvvpqfv/737N8+fL6+igVFBUV4efnR3h4eIPdsznyaAAkIiIiIiIi0mgZBhTmVO8rPwu+ehAwKruQ82XZDOdx1bmeUdl1Ts9qtRIZGUnbtm259tprue6661i0aJHbMWFhYURGRtKtWzeefvppioqKWL16dZXXDgkJITIyks6dO/PII48QGhrKihUrXO2ZmZncdttthIeHExwczKhRo0hMTHS1WSwWfvnll5JvqUFoaCgXXHCB6/z333/ftfBTaW+ljz76iBEjRuDr68u7777rNgTsrbfeYvbs2SQmJrp6J5X2SjpTLQCJiYmMHDmSIFsIwV0v4vz4a/n5559r9L1uqjy6CpiIiIiIiIhIo1WUC3Oi6+hihrNn0DNtq3f4I8ngE1Dru/n5+VFUVFRpW1FREW+++SYA3t7e1b6m3W7n008/JT093XWeYRhcdtllhIaGsnTpUmw2G6+//joXX3wxu3fvJjQ0lD59+pCQkMD555/P5s2bAdi8eTNZWVkEBweTkJDA8OHD3e41Y8YMnn/+eRYsWIDVanULnK6++mq2bt3KsmXL+PrrrwGw2WzVquW6666jb9++zH/lZSzpe9i0bVeNvgdNmQIgERERERERkWbkp59+4r333uPiiy922z948GDMZjN5eXk4HA46dOjAVVddVeX1fve732GxWMjPz8dutxMaGsott9wCwOrVq9myZQtpaWlYrVYA/va3v7Fo0SI++eQTbrvtNkaMGEFCQgL33XcfCQkJXHzxxezdu5e1a9dy6aWXkpCQwL333ut2z2nTpjFlypRK6/Hz8yMwMBAvLy8iIyNd+1etWlVlLQcPHuSBBx6gW7dukFpITKd2EHle9b+5TZgCIBEREREREZHKePs7e+JUx4F18N8rqj7uuk+g/eDq3bsGvvjiCwIDAykuLqaoqIiJEyfyj3/8w+2YDz/8kG7durF7926mTZvGa6+9RmhoaJXXfvHFFxk9ejSHDh1i+vTp3HvvvXTp0gWAX375hZMnTxIWFuZ2Tuk8vwAjRozgX//6Fw6HgzVr1nDxxRfTrl071qxZQ79+/di9e3eFHkD9+/ev0eevbi3Tp0/nlltu4T//eYfRA3pw5eWj6awASEREREREROQcZjJVfxhW51EQHO2c8LnSeYBMzvbOo8BsqcsqARg5ciTz58/H29ub6OjoSoc1tW3blpiYGGJiYggMDGTq1Kls3769ysmVIyMj6dKlC126dOHjjz+mb9++9O/fn7i4OBwOB1FRUSQkJFQ4r3TOnmHDhpGdnc2GDRv47rvv+Otf/0rbtm2ZM2cOffr0ITw8nO7du7udGxBQ8+Fv1all1qxZXHvttXz5xed8tfgTZj7/Gh+89z6Tp06t8f2aGk0CLSIiIiIiInK2zBaIn1eyYTqlsWQ7/pl6CX/AGZh06dKF9u3bV2tOm+HDh9OzZ0+efvrpGt2nS5cuTJ06lYcffhiAfv36kZqaipeXlyskKv1q2bIl4Jyfp0+fPrz88suYTCbi4uK46KKL2LhxI1988UWF3j/V4ePjg91ud9tXnVoAYmNjuXfaNFa8/ypTLhnFAg8sa+8JCoBERERERERE6kLcBLjqHQiOct8fHO3cHzfBM3Wdxn333cfrr79OUlJSjc/7/PPP+fnnnxk9ejSDBg1i0qRJLF++nP3797Nu3Toee+wxt9W1RowYwbvvvsvw4cMxmUy0aNGCuLg4PvzwQ0aMGFHj2jt06MC+ffvYtGkTx44do6CgoMpa8vLy+POf/0xCQgIHDhzgf+s3sT5xG927d6vx/ZsiBUAiIiIiIiIidSVuAkzbCjd9AVP/5XydtqXRhT8Al19+OR06dKhxL6BevXoxevRonnjiCUwmE0uXLmXYsGH84Q9/IDY2lmuuuYb9+/cTERHhOmfkyJHY7Xa3sGf48OHY7fZa9QCaOnUq8fHxjBw5klatWvH+++9XWYvFYuH48ePceOONxHbrzlV/msElI4cwe9asGt+/KTIZhlHZ4MRmIysrC5vNRmZmJsHBwZ4uR0RERERERBqp/Px89u3bR8eOHfH19fV0OVKfHHZIdS5JT+R59TY0ry6c6c9lTTIP9QASEREREREREWnmFACJiIiIiIiIiDRzCoBERERERERERJo5BUAiIiIiIiIiIs2cAiARERERERGRcpr5WknSxNTVn0cFQCIiIiIiIiKAxeJcCaqwsNDDlYiUyc3NBcDb2/usruNVF8WIiIiIiIiINHVeXl74+/tz9OhRvL29MZvVZ6LZctihuKRnTX5+o1wG3jAMcnNzSUtLIyQkxBVQ1pYCIBERERERERHAZDIRFRXFvn37OHDggKfLkfpkOCDzqPP9SSuYGm/YFxISQmRk5FlfRwGQiIiIiIiISAkfHx9iYmI0DKy5K8yFpVc739/2Lfj4e7ae0/D29j7rnj+lFACJiIiIiIiIlGM2m/H19fV0GVKfzHY4ecj53tcKPs3/eTfePk4iIiIiIiIiIvXBYS97v3+d+3YzpQBIRERERERERM4d25fAKxeUbb93BbzU07m/GVMAJCIiIiIiIiLnhu1L4KMbITvVfX9WinN/Mw6BFACJiIiIiIiISPPnsMOyGYBRSWPJvmUPNdvhYAqARERERERERKT5O7AOspLPcIABWUnO45ohBUAiIiIiIiIi0vydPFK3xzUxCoBEREREREREpPk79mv1jguMqN86PMTL0wWIiIiIiIiIiNSbwhxY9jBseLuKA00QHA3tBzdIWQ1NPYBEREREREREpHlK2QxvjCgJf0zQbbzztYKSffHPgNnScPU1IAVAIiIiIiIiItK8OBzw/Svwz4vh2G4IioIbF8M178JV70BQpPvxwdHO/XETPFNvA9AQMBERERERERFpPk6mwaI7YM/Xzu2ul8HEl8E/1LkdNwE6jYBn2jq3r/0Euoxqtj1/SikAEhEREREREZHm4devYdGfIOcoePnCuDnQ/w9gOmXYV/mwp8PgZh/+gAIgEREREREREWnqigvg69nwwyvO7fAecMW/ILy7Z+tqRBQAiYiIiIiIiEjTdXQ3fPoHSN3i3B5wO4x5Erx9PVtXI6MASERERERERESaHsOADe/AsoegKBf8w2Diq9A13tOVNUoKgERERERERESkack7AZ/fA9sXO7c7jYDJr1dc3UtcFACJiIiIiIiISNNxYB18eitkHQazF1z8BAz6C5jNnq6sUVMAJCIiIiIiIiKNn70Y1syD7/4GhgNCO8PUf0Lrfp6urElQACQiIiIiIiIijduJA/DpLXD4J+d2n+vhknlgDfRsXU2IAiARERERERERaby2fAJf3AsFWWANhstfhF5XeLqqJkcBkIiIiIiIiIg0PgXZ8NUM2PRf53abAc4hXy3ae7auJkoBkIiIiIiIiIg0Lkkb4NM/QvpeMJnhovth+AywKMaoLX3nRERERERERKRxcDhg3d9h1V/BUQzBbWDKG9BhiKcra/IUAImIiIiIiIiI52WnwsLbYW+Cc7v7BJjwd/Br4dGymgsFQCIiIiIiIiLiWbuWweI7Ifc4ePtD/DPQ70YwmTxdWbOhAEhEREREREREPKMoH1Y+AT+97tyO7AVT/w2tYj1bVzOkAEhEREREREREGl7aDvjkj5C2zbl94V0weiZ4WT1bVzOlAEhEREREREREGo5hwM//guWPQnE+BLSCSa9BzGhPV9asKQASERERERERkYaRmw5L/gI7v3BudxkNk+ZDYLhn6zoHKAASERERERERkfq371v47DbITgGLD4yeDQP/BGazpys7JygAEhEREREREZH6Yy+C1XNg7YuAAWExcMW/IKq3pys7pygAEhEREREREZH6kb4XPr0Fkn5xbve7CeLngk+AZ+s6BykAEhEREREREZG6l/ghfHkfFGaDrw3G/x16TPJ0VecsBUAiIiIiIiIiUnfy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76Zt27Z8+eWXdO7cua7rFBERERERkeYofV/JBM5fOSdzdhSXtfm1gJhxzp4+nS8G3+BKL5GdX8RXW1L5bONhfthbNidt6bw+U/q15qKY6s/rI82fv48X+5+5zNNlNKhaBUB33303nTt35ocffiA0NBSA48ePc/3113P33Xfz5Zdf1mmRIiIiIiIi0kw47JD0izPw2fUVHN3h3h4W4+zl0/USaDMALJX/2lpkd/Ddr0f5bEMSK7cfcZvX58JOoUzp24b4XpGa10ekRK0CoDVr1riFPwBhYWE888wzDBkypM6KExERERERkWag4CTsXe0c2rV7GeQeK2szWaDdoLLQJ+z0I0oMw2BLUiafbUji88RkjueUzevTJTyQyX1bM6lva1qH+NXnpxFpkmoVAFmtVrKzsyvsP3nyJD4+PmddlIiIiIiIiDRxmUnOZdp3LYN934K9oKzNaoMuFzsncO5yMfiHnv46lM3r89mGw/x2NMe1v2Vgybw+fdvQs3Ww5vUROYNaBUCXX345t912G//6178YMGAAAD/++CN/+tOfmDBhQp0WKCIiIiIics4ozIE50c73jyRXWM68UXM4IGVT2Xw+qZvd21t0cC7T3vUSaD8YLGcempWVX8RXW1L4bEMSP+5zn9dnbI9IpvRtzdCYlprXR6SaahUA/f3vf+emm25i0KBBeHs7/9IWFxczYcIE/u///q9WhcydO5dHHnmEe+65h5deeglwdu+bPXs2b7zxBidOnGDgwIG88sor9OjRo1b3EBERERERkTpUlAd71zh7+uxeDtkp5RpN0HaAc8WurpdCq65QRQ+d0nl9Pt2QxNeVzevTrw2X9IwkSPP6iNRYrQKgkJAQFi9ezJ49e9ixYweGYRAXF0eXLl1qVcT69et54403OO+889z2P/vss7zwwgu89dZbxMbG8tRTTzFmzBh27dpFUFBQre4lIiIiIiIiZyH7iLOXz+5l8NtqKM4ra/MOgC6jnD19YsZCYKsqL6d5fUQaRq0CoFJdunSpdehT6uTJk1x33XW8+eabPPXUU679hmHw0ksv8eijjzJlyhQA3n77bSIiInjvvfe4/fbbz+q+IiIiIiIiUg2GAUe2OYd17f7KuYJXecFtnMu0x14CHYaCt2+1Lnv4RC6LNyU3/Xl9fALokP8eANub0pA9OefUKgC64oor6N+/Pw899JDb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jo5GYmIiwsLC4O/vr9R98MEHMBqN6NGjBxwcHLB582YYDAblzVqBgYHYvXs3+vfvD2dnZ3h5eWHhwoUYNmwYAgIC8Oyzz8LBwQF5eXnIz8/HO++8c19z+Tfzu6OiogKRkZHo0aMHpkyZgtOnTyt1BoMBzz33HN577z1ERUVh0aJF8Pf3x/Hjx7FlyxYkJiaqzgsRERHZHx8BIyIiokaVk5ODnj17qraFCxfeV1/dunXD3r17UVRUhAEDBqBnz5544403lLWCfHx8kJ6ejs2bN+ORRx7B0qVL8f7779/Xsfr27YuysjJMmzYNXbp0waBBg/DTTz8hMzMTgwYNUrWdNGkSqqqqEB8fryr38PDAu+++i+DgYPTp0wclJSX4+uuv4eBw+yfX8uXLkZ2djYCAAPTs2RMAEB4ejh07diA7Oxt9+vRBSEgIVqxYAbPZfF/zaIz5AcCZM2fw559/4ttvv4Wfnx+MRqOyAYCbmxtyc3NhMpkQHR2Nzp07Iz4+HhUVFbwjiIiI6AGkERGx9yCIiIiI/kvWr1+PWbNm4dSpU9DpdPYeDhEREdE98REwIiIiogYqLy9HcXExlixZgqlTpzL5Q0RERP8ZfASMiIiIqIGWLVuGHj16oHXr1pg7d669h0NERETUYHwEjIiIiIiIiIiomeMdQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzRwTQEREREREREREzdz/ANwRfpg7K2vfAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 1400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(14,4))\n",
"colors = ['blue', 'orange']\n",
"names = ['Current Rewrites', 'PR Rewrites']\n",
"\n",
"for i in range(2):\n",
" ax.plot(n_states, [x[i].average for x in matrix_size_results], marker='o', c=f'tab:{colors[i]}', label=names[i])\n",
" ax.vlines(n_states, ymin=[x[i].average - 1.96 * x[i].stdev for x in matrix_size_results], \n",
" ymax=[x[i].average + 1.96 * x[i].stdev for x in matrix_size_results],\n",
" color=f'tab:{colors[i]}')\n",
"ax.legend()\n",
"ax.set(xticks=np.array(n_states) + 2, xlabel='Linear System Size', ylabel='Seconds', title='Kalman Filter Speed Tests')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b538732f-8857-40e6-8958-9bbd6271b04b",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "7edbfea3-019f-4c7a-b073-1260e55d0863",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment