簡體   English   中英

將無向加權圖拆分為 k 個相等的子圖,同時最小化切割邊的權重

[英]Split undirected weighted graph into k equal subgraphs while minimizing weight of cutted edges

我有以下帶有 28 個頂點的加權圖: 在此處輸入圖片說明

我的目標是將這個 Graph 分成 k 個(在本例中為 3)個大小幾乎相同(10、9、9)的分區,以便分區中的邊權重最大化(切割邊權重最小化)。

我已經閱讀了很多關於 k-cut 算法的內容,但找不到一個返回大小盡可能相等的分區的算法。

盡管如此,我還是發現了這個: https : //towardsdatascience.com/a-simple-and-fast-deterministic-algorithm-for-the-minimum-k-way-cut-74d7ee2a521a

它現在在 Amazon EC2 z1d.6xlarge 上運行了大約 2 個小時,其中 192GiB 的 RAM 目前使用了 140GiB。 所以我想我很快就會用完它的內存。

沒有必要找到絕對的最小切割。 所以確定性算法不是必須的。

任何建議表示贊賞。

先感謝您。

只有 28 個頂點,您可能可以像蠻力一樣智能地強制它,但要更智能一點。 這里的好處是這些事情往往更容易實現。

將您的節點隨機分成 3 組所需大小。 現在我們只需弄清楚我們正在移動多少元素。 基本上弄清楚將從每個組中取出多少個值。 然后生成那些被取出的可能組合。 然后組合這些值並為這些值生成排列並將每個值分配到它們被換出的組,然后在交換后計算新的總和。

組合為 5 的示例

# This is more psuedo code than valid code, though it's based on Ruby
nodes = node.shuffle # Randomize the order of the nodes list
A = nodes.pop(9)
B = nodes.pop(9)
C = nodes # Remaining 10

min_k = 1 # Adjust if you want to say resume calculations
K = 9
best_weight = 0
best_combo = nil
(min_k..K).each do |a|
  (1..(K - i)).each do |b|
    c = K - a - b # a + b + c = k, a,b,c <= K
    a_combinations = A.combinations(a) # https://apidock.com/ruby/Array/combination
    b_combinations = B.combinations(b)
    c_combinations = C.combinations(c)
    products = a_combinations.product(b_combinations,c_combinations)
    # https://apidock.com/ruby/Array/product
    products.each do |a_values, b_values, c_values|
      values = a_values + b_values + c_values # Merge values into 1 list
      permutations = values.permutations(values.size) # All possible orderings
      permutations.each do |permutation| # https://apidock.com/ruby/Array/permutation
        new_a_values = permutation.pop(a)
        new_b_values = permutation.pop(b)
        new_c_values = permutation.pop(c) # permutation should now be an empty list
        # Swap out old values with new values
        new_A = A.duplicate().delete_all(a_values).add_all(new_a_values)
        new_B = B.duplicate().delete_all(b_values).add_all(new_b_values)
        new_C = C.duplicate().delete_all(c_values).add_all(new_c_values)
        # See how it worked out.
        new_weight = edge_weight(new_A) + edge_weight(new_B) + edge_weight(new_C)
        if new_weight >= best_weight
          best_weight = best_combo
          best_combo = [new_A,new_B,new_C]
          # definitely important to see results as the algorithm runs
          log("New Best Weight: " + best_weight + " by " + best_combo)
        end
      end
    end
  end
end 

return best_weight 

我懷疑你會在 K=3 到 K=5 的情況下很快得到好的結果(而且你總是可以生成一個新的隨機種子並再次運行它)。

在平均情況下計算該算法的確切性能是很棘手的。 但粗略地說,它應該是O(K^2*K^(K/2)*k!)大約是9^2*9^5*9!= 10^12 個循環(可能不實用)。 但是,即使在 K=5 時,您也應該看到相當不錯的結果,這在高端只需要 375K 循環。 我想這是可以在幾分鍾或更短的時間內運行的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM