Beispiel #1
0
def initialize(dag: DirectGraph, s: Vertex, t: Vertex):
    """
    做搜索前 forward backward 的初始化
    :return:
    """
    Sf = {s}
    Sb = {t}
    Qf = set()
    Qb = set()
    df = {s: 0}
    db = {t: 0}
    paif = {s: None}
    paib = {t: None}
    for u in dag.vertexes:
        if u != s:
            Qf.add(u)
            w = dag.get_edge_weight(s, u)
            df[u] = w
            if w < sys.maxsize:
                paif[u] = s
            else:
                paif[u] = None
        if u != t:
            Qb.add(u)
            w = dag.get_edge_weight(u, t)
            db[u] = w
            if w < sys.maxsize:
                paib[u] = t
            else:
                paib[u] = None
    return Sf, Sb, Qf, Qb, df, db, paif, paib
Beispiel #2
0
def dijkstra(dg: DirectGraph, s: Vertex):
    """
    使用 Dijkstra 遍历有向无环图,假设该图为有向无环图 DAG,以下代码不做判断
    :param dg: course13.graph.DirectGraph
    :param s: 寻找DAG中所有顶点到 s 的最短路径 S.P
    :return:
    """
    if not dg.has_vertex(s):
        print(dg)
        raise Exception("顶点: {} 不在 DAG 中")
    # S 为已经找到最短路径的顶点
    # Q 为尚未找到最短路径的顶点
    # d 为对应目前迭代中该顶点到 s 的距离
    # pai 用于记录在最短路径中,该顶点的上一个顶点
    S, Q, d, pai = initialize(dg, s)
    while Q:
        # extract-min from Q
        v, minimize = extract_min(Q, d)
        if v is not None:
            S.add(v)
            Q.remove(v)
            relax(dg, d, pai, v)
        else:
            # 所有可以被 S 达到的顶点都已经被遍历,剩下的顶点无法从 s 到达
            break
    return d, pai
Beispiel #3
0
def dijkstra_single_source_single_target(dg: DirectGraph, s: Vertex,
                                         t: Vertex):
    """
    使用 Dijkstra 遍历有向无环图,假设该图为有向无环图 DAG,以下代码不做判断
    寻找 DAG 中 s-->t 的最短路径
    :param dg: course13.graph.DirectGraph
    :param s: 寻找DAG中所有顶点到 s 的最短路径 S.P
    :param t: 目标顶点
    :return:
    """
    if not dg.has_vertex(s):
        print(dg)
        raise Exception("顶点: {} 不在 DAG 中")
    # S 为已经找到最短路径的顶点
    # Q 为尚未找到最短路径的顶点
    # d 为对应目前迭代中该顶点到 s 的距离
    # pai 用于记录在最短路径中,该顶点的上一个顶点
    S, Q, d, pai = initialize(dg, s)
    while Q:
        # extract-min from Q
        v, minimize = extract_min(Q, d)
        # 如果 v == t 那么可以停止搜索,已经找到了目标 s-->t 最短路径
        if v == t:
            S.add(v)
            Q.remove(v)
            break
        if v is not None:
            S.add(v)
            Q.remove(v)
            relax(dg, d, pai, v)
        else:
            # 所有可以被 S 达到的顶点都已经被遍历,剩下的顶点无法从 s 到达
            # 有可能 s-x->t 不存在这样的路径,也就是 d[t] = sys.maxsize
            break
    return d, pai
Beispiel #4
0
def initialize(dag: DirectGraph):
    """
    对进行 Floyd 算法求解之前先进行数据的初始化
    :return:
    """
    vexnum = dag.get_vertex_num()
    # Graph 中顶点以 set() 集和存储,这里我们需要将其转化为 list,方便使用下标 index 访问,list 中保存的只是引用,根本上还是 Graph 中 set 的顶点
    vexes = list(
        dag.vertexes)  # 由于是从 set 转化为 list,所以即使是相同的顶点,生成的 list 每次顶点顺序也可能不一样
    # 用于记录最短路径的关系的三维数组 p
    p = [[[False for _ in range(vexnum)] for j in range(vexnum)]
         for i in range(vexnum)]
    # 生成用于记录图中每两个顶点之间的最短路径的二维数组 d[i][j] 代表 vi-->vj 的距离
    d = [[
        dag.get_edge_weight(vexes[i], vexes[j]) if i != j else 0
        for j in range(vexnum)
    ] for i in range(vexnum)]
    for i in range(vexnum):
        for j in range(vexnum):
            if d[i][j] < sys.maxsize:
                p[i][j][i], p[i][j][j] = True, True
    return d, p, vexes, vexnum
