在Python中从元组列表中查找路径

在Python中从元组列表中查找路径,python,Python,我有一个元组列表: data = [('Abe', 'Bob', '3'), ('Abe', 'Frank', '5'), ('Abe', 'George', '4'), ('Carl', 'Bob', '1'), ('Dan', 'Carl', '2')] 此数据模拟一个无向图,其中存在大小为3的从“Abe”到“Bob”的连接。因为图形是无向的,这也意味着从“Bob”到大小为3的“Abe”之间存在连接 我需要显示两个输入之间是

我有一个元组列表:

data = [('Abe', 'Bob', '3'), 
        ('Abe', 'Frank', '5'),
        ('Abe', 'George', '4'),
        ('Carl', 'Bob', '1'),
        ('Dan', 'Carl', '2')]
此数据模拟一个无向图,其中存在大小为3的从“Abe”到“Bob”的连接。因为图形是无向的,这也意味着从“Bob”到大小为3的“Abe”之间存在连接

我需要显示两个输入之间是否存在连接,以及它的权重是多少。例如,如果输入为'Abe','Dan',结果将返回从'Abe'到'Dan'的最短(最少节点跳数,而不是最少权重)路径,即Abe、Bob、Carl、Dan和权重,3+1+2=6

我有一段代码,显示“Abe”是否会到达“Dan”,但我不知道如何返回路径

def get_path_and_weight(data, start, end):

    reachable = [start]
    added = -1

    while added != 0:
        added = 0
        for first, second, weight in data:
            if(first in reachable) and (second not in reachable):
                reachable.append(second)
                added += 1
            if(first not in reachable) and (second in reachable): 
                reachable.append(first)
                added += 1

        if (end in reachable):
            print("YES")
            #return path
        else:
            print("NO")
样本输出

['Abe', 'Bob', 'Carl', 'Dan'] 6 True
['Dan', 'Carl'] 2 False

上面的示例可以获取路径并确定是否可访问,但我认为您需要进一步增强它以处理多个路径。

您可以生成所有可能的路径,并按权重对它们进行排序。注意,我已将数据中的权重更改为数字,而不是字符串:

data = [
    ('Abe', 'Bob', 3), 
    ('Abe', 'Frank', 5),
    ('Abe', 'George', 4),
    ('Carl', 'Bob', 1),
    ('Dan', 'Carl', 2),
]

WEIGHT = 0
NODES = slice(1, None)

def get_path_and_weight(data, start, end):

    paths = [[0, start]]
    added = True

    while added:
        added = False

        for first, second, weight in data:
            for path in paths:
                candidate = None

                if (first in path[NODES]) and (second not in path[NODES]):
                    candidate = second
                elif (first not in path[NODES]) and (second in path[NODES]):
                    candidate = first

                if candidate:
                    new_path = list(path)
                    new_path.append(candidate)
                    new_path[WEIGHT] += weight

                    if new_path not in paths:
                        paths.append(new_path)
                        added = True

    for path in sorted(paths):
        if end in path[NODES]:
            return path

    return None
然后,您可以将其称为:

weight, *path = get_path_and_weight(data, "Abe", "Dan")

print(path, "with weight", weight)
给出了结果:

['Abe', 'Bob', 'Carl', 'Dan'] with weight 6
由于它返回路径或
None
,您仍然可以将其用作谓词函数:

if get_path_and_weight(data, "Abe", "Dan"):
    print("connected")

有几个已经开发和调试的软件包可以实现这一点,例如


你确定算法本身是正确的吗?也许你无法找出路径的原因是你没有真正检查它。检查是否有断开连接的图形。乍一看,你们只需回答一个顶点是否在图中。你要做的是广度优先搜索或深度优先搜索。我还没有喝咖啡,但我的第一个想法是只对每一条边进行Dijkstra,伪权重为1,这将为你提供从一个节点到另一个节点的跳数最少的路径。然后添加以后使用的边的实际权重。这似乎有一个缺陷,如果你反转开始和结束,用权重(数据,'Dan','Abe')获取路径。你应该得到相同的基本结果,只是路径反转,但是你得到:
['Dan','Carl']2 False
是的,因为这个例子只是想激发灵感,而不是给出一个取舍的答案,所以反向路径和多重路径没有处理。也许以后吧。:)
if get_path_and_weight(data, "Abe", "Dan"):
    print("connected")
import networkx as nx

data = [('Abe', 'Bob', '3'), 
        ('Abe', 'Frank', '5'),
        ('Abe', 'George', '4'),
        ('Carl', 'Bob', '1'),
        ('Dan', 'Carl', '2')]

g = nx.Graph()
for e in data:
    g.add_edge(e[0], e[1], distance=int(e[2]))
>>> nx.shortest_path(g, 'Abe', 'Bob', 'distance'), nx.shortest_path_length(g, 'Abe', 'Bob', 'distance')
(['Abe', 'Bob'], 3)