web-dev-qa-db-ja.com

有向グラフの最小/最大長を見つける

問題は紙の上で簡単です...しかし、それを解決するためのアルゴリズムを書くことになると、少し難しいです。

次のグラフを使用してみましょう。

enter image description here

前編

このグラフには、エントリポイントAと、2つの可能な出口BおよびJがあります。入口から出口に移動するために必要なノードの最小数と最大数を見つける方法を探しています(計画は[〜#〜] any [ 〜#〜]ノードから出口までですが、とりあえず最初から最後まで行きましょう)。

上記のグラフでは、最小長は明らかに1(A -> B)。ノードEは「前の」ノードCにリンクされており、無限ループを作成する可能性があるため、最大距離を見つけるのは難しくなります。 Eを除外すると、最大長は6(A -> C -> D -> F -> G -> I -> B)。

ただし、Eを保持する場合、無限ループを回避するための最善の方法は何ですか?

  • リンクが2度交差しないように、アクセス時にリンクにタグを付けますか?
    • Cから来た場合、Eの後に再び移動することはできません。
  • 大きな値を無限ループに設定します(このようなセクションを1000回以上超えたときに終了するなど)?
    • 小さなループを含むすべてのグラフの最大長は1000ですが、これは関係ありません。

行く方法は何ですか?最小/最大距離を最も適切な方法で見つける方法は?

後編

最終的には、グラフのノードからの最小/最大距離を取得することが目標です(たとえば、CG、またはEから開始)。

また、特定のノードにクロス/リンクできるノードを定義するために、いくつかの条件を設定できます。たとえば、Eを使用している場合、特定の値と変数の状態に応じて、Gしか使用できない場合があります...

ご協力いただきありがとうございます。

4
lvictorino

最初の部分:

入口点と出口点のリストがわかっていて、適切なヒューリスティックがない場合、簡単なアプローチは、すべての(入口、出口)ペアに対して、 Dijkstraのアルゴリズム を使用し、最短のみを維持することです。

最長パスの場合、アルゴリズムの距離の代わりに負の距離を使用します。

ヒューリスティックな場合(たとえば、グラフに地理が含まれている場合)は、より効率的であるため、 A *アルゴリズム をお勧めします。

これはささいなことですが、最も効率的ではありません。開始点が1つなので、同じサブパスの距離を数回再計算します。したがって、すべてのターゲットノードに到達したときにのみ停止し、最短距離と最長距離で同時に動作するように、ダイクストラのアルゴリズムを適応させるのは興味深いかもしれません。

後編

達成しようとしていることが明確ではありません:2つのノード間で最小/最大?またはエントリポイントからのみですか?

この広範な部分の一般的なヒントとして、 スパニングツリーアルゴリズム を確認し、目的に合わせて結果を活用する方法を確認することをお勧めします。

たとえば、 最小スパニングツリー (MST)を作成すると、接続されたノード間のすべての最短パスを含む非循環グラフができます。したがって、可能なすべてのペアに対してダイクストラのアルゴリズムを実行する必要はありません。 2つのノードを含むMST内の唯一のパスを見つける必要があるだけです。 (注:「ツリー」という用語は誤解を招く可能性があります。ここでは、ルートノードの周りに構築およびバランスされたツリーではなく、グラフ理論の場合のツリー、つまり非循環2つのノード間にパスが1つしかないグラフ

MSTには、グラフの最適化に関する他のいくつかのアプリケーションがあります。

グラフに複数の独立した接続コンポーネント(コンポーネント間で到達可能なノードのグループ)が含まれている場合、スパニングツリーのフォレスト(接続コンポーネントごとに1つのツリー)が必要になることに注意してください。スパニングツリーに、ツリー内のノードのセットを簡単に提供するデータ構造を使用する場合、2つのノードが接続されている場合、非常に簡単に見つけることができます。両方が同じスパニングツリーのノードのセットに属している必要があります。 。

1
Christophe

最短経路については、よく知られたダイクストラのアルゴリズムから始めます。


Eにいるとき、特定の値と変数の状態に応じて、Gのみが使用可能になる場合があります...

簡単な解決策-実装をお勧めします-は、指定されたノードから外部リンクを取得する関数を呼び出すようにダイクストラを実装することです。その後、そこでチェックを行うことができます。条件が変わったら、検索結果を無効にして、再度実行します。

:ノードを無効化済みとしてマークできるとなお良いです。このようにして、アルゴリズムはリンクのリストをキャッシュし、無効化されたノードのみを再評価できます。

使用中のグラフを変更できない場合、特定のリンクまたはノードが使用できなくなることは、実際には問題ではありません。グラフの計算を行うだけです。

これは懸念事項であるため、グラフをトラバースするものがあると思います。ある瞬間から別の瞬間に変化したことがわかります...それが起こると、この何かはグラフ上である程度の距離を進んでいます。変更されたグラフ上の現在位置からターゲットまでのパスを計算することは理にかなっています。


最長パスをどのように定義するかわかりません...

おそらく、最長パスの適切な定義は次のとおりです。訪問済みノードの数を最大化する最短パス。その定義では、無限ループを歩くことは有益ではありません。

最短経路を検索します...しかし、「距離」を呼び出す新しいメトリックが必要です。私の最初の直感は、新しいノードにアクセスしても増加しないメトリックを使用することです。

新しいノードにアクセスしたときに距離が増減しない場合、次のパスは同じ長さです。

A -> B
A -> C -> F -> G -> I -> B

ただし、2番目のパスを改善する必要があります(つまり、「短い」、つまり、メトリックの値が低いほど、つまり優先されることを意味します)。

簡単な解決策は、新しいノードにアクセスするときにメトリックを減らすことです。

メモ:

  • 負の指標は問題となる可能性があります。パス検索では、ダイクストラをネガティブと共に使用することは安全ではありません。比較する前にシグモイド関数を使用して、正の値のみに正規化できます。
  • また、ノードにアクセスしたかどうかにかかわらず、距離が異なるというルールをエンコードする必要があります。これは、グラフの一部を使用できないようにするために説明したのと同様の方法で解決できます。ただし、現在のノードを渡して使用可能なリンクを評価する代わりに、現在のパスを渡します。

このメトリックを使用すると、次のようになります。

A B - length: -1

A C D F G I B - length: -6

A C D E G I B - length: -6

A C D E B - length: -4

A C D E J - length: -4

A C D E C D F G I B - length: -5
        ¯ ¯
A C D E C D E G I B - length: -3
        ¯ ¯ ¯
A C D E C D E B - length: -1
        ¯ ¯ ¯
A C D E C D E J - length: -1
        ¯ ¯ ¯
A C D E C D E C D E F G I B - length: -1
        ¯ ¯ ¯ ¯ ¯ ¯

次に、「最長」パスは、ループしない2つの長いパスの1つです(A C D F G I BまたはA C D E G I B)。

明らかでない場合、ループのあるパスは常にループのないバリアントよりも悪いと見なされます。これは、ループが訪問したノードを通過するため、メトリックが増加するためです。そして、メトリックを最小化していることを思い出してください。

このメトリックのシグモイドを使用してダイクストラを使用している場合-私が示唆するように-ループは破棄されます-上で説明したように-ループがない場合よりも常に最悪のパスが生成されるためです。

補遺:回答を投稿した後、興味深い結果が得られたことに気づきました...例:A C D E C D F G I BA C D F G I Bよりも多くのノードにアクセスできますが、スコアは高くなります(高い) 、それは私が期待したものではありません。追加または短縮された距離に係数を適用することで、ターゲットに到達する前に多くのノードに到達するために多少の関心を払うように微調整できると思います...たとえば、訪問したノードをトラバースします。増加するのに理想的な割合はどれくらいですか?何も思いつきません。実用的な目的のために、設計または問題の領域に合わせて調整できます。

1
Theraot

奇妙な問題、コメントで述べたように、それは Longest path problem のインスタンスであるように見えます。これはNP困難です。ただし、バックトラッキングを使用した指数時間ソリューションがあるはずです。そのためには、どのエッジ/ノードがパスによってすでにプローブされているかについて、ある種の予約(フラグ、ハッシュセット)が必要です。
ソリューションは次のように説明できます

  1. 現在のノードが目標ノードである場合、これまでの最長/最短パスを記録します
  2. 未訪問のノードにつながる未訪問のエッジがある場合、それを通過します
  3. そのようなエッジがない場合は、そのようなエッジを持つノードが見つかるまでバックトラックします(展開されたパスパーツの通過フラグをリセットします)。
  4. 入口ノードに戻って、利用可能なエッジがない場合(=パスが空)に終了する
1
wondra

目標指向の行動計画を確認する

https://gamedevelopment.tutsplus.com/tutorials/goal-oriented-action-planning-for-a-smarter-ai--cms-2079

これにより、使用可能なノードの条件を設定できます。

ただし、ループの問題はより困難です。繰り返しとして数えるものを定義する必要があり、同じノードを2回訪問するほど単純ではありません。

たとえば、次のように例の最長パスを考えることができます

A C D E[〜#〜] c [〜#〜]D F G I B

0
Ewan