Beispiel #5
0
def initialize(dg: DirectGraph, s: Vertex):
    """
    对数据进行初始化,这里仅仅初始化 distance dict, pai 记录最路径中访问的上一个顶点
    :param dg:
    :return:
    """
    d = {s: 0}
    pai = {s: None}
    for v in dg.vertexes:
        pai[v] = None
        if v != s:
            d[v] = dg.get_edge_weight(s, v)
            # 使用 sys.maxsize 代表两者之间没有任何关联
            if d[v] < sys.maxsize:
                pai[v] = s
    return d, pai
Beispiel #6
0
def topology(dag: DirectGraph):
    """
    求 DAG 的拓扑结构
    :param dag:
    :return:
    """
    indegree = initialize(dag)
    # 顶点加入拓扑结构的顺序
    order = []
    vexnum = dag.get_vertex_num()
    while len(order) < vexnum:
        for v, c in indegree.items():
            if c == 0:
                order.append(v)
                # 更新 -1 代表已经加入了拓扑结果
                indegree[v] = -1
                update(dag, v, indegree)
                break
        else:
            # 图中有环,无法计算该图的拓扑结构
            raise CycleException('图中有环,无法计算该图的拓扑结构')
    return order
Beispiel #7
0
def initialize(dg: DirectGraph, s):
    """
    在进行 Dijkstra 算法前先进行初始化数据
    :param dg:
    :param s:
    :return:
    """
    # 所有已经找到了最短路径的顶点集和
    S = {s}
    # 所有还没有找到最短路径的顶点集和
    Q = set()
    d = {s: 0}
    pai = {s: None}
    # 将所有非 s 顶点加入到 Q 中
    for v in dg.vertexes:
        pai[v] = None
        if v != s:
            Q.add(v)
            d[v] = dg.get_edge_weight(s, v)
            if d[v] < sys.maxsize:
                pai[v] = s
    return S, Q, d, pai
Beispiel #8
0
def bellman_ford(dg: DirectGraph, s: Vertex):
    """
    使用 Bellman-Ford 寻找图中的最短路径
    :param dg: 有向图,其中图中可以存在 negative-weight cycle,Bellman-Ford 算法可以发现 negative-weight cycle
    :param s: 源点 s
    :return:
    """
    # d 用来记录每个顶点距离 s 的最短路径
    # pai 用于记录每个顶点在最短路径中访问的上一个顶点
    d, pai = initialize(dg, s)
    vertex_num = dg.get_vertex_num()
    # 进行 |V| - 1 次循环
    for _ in range(1, vertex_num):
        # 这里从每个顶点开始遍历每一条边
        for u, l in dg.edges.items():
            for v, w in l:
                relax(u, v, w, d, pai)
    try:
        check(dg, d)
    except NegativeCycleException:
        print("图中存在 negative-weight cycle")
    else:
        print("图中不存在 negative-weight cycle")
    return d, pai
Beispiel #9
0
def test_dijkstra():
    dg = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    dg.add_vertex(a)
    dg.add_vertex(b)
    dg.add_vertex(c)
    dg.add_vertex(d)
    dg.add_vertex(e)
    dg.add_vertex(f)
    dg.add_vertex(g)
    dg.add_edge(a, b, 2)
    dg.add_edge(d, a, 3)
    dg.add_edge(b, c, 3)
    dg.add_edge(c, d, 5)
    dg.add_edge(c, e, 6)
    dg.add_edge(c, f, 4)
    dg.add_edge(g, e, 1)
    dg.add_edge(f, g, 2)
    dg.add_edge(b, e, 2)
    dg.add_edge(e, g, 3)

    d, pai = dijkstra(dg, a)
    print(d, pai)
Beispiel #10
0
def test():
    # 以下图中有两条关键路径
    # 1: a-->b-->e-->g-->h
    # 2: a-->b-->e-->f-->h
    dag = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    h = Vertex('h')
    i = Vertex('i')

    dag.add_vertex(a)
    dag.add_vertex(b)
    dag.add_vertex(c)
    dag.add_vertex(d)
    dag.add_vertex(e)
    dag.add_vertex(f)
    dag.add_vertex(g)
    dag.add_vertex(h)
    dag.add_vertex(i)

    dag.add_edge(a, b, 6)
    dag.add_edge(a, c, 4)
    dag.add_edge(a, d, 5)
    dag.add_edge(b, e, 1)
    dag.add_edge(c, e, 1)
    dag.add_edge(d, i, 2)
    dag.add_edge(e, f, 9)
    dag.add_edge(e, g, 7)
    dag.add_edge(f, h, 2)
    dag.add_edge(g, h, 4)
    dag.add_edge(i, g, 4)

    key_path = find_key_path(dag)
    print(key_path)
