(4-3)Floyd-Warshall算法:Floyd-Warshall算法的应用案例

4.3  Floyd-Warshall算法的应用案例

Floyd-Warshall算法在许多实际应用中都有着广泛的应用,特别是在需要计算图中所有顶点对之间的最短路径时,它是一种非常有效的解决方案。

4.3.1  自驾线路规划

暑假来临,家庭A决定自驾旅行,计划去四个城市:A、B、C、D,每个城市之间的行车距离如下:

  1. A <-> B: 100km
  2. A <-> D: 200km
  3. B <-> C: 150km
  4. C <-> D: 300km

请使用Floyd-Warshall算法,帮助航家庭A规划最短的航线,以最大程度地减少自驾距离和时间。请计算出每对城市之间的最短自驾距离,并给出优化后的自驾线路信息。

实例4-3:解决航空网络规划问题codes/4/air.py

实例文件air.py的具体实现代码如下所示。

import numpy as np
import matplotlib.pyplot as plt

INF = float('inf')

# 城市之间的自驾距离(邻接矩阵表示)
flightDistances = [
    [0, 100, INF, 200],   # A
    [100, 0, 150, INF],   # B
    [INF, 150, 0, 300],   # C
    [200, INF, 300, 0]    # D
]

# 城市名称
cityNames = ["A", "B", "C", "D"]

def floydWarshall():
    V = len(flightDistances)
    dist = [row[:] for row in flightDistances]

    # Floyd-Warshall算法
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][k] != INF and dist[k][j] != INF and dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]

    # 输出最短自驾距离矩阵
    print("Shortest Self-driving distances between every pair of cities:")
    for row in dist:
        for distance in row:
            print("INF" if distance == INF else distance, end=" ")
        print()

    # 输出自驾线路信息
    print("\nOptimized Self-driving routes:")
    for i in range(V):
        for j in range(i + 1, V):
            if dist[i][j] != INF:
                print(f"From {cityNames[i]} to {cityNames[j]}, distance: {dist[i][j]} km")

    # 绘制自驾线路图
    draw_flight_map(dist)

def draw_flight_map(distances):
    cities = len(distances)
    positions = np.random.rand(cities, 2)  # 随机生成城市位置
    plt.figure(figsize=(8, 6))

    # 绘制城市节点
    for i in range(cities):
        plt.plot(positions[i, 0], positions[i, 1], 'o', markersize=10, label=cityNames[i])

    # 绘制自驾线路
    for i in range(cities):
        for j in range(i + 1, cities):
            if distances[i][j] != INF:
                plt.plot([positions[i, 0], positions[j, 0]], [positions[i, 1], positions[j, 1]], 'k-')

    plt.title("Self-driving Routes between Cities")
    plt.xlabel("Longitude")
    plt.ylabel("Latitude")
    plt.legend()
    plt.grid(True)
    plt.show()

def main():
    floydWarshall()

if __name__ == "__main__":
    main()

在这个例子中,我们假设有4个城市(A、B、C、D),并给出了它们之间的线路距离。然后,我们使用Floyd-Warshall算法计算了每对城市之间的最短自驾线路距离,并输出了优化后的线路信息。这有助于规划自驾线路,以最大程度地减少自驾距离和时间。上述代码的实现流程如下所示:

(1)首先,定义了四个城市之间的自驾线路距离和城市名称,并导入了必要的库,包括 numpy 和 matplotlib.pyplot。

(2)接着,定义了floydWarshall 函数,该函数执行 Floyd-Warshall 算法来计算最短自驾线路距离。在算法执行过程中,首先复制了自驾线路距离矩阵,然后使用三重循环来更新最短距离。内部循环遍历所有城市对,如果经过中间城市可以缩短当前两个城市之间的距离,则更新最短距离。算法完成后,输出了最短航线距离矩阵和优化后的自驾线路信息。

(3)然后,定义了draw_flight_map 函数,用于绘制城市之间的自驾线路图。该函数接受一个距离矩阵作为输入,并生成城市的随机位置。然后,它绘制城市节点和自驾线路,并设置图形的标题、标签和图例。最后,通过调用 plt.show() 函数显示图形。

(4)最后,在主 main 函数中调用了 floydWarshall 函数,触发整个流程的执行。

执行后将使用 Floyd-Warshall 算法计算城市之间的最短自驾线路距离打印输出如下所示的计算结果。同时,它还绘制了如图4-1所示的城市间的自驾线路图,以可视化展示自驾路线。

Shortest Self-driving distances between every pair of cities:
0 100 250 200 
100 0 150 300 
250 150 0 300 
200 300 300 0 

Optimized Self-driving routes:
From A to B, distance: 100 km
From A to C, distance: 250 km
From A to D, distance: 200 km
From B to C, distance: 150 km
From B to D, distance: 300 km
From C to D, distance: 300 km

对上面输出结果的具体说明如下所示:

  1. Shortest Self-driving distances between every pair of cities" 部分显示了每对城市之间的最短自驾线路距离矩阵。例如,从城市A到城市B的最短自驾线路距离是100公里,从城市A到城市C的最短自驾线路距离是250公里,以此类推。
  2. "Optimized Self-driving routes" 部分列出了优化后的自驾线路信息。每行显示了从一个城市到另一个城市的最短自驾线路距离,以及航线的具体路径。例如,从城市A到城市B的最短自驾线路距离是100公里,从城市A到城市C的最短自驾线路距离是250公里,以此类推。

