DFSに関するグラフ検索バージョンとツリー検索バージョンの違いは何ですか?人工知能でのA *検索?
DFSに関するグラフ検索バージョンとツリー検索バージョンの違いは何ですか?人工知能でのA *検索?
回答:
既存の回答から判断すると、この概念については多くの混乱があるようです。
ツリー検索とグラフ検索の違いは、問題のグラフがツリーであるか一般的なグラフであるかに関係しません。一般的なグラフを扱っていると常に想定されています。違いは、グラフ状またはツリー状のグラフを検索するために使用されるトラバーサルパターンにあります。
ツリー状の問題を処理している場合、両方のアルゴリズムのバリエーションは同等の結果を導きます。したがって、より単純なツリー検索バリアントを選択できます。
基本的なグラフ検索アルゴリズムは次のようになります。開始ノードstart
、有向エッジ、successors
およびgoal
ループ条件で使用される仕様。open
現在検討中のオープンリストであるノードをメモリに保持します。次の疑似コードは、すべての側面で正しくないことに注意してください(2)。
open <- []
next <- start
while next is not goal {
add all successors of next to open
next <- select one node from open
remove next from open
}
return next
の実装方法に応じてselect from open
、深さ優先検索(DFS)(最新の要素を選択)、幅優先検索(BFS)(最も古い要素を選択)、均一コスト検索(パスコストが最も低い要素を選択)など、さまざまな種類の検索アルゴリズムを取得します。 )、最も低いコストにヒューリスティック値を加えたノードを選択することによる、人気のあるAスター検索など。
上記のアルゴリズムは、実際にはツリー検索と呼ばれています。開始状態をルートとする複数の有向パスがある場合、根本的な問題のグラフの状態を複数回訪問します。有向ループ上にある場合、状態を何度も訪問することも可能です。ただし、各訪問は、検索アルゴリズムによって生成されたツリーの異なるノードに対応しています。後で説明するように、この明らかな非効率性が必要になる場合があります。
見てきたように、ツリー検索は州を複数回訪れることができます。そのため、この状態の後に見つかった「サブツリー」を数回探索します。グラフ検索は、閉じたリストですべての訪問済み状態を追跡することにより、これを修正します。新しく見つかった後継next
がすでにわかっている場合は、開いているリストに挿入されません。
open <- []
closed <- []
next <- start
while next is not goal {
add next to closed
add all successors of next to open, which are not in closed
remove next from open
next <- select from open
}
return next
すべての訪問状態を追跡するため、グラフ検索にはより多くのメモリが必要です。これは、オープンリストが小さいことで補われる場合があり、検索効率が向上します。
実装のいくつかの方法は、select
最適なソリューションを返すことを保証できます-つまり、最短パスまたは最小コストのパス(コストがエッジに接続されているグラフの場合)。これは基本的に、コストが増加する順にノードが展開される場合、またはコストがゼロ以外の正の定数である場合に当てはまります。この種の選択を実装する一般的なアルゴリズムは、均一コスト検索、またはステップコストが同一の場合はBFSまたはIDDFSです。IDDFSは、BFSの積極的なメモリ消費を回避し、ステップサイズが一定である場合、通常、無知の検索(別名ブルートフォース)に推奨されます。
また、(非常に人気のある)A * ツリー検索アルゴリズムは、許容ヒューリスティックと共に使用すると最適なソリューションを提供します。ただし、A * グラフ検索アルゴリズムは、一貫性のある(または「単調な」)ヒューリスティック(許容よりも強い条件)で使用した場合にのみ、この保証を行います。
簡単にするために、提示されたコードは以下を行いません:
state
かnode
は、コンテキストに依存します。しかし、問題のグラフの頂点とトラバーサルグラフに使用すると、回答の明確さを確実に向上させることができます。すぐ書き直してみます。ありがとうございました。state
node
ツリーはグラフの特殊なケースであるため、一般的なグラフで機能するものはすべてツリーで機能します。ツリーは、ノードの各ペア間に正確に1つのパスがあるグラフです。これは、以前の回答で述べたように、サイクルが含まれていないことを意味しますが、サイクルのない有向グラフ(DAG、有向非巡回グラフ)は必ずしもツリーではありません。
ただし、グラフにツリーやDAGなどの制限があることがわかっている場合は、通常、制限のないグラフよりも効率的な検索アルゴリズムを見つけることができます。たとえば、ツリー上でA *またはその非ヒューリスティックな「ダイクストラのアルゴリズム」を使用することはおそらくあまり意味がありません(とにかく選択するパスが1つだけあり、DFSまたはBFSで見つけることができます)またはDAG(トポロジーソートで取得した順序で頂点を検討することで最適なパスを見つけることができます)
無向対指向については、無向グラフからエッジ(リンク、遷移)がある場合に向かう一つのルールに従う、すなわちケース」の特別な場合であるUとVはエッジからもあるVにU。
更新:グラフ自体の構造ではなく、検索のトラバーサルパターンが重要な場合、これは答えではないことに注意してください。たとえば、@ ziggystarの回答を参照してください。
グラフとツリーの唯一の違いはサイクルです。グラフにはサイクルを含めることができますが、ツリーには含めることができません。したがって、ツリーに検索アルゴリズムを実装する場合は、サイクルの存在を考慮する必要はありませんが、任意のグラフを操作する場合は、それらを考慮する必要があります。サイクルを処理しない場合、アルゴリズムは最終的に無限ループまたは無限再帰に陥る可能性があります。
もう1つ考えなければならない点は、処理するグラフの方向特性です。ほとんどの場合、各エッジで親子関係を表すツリーを扱います。DAG(有向非循環グラフ)も同様の特性を示します。ただし、双方向のグラフは異なります。双方向グラフの各エッジは、2つの近傍を表します。したがって、これらの2種類のグラフでは、アルゴリズムによるアプローチが少し異なるはずです。
グラフ対ツリー
ただし、AIグラフ検索とツリー検索の場合
グラフ検索には、アルゴリズムが新しいノードを探索し、それを「visited」とマークするたびに「使用されるアルゴリズムに関係なく」という優れた特性があります。アルゴリズムは通常、現在のノードから到達可能な他のすべてのノードを探索します。
たとえば、3つの頂点ABとCを含む次のグラフを考え、次のエッジを考えます。
AB、BC、CA、CからAへのサイクルがあります。
そして、Aから始まるDFSを実行すると、Aは新しい状態Bを生成し、Bは新しい状態Cを生成しますが、Cが探索されると、アルゴリズムは新しい状態Aを生成しようとしますが、Aはすでにアクセスされているため、無視されます。涼しい!
しかし、木はどうですか?よく木アルゴリズムは訪問済みノードを訪問済みとしてマークしませんが、ツリーにはサイクルがありません。無限ループに入るにはどうすればよいですか?
3つの頂点を持つこのツリーを考え、次のエッジを考えます
A-B-CはAをルートとし、下向き。そして、DFSアルゴリズムを使用しているとしましょう
Aは新しい状態Bを生成し、Bは2つの状態A&Cを生成します。これは、ツリーに「探索されたノードを訪問済みとしてマークする」ことがないため、DFSアルゴリズムがAを再度探索し、新しい状態Bを生成するためです。私たちは無限ループに入っています。
しかし、何か気づいたことがありますか?私たちは無向エッジに取り組んでいます。つまり、ABとBAの間に関係があります。もちろん、これはサイクルではありません。サイクルは、頂点が> = 3でなければならず、最初と最後のノードを除いてすべての頂点が異なることを意味するためです。
ST A-> B-> A-> B-> Aサイクルプロパティに違反しているため、サイクルではありません> =3。しかし、実際にはA-> B-> C-> Aはサイクル> = 3つの異なるノードチェックされています、最初と最後のノードは同じCheckedです。
ここでも、ツリーのエッジA-> B-> C-> B-> Aを検討します。もちろん、サイクルではありません。2つのBがあり、すべてのノードが異なるわけではないためです。
最後に、ツリー検索アルゴリズムを実装して、同じノードを2回探索するのを防ぐことができます。しかし、それは結果をもたらします。