【问题标题】:Find shortest path to one of many nodes with attribute查找具有属性的多个节点之一的最短路径
【发布时间】:2017-01-31 20:24:27
【问题描述】:

我有一个 networkx 图,表示大约 100 万个对象(顶点)的最小生成树。我想知道是否有一种有效的方法可以找到给定顶点和许多其他顶点之一之间的最短路径。

这是一个顶点数较少 (110) 的示例图

nodes = [(0.0, {'label': 2}) ,
         (1.0, {'label': 2}) ,
         (2.0, {'label': 0}) ,
         (3.0, {'label': 2}) ,
         (4.0, {'label': 2}) ,
         (5.0, {'label': 0}) ,
         (6.0, {'label': 0}) ,
         (7.0, {'label': 2}) ,
         (8.0, {'label': 2}) ,
         (9.0, {'label': 1}) ,
         (10.0, {'label': 0}) ,
         (11.0, {'label': 1}) ,
         (12.0, {'label': 1}) ,
         (13.0, {'label': 0}) ,
         (14.0, {'label': 1}) ,
         (15.0, {'label': 2}) ,
         (16.0, {'label': 1}) ,
         (17.0, {'label': 1}) ,
         (18.0, {'label': 2}) ,
         (19.0, {'label': 2}) ,
         (20.0, {'label': 0}) ,
         (21.0, {'label': 1}) ,
         (22.0, {'label': 1}) ,
         (23.0, {'label': 0}) ,
         (24.0, {'label': 1}) ,
         (25.0, {'label': 2}) ,
         (26.0, {'label': 0}) ,
         (27.0, {'label': 0}) ,
         (28.0, {'label': 1}) ,
         (29.0, {'label': 0}) ,
         (30.0, {'label': 2}) ,
         (31.0, {'label': 1}) ,
         (32.0, {'label': 2}) ,
         (33.0, {'label': 1}) ,
         (34.0, {'label': 1}) ,
         (35.0, {'label': 1}) ,
         (36.0, {'label': 1}) ,
         (37.0, {'label': 2}) ,
         (38.0, {'label': 0}) ,
         (39.0, {'label': 0}) ,
         (40.0, {'label': 2}) ,
         (41.0, {'label': 0}) ,
         (42.0, {'label': 1}) ,
         (43.0, {'label': 0}) ,
         (44.0, {'label': 0}) ,
         (45.0, {'label': 2}) ,
         (46.0, {'label': 0}) ,
         (47.0, {'label': 2}) ,
         (48.0, {'label': 0}) ,
         (49.0, {'label': 1}) ,
         (50.0, {'label': 0}) ,
         (51.0, {'label': 1}) ,
         (52.0, {'label': 2}) ,
         (53.0, {'label': 0}) ,
         (54.0, {'label': 1}) ,
         (55.0, {'label': 1}) ,
         (56.0, {'label': 2}) ,
         (57.0, {'label': 1}) ,
         (58.0, {'label': 1}) ,
         (59.0, {'label': 0}) ,
         (60.0, {'label': 2}) ,
         (61.0, {'label': 1}) ,
         (62.0, {'label': 1}) ,
         (63.0, {'label': 2}) ,
         (64.0, {'label': 0}) ,
         (65.0, {'label': 0}) ,
         (66.0, {'label': 0}) ,
         (67.0, {'label': 0}) ,
         (68.0, {'label': 1}) ,
         (69.0, {'label': 2}) ,
         (70.0, {'label': 0}) ,
         (71.0, {'label': 1}) ,
         (72.0, {'label': 0}) ,
         (73.0, {'label': 2}) ,
         (74.0, {'label': 0}) ,
         (75.0, {'label': 1}) ,
         (76.0, {'label': 1}) ,
         (77.0, {'label': 0}) ,
         (78.0, {'label': 2}) ,
         (79.0, {'label': 2}) ,
         (80.0, {'label': 2}) ,
         (81.0, {'label': 1}) ,
         (82.0, {'label': 2}) ,
         (83.0, {'label': 2}) ,
         (84.0, {'label': 1}) ,
         (85.0, {'label': 0}) ,
         (86.0, {'label': 1}) ,
         (87.0, {'label': 2}) ,
         (88.0, {'label': 1}) ,
         (89.0, {'label': 0}) ,
         (90.0, {'label': 0}) ,
         (91.0, {'label': 2}) ,
         (92.0, {'label': 0}) ,
         (93.0, {'label': 1}) ,
         (94.0, {'label': 1}) ,
         (95.0, {'label': 2}) ,
         (96.0, {'label': 2}) ,
         (97.0, {'label': 0}) ,
         (98.0, {'label': 2}) ,
         (99.0, {'label': 2}) ,
         (100.0, {'label': -1}) ,
         (101.0, {'label': -1}) ,
         (102.0, {'label': 1}) ,
         (103.0, {'label': -1}) ,
         (104.0, {'label': -1}) ,
         (105.0, {'label': -1}) ,
         (106.0, {'label': -1}) ,
         (107.0, {'label': 1}) ,
         (108.0, {'label': 0}) ,
         (109.0, {'label': -1})]
