Оператор матричного умножения
Мало кто знает, но в Python есть оператор @
, предназначенный для работы с матрицами. По умолчанию он не работает со стандартными типами данных, его можно только переопределить с помощью методов __matmul__
, __rmatmul__
(@) и __imatmul__
(@=).
Демонстрация
Так оно выглядит в коде:
A = Matrix([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
B = Matrix([[1, 2],
[3, 4],
[5, 6]])
print(A @ B)
[[22, 28], [49, 64], [76, 100]]
Определение матричного умножения
Воспользуемся определением из википедии, чтобы вспомнить линейную алгебру:
Пусть даны две прямоугольные матрицы и размерности и соответственно:
Тогда матрица размерностью :
в которой
называется их произведением.
Операция умножения двух матриц выполнима только в том случае, если число столбцов в первом сомножителе равно числу строк во втором; в этом случае говорят, что матрицы согласованы. В частности, умножение всегда выполнимо, если оба сомножителя — квадратные матрицы одного и того же порядка.
Реализация матричного умножения в Python
def matmul(a, b):
a_rows, a_cols = len(a), len(a[0])
b_rows, b_cols = len(b), len(b[0])
assert a_cols == b_rows
c = [[0 for _ in range(b_cols)] for __ in range(a_rows)]
for i in range(a_rows):
for j in range(b_cols):
c[i][j] = sum(a[i][r] * b[r][j] for r in range(b_rows))
return c
if __name__ == '__main__':
A = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
B = [[1, 2],
[3, 4],
[5, 6]]
print(matmul(A, B))
[[22, 28], [49, 64], [76, 100]]
Переопределение оператора @
Создадим класс Matrix и определим у него метод __matmul__
:
class Matrix:
def __init__(self, matrix):
self._matrix = matrix
self.rows = len(matrix)
self.cols = len(matrix[0])
def __getitem__(self, item):
return self._matrix[item]
def __matmul__(self, other: 'Matrix') -> 'Matrix':
assert self.cols == other.rows
c = [[0 for _ in range(other.cols)] for __ in range(self.rows)]
for i in range(self.rows):
for j in range(other.cols):
c[i][j] = sum(self[i][r] * other[r][j] for r in range(other.rows))
return Matrix(c)
def __repr__(self):
return str(self._matrix)
if __name__ == '__main__':
A = Matrix([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
B = Matrix([[1, 2],
[3, 4],
[5, 6]])
print(A @ B)
[[22, 28], [49, 64], [76, 100]]