본문 바로가기

알고리즘 & 자료구조

A* algorithm

안녕하세요.

오늘은 A* algorithm (A star algorithm) 에 대해 알아보겠습니다.


최단 경로 휴리스틱 알고리즘

시작 정점 s에서 끝 정점 e 까지의 최단 경로를 근사화한 값을 구하기 위한 최단 경로 알고리즘 입니다.

 

휴리스틱 알고리즘 중 하나 입니다.


최단 경로를 찾는데 가장 유명한 알고리즘이 다익스트라 알고리즘 입니다.

다익스트라 알고리즘은 시작 정점에서 현재 정점까지 걸린 비용이 작은 것을 우선으로 탐색합니다.

 

A* algorithm은 f cost가 작은 것을 우선으로 탐색합니다.

f cost = g cost + h cost
g cost = 시작 정점에서 현재 정점까지 걸린 비용
h cost = 현재 정점에서 끝 정점까지 걸릴 예상 비용

 

g cost가 다익스트라 알고리즘에서 우선시하는 비용인 시작 정점에서 현재 정점까지 걸린 비용입니다.

A* algorithm은 여기에 h cost 라는 것을 더한 비용을 확인합니다.

 

모든 노드의 h cost를 0으로 둔다면 f cost = g cost가 됩니다.

이는 다익스트라 알고리즘과 똑같은 비용입니다.

=> 다익스트라 알고리즘과 A* algorithm의 차이는 h cost 뿐 입니다.

 

(다익스트라 알고리즘 설명 : https://blog.naver.com/kdr06006/221780930566)

 

다익스트라 (Dijkstra Algorithm)

안녕하세요. 오늘은 다익스트라에 대해 포스팅 하겠습니다. 다익스트라 알고리즘은 하나의 정점으로부터 다...

blog.naver.com

 

h cost는 끝 정점까지 걸릴 비용을 예측하는 것으로, 이로 인해 답과 인접한 근사치를 구할 수 있습니다.

h cost를 어떻게 잡냐에 따라 알고리즘 성능이 좌우되므로, 매우 중요한 휴리스틱 값입니다.


h cost 구하기

https://www.youtube.com/watch?v=71CEj4gKDnE

h cost를 설명하는 자료 중 인상 깊은 자료가 있어 들고왔습니다.

 

미로에서 쥐가 치즈를 찾으러 갈 때, 어떤 방법을 사용할 수 있을까요?

 

1. 그냥 탐색

미로의 동서남북 4방향을 다 탐색해보면서 그냥 다 가보는 방식입니다.

이는 벽이나 도착점을 만날 때 까지 직접 가봐야 알 수 있습니다.

 

2. 후각을 사용해 치즈의 냄새를 쫓아감

냄새는 거리가 가까워질 수록 더 강하게 납니다.

쥐는 냄새를 이용해 치즈를 빠르게 찾을 수 있습니다.

 

도착점까지 가까워질 수록 냄새가 더 강하게 나고, 냄새가 이끄는 대로 따라가면 됩니다.

이 냄새가 바로 h cost가 됩니다.


그렇다면 저희는 어떻게 h cost를 정할 수 있을까요?

 

2차원 격자에 4개의 노드가 있음

2차원 좌표 상에서 h cost를 정해보겠습니다.

 

여러 방법이 있을 수 있지만, 대표적으로 많이 사용되는 2가지 방법을 알아보겠습니다.

 

1. Manhattan distance

두 노드의 x 좌표의 차이 + y 좌표의 차이의 합으로 구합니다.

두 노드의 x, y 좌표의 차이

두 노드의 x 좌표의 차이는 1,

두 노드의 y 좌표의 차이는 4 입니다.

h cost = 1 + 4 = 5로 설정할 수 있습니다.

 

2. Euclidean distance

좌표 상의 실제 거리인 sqrt(x좌표 차이 ^ 2 + y 좌표 차이 ^ 2)로 구합니다.

두 노드의 직선 거리

1번 노드와 2번 노드의 직선 거리를 h cost로 설정합니다.

h = sqrt(1 + 16)


과정

아래 사이트의 수도 코드를 참고해 작성했습니다.

https://www.geeksforgeeks.org/a-search-algorithm/

 

A* Search Algorithm - GeeksforGeeks

A* Search algorithm is one of the best and popular technique used in path-finding and graph traversals.

www.geeksforgeeks.org

1. open list, closed list를 준비

2. start node를 open list에 넣기
(start node는 f 값을 0으로 둬도 상관 없음)

3. open list가 빌 때 까지 반복

	a) open list에서 f 값이 가장 작은 노드를 찾기 => current node

	b) current node가 target node 이면, return_value 갱신

	c) current node를 closed list에 넣기

	d) current node를 open list에서 삭제

	e) 인접한 노드 (4방향, 6방향, 8방향... 문제에 따라 다름) 를 탐색
		-> neighbor node

		i) neighbor node의 f cost와 계산하기

		if) neighbor node가 open list에 들어있고, f cost가 더 작다면
				continue

		else if) neighbor node가 closed list에 들어있고, f cost가 더 작다면
				continue

		else) open list에 neighbor node와 f cost 넣기

