[Python3]Bellman-Ford的实现及Yen式优化

原理分析见本人Github:

https://github.com/youhengchan/Yen-Bellman-Ford/blob/master/group2_ppt_yen.pdf

测试数据:

原始算法:

伪代码:

实现:

import time

graph_size = 10
counter = 0

class Edge:
    def __init__(self, u, v, w):
        self.u = u
        self.v = v
        self.w = w


def recursive_print(dis, pre):
    global graph_size

    def print_helper(index, destination):
        if pre[index] == index:
            print("Route : {} -> ".format(index), end="")
            return
        print_helper(pre[index], destination)
        if index == destination:
            print("{} Distance = {}".format(destination, dis[destination]), end="")
        else:
            print("{} -> ".format(index), end="")

    for i in range(graph_size):
        if pre[i] == i:
            print("Route : {} Distance = 0".format(i), end="")
        else:
            print_helper(i, i)
        print("")


def bellman_ford(edges, source):
    global graph_size, counter
    begin = time.perf_counter()
    dis = []  # distance from source to the node
    pre = []  # predecessor of node
    error = False
    for i in range(graph_size):
        dis.append(float('inf'))
        pre.append(i)
    dis[source] = 0
    # Initialize the graph
    for i in range(graph_size - 1):   # |V| - 1 times
        counter += 1
        # change = False
        for edge in edges:
            if dis[edge.u] != float("inf") and dis[edge.v] > (dis[edge.u] + edge.w):
                dis[edge.v] = dis[edge.u] + edge.w
                pre[edge.v] = edge.u
                # change = True
        # if not change:
        #     break
    # check for the negative-weight cycle
    for edge in edges:
        if (dis[edge.u] + edge.w) < dis[edge.v]:
            print("dis[{}] ({}) < dis[{}] ({}) + {}".format(edge.u, dis[edge.u], edge.v, dis[edge.v], edge.w))
            error = True
    end = time.perf_counter()
    return error, dis, pre, end-begin


def main():
    global counter
    edges = []
    edges.append(Edge(0, 9, 9))
    edges.append(Edge(0, 2, 3))
    edges.append(Edge(0, 5, 5))
    edges.append(Edge(7, 9, 2))
    edges.append(Edge(7, 3, 0))
    edges.append(Edge(2, 7, 1))
    edges.append(Edge(9, 4, 3))
    edges.append(Edge(3, 4, 2))
    edges.append(Edge(3, 8, 1))
    edges.append(Edge(8, 2, 8))
    edges.append(Edge(8, 6, 2))
    edges.append(Edge(4, 8, -8))
    edges.append(Edge(6, 1, 0))
    edges.append(Edge(5, 1, 2))
    edges.append(Edge(1, 4, 9))

    err, dis, pre, time_consumption = bellman_ford(edges, 0)
    if err:
        print("Negative-weight cycle exist")
    else:
        print("Time consumption = ", time_consumption)
        recursive_print(dis, pre)
    print("Counter = ", counter)


if __name__ == "__main__":
    main()

运行结果:

Yen氏优化:

伪代码:

实现:

import time
graph_size = 10
counter = 0


class Edge:
    def __init__(self, u, v, w):
        self.u = u
        self.v = v
        self.w = w


def recursive_print(dis, pre):
    global graph_size

    def print_helper(index, destination):
        if pre[index] == index:
            print("Route : {} -> ".format(index), end="")
            return
        print_helper(pre[index], destination)
        if index == destination:
            print("{} Distance = {}".format(destination, dis[destination]), end="")
        else:
            print("{} -> ".format(index), end="")

    for i in range(graph_size):
        if pre[i] == i:
            print("Route : {} Distance = 0".format(i), end="")
        else:
            print_helper(i, i)
        print("")


def yen_bellman_ford(edges, edge_plus, edge_minus, source):
    begin = time.perf_counter()
    global graph_size, counter
    dis = []  # distance from source to the node
    pre = []  # predecessor of node
    error = False
    for i in range(graph_size):
        dis.append(float('inf'))
        pre.append(i)
    dis[source] = 0
    # Initialize the graph
    for i in range(graph_size - 1):   # |V| - 1 times
        counter += 1
        change = False
        for edge in edge_plus:
            if dis[edge.u] != float("inf") and dis[edge.v] > (dis[edge.u] + edge.w):
                dis[edge.v] = dis[edge.u] + edge.w
                pre[edge.v] = edge.u
                change = True
        for edge in edge_minus:
            if dis[edge.u] != float("inf") and dis[edge.v] > (dis[edge.u] + edge.w):
                dis[edge.v] = dis[edge.u] + edge.w
                pre[edge.v] = edge.u
                change = True
        if not change:
            break
    # check for the negative-weight cycle
    for edge in edges:
        if (dis[edge.u] + edge.w) < dis[edge.v]:
            print("dis[{}] ({}) < dis[{}] ({}) + {}".format(edge.u, dis[edge.u], edge.v, dis[edge.v], edge.w))
            error = True
    end = time.perf_counter()
    return error, dis, pre, end-begin


def main():
    edges = []
    edge_plus = []
    edge_minus = []
    edge_plus.append(Edge(0, 2, 3))
    edge_plus.append(Edge(0, 5, 5))
    edge_plus.append(Edge(0, 9, 9))
    edge_plus.append(Edge(1, 4, 9))
    edge_plus.append(Edge(2, 7, 1))
    edge_plus.append(Edge(3, 4, 2))
    edge_plus.append(Edge(3, 8, 1))
    edge_plus.append(Edge(4, 5, 0))
    edge_plus.append(Edge(4, 8, -8))
    edge_plus.append(Edge(7, 9, 2))
    edge_minus.append(Edge(9, 4, 3))
    edge_minus.append(Edge(8, 6, 2))
    edge_minus.append(Edge(8, 2, 8))
    edge_minus.append(Edge(7, 3, 0))
    edge_minus.append(Edge(6, 1, 0))
    edge_minus.append(Edge(5, 1, 2))
    edges.extend(edge_minus)
    edges.extend(edge_plus)
    err, dis, pre, time_consumption = yen_bellman_ford(edges, edge_plus, edge_minus, 0)
    if err:
        print("Negative-weight cycle exist")
    else:
        print("Time consumption = ", time_consumption)
        recursive_print(dis, pre)
    print("Counter = ", counter)

if __name__ == "__main__":
    main()

运行结果:

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值