图4-1  城市间的航线图

4.3.2  城市交通规划应用

在实际应用中,城市交通规划者可以利用Floyd-Warshall算法来计算城市道路网络中各个路段的最短路径,从而优化交通流量并减少拥堵。请看下面的题目:

在一个由五个交叉路口A、B、C、D和E组成的城市中,每个交叉路口之间通过道路相连。通过给出每个路口之间的道路距离和交通规则,你需要设计一个交通规划系统,帮助司机在城市中选择最短路径到达目的地。道路网络的信息如下所示。

  1. 交叉路口名称:A、B、C、D和E。
  2. 道路距离:给出了每个交叉路口之间的道路距离,以邻接矩阵的形式表示。
  3. 交通规则:存在单行道和禁止左转等限制,通过布尔类型的二维数组表示。

请编写一个程序,计算出从交叉路口A到其他交叉路口的最短路径,并输出最短路径以及对应的距离。同时,确保所计算出的路径不违反任何交通规则。你可以假设司机总是从交叉路口A出发,但目的地可以是任何一个交叉路口。请你在考虑交通规则的情况下,设计一个算法来找到最佳路径,并解释他们的思路和算法设计。

实例4-4:解决城市交通规划的最短路径问题codes/4/city.py

实例文件city.py的具体实现代码如下所示。

import networkx as nx
import matplotlib.pyplot as plt

INF = float('inf')

# 城市道路网络中各路段之间的距离(邻接矩阵表示)
roadDistances = [
    [0, 10, 5, INF, INF],   # Road from A
    [INF, 0, 3, 2, INF],    # Road from B
    [INF, 2, 0, 1, 7],      # Road from C
    [INF, INF, INF, 0, 4],  # Road from D
    [INF, INF, INF, INF, 0] # Road from E
]

# 交叉路口名称
junctions = ["A", "B", "C", "D", "E"]

# 交叉路口之间的单行道和禁止左转等限制
roadRestrictions = [
    [False, False, False, False, False],  # Road from A
    [False, False, True, False, False],   # Road from B
    [False, False, False, False, True],    # Road from C
    [False, False, False, False, False],   # Road from D
    [False, False, False, False, False]    # Road from E
]

def floydWarshall():
    V = len(roadDistances)
    dist = [row[:] for row in roadDistances]  # Make a deep copy of roadDistances

    # 考虑单行道和禁止左转等限制
    for i in range(V):
        for j in range(V):
            if roadRestrictions[i][j]:
                dist[i][j] = INF  # 将有限制的路段距离设为无穷大

    # Floyd-Warshall算法
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][k] != INF and dist[k][j] != INF and dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]

    # 创建图
    G = nx.Graph()
    for i in range(V):
        for j in range(V):
            if i != j and dist[i][j] != INF:
                G.add_edge(junctions[i], junctions[j], weight=dist[i][j])

    # 可视化图
    pos = nx.spring_layout(G)
    plt.figure(figsize=(8, 6))
    nx.draw(G, pos, with_labels=True, node_size=1000, node_color="lightblue", font_size=12, font_weight="bold")
    labels = nx.get_edge_attributes(G, 'weight')
    nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)
    plt.title("City Road Network Visualization")
    plt.show()

    # 输出最短路径距离矩阵
    print("Shortest distances between every pair of junctions:")
    for i in range(V):
        for j in range(V):
            if dist[i][j] == INF:
                print("INF", end=" ")
            else:
                print(dist[i][j], end=" ")
        print()

    # 输出路线信息
    print("Optimized traffic routes:")
    for i in range(V):
        for j in range(V):
            if i != j and dist[i][j] != INF:
                print(f"Shortest route from {junctions[i]} to {junctions[j]}: {junctions[i]}", end="")
                k = j
                while k != i:
                    print(f" -> {junctions[k]}", end="")
                    k = dist[i][k] if dist[i][k] < INF else j  # Follow the shortest path
                print(f", distance: {dist[i][j]} km")

if __name__ == "__main__":
    floydWarshall()

上述代码的实现流程如下所示:

(1)首先,定义了城市道路网络中各路段之间的距离(邻接矩阵表示),以及交叉路口之间的交通规则(如单行道和禁止左转)。

(2)然后,使用 Floyd-Warshall 算法计算从交叉路口 A 到其他交叉路口的最短路径。在计算过程中考虑交通规则,并将有限制的路段距离设为无穷大。

(3)接着,将计算得到的最短路径结果转换为 NetworkX 图形对象,并利用 Matplotlib 库进行可视化。在绘制时使用节点表示交叉路口,边表示道路,边的权重表示道路距离。

(4)最后,打印输出如下所示的最短路径距离矩阵和优化的交通路线信息,并绘制如图4-2所示的城市道路网络的可视化图。图中的节点代表交叉路口,边代表道路,边的权重表示道路距离。通过可视化图形,可以直观地展示城市道路网络的结构,以及各个交叉路口之间的连接关系和距离。

Shortest distances between every pair of junctions:
0 7 5 6 10
INF 0 INF 2 6
INF 2 0 1 5
INF INF INF 0 4
INF INF INF INF 0
Optimized traffic routes:
Shortest route from A to B: A -> B

图4-2  城市道路网络的可视化图

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值