如何在图表中隔​​离这些(包含图像的)路径?

时间:2014-01-10 08:44:27

标签: python graph networkx

我有一个图表,想要从中隔离不同的路径。由于我无法用图解术语轻松地表达这一点,所以这是一个草图:

[Source graph (left) and intended result (right)]

左侧是源代码图的高度简化表示。该图具有仅具有2个邻居的节点(显示为蓝色方块)。然后它有交叉点和末端节点,有2个以上的邻居或正好是1个邻居(显示为红点)。

右侧,以三种不同的颜色编码,是我想要隔离的路径。我想隔离连接红点的所有路径。生成的路径不得交叉(穿过)任何红点。每条边可能只是一个不同结果路径的一部分。不应留下任何边缘(最短路径长度为1)。

我确信这是图世界中的一项已知任务。我已经在NetworkX中对图形进行了建模,我是第一次使用它,并且无法找到正确的方法来执行此操作。我确信我可以用很难的方式对它进行编码,但如果它存在的话,我会很高兴使用一种简单快速的方法。谢谢!

修改:在随机浏览NetworkX文档后,我遇到了all_simple_paths方法。我的想法现在是

  1. 迭代所有节点并识别红点(邻居数量!= 2)
  2. 对红点使用all_simple_paths()成对,收集生成的路径
  3. 对结果路径进行重复数据删除,丢弃除开始和结束节点之外的所有包含红点的内容
  4. 第2步,当然,不会很好地扩展。有了~2000个交叉点节点,这似乎仍然可能。

    编辑2: all_simple_paths似乎太慢而无法以这种方式使用它。

1 个答案:

答案 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

如果您的图表非常大并且您不想在内存中保存一组所有直接节点,那么您可以改为通过它们进行迭代,但是检查下一个邻居是否是直的会变得不那么可读(尽管可能甚至更快)。这种方法的真正问题在于你必须引入一个检查来防止直路径被多次产生。