スクラッチゲームの伝統的な誘導アルゴリズム

1 深さ優先アルゴリズム (DFS)

        このアルゴリズムは最短経路アルゴリズムではなく、基本的な検索アルゴリズムですが、指定されたノードがグラフ内で見つかるかどうかで結論付けることができます。

一般的なアイデア:

  1. 開始ノードから始めて、訪問済みとしてマークします。

  2. 現在のノードの近隣ノードの中に未訪問のノードがあるかどうかを確認します。

  3. 未訪問のノードがある場合は、未訪問のノードの 1 つを次の現在のノードとして選択し、それを訪問済みとしてマークします。その後、ステップ 2 に戻ります。

  4. 未訪問のノードがない場合は、前のノードに戻り、つまりこのノードの上位ノードに戻り、手順 2 を繰り返します。

  5. すべてのノードにアクセスするまでステップ 4 を繰り返します。


具体的な実施

再帰

        グラフ全体を記述する 2 次元配列または隣接リストを格納するグローバル変数があります。

        関数 dfs を作成します。パラメーターは、グラフ内の現在のノードの位置と、ターゲット ノードの特性または位置をマークします。戻り値は、それが見つかったかどうかです。

        関数を入力し、まず現在のノードを訪問済みとして設定します。

        現在のノードがターゲットの場合は、直接 true を返します

        周囲に到達可能な未訪問のノードを一定の順序で読み取り、再帰的に dfs 関数を呼び出します。dfs が true を返した場合、関数はすぐに true を返します。dfs が false を返した場合は、周囲のノードの検索を続けます。

        周囲のノードがどれも移動できない場合、つまり関数がここで実行された場合、 false を返します。

スタック

  1. グラフ全体を記述する 2 次元配列または隣接リストを格納するグローバル変数がまだ存在します。
  2. スタックを構築する
  3. 開始点をスタックにプッシュし、開始点を訪問済みとしてマークします
  4. スタックに要素がある限りループします。
  5. スタックの最上位要素を現在のノードとして取得します
  6. スタックの最上位要素をポップオフします
  7. 現在のノードがエンドポイントを満たしている場合、ループから抜け出します。
  8. 特定の順序で到達可能な未訪問のノードを読み取り、それらをスタックにプッシュし、訪問済みとしてマークします。

幅優先アルゴリズム (BFS)

        一般的には最初に dfs を学習してから bfs を学習しますが、bfs の方が dfs より簡単だと思います。

アイデアは次のとおりです。

  1. 開始ノードから開始し、それを訪問済みとしてマークし、キューに入れます。

  2. キューからノードを現在のノードとして取得します。

  3. このノードが終点であるかどうかを判断します。終点である場合、サイクル数は最短のパス長であり、

  4. 現在のノードのすべての隣接ノードの中に未訪問のノードがあるかどうかを確認します。

  5. 未訪問のノードがある場合は、それらを訪問済みとしてマークし、キューに入れます。

  6. キューが空になるまで手順 2 ~ 5 を繰り返します。

その実装は多かれ少なかれ次のようになります。


ダイクストラのアルゴリズム

        次に、初期のヒューリスティック検索について説明します。これは、エッジの重みを考慮するため、グラフ パスファインディングで最も広く参照されるシナリオですが、エッジの重みが 0 の場合、幅優先検索に退化します。

アイデアは次のとおりです。

  1. 初期化: 開始ノードを訪問済みとしてマークし、開始ノードからの距離を 0 に設定し、他のすべてのノードの距離を無限大に設定します。

  2. 最短パスを見つける: 開始ノードから開始し、現在わかっている最短距離に従って、訪問する未訪問のノードの中から距離が最小のノードを選択します。

  3. ノード距離の更新: 選択したノードについて、ノードとその隣接ノードの距離の合計を計算します。現在のノードを経由して隣接するノードまでの距離が、以前に記録された最短距離よりも小さい場合は、最短距離を更新します。

  4. 訪問済みとしてマーク: 現在のノードを訪問済みとしてマークします。これは、開始ノードからこのノードまでの最短パスが見つかったことを意味します。

  5. ステップ 2 ~ 4 を繰り返します。すべてのノードが訪問済みとしてマークされるか、到達可能なノードがなくなるまで、ステップ 2 ~ 4 を繰り返します。このようにして、各ノードの最短経路が決定される。

  6. 最短経路の出力: 最後に、計算された最短経路情報に従って、開始ノードから各ノードまでの特定の経路を出力できます。

        実装も同様です。今コードを投稿するのは不便なので、アイデアについてのみ話します。一般的な実装では、2 次元配列ではなく隣接リストを設定します。2 次元配列は不便だからです。エッジの重みを説明します。


フロイドのアルゴリズム