return return_value

 

이 수도 코드를 바탕으로 그림과 함께 A* algorithm의 작동 과정을 알아보겠습니다.


2차원 격자와 노드들

2차원 격자에 4개의 노드가 있다고 가정하겠습니다.

시작 정점을 1, 도착 정점을 4로 두겠습니다.


h cost 구하기

h cost 값은 도착 정점까지의 x 좌표 차이와 y 좌표 차이의 합으로 계산하겠습니다.

 

h(1) = 시작 정점이므로 따로 구하지 않음

h(2) = 4 + 3 = 7

h(3) = 0 + 5 = 5

h(4) = 0


간선을 추가한 모습

각 노드를 연결시켜주는 간선이 이렇게 있다고 가정하겠습니다.


1번 노드 탐색 과정

1번 노드부터 탐색을 시작합니다.

closed list에 1번 노드가 담깁니다.

 

1번 노드의 인접 정점을 확인합니다.

f(2) = g cost + h cost = 3 + 7 = 10

f(3) = g cost + h cost = 4 + 5 = 9

=> 2번과 3번 노드가 open list에 들어갑니다.

 

open list에는 f cost가 작은 순으로 정렬 됩니다.


3번 노드 탐색 과정

open list에서 가장 f 값이 작은 3번 노드를 추출합니다.

closed list에 3번 노드가 담깁니다.

 

3번 노드의 인접 정점을 확인합니다.

f(1) = g cost + h cost = 8 + 0 = 8

f(2) = g cost + h cost = 6 + 7 = 13

f(4) = g cost + h cost = 18 = 0 = 18

 

=> 1번과 2번 노드는 open과 closed list에 이미 더 작은 값으로 들어갔기 때문에 open list에 넣지 않습니다.

=> 4번 노드는 open list에 넣습니다.


2번 노드 탐색

open list에서 가장 f cost가 작은 2번 노드를 추출했습니다.

 

2번의 인접 노드를 보면 아래와 같습니다.

f(1) = g cost + h cost = 6 + 0 = 6

f(3) = g cost + h cost = 5 + 5 = 10

f(4) = g cost + h cost = 7 + 0 = 7

=> 4번 노드의 가중치가 18에서 7로 갱신됩니다.


4번 노드 탐색

마지막 4번 노드까지 탐색하고 인접한 정점을 봅니다.

인접한 정점이 모두 open list나 closed list에 더 작은 값으로 들어있기 때문에 open list에 아무것도 넣지 않습니다.

 

그리고 open list는 비어있기 때문에 종료됩니다.

 

위의 그림에서 초록색 간선 경로를 따라가면 최단 경로가 나옵니다.

(1 -> 2 -> 4)


 

 

다익스트라 알고리즘과 다르게 A* algorithm은 도착 정점에 도달해도 탐색을 계속 이어나가야 합니다.

f cost가 작은 순으로 탐색을 하기 때문입니다.

 

2번 노드의 h cost를 터무니 없이 크게 잡는다면 탐색 노드 순서는 아래와 같습니다.

1번 노드 -> 3번 노드 -> 4번 노드 -> 2번 노드 -> 3, 4번 노드

 

f cost는 크지만, 우리가 구하고자 하는 값은 g cost 이기에 open list에 원소가 없을 때까지 탐색을 계속 해야합니다.


속도 비교

아래 사이트는 여러 길찾기 알고리즘의 시각화 사이트입니다.

https://qiao.github.io/PathFinding.js/visual/

 

PathFinding.js

 

qiao.github.io

속도 비교

다익스트라 알고리즘과 A* (A star) algorithm의 속도를 비교한 결과입니다.

 

훨씬 더 적은 노드를 탐색하고 금방 target node 까지 도달한 것을 확인할 수 있습니다.

 

이러한 성능적인 측면으로, A* algorithm이 지도 상의 길찾기 기능이나 게임의 길찾기 기능에 많이 사용된다고 알려져 있습니다.


참고 자료

다익스트라 : https://blog.naver.com/kdr06006/221780930566

A* algorithm : https://www.geeksforgeeks.org/a-search-algorithm/

휴리스틱 : https://www.youtube.com/watch?v=71CEj4gKDnE 

 

감사합니다.

'알고리즘 & 자료구조' 카테고리의 다른 글

2-SAT  (0) 2023.07.24
강한 연결 요소 (Strongly Connected Component)  (0) 2023.07.20
최소 스패닝 트리 (Minimun Spanning Tree)  (0) 2023.07.14
Topological Sort (위상 정렬)  (0) 2023.06.29
Disjoint-set  (0) 2023.06.27