グラフの最も一般的な祖先の類似アルゴリズム


7

私は型システムに取り組んでいて、最も低い共通の祖先に似ているように見える問題を見つけました。2つのタイプがある場合、同じターゲットタイプになる変換の最小シーケンスを見つける必要があります。単純なタイプツリーがある場合、結果を取得する方法はわかっていますが、残念ながら、もう少し複雑なグラフ構造があります。

そのグラフにはいくつかの重要なポイントがあります。これは単方向であり、ループは形成されません。タイプの数に制限がないため、静的に作成することはできません。パスの距離は一般的に非常に短いです。それは、多くのショートカットエッジを持つツリーのように「感じ」ます。

最初は最低の共通祖先を調べましたが、それは主にツリーアルゴリズムとして記述されています。私はそれを適応させることができるという希望をまだあきらめていません。他の可能性は、より一般的な経路探索アルゴリズムです。

私は誰かが以前にこの問題、または同様の問題を見たことがあることを願っています。何かが存在している必要があると思い込み、間違った用語/名前を検索しているだけであることは十分によく知られているようです。


これをより正式に説明するための私の試みは次のとおりです。

グラフがあり、各頂点に1組の出力エッジます。グラフは動的で、場合によっては無限なので、グラフ全体に対してG = \ {V、E =(V_x、V_y)\}の形式を作成する方法はありません。G={V}V={E=Vx}G={VE=VバツVy}

パスは、そのノードから利用可能なエッジのいずれかをたどることにより、頂点から形成されます。。このパスの長さは、シーケンス内の頂点の数と同じです。可能なサイクルはありません。2つのノード間のすべてのパスのセットは、として表されます。Pメートルバツ=VVメートルPメートル={VVメートル}

は有限のステップ数で空であると判断できることに注意してください。セット全体を列挙することは実際には不可能です。PメートルPメートル

問題は、2つの頂点から3番目の頂点への最短経路を見つけることです。すなわち、所与の、ある見つけるパスするようと存在し、最小です。VaVbVcPacバツPbcylegthPacバツ+legthPbcy


1
有向サイクルのない有向グラフは、DAGと呼ばれます。あなたの場合、グラフにはループが含まれていないと言います。サイクルを含めることができますか?
Yuval Filmus 2013年

1
また、問題をより正式に述べることができますか?ここに1つの可能性があります、を最小化するノードを探します。ここで、は有向距離です。また、ノードを指定すると、そのノードを指すすべてのエッジ、つまり、すべての直接の祖先を列挙できますか?バツyzdzバツ+dzyd
Yuval Filmus 2013年

1
を最小化する必要があると思いました。最下位の祖先はどの場合にも存在しますか(例:のような「ルート」はありますか)?最高dzバツdzyjava.lang.Object
frafl 2013年

編集。ノードを指定すると、はい、その直接の祖先をすべて列挙できます。いいえ、共通のルートはなく、2つのタイプに共通の祖先があることは保証されません。
edA-qa mort-ora-y 2013

1
「すべての直接の祖先を列挙できる」とは、直接の祖先の数が有限であることを意味するものではないことに注意してください。これはおそらく言いたいことです。「最短経路を見つける」ルールが、型システムのあいまいさを解決するためのその場限りの方法として意図されている場合、望ましくないプロパティが存在することが判明する可能性があります。一方、適切に使用すれば望ましくない特性がないことを示すことができれば、興味深い結果になります。それ以外の場合、Posetの「最小上限」は、「最も低い共通祖先」のより自然な解釈になります。
Thomas Klimpel 2013年

回答:


5

2つのタイプの最も低い共通の祖先が常に存在し、一意である場合、構造は結合セミラティスです。最も低い共通の祖先を計算することは可能ですが、最悪の場合のランタイムの複雑さは、私が直感的に予想したほどにはよくありません。私は尋ねた、関連する質問をいくつかの時間前、私は「文学」の関連する解決策を発見した後に答えを書くのが面倒でした。私は今答えを書きました、そしてそれは次のように始まります:

格子理論に関するこのブログポストには、特にVijay K. Gargによる「アプリケーションを備えた格子理論」を含む有用な参照セクションがあります。第2章「ポセットの表現」では、ポセットを表現するためのいくつかのデータ構造について説明し、そのようなデータ構造を使用してjoin(x、y)を計算する方法について説明します。

2.3.1章の関連部分は次のとおりです。

次に、アルゴリズムを使用して、2つの要素と結合を計算します。結合が存在しない場合、アルゴリズムは返し。まず、カバーリレーションを使用していると仮定します。を計算には、次のようにします。O+|e|バツyあなたlljoバツy

  • ステップ0:すべてのノードを白に着色します。
  • ステップ1:から到達可能なすべてのノードを灰色に色付けします。これは、ノードから始まるBFSまたはDFSによって実行できます。バツバツ
  • ステップ2:ノードからBFS / DFSを実行します。到達したすべての灰色のノードを黒に色付けします。y
  • ステップ3:現在、各黒ノードのために決定、それをポイントブラックノード数。この番号を任意のノード呼び出します。この手順は、すべてのブラックノードの隣接リストを、配列の累積カウントを維持することにより、で実行できます。zzBlack[z]zO+|e|Black
  • ステップ4:我々は黒ノードの数カウントとに等しい。ノードが1つしかない場合は、そのノードを答えとして返します。それ以外の場合はを返し。zBlack[z]0あなたll

この回答は、DAGで定義された半順序に関して「最も低い共通祖先」を解釈します。パスの長さに関する読み取りでは、半格子はもうありませんが、アルゴリズムはBFSを使用して両方の検索を適切にインターリーブするだけで適応できます。posetの解釈は、少なくとも1つの「最下位の共通祖先」候補が存在するかどうかを判断するのに依然として役立ちます。
Thomas Klimpel 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.