フロイド氏の考えた最も単純なアルゴリズムは次のとおりです。

  1. 初期化: ノード間の最短パス距離を保存するために 2 次元配列 D を作成します。最初に、2 点間にエッジがある場合、その距離は D に割り当てられ、2 点間にエッジがない場合、その距離は無限大に設定されます。

  2. 反復更新: 各頂点 k について、ノード i と j の各ペアを順次に走査し、ノード k を通るノード i とノード j の間の最短パスの改善を試みます。つまり、ノード i からノード j までの距離が、ノード i からノード k までの距離にノード k からノード j までの距離を加えたものより大きい場合 (つまり、D[i][k] + D[k][j]) 、ノード i を更新します。ノード j までの距離は D[i][k] + D[k][j] です。

  3. 反復を繰り返す: すべてのノードが一度中間ノードとみなされるまで、毎回新しい中間ノード k を考慮して反復更新を続けます。

  4. 最短パスを出力する: 反復の完了後、2 次元配列 D に格納されるのは、任意の 2 点間の最短パス距離です。

ただし、その時間計算量は許容範囲外であり、O(n^3) と同じくらい高くなります。


貪欲な検索

        選択の各段階で現時点で最善の選択を採用し、一連の局所的に最適な選択を経て全体的な最適に到達することを望み、過去を振り返ることはありません。

貪欲検索の基本的な考え方は次のとおりです。

  1. 初期化: 問題の初期状態を判断します。

  2. 選択フェーズ: 現在の状態から開始して、何らかの基準に従って最善のアクションまたは決定が選択されます。この選択はローカル情報に基づいており、以前の選択や将来の結果は考慮されていません。

  3. ステータスの更新: 選択したアクションまたは決定に基づいて、現在のステータスを更新します。

  4. 終了条件: 現在の状態が終了条件を満たす(終点に到達する)場合は検索を終了し、そうでない場合は手順2に戻ります。

        特定の実装は、周囲のどの点が終点に近いかを検出するヒューリスティック関数に依存しています。

        貪欲なアルゴリズムは近視眼的であるため、得られる結果は正しくない可能性がありますが、通常は高速に実行されます。したがって、場合によっては、貪欲な検索によって次善の解決策が得られたり、解決策が見つからなかったりすることがあります。したがって貪欲なアルゴリズムは適していません


最良の最初の検索

        Best-First Search は、評価関数に基づいて次に展開されるノードを選択するヒューリスティックな検索アルゴリズムです。評価関数は、現在のノードからターゲット ノードまでのコストまたは距離を推定するために使用され、アルゴリズムは常に評価値が最も低いノードを選択して拡張します。

最良優先検索の基本的な考え方は次のとおりです。

  1. 初期化: 問題の初期状態を判断します。

  2. 拡張するノードの優先キューを維持し、最初に初期状態をキューに入れます。

  3. 解決策が見つかるかキューが空になるまで、次の手順を繰り返します。

a. 評価値が最も低いノードをキューから削除します。

b. 現在のノードがターゲット ノードであるかどうかを確認し、ターゲット ノードである場合は、解決策が見つかったことになり、検索が終了します。

c. それ以外の場合は、現在のノードに従ってすべての可能な子ノードを展開し、各子ノードの評価値を計算します。

d. 子ノードを評価値の降順にキューに挿入します。

        最良優先検索では、評価関数を使用して展開する次のノードを選択し、評価値でソートします。このソート戦略により、検索アルゴリズムがターゲットに近い方向に移動する可能性が高くなり、検索効率が向上します。ただし、ベストファースト検索は、現在の最適なノードのみに焦点を当て、以前の選択や将来の結果を考慮しないため、全体的な最適解を見つけることを保証しませんが、ベストファーストアルゴリズムは、最適解を取得するのが簡単です。貪欲な検索ソリューション。バックトラッキングを考慮する場合もありますが、それでも最適なソリューションが保証されるわけではありません


あ*

        A* (A-Star) は、最良優先探索とダイクストラのアルゴリズムを組み合わせたヒューリスティック検索アルゴリズムです。検索プロセス中に 2 つの値を維持します。1 つは開始ノードから現在のノードまでの実際のコスト (g 値)、もう 1 つは現在のノードからターゲット ノードまでの推定コスト (h 値) です。

A* アルゴリズムの基本的な考え方は次のとおりです。

  1. 初期化: 問題の初期状態を決定し、開始ノードをオープン リストに追加します。

  2. 2 つのリストを維持します。 オープン リスト: 展開されるノードを f 値 (f = g + h) でソートして保存します。閉じたリスト: 展開されたノードを格納します。

  3. 解決策が見つかるか、開いているリストが空になるまで、次の手順を繰り返します。

a. 開いたリストから f 値が最小のノードを現在のノードとして選択します。

b. 現在のノードがターゲット ノードであるかどうかを確認し、ターゲット ノードである場合は、解決策が見つかったことになり、検索が終了します。

c. それ以外の場合は、現在のノードを開いているリストから閉じたリストに移動します。

d. 現在のノードに従ってすべての可能な子ノードを展開し、各子ノードの g 値と h 値を計算します。