edges = [(0.0, 25.0, {'weight': 1.3788141613435239}) ,
         (0.0, 15.0, {'weight': 1.1948288781935414}) ,
         (1.0, 99.0, {'weight': 2.1024875417678257}) ,
         (1.0, 52.0, {'weight': 1.5298566582843918}) ,
         (2.0, 59.0, {'weight': 1.2222170767316791}) ,
         (3.0, 96.0, {'weight': 0.77235026806254947}) ,
         (3.0, 98.0, {'weight': 0.75540026318653475}) ,
         (3.0, 83.0, {'weight': 0.63745598060956865}) ,
         (4.0, 8.0, {'weight': 1.1460983565815646}) ,
         (5.0, 39.0, {'weight': 0.57882005244148982}) ,
         (6.0, 27.0, {'weight': 0.77903808587705414}) ,
         (6.0, 38.0, {'weight': 0.87763345274858739}) ,
         (7.0, 83.0, {'weight': 1.0592473391743824}) ,
         (7.0, 52.0, {'weight': 1.1650063193499598}) ,
         (8.0, 18.0, {'weight': 0.62985157194068553}) ,
         (8.0, 63.0, {'weight': 0.66061808561292024}) ,
         (9.0, 57.0, {'weight': 0.73138423240527128}) ,
         (9.0, 14.0, {'weight': 0.68690071596776681}) ,
         (10.0, 43.0, {'weight': 1.0938913337235003}) ,
         (11.0, 76.0, {'weight': 1.8066534138474315}) ,
         (11.0, 22.0, {'weight': 1.5814274601380762}) ,
         (12.0, 68.0, {'weight': 0.82964162447510292}) ,
         (12.0, 28.0, {'weight': 0.56687613489965616}) ,
         (13.0, 41.0, {'weight': 0.67883257822079479}) ,
         (13.0, 70.0, {'weight': 0.69594526555853065}) ,
         (13.0, 39.0, {'weight': 0.62690609201673064}) ,
         (14.0, 42.0, {'weight': 0.51384098628821639}) ,
         (15.0, 91.0, {'weight': 0.80363040334950342}) ,
         (15.0, 63.0, {'weight': 0.74055429404201112}) ,
         (16.0, 75.0, {'weight': 0.89225782872169068}) ,
         (16.0, 36.0, {'weight': 0.97796463842832249}) ,
         (16.0, 61.0, {'weight': 1.2426060084547763}) ,
         (17.0, 24.0, {'weight': 0.48569989925661516}) ,
         (17.0, 88.0, {'weight': 0.58411688395739225}) ,
         (17.0, 42.0, {'weight': 0.48569989925661516}) ,
         (18.0, 19.0, {'weight': 0.73750301595928458}) ,
         (18.0, 87.0, {'weight': 0.62985157194068553}) ,
         (19.0, 80.0, {'weight': 0.77740196142918039}) ,
         (20.0, 53.0, {'weight': 1.5817584651620507}) ,
         (21.0, 33.0, {'weight': 1.558483049272277}) ,
         (21.0, 35.0, {'weight': 1.022218339608882}) ,
         (22.0, 93.0, {'weight': 1.4628634684132413}) ,
         (22.0, 101.0, {'weight': 7.494583622053641}) ,
         (23.0, 97.0, {'weight': 0.86085201141197409}) ,
         (23.0, 90.0, {'weight': 1.4629842172999594}) ,
         (23.0, 65.0, {'weight': 0.94746570241498318}) ,
         (24.0, 34.0, {'weight': 0.55323853417352553}) ,
         (25.0, 104.0, {'weight': 4.9839694794161371}) ,
         (26.0, 85.0, {'weight': 1.5024751933287497}) ,
         (26.0, 46.0, {'weight': 1.2053565344116006}) ,
         (27.0, 72.0, {'weight': 0.72860577250944303}) ,
         (27.0, 92.0, {'weight': 0.74002007166874428}) ,
         (28.0, 54.0, {'weight': 0.55323853417352553}) ,
         (29.0, 50.0, {'weight': 0.81426784351619774}) ,
         (30.0, 98.0, {'weight': 0.77235026806254947}) ,
         (30.0, 78.0, {'weight': 0.79413937142096647}) ,
         (30.0, 95.0, {'weight': 0.78901093530213129}) ,
         (31.0, 68.0, {'weight': 0.98851671776185412}) ,
         (32.0, 95.0, {'weight': 0.8579399666494596}) ,
         (34.0, 54.0, {'weight': 0.55323853417352553}) ,
         (34.0, 55.0, {'weight': 0.60906522381767525}) ,
         (35.0, 62.0, {'weight': 0.66697239833732958}) ,
         (36.0, 93.0, {'weight': 1.2932994772208264}) ,
         (37.0, 80.0, {'weight': 0.85527462610640648}) ,
         (37.0, 96.0, {'weight': 0.85527462610640648}) ,
         (38.0, 46.0, {'weight': 0.95334944284759993}) ,
         (39.0, 50.0, {'weight': 0.52028039541706872}) ,
         (40.0, 69.0, {'weight': 1.7931323073700682}) ,
         (42.0, 62.0, {'weight': 0.51384098628821639}) ,
         (42.0, 81.0, {'weight': 0.5466147583189902}) ,
         (43.0, 65.0, {'weight': 1.0581157274507453}) ,
         (44.0, 108.0, {'weight': 3.0598509599260266}) ,
         (44.0, 70.0, {'weight': 1.0805691635112824}) ,
         (45.0, 56.0, {'weight': 1.3420236519319457}) ,
         (45.0, 79.0, {'weight': 1.6201017824952586}) ,
         (46.0, 53.0, {'weight': 1.070516213146298}) ,
         (47.0, 78.0, {'weight': 1.2822937333699174}) ,
         (47.0, 103.0, {'weight': 3.9053251231648707}) ,
         (48.0, 97.0, {'weight': 0.86085201141197409}) ,
         (48.0, 67.0, {'weight': 0.75656062694199944}) ,
         (49.0, 94.0, {'weight': 1.6216528905308547}) ,
         (49.0, 86.0, {'weight': 0.80157999082131093}) ,
         (49.0, 62.0, {'weight': 0.7081136236724922}) ,
         (51.0, 102.0, {'weight': 1.4704389417937378}) ,
         (51.0, 71.0, {'weight': 0.83506431983724716}) ,
         (54.0, 75.0, {'weight': 0.70074754481170742}) ,
         (55.0, 58.0, {'weight': 0.78571631647476448}) ,
         (56.0, 82.0, {'weight': 1.3387438494166808}) ,
         (57.0, 84.0, {'weight': 1.558483049272277}) ,
         (59.0, 64.0, {'weight': 1.0416266944398496}) ,
         (60.0, 98.0, {'weight': 1.2534403896544031}) ,
         (63.0, 73.0, {'weight': 0.83646303763566465}) ,
         (64.0, 72.0, {'weight': 0.8620326535711742}) ,
         (66.0, 77.0, {'weight': 0.79981721989351606}) ,
         (67.0, 72.0, {'weight': 0.74002007166874428}) ,
         (69.0, 83.0, {'weight': 1.5000235782351021}) ,
         (70.0, 77.0, {'weight': 0.75999034076724692}) ,
         (71.0, 88.0, {'weight': 0.66450874893016454}) ,
         (74.0, 97.0, {'weight': 0.8743417572549379}) ,
         (76.0, 107.0, {'weight': 2.0300278349030831}) ,
         (77.0, 89.0, {'weight': 0.75999034076724692}) ,
         (79.0, 106.0, {'weight': 4.5661761296968333}) ,
         (82.0, 95.0, {'weight': 1.083633962514291}) ,
         (84.0, 99.0, {'weight': 2.1024875417678257}) ,
         (89.0, 92.0, {'weight': 0.75419548272456249}) ,
         (100.0, 107.0, {'weight': 2.9259491743365307}) ,
         (101.0, 109.0, {'weight': 7.6747981730730297}) ,
         (102.0, 108.0, {'weight': 4.3128725576385092}) ,
         (104.0, 105.0, {'weight': 7.5515191839631273})]
