{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>San Jose State University<br>Department of Applied Data Science</center>\n",
    "#  <center>DATA 220<br>Mathematical Methods for Data Analysis</center>\n",
    "### <center>Spring 2021<br>Instructor: Ron Mak</center>\n",
    "#  <center>Assignment #11<br>Matrix Operations Problem Set<BR>SOLUTION</center>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from numpy.linalg import solve, inv, qr, norm\n",
    "\n",
    "%precision 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr>\n",
    "\n",
    "#### <strong>PROBLEM 1.</strong> Amalgamated Widgets, Inc. manufactures several products using various amounts of materials per product:\n",
    "<table>\n",
    "    <tr>\n",
    "        <th>Product</th><th>Metal</th><th>Wood</th><th>Plastic</th><th>Cloth</th><th>Paper</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>A</td><td>0</td><td>1.3</td><td>0.2</td><td>0.8</td><td>0.4</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>B</td><td>0</td><td>0</td><td>1.5</td><td>0.4</td><td>0.3</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>C</td><td>0.25</td><td>0</td><td>0</td><td>0.2</td><td>0.7</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>D</td><td>0</td><td>0</td><td>0.3</td><td>0.7</td><td>0.5</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>E</td><td>0.15</td><td>0</td><td>0.5</td><td>0.4</td><td>0.8</td>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "#### On a certain day, the following total amounts of materials were used:\n",
    "<table>\n",
    "    <tr>\n",
    "        <th>Metal</th>\n",
    "        <th>Wood</th>\n",
    "        <th>Plastic</th>\n",
    "        <th>Cloth</th>\n",
    "        <th>Paper</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>51.0</td><td>312.0</td><td>215.4</td><td>373.1</td><td>356.0</td>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "#### How many of each product were made that day?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### <strong>SOLUTION.</strong> Let <em>x<sub>A</sub></em>, <em>x<sub>B</sub></em>, <em>x<sub>C</sub></em>, <em>x<sub>D</sub></em>, <em>x<sub>E</sub></em> be the numbers made of each product. Then we must have\n",
    "<table>\n",
    "    <tr>\n",
    "        <td align=right>0<em>x<sub>A</sub></em></td><td>+</td><td align=right>0<em>x<sub>B</sub></em></td><td>+</td><td align=right>0.25<em>x<sub>C</sub></em></td><td>+</td><td align=right>0<em>x<sub>D</sub></em></td><td>+</td><td align=right>0.15<em>x<sub>E</sub></em></td><td>=</td><td align=right>51.0</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td align=right>1.3<em>x<sub>A</sub></em></td><td>+</td><td align=right>0<em>x<sub>B</sub></em></td><td>+</td><td align=right>0<em>x<sub>C</sub></em></td><td>+</td><td align=right>0<em>x<sub>D</sub></em></td><td>+</td><td align=right>0<em>x<sub>E</sub></em></td><td>=</td><td align=right>312.0</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td align=right>0.2<em>x<sub>A</sub></em></td><td>+</td><td align=right>1.5<em>x<sub>B</sub></em></td><td>+</td><td align=right>0<em>x<sub>C</sub></em></td><td>+</td><td align=right>0.3<em>x<sub>D</sub></em></td><td>+</td><td align=right>0.5<em>x<sub>E</sub></em></td><td>=</td><td align=right>215.4</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td align=right>0.8<em>x<sub>A</sub></em></td><td>+</td><td align=right>0.4<em>x<sub>B</sub></em></td><td>+</td><td align=right>0.2<em>x<sub>C</sub></em></td><td>+</td><td align=right>0.7<em>x<sub>D</sub></em></td><td>+</td><td align=right>0.4<em>x<sub>E</sub></em></td><td>=</td><td align=right>373.1</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td align=right>0.4<em>x<sub>A</sub></em></td><td>+</td><td align=right>0.3<em>x<sub>B</sub></em></td><td>+</td><td align=right>0.7<em>x<sub>C</sub></em></td><td>+</td><td align=right>0.5<em>x<sub>D</sub></em></td><td>+</td><td align=right>0.8 <em>x<sub>E</sub></em></td><td>=</td><td align=right>356.0</td>\n",
    "    </tr>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "#### So we really want the <u>transpose</u> of the above materials table:\n",
    "<table>\n",
    "    <tr><th>Material</th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th></tr>\n",
    "    <tr><td>Metal</td><td>0</td><td>0</td><td>0.25</td><td>0</td><td>0.15</td></tr>\n",
    "    <tr><td>Wood</td><td>1.3</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>\n",
    "    <tr><td>Plastic</td><td>0.2</td><td>1.5</td><td>0</td><td>0.3</td><td>0.5</td></tr>\n",
    "    <tr><td>Cloth</td><td>0.8</td><td>0.4</td><td>0.2</td><td>0.7</td><td>0.4</td></tr>\n",
    "    <tr><td>Paper</td><td>0.4</td><td>0.3</td><td>0.7</td><td>0.5</td><td>0.8</td></tr>\n",
    "</table>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = ['A', 'B', 'C', 'D', 'E']\n",
    "m = ['metal', 'wood', 'plastic', 'cloth', 'paper']\n",
    "\n",
    "# Matrix of materials used.\n",
    "M = np.array([[0, 1.3, 0.2, 0.8, 0.4],\n",
    "              [0, 0, 1.5, 0.4, 0.3],\n",
    "              [0.25, 0, 0, 0.2, 0.7],\n",
    "              [0, 0, 0.3, 0.7, 0.5],\n",
    "              [0.15, 0, 0.5, 0.4, 0.8]])\n",
    "\n",
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "product_materials = []\n",
    "\n",
    "print('Product   Metal     Wood  Plastic    Cloth    Paper')\n",
    "print('---------------------------------------------------')\n",
    "\n",
    "for i in range(len(p)):\n",
    "    product_materials.append(M[i])\n",
    "    print(f'{p[i]}     ', end='')\n",
    "    \n",
    "    for j in range(len(m)):\n",
    "        print(f'{product_materials[i][j]:9.2f}', end='')\n",
    "\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vector b of total amounts.\n",
    "b = np.array([51.0, 312.0, 215.4, 373.1, 356.0])\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('    Metal     Wood  Plastic    Cloth    Paper')\n",
    "print('---------------------------------------------')\n",
    "\n",
    "for i in range(len(b)):\n",
    "    print(f'{b[i]:9.1f}', end='')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Transpose the materials matrix.\n",
    "A = M.T\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vector n of numbers of products made.\n",
    "n = solve(A, b)\n",
    "n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Product  Number')\n",
    "print('-------  ------')\n",
    "\n",
    "for i in range(len(p)):\n",
    "     print(f'{p[i]}        {n[i]:6.2f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verification: Should equal b.\n",
    "A@n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr>\n",
    "\n",
    "#### <strong>PROBLEM 2.</strong> Find the least-squares regression line for the points (1,1), (2,2), (3,4), (4,4), and (5,6) using the matrix form of the normal equations <em>A.T</em>@<em>A</em>@<strong>x</strong> = <em>A.T</em>@<strong>b</strong>.\n",
    "\n",
    "#### <strong>SOLUTION</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 1],\n",
    "              [1, 2],\n",
    "              [1, 3],\n",
    "              [1, 4],\n",
    "              [1, 5]])\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([1, 2, 4, 4, 6])\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "AT = A.T\n",
    "AT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATA = AT@A\n",
    "ATA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%precision 3\n",
    "\n",
    "ATAinv = inv(ATA)\n",
    "ATAinv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATb = AT@b\n",
    "ATb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Coefficients of the least-squares regression line:\")\n",
    "\n",
    "xhat = ATAinv@ATb\n",
    "xhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test the least-squares regression line: Should approximate b.\n",
    "# y = a0 + a1*x\n",
    "A@xhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr>\n",
    "\n",
    "#### <strong>PROBLEM 3.</strong> The following table shows the mean distances <em>x</em> in astonomical units (multiples of the distance between the sun and the earth) and the periods <em>y</em> in years (how many earth-years to orbit the sun):\n",
    "<table>\n",
    "    <tr>\n",
    "        <th>Planet</th>\n",
    "        <th>Mercury</th>\n",
    "        <th>Venus</th>\n",
    "        <th>Earth</th>\n",
    "        <th>Mars</th>\n",
    "        <th>Jupiter</th>\n",
    "        <th>Saturn</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Distance </em>x</em></td><td>0.387</td><td>0.723</td><td>1.000</td><td>1.524</td><td>5.203</td><td>9.537</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Years </em>y</em></td><td>0.241</td><td>0.615</td><td>1.000</td><td>1.881</td><td>11.862</td><td>29.457</td>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "#### It turns out that if you take the <strong>natural logarithm</strong> of the numbers in the table, the transformed points lie roughly in a straight line. Find the least-squares regression line using the matrix form of the normal equations <em>A.T</em>@<em>A</em>@<strong>x</strong> = <em>A.T</em>@<strong>b</strong>. \n",
    "\n",
    "#### <strong>SOLUTION</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Matrix of planetary data.\n",
    "P = np.array([[0.387, 0.723, 1.000, 1.524,  5.203,  9.537],\n",
    "              [0.241, 0.615, 1.000, 1.881, 11.862, 29.457]])\n",
    "P"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Matrix of natural logs of planetary data.\n",
    "L = np.log(P)\n",
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize matrix A using the first row of matrix L.\n",
    "A = L[0].reshape(len(L[0]), 1)\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Insert the column of ones.\n",
    "A = np.insert(A, 0, 1, axis=1)\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vector b is the second row of matrix L.\n",
    "b = L[1]\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "AT = A.T\n",
    "AT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATA = AT@A\n",
    "ATA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATAinv = inv(ATA)\n",
    "ATAinv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATb = AT@b\n",
    "ATb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Coefficients of the least-squares regression line:\")\n",
    "\n",
    "xhat = ATAinv@ATb\n",
    "xhat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Therefore, ln <em>y</em> = 0 + (3/2)ln <em>x</em>, and <em>y</em> = <em>x</em><sup>3/2</sup>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr>\n",
    "\n",
    "#### <strong>PROBLEM 4.a.</strong> Here's more data about that certain day at Amalgamated Widgets, Inc. There are three more products and the cost  to make one of each product.\n",
    "<table>\n",
    "    <tr>\n",
    "        <th>Product</th>\n",
    "        <th>Metal</th>\n",
    "        <th>Wood</th>\n",
    "        <th>Plastic</th>\n",
    "        <th>Cloth</th>\n",
    "        <th>Paper</th>\n",
    "        <th>Cost</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>A</td><td>0</td><td>1.3</td><td>0.2</td><td>0.8</td><td>0.4</td><td>21.60</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>B</td><td>0</td><td>0</td><td>1.5</td><td>0.4</td><td>0.3</td><td>17.20</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>C</td><td>0.25</td><td>0</td><td>0</td><td>0.2</td><td>0.7</td><td>4.70</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>D</td><td>0</td><td>0</td><td>0.3</td><td>0.7</td><td>0.5</td><td>9.60</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>E</td><td>0.15</td><td>0</td><td>0.5</td><td>0.4</td><td>0.8</td><td>15.70</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>F</td><td>1.00</td><td>0.90</td><td>0.00</td><td>0.65</td><td>0.00</td><td>26.80</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>G</td><td>0.22</td><td>0.00</td><td>1.80</td><td>1.00</td><td>1.25</td><td>25.50</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>H</td><td>0.20</td><td>0.75</td><td>0.65</td><td>1.00</td><td>1.25</td><td>22.40</td>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "#### The manufacturing cost of a product is related to the amounts of materials used to make the product. Find the least-squares regression line using the matrix form of the normal equations <em>A.T</em>@<em>A</em>@<strong>x</strong> = <em>A.T</em>@<strong>b</strong> that will compute an estimated manufacturing cost of a product.\n",
    "\n",
    "#### <strong>SOLUTION</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']\n",
    "m = ['metal', 'wood', 'plastic', 'cloth', 'paper']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Matrix of materials used.\n",
    "M = np.array([[0, 1.3, 0.2, 0.8, 0.4],\n",
    "              [0, 0, 1.5, 0.4, 0.3],\n",
    "              [0.25, 0, 0, 0.2, 0.7],\n",
    "              [0, 0, 0.3, 0.7, 0.5],\n",
    "              [0.15, 0, 0.5, 0.4, 0.8],\n",
    "              [1.0, 0.9, 0, 0.65, 0],\n",
    "              [0.22, 0, 1.8, 1.0, 1.25],\n",
    "              [0.2, 0.75, 0.65, 1.0, 1.25]])\n",
    "\n",
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "product_materials = []\n",
    "\n",
    "print('Product   Metal     Wood  Plastic    Cloth    Paper')\n",
    "print('---------------------------------------------------')\n",
    "\n",
    "for i in range(len(p)):\n",
    "    product_materials.append(M[i])\n",
    "    print(f'{p[i]}     ', end='')\n",
    "    \n",
    "    for j in range(len(m)):\n",
    "        print(f'{product_materials[i][j]:9.2f}', end='')\n",
    "\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cost vector b.\n",
    "b = np.array([21.60, 17.20,  4.70,  9.60, 15.70, 26.80, 25.50, 22.40])\n",
    "\n",
    "print('Product  Cost')\n",
    "print('--------------')\n",
    "\n",
    "for i in range(len(p)):\n",
    "     print(f'{p[i]}     {b[i]:7.2f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Matrix A is matrix M with an inserted column of ones.\n",
    "A = np.insert(M, 0, 1, axis=1)\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "AT = A.T\n",
    "AT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATA = AT@A\n",
    "ATA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATAinv = inv(ATA)\n",
    "ATAinv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ATb = AT@b\n",
    "ATb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Coefficients of the least-squares regression line:\")\n",
    "\n",
    "xhat = ATAinv@ATb\n",
    "xhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test the least-squares regression line: Should approximate b.\n",
    "A@xhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr>\n",
    "\n",
    "#### <strong>PROBLEM 4.b.</strong> Find the least-squares regression line for the same data using <em>QR</em> factorization. Verify that matrix <em>R</em> is upper-triangular and invertible. Verify that the columns of matrix <em>Q</em> are orthonormal. \n",
    "\n",
    "#### <strong>SOLUTION</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Q,R = qr(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verify R is upper-triangular.\n",
    "R"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verify R is invertible.\n",
    "Rinv = inv(R)\n",
    "Rinv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verify R is invertible: Should be the identify matrix I.\n",
    "Rinv@R"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "QT = Q.T\n",
    "QT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verify Q is orthonormal: The norms of each column of Q \n",
    "#                          (here using the rows of Q.T) should be 1.\n",
    "for r in QT:\n",
    "    print(norm(r))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Verify Q is orthonormal: The dot product of each column of Q \n",
    "#                          (here using the rows of Q.T) \n",
    "#                          with each other column should be 0.\n",
    "for i in range(len(QT) - 1):\n",
    "    for j in range(i + 1, len(QT)):\n",
    "        print(f'columns {i} and {j}: {QT[i]@QT[j]}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Should be the identify matrix I.\n",
    "QT@Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Coefficients of the least-squares regression line:\")\n",
    "\n",
    "xhat = Rinv@QT@b\n",
    "xhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
