Произведение матриц как композиция

Перемножить две матрицы — значит склеить два преобразования в одно: сначала одно, потом другое.

Произведение матриц $AB$ — это матрица преобразования, которое получается, если сначала применить $B$, а затем $A$.

Правило «строка на столбец» для умножения матриц на первый взгляд выглядит произвольным. Но за ним стоит ясная геометрия: умножение — это композиция функций. Если $B$ поворачивает, а $A$ растягивает, то $AB$ — «повернуть, потом растянуть». Это и объясняет, почему порядок важен.

Правило умножения

Элемент результата в строке $i$ и столбце $j$ — скалярное произведение $i$-й строки $A$ на $j$-й столбец $B$:

$$(AB)_{ij} = \sum_{t} A_{it} \, B_{tj}$$

Чтобы умножение было определено, число столбцов $A$ должно совпадать с числом строк $B$. Почему именно так? Потому что $AB$ применённое к вектору $\vec{v}$ должно давать $A(B\vec{v})$ — сначала $B$ действует на $\vec{v}$, потом $A$ на результат. Раскрыв это, мы и получаем правило строка-на-столбец.

Композиция и порядок

$$ (AB)\vec{v} = A(B\vec{v}) $$

Справа налево читается как «сначала $B$, затем $A$». Поэтому в общем случае $AB \neq BA$: повернуть-потом-растянуть и растянуть-потом-повернуть дают разный результат.

import math

def matmul(A, B):
    n, m, k = len(A), len(B[0]), len(B)
    return [[sum(A[i][t] * B[t][j] for t in range(k))
             for j in range(m)] for i in range(n)]

def rot(theta):
    c, s = math.cos(theta), math.sin(theta)
    return [[c, -s], [s, c]]

# два поворота на 90 = один поворот на 180
R90 = rot(math.pi / 2)
R180 = matmul(R90, R90)
print("R90 * R90 =", [[round(x, 3) for x in row] for row in R180])

Вывод:

R90 * R90 = [[-1.0, -0.0], [0.0, -1.0]]

Композиция подтверждается

Два поворота по $90°$ дали матрицу $\begin{bmatrix} -1 & 0 \\ 0 & -1 \end{bmatrix}$ — это поворот на $180°$, который переворачивает любой вектор. Математика композиции в точности совпала с геометрией: «дважды повернуть на $90°$» = «повернуть на $180°$».

Как работает под капотом

Тройной цикл в matmul буквально считает формулу $\sum_t A_{it} B_{tj}$: внешние индексы $i, j$ пробегают позиции результата, а внутренний $t$ — общую размерность, по которой идёт суммирование. Умножение матриц ассоциативно ($A(BC) = (AB)C$), что соответствует «применить три преобразования подряд можно группировать как угодно», но не коммутативно. Единичная матрица $I$ (единицы на диагонали) играет роль «ничего не делать»: $AI = IA = A$.

Частые ошибки

  • Читать $AB$ как «сначала $A$, потом $B$». Наоборот: преобразования применяются справа налево, сначала $B$.
  • Ожидать, что $AB = BA$. Для матриц это почти никогда не так — порядок преобразований важен.
  • Перемножать матрицы несогласованных размеров. Число столбцов левой обязано равняться числу строк правой.

Итог

  • Произведение матриц = композиция преобразований: $(AB)\vec{v} = A(B\vec{v})$.
  • Правило строка-на-столбец вытекает из требования $A(B\vec{v})$.
  • Умножение ассоциативно, но не коммутативно: $AB \neq BA$.
  • Единичная матрица $I$ — нейтральный элемент: $AI = IA = A$.
Проверьте себя
1. Произведение AB применяется к вектору как:
Aсначала A, потом B
Bсначала B, потом A
Cодновременно
DB и A нельзя комбинировать
2. Почему в общем случае AB ≠ BA?
Aиз-за ошибок округления
Bпотому что порядок применения преобразований влияет на результат
Cпотому что у матриц разные размеры
Dэто неверно, всегда AB = BA
3. Чтобы умножить матрицу A (m×n) на B (p×q), нужно чтобы:
Am = q
Bn = p (столбцы A = строки B)
Cm = p
Dвсе размеры были равны