Problem 9.4.3
We'll work through this as a close analogue of the assigned Problem 9.4.4. The task is to find a basis for $$ \mathrm{span}~\{1+x+x^2,\ 1+2x,\ 1+5x-3x^2\}. $$ We will once more encode polynomials $$ a_nx^n+a_{n-1}x^{n-1}+\cdots + a_1x + a_0 $$ as vectors $$ \left[ \begin{array}{c} a_0\\ a_1\\ \vdots\\ a_{n-1}\\ a_n \end{array} \right]. $$ In this specific case, the vectors are $$ \left[ \begin{array}{r} 1\\ 1\\ 1 \end{array} \right] ,\quad \left[ \begin{array}{r} 1\\ 2\\ 0 \end{array} \right] \quad\text{and}\quad \left[ \begin{array}{r} 1\\ 5\\ -3 \end{array} \right]. $$ We went through how to do this in class: collect the vectors together as the columns of a matrix $$ A= \left[ \begin{array}{rrr} 1&1&1\\ 1&2&5\\ 1&0&-3 \end{array} \right], $$ make that matrix echelon to see where the pivots are, and then keep the pivot columns (of the original matrix $A$, not of the echelon matrix you wound up turning it into). Let's implement all of that then.
from sympy import *
init_printing(use_latex='mathjax')
A=Matrix([[1,1,1],[1,2,5],[1,0,-3]]); A
And then you just ask for the echelon form (even reduced echelon if you like, just for good measure):
A.rref()
The answer even directly tells us which columns are pivot: that $(0,1)$ there means the pivot columns are the $0^{th}$ and the $1^{st}$ (remember, Python starts numbering at 0!). In plain human English, that means columns 1 and 2 are pivot. So that's our basis then: the first two polynomials: $$ 1+x+x^2 \quad\text{and}\quad 1+2x. $$ Now that we got this far though, it might not hurt, just as a sanity check, to express the third polynomial (or vector) as a linear combo of these two. If $a_i$, $1\le i\le 3$ are the columns of $A$ above, then I want $c_1$ and $c_2$ such that $$ c_1\cdot a_1 + c_2\cdot a_2 = a_3. $$ This, you can straight-up ask for:
The command now is of the form
A'.solve(a3)
where $A'$ is the matrix obtained by dropping the last column of $A$ and $a_3$ is that last column. You can define these ($A'$ and $a_3$) "by hand", but you don't have to: you can extract portions of a matrix (some of the rows, some of the columns):
A.extract(range(0,A.rows),[0,1])
That told SymPy to take all of the rows (the range
thing) and columns 0 and 1 (i.e. the first two; again, remember that Python starts numbering at 0). Let's put it all together. The A.col(-1)
below means the last column; this could also have been rendered as A.col(2)
in our case, because last=$3^{rd}$.
A.extract(range(0,A.rows),[0,1]).solve(A.col(-1))
This tells me that my coordinates for the third column $a_3$ in the basis $(a_1,a_2)$ are $-3$ and $4$. Or: $$ a_3 = -3a_1+4a_2. $$ Why don't we just check that?
A.col(2) == (-3)*A.col(0) + 4*A.col(1)
True