問題は紙の上で簡単です...しかし、それを解決するためのアルゴリズムを書くことになると、少し難しいです。
次のグラフを使用してみましょう。
このグラフには、エントリポイントA
と、2つの可能な出口B
およびJ
があります。入口から出口に移動するために必要なノードの最小数と最大数を見つける方法を探しています(計画は[〜#〜] any [ 〜#〜]ノードから出口までですが、とりあえず最初から最後まで行きましょう)。
上記のグラフでは、最小長は明らかに1(A -> B
)。ノードE
は「前の」ノードC
にリンクされており、無限ループを作成する可能性があるため、最大距離を見つけるのは難しくなります。 E
を除外すると、最大長は6(A -> C -> D -> F -> G -> I -> B
)。
ただし、E
を保持する場合、無限ループを回避するための最善の方法は何ですか?
C
から来た場合、E
の後に再び移動することはできません。行く方法は何ですか?最小/最大距離を最も適切な方法で見つける方法は?
最終的には、グラフのノードからの最小/最大距離を取得することが目標です(たとえば、C
、G
、またはE
から開始)。
また、特定のノードにクロス/リンクできるノードを定義するために、いくつかの条件を設定できます。たとえば、E
を使用している場合、特定の値と変数の状態に応じて、G
しか使用できない場合があります...
ご協力いただきありがとうございます。
入口点と出口点のリストがわかっていて、適切なヒューリスティックがない場合、簡単なアプローチは、すべての(入口、出口)ペアに対して、 Dijkstraのアルゴリズム を使用し、最短のみを維持することです。
最長パスの場合、アルゴリズムの距離の代わりに負の距離を使用します。
ヒューリスティックな場合(たとえば、グラフに地理が含まれている場合)は、より効率的であるため、 A *アルゴリズム をお勧めします。
これはささいなことですが、最も効率的ではありません。開始点が1つなので、同じサブパスの距離を数回再計算します。したがって、すべてのターゲットノードに到達したときにのみ停止し、最短距離と最長距離で同時に動作するように、ダイクストラのアルゴリズムを適応させるのは興味深いかもしれません。
達成しようとしていることが明確ではありません:2つのノード間で最小/最大?またはエントリポイントからのみですか?
この広範な部分の一般的なヒントとして、 スパニングツリーアルゴリズム を確認し、目的に合わせて結果を活用する方法を確認することをお勧めします。
たとえば、 最小スパニングツリー (MST)を作成すると、接続されたノード間のすべての最短パスを含む非循環グラフができます。したがって、可能なすべてのペアに対してダイクストラのアルゴリズムを実行する必要はありません。 2つのノードを含むMST内の唯一のパスを見つける必要があるだけです。 (注:「ツリー」という用語は誤解を招く可能性があります。ここでは、ルートノードの周りに構築およびバランスされたツリーではなく、グラフ理論の場合のツリー、つまり非循環2つのノード間にパスが1つしかないグラフ)
MSTには、グラフの最適化に関する他のいくつかのアプリケーションがあります。
グラフに複数の独立した接続コンポーネント(コンポーネント間で到達可能なノードのグループ)が含まれている場合、スパニングツリーのフォレスト(接続コンポーネントごとに1つのツリー)が必要になることに注意してください。スパニングツリーに、ツリー内のノードのセットを簡単に提供するデータ構造を使用する場合、2つのノードが接続されている場合、非常に簡単に見つけることができます。両方が同じスパニングツリーのノードのセットに属している必要があります。 。
最短経路については、よく知られたダイクストラのアルゴリズムから始めます。
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 B
はA C D F G I B
よりも多くのノードにアクセスできますが、スコアは高くなります(高い) 、それは私が期待したものではありません。追加または短縮された距離に係数を適用することで、ターゲットに到達する前に多くのノードに到達するために多少の関心を払うように微調整できると思います...たとえば、訪問したノードをトラバースします。増加するのに理想的な割合はどれくらいですか?何も思いつきません。実用的な目的のために、設計または問題の領域に合わせて調整できます。
奇妙な問題、コメントで述べたように、それは Longest path problem のインスタンスであるように見えます。これはNP困難です。ただし、バックトラッキングを使用した指数時間ソリューションがあるはずです。そのためには、どのエッジ/ノードがパスによってすでにプローブされているかについて、ある種の予約(フラグ、ハッシュセット)が必要です。
ソリューションは次のように説明できます
目標指向の行動計画を確認する
これにより、使用可能なノードの条件を設定できます。
ただし、ループの問題はより困難です。繰り返しとして数えるものを定義する必要があり、同じノードを2回訪問するほど単純ではありません。
たとえば、次のように例の最長パスを考えることができます
A C D E[〜#〜] c [〜#〜]D F G I B