Здесь есть некоторые проблемы:
- вы делаете не сбрасывает матрицу
result
после умножения, следовательно, вы продолжаете добавлять больше значений;и - вы никогда не назначаете
result
обратно на m
для выполнения умножения следующее .
Наивное мощностьреализация
Я думаю, что также лучше "инкапсулировать" умножение матриц в отдельную функцию, например:
def matmul(a1, a2):
m, ka = a1.shape
kb, n = a2.shape
if ka != kb:
raise ValueError()
res = np.zeros((m, n))
for i in range(m):
for j in range(n):
d = 0.0
for k in range(ka):
d += a1[i,k] * a2[k,j]
res[i, j] = d
return res
Тогда мы можем вычислить мощность этой матрицы с помощью:
m2 = m
for i in range(topow-1):
m = matmul(m, m2)
Обратите внимание, что мы можем не использовать m
здесь в качестве единственной матрицы.Так как если мы напишем m = matmul(m, m)
, то m
будет m
2
.Но это означает, что если мы выполним умножение во второй раз, мы получим m
4
вместо m
3
.
Это тогдадает ожидаемые результаты:
>>> cross = np.array([[1,0,1],[0,1,0], [1,0,1]])
>>> matmul(cross, cross)
array([[2., 0., 2.],
[0., 1., 0.],
[2., 0., 2.]])
>>> matmul(cross, matmul(cross, cross))
array([[4., 0., 4.],
[0., 1., 0.],
[4., 0., 4.]])
>>> matmul(cross, matmul(cross, matmul(cross, cross)))
array([[8., 0., 8.],
[0., 1., 0.],
[8., 0., 8.]])
Логарифмический умножение мощности
Выше можно рассчитать M n in O (n) (линейное время), но мы можем добиться большего, мы можем вычислить эту матрицу за логарифмическое время: мы делаем это, посмотрев, равна ли мощность 1
, если онато есть мы просто возвращаем матрицу, если это не так, мы проверяем, является ли мощность четной, если она четной, мы умножаем матрицу на себя и вычисляем мощность этой матрицы, но с мощностью, деленной на два, так M 2 n = (M × M) n .Если мощность нечетная , мы делаем более или менее то же самое, за исключением того, что мы умножаем его на исходное значение для M : M 2 n + 1 *1 073 * = М × (M × M) N .Например:
def matpow(m, p):
if p <= 0:
raise ValueError()
if p == 1:
return m
elif p % 2 == 0: # even
return matpow(matmul(m, m), p // 2)
else: # odd
return matmul(m, matpow(matmul(m, m), p // 2))
Выше можно написать более изящно, но я оставляю это как упражнение:).
Обратите внимание, однако, что использование массивов с пустяками для скалярных вычислений обычно меньше эффективнее, чем использование умножения матриц (и других функций).Они оптимизированы и интерпретируются , а не , и обычно значительно превосходят эквиваленты Python.Поэтому я бы очень посоветовал вам использовать их.Также проверяются функции numpy, что снижает вероятность ошибок в них.