G2 = nx.Graph()
G2.add_nodes_from(nodes)
G2.add_edges_from(edges)

我想要的是“标签 >= 0 的顶点最接近标签 = -1 的每个顶点”。对于像这样的小图,使用类似nx.all_pairs_dijkstra_path_length() 然后检查标签的蛮力方法可以正常工作,但它不能扩展到非常大的图。是否有更有效的算法,尤其是内置于 networkx 的算法,我可以使用?

更新:

我使用理查德的出色建议和下面的评论来写这篇文章。我真正想要的是一系列标签,我认为这使得事情不像 Richard 在 networkx 中提到的那样混乱。在一个数据集上,整个重新标记需要 45 秒,而暴力破解需要一个小时!

def relabel(G, indices_to_relabel):
    """ 
    Update the anomaly labels to be the closest cluster.
    """
    # Add a "special" node that has zero weight to all the cluster nodes
    print('Adding special node')
    G.add_node('special', {'label': 'special'})
    special_edges = [(n, 'special', {'weight': 0}) 
                     for n, ndat in G.nodes_iter(data=True) 
                     if ndat['label'] != 'special' and ndat['label'] >= 0]
    G.add_edges_from(special_edges)

    print('Calculating path from special node to all other nodes')
    paths = nx.shortest_path(G, source='special', target=None, weight='weight')

    print('Updating labels')
    new_labels = np.array([ndat['label'] for _, ndat in G.nodes_iter(data=True)])
    new_labels[indices_to_relabel] = [G.node[paths[n][1]]['label'] for n in indices_to_relabel]

    # Clean up
    G.remove_node('special')
    return new_labels

