{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "95ef8429-f5c0-42eb-ac2d-c7bdb438f158",
   "metadata": {},
   "source": [
    "# Import libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "id": "71894972-488a-438f-8dc9-7be10a7c4d28",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import scipy as sc  # only for null_space\n",
    "import sympy as sy  # only for Matrix and gauss_jordan_solve\n",
    "from sklearn.linear_model import LinearRegression  # only for least square solution\n",
    "from sklearn.metrics import root_mean_squared_error  # only for rmse"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db94c9b4-d5a6-4082-bb90-a0379f740d8f",
   "metadata": {},
   "source": [
    "# Element wise mat mat mult vs. real mat mat mult"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "ca3eee9d-d31a-401a-8da4-adede37a23a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "M1 = np.array([[1,2],[3,4]])\n",
    "M2 = np.array([[5,6],[7,8]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "3bba24c4-daa3-431c-b3dd-c53f95f6801d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "11531db0-d5a5-4081-8982-22f6abf04727",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5, 6],\n",
       "       [7, 8]])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1df0989d-6ba9-4a40-a989-33b1298d8c76",
   "metadata": {},
   "source": [
    "**Get M1(1, 2)**  \n",
    "Python starts at 0, so we have to shift index by one"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "055dafaa-a5b0-4911-b736-85289b393377",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.int64(2)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1[0, 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76031680-1230-4270-abb0-6ba264353b73",
   "metadata": {},
   "source": [
    "**Or get second column**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "f078c924-0535-4023-8bb9-edd972fd099e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1[:, 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b224c3a-e830-4a85-b95c-dcbb54c62243",
   "metadata": {},
   "source": [
    "**Elementwise multiplication**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "02e4fb58-b049-4bd9-8a71-0398b7a6b79b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5, 12],\n",
       "       [21, 32]])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1*M2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "ba642768-fa0a-4d72-9140-2691cb9c7c40",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5, 12],\n",
       "       [21, 32]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.multiply(M1, M2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "55a95ebc-e7a1-40ad-bf93-9dbe6a65bcbc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ True,  True],\n",
       "       [ True,  True]])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1*M2 == M2*M1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10de14d5-e558-47c4-b325-d929b5b38b40",
   "metadata": {},
   "source": [
    "**Real matrix-matrix-multiplication**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "b35eee49-ea00-4e0d-827f-c2d9dd15b11b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[19, 22],\n",
       "       [43, 50]])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.matmul(M1, M2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "2f79c84d-59e6-4a24-8256-4fbefd416011",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[19, 22],\n",
       "       [43, 50]])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(M1, M2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "3fa71f05-f411-4925-8597-c30dfdb15464",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[19, 22],\n",
       "       [43, 50]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1@M2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "0ba69b9c-02d8-4ecf-b3fa-fbd8e5627fba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False],\n",
       "       [False, False]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.matmul(M1, M2) == np.matmul(M2, M1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3a26dc6-b9f8-4b72-8245-7f14f84902f1",
   "metadata": {},
   "source": [
    "# Linear system with unique solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "2c85b379-ec0f-43d2-9cb8-7f55ee50dbdf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0, 1],\n",
       "       [0, 1, 1, 0],\n",
       "       [2, 0, 1, 2],\n",
       "       [0, 0, 0, 1]])"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M = np.array([\n",
    "    [1, 0, 0, 1],\n",
    "    [0, 1, 1, 0],\n",
    "    [2, 0, 1, 2],\n",
    "    [0, 0, 0, 1]\n",
    "])\n",
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "e7beff58-5925-414c-b7e1-67aeaac14fb0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.,  0.,  0., -1.],\n",
       "       [ 2.,  1., -1.,  0.],\n",
       "       [-2., -0.,  1., -0.],\n",
       "       [ 0.,  0.,  0.,  1.]])"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M_inv = np.linalg.inv(M)\n",
    "M_inv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "755a9e54-95ae-48fe-9dbd-f49625807343",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 0, 2])"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f = np.array([1, 2, 0, 2])\n",
    "f"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "ff27bd7c-1c66-4041-8f63-c2e46c8f95df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.,  4., -2.,  2.])"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.matmul(M_inv, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "913f1aae-a88a-404f-a2e0-92c57560f03e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.,  4., -2.,  2.])"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.linalg.solve(M, f)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4f7fd46-d605-43fd-9d86-47c3e86bcc24",
   "metadata": {},
   "source": [
    "**Check solution with allclose**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "9c9a9e56-bafd-414a-8f00-2d8613b29534",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(np.matmul(M, x), f)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74bac408-ff7f-4d6d-925f-2da43bc128d5",
   "metadata": {},
   "source": [
    "# Linear system with many solutions - minimal norm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "aa9c7da3-1708-497a-a1a7-828b5684bff3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 1, 2, 1],\n",
       "       [2, 0, 0, 2],\n",
       "       [0, 2, 1, 1],\n",
       "       [4, 3, 3, 4]])"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M = np.array([\n",
    "    [2, 1, 2, 1],\n",
    "    [2, 0, 0, 2],\n",
    "    [0, 2, 1, 1],\n",
    "    [4, 3, 3, 4]\n",
    "])\n",
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "a438a4d9-9701-49db-bb56-bcfe0cdf9aba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 1, 4])"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f = np.array([1, 2, 1, 4])\n",
    "f"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4d915c3-792e-4928-bc01-2a12a025daea",
   "metadata": {},
   "source": [
    "**The follwoing does not work because the inverse does not exist**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "0021a667-e6dd-4ba9-ac3f-95c7322522b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# M_inv = np.linalg.inv(M)\n",
    "# M_inv"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1e52705-18a0-4873-a603-ab57c8cb94c1",
   "metadata": {},
   "source": [
    "**Same problem here!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "ac99cd51-d50e-4ae4-b7a0-48f52ce9fb4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# x = np.linalg.solve(M, f)\n",
    "# x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0406c18c-f0db-411d-b08f-89d2c0b5ff57",
   "metadata": {},
   "source": [
    "**Here we get one solution (the one with minimum norm)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "id": "dcca6a3d-55c3-444b-9ee4-1dc8f01deb85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.25,  0.25, -0.25,  0.75])"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, residuals, rank, s = np.linalg.lstsq(M, f)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d686de5b-623a-43db-9117-7943f24abfe8",
   "metadata": {},
   "source": [
    "**Check solution**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "ecb9a78c-688e-41de-aab2-34569b6d6789",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(np.matmul(M, x), f)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7b6d375-34c0-4233-843f-db95bfe31286",
   "metadata": {},
   "source": [
    "**Using null_space we get the general solution**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "id": "98eaf002-16cc-43ce-adae-7d913928e9f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.5],\n",
       "       [ 0.5],\n",
       "       [-0.5],\n",
       "       [-0.5]])"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M_null = sc.linalg.null_space(M)\n",
    "M_null"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "adafdc6e-5e48-4bb3-81a9-ce9d6f2f202e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 25.25,  25.25, -25.25, -24.25])"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = 50\n",
    "x_new = x + t * M_null[:, 0]\n",
    "x_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "baf63145-2dc6-47bc-b3f1-fbede802b63b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(np.matmul(M, x_new), f)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd78959d-5265-47c9-b952-9b90818747f7",
   "metadata": {},
   "source": [
    "**Or use sympy (symbolic way, possible for small matrices)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "id": "a498df4d-6157-4fb7-bf8d-298205644b24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}1 - \\tau_{0}\\\\1 - \\tau_{0}\\\\\\tau_{0} - 1\\\\\\tau_{0}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "Matrix([\n",
       "[1 - tau0],\n",
       "[1 - tau0],\n",
       "[tau0 - 1],\n",
       "[    tau0]])"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M_sym = sy.Matrix(M)\n",
    "f_sym = sy.Matrix(f)\n",
    "sol, params = M_sym.gauss_jordan_solve(f_sym)\n",
    "sol"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "848a7fcf-7818-414f-b889-a0ffc08dff2e",
   "metadata": {},
   "source": [
    "# Linear system without a solution - least square"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 235,
   "id": "521432be-4907-4ad7-b843-c6025f5265d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([\n",
    "    [5, 1],\n",
    "    [10, 1],\n",
    "    [8, 1],\n",
    "    [11, 1],\n",
    "    [16, 1]\n",
    "])\n",
    "\n",
    "f = np.array([1000, 1100, 1200, 1500, 1500])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebe5cdca-ad99-42a2-95e1-cc4f0359b274",
   "metadata": {},
   "source": [
    "### Solve the solution with minimal error by hand"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 236,
   "id": "c27ccfc5-5b5e-4d15-b98c-0da2f7cdbe5c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 46.96969697, 790.3030303 ])"
      ]
     },
     "execution_count": 236,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.linalg.solve(np.matmul(np.transpose(X), X), np.matmul(np.transpose(X), f))\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71f24d59-6f19-4383-b314-1cda8ba4c23f",
   "metadata": {},
   "source": [
    "**Prediction**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 237,
   "id": "1179192b-b4bb-4ae4-98d0-8be2e62f02a2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1025.15151515, 1260.        , 1166.06060606, 1306.96969697,\n",
       "       1541.81818182])"
      ]
     },
     "execution_count": 237,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fhat = np.matmul(X, x)\n",
    "fhat"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18699804-8048-4932-8cb2-8d763a4ca95e",
   "metadata": {},
   "source": [
    "**Residual norm**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 238,
   "id": "1776e24d-7760-410a-92ad-2152fe2dd4c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(257.67021440969734)"
      ]
     },
     "execution_count": 238,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res_norm = np.linalg.norm(f-fhat)\n",
    "res_norm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf6905df-aa5b-4a9b-80c6-d3dfda4b74dd",
   "metadata": {},
   "source": [
    "**RMSE - root mean squared error**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 239,
   "id": "2a33e92a-eb25-4005-a4c3-1c5a18b0321f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(115.23362303940581)"
      ]
     },
     "execution_count": 239,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(1/np.size(f))*res_norm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ceb7005-945b-4dde-a345-1de83e9ce9aa",
   "metadata": {},
   "source": [
    "### Or use a simpler command for the same"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 240,
   "id": "acbeef96-d0b6-471f-80e0-836b0eea7622",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 46.96969697, 790.3030303 ])"
      ]
     },
     "execution_count": 240,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, residuals, rank, s = np.linalg.lstsq(X, f)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66098d80-291f-4b2a-8c34-529a021862bc",
   "metadata": {},
   "source": [
    "**Prediction**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 241,
   "id": "9c98519d-3852-4583-901b-d2e097111273",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1025.15151515, 1260.        , 1166.06060606, 1306.96969697,\n",
       "       1541.81818182])"
      ]
     },
     "execution_count": 241,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fhat = np.matmul(X, x)\n",
    "fhat"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ec8d26f-4a22-487f-991f-4dbb8ff4bb65",
   "metadata": {},
   "source": [
    "**Residual norm**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 242,
   "id": "e85ffe45-8c88-4620-b060-1ef5df173e54",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([257.67021441])"
      ]
     },
     "execution_count": 242,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res_norm = np.sqrt(residuals)\n",
    "res_norm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "113670fd-e208-43f4-98bb-f23aaa1fe76a",
   "metadata": {},
   "source": [
    "**RMSE - root mean squared error**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 243,
   "id": "62963cb6-d774-4d70-8805-8bf6380ced78",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([115.23362304])"
      ]
     },
     "execution_count": 243,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(1/np.size(f))*res_norm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68b9dc09-ed1e-47d5-b871-23faa26928a1",
   "metadata": {},
   "source": [
    "### Or use scikit learn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 244,
   "id": "e48f3b69-213a-46a0-a2a5-d7465b3b8fb5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[46.96969697] 790.3030303030305\n"
     ]
    }
   ],
   "source": [
    "linreg = LinearRegression()\n",
    "# here we use X[:, 0:1] because we do not need intercept one (automatically implemented)\n",
    "# and we use X[:, 0:1] and not X[:, 0] because we have to use it as matrix and not as vector\n",
    "linreg.fit(X[:, 0:1], f)\n",
    "print(linreg.coef_, linreg.intercept_)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0a4e399-8578-4037-82b2-8ef5e569d70b",
   "metadata": {},
   "source": [
    "**Prediction**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 245,
   "id": "bb72f049-1e9d-4849-a43e-ff5ee75052de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1025.15151515, 1260.        , 1166.06060606, 1306.96969697,\n",
       "       1541.81818182])"
      ]
     },
     "execution_count": 245,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fhat = linreg.predict(X[:, 0:1])\n",
    "fhat"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d71b3c03-561f-4896-91b7-5b794ec8e8f9",
   "metadata": {},
   "source": [
    "**Residual norm**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 246,
   "id": "ff1d6d92-84fb-4b6d-9df0-2079a00eb631",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(257.67021440969734)"
      ]
     },
     "execution_count": 246,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res_norm = np.linalg.norm(f-fhat)\n",
    "res_norm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbd14be4-585f-4730-928d-d44d008c06c9",
   "metadata": {},
   "source": [
    "**RMSE - root mean squared error**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 247,
   "id": "146a6366-1503-401a-8c82-1b2613af9846",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "115.23362303940581"
      ]
     },
     "execution_count": 247,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "root_mean_squared_error(f, fhat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ee91040-88f6-4a79-9b1e-af712e4df027",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7e883f2f-cb88-46ff-addb-b9fd0e4ec783",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
