2024. 1. 31. 21:22ใCS - Roadmap.sh/3. Common Algorithms
CS - 3. Common Algorithms - 3.5 Graph - 3.5.5 A* Algorithm
A* Algorithm
๐ก A* is a graph traversal algorithm that is used to find the shortest path between two nodes in a graph. It is a modified version of Dijkstra’s algorithm that uses heuristics to find the shortest path. It is used in pathfinding and graph traversal.
A*๋ ๊ทธ๋ํ์์ ๋ ๋ ธ๋ ์ฌ์ด์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ทธ๋ํ ํ์ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค. ์ด๋ ํด๋ฆฌ์คํฑ์ ์ฌ์ฉํ์ฌ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ Dijkstra ์๊ณ ๋ฆฌ์ฆ์ ์์ ๋ฒ์ ์ ๋๋ค. ๊ฒฝ๋ก ์ฐพ๊ธฐ ๋ฐ ๊ทธ๋ํ ํ์์ ์ฌ์ฉ๋ฉ๋๋ค.
A* (A Star) ์๊ณ ๋ฆฌ์ฆ์, ๊ทธ๋ํ์์ ์์ - ๋ชฉํ ๋ ธ๋์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๊ฒ์ด ๋ชฉํ์ธ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
A*๋ ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ํด๋ฆฌ์คํฑ ํจ์๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํด ํ์์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์ํํฉ๋๋ค.
ํด๋ฆฌ์คํฑ ํจ์๋ ๋ฌด์์ผ๊น์?
๋ฌธ์ ํด๊ฒฐ ๊ณผ์ ์์ ๋ ๋์ ๊ฒฐ์ ์ ๋ด๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ถ์ ํจ์๋ฅผ ์๋ฏธํฉ๋๋ค.
์ฃผ๋ก ํ์ฌ ์ํ์์ ๋ชฉํ ์ํ๊น์ง์ ๋น์ฉ์ ์ถ์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
A* ์๊ณ ๋ฆฌ์ฆ์์ ํด๋ฆฌ์คํฑ ํจ์ h(n)์ ํ์ฌ ๋ ธ๋์์ ๋ชฉํ๋ ธ๋๊น์ง์ ์ถ์ ๊ฑฐ๋ฆฌ๋ฅผ ๋ํ๋ ๋๋ค.
์ด๋ ๊ฒ ํ๋ ์ด์ ๋, ๋ ๋น ๋ฅด๊ฒ ๋ชฉํ ๋ ธ๋์ ๋๋ฌํ๊ธฐ ์ํด ํ์ ๊ฒฝ๋ก๋ฅผ ์๋ดํ๊ธฐ ์ํด์์ ๋๋ค.
๊ฐ๋จํ ์์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
2์ฐจ์ array์์ ๊ฒฝ๋ก ์ฐพ๊ธฐ ๋ฌธ์ ๋ฅผ ์๊ฐํด ๋ณผ์ ์์ต๋๋ค.
ํด๋ฆฌ์คํฑ ํจ์๋ก ์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ( ๋ ์ ์ฌ์ด์ ์ง์ ๊ฑฐ๋ฆฌ)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
(์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ, ๋งจํดํผ ๊ฑฐ๋ฆฌ, ํด๋ฐ ๊ฑฐ๋ฆฌ ๋ฑ ์ด ์์ต๋๋ค.)
ํ์ฌ ๋ ธ๋๊ฐ (1,2)์ด๊ณ ๋ชฉํ๋ ธ๋๊ฐ (4,3)์ด๋ผ๋ฉด ํด๋ฆฌ์คํฑ ํจ์ h(n)์
h(n) = sqrt((4-1)^2 + (3-2)^2) ์ด๋ผ ํ ์ ์๊ฒ ์ต๋๋ค.
์ด๋ ๊ฒ ๊ณ์ฐํ h(n)์ ํ์ฌ ๋ ธ๋์์ ๋ชฉํ ๋ ธ๋ ๊น์ง์ ์ถ์ ๊ฑฐ๋ฆฌ๋ฅผ ๋ํ๋ ๋๋ค.
์ด ๊ฐ์ ์ด์ฉํ์ฌ, A* ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ฅ ํจ์จ์ ์ธ ํ์ ๊ฒฝ๋ก๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋ฉ๋๋ค.
๋ฌผ๋ก ์ด๋ ์์ฃผ ๊ฐ๋จํ ๋ฌธ์ ๊ณ , ๋ฌธ์ ์ ํน์ฑ, ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ค์ ๋ ์ ์์ต๋๋ค.
In Python
import heapq
# ํด๋ฆฌ์คํฑ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. - ๋ฌธ์ ์ ๋ง์ถฐ์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ์ฌ๊ธฐ์๋ ๋งจํดํผ ๊ฑฐ๋ฆฌ ์ฌ์ฉ
def heuristic(a, b):
return abs(b[0] - a[0]) + abs(b[1] - a[1])
# A* ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ, 2์ฐจ์๋ฐฐ์ด(array), ์์๋
ธ๋(start), ๋ชฉํ๋
ธ๋(goal) ์ ์
๋ ฅ๋ฐ์
def astar(array, start, goal):
# 8 ๋ฐฉํฅ ์ด๋์ ์ํ ์ด์ ๋
ธ๋(neighbors)์ ์ขํ ์ ์
neighbors = [(0,1),(0,-1),(1,0),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)]
# ๊ฐ์ข
๋ณ์
# close_set : ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋์ ์งํฉ,
# came_from : ๊ฐ ๋
ธ๋์ ์ด์ ๋
ธ๋๋ฅผ ์ ์ฅํ dict,
# gscroe : ์์๋
ธ๋ ์์ ๊ฐ ๋
ธ๋๊น์ง์ ์ค์ ๋น์ฉ,
# fscore : gscore์ ํด๋ฆฌ์คํฑ ํจ์๋ฅผ ํตํด ๊ฒ์ฐํ ์ถ์ ๋น์ฉ์ํฉ,
# oheap : ๋ฐฉ๋ฌธํ ๋
ธ๋๋ค์ ์ ์ฅํ๋ ์ฐ์ ์์ ํ
close_set = set()
came_from = {}
gscore = {start:0}
fscore = {start:heuristic(start, goal)}
oheap = []
# ์์ ๋
ธ๋๋ฅผ ์ฐ์ ์์ ํ์ ์ถ๊ฐ
heapq.heappush(oheap, (fscore[start], start))
#์ฐ์ ์์ ํ๊ฐ ๋น๋๊น์ง(๋ชจ๋ ๋
ธ๋ ๋ฐฉ๋ฌธ) ๋ฐ๋ณต
while oheap:
#์ฐ์ ์์ ํ์์ ๊ฐ์ฅ ๋ฎ์ ๋น์ฉ์ ๋
ธ๋ ์ถ์ถ
current = heapq.heappop(oheap)[1]
#์ถ์ถ ๋
ธ๋๊ฐ ๋ชฉํ ๋
ธ๋๋ผ๋ฉด, ๊ฒฝ๋ก๋ฅผ ๊ตฌ์ฑํ๊ณ ๋ฐํ
if current == goal:
data = []
while current in came_from:
data.append(current)
current = came_from[current]
return data
#์ถ์ถํ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋
ธ๋์ ์งํฉ์ ์ถ๊ฐ
close_set.add(current)
#์ถ์ถํ ๋
ธ๋์ ์ด์๋
ธ๋์ ๋ํด ์ํํ๋ ๊ฒ๋ค
for i, j in neighbors:
#์ด์ ๋
ธ๋์ ์ขํ๋ฅผ ๊ณ์ฐ
neighbor = current[0] + i, current[1] + j
#ํ์ฌ๋
ธ๋์์ ์ด์๋
ธ๋๊น์ง ๋น์ฉ ๊ณ์ฐ
tentative_g_score = gscore[current] + heuristic(current, neighbor)
# ์ด์ ๋
ธ๋๊ฐ ๊ทธ๋ํ ๋ด์ ์๋์ง, ์ฅ์ ๋ฌผ์ด ์๋์ง, ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋์ธ์ง ํ์ธ, ์ด์ ํด๋นํ๋ฉด ์ด์ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ์ง ์๊ณ ๊ฑด๋๋
if 0 <= neighbor[0] < array.shape[0]:
if 0 <= neighbor[1] < array.shape[1]:
if array[neighbor[0]][neighbor[1]] == 1:
continue
else:
continue
else:
continue
if neighbor in close_set and tentative_g_score >= gscore.get(neighbor, 0):
continue
# ์ด์ ๋
ธ๋์ ์ด ๋น์ฉ์ด ํ์ฌ๊น์ง ๊ณ์ฐํ ๋น์ฉ๋ณด๋ค ์๊ฑฐ๋, ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ๋
ธ๋๋ผ๋ฉด ์ด ๋น์ฉ๊ณผ ์ด์ ๋
ธ๋ ๊ฐฑ์ , ์ฐ์ ์์ ํ์ ์ถ๊ฐ
if tentative_g_score < gscore.get(neighbor, 0) or neighbor not in [i[1]for i in oheap]:
came_from[neighbor] = current
gscore[neighbor] = tentative_g_score
fscore[neighbor] = tentative_g_score + heuristic(neighbor, goal)
heapq.heappush(oheap, (fscore[neighbor], neighbor))
return False
์ด๋ฐ์์ผ๋ก ๊ตฌํํ์์ต๋๋ค.
nmap = np.array([
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,1,0,1,0,0,0],
[0,0,0,0,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0]
])
์ด๋ฐ array ๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ์๋ค.
๋นจ๊ฐ์ (0,0) ์์ ํ๋์ (4,5) ๊น์ง์ ์ต์ ๋ฃจํธ๋ฅผ ์๊ณ ์ถ์ต๋๋ค.
(์ผ๋ฐ์ ์ธ x,y ๋ฐ์นด๋ฅดํธ ์ขํํ๋ฉด์ด ์๋๋ผ array ๋ฅผ ๊ตฌํํ ์ขํ์์ ๊ฐ์ํด์ฃผ์ธ์.(์ฐจํ์์ ))
์ฃผํฉ์ ์ ์ ์ด์ผ๋ฉด ๋นจ๊ฐ์ ๊ณผ ํ๋์ ์ ์ต์ ๋น์ฉ ๊ตฌ๊ฐ์ ๋๋ค.
ํ์ฉ
๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ๊ณผ A* ์๊ณ ๋ฆฌ์ฆ์ ์ต๋จ ๋น์ฉ ๊ฑฐ๋ฆฌ๋ฅผ ํ์ํ๋ค๋ ์ ์ ๋น์ทํฉ๋๋ค.
ํ์ง๋ง ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ๊ฒ์ํ๊ณ , A*๋ ํด๋ฆฌ์คํฑ ํจ์๋ฅผ ํ์ฉํด ์ข๋ ํจ์จ์ ์ผ๋ก ์ฐพ์์ ์๊ฒ ๋ฉ๋๋ค.
์ด๋ ๋ฏธ๋ก์ฐพ๊ธฐ์ ํ์ฉํ๊ธฐ ์ฝ๊ณ , ๋ฐ๋ผ์ ๊ฒฝ๋ก ๊ณํ, ๊ฒ์ ์ธ๊ณต์ง๋ฅ, ์์จ์ฃผํ ๋ฑ ๋ค์ํ ๋ถ์ผ์์ ํ์ฉํ ์ ์์ต๋๋ค.
์ฐธ๊ณ ๋งํฌ
https://aliencoder.tistory.com/32
https://choiseokwon.tistory.com/210
'CS - Roadmap.sh > 3. Common Algorithms' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
3.6 Greedy Algorithms - 3.6.1 Huffman Coding (0) | 2024.02.03 |
---|---|
3.6 Greedy Algorithms (0) | 2024.02.02 |
3.5 Graph - 3.5.4 Dijkstraโs Algorithm (2) | 2024.01.30 |
3.5 Graph - 3.5.3 Bellman Fordโs Algorithm (1) | 2024.01.29 |
3.5 Graph - 3.5.2 Depth First Search(DFS) (1) | 2024.01.29 |