【问题讨论】:

  • 这里有边长吗?或者他们是统一的

标签: python algorithm graph-theory networkx


【解决方案1】:

我认为 networkx 中没有内置这样的算法,但似乎有一种算法可以扩展最小成本路径直到达到某个条件是明智的。然而,即使 networkx 不包含这样的功能,也很容易构建一个算法来做到这一点。

  • 调用源节点为label==-1的节点。
  • 使用label>=0 调用最接近其目标节点的源节点的节点。我们的目标是找到目标节点。
  • 创建一个新节点。这将是 special 节点。
  • 将所有潜在目标节点连接到权重为 0 的特殊节点。
  • 对于每个源节点,找到到特殊节点的最短路径。此路径上的倒数第二个节点必然是目标节点,并且是最接近源节点的节点。
  • 完成后,消除特殊节点及其所有连接边。

如果源节点数为S,则该算法运行时间O(S(|E|+|V| log |V|))时间(假设最短路径算法是 Dijkstra)。

(可能是我误解了您是否希望 -1 最接近 >=0 或 >=0 最接近 -1。如果我有,只需反转源/目标标签。)

#!/usr/bin/env python3

import networkx as nx

nodes = [(0.0, {'label': 2}) ,
         (1.0, {'label': 2}) ,
         (2.0, {'label': 0}) ,
         (3.0, {'label': 2}) ,
         (4.0, {'label': 2}) ,
         (5.0, {'label': 0}) ,
         (6.0, {'label': 0}) ,
         (7.0, {'label': 2}) ,
         (8.0, {'label': 2}) ,
         (9.0, {'label': 1}) ,
         (10.0, {'label': 0}) ,
         (11.0, {'label': 1}) ,
         (12.0, {'label': 1}) ,
         (13.0, {'label': 0}) ,
         (14.0, {'label': 1}) ,
         (15.0, {'label': 2}) ,
         (16.0, {'label': 1}) ,
         (17.0, {'label': 1}) ,
         (18.0, {'label': 2}) ,
         (19.0, {'label': 2}) ,
         (20.0, {'label': 0}) ,
         (21.0, {'label': 1}) ,
         (22.0, {'label': 1}) ,
         (23.0, {'label': 0}) ,
         (24.0, {'label': 1}) ,
         (25.0, {'label': 2}) ,
         (26.0, {'label': 0}) ,
         (27.0, {'label': 0}) ,
         (28.0, {'label': 1}) ,
         (29.0, {'label': 0}) ,
         (30.0, {'label': 2}) ,
         (31.0, {'label': 1}) ,
         (32.0, {'label': 2}) ,
         (33.0, {'label': 1}) ,
         (34.0, {'label': 1}) ,
         (35.0, {'label': 1}) ,
         (36.0, {'label': 1}) ,
         (37.0, {'label': 2}) ,
         (38.0, {'label': 0}) ,
         (39.0, {'label': 0}) ,
         (40.0, {'label': 2}) ,
         (41.0, {'label': 0}) ,
         (42.0, {'label': 1}) ,
         (43.0, {'label': 0}) ,
         (44.0, {'label': 0}) ,
         (45.0, {'label': 2}) ,
         (46.0, {'label': 0}) ,
         (47.0, {'label': 2}) ,
         (48.0, {'label': 0}) ,
         (49.0, {'label': 1}) ,
         (50.0, {'label': 0}) ,
         (51.0, {'label': 1}) ,
         (52.0, {'label': 2}) ,
         (53.0, {'label': 0}) ,
         (54.0, {'label': 1}) ,
         (55.0, {'label': 1}) ,
         (56.0, {'label': 2}) ,
         (57.0, {'label': 1}) ,
         (58.0, {'label': 1}) ,
         (59.0, {'label': 0}) ,
         (60.0, {'label': 2}) ,
         (61.0, {'label': 1}) ,
         (62.0, {'label': 1}) ,
         (63.0, {'label': 2}) ,
         (64.0, {'label': 0}) ,
         (65.0, {'label': 0}) ,
         (66.0, {'label': 0}) ,
         (67.0, {'label': 0}) ,
         (68.0, {'label': 1}) ,
         (69.0, {'label': 2}) ,
         (70.0, {'label': 0}) ,
         (71.0, {'label': 1}) ,
         (72.0, {'label': 0}) ,
         (73.0, {'label': 2}) ,
         (74.0, {'label': 0}) ,
         (75.0, {'label': 1}) ,
         (76.0, {'label': 1}) ,
         (77.0, {'label': 0}) ,
         (78.0, {'label': 2}) ,
         (79.0, {'label': 2}) ,
         (80.0, {'label': 2}) ,
         (81.0, {'label': 1}) ,
         (82.0, {'label': 2}) ,
         (83.0, {'label': 2}) ,
         (84.0, {'label': 1}) ,
         (85.0, {'label': 0}) ,
         (86.0, {'label': 1}) ,
         (87.0, {'label': 2}) ,
         (88.0, {'label': 1}) ,
         (89.0, {'label': 0}) ,
         (90.0, {'label': 0}) ,
         (91.0, {'label': 2}) ,
         (92.0, {'label': 0}) ,
         (93.0, {'label': 1}) ,
         (94.0, {'label': 1}) ,
         (95.0, {'label': 2}) ,
         (96.0, {'label': 2}) ,
         (97.0, {'label': 0}) ,
         (98.0, {'label': 2}) ,
         (99.0, {'label': 2}) ,
         (100.0, {'label': -1}) ,
         (101.0, {'label': -1}) ,
         (102.0, {'label': 1}) ,
         (103.0, {'label': -1}) ,
         (104.0, {'label': -1}) ,
         (105.0, {'label': -1}) ,
         (106.0, {'label': -1}) ,
         (107.0, {'label': 1}) ,
         (108.0, {'label': 0}) ,
         (109.0, {'label': -1})]
