FSG算法

原文An Efficient Algorithm for Discovering Frequent Subgraphs

生成候选子图

通过将两个大小为kk的图合并,从而得到k+1k+1图。同时两个kk图要满足必须包含相同的k1k-1子图的条件。为了避免生成很多无用的kk图,采用如下方式。令FiF_i表示一个频繁kk子图,P(Fi)={Hi,1,Hi,2}\mathcal{P}(F_i)=\{H_{i,1},H_{i,2}\}表示FiF_i的两个k1k-1子图,其中Hi,1H_{i,1}的canonical label 最小,Hi,2H_{i,2}的canonical label第二小,这两个图也称为FiF_i的基本子图。当且仅当P(Fi)P(Fj)\mathcal{P}(F_i) \cap \mathcal{P}(F_j)\ne\empty时,两个子图FiF_iFjF_j可以合并。合并后可能会产生多个k+1k+1图,如下图所示:
FSG算法
FSG算法

统计频率

对每一个频繁子图,我们都关联一个transaction id list(图数据库中的每个图称为transaction,每个transaction都有一个唯一的id)。表示包含该频繁子图的transaction。当需要计算k+1k+1子图的频繁度时,首先对kk频繁子图的TID取交集。如果交集的元素个数小于阈值,则不生成k+1k+1子图。如果大于阈值,则判断交集中的每个图是否包含k+1k+1子图。为了减少TID list的存储消耗,采用了对数据库分块的方法,具体操作见论文。

Canonical Label

Canonical label使用了邻接矩阵存储格式,因此FSG需要首先把邻接列表格式转换成邻接矩阵格式,然后生成canonical label。

Vertex Invariants

顶点的度或者标签与图的拓扑排序是无关的,因此无论如何对图进行排序,这些性质是不变得。通过vertex invariants,将节点分类,具有相同属性值(度相同)的节点归为一类。在对节点排序时,我们保持类别间的顺序不便,只对每个类别中的节点进行排列,这样生成的code就会非常少,也更容易找到canonical label。分类越细致,所需要生成的code就越少,因此,论文中进一步采用了neighbor list的方法进行细分。每个节点uu的邻接节点vv都用用一个三元组{l(e),d(v),l(v)}\{l(e),d(v),l(v)\}表示,l(e)l(e)表示边u,vu,v的标签,d(v)d(v)表示vv的度,l(v)l(v)表示vv的标签。节点uu的所有邻接节点的三元组构成了集合nl(u)nl(u)。只有当两个节点的nlnl相等时,才将两个节点归为一类。该细分是在上一步划分的基础上执行的。
为了更细致的划分,论文用一个二元组{p(v),l(e)}\{p(v),l(e)\}代替了三元组。其中p(v)p(v)表示邻居节点vv所属的类别的id。然后通过邻居节点二元组的集合,迭代的对每个类别分类,直到不能分类为止。

类别排序

通过适当的对类别排序,可以进一步减少canonical label的时间。这是因为通过类别的排序我们可以知道当前的排列是否可能生成比现有最好的canonical label更小。论文将类别按照度递减的顺序排列。

Vertex Stabilization

当迭代划分之后,仍有某些类别包含很多个节点时,需要用到该方法。当所有的节点和边有相同的标签时,并且每个节点与其它节点的度相同(对称的图),此时便无法对节点划分。论文中强制的将一个节点认为是不同的,然后将其单独拿出来构造一个类,接着使用迭代划分。划分的过程仍然可能需要使用vertex stabilization方法。由于是随机选择的一个节点,因此,该类别中的每个节点都要选择一次才行。即使这样仍然比判断所有节点的排列要快。