絕對均勻圖生成算法


最近在研究圖計算的性能,需要構造不同的測試數據對圖算法進行壓測,其中就涉及到均勻圖的概念。

因為做的是理論測試,因此就需要一種理論上絕對均勻的圖測試數據,接下來我們就討論一下絕對均勻圖的生成。

一、何為絕對均勻圖?

為了方便討論,我們只討論無向圖,而且圖中的邊是無權值的,且兩點之間只能存在一條邊,即邊僅代表結點之間的關聯。

從圖論角度出發,我們都知道圖都是由結點以及結點之間的關聯邊組成的。直觀上理解,絕對均勻的圖應該是圖中的所有結點的度都完全相同,這樣每個結點都是同構的,也就是說從任何一個結點進行觀察,得到的都是同樣的結果。

形式化的描述應該是這樣,對於圖 \(G=(V, E)\) ,其中\(V\)是結點集合,\(E\)是邊集合,記 \(|V|\) 為結點數, \(|E|\) 為邊數,圖的平均度為 \(D\) ,由於每條邊為圖貢獻兩個度,於是存在以下關系:
\( D = \frac{2\cdot|E|}{|V|}(公式1) \)

因此,根據前面對均勻概念的理解,對於絕對均勻圖,任何一個節點的度數都滿足:
\( d_v = D = \frac{2\cdot|E|}{|V|}(公式2) \)

二、簡單討論一下

明確了絕對均勻圖的概念后,接下來就是如何生成的問題。由於
\( |E| = \frac{d_v\cdot|V|}{2}(公式3) \)
我們只需要控制結點數 \(|V|\) 和每個結點的度數 \(d_v\) 這兩個變量即可。因此我們的目標就是生成任意結點數,且結點度數任意的絕對均勻圖

我們知道,完全圖其實就是一種絕對均勻圖,其所有節點的度數為 \(|V| - 1\) ,這已經是圖中結點可以達到的最高度數了。相應的,空圖(只有點,沒有邊)也是絕對均勻圖,即所有節點的度數都為 \(0\),為最低度數。因此絕對均勻圖的結點度數總是滿足:
\( 0\le d_v\lt|V|(公式4) \)

通過觀察上面的公式2,我們還可以得出如下結論:

  1. 當結點數為奇數時,\(|V| = 2k - 1, k=1,2...\) , 由於 \(|E|\) 是整數,因此 \(d_v\) 必為偶數。
  2. 當結點數為偶數時,\(|V| = 2k, k=1,2...\)\(d_v\) 沒有限制,因為總有 \(|E| = d_v\cdot k\)

一言以蔽之,對於奇數點數的絕對均勻圖,結點度數只能取 \([0, |V|)\) 之內的偶數。故而在圖生成算法上需要對奇數點數圖區分對待。

三、試一下遞歸?

那么如何構建絕對均勻圖呢?首先比較容易想到的就是遞歸思想,遞歸的基本思路是:

  1. 構建問題最簡單的規模實例,即遞歸的初值,或稱為終止條件。
  2. 在最簡單規模的實例基礎上,通過增加問題規模,推測問題規模增大時,問題變化的規律。
  3. 繼而推導在問題規模為\(n\)的時,構造問題規模為\(n+1\)的遞歸條件。這也就意味着,問題規模增大時得到的結果,總是蘊含,甚至包含上一級規模問題的結果

上面討論過,對於絕對均勻圖,有兩個變量影響圖的規模:結點數 \(|V|\) 和結點度數 \(d_v\) 。因此分析時,要假定其中有一個不變量才比較好思考。

1. 結點度數不變,增大結點數

由於奇數結點數的圖的結點度數不可能為奇數,因此我們保持結點度數為偶數不變,保證結點數從奇數到偶數再到奇數時,可以連續地推導問題變化規律。

這里取\(d_v = 2(0度不具備參考性,可作為邊界條件考慮)\),令 \(|V| = 3, 4, 5, 6\),可以得到如下圖實例。

