我有一个经历循环的网络,并且对于每次迭代,其边缘都会更新其权重。其中一些增加了自己的权重,加强了两个节点之间的联系,而一些则减少了自己的权重,削弱了组成节点之间的联系。
考虑到权重作为图的属性收集为
G[node1][node2]["weight"]
,是否有一种方法可以可视化网络,即对于循环的每次迭代,那些权重相对于前一次迭代增加的边,看到它们的组件节点变得更近(它们彼此靠近),而那些变得更弱的边缘,看到它们的组件节点分离到更长的距离吗?
虽然我需要边缘接近或移开,但节点的位置应保持静态:除非边缘权重发生变化,否则节点将保留在最初设置的位置。仅当它们的边权重发生变化时,才会发生移动(朝向或远离关联节点)。
也许,最后,将其收集到
gif
中以查看运动。
任何帮助将非常感激。谢谢你。
IIUC,一个可能的选择是使用 matplotlib 的 animation :
init_pos = nx.spring_layout(G, seed=7)
def movedge(pos, p1, p2, distance):
nodes = p1, p2
p1, p2 = itemgetter(p1, p2)(pos)
curr_distance = np.linalg.norm(p2 - p1)
scale = distance / curr_distance
new_p1 = p1 + (p2 - p1) * scale
new_p2 = p2 + (p1 - p2) * scale
return {**pos, **dict(zip(nodes, (new_p1, new_p2)))}
# `drawg()` goes here.. (see full code)
fig, ax = plt.subplots(figsize=(10, 6))
N = 20
frames = {}
H = G.copy(); new_pos = init_pos.copy()
for move, rng in zip(moves, np.arange(1, len(moves) * N + 1).reshape(-1, N)):
p1, p2 = move["p1"], move["p2"]; init = H[p1][p2]["weight"]
for i, j in zip(rng, np.linspace(init, move["distance"], N).round(2)):
H[p1][p2]["weight"] = j; move["distance"] = j-init
new_pos.update(movedge(**move, pos=new_pos))
frames[i] = {"g": H.copy(), "curr_pos": movedge(**move, pos=new_pos)}
def animate(i):
ax.clear()
drawg(**frames[i + 1], ax=ax)
在笔记本中可视化它:
%matplotlib notebook
ani = FuncAnimation(
fig, animate, frames=N * len(moves), interval=150, repeat=True
)
保存 (
.gif
) :
writer = PillowWriter(
fps=15, metadata=dict(artist="Me"), bitrate=1800,
)
ani.save("output.gif", writer=writer)
使用的图表(
G
):来自networkx/docs的示例。
使用的动作:
moves = ( # some random moves
{"p1": "a", "p2": "b", "distance": 0.57},
{"p1": "c", "p2": "d", "distance": 0.12},
{"p1": "c", "p2": "f", "distance": 0.88},
{"p1": "c", "p2": "d", "distance": 0.07},
{"p1": "c", "p2": "e", "distance": 0.68},
{"p1": "a", "p2": "b", "distance": 0.59},
)