前言
本人前段时间在完成一篇论文,其中一个核心模块是流程图相似度计算,而这部分又以流程图的分层为前提。
我在网上大致找了一下,没有找到跟流程图层次划分相关的程序实现,于是想自己实现这部分的算法。
一、任务描述
输入:流程图(以邻接矩阵表示)
输出:分层的结果
示例:
该流程图应分为3层为,即[[A ,B]、[C,D,E]、[F,G]]
说明:此处涉及的流程图只包含简单的前驱和后继关系,不包含循环等复杂结构
二、算法思想
1.从流程图的邻接矩阵中提取出连接信息(边);判断每个节点所处的位置2.通过遍历边,并依据"相连的一条边上的两个节点一定位于相邻的两层"确定当前一层
3.删除当前层包含的元素的所有连接信息
注意:确定一层节点时,要考虑两种情况,即该节点是否有与之相连的后继节点
三、算法实现
代码如下(核心在于怎样确定一层):
def layer_decomposition(adj_matrix:list):
# var definition
edges = []
layer = []
length = len(matrix)
# create edges
for i in range(0, length):
for j in range(i, length):
if matrix[i][j] == 1:
edge = []
edge.append(i)
edge.append(j)
edges.append(edge)
edges_copy = copy.deepcopy(edges)
while len(edges):
next_layer = []
special_list = []
head_node = []
tail_node = []
for j in range(0, len(edges)):
head_node.append(edges[j][0])
tail_node.append(edges[j][1])
head_node = list(set(head_node))
tail_node = list(set(tail_node))
for head in head_node:
if head not in tail_node and head not in layer:
special_list.append(head)
# covert layer to 1D
check_list = [b for a in layer for b in a]
# only in layer 1
if not(set(check_list) > set(special_list)):
layer.append(special_list)
for edge in edges:
for head in special_list:
if head == edge[0]:
next_layer.append(edge[1])
# remove edges connected with layer
for i in range(0, len(edges_copy)):
temp = copy.deepcopy(edges_copy[i])
for ele in special_list:
if ele in temp and edges_copy[i] in edges:
edges.remove(edges_copy[i])
next_layer = list(set(next_layer))
layer.append(next_layer)
return layer
总结
完成这个算法还是费了些力气,后面还会多加总结和练习 ^ _ ^