Если ваша матрица обратима, кофактор связан с обратным:
def matrix_cofactor(matrix):
return np.linalg.inv(matrix).T * np.linalg.det(matrix)
Это дает большие ускорения (~ 1000x для матриц 50x50).Основная причина фундаментальна: это алгоритм O(n^3)
, в то время как алгоритм на основе второстепенных является O(n^5)
.
Это, вероятно, означает, что и для необратимых матриц существует некоторый разумный способвычислить кофактор (т. е. использовать не математическую формулу, которую вы используете выше, а какое-то другое эквивалентное определение).
Если вы придерживаетесь подхода, основанного на детях, то вы можете сделать следующее:
Большую часть времени, похоже, проводят внутри det
.(Проверьте line_profiler , чтобы узнать это сами.) Вы можете попытаться ускорить эту часть, связав Numpy с Intel MKL, но кроме этого, мало что можно сделать.
Вы можете ускорить другую часть кода следующим образом:
minor = np.zeros([nrows-1, ncols-1])
for row in xrange(nrows):
for col in xrange(ncols):
minor[:row,:col] = matrix[:row,:col]
minor[row:,:col] = matrix[row+1:,:col]
minor[:row,col:] = matrix[:row,col+1:]
minor[row:,col:] = matrix[row+1:,col+1:]
...
Это дает 10-50% общего времени выполнения в зависимости от размера ваших матриц.Исходный код имеет Python range
и манипуляции со списком, которые медленнее, чем прямая индексация фрагментов.Вы также можете попытаться быть более умным и скопировать только те части второстепенных, которые действительно меняются, однако уже после вышеуказанного изменения почти * 100% времени тратится внутри numpy.linalg.det
, так что дальнейшая оптимизация других частейне имеет особого смысла.