AOV/AOE网及其算法

用图中的顶点表示某个有一定规模的“工程”里的不同活动,用图中的边表示各项活动之间的先后顺序关系。这样的有向图成为活动顶点网(active on vertex network)AOV网。

对于给定的AOV网N, 如果N中的所有顶点能排成一个线性序列 S = v0,v1,v2,v3...vn,满足:如果N中存在从顶点Vi到顶点Vj的路径,那么S里Vi就排在Vj之前,则S称为N的一个拓扑序列,而构造拓扑序列的操作称为拓扑排序。

拓扑排序算法:

1、定义一个字典,记录每个顶点对应的入度

2、遍历图中顶点及其neighbor,建立顶点的入度表

3、遍历图中顶点,如果顶点的入度为0,则将该顶点加入result,该顶点的neighbor的入度-1

4、判断neighbor中是否存在入度为0的顶点,如果有则重复3,直到选出了图中的全部顶点,或者找不到入度为0的顶点。

具体实现:https://blog.csdn.net/qq_36387683/article/details/81199565

AOE网(active on edge network)是一种无环的带权有向图,其中:

顶点表示事件,有向边表示活动,边上的权值表示活动的持续时间。

图中一个顶点表示的事件,也就是它的入边所表示的活动已经完成,它的出边所表示的活动可以开始的那个状态,把这个情况看做事件。

完成整个工程的最短时间,也就是从开始顶点到完成顶点的最长路径的长度(即路径上各条边的权值之和)。这种最长路径称为AOE网的关键路径。

关键路径算法:

首先定义几组关键的变量: 有点难理解

1、事件Vj的最早可能发生时间ee[j]。显然,这一时间要根据在它之前的事件(顶点)和相关活动(边及其权值)确定,不可能更早发生(最大时间)。ee[j]可以递推计算:

ee[0] = 0(初始事件总在时刻0发生)

ee[j] = max{ ee[i] + w(<Vi,Vj>) | < Vi, Vj> ∈E}, 0 ≤ j ≤ n-1

对于每个j,只需要考虑以Vi为终点的入边集

2、事件Vi的最迟允许发生时间 le[i]。事件的发生可能推迟更晚,但有些事件过迟发生就会延误整个工程的进度(最小时间)。可以根据已知的ee值反向地递推计算:

le[n-1] = ee[n-1] (最后一个事件绝对不能再延迟)

le[i] = min{ le[j] + w(<Vi, Vj>) | <Vi, Vj> ∈E},  0 ≤ i ≤ n-2

对于每个i, 只需要考虑以Vi 为始点的出边集

3、在这个网络中活动Ak = <Vi, Vj>的最早可能开始时间e[k] = ee[i],以及它的最迟允许开始时间l[k] = le[j] - w(<Vi, Vj>)。当

e[k ]== l [k], 称这个活动为关键活动,它们中的任何一个推迟开始,都会延误整个工程的工期。

所有完全由关键活动构成的从初始点到终点的路径就是图中的关键路径

算法实现分为四个步骤:

1、生成AOE网的一个拓扑序列

2、生成ee表的值,应该按照拓扑序列的顺序计算

3、生成le表的值,应该按照拓扑序列的逆序计算

4、最后对ee表和le表进行比较,得到关键活动,进而的到关键路径。

具体实现,暂时没有碰到提,只能不能对症下药:

def critical_paths(graph):
    def events_earliest_itme(vnum, graph, toposeq):
        ee = [0] * vnum
        for i in toposeq:
            for j, w in graph.out_edges(i):
                if ee[j] + w > ee[j]:
                    ee[j] = ee[i] + w
        return  ee

    def events_latest_time(vnum, graph, toposeq, eelast):
        le = [eelast] * vnum # 由ee逆推
        for k in range(vnum-2, -1, -1):
            i = toposeq[k]
            for j, w in graph.out_edges(i):
                if le[j] -w < le[j]:
                    le[j] = le[j] - w
        return le
    
    def crt_paths(vnum, graph, ee, le):
        crt_actions = []
        for i in range(vnum):
            for j, w in graph.out_edges(i):
                if ee[i] == le[j] - w:  #关键活动
                    crt_actions.append((i, j, ee[i]))
        return crt_actions
    
    toposeq = toposort(graph) # 拓扑排序算法
    if not toposeq:
        return False
    vnum = graph.vertex_num() 
    ee = events_earliest_itme(vnum, graph, toposeq)
    le = events_latest_time(vnum, graph, toposeq, ee[vnum-1])
    return  crt_paths(vnum, ee, le)

猜你喜欢

转载自blog.csdn.net/qq_36387683/article/details/81199847
AOE