簡介
對於同一個圖,我們可以用各種不同的形式來描述,這些形式都具有相同數目的邊,具有相同數目的頂點,它們有着一一對應的關系,對應的頂點具有相同的連接性。這些圖的不同形式,我們稱之為圖同構。
直觀來說,如果圖G1,G2頂點和邊數量相同,且邊(具有方向性,即有向圖)的連接性相同,這兩個圖定義為同構。可以認為,G1的點是由G2中的點映射得到。
隨着上世紀八九十年代一大批(應用)數學家投入到對圖論中這個問題的研究,各種研究成果也層出不窮。重要的是應用能很快投入實際。從圖像處理識別到視頻動態分析,從生物高分子學到文檔語言處理,圖論中的這個問題也成為相對熱門的研究對象。
圖同構問題一般可以分為四個不同的研究種類:精確圖完全同構、精確子圖同構、不精確圖完全同構、不精確子圖同構。證明已后面三者是NP-Complete問題,第一類問題還沒有定論,一般認為是NP問題。這個blog的系列主要研究精確圖同構問題。
以圖a和圖b為例:
不言而喻,從圖b到圖a存在着一組映射:
a_1->b_3 a_2->b_4 a_3->b_1 a_4->b_2
因此兩圖是同構的。這就是exact matching。
子圖同構問題,顧名思義描述的是圖b能否與圖有向a的某個子圖同構。還是以上述兩個圖為例,在圖a中增加一條3到2的有向邊。此時圖a的子圖(subgraph)a’和圖b同構(顯然)。
算法框架
1971年的ACM雜志上,刊登了一篇被人廣泛引用的論文。埃因霍溫大學的C Bron,對無向圖的Maximal Clique問題做了一點微小的工作,然后地位就不知道高到哪里去了。過了40年,某學者在IEEE上發圖同構綜述,還把這篇論文尊為鼻祖。也許有人要問了,我們前面看的不是有向圖嗎,為什么要放一篇八竿子打不着關系的文章上來,發ranka是不是也要湊字數湊引文啊?
說毫無關系也是不對的。看下這篇Finding All Cliques of an Undirected Graph,70年代的行文風格簡單粗暴,上來也沒有像今天寫論文或是本文這樣纏纏綿綿的引用和簡介,intro只有一句話:不在任意一個完全子圖里面的完全子圖(又稱為團,Clique),稱之為Maximal Clique(最大團)。然后立刻放出求最大團的兩個算法,就像啪啪兩槍直刺心臟,毫無一句廢話。技巧有二:第一叫做backtracing(回溯),第二叫做branch & bound(剪枝)。雖然目標不同,但這就是解決圖同構問題的基本框架(之一)了。兩個技巧被后世的高中生們學了去,在OI界大殺特殺,這又是后話。
第一個算法也是無比brute,維持一個搜索狀態,不斷將點加入到有可能的點集中,直到無法繼續擴展。(2b continued…)
在搜索的基礎上,我們可以寫一個簡單的處理同構問題的框架。以剛才的例子來說,圖同構最后得到的結果是一串序列:3,4,1,2,代表b圖對a圖的映射關系。因此可以進行如下的搜索過程:
上圖為初始狀態,搜索節點為空,用{}{}表示,先假定a圖的搜索順序為{1,2,3,4}{1,2,3,4},最后形成的搜索結果應為{(1,bs1),(2,bs2),(3,bs3),(4,bs4)}{(1,bs1),(2,bs2),(3,bs3),(4,bs4)},其中snsn代表b圖點搜索的順序。
第一步,將b圖中的節點1加入搜索,與a圖中的節點1對應。映射關系用紅色表示。狀態為狀態為{(1,1)}
第二步,加入b圖中的節點2。因為兩個圖中1到2都存在一條有向邊,所以目前這個狀態沒有問題。狀態為 {(1,1),(2,2)}
第三步,加入b圖中的節點3。檢查邊的情況,發現圖b中紅色的邊與圖a中相對應的邊連通性不同,即圖a應有一條邊從3指向1而實際情況不同。因此搜索回溯,回到第二步中的狀態
{(1,1),(2,2)} ,再繼續往下加入節點4形成新的狀態
{(1,1),(2,2),(3,4)}。這里檢查的准則是,只要當前搜索到的b子圖中存在某條邊,對應的a子圖中就應該存在相對應的邊,這樣就能夠得到b和a中的某個子圖同構。
有搜索基礎就知道,這其實就一個深度優先搜索(DFS)。以此類推,最后得到完全匹配的狀態{(1,3),(2,4),(3,1),(4,2)}
這是一個比較簡單的搜索,但是效率顯然低下。問題出在沒有利用圖a的任何一條性質,而是簡單的從1,2…..一直到n搜索a,造成搜索樹的大量分叉。那就改改吧!圖a本身可以用dfs生成一個圖的搜索前序。這樣的好處是可以盡快將不可能的情況進行剪枝。直觀的來說,a的子圖里面邊越多,限定的條件也就越多,剪枝的效率越高。所以a的搜索順序應遵循兩個原則:1、出入度多的在前面。2、按照前序。
以下,用生成的數據做了一組簡略的測試。圖a有15個節點,30條邊,圖b有15個節點,39條邊,測試在圖b中找到圖a的同構子圖。以下圖沒有雙向邊,沒有點指向本身的圈。對於每個圖,數據格式第一行為n m,代表圖的節點數量和邊數量。下面m行u v 代表從u到v存在有向邊。
15 30
1 3
1 4
1 5
1 14
2 12
3 9
3 10
3 11
4 2
4 3
4 10
4 11
5 2
5 10
6 7
6 10
7 11
8 4
8 14
9 4
9 11
9 15
10 2
10 7
12 1
12 11
13 1
13 8
14 9
14 1115 39
11 5
11 10
11 3
11 13
4 8
5 1
5 9
5 6
10 4
10 5
10 9
10 6
3 4
3 9
7 14
7 9
14 6
15 10
15 13
1 10
1 6
1 2
9 4
9 14
8 11
8 6
12 11
12 15
13 1
13 6
4 1
9 6
2 3
4 12
11 4
7 12
5 7
8 2
4 15
最后用VS2012測試得到結果如下:
算法1遍歷1477個狀態,算法2遍歷171個狀態。符合預期。
而在下面這個例子中,兩個算法的效率差異是驚人的:
20 50
1 14
2 18
3 10
4 3
4 9
4 11
4 18
5 2
5 12
5 15
6 7
6 8
6 13
7 8
7 15
8 1
9 1
9 12
9 15
11 1
11 2
11 5
11 8
11 14
11 15
11 20
12 6
12 19
13 2
13 16
13 18
14 7
14 12
15 18
16 1
16 3
16 12
16 14
16 19
17 2
17 9
17 10
18 3
18 5
18 6
18 8
18 9
19 8
20 9
20 1020 64
11 15
18 4
16 13
17 16
17 2
17 6
17 4
10 18
10 1
10 7
12 3
12 5
12 20
3 5
3 7
5 11
2 11
2 1
2 7
6 11
6 18
6 10
6 5
6 15
6 7
6 8
1 12
1 19
20 18
20 14
20 4
15 3
15 1
7 4
14 11
14 16
14 1
14 15
14 19
9 18
9 2
9 13
4 16
4 10
4 12
4 5
4 2
19 5
8 2
8 13
5 13
17 14
14 6
14 7
6 13
2 15
3 8
16 15
12 8
20 2
13 3
20 6
7 1
1 20
針對50條邊的圖a,算法1搜索了2834001個狀態,而改良后的搜索只遍歷了953個狀態!在稀疏圖面前,這個剪枝還是相當強的。