edges = [(0.0, 25.0, {'weight': 1.3788141613435239}) ,
         (0.0, 15.0, {'weight': 1.1948288781935414}) ,
         (1.0, 99.0, {'weight': 2.1024875417678257}) ,
         (1.0, 52.0, {'weight': 1.5298566582843918}) ,
         (2.0, 59.0, {'weight': 1.2222170767316791}) ,
         (3.0, 96.0, {'weight': 0.77235026806254947}) ,
         (3.0, 98.0, {'weight': 0.75540026318653475}) ,
         (3.0, 83.0, {'weight': 0.63745598060956865}) ,
         (4.0, 8.0, {'weight': 1.1460983565815646}) ,
         (5.0, 39.0, {'weight': 0.57882005244148982}) ,
         (6.0, 27.0, {'weight': 0.77903808587705414}) ,
         (6.0, 38.0, {'weight': 0.87763345274858739}) ,
         (7.0, 83.0, {'weight': 1.0592473391743824}) ,
         (7.0, 52.0, {'weight': 1.1650063193499598}) ,
         (8.0, 18.0, {'weight': 0.62985157194068553}) ,
         (8.0, 63.0, {'weight': 0.66061808561292024}) ,
         (9.0, 57.0, {'weight': 0.73138423240527128}) ,
         (9.0, 14.0, {'weight': 0.68690071596776681}) ,
         (10.0, 43.0, {'weight': 1.0938913337235003}) ,
         (11.0, 76.0, {'weight': 1.8066534138474315}) ,
         (11.0, 22.0, {'weight': 1.5814274601380762}) ,
         (12.0, 68.0, {'weight': 0.82964162447510292}) ,
         (12.0, 28.0, {'weight': 0.56687613489965616}) ,
         (13.0, 41.0, {'weight': 0.67883257822079479}) ,
         (13.0, 70.0, {'weight': 0.69594526555853065}) ,
         (13.0, 39.0, {'weight': 0.62690609201673064}) ,
         (14.0, 42.0, {'weight': 0.51384098628821639}) ,
         (15.0, 91.0, {'weight': 0.80363040334950342}) ,
         (15.0, 63.0, {'weight': 0.74055429404201112}) ,
         (16.0, 75.0, {'weight': 0.89225782872169068}) ,
         (16.0, 36.0, {'weight': 0.97796463842832249}) ,
         (16.0, 61.0, {'weight': 1.2426060084547763}) ,
         (17.0, 24.0, {'weight': 0.48569989925661516}) ,
         (17.0, 88.0, {'weight': 0.58411688395739225}) ,
         (17.0, 42.0, {'weight': 0.48569989925661516}) ,
         (18.0, 19.0, {'weight': 0.73750301595928458}) ,
         (18.0, 87.0, {'weight': 0.62985157194068553}) ,
         (19.0, 80.0, {'weight': 0.77740196142918039}) ,
         (20.0, 53.0, {'weight': 1.5817584651620507}) ,
         (21.0, 33.0, {'weight': 1.558483049272277}) ,
         (21.0, 35.0, {'weight': 1.022218339608882}) ,
         (22.0, 93.0, {'weight': 1.4628634684132413}) ,
         (22.0, 101.0, {'weight': 7.494583622053641}) ,
         (23.0, 97.0, {'weight': 0.86085201141197409}) ,
         (23.0, 90.0, {'weight': 1.4629842172999594}) ,
         (23.0, 65.0, {'weight': 0.94746570241498318}) ,
         (24.0, 34.0, {'weight': 0.55323853417352553}) ,
         (25.0, 104.0, {'weight': 4.9839694794161371}) ,
         (26.0, 85.0, {'weight': 1.5024751933287497}) ,
         (26.0, 46.0, {'weight': 1.2053565344116006}) ,
         (27.0, 72.0, {'weight': 0.72860577250944303}) ,
         (27.0, 92.0, {'weight': 0.74002007166874428}) ,
         (28.0, 54.0, {'weight': 0.55323853417352553}) ,
         (29.0, 50.0, {'weight': 0.81426784351619774}) ,
         (30.0, 98.0, {'weight': 0.77235026806254947}) ,
         (30.0, 78.0, {'weight': 0.79413937142096647}) ,
         (30.0, 95.0, {'weight': 0.78901093530213129}) ,
         (31.0, 68.0, {'weight': 0.98851671776185412}) ,
         (32.0, 95.0, {'weight': 0.8579399666494596}) ,
         (34.0, 54.0, {'weight': 0.55323853417352553}) ,
         (34.0, 55.0, {'weight': 0.60906522381767525}) ,
         (35.0, 62.0, {'weight': 0.66697239833732958}) ,
         (36.0, 93.0, {'weight': 1.2932994772208264}) ,
         (37.0, 80.0, {'weight': 0.85527462610640648}) ,
         (37.0, 96.0, {'weight': 0.85527462610640648}) ,
         (38.0, 46.0, {'weight': 0.95334944284759993}) ,
         (39.0, 50.0, {'weight': 0.52028039541706872}) ,
         (40.0, 69.0, {'weight': 1.7931323073700682}) ,
         (42.0, 62.0, {'weight': 0.51384098628821639}) ,
         (42.0, 81.0, {'weight': 0.5466147583189902}) ,
         (43.0, 65.0, {'weight': 1.0581157274507453}) ,
         (44.0, 108.0, {'weight': 3.0598509599260266}) ,
         (44.0, 70.0, {'weight': 1.0805691635112824}) ,
         (45.0, 56.0, {'weight': 1.3420236519319457}) ,
         (45.0, 79.0, {'weight': 1.6201017824952586}) ,
         (46.0, 53.0, {'weight': 1.070516213146298}) ,
         (47.0, 78.0, {'weight': 1.2822937333699174}) ,
         (47.0, 103.0, {'weight': 3.9053251231648707}) ,
         (48.0, 97.0, {'weight': 0.86085201141197409}) ,
         (48.0, 67.0, {'weight': 0.75656062694199944}) ,
         (49.0, 94.0, {'weight': 1.6216528905308547}) ,
         (49.0, 86.0, {'weight': 0.80157999082131093}) ,
         (49.0, 62.0, {'weight': 0.7081136236724922}) ,
         (51.0, 102.0, {'weight': 1.4704389417937378}) ,
         (51.0, 71.0, {'weight': 0.83506431983724716}) ,
         (54.0, 75.0, {'weight': 0.70074754481170742}) ,
         (55.0, 58.0, {'weight': 0.78571631647476448}) ,
         (56.0, 82.0, {'weight': 1.3387438494166808}) ,
         (57.0, 84.0, {'weight': 1.558483049272277}) ,
         (59.0, 64.0, {'weight': 1.0416266944398496}) ,
         (60.0, 98.0, {'weight': 1.2534403896544031}) ,
         (63.0, 73.0, {'weight': 0.83646303763566465}) ,
         (64.0, 72.0, {'weight': 0.8620326535711742}) ,
         (66.0, 77.0, {'weight': 0.79981721989351606}) ,
         (67.0, 72.0, {'weight': 0.74002007166874428}) ,
         (69.0, 83.0, {'weight': 1.5000235782351021}) ,
         (70.0, 77.0, {'weight': 0.75999034076724692}) ,
         (71.0, 88.0, {'weight': 0.66450874893016454}) ,
         (74.0, 97.0, {'weight': 0.8743417572549379}) ,
         (76.0, 107.0, {'weight': 2.0300278349030831}) ,
         (77.0, 89.0, {'weight': 0.75999034076724692}) ,
         (79.0, 106.0, {'weight': 4.5661761296968333}) ,
         (82.0, 95.0, {'weight': 1.083633962514291}) ,
         (84.0, 99.0, {'weight': 2.1024875417678257}) ,
         (89.0, 92.0, {'weight': 0.75419548272456249}) ,
         (100.0, 107.0, {'weight': 2.9259491743365307}) ,
         (101.0, 109.0, {'weight': 7.6747981730730297}) ,
         (102.0, 108.0, {'weight': 4.3128725576385092}) ,
         (104.0, 105.0, {'weight': 7.5515191839631273})]
