GSpan频繁子图挖掘算法,网上有很多相关的介绍,中文的一些资料总是似是而非,讲的不是很清楚(感觉都是互相抄来抄去,,,基本都是一个样,,,),仔细的研读了原论文后,在这里做一个总结。
1. GSpan频繁子图挖掘算法:
总的思想是,先生成频繁树,再在频繁树的基础上,生成频繁子图,满足最小支持度,满足最小DFS编码的所有频繁子图。
GraphGen.
输入:图集 GD,最小支持度阈值 min_sup;
输出:频繁子图集合 FG.
(1) 扫描图集并找到图集 GD 中所有频繁边;
(2) 删除所有非频繁边;
(3) E→{GD中所有频繁边};
(4) 将 E 中的边按 DFS 编码顺序(后文中有介绍)和频率的降序进行排列;
(5) T→NULL; /*T为频繁子树集合*/
(6) t→e1; /*E中的第 1 条边作FTGen的初始值*/
(7) FTGen(D,t,E,T); /*频繁树生成算法*/(后文中有介绍)
(8) 将集合 T 中的元素按节点数与 DFS 编码顺序进行排序;
(9) FG→T;
(10) for T 中的每棵树
(11) g→t;
(12) E‘{e是频繁边,且 e 是内边(后文中有介绍),并能在图集中找到(g<>e)};
(13) for E' 中的每条边
(14) E' →E‘ - e;
(15) g→g<>e;
(16) if g ≠ min(g) then break;
(17) if FG中无 g 的同构子图 then FG <— FG‘ ∪ g;
(18) endfor;
(19) endfor;
(20) return FG;
GraphGen 分为 3 个部分,算法 2 给出了这种算法的细节.
算法在第 1 部分(第 1 行~第 6 行)对图集 GD进行预处理.作为图挖掘的基础,必须从图集中提取出必要的 信息,如频繁边集、频繁节点集等.在这一部分中,GraphGen 扫描图集 GD并得到频繁边集,将频繁边集按频率递 减与 DFS 编码值递增的顺序进行排列,供算法进一步计算。
算法在第 2 部分(第 7 行)进行频繁子树的挖掘工作,具体的挖掘过程后面的频繁树生成算法。
算法的第 3 部分(第 8 行~第 19 行)是由树向图的扩展过程.针对每一棵频繁子树,从频繁边集中找出能与之 联接的内边,逐一加入到该树,从而形成频繁子图.算法在第 12 行找到所有能与图 g 联接的频繁内边,并将这些 边在第 13 行~第 17 行的子循环中加入到图 g 中.算法的执行结果为频繁子图集合 FG。
与FTGen相似,算法GraphGen主体的时间复杂性也分为两部分:一部分是子图同构的时间复杂性.由于子图 同构的测试是NP完全问题,算法在第 17 行进行的图同构测试,其时间复杂性为O(2n);另一部分是扩展边的时间 复杂性.由于我们仅向频繁图中加入内边,通过两层循环完成,因此,这部分时间复杂性为O(n2).边的每一次扩展, 都需要检验所生成的图是否与结果集的元素重复,因此,算法总的时间复杂性为O(2n·n2)。
2. 算法 2. FTGen.频繁子树生成算法
输入:图集 GD,频繁子树 t,频繁边集 E;
输出:频繁子树集 T.
(1) if t ≠ min(t) then return; /*检查 t 是否具有最小 DFS 编码*/(后文中有介绍)
(2) E‘ <— {e是频繁外边};
(3) for E‘ 中的每条边
(4) E‘ <— E‘ - e;
(5) if (t<>e)存在于图集中;
(6) then t <— t<>e;
(7) if (T中无 t 的同构子树) then T<—T∪ t;
(8) FTGen(GD,t,E,T);
endfor;
3. 定义:外边,内边:
在图的扩展过程中,如果一条扩展边引入了一个新的节点,则称该扩展边为外边,由eo表示.若该扩 展边未引入新的节点(扩展边的两个节点已存在于该图中),则称其为内边。
4. 定义:最小DFS编码:
4.1 什么是DFS编码?
对图进行深度优先遍历
所有节点根据发现时间排序
最后发现的节点叫做最右节点
从第一个节点到最右节点的直线路径叫做最右路径
所有边表示为五元组(i,j,ni,lij,nj)
前向边i<j
后向边i>j
边的排序:e1<e2, if
同是前向边,且j1<j2
同是后向边,且i1<i2或者i1=i2&& j1<j2
e1是前向边,e2是后向边,且j1<=i2
e1是后向边,e2是前向边,且i1<j2
根据边的次序得到的边序列是图的DFS编码
eg:
最小DFS编码:
eg:
4.2 DFS编码树:
4.3 DFS树的剪枝:
剪枝后的所有生成树,DFS编码最小的就是最小DFS编码树。