์ด๋ฆฐ์ด๋ฅผ ์ํ ์์ ๊ธธ ์ฐพ๊ธฐ ์ดํ์ ๋ง๋ค์๋ ๋ฐ, ํด๋น ์ดํ์์ ์ฌ์ฉํ ๊ธธ ์ฐพ๊ธฐ ์๊ณ ๋ฆฌ์ฆ์ ๋ํด ์ ์ด๋ณด๋ ค๊ณ ํ๋ค.
์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ์ A* ์๊ณ ๋ฆฌ์ฆ์ด๋ฉฐ, ๋ณธ ๊ธ์์๋ A* ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ ๊ฐ๋จํ ์์๋ฅผ ์ค๋ช ํ๊ณ ์ ํ๋ค.
โ๏ธ A* ์๊ณ ๋ฆฌ์ฆ(A star algorithm)
A*์๊ณ ๋ฆฌ์ฆ์ ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ํ์ฅ์ผ๋ก, ํด๋ฆฌ์คํฑ์ ๊ฒฐํฉํ ์ต๋จ๊ฑฐ๋ฆฌ ํ์ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
โ๏ธ ํด๋ฆฌ์คํฑ(heuristic)
ํด๋ฆฌ์คํฑ์ด๋ ์์๊ฐ์ผ๋ก, ๋ณต์กํ๊ณ ๊ณ์ฐ ๋น์ฉ์ด ๋์ ๋ฌธ์ ์์ ์ฌ์ฉํ ์ ์๋ค. A* ์๊ณ ๋ฆฌ์ฆ์์๋ ํด๋ฆฌ์คํฑ์ ์ฌ์ฉํ์ฌ ๊ฐ ๋ ธ๋๊น์ง์ ์์ ๋น์ฉ์ ๊ณ์ฐํ๋ค.
์๋ฅผ ๋ค๋ฉด, ๋ ธ๋ ๊ฐ ์ง์ ๊ฑฐ๋ฆฌ๋ฅผ ํด๋ฆฌ์คํฑ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. ์ถ๋ฐ ๋ ธ๋์์ ๋ค์ ๋ ธ๋๋ฅผ ์ด๋ค ๋ ธ๋๋ก ์ ํํ ์ง ๋น๊ตํ ๋, ์ถ๋ฐ ๋ ธ๋์ ๋ค์ ๋ ธ๋์ ์ค์ ๊ฑฐ๋ฆฌ ๋ฟ๋ง ์๋๋ผ ๋ชฉ์ ์ง๊น์ง ์ง์ ๊ฑฐ๋ฆฌ๋ ํจ๊ป ๊ณ ๋ คํด์ ๋น๊ตํ๋ค.
f(n) = g(n) + h(n)
f(n) : ์ด ๋น์ฉ
g(n) : ์ถ๋ฐ ๋ ธ๋์์ ํ์ฌ๋ ธ๋๊น์ง์ ์ค์ ๋น์ฉ
h(n) : ํด๋ฆฌ์คํฑ, ๋ชฉ์ ์ง๊น์ง์ ์์๋น์ฉ
โ๏ธ open list & closed list
open list : ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋๋ค์ ์งํฉ์ด๋ค. ์ด๊ธฐ์๋ ์์ ๋ ธ๋๋ง ์๋ค.
closed list : ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋ ธ๋๋ค์ ์งํฉ์ด๋ค. closed list์ ์ถ๊ฐ๋ ๋ ธ๋๋ ๋ ์ด์ ๊ณ ๋ คํ์ง ์๋๋ค. ์ค๋ณต ๋ฐฉ๋ฌธ์ ๋ฐฉ์งํ ์ ์๋ค.
โ๏ธ ๊ตฌํ
(์ ์ฒด ์ฝ๋๋ ์๋์)
def a_star_algorithm(self, start_node, stop_node):
1. ์ด๊ธฐํ
# ์์ ๋
ธ๋๋ฅผ ์ด๊ธฐ๊ฐ์ผ๋ก ๊ฐ์ง๋ฉฐ, ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ๋
ธ๋์ ์งํฉ
open_list = set([start_node])
# ์ด๊ธฐ์๋ ๋น์ด ์์ผ๋ฉฐ, ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ค์ ์งํฉ
closed_list = set([])
# ๊ฐ ๋
ธ๋๊น์ง์ ํ์ฌ๊น์ง์ ์ต์ ๋น์ฉ์ ์ ์ฅํ๋ ๋์
๋๋ฆฌ
g = {}
g[start_node] = 0
# ๊ฐ ๋
ธ๋์ ๋ถ๋ชจ ๋
ธ๋๋ฅผ ์ ์ฅํ๋ ๋์
๋๋ฆฌ
parents = {}
parents[start_node] = start_node
2. ํ์ ๋ฃจํ
# Open List๊ฐ ๋น์ด์์ ๋๊น์ง ๋ฐ๋ณต
while len(open_list) > 0:
3. ํ์ฌ ๋ ธ๋ ์ ํ
# ํ์ฌ ๋
ธ๋๋ฅผ ๋ํ๋ด๋ ๋ณ์๋ฅผ ์ด๊ธฐํ
n = None
# Open List์์ ๊ฐ์ฅ ๋ฎ์ ๋น์ฉ์ ๋
ธ๋๋ฅผ ์ ํ
for v in open_list:
if n == None or g[v] + self.h(v) < g[n] + self.h(n):
n = v
4. ๊ฒฝ๋ก์ ์กด์ฌ ์ฌ๋ถ ํ์ธ
# ํ์ฌ ๋
ธ๋๊ฐ ์์ผ๋ฉด ๊ฒฝ๋ก๊ฐ ์กด์ฌํ์ง ์๋๋ค๊ณ ์ถ๋ ฅํ๊ณ None์ ๋ฐํ
if n == None:
print('Path does not exist!')
return None
5. ๋ชฉ์ ์ง ๋๋ฌ ์ฌ๋ถ ํ์ธ
# ํ์ฌ ๋
ธ๋๊ฐ ๋ชฉ์ ์ง ๋
ธ๋์ ์ผ์นํ๋ฉด, ์ต์ ๊ฒฝ๋ก๋ฅผ ์ฌ๊ตฌ์ฑํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๊ณ ๋ฐํ
if n == stop_node:
reconst_path = []
while parents[n] != n:
reconst_path.append(n)
n = parents[n]
reconst_path.append(start_node)
reconst_path.reverse()
print('Path found: {}'.format(reconst_path))
return reconst_path
6. ์ด์ ๋ ธ๋ ํ์ ๋ฐ ์ ๋ฐ์ดํธ
# ํ์ฌ ๋
ธ๋์ ์ด์ ๋
ธ๋๋ค์ ํ์
for (m, weight) in self.get_neighbors(n):
# ์ด์ ๋
ธ๋๊ฐ Open List์ Closed List์ ์์ผ๋ฉด ์ถ๊ฐํ๊ณ ์ ๋ณด๋ฅผ ์
๋ฐ์ดํธ
if m not in open_list and m not in closed_list:
open_list.add(m)
parents[m] = n
g[m] = g[n] + weight
# ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋์ด๊ฑฐ๋ Open List์ ํฌํจ๋ ๊ฒฝ์ฐ, ๋น์ฉ์ ๋น๊ตํ์ฌ ์
๋ฐ์ดํธ
else:
if g[m] > g[n] + weight:
g[m] = g[n] + weight
parents[m] = n
if m in closed_list:
closed_list.remove(m)
open_list.add(m)
7. ํ์ฌ ๋ ธ๋๋ฅผ Closed List๋ก ์ด๋
# ํ์ฌ ๋
ธ๋๋ฅผ Open List์์ ์ ๊ฑฐ
open_list.remove(n)
# ํ์ฌ ๋
ธ๋๋ฅผ Closed List์ ์ถ๊ฐ
closed_list.add(n)
8. ์ต์ ๊ฒฝ๋ก๊ฐ ์๋ ๊ฒฝ์ฐ ์ฒ๋ฆฌ
# ์ต์ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ, 'Path does not exist!'๋ฅผ ์ถ๋ ฅํ๊ณ None์ ๋ฐํ
print('Path does not exist!')
return None
โ๏ธ ์ ์ฒด ์ฝ๋
class Graph:
def __init__(self, adjacency_list):
self.adjacency_list = adjacency_list
def get_neighbors(self, v):
return self.adjacency_list[v]
def h(self, n):
H = {
'A': 1,
'B': 1,
'C': 1,
'D': 1
}
return H[n]
def a_star_algorithm(self, start_node, stop_node):
open_list = set([start_node])
closed_list = set([])
g = {}
g[start_node] = 0
parents = {}
parents[start_node] = start_node
while len(open_list) > 0:
n = None
for v in open_list:
if n == None or g[v] + self.h(v) < g[n] + self.h(n):
n = v;
if n == None:
print('Path does not exist!')
return None
if n == stop_node:
reconst_path = []
while parents[n] != n:
reconst_path.append(n)
n = parents[n]
reconst_path.append(start_node)
reconst_path.reverse()
print('Path found: {}'.format(reconst_path))
return reconst_path
for (m, weight) in self.get_neighbors(n):
if m not in open_list and m not in closed_list:
open_list.add(m)
parents[m] = n
g[m] = g[n] + weight
else:
if g[m] > g[n] + weight:
g[m] = g[n] + weight
parents[m] = n
if m in closed_list:
closed_list.remove(m)
open_list.add(m)
open_list.remove(n)
closed_list.add(n)
print('Path does not exist!')
return None
adjacency_list = {
'A': [('B', 1), ('C', 3), ('D', 7)],
'B': [('D', 5)],
'C': [('D', 12)]
}
graph1 = Graph(adjacency_list)
graph1.a_star_algorithm('A', 'D')
์์ ์ฝ๋๋ ๊ฐ ๋ ธ๋์ ํด๋ฆฌ์คํฑ ๊ฐ์ 1๋ก ์ ์ฉํ ๊ฐ๋จํ ์์์ด๋ค.