如果转载,请在文章标题注明(转载)并且在文章开头注明转载自本博客:stanly7 http://blog.csdn.net/stanly7 。谢谢。
最近在学习子图同构算法。什么是子图同构,看这里-->图论。在图论的维基百科中有子图同构的描述。
子图同构一直是图论中比较重要的一个问题,经过各位大牛长时间的学习和研究,发现求解子图同构是一个NP完全问题。什么是NP完全问题,可以戳这里--->NP完全。
在经过不断地搜索和阅读论文,发现了不少论文都在讨论子图同构算法。出现得比较多并且很多人都知道并认可的,有这么几种算法:Ullmann算法、Nauty算法、SD算法、VF算法以及在VF算法上进行改进的VF2算法。其中Ullmann算法应该是最早提出的可以找到子图同构的算法。因此现在学习图论如果设计到同构,虽然不会用ullmann算法,但是一般都会以其作为对子图同构的基础进行了解和学习。中间三种算法尚未研究,以后可能会看,因为时间和研究原因我的重点在第一个ullmann和最后的公认最好的VF2算法。
在最坏情况下,ullmann算法的时间复杂度与图中节点数目的指数成正比。ullmann算法以深度优先的方式进行搜索,搜索过程表示为一个布尔矩阵。当节点不匹配时则回溯到最近匹配的节点,寻找其他的搜索方向。同时,算法还会检查匹配点对的邻接点的匹配情况,尽可能早的识别出不可匹配的节点。提高算法的效率。
先介绍深度优先的简单穷举方法,这个阶段不包含上面说的检查匹配点对的邻接点的匹配情况(即refine procedure),将在后面我写好代码之后再发。
此搜索方法其实是深度优先遍历两图的关联矩阵,来找到满足其子图同构的关联矩阵。
对于给定的两个图,是从节点数目大的那个图中寻找部分节点和边,和节点数目小的图是同构的。
图G1=
该算法要寻找的同构关系表现为寻找两图的一个关联矩阵M,这是一个p1*p2的矩阵,其元素mij表示G1的第 i 个节点和G2的第 j 个节点是否对应。因此这个矩阵的限制为:每行只有一个1,而每列最多只有一个1 。因此mij==1表示G1的第 i 个节点和G2的第 j 个节点对应。否则不对应。
条件(1)判定:当找到这样一个M`的时候我们进行如下操作得到另一个p1*p1的矩阵C,定义C为:C=M`(M`B)T,后面的T表示(M`B)做转置。即M`乘以[(M`B)的转置]得到C,如果对于每一个i , j 都属于(1,p1)都满足当aij == 1 时 有cij == 1。那么我们就称此时的矩阵M`标识了G1 到G2子图的一个同构。
初始化M的时候,遵循下面的原则:
如果G2的第 j 个节点的度大于或者等于G1的第 i 个节点的度(表示可能匹配但是不一定),则mij = 1。否则等于0。(此原则是针对无向图,如果是对于有向图则有出度和入度均要大于等于,对于节点可能有其他属性的情况也是类似,保证G2的属性或者条件强于G1即可)。
所以深度优先搜索的就是将M0深度遍历找到所有的满足条件(1)判定的矩阵。
深度优先搜索中,使用d来表示搜索中的层(第几行),使用一个大小为p2的向量F{F1,F2,…F(x)…,F(p2)}(数组表示)来表示哪一列被使用了。比如F[2]==1表示在搜索中第二列被使用了,如果F[2]==0则表示没被使用。同样还使用一个大小为p1的向量H{H1,H2,……,H(p1)}来表示在哪一层使用了哪一列。H[d] = k表示在层d中使用了第k列。
除此之外,还需要一个三维矩阵来记录每层变化过的M`,保证回溯的时候可以回到上一层。第一维长度和d大小一样。二维三维即为M的维度。
Ullmann算法的提出者Ullmann的论文,比较早论文写得挺难懂的。他的伪代码有些需要改动。伪代码如下:
step1
construct M0,M=M0,d=0, H[0] = 0;
for element in F set element = 0
if m has a row that all zero return; (这一步可以放在refine里面)
step2
if there are no value of j such that m[d][j] && F[j] = 0 then goto step7
matrixlist[d] = M
if d = 0 then k = H[0] else k = 0
step3
if matrixlist[d][d][k] = 0 or F[k] == 1
then if k < p2-1 then k+=1 and goto step3 else goto step7
else for all j != k set m[d][j] = 0;
step4 if d < p1 then goto step6 else ( H[d] = k and use condition(1) and giveoutput if an isomorphism is found )
step5
if there is no j > k such that m[d][j] = 1 and F[j] = 0 then k += 1 and goto step7
else k += 1 and goto step3
step6
H[d] = k
F[k] = 1
d +=1
goto step2
step7
if d ==0 then terminate algorithm
if k < p2-1 then copy matrixlist[d] to M and goto step5
else d= d-1 k = H[d] F[k]=0 copy matrixlist[d] to M and goto step5
以上就是算法程序的伪代码。具体实现还是需要自己动手。主要流程就是这样的,缺少的就是condition(1)的判断(包含矩阵的转置和两矩阵的乘法)。很简单,自己加上。之后学习完refine procedure之后会再加上。暂时就这么多。
国内真心很少有这个问题的资料,一些论文都是应用子图同构算法,极少有详细讲这些算法的。
转载请注明出处,谢谢。
You will never walk alone. 我不是一个kop,但是我很喜欢这种精神。http://blog.csdn.net/stanly7