Перейти до вмісту
Посібник Varlig
Головна сторінка Varlig

Вектори й матриці

Вектор — одновимірний список чисел, наприклад напрямок у просторі або набір кількостей. Матриця — список рядків. Тут описано скалярний і векторний добутки, множення матриць, визначники й обернені матриці, системи лінійних рівнянь і чисельні засоби лінійної алгебри: власні значення та QR-, LU- і сингулярний розклади.

Це корисно для навчальних завдань із лінійної алгебри, геометрії, перетворень і задач із кількома невідомими, пов’язаними лінійними рівняннями. Вектори й матриці є звичайними списками, тому правила зі сторінки Списки й статистика, зокрема індексація, діють і тут.

Вектори

calc
dot([1, 2, 3], [4, 5, 6]) дорівнює 32
dot([3, 4], [4, -3]) дорівнює 0
cross([1, 0, 0], [0, 1, 0]) дорівнює [0, 0, 1]
cross([1, 2, 3], [4, 5, 6]) дорівнює [-3, 6, -3]
v = [3, 4]
sqrt(dot(v, v)) дорівнює 5

dot множить відповідні елементи й додає результати. Нульовий скалярний добуток означає перпендикулярність, як для [3, 4] і [4, -3]. cross повертає вектор, перпендикулярний обом аргументам: добуток напряму x на напрям y дає напрям z. Довжина вектора — квадратний корінь зі скалярного добутку вектора на самого себе.

dot потребує двох векторів однакової довжини, а cross — двох векторів із трьох елементів. Для додавання чи масштабування використовуйте арифметику списків: [1, 2] + [3, 4] дає [4, 6], а 2 * [3, 4] — [6, 8].

Запис і множення матриць

Записуйте матрицю як список рядків, кожен у власних квадратних дужках:

