【问题标题】:Networkx: How to find all unique paths of max given length in an unweighted, undirected, unlabeled, connected graph?Networkx:如何在未加权,无向,未标记,连通图中找到最大给定长度的所有唯一路径?
【发布时间】:2019-12-20 01:07:34
【问题描述】:

假设我有以下未加权(所有边权重 = 1)、无向、未标记、连通图,并且我想找到最大给定长度的所有唯一路径。此外,节点不能在路径中出现两次。我在 networkx atm 中找不到执行此操作的例程。

有谁知道这样的事情是否存在? 或者有什么好的方法可以解决这个问题?

import networkx as nx
G = nx.Graph()
G.add_nodes_from([1, 2, 3, 4, 5, 6, 7, 8, 9])
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (2, 4), (6, 9), (8, 9), (9, 6)])

示例图如下所示

假设我需要最大长度 = 2,我想要这个输出

[1 2]
[2 3]
[2 4]
[3 4]
[4 5]
[5 6]
[6 7]
[7 8]
[8 9]
[6 9]
[1 2 3]
[1 2 4]
[2 3 4]
[2 4 5]
[3 4 5]
[4 5 6]
[5 6 7]
[5 6 9]
[6 7 9]
[6 7 8]
[7 8 9]
[6 9 8]

编辑:我正在寻找一个更好的解决方案,而不是使用 itertools 生成 required_max_path_length-1 节点数的所有节点组合 + 使用 G.has_edge(node_1, node_2) 在组合组或类似的东西中检查连通性,这似乎是一个非常糟糕的解决方案。

【问题讨论】:

  • 小于2的路径怎么办?
  • 这也是必需的,我正在编辑我的例子谢谢
  • 看看all_simple_paths。它允许您指定截止值。它仍然是 n^2 因为您需要指定每个开始和结束节点
  • 我在考虑all_simple_paths,但必须指定开始和结束节点让我觉得这是一个糟糕的解决方案。但是您是说使用itertools 获得所有成对节点组合+all_simple_paths 在每个节点组合之间以最大长度截止+过滤所有生成的路径以获得唯一性,对吗?我猜它会起作用,但我仍然想知道是否有更好的解决方案。
  • 你不应该需要 itertools。

标签: python-3.x networkx enumeration


【解决方案1】:

所以现在我正在向@user3483203 执行此操作,它会产生预期的输出。可以避免使用 Itertools,但在我的具体情况下我不介意。

我仍然觉得它会比其他更大的图表更糟糕,如果有人找到更好的解决方案,我会改变接受的答案。

import networkx as nx
import itertools

required_max_path_length = 2 # (inferior or equal to)

G = nx.Graph()
G.add_nodes_from([1, 2, 3, 4, 5, 6, 7, 8, 9])
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (2, 4), (6, 9), (8, 9), (9, 6)])

all_paths = []
nodes_combs = itertools.combinations(G.nodes, 2)

for source, target in nodes_combs:
    paths = nx.all_simple_paths(G, source=source, target=target, cutoff=required_max_path_length)

    for path in paths:
        if path not in all_paths and path[::-1] not in all_paths:
            all_paths.append(path)

for path in all_paths:
    print(path)

如果您希望将路径作为边列表,您可以这样做:

for path in map(nx.utils.pairwise, all_paths):
    print(list(path))

你会得到:

[(1, 2)]
[(1, 2), (2, 3)]
[(1, 2), (2, 4)]
[(2, 3)]
[(2, 3), (3, 4)]
[(2, 4)]
[(2, 4), (4, 5)]
[(3, 4)]
[(3, 4), (4, 5)]
[(4, 5)]
[(4, 5), (5, 6)]
[(5, 6)]
[(5, 6), (6, 7)]
[(5, 6), (6, 9)]
[(6, 7)]
[(6, 7), (7, 8)]
[(6, 8), (8, 9)]
[(6, 9)]
[(7, 8)]
[(6, 7), (7, 9)]
[(7, 8), (8, 9)]
[(8, 9)]

【讨论】:

    【解决方案2】:

    以下代码应该可以解决您的任务,但它输出的路径比您提供的要多(例如 [1,2][2,1]):

    def find_all_simple_paths(graph, cutoff):
    
        if cutoff == 0:
            return [[node] for node in graph]
        else:
            all_paths = []
            current_paths = [[node] for node in graph]
            # If you want to include paths of length 0
            # all_paths.extend(current_paths)
            for _ in range(min(cutoff, len(graph))):
                next_paths = []
                for path in current_paths:
                    #print(path)
                    for neighbor in graph.neighbors(path[-1]):
                        if neighbor not in path:
                            new_path = path[:] + [neighbor]
                            next_paths.append(new_path)
                            all_paths.append(new_path)
                current_paths = next_paths
    
            return all_paths
    find_all_simple_paths(G,2)
    

    输出

    [[1, 2],
     [2, 1],
     [2, 3],
     [2, 4],
     [3, 2],
     [3, 4],
     [4, 3],
     [4, 5],
     [4, 2],
     [5, 4],
     [5, 6],
     [6, 5],
     [6, 7],
     [6, 9],
     [7, 6],
     [7, 8],
     [8, 7],
     [8, 9],
     [9, 6],
     [9, 8],
     [1, 2, 3],
     [1, 2, 4],
     [2, 3, 4],
     [2, 4, 3],
     [2, 4, 5],
     [3, 2, 1],
     [3, 2, 4],
     [3, 4, 5],
     [3, 4, 2],
     [4, 3, 2],
     [4, 5, 6],
     [4, 2, 1],
     [4, 2, 3],
     [5, 4, 3],
     [5, 4, 2],
     [5, 6, 7],
     [5, 6, 9],
     [6, 5, 4],
     [6, 7, 8],
     [6, 9, 8],
     [7, 6, 5],
     [7, 6, 9],
     [7, 8, 9],
     [8, 7, 6],
     [8, 9, 6],
     [9, 6, 5],
     [9, 6, 7],
     [9, 8, 7]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      相关资源
      最近更新 更多