原文An Efficient Algorithm for Discovering Frequent Subgraphs
生成候选子图
通过将两个大小为
k
k
k的图合并,从而得到
k
+
1
k+1
k+1图。同时两个
k
k
k图要满足必须包含相同的
k
−
1
k-1
k−1子图的条件。为了避免生成很多无用的
k
k
k图,采用如下方式。令
F
i
F_i
Fi表示一个频繁
k
k
k子图,
P
(
F
i
)
=
{
H
i
,
1
,
H
i
,
2
}
\mathcal{P}(F_i)=\{H_{i,1},H_{i,2}\}
P(Fi)={Hi,1,Hi,2}表示
F
i
F_i
Fi的两个
k
−
1
k-1
k−1子图,其中
H
i
,
1
H_{i,1}
Hi,1的canonical label 最小,
H
i
,
2
H_{i,2}
Hi,2的canonical label第二小,这两个图也称为
F
i
F_i
Fi的基本子图。当且仅当
P
(
F
i
)
∩
P
(
F
j
)
≠
∅
\mathcal{P}(F_i) \cap \mathcal{P}(F_j)\ne\empty
P(Fi)∩P(Fj)=∅时,两个子图
F
i
F_i
Fi和
F
j
F_j
Fj可以合并。合并后可能会产生多个
k
+
1
k+1
k+1图,如下图所示:
统计频率
对每一个频繁子图,我们都关联一个transaction id list(图数据库中的每个图称为transaction,每个transaction都有一个唯一的id)。表示包含该频繁子图的transaction。当需要计算 k + 1 k+1 k+1子图的频繁度时,首先对 k k k频繁子图的TID取交集。如果交集的元素个数小于阈值,则不生成 k + 1 k+1 k+1子图。如果大于阈值,则判断交集中的每个图是否包含 k + 1 k+1 k+1子图。为了减少TID list的存储消耗,采用了对数据库分块的方法,具体操作见论文。
Canonical Label
Canonical label使用了邻接矩阵存储格式,因此FSG需要首先把邻接列表格式转换成邻接矩阵格式,然后生成canonical label。
Vertex Invariants
顶点的度或者标签与图的拓扑排序是无关的,因此无论如何对图进行排序,这些性质是不变得。通过vertex invariants,将节点分类,具有相同属性值(度相同)的节点归为一类。在对节点排序时,我们保持类别间的顺序不便,只对每个类别中的节点进行排列,这样生成的code就会非常少,也更容易找到canonical label。分类越细致,所需要生成的code就越少,因此,论文中进一步采用了neighbor list的方法进行细分。每个节点
u
u
u的邻接节点
v
v
v都用用一个三元组
{
l
(
e
)
,
d
(
v
)
,
l
(
v
)
}
\{l(e),d(v),l(v)\}
{l(e),d(v),l(v)}表示,
l
(
e
)
l(e)
l(e)表示边
u
,
v
u,v
u,v的标签,
d
(
v
)
d(v)
d(v)表示
v
v
v的度,
l
(
v
)
l(v)
l(v)表示
v
v
v的标签。节点
u
u
u的所有邻接节点的三元组构成了集合
n
l
(
u
)
nl(u)
nl(u)。只有当两个节点的
n
l
nl
nl相等时,才将两个节点归为一类。该细分是在上一步划分的基础上执行的。
为了更细致的划分,论文用一个二元组
{
p
(
v
)
,
l
(
e
)
}
\{p(v),l(e)\}
{p(v),l(e)}代替了三元组。其中
p
(
v
)
p(v)
p(v)表示邻居节点
v
v
v所属的类别的id。然后通过邻居节点二元组的集合,迭代的对每个类别分类,直到不能分类为止。
类别排序
通过适当的对类别排序,可以进一步减少canonical label的时间。这是因为通过类别的排序我们可以知道当前的排列是否可能生成比现有最好的canonical label更小。论文将类别按照度递减的顺序排列。
Vertex Stabilization
当迭代划分之后,仍有某些类别包含很多个节点时,需要用到该方法。当所有的节点和边有相同的标签时,并且每个节点与其它节点的度相同(对称的图),此时便无法对节点划分。论文中强制的将一个节点认为是不同的,然后将其单独拿出来构造一个类,接着使用迭代划分。划分的过程仍然可能需要使用vertex stabilization方法。由于是随机选择的一个节点,因此,该类别中的每个节点都要选择一次才行。即使这样仍然比判断所有节点的排列要快。