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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Takashi Makino
April 25, 2021
Programming
1.6k
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
120
Flutterでもテスト駆動したい
makky0620
0
390
Discord botにScrumの Discord botにScrumの手伝いをしてもらう手伝いをしてもらう
makky0620
0
430
Other Decks in Programming
See All in Programming
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.7k
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
100
これって Effect でできたのでは? / TSKaigi Mashup Kansai #2
susisu
0
250
AIを紡ぐPMのお話
swdtkuy
0
120
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.8k
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
270
不幸な GC
chencmd
0
570
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
690
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
140
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
350
What's New in Android 2026
veronikapj
0
270
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
360
Technical Leadership for Architectural Decision Making
baasie
3
520
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Being A Developer After 40
akosma
91
590k
Bash Introduction
62gerente
615
220k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Product Roadmaps are Hard
iamctodd
55
12k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
250
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
From π to Pie charts
rasagy
0
310
How to make the Groovebox
asonas
2
2.3k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
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