calc
shape([[1, 2, 3], [4, 5, 6]]) дорівнює [2, 3]
transpose([[1, 2, 3], [4, 5, 6]]) дорівнює [[1, 4], [2, 5], [3, 6]]
identity(3) дорівнює [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
[[1, 2], [3, 4]] * [[5, 6], [7, 8]] дорівнює [[19, 22], [43, 50]]

shape повертає [rows, columns]. transpose міняє місцями рядки й стовпці. identity(n) — одинична матриця розміру n на n, множення на яку не змінює іншу матрицю.

* між матрицями означає матричне множення: кількість стовпців лівої має дорівнювати кількості рядків правої. Для множення матриці на вектор запишіть його стовпцем, по одному елементу на рядок:

calc
# Rotate the point (3, 1) by 90° anticlockwise
rotate = [[0, -1], [1, 0]]
rotate * [[3], [1]] дорівнює [[-1], [3]]
rotate * rotate дорівнює [[-1, 0], [0, -1]]

Два повороти на 90° дають півоберту, тому rotate * rotate змінює обидва знаки. Одновимірний список на кшталт [3, 1] праворуч від матриці не приймається. Якщо список має ім’я, transpose([v]) перетворює його на стовпець.

Матриці однакового розміру можна додавати й віднімати, а також множити чи ділити на число, як інші списки.

Для всіх матричних операцій діють правила:

  • Усі рядки мають містити однакову кількість елементів.
  • Елементи мають бути числами без одиниць. Одиниці й гроші не підтримуються.
  • Матриця може мати до 32 рядків і 32 стовпців.
  • Скороченого запису з крапкою з комою немає. Пишіть [[1, 2], [3, 4]], а не [1, 2; 3, 4].

Визначник, обернена матриця, слід і ранг

calc
M = [[2, 1], [5, 3]]
det(M) дорівнює 1
inverse(M) дорівнює [[3, -1], [-5, 2]]
M * inverse(M) дорівнює [[1, 0], [0, 1]]
trace(M) дорівнює 5
inverse([[2, 1], [1, 3]]) дорівнює [[0.6, -0.2], [-0.2, 0.4]]
det([[1, 2], [2, 4]]) дорівнює 0
rank([[1, 2, 3], [2, 4, 6]]) дорівнює 1

det, inverse і trace (сума головної діагоналі) потребують квадратної матриці. Нульовий визначник означає виродженість: рядки лінійно залежні й оберненої матриці немає, тому inverse([[1, 2], [2, 4]]) дає помилку. rank рахує лінійно незалежні рядки й приймає також неквадратні матриці. В останньому рядку другий рядок матриці вдвічі більший за перший, тому ранг дорівнює 1.

Ці чотири функції використовують точні дроби, а не десяткові наближення, тому M * inverse(M) дає точно одиничну матрицю.

Розв'язання лінійної системи

Припустімо, три кави й два чаї коштують £13,50, а одна кава й чотири чаї — £11,50. Запишіть кількості напоїв рядками за рівняннями, у фіксованому порядку стовпців (кава, чай), а суми — відповідним списком:

calc
solve_system([[3, 2], [1, 4]], [13.5, 11.5]) дорівнює [3.1, 2.1]

Відповідь має порядок стовпців: кава коштує £3,10, чай — £2,10. Не додавайте валютні символи, оскільки елементи матриці мають бути числами без одиниць.

solve_system(A, b) розв’язує A * x = b відносно x. Потрібні квадратна матриця з одним рядком на невідому та одновимірний список правих частин тієї самої довжини. Використовуються точні дроби, тому похибки округлення немає.

Якщо рівняння не визначають єдиної відповіді, повідомлення пояснює, що система не має єдиного розв’язку. Наприклад, solve_system([[1, 2], [2, 4]], [3, 6]) дає помилку, бо друге рівняння — подвоєне перше. solve_system працює лише з лінійними рівняннями. Для рівнянь на кшталт x^2 = 2 використовуйте solve із розділу Сумування, рівняння й математичний аналіз.

Власні значення

calc
eigenvalues([[2, 1], [1, 2]]) дорівнює [1, 3]
eigenvalues([[4, 1], [2, 3]]) дорівнює [5, 2]
eigenvalues([[0, -1], [1, 0]]) дорівнює [i, -i]

eigenvalues приймає квадратну матрицю й повертає одновимірний список. Поворот на 90° не зберігає жодного дійсного напряму, тому власні значення — комплексна пара i та -i; див. Комплексні числа. Не покладайтеся на порядок списку.

Розклади QR, LU і SVD

Кожен розклад повертає список матриць. Діставайте складові за індексами:

calc
A = [[3, 0], [4, 5]]
parts = qr(A)
q = parts[0] дорівнює [[0.6, -0.8], [0.8, 0.6]]
r = parts[1] дорівнює [[5, 4], [0, 3]]
q * r дорівнює [[3, 0], [4, 5]]

Добуток множників знову дає A, тому розклад легко перевірити. Двійкова арифметика з рухомою комою залишає дрібні похибки округлення близько 10⁻¹⁵; у списках і матрицях Varlig показує їх як 0. Збережені значення містять усі цифри, тому порівнюйте результати розкладів візуально або за різницею, а не через ==.

calc
lu([[2, 1], [4, 3]]) дорівнює [[[0, 1], [1, 0]], [[1, 0], [0.5, 1]], [[4, 3], [0, -0.5]]]

lu повертає [P, L, U], де P зберігає перестановки рядків, а P * A дорівнює L * U. Тут рядки поміняли місцями, щоб спочатку використати більше число — 4.

calc
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 дорівнює [[3, 1], [4, 7]]
svd([[3, 4]]) дорівнює [[[1]], [5], [[0.6, 0.8]]]

svd повертає [U, s, Vt], де s — одновимірний список сингулярних значень за спаданням. У підручниках B дорівнює U * diag(s) * Vt. Функції diag немає, тому створіть діагональну матрицю самостійно, наприклад [[s[0], 0], [0, s[1]]].

Функція Вимоги й результат
identity(n) Одинична матриця розміром n на n
shape(A) [rows, columns]
transpose(A) Рядки й стовпці поміняні місцями
det(A) Визначник квадратної матриці
inverse(A) Обернена до квадратної матриці з ненульовим визначником
trace(A) Сума діагональних елементів квадратної матриці
rank(A) Кількість незалежних рядків; будь-яка прямокутна матриця
solve_system(A,b) Розв'язок A * x = b для квадратної матриці з єдиним розв'язком
eigenvalues(A) Власні значення квадратної матриці, можливо комплексні, без визначеного порядку
qr(A) [Q, R], де Q * R приблизно дорівнює A; будь-яка прямокутна матриця
lu(A) [P, L, U], де P * A приблизно дорівнює L * U; квадратна матриця
svd(A) [U, s, Vt], де s — одновимірний список; будь-яка прямокутна матриця

Для неквадратної матриці qr і svd повертають скорочені множники: для матриці 3 на 2 матриця Q також має розмір 3 на 2, а не 3 на 3.

Точні результати й неприпустимі операції

Додавання, віднімання й множення матриць, множення на число, transpose, det та inverse обчислюються точними дробами для всіх підтримуваних матриць. Значення не округлюються ні на вході, ні перед подальшими обчисленнями, тому добуток матриці на її обернену дає точно одиничну матрицю:

calc
[[1, 2], [3, 4]] + [[10, 20], [30, 40]] дорівнює [[11, 22], [33, 44]]
[[1, 2], [3, 4]] - [[1, 1], [1, 1]] дорівнює [[0, 1], [2, 3]]
3 * [[1, 2], [3, 4]] дорівнює [[3, 6], [9, 12]]
[[1, 2], [3, 4]] * [[0, 1], [1, 0]] дорівнює [[2, 1], [4, 3]]
det([[1, 2], [3, 4]]) дорівнює -2
inverse([[1, 2], [3, 4]]) дорівнює [[-2, 1], [1.5, -0.5]]
inverse([[1, 2], [3, 4]]) * [[1, 2], [3, 4]] дорівнює [[1, 0], [0, 1]]

Перед показом відповіді перевіряються всі умови; повідомлення називає порушену:

calc
det([[1, 2, 3], [4, 5, 6]]) дорівнює Unsupported: Expected a square matrix
inverse([[1, 2], [2, 4]]) дорівнює Unsupported: Singular matrix has no inverse
[[1, 2], [3, 4]] + [[1, 2, 3], [4, 5, 6]] дорівнює Unsupported: List dimensions do not match
[[1, 2, 3], [4, 5, 6]] * [[1, 2], [3, 4]] дорівнює Unsupported: Matrix inner dimensions do not match

Елементи матриці — числа без одиниць. Одиниця, гроші або комплексне значення зупиняють обчислення, оскільки матричні операції не зберегли б їхній зміст:

calc
det([[1 kg, 2], [3, 4]]) дорівнює Unsupported: Matrix entries must be plain numbers; units, money and complex values are not supported

Матрицею вважається лише список рядків. Одновимірний список зберігає своє значення: [1, 2] + [3, 4] дає поелементне [4, 6], а [1, 2] * [3, 4] — помилку з підказкою dot.

Спільні правила точності рівнянь, матриць і статистики зібрано в розділі Гарантії обчислювального рушія.

Алгоритми й обмеження

det, inverse, rank і solve_system використовують точні дроби в межах допустимого розміру числа. eigenvalues, qr, lu та svd працюють із двійковими числами з рухомою комою й дають близькі наближення. Ітерації зупиняються після 10 000 кроків.

Матриці з майже залежними рядками, як-от [[1, 1], [1, 1.0000001]], називають погано обумовленими. Невеликі похибки округлення в них значно зростають, тому розклади й власні значення можуть втрачати точність. У крайніх випадках перевищуються числові межі й виникає помилка.

Повні правила наведено в довіднику з вищої математики.

Поєднання можливостей

У трьох чеках із ринку записано кількість яблук, бананів і апельсинів та загальну суму, але не ціни за штуку:

calc
# Each row: apples, bananas, oranges
baskets = [[2, 3, 1], [1, 2, 3], [4, 1, 2]]
paid = [2.15, 2.70, 3.05]
det(baskets) дорівнює 25
prices = solve_system(baskets, paid) дорівнює [0.4, 0.25, 0.6]
# Check the prices against every receipt
baskets * transpose([prices]) дорівнює [[2.15], [2.7], [3.05]]
# What would 5 apples, 2 bananas and 4 oranges cost?
dot([5, 2, 4], prices) дорівнює 4.9

Ненульовий визначник підтверджує, що чеків достатньо для єдиного набору цін: яблуко — 40 пенсів, банан — 25, апельсин — 60. Множення матриці покупок на стовпець цін відтворює суми, а dot оцінює новий кошик у £4,90.