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

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

[[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億のブルーオーシャンが呼び寄せる、電力検査ロボットが最前線に

ブログ    
ブログ    

推薦する

Keras によるステートフル LSTM リカレント ニューラル ネットワークの理解

[[327815]]この記事を読むと、次のことがわかります。 1. シーケンス予測問題のための単純な...

予想外?今年の建国記念日に最も多く目にするのはドローンかもしれません!

[[426834]]国慶節のゴールデンウィークが近づいてきました。旅行の計画はお決まりですか?昨今...

GPT-4を直接使用してエアコンを制御する、マイクロソフトのトレーニング不要の手法によりLLMは産業用制御に向けて前進

大規模言語モデル (LLM) 技術が成熟するにつれて、その適用範囲が拡大しています。インテリジェント...

AIの負担を軽減する時が来た。Python AIライブラリ5選のおすすめ

機械学習は興味深いものですが、作業範囲が広く複雑で困難です。開発者として学ぶべきツールはたくさんあり...

AIが再生可能エネルギーグリッドの回復力の鍵となる理由

[[393199]]画像提供:ロイター/セルジオ・ペレスエマニュエル・ラガリグシュナイダーエレクトリ...

2020年世界人工知能会議が開催されます! AI が人間の言語の高度な能力をいかにして習得するかをご覧ください。

2020年7月9日、2020年世界人工知能大会(WAIC)クラウドサミットが正式に開幕しました。I...

...

...

60年ぶり! AI が新しい抗生物質の最初のバッチを発見し、MIT の主要な研究が Nature に掲載されました。人類はスーパーバグとの戦いに希望を持っている

60年間、人類は抗生物質の研究において大きな進歩を遂げていません。しかし、このギャップはAIによって...

「スマートストア」のAIカメラは何ができるのか?

スマートシティが理論的な概念から正式な計画と建設へと進化するにつれて、スマートストアはスマートシティ...

世界の自動運転「M&A」を4大勢力が攻勢

偉大な将軍の名声の裏には、数え切れないほどの兵士たちの援助がある。この声明は自動運転の分野にも当ては...

人工知能とモノのインターネットを組み合わせた5つの技術応用トレンド

今年末までに、世界中で接続されるデバイスの数は 500 億台に達すると予測されており、モノのインター...

...

「未来ロボット」が1億元の資金調達を完了。自動物流が次の「阿修羅場」となるか?

2021年上半期、世界経済が回復し始めると、自動車業界も着実に回復し始め、自動車メーカーは電動化と...

...