e. 各子ノードについて、それがすでにオープン リストまたはクローズド リストに含まれている場合は、新しい g 値と既存の g 値を比較し、より小さい更新を選択します。それ以外の場合は、子ノードをオープン リストに追加します。

        A アルゴリズムは、ヒューリスティック推定関数を使用して検索プロセスをガイドし、実際のコストと推定コストを組み合わせます。g 値は開始ノードから現在のノードまで (すでに拡張されたパスを経由) の実際のコストを表し、h 値は通常ヒューリスティック関数 (マンハッタン距離など) を使用して、現在のノードからゴール ノードまでの推定コストを表します。またはユークリッド距離) を計算します。A アルゴリズムでは、f 値が最も小さいノードが拡張用に選択され、f 値が小さいノードの優先順位が高くなります。

        A アルゴリズムは、特定の条件下で最短パス (最適解) を見つけることを保証できます。つまり、最小の f 値を持つノードが全体的な最適解になります。ただし、場合によっては、A アルゴリズムがヒューリスティック関数の影響を受けて最適解を見つけることができなかったり、探索空間が非常に大きい場合に多くの時間とメモリを消費したりすることがあります。


B*

        次に、A* に対していくつかの最適化を実行します。

        A* アルゴリズムでは、h 値はヒューリスティック関数によって推定され、この推定値は検索の効率と品質に大きな影響を与えます。ただし、ヒューリスティック関数が正確な推定値を提供しない状況もあります。たとえば、問題によっては、ヒューリスティック関数がターゲット ノードの正確な推定コストを取得できない場合があり、その結果、検索アルゴリズムが偏り、最適な解決策を見つけることができなくなります。

        B アルゴリズムでは、サブゴールという新しい概念を導入し、より柔軟な推定方法を採用しています。B アルゴリズムでは、アルゴリズムは最初にサブ目標を生成し、次にそのサブ目標を使用してヒューリスティック関数の推定値を修正します。具体的な手順は次のとおりです。

  1. 初期化: 問題の初期状態を決定し、開始ノードをオープン リストに追加します。

  2. 2 つのリストを維持します。 オープン リスト: 展開されるノードを f 値 (f = g + h) でソートして保存します。閉じたリスト: 展開されたノードを格納します。

  3. 解が見つかるか、開いているリストが空になるまで、次の手順を繰り返します: a. 開いているリストから f 値が最小のノードを現在のノードとして選択します。b. 現在のノードがターゲット ノードであるかどうかを確認し、ターゲット ノードである場合は、解決策が見つかったことになり、検索が終了します。c. それ以外の場合は、現在のノードを開いているリストから閉じたリストに移動します。d. 現在のノードに従ってすべての可能な子ノードを展開し、各子ノードの g 値と h 値を計算します。e. 各子ノードについて、サブ目的に従ってヒューリスティック関数の推定値を修正し、新しい f 値を計算します。f. 子ノードを開いているリストに追加します。

        B アルゴリズムは、ヒューリスティック関数の推定値を継続的に調整することで、より正確なパス推定値を取得します。サブゴールを使用して検索プロセスをガイドし、サブゴールの情報に従ってヒューリスティック関数の推定値を修正し、新しい推定値に従ってノード拡張を実行します。このプロセスにより、B アルゴリズムは探索中にパス推定を徐々に修正し、問題の特性によりよく適応できるようになります。


D*

        D* (D-Star) は、変更グラフ検索とパス計画に基づいた増分アルゴリズムです。これは、環境の既知のマップ上での経路計画に使用され、マップ情報が変化したときに迅速に更新できます。

D* アルゴリズムの基本的な考え方は次のとおりです。

  1. 初期化: 開始ノードと目標ノードを含む問題の初期状態を決定し、他の関連データ構造を初期化します。

  2. 2 つの主要なデータ構造を維持します。 状態グラフ: 各ノードの状態、コスト、接続関係などの情報を記録します。優先キュー (Priority Queue): コストによってソートされたキュー。次の拡張ノードを選択するために使用されます。

  3. 解決策が見つかるかパスが見つからなくなるまで、次の手順を繰り返します: a. プライオリティ キューからコストが最も低いノードを現在のノードとして選択します。b. 現在のノードに変更(コストの更新や接続関係の変更など)があったかどうかを確認し、変更がある場合は、関連する情報を更新します。c. 現在のノードに隣接するノードのコストを更新し、新しいコスト値を計算します。d. ターゲットノードのコストが変化した場合は、パスを再評価します。それ以外の場合は、最適なパスに沿って展開します。e. 更新された情報に基づいて優先キューを並べ替えます。

        D アルゴリズムは、コストとノードの接続関係を継続的に更新することでマップの変更に適応し、経路計画プロセスを動的に調整します。これは、増分検索および更新戦略を使用しており、マップまたはコスト情報を変更した後にパスを迅速に再計画できます。D アルゴリズムは、ターゲット ノードに到達するかパスが見つからなくなるまで、ノードの選択と展開を繰り返します。


逆方向および双方向の最適化

        始点と終点を入れ替えてアルゴリズムを実行すると逆になりますが、あまり最適化効果はありません。

        2 つの配列が重なるまで順方向の検索結果を 1 つの配列に入れ、逆方向の検索結果を別の配列に入れて、それらが見つかったことを示すというアイデア。これにより、検索範囲を効果的に縮小し、最適化を達成できます。

おすすめ

転載: blog.csdn.net/leyang0910/article/details/131946401