Определение. Функция называется линейной, если для неё выполнено:
Например, линейными являются:
- Функция, которая «растягивает» вектор в раз: .
- Функция, которая поворачивает вектор на плоскости на угол .
- Функция, которая проецирует трёхмерный вектор на какую-нибудь плоскость.
- Скалярное произведение также линейно по обоим параметрам.
Из одних лишь двух пунктов в определении можно вывести много полезных свойств:
- Сумма линейных функций является линейной функцией.
- Композиция линейных функций является линейной функцией.
- Сумма линейных функций коммутативна: .
- Сумма линейных функций ассоциативна: .
- Композиция линейных функций ассоциативна: .
- Композиция в общем случае не коммутативна. Пример: — поворот точки на плоскости на прямой угол, — проекция на . Почти для всех точек плоскости важен порядок этих двух операций.
Линейная алгебра занимается изучением линейных функций.
#Матрицы
Можно показать, что любую линейную функцию можно представить в следующем виде:
Матрицы представляют собой просто очень компактную запись этих коэффициентов .Каждой линейной функции из в соответствует какая-то матрица размера и наоборот. Число равно количеству строк, а — количеству столбцов. Элемент на пересечении -ой строки и -го столбца будем обозначать . Не перепутайте.
#Связь с векторами
Если вектор — это упорядоченный набор скаляров, то матрицу можно рассматривать как вектор векторов. Вектор, в частности, можно представить как матрицу, у которой одна из размерностей равна единице — тогда его называют вектор-столбец либо вектор-строка.
typedef vector<vector<int>> matrix;
Ещё есть тензоры — ими называют все объекты ещё более высокого порядка: векторы матриц (трёхмерный тензор), матрицы матриц (четырёхмерный тензор) и векторы матриц матриц и так далее.

У тензоров есть своя интересная алгебра, но в контекстах, в которых с ними сталкивается обычный программист, никакая алгебра, как правило, не подразумевается, и этот термин используется лишь потому, что в словосочетании «многомерный массив» слишком много букв.
#Матричное умножение
Пусть линейной функции соответствует матрица , а функции соответствует матрица . Тогда композиции этих функций будет соответствовать произведение матриц и , определяемое следующим образом:
Читатель может убедиться в этом, аккуратно расписав подстановку формул для на вход .
При перемножении матриц руками удобно думать так: элемент на пересечении -го столбца и -той строки — это скалярное произведение -той строки и -того столбца . Заметим, что это накладывает ограничение на размерности перемножаемых матриц: если первая матрица имеет размер , то вторая должна иметь размер , то есть «средние» размерности должны совпадать.

Исходное выражение для теперь можно компактно записать как вместо уравнений с слагаемыми в каждом.
Напишем функцию, реализующую матричное умножение:
const int n, k, m;
matrix matmul(matrix a, matrix b) {
matrix c(n, vector<int>(m, 0));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int t = 0; t < k; t++)
c[i][j] += a[i][t] * b[t][j];
return c;
}
Такая реализация хоть и наиболее простая, но не оптимальная: мы на каждой итерации двигаем указатель для на шагов вперёд, что приводит к лишним загрузкам кэш-линий и не позволяет компилятору применить автовекторизацию. Однако это легко исправить, если перед всеми циклами транспонировать , то есть поменять каждый её -тый элемент на -тый — такая реализация будет работать в 5-10 раз быстрее.
Существуют способы соптимизировать матричное умножение и сильно дальше — в 50-100 раз по сравнению с наивным — но они выходят далеко за рамки этой статьи. Также наука знает способы способы перемножать матрицы асимптотически быстрее чем , но на практике они становятся эффективными только на матрицах от нескольких тысяч элементов.
#Свойства матриц
К матрицам не нужно относиться как к табличкам, в которых стоят какие-то числа. Каждой матрице соответствует какая-то линейная функция, как-то преобразующая вектора. Центральными объектами линейной алгебры являются именно линейные функции, а не матрицы.
Благодаря этому взаимно однозначному соотношению все ранее упомянутые свойства линейных функций переносятся и на матрицы:
- Сумма матриц и тоже является матрицей: .
- Сумма матриц коммутативна: .
- Сумма матриц ассоциативна: .
- Умножение матриц ассоциативно: .
- Умножение матриц в общем случае не коммутативно.
Матрицы не обязательно рассматривать только для действительных чисел — все эти свойства переносятся на произвольные поля: множества, для которых определены и с определенными ограничениями на операции.
Самый популярный класс таких полей — остатки по простому модулю. В частном случае, когда , в поле будет всего два элемента — ноль и единица — а также xor
в качестве сложения и and
в качестве умножения. Это позволяет эффективно хранить матрицы в виде битовых последовательностей.
#Примеры матриц
Матрица «увеличь всё в два раза»:
Матрица «поменяй и местами»: Матрица поворота на угол на плоскости: Матрица проецирования на плоскость в трёхмерном пространстве: Матрица «ничего не делай», также известная как единичная матрица: Единичную матрицу обычно обозначают как или . На её главной диагонали всегда единицы, а вне — нули.