我有一个图表,想要从中隔离不同的路径。由于我无法用图解术语轻松地表达这一点,所以这是一个草图:
在左侧是源代码图的高度简化表示。该图具有仅具有2个邻居的节点(显示为蓝色方块)。然后它有交叉点和末端节点,有2个以上的邻居或正好是1个邻居(显示为红点)。
右侧,以三种不同的颜色编码,是我想要隔离的路径。我想隔离连接红点的所有路径。生成的路径不得交叉(穿过)任何红点。每条边可能只是一个不同结果路径的一部分。不应留下任何边缘(最短路径长度为1)。
我确信这是图世界中的一项已知任务。我已经在NetworkX中对图形进行了建模,我是第一次使用它,并且无法找到正确的方法来执行此操作。我确信我可以用很难的方式对它进行编码,但如果它存在的话,我会很高兴使用一种简单快速的方法。谢谢!
修改:在随机浏览NetworkX文档后,我遇到了all_simple_paths方法。我的想法现在是
第2步,当然,不会很好地扩展。有了~2000个交叉点节点,这似乎仍然可能。
编辑2: all_simple_paths似乎太慢而无法以这种方式使用它。
答案 0 :(得分:2)
我建议找到所有直接节点(即只有两个邻居的节点),然后从这些节点的列表中选择所有直路径的列表一个直的节点随机并跟随它的两个导致它们的两端(第一个非直线节点)。
在代码中:
def eachStraightPath(g):
straightNodes = { node for node in g.node if len(g.edge[node]) == 2 }
print straightNodes
while straightNodes:
straightNode = straightNodes.pop()
straightPath = [ straightNode ]
neighborA, neighborB = g.edge[straightNode].keys()
while True: # break out later if node is not straight
straightPath.insert(0, neighborA)
if neighborA not in straightNodes:
break
newNeighborA = (set(g.edge[neighborA]) ^ { straightPath[1] }).pop()
straightNodes.remove(neighborA)
neighborA = newNeighborA
while True: # break out later if node is not straight
straightPath.append(neighborB)
if neighborB not in straightNodes:
break
newNeighborB = (set(g.edge[neighborB]) ^ { straightPath[-2] }).pop()
straightNodes.remove(neighborB)
neighborB = newNeighborB
yield straightPath
g = nx.lollipop_graph(5, 7)
for straightPath in eachStraightPath(g):
print straightPath
如果您的图表非常大并且您不想在内存中保存一组所有直接节点,那么您可以改为通过它们进行迭代,但是检查下一个邻居是否是直的会变得不那么可读(尽管可能甚至更快)。这种方法的真正问题在于你必须引入一个检查来防止直路径被多次产生。