貌似按照環形圖的思考方式,問題是可以遞歸的。每增加一個結點時,只需要選取一條邊斷開,然后連接到新的結點即可。

再考慮一下\(d_v = 4\)的情況,令 \(|V| = 5, 6\),可以得到如下圖實例。

這種情況下,好像使用上述的遞歸擴展方式就不太容易了。那另外一種情況呢?

2. 結點數不變,增大結點度數

這里取 \(|V| = 6\),令 \(d_v = 0, 1, 2, 3, 4, 5, 6\),可以得到如下圖實例。

可以看到,當度從\(3\)增長到\(4\)時,新規模問題的解並不包含上一級問題所有的解,而且每一級變化的規律並不穩定。

因此用上面的遞歸思想去分析絕對均勻圖生成的問題可能並不方便,我們需要轉換一下思路。

四、核心思想

回到第一節對絕對均勻圖的概念描述:絕對均勻圖的結點是同構的,滿足各向同性。這就意味着我們可以從一個結點出發,去設法尋找它的關聯節點,並且這種方式對任何一個結點都是相同的。

那么如何找到關聯結點呢?考慮到絕對均勻圖每個點都是同構的,因此絕對均勻圖一定是中心對稱的!假設這個虛擬的對稱中心為\(O\),在\(d_v = 1\)的情況下,關聯結點一定是當前結點的中心對稱結點。

那在\(d_v = 2\)的情況下呢?

或許會有人好奇,這個\(d_v = 2\)的圖怎么不是環呢?其實對於同樣結點數和度數的絕對均勻圖,圖的結構可能不止一種

按照中心對稱思想依此類推,可以得到其他度的絕對均勻圖。

因此,關聯結點的尋找思路如下:

  1. \(d_v=2k(k=0, 1, 2...)\) 時,關聯結點為當前結點的中心對稱結點兩側的各\(k\)個結點。
  2. \(d_v = 2k + 1(k=0, 1, 2...)\) 時,關聯結點為當前結點的中心對稱結點加上中心對稱結點兩側的各\(k\)個結點。

我們發現,前面討論的不可行的遞歸方式主要是被環形圖的思路干擾了。利用中心對稱的關聯結點尋找方式是也是可以遞歸的,不過使用循環實現可能更方便。

五、算法實現與測試

基於中心對稱思想的絕對均勻圖生成算法實現如下:

public boolean generate(int count, int degree) {

    // 基本參數校驗
    if (!(count > 0 && degree >= 0 && degree < count)) {
        System.err.println("Invalid arguments !");
        return false;
    }

    // 檢查奇數點圖的度是否是偶數
    if (count % 2 == 1 && degree % 2 != 0) {
        System.err.println("Degree should be odd when vertices' count is even !");
        return false;
    }

    // 生成點
    System.out.println("Generating vertices:");
    for (int index = 0; index < count; index++) {
        System.out.println(index);
    }

    // 生成邊
    System.out.println("Generating edges:");
    for (int index = 0; index < count; index++) {

        // 對面的點
        int opposite = (index + count / 2) % count;

        // 點偶數,度奇數,鏈接中心對稱結點
        if (count % 2 == 0 && degree % 2 == 1) {
            System.out.println(index + " -> " + opposite);
        }

        // 鏈接中心對稱結點兩側的點
        for (int i = (count + 1) % 2; i <= (degree - count % 2) / 2; i++) {
            final int previous = (opposite - i + count) % count;
            final int next = (opposite + i + count % 2) % count;

            System.out.println(index + " -> " + previous);
            System.out.println(index + " -> " + next);
        }
    }

    return true;
}

為了更直觀的展示生成的絕對均勻圖,可以借助vis.js庫進行繪制。

具體實現方式可以訪問github源碼drawG,該項目實現了一個簡單的圖生成與繪制框架,可以方便定制和擴展圖生成器和處理器。

最后,看一下使用該框架生成的絕對均勻圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM