Создание цепи Маркова

Написал код, а распределение вероятностей через три шага равно 1 0 0 0 0 0. Не могу это исправить. Задание:

  1. Задать цепь Маркова: множество состояний, начальное распределение (все случаи), матрицу переходных вероятностей, граф цепи Маркова.
  2. Найти распределение состояний цепи Маркова на любом шаге: вход задаем число состояний, начальное распределение, число шагов.
  3. Классифицировать состояния цепи Маркова. Вариант: Урна содержит N белых шаров. За 1 шаг из урны по схеме случайного равновероятного выбора вынимают один шар и заменяют его черным. Множество состояний – число белых шаров Мой код:
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt

def create_transition_matrix(N):
    """
    Создает матрицу переходных вероятностей для задачи.
    """
    P = np.zeros((N+1, N+1))  # Матрица переходов размером (N+1) x (N+1)

    for k in range(N+1):
        if k > 0:  # Переход в состояние k-1 (вынут белый шар)
            P[k, k-1] = k / (k + (N-k))  # k белых из общего количества
        if k < N:  # Переход в то же состояние (вынут черный шар)
            P[k, k] = (N-k) / (k + (N-k))  # (N-k) черных из общего количества

    return P


def compute_distribution(P, pi0, steps):
    """
    Вычисляет распределение вероятностей на любом шаге.
    P: матрица переходных вероятностей.
    pi0: начальное распределение (вектор длины N+1).
    steps: число шагов.
    """
    pi_t = np.array(pi0)
    for _ in range(steps):
        pi_t = pi_t @ P  # Итеративное умножение для расчета распределения
    return pi_t

def classify_states(P):
    """
    Классифицирует состояния цепи Маркова.
    P: матрица переходных вероятностей.
    """
    N = P.shape[0]
    classifications = []
    for state in range(N):
        if np.all(P[:, state] == 0):  # Проверяем, поглощающее ли состояние
            classifications.append((state, "Поглощающее"))
        else:
            classifications.append((state, "Переходное"))
    return classifications

def draw_graph(P):
    """
    Строит граф цепи Маркова.
    P: матрица переходных вероятностей.
    """
    G = nx.DiGraph()
    N = P.shape[0]

    for i in range(N):
        for j in range(N):
            if P[i, j] > 0:
                G.add_edge(i, j, weight=round(P[i, j], 2))

    pos = nx.spring_layout(G)
    nx.draw(G, pos, with_labels=True, node_size=700, node_color="lightblue", font_size=10, font_weight="bold")
    edge_labels = nx.get_edge_attributes(G, 'weight')
    nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
    plt.title("Граф цепи Маркова")
    plt.show()

# Параметры задачи
N = 5  # Число белых шаров в начале
P = create_transition_matrix(N)  # Матрица переходов

# 1. Матрица переходов и граф цепи Маркова
print("Матрица переходов P:")
print(P)

# Построим граф
draw_graph(P)

# 2. Распределение состояний
pi0 = [1] + [0] * N  # Начальное распределение: 100% белых шаров
steps = 3  # Число шагов
pi_t = compute_distribution(P, pi0, steps)

print(f"\nРаспределение вероятностей через {steps} шага(ов):")
print(pi_t)

# 3. Классификация состояний
classifications = classify_states(P)
print("\nКлассификация состояний:")
for state, class_type in classifications:
    print(f"Состояние {state}: {class_type}")


Ответы (1 шт):

Автор решения: Pak Uula

Для задачи про переходы между точками на окружности матрица вероятностей переходов выглядит так:

def create_circle_transition_matrix(N):
    """
    Создает матрицу переходных вероятностей для задачи с частицей на окружности.
    N: половина от числа точек на окружности.
    Возвращает матрицу размерностью 2N x 2N.
    """
    P = np.zeros((2*N, 2*N))  # Матрица переходов размером 2N x 2N

    for i in range(2*N):
        P[i, (i+1) % (2*N)] = 0.25  # Переход по часовой стрелке
        P[i, (i-1) % (2*N)] = 0.25  # Переход против часовой стрелки
        P[i, (i+N) % (2*N)] = 0.5   # Переход в диаметрально противоположную точку

    return P

Пример для случая восьми точек (N = 4):

N = 4  # На окружности 8 точек
P_circle = create_circle_transition_matrix(N)

print("Матрица переходов для частицы на окружности:")
print(P_circle)

# Построим граф для новой матрицы переходов
draw_graph(P_circle)
[[0.   0.25 0.   0.   0.5  0.   0.   0.25]
 [0.25 0.   0.25 0.   0.   0.5  0.   0.  ]
 [0.   0.25 0.   0.25 0.   0.   0.5  0.  ]
 [0.   0.   0.25 0.   0.25 0.   0.   0.5 ]
 [0.5  0.   0.   0.25 0.   0.25 0.   0.  ]
 [0.   0.5  0.   0.   0.25 0.   0.25 0.  ]
 [0.   0.   0.5  0.   0.   0.25 0.   0.25]
 [0.25 0.   0.   0.5  0.   0.   0.25 0.  ]]

Граф переходов для 8 точек

# 2. Распределение состояний
# Начальное распределение: точка с номером 0
p_circle_0 = [1] + [0] * (2*N-1)  
steps = 3  # Число шагов
p_circle_t = compute_distribution(P_circle, p_circle_0, steps)

print(f"\nРаспределение вероятностей через {steps} шага(ов):")
print(p_circle_t)
Распределение вероятностей через 3 шага(ов):
[0.       0.234375 0.09375  0.015625 0.3125   0.015625 0.09375  0.234375]

Полный пример в блокноте

→ Ссылка