Найти собственный вектор стохастической матрицы с собственным числом 1
Я решаю задачу из acm.timus №1766. Всё решение задачи сводится к расчёту стационарного вектора вероятностей из матрицы перехода. Составить стохастическую матрицу перехода не представляет труда, но у меня нет ни единой идеи как сделать алгоритм для нахождения её собственного вектора. На данный момент есть код для обработки ввода и составления матрицы перехода:
markov = [[0] * 65 for i in range(64)] #Стохастическая матрица переходов
for i in range(8): #Получаем построчный ввод зелюков и создаём матрицу
row = [int(x) for x in input().split()]
zeluki.append(row)
for i in range(8): #Создание стохастической матрицы
for j in range(8):
summ = 0
for x in range (-1, 2): #Для каждой клетки поля считаем количество зелюков на соседних с ней
for y in range(-1, 2):
if x or y:
if i + x >= 0 and i + x < 8 and j + y >= 0 and j + y < 8:
summ += zeluki[j + y][i + x]
for x in range (-1, 2): #Для матрицы переходов считаем вероятность перехода из одной клетки на другую
for y in range(-1, 2): #для чего делится количество зелюков на ней на сумму зелюков с соседних клеток
if x or y:
if i + x >= 0 and i + x < 8 and j + y >= 0 and j + y < 8:
markov[i + j * 8][i + x + (j + y) * 8] = zeluki[j + y][i + x]/summ
В интернете я смог найти только подобное решение задачи, но этот код в последний столбец, в котором по идее и должен быть ответ, пишет числа равные 1/64:
def addTo(j, i, d):
for k in range(65):
markov[j][k] += d * markov[i][k]
for i in range(64):
markov[i][i] -= 1
for i in range(65):
markov[63][i] = 1
for i in range(64):
normal = markov[i][i]
for j in range(65):
markov[i][j] /= normal
for j in range(64):
if i != j:
addTo(j, i, -markov[j][i])
for j in range(8):
row = ''
for i in range(8):
row += format(markov[i + j * 8][64], '.12f')
row += " "
print(row)
UPD: Добиться верного числового ответа помогло возведение матрицы перехода в квадрат, но для успешной сдачи задачи не хватает быстродействия. Можно ли как то оптимизировать это решение или надо думать в другую сторону?
n = 9
while n > 0:
markov = [[sum(e1 * e2 for e1, e2 in zip(row, column))
for column in zip(*markov)]for row in markov]
n -= 1