将 Numpy 数组转换为单调图 (networkx)
Convert Numpy Array to Monotone Graph (networkx)
我有一个简单的 1 和 0 数组,我想在满足以下条件的情况下使用 NetworkX 将该数组转换为图形:
- 单调
- 定向
- 加权图(go/no 去区域)
- 从左下角开始,向右工作
有一个名为 from_numpy_matrix
的内置函数
见this
目标是使用此图并显示我可以从矩阵的左下角(想想栅格数据集)到达右上角,而无需向后或向下移动。
示例数组:
array = [[0,0,1,0,0],
[1,0,0,1,0],
[1,0,1,1,0],
[0,0,1,1,0]]
myarray = np.array(array)
0 means go area, 1 means blocked.
那很有趣。
from_numpy_matrix
没有帮助,因为没有从迷宫到邻接矩阵的简单转换。相反,迭代允许的位置(即 "not wall")并检查在允许的方向(上、右、对角线右上)是否有允许的位置要容易得多。
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
def maze_to_graph(is_wall, allowed_steps):
"""
Arguments:
----------
is_wall -- 2D boolean array marking the position of walls in the maze
allowed_steps -- list of allowed steps; e.g. [(0, 1), (1, 1)] signifies that
from coming from tile (i, j) only tiles (i, j+1) and (i+1, j+1)
are reachable (iff there is no wall)
Returns:
--------
g -- networkx.DiGraph() instance
pos2idx -- dict mapping (i, j) position to node idx (for testing if path exists)
idx2pos -- dict mapping node idx to (i, j) position (for plotting)
"""
# map array indices to node indices and vice versa
node_idx = range(np.sum(~is_wall))
node_pos = zip(*np.where(~is_wall))
pos2idx = dict(zip(node_pos, node_idx))
# create graph
g = nx.DiGraph()
for (i, j) in node_pos:
for (delta_i, delta_j) in allowed_steps: # try to step in all allowed directions
if (i+delta_i, j+delta_j) in pos2idx: # i.e. target node also exists
g.add_edge(pos2idx[(i,j)], pos2idx[(i+delta_i, j+delta_j)])
idx2pos = dict(zip(node_idx, node_pos))
return g, idx2pos, pos2idx
def test():
arr = np.array([[0,0,1,0,0],
[1,0,0,1,0],
[1,0,1,1,0],
[0,0,1,1,0]]).astype(np.bool)
steps = [(0, 1), # right
(-1, 0), # up
(-1, 1)] # diagonal up-right
g, idx2pos, pos2idx = maze_to_graph(arr, steps)
nx.draw(g, pos=idx2pos, node_size=1200, node_color='w', labels=idx2pos)
start = (3, 0)
stop = (0, 4)
print "Has path: ", nx.has_path(g, pos2idx[start], pos2idx[stop])
return
我有一个简单的 1 和 0 数组,我想在满足以下条件的情况下使用 NetworkX 将该数组转换为图形:
- 单调
- 定向
- 加权图(go/no 去区域)
- 从左下角开始,向右工作
有一个名为 from_numpy_matrix
见this
目标是使用此图并显示我可以从矩阵的左下角(想想栅格数据集)到达右上角,而无需向后或向下移动。
示例数组:
array = [[0,0,1,0,0],
[1,0,0,1,0],
[1,0,1,1,0],
[0,0,1,1,0]]
myarray = np.array(array)
0 means go area, 1 means blocked.
那很有趣。
from_numpy_matrix
没有帮助,因为没有从迷宫到邻接矩阵的简单转换。相反,迭代允许的位置(即 "not wall")并检查在允许的方向(上、右、对角线右上)是否有允许的位置要容易得多。
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
def maze_to_graph(is_wall, allowed_steps):
"""
Arguments:
----------
is_wall -- 2D boolean array marking the position of walls in the maze
allowed_steps -- list of allowed steps; e.g. [(0, 1), (1, 1)] signifies that
from coming from tile (i, j) only tiles (i, j+1) and (i+1, j+1)
are reachable (iff there is no wall)
Returns:
--------
g -- networkx.DiGraph() instance
pos2idx -- dict mapping (i, j) position to node idx (for testing if path exists)
idx2pos -- dict mapping node idx to (i, j) position (for plotting)
"""
# map array indices to node indices and vice versa
node_idx = range(np.sum(~is_wall))
node_pos = zip(*np.where(~is_wall))
pos2idx = dict(zip(node_pos, node_idx))
# create graph
g = nx.DiGraph()
for (i, j) in node_pos:
for (delta_i, delta_j) in allowed_steps: # try to step in all allowed directions
if (i+delta_i, j+delta_j) in pos2idx: # i.e. target node also exists
g.add_edge(pos2idx[(i,j)], pos2idx[(i+delta_i, j+delta_j)])
idx2pos = dict(zip(node_idx, node_pos))
return g, idx2pos, pos2idx
def test():
arr = np.array([[0,0,1,0,0],
[1,0,0,1,0],
[1,0,1,1,0],
[0,0,1,1,0]]).astype(np.bool)
steps = [(0, 1), # right
(-1, 0), # up
(-1, 1)] # diagonal up-right
g, idx2pos, pos2idx = maze_to_graph(arr, steps)
nx.draw(g, pos=idx2pos, node_size=1200, node_color='w', labels=idx2pos)
start = (3, 0)
stop = (0, 4)
print "Has path: ", nx.has_path(g, pos2idx[start], pos2idx[stop])
return