Wektory i macierze
Wektor to płaska lista liczb, na przykład kierunek w przestrzeni lub zestaw ilości. Macierz to lista wierszy. Ta strona opisuje iloczyny skalarne i wektorowe, mnożenie macierzy, wyznaczniki i macierze odwrotne, układy równań oraz narzędzia numerycznej algebry liniowej: wartości własne i rozkłady QR, LU oraz SVD.
Przydaje się do zadań z algebry liniowej, geometrii, przekształceń i problemów z wieloma niewiadomymi związanymi równaniami liniowymi. Wektory i macierze są zwykłymi listami, więc obowiązuje też opis List i statystyki, w tym indeksowanie.
Wektory
dot([1, 2, 3], [4, 5, 6]) daje 32dot([3, 4], [4, -3]) daje 0cross([1, 0, 0], [0, 1, 0]) daje [0, 0, 1]cross([1, 2, 3], [4, 5, 6]) daje [-3, 6, -3]v = [3, 4]sqrt(dot(v, v)) daje 5dot mnoży odpowiadające elementy i sumuje wyniki. Iloczyn skalarny równy zero oznacza prostopadłość, jak dla [3, 4] i [4, -3]. cross daje wektor prostopadły do obu wejściowych: kierunek x razy wektorowo kierunek y daje z. Długość wektora to pierwiastek z jego iloczynu skalarnego z samym sobą.
dot wymaga dwóch wektorów tej samej długości, a cross dwóch trójelementowych. Do dodawania i skalowania użyj zwykłej arytmetyki list: [1, 2] + [3, 4] daje [4, 6], a 2 * [3, 4] — [6, 8].
Zapisywanie i mnożenie macierzy
Zapisz macierz jako listę wierszy, każdy w osobnych nawiasach kwadratowych:
shape([[1, 2, 3], [4, 5, 6]]) daje [2, 3]transpose([[1, 2, 3], [4, 5, 6]]) daje [[1, 4], [2, 5], [3, 6]]identity(3) daje [[1, 0, 0], [0, 1, 0], [0, 0, 1]][[1, 2], [3, 4]] * [[5, 6], [7, 8]] daje [[19, 22], [43, 50]]shape daje [rows, columns]. transpose zamienia wiersze z kolumnami. identity(n) to macierz jednostkowa n na n, która przy mnożeniu pozostawia drugą macierz bez zmian.
* między macierzami oznacza mnożenie macierzowe. Lewa macierz musi mieć tyle kolumn, ile prawa ma wierszy. Aby pomnożyć macierz przez wektor, zapisz wektor jako kolumnę, po jednym elemencie w wierszu:
# Rotate the point (3, 1) by 90° anticlockwiserotate = [[0, -1], [1, 0]]rotate * [[3], [1]] daje [[-1], [3]]rotate * rotate daje [[-1, 0], [0, -1]]Dwa obroty o 90° dają pół obrotu, dlatego rotate * rotate odwraca oba znaki. Płaska lista taka jak [3, 1] nie jest przyjmowana po prawej stronie macierzy. Jeśli masz płaską listę pod nazwą, transpose([v]) zamienia ją w kolumnę.
Macierze tego samego rozmiaru można dodawać i odejmować oraz mnożyć i dzielić przez liczbę, tak jak inne listy.
Każda operacja macierzowa podlega kilku zasadom:
- Każdy wiersz musi mieć tę samą liczbę elementów.
- Elementy muszą być liczbami bez jednostek. Jednostki i pieniądze nie są przyjmowane.
- Macierz może mieć najwyżej 32 wiersze i 32 kolumny.
- Nie ma skrótu ze średnikiem. Pisz
[[1, 2], [3, 4]], a nie[1, 2; 3, 4].
Wyznacznik, macierz odwrotna, ślad i rząd
M = [[2, 1], [5, 3]]det(M) daje 1inverse(M) daje [[3, -1], [-5, 2]]M * inverse(M) daje [[1, 0], [0, 1]]trace(M) daje 5inverse([[2, 1], [1, 3]]) daje [[0.6, -0.2], [-0.2, 0.4]]det([[1, 2], [2, 4]]) daje 0rank([[1, 2, 3], [2, 4, 6]]) daje 1det, inverse i trace (suma przekątnej) wymagają macierzy kwadratowej. Wyznacznik zero oznacza macierz osobliwą: wiersze nie są niezależne, więc macierz nie ma odwrotności i inverse([[1, 2], [2, 4]]) daje błąd. rank liczy niezależne wiersze i przyjmuje również macierze niekwadratowe. W ostatnim wierszu drugi wiersz macierzy jest dwukrotnością pierwszego, więc rząd wynosi 1.
Te cztery funkcje używają dokładnych ułamków zamiast liczb dziesiętnych, dlatego M * inverse(M) daje dokładnie macierz jednostkową.
Rozwiązywanie układu liniowego
Załóżmy, że trzy kawy i dwie herbaty kosztują £13,50, a jedna kawa i cztery herbaty £11,50. Wpisz ilości napojów w osobnym wierszu dla każdego równania, w stałej kolejności kolumn (kawa, herbata), a sumy w odpowiadającej liście:
solve_system([[3, 2], [1, 4]], [13.5, 11.5]) daje [3.1, 2.1]Wynik ma tę samą kolejność co kolumny: kawa kosztuje £3,10, a herbata £2,10. Pomiń symbole walut, ponieważ elementy macierzy muszą być liczbami bez jednostek.
solve_system(A, b) rozwiązuje A * x = b względem x. Wymaga macierzy kwadratowej, po jednym wierszu na niewiadomą, i płaskiej listy prawych stron tej samej długości. Używa dokładnych ułamków, więc wynik nie ma błędu zaokrąglenia.
Jeśli równania nie wyznaczają jednego rozwiązania, pojawia się błąd braku jednoznacznego rozwiązania. Na przykład solve_system([[1, 2], [2, 4]], [3, 6]) nie działa, bo drugie równanie jest podwojonym pierwszym. solve_system obsługuje tylko równania liniowe. Dla x^2 = 2 użyj solve z Sumowania, równań i rachunku różniczkowego.
Wartości własne
eigenvalues([[2, 1], [1, 2]]) daje [1, 3]eigenvalues([[4, 1], [2, 3]]) daje [5, 2]eigenvalues([[0, -1], [1, 0]]) daje [i, -i]eigenvalues przyjmuje macierz kwadratową i zwraca płaską listę. Obrót o 90° nie zachowuje żadnego kierunku, więc ma zespolone wartości własne i i -i; zobacz Liczby zespolone. Nie polegaj na kolejności listy.
Rozkłady: QR, LU i SVD
Każdy rozkład zwraca listę macierzy. Wydziel części przez indeksy:
A = [[3, 0], [4, 5]]parts = qr(A)q = parts[0] daje [[0.6, -0.8], [0.8, 0.6]]r = parts[1] daje [[5, 4], [0, 3]]q * r daje [[3, 0], [4, 5]]Pomnożenie czynników daje z powrotem A, więc łatwo sprawdzić rozkład. Binarna arytmetyka zmiennoprzecinkowa pozostawia drobne błędy zaokrągleń, około 10⁻¹⁵, które Varlig pokazuje w listach i macierzach jako 0. Zapisane wartości zachowują wszystkie cyfry, więc oceniaj wynik wizualnie lub przez różnicę, a nie ==.
lu([[2, 1], [4, 3]]) daje [[[0, 1], [1, 0]], [[1, 0], [0.5, 1]], [[4, 3], [0, -0.5]]]lu zwraca [P, L, U], gdzie P zapisuje zamiany wierszy, a P * A jest równe L * U. Tutaj wiersze zamieniono, aby najpierw użyć większej liczby, 4.
B = [[3, 1], [4, 7]]f = svd(B)u = f[0]s = f[1]vt = f[2]u * [[s[0], 0], [0, s[1]]] * vt daje [[3, 1], [4, 7]]svd([[3, 4]]) daje [[[1]], [5], [[0.6, 0.8]]]svd zwraca [U, s, Vt], gdzie s jest płaską listą wartości osobliwych od największej. W zapisie podręcznikowym B jest równe U * diag(s) * Vt. Nie ma funkcji diag, więc zbuduj macierz diagonalną samodzielnie, jak w [[s[0], 0], [0, s[1]]].
| Funkcja | Wymagania i zwracany wynik |
|---|---|
identity(n) |
Macierz jednostkowa o wymiarach n na n |
shape(A) |
[rows, columns] |
transpose(A) |
Zamienione wiersze i kolumny |
det(A) |
Wyznacznik macierzy kwadratowej |
inverse(A) |
Macierz odwrotna do macierzy kwadratowej o niezerowym wyznaczniku |
trace(A) |
Suma elementów przekątnej macierzy kwadratowej |
rank(A) |
Liczba liniowo niezależnych wierszy; dowolna macierz prostokątna |
solve_system(A,b) |
Rozwiązanie A * x = b dla macierzy kwadratowej z jednym rozwiązaniem |
eigenvalues(A) |
Wartości własne macierzy kwadratowej, możliwie zespolone, w nieokreślonej kolejności |
qr(A) |
[Q, R], gdzie Q * R jest w przybliżeniu równe A; dowolna macierz prostokątna |
lu(A) |
[P, L, U], gdzie P * A jest w przybliżeniu równe L * U; macierz kwadratowa |
svd(A) |
[U, s, Vt], gdzie s jest płaską listą; dowolna macierz prostokątna |
Dla macierzy niekwadratowej qr i svd zwracają zredukowane czynniki: dla macierzy 3 na 2 macierz Q również ma 3 na 2 zamiast 3 na 3.
Co jest dokładne, a co jest odrzucane
Dodawanie, odejmowanie i mnożenie macierzy, mnożenie przez liczbę, transpose, det i inverse używają dokładnych ułamków dla każdej obsługiwanej macierzy. Nic nie jest zaokrąglane na wejściu ani przed dalszym obliczeniem, dlatego iloczyn z macierzą odwrotną daje dokładnie macierz jednostkową:
[[1, 2], [3, 4]] + [[10, 20], [30, 40]] daje [[11, 22], [33, 44]][[1, 2], [3, 4]] - [[1, 1], [1, 1]] daje [[0, 1], [2, 3]]3 * [[1, 2], [3, 4]] daje [[3, 6], [9, 12]][[1, 2], [3, 4]] * [[0, 1], [1, 0]] daje [[2, 1], [4, 3]]det([[1, 2], [3, 4]]) daje -2inverse([[1, 2], [3, 4]]) daje [[-2, 1], [1.5, -0.5]]inverse([[1, 2], [3, 4]]) * [[1, 2], [3, 4]] daje [[1, 0], [0, 1]]Każdy warunek jest sprawdzany przed pokazaniem wyniku, a komunikat wskazuje niespełniony:
det([[1, 2, 3], [4, 5, 6]]) daje Unsupported: Expected a square matrixinverse([[1, 2], [2, 4]]) daje Unsupported: Singular matrix has no inverse[[1, 2], [3, 4]] + [[1, 2, 3], [4, 5, 6]] daje Unsupported: List dimensions do not match[[1, 2, 3], [4, 5, 6]] * [[1, 2], [3, 4]] daje Unsupported: Matrix inner dimensions do not matchElementy macierzy są liczbami bez jednostek. Jednostka, kwota lub liczba zespolona w dowolnym elemencie zatrzymuje obliczenie zamiast przechodzić dalej, ponieważ operacje macierzowe ich nie zachowują:
det([[1 kg, 2], [3, 4]]) daje Unsupported: Matrix entries must be plain numbers; units, money and complex values are not supportedTylko lista wierszy jest interpretowana jako macierz. Płaska lista zachowuje własne znaczenie, więc [1, 2] + [3, 4] nadal daje elementowo [4, 6], a [1, 2] * [3, 4] — błąd wskazujący dot.
Zasady dokładności równań, macierzy i statystyk zebrano w Co gwarantuje silnik.
Algorytmy i limity
det, inverse, rank i solve_system używają dokładnych ułamków w granicach rozmiaru liczb kalkulatora. eigenvalues, qr, lu i svd używają binarnej arytmetyki zmiennoprzecinkowej, więc dają bliskie przybliżenia. Iteracje kończą się po 10 000 kroków.
Macierze z prawie zależnymi wierszami, jak [[1, 1], [1, 1.0000001]], są źle uwarunkowane. Drobne błędy zaokrągleń mogą się w nich silnie powiększać, więc rozkłady i wartości własne tracą dokładność. Skrajne przypadki mogą przekroczyć limity numeryczne i dać błąd.
Pełne zasady są w dokumentacji zaawansowanej matematyki.
Przykład całościowy
Trzy paragony ze straganu podają ilości jabłek, bananów i pomarańczy oraz sumy zapłaty, ale nie ceny jednostkowe:
# Each row: apples, bananas, orangesbaskets = [[2, 3, 1], [1, 2, 3], [4, 1, 2]]paid = [2.15, 2.70, 3.05]det(baskets) daje 25prices = solve_system(baskets, paid) daje [0.4, 0.25, 0.6]# Check the prices against every receiptbaskets * transpose([prices]) daje [[2.15], [2.7], [3.05]]# What would 5 apples, 2 bananas and 4 oranges cost?dot([5, 2, 4], prices) daje 4.9Niezerowy wyznacznik potwierdza, że paragony wystarczają do jednoznacznego ustalenia cen: jabłka 40p, banany 25p i pomarańcze 60p. Pomnożenie koszyków przez kolumnę cen odtwarza sumy, a dot wycenia nowy koszyk na £4,90.