{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "**Simple Linear Regression**"
      ],
      "metadata": {
        "id": "2G9GnrLl9U4t"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 1: Import Libraries"
      ],
      "metadata": {
        "id": "5TLnohB39dDV"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import numpy as np\n",
        "import matplotlib.pyplot as plt"
      ],
      "metadata": {
        "id": "omZtZ3DG9aCn"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 2: Implement Simple Linear Regression Class"
      ],
      "metadata": {
        "id": "Oh-fvnuE9sKl"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class SimpleLinearRegression:\n",
        "    def __init__(self):\n",
        "        self.coefficient_ = None\n",
        "        self.intercept_ = None\n",
        "        self.r2score_ = None\n",
        "\n",
        "    def fit(self, X, y):\n",
        "        n = len(X)\n",
        "        X_b = np.c_[np.ones((n,1)), X]\n",
        "\n",
        "        self.coefficients_ = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)\n",
        "        self.intercept_ = self.coefficients_[0]\n",
        "        y_pred = X_b.dot(self.coefficients_)\n",
        "        # R²\n",
        "        self.r2score_ = 1 - (np.sum((y - y_pred)**2) / np.sum((y - np.mean(y))**2))\n",
        "        self.y_pred_ = y_pred\n",
        "\n",
        "    def predict(self, X):\n",
        "        X_b = np.c_[np.ones((len(X),1)), X]\n",
        "        return X_b.dot(self.coefficients_)"
      ],
      "metadata": {
        "id": "Sg7RFSKy9jtI"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 3: Fit the Model and Visualize Results"
      ],
      "metadata": {
        "id": "OaI5BxeP9v6z"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "X_simple = np.array([1,2,3,4,5,6,7,8,9,10]).reshape(-1,1)\n",
        "y_simple = np.array([2,4,5,4,5,7,8,9,10,12])\n",
        "\n",
        "slr = SimpleLinearRegression()\n",
        "slr.fit(X_simple, y_simple)\n",
        "\n",
        "\n",
        "print(f\"Simple LR Coefficients: {slr.coefficients_}\")\n",
        "print(f\"R² Score: {slr.r2score_:.2f}\")\n",
        "\n",
        "plt.scatter(X_simple, y_simple, color='blue', label='Data')\n",
        "plt.plot(X_simple, slr.y_pred_, color='red', label='Regression Line')\n",
        "plt.title(\"Simple Linear Regression\")\n",
        "plt.xlabel(\"X\")\n",
        "plt.ylabel(\"y\")\n",
        "plt.legend()\n",
        "plt.show()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 508
        },
        "id": "VxCjC4bn9y06",
        "outputId": "b6e57a39-f449-4d2b-a47b-bfa0d1c5cb25"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Simple LR Coefficients: [1.06666667 1.00606061]\n",
            "R² Score: 0.94\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAHHCAYAAACle7JuAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVRZJREFUeJzt3Xt8zvX/x/HH5WIzO5EcNsYWcpozCY2Ukr5f33wlv0qZQ4WclZCvVEilIgpRDpUOYg7lkPNZjJlQTkWt5VBicxyufX5/vL/b1zIM2z7Xtet5v92uW96f63Nd1+vatVxPr8/7/fk4LMuyEBEREfFA+ewuQERERORGKciIiIiIx1KQEREREY+lICMiIiIeS0FGREREPJaCjIiIiHgsBRkRERHxWAoyIiIi4rEUZERERMRjKciIZKPw8HA6dOhgy2u//PLLOByOXH3NgwcP4nA4mDZtWq6+rmSvDh06EB4ebncZIjdEQUYkC3bs2EGbNm0oW7YsBQsWpFSpUtx3332MGzfO7tJyzLRp03A4HGzZssXuUnJMWvhLuxUoUIDw8HB69erFiRMn7C5PRLIgv90FiLi7DRs20LRpU8qUKcPTTz9NyZIlSUhI4LvvvuPdd9+lZ8+e6fvu2bOHfPm8598HZcuW5ezZsxQoUMDuUm7KhAkTCAgI4PTp0yxfvpxx48YRFxfHunXr7C4tV0yePJnU1FS7yxC5IQoyItcwYsQIgoODiY2NpXDhwhnuO3r0aIaxr69vLlZmP4fDQcGCBe0u46rOnDlDoUKFrrpPmzZtuPXWWwHo0qULjz76KF9++SWbN2/mjjvuyI0yAUhNTeX8+fO5/jP19CAq3s17/ukocoN++uknqlatelmIAShevHiG8d/nyKQdnlm3bh29evWiWLFiFC5cmC5dunD+/HlOnDhB+/btKVKkCEWKFOGFF17g0gvSp81Beeuttxg9ejRly5bFz8+PJk2asHPnzizV/+mnn1KnTh38/Py45ZZbePTRR0lISLihn8XfZTZHpkOHDgQEBJCYmEirVq0ICAigWLFiPP/887hcrgyPT01NZcyYMVStWpWCBQtSokQJunTpwvHjxzPsN2/ePP7xj38QGhqKr68v5cqVY9iwYZc93913301kZCRbt26lcePGFCpUiBdffPG631dUVBRgPvtLbdq0iQceeIDg4GAKFSpEkyZNWL9+/WWPX7VqFXXr1qVgwYKUK1eODz74INM5TA6Hgx49ejBjxgyqVq2Kr68vixcvBiAxMZFOnTpRokQJfH19qVq1KlOmTLnstcaNG0fVqlUpVKgQRYoUoW7dunz22Wfp9588eZI+ffoQHh6Or68vxYsX57777iMuLi59n8zmyJw+fZrnnnuOsLAwfH19qVixIm+99VaG389L38PcuXOJjIxMrzXtfYjkNHVkRK6hbNmybNy4kZ07dxIZGXlDz9GzZ09KlizJK6+8wnfffcekSZMoXLgwGzZsoEyZMrz22mssXLiQUaNGERkZSfv27TM8/uOPP+bkyZN0796dc+fO8e6773LPPfewY8cOSpQoccXXHTFiBEOGDKFt27Y89dRT/PHHH4wbN47GjRuzbdu2TMNZdnC5XDRv3pz69evz1ltvsWzZMt5++23KlStHt27d0vfr0qUL06ZNo2PHjvTq1YsDBw7w3nvvsW3bNtavX5/eKZg2bRoBAQH069ePgIAAVqxYwUsvvURycjKjRo3K8NrHjh2jRYsWPProozzxxBNX/flcycGDBwEoUqRI+rYVK1bQokUL6tSpw9ChQ8mXLx9Tp07lnnvuYe3atemdm23btvHAAw8QEhLCK6+8gsvl4tVXX6VYsWKZvtaKFSuYOXMmPXr04NZbbyU8PJwjR45w5513poeEYsWKsWjRIjp37kxycjJ9+vQBzCGhXr160aZNG3r37s25c+f4/vvv2bRpE48//jgAXbt2ZdasWfTo0YMqVapw7Ngx1q1bx48//kjt2rUzrcmyLP71r3+xcuVKOnfuTM2aNfn222/p378/iYmJjB49OsP+69atIyYmhmeffZbAwEDGjh3Lww8/zK+//krRokWv++cvcl0sEbmqJUuWWE6n03I6nVaDBg2sF154wfr222+t8+fPX7Zv2bJlrejo6PTx1KlTLcBq3ry5lZqamr69QYMGlsPhsLp27Zq+7eLFi1bp0qWtJk2apG87cOCABVh+fn7Wb7/9lr5906ZNFmD17ds3fdvQoUOtS/+XPnjwoOV0Oq0RI0ZkqHHHjh1W/vz5L9v+d2m1x8bGXnGftPqmTp2avi06OtoCrFdffTXDvrVq1bLq1KmTPl67dq0FWDNmzMiw3+LFiy/bfubMmcteu0uXLlahQoWsc+fOpW9r0qSJBVgTJ0686ntLk/Yz27Nnj/XHH39YBw8etKZMmWL5+flZxYoVs06fPm1ZlmWlpqZaFSpUuOxzPHPmjBUREWHdd9996dtatmxpFSpUyEpMTEzftm/fPit//vzW3//KBax8+fJZu3btyrC9c+fOVkhIiPXnn39m2P7oo49awcHB6T+Phx56yKpatepV32NwcLDVvXv3q+4THR1tlS1bNn08d+5cC7CGDx+eYb82bdpYDofD2r9/f4b34OPjk2Hb9u3bLcAaN27cVV9XJDvo0JLINdx3331s3LiRf/3rX2zfvp0333yT5s2bU6pUKebPn5+l5+jcuXOGwwr169fHsiw6d+6cvs3pdFK3bl1+/vnnyx7fqlUrSpUqlT6+4447qF+/PgsXLrzia8bExJCamkrbtm35888/028lS5akQoUKrFy5Mku136iuXbtmGEdFRWV4b1999RXBwcHcd999GeqrU6cOAQEBGerz8/NL//PJkyf5888/iYqK4syZM+zevTvD6/j6+tKxY8frqrVixYoUK1aM8PBwOnXqRPny5Vm0aFH63Jr4+Hj27dvH448/zrFjx9JrPX36NPfeey9r1qwhNTUVl8vFsmXLaNWqFaGhoenPX758eVq0aJHpazdp0oQqVaqkjy3LYvbs2bRs2RLLsjL8bJo3b05SUlL6YaHChQvz22+/ERsbe8X3VrhwYTZt2sTvv/+e5Z/HwoULcTqd9OrVK8P25557DsuyWLRoUYbtzZo1o1y5cunj6tWrExQUlOnvskh206ElkSyoV68eMTExnD9/nu3btzNnzhxGjx5NmzZtiI+Pz/BFlJkyZcpkGAcHBwMQFhZ22fa/zw8BqFChwmXbbr/9dmbOnHnF19y3bx+WZWX6WMjZCZ4FCxa87FBKkSJFMry3ffv2kZSUdNk8ozSXTqTetWsX//nPf1ixYgXJyckZ9ktKSsowLlWqFD4+PtdV7+zZswkKCuKPP/5g7NixHDhwIEN42rdvHwDR0dFXfI6kpCTOnTvH2bNnKV++/GX3Z7YNICIiIsP4jz/+4MSJE0yaNIlJkyZl+pi0n82AAQNYtmwZd9xxB+XLl+f+++/n8ccfp1GjRun7vvnmm0RHRxMWFkadOnV48MEHad++PbfddtsV38svv/xCaGgogYGBGbZXrlw5/f5L/f33Gy7/vEVyioKMyHXw8fGhXr161KtXj9tvv52OHTvy1VdfMXTo0Ks+zul0Znm79bfJlDcqNTUVh8PBokWLMn2dgICAbHmdzFzp/V4qNTWV4sWLM2PGjEzvTwtCJ06coEmTJgQFBfHqq69Srlw5ChYsSFxcHAMGDLhs2fClASSrGjdunL5qqWXLllSrVo127dqxdetW8uXLl/4ao0aNombNmpk+R0BAAOfOnbvu1/57vWmv9cQTT1wxOFWvXh0wwWLPnj188803LF68mNmzZzN+/HheeuklXnnlFQDatm1LVFQUc+bMYcmSJYwaNYo33niDmJiYK3aJrteVPu/s+l0WuRoFGZEbVLduXQAOHTqU46+V1hG41N69e696NtZy5cphWRYRERHcfvvtOVjdjSlXrhzLli2jUaNGVw0fq1at4tixY8TExNC4ceP07QcOHMiRugICAhg6dCgdO3Zk5syZPProo+mHTYKCgmjWrNkVH1u8eHEKFizI/v37L7svs22ZKVasGIGBgbhcrqu+Vhp/f3/+7//+j//7v//j/PnztG7dmhEjRjBo0KD0ZdwhISE8++yzPPvssxw9epTatWszYsSIKwaZsmXLsmzZMk6ePJmhK5N2GK9s2bJZei8iuUFzZESuYeXKlZn+yzJtfkrFihVzvIa5c+eSmJiYPt68eTObNm266r+oW7dujdPp5JVXXrmsfsuyOHbsWI7VmxVt27bF5XIxbNiwy+67ePFi+pl10/61f+l7OH/+POPHj8+x2tq1a0fp0qV54403AKhTpw7lypXjrbfe4tSpU5ft/8cff6TX2qxZM+bOnZthTsr+/fsvm1dyJU6nk4cffpjZs2dnusQ+7bWAyz5DHx8fqlSpgmVZXLhwAZfLddmht+LFixMaGkpKSsoVa3jwwQdxuVy89957GbaPHj0ah8ORbZ0ckeygjozINfTs2ZMzZ87w73//m0qVKnH+/Hk2bNjAl19+SXh4+HVPLL0R5cuX56677qJbt26kpKQwZswYihYtygsvvHDFx5QrV47hw4czaNAgDh48SKtWrQgMDOTAgQPMmTOHZ555hueff/6arz1lypRMzwnSu3fvm3pPTZo0oUuXLowcOZL4+Hjuv/9+ChQowL59+/jqq6949913adOmDQ0bNqRIkSJER0fTq1cvHA4Hn3zySY4etihQoAC9e/emf//+LF68mAceeIAPP/yQFi1aULVqVTp27EipUqVI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KVmyZI489/UoVqyY3SWIiEgWqSPjoXx9fSlZsiRhYWG0atWKZs2asXTp0vT7U1NTGTlyJBEREfj5+VGjRg1mzZqV4Tnmz59PhQoVKFiwIE2bNmX69Ok4HA5OnDgBwLRp0yhcuDDz58+nSpUq+Pr68uuvv5KSksLzzz9PqVKl8Pf3p379+qxatSr9eX/55RdatmxJkSJF8Pf3p2rVqixcuBCA48eP065dO4oVK4afnx8VKlRg6tSpQOaHllavXs0dd9yBr68vISEhDBw4kIsXL6bff/fdd9OrVy9eeOEFbrnlFkqWLMnLL798Uz/bvx9acjgcfPjhh/z73/+mUKFCVKhQgfnz52d4zM6dO2nRogUBAQGUKFGCJ598kj///POm6hARkWtTkLmUZcHp0/bcbuIi5Dt37mTDhg34+Pikbxs5ciQff/wxEydOZNeuXfTt25cnnniC1atXA3DgwAHatGlDq1at2L59O126dGHw4MGXPfeZM2d44403+PDDD9m1axfFixenR48ebNy4kS+++ILvv/+eRx55hAceeIB9+/YB0L17d1JSUlizZg07duzgjTfeICAgAIAhQ4bwww8/sGjRIn788UcmTJjArbfemun7SkxM5MEHH6RevXps376dCRMm8NFHHzF8+PAM+02fPh1/f382bdrEm2++yauvvpoh1GWHV155hbZt2/L999/z4IMP0q5dO/766y8ATpw4wT333EOtWrXYsmULixcv5siRI7Rt2zZbaxARkUxYeVxSUpIFWElJSZfdd/bsWeuHH36wzp49azacOmVZJlLk/u3UqSy/p+joaMvpdFr+/v6Wr6+vBVj58uWzZs2aZVmWZZ07d84qVKiQtWHDhgyP69y5s/XYY49ZlmVZAwYMsCIjIzPcP3jwYAuwjh8/blmWZU2dOtUCrPj4+PR9fvnlF8vpdFqJiYkZHnvvvfdagwYNsizLsqpVq2a9/PLLmdbesmVLq2PHjpned+DAAQuwtm3bZlmWZb344otWxYoVrdTU1PR93n//fSsgIMByuVyWZVlWkyZNrLvuuivD89SrV88aMGBApq9hWZY1dOhQq0aNGle8v2zZstbo0aPTx4D1n//8J3186tQpC7AWLVpkWZZlDRs2zLr//vszPEdCQoIFWHv27Mn0NS773RMRkQyu9v19Kc2R8VBNmzZlwoQJnD59mtGjR5M/f34efvhhAPbv38+ZM2e47777Mjzm/Pnz1KpVC4A9e/ZQr169DPffcccdl72Oj48P1atXTx/v2LEDl8vF7bffnmG/lJQUihYtCkCvXr3o1q0bS5YsoVmzZjz88MPpz9GtWzcefvhh4uLiuP/++2nVqhUNGzbM9D3++OOPNGjQAIfDkb6tUaNGnDp1it9++40yZcoAZKgPICQkhKNHj17hJ3djLn0Nf39/goKC0l9j+/btrFy5Mr3rdKmffvrpsp+ViIhkHwWZSxUqBKdO2ffa18Hf35/y5csDMGXKFGrUqMFHH31E586dOfXf97BgwQJKlSqV4XG+vr7X9Tp+fn4ZgsSpU6dwOp1s3boVp9OZYd+0L/KnnnqK5s2bs2DBApYsWcLIkSN5++236dmzJy1atOCXX35h4cKFLF26lHvvvZfu3bvz1ltvXVddlypQoECGscPhIDU19Yaf73pf49SpU7Rs2TLTidYhISHZWoeIiGSkIHMphwP8/e2u4rrly5ePF198kX79+vH4449nmJjbpEmTTB9TsWLF9Am4aWJjY6/5WrVq1cLlcnH06FGioqKuuF9YWBhdu3ala9euDBo0iMmTJ9OzZ0/ArAqKjo4mOjqaqKgo+vfvn2mQqVy5MrNnz8ayrPQwtX79egIDAylduvQ1a80ttWvXZvbs2YSHh5M/v/6XEhHJTZrsm0c88sgjOJ1O3n//fQIDA3n++efp27cv06dP56effiIuLo5x48Yxffp0ALp06cLu3bsZMGAAe/fuZebMmUybNg0gQwfm726//XbatWtH+/btiYmJ4cCBA2zevJmRI0eyYMECAPr06cO3337LgQMHiIuLY+XKlVSuXBmAl156iXnz5rF//3527drFN998k37f3z377LMkJCTQs2dPdu/ezbx58xg6dCj9+vW76SXgZ8+eJT4+PsPtp59+uqHn6t69O3/99RePPfYYsbGx/PTTT3z77bd07NgRl8t1U3WKiMjVKcjkEfnz56dHjx68+eabnD59mmHDhjFkyBBGjhxJ5cqVeeCBB1iwYAEREREAREREMGvWLGJiYqhevToTJkxIX7V0rcNPU6dOpX379jz33HNUrFiRVq1aERsbmz5nxeVy0b179/TXvf322xk/fjxg5twMGjSI6tWr07hxY5xOJ1988UWmr1OqVCkWLlzI5s2bqVGjBl27dqVz58785z//uemf1969e6lVq1aGW5cuXW7ouUJDQ1m/fj0ul4v777+fatWq0adPHwoXLpxj59wREXEbp0/b+vIOy7qJdb8eIDk5meDgYJKSkggKCspw37lz5zhw4AAREREULFjQpgrdx4gRI5g4cSIJCQl2l5Ln6XdPRDxeaiqMHQvDhsHGjZDNCxuu9v19Kf1z0YuNHz+e2NhYfv75Zz755BNGjRpFdHS03WWJiIi7++knuPtu6NsX/voLJk2yrRTNTPRi+/btY/jw4fz111+UKVOG5557jkGDBtldloiIuKvUVJg4EV54wRxS8veHt96CGzw0nx0UZLzY6NGjGT16tN1liIiIJ/jlF+jcGZYvN+MmTWDKFLjtNlvL0qElERERuTLLgg8/hGrVTIjx84N334UVK2wPMaCODAB5fL6zuCH9zomIR0hMhKefhkWLzLhhQ5g6Ndsn9t4Mr+7IpJ2t9cyZMzZXIt4m7Xfu72cMFhFxC5YFn3wCkZEmxPj6wqhRsGaNW4UY8PKOjNPppHDhwunXzClUqNBVTwYncrMsy+LMmTMcPXqUwoULX3aZBxER2x0+DF27wrx5ZlyvHkybBlWq2FrWlXh1kAEoWbIkQLZfZFDkagoXLpz+uyci4ja+/BK6d4djx6BAAXj5ZbNCyY0vv+K+leUSh8NBSEgIxYsX58KFC3aXI16gQIEC6sSIiHv54w8TYL76yoxr1oTp06F6dVvLygqvDzJpnE6nvlxERMT7zJljDiUdPWo6L4MHw4svgo+P3ZVliYKMiIiIN/rrL+jVC2bMMOOqVeHjj6F2bXvruk5evWpJRETEKy1YYFYkzZgB+fLBwIGwdavHhRhQR0ZERMR7JCWZ6yNNnWrGFSuaFUl33mlrWTdDHRkRERFvsGSJ6cJMnQoOB/TrB9u2eXSIAXVkRERE8raTJ6F/f/jgAzMuV86Emagoe+vKJurIiIiI5FWrVpkl1GkhpkcP2L49z4QYUJARERHJe06fNiuSmjaFgwehbFlzwcdx48Df3+7qspUOLYmIiOQl69dDhw6wf78ZP/MMvPUWBAbaWlZOUUdGREQkLzh3zsyFiYoyIaZUKVi82BxWyqMhBtSRERER8XybN0N0NOzebcYdOsDo0VC4sJ1V5Qp1ZERERDxVSoq5pECDBibElCwJ8+ebVUleEGJAHRkRERHPtG2b6cLs2GHGjz8OY8dC0aL21pXL1JERERHxJBcuwCuvwB13mBBTrBjMmmUuN+BlIQbUkREREfEcO3aYLsy2bWb88MMwfjwUL25vXTZSR0ZERMTdXbwII0dCnTomxBQpAp99Bl995dUhBtSRERERcW+7d5suzObNZtyypVlSHRJib11uQh0ZERERd+RywdtvQ82aJsQEB5srVc+bpxBzCXVkRERE3M3+/eZcMOvXm3Hz5vDhh1C6tK1luSN1ZERERNxFaqq5HlL16ibEBATApEmwaJFCzBWoIyMiIuIODh6ETp1g5UozbtoUpkyB8HA7q3J76siIiIjYybJM16VaNRNiChWC996DZcsUYrJAHRkRERG7JCTAU0/BkiVmfNdd5vIC5cvbW5cHUUdGREQkt1mWWYEUGWlCTMGC8M47sGqVQsx1UkdGREQkF7l+O8Txts9w68ZvALDuqI9j+jSoVMnewjyUrR2ZNWvW0LJlS0JDQ3E4HMydOzfD/ZZl8dJLLxESEoKfnx/NmjVj37599hQrIiJyMyyLzX0/42SZqty68RtS8GEgI4lIXEfMDwoxN8rWIHP69Glq1KjB+++/n+n9b775JmPHjmXixIls2rQJf39/mjdvzrlz53K5UhERkZtw9CiJDdpwx5h2FLaOs5Xa1GErbzCQX3/PT5s2EBNjd5GeyWFZlmV3EQAOh4M5c+bQqlUrwHRjQkNDee6553j++ecBSEpKokSJEkybNo1HH300S8+bnJxMcHAwSUlJBAUF5VT5IiIimZs1C6tbNxx//skF8jOMIYxkEBcpkL6Lw2FOE3PgADidNtbqRrL6/e22k30PHDjA4cOHadasWfq24OBg6tevz8aNG6/4uJSUFJKTkzPcREREct2xY/DYY/DIIzj+/JPvqcYdbGYYL2UIMWDm/iYkwNq1NtXqwdw2yBw+fBiAEiVKZNheokSJ9PsyM3LkSIKDg9NvYWFhOVqniIjIZebPh6pV4YsvwOlkZ6vB1GUL8dS66sMOHcql+vIQtw0yN2rQoEEkJSWl3xISEuwuSUREvMWJE+ZK1Q89BEeOQOXKsHEjf/YezgV8rvlwXQvy+rltkClZsiQAR44cybD9yJEj6fdlxtfXl6CgoAw3ERGRHLd4sTkvzMcfm0kv/ftDXBzUq0dUlJkD43Bk/lCHA8LCICoqd0vOC9w2yERERFCyZEmWL1+evi05OZlNmzbRoEEDGysTERG5RHIyPP00tGgBiYlQoQKsWwdvvmlOdIeZwPvuu2b3v4eZtPGYMZroeyNsDTKnTp0iPj6e+Ph4wEzwjY+P59dff8XhcNCnTx+GDx/O/Pnz2bFjB+3btyc0NDR9ZZOIiIitli8310j68EMz7t0b4uOhYcPLdm3dGmbNglKlMm4vXdpsb90658vNi2xdfr1q1SqaNm162fbo6GimTZuGZVkMHTqUSZMmceLECe666y7Gjx/P7bffnuXX0PJrERHJdqdOwYABMH68GUdEmGskNWlyzYe6XGZ10qFDZk5MVJQ6MZnJ6ve325xHJqcoyIiISLZauxY6dICffzbjbt3MYaSAAFvLyms8/jwyIiIibuXsWejb13Rdfv7ZzM5dutR0ZRRibKOLRoqIiFzLd9+ZZdV795px587w9tsQHGxvXaKOjIiIyBWdOwcDB0KjRibEhIbCggVmcq9CjFtQR0ZERCQzW7dC+/bwww9m/OSTZg11kSL21iUZqCMjIiJyqfPn4aWXoH59E2KKF4e5c82J7hRi3I46MiIiImm2bzdzYbZvN+O2beH99+HWW+2tS65IHRkREZELF2D4cKhXz4SYokXhyy/NTSHGrakjIyIi3m3XLtOF2brVjFu1gokToUQJW8uSrFFHRkREvJPLZU5kV7u2CTGFC8Onn0JMjEKMB1FHRkREvM/evebsvBs3mvGDD8LkyWZ5tXgUdWRERMR7pKaay0zXqGFCTFAQTJkC33yjEOOh1JERERHv8PPP0LEjrFljxvfdZ05sV6aMvXXJTVFHRkRE8rbUVHM9pOrVTYjx9zeTeb/9ViEmD1BHRkRE8q5ffjHXRVq+3IybNIGpUyEiwt66JNuoIyMiInmPZZnDRtWqmRDj52cuL7BihUJMHqOOjIiI5C2JifD007BokRk3bAjTpkGFCraWJTlDHRkREckbLAs++QQiI02I8fWFUaPMvBiFmDxLHRkREfF8hw9D164wb54Z16tnujBVqthaluQ8dWRERMSzffml6cLMmwcFCsCIEbBhg0KMl1BHRkREPNMff0D37vDVV2ZcsyZMn26WWYvXUEdGREQ8z5w5pgvz1VeQPz8MHQqbNyvEeCF1ZERExHP89Rf06gUzZphxZKTpwtSubW9dYht1ZERExCO45i8g5fZImDEDK18+UgcMgi1bFGK8nIKMiIi4t6QkDt7bCedD/8T32CF2U5E7UzdQdsZrxCzwtbs6sZmCjIiIuK8lSzhTLpLwFVNJxcFbPEcttrGZ+iQmQps2EBNjd5FiJwUZERFxPydPmvPCNG9OoWO/sZ9yNGYN/XmLc/gB5vx3AH36gMtlX6liLwUZERFxL6tWmdVHH3wAwDh6UIPtrOeuy3a1LEhIgLVrc7lGcRsKMiIi4h7OnDErkpo2hYMHoWxZlg9eQS/GcQb/qz700KHcKVHcj4KMiIjYb/16qFEDxo0z42eegR07cDZrmqWHh4TkYG3i1hRkRETEPufOQf/+EBUF+/dDqVKweLE5rBQYSFQUlC4NDkfmD3c4ICzMPFy8k4KMiIjYY/NmqFUL3nrLTHbp0AF27oTmzdN3cTrh3XfNn/8eZtLGY8aY/cQ7KciIiEjuSkmBwYOhQQPYvRtKloSvv4apU6Fw4ct2b90aZs0yzZpLlS5ttrdunTtli3vSJQpERCT3bNsG0dGwY4cZP/44jB0LRYte9WGtW8NDD5nVSYcOmTkxUVHqxIiCjIiI5IYLF+C112D4cLh4EYoVgwkT4OGHs/wUTifcfXfOlSieSUFGRERy1s6dpgsTF2fGDz9sQkyxYvbWJXmC5siIiEjOuHgRRo6EOnVMiLnlFvj8c/jqK4UYyTbqyIiISPbbvdt0YTZvNuOWLWHSJDOxVyQbqSMjIiLZx+WCt9+GmjVNiAkOhunTYd48hRjJEerIiIhI9ti/35wLZv16M27eHD780KyTFskh6siIiMjNSU2F994zlxhYvx4CAsxhpEWLFGIkx6kjIyIiN+7gQejUCVauNON77oEpU6BsWVvLEu+hjoyIiFw/yzJdl2rVTIgpVMh0ZZYuVYiRXKWOjIiIXJ+EBHjqKViyxIyjoszlBcqVs7cu8UrqyIiISNZYFkybBpGRJsQULAjvvAOrVinEiG3UkRERkWs7dAieeQa++caM69c3y6orVrS3LvF66siIiMiVWRZ89hlUrWpCjI8PvP46rFunECNuQR0ZERHJ3NGj0K0bxMSYce3apgsTGWlvXSKXUEdGREQuN2uW6cLExED+/PDqq/Dddwox4nbUkRERkf85dgx69IAvvjDj6tVNF6ZmTVvLErkSdWRERMSYP990Yb74ApxOGDwYYmMVYsStqSMjIuLtTpyA3r3h44/NuHJl04WpV8/WskSyQh0ZERFvtnixmffy8cfgcED//hAXpxAjHkMdGRERb5ScDM8/D5Mnm3GFCuZkdw0b2lqWyPVSR0ZExNusWGGukZQWYnr3hvh4hRjxSOrIiIh4i1OnYOBAeP99M46IMNdIatLE3rpEboI6MiIieZzLBdvGruVkuRr/CzHdusH33yvEiMdz6yDjcrkYMmQIERER+Pn5Ua5cOYYNG4ZlWXaXJiLiEeZ+fpYphftRo3cTAo/+zK+E8ditS4lpNh4CAuwuT+SmufWhpTfeeIMJEyYwffp0qlatypYtW+jYsSPBwcH06tXL7vJERNzayte/o/KgaFqxF4CP6EQ/3uHksWC+bGNO3tu6tc1Fitwktw4yGzZs4KGHHuIf//gHAOHh4Xz++eds3rzZ5spERNxYSgqpQ4bSeNQonKSSSChPM5lFPGjut8xK6z594KGHzLnvRDyVWx9aatiwIcuXL2fvXvOvie3bt7Nu3TpatGhxxcekpKSQnJyc4SYi4jW2boU6dcg36g2cpPIxTxLJzv+FmP+yLEhIgLVrbapTJJu4dUdm4MCBJCcnU6lSJZxOJy6XixEjRtCuXbsrPmbkyJG88soruViliIgbOH8ehg+H114Dl4tzQcX5v+RJzOehqz7s0KFcqk8kh7h1R2bmzJnMmDGDzz77jLi4OKZPn85bb73F9OnTr/iYQYMGkZSUlH5LSEjIxYpFRGywfTvUrw/DhpklSm3bsvXjXdcMMQAhIblQn0gOclhuvAQoLCyMgQMH0r179/Rtw4cP59NPP2X37t1Zeo7k5GSCg4NJSkoiKCgop0oVEcl9Fy/C66/Dq6/ChQtQtCiMHw9t2+JyQXg4JCaaw0h/53BA6dJw4IDmyIh7yur3t1t3ZM6cOUO+fBlLdDqdpKam2lSRiIib+OEHaNAAhgwxIaZVK9i1C9q2BUw4efdds6vDkfGhaeMxYxRixPO5dZBp2bIlI0aMYMGCBRw8eJA5c+bwzjvv8O9//9vu0kRE7OFywahRULs2bNkChQvDp59CTAyUKJFh19atzRLrUqUyPkXp0lp6LXmHWx9aOnnyJEOGDGHOnDkcPXqU0NBQHnvsMV566SV8fHyy9Bw6tCQiecbevdChA2zcaMYPPmiulxQaetWHuVxmddKhQ2ZOTFSUOjHi/rL6/e3WQSY7KMiIiMdLTYVx42DQIDh7FoKCzHGhDh0uP24kkkdk9fvbrZdfi4h4vZ9/ho4dYc0aM77vPvjwQyhTxt66RNyEW8+RERHxWpYFEyZA9eomxPj7m/G33yrEiFxCHRkREXfz66/QuTMsW2bGTZrAlClw22321iXihtSRERFxF5YFH30EkZEmxPj5mTXUK1YoxIhcgToyIiLuIDERnnkGFi4044YNYepUuP12e+sScXPqyIiI2Mmy4JNPTBdm4ULw9TXniVmzRiFGJAvUkRERscuRI9ClC8ybZ8b16sG0aVCliq1liXgSdWREROzw5ZdQtaoJMQUKwIgRsGGDQozIdVJHRkQkN/35Jzz7LHz1lRnXrAnTp5tl1iJy3dSRERHJLXPnmi7MV19B/vwwdChs2qQQI3IT1JEREclpx49Dz54wY4YZV60KH39sLvwoIjdFHRkRkZy0YIEJLjNmQL585npJW7cqxIhkE3VkRERyQlIS9O1rzgUDULGimQtTv769dYnkMerIiIhkt6VLoVo1E2IcDujXD7ZtU4gRyQHqyIiIZJdTp6B/f5g40YzLlTNhJirK3rpE8jB1ZEREssOqVaYLkxZievSA7dsVYkRymIKMiMjNOHMGeveGpk3h4EEoWxaWL4dx48Df3+7qRPI8HVoSEblRGzZAdDTs32/GzzwDb70FgYH21iXiRdSRERG5XufOmbkwd91lQkypUrB4MXzwgUKMSC5TR0ZE5HrExpouzI8/mnGHDjB6NBQubGdVIl5LHRkRkaxISYHBg6FBAxNiSpaE+fPNqiSFGBHbqCMjInIt27aZLsyOHWb8+OMwdiwULWpvXSKijoyIyJW4zl3gQMdXSa13B+zYgVWsGMyaZS43oBAj4hYUZEREMrFszE52Bd1JxLSh5HNdZBYPUyv/TmIcD9tdmohc4rqDTHR0NGvWrMmJWkRE7HfxIjufGElU3zpUvxDHXxThMT7jEb7i+8PFadMGYmLsLlJE0lx3kElKSqJZs2ZUqFCB1157jcTExJyoS0Qk9+3ejdXoLiJnvIgv55lPS6qyiy94DHBgWWa3Pn3A5bKzUBFJc91BZu7cuSQmJtKtWze+/PJLwsPDadGiBbNmzeLChQs5UaOISM5yueCdd6BWLRybN3GCYKKZxkPM4zAhGXa1LEhIgLVrbapVRDK4oTkyxYoVo1+/fmzfvp1NmzZRvnx5nnzySUJDQ+nbty/79u3L7jpFRHLG/v1w993w3HNw7hyHqjcnkp18TDTguOLDDh3KtQpF5CpuarLvoUOHWLp0KUuXLsXpdPLggw+yY8cOqlSpwujRo7OrRhGR7JeaCu+9BzVqwLp1EBAAkyaxZ8wiEil9zYeHhFxzFxHJBQ7LSjvqmzUXLlxg/vz5TJ06lSVLllC9enWeeuopHn/8cYKCggCYM2cOnTp14vjx4zlS9PVITk4mODiYpKSk9PpExMsdPAidOsHKlWbctClMmQLh4bhcEB4OiYmQ2d+ODgeULg0HDoDTmZtFi3iXrH5/X/cJ8UJCQkhNTeWxxx5j8+bN1KxZ87J9mjZtSmGd6VJE3I1lweTJ5jDSqVNQqBC8+SZ06wb5TIPa6YR334U2bUxouTTMOP57pGnMGIUYEXdx3R2ZTz75hEceeYSCBQvmVE3ZSh0ZEQHgt9/gqafg22/N+K67zOUFypfPdPeYGOjd2zwsTViYCTGtW+d8uSLeLqvf39cdZDyNgoyIl7MsmD7drJlOSoKCBeG116BXr2u2VVwuszrp0CEzJyYqSp0YkdySY4eWREQ8xqFD0KULfP21GdevD9OmQaVKWXq402kWNImI+9IlCkQk77Es+PxzqFrVhBgfHxg50qxOymKIERHPoI6MiOQtR4/Cs8/C7NlmXLu2ObQUGWlvXSKSI9SREZG8Y/Zs04WZPRvy54dXXoHvvlOIEcnD1JEREc937Bj07GkOJwFUq2a6MLVq2VuXiOQ4dWRExLN9/bXpuHz+uZmdO3gwbNmiECPiJdSRERHPdOKEWVI9fboZV65s/lyvnp1ViUguU0dGRDzP4sWmCzN9ujndbv/+EBenECPihdSRERHPcfKkubzA5MlmXKGCOS9Mw4a2liUi9lFHRkQ8w4oVZhJvWojp1Qvi4xViRLycOjIi4t5On4YBA+D99804IsJcI6lJE3vrEhG3oCAjIu5r3Tro0AF++smMu3aFUaMgIMDWskTEfejQkoi4n7NnoV8/aNzYhJiwMFiyBCZMUIgRkQzUkRER97JpE0RHw549ZtypE7zzDgQH21uXiLgldWRExD2kpMCgQWby7p49EBIC33wDH32kECMiV6SOjIjYb+tW04XZtcuMn3gCxo6FIkXsrUtE3J46MiJin/PnYehQqF/fhJjixWHOHPjkE4UYEckSdWRExB7ff2+6MPHxZty2rVlifeuttpYlIp5FHRkRyV0XL8KIEVC3rgkxRYvCl1+am0KMiFwndWREJPf88IPpwmzZYsatWsHEiVCihK1liYjnUkdGRHKey2VOZFe7tgkxhQubeTAxMQoxInJT1JERkZy1b585O++GDWbcooW5XlKpUraWJSJ5gzoyIpIzUlPh3XehRg0TYgIDzTlhFixQiBGRbOP2QSYxMZEnnniCokWL4ufnR7Vq1diSdnxdRNzTzz/DPfdAnz7mcgPNmsHOneYsvQ6H3dWJSB7i1oeWjh8/TqNGjWjatCmLFi2iWLFi7Nu3jyI6v4SIe7Is+OADeP55c9Vqf3946y3o0kUBRkRyhFsHmTfeeIOwsDCmTp2avi0iIsLGikTkin79FTp3hmXLzLhJE5gyBW67zd66RCRPc+tDS/Pnz6du3bo88sgjFC9enFq1ajF58mS7yxKRS1mWCSzVqpkQ4+dn5sasWKEQIyI5zq2DzM8//8yECROoUKEC3377Ld26daNXr15Mnz79io9JSUkhOTk5w01Ecsjvv8M//2k6McnJ0KCBOcldr16Qz63/ehGRPMJhWZZldxFX4uPjQ926ddmQtmwT6NWrF7GxsWzcuDHTx7z88su88sorl21PSkoiKCgox2oV8SqWBTNmQM+ecOIE+PrCsGHQrx84nXZXJyJ5QHJyMsHBwdf8/nbrfzKFhIRQpUqVDNsqV67Mr7/+esXHDBo0iKSkpPRbQkJCTpcp4l2OHIF//xuefNKEmHr1IC4O+vdXiBGRXOfWk30bNWrEnj17Mmzbu3cvZcuWveJjfH198fX1zenSRLzTzJnw7LNw7BgUKGCuXD1gAOR3679KRCQPc+u/ffr27UvDhg157bXXaNu2LZs3b2bSpElMmjTJ7tJEvMuff0L37ibIANSsCdOnQ/XqtpYlIuLWh5bq1avHnDlz+Pzzz4mMjGTYsGGMGTOGdu3a2V2aiPeYOxeqVjUhxumEl16CTZsUYkTELbj1ZN/skNXJQiLyN8ePm9VHn35qxlWrmi5MnTr21iUiXiFPTPYVEZssXGiCy6efmmXUAwfC1q0KMSLidtx6joyI5LKkJLOEesoUM65YEaZNgzvvtLUsEZErUUdGRIylS83ZeadMMddF6tcPtm1TiBERt6aOjIi3O3XKnANm4kQzLlcOpk6FqCh76xIRyQJ1ZES82apVpguTFmJ69IDt2xViRMRjKMiIeKMzZ6B3b2jaFA4ehLJlYflyGDcO/P3trk5EJMt0aEnE22zYANHRsH+/GT/zDIwaBTo9gYh4IHVkRLzFuXNmLsxdd5kQU6oULF4MH3ygECMiHksdGRFvsHmz6cLs3m3GHTrA6NFQuLCdVYmI3DR1ZETyspQUGDwYGjY0IaZkSZg/36xKUogRkTxAHRmRvGrbNtOF2bHDjB9/HMaOhaJF7a1LRCQbqSMjktdcuACvvAJ33GFCTLFiMGsWzJihECMieY46MiJ5yc6dpgsTF2fGDz8M48dD8eL21iUikkPUkRHJCy5ehJEjzUUd4+Lgllvg88/hq68UYkQkT1NHRsTT7d5tViFt2mTGLVuaJdUhIbaWJSKSG9SREfFULhe88w7UqmVCTHCwuVL1vHkKMSLiNdSREfFE+/dDx46wbp0ZN28OH34IpUvbW5eISC5TR0bEk6SmwnvvQY0aJsQEBMCkSbBokUKMiHgldWREPMXBg9CpE6xcacZNm8KUKRAebmdVIiK2UkdGxN1Zlum6VKtmQkyhQqYrs2yZQoyIeD11ZETcWUICPPUULFlixnfdZS4vUL68vXWJiLgJdWRE3JFlmRVIkZEmxBQsaFYorVqlECMicgl1ZCRPcLlg7Vo4dMisPI6KAqfT7qpu0KFD8Mwz8M03Zly/PkyfDhUr2lvXdchTn4eIuDV1ZMTjxcSYqSJNm5rrIjZtasYxMXZXdp0sCz77DKpWNSHGxwdef92sTvKgEJNnPg8R8QgKMuLRYmKgTRv47beM2xMTzXaP+fI8etQU3K4dHD8OtWvD1q0wYADk95zGaZ75PETEYzgsy7LsLiInJScnExwcTFJSEkFBQXaXI9nI5TL/0v/7l2Yah8OcWuXAATc/rDFrFnTrBn/+aULLSy/BwIFQoIDdlV2XPPN5iIhbyOr3tzoy4rHWrr3ylyaYIzUJCWY/t3TsGDz2GDzyiAkx1atDbCwMGeJxIQbywOchIh5JQUY81qFD2btfrpo/38yF+eIL054YPNiEmJo17a7shnn05yEiHstzDr6L/E1Wr4voVtdPPHECeveGjz8248qVzYqkevVsLSs7eOTnISIeTx0Z8VhRUWbOhcOR+f0OB4SFmf3cwuLF5rwwH39siuvfH+Li8kSIAQ/8PEQkT1CQEY/ldMK775o///3LM208ZowbTCxNTjbnhWnRwizfqVDBLKl+801zors8wmM+DxHJUxRkxKO1bm0W/ZQqlXF76dJme+vW9tSVbsUKc42kyZPNuHdviI+Hhg1tLSunuP3nISJ5jpZfS57gdmeSPXXKLKF+/30zjogw10hq0sTGonKP230eIuJxsvr9rcm+kic4nXD33XZX8V9r10KHDvDzz2bcrZs5jBQQYGtZucmtPg8RydN0aEkku5w9C/36ma7Lzz+bma1Ll8L48V4VYkREcpM6MiLZ4bvvIDoa9u41406dzNWqg4PtrUtEJI9TR0bkZqSkmLkwjRqZEBMaCgsWwEcfKcSIiOQCdWREbtTWraYLs2uXGT/xBIwdC0WK2FuXiIgXUUdG5HqdP28u7Fi/vgkxxYvDnDnwyScKMSIiuUwdGZHr8f33pgsTH2/GbduaJda33mprWSIi3kodGZGsuHgRRoyAunVNiClaFL780twUYkREbKOOjMi1/PCD6cJs2WLGrVrBxIlQooStZYmIiDoyIlfmcsGoUVC7tgkxhQubeTAxMQoxIiJuQh0Zkczs3WvOzrtxoxm3aGGul/T3iwiJiIit1JERuVRqqrmEc82aJsQEBppzwixYoBAjIuKG1JERSfPzz9CxI6xZY8bNmpkQU6aMvXWJiMgVqSMjYlkwYQJUr25CjL+/GS9ZohAjIuLm1JER7/brr9C5MyxbZsZNmsCUKXDbbfbWJSIiWaKOjHgnyzKHjSIjTYjx84MxY2DFCoUYEREPoo6MeJ/ERHjmGVi40IwbNIBp0+D2220tS0RErp86MuI9LMucByYy0oQYX194801Yu1YhRkTEQ6kjI97hyBHo0gXmzTPjevVMF6ZKFVvLEhGRm6OOjOR9M2dC1aomxBQoAMOHw4YNCjEiInmAOjKSd/35Jzz7LHz1lRnXqAHTp5v/iohInqCOjORNc+eaLsxXX4HTCS+9BJs3K8SIiOQx6shI3nL8OPTsCTNmmHHVqqYLU6eOvXWJiEiO8KiOzOuvv47D4aBPnz52l5JnuFywahV8/rn5r8tld0U3YcECE1xmzIB8+WDgQNi61aNCTJ76PEREcoHHdGRiY2P54IMPqF69ut2l5BkxMdC7N/z22/+2lS5trpnYurV9dV23pCTo18+ckRegYkWzIunOO20t63rlmc9DRCQXeURH5tSpU7Rr147JkydTpEgRu8vJE2JioE2bjF+aYM4V16aNud8jLF0K1aqZEONwQN++sG2bR4aYPPF5iIjkMo8IMt27d+cf//gHzZo1s7uUPMHlMv/yt6zL70vb1qePmx/WOHUKunWD+++HhAQoVw5Wr4Z33jGXG/AgeeLzEBGxidsfWvriiy+Ii4sjNjY2S/unpKSQkpKSPk5OTs6p0jzW2rWX/8v/UpZlssHatXD33blWVtatWgUdO8LBg2bcvTu88Ya5arUH8vjPQ0TERm7dkUlISKB3797MmDGDggULZukxI0eOJDg4OP0WFhaWw1V6nkOHsne/XHPmjGldNG1qQkzZsrB8Obz3nseGGPDgz0NExA24dZDZunUrR48epXbt2uTPn5/8+fOzevVqxo4dS/78+XFl0msfNGgQSUlJ6beEhAQbKndvISHZu1+u2LDBnANm7Fgzfvpp+P57uOcee+vKBh75eYiIuAmHZWV2ZN49nDx5kl9++SXDto4dO1KpUiUGDBhAZGTkNZ8jOTmZ4OBgkpKSCAoKyqlSPYrLBeHhZiJpZp++w2FWyxw4YM4lZ6tz52DIEHj7bVNsqVLw4YfwwAM2F5Z9POrzEBHJJVn9/nbrOTKBgYGXhRV/f3+KFi2apRAjmXM6zZLeNm3Ml+SlX54Oh/nvmDFu8KUZGwvR0fDjj2YcHW0KK1zYzqqyncd8HiIibsitDy1JzmndGmbNMg2OS5Uubbbbet6SlBQYPBgaNDAhpkQJc8HHadPyXIhJ49afh4iIG3PrQ0vZQYeWrs7lMqthDh0yczCiomz+l/+2babzsmOHGT/2GIwbB0WL2lhU7nG7z0NExCZ54tCS5Dyn002W9F64AK+9BsOHw8WLcOutMHEiPPyw3ZXlKrf5PEREPISCjNhv507ThYmLM+PWrWHCBChe3N66RETE7WmOjNjn4kUYOdJc1DEuDooUgc8+M5NCFGJERCQL1JERe+zeDR06wKZNZvzPf8KkSTpZioiIXBd1ZCR3uVzmeki1apkQExxsViPNn68QIyIi100dGck9+/ebayStW2fG998PH31k1hiLiIjcAHVkJOelpprrIdWoYUJMQIA5jLR4sUKMiIjcFHVkJGcdPAidOsHKlWbctClMmWLOyS8iInKT1JGRnGFZputSrZoJMYUKmRPbLVumECMiItlGHRnJfr/9Bk89Bd9+a8aNGpkJveXL21qWiIjkPerISPaxLBNYIiNNiPH1NVetXr1aIUZERHKEOjKSPQ4dgi5d4OuvzfiOO2D6dKhUyd66REQkT1NHRm6OZcHnn0PVqibE+PiYs/WuX68QIyIiOU4dGblxR4/Cs8/C7NlmXKsWfPyxObQkIiKSC9SRkRsze7YJLLNnQ/788Mor5ky9CjEiIpKL1JGR63PsGPTsaQ4ngVlePX266caIiIjkMnVkJOu+/tp0XD7/HJxOGDwYYmMVYkRExDbqyMi1nTgBffqYzgtA5crmz/Xq2VmViIiIOjJyDYsXmy7M9OngcMDzz0NcnEKMiIi4BXVkJHMnT8Jzz8HkyWZcvrw52V2jRraWJSIicil1ZORyK1aYSbxpIaZXL9i+XSFGRETcjjoy8j+nT8OAAfD++2YcHg5Tp8Ldd9tZlYiIyBUpyIixbh106AA//WTGXbvCqFEQEGBrWSIiIlejQ0ve7uxZMxemcWMTYsLCYMkSmDBBIUZERNyeOjLebNMmiI6GPXvMuFMneOcdCA62ty4REZEsUkfGG6WkwKBB0LChCTEhIfDNN/DRRwoxIiLiUdSR8TZbt5ouzK5dZvzEE/Duu3DLLfbWJSIicgPUkfEW58/D0KFQv74JMcWLQ0wMfPKJQoyIiHgsdWS8wfffmy5MfLwZP/KIWWJdrJitZYmIiNwsdWTysosXYcQIqFvXhJiiReHLL2HmTIUYERHJE9SRyat+/NF0YWJjzfihh2DiRChZ0t66REREspE6MnmNy2VOZFerlgkxhQvDxx/DnDkKMSIikueoI5OX7Ntnzs67YYMZt2hhrpdUqpStZYmIiOQUdWTygtRUs4S6Rg0TYgID4cMPYcEChRgREcnT1JHxdD//bM7Iu3q1GTdrZk5sV6aMvXWJiIjkAnVkPJVlmcm71aubEOPvD+PHm+skKcSIiIiXUEfGE/36K3TuDMuWmXHjxjB1Ktx2m711iYiI5DJ1ZDyJZcGUKVCtmgkxBQvCmDGwcqVCjIiIeCV1ZDzF77/D00/DwoVm3KABTJsGt99ua1kiIiJ2UkfG3VkWfPopVK1qQoyPD7z5JqxdqxAjIiJeTx0Zd3bkCHTtCnPnmnHdujB9OlSpYmtZIiIi7kIdGXc1c6bpwsydCwUKwLBhsHGjQoyIiMgl1JFxN3/+Cd27myAD5iR306eb/4qIiEgG6si4k3nzTBdm5kxwOmHIENi8WSFGRETkCtSRcQfHj0Pv3vDJJ2ZcpYrpwtSta29dIiIibk4dGbstWgSRkSbE5MsHAwbA1q0KMSIiIlmgjoxdkpLguefMdZHALKWePh3uvNPeukRERDyIOjJ2WLbMnJ33o4/A4YC+fSE+XiFGRETkOqkjk5tOnYIXXoAJE8z4ttvM2XmjomwtS0RExFOpI5NbVq82V6pOCzHPPgvbtyvEiIiI3AQFmZx25gz06QN33w0HDkCZMubQ0vvvQ0CA3dWJiIh4NB1aykkbNkCHDrBvnxk/9RS8/TYEBdlaloiISF6hjkxOOHfOzIWJijIhplQps8x68mSFGBERkWykjkx227IFoqPhhx/MuH17ePddKFzY1rJERETyInVkssv58+aSAnfeaUJMiRLmkgPTpyvEiIiI5BB1ZLJDfLzpwnz/vRk/+ii89x4ULWprWSIiInmdgswNcLlg7Vo4nHCB+itfJ/yTV3FcvAi33mqWV7dpY3eJIiIiXsGtDy2NHDmSevXqERgYSPHixWnVqhV79uyxtaaYGAgPh+5Nd1G+fQMipr6E4+JFEuu3hl27FGJERERykVsHmdWrV9O9e3e+++47li5dyoULF7j//vs5ffq0LfXExJic8ttvMJ5nqctW/qII7ZhB2KZZxKwrbktdIiIi3sphWZZldxFZ9ccff1C8eHFWr15N48aNs/SY5ORkgoODSUpKIugmlj67XKYT89tvZlyR3QznP/RiLIcIxeGA0qXNOe+czht+GRERESHr398eNUcmKSkJgFtuueWK+6SkpJCSkpI+Tk5OzpbXXrv2fyEGYA+VeIRZ6WPLgoQEs9/dd2fLS4qIiMg1uPWhpUulpqbSp08fGjVqRGRk5BX3GzlyJMHBwem3sLCwbHn9Q4eydz8RERG5eR4TZLp3787OnTv54osvrrrfoEGDSEpKSr8lJCRky+uHhGTvfiIiInLzPOLQUo8ePfjmm29Ys2YNpUuXvuq+vr6++Pr6ZnsNUVFmDkxiojmM9Hdpc2R0MWsREZHc49YdGcuy6NGjB3PmzGHFihVERETYVovTaa40ACa0XCptPGaMJvqKiIjkJrcOMt27d+fTTz/ls88+IzAwkMOHD3P48GHOnj1rSz2tW8OsWeYakJcqXdpsb93alrJERES8llsvv3b8vfXxX1OnTqVDhw5Zeo7sWn59qbQz+x46ZObEREWpEyMiIpKd8sTya3fNWE6nlliLiIi4A7c+tCQiIiJyNQoyIiIi4rEUZERERMRjKciIiIiIx1KQEREREY+lICMiIiIeS0FGREREPJaCjIiIiHgsBRkRERHxWG59Zt/skHZ24OTkZJsrERERkaxK+96+1ln+83yQOXnyJABhYWE2VyIiIiLX6+TJkwQHB1/xfre+aGR2SE1N5ffffycwMPCKF6H0dsnJyYSFhZGQkJBtF9aUG6fPw73o83Av+jzcS05+HpZlcfLkSUJDQ8mX78ozYfJ8RyZfvnyULl3a7jI8QlBQkP5icCP6PNyLPg/3os/DveTU53G1TkwaTfYVERERj6UgIyIiIh5LQUbw9fVl6NCh+Pr62l2KoM/D3ejzcC/6PNyLO3weeX6yr4iIiORd6siIiIiIx1KQEREREY+lICMiIiIeS0FGREREPJaCjJcaOXIk9erVIzAwkOLFi9OqVSv27Nljd1nyX6+//joOh4M+ffrYXYpXS0xM5IknnqBo0aL4+flRrVo1tmzZYndZXsnlcjFkyBAiIiLw8/OjXLlyDBs27JrX4ZHssWbNGlq2bEloaCgOh4O5c+dmuN+yLF566SVCQkLw8/OjWbNm7Nu3L1dqU5DxUqtXr6Z79+589913LF26lAsXLnD//fdz+vRpu0vzerGxsXzwwQdUr17d7lK82vHjx2nUqBEFChRg0aJF/PDDD7z99tsUKVLE7tK80htvvMGECRN47733+PHHH3njjTd48803GTdunN2leYXTp09To0YN3n///Uzvf/PNNxk7diwTJ05k06ZN+Pv707x5c86dO5fjtWn5tQDwxx9/ULx4cVavXk3jxo3tLsdrnTp1itq1azN+/HiGDx9OzZo1GTNmjN1leaWBAweyfv161q5da3cpAvzzn/+kRIkSfPTRR+nbHn74Yfz8/Pj0009trMz7OBwO5syZQ6tWrQDTjQkNDeW5557j+eefByApKYkSJUowbdo0Hn300RytRx0ZAcwvHcAtt9xicyXerXv37vzjH/+gWbNmdpfi9ebPn0/dunV55JFHKF68OLVq1WLy5Ml2l+W1GjZsyPLly9m7dy8A27dvZ926dbRo0cLmyuTAgQMcPnw4w99bwcHB1K9fn40bN+b46+f5i0bKtaWmptKnTx8aNWpEZGSk3eV4rS+++IK4uDhiY2PtLkWAn3/+mQkTJtCvXz9efPFFYmNj6dWrFz4+PkRHR9tdntcZOHAgycnJVKpUCafTicvlYsSIEbRr187u0rze4cOHAShRokSG7SVKlEi/LycpyAjdu3dn586drFu3zu5SvFZCQgK9e/dm6dKlFCxY0O5yBBPw69aty2uvvQZArVq12LlzJxMnTlSQscHMmTOZMWMGn332GVWrViU+Pp4+ffoQGhqqz8PL6dCSl+vRowfffPMNK1eupHTp0naX47W2bt3K0aNHqV27Nvnz5yd//vysXr2asWPHkj9/flwul90lep2QkBCqVKmSYVvlypX59ddfbarIu/Xv35+BAwfy6KOPUq1aNZ588kn69u3LyJEj7S7N65UsWRKAI0eOZNh+5MiR9PtykoKMl7Isix49ejBnzhxWrFhBRESE3SV5tXvvvZcdO3YQHx+ffqtbty7t2rUjPj4ep9Npd4lep1GjRpedkmDv3r2ULVvWpoq825kzZ8iXL+NXltPpJDU11aaKJE1ERAQlS5Zk+fLl6duSk5PZtGkTDRo0yPHX16ElL9W9e3c+++wz5s2bR2BgYPpxzODgYPz8/GyuzvsEBgZeNj/J39+fokWLat6STfr27UvDhg157bXXaNu2LZs3b2bSpElMmjTJ7tK8UsuWLRkxYgRlypShatWqbNu2jXfeeYdOnTrZXZpXOHXqFPv3708fHzhwgPj4eG655RbKlClDnz59GD58OBUqVCAiIoIhQ4YQGhqavrIpR1nilYBMb1OnTrW7NPmvJk2aWL1797a7DK/29ddfW5GRkZavr69VqVIla9KkSXaX5LWSk5Ot3r17W2XKlLEKFixo3XbbbdbgwYOtlJQUu0vzCitXrsz0OyM6OtqyLMtKTU21hgwZYpUoUcLy9fW17r33XmvPnj25UpvOIyMiIiIeS3NkRERExGMpyIiIiIjHUpARERERj6UgIyIiIh5LQUZEREQ8loKMiIiIeCwFGREREfFYCjIiIiLisRRkRMSjuFwuGjZsSOvWrTNsT0pKIiwsjMGDB9tUmYjYQWf2FRGPs3fvXmrWrMnkyZNp164dAO3bt2f79u3Exsbi4+Njc4UiklsUZETEI40dO5aXX36ZXbt2sXnzZh555BFiY2OpUaOG3aWJSC5SkBERj2RZFvfccw9Op5MdO3bQs2dP/vOf/9hdlojkMgUZEfFYu3fvpnLlylSrVo24uDjy589vd0kikss02VdEPNaUKVMoVKgQBw4c4LfffrO7HBGxgToyIuKRNmzYQJMmTViyZAnDhw8HYNmyZTgcDpsrE5HcpI6MiHicM2fO0KFDB7p160bTpk356KOP2Lx5MxMnTrS7NBHJZerIiIjH6d27NwsXLmT79u0UKlQIgA8++IDnn3+eHTt2EB4ebm+BIpJrFGRExKOsXr2ae++9l1WrVnHXXXdluK958+ZcvHhRh5hEvIiCjIiIiHgszZERERERj6UgIyIiIh5LQUZEREQ8loKMiIiIeCwFGREREfFYCjIiIiLisRRkRERExGMpyIiIiIjHUpARERERj6UgIyIiIh5LQUZEREQ8loKMiIiIeKz/B+lrQGXFohpJAAAAAElFTkSuQmCC\n"
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "**Multiple** **Linear Regression**"
      ],
      "metadata": {
        "id": "AMkUC_Ab917R"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 1: Import Libraries"
      ],
      "metadata": {
        "id": "Dy1_Mhsx99Yl"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from mpl_toolkits.mplot3d import Axes3D"
      ],
      "metadata": {
        "id": "uP7Tl7_b98l8"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 2: Implement Multiple Linear Regression Class"
      ],
      "metadata": {
        "id": "ipXYhjPk92Fz"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class MultipleLinearRegression:\n",
        "    def __init__(self):\n",
        "        self.coefficients_ = None\n",
        "        self.intercept_ = None\n",
        "        self.r2score_ = None\n",
        "\n",
        "    def fit(self, X, y):\n",
        "        n = X.shape[0]\n",
        "        X_b = np.c_[np.ones((n,1)), X]\n",
        "        self.coefficients_ = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)\n",
        "        self.intercept_ = self.coefficients_[0]\n",
        "        y_pred = X_b.dot(self.coefficients_)\n",
        "        self.r2score_ = 1 - (np.sum((y - y_pred)**2)/np.sum((y - np.mean(y))**2))\n",
        "        self.y_pred_ = y_pred\n",
        "\n",
        "    def predict(self, X):\n",
        "        X_b = np.c_[np.ones((X.shape[0],1)), X]\n",
        "        return X_b.dot(self.coefficients_)"
      ],
      "metadata": {
        "id": "YctgNaQh-fz1"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 3: Generate Sample Dataset"
      ],
      "metadata": {
        "id": "1kNTAPTC-gJq"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "np.random.seed(0)\n",
        "X1 = np.random.randint(1, 11, 15)\n",
        "X2 = np.random.randint(1, 11, 15)\n",
        "X_multi = np.column_stack((X1, X2))\n",
        "y_multi = 1 + 2*X1 + 3*X2 + np.random.randn(15)*2"
      ],
      "metadata": {
        "id": "x1tkgEwT-glU"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Step 4: Fit the Model and Visualize"
      ],
      "metadata": {
        "id": "yEmMXOPy-or9"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "mlr = MultipleLinearRegression()\n",
        "mlr.fit(X_multi, y_multi)\n",
        "print(f\"Multiple LR Coefficients: {mlr.coefficients_}\")\n",
        "print(f\"R² Score: {mlr.r2score_:.2f}\")\n",
        "\n",
        "fig = plt.figure(figsize=(10,7))\n",
        "ax = fig.add_subplot(111, projection='3d')\n",
        "\n",
        "ax.scatter(X_multi[:,0], X_multi[:,1], y_multi, color='blue', label='Data')\n",
        "\n",
        "x1_surf, x2_surf = np.meshgrid(\n",
        "    np.linspace(X_multi[:,0].min(), X_multi[:,0].max(), 10),\n",
        "    np.linspace(X_multi[:,1].min(), X_multi[:,1].max(), 10)\n",
        ")\n",
        "\n",
        "pred_surf = mlr.predict(np.c_[x1_surf.ravel(), x2_surf.ravel()]).reshape(x1_surf.shape)\n",
        "\n",
        "ax.plot_surface(x1_surf, x2_surf, pred_surf, color='red', alpha=0.5, rstride=1, cstride=1)\n",
        "\n",
        "ax.set_xlabel('X1')\n",
        "ax.set_ylabel('X2')\n",
        "ax.set_zlabel('y')\n",
        "ax.set_title(\"Multiple Linear Regression with Regression Plane\")\n",
        "ax.legend()\n",
        "plt.show()"
      ],
      "metadata": {
        "id": "Rm2Vp2x6-nyB"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}