グラフアルゴリズムシリーズ: 計算グラフにおける最短経路

グラフアルゴリズムシリーズ: 計算グラフにおける最短経路

[[398324]]

この記事はWeChatの公開アカウント「Beta Learns JAVA」から転載したもので、著者はSilently9527です。この記事を転載する場合は、Beta Learning JAVA パブリック アカウントにお問い合わせください。

序文

前の 2 つの記事では、深さ優先探索を使用して、グラフ内の頂点 v から頂点 w までのパスを見つけることができました。ただし、深さ優先探索は頂点の入力に大きく関係しており、見つかったパスは必ずしも最短ではありません。通常、map 関数など、グラフ内の最短パスを見つける必要があることがよくあります。ここでは幅優先探索アルゴリズムを使用する必要があります

幅優先探索

以前に定義されたパス検索APIを引き続き使用します

  1. パブリッククラスPaths{
  2. パス(グラフ グラフ、 int s);
  3.      
  4. boolean hasPathTo( int v); // s->v からのパスがあるかどうかを判定する
  5.      
  6. Iterable< Integer > pathTo( int v); //パスが存在する場合はパスを返す
  7. }

幅優先探索では、最短経路を見つけるために、再帰を使用してそれを達成するのではなく、開始点の順序ですべての頂点をトラバースする必要があります。アルゴリズムの考え方は次のとおりです。

  • マークされているが、隣接リストがまだ走査されていない頂点を格納するためにキューを使用します。
  • キューから次の頂点vを取り出してマークする
  • vに隣接するマークされていない頂点をすべてキューに追加します。

このアルゴリズムでは、パスを保存するために、エッジ配列 edgeTo[] を使用し、親リンク ツリーを使用して、ルート ノードから接続されているすべての頂点までの最短パスを表す必要があります。

  1. パブリッククラスBreadthFirstPaths {
  2. プライベートブール値 marked[];
  3. プライベートint []エッジTo;
  4. プライベートint s;
  5. プライベート Queue< Integer > queue = new LinkedListQueue<>();
  6.  
  7. パブリックBreadthFirstPaths(グラフグラフ、 int s) {
  8. this.s = s;
  9. this.marked = 新しいブール値[graph.V()];
  10. this.edgeTo = 新しいint [graph.V()];
  11.  
  12. bfs(グラフ, s);
  13. }
  14.  
  15. プライベートvoid bfs(グラフグラフ、 int s) {
  16. this.marked[s] = true ;
  17. this.queue.enqueue(s);
  18. while (!this.queue.isEmpty()) {
  19. 整数v = this.queue.dequeue();
  20. ( int w : graph.adj(v))の場合{
  21. if (!this.marked[w]) {
  22. this.marked[w] = true ;
  23. this.edgeTo[w] = v;
  24. this.queue.enqueue(w);
  25. }
  26. }
  27. }
  28.  
  29.  
  30. }
  31.  
  32. パブリックブール値hasPathTo( int v) {
  33. this.marked[v]を返します
  34. }
  35.  
  36. パブリックイテラブル<整数> pathTo( int v) {
  37. (!hasPathTo(v))の場合{
  38. 新しい IllegalStateException をスローします ( "s は v に到達できません" );
  39. }
  40. Stack<整数> stack = new LinkedListStack<>();
  41. スタックをプッシュします。
  42. (edgeTo[v] != s) の間 {
  43. スタックをプッシュします(edgeTo[v]);
  44. v = エッジ[v];
  45. }
  46. スタックをプッシュします。
  47. スタックを返します
  48. }
  49. }

次の図を列としてとらえ、幅優先探索の軌跡を見てみましょう。

ユニットテストコード:

  1. @テスト
  2. パブリックボイドテスト(){
  3. グラフ graph = new Graph(8);
  4. グラフにエッジを追加します。(0, 1);
  5. グラフにエッジを追加します(0, 2);
  6. グラフにエッジを追加します(0, 5);
  7. グラフにエッジを追加します。(1, 3);
  8. グラフにエッジを追加します。
  9. グラフにエッジを追加します(4, 3);
  10. グラフにエッジを追加します(5, 3);
  11. グラフにエッジを追加します(6, 7);
  12.  
  13. BreadthFirstPaths パス = new BreadthFirstPaths(graph, 0);
  14. システム.out.println (paths.hasPathTo(5));
  15. System.out.println (paths.hasPathTo(2)) ;
  16. システム.out.println (paths.hasPathTo(6));
  17.  
  18. paths.pathTo(5).forEach(System.out:: print );
  19. System.out.println( ) ;
  20. paths.pathTo(4).forEach(System.out:: print );
  21. System.out.println( ) ;
  22. paths.pathTo(2).forEach(System.out:: print );
  23. System.out.println( ) ;
  24. paths.pathTo(3).forEach(System.out:: print );
  25.  
  26. }

実行結果は、私たちが分析した走行軌跡と一致しています。

シンボル図

最近の記事で学んだグラフ アルゴリズムはすべて、数値を頂点として使用しています。これは、数値を使用してこれらのアルゴリズムを実装するのが非常に簡単で便利だからです。ただし、実際のシナリオでは、地図上の場所や映画と俳優の関係など、数値ではなく文字が頂点として使用されることがよくあります。

実際のシナリオに対応するには、数字と文字列のマッピングを作成する必要があります。このとき、前回の記事で実装したマップ(マップはバイナリツリー、赤黒木、ハッシュテーブルなどを通じて実装されます。興味のある学生は調べることができます)を考え、Mapを使用して文字列と数字のマッピング関係を維持します。

  1. パブリックインターフェースSymbolGraph {
  2. boolean contains (String key ); //頂点が存在するかどうかを判断します
  3.  
  4. 整数  index (String key ); //名前で対応するデジタル頂点を返す
  5.  
  6. String name ( int v); //デジタル頂点を通じて対応する文字名を返す
  7.  
  8. グラフ graph();
  9. }

