{ "cells": [ { "cell_type": "markdown", "id": "md-000-fe4eade2", "metadata": {}, "source": [ "# Lesson 10 - From Balance Laws to Linear Systems\n", "\n", "> **Learning goals.** By the end of this lecture, students should be able to:\n", ">\n", "> - translate a small steady balance model into simultaneous linear equations,\n", "> - identify the physical meaning of the unknown vector, coefficient matrix, and right-hand side,\n", "> - assemble a matrix equation of the form $\\mathbf{A}\\mathbf{x}=\\mathbf{b}$,\n", "> - use a black-box numerical solve and check the residual,\n", "> - interpret an inverse conceptually as a source-to-solution response matrix,\n", "> - explain why a coupled system must be solved as a system rather than one row at a time.\n", ">\n", "> **Key terms.** balance law, unknown vector, coefficient matrix, right-hand side, residual.\n", "\n", "## Why linear systems appear in engineering models\n", "\n", "Many engineering calculations begin with a balance. Over a control volume, cell, energy group, or state, the balance has the schematic form\n", "\n", "$$\n", "\\text{in} - \\text{out} + \\text{production} = \\text{accumulation or requirement}.\n", "$$\n", "\n", "If the model is steady, the accumulation term is zero or prescribed. If the rates are proportional to the quantities being modeled, the result is a linear equation.\n", "\n", "One balance is useful. Several balances coupled together are more useful. If region 1 exchanges material, energy, or particles with region 2, the unknown $x_1$ in region 1 appears in the balance for region 2, and the unknown in region 2 $x_2$ appears in the balance for region 1. Systems for which this coupling is linear are the focus of linear algebra, the language of which includes *vectors* and *matrices*.\n", "\n", "The basic object of this chapter is therefore\n", "\n", "$$\n", "\\mathbf{A}\\mathbf{x}=\\mathbf{b}.\n", "$$\n", "\n", "The vector $\\mathbf{x}$ contains all the unknown quantities. Each row of $\\mathbf{A}$ represents one balance equation. The right-hand side vector $\\mathbf{b}$ contains sources, requirements, boundary data, or other known forcing terms.\n", "\n", "## A fixed-step walk with absorption\n", "\n", "To make the idea concrete, consider a one-dimensional line of four cells. A source injects particles into the first cell. During each step, a fraction $c$ of the population survives and scatters to neighboring cells. The remaining fraction $1-c$ is absorbed or lost. At the ends of the domain, particles that step out of the system leak away.\n", "\n", "Let\n", "\n", "$$\n", "x_i = \\text{expected steady population in cell } i,\n", " \\qquad i=1,2,3,4.\n", "$$\n", "\n", "Let the source be\n", "\n", "$$\n", "\\mathbf{s}=\\begin{bmatrix}1\\\\0\\\\0\\\\0\\end{bmatrix}.\n", "$$\n", "\n", "For this system, the source vector is the right-hand side, so later we will write $\\mathbf{b}=\\mathbf{s}$. In this toy model the entries are source-normalized particle counts: $\\mathbf{s}$ represents one injected source particle, $x_i$ is the expected number of visits or population units per source particle, and $c$ is dimensionless.\n", "\n", "The first cell receives the external source and particles scattered from cell 2. Since only half of the surviving particles in cell 2 move left, the balance is\n", "\n", "$$\n", "x_1 = 1 + \\frac{c}{2}x_2.\n", "$$\n", "\n", "The second cell receives particles scattered from cells 1 and 3:\n", "\n", "$$\n", "x_2 = \\frac{c}{2}x_1 + \\frac{c}{2}x_3.\n", "$$\n", "\n", "Likewise,\n", "\n", "$$\n", "x_3 = \\frac{c}{2}x_2 + \\frac{c}{2}x_4,\n", "$$\n", "\n", "$$\n", "x_4 = \\frac{c}{2}x_3.\n", "$$\n", "\n", "These four equations are coupled. For example, $x_2$ depends on $x_1$ and $x_3$, but $x_1$ and $x_3$ also depend on $x_2$. Guessing one unknown at a time is not the natural approach; solving all four equations together is.\n", "\n", "## A boundary-value variant\n", "\n", "The same algebraic balance idea also appears with dimensionless probabilities rather than dimensional populations. Suppose a particle moves on the integer sites $0,1,\\ldots,N$. Let\n", "\n", "$$\n", "u_i = \\text{probability of reaching } N\n", " \\text{ before either leaking left or being absorbed}\n", " \\quad\\text{from site } i.\n", "$$\n", "\n", "The $u_i$ are dimensionless probabilities or source-normalized responses.\n", "\n", "The boundary values are known:\n", "\n", "$$\n", "u_0=0,\\qquad u_N=1.\n", "$$\n", "\n", "If an interior collision scatters left or right with equal probability and the scattering ratio is $c$, then the interior balance is\n", "\n", "$$\n", "u_i=\\frac{c}{2}u_{i-1}+\\frac{c}{2}u_{i+1},\n", " \\qquad i=1,2,\\ldots,N-1.\n", "$$\n", "\n", "Moving unknowns to the left gives\n", "\n", "$$\n", "-\\frac{c}{2}u_{i-1}+u_i-\\frac{c}{2}u_{i+1}=0.\n", "$$\n", "\n", "For interior nodes away from the boundary, this produces the same tridiagonal pattern seen below: a diagonal coefficient and two nearest-neighbor coefficients. At the right boundary, however, the known value $u_N=1$ is moved to the right-hand side:\n", "\n", "$$\n", "-\\frac{c}{2}u_{N-2}+u_{N-1}\n", " =\\frac{c}{2}u_N\n", " =\\frac{c}{2}.\n", "$$\n", "\n", "Thus boundary data can appear in $\\mathbf{b}$ even when the original interior balance has no external source term.\n", "\n", "> **Takeaway.**\n", ">\n", "> Boundary conditions are known values. When a known boundary value appears in an equation for an unknown interior value, move that known contribution to the right-hand side.\n", "\n", "> **Worked example: boundary data in the right-hand side.**\n", ">\n", "> **Problem.** Take $N=4$, so the unknown responses are $u_1,u_2,u_3$, with\n", ">\n", "> $$\n", "> u_0=0,\\qquad u_4=1.\n", "> $$\n", ">\n", "> Use $c=0.8$. Assemble the matrix equation and identify where the boundary data enters the right-hand side.\n", ">\n", "> **Solution.** Since $c/2=0.4$, the interior equations are\n", ">\n", "> $$\n", "> \\begin{alignedat}{3}\n", "> u_1 &= 0.4u_0+0.4u_2,\n", "> &\\qquad&\n", "> u_1-0.4u_2 &= 0,\\\\\n", "> u_2 &= 0.4u_1+0.4u_3,\n", "> &\\qquad&\n", "> -0.4u_1+u_2-0.4u_3 &= 0,\\\\\n", "> u_3 &= 0.4u_2+0.4u_4,\n", "> &\\qquad&\n", "> -0.4u_2+u_3 &= 0.4.\n", "> \\end{alignedat}\n", "> $$\n", ">\n", "> The right boundary value $u_4=1$ is known, so its contribution becomes the nonzero entry in the right-hand side:\n", ">\n", "> $$\n", "> \\underbrace{\\begin{bmatrix}\n", "> 1 & -0.4 & 0\\\\\n", "> -0.4 & 1 & -0.4\\\\\n", "> 0 & -0.4 & 1\n", "> \\end{bmatrix}}_{\\mathbf{A}}\n", "> \\underbrace{\\begin{bmatrix}u_1\\\\u_2\\\\u_3\\end{bmatrix}}_{\\mathbf{u}}\n", "> =\n", "> \\underbrace{\\begin{bmatrix}0\\\\0\\\\0.4\\end{bmatrix}}_{\\mathbf{b}}.\n", "> $$\n", ">\n", "> Solving gives\n", ">\n", "> $$\n", "> \\mathbf{u}\\approx\n", "> \\begin{bmatrix}\n", "> 0.0941\\\\\n", "> 0.2353\\\\\n", "> 0.4941\n", "> \\end{bmatrix}.\n", "> $$\n", ">\n", "> The response increases as the starting site moves toward the right boundary. The values are below the pure random-walk probabilities $1/4,1/2,3/4$ because $c<1$ leaves room for absorption or loss before either boundary is reached.\n", ">\n", "> The units also check out. The matrix entries $1$ and $-0.4$ are dimensionless probabilities or survival fractions, the boundary responses $u_0$ and $u_4$ are dimensionless, and every entry of $\\mathbf{b}$ has the same dimensionless response units as $\\mathbf{u}$.\n", "\n", "## Putting the balances into matrix form\n", "\n", "Move all unknown terms to the left-hand side. Then rewrite each equation so that every unknown appears in the same order, even when its coefficient is zero:\n", "\n", "$$\n", "\\begin{alignedat}{3}\n", "x_1 - \\frac{c}{2}x_2\n", " &{}= 1\n", " &\\quad\\Longrightarrow\\quad&\n", " 1x_1 {\\color{#512888}{- \\frac{c}{2}x_2}}\n", " + {\\color{#D55E00}{0x_3}} + 0x_4\n", " &{}= 1, \\\\\n", " -\\frac{c}{2}x_1 + x_2 - \\frac{c}{2}x_3\n", " &{}= 0\n", " &\\quad\\Longrightarrow\\quad&\n", " -\\frac{c}{2}x_1 + {\\color{#512888}{1x_2}}\n", " {\\color{#D55E00}{- \\frac{c}{2}x_3}} + 0x_4\n", " &{}= 0, \\\\\n", " -\\frac{c}{2}x_2 + x_3 - \\frac{c}{2}x_4\n", " &{}= 0\n", " &\\quad\\Longrightarrow\\quad&\n", " 0x_1 {\\color{#512888}{- \\frac{c}{2}x_2}}\n", " + {\\color{#D55E00}{1x_3}} - \\frac{c}{2}x_4\n", " &{}= 0, \\\\\n", " -\\frac{c}{2}x_3 + x_4\n", " &{}= 0\n", " &\\quad\\Longrightarrow\\quad&\n", " 0x_1 + {\\color{#512888}{0x_2}}\n", " {\\color{#D55E00}{- \\frac{c}{2}x_3}} + 1x_4\n", " &{}= 0.\n", "\\end{alignedat}\n", "$$\n", "\n", "Now the coefficient matrix is visible:\n", "\n", "$$\n", "\\underbrace{\\begin{bmatrix}\n", "1 & {\\color{#512888}{-c/2}} & {\\color{#D55E00}{0}} & 0 \\\\\n", "-c/2 & {\\color{#512888}{1}} & {\\color{#D55E00}{-c/2}} & 0 \\\\\n", "0 & {\\color{#512888}{-c/2}} & {\\color{#D55E00}{1}} & -c/2 \\\\\n", "0 & {\\color{#512888}{0}} & {\\color{#D55E00}{-c/2}} & 1\n", "\\end{bmatrix}}_{\\mathbf{A}}\n", "\\underbrace{\\begin{bmatrix}\n", "x_1\\\\\n", "{\\color{#512888}{x_2}}\\\\\n", "{\\color{#D55E00}{x_3}}\\\\\n", "x_4\n", "\\end{bmatrix}}_{\\mathbf{x}}\n", "=\n", "\\underbrace{\\begin{bmatrix}1\\\\0\\\\0\\\\0\\end{bmatrix}}_{\\mathbf{b}}.\n", "$$\n", "\n", "This matrix has a clear physical interpretation. The diagonal entries multiply the population being balanced in each cell. The off-diagonal entries describe coupling between neighboring cells. The zeros say that non-neighboring cells do not exchange particles directly in this model. In this source-normalized example, $\\mathbf{A}$ is dimensionless and $\\mathbf{x}$, $\\mathbf{b}$, and the residual $\\mathbf{r}=\\mathbf{b}-\\mathbf{A}\\mathbf{x}$ all use the same population-per-source-particle units. In a dimensional reactor balance matrix, entries may instead contain terms such as $V_i\\Sigma_{a,i}$, leakage coefficients, or scattering/removal rates with units chosen so each row matches $\\mathbf{b}$.\n", "\n", "If $c=0.8$, then\n", "\n", "$$\n", "\\mathbf{A}=\\begin{bmatrix}\n", "1 & -0.4 & 0 & 0 \\\\\n", "-0.4 & 1 & -0.4 & 0 \\\\\n", "0 & -0.4 & 1 & -0.4 \\\\\n", "0 & 0 & -0.4 & 1\n", "\\end{bmatrix}.\n", "$$\n", "\n", "## Solving first, opening the box later\n", "\n", "For now, we use `np.linalg.solve` as a \"black box\" tool - we give it an input, it gives us an output, and we ignore the details. Later chapters explain the operations and factorizations behind this call.\n", "\n", "With $c=0.8$, the example above can be defined and solved via\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "code-001-5db8e567", "metadata": { "execution": { "iopub.execute_input": "2026-06-17T02:17:43.235001Z", "iopub.status.busy": "2026-06-17T02:17:43.234914Z", "iopub.status.idle": "2026-06-17T02:17:43.372415Z", "shell.execute_reply": "2026-06-17T02:17:43.371989Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.24633431 0.61583578 0.29325513 0.11730205]\n", "0.0\n" ] } ], "source": [ "import numpy as np\n", "\n", "c = 0.8\n", "A = np.array([[1.0, -c/2, 0.0, 0.0],\n", " [-c/2, 1.0, -c/2, 0.0],\n", " [0.0, -c/2, 1.0, -c/2],\n", " [0.0, 0.0, -c/2, 1.0]])\n", "b = np.array([1.0, 0.0, 0.0, 0.0])\n", "\n", "x = np.linalg.solve(A, b)\n", "r = b - A @ x\n", "print(x)\n", "print(np.linalg.norm(r))\n" ] }, { "cell_type": "markdown", "id": "md-002-842c6495", "metadata": {}, "source": [ "\n", "\n", "The computed solution is approximately\n", "\n", "$$\n", "\\mathbf{x}\\approx\n", " \\begin{bmatrix}\n", " 1.2463\\\\\n", " 0.6158\\\\\n", " 0.2933\\\\\n", " 0.1173\n", " \\end{bmatrix}.\n", "$$\n", "\n", "The values decrease as we move away from the source, which matches the physical picture. The source enters cell 1 directly. Particles reach cells 2, 3, and 4 only after one or more scattering events, and absorption reduces the expected population along the way.\n", "\n", "## Residuals as a first quality check\n", "\n", "The computed $\\mathbf{x}$ is only useful if it nearly satisfies the original equations. The residual is\n", "\n", "$$\n", "\\mathbf{r}=\\mathbf{b}-\\mathbf{A}\\mathbf{x}.\n", "$$\n", "\n", "If $\\mathbf{r}=\\mathbf{0}$, the equations are satisfied exactly. In floating-point arithmetic, we usually ask whether $\\mathbf{r}$ is small. Each component of $\\mathbf{r}$ is a defect in the balance equations. The residual has the same units as $\\mathbf{b}$. In this random-walk example it is source-normalized; in a dimensional source balance it would have source or rate units.\n", "\n", "For the random-walk example, the first residual component is\n", "\n", "$$\n", "r_1 = 1 - \\left(x_1-\\frac{c}{2}x_2\\right).\n", "$$\n", "\n", "Thus $r_1$ directly checks the first cell balance. The other components check the other cells. This is the first important diagnostic for numerical linear algebra: after computing a candidate solution, put it back into the model.\n", "\n", "> **Takeaway.**\n", ">\n", "> The residual $\\mathbf{r}=\\mathbf{b}-\\mathbf{A}\\mathbf{x}$ measures how much the computed solution fails to satisfy the original equations. Its components are defects in the balance equations.\n", "\n", "## A second view: source-to-solution response\n", "\n", "Now we can introduce the inverse idea with minimal extra machinery. Keep $\\mathbf{A}$ fixed. The solver takes a source pattern $\\mathbf{b}$ and returns the corresponding solution $\\mathbf{x}$:\n", "\n", "$$\n", "\\mathbf{b}\n", "\\quad\\longmapsto\\quad\n", "\\mathbf{x}.\n", "$$\n", "\n", "For this lecture, call that mapping the *response map*.\n", "\n", "Returning to the source-normalized population model, the easiest way to see the response map is to use unit source patterns. Define\n", "\n", "$$\n", "\\mathbf{e}_1=\\begin{bmatrix}1\\\\0\\\\0\\\\0\\end{bmatrix},\\quad\n", "\\mathbf{e}_2=\\begin{bmatrix}0\\\\1\\\\0\\\\0\\end{bmatrix},\\quad\n", "\\mathbf{e}_3=\\begin{bmatrix}0\\\\0\\\\1\\\\0\\end{bmatrix},\\quad\n", "\\mathbf{e}_4=\\begin{bmatrix}0\\\\0\\\\0\\\\1\\end{bmatrix}.\n", "$$\n", "\n", "Let $\\mathbf{m}_j$ be the solution caused by the unit source $\\mathbf{e}_j$:\n", "\n", "$$\n", "\\mathbf{A}\\mathbf{m}_j=\\mathbf{e}_j,\n", "\\qquad j=1,2,3,4.\n", "$$\n", "\n", "Thus $\\mathbf{m}_1$ is the response to a unit source in cell 1, $\\mathbf{m}_2$ is the response to a unit source in cell 2, and so on.\n", "\n", "For $c=0.8$, these four response vectors are approximately the columns of\n", "\n", "$$\n", "\\mathbf{M}\\approx\n", "\\begin{bmatrix}\n", "1.2463 & 0.6158 & 0.2933 & 0.1173 \\\\\n", "0.6158 & 1.5396 & 0.7331 & 0.2933 \\\\\n", "0.2933 & 0.7331 & 1.5396 & 0.6158 \\\\\n", "0.1173 & 0.2933 & 0.6158 & 1.2463\n", "\\end{bmatrix}.\n", "$$\n", "\n", "The first column is exactly the solution we computed for the original source $\\mathbf{b}=\\mathbf{e}_1$.\n", "\n", "Why does this help with a general source? Because the equations are linear. A source vector such as\n", "\n", "$$\n", "\\mathbf{b}=b_1\\mathbf{e}_1+b_2\\mathbf{e}_2+b_3\\mathbf{e}_3+b_4\\mathbf{e}_4\n", "$$\n", "\n", "can be built from unit sources. The corresponding solution is the same combination of unit-source responses:\n", "\n", "$$\n", "\\mathbf{x}\n", "=b_1\\mathbf{m}_1+b_2\\mathbf{m}_2+b_3\\mathbf{m}_3+b_4\\mathbf{m}_4.\n", "$$\n", "\n", "The compact notation for this weighted combination is\n", "\n", "$$\n", "\\mathbf{x}=\\mathbf{M}\\mathbf{b}.\n", "$$\n", "\n", "The coefficient matrix now has a physical role. Given a candidate state $\\mathbf{x}$, the product $\\mathbf{A}\\mathbf{x}$ evaluates all of the balances and tells us what source or requirement vector would be needed to support that state:\n", "\n", "$$\n", "\\mathbf{A}\\mathbf{x}=\\mathbf{b}.\n", "$$\n", "\n", "But the usual engineering question runs the other way. We are given the source, forcing, or boundary data $\\mathbf{b}$, and we want the state $\\mathbf{x}$ that the system produces. We can represent that opposite direction by a response map:\n", "\n", "$$\n", "\\mathbf{x}=\\mathbf{M}\\mathbf{b}.\n", "$$\n", "\n", "In words,\n", "\n", "$$\n", "\\begin{array}{ccc}\n", "\\text{balance operator} & & \\text{response map} \\\\\n", "\\mathbf{A}:\\ \\mathbf{x}\\mapsto\\mathbf{b} & \\qquad &\n", "\\mathbf{M}:\\ \\mathbf{b}\\mapsto\\mathbf{x}.\n", "\\end{array}\n", "$$\n", "\n", "When a square system has one solution for every right-hand side, this response map is the inverse of the balance operator:\n", "\n", "$$\n", "\\mathbf{M}=\\mathbf{A}^{-1}.\n", "$$\n", "\n", "The inverse is therefore best understood first as a map from inputs to responses. The units of a response-map entry are the units of solution divided by the units of source; in this normalized example the entries are dimensionless. It is useful notation, but it is usually not the object we form in a computation. In practice, we solve $\\mathbf{A}\\mathbf{x}=\\mathbf{b}$ directly and check the residual $\\mathbf{b}-\\mathbf{A}\\mathbf{x}$.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "code-003-672c4fd9", "metadata": { "execution": { "iopub.execute_input": "2026-06-17T02:17:43.381017Z", "iopub.status.busy": "2026-06-17T02:17:43.380761Z", "iopub.status.idle": "2026-06-17T02:17:43.384239Z", "shell.execute_reply": "2026-06-17T02:17:43.383634Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1.24633431 0.61583578 0.29325513 0.11730205]\n", " [0.61583578 1.53958944 0.73313783 0.29325513]\n", " [0.29325513 0.73313783 1.53958944 0.61583578]\n", " [0.11730205 0.29325513 0.61583578 1.24633431]]\n", "[1.24633431 0.61583578 0.29325513 0.11730205]\n" ] } ], "source": [ "responses = []\n", "for j in range(4):\n", " e = np.zeros(4)\n", " e[j] = 1.0\n", " responses.append(np.linalg.solve(A, e))\n", "\n", "M = np.column_stack(responses)\n", "print(M)\n", "\n", "# Original b = e_1, so its solution is column 0.\n", "print(M[:, 0])\n" ] }, { "cell_type": "markdown", "id": "md-004-5416a149", "metadata": {}, "source": [ "\n", "\n", "> **Takeaway.**\n", ">\n", "> A good first reading is: $\\mathbf{A}$ maps a candidate solution to the source pattern required by the balances, while $\\mathbf{M}$ maps a source pattern to the solution. The inverse is the response map, not the recommended way to compute the solution.\n", "\n", "## Exercises\n", "\n", "1. For the four-cell fixed-step walk with $c=0.8$, write the matrix $\\mathbf{A}$ for the source-normalized population model.\n", "\n", "2. In the boundary-value variant, let $u_0=0$, $u_4=1$, and $c=0.8$. Explain why the right boundary contributes $0.4$ to the third entry of $\\mathbf{b}$.\n", "\n", "3. For\n", "\n", " $$\n", " \\mathbf{A}=\\begin{bmatrix}\n", " 1 & -0.4 & 0\\\\\n", " -0.4 & 1 & -0.4\\\\\n", " 0 & -0.4 & 1\n", " \\end{bmatrix},\n", " \\qquad\n", " \\mathbf{x}=\\begin{bmatrix}1\\\\1\\\\1\\end{bmatrix},\n", " \\qquad\n", " \\mathbf{b}=\\begin{bmatrix}0.6\\\\0.2\\\\0.6\\end{bmatrix},\n", " $$\n", "\n", " compute the residual $\\mathbf{r}=\\mathbf{b}-\\mathbf{A}\\mathbf{x}$.\n", "\n", "4. If $\\mathbf{M}=\\mathbf{A}^{-1}$, what does column 2 of $\\mathbf{M}$ represent in a source-response interpretation?\n", "\n", "**Answers.**\n", "\n", "1. $\\mathbf{A}$ has $1$ on the diagonal and $-0.4$ on the neighboring off-diagonals:\n", "\n", " $$\n", " \\begin{bmatrix}\n", " 1&-0.4&0&0\\\\\n", " -0.4&1&-0.4&0\\\\\n", " 0&-0.4&1&-0.4\\\\\n", " 0&0&-0.4&1\n", " \\end{bmatrix}.\n", " $$\n", "\n", "2. The right boundary term enters the balance for cell 3 as $(c/2)u_4=(0.8/2)(1)=0.4$. It is known boundary data, so it moves to the right-hand side.\n", "\n", "3. $\\mathbf{A}\\mathbf{x}=[0.6,0.2,0.6]^{\\mathsf{T}}$, so $\\mathbf{r}=\\mathbf{0}$.\n", "\n", "4. Column 2 is the solution produced by a unit source in entry 2, with all other source entries zero. It is a response column, not a probability column.\n", "\n", "## End-of-lecture summary\n", "\n", "> **Takeaway.**\n", ">\n", ">\n", "> - Steady linear balance laws and boundary data lead naturally to systems of equations.\n", "> - The unknown vector stores the quantities being solved for, one per cell, region, group, or state.\n", "> - Each row of the matrix represents one balance equation.\n", "> - `np.linalg.solve` gives a practical first solve, but the residual $\\mathbf{b}-\\mathbf{A}\\mathbf{x}$ should always be checked as a defect in the balance equations.\n", "> - The inverse can be read conceptually as a response matrix whose columns are unit-source solutions.\n", "> - Lesson 11 opens the black box by explaining the dot products and matrix-vector products behind $\\mathbf{A}\\mathbf{x}$.\n" ] } ], "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.13.13" } }, "nbformat": 4, "nbformat_minor": 5 }