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