Beispiel #11
0
def test_cycle():
    dag = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    h = Vertex('h')
    dag.add_vertex(a)
    dag.add_vertex(b)
    dag.add_vertex(c)
    dag.add_vertex(d)
    dag.add_vertex(e)
    dag.add_vertex(f)
    dag.add_vertex(g)
    dag.add_vertex(h)
    dag.add_edge(a, b, 2)
    dag.add_edge(d, a, 3)
    dag.add_edge(b, c, 3)
    dag.add_edge(c, d, 5)
    dag.add_edge(c, e, 6)
    dag.add_edge(c, f, 4)
    dag.add_edge(g, e, 1)
    dag.add_edge(f, g, 2)
    dag.add_edge(b, e, 2)
    dag.add_edge(e, g, 3)
    dag.add_edge(g, c, 3)

    order = topology(dag)
    print(order)
Beispiel #12
0
def test_topology():
    dag = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    dag.add_vertex(a)
    dag.add_vertex(b)
    dag.add_vertex(c)
    dag.add_vertex(d)
    dag.add_vertex(e)
    dag.add_vertex(f)
    dag.add_vertex(g)

    dag.add_edge(a, b)
    dag.add_edge(b, c)
    dag.add_edge(c, d)
    dag.add_edge(e, c)
    dag.add_edge(c, g)
    dag.add_edge(c, f)
    dag.add_edge(d, f)

    order = topology(dag)
    print(order)
Beispiel #13
0
def test_dijkstra_single_source_single_target():
    dg = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    dg.add_vertex(a)
    dg.add_vertex(b)
    dg.add_vertex(c)
    dg.add_vertex(d)
    dg.add_vertex(e)
    dg.add_vertex(f)
    dg.add_vertex(g)
    dg.add_edge(a, b, 2)
    dg.add_edge(d, a, 3)
    dg.add_edge(b, c, 3)
    dg.add_edge(c, d, 5)
    dg.add_edge(c, e, 6)
    dg.add_edge(c, f, 4)
    dg.add_edge(g, e, 1)
    dg.add_edge(f, g, 2)
    dg.add_edge(b, e, 2)
    dg.add_edge(e, g, 3)

    s, t = a, g

    d, pai = dijkstra_single_source_single_target(dg, s, t)
    print(d, pai)
    print('=======')
    print_shortest_path(pai, s, t)
Beispiel #14
0
def test_floyd():
    dag = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    h = Vertex('h')
    dag.add_vertex(a)
    dag.add_vertex(b)
    dag.add_vertex(c)
    dag.add_vertex(d)
    dag.add_vertex(e)
    dag.add_vertex(f)
    dag.add_vertex(g)
    # dag.add_vertex(h)
    dag.add_edge(a, b, 2)
    dag.add_edge(d, a, 3)
    dag.add_edge(b, c, 3)
    dag.add_edge(c, d, 5)
    dag.add_edge(c, e, 6)
    dag.add_edge(c, f, 4)
    dag.add_edge(g, e, 1)
    dag.add_edge(f, g, 2)
    dag.add_edge(b, e, 2)
    dag.add_edge(e, g, 3)
    dag.add_edge(g, c, 3)
    d, p, vexes = floyd(dag)
    pprint.pprint(vexes)
    pprint.pprint(d)
    pprint.pprint(p)
Beispiel #15
0
def test():
    dag = DirectGraph()
    a = Vertex('a')
    b = Vertex('b')
    c = Vertex('c')
    d = Vertex('d')
    e = Vertex('e')
    f = Vertex('f')
    g = Vertex('g')
    h = Vertex('h')
    dag.add_vertex(a)
    dag.add_vertex(b)
    dag.add_vertex(c)
    dag.add_vertex(d)
    dag.add_vertex(e)
    dag.add_vertex(f)
    dag.add_vertex(g)
    dag.add_vertex(h)
    dag.add_edge(a, b, 2)
    dag.add_edge(d, a, 3)
    dag.add_edge(b, c, 3)
    dag.add_edge(c, d, 5)
    dag.add_edge(c, e, 6)
    dag.add_edge(c, f, 4)
    dag.add_edge(g, e, 1)
    dag.add_edge(f, g, 2)
    dag.add_edge(b, e, 2)
    dag.add_edge(e, g, 3)
    dag.add_edge(g, c, 3)
    try:
        df, db, paif, paib, n = bi_dijkstra(dag, g, a)
        print('df: ', df)
        print('db: ', db)
        print('paif: ', paif)
        print('paib ', paib)
        print_shortest_path(paif, paib, n)
    except NoPathException as e:
        print(e)