【问题标题】:All shortest paths in networkx subject to routing criterianetworkx 中的所有最短路径均受路由标准约束
【发布时间】:2021-12-08 02:48:49
【问题描述】:

我有一个加权无向图(~90 个节点,~120 个边),我想在其中找到节点子集的所有组合之间的最短路径,存储为列表“endPoints”。最短路径受以下几个标准的约束:

  1. 对于 endPoints 中 (s)source 和 (d)estination 节点的每种组合,图中都有一组不同的中间节点,我需要最短路径来包含
  2. 对于 s 和 d 的每种组合,都有一组不同的中间节点,我需要最短路径来排除
  3. 对于 s 和 d 的每个组合,可以选择遍历图中未在 1) 或 2) 中指定的任何其他节点。

例如对于包含节点 A-E 的图,我想找到 AB、AC、AD、AE、BC、BD、BE、CD、CE、DE 之间的最短路径。对于 AE,路径必须经过 B 和 C,但不能经过 D;对于 BD,路径必须经过 A,不得经过 C,可以选择经过 E,等等。

我认为使用的方法是在图中找到每个 s 和 d 之间的所有简单路径,然后对它们进行迭代,排除那些不符合标准 1) 和 2) 的路径,然后找到每个路径的最短路径剩余的 s 和 d 组合使用 nx.shortest_path。

查找所有简单路径会返回每个 s-d 对的生成器对象,我不确定如何迭代这些 s,d 生成器以应用标准 1) 和 2)

谁能帮助下一步(或建议替代方法)吗?

from itertools import combinations

allPaths = []
for s, d in combinations(endPoints, 2):
    allPaths.append((s, d, nx.all_simple_paths(G, s, d, cutoff=999)))

allPaths 

返回

[('ep01',
  'ep02',
  <generator object _all_simple_paths_graph at 0x0000025656C91BC8>),
 ('ep01',
  'ep03',
  <generator object _all_simple_paths_graph at 0x0000025656C91C48>),
 etc.

【问题讨论】:

    标签: python networkx graph-databases


    【解决方案1】:

    你可以这样做:

    import networkx as nx
    from itertools import combinations
    
    def check_criteria(path, include, exclude):
        path_set = set(path)
        return include <= path_set and exclude.isdisjoint(path_set)
    
    min_paths = {}
    for s, d in combinations(end_points, 2):
        min_len = None
        paths = []
        for path in nx.all_simple_paths(G, s, d):
            if check_criteria(path, includes[s, d], excludes[s, d]):
                path_len = nx.path_weight(G, path, "weight")
                if min_len is None:
                    min_len = path_len
                if path_len == min_len:
                    paths.append(path)
                elif path_len < min_len:
                    paths = [path]
                    min_len = path_len
        min_paths[s, d] = paths
    

    编辑: 如果您也想收集路径的长度,那么您可以将路径和长度都打包到一个元组中:

                ...
                if path_len == min_len:
                    paths.append((path, path_len))
                elif path_len < min_len:
                    paths = [(path, path_len)]
                ...
    

    假设:

    • 所需的“包含”/“排除”存储在名为 includes/excludes 的字典中。
    • 路径长度是边缘权重的总和(边缘属性"weight"),因此可以通过nx.path_weight 计算。如果不是这种情况,则进行相应调整(例如,将 nx.path_weight(...) 替换为 len(path) 等)。

    以下示例有望说明这一点:

    import networkx as nx
    from itertools import combinations
    from random import seed, random, sample, randint
    
    seed(12345)
    n = 20
    G = nx.gnp_random_graph(n, 0.2, seed=12345)
    for edge in G.edges:
        G.edges[edge]["weight"] = random()
    end_points = [0, 1, 2]
    combos = list(combinations(end_points, 2))
    nodes = set(G.nodes)
    includes = {
        c: set(sample(nodes - set(c), randint(1, 3))) for c in combos
    }
    excludes = {
        c: set(sample(nodes - includes[c].union(c), randint(1, 3))) for c in combos
    }
    
    includes = {(0, 1): {10}, (0, 2): {18, 6, 15}, (1, 2): {7}}
    excludes = {(0, 1): {2, 6}, (0, 2): {8}, (1, 2): {8, 9, 13}}
    

    结果是

    {(0, 1): [[0, 9, 11, 10, 7, 4, 1]],
     (0, 2): [[0, 6, 15, 1, 4, 18, 2]],
     (1, 2): [[1, 4, 7, 5, 11, 18, 2]]}
    

    或有长度

    {(0, 1): [([0, 9, 11, 10, 7, 4, 1], 2.062744452478362)],
     (0, 2): [([0, 6, 15, 1, 4, 18, 2], 1.2822628572757941)],
     (1, 2): [([1, 4, 7, 5, 11, 18, 2], 1.2624381263403164)]}
    

    【讨论】:

    • 谢谢@Timus,这很好,尽管我在我的数据上实现它时遇到了几个问题 - 1)return include &lt;= path_set and exclude.isdisjoint(path_set) 导致TypeError: '&lt;=' not supported between instances of 'dict' and 'set' 和 2)路径长度应该确实是基于边缘"weight" 属性,但我收到一个AttributeError module 'networkx' has no attribute 'path_weight' - 有什么想法吗?谢谢
    • @user1608180 感谢您的反馈! Re 1) 你如何构建你的 inclusion 数据?在示例中,我将 includes[s, d]excludes[s, d] 设置为设置。看来你没有。因此,要么更改您的数据设置,要么更改check_criteria 函数以将include/exclude 转换为集合(例如path_set, include, exclude = set(path), set(include), set(exclude))。
    • @user1608180 Re 2) 查看我的编辑。使用 Python 3.8 和 NetworkX 2.5 版对我来说效果很好。我添加了一个替代方案。如果您遇到更多问题,请告诉我。
    • 再次感谢。 Re 2) 我更新到最新版本的 NetworkX,现在一切正常。
    • .@Timus Re 1) 在对我的包含和排除数据进行大量搜索后,我发现了一个错误,现在这也按预期工作。但是,如果我将任何 includes 键留空,例如对于 includes = {('a', 'b'): {''}, ('a', 'c'): {'b', 'd'}} 中的 a,b - 因为没有 要求 遍历 a 和 b 之间的任何特定节点(所有节点都是 可用 只要它们不在excludes 中对应的('a', 'b') 条目)然后相关的min_path 也返回空白:('a', 'b'): [] - 我该如何解决这个问题并显示所有min_paths 的路径长度?谢谢
    猜你喜欢
    • 1970-01-01
    • 2017-11-21
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2021-11-30
    相关资源
    最近更新 更多