子图同构算法——Ullmann算法(1)不包含refine procedure的简单穷举算法。
摘要: 轉(zhuǎn)載請注明來自stanlysheng——talk is cheap, show me your code。http://www.cnblogs.com/stanly/?。謝謝。此文我也在CSDN發(fā)過。
最近在學(xué)習(xí)子圖同構(gòu)算法。什么是子圖同構(gòu),看這里-->圖論。在圖論的維基百科中有子圖同構(gòu)的描述。
子圖同構(gòu)一直是圖論中比較重要的一個問題,經(jīng)過各位大牛長時間的學(xué)習(xí)和研究,發(fā)現(xiàn)求解子圖同構(gòu)是一個NP完全問題。什么是NP完全問題,可以戳這里--->NP完全。
在經(jīng)過不斷地搜索和閱讀論文,發(fā)現(xiàn)了不少論文都在討論子圖同構(gòu)算法。出現(xiàn)得比較多并且很多人都知道并認(rèn)可的,有這么幾種算法:Ullmann算法、Nauty算法、SD算法、VF算法以及在VF算法上進行改進的VF2算法。其中Ullmann算法應(yīng)該是最早提出的可以找到子圖同構(gòu)的算法。因此現(xiàn)在學(xué)習(xí)圖論如果設(shè)計到同構(gòu),雖然不會用ullmann算法,但是一般都會以其作為對子圖同構(gòu)的基礎(chǔ)進行了解和學(xué)習(xí)。中間三種算法尚未研究,以后可能會看,因為時間和研究原因我的重點在第一個ullmann和最后的公認(rèn)最好的VF2算法。
在最壞情況下,ullmann算法的時間復(fù)雜度與圖中節(jié)點數(shù)目的指數(shù)成正比。ullmann算法以深度優(yōu)先的方式進行搜索,搜索過程表示為一個布爾矩陣。當(dāng)節(jié)點不匹配時則回溯到最近匹配的節(jié)點,尋找其他的搜索方向。同時,算法還會檢查匹配點對的鄰接點的匹配情況,盡可能早的識別出不可匹配的節(jié)點。提高算法的效率。
先介紹深度優(yōu)先的簡單窮舉方法,這個階段不包含上面說的檢查匹配點對的鄰接點的匹配情況(即refine procedure),將在后面我寫好代碼之后再發(fā)。
此搜索方法其實是深度優(yōu)先遍歷兩圖的關(guān)聯(lián)矩陣,來找到滿足其子圖同構(gòu)的關(guān)聯(lián)矩陣。
對于給定的兩個圖,是從節(jié)點數(shù)目大的那個圖中尋找部分節(jié)點和邊,和節(jié)點數(shù)目小的圖是同構(gòu)的。
圖G1=<V1,E1>,G2=<V1,E1>,G1 和G2 的節(jié)點數(shù)分別為p1和p2。他們的鄰接矩陣表示分別為A=[aij]和B=[bij]。
該算法要尋找的同構(gòu)關(guān)系表現(xiàn)為尋找兩圖的一個關(guān)聯(lián)矩陣M,這是一個p1*p2的矩陣,其元素mij表示G1的第 i 個節(jié)點和G2的第 j 個節(jié)點是否對應(yīng)。因此這個矩陣的限制為:每行只有一個1,而每列最多只有一個1 。因此mij==1表示G1的第 i 個節(jié)點和G2的第 j 個節(jié)點對應(yīng)。否則不對應(yīng)。
條件(1)判定:當(dāng)找到這樣一個M`的時候我們進行如下操作得到另一個p1*p1的矩陣C,定義C為:C=M`(M`B)T,后面的T表示(M`B)做轉(zhuǎn)置。即M`乘以[(M`B)的轉(zhuǎn)置]得到C,如果對于每一個i , j 都屬于(1,p1)都滿足當(dāng)aij == 1 時 有cij == 1。那么我們就稱此時的矩陣M`標(biāo)識了G1 到G2子圖的一個同構(gòu)。
初始化M的時候,遵循下面的原則:
如果G2的第 j 個節(jié)點的度大于或者等于G1的第 i 個節(jié)點的度(表示可能匹配但是不一定),則mij = 1。否則等于0。(此原則是針對無向圖,如果是對于有向圖則有出度和入度均要大于等于,對于節(jié)點可能有其他屬性的情況也是類似,保證G2的屬性或者條件強于G1即可)。
所以深度優(yōu)先搜索的就是將M0深度遍歷找到所有的滿足條件(1)判定的矩陣。
深度優(yōu)先搜索中,使用d來表示搜索中的層(第幾行),使用一個大小為p2的向量F{F1,F2,…F(x)…,F(p2)}(數(shù)組表示)來表示哪一列被使用了。比如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
以上就是算法程序的偽代碼。具體實現(xiàn)還是需要自己動手。主要流程就是這樣的,缺少的就是condition(1)的判斷(包含矩陣的轉(zhuǎn)置和兩矩陣的乘法)。很簡單,自己加上。之后學(xué)習(xí)完refine procedure之后會再加上。暫時就這么多。
國內(nèi)真心很少有這個問題的資料,一些論文都是應(yīng)用子圖同構(gòu)算法,極少有詳細(xì)講這些算法的。
摘要: 轉(zhuǎn)載請注明來自stanlysheng——talk is cheap, show me your code。http://www.cnblogs.com/stanly/?。謝謝。
轉(zhuǎn)載于:https://www.cnblogs.com/stanly/p/ullmann_algorithm.html
總結(jié)
以上是生活随笔為你收集整理的子图同构算法——Ullmann算法(1)不包含refine procedure的简单穷举算法。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 进入前端开发这个领域 ,请问如何进行系统
- 下一篇: 4-9