{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# MATH 4242 Python Lab 6: Gram--Schmidt and QR factorization\n",
        "\n",
        "**Course sections:** 4.1--4.2\n",
        "\n",
        "This notebook accompanies LEAP Assignment 6. LEAP supplies your\n",
        "parameter values and grades your mathematical responses. Copy those\n",
        "values into the indicated cell below. Run a cell with **Shift+Enter**.\n",
        "\n",
        "The notebook is a computational scratchpad: your graded answers are\n",
        "entered in LEAP unless your instructor says otherwise.\n",
        "\n",
        "**Programming support:** Supported independence. The mathematical goal and useful NumPy tools are supplied; you assemble several lines.\n",
        "\n",
        "A cell marked `TODO` is intentionally unfinished. Read the directions\n",
        "immediately above it before running it. Placeholders such as zero keep\n",
        "the notebook runnable, but their output is not an answer. If you are\n",
        "new to notebooks,\n",
        "complete `00_Getting_Started.ipynb` before this lab.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "np.set_printoptions(precision=6, suppress=True)\n",
        "print(\"NumPy version:\", np.__version__)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 1. Classical Gram--Schmidt\n",
        "\n",
        "Copy `k` from LEAP. Treat the columns of `A` as the vectors to be\n",
        "orthonormalized. Keep the intermediate vector `u2`; it makes the\n",
        "geometry visible.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Replace this example value with your LEAP value.\n",
        "k = 2\n",
        "\n",
        "a1 = np.array([1, 1, 0], dtype=float)\n",
        "a2 = np.array([1, 0, k], dtype=float)\n",
        "A = np.column_stack((a1, a2))\n",
        "\n",
        "# TODO: complete the four Gram--Schmidt lines.\n",
        "q1 = np.zeros(3)  # TODO: normalize a1\n",
        "r12 = 0           # TODO: compute q1 @ a2\n",
        "u2 = np.zeros(3)  # TODO: subtract the q1 projection from a2\n",
        "q2 = np.zeros(3)  # TODO: normalize u2\n",
        "\n",
        "print(\"q1 =\", q1)\n",
        "print(\"r12 =\", r12)\n",
        "print(\"u2 =\", u2)\n",
        "print(\"q2 =\", q2)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 2. Assemble and verify a QR factorization\n",
        "\n",
        "The columns of `Q` should be orthonormal and `Q @ R` should recover\n",
        "`A`. These are stronger checks than merely printing `Q` and `R`.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# TODO: assemble Q and compute R from Q^T A.\n",
        "Q = np.zeros((3, 2))  # TODO: column-stack q1 and q2\n",
        "R = np.zeros((2, 2))  # TODO: compute Q.T @ A\n",
        "\n",
        "print(\"Q^T Q =\\n\", Q.T @ Q)\n",
        "print(\"R =\\n\", R)\n",
        "print(\"factorization error:\", np.linalg.norm(A - Q @ R))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 3. Compare with NumPy's implementation\n",
        "\n",
        "QR factorizations are not unique: signs of corresponding columns and\n",
        "rows may change. Compare reconstruction and orthogonality rather than\n",
        "requiring every displayed entry to have the same sign.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "Q_np, R_np = np.linalg.qr(A)\n",
        "print(\"NumPy Q =\\n\", Q_np)\n",
        "print(\"NumPy R =\\n\", R_np)\n",
        "print(\"NumPy reconstruction error:\", np.linalg.norm(A - Q_np @ R_np))\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3",
      "mimetype": "text/x-python",
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "pygments_lexer": "ipython3",
      "nbconvert_exporter": "python",
      "file_extension": ".py"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}
