ディペンデンシーグラフからの冗長なエッジの削減


8

多くの冗長エッジを含む依存関係のDAGがあります(以下の例を参照)。最小限のサブグラフを見つける「クイック」アルゴリズム(つまり、数千のノード/エッジを持つグラフを処理できる)が必要です。

例えば:

A -> B -> C
A -> C

つまり、AはBの前提条件であり、BはCの前提条件であり、AもCの前提条件です。この場合、A-> Cは冗長です(BはCに到達するためにすでに必要であり、AはBに到達するために必要なので) 。

アルゴリズムを研究してからしばらく経ちましたが、どこから始めればよいかわかりません。

ちなみに、アルゴリズムがグローバル最小値、ローカル最小値を見つけることが重要であることは重要ではありません(エッジ削減は、処理の次の段階のランタイム最適化にすぎません)。

また、これはプログラミングではなくCS QAであることに気づきましたが、私のプログラムはPythonで書かれているため、ご存知の場合に備えて、この削減を行うためのpythonモジュールまたはオープンソースについて学ぶことができれば幸いです。

前もって感謝します!


DFSがここで役立つかどうか疑問に思っていましたか?
Pratik Deoghare、2011年

3
依存関係グラフの「推移的な削減」を探しています。
Dave Clarke

強結合コンポーネントを見つけます。コンポーネントの各ペアの間に1つのエッジのみを残します。強く接続されたコンポーネントごとに、それをカバーするサイクルの最小数を見つける必要があります。最小サイクル数を見つけることはハミルトニシティを決定するため、NP完全であるように見えますが、ローカル最小値のみが必要であるため、強い接続が失われるまで各コンポーネントからエッジを削除するだけです。
カヴェ

回答:


13

有向グラフの推移的な削減AV Aho、MR Garey、JD Ullman

wikipediaによると、このアルゴリズムはtredGraphVizパッケージで利用可能な推移的削減のためのツールであるによって使用されます。あなたはそれをあなたのグラフ上で実行して、縮小グラフを得ることができます。

この質問は、このstackoverflow質問の複製です。

ここのコード graphviz/tools/src/tred.c DFSを使用ます。;-)


2
知りませんtredでした、ありがとう。
Anthony Labarre

1
MachineCharmerに感謝します。私は大学の外にいて、25ドルを支払わないと論文をダウンロードできません...このアルゴリズムを説明する無料のオンラインソースはありますか?tredソースは小さくて読みやすいですが、説明はありません。
イフタ、2011年

いいえ。その論文の無料ダウンロードリンクはありません。しかし、あなたはいくつかの大学で友達を持っているかもしれません:)
Pratik Deoghare '27

-1

私はこのようにそれを解決することになりました:

私のデータ構造はdependends、ノードIDからそれに依存するノードのリスト(DAGでのフォロワー)まで、辞書で構成されています。

正確な複雑さは計算していませんが、数千のグラフを一瞬で飲み込んでしまいました。

_transitive_closure_cache = {}
def transitive_closure(self, node_id):
    """returns a set of all the nodes (ids) reachable from given node(_id)"""
    global _transitive_closure_cache
    if node_id in _transitive_closure_cache:
        return _transitive_closure_cache[node_id]
    c = set(d.id for d in dependents[node_id])
    for d in dependents[node_id]:
        c.update(transitive_closure(d.id))  # for the non-pythonists - update is update self to Union result
    _transitive_closure_cache[node_id] = c
    return c

def can_reduce(self, source_id, dest_id):
    """returns True if the edge (source_id, dest_id) is redundant (can reach from source_id to dest_id without it)"""
    for d in dependents[source_id]:
        if d.id == dest_id:
            continue
        if dest_id in transitive_closure(d.id):
            return True # the dest node can be reached in a less direct path, then this link is redundant
    return False

# Reduce redundant edges:
for node in nodes:      
    dependents[node.id] = [d for d in dependents[node.id] if not can_reduce(node.id, d.id)]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.