如何在 Python 上获取 Mesa 和 Networkx 节点之间的距离?
How to get the distance between nodes with Mesa and Networkx on Python?
我正在关注使用 Networkx 创建网络图的 Mesa 库中的 example called Virus on Network。
这是它筛选节点邻居的功能,试图用病毒感染他们。
def try_to_infect_neighbors(self):
neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
agent.state is State.SUSCEPTIBLE]
for a in susceptible_neighbors:
if self.random.random() < self.virus_spread_chance:
a.state = State.INFECTED
不过,我喜欢获取节点与其邻居之间的距离。 Mesa 的 another example called Sugarscape 似乎就是这样做的。
于是我将代码修改为:
def try_to_infect_neighbors(self):
neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
agent.state is State.SUSCEPTIBLE]
for a in susceptible_neighbors:
print('Self position:', self.pos, 'Neightbor position:', neighbor_agent.pos)
# Output: Self position: 52 Neightbor position: 13
neightbor_distance = get_distance(self.pos, neighbor_agent.pos)
# TypeError: 'int' object is not iterable
print(neightbor_distance)
if neightbor_distance <= 1:
if self.random.random() < self.virus_spread_chance:
a.state = State.INFECTED
def get_distance(pos_1, pos_2):
""" Get the distance between two point
Args:
pos_1, pos_2: Coordinate tuples for both points.
"""
x1, y1 = pos_1
x2, y2 = pos_2
dx = x1 - x2
dy = y1 - y2
return math.sqrt(dx**2 + dy**2)
在 Sugarscape 示例中,a.pos
给出了 x 和 y 位置的元组。但是在 Virus on Network 中,a.pos
给出了代理的 ID。如何在网络病毒示例中访问代理的 x 和 y 位置?我尝试通过以下变量从 a.model.G
和 a.model.grid
中搜索它们:self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
和 self.grid = NetworkGrid(self.G)
,但我无法识别它们并且我认为不应该那样隐藏。
这里是一些添加边权重或获取随机节点位置的代码(也许你想缩放它们)。
import networkx as nx
import random
num_nodes = 10
prob = .25
G = nx.erdos_renyi_graph(n=num_nodes, p=prob)
# you need to add this in the __init__ of VirusOnNetwork
for u, v in G.edges():
# add random weights between 0 and 10
G[u][v]["weight"] = random.random() * 10
# you can access these weights in the same way (G[from_node][target_node]["weight"]
print(G.edges(data=True))
# [(0, 5, {'weight': 2.3337749464751454}), (0, 9, {'weight': 6.127630949347937}), (1, 4, {'weight': 9.048896640242369}), (2, 4, {'weight': 1.4236964132196228}), (2, 6, {'weight': 4.749936581386136}), (2, 9, {'weight': 2.037644705935693}), (3, 5, {'weight': 2.296192134297448}), (3, 7, {'weight': 1.5250362478641677}), (3, 9, {'weight': 7.362866019415747}), (4, 6, {'weight': 7.365668938333058}), (5, 6, {'weight': 1.1855367672698724}), (5, 8, {'weight': 3.219373770451519}), (7, 9, {'weight': 4.025563800958256})]
# alternative node positions
# you can store them in the graph or as separate attribute of your model
pos = nx.random_layout(G)
print(pos)
#{0: array([0.8604371 , 0.19834588], dtype=float32), 1: array([0.13099413, 0.97313595], dtype=float32), 2: array([0.30455875, 0.8844262 ], dtype=float32), 3: array([0.575425, 0.517468], dtype=float32), 4: array([0.7437008 , 0.89525336], dtype=float32), 5: array([0.9664812 , 0.21694745], dtype=float32), 6: array([0.89979964, 0.33603832], dtype=float32), 7: array([0.7894464, 0.7614578], dtype=float32), 8: array([0.44350627, 0.9081728 ], dtype=float32), 9: array([0.8049214 , 0.20761919], dtype=float32)}
# you can use this position for visualisation with networkx
nx.draw(G, pos)
我正在关注使用 Networkx 创建网络图的 Mesa 库中的 example called Virus on Network。
这是它筛选节点邻居的功能,试图用病毒感染他们。
def try_to_infect_neighbors(self):
neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
agent.state is State.SUSCEPTIBLE]
for a in susceptible_neighbors:
if self.random.random() < self.virus_spread_chance:
a.state = State.INFECTED
不过,我喜欢获取节点与其邻居之间的距离。 Mesa 的 another example called Sugarscape 似乎就是这样做的。
于是我将代码修改为:
def try_to_infect_neighbors(self):
neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
agent.state is State.SUSCEPTIBLE]
for a in susceptible_neighbors:
print('Self position:', self.pos, 'Neightbor position:', neighbor_agent.pos)
# Output: Self position: 52 Neightbor position: 13
neightbor_distance = get_distance(self.pos, neighbor_agent.pos)
# TypeError: 'int' object is not iterable
print(neightbor_distance)
if neightbor_distance <= 1:
if self.random.random() < self.virus_spread_chance:
a.state = State.INFECTED
def get_distance(pos_1, pos_2):
""" Get the distance between two point
Args:
pos_1, pos_2: Coordinate tuples for both points.
"""
x1, y1 = pos_1
x2, y2 = pos_2
dx = x1 - x2
dy = y1 - y2
return math.sqrt(dx**2 + dy**2)
在 Sugarscape 示例中,a.pos
给出了 x 和 y 位置的元组。但是在 Virus on Network 中,a.pos
给出了代理的 ID。如何在网络病毒示例中访问代理的 x 和 y 位置?我尝试通过以下变量从 a.model.G
和 a.model.grid
中搜索它们:self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
和 self.grid = NetworkGrid(self.G)
,但我无法识别它们并且我认为不应该那样隐藏。
这里是一些添加边权重或获取随机节点位置的代码(也许你想缩放它们)。
import networkx as nx
import random
num_nodes = 10
prob = .25
G = nx.erdos_renyi_graph(n=num_nodes, p=prob)
# you need to add this in the __init__ of VirusOnNetwork
for u, v in G.edges():
# add random weights between 0 and 10
G[u][v]["weight"] = random.random() * 10
# you can access these weights in the same way (G[from_node][target_node]["weight"]
print(G.edges(data=True))
# [(0, 5, {'weight': 2.3337749464751454}), (0, 9, {'weight': 6.127630949347937}), (1, 4, {'weight': 9.048896640242369}), (2, 4, {'weight': 1.4236964132196228}), (2, 6, {'weight': 4.749936581386136}), (2, 9, {'weight': 2.037644705935693}), (3, 5, {'weight': 2.296192134297448}), (3, 7, {'weight': 1.5250362478641677}), (3, 9, {'weight': 7.362866019415747}), (4, 6, {'weight': 7.365668938333058}), (5, 6, {'weight': 1.1855367672698724}), (5, 8, {'weight': 3.219373770451519}), (7, 9, {'weight': 4.025563800958256})]
# alternative node positions
# you can store them in the graph or as separate attribute of your model
pos = nx.random_layout(G)
print(pos)
#{0: array([0.8604371 , 0.19834588], dtype=float32), 1: array([0.13099413, 0.97313595], dtype=float32), 2: array([0.30455875, 0.8844262 ], dtype=float32), 3: array([0.575425, 0.517468], dtype=float32), 4: array([0.7437008 , 0.89525336], dtype=float32), 5: array([0.9664812 , 0.21694745], dtype=float32), 6: array([0.89979964, 0.33603832], dtype=float32), 7: array([0.7894464, 0.7614578], dtype=float32), 8: array([0.44350627, 0.9081728 ], dtype=float32), 9: array([0.8049214 , 0.20761919], dtype=float32)}
# you can use this position for visualisation with networkx
nx.draw(G, pos)