G2 = nx.Graph()
G2.add_nodes_from(nodes)
G2.add_edges_from(edges)

G2.add_node('special', {'label': 'special'})

special_edges = []
for n, ndat in G2.nodes_iter(data=True):
   if ndat['label']!='special' and ndat['label']>=0:
      special_edges.append( (n,'special', {'weight':0}) )

G2.add_edges_from(special_edges)

for n, ndat in G2.nodes_iter(data=True):
   if ndat['label']==-1:
      path = nx.shortest_path(G2, source=n, target='special', weight='weight')
      ndat['closest'] = path[-2] #Closest node with label>=0

G2.remove_node('special')

【讨论】:

  • 您不能在一个 Dijkstra 调用中通过从特殊节点搜索到源节点来执行此操作吗?
  • 是的,尽管这只适用于无向图。我在写这篇文章时确实考虑了你的想法,如果你正在构建自己的算法,我认为这是最直接的方法;但是,使用 networkx 框架实现它会比我这里的更复杂。
  • 你可以加速这个算法,每次运行最短路径算法后,通过最短路径中的节点跟踪与特殊节点的距离,并删除最短路径节点图表。每次删除节点时,将其邻居连接到具有适当计算距离的特殊节点。 (以及每个被删除的节点,如果是-1节点,也记录下它的解)。
  • @robertking:这可能有效,但简单是一种美德。如果您查看 OP 对他们问题的编辑,他们的运行时间从 1 小时减少到 45 秒。此时进行进一步算法开发的潜在节省可能会被开发时间大大抵消。如果代码被频繁使用,也许值得尝试。
【解决方案2】:

如果我理解您的问题,那么您的问题就是旅行商问题,这意味着没有比(在最坏的情况下)测试单一可能性更快的精确解决方案。

【讨论】:

    【解决方案3】:
    h = heapq
    solution = {}
    g = build_nx_graph()
    for node in g:
        if label_is_neg_1(node):
            solution[node] = false
            heappush(h, (0, node))
    while h:
        distance, node = heappop(h)
        for neighbour, neighbour_dist in iterate_neighbours(g):
            bs = best_solution(neighbour, neighbour_dist)
            if not bs == solution.get(neighbour, bs):
                solution[neighbour] = bs
                heappush(h, (bs, neighbour))
        if len(solution) == len(g):
            break
    

    这个不完整的伪代码应该从所有 -1 节点开始,然后“扇出”,依次计算到所有非 -1 节点的距离。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多