{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# MATH 4242 Python Lab 1: Vectors, matrices, and the @ operator\n",
        "\n",
        "**Course sections:** 1.1--1.3\n",
        "\n",
        "This notebook accompanies LEAP Assignment 1. 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:** Highly guided. Read each worked line, run it, and change only the values or expressions specifically marked.\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": [
        "## 0. Watch one complete example\n",
        "\n",
        "This first cell is an **I do** example: nothing is missing. Before\n",
        "running it, predict the number of entries in the output. Then run it\n",
        "and connect each displayed number to a row-by-column dot product.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "example_matrix = np.array([[1, 2],\n",
        "                           [3, 4]], dtype=float)\n",
        "example_vector = np.array([5, -1], dtype=float)\n",
        "example_product = example_matrix @ example_vector\n",
        "\n",
        "print(\"matrix @ vector =\", example_product)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 1. Build the arrays\n",
        "\n",
        "Copy your values of `a` and `b` from LEAP. A NumPy vector is a\n",
        "one-dimensional array; a matrix is a two-dimensional array. This is\n",
        "**we do** practice: replace only the two numbers marked below, then\n",
        "run the cell.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Replace 3 and 2 with your own LEAP values.\n",
        "a = 3\n",
        "b = 2\n",
        "\n",
        "A = np.array([[a, 1],\n",
        "              [-1, b]], dtype=float)\n",
        "x = np.array([2, -1], dtype=float)\n",
        "y = np.array([1, 3], dtype=float)\n",
        "\n",
        "print(\"A =\\n\", A)\n",
        "print(\"shape of A:\", A.shape)\n",
        "print(\"shape of x:\", x.shape)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 2. Matrix multiplication versus elementwise multiplication\n",
        "\n",
        "In NumPy, `A @ x` is the linear-algebra product. The expression\n",
        "`A * x` multiplies entries using broadcasting and means something\n",
        "different. The first product is supplied as a model. Complete the\n",
        "second line by imitating its structure.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Worked line: read this as \"A times x.\"\n",
        "Ax = A @ x\n",
        "\n",
        "# TODO: replace the 0 with A @ (x + y).\n",
        "A_combo = 0\n",
        "\n",
        "print(\"A @ x =\", Ax)\n",
        "print(\"A @ (x+y) =\", A_combo)\n",
        "\n",
        "# Compare with elementwise multiplication.\n",
        "print(\"A * x =\\n\", A * x)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 3. Check linearity computationally\n",
        "\n",
        "Two expressions that are mathematically equal can differ by tiny\n",
        "floating-point rounding errors. `np.allclose` is therefore usually\n",
        "preferable to `==` when comparing computed arrays.\n",
        "\n",
        "This is your first **you do** line. The hint gives every piece; you\n",
        "decide how to combine them.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# TODO: replace the 0. Hint: use A @ x, A @ y, and +.\n",
        "right_side = 0\n",
        "print(\"left side: \", A @ (x + y))\n",
        "print(\"right side:\", right_side)\n",
        "print(\"linearity check:\", np.allclose(A @ (x + y), right_side))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Reflection.** Explain in LEAP why `A * x` is not a substitute for\n",
        "the matrix-vector product, even when NumPy permits the calculation.\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
}
