{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# OLS Linear Regression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{index} OLS Linear Regression\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We begin with the familiar topic of ordinary least squares (OLS) linear regression. The table below shows an excerpt of Chicago Public School data for 2011--2012 from the Chicago Data Portal. One expects a higher average ACT score to be associated with a higher percentage of college eligibility. \n",
"
\n",
"
\n",
"
School zipcode
\n",
"
Average ACT Score
\n",
"
College Eligibility
\n",
"
\n",
"
60605
\n",
"
25.1
\n",
"
80.7
\n",
"
\n",
"
60607
\n",
"
27
\n",
"
91.6
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
60660
\n",
"
16.5
\n",
"
14.2
\n",
"
\n",
"
\n",
"\n",
"\n",
"\n",
"Source: Chicago Data Portal, \n",
"\n",
"https://data.cityofchicago.org/Education/Chicago-Public-Schools-Progress-Report-Cards-2011-/9xs2-f89t\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The figure below shows a scatterplot of $n= 83 $ data points partly reproduced in the above table together with the OLS regression line.\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{index} Least-Squares Solutions\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Least-Squares Solutions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Consider a collection of $n$ data points $(x_1,y_1),(x_2,y_2),\\dots,(x_n,y_n)$ in $\\mathbb{R}^2.$ We seek the line $y=c_0+c_1x$ that best fits these data, where $c_0$ is the $y$-intercept of the line and $c_1$ the slope of the line. As shown in the figure below, an OLS loss function $J(c_0,c_1)$ sums the squared vertical separations between the data points $(x_1,y_1),(x_2,y_2),\\dots,(x_n,y_n)$ and the line $y=c_0+c_1x$.\n",
"\n",
"\n",
" \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"If the $n$ data points are collinear, then there exists an exact solution $(c_0,c_1)$ to the system\n",
"\t\n",
"$$\n",
"c_0 + c_1 x_1 = y_1,\n",
"$$\n",
"\n",
"$$\n",
"c_0+c_1x_2 = y_2,\n",
"$$\n",
"\n",
"$$\\vdots$$\n",
"\n",
"$$\n",
"c_0+c_1 x_n = y_n. \n",
"$$\n",
"\n",
"In matrix form, this system of equations becomes \n",
"\n",
"$$\n",
"\\mathbf{A}\\mathbf{c}=\\mathbf{y}, \n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
" \\mathbf{A}=\n",
"\\begin{pmatrix}\n",
"1& x_1\\\\\n",
"1& x_2\\\\\n",
"\\vdots&\\vdots\\\\\n",
"1& x_n\n",
"\\end{pmatrix},\\quad \\mathbf{c}=\n",
"\\begin{pmatrix}\n",
"c_0\\\\\n",
"c_1\n",
"\\end{pmatrix}, \\quad \\, and \\, \\quad \\mathbf{y}=\n",
"\\begin{pmatrix}\n",
"y_1\\\\\n",
"y_2\\\\\n",
"\\vdots\\\\\n",
"y_n\n",
"\\end{pmatrix}.\n",
"$$\n",
"\n",
"\n",
"In general, this linear system with $n>2$ equations and 2 unknowns ($c_0,c_1$) will not have an exact solution. Instead, our goal to find a linear fit to the data is based on a *least-squares solution*, one that solves the following optimization problem:\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{index} Optimization Problem\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### OLS LINEAR REGRESSION OPTIMIZATION PROBLEM "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::::{admonition} OLS Linear Regression Optimization Problem\n",
":class: tip\n",
"\n",
"Find $(c_0,c_1)$ which minimizes the loss function $J(c_0,c_1)$ defined as\n",
"\n",
"$$\n",
"J(c_0,c_1)=\\tfrac{1}{2}\\sum_{i=1}^n (y_i-(c_0+c_1x_i) )^2=\\tfrac{1}{2}\\|\\mathbf{y} - \\mathbf{A}\\mathbf{c}\\|^2.\n",
"$$\n",
"\n",
"(The factor of 1/2 multiplying the sum is introduced to simplify the theoretical analysis of the loss function.)\n",
"\n",
":::::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The loss function $J$ is zero when the points are collinear and situated on the line $y=c_0+c_1x$; otherwise, $J$ is positive, since it is half the sum of the squared vertical separations between data points and the line $y=c_0+c_1x$, as shown in the previous figure."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{index} Minimizing the OLS Loss Function via Normal Equations\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Minimizing the OLS Loss Function via Normal Equations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let $\\mathbf{A}$ be an $n\\times 2$ matrix of real numbers, and let the linear transformation $\\mathbf{L}:\\mathbb{R}^2\\rightarrow\\mathbb{R}^n$ be defined by $\\mathbf{L}(\\mathbf{c})= \\mathbf{A}\\mathbf{c}$, where $\\mathbf{c}$ is a $2\\times 1$ column vector. The range of $\\mathbf{A}$ is the set of all $n\\times 1$ vectors defined by\n",
"\n",
"$$\n",
"range\\, of \\, \\mathbf{A} = \\{ \\mathbf{A}\\mathbf{c} \\mid \\mathbf{c}\\in\\mathbf{R}^2\\}. \n",
"$$\n",
"\n",
"By choosing $\\mathbf{c}=(1,0)^T$, we see that the first column of $\\mathbf{A}$ (denoted $\\mathbf{a}_1$) is in the range of $\\mathbf{A}$. By choosing $\\mathbf{c}=(0,1)^T$, we see that the second column of $\\mathbf{A}$ (denoted $\\mathbf{a}_2$) is also in the range of $\\mathbf{A}$. \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Minimizing the loss function $J(\\mathbf{c}) =\\frac{1}{2}\\|\\mathbf{y} - \\mathbf{A}\\mathbf{c}\\|^2$ is equivalent to minimizing $\\|\\mathbf{y} - \\mathbf{A}\\mathbf{c}\\|$, the latter being the distance between $\\mathbf{y}$ and an arbitrary vector $\\mathbf{A} \\mathbf{c}$ that is in the range of $\\mathbf{A}$ (see figure below). If there is no exact solution (i.e., $\\mathbf{y}$ is not in the range of $\\mathbf{A})$, this minimization is accomplished by choosing $\\mathbf{\\hat{c}}$ such that vector $\\mathbf{y}-\\mathbf{A}\\hat{c}$ is orthogonal to the range of $\\mathbf{A}$. That is, for $\\mathbf{\\hat{c}}$ to be a least-squares solution to $ \\mathbf{A}\\mathbf{c}=\\mathbf{y}$, the vector $\\mathbf{y}-\\mathbf{A}\\mathbf{\\hat{c}}$ must be orthogonal (perpendicular) to each vector in the range of $\\mathbf{A}$. Since both column vectors of $\\mathbf{A}$ (namely, $\\mathbf{a}_1$ and $\\mathbf{a}_2$) are in the range of $\\mathbf{A}$, it follows that $\\mathbf{a}_i\\cdot(\\mathbf{y}-\\mathbf{A}\\mathbf{\\hat{c}})=\\mathbf{a}_i^T(\\mathbf{y}-\\mathbf{A}\\mathbf{\\hat{c}})=0$ for each column vector $\\mathbf{a}_i$ of matrix~$\\mathbf{A}.$\n",
"\n",
" \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hence,\n",
" \n",
"$$\n",
"\\mathbf{A}^T(\\mathbf{y}-\\mathbf{A}\\mathbf{\\hat{c}})=\\mathbf{0}\\Rightarrow \\label{N1}\n",
"$$\n",
"\n",
"$$\n",
"\\mathbf{A}^T\\mathbf{y}-\\mathbf{A}^T\\mathbf{A}\\mathbf{\\hat{c}} = \\mathbf{0}\\Rightarrow \n",
"$$\n",
"\n",
"$$\n",
"\\mathbf{A}^T\\mathbf{y}=\\mathbf{A}^T\\mathbf{A}\\mathbf{\\hat{c}}\n",
"$$\n",
"\n",
"The last equation is called the **normal equation** for the system $\\mathbf{A}\\mathbf{c}=\\mathbf{y}.$ Solving the normal equations, one obtains optimal values for $c_0,c_1$. \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Example 2.1."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{admonition} Example 2.1\n",
"\n",
"Consider the data $(-1, 1)$, $(0, 0)$, $(1, 2)$, $(2, 3)$. Use the normal equations to find the OLS regression line for the data.\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{toggle}\n",
"**Solution.**\n",
"\n",
"The system is\n",
"\n",
"\\begin{align*}\n",
"c_0-c_1&=1,\\\\\n",
"c_0&=0,\\\\\n",
"c_0+c_1&=2,\\\\\n",
"c_0+2c_1&=3;\\\\\n",
"\\end{align*}\n",
"\n",
"\n",
"or, in matrix form,\n",
"\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"1& -1\\\\\n",
"1& 0\\\\\n",
"1&1\\\\\n",
"1& 2\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"c_0\\\\\n",
"c_1\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1\\\\\n",
"0\\\\\n",
"2\\\\\n",
"3\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"The normal equations are \n",
"\\begin{eqnarray}\n",
"\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"1\\\\\n",
"0\\\\\n",
"2\\\\\n",
"3\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"1& -1\\\\\n",
"1& 0\\\\\n",
"1&1\\\\\n",
"1& 2\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"c_0\\\\\n",
"c_1\n",
"\\end{pmatrix},\n",
"\\label{ne}\n",
"\\end{eqnarray}\n",
"or\n",
"\\begin{eqnarray*}\n",
"\\begin{pmatrix}\n",
"6\\\\\n",
"7\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"4&2\\\\\n",
"2&6\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"c_0\\\\\n",
"c_1\n",
"\\end{pmatrix}.\n",
"\\end{eqnarray*}\n",
"The least-squares solution is therefore $c_0=11/10$, $c_1=4/5.$ \n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{index} Gradient-Based Optimization\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Equivalence of Gradient-Based Optimization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Note that the normal equations are equivalent to gradient-based minimization of the OLS linear regression loss function $J(c_0,c_1)=\\frac{1}{2}\\sum_{i=1}^n (y_i-(c_0+c_1x_i) )^2$:\n",
"\n",
"\\begin{align*}\n",
"\\mathbf{A}^T(\\mathbf{y}-\\mathbf{A}\\mathbf{\\hat{c}})&=\n",
"\\begin{pmatrix}\n",
"1 & 1& \\dots& 1\\\\\n",
"x_1&x_2&\\dots&x_n\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"y_1-(c_0+c_1x_1)\\\\\n",
"y_2-(c_0+c_1x_2)\\\\\n",
"\\dots\\\\\n",
"y_n-(c_0+c_1x_n)\n",
"\\end{pmatrix}\\\\\n",
"&=\n",
"\\begin{pmatrix}\n",
"\\sum_{i=1}^n \\bigl(y_i-(c_0+c_1x_i)\\bigr)\\\\\\\\\n",
"\\sum_{i=1}^n x_i\\bigl(y_i-(c_0+c_1x_i)\\bigr)\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"-\\tfrac{\\partial J}{\\partial c_0}\\\\\n",
"-\\tfrac{\\partial J}{\\partial c_1}\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"0\\\\\n",
"0\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"The normal equations are equivalent to setting both partial derivatives of $J$ equal to zero, as is required to minimize the loss function $J(c_0,c_1)$.\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Example 2.2."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{admonition} Example 2.2\n",
"\n",
"For the data points in Example 2.1, show how gradient-based optimization of the loss function $J$ gives the same values for $c_0$ and $c_1$.\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{toggle}\n",
"\n",
"**Solution:**\n",
"\n",
"The loss function $J(c_0,c_1)$ is \n",
"\n",
"\\begin{align*}\n",
"J(c_0,c_1)&=\\tfrac{1}{2}[\\bigl(1-(c_0-c_1)\\bigr)^2+(0-c_0)^2+\\bigl(2-(c_0+c_1)\\bigr)^2+\\\\\n",
"&\\qquad\\bigl(3-(c_0+2c_1)\\bigr)^2].\n",
"\\end{align*}\n",
"\n",
"To minimize $J$, we solve the linear system for $\\nabla J(c_1,c_2)=\\mathbf{0}$: \n",
"\n",
"$$\n",
"\\frac{\\partial J}{\\partial c_0}\n",
"=4c_0+2c_1-6=0, \\qquad\n",
"\\frac{\\partial J}{\\partial c_1} =2c_0+6c_1-7=0.\n",
"$$\n",
"\n",
"Solving this system, we obtain $c_0=11/10$ and $c_1=4/5$. \n",
"\n",
"\n",
"\n",
"The system used to find these critical values is equivalent to:\n",
"\n",
"\\begin{align}\n",
"%\\scriptstyle\n",
"\\begin{pmatrix}\n",
"%\\scriptstyle\n",
"-\\frac{\\partial J}{\\partial c_0}\\\\\n",
"-\\frac{\\partial J}{\\partial c_1}\n",
"\\end{pmatrix}&=\n",
"\\begin{pmatrix}\n",
"\\scriptstyle\n",
"\\bigl(1-(c_0-c_1)\\bigr)+(0-c_0)+\\bigl(2-(c_0+c_1)\\bigr)+\\bigl(3-(c_0+2c_1\\bigr) \\\\\n",
"\\scriptstyle-\\bigl(1-(c_0-c_1)\\bigr)+0(0-c_0)+\\bigl(2-(c_0+c_1)\\bigr)+2\\bigl(3-(c_0+2c_1)\\bigr)\n",
"\\end{pmatrix}\\nonumber\\\\\n",
"&=\n",
"\\scriptstyle\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\n",
"\\end{pmatrix}\n",
"\\scriptstyle\n",
"\\begin{pmatrix}\n",
"1\\\\\n",
"\\textstyle 0\\\\\n",
"2\\\\\n",
"3\n",
"\\end{pmatrix}-\n",
"\\scriptstyle\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\n",
"\\end{pmatrix}\n",
"\\scriptstyle\\begin{pmatrix}\n",
"1& -1\\\\\n",
"1& 0\\\\\n",
"1&1\\\\\n",
"1& 2\n",
"\\end{pmatrix}\n",
"\\scriptstyle\\begin{pmatrix}\n",
"c_0\\\\\n",
"c_1\n",
"\\end{pmatrix}=\n",
"\\scriptstyle\n",
"\\begin{pmatrix}\n",
"0\\\\\n",
"0\n",
"\\end{pmatrix},\n",
"\\label{ne1}\n",
"\\end{align}\n",
"\n",
"\n",
"Gradient-based optimization expressed is indeed equivalent to the normal equations.\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To say that solving the normal equations is mathematically equivalent to gradient-based optimization of the OLS loss function does not imply that the normal equations offer the best numerical method for optimization of the loss function [Epperly 2022]. Beyond the scope of this Module is an assessment of different numerical approaches such as gradient descent and its variants including the Adam method [Sun et. al. 2019], matrix factorizations such as $SVD$ or $QR$ [Aggarwal 2020], and mean-centering and standardizing data [Toth 2020]. \n",
"\n",
"In addition to facilitating numerical analysis, mean-centering simplifies the linear algebra approach. Mean-centered data is obtained from a collection of data points by replacing the original dataset $(x_i,y_i)$ with the data points $(x_i-\\bar{x},y_i-\\bar{y})$, $i=1, \\dots n$, where $\\bar{x}$ and $\\bar{y}$ are the respective means of the $x$ and $y$ coordinates of the original data. One can show that for mean-centered data, $\\hat{c}_0=0$, and the regression line is $y = \\hat{c}_1 x$. Let $\\mathbf{x}=(x_1,x_2,...,x_n)^{tr}$. For mean-centered data, the regression vector ${\\bf \\hat{y}}=\\hat{c}_1\\mathbf{x}$ is obtained by projecting the vector ${\\bf y}$ directly onto the vector ${\\bf x}$ as shown in the figure below.\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"The *variation equation* states that the total variation in the y-values is the sum of the explained variation (variation in the corresponding $y$-values on the regression line) and the unexplained variation (the sum of squared residuals or twice the value of the loss function $J$). For mean-centered data, the total variation is $\\mid\\mid \\mathbf{y}\\mid\\mid^2$, the explained variation is $\\mid\\mid \\hat{c}_1\\mathbf{x}\\mid\\mid^2$ and the unexplained variation is $\\mid\\mid \\mathbf{y} -\\hat{c}_1 \\mathbf{x}\\mid\\mid^2$. In other words, the variation equation for mean-centered data is simply the Pythagorean theorem."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Practice Problems"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{admonition} Practice Problems\n",
"\n",
"1) Consider the data $(1, 0)$, $(4, 5)$, $(7, 8)$. Use the normal equations to find the least-squares solution line $y = a + bx$ that best fits the data. \n",
"\n",
"\n",
"2) Consider the data $(-1,1)$, $(0,0)$, $(1,2)$, $(2,3)$. Use the normal equations to find the least-squares solution for the parabola $y=a+bx+cx^2$ that best fits the data.\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Solutions to Practice Problems"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{toggle}\n",
"\n",
"Problem 1) \n",
"The system is\n",
"\n",
"\\begin{align*}\n",
"a+b&=0,\\\\\n",
"a + 4b&=5,\\\\\n",
"a+7b&=8;\n",
"\\end{align*}\n",
"\n",
"or, in matrix form,\n",
"\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"1& 1\\\\\n",
"1& 4\\\\\n",
"1&7\\\\\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\\\\\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"0\\\\\n",
"5\\\\\n",
"8\\\\\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"\n",
"The normal equations are\n",
"\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"1& 1&1\\\\\n",
"1&4&7\\\\\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"0\\\\\n",
"5\\\\\n",
"8\\\\\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1& 1&1\\\\\n",
"1&4&7\\\\\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"1& 1\\\\\n",
"1& 4\\\\\n",
"1&7\\\\\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\n",
"\\end{pmatrix},\n",
"\\end{align*}\n",
"\n",
"or\n",
"\t\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"13\\\\\n",
"76\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"3&12\\\\\n",
"12&66\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"\n",
"Solving the normal equations gives the least-squares solution $a=-1$, $b=4/3$. \n",
"\n",
":::\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{toggle}\n",
"\n",
"\n",
"Problem 2)\n",
"\n",
"The system is\n",
"\t\n",
"\\begin{align*}\n",
"a-b+c&=1,\\\\\n",
"a&=0,\\\\\n",
"a+b+c&=2,\\\\\n",
"a+2b+4c&=3;\\\\\n",
"\\end{align*}\n",
"\t\n",
"or, in matrix form,\n",
"\t\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"1& -1&1\\\\\n",
"1& 0&0\\\\\n",
"1&1&1\\\\\n",
"1& 2&4\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\\\\\n",
"c\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1\\\\\n",
"0\\\\\n",
"2\\\\\n",
"3\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"\n",
"The normal equations are\n",
"\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\\\\\n",
"1&0&1&4\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"1\\\\\n",
"0\\\\\n",
"2\\\\\n",
"3\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1& 1&1&1\\\\\n",
"-1&0&1&2\\\\\n",
"1&0&1&4\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"1& -1&1\\\\\n",
"1& 0&0\\\\\n",
"1&1&1\\\\\n",
"1& 2&4\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\n",
"\\end{pmatrix},\n",
"\\end{align*}\n",
"or\n",
"\\begin{align*}\n",
"\\begin{pmatrix}\n",
"6\\\\\n",
"7\\\\\n",
"15\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"4&2&6\\\\\n",
"2&6&8\\\\\n",
"6&8&18\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"a\\\\\n",
"b\\\\\n",
"c\n",
"\\end{pmatrix}.\n",
"\\end{align*}\n",
"\n",
"Solving the normal equations gives the least-squares solution $a=3/5, b=3/10$, and $c=1/2.$\n",
"\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this lab we will make scatterplots of data which include the OLS regression line.\n",
"\n",
"We begin by importing libraries."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.linear_model import LinearRegression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{admonition} OLS Regression of ACT and College Eligibility\n",
"Datafile: ACTCollegeEligible.csv\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1) Import Libraries, dropping rows with missing data."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
School Name
\n",
"
Street Address
\n",
"
ZIP
\n",
"
Average Score ACT 2012
\n",
"
5-Year Cohort Graduation Rate 2012 - Percent
\n",
"
One-Year Dropout Rate 2012 - Percent
\n",
"
Freshman On-Track to Graduate 2012 - Percent
\n",
"
College Eligibility 2012 - Percent
\n",
"
College Enrollment 2012 - Percent
\n",
"
College Retention 2010 - Percent
\n",
"
Misconducts Resulting in Suspensions 2012 - Percent
\n",
"
Average Days of Suspension 2012
\n",
"
Student Attendance 2012 - Percent
\n",
"
Teacher Attendance 2012 - Percent
\n",
"
X Coordinate
\n",
"
Y Coordinate
\n",
"
Longitude
\n",
"
Latitude
\n",
"
Location
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
Chicago Academy High School
\n",
"
3400 N Austin Ave
\n",
"
60634
\n",
"
19.3
\n",
"
71.0
\n",
"
4.0
\n",
"
82.2
\n",
"
35.2
\n",
"
75.8
\n",
"
71.0
\n",
"
4.5
\n",
"
2.6
\n",
"
93.6
\n",
"
95.6
\n",
"
1135740.091
\n",
"
1922002.941
\n",
"
-87.776506
\n",
"
41.942154
\n",
"
(-87.77650575, 41.94215439)
\n",
"
\n",
"
\n",
"
3
\n",
"
William Jones College Preparatory High School
\n",
"
606 S State St
\n",
"
60605
\n",
"
25.1
\n",
"
87.1
\n",
"
1.5
\n",
"
98.0
\n",
"
80.7
\n",
"
92.2
\n",
"
90.8
\n",
"
10.6
\n",
"
4.5
\n",
"
93.9
\n",
"
95.3
\n",
"
1176412.354
\n",
"
1897618.088
\n",
"
-87.627755
\n",
"
41.874419
\n",
"
(-87.62775497, 41.87441898)
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" School Name Street Address ZIP \n",
"0 Chicago Academy High School 3400 N Austin Ave 60634 \\\n",
"3 William Jones College Preparatory High School 606 S State St 60605 \n",
"\n",
" Average Score ACT 2012 5-Year Cohort Graduation Rate 2012 - Percent \n",
"0 19.3 71.0 \\\n",
"3 25.1 87.1 \n",
"\n",
" One-Year Dropout Rate 2012 - Percent \n",
"0 4.0 \\\n",
"3 1.5 \n",
"\n",
" Freshman On-Track to Graduate 2012 - Percent \n",
"0 82.2 \\\n",
"3 98.0 \n",
"\n",
" College Eligibility 2012 - Percent College Enrollment 2012 - Percent \n",
"0 35.2 75.8 \\\n",
"3 80.7 92.2 \n",
"\n",
" College Retention 2010 - Percent \n",
"0 71.0 \\\n",
"3 90.8 \n",
"\n",
" Misconducts Resulting in Suspensions 2012 - Percent \n",
"0 4.5 \\\n",
"3 10.6 \n",
"\n",
" Average Days of Suspension 2012 Student Attendance 2012 - Percent \n",
"0 2.6 93.6 \\\n",
"3 4.5 93.9 \n",
"\n",
" Teacher Attendance 2012 - Percent X Coordinate Y Coordinate Longitude \n",
"0 95.6 1135740.091 1922002.941 -87.776506 \\\n",
"3 95.3 1176412.354 1897618.088 -87.627755 \n",
"\n",
" Latitude Location \n",
"0 41.942154 (-87.77650575, 41.94215439) \n",
"3 41.874419 (-87.62775497, 41.87441898) "
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df=pd.read_csv(\"ACTCollegeEligible.csv\")\n",
"df=df.dropna()\n",
"df.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2) Specify the x and y coordinates of the points to be plotted."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"X=df[[\"Average Score ACT 2012\"]]\n",
"Y=df[[\"College Eligibility 2012 - Percent\"]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3) Create the OLS regression model."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OLS regression line y=mx+b\n",
"slope m= [[6.09611136]]\n",
"intercept b= [-80.78259412]\n"
]
}
],
"source": [
"OLSmodel = LinearRegression()\n",
"OLSmodel.fit(X, Y)\n",
"print(\"OLS regression line y=mx+b\")\n",
"print(\"slope m=\",OLSmodel.coef_)\n",
"print(\"intercept b=\",OLSmodel.intercept_)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"4) Make the scatterplot with regression line."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Intercept is [-80.78259412]\n",
"Slope is [[6.09611136]]\n",
"R^2 for OLS is 0.9351396968249491\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAGwCAYAAABPSaTdAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB7TklEQVR4nO3dd1iT19sH8G/YoEyVoaLiFhfu4mwFcVXtdG+rP2fdu+5tXbVaV511oLVq1SpKnVVxIlq3UKyDpSKEIRCS8/7hS2okQAIJgfD9XBdX5RnnuZ/TgLdnSoQQAkRERERGysTQARARERHpE5MdIiIiMmpMdoiIiMioMdkhIiIio8Zkh4iIiIwakx0iIiIyakx2iIiIyKiZGTqAgkChUCAiIgK2traQSCSGDoeIiIg0IIRAQkICSpcuDROTrNtvmOwAiIiIgLu7u6HDICIiolx49uwZypYtm+V5JjsAbG1tAbyrLDs7OwNHk79kMhlOnjwJPz8/mJubGzqcAoF1oor1oYr1oYr1kRnrRJU+60MqlcLd3V3593hWmOwAyq4rOzu7Ipns2NjYwM7Ojj+U/491oor1oYr1oYr1kRnrRFV+1EdOQ1A4QJmIiIiMGpMdIiIiMmpMdoiIiMioccwOERERGYRCoUBaWlqW583NzWFqaprn5zDZISIionyXlpaG8PBwKBSKbK9zcHCAq6trntbBY7JDRERE+UoIgcjISJiamsLd3V3tgoBCCCQnJyMmJgYA4ObmluvnMdkhIiKifJWeno7k5GSULl0aNjY2WV5nbW0NAIiJiYGzs3Ouu7Q4QJmIiIjylVwuBwBYWFjkeG1GMiSTyXL9PCY7REREZBCajMPRxZ6VTHaIiIjIqDHZISIiIqPGZIeIiIiMGpMdIiIi0pu4uDjcvXtX7TkhRI73a3JNTpjsEBERkV5cu3YNTZo0wbx58/D48WPl8Ywp5NmtnpwhOTkZAPK0YzrX2SEiIiKdEkLghx9+wKRJkyCTyeDs7IzExETleTMzM9jY2ODly5cwNzfPcVFBBweHPG0bwWSHiIiIdCY2NhYDBgzA4cOHAQCfffYZvvrqK9SrV095jUQigZubG8LDw/Hvv/9mW17GdhF5wWSHiIiIdCIoKAjdu3fH06dPYWFhgRUrVmDw4ME4fvx4pmstLCxQpUqVfNkI1KBjds6fP49OnTqhdOnSkEgkOHTokMp5IQRmzpwJNzc3WFtbw9fXV6XPD3iXQfbq1Qt2dnZwcHDAoEGDVJrKiIiISL8UCgW+//57tGzZEk+fPkWlSpUQFBSEESNGZLsooImJCaysrLL80kWiAxg42UlKSkLdunWxdu1ateeXLl2K1atXY/369bhy5QqKFSuGtm3bIiUlRXlNr169cPfuXQQGBuLo0aM4f/48hgwZkl+vQEREVKS9evUKnTp1wqRJk5Ceno5u3bohODgY9evXN3RoSgbtxmrfvj3at2+v9pwQAqtWrcJ3332HLl26AAB27NgBFxcXHDp0CN27d8f9+/cREBCAa9euoWHDhgCAH3/8ER06dMCyZctQunTpfHsXIiKioubChQvo3r07Xrx4AUtLS6xevRqDBw/WyRYPulRgx+yEh4cjKioKvr6+ymP29vZo0qSJsk8wKCgIDg4OykQHAHx9fWFiYoIrV67g888/V1t2amoqUlNTld9LpVIA7zYZy8tGY4VRxvsWtffODutEFetDFetDFesjs6JQJwqFAkuXLsWcOXMgl8tRtWpV7N69G3Xq1EF6errKtfqsD03LLLDJTlRUFADAxcVF5biLi4vyXFRUFJydnVXOm5mZwcnJSXmNOosWLcKcOXMyHT958mS2W80bs8DAQEOHUOCwTlSxPlSxPlSxPjIz1jqJi4vDqlWrEBISAgBo1aoVhg4diufPn+P58+dZ3qeP+shYgycnBTbZ0aepU6di3Lhxyu+lUinc3d3h5+cHOzs7A0aW/2QyGQIDA9GmTZs8LdhkTFgnqlgfqlgfqlgfmRlznZw7dw7Dhg1DZGQkrK2tsXr1avTt2zfbbit91kdGz0xOCmyykzGnPjo6Gm5ubsrj0dHR8PLyUl4TExOjcl96ejpiY2OznZNvaWkJS0vLTMfNzc2N7oOpqaL87llhnahifahifahifWRmTHUil8sxf/58zJ07FwqFAp6enti3bx9q1qypcRn6qA9Nyyuw20V4eHjA1dUVp06dUh6TSqW4cuUKvL29AQDe3t6Ii4vDjRs3lNecPn0aCoUCTZo0yfeYiYiIjE1UVBT8/Pwwe/ZsKBQKDBgwAGv2BiBU5oCgsNeQK/K+d5W+GbRlJzExEaGhocrvw8PDERISAicnJ5QrVw5jxozB/PnzUaVKFXh4eGDGjBkoXbo0PvvsMwBAjRo10K5dOwwePBjr16+HTCbDyJEj0b17d87EIiIiyqM///wTvXr1QkxMDIoVK4Zh0xfhAjwxYOdt5TVu9laY1ckT7Wq5ZVOSYRm0Zef69euoV6+ecgnpcePGoV69epg5cyYAYNKkSRg1ahSGDBmCRo0aITExEQEBAbCyslKWsWvXLlSvXh0+Pj7o0KEDmjdvjo0bNxrkfYiIiIxBeno6ZsyYAT8/P8TExKBOnTpYufsY9sdXRGR8isq1UfEpGLYzGAF3Ig0Ubc4M2rLz8ccfZ7t1u0Qiwdy5czF37twsr3FycsLu3bv1ER4REVGR8+LFC/To0QN//fUXAOB///sfli1fgTarg6Dub2wBQAJgzpF7aOPpClOTgrXGDlCAx+wQERFR/jp+/Di8vLzw119/wdbWFv7+/li/fj3+jnqbqUXnfQJAZHwKrobH5l+wWmCyQ0REVMTJZDJMnjwZHTp0wKtXr1C/fn0EBwejW7duAICYhKwTnfdpel1+K7BTz4mIiEj/nj59ih49euDSpUsAgJEjR2LZsmUqS7Q421pldbsKTa/Lb2zZISIiKqIOHz4MLy8vXLp0Cfb29ti/fz9+/PHHTGvRNfZwgpu9FbIajSPBu1lZjT2c9B5zbjDZISIiKmLS0tIwbtw4dOnSBW/evEGjRo0QHByML7/8Uu31piYSzOrkCQCZEp6M72d18iyQg5MBJjtERERFSnh4OFq0aIGVK1cCAMaOHYsLFy6gYsWK2d7XrpYb1vWuD1d71a4qV3srrOtdv0Cvs8MxO0REREXEgQMHMHDgQMTHx8PR0RHbtm1D586dNb6/XS03tPF0xdXwWMQkpMDZ9l3XVUFt0cnAZIeIiMjIpaSkYOLEiVizZg2Ad9st7dmzB+XLl9e6LFMTCbwrldB1iHrFbiwiIiIjFhoaiqZNmyoTnUmTJuHcuXO5SnQKK7bsEBERGam9e/di8ODBSEhIQIkSJbBjxw506NDB0GHlO7bsEBERGZm3b99i6NCh6N69OxISEtC8eXOEhIQUyUQHYMsOERFRvpErhN4H9z58+BBdu3bF7du3IZFIMHXqVMyZMwdmZkX3r/yi++ZERET5KOBOJOYcuaeyx5SbvRVmdfLU2bTtnTt3YujQoUhKSkKpUqWwc+dO+Pn56aTswozdWERERHoWcCcSw3YGZ9pMMyo+BcN2BiPgTmSeyk9OTsagQYPQp08fJCUl4eOPP8atW7eY6Pw/JjtERER6JFcIzDlyD0LNuYxjc47cg1yh7oqc3bt3D40aNcKWLVsgkUgwa9Ys/Pnnn3BzK7iL/OU3JjtERER6dDU8NlOLzvsEgMj4FFwNj9WqXCEEtm7dioYNG+LevXtwdXXFn3/+idmzZ8PU1DSPURsXjtkhIiL6gC4HEsckZJ3o5OY6AEhMTMTw4cPxyy+/AADatGmDX375BS4uLrmK0dgx2SEiInqPrgcSO9ta5XyRFtf9/fff6Nq1Kx48eAATExPMmzcPU6ZMgYkJO2uywpohIiL6f/oYSNzYwwlu9laZdgvPIMG7ZKqxh1O25QghsGnTJjRu3BgPHjxAmTJlcPbsWUybNo2JTg5YO0RERNDfQGJTEwlmdfIEgEwJT8b3szp5ZttNJpVK0bNnTwwZMgQpKSlo3749QkJC0KJFC61iKaqY7BAREUF/A4mBd7uFr+tdH672ql1VrvZWWNe7frbdYzdv3kSDBg3g7+8PU1NTLF26FEePHkXJkiW1jqOo4pgdIiIi6Gcg8fva1XJDG09XjQc+CyGwbt06jB07FmlpaShXrhz8/f3h7e2dq+cXZUx2iIiIoPuBxOqYmkjgXalEjtfFx8fjm2++wf79+wEAnTt3xtatW+HklP24HlKP3VhERETQ3UDivLp27Rrq1auH/fv3w9zcHCtXrsShQ4eY6OQBkx0iIiLoZiBxXgghsGrVKjRr1gzh4eGoUKECLly4gDFjxkAi0c8ziwomO0RERP8vLwOJ8yI2Nhaff/45xo4dC5lMhi+++AI3b95E48aN9fK8ooZjdoiIiN6j7UDivAoKCkL37t3x9OlTWFhYYMWKFRg+fDhbc3SIyQ4REdEHNB1InBcKhQLLly/HtGnTkJ6ejkqVKmHfvn2oX7++Xp9bFDHZISIiymevXr1Cv379cOzYMQBAt27dsHHjRtjZ2Rk4MuPEZIeIiCgfXbhwAd27d8eLFy9gaWmJ1atXY/Dgwey20iMOUCYiIsoHCoUCCxcuxMcff4wXL16gatWquHLlCoYMGcJER8/YskNERKRnMTEx6NOnD06ePAkA6N27N9atW4fixYsbOLKigckOERGRHp09exY9e/ZEZGQkrK2tsWbNGgwYMICtOfmI3VhERER6IJfLMWfOHPj4+CAyMhKenp64du0aBg4cyEQnn7Flh4iISMfevHmDDh064MyZMwCA/v37Y82aNShWrJiBIyuamOwQERHp0KlTpzBmzBjEx8ejWLFiWLduHfr06WPosIo0dmMRERHpQHp6Or777jt06NAB8fHxqFWrFq5fv85EpwBgyw4REVEevXjxAj179sT58+cBAG3atMH+/fu5SGABwWSHiIgoDwICAtCnTx+8evUKxYsXx7p162Brawtra2tDh0b/j91YREREuSCTyTBlyhS0b98er169Qr169RAcHIxu3boZOjT6AFt2iIiItPT06VP06NEDly5dAgCMGDECy5Ytg5WVFWQymYGjow8x2SEiItLCkSNH0L9/f8TGxsLe3h6bN2/Gl19+aeiwKBvsxiIiItJAWloaxo8fj86dOyM2NhaNGjVCcHAwE51CQOtkp3Xr1oiLi8t0XCqVonXr1rqIiYiIqEAJDw9HixYtsGLFCgDAmDFjcOHCBVSsWNHAkZEmtO7GOnv2LNLS0jIdT0lJwV9//aWToIiIiAqKAwcOYODAgYiPj4eDgwO2bduGLl26GDos0oLGyc7t27eVf7537x6ioqKU38vlcgQEBKBMmTK6jY6IiMhAUlNTMXHiRPz4448AgI8++gj+/v4oX768gSMjbWmc7Hh5eUEikUAikajtrrK2tlZ+IIiIiAqz0NBQdOvWDcHBwQCAiRMnYsGCBTA3NzdwZJQbGic74eHhEEKgYsWKuHr1KkqVKqU8Z2FhAWdnZ5iamuolSCIiovyyb98+fPPNN0hISECJEiWwfft2dOzY0dBhUR5onOxkNNspFAq9BUNERGQob9++xdixY7FhwwYAQPPmzbFnzx6ULVvWwJFRXuVqnZ3Hjx/jzJkziImJyZT8zJw5UyeBERER5ZeHDx+ia9euuH37NiQSCaZOnYo5c+bAzIzL0RkDrf8vbtq0CcOGDUPJkiXh6uoKiUSiPCeRSJjsEBFRobJz504MHToUSUlJKFWqFHbu3Ak/Pz9Dh0U6pHWyM3/+fCxYsACTJ0/WRzxERET5Ijk5GaNGjcKWLVsAAB9//DF27dqF0qVLGzgy0jWtk503b97g66+/1kcsRERUSMkVAtfDXiMmIQXOtlZo7OEEUxNJzjcayL1799C1a1fcvXtX2SsxY8YMTrQxUlonO19//TVOnjyJoUOH6iMeIiIqZG69lmDR8vOIkqYqj7nZW2FWJ0+0q+VmwMjU27ZtG4YPH463b9/C1dUVu3bt4g4ARk7rZKdy5cqYMWMGLl++jNq1a2dac+Dbb7/VWXBERFSwnbgbjS2PTACkqhyPik/BsJ3BWNe7foFJeBITEzFixAjs2LEDAODr64udO3fCxcXFwJGRvmmd7GzcuBHFixfHuXPncO7cOZVzEomEyQ4RUREhVwjMP/ZA7TkBQAJgzpF7aOPpavAurb///htdu3bFgwcPYGJigrlz52LKlCnstioitN4INDw8PMuvf/75R6fByeVyzJgxAx4eHrC2tkalSpUwb948CCGU1wghMHPmTLi5ucHa2hq+vr54/PixTuMgIqLMrobH/n/XlfpERgCIjE/B1fDYfI1LJQYhsGnTJjRu3BgPHjxA6dKlcebMGUyfPp2JThGidbKTIS0tDQ8fPkR6erou41GxZMkSrFu3DmvWrMH9+/exZMkSLF26VGVbiqVLl2L16tVYv349rly5gmLFiqFt27ZISUnRW1xERATEJGj2e1bT63RNKpWiZ8+eGDJkCFJSUtCuXTuEhISgZcuWBomHDEfrZCc5ORmDBg2CjY0NatasiadPnwIARo0ahcWLF+s0uEuXLqFLly7o2LEjKlSogK+++gp+fn64evUqgHcZ+6pVq/Ddd9+hS5cuqFOnDnbs2IGIiAgcOnRIp7EQEZEqZ1srnV6nSzdv3kSDBg3g7+8PU1NTLF68GH/88YfKVkdUdGg9Zmfq1Km4desWzp49i3bt2imP+/r6Yvbs2ZgyZYrOgmvatCk2btyIR48eoWrVqrh16xYuXLiAFStWAHjXpRYVFQVfX1/lPfb29mjSpAmCgoLQvXt3teWmpqYiNfW/wXRSqRQAIJPJIJPJdBZ/YZDxvkXtvbPDOlHF+lDF+vhPvbK2cLGzRLQ0Beq6siQAXO0tUa+sbb7VlxACGzZswIQJE5CWlgZ3d3fs3LkT3t7ekMvlkMvleo+BnxFV+qwPTcvUOtk5dOgQ9u7di48++khl9eSaNWsiLCxM2+KyNWXKFEilUlSvXh2mpqaQy+VYsGABevXqBQCIiooCgEwj6V1cXJTn1Fm0aBHmzJmT6fjJkydhY2OjwzcoPAIDAw0dQoHDOlHF+lDF+nino6sEW6Qm+G9IcgYBAaC9SzJOBBzPl1iSkpKwdu1aXLp0CQDQqFEjjBo1Cm/evMGxY8fyJYb38TOiSh/1kZycrNF1Wic7L1++hLOzc6bjSUlJKsmPLuzbtw+7du3C7t27UbNmTYSEhGDMmDEoXbo0+vXrl+typ06dinHjxim/l0qlcHd3h5+fH+zs7HQReqEhk8kQGBiINm3aZFpGoKhinahifahifahqI5MB/n/ijygbRH+wzs709tXRtmb+TOu+ceMGevbsifDwcJiZmWHhwoUYPXq0zv9e0gQ/I6r0WR8ZPTM50TrZadiwIf744w+MGjUKAJQfpJ9//hne3t7aFpetiRMnYsqUKcruqNq1a+Pff//FokWL0K9fP7i6ugIAoqOj4eb23zoO0dHR8PLyyrJcS0tLWFpaZjpubm5eZD+YRfnds8I6UcX6UMX6+E/dEgKTerXEzecJ+b6CshACq1evxsSJEyGTyVChQgXs3bsXjRs31vuzc8LPiCp91Iem5Wmd7CxcuBDt27fHvXv3kJ6ejh9++AH37t3DpUuXMq27k1fJyckwMVEdQ21qaqrcad3DwwOurq44deqUMrmRSqW4cuUKhg0bptNYiIgoa6YmEnhXKpGvz3zz5g0GDhyonJDyxRdfYPPmzXBwcMjXOKjg03o2VvPmzRESEoL09HTUrl0bJ0+ehLOzM4KCgtCgQQOdBtepUycsWLAAf/zxB548eYKDBw9ixYoV+PzzzwG8a1UaM2YM5s+fj8OHD+Pvv/9G3759Ubp0aXz22Wc6jYWIiAqOK1euoF69ejh06BAsLCzw448/Yv/+/Ux0SC2tW3YAoFKlSti0aZOuY8nkxx9/xIwZMzB8+HDExMSgdOnS+N///oeZM2cqr5k0aRKSkpIwZMgQxMXFoXnz5ggICICVVf5PdSQiIv1SKBRYuXIlpkyZgvT0dFSqVAn79u1D/fr1DR0aFWBaJzvHjh2Dqakp2rZtq3L8xIkTUCgUaN++vc6Cs7W1xapVq7Bq1aosr5FIJJg7dy7mzp2rs+cSEVHB8/r1a/Tv3x9Hjx4FAHTr1g0bN24schNLSHtad2NNmTJF7ToFQgidrrFDRESU4cKFC/Dy8sLRo0dhaWmJ9evXY8+ePUx0SCNaJzuPHz+Gp6dnpuPVq1dHaGioToIiIiIC3nVbLVq0CB9//DGeP3+OqlWr4sqVK/jf//5nkGnlVDhpnezY29ur3fAzNDQUxYoV00lQREREMTEx6NChA6ZNmwa5XI7evXvjxo0bqFu3rqFDo0JG62SnS5cuGDNmjMpqyaGhoRg/fjw6d+6s0+CIiKhoOnv2LLy8vHDixAlYW1tj8+bN2LFjB4oXL27o0KgQ0jrZWbp0KYoVK4bq1avDw8MDHh4eqFGjBkqUKIFly5bpI0YiIioi5HI55s6dCx8fH0RGRqJGjRq4du0aBg4cyG4ryjWtZ2PZ29vj0qVLCAwMxK1bt2BtbY06deqgZcuW+oiPiIiKiKioKPTq1QunT58GAAwYMAA//vgjh0hQnmmV7MhkMlhbWyMkJAR+fn7w8/PTV1xERFSE/Pnnn+jVqxdiYmJgY2OD9evXo0+fPoYOi4yEVt1Y5ubmKFeunNqp50RERNpKT0/HjBkz4Ofnh5iYGNSqVQs3btxgokM6pfWYnenTp2PatGmIjY3VRzxERFREvHjxAj4+Ppg/fz6EEBg8eDCuXr2K6tWrGzo0MjJaj9lZs2YNQkNDUbp0aZQvXz5TX2pwcLDOgiMiIuMUEBCAPn364NWrVyhevDg2btyIHj16GDosMlJaJzvcYJOIiHJLJpNhxowZWLJkCQDAy8sLe/fuRdWqVQ0cGRkzrZOdWbNm6SMOIiIycs+ePUP37t1x6dIlAMDw4cOxfPlybtxMeqf1mB0AiIuLw88//4ypU6cqx+4EBwfjxYsXOg2OiIiMw5EjR+Dl5YVLly7Bzs4O+/btw9q1a5noUL7QumXn9u3b8PX1hb29PZ48eYLBgwfDyckJBw4cwNOnT7Fjxw59xElERIVQWloapk2bhuXLlwMAGjRogL1796JSpUoGjoyKEq1bdsaNG4f+/fvj8ePHKhl5hw4dcP78eZ0GR0REhdeTJ0/QsmVLZaLz7bff4uLFi0x0KN9p3bJz7do1bNiwIdPxMmXKICoqSidBERFR4Xbo0CEMGDAAcXFxcHBwwNatWznBhQxG65YdS0tLSKXSTMcfPXqEUqVK6SQoIiIqnFJTUzF69Gh8/vnniIuLQ5MmTXDz5k0mOmRQWic7nTt3xty5cyGTyQAAEokET58+xeTJk/Hll1/qPEAiIsqeXCEQFPYav4e8QFDYa8gVwiBxhIWFoVmzZli9ejUAYPz48Th//jwqVKhgkHiIMmjdjbV8+XJ89dVXcHZ2xtu3b9GqVStERUXB29sbCxYs0EeMRESUhYA7kZhz5B4i41OUx9zsrTCrkyfa1XLLtzj279+PoUOHQiqVwsnJCdu3b8enn36ab88nyk6udj0PDAzExYsXcevWLSQmJqJ+/frw9fXVR3xERJSFgDuRGLYzGB+240TFp2DYzmCs611f7wlPSkoK1q9fj4CAAABAs2bNsGfPHri7u+v1uUTa0CrZ2bt3Lw4fPoy0tDT4+Phg+PDh+oqLiIiyIVcIzDlyL1OiAwACgATAnCP30MbTFaYmEr3E8PjxY3z99de4desWAGDq1KmYO3cuzMy0/nc0kV5pPGZn3bp16NGjB65fv47Hjx9jxIgRmDhxoj5jIyKiLFwNj1XpuvqQABAZn4Kr4frZtHnPnj2oX78+bt26BXt7exw9ehQLFy5kokMFksbJzpo1azBr1iw8fPgQISEh2L59O3766Sd9xkZERFmIScg60cnNdZpKTk7G4MGD0bNnTyQmJqJVq1ZYuXIl/Pz8dPocIl3SONn5559/0K9fP+X3PXv2RHp6OiIjI/USGBERZc3ZVrNtFjS9ThP3799HkyZN8PPPP0MikWDmzJkICAiAk5OTzp5BpA8atzempqaiWLFiyu9NTExgYWGBt2/f6iUwIiLKWmMPJ7jZWyEqPkXtuB0JAFd7KzT20E0isn37dgwfPhzJyclwcXHBrl274OPjo1yGhKgg06pzdcaMGbCxsVF+n5aWhgULFsDe3l55bMWKFbqLjoiI1DI1kWBWJ08M2xkMCaCS8GQMR57VyTPPg5OTkpIwYsQIbN++HQDg4+ODnTt3wtXVNU/lEuUnjZOdli1b4uHDhyrHmjZtin/++Uf5vUSinxH/RESUWbtabljXu36mdXZcdbTOzp07d9C1a1fcv38fJiYmmD17NqZNmwZTU9O8hk6UrzROds6ePavHMIiIKDfa1XJDG09XXA2PRUxCCpxt33Vd5aVFRwiBzZs3Y9SoUUhJSUHp0qWxe/dutGrVSoeRE+UfzhEkIirkTE0k8K5UQidlJSQkYOjQodi9ezcAoF27dtixYwf3PqRCTeu9sYiIyDiFhISgYcOG2L17N0xNTbFo0SL88ccfTHSo0GPLDhFRESeEwIYNGzBmzBikpqaibNmy8Pf3R7NmzQwdGpFOMNkhIirCpFIpBg8ejH379gEAPv30U2zbtg0lSuimW4yoIGA3FhFREXXjxg3Ur18f+/btg5mZGZYvX47Dhw8z0SGjk6dkp3bt2nj27JmuYiEionwghMCPP/6Ipk2bIiwsDOXLl8eFCxcwbtw4LiFCRilP3VhPnjzh6plERIXImzdvMGjQIBw8eBAA8Pnnn2Pz5s1wdHQ0cGRE+sNuLCKiIuLKlSuoV68eDh48CAsLC6xevRq//fYbEx0yenlKdlq0aAFra2tdxUJERHoghMDy5cvRvHlz/Pvvv6hYsSIuXbqEUaNGsduKioQ8dWMdO3ZMV3EQEZEevH79Gv3798fRo0cBAF27dsXGjRtV9jQkMnbsxiIiMlIXL15EvXr1cPToUVhaWmLdunXw9/dnokNFDpMdIiIjo1AosGTJErRq1QrPnj1DlSpVcPnyZQwdOpTdVlQkcVFBIiIj8vLlS/Tt2xcBAQEAgJ49e2L9+vWwtbU1cGREhsNkh4jISJw7dw49e/ZEREQErKyssGbNGgwcOJCtOVTksRuLiKiQk8vlmDdvHlq3bo2IiAjUqFED165dw6BBg5joEEHLZOenn36Cr68vunbtilOnTqmce/XqFSpWrKjT4IiIKHtRUVFo27YtZs6cCYVCgX79+uHatWuoVauWoUMjKjA0TnZWr16NiRMnonr16rC0tESHDh2waNEi5Xm5XI5///1XL0ESEVFmp06dgpeXF06dOgUbGxts27YN27ZtQ7FixQwdGlGBovGYnQ0bNmDTpk3o2bMnAGDYsGH47LPP8PbtW8ydO1dvARIRkSq5XI65c+di3rx5EEKgVq1a2LdvH2rUqGHo0IgKJI2TnfDwcDRt2lT5fdOmTXH69Gn4+vpCJpNhzJgx+oiPiIjeExERgV69euHs2bMAgG+++QY//PADbGxsDBsYUQGmcbJTsmRJPHv2DBUqVFAeq1WrFk6fPq0cFEdERPpz8uRJ9O7dGy9fvkTx4sWxYcMGZWs7EWVN4zE7zZs3x4EDBzId9/T0xKlTp3D8+HGdBkZERO+kp6dj2rRpaNu2LV6+fIm6devixo0bTHSINKRxy86UKVNw48YNtedq1qyJ06dP47ffftNZYEREBDx79gw9evTAxYsXAQDDhw/H8uXLYWVlZeDIiAoPjZOdOnXqoE6dOlmer1WrFqc6EhHp0B9//IG+ffsiNjYWdnZ2+Pnnn/H1118bOiyiQkdniwomJSXh/PnzuiqOiKjIkslkmDhxIj799FPExsaiQYMGCA4OZqJDlEs62y4iNDQUn3zyCeRyua6KJCIqcv799190794dly9fBgCMGjUK33//PSwtLQ0cGVHhxb2xiIgKiEOHDmHAgAGIi4uDg4MDtmzZgs8//9zQYREVehonO05OTtmeZ4sOEVHupKamYvLkyfjhhx8AAI0bN8bevXtVlvogotzTONlJTU3FsGHDULt2bbXn//33X8yZM0dngRERFQVhYWHo1q2bcrbr+PHjsXDhQlhYWBg4MiLjoXGy4+XlBXd3d/Tr10/t+Vu3bukl2Xnx4gUmT56M48ePIzk5GZUrV8bWrVvRsGFDAIAQArNmzcKmTZsQFxeHZs2aYd26dahSpYrOYyEi0qX9+/dj0KBBkEqlcHJywvbt2/Hpp58aOiwio6PxbKyOHTsiLi4uy/NOTk7o27evLmJSevPmDZo1awZzc3McP34c9+7dw/Lly+Ho6Ki8ZunSpVi9ejXWr1+PK1euoFixYmjbti1SUlJ0GgsRka6kpKRg+PDh+PrrryGVStGsWTOEhIQw0SHSE41bdqZNm5bteXd3d2zdujXPAb1vyZIlmcr18PBQ/lkIgVWrVuG7775Dly5dAAA7duyAi4sLDh06hO7du+s0HiKivHr06BG6du2KW7duAQCmTp2KOXPmwNzc3MCRERmvAj0b6/Dhw2jbti2+/vprnDt3DmXKlMHw4cMxePBgAO82J42KioKvr6/yHnt7ezRp0gRBQUFZJjupqalITU1Vfi+VSgG8W9tCJpPp8Y0Knoz3LWrvnR3WiSrWh6q81Ie/vz+GDx+OxMRElCxZEtu2bYOfn1+uyysI+PnIjHWiSp/1oWmZEiGE0LTQtLQ0HDp0CEFBQYiKigIAuLq6omnTpujSpYvOB9RlLIc+btw4fP3117h27RpGjx6N9evXo1+/frh06RKaNWuGiIgIuLm5Ke/r2rUrJBIJ9u7dq7bc2bNnqx1ftHv3bu4cTEQ6l5qaip9//hmBgYEA3m2xM27cOJQoUcLAkREVbsnJyejZsyfi4+NhZ2eX5XUaJzuhoaFo27YtIiIi0KRJE7i4uAAAoqOjceXKFZQtWxbHjx9H5cqVdfMGACwsLNCwYUNcunRJeezbb7/FtWvXEBQUlOtkR13Ljru7O169epVtZRkjmUyGwMBAtGnThs3o/491oqqw14dcIXD93zeISUiFs60lGpZ3hKmJJNflaVsf9+/fR8+ePXH37l1IJBJMnToV3333HczMCnTDusYK++dDH1gnqvRZH1KpFCVLlswx2dH4py1j2vnNmzczFSiVStG3b1+MGDECJ06cyH3UH3Bzc4Onp6fKsRo1aig3HHV1dQXwLuF6P9mJjo6Gl5dXluVaWlqqXY3U3Ny8yH4wi/K7Z4V1oqow1kfAnUjMOXIPkfH/TVhws7fCrE6eaFfLLZs7c6ZJfezYsQPDhg1DcnIyXFxcsHPnTpVud2NSGD8f+sY6UaWP+tC0PI1nY128eBHz589XmznZ2dlh3rx5+OuvvzSPUAPNmjXDw4cPVY49evQI5cuXB/BusLKrqytOnTqlPC+VSnHlyhV4e3vrNBYiKlwC7kRi2M5glUQHAKLiUzBsZzAC7kTq7dlJSUkYMGAA+vXrh+TkZPj4+CAkJMRoEx2igk7jZMfBwQFPnjzJ8vyTJ0/g4OCgg5D+M3bsWFy+fBkLFy5EaGgodu/ejY0bN2LEiBEAAIlEgjFjxmD+/Pk4fPgw/v77b/Tt2xelS5fGZ599ptNYiKjwkCsE5hy5B3V99BnH5hy5B7lC4yGLGrt79y4aN26Mbdu2wcTEBHPnzsWJEyeULdFElP807sb65ptv0LdvX8yYMQM+Pj4qY3ZOnTqF+fPnY9SoUToNrlGjRjh48CCmTp2KuXPnwsPDA6tWrUKvXr2U10yaNAlJSUkYMmQI4uLi0Lx5cwQEBCgHNxNR0XM1PDZTi877BIDI+BRcDY+FdyXdDBIWQmDLli0YNWoU3r59Czc3N+zZswetWrXSSflElHsaJztz585FsWLF8P3332P8+PGQSN4N8BNCwNXVFZMnT8akSZN0HuCnn36a7UJbEokEc+fOxdy5c3X+bCIqnGISNFtUVNPrcpKQkIBhw4Zh165dAIB27dphx44dKFWqlE7KJ6K80Wo6wOTJkzF58mTl+jbAu0HC7y/0R0RkaM62mrXsanpddm7duoWuXbvi0aNHMDU1xYIFCzBx4kSYmGg8SoCI9CxXcx89PDyY4BBRgdXYwwlu9laIik9RO25HAsDV3gqNPZxy/QwhBNavX48xY8YgNTUVZcuWhb+/P5o1a5brMolIP7T6p0dkZCR27tyJY8eOIS0tTeVcUlISu5KIqEAwNZFgVqd3y1Z8uKJOxvezOnnmer2d5ORk9OrVC8OGDUNqaio+/fRThISEMNEhKqA0TnauXbsGT09PjBgxAl999RVq1qyJu3fvKs8nJibqZddzIqLcaFfLDet614ervWpXlau9Fdb1rp/rdXaCg4Mxbtw47N+/H2ZmZli2bBkOHz7M1ZCJCjCtNgL9/PPP8fPPPyMpKQmTJ09Gq1atEBgYiHr16ukzRiKiXGlXyw1tPF1xNTwWMQkpcLZ913WVmxYdIQTWrFmDCRMmIC0tDeXLl4e/vz8++ugjPURORLqkcbJz48YNrF27FiYmJrC1tcVPP/2EcuXKwcfHBydOnEC5cuX0GScRUa6YmkjyPL38zZs3GDRoEA4ePAgAaNKkCQ4fPgxnZ2ddhEhEeqbVAOWUFNVpmlOmTIGZmRn8/PywZcsWnQZGRFQQXL16Fd26dcOTJ09gbm6OxYsXo2LFinB0dDR0aESkIY2TnVq1auHSpUuoU6eOyvEJEyZAoVCgR48eOg+OiMhQhBBYuXIlJk+ejPT0dFSsWBF79+5F3bp1cezYMUOHR0Ra0HiAct++fXHx4kW15yZNmoQ5c+awK4uIjEJsbCw6d+6C8ePHIz09HZ+064xr12+gYcOGhg6NiHJB42Tnm2++wS+//JLl+YzFBomICrNLly6hes3aOHr0CGBqDie/4QirMxgd19/Q6+ahRKQ/XOKTiAiAQqHAkiVL0KJlS7yMioCZY2m49VkO23odIJFIlLuln7gbbehQiUhLuVpBmYjImLx8+RJ9+/ZFQEAAAMCmRiuUaDsCJpY2ymsE3i1IuOD4A0yqYZg4iSh3mOwQUZF2/vx59OjRAxEREbCwtELxTwajeB0/5WbH73u3W3oqwqS5W3mZiAyD3VhEVCTJ5XLMnz8fn3zyCSIiIlC9enUs/eUIbOu2VZvovE8qy6cgiUgntE52/vnnH33EQUSUb6Kjo9G2bVvMmDEDCoUC/fr1w/Xr19G4vmarwduZ6zlAItIprZOdypUr45NPPsHOnTszLTJIRFTQnT59GnXr1sWpU6dgY2ODbdu2Ydu2bShWrJhyt/Ss2nUkANzsLVHJTt1e6kRUUGmd7AQHB6NOnToYN24cXF1d8b///Q9Xr17VR2xERDojl8sxa9Ys+Pr6Ijo6GjVr1sS1a9fQr18/5TWa7JY+vX115HKzdCIyEK2THS8vL/zwww+IiIjAli1bEBkZiebNm6NWrVpYsWIFXr58qY84iYhyLSIiAr6+vpg7dy6EEPjmm29w9epVeHp6Zro2p93S29Z0ya+wiUhHcj0by8zMDF988QU6duyIn376CVOnTsWECRMwbdo0dO3aFUuWLIGbm5suYyUi0trJkyfRu3dvvHz5EsWLF8eGDRvQs2fPbO/Jbrd0mYyjk4kKm1zPxrp+/TqGDx8ONzc3rFixAhMmTEBYWBgCAwMRERGBLl266DJOIiKtpKenY/r06WjXrh1evnyJunXr4saNGzkmOhkydkvv4lUG3pVKwJR9V0SFltYtOytWrMDWrVvx8OFDdOjQATt27ECHDh1gYvIub/Lw8MC2bdtQoUIFXcdKRKSR58+fo0ePHrhw4QIAYNiwYVixYgWsrKxyuJOIjJHWyc66deswcOBA9O/fP8tuKmdnZ2zevDnPwRERaevYsWPo27cvXr9+DTs7O2zatAldu3Y1dFhEZEBaJzuBgYEoV66csiUngxACz549Q7ly5WBhYaEyw4GISN9kMhmmT5+O77//HgBQv3597Nu3D5UqVTJwZERkaFqP2alUqRJevXqV6XhsbCw8PDx0EhQRFVxyhUBQ2Gv8HvICQWGvIVcYfs2Zf//9Fy1btlQmOt9++y0uXbrERIeIAOSiZUcI9b/YEhMT2R9OZOQC7kRizpF7iIz/b0FRN3srzOrkiXa1DDP78vfff8eAAQPw5s0bODg4YMuWLfj8888NEgsRFUwaJzvjxo0DAEgkEsycORM2Nv/tBiyXy3HlyhV4eXnpPEAiKhhO3I3GKP9b+PCfO1HxKRi2MxjretfP14QnLS0NkydPxqpVqwAAjRs3xt69ezk5gogy0TjZuXnzJoB3LTt///03LCwslOcsLCxQt25dTJgwQfcREpHBKQSw6NiDTIkO8G4ncAmAOUfuoY2na75M0f7nn3/QrVs3XL9+HQAwfvx4LFy4UOX3EhFRBo2TnTNnzgAABgwYgB9++AF2dnZ6C4qICpYwqQRR0tQszwsAkfEpuBoeC+9KJfQay2+//YaBAwdCKpXCyckJ27ZtQ6dOnfT6TCIq3LQes7N161Z9xEFEBZhUw0WDYxL0tzlwSkoKJkyYgLVr1wIAmjVrhj179sDd3V1vzyQi46BRsvPFF19g27ZtsLOzwxdffJHttQcOHNBJYERUcNiZa3ads61+Jik8fvwY3bp1U3anT5kyBXPnzoW5uYaBEVGRplGyY29vD4lEovwzERUtlewEXO0sES1NVTtuR4J3G2U29nDS+bP9/f0xePBgJCYmomTJkvjll1/Qrl07nT+HiIyXRsnO+11X7MYiKnpMJMB3HapjlP8tSACVhCdjOPKsTp46HZz89u1bjBkzBhs3bgQAtGzZErt370aZMmV09gwiKhpyvREoERUtbWu6YF3v+nC1V+2qcrW30vm08wcPHqBJkybYuHEjJBIJZsyYgVOnTjHRIaJc0ahlp169espurJwEBwfnKSAiKrja1XJDG09XXA2PRUxCCpxt33Vd6bJF55dffsGwYcOQlJQEFxcX7Ny5E76+vjorn4iKHo2Snc8++0zPYRBRYWFqItHL9PKkpCSMGjVK2VXeunVr7Nq1C66urjp/FhEVLRolO7NmzdJ3HERUhN29exddu3bFvXv3YGJiglmzZmH69OkwNTU1dGhEZAS0XmeHiEhXhBDYunUrRo4cibdv38LNzQ27du3CJ598YujQiMiIaJTsODk54dGjRyhZsiQcHR2zHb8TGxurs+CIyHglJCRg2LBh2LVrFwDAz88Pv/zyC5ydnQ0cGREZG42SnZUrV8LW1hYAlJvuERHl1q1bt9C1a1c8evQIpqammDdvHiZPngwTE04QJSLd0yjZ6devn9o/ExFpQwiBjRs3YvTo0UhNTUWZMmXg7++P5s2bGzo0IjJiuRqzI5fLcfDgQdy/fx8A4OnpiS5dusDMjEOAiEg9qVSKwYMHY9++fQCAjh07Ytu2bShZsqSBIyMiY6d1dnL37l107twZUVFRqFatGgBgyZIlKFWqFI4cOYJatWrpPEgiKtyCg4PRtWtXhIWFwczMDIsWLcK4cePYbUVE+ULr3zTffPMNatasiefPnyM4OBjBwcF49uwZ6tSpgyFDhugjRiIqpIQQWLNmDby9vREWFoby5cvjr7/+woQJE5joEFG+0bplJyQkBNevX4ejo6PymKOjIxYsWIBGjRrpNDgiKrzi4uIwaNAgHDhwAADQpUsXbN26VeV3BxFRftD6n1ZVq1ZFdHR0puMxMTGoXLmyToIiosLt6tWrqFevHg4cOABzc3OsWrUKBw8eZKJDRAahUbIjlUqVX4sWLcK3336L/fv34/nz53j+/Dn279+PMWPGYMmSJfqOl4gKMCEEVq5ciebNm+PJkyfw8PDAxYsXMXr0aI331yMi0jWNurEcHBxUflEJIdC1a1flMSEEAKBTp06Qy+V6CJOICrrY2Fj0798fR44cAQB89dVX+Pnnn2Fvb2/gyIioqNMo2Tlz5oy+4yCiQuzSpUvo3r07nj17BgsLC6xcuRLDhg1jaw4RFQgaJTutWrXSdxxEVAgpFAosW7YM06ZNg1wuR5UqVbBv3z54eXkZOjQiIiWNkp3bt2+jVq1aMDExwe3bt7O9tk6dOjoJjIgKtpcvX6Jfv344fvw4AKBHjx7YsGGDcmsZIqKCQqNkx8vLC1FRUXB2doaXlxckEolynM77JBIJx+wQFQHnz59Hjx49EBERASsrK6xevRrffPNNoey2kisErobHIiYhBc62Vmjs4QRTk8L3HkSUNY2SnfDwcJQqVUr5ZyIqmhQKBRYtWoSZM2dCoVCgevXq2LdvH2rXrm3o0HIl4E4k5hy5h8j4FOUxN3srzOrkiXa13AwYGRHpkkbJTvny5dX+mYiKjujoaAwcOBCBgYEAgD59+uCnn35C8eLFDRxZ7gTcicSwncH4sI06Kj4Fw3YGY13v+kx4iIyE1isoHz58WO1xiUQCKysrVK5cGR4eHnkOjIgKjtu3b2Po0KGIioqCtbU11q5di/79+xfKbivgXdfVnCP3MiU6ACAASADMOXIPbTxd2aVFZAS0TnY+++wztWN2Mo5JJBI0b94chw4d4mqpRIWcXC7H3LlzsWDBAgghULNmTezbtw+enp66Kd9A42WuhseqdF19SACIjE/B1fBYeFcqofd4iEi/tN4uIjAwEI0aNUJgYCDi4+MRHx+PwMBANGnSBEePHsX58+fx+vVrTJgwQR/xElE+iYyMhK+vL+bPnw8hBAYMGICrV6/qLNEJuBOJ5ktOo8emyxjtH4Iemy6j+ZLTCLgTqZPysxOTkHWik5vriKhg0zrZGT16NFasWAEfHx/Y2trC1tYWPj4++P777zFx4kQ0a9YMq1atUvbr69LixYshkUgwZswY5bGUlBSMGDECJUqUQPHixfHll1+q3buLSBNyhcCV8FjceCXBlfBYyBXqOjqMX2BgILy8vHD27FkUK1YMY8eOxYYNG2BjY6OT8jPGy3zYupIxXkbfCY+zrZVOryOigk3rZCcsLAx2dnaZjtvZ2eGff/4BAFSpUgWvXr3Ke3TvuXbtGjZs2JBpHZ+xY8fiyJEj+PXXX3Hu3DlERETgiy++0OmzqWjIaGnoveU6djw2Re8t1/OtpUGuEAgKe43fQ14gKOy1wZKs9PR0fPfdd2jbti1iYmJQp04dXL58WacLi+Y0XgZ4N15Gn3XQ2MMJbvZWyKrDTIJ3s7IaezjpLQYiyj9aj9lp0KABJk6ciB07diino798+RKTJk1Co0aNAACPHz+Gu7u7zoJMTExEr169sGnTJsyfP195PD4+Hps3b8bu3bvRunVrAMDWrVtRo0YNXL58GR999JHa8lJTU5Gamqr8XiqVAgBkMhlkMpnO4i4MMt63qL33h07cjcYo/1tZzsz5sXtdtK3pordnzz/2AFHS/z6TrnaW+K5Ddb09U53nz5+jb9++uHDhAgBgyJAh+P7772FmZoawsDCdfUauaDheJig0Bk30mGxMb18No/xvQQKo/H+XvHdeIU+H4oOlw/gzo4r1kRnrRJU+60PTMiVC3eqA2Xj48CG6dOmC8PBwZULz7NkzVKxYEb///juqVq2KQ4cOISEhAX369NE+cjX69esHJycnrFy5Eh9//DG8vLywatUqnD59Gj4+Pnjz5g0cHByU15cvXx5jxozB2LFj1ZY3e/ZszJkzJ9Px3bt366yZngoPhQDmBJsiLg2A2n/rCzhYALPqy6HrsbO3Xkuw5VFGA+v7hb/7sRxYVYG6JfTfynP9+nX88MMPSEhIgLW1NUaMGIHmzZurvVYhgDCpBFIZYGcOVLITWtXLjVcS7HhsmuN1favI0aCkft/91msJDjwxQVzafy/gYCHwRYX8qXciypvk5GT07NkT8fHxanudMmjdslOtWjXcu3cPJ0+exKNHj5TH2rRpAxOTd7+0P/vss9xFrYa/vz+Cg4Nx7dq1TOeioqJgYWGhkugAgIuLC6KiorIsc+rUqRg3bpzye6lUCnd3d/j5+WVbWcZIJpMhMDAQbdq0gbm5uaHDMYgr4bGIu3w9myskiEsDSnl+pNOWBrlCYNHy8wBS1ZyVQALgeLQNJvVqqbcZSjKZDDNmzMCKFSsAAPXq1cOuXbtQuXJllWsyPiOnH8ViUR5boUqEx2LH4+zq+x2/Fk302rIDAB0ATFIIXP/3DWISUuFsa4mG5R2zrW/+zKhifWTGOlGlz/rI6JnJidbJDgCYmJigXbt2aNeuXW5u19izZ88wevRoBAYGwspKdwMFLS0tYWlpmem4ubl5kf1gFuV3f52crvF1uqyj62GvVZKGD73rzknFzecJepn+/O+//6J79+64fPkyAGDkyJFYtmyZ2p8NADj9KFZtV1+0NBWj/G9pvAifd2VnuNlbISo+Re24HQkAV3sreFd2zpdp6OYAmlfVvruwKP/MqMP6yIx1okof9aFpeRolO6tXr8aQIUOUe+Bk59tvv9XowZq4ceMGYmJiUL9+feUxuVyO8+fPY82aNThx4gTS0tIQFxen0roTHR0NV1dXncVBxs1QM3MMOf35999/x4ABA/DmzRvY29tjy5Yt2Q7sVwhg0bEHOlmEz9REglmdPDFsZ3CW42VmdfLkYn5EpDMaJTsrV65Er169YGVlhZUrV2Z5nUQi0Wmy4+Pjg7///lvl2IABA1C9enVMnjwZ7u7uMDc3x6lTp/Dll18CeDem6OnTp/D29tZZHGTcMmbm5NTSoOuZOYZIstLS0jB58mSsWrUKANCoUSPs3bs3x1XPw6QSDVqhNF+Er10tN6zrXT/TvlSu3JeKiPRA441A1f1Z32xtbVGrVi2VY8WKFUOJEiWUxwcNGoRx48bByckJdnZ2GDVqFLy9vbOciUX0IUO1NOR3khUeHo5u3bopx7+NHTsWixcvhoWFRY73SjWcRKFNK1S7Wm5o4+nKHceJSO+0XmenoFm5ciU+/fRTfPnll2jZsiVcXV1x4MABQ4dFhUxGS4OrvWoriqu9ld42hMxIsoDMc8B0nWQdOHAA9erVw7Vr1+Do6IjDhw9jxYoVGiU6wLtZV5rQthXK1EQC70ol0MWrDLwrlWCiQ0R6oVHLzvszl3KSMatDX86ePavyvZWVFdauXYu1a9fq9blk/DJaGoJCY3Dyryvwa9FE74Nk9d2dk5KSgokTJ2LNmjUAAG9vb/j7+6NcuXJalVPJTsDVzhLR0tR87eojItIFjZKdmzdvalRYYd0BmSiDqYkETTyc8Pq+QJN86lLRV3dOaGgounbtqvz5nTRpEubPn5+r2RAmEuC7DtWzXYSPg4qJqKDSKNk5c+aMvuMgKtIyunN0Ze/evRg8eDASEhJQsmRJ7NixA+3bt89TmW1runBQMREVSrlaZycrMTExcHZ21mWRRKSFt2/fYsyYMdi4cSMAoEWLFtizZw/KlCmjk/I5qJiICiONByjb2Njg5cuXyu87duyIyMj/NkiMjo6Gmxv/ZUdkKA8ePECTJk2wceNGSCQSfP3NaCzY9Ctc3Urr9DkcVExEhY3GLTspKSl4fxut8+fP4+3btyrXaLnNFhFpSK4Q2bam7Ny5E0OHDkVSUhLMiznAseN4XC1RD322Xocbu5mIqIjTaTcWBygT6V7AnchM42QyEpgWHu/Wltq6dSsAwKpcHZToNAFmxf+bFZWxc7u+ptATERV0Ok12iEi3Au5EYtjO4EzTvaPiUzBo5UGYnfsBT8MewcTEBKU/6QOT+l9AYqK6o7i22zkQERkbjcfsSCQSlZabD78nIt2SKwTmHLmXKdERQiDhdiAid4zD07BHcHV1xeodB2Da8OtMiY7yHvy3nQMRUVGjccuOEAJVq1ZVJjiJiYmoV68eTExMlOeJSHeuhseqdF0BgCLtLWJP/oSku++Wg7CqUA8/792NdAtb4O+QHMvUx6aiREQFncbJTsaYACLKHx8mJmkx4Xj5+xKkxz4HJCZwaNEbdh99hXQLW4Pt3E5EVBhonOz069dPn3EQ0QcyEhMhBBJvnUDsnxsAuQymxUugZOeJsHKvpbzOUDu3ExEVBoV+I1AiY9XYwwmlLOV4feR7xJ5YA8hlsKrYAG4DVsPKvRYkeDcrK2Maen5tKkpEVNgw2SEqoG7fCkHEtjFIun/+XbfVxwPg/NUsmNrYq01gDLFzOxFRYcCp50QFjBACP/30E8aNG4e0tDQ4u5VBqS6TkWhfUXlNVvtRcTsHIqLMmOwQFSBxcXH45ptv8NtvvwEAOnfujK1bt8LewVHjBEbXm4oSERV2uU520tLSEB4ejkqVKsHMjDkTUV5du3YN3bp1Q3h4OMzNzbFkyRKMGTNGudwDExgiotzResxOcnIyBg0aBBsbG9SsWRNPnz4FAIwaNQqLFy/WeYBEBZFcIRAU9hq/h7xAUNhryBW5X2dKCIFVq1ahWbNmCA8PR4UKFXDhwgWMHTuWC3cSEemA1snO1KlTcevWLZw9exZWVv8NhPT19cXevXt1GhxRQRRwJxLNl5xGj02XMdo/BD02XUbzJacRcCdS67JiY2Px2WefYezYsZDJZPjiiy9w8+ZNNG7cWA+RExEVTVonO4cOHcKaNWvQvHlzlX911qxZE2FhYToNjqigydir6sOVjTM229Qm4QkKCkK9evVw+PBhWFhYYM2aNdi/fz8cHBzyFKMuW52IiIyB1oNtXr58CWdn50zHk5KS2ORORi2rvaoA7TbbVCgUWL58OaZNm4b09HRUrlwZe/fuRf369fMcY3Y7pHPqOREVVVq37DRs2BB//PGH8vuMBOfnn3+Gt7e37iIjKmDU7VX1Pk0223z16hU6deqESZMmIT09Hd27d8eNGzd0lujoqtWJiMiYaN2ys3DhQrRv3x737t1Deno6fvjhB9y7dw+XLl3CuXPn9BEjUYGg6SaaWV134cIFdO/eHS9evICFpSXGzFiIBVPGwMw072t76qrViYjIGGn9W7Z58+YICQlBeno6ateujZMnT8LZ2RlBQUFo0KCBPmIkKhByu9mmQqHAwoUL0erjj/HixQuYOZVFiZ7LsDehGlosPaOTFhddtDoRERmrXC2QU6lSJWzatEnXsRAVaLnZbDMmJgZ9+vTByZMnAQDFan4CJ7/hMLGwBvBfF1Net3PIa6sTEZEx07plRyqVqv1KSEhAWlqaPmIkKhC03Wzz7Nmz8PLywsmTJ2FibokS7UejRMdxykQHgDJpmnPkXp5mTeW21YmIqCjQOtlxcHCAo6Njpi8HBwdYW1ujfPnymDVrFhQKhT7iJTIoTTbblMvlmDt3Lnx8fBAZGQmPytXg0mcFitdpo3bGoi66mDJanbIajfP+DulEREWN1t1Y27Ztw/Tp09G/f3/lwmdXr17F9u3b8d133+Hly5dYtmwZLC0tMW3aNJ0HTGRo2W22GRkZid69e+P06dMAgAEDBqDt4KmY/PujHMvNSxdTRqvTsJ3BkAAq3WzqWp2IiIoSrZOd7du3Y/ny5ejatavyWKdOnVC7dm1s2LABp06dQrly5bBgwQImO2S01G22GRgYiN69eyMmJgbFihXDunXr0KdPHwSFvdaozLx2MWW0On24zk5WO6QTERUVWic7ly5dwvr16zMdr1evHoKCggC8m7GVsWcWkbFLT0/H7NmzsXDhQgghULt2bezbtw/Vq1cHkLuBzbmVXasTEVFRpfWYHXd3d2zevDnT8c2bN8Pd3R0A8Pr1azg6OuY9OqIC7vnz52jdujUWLFgAIQT+97//4cqVK8pEB9B+YHNeZbQ6dfEqA+9KJZjoEFGRp3XLzrJly/D111/j+PHjaNSoEQDg+vXrePDgAfbv3w8AuHbtGrp166bbSIkKmGPHjqFv3754/fo1bG1tsXHjRnTv3l3ttexiIiIyHK2Tnc6dO+PBgwfYsGEDHj16N+iyffv2OHToECpUqAAAGDZsmE6DJCpIZDIZvvvuOyxduhTAuy7cvXv3okqVKtnexy4mIiLDyNWigh4eHli8eLGuYyEq8J4+fYru3bsrx6eNGDECy5Ytg5WVZoOL1Q1sJiIi/crVpjx//fUXevfujaZNm+LFixcAgF9++QUXLlzQaXBk/OQKgaCw1/g95AWCwl5nWlgvp/P56fDhw/Dy8kJQUBDs7Ozw66+/Ys2aNRonOkREZBhat+z89ttv6NOnD3r16oXg4GCkpqYCAOLj47Fw4UIcO3ZM50GScQq4E5lpDIvbe2NYcjqfX9LS0jBlyhSsXLkSANCoUSP4+/ujYsWK+RYDERHlntYtO/Pnz8f69euxadMmmJubK483a9YMwcHBOg2OjFfAnUgM2xmcafPKjL2iFh27l+15XWyeqYnw8HC0aNFCmeiMGTMGFy5cYKJDRFSIaJ3sPHz4EC1btsx03N7eHnFxcbqIiYycXCEw58g9tWvOiP//2vRXeJbngbzvJaWJgwcPol69erh69SocHBxw6NAhLFu+AjeeJRSIbjUiItKM1t1Yrq6uCA0NVc68ysB/7ZKmrobHZmqx+VB2OcT7e0nldrCvXCGynBWVmpqKjRs3KrtkP/roI/j7++N+ggWaLzlt8G41IiLSjtbJzuDBgzF69Ghs2bIFEokEERERCAoKwoQJEzBjxgx9xEhGJi97QOminOzGAlW2SkLXrl1x8+ZNAMDEiROxYMECnHr4CsN2BmdqbcroVlNuAppNEkVERIahdbIzZcoUKBQK+Pj4IDk5GS1btoSlpSUmTJiAUaNG6SNGMjJ53QMqL+VkjBVSl7T0nb4Kiad+wtukRNja2uKXX35Bly5dcux2k+Bdt5pCITDvj/ts+SEiKmC0TnYkEgmmT5+OiRMnIjQ0FImJifD09ETx4sX1ER8ZoZz2igIAEwkgBHS6l1RWSYtCloo3pzchMSQAANC0aTMMHDgAHTp0AJBzt1tGt9rw3Tcznfuw5YeIiPJfrtbZAQALCwt4enqicePGTHRIKzntFSUBMLiFR5bngdztJaUuaZG9fo6oX8b/f6IjgZ13VyzYtBclS5ZUXpOXbrf8HFBNRETqadSy88UXX2hc4IEDB3IdDBUdmuwVVa+cY457SWkzRubDpCXx7hnEnlgLIUuBiY09Sn46HtYe9RH7Vg7T967La7ebLgZUExFR7mmU7Njb2+s7DiqCctorKqfz2i46mJG0KGQpiA3cgKS/AwEAluVqo2SniTAr7vT/11ni9Xv3adLtpgldDcwmIiLtaJTsbN26Vd9xUBGV015RWZ3PbqBxVmNkGns4wT4lGvd3zYHs1VMAEtg36wH7pt0gMTFVjgVqWN4RJ+6rxjCrkyeG7QyGBKrjiD78Pju6GphNRETayfWYHSJDyWl2FKB+jMwvO7bj4caRkL16CtNijnDpvgAOzXtCYmKqvLd7o3Jqn5nR7eZqr5qw2NuYY4xPFbjaWWYaX5RBgnctTtoOqCYiIt3QqGWnXr16kEg0GwzKLSNI3zSdHZUxRiYxMREjRozAjh07AAD1vFtC8vEovFZYZ7p35Z+PsOfqv+jgKkGHD85ldKutOf0YWy8+QdxbGeKSZVh16jEcbMyV09A/bPkBcjegmoiIdEOjZOezzz7TcxhEmtN07EtU/Fvcvn0b3bp1w4MHD2BiYoK5c+di6tSpEJBgzenHWPnn40z3RUtTsUVqgvp3o/GpV1mVc4H3orDqz8eZWpXik2UA3rX0xP3/n4HMA6qJiCj/aZTszJo1S99xEKmlbraVJmNfhBAYPWcZok9sQFpqCsqUKYM9e/agRYsWynL9rz1Tf+///3fB8QdoX6eMskVGk8UFrc1NsXZQfbxKSuUKykREBYTWiwpmuHHjBu7ffzeKs2bNmqhXr57OgiICsp5tNa1DDZhIst4/S5GajNcn1iD5/nkAQMPmrXH8oOraOTnvzyVBZHyqynRxTbvPTEwk6OJVRuP3JCIi/dI62YmJiUH37t1x9uxZODg4AADi4uLwySefwN/fH6VKldJ1jFQEZTfbatSezCsVZ0iLDsPL3xcj/U0kIDGBY6u+MPXtCUcn1RldmnaFvX9dbu4hIiLD03o21qhRo5CQkIC7d+8iNjYWsbGxuHPnDqRSKb799lt9xEhFjCazrTIdFwIJwUcR+ct4pL+JhKltKbj2WgK7Jl8hKiENV8NjVa7XdBr4+9fl5h4iIjI8rVt2AgIC8Oeff6JGjRrKY56enli7di38/Px0GhwVTTl3MalSpCTidcCPSH54EQBgXbkJSnQYA1NrW+U1H7a25LxQoMg0XTyne3K7ZxcREemX1i07CoUC5ubmmY6bm5tDoVDoJCgq2rTpBkqNfITIbaPfJTompnBs/Q1KffGdSqIDZG5tyWl/LgCY3r66yuBiTe7hFHMiooJH62SndevWGD16NCIiIpTHXrx4gbFjx8LHx0enwVHRpOlsK+m13xG1cxLS46Nhau8C115LYdfoM5U1obJb0C+rhQJd7S0xsKoCbWu6aHGPFXc2JyIqoLTuxlqzZg06d+6MChUqwN3dHQDw7Nkz1KpVCzt37tR5gFT05NRdJH+bgNfHf8Dbx5cBADZVm6JE+29hYlVc5TpNWlvU7b9Vr6wtTgQczzK+D+8pWdwSEMCrpFQEhb3mdHMiogJG62TH3d0dwcHB+PPPP/HgwQMAQI0aNeDr66vz4BYtWoQDBw7gwYMHsLa2RtOmTbFkyRJUq1ZNeU1KSgrGjx8Pf39/pKamom3btvjpp5/g4pL5X+VUOGS3F1Xqiwd4eXgJ5NKXgKkZHD8ZBNv6n6pd4VvTBf0+3H9LJpNlc7XqPQF3IjHh11sab0ZKRET5L1fr7EgkErRp0wZt2rTRdTwqzp07hxEjRqBRo0ZIT0/HtGnT4Ofnh3v37qFYsWIAgLFjx+KPP/7Ar7/+Cnt7e4wcORJffPEFLl68qNfYSL8yuosy1tkRQgHp1YOIO78DUMhh5uCGkl0mw9K1cqZ7R35SGc0ql9R7C0tuNiN9n7oFE9kiRESkexonO6dPn8bIkSNx+fJl2NnZqZyLj49H06ZNsX79euUKtboQEBCg8v22bdvg7OyMGzduoGXLloiPj8fmzZuxe/dutG7dGsC7Hdpr1KiBy5cv46OPPlJbbmpqKlJTU5XfS6VSAO/+Ra/Jv+qNScb7FsT39qlWEh9XaYE/b4Zi9sRReHrhNADApnoLlGg3CiaWNmrvq1jSGg3L2UEhT4dCrv1zNakTuUJg9uG72a6mPOfIXXxcpYTaBObE3WjMP/YAUdL/Poeudpb4rkN1tWOFDKkgf0YMgfWhivWRGetElT7rQ9MyJUKIrJYuUdG5c2d88sknGDt2rNrzq1evxpkzZ3Dw4EHNo9RSaGgoqlSpgr///hu1atXC6dOn4ePjgzdv3igXOASA8uXLY8yYMVnGOnv2bMyZMyfT8d27d8PGRv1foEWJQgBhUgmkMsDOHKhkJ6CvBoecnnXv3j0sX74cr1+/hpm5OexaD0Hxuu2y3Zh2pKccVew1+ljn2uN4CdbcM83xOnWx3HotwZZHGXMD3n+Pd9cNrKpA3RL6jZ+IyBgkJyejZ8+eiI+Pz9QQ8z6NW3Zu3bqFJUuWZHnez88Py5Yt0y5KLSgUCowZMwbNmjVDrVq1AABRUVGwsLBQSXQAwMXFBVFRUVmWNXXqVIwbN075vVQqhbu7O/z8/LKtLGMkk8kQGBiINm3awNzcHCfuRmNRPrU4ZPesNjVK4fvvv8fs2bMhl8tRpUoV7Ny1G98GxiFamprNOjeWGNmtZZ66gz6sE3WO3I4E7v2dY1kVa3qhQ53/urLkCoFFy88DSFVztQQSAMejbTCpV97eQZc0qY+ihPWhivWRGetElT7rI6NnJicaJzvR0dHZBmlmZoaXL19qWpzWRowYgTt37uDChQt5LsvS0hKWlpaZjpubmxfZD6a5uTlOPXyFUf63MiUS0dJUjPS/hbG+VVChZDGdjC8JuBOZ5bOGbz6HUsGbEHzpHACgd+/eWLduHYoXL47Z1pFqBy7/N/OqJqwsLXId1/uy+zy4ORTTqAw3h2IqZVwPe62S3H3o3f5aqbj5PEFl0HRBUJR/PtRhfahifWTGOlGlj/rQtDyNk50yZcrgzp07qFw584BQALh9+zbc3PQz+2TkyJE4evQozp8/j7JlyyqPu7q6Ii0tDXFxcSqtO9HR0XB1ddVLLMZKky0aVv75WHksLzOOsnvW26e38erIMjxLjIWFlRUmzFqCORNHwsz0XbfPhwOXM2g680pXcruaMvfXIiLKfxovKtihQwfMmDEDKSmZfwm/ffsWs2bNwqeffqrT4IQQGDlyJA4ePIjTp0/Dw8ND5XyDBg3etUicOqU89vDhQzx9+hTe3t46jcXYXf/3jVZbNGTMOAq4E6n1s9RtByEUcsRd3INo/+8gT4yFeYlyKNFzOXbFVUKLpWdUntOulhsuTG6NPYM/wg/dvbBn8Ee4MLl1vk71zu1qytxfi4go/2ncsvPdd9/hwIEDqFq1KkaOHKlc6+bBgwdYu3Yt5HI5pk+frtPgRowYgd27d+P333+Hra2tchyOvb09rK2tYW9vj0GDBmHcuHFwcnKCnZ0dRo0aBW9v7yxnYpF6MQlZd62o89+Mo3to4+mqVZfWh60W8sQ3eHX0e6T8exsAUKy2L5x8h8LE4t1f+Oqmcn+4No4h5KaViftrERHlP42THRcXF1y6dAnDhg3D1KlTkTGJSyKRoG3btli7dq3OF/Jbt24dAODjjz9WOb5161b0798fALBy5UqYmJjgyy+/VFlUkLTjbJt5DFNO3o0vScHV8FitEo/3Wy3ePgnBqyPLoEiOg8TcCk5+w1G8VutMz8ltYqVv6lZgzm48U3YLJnJ/LSIi/dBqUcHy5cvj2LFjePPmDUJDQyGEQJUqVeDo6KiX4DSZFW9lZYW1a9di7dq1eomhqGhY3jGHXcCzpu34ksYeTnAtbo4Hx7YgPmgfAAHzUhVQqstkmJdwV3uPJomVoRbp07aVqaCMOyIiKipytYKyo6MjGjVqpOtYyICya3HIScniWbcKqUtAoiIjkHRoFuJvvNvbqnjddnD0GQwT85xbl7JKrALuRGZKHgrytg3atggREVHu5SrZIeOUVYtDjrLIjNQlINbRtxHx+zJI38TC2qYYynQaA1kFzQeTqxu4m9dtGwylIIw7IiIqCpjskIr3WxyO34nEjqB/c7wnJjHz4OYPExAhT0fcXzvx75X9AIBKNWrh+O8HULFSZVwNj0VU/FvM++M+YpPSsnyOm5qBuzlNmS+oY32IiCj/aDz1nIqOjBaH9hq2hsw7eldlaviHCUi6NAbRe6ZC+v+Jjm39jijRfSkqVqqsfNbn9cvi6wZlsn1O57pumRIWddPY3/f+WB8iIiqamOxQljKmSefUHhKbJFNZc+f9BCQ59Aoit45G6ov7kFjYoGSXKXBqMwzRyQqVBESuEDh8K/s1ew7fioRcodqGw0X6iIgoJ0x2KEvvL5yniTlH7kGuEIhJSIGQyxB7+me8/G0eFCkJsHCtArcBq1GsenPl9e8nIDm10ADqW2i4SB8REeWEY3aMhC6nXX9Y1jctPPDzhXBktxLA+91F6XHRiNo1GWmRjwAAtg27wPHj/pCYqu5h8n4CEhX/VqPYPryuQXlHmEje7Z6eFRPJu+uIiKhoYrJjBHQ57VpdWdr4/dABrJ83EWnx8TCxLIYSHcfCporqatbqVgnObmDy+14lql5349832SY6wLtE6Ma/bzjziYioiGKyU8jpctp1VmVpQqTL8ObMZiwJPgoAqF6nARKbjoCZvbNGqwQ7ZbNWz/vWnHkMdydr5TtxzA4REeWEY3YKMU12Ks8YR5PV/VfCY3HjlQRBYa8x+7D6snIiexOBqJ0TkPD/ic7EiRNx+3oQNo1oB1d71bEyrvZWahMwVzvNxtTEv01XGQzNMTtERJQTtuwUAlmNx9Fm2vWHXTiq3VWm2PH4Rq5iS7r/F14HrIZIews7B0fs3vkLOnbsCEC7VYIzZn5p2n2WsXYON9YkIqKcMNkp4LIbj5OartCojA+7cPLSXZVBIUvFm9ObkBgSAACoWb8xAn7/DWXLllW57v1VgrMbRP3+dhU5xfVhEseNNYmIKDvsxirAMpKSD1s7MsbjPHmVpFE573fhZNf1pSnZ6+eI2jlBmehMmjwFIVcuZkp03hdwJxLNl5xGj02XMdo/BD02XUbzJadVFiPM2K7Cwdo8y3Lel5HEZdynaZcZEREVLWzZKaA02QZhz9WncLWzQrRU8y6cy2Gvcz3TCgAS755B7Im1ELIUmNjYY+6KdZj+vx7Z3qPNIOp2tdxga2mOXpuv5BjL+0kcN9YkIqKsMNkpoDQZjxMlTcVY36pY9ecjtV04AkD3Ru44ejsCzrZWeJOUimkH7+QqHoUsBW/+3IjE2ycBAHYedfHTz1vRq3W9bO/Lzd5VH1UqkatxONxYk4iI1GGyU0BpOlW6QkkbtTuV29u86wpa+efjPMdinxKN+KNLkRj2EBKJBANGjMe6FYtgYZ7zxyc3g6jfH7/DcThERJRXTHYKKG2mVHtXKqHShfPkVTJW/fkoV+NyJABc7CyxvKsXXiWm4trJg1g5ZzKSk5Ph4uKC3bt3o3Xr1pnuy2rwcW7XwckYh/NhEueay8USiYio6GKyU0BpO6U6owtHrhBovuR0ngYgz+5cE3VdrTBixHjs2LEDAODj44OdO3fC1dU10/XZzRjLzTo4GYlTaroCy76uCwjgVVJqjuNwdLllBhERGQ8mOwVUbrtyNNlQMysO1uZY/GVtlBGv0KhRazx48AAmJiaYO3cupkyZAlNT00z35DT4eG3P+lolbdklTtmNx9HllhlERGRcOPW8AMvNlOq8bIuwpmc9PL/8Bxo3bowHDx6gdOnSOHPmDKZPn6420dFkBed5f9zDjI41APyXpGX4MGnLaar9+9PU35fb+4iIqGhgy04Bp+2U6txtiyDgbKXA2pmj4e+/591z27XDjh07UKpUqSzv0nTwsWMxyxzH3+Rm1haQu9leRERUtDDZKQS0mVLdoLwjnIpZaLyLuARAavQ/eHF6Fa49DYepqSkWLlyICRMmwMQk+4Y/bQYfd/Eqk23SltutL/KyZQYRERUNTHaMSMa4FU0THSEEJA8C8fLYOqSny+Du7g5/f380bdpUo/u1HXycXdKW21lb3PWciIhywmTHSGiy35WbvRVmdPSEYzELhEfE4OeFU3Am4DAAoGPHjtixYwecnDTfMFOXm3Dmdvdy7npOREQ54QBlI6DJfldOxcxxbuIn6FDHDeZvwvFdv444E3AY5ubmGDBgAA4cOKBVogP8N2MMyHnwcU4yEqesrpTgXbL2YeKU2/uIiKjoYLJTgMkVAkFhr/F7yAsEhb2GXKE+ndFkunlskgzbLobjm0lz4N20KcLDw1GhQgWcPXsWXbp0gUSSu8G7utqEM7eJky4TLiIiMk7sxiqgtFk3RpPxKPK3CRgzuDfePr4MAHCq2Rzfb9yERo0q4dixY3mKVVebcOZ21WSutkxERNlhsqMnOa3mm915bXYJB3Iej5L64gFeHl4CufQlYGoGx08Gwbb+p5h4OAxWNsWV8VwPe53rZEVXm3DmNnHirudERJQVJjt6kFOrTMCdSMw+fBdR0lTleVc7S8zuXBNtPF21Xjcmq4HCQiggvXoIcee3Awo5zBzcULLLZFi6VlZes+D4A7R1lmDR8vMq8Rhy9eHcJk7c9ZyIiNThmB0dy2k130XH7mHozmCVxAIAoqSpGLozGGtOh2q8bkyG98etZJC/leLlb/MQd3YLoJDDpnoLuPVfpZLovCsrFdsem2SOh6sPExGRkWCyo0M5reYrAGw8H55tGRvOh2n0rKx2Cbe3MkPK87uI3Pot3oZdA0zN4eQ3HCU7T4KJZTHNXgT/bfcw58i9TAOjNR04TUREVBCwG0uHNJkVlVNakJwm1+hZ6sbp+Hm6YGPkKdzevRwQCpg5lUGpLpNh4Vwxh9LUj2tRt/owN9wkIqLChi07OqSrVXqLWWTedPN96taNiYmJQYcOHXBw4/eAUKCY58dw67tSg0QnZxnvxQ03iYioMGKyo0O6WqW3mkvxbM93ruumMsvo3LlzqFevHk6cOAELSys4tfsWJT4dDxNLG53E42xrpdEO5+q6vIiIiAyNyY4ONfZwgoONeZ7LCX+dnO35w7ciIVcIyOVyzJs3D61bt0ZERARq1KiBy5evwN7LT8tFArNOUEwk7zYX1WbDTSIiooKEyU4+yykFKW5phjfJsmyviYxPwfGr99G2bVvMnDkTCoUC/fv3x7Vr15BiWwbaN65kHZVCADf+fcMNN4mIqNBisqNDV8NjEZdDopJTHtK1Ydkcn/P2SQj6fPoxTp06BStrG4yeuwpDvlsGK2sbREl1n2xkLNKnCW64SUREBQ2THR3StFVjYLMKcLVTTQrc7K2wvnd9tPF0zfI+oZAj7q+diNk7A3GvX8LapQKcei7HoaTK6LHpMpovOY2Lj19pFIOdlRnG+FTR6NqM1Yi54SYRERVGnHquQ5q2arTxdMX0jp5qtzaQK4Ta1ZDTE17j1ZHvkfrsDgCgeN22cPQZAhNzS+U1UfEp2B/8XKMYPq9XGv7XnmZ7jQTv9pfKiG1WJ08M2xkMCVRbqLjhJhERFWRs2dEhbVo/MrY26OJVBt6VSiiTBHW7eL/95wYit45C6rM7kFhYo9xXU1Ci3SiVRAfIuYvsfduDnmZaNfnDWAHVBEZXO5wTERHlJ7bs6JCuWj8ykopZh27jwR8/Q3p5PwDAxq0Sxixci10P0vMUp4kEOQ5izmrHcG64SUREhQ1bdnRMV60fNe3TYXp8rjLR+aLXQMSE/o3GXrXyHKMms7WWfVU3y1izapUiIiIqiNiyowd5bf04evQo+vXrh9jYWNjZ2WHz5s346quvAGg+LmisbxX4X3uWaVuH9rVcseXikxzvf5WUdRcXERFRYcJkR08yWj+0kZaWhqlTp2LFihUAgIYNG2Lv3r2oWPG/LR8yxgV9OIA5Q8ag4pGtq2Bk6yqZEq6r4bEaJTucQk5ERMaC3VgFxJMnT9CyZUtlojN69GhcuHBBJdEB1A9gzvDhuCB13U2cQk5EREUNk50C4NChQ6hXrx6uXLkCBwcHHDp0CKtWrYKlpaXa6/MyLkibZImIiMgYsBvLgFJTUzFp0iSsXr0aAPDRRx/B398f5cuXz/HevIwLykiW5hy5pzKmJ6sZWERERIUZkx0DCQsLQ7du3XDjxg0AwIQJE7Bw4UKYm2u+kWhuxgVlyEiWgkJjcPKvK/Br0QTelZ3ZokNEREaHyY4B/Prrr/jmm28glUpRokQJbN++HR07dsz3OExNJGji4YTX9wWacK0cIiIyUhyzk49SUlIwfPhwdO3aFVKpFM2aNUNISIhBEh0iIqKigslOPnn06BG8vb2xbt06AMDUqVNx9uxZlC2b8y7nRERElHvsxsoHu3fvxv/+9z8kJiaiVKlS+OWXX9C2bVtDh0VERFQksGVHj96+fYvBgwejV69eSExMxMcff4yQkBAmOkRERPmILTt6Ehsbi1atWuHOnTuQSCSYMWMGZs6cCVNTU0OHRkREVKQw2dETR0dHVKtWDS9fvsTu3bvRunVrQ4dERERUJBlNN9batWtRoUIFWFlZoUmTJrh69apB45FIJPj5558REhLCRIeIiMiAjCLZ2bt3L8aNG4dZs2YhODgYdevWRdu2bRETE2PQuBwcHODq6mrQGIiIiIo6o0h2VqxYgcGDB2PAgAHw9PTE+vXrYWNjgy1bthg6NCIiIjKwQj9mJy0tDTdu3MDUqVOVx0xMTODr64ugoCC196SmpiI1NVX5vVQqBQDIZDLIZDL9BlzAZLxvUXvv7LBOVLE+VLE+VLE+MmOdqNJnfWhapkQIIXT+9HwUERGBMmXK4NKlS/D29lYenzRpEs6dO4crV65kumf27NmYM2dOpuO7d++GjY2NXuMlIiIi3UhOTkbPnj0RHx8POzu7LK8r9C07uTF16lSMGzdO+b1UKoW7uzv8/PyyrSxjJJPJEBgYiDZt2mi1CakxY52oYn2oYn2oYn1kxjpRpc/6yOiZyUmhT3ZKliwJU1NTREdHqxyPjo7OcnCwpaUlLC0tMx03Nzcvsh/MovzuWWGdqGJ9qGJ9qGJ9ZMY6UaWP+tC0vEI/QNnCwgINGjTAqVOnlMcUCgVOnTql0q1FRERERVOhb9kBgHHjxqFfv35o2LAhGjdujFWrViEpKQkDBgwwdGhERERkYEaR7HTr1g0vX77EzJkzERUVBS8vLwQEBMDFxcXQoREREZGBGUWyAwAjR47EyJEjDR0GERERFTCFfswOERERUXaY7BAREZFRY7JDRERERo3JDhERERk1oxmgnBcZO2ZouhKjMZHJZEhOToZUKuXiV/+PdaKK9aGK9aGK9ZEZ60SVPusj4+/tnHa+YrIDICEhAQDg7u5u4EiIiIhIWwkJCbC3t8/yfKHfCFQXFAoFIiIiYGtrC4lEYuhw8lXGvmDPnj0rcvuCZYV1oor1oYr1oYr1kRnrRJU+60MIgYSEBJQuXRomJlmPzGHLDgATExOULVvW0GEYlJ2dHX8oP8A6UcX6UMX6UMX6yIx1okpf9ZFdi04GDlAmIiIio8Zkh4iIiIwak50iztLSErNmzYKlpaWhQykwWCeqWB+qWB+qWB+ZsU5UFYT64ABlIiIiMmps2SEiIiKjxmSHiIiIjBqTHSIiIjJqTHaIiIjIqDHZMSLnz59Hp06dULp0aUgkEhw6dEjlfP/+/SGRSFS+2rVrl2O5a9euRYUKFWBlZYUmTZrg6tWrenoD3cupTj6sj4yv77//PssyZ8+enen66tWr6/lNdGPRokVo1KgRbG1t4ezsjM8++wwPHz5UuSYlJQUjRoxAiRIlULx4cXz55ZeIjo7OtlwhBGbOnAk3NzdYW1vD19cXjx8/1uer6ERO9REbG4tRo0ahWrVqsLa2Rrly5fDtt98iPj4+23Jz+7NmaJp8Pj7++ONM7zZ06NBsyzXWz8eTJ0+y/B3y66+/ZlluYf18AMC6detQp04d5QKB3t7eOH78uPJ8Qf39wWTHiCQlJaFu3bpYu3Ztlte0a9cOkZGRyq89e/ZkW+bevXsxbtw4zJo1C8HBwahbty7atm2LmJgYXYevFznVyft1ERkZiS1btkAikeDLL7/MttyaNWuq3HfhwgV9hK9z586dw4gRI3D58mUEBgZCJpPBz88PSUlJymvGjh2LI0eO4Ndff8W5c+cQERGBL774Ittyly5ditWrV2P9+vW4cuUKihUrhrZt2yIlJUXfr5QnOdVHREQEIiIisGzZMty5cwfbtm1DQEAABg0alGPZ2v6sFQSafD4AYPDgwSrvtnTp0mzLNdbPh7u7e6bfIXPmzEHx4sXRvn37bMsujJ8PAChbtiwWL16MGzdu4Pr162jdujW6dOmCu3fvAijAvz8EGSUA4uDBgyrH+vXrJ7p06aJVOY0bNxYjRoxQfi+Xy0Xp0qXFokWLdBBl/lJXJx/q0qWLaN26dbbXzJo1S9StW1d3gRlQTEyMACDOnTsnhBAiLi5OmJubi19//VV5zf379wUAERQUpLYMhUIhXF1dxffff688FhcXJywtLcWePXv0+wI69mF9qLNv3z5hYWEhZDJZltfk5metIFJXH61atRKjR4/WuIyi9vnw8vISAwcOzLYcY/l8ZHB0dBQ///xzgf79wZadIubs2bNwdnZGtWrVMGzYMLx+/TrLa9PS0nDjxg34+voqj5mYmMDX1xdBQUH5EW6+io6Oxh9//KHRv9ofP36M0qVLo2LFiujVqxeePn2aDxHqXkZ3jJOTEwDgxo0bkMlkKv/Pq1evjnLlymX5/zw8PBxRUVEq99jb26NJkyaF7nPyYX1kdY2dnR3MzLLfWlCbn7WCKqv62LVrF0qWLIlatWph6tSpSE5OzrKMovT5uHHjBkJCQjT6HWIMnw+5XA5/f38kJSXB29u7QP/+4EagRUi7du3wxRdfwMPDA2FhYZg2bRrat2+PoKAgmJqaZrr+1atXkMvlcHFxUTnu4uKCBw8e5FfY+Wb79u2wtbXNscm1SZMm2LZtG6pVq6Zstm7RogXu3LkDW1vbfIo27xQKBcaMGYNmzZqhVq1aAICoqChYWFjAwcFB5VoXFxdERUWpLSfjuLrPSVb3FETq6uNDr169wrx58zBkyJBsy9L2Z60gyqo+evbsifLly6N06dK4ffs2Jk+ejIcPH+LAgQNqyylKn4/NmzejRo0aaNq0abZlFfbPx99//w1vb2+kpKSgePHiOHjwIDw9PRESElJgf38w2SlCunfvrvxz7dq1UadOHVSqVAlnz56Fj4+PASMrGLZs2YJevXrBysoq2+ve74uvU6cOmjRpgvLly2Pfvn0a/YuuoBgxYgTu3LlTaMYb6VtO9SGVStGxY0d4enpi9uzZ2ZZlDD9rWdXH+4le7dq14ebmBh8fH4SFhaFSpUr5HWa+yenz8fbtW+zevRszZszIsazC/vmoVq0aQkJCEB8fj/3796Nfv344d+6cocPKFruxirCKFSuiZMmSCA0NVXu+ZMmSMDU1zTSSPjo6Gq6urvkRYr7566+/8PDhQ3zzzTda3+vg4ICqVatmWY8F0ciRI3H06FGcOXMGZcuWVR53dXVFWloa4uLiVK7P7v95xvHC/DnJqj4yJCQkoF27drC1tcXBgwdhbm6uVfk5/awVNDnVx/uaNGkCAFm+W1H4fADA/v37kZycjL59+2pdfmH7fFhYWKBy5cpo0KABFi1ahLp16+KHH34o0L8/mOwUYc+fP8fr16/h5uam9ryFhQUaNGiAU6dOKY8pFAqcOnUK3t7e+RVmvti8eTMaNGiAunXran1vYmIiwsLCsqzHgkQIgZEjR+LgwYM4ffo0PDw8VM43aNAA5ubmKv/PHz58iKdPn2b5/9zDwwOurq4q90ilUly5cqXAf05yqg/g3bv4+fnBwsIChw8fzrHlT52cftYKCk3q40MhISEAkOW7GfvnI8PmzZvRuXNnlCpVSuvnFJbPR1YUCgVSU1ML9u8PnQ11JoNLSEgQN2/eFDdv3hQAxIoVK8TNmzfFv//+KxISEsSECRNEUFCQCA8PF3/++aeoX7++qFKlikhJSVGW0bp1a/Hjjz8qv/f39xeWlpZi27Zt4t69e2LIkCHCwcFBREVFGeIVtZZdnWSIj48XNjY2Yt26dWrL+LBOxo8fL86ePSvCw8PFxYsXha+vryhZsqSIiYnR+/vk1bBhw4S9vb04e/asiIyMVH4lJycrrxk6dKgoV66cOH36tLh+/brw9vYW3t7eKuVUq1ZNHDhwQPn94sWLhYODg/j999/F7du3RZcuXYSHh4d4+/Ztvr1bbuRUH/Hx8aJJkyaidu3aIjQ0VOWa9PR0ZTnv14emP2sFUU71ERoaKubOnSuuX78uwsPDxe+//y4qVqwoWrZsqVJOUfl8ZHj8+LGQSCTi+PHjassxls+HEEJMmTJFnDt3ToSHh4vbt2+LKVOmCIlEIk6ePCmEKLi/P5jsGJEzZ84IAJm++vXrJ5KTk4Wfn58oVaqUMDc3F+XLlxeDBw/OlLSUL19ezJo1S+XYjz/+KMqVKycsLCxE48aNxeXLl/PxrfImuzrJsGHDBmFtbS3i4uLUlvFhnXTr1k24ubkJCwsLUaZMGdGtWzcRGhqq5zfRDXV1AUBs3bpVec3bt2/F8OHDhaOjo7CxsRGff/65iIyMzFTO+/coFAoxY8YM4eLiIiwtLYWPj494+PBhPr1V7uVUH1l9fgCI8PBwlXIy7tH0Z60gyqk+nj59Klq2bCmcnJyEpaWlqFy5spg4caKIj4/PVE5R+HxkmDp1qnB3dxdyuTzLcozh8yGEEAMHDhTly5cXFhYWolSpUsLHx0eZ6AhRcH9/SP7/wURERERGiWN2iIiIyKgx2SEiIiKjxmSHiIiIjBqTHSIiIjJqTHaIiIjIqDHZISIiIqPGZIeIiIiMGpMdIiIiMmpMdoiIiMioMdkhKqCCgoJgamqKjh07GjqUfHHu3Dm0bt0aTk5OsLGxQZUqVdCvXz+kpaUZOrQs7dmzB6amphgxYoTa81KpFNOnT0f16tVhZWUFV1dX+Pr64sCBAwgPD4dEIsn2a9u2bZnKjI2NxahRo1CtWjVYW1ujXLly+PbbbxEfH69y3dOnT9GxY0fY2NjA2dkZEydORHp6uvJ8ZGQkevbsiapVq8LExARjxozJ9KxNmzahRYsWcHR0hKOjI3x9fXH16tU81RmRITDZISqgNm/ejFGjRuH8+fOIiIjQ67OEECp/Eea3e/fuoV27dmjYsCHOnz+Pv//+Gz/++CMsLCwgl8v18kxdvPPmzZsxadIk7NmzBykpKSrn4uLi0LRpU+zYsQNTp05FcHAwzp8/j27dumHSpEmws7NDZGSk8mv8+PGoWbOmyrFu3bplemZERAQiIiKwbNky3LlzB9u2bUNAQAAGDRqkvEYul6Njx45IS0vDpUuXsH37dmzbtg0zZ85UXpOamopSpUrhu+++Q926ddW+39mzZ9GjRw+cOXMGQUFBcHd3h5+fH168eJGneiPKdzrdaYuIdCIhIUEUL15cPHjwQHTr1k0sWLBAea5Hjx6ia9euKtenpaWJEiVKiO3btwshhJDL5WLhwoWiQoUKwsrKStSpU0f8+uuvyuszNrg8duyYqF+/vjA3NxdnzpwRoaGhonPnzsLZ2VkUK1ZMNGzYUAQGBqo8KyIiQnTo0EFYWVmJChUqiF27dony5cuLlStXKq958+aNGDRokChZsqSwtbUVn3zyiQgJCcnyfVeuXCkqVKiQY71cuHBBtGrVSlhbWwsHBwfh5+cnYmNjhRBCpKSkiFGjRolSpUoJS0tL0axZM3H16tUc3zmnusrKP//8o9xAtkmTJmLXrl0q54cNGyaKFSsmXrx4kenehIQEIZPJVI7NmjVL1K1bN8fnqrNv3z5hYWGhLPPYsWPCxMREZXPJdevWCTs7O5Gamprp/latWonRo0fn+Jz09HRha2ur/JwRFRZs2SEqgPbt24fq1aujWrVq6N27N7Zs2QLx/3v29urVC0eOHEFiYqLy+hMnTiA5ORmff/45AGDRokXYsWMH1q9fj7t372Ls2LHo3bs3zp07p/KcKVOmYPHixbh//z7q1KmDxMREdOjQAadOncLNmzfRrl07dOrUCU+fPlXe07dvX0RERODs2bP47bffsHHjRsTExKiU+/XXXyMmJgbHjx/HjRs3UL9+ffj4+CA2Nlbt+7q6uiIyMhLnz5/Psk5CQkLg4+MDT09PBAUF4cKFC+jUqZOy5WfSpEn47bffsH37dgQHB6Ny5cpo27Ztpmd++M6a1tWHtm7dio4dO8Le3h69e/fG5s2blecUCgX8/f3Rq1cvlC5dOtO9xYsXh5mZWbblayM+Ph52dnbKMoOCglC7dm24uLgor2nbti2kUinu3r2b6+ckJydDJpPByckpzzET5StDZ1tElFnTpk3FqlWrhBBCyGQyUbJkSXHmzBmV73fs2KG8vkePHqJbt25CiHctHDY2NuLSpUsqZQ4aNEj06NFDCPFfK8ehQ4dyjKVmzZrixx9/FEIIcf/+fQFAXLt2TXn+8ePHAoCyZeevv/4SdnZ2IiUlRaWcSpUqiQ0bNqh9Rnp6uujfv78AIFxdXcVnn30mfvzxRxEfH6/yjs2aNVN7f2JiojA3N1dpXUlLSxOlS5cWS5cuzfKdNakrdeRyuXB3d1eW9fLlS2FhYSH++ecfIYQQ0dHRAoBYsWJFlmV8KLctOy9fvhTlypUT06ZNUx4bPHiw8PPzU7kuKSlJ2bL1IU1bdoYNGyYqVqwo3r59q3WcRIbElh2iAubhw4e4evUqevToAQAwMzNDt27dlC0HZmZm6Nq1K3bt2gUASEpKwu+//45evXoBAEJDQ5GcnIw2bdqgePHiyq8dO3YgLCxM5VkNGzZU+T4xMRETJkxAjRo14ODggOLFi+P+/fvKlp2HDx/CzMwM9evXV95TuXJlODo6Kr+/desWEhMTUaJECZXnh4eHZ3p+BlNTU2zduhXPnz/H0qVLUaZMGSxcuFA5hgX4r2VHnbCwMMhkMjRr1kx5zNzcHI0bN8b9+/ezfGdt6up9gYGBSEpKQocOHQAAJUuWRJs2bbBlyxYAULbC6ZtUKkXHjh3h6emJ2bNn6/VZixcvhr+/Pw4ePAgrKyu9PotI13TXjkpEOrF582akp6erdH8IIWBpaYk1a9bA3t4evXr1QqtWrRATE4PAwEBYW1ujXbt2AKDs3vrjjz9QpkwZlbItLS1Vvi9WrJjK9xMmTEBgYCCWLVuGypUrw9raGl999ZVWM6ISExPh5uaGs2fPZjrn4OCQ7b1lypRBnz590KdPH8ybNw9Vq1bF+vXrMWfOHFhbW2scQ3bef2dt6up9mzdvRmxsrEpMCoUCt2/fxpw5c1CqVCk4ODjgwYMHOolZnYSEBLRr1w62trY4ePAgzM3NledcXV0zzZqKjo5WntPWsmXLsHjxYvz555+oU6dO3gInMgC27BAVIOnp6dixYweWL1+OkJAQ5detW7dQunRp7NmzBwDQtGlTuLu7Y+/evdi1axe+/vpr5V92np6esLS0xNOnT1G5cmWVL3d392yff/HiRfTv3x+ff/45ateuDVdXVzx58kR5vlq1akhPT8fNmzeVx0JDQ/HmzRvl9/Xr10dUVBTMzMwyPb9kyZIa14WjoyPc3NyQlJQEAKhTpw5OnTql9tpKlSrBwsICFy9eVB6TyWS4du0aPD09s3xGburq9evX+P333+Hv76/y/+jmzZt48+YNTp48CRMTE3Tv3h27du1SO5MuMTExTzPBpFIp/Pz8YGFhgcOHD2dqafH29sbff/+tMpYqMDAQdnZ22daHOkuXLsW8efMQEBCQqSWQqNAwdD8aEf3n4MGDwsLCQsTFxWU6N2nSJNGwYUPl99OnTxeenp7CzMxM/PXXXyrXTp8+XZQoUUJs27ZNhIaGihs3bojVq1eLbdu2CSH+G7/y5s0blfs+//xz4eXlJW7evClCQkJEp06dhK2trcp4Dl9fX1G/fn1x5coVERwcLD755BNhbW2tHGOkUChE8+bNRd26dcWJEydEeHi4uHjxopg2bZrKWJ/3rV+/XgwdOlScOHFChIaGijt37ohJkyYJExMTcfbsWSGEEA8fPhQWFhZi2LBh4tatW+L+/fvip59+Ei9fvhRCCDF69GhRunRpcfz4cXH37l3Rr18/4ejoqJytldU751RXH1q5cqVwc3MTCoUi07muXbuKr776SgghxOvXr0X16tVF2bJlxfbt28Xdu3fFo0ePxObNm0XlypUzxaHpmJ34+HjRpEkTUbt2bREaGioiIyOVX+np6UKId2OgatWqJfz8/ERISIgICAgQpUqVElOnTlUp6+bNm+LmzZuiQYMGomfPnuLmzZvi7t27yvOLFy8WFhYWYv/+/SrPSUhIyDFOooKEyQ5RAfLpp5+KDh06qD135coVAUDcunVLCCHEvXv3BABRvnz5TH/xKhQKsWrVKlGtWjVhbm4uSpUqJdq2bSvOnTsnhMj6L/7w8HBl8uLu7i7WrFmTafBqRESEaN++vbC0tBTly5cXu3fvFs7OzmL9+vXKa6RSqRg1apQoXbq0MDc3F+7u7qJXr17i6dOnat8tODhY9O7dW3h4eAhLS0tRokQJ0bJlS3H48GGV686ePSuaNm0qLC0thYODg2jbtq3yHd6+fStGjRolSpYsme3U8w/fOae6+lDt2rXF8OHD1Z7bu3evsLCwUCZgcXFxYsqUKaJKlSrCwsJCuLi4CF9fX3Hw4MFM/880TXYy3kPdV3h4uPK6J0+eiPbt2wtra2tRsmRJMX78+EzT3dWVUb58eeX58uXLq71m1qxZOcZJVJBIhMinkXREZJSeP38Od3d3/Pnnn1kOICYiMiQmO0SkldOnTyMxMRG1a9dGZGQkJk2ahBcvXuDRo0cqg2SJiAoKzsYiIq3IZDJMmzYN//zzD2xtbdG0aVPs2rWLiQ4RFVhs2SEiIiKjxqnnREREZNSY7BAREZFRY7JDRERERo3JDhERERk1JjtERERk1JjsEBERkVFjskNERERGjckOERERGbX/A52IKUJMZzV6AAAAAElFTkSuQmCC",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from sklearn.linear_model import LinearRegression #sklearn is a machine learning library\n",
"X=df[[\"Average Score ACT 2012\"]]\n",
"Y=df[[\"College Eligibility 2012 - Percent\"]]\n",
"reg=LinearRegression()\n",
"reg.fit(X,Y)\n",
"print(\"Intercept is \", reg.intercept_)\n",
"print(\"Slope is \", reg.coef_)\n",
"print(\"R^2 for OLS is \", reg.score(X,Y))\n",
"# x values on the regression line will be between 13.5 and 30 \n",
"x = np.linspace(13.5, 30 ,100) \n",
"# define the regression line y = mx+b here\n",
"[[m]]=reg.coef_\n",
"[b]=reg.intercept_\n",
"y = m*x + b \n",
"#plot the data points \n",
"fig=df.plot(x=\"Average Score ACT 2012\", y=\"College Eligibility 2012 - Percent\", style='o') \n",
"plt.xlabel(\"Average Score ACT 2012\") \n",
"plt.ylabel(\"College Eligibility 2012 - Percent\") \n",
"# plot the regression line \n",
"plt.plot(x,y, 'k') #add the color for red\n",
"plt.legend([],[], frameon=True)\n",
"plt.grid()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{admonition} Linear Regression of Chicago Public School Data \n",
"Data File: Imported directly from the Chicago data portal in Step 1.\n",
":::"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1) Let's begin by executing the following cell to retrieve a Chicago Public School (CPS) dataset."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
school_id
\n",
"
legacy_unit_id
\n",
"
finance_id
\n",
"
short_name
\n",
"
long_name
\n",
"
primary_category
\n",
"
is_high_school
\n",
"
is_middle_school
\n",
"
is_elementary_school
\n",
"
is_pre_school
\n",
"
...
\n",
"
fifth_contact_title
\n",
"
fifth_contact_name
\n",
"
seventh_contact_title
\n",
"
seventh_contact_name
\n",
"
refugee_services
\n",
"
visual_impairments
\n",
"
freshman_start_end_time
\n",
"
sixth_contact_title
\n",
"
sixth_contact_name
\n",
"
hard_of_hearing
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
609966
\n",
"
3750
\n",
"
23531
\n",
"
HAMMOND
\n",
"
Charles G Hammond Elementary School
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
True
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
1
\n",
"
400069
\n",
"
4150
\n",
"
67081
\n",
"
POLARIS
\n",
"
Polaris Charter Academy
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
False
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
2
\n",
"
610191
\n",
"
6070
\n",
"
29291
\n",
"
STONE
\n",
"
Stone Elementary Scholastic Academy
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
False
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
3
\n",
"
400173
\n",
"
9648
\n",
"
66801
\n",
"
PATHWAYS - BRIGHTON PARK HS
\n",
"
Pathways in Education- Brighton Park
\n",
"
HS
\n",
"
True
\n",
"
False
\n",
"
False
\n",
"
False
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
4
\n",
"
610153
\n",
"
5670
\n",
"
25191
\n",
"
RYDER
\n",
"
William H Ryder Math & Science Specialty ES
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
True
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
" \n",
"
\n",
"
5 rows × 92 columns
\n",
"
"
],
"text/plain": [
" school_id legacy_unit_id finance_id short_name \n",
"0 609966 3750 23531 HAMMOND \\\n",
"1 400069 4150 67081 POLARIS \n",
"2 610191 6070 29291 STONE \n",
"3 400173 9648 66801 PATHWAYS - BRIGHTON PARK HS \n",
"4 610153 5670 25191 RYDER \n",
"\n",
" long_name primary_category \n",
"0 Charles G Hammond Elementary School ES \\\n",
"1 Polaris Charter Academy ES \n",
"2 Stone Elementary Scholastic Academy ES \n",
"3 Pathways in Education- Brighton Park HS \n",
"4 William H Ryder Math & Science Specialty ES ES \n",
"\n",
" is_high_school is_middle_school is_elementary_school is_pre_school ... \n",
"0 False True True True ... \\\n",
"1 False True True False ... \n",
"2 False True True False ... \n",
"3 True False False False ... \n",
"4 False True True True ... \n",
"\n",
" fifth_contact_title fifth_contact_name seventh_contact_title \n",
"0 NaN NaN NaN \\\n",
"1 NaN NaN NaN \n",
"2 NaN NaN NaN \n",
"3 NaN NaN NaN \n",
"4 NaN NaN NaN \n",
"\n",
" seventh_contact_name refugee_services visual_impairments \n",
"0 NaN NaN NaN \\\n",
"1 NaN NaN NaN \n",
"2 NaN NaN NaN \n",
"3 NaN NaN NaN \n",
"4 NaN NaN NaN \n",
"\n",
" freshman_start_end_time sixth_contact_title sixth_contact_name \n",
"0 NaN NaN NaN \\\n",
"1 NaN NaN NaN \n",
"2 NaN NaN NaN \n",
"3 NaN NaN NaN \n",
"4 NaN NaN NaN \n",
"\n",
" hard_of_hearing \n",
"0 NaN \n",
"1 NaN \n",
"2 NaN \n",
"3 NaN \n",
"4 NaN \n",
"\n",
"[5 rows x 92 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"raw_CPS_data= pd.read_json('https://data.cityofchicago.org/resource/kh4r-387c.json?$limit=100000')\n",
"raw_CPS_data.head() "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2) Let's get the column names"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Index(['school_id', 'legacy_unit_id', 'finance_id', 'short_name', 'long_name',\n",
" 'primary_category', 'is_high_school', 'is_middle_school',\n",
" 'is_elementary_school', 'is_pre_school', 'summary',\n",
" 'administrator_title', 'administrator', 'secondary_contact_title',\n",
" 'secondary_contact', 'address', 'city', 'state', 'zip', 'phone', 'fax',\n",
" 'cps_school_profile', 'website', 'facebook', 'attendance_boundaries',\n",
" 'grades_offered_all', 'grades_offered', 'student_count_total',\n",
" 'student_count_low_income', 'student_count_special_ed',\n",
" 'student_count_english_learners', 'student_count_black',\n",
" 'student_count_hispanic', 'student_count_white', 'student_count_asian',\n",
" 'student_count_native_american', 'student_count_other_ethnicity',\n",
" 'student_count_asian_pacific', 'student_count_multi',\n",
" 'student_count_hawaiian_pacific', 'student_count_ethnicity_not',\n",
" 'statistics_description', 'demographic_description', 'dress_code',\n",
" 'prek_school_day', 'kindergarten_school_day', 'school_hours',\n",
" 'after_school_hours', 'earliest_drop_off_time', 'classroom_languages',\n",
" 'bilingual_services', 'title_1_eligible', 'preschool_inclusive',\n",
" 'preschool_instructional', 'transportation_bus', 'transportation_el',\n",
" 'school_latitude', 'school_longitude', 'overall_rating',\n",
" 'rating_status', 'rating_statement', 'classification_description',\n",
" 'school_year', 'third_contact_title', 'third_contact_name', 'network',\n",
" 'is_gocps_participant', 'is_gocps_prek', 'is_gocps_elementary',\n",
" 'is_gocps_high_school', 'open_for_enrollment_date', 'twitter',\n",
" 'youtube', 'pinterest', 'college_enrollment_rate_school',\n",
" 'college_enrollment_rate_mean', 'graduation_rate_school',\n",
" 'graduation_rate_mean', 'significantly_modified',\n",
" 'transportation_metra', 'fourth_contact_title', 'fourth_contact_name',\n",
" 'fifth_contact_title', 'fifth_contact_name', 'seventh_contact_title',\n",
" 'seventh_contact_name', 'refugee_services', 'visual_impairments',\n",
" 'freshman_start_end_time', 'sixth_contact_title', 'sixth_contact_name',\n",
" 'hard_of_hearing'],\n",
" dtype='object')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_CPS_data.columns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3) Let's find the number of rows in each column which have data using a command of the form df.count()."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"school_id 654\n",
"legacy_unit_id 654\n",
"finance_id 654\n",
"short_name 654\n",
"long_name 654\n",
" ... \n",
"visual_impairments 6\n",
"freshman_start_end_time 101\n",
"sixth_contact_title 45\n",
"sixth_contact_name 45\n",
"hard_of_hearing 13\n",
"Length: 92, dtype: int64"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_CPS_data.count()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"4) Let's check what entries there are in the 'grades_offered' column."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"grades_offered\n",
"PK,K-8 327\n",
"9-12 144\n",
"K-8 82\n",
"7-12 11\n",
"PK,K-6 10\n",
"PK,K-5 10\n",
"6-12 9\n",
"K-6 8\n",
"6-8 6\n",
"PK,K-4 4\n",
"K-12 4\n",
"PE,PK,K-8 4\n",
"11-12 4\n",
"5-8 3\n",
"PK 3\n",
"K-5 3\n",
"PK,K-3 3\n",
"8-12 2\n",
"PK,K-2 2\n",
"7-8 2\n",
"PK,3-8 1\n",
"9 1\n",
"K,4-8 1\n",
"K-1,5-8 1\n",
"3-12 1\n",
"K-3,5-8 1\n",
"1-8 1\n",
"PK,K-7 1\n",
"10-12 1\n",
"4-11 1\n",
"K-3 1\n",
"K-2 1\n",
"4-8 1\n",
"Name: count, dtype: int64"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_CPS_data['grades_offered'].value_counts()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5) Let's create a dataframe called mid with just the data for PK,K-8 "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
school_id
\n",
"
legacy_unit_id
\n",
"
finance_id
\n",
"
short_name
\n",
"
long_name
\n",
"
primary_category
\n",
"
is_high_school
\n",
"
is_middle_school
\n",
"
is_elementary_school
\n",
"
is_pre_school
\n",
"
...
\n",
"
fifth_contact_title
\n",
"
fifth_contact_name
\n",
"
seventh_contact_title
\n",
"
seventh_contact_name
\n",
"
refugee_services
\n",
"
visual_impairments
\n",
"
freshman_start_end_time
\n",
"
sixth_contact_title
\n",
"
sixth_contact_name
\n",
"
hard_of_hearing
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
609966
\n",
"
3750
\n",
"
23531
\n",
"
HAMMOND
\n",
"
Charles G Hammond Elementary School
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
True
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
4
\n",
"
610153
\n",
"
5670
\n",
"
25191
\n",
"
RYDER
\n",
"
William H Ryder Math & Science Specialty ES
\n",
"
ES
\n",
"
False
\n",
"
True
\n",
"
True
\n",
"
True
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
" \n",
"
\n",
"
2 rows × 92 columns
\n",
"
"
],
"text/plain": [
" school_id legacy_unit_id finance_id short_name \n",
"0 609966 3750 23531 HAMMOND \\\n",
"4 610153 5670 25191 RYDER \n",
"\n",
" long_name primary_category \n",
"0 Charles G Hammond Elementary School ES \\\n",
"4 William H Ryder Math & Science Specialty ES ES \n",
"\n",
" is_high_school is_middle_school is_elementary_school is_pre_school ... \n",
"0 False True True True ... \\\n",
"4 False True True True ... \n",
"\n",
" fifth_contact_title fifth_contact_name seventh_contact_title \n",
"0 NaN NaN NaN \\\n",
"4 NaN NaN NaN \n",
"\n",
" seventh_contact_name refugee_services visual_impairments \n",
"0 NaN NaN NaN \\\n",
"4 NaN NaN NaN \n",
"\n",
" freshman_start_end_time sixth_contact_title sixth_contact_name \n",
"0 NaN NaN NaN \\\n",
"4 NaN NaN NaN \n",
"\n",
" hard_of_hearing \n",
"0 NaN \n",
"4 NaN \n",
"\n",
"[2 rows x 92 columns]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mid=raw_CPS_data[raw_CPS_data['grades_offered']=='PK,K-8']\n",
"mid.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"6) Let's streamline the data to a dataframe df which includes just the columns ['address','student_count_total','student_count_black','student_count_hispanic','student_count_white','zip']"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"