実装のアイデア:

  • マップを使用して文字列と数値のマッピングを保存します。キーは文字列、値は数値です。
  • 配列を使用して、数値から文字列へのマッピングを逆にします。配列の添え字は数値の頂点に対応し、値は文字列名に対応します。
  • 構築されたグラフの頂点と辺が、a、b、c、d\nb、a、h、l、p\ng、s、z などの文字列で表されるとします。\n で区切られた各セグメントの最初の文字列は頂点 v を表し、次の文字列は頂点 v に接続された隣接頂点を表します。

実際のプロセスは、特定の状況に応じて決定されます。必ずしもこの種類の文字列である必要はありません。データベースまたはネットワーク要求から取得できます。

コードは次のように実装されます。

  1. パブリッククラスSymbolGraph {
  2. プライベート Map<String, Integer > map = new RedBlack23RedBlackTreeMap<>();
  3. プライベートString[]キー;
  4. プライベートグラフグラフ;
  5.  
  6. パブリックシンボルグラフ(文字列テキスト) {
  7. Arrays.stream(text.split( "\n" )).forEach(行 -> {
  8. 文字列[]を分割 = line.split( "," );
  9. ( int i = 0; i < split.length; i++) {
  10. map.put([i], i);
  11. }
  12. });
  13.  
  14. this.keys = 新しい文字列[ map.size ()];
  15. map.keys().forEach(キー-> {
  16. this.keys[this.map.get( key )] =キー;
  17. });
  18.  
  19. this.graph = 新しいグラフ(this.keys.length);
  20. Arrays.stream(text.split( "\n" )).forEach(行 -> {
  21. 文字列[]を分割 = line.split( "," );
  22. 分割されたマップ0に分割します。
  23. ( int i = 1; i < split.length; i++) {
  24. this.graph.addEdge(v, this.map.get(split[i]));
  25. }
  26. });
  27.          
  28. }
  29.  
  30. パブリックブール値には(文字列キー)が含まれます
  31. map.contains (キー)を返します
  32. }
  33.  
  34. 公共 整数 インデックス(文字列キー) {
  35. map.get(キー)を返します
  36. }
  37.  
  38. パブリック文字列( int  索引) {
  39. this.keys[インデックス]を返します
  40. }
  41.  
  42. パブリックグラフグラフ() {
  43. this.graphを返します
  44. }
  45.  
  46. 公共 静的void main(String[] args) {
  47. システム.out .println(Arrays.toString( "323\n2323" .split( "\n" )));
  48. }
  49. }

この記事のすべてのソースコードは、github リポジトリに保存されています: https://github.com/silently9527/JavaCore

<<:  AIに関する4つの最も一般的な誤解

>>:  50億のブルーオーシャンが呼び寄せる、電力検査ロボットが最前線に

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

パスワードを忘れたことが引き起こすアルゴリズム思考

2日前、ウェブサイトにログインしようとしていたとき、よく使うパスワードを何回か試して失敗した後、「パ...

...

AI 請求書認識を実現する PaddleOCR ベースの Asp.net Core アプリケーション

簡単な紹介ユーザーは、認識する必要のある写真を一括でアップロードします。アップロードが成功すると、シ...

数人のアメリカ人作家が共同で書簡を書き、AIが著作権のあるコンテンツを使って作品を生み出す場合、著者に補償を与えるよう求めた。

アクションネットワークによると、7月19日、約8,000人の作家がニューヨーク作家組合宛ての公開書簡...

梅雨から台風シーズンまで、ドローンが再び活躍

最近、静かに梅雨の季節が去り、猛烈な台風の季節が勢いよくやって来ています。 [[336317]] 8...

ソフトバンクの孫正義社長:AIの知能は10年以内に人間を超えると予想

ロイター通信は10月4日、ソフトバンクグループの創業者兼CEOの孫正義氏が本日、汎用人工知能(AGI...

致命的な幻覚問題、GPU 代替品の開発、大規模モデルが直面するその他の 10 の課題

ChatGPT、GPT-4などのリリースにより、大規模モデル(LLM)の魅力が明らかになった一方で、...

2023 年の 5 つの驚くべき自動化の進歩

自動化は、業界やプロセスの変革の原動力となり、効率性、コスト効率、エラーの低減を実現しています。 2...

AI に役立つ 7 つのオープンソース ツール

[[282843]]人工知能は未来の道を歩み続ける注目すべき技術です。この進化する時代において、それ...

Google MobileNetを超えろ! Huawei がエッジツーエッジ ニューラル ネットワーク アーキテクチャ GhostNet を提案 | オープンソース

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

スマートホームシステム設計の5つの原則

スマートホームコントロールの開発の鍵は、設計コンセプトとオペレーターの考え方にあります。市場のターゲ...

AI.com ドメインが ChatGPT から X.ai にリダイレクトされました

AI.com ドメイン名は、もともと今年 2 月に OpenAI によって購入され、ChatGPT ...

カーリー:プロのカーリング選手に匹敵するスポーツロボット

海外メディアの報道によると、ロボットは多くのスポーツや活動で優れているが、1つのタスクだけを実行する...

IDC: 中国のAI投資は2027年までに381億ドルに達すると予想

IDC は、2027 年までに人工知能への世界総投資額が 4,236 億米ドルに達し、2022 年か...

IDCは、年平均成長率31.4%で、世界のAIソフトウェアの収益は2027年に2,790億ドルに達すると予測している。

11月2日、市場調査会社IDCが発表した最新の予測レポートによると、世界のAIソフトウェア市場規模...