Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
A_アルゴリズム高速化を目指して
Search
Takashi Makino
April 25, 2021
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
A_アルゴリズム高速化を目指して
Takashi Makino
April 25, 2021
More Decks by Takashi Makino
See All by Takashi Makino
あなたの知らないスクラムの世界
makky0620
0
110
Flutterでもテスト駆動したい
makky0620
0
380
Discord botにScrumの Discord botにScrumの手伝いをしてもらう手伝いをしてもらう
makky0620
0
430
Other Decks in Programming
See All in Programming
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
510
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
780
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
670
Contextとはなにか
chiroruxx
1
320
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
170
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
540
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
750
Agentic UI
manfredsteyer
PRO
0
160
DynamoDBには集計系のクエリがないけどなんとかしたい
musan
1
140
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
230
The NotImplementedError Problem in Ruby
koic
1
780
Featured
See All Featured
KATA
mclloyd
PRO
35
15k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
840
The Pragmatic Product Professional
lauravandoore
37
7.3k
The Cult of Friendly URLs
andyhume
79
6.9k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
330
How to build a perfect <img>
jonoalderson
1
5.6k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
170
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
190
Are puppies a ranking factor?
jonoalderson
1
3.5k
Mobile First: as difficult as doing things right
swwweet
225
10k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
200
Transcript
A*アルゴリズム 高速化を目指して 牧野トミー孝史 2021/04/21@TechBash
高速化の前に理解しよう • 一般的な経路探索アルゴリズムに A*アルゴリズムがある • Wikipediaにこうしたら速くなるよと書いてある ◦ データ構造の工夫 ◦ ヒューリスティック関数の工夫
• そもそものアルゴリズムを自分で実装したことがない →しっかり理解したことをみんなに伝えてみよう!
どんな問題を解くのか StartからGoalまでの経路を求める! • ノード(青い点):81個 • エッジ(線):144本 Start Goal
どんな問題を解くのか StartからGoalまでの経路を求める! • ノード(青い点):81個 • エッジ(線):144本 Start Goal 赤い線っぽくなってく れたらいいな
A*の考え方 S G (0, 0) (100, 100) (50, 100) (0,
100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) f(n) = g(n) + h(n) のf(n)が最小となる経路をたどっていく
A*の考え方 最小経路の時のコストをf(n)*と置くと ※nはノードを指している f(n)* = g(n)* + h(n)* g(n)*はスタートからノードnまでのコスト h(n)*はノードnからゴールまでのコスト
g(n)*とh(n)*はわからないため、推定値として計 算する必要がある。推定値 f(n)と置くと f(n) = g(n) + h(n) g(n)は通った時に算出すれば良いが、 h(n)はゴールに辿り着くまで不明である。 S G (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50)
A*の考え方 最小経路の時のコストをf(n)*と置くと ※nはノードを指している f(n)* = g(n)* + h(n)* g(n)*はスタートからノードnまでのコスト h(n)*はノードnからゴールまでのコスト
g(n)*とh(n)*はわからないため、推定値として計 算する必要がある。推定値 f(n)と置くと f(n) = g(n) + h(n) g(n)は通った時に算出すれば良いが、 h(n)はゴールに辿り着くまで不明である。 S G (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) f(n)* = 50 + 50*3 = 200
(50, 50) A*の考え方 最小経路の時のコストをf(n)*と置くと ※nはノードを指している f(n)* = g(n)* + h(n)*
g(n)*はスタートからノードnまでのコスト h(n)*はノードnからゴールまでのコスト g(n)*とh(n)*はわからないため、推定値として計 算する必要がある。推定値 f(n)と置くと f(n) = g(n) + h(n) g(n)は通った時に算出すれば良いが、 h(n)はゴールに辿り着くまで不明である。 S G (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (100, 50) f(n) = 50 + ? = ??
(50, 50) A*の考え方 最小経路の時のコストをf(n)*と置くと ※nはノードを指している f(n)* = g(n)* + h(n)*
g(n)*はスタートからノードnまでのコスト h(n)*はノードnからゴールまでのコスト g(n)*とh(n)*はわからないため、推定値として計 算する必要がある。推定値 f(n)と置くと f(n) = g(n) + h(n) g(n)は通った時に算出すれば良いが、 h(n)はゴールに辿り着くまで不明である。 S G (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (100, 50) h(n)にはヒューリスティックな関数を定 義する e.g. ユークリッド距離 マンハッタン距離 e.g. マンハッタン距離の時 h(n) = (100-50) + (100-0) h(n) = 150 f(n) = 50 + 150 = 200
コストを使ってどうやって経路探索するのか Wikipediaの実装をそのまま再現 事前準備・備考 • 優先度付きキューOPENとCLOSEを用意 • 優先度はf(n)の低い順 • h(n)はマンハッタン距離 S
G (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50)
OPEN:[11] CLOSE:[] TARGET: 説明 スタートのノードをOPENへ入れる (0, 0) (100, 100) (50,
100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33
OPEN:[] CLOSE:[11] TARGET:11 説明 OPENから一つ取り出しCLOSEに加える (0, 0) (100, 100) (50,
100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33
12 21 OPEN:[] CLOSE:[11] TARGET:11 説明 TARGETと隣接しているノードがOPENまたはCLOSE に含まれるか確認する (含まれなかった) (0,
0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 13 22 31 32 23 33
12 21 OPEN:[12(200), 21(200)] CLOSE:[11] TARGET:11 説明 TARGETと隣接しているノードのfn(n)を求めてOPEN に追加する f(12)
= 50 + 150 = 200 f(21) = 50 + 150 = 200 この時各ノードに親情報( 11から繋がっている)を付 与する ここまで1セット (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 13 22 31 32 23 33
OPEN:[21(200)] CLOSE:[11, 12(200)] TARGET:12(200) 説明 OPENから一つ取り出しCLOSEに加える (0, 0) (100, 100)
(50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33
13 22 OPEN:[21(200)] CLOSE:[11, 12(200)] TARGET:12(200) 説明 TARGETと隣接しているノードがOPENまたはCLOSE に含まれるか確認する (含まれなかった)
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 21 31 32 23 33
13 22 OPEN:[21(200), 13(200), 22(200)] CLOSE:[11, 12(200)] TARGET:12(200) 説明 TARGETと隣接しているノードのfn(n)を求めてOPEN
に追加する f(13) = 100 + 100 = 200 f(22) = 100 + 100 = 200 この時各ノードに親情報を付与する (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 21 31 32 23 33
13 22 OPEN:[21(200), 13(200), 22(200)] CLOSE:[11, 12(200)] TARGET:12(200) 説明 TARGETと隣接しているノードのfn(n)を求めてOPEN
に追加する f(13) = 100 + 100 = 200 f(22) = 100 + 100 = 200 この時各ノードに親情報を付与する (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 21 31 32 23 33
OPEN:[13(200), 22(200)] CLOSE:[11, 12(200), 21(200)] TARGET:21(200) 説明 OPENから一つ取り出しCLOSEに加える (0, 0)
(100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33
22 31 OPEN:[13(200), 22(200)] CLOSE:[11, 12(200), 21(200)] TARGET:21(200) 説明 TARGETと隣接しているノードがOPENまたはCLOSE
に含まれるか確認する (22がOPENに含まれている) (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 32 23 33
22 31 OPEN:[13(200), 22(200), 31(200)] CLOSE:[11, 12(200), 21(200)] TARGET:21(200) 説明
TARGETと隣接しているノードのfn(n)を求めてOPEN に追加する f(31) = 90 + 110 = 200 f(22) = 100 + 100 = 200 もしf(22)が元のコストより低ければコストと親情報を 更新する この時各ノードに親情報を付与する (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 32 23 33
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0)
(90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33 OPEN:[13(200), 22(200)] CLOSE:[11, 12(200), 21(200), 31(200)] TARGET:31(200) 説明 OPENから一つ取り出しCLOSEに加える (ちょっと恣意的に31を取り出しました)
32 22 31 OPEN:[13(200), 22(200)] CLOSE:[11, 12(200), 21(200), 31(200)] TARGET:31(200)
説明 TARGETと隣接しているノードがOPENまたはCLOSE に含まれるか確認する (含まれなかった) (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 23 33
32 22 31 OPEN:[13(200), 22(200), 32(200] CLOSE:[11, 12(200), 21(200), 31(200)]
TARGET:31(200) 説明 TARGETと隣接しているノードのfn(n)を求めてOPEN に追加する f(32) = 150 + 50 = 200 この時各ノードに親情報を付与する (0, 0) (100, 100) (50, 100) (0, 100) (50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 23 33
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0)
(90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33 OPEN:[13(200), 22(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200)] TARGET:32(200) 説明 OPENから一つ取り出しCLOSEに加える (ちょっと恣意的に32を取り出しました)
22 33 (0, 0) (100, 100) (50, 100) (0, 100)
(50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 31 32 23 OPEN:[13(200), 22(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200)] TARGET:32(200) 説明 TARGETと隣接しているノードがOPENまたはCLOSE に含まれるか確認する (22がOPENに含まれる)
22 33 (0, 0) (100, 100) (50, 100) (0, 100)
(50, 0) (90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 21 31 32 23 OPEN:[13(200), 22(200), 33(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200)] TARGET:32(200) 説明 TARGETと隣接しているノードのfn(n)を求めてOPEN に追加する f(22) = 250 + 100 = 350 f(33) = 0+200 = 200 この時各ノードに親情報を付与する
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0)
(90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33 OPEN:[13(200), 22(200), 33(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200), 33(200] TARGET:33(200) 説明 OPENから一つ取り出しCLOSEに加える (ちょっと恣意的に33を取り出しました)
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0)
(90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33 OPEN:[13(200), 22(200), 33(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200), 33(200] TARGET:33(200) 説明 TARGETがGoalと等しいので終了
(0, 0) (100, 100) (50, 100) (0, 100) (50, 0)
(90, 0) (0, 50) (50, 50) (100, 50) 11 12 13 22 21 31 32 23 33 OPEN:[13(200), 22(200), 33(200)] CLOSE: [11, 12(200), 21(200), 31(200), 32(200), 33(200] TARGET:33(200) 説明 TARGETの親情報をたどっていけば 33->32->31->21->11 という経路となることがわかる
実際に解いてみると Start Goal • ノード(青い点):81個 • エッジ(線):144個 • 計算時間:0.00536s
こんな複雑な問題も解ける Start Goal • ノード(青い点):2401個 • エッジ(線):3984個 • 計算時間:3.24s(これじゃ遅い)
余談:ダイクストラ法って何? A*アルゴリズムの特殊版 ヒューリスティックな値が0として、スタートからノードnまでのコストのみで計算 f(n) = g(n) + h(n) h(n) =
0