{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "376c464d-d41f-41b3-ac35-5ff8ce677541",
   "metadata": {},
   "source": [
    "# Using Sage for Computations in Linear Algebra"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4674e045-c456-43f9-8be4-94aa1713f1eb",
   "metadata": {},
   "source": [
    "[Sage](http://sagemath.org) is a more generic math package, made to replace Mathematica, Maple, MatLab, etc.  It is built on top of [Python](http://python.org).\n",
    "\n",
    "You can use it online with [Cocalc](http://cocalc.com).  (You can use a free account.)\n",
    "\n",
    "For simple computations, you can use the [Sage Cell Server](https://sagecell.sagemath.org/).\n",
    "\n",
    "**Notebook:** If you have how to run Jupyter Notebooks with Sage, you can download the notebook [here](https://web.math.utk.edu/~finotti/s24/m559/files/CompSage.ipynb)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81f93753-eec7-45c7-b3e9-77ae68ba3007",
   "metadata": {},
   "source": [
    "## Matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2a99e9d-8c7d-4410-b023-d56806f07934",
   "metadata": {},
   "source": [
    "Let's create the matrix\n",
    "$$\n",
    "A = \\begin{bmatrix}\n",
    "  2 & 8 & 4 \\\\\n",
    "  2 & 5 & 1 \\\\\n",
    "  4 & 10 & -1\n",
    "\\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a8220df5-2b13-4a9f-88d2-31d6ecb7e405",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4]\n",
       "[ 2  5  1]\n",
       "[ 4 10 -1]"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix([[2, 8, 4], [2, 5, 1], [4, 10, -1]])  # enter a list of rows (each row also a list)\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "daa88889-aa84-47ad-acda-794251d3bb19",
   "metadata": {},
   "source": [
    "We can also do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "061dd03e-3fb9-41c5-9ddb-0f530fc29736",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4]\n",
       "[ 2  5  1]\n",
       "[ 4 10 -1]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(3, 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])  # enter the dimensions and list\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8d9f859-0533-4c6f-9700-8deefd0bcdcd",
   "metadata": {},
   "source": [
    "Or even"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d7ffc4eb-fb3b-4182-9625-35173ba07879",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4]\n",
       "[ 2  5  1]\n",
       "[ 4 10 -1]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(3, [2, 8, 4, 2, 5, 1, 4, 10, -1])  # for square matrices we can give only one dimension\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2fecbac9-ce86-4113-b42f-3b4eae82f4d8",
   "metadata": {},
   "source": [
    "We can also specify where the coefficients lie.  For instance, to have the same matrix over $\\mathbb{F}_5 = \\mathbb{Z}/5\\mathbb{Z}$ (i.e., the field with $5$ elements), we can do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3ba712be-7ddf-4299-aee1-08021d90b2ea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2 3 4]\n",
       "[2 0 1]\n",
       "[4 0 4]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(FiniteField(5), 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])  # for square matrices we can give only one dimension\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1feaf9fb-3dfe-4f1a-b3ba-a05f9023dfbe",
   "metadata": {},
   "source": [
    "(Note how the entries are reduced modulo $5$!)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca68d8ac-b43b-4fa8-ae30-287be7e3b41e",
   "metadata": {},
   "source": [
    "We can call the function `latex` to produce a $\\LaTeX$ representation of our matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "daaffcf2-0bbb-4ece-8c3e-d65b49521fe2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\\left(\\begin{array}{rrr}\n",
       "2 & 3 & 4 \\\\\n",
       "2 & 0 & 1 \\\\\n",
       "4 & 0 & 4\n",
       "\\end{array}\\right)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "latex(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d2e2cdc-bd22-41b9-9397-6be02b5109d7",
   "metadata": {},
   "source": [
    "## Special Matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5ecfc58-c58f-4f08-a888-032ba3d4bb0f",
   "metadata": {},
   "source": [
    "We can create the identity matrix of any dimension:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "733ade17-f4f1-4397-8564-2f25410a6edb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 0 0 0]\n",
       "[0 1 0 0]\n",
       "[0 0 1 0]\n",
       "[0 0 0 1]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "identity_matrix(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99a9f950-809c-49e4-8cd4-029853ab1035",
   "metadata": {},
   "source": [
    "We can also specify the type of coefficients.  For instance, for coefficients in $\\mathbb{F}_3 = \\mathbb{Z} / 3 \\mathbb{Z}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "28c33958-39fa-491d-84fe-11a493c38147",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 0]\n",
       "[0 1]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "identity_matrix(FiniteField(3), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cbc162a-0483-458d-a29d-28cdd8256666",
   "metadata": {},
   "source": [
    "Similarly for zero matrices:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7bac12a9-796e-46fe-a8cc-5719f1b61324",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0 0 0 0]\n",
       "[0 0 0 0]\n",
       "[0 0 0 0]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zero_matrix(3, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "525a670f-872d-49ca-9ab2-d5c6d862246b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.000000000000000 0.000000000000000]\n",
       "[0.000000000000000 0.000000000000000]\n",
       "[0.000000000000000 0.000000000000000]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zero_matrix(CC, 3, 2)  # CC = complex numbers (using floats)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bf7c87a-288d-4e91-b13d-bb9ae86974ec",
   "metadata": {},
   "source": [
    "We can create random matrices.  For finite entry ring (or field), it is as you'd expect:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "5acf3aac-b791-46f2-820c-1079ea321ed6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 7 0 9]\n",
       "[6 6 1 9]\n",
       "[1 0 2 8]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "random_matrix(FiniteField(11), 3, 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3aa04a5e-238a-48df-9221-5918086692c9",
   "metadata": {},
   "source": [
    "(Run the cell above a few times to see different random results.)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c386bf4c-1d95-4760-8492-40724ce706db",
   "metadata": {},
   "source": [
    "For $\\mathbb{Q}$ we can specifiy bounds for the numerator and denominator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "eff94b4d-7693-4f5b-adf8-848fa860bb9c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 3/4 -7/2 -5/2  -10   -3]\n",
       "[-7/5    5  5/8    0   -2]\n",
       "[-1/3  3/7 -2/3  3/8 -1/9]\n",
       "[-9/7 -2/5 -3/2 -8/5 -5/7]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "random_matrix(QQ, 4, 5, num_bound=10, den_bound=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51d96ac2-a413-4391-b7c4-f6e5c6f771e4",
   "metadata": {},
   "source": [
    "For $\\mathbb{R}$ (`RR` in Sage), we can specify the maximum and minimum:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "eb088069-93a5-40ee-aa04-1920b25ffc33",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.891317069574020  8.43768596822291]\n",
       "[-1.60966517026439 -9.00857316074933]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "random_matrix(RR, 2, 2, min=-10, max=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf1edf72-8a53-45a1-8fda-9208048be28e",
   "metadata": {},
   "source": [
    "## Complex Matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bb5613a-f47a-4887-8d3c-41b3a9713485",
   "metadata": {},
   "source": [
    "There a few implementations of complex matrices in Sage: some \"numeric\" (using floats/decimals) and one \"symbolic\" (with exact rational numbers and $i$).  The latter uses `I` for the imaginary number $i$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "577a3efa-fe80-490f-9791-59f926da8fd6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "I^2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b130a726-bcaa-416a-8171-d68e4d981dc2",
   "metadata": {},
   "source": [
    "So, we can make matrices such as:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1a0e1056-a4b5-40a2-b52a-a8602640442f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[    1/2*I         0]\n",
       "[3*I + 1/4        -3]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(2, 2, [I/2, 0, 1/4 + 3*I, -3])\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42d246e0-47d0-428c-abd9-2a1664def3ca",
   "metadata": {},
   "source": [
    "We can use `CC` to use floats:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "b0b79ac9-b7ef-4886-8c0d-ef509b569988",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[                   0.500000000000000*I                      0.000000000000000]\n",
       "[0.250000000000000 + 3.00000000000000*I                      -3.00000000000000]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = matrix(CC, 2, 2, [I/2, 0, 1/4 + 3*I, -3])\n",
    "B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d85ea2c-62c4-4050-86a2-aa360c5f74c1",
   "metadata": {},
   "source": [
    "If one wants to specify the \"symbolic\" complex numbers, we can save if in a variable and use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "5ba71747-b84d-4c29-ae63-c70aa73a5d61",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Number Field in I with defining polynomial x^2 + 1 with I = 1*I"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "CCs = I.parent()  # save the \"symbolic complex field\" in CCs\n",
    "CCs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a29ed94a-4bf5-4492-8cad-76dff2b89a13",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[  1   0]\n",
       "[1/3   I]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = matrix(CCs, 2, 2, [1, 0, 1/3, I])\n",
    "C"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37b5b4a0-16f0-4e17-8021-ef49c356e66d",
   "metadata": {},
   "source": [
    "## Symbolic Matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b079394a-5e08-4e3b-b003-1f29b6b7a99a",
   "metadata": {},
   "source": [
    "If we want to use symbolic computations, we need to introduce the variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3bc884c9-55a0-48c7-997d-0828c5540078",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[a11 a12]\n",
       "[a21 a22]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "var(\"a11, a12, a21, a22\")\n",
    "A = matrix(2, 2, [a11, a12, a21, a22])\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "42341164-cc6b-4d6e-8f64-36ab67a316e1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-a12*a21 + a11*a22"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.det()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "4522e7b2-42b7-46a2-9e09-73fd6af039b4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[  a11^2 + a12*a21 a11*a12 + a12*a22]\n",
       "[a11*a21 + a21*a22   a12*a21 + a22^2]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A^2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "22d0745a-cbfc-4386-b4da-c2d9293b0106",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1/a11 - a12*a21/(a11^2*(a12*a21/a11 - a22))               a12/(a11*(a12*a21/a11 - a22))]\n",
       "[              a21/(a11*(a12*a21/a11 - a22))                      -1/(a12*a21/a11 - a22)]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A^(-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff1543e0-94fe-494e-bb76-3f2790da7c99",
   "metadata": {},
   "source": [
    "## Matrix Operations"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f836155a-ba91-4f1c-a1ea-b9d2fa3e39d0",
   "metadata": {},
   "source": [
    "We can add matrices:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "040722c8-b17b-497c-9336-052e3a1f8e60",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = random_matrix(QQ, 3, 2, num_bound=5, den_bound=5)\n",
    "B = random_matrix(QQ, 3, 2, num_bound=5, den_bound=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "5fc5baaf-4ab1-4df1-bd9f-a0890b87e10b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 0 -1]\n",
       "[-3 -1]\n",
       "[ 2  1]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ef31da96-d762-40d1-a3c8-031879e8c777",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[-3/5  1/2]\n",
       "[ 1/4 -1/4]\n",
       "[   0    1]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "a5519559-2020-4be5-8cad-0053518b9e1c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ -3/5  -1/2]\n",
       "[-11/4  -5/4]\n",
       "[    2     2]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A + B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11f4c488-9a85-40cb-b13f-4c445f98fa07",
   "metadata": {},
   "source": [
    "We can also do scalar multiplication:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "0a603b0f-2f15-4c26-9e7e-805f7be50f78",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[   0 -1/3]\n",
       "[  -1 -1/3]\n",
       "[ 2/3  1/3]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 / 3 * A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3f947ca-1eb9-4c93-9cc5-667a958b40af",
   "metadata": {},
   "source": [
    "We can multiply matrices as expected:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "0f49c1aa-0d1f-4de2-a596-49dca425a890",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(3, [2, 8, 4, 2, 5, 1, 4, 10, -1])  # for square matrices we can give only one dimension\n",
    "B = matrix(3, 2, [1, 2, 0, 1, 1, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "875d3294-32ca-41e4-be83-2098423242cb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4]\n",
       "[ 2  5  1]\n",
       "[ 4 10 -1]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "e3947b56-5f58-4abc-a55b-594fb27ab949",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 2]\n",
       "[0 1]\n",
       "[1 1]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "a23274ae-38f8-46e3-ac30-97984044a81d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 6 16]\n",
       "[ 3 10]\n",
       "[ 3 17]"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A * B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61a0ef6c-67c2-4d00-970f-8dc8adbc2283",
   "metadata": {},
   "source": [
    "We can transpose:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "e51702b5-007e-4216-94a0-162eef1dc45d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  2  4]\n",
       "[ 8  5 10]\n",
       "[ 4  1 -1]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d249bec4-38c1-4f62-b5d8-ea920693ae8b",
   "metadata": {},
   "source": [
    "We can take determinants:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "a58d66a7-63a0-4e10-aa5a-d83561786c8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "18"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.det()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d19ae81-1f34-42a8-88cc-162ebf0fd4a2",
   "metadata": {},
   "source": [
    "We can invert, if possible:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "35793c9b-1732-4888-8904-84ea3c85a626",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[-5/6  8/3 -2/3]\n",
       "[ 1/3   -1  1/3]\n",
       "[   0  2/3 -1/3]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A^(-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30058df1-8b57-4c88-8bd9-d8934760a7ca",
   "metadata": {},
   "source": [
    "(Note that the result is made of **rational numbers**, not *floats* (i.e., decimals).)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f34c82bd-6518-4a28-ae40-9fe393e56964",
   "metadata": {},
   "source": [
    "## Echelon Form"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccf0d912-cf27-46fc-8647-0dd35351d403",
   "metadata": {},
   "source": [
    "We can get the *reduced row echelon form:*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "d2d26da4-5c9c-4f39-a362-85dfc0f47ee6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2 2 1]\n",
       "[0 3 0]\n",
       "[0 0 3]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.echelon_form()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d906e1e8-40f9-40ea-8ee7-6c6afceafb47",
   "metadata": {},
   "source": [
    "This result seems unexpected, since we don't have leading ones!  This is because Sage is staying with the *integers* for entries!  If we want to allow fractions, we must declare the matrix over the rationals $\\mathbb{Q}$, which in Sage is `QQ`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "71193b2b-cd58-418a-9df2-58ed76f3950f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4]\n",
       "[ 2  5  1]\n",
       "[ 4 10 -1]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])  # declare rational entries!!\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "5165840f-f265-4920-8327-2a026900f623",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 0 0]\n",
       "[0 1 0]\n",
       "[0 0 1]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.echelon_form()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e668580-a225-4988-bee5-f8380cc22015",
   "metadata": {},
   "source": [
    "## Vectors"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02ec8409-307a-446e-ab76-64e54616c360",
   "metadata": {},
   "source": [
    "We also have vectors:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "3c035527-7f02-4ffd-b484-8ea696820c1a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2, 3)"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = vector([1, 2, 3])\n",
    "v"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5fa3dc88-0dc9-4011-8db8-6f6441a45798",
   "metadata": {},
   "source": [
    "We can then use if for matrix multiplication:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "46f253fa-9242-47a8-b473-113620e0fb51",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(30, 15, 21)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A * v"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c06d5cf1-770f-484e-a69a-5b271cfe1bcb",
   "metadata": {},
   "source": [
    "Note that it knows that the vector must be interpreted as a *column* matrix!\n",
    "\n",
    "But we can also do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "d7307db6-cd20-40a0-bf1f-8c6285fd1318",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(18, 48, 3)"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v * A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61cb7f4b-28ac-4683-aa6b-6bdfdee1e892",
   "metadata": {},
   "source": [
    "Now, it is interpreted as a *row* matrix."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e6ee662-5bf4-443d-950b-709d61e0f7f4",
   "metadata": {},
   "source": [
    "## Row Operations"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a13b07a-6665-41ea-8541-0851a19f9c65",
   "metadata": {},
   "source": [
    "We can perform row operations.\n",
    "\n",
    "*Remember that Python starts indexing from $0$, not $1$*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "ff9363de-2ffe-4922-afb1-96df31ae5b77",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0 1 2]\n",
       "[3 4 5]\n",
       "[6 7 8]"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 3, range(9))\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15c16a54-ee29-40e4-ac6d-33dd88cf551b",
   "metadata": {},
   "source": [
    "Let's add $-3$ times the first row to the second:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "2212e976-0e8d-4774-bb97-12bc23ee73cf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 0  1  2]\n",
       "[ 3  1 -1]\n",
       "[ 6  7  8]"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.add_multiple_of_row(1, 0, -3)\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59329c14-2f0a-416b-8ecf-1dc6dbbb39a6",
   "metadata": {},
   "source": [
    "Note that this **changes** the original matrix!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "336073fd-d1a7-4e0a-8543-430607a98b02",
   "metadata": {},
   "source": [
    "Let's multiply the first row by $5$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "a860797d-8c27-4fc5-af8b-96d6516034c2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 0  5 10]\n",
       "[ 3  1 -1]\n",
       "[ 6  7  8]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.rescale_row(0, 5)\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02436fea-1945-4c69-883c-2b329c198e55",
   "metadata": {},
   "source": [
    "Let's swap the first and third rows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "bd1943d9-f331-40c0-b758-2c882b576cb7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 6  7  8]\n",
       "[ 3  1 -1]\n",
       "[ 0  5 10]"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.swap_rows(0, 2)\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6407e342-95ea-4500-a225-707de2350ee3",
   "metadata": {},
   "source": [
    "## Row Equivalency\n",
    "\n",
    "There is no way to check directly if two matrices are *row equivalent*, i.e., one can be obtained from the other by row operations.  But we can still do it: $A$ and $B$ are row equivalent if and only if they have the same reduced row echelon form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "64f5ea07-e702-4813-b33c-faac18c2bb87",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 0  1  2  3]\n",
       "[ 4  5  6  7]\n",
       "[ 8  9 10 11]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 3, 4, range(12))\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "ef06de60-b3da-4c43-b2b7-09be7cf8c143",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  3  4  5]\n",
       "[ 6  7  8  9]\n",
       "[10 11 12 13]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = matrix(QQ, 3, 4, range(2, 14))\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "41ce6199-2acb-4059-bb65-6e087f79bd16",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.echelon_form() == B.echelon_form()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04d8e6c2-6d5c-4233-b32c-64077d2c4bba",
   "metadata": {},
   "source": [
    "So, $A$ and $B$ are row equivalent."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a21c583-03cd-4446-aea2-a1cc861a0558",
   "metadata": {},
   "source": [
    "Let's check another matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "c86c7ccf-07c6-45ca-8263-5626d40a6d85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[  0   1   4   9]\n",
       "[ 16  25  36  49]\n",
       "[ 64  81 100 121]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = matrix(QQ, 3, 4, [i^2 for i in range(12)])\n",
    "C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "ffa50d67-30d3-485a-991c-75cf916534eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.echelon_form() == C.echelon_form()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fdd9e757-7445-4e3c-9bd2-19921931fb45",
   "metadata": {},
   "source": [
    "So $A$ and $C$ are not row equivalent."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4946834-2091-4511-a965-21254708b9b2",
   "metadata": {},
   "source": [
    "## Matrix Spaces"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "212802f1-8d89-4e8d-b07b-a1128e097db4",
   "metadata": {},
   "source": [
    "Let's start with a $4 \\times 3$ matrix $A$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "a5ff3f7c-ce5a-449b-82d6-ba1a18081a32",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 0  1  2]\n",
       "[ 3  4  5]\n",
       "[ 6  7  8]\n",
       "[ 9 10 11]"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 4, 3, range(12))\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0318d3cb-bf3f-4e2c-9c1d-e0dab7f23b53",
   "metadata": {},
   "source": [
    "We can ask for the row space:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "f65280b7-3d95-488e-b59d-3aa9c011de1c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 3 and dimension 2 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1  0 -1]\n",
       "[ 0  1  2]"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.row_space()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15951022-bda0-438e-8a4f-58330f083079",
   "metadata": {},
   "source": [
    "We can ask for the column space:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "7e444439-caf7-4640-8e24-a4d160b4a757",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 4 and dimension 2 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1  0 -1 -2]\n",
       "[ 0  1  2  3]"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.column_space()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a14531f-1e49-4c88-85cd-e1dc77aa895f",
   "metadata": {},
   "source": [
    "We can ask for the rank:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "c0741baa-0cc2-43aa-98db-b2a23b51bc0a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.rank()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10c4bc0a-aa9a-4dc8-b7c1-521db71d97b5",
   "metadata": {},
   "source": [
    "For the nullspace, we use `right_kernel`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "c2dd805b-ac4a-4e05-9220-b51928f414bb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 3 and dimension 1 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1 -2  1]"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.right_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "940a1575-c707-4cd2-9343-151e3231337d",
   "metadata": {},
   "source": [
    "Note that the method `kernel` gives the **left** kernel, meaning the space of solutions of $\\vec{x} \\cdot A = \\vec{0}$!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "4d4e60e3-1d71-4001-9345-f094c1887fc7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 4 and dimension 2 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1  0 -3  2]\n",
       "[ 0  1 -2  1]"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.kernel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "d94aa31e-e9c8-4fb8-88f7-c8882e3a1045",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 4 and dimension 2 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1  0 -3  2]\n",
       "[ 0  1 -2  1]"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.left_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "379d8d02-5a1c-483d-a891-96c8faf23b3b",
   "metadata": {},
   "source": [
    "(Note how `left_kernel` gives a subspace in $4$ dimensions, while `right_kernel` gives a subspace in $3$ dimensions, since $A$ is $4 \\times 3$!)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad53917c-1a77-42a7-ace0-8973f0dc4611",
   "metadata": {},
   "source": [
    "So, for the nullity, we need to ask for `right_nullity`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "a14b853a-2837-49ac-847b-3945fdaec5a7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.right_nullity()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "56f3a8df-9eef-44a9-910a-b13f8f9cb0dd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 4 and dimension 2 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1  0 -3  2]\n",
       "[ 0  1 -2  1]"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(A.T).right_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "161f36b9-c0cb-48ec-be21-fb7248a2c872",
   "metadata": {},
   "source": [
    "## Solving Numerical Linear Systems"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20d9e9b8-ff88-4e37-9879-06618461f529",
   "metadata": {},
   "source": [
    "### Solving Numerical Linear Symbolically"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b548a27-d116-4f70-ba75-fdad4f775d9a",
   "metadata": {},
   "source": [
    "Suppose we want to solve:\n",
    "\n",
    "\\begin{align*}\n",
    "  2x + 8y + 4z &= 2 \\\\\n",
    "  2x + 5y + z &= 5 \\\\\n",
    "  4x + 10y - z &= 1\n",
    "\\end{align*}\n",
    "\n",
    "We can do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "4cf9f46f-0e6c-47bf-8a78-184b62ce3bb8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[x == 11, y == -4, z == 3]]"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "var(\"x y z\")  # declare the symbolic variables\n",
    "eqs = [2*x + 8*y + 4*z == 2, 2*x + 5*y + z == 5, 4*x + 10*y -z == 1]  # make a list of equations\n",
    "solve(eqs, (x, y, z))  # call solve"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eb068ec-ada2-4278-92b9-12105ccb164d",
   "metadata": {},
   "source": [
    "If the system has no solution, say\n",
    "\n",
    "\\begin{align*}\n",
    " x + y &= 1\\\\\n",
    " x + y & = 2\n",
    "\\end{align*}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "cc933b18-6173-41f7-b42a-c5dd13c59d02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eqs = [x + y == 1, x + y == 2]\n",
    "solve(eqs, (x, y))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5f0d649-0f8d-4b29-93ff-58a27d906986",
   "metadata": {},
   "source": [
    "It may have infinitely many, as in\n",
    "\n",
    "\\begin{align*}\n",
    " x + y &= 1\\\\\n",
    " x + y & = 1\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "1e1dfb8a-3ad8-41e1-99b2-21f74cb21aad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[x == -r1 + 1, y == r1]]"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eqs = [x + y == 1, x + y == 1]\n",
    "solve(eqs, (x, y))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a869589-a962-4d82-8d1b-f33bd10348d3",
   "metadata": {},
   "source": [
    "As you can see, it gives us a free parameter `r1`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ca9f9f3-ea0f-41fd-b7cc-bdc7ba6ef5a1",
   "metadata": {},
   "source": [
    "### Solving Numerical Linear Using Matrices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf1f51f3-8bfd-4316-bbe5-1a995e2509a3",
   "metadata": {},
   "source": [
    "We can also solve systems using matrices:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "ca5cbbee-202d-412b-a677-c8a5c311334f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, -4, 3)"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 3, 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])\n",
    "v = vector(QQ, [2, 5, 1])\n",
    "A.solve_right(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39229615-f71b-4d18-b22a-6fc22f956bbf",
   "metadata": {},
   "source": [
    "For the other examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "24adf570-63f7-47ca-aab8-d035b56689f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 1]\n",
       "[1 1]"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = matrix(QQ, 2, 4 * [1])\n",
    "B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12d049aa-c616-4101-96f2-246d8a89c608",
   "metadata": {},
   "source": [
    "We get an error when there is no solution:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "53c8b197-4a54-4323-8467-3ca7b343299e",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "matrix equation has no solutions",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNotFullRankError\u001b[0m                          Traceback (most recent call last)",
      "File \u001b[0;32m~/src/sage-10.2/src/sage/matrix/matrix2.pyx:942\u001b[0m, in \u001b[0;36msage.matrix.matrix2.Matrix.solve_right\u001b[0;34m()\u001b[0m\n\u001b[1;32m    941\u001b[0m try:\n\u001b[0;32m--> 942\u001b[0m     X = self._solve_right_nonsingular_square(C, check_rank=True)\n\u001b[1;32m    943\u001b[0m except NotFullRankError:\n",
      "File \u001b[0;32m~/src/sage-10.2/src/sage/matrix/matrix2.pyx:988\u001b[0m, in \u001b[0;36msage.matrix.matrix2.Matrix._solve_right_nonsingular_square\u001b[0;34m()\u001b[0m\n\u001b[1;32m    987\u001b[0m if check_rank and self.rank() < self.nrows():\n\u001b[0;32m--> 988\u001b[0m     raise NotFullRankError\n\u001b[1;32m    989\u001b[0m D = self.augment(B)\n",
      "\u001b[0;31mNotFullRankError\u001b[0m: ",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn [63], line 2\u001b[0m\n\u001b[1;32m      1\u001b[0m v \u001b[38;5;241m=\u001b[39m vector(QQ, [Integer(\u001b[38;5;241m1\u001b[39m), Integer(\u001b[38;5;241m2\u001b[39m)])\n\u001b[0;32m----> 2\u001b[0m \u001b[43mB\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msolve_right\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/src/sage-10.2/src/sage/matrix/matrix2.pyx:944\u001b[0m, in \u001b[0;36msage.matrix.matrix2.Matrix.solve_right\u001b[0;34m()\u001b[0m\n\u001b[1;32m    942\u001b[0m         X = self._solve_right_nonsingular_square(C, check_rank=True)\n\u001b[1;32m    943\u001b[0m     except NotFullRankError:\n\u001b[0;32m--> 944\u001b[0m         X = self._solve_right_general(C, check=check)\n\u001b[1;32m    945\u001b[0m \n\u001b[1;32m    946\u001b[0m if b_is_vec:\n",
      "File \u001b[0;32m~/src/sage-10.2/src/sage/matrix/matrix2.pyx:1062\u001b[0m, in \u001b[0;36msage.matrix.matrix2.Matrix._solve_right_general\u001b[0;34m()\u001b[0m\n\u001b[1;32m   1060\u001b[0m     # Have to check that we actually solved the equation.\n\u001b[1;32m   1061\u001b[0m     if self*X != B:\n\u001b[0;32m-> 1062\u001b[0m         raise ValueError(\"matrix equation has no solutions\")\n\u001b[1;32m   1063\u001b[0m return X\n\u001b[1;32m   1064\u001b[0m \n",
      "\u001b[0;31mValueError\u001b[0m: matrix equation has no solutions"
     ]
    }
   ],
   "source": [
    "v = vector(QQ, [1, 2])\n",
    "B.solve_right(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85a3516e-6948-4108-8444-5d2eb74b6adb",
   "metadata": {},
   "source": [
    "Here is the one with infinitely many solutions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "103a4dfd-dffd-4b32-a210-52fafc67c0aa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 0)"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = vector(QQ, [1, 1])\n",
    "B.solve_right(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0226cc9e-4795-40dc-8ebd-31d88e2d1a7d",
   "metadata": {},
   "source": [
    "Note that when there are infinitely many solutions, it only gives *one particular solution*!  To see if there are more, we need to inspect the kernel/nullspace:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "677c885e-f33c-4717-8517-96d9464b2088",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector space of degree 2 and dimension 1 over Rational Field\n",
       "Basis matrix:\n",
       "[ 1 -1]"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.right_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d11646a3-e772-4401-8fcb-3f7b55a59414",
   "metadata": {},
   "source": [
    "So, we see that there kernel is not trivial, and thus we have infinitely many solutions.\n",
    "\n",
    "Let's save the particular solutions in `s1`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "2a3ccc8e-e3e7-4afd-91ea-40d28988ff76",
   "metadata": {},
   "outputs": [],
   "source": [
    "s1 = B.solve_right(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ac2c3f9-206e-4f4e-9ed9-233fa28a2964",
   "metadata": {},
   "source": [
    "Let's save the *basis* for the kernel in `kernel_basis`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "bfce7bf7-0a31-4d59-b5fc-f939be77ebfd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\n",
       "(1, -1)\n",
       "]"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kernel_basis = B.right_kernel().basis()\n",
    "\n",
    "kernel_basis"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4b086e5-65a2-489b-a9ad-b37718ed2f3f",
   "metadata": {},
   "source": [
    "We can see the the size of the basis (i.e., the dimension) is $1$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "152220a6-14b4-4116-8258-fb5dda6fcc08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(kernel_basis)  # len = length = number of elements"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f14b8953-31a8-43a1-ac59-e80fc085176a",
   "metadata": {},
   "source": [
    "We can now produce new solutions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "d98ce525-5357-415c-80d7-9f0d0649d8c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B * (s1 + 37/54 * kernel_basis[0]) == v"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65888a2e-690d-44bb-b82c-cff2c73be601",
   "metadata": {},
   "source": [
    "### Solving Systems with the Augmented Matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "6fcea274-e269-48b5-b750-ad8b258ce92b",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(QQ, 3, 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])\n",
    "v = vector(QQ, [2, 5, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "a17f69ec-a603-42f4-bf8c-34a31750a0af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4  2]\n",
       "[ 2  5  1  5]\n",
       "[ 4 10 -1  1]"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = A.augment(v)\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "b6c5c5be-ff86-43d3-85e5-d4d418f6cc54",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 1  0  0 11]\n",
       "[ 0  1  0 -4]\n",
       "[ 0  0  1  3]"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.echelon_form()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "b9f1a6e4-eef0-4a54-86d8-603cbac269f5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, -4, 3)"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.echelon_form().column(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c17ae75-faa7-42ff-ab8f-61658677850d",
   "metadata": {},
   "source": [
    "We can solve multiple systems at once!  To solve $A \\cdot \\vec{x} = \\vec{u}$, $A \\cdot \\vec{x} = \\vec{v}$, $A \\cdot \\vec{x} = \\vec{w}$, we can do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "876d365d-d474-4552-9dc2-b9f501dc9309",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(QQ, 3, 3, [2, 8, 4, 2, 5, 1, 4, 10, -1])\n",
    "u = vector(QQ, [1, 1, 0])\n",
    "v = vector(QQ, [2, 5, 1])\n",
    "w = vector(QQ, [0, -1, 3])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae74c583-4da5-4fe5-881d-83d9fe87ac6e",
   "metadata": {},
   "source": [
    "We augment the matrix by the three vectors:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "b5342fc6-6f00-4858-987c-f4b77bb9d22d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ 2  8  4  1  2  0]\n",
       "[ 2  5  1  1  5 -1]\n",
       "[ 4 10 -1  0  1  3]"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = A.augment(matrix([u, v, w]).T)  # note the .T to make the vectors into columns!\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "f0b8f953-1ec4-4770-a0ae-65d3e386959b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[    1     0     0  11/6    11 -14/3]\n",
       "[    0     1     0  -2/3    -4     2]\n",
       "[    0     0     1   2/3     3  -5/3]"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = B.echelon_form()\n",
    "C"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2222c1db-177c-4418-aa7c-e5932373036a",
   "metadata": {},
   "source": [
    "The solutions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "97d0f022-faea-4beb-8af9-4251aa7e014c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((11/6, -2/3, 2/3), (11, -4, 3), (-14/3, 2, -5/3))"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C.column(3), C.column(4), C.column(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c58ff66f-14da-4f62-a718-365cf187f6b3",
   "metadata": {},
   "source": [
    "We can also use this method to see when there are no solutions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "ab2ae75e-b348-4ce5-a5ba-0b9e1fe89ad6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 1]\n",
       "[1 1]"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = matrix(QQ, 2, 2, 4 * [1])\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "9a2d2295-6eba-4feb-ba7e-1d03f5eb08a7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 1 1 1]\n",
       "[1 1 2 1]"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = vector(QQ, [1, 2])\n",
    "w = vector(QQ, [1, 1])\n",
    "B = A.augment(matrix([v, w]).T)\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "75abfc9d-6760-4c8d-a33b-abea8e6006c5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 1 0 1]\n",
       "[0 0 1 0]"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.echelon_form()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "SageMath 10.2",
   "language": "sage",
   "name": "sage-10.2"
  },
  "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.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
