Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
A_アルゴリズム高速化を目指して
Takashi Makino
April 25, 2021
Programming
0
670
A_アルゴリズム高速化を目指して
Takashi Makino
April 25, 2021
Tweet
Share
More Decks by Takashi Makino
See All by Takashi Makino
Discord botにScrumの Discord botにScrumの手伝いをしてもらう手伝いをしてもらう
makky0620
0
210
Other Decks in Programming
See All in Programming
The strategies behind ddd – AdeoDevSummit 2022
lilobase
PRO
4
250
Springin‘でみんなもクリエイターに!
ueponx
0
200
模組化的Swift架構(二) DDD速成
haifengkao
0
380
シェーダー氷山発掘記
logilabo
0
140
Amazon Aurora の v1 が EOL になるので 10 クラスタアップグレードして出てきたノウハウ
dekokun
0
860
Deep Dive Into Google Zanzibar and its Concepts for Authorization Scenarios
dschenkelman
1
120
Overview of The Modern Data Stack / モダンデータスタック概論
satoshihirose
6
3.3k
What's new in Android development tools まとめ
mkeeda
0
320
UI Testing of Jetpack Compose Apps, AppDevCon
alexzhukovich
0
150
NEWT.net: Frontend Technology Selection
xpromx
0
240
GitHub Actions を導入した経緯
tamago3keran
1
430
開発速度を5倍早くするVSCodeの拡張機能を作った
purp1eeeee
2
150
Featured
See All Featured
Web Components: a chance to create the future
zenorocha
303
40k
Art Directing for the Web. Five minutes with CSS Template Areas
malarkey
196
9.4k
Designing the Hi-DPI Web
ddemaree
272
32k
Building Flexible Design Systems
yeseniaperezcruz
310
34k
Fontdeck: Realign not Redesign
paulrobertlloyd
73
4.1k
Optimizing for Happiness
mojombo
365
63k
Making the Leap to Tech Lead
cromwellryan
113
7.4k
Producing Creativity
orderedlist
PRO
333
37k
Fireside Chat
paigeccino
11
1.3k
GraphQLの誤解/rethinking-graphql
sonatard
27
6.6k
Streamline your AJAX requests with AmplifyJS and jQuery
dougneiner
126
8.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
27
1.5k
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