如何在 Python 中以可视化方式制作马尔可夫链动画?

Ami*_*adi 7 python simulation animation markov-chains networkx

我想“视觉上”对马尔可夫链进行动画处理,如下所示: http: //markov.yoriz.co.uk/,但使用Python而不是html css和javascript。

我不知道是否有任何库可以使这变得简单,直到现在我设法使用 Networkx 库制作马尔可夫链的可视化表示,如下图所示,但无法将其动画化(或模拟)

到目前为止,这是我的代码:

from networkx.drawing.nx_pydot import write_dot
import networkx as nx
import matplotlib.pyplot as plt

states = [(0, 0),
          (1, 0),
          (2, 0),]


Q = [[5, 5, 0.4],
     [1, 2, 3],
     [4, 0.7, 0]
     ]


G = nx.MultiDiGraph()
labels={}
edge_labels={}

for i, origin_state in enumerate(states):
    for j, destination_state in enumerate(states):
        rate = Q[i][j]
        if rate > 0:
            G.add_edge(origin_state, destination_state, weight=rate, label="{:.02f}".format(rate))
            edge_labels[(origin_state, destination_state)] = label="{:.02f}".format(rate)



plt.figure(figsize=(10,7))
node_size = 200
pos = {state:list(state) for state in states}
nx.draw_networkx_edges(G,pos,width=1.0,alpha=0.5)
nx.draw_networkx_labels(G, pos, font_weight=2)
nx.draw_networkx_edge_labels(G, pos, edge_labels)
plt.axis('off');
plt.show()

write_dot(G, 'mc.dot')

from subprocess import check_call
nfile = 'w.png' 
check_call(['dot', '-Tpng', 'mc.dot', '-o', nfile])

import matplotlib.image as mpimg
img = mpimg.imread(nfile)
plt.axis('off')
plt.imshow(img)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

jyl*_*lls 1

您可以通过在一定数量的步骤(下面的代码中为 100)中对马尔可夫链进行采样并在每一步修改所选节点的颜色来实现这一点(请参阅此处有关如何使用 graphviz 更改节点颜色的更多信息)。然后,您可以为每个步骤创建一个网络的 png 文件,并使用 imageio 从 png 图像生成 GIF(有关如何执行此操作的更多详细信息,请参阅此处)。

下面是完整的代码:

import networkx as nx
from networkx.drawing.nx_agraph import to_agraph
import numpy as np
import imageio

#Markov chain parameters
states = [(0, 0),
          (1, 0),
          (2, 0),]


Q = [[0.2, 0.3, 0.5],
     [0.1, 0.2, 0.7],
     [0.3, 0.7, 0]
     ]

#Sampling the markov chain over 100 steps
N_steps=100
node_ind=0
node_sel=[node_ind]
for i in range(N_steps):
  temp_ni=np.random.choice(3,p=Q[node_ind])
  node_sel.append(temp_ni)
  node_ind=temp_ni

#Setting up network
G = nx.MultiDiGraph()
[G.add_node(s,style='filled',fillcolor='white',shape='circle',fixedsize='true',width=0.5) for s in states]

labels={}
edge_labels={}

for i, origin_state in enumerate(states):
    for j, destination_state in enumerate(states):
        rate = Q[i][j]
        if rate > 0:
            G.add_edge(origin_state, destination_state, weight=rate, label="{:.02f}".format(rate),len=2)

#Setting up node color for each iteration     
for k in range(N_steps):
  for i,n in enumerate(G.nodes(data=True)):
    if i==node_sel[k]:
      n[1]['fillcolor']='blue'
    else:
      n[1]['fillcolor']='white'
    
  A = to_agraph(G)
  A.layout()
  A.draw('net_'+str(k)+'.png')

#Create gif with imageio
images = []
filenames=['net_'+str(k)+'.png' for k in range(N_steps)]
for filename in filenames:
    images.append(imageio.imread(filename))
imageio.mimsave('markov_chain.gif', images,fps=3)
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此输入图像描述