簡體   English   中英

驗證和規范化部分有序集

[英]Validating and normalizing a partially ordered set

我有一對像這樣的對:

[["a", "b"], ["b", "d"], ["a", "c"], ["e", "d"], ["a", "d"], ..., ["s", "f"]]
  1. 檢查給定數組是否可以表達部分排序的有效方法是什么? 也就是說,給定數組中沒有“循環”,如["a", "b"], ["b", "c"], ["c", "a"]

  2. 如果確認數組表示偏序,我想通過去除所有可以通過自反性或傳遞性導出的對來對其進行標准化。 例如,在上文中,由於存在["a", "b"]["b", "d"] ,所以該對["a", "d"]是多余的,應該被移除。

1到2之間的順序無關緊要。 如果2應該在1的過程之前或之內完成,那么,那很好。

我最好在Ruby 1.9.3中使用它,但只需偽代碼即可。

對於1號:
您可以將問題模塊化為圖形 ,並且每對都是邊緣,接下來您可以運行拓撲排序 - 如果算法失敗,圖形不是DAG - 並且存在“循環” - 否則 - 您得到一個可能的偏序,作為拓撲排序的輸出。

對於number2:
我根本不確定這個部分,所以這個答案實際上只是部分的,抱歉 - 但只是一個初步的:
您可以使用DFS ,並將“已發現”頂點中的邊刪除到[剛剛發現的頂點] [在同一路徑上]。 雖然我認為它不是最優的,但是可能會反復進行[直到沒有做出任何改變]才能改進它。

更深入的數字2:
我不確定你的意思,但DFS創建的森林滿足了你的要求,但是我擔心你可能會丟失過多的數據,例如: ["a","b"],["a","c"],["b",d"],["c","d"]將修剪["b","d"]["c","d"] ,這可能是太多了,但它也會修剪所有“冗余”邊緣,如示例中所述。

第二個問題被稱為傳遞減少

對於這個問題的第一部分,我想到了我自己的答案在這里有一個答案在數學的網站上的幫助。

對於問題的第二部分,在遵循其他答案中給出的建議后,我在Ruby(i) Floyd-Warshall算法中實現了計算傳遞閉包,(ii)組成,以及(iii)使用公式R的傳遞減少^ - = R - R \\ cdot R ^ +。

module Digraph; module_function
    def vertices graph; graph.flatten(1).uniq end
    ## Floyd-Warshall algorithm
    def transitive_closure graph
        vs = vertices(graph)
        path = graph.inject({}){|path, e| path[e] = true; path}
        vs.each{|k| vs.each{|i| vs.each{|j| path[[i, j]] ||= true if path[[i, k]] && path[[k, j]]}}}
        path.keys
    end
    def compose graph1, graph2
        vs = (vertices(graph1) + vertices(graph2)).uniq
        path1 = graph1.inject({}){|path, e| path[e] = true; path}
        path2 = graph2.inject({}){|path, e| path[e] = true; path}
        path = {}
        vs.each{|k| vs.each{|i| vs.each{|j| path[[i, j]] ||= true if path1[[i, k]] && path2[[k, j]]}}}
        path.keys
    end
    def transitive_reduction graph
            graph - compose(graph, transitive_closure(graph))
    end
end

用法示例:

Digraph.transitive_closure([[1, 2], [2, 3], [3, 4]])
#=> [[1, 2], [2, 3], [3, 4], [1, 3], [1, 4], [2, 4]]

Digraph.compose([[1, 2], [2, 3]], [[2, 4], [3, 5]])
#=> [[1, 4], [2, 5]]

Digraph.transitive_reduction([[1, 2], [2, 3], [3, 4], [1, 3], [1, 4], [2, 4]])
#=> [[1, 2], [2, 3], [3, 4]]

暫無
暫無

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

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