5.8. Vektorer og matricer#

I denne notebook vil vi have fokus på hvordan man definerer, manipulerer og foretager forskellige udregninger med matricer og vektorer. Som altid starter vi med at importere SymPy.

import sympy as sp                    # Importer sympy

Det grundlæggende er at definere matricer og vektorer på den nemmeste måde. Dette gøres ved at benytte den funktion, der hedder Matrix() fra SymPy. Da man oftest skal bruge denne mange gange, kan det være praktisk at importere den særskilt ved at skrive from sympy import Matrix, men det er lige så fint at skrive sp.Matrix().

5.8.1. Vektorer - definition og regneoperationer#

Vektorer defineres ved at give en liste til Matrix funktionen. Vi kan altså skrive Matrix([1, 1, 0]) for at få vektoren: \(\displaystyle \left[\begin{matrix}1\\1\\0\end{matrix}\right]\)

Vi kan angive de enkelte indgange som tal eller bruge symbolske variable som vi i forvejen har importeret fra sympy.abc ligesom vi tidligere har gjort med \(x\).

Eksempel:

from sympy import Matrix
from sympy.abc import a, b, c

vektor1 = Matrix([a, b, c])
vektor1
\[\begin{split}\displaystyle \left[\begin{matrix}a\\b\\c\end{matrix}\right]\end{split}\]

Det ligger os selvfølgelig også frit for at kombinere tal og variable:

vektor2 = Matrix([a, sp.Rational(3, 4), b ** 2 / 2])   # Husk at bruge sp.Rational() til at definere brøker
vektor2
\[\begin{split}\displaystyle \left[\begin{matrix}a\\\frac{3}{4}\\\frac{b^{2}}{2}\end{matrix}\right]\end{split}\]

De to vektorer vektor og vektor2 kan nu kombineres på sædvanlig vis ved addition, subtraktion og skalarmultiplikation:

vektor1 + vektor2   # Blot læg de to vektorer sammen med et almindeligt +
\[\begin{split}\displaystyle \left[\begin{matrix}2 a\\b + \frac{3}{4}\\\frac{b^{2}}{2} + c\end{matrix}\right]\end{split}\]
a * vektor2       # a er importeret som et symbol, så vi kan bruge det som en skalar
\[\begin{split}\displaystyle \left[\begin{matrix}a^{2}\\\frac{3 a}{4}\\\frac{a b^{2}}{2}\end{matrix}\right]\end{split}\]

Hvis vi til gengæld forsøger at multiplicere de to vektorer får vi en fejl, da * mellem to Matrix-elementer er matrix-multiplikation, som ikke er defineret for to 3 x 1 matricer. Vi vender tilbage til matrixmultiplikation nedenfor, mens krydsprodukter kan findes i sektionen om flere metoder i linæer algebra.

Et produkt, der derimod er defineret for vektorer, er det fra gymnasiet velkendte skalarprodukt eller prikprodukt \(\mathbf{v_1} \cdot \mathbf{v_2}\) som er et eksempel på et indre produkt (i Messers notation \(\langle \mathbf{v_1}, \mathbf{v_2}\rangle\)).

Et indre produkt mellem to vektorer vektor1 og vektor2 beregnes med vektor1.dot(vektor2):

vektor1.dot(vektor2)
\[\displaystyle a^{2} + \frac{b^{2} c}{2} + \frac{3 b}{4}\]

Som forventet får vi summen af produkterne af vektorens indgange, dog i en anden rækkefølge end vi normalt ville vælge ved udregning i hånden.

5.8.2. Matricer - definition og regneoperationer#

Matricer defineres på samme måde, som vi har gjort det med vektorer, altså ved at benytte Matrix() - funktionen. Når vi laver en matrix, så skal vi dog give en liste af rækker, der hver især selv er lister. Formatet er det samme, som man bruger til at lave arrays i numpy. Hvis man eksempelvis blot vil lave en tabel med indgange fra 1 til 9, skal man angive det som:

A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
display(A)
\[\begin{split}\displaystyle \left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\\7 & 8 & 9\end{matrix}\right]\end{split}\]

Det er naturligvis en forudsætning, at alle rækkerne har lige mange elementer.

Som for vektorer kan vi benytte symboler i matricer:

B = Matrix([[a, b, c], [b, c, b], [c, b, a]])
display(B)
\[\begin{split}\displaystyle \left[\begin{matrix}a & b & c\\b & c & b\\c & b & a\end{matrix}\right]\end{split}\]

Også addition og skalarmultiplikation fungerer som for vektorer:

A + 3 * B
\[\begin{split}\displaystyle \left[\begin{matrix}3 a + 1 & 3 b + 2 & 3 c + 3\\3 b + 4 & 3 c + 5 & 3 b + 6\\3 c + 7 & 3 b + 8 & 3 a + 9\end{matrix}\right]\end{split}\]
42*B
\[\begin{split}\displaystyle \left[\begin{matrix}42 a & 42 b & 42 c\\42 b & 42 c & 42 b\\42 c & 42 b & 42 a\end{matrix}\right]\end{split}\]

Matricer kan også multipliceres med hinanden (se Messer afsnit 5.1) så længe de har passende dimensioner. Man kan opfatte indgangen på plads (i,j) i produktet AB som prikproduktet af den i’te række i A med den j’te søjle i B, og for at dette kan lade sig gøre, skal antallet af søjler i A være det samme som antallet af rækker i B. Vi kan også skrive betingelsen som at hvis A er en matrix af dimension \(m \times n\), skal B have dimension \(n \times p\)). I dette tilfælde kan vi gange dem sammen ved at benytte *:

A * B
\[\begin{split}\displaystyle \left[\begin{matrix}a + 2 b + 3 c & 4 b + 2 c & 3 a + 2 b + c\\4 a + 5 b + 6 c & 10 b + 5 c & 6 a + 5 b + 4 c\\7 a + 8 b + 9 c & 16 b + 8 c & 9 a + 8 b + 7 c\end{matrix}\right]\end{split}\]

Ligesom med arrays i numpy, kan vi også trække rækker/kolonner ud af matricer. Hvis vi vil have det øverste element til venstre i ovenstående matrix, kan vi gøre det ved:

C = A * B
C[0, 0]
\[\displaystyle a + 2 b + 3 c\]

Eller vi kan tage den tredje søjle ved:

C[:, 2]
\[\begin{split}\displaystyle \left[\begin{matrix}3 a + 2 b + c\\6 a + 5 b + 4 c\\9 a + 8 b + 7 c\end{matrix}\right]\end{split}\]

5.8.3. Indbyggede matricer#

Til at definere en række meget almindeligt forekommende matricer er der indbygget smutveje.

Disse matricer skal importeres fra sympy.matrices.

Identitetsmatricer: findes ved funktionen eye(dimension). Navnet skyldes at “eye” udtales omtrent som “I”, der ofte anvendes som symbol for identitetsmatricen, men allerede er reserveret til den imaginære enhed for komplekse tal. Da identitetsmatricen pr. definition er kvadratisk, angiver man blot dimensionen \(n\) og får en \(n\times n\) matrix med \(1\) i diagonalen og \(0\) alle andre steder:

from sympy.matrices import eye

Id4 = eye(4)
display(Id4)
\[\begin{split}\displaystyle \left[\begin{matrix}1 & 0 & 0 & 0\\0 & 1 & 0 & 0\\0 & 0 & 1 & 0\\0 & 0 & 0 & 1\end{matrix}\right]\end{split}\]

0- og 1-matricer: Funktionerne zeros(dimension) og ones(dimension) giver en matrix af den ønskede størrelse fyldt med hhv. 0 eller 1-taller. Her kan dimension være to tal n, m eller et enkelt tal n, hvilket resulterer i en \(n \times n\) matrix:

from sympy.matrices import zeros, ones

nul_matrix = zeros(4)
display(nul_matrix)
\[\begin{split}\displaystyle \left[\begin{matrix}0 & 0 & 0 & 0\\0 & 0 & 0 & 0\\0 & 0 & 0 & 0\\0 & 0 & 0 & 0\end{matrix}\right]\end{split}\]
fire_matrix = 4 * ones(3, 4)
display(fire_matrix)
\[\begin{split}\displaystyle \left[\begin{matrix}4 & 4 & 4 & 4\\4 & 4 & 4 & 4\\4 & 4 & 4 & 4\end{matrix}\right]\end{split}\]

Diagonalmatricer: laves med funktionen diag(liste). Denne funktion giver man som input blot en liste med de ønskede diagonalelementer. Alle andre indgange er \(0\):

from sympy.matrices import diag

D = diag(1, 2, 3, 4)
display(D)
\[\begin{split}\displaystyle \left[\begin{matrix}1 & 0 & 0 & 0\\0 & 2 & 0 & 0\\0 & 0 & 3 & 0\\0 & 0 & 0 & 4\end{matrix}\right]\end{split}\]

Man kan også indsætte matricer langs diagonalen i større maricer, således at man får en blok-diagonal-matrix. Man kan f.eks. indsætte en matrix, der beskriver en rotation i planen, i en større matrix, der beskriver samme rotation i \((x,y)\)-planen indlejret i et tredimensionalt rum:

from sympy.abc import theta   # Importer theta

# Definer matrix
plan_rot = Matrix([[sp.cos(theta), sp.sin(-theta)], [sp.sin(theta), sp.cos(theta)]])
plan_rot
\[\begin{split}\displaystyle \left[\begin{matrix}\cos{\left(\theta \right)} & - \sin{\left(\theta \right)}\\\sin{\left(\theta \right)} & \cos{\left(\theta \right)}\end{matrix}\right]\end{split}\]
# Lav diagonal med et 1-tal og så en matrice. diag fylder nu 0 ud alle andre steder.
rum_rot = diag(plan_rot, 1)
rum_rot
\[\begin{split}\displaystyle \left[\begin{matrix}\cos{\left(\theta \right)} & - \sin{\left(\theta \right)} & 0\\\sin{\left(\theta \right)} & \cos{\left(\theta \right)} & 0\\0 & 0 & 1\end{matrix}\right]\end{split}\]

Det er desuden muligt at sætte matricer sammen og definere matricer hvor hver indgang er resulatet af en beregning eller logisk test. Disse metoder kan findes i dokumentationen her men vil ikke være nødvendige i LinALys-kurset.