A * 길 찾기는 어떻게 작동합니까?


67

A * 길 찾기가 작동하는 방식을 기본적으로 이해하고 싶습니다. 시각화뿐만 아니라 모든 코드 또는 의사 코드 구현이 도움이 될 것입니다.


다음은 Dijkstra의 모션 알고리즘을 보여주는 애니메이션 GIF 가있는 작은 기사 입니다.
Ólafur Waage

Amit의 A * 페이지 는 저에게 좋은 소개였습니다. YouTube 에서 AStar Algorithm 을 검색하는 훌륭한 시각화 자료를 많이 찾을 수 있습니다 .
jdeseno

이 훌륭한 튜토리얼을 찾기 전에 A *에 대한 많은 설명이 혼란 스러웠습니다. policyalmanac.org/games/aStarTutorial.htm ActionScript에서 A *의 구현을 작성할 때 주로 언급했습니다 : newarteest.com/flash /astar.html
jhocking

4
-1 Wikipedia에는 ​​A *에 대한 설명, 소스 코드, 시각화 및 ... 관련 기사가 있습니다. 여기에있는 답변 중 일부는 해당 위키 페이지의 외부 링크를 가지고 있습니다.
user712092

4
또한 이것은 게임 개발자들에게 큰 관심을 끄는 주제이기 때문에 여기서 정보를 원한다고 생각합니다. Joel은 사람들이 Google 프로그래밍 질문을 할 때 StackOverflow가 최고의 인기를 얻고 싶다고 말한 것을 기억합니다.
jhocking 2012

답변:


63

기권

온라인으로 찾을 수있는 수많은 코드 예제와 A *에 대한 설명이 있습니다. 이 질문에는 유용한 링크가 많은 훌륭한 답변이 많이 있습니다. 내 대답에서는 코드 또는 설명보다 이해하기 쉬운 알고리즘의 그림 예제를 제공하려고합니다.


Dijkstra의 알고리즘

A *를 이해하려면 먼저 Dijkstra의 알고리즘을 살펴 보는 것이 좋습니다 . Dijkstra의 알고리즘이 검색을 위해 수행 할 단계를 안내해 드리겠습니다.

시작 노드는 A최단 경로를 찾고 싶습니다 F. 그래프의 각 가장자리에는 관련된 이동 비용이 있습니다 (가장자리 옆에 검은 색 숫자로 표시됨). 우리의 목표는 목표 노드에 도달 할 때까지 그래프의 각 정점 (또는 노드)에 대한 최소 이동 비용을 평가하는 것입니다.

Dijkstra의 그림 1 부

이것이 우리의 출발점입니다. 검사 할리스트 노드가 있는데,이리스트는 현재 다음과 같습니다 :

{ A(0) }

A의 비용이 0있고 다른 모든 노드는 무한대 로 설정됩니다 (일반적인 구현에서는 비슷 int.MAX_VALUE하거나 유사합니다).

Dijkstra의 그림 2 부

우리는 노드 목록에서 가장 저렴한 비용으로 노드를 가져옵니다 (목록에 포함되어 있기 때문에 A후보자입니다) 모든 이웃을 방문하십시오. 각 이웃 의 비용 을 다음과 같이 설정 했습니다.

Cost_of_Edge + Cost_of_previous_Node

이전 노드를 추적합니다 (노드 아래에 작은 분홍색 문자로 표시). A이제는 해결됨 (빨간색)으로 표시되어 다시 방문하지 않습니다. 후보자 목록은 다음과 같습니다.

{ B(2), D(3), C(4) }

Dijkstra의 일러스트 3 부

다시 한 번, 목록 ( B) 에서 가장 저렴한 비용으로 노드를 가져 와서 이웃을 평가합니다. 의 경로 D가의 현재 비용보다 비싸 D므로이 경로를 무시할 수 있습니다. E후보 목록에 추가됩니다. 이제 다음과 같습니다.

{ D(3), C(4), E(4) }

다이크 스트라의 일러스트 4 부

검사 할 다음 노드는 이제 D입니다. C경로가 기존 비용보다 짧지 않으므로에 대한 연결을 버릴 수 있습니다 . 짧은 경로를 찾았 E으므로 비용 E과 이전 노드가 업데이트됩니다. 우리의 목록은 다음과 같습니다 :

{ E(3), C(4) }

다이크 스트라의 일러스트 5 부

이전과 마찬가지로 목록에서 가장 저렴한 비용으로 노드를 검사합니다 E. E하나의 미해결 이웃 만 있으며 이는 또한 대상 노드입니다. 대상 노드에 도달하는 비용이로 설정되고 10이전 노드 가로 설정 됩니다 E. 후보자 목록은 다음과 같습니다.

{ C(4), F(10) }

다이크 스트라의 일러스트 6 부

다음으로 검사 C합니다. 에 대한 비용과 이전 노드를 업데이트 할 수 있습니다 F. 우리의 목록은 이제 F최저 비용의 노드로 사용 되었으므로 완료되었습니다. 이전 최단 노드를 역 추적하여 경로를 구성 할 수 있습니다.


A * 알고리즘

그래서 왜 A * 알고리즘 대신 Dijkstra를 설명했는지 궁금 할 것입니다 . 글쎄, 유일한 차이점은 후보자를 어떻게 평가 (또는 분류) 하는가에있다. Dijkstra를 사용하면 다음과 같습니다.

Cost_of_Edge + Cost_of_previous_Node

A *를 사용하면 다음과 같습니다.

Cost_of_Edge + Cost_of_previous_Node + Estimated_Cost_to_reach_Target_from(Node)

어디 Estimated_Cost_to_reach_Target_from일반적이라고 휴리스틱 기능. 목표 노드에 도달하기위한 비용을 추정하는 기능입니다. 좋은 휴리스틱 기능을 사용하면 대상을 찾기 위해 더 적은 수의 노드를 방문해야합니다. Dijkstra의 알고리즘은 사방으로 확장되지만 A *는 (추론 적 덕분에) 대상 방향으로 검색합니다.

휴리스틱에 대한 Amit의 페이지 에는 일반적인 휴리스틱에 대한 좋은 개요가 있습니다.


2
휴리스틱이 항상 최선의 경로를 찾기 위해 검색을 추진하지는 않습니다. 예를 들어 휴리스틱이 대상까지의 거리이지만 실행 가능한 경로가지도의 가장자리 주위에있는 경우이 경우 검색시 전체 경로를 검색하여 올바른 경로를 얻습니다. 확실히, 당신은 생각해야합니다, 내가 얻지 못하는 것이 있습니까? 작동하지 않습니다! -이해해야 할 것은 휴리스틱의 목적은 대부분의 경우 검색을 줄이는 것이며, 특정 요구에 맞는 사용 가능한 모든 솔루션 중 '가장 좋은'것을 찾는 것입니다.
SirYakalot

2
@AsherEinhorn 그것은 여전히 ​​Djikstra와 같은 정보가없는 검색보다 더 나을 것입니다.
bummzack

예, 그렇습니다. 어쩌면 나는 위의 의견에서 이야기 한 사례가 A *의 이론적 인 '최악의 경우'시나리오와 휴리스틱 그러나 Dijkstra가 매번 할 것이라고 생각합니다. 대부분의 경우 A *는 매우 간단한 휴리스틱으로도 더 좋습니다. 필자의 목표는 휴리스틱이 처음에는 혼란 스러울 수 있다는 점이었다. '타겟까지의 거리'가 모든 시나리오에 항상 의미가있는 것은 아니기 때문이다.
SirYakalot

또한 다음을 참조하십시오 : qiao.github.io/PathFinding.js/visual
David Chouinard

이 답변은 A *가 최단 경로를 찾도록 보장한다는 의미에서 휴리스틱을 허용하는 것에 대한 언급을 사용할 수 있습니다. (Briefly : 휴리스틱이 허용 되려면 휴리스틱이 대상까지의 실제 거리를 과대 평가해서는 안됩니다. 허용되지 않는 휴리스틱이 유용 할 수 있지만 A *가 차선 경로를 반환 할 수 있습니다.)
Ilmari Karonen

26

A * 경로 찾기는 추론을 추가로 사용하는 가장 좋은 유형 검색입니다.

가장 먼저해야 할 일은 검색 영역을 나누는 것입니다. 이 설명에서는 대부분의 2D 게임이 타일 그리드를 사용하고 시각화하기 때문에 맵이 정사각형 타일 그리드입니다. 그러나 검색 영역은 16 진수 그리드 또는 위험과 같은 임의의 모양으로 원하는 방식으로 나눌 수 있습니다. 다양한 맵 위치를 "노드"라고하며이 알고리즘은 트래버스 할 노드가 많고 노드 사이에 연결을 정의 할 때마다 작동합니다.

어쨌든 주어진 시작 타일에서 시작합니다.

  • 시작 타일 주위의 8 개 타일은 a) 현재 타일에서 다음 타일로 이동하는 비용 (일반적으로 수평 또는 수직 이동의 경우 1, 대각선 이동의 경우 sqrt (2))에 따라 "점수"로 표시됩니다.

  • 그런 다음 각 타일에는 추가 "휴리스틱"점수가 할당됩니다. 즉, 각 타일로 이동할 상대적 가치의 근사치입니다. 다른 휴리스틱이 사용되는데, 가장 단순한 것은 주어진 타일의 중심과 끝 타일 사이의 직선 거리입니다.

  • 그런 다음 현재 타일이 "닫히고"에이전트가 열려 있고 이동 점수가 가장 낮고 휴리스틱 점수가 가장 낮은 인접 타일로 이동합니다.

  • 이 프로세스는 목표 노드에 도달하거나 더 이상 열린 노드가 없을 때까지 반복됩니다 (에이전트가 차단됨을 의미).

이러한 단계를 설명하는 다이어그램은이 초보자 용 자습서를 참조하십시오 .

휴리스틱을 개선 할 때 주로 개선 할 수있는 부분이 있습니다.

  • 지형 차이, 거칠기, 가파른 정도 등을 고려

  • 효율적인 경로가 아닌 맵의 영역을 차단하기 위해 그리드를 가로 질러 "스위프"를 수행하는 것도 유용합니다. 스위프 테스트가 없으면 에이전트는 먼저 U에 들어가서 돌아 서서 U의 가장자리를 돌아 다니게됩니다. "실제"지능형 에이전트는 U 자형 트랩을 인식하고 간단히 피합니다. 청소는 이것을 시뮬레이션하는 데 도움이 될 수 있습니다.


1
그래프, 노드, 가장자리에 대한 설명은 타일에 대한 것보다 명확합니다. 게임의 공간 구조에 관계없이이 공간에서 위치 정보가 서로 연결되어있는 한 동일한 알고리즘을 적용 할 수 있다는 것을 이해하는 데 도움이되지 않습니다.
Klaim

시각화하기가 더 어렵 기 때문에 실제로는 명확하지 않다고 주장합니다. 그러나이 설명은 타일 그리드가 필요하지 않다는 것을 언급해야합니다. 사실, 그 점을 편집하겠습니다.
jhocking

14

최고는 아니지만 몇 년 전 C ++에서 A *를 사용한 구현 입니다.

전체 알고리즘을 설명하는 것보다 리소스를 알려주는 것이 좋습니다. 또한, 위키 기사를 읽으면서 데모를 가지고 플레이하고 어떻게 작동하는지 시각화 할 수 있는지 확인하십시오. 특정 질문이 있으면 의견을 남겨주십시오.

  1. Wikipedia의 A *
  2. A * Java 데모

4
파이썬 예제는 C ++입니다.
알루미늄 번즈

@finish-누군가가 그것을 만나서 반가워요! 일상적인 활동은 요즘 파이썬을 중심으로 이루어집니다. 감사!
David McGraw

3
당신의 C ++ 예제는 C 일 수도 있습니다.
deceleratedcaviar

4
예제는 모든 구조에 대해 어셈블러에있을 수 있습니다. A *도 아닙니다. 어떻게 받아 들여 질까요?

4
그것은 파스 파에 달려 있지 않아 죄송합니다. 시작했을 때 처음으로 시도한 코딩 중 하나였습니다. 의견에 뭔가를 공헌하거나 게시물을 편집하여 나만의 솔루션을 공유하십시오.
David McGraw 2016 년

6

경로 찾기 에 대한 ActiveTut의 기사가 유용 할 수 있습니다. 그것은 A *와 Dijkstra의 알고리즘과 그 차이점을 모두 다룹니다. Flash 개발자를 대상으로하지만 Flash를 사용하지 않더라도 이론에 대한 통찰력을 제공해야합니다.


4

A *와 Dijkstra의 알고리즘을 다룰 때 시각화해야 할 중요한 것은 A *가 지시된다는 것입니다. 어떤 방향으로 볼 것인지 "추측"하여 특정 지점까지의 최단 경로를 찾습니다. Dijkstra의 알고리즘은 / every / 지점까지의 최단 경로를 찾습니다.


1
A *와 Dijkstra의 차이점에 대한 정확한 설명은 아닙니다. Dijkstra는 모든 지점에 대한 단일 소스를 해결하는 것이 사실이지만, 게임에 사용될 때는 일반적으로 목표에 대한 경로를 찾 자마자 잘립니다. 이 둘의 실제 차이점은 A *에 휴리스틱이 알려주고 더 적은 분기로 해당 목표를 찾을 수 있다는 것입니다.

Joe의 설명에 덧붙여서 : A *는 당신이 허락한다면 모든 지점까지가는 길을 찾을 것입니다. 그러나 게임에서 우리는 보통 일찍 멈추기를 원합니다. A *는 휴리스틱이 노드를 재정렬하여 가장 유망한 경로를 먼저 탐색하는 것을 제외하고는 Dijsktra의 알고리즘과 유사합니다. 그렇게하면 보통 Dijkstra의 알고리즘보다 더 일찍 중지 할 수 있습니다. 예를 들어,지도 중심에서 동쪽으로가는 경로를 찾으려면 Dijkstra의 알고리즘은 모든 방향으로 똑같이 탐색하고 동쪽을 찾으면 중지합니다. A *는 서쪽보다 동쪽으로가는 데 더 많은 시간을 보내고 더 빨리 도착합니다.
amitp

3

따라서 첫 번째 진술처럼 A *는 그래프 탐색 알고리즘의 핵심입니다. 일반적으로 게임에서 우리는 타일 또는 다른 세계 지오메트리를 그래프로 사용하지만 다른 것에는 A *를 사용할 수 있습니다. 그래프 탐색을위한 두 가지 ur 알고리즘은 깊이 우선 검색과 너비 우선 검색입니다. DFS에서는 현재 노드의 형제를보기 전에 항상 현재 분기를 완전히 탐색하고 BFS에서는 항상 형제를 먼저보고 자식을 봅니다. A *는 원하는 목표에 가까워 질 때 지점 (DFS와 같이)을 탐색하는 지점 사이에서 중간 지점을 찾으려고 시도하지만 지점에서 더 나은 결과를 얻을 수있는 경우 형제를 중지하고 때로는 시도합니다. 실제 수학은 다음에 탐색 할 수있는 노드 목록을 유지하여 각 노드에 "좋은 점"이있는 것입니다. 점수는 목표와 얼마나 가까운 지 (어떤 종류의 추상적 의미로) 표시하며 점수가 낮을수록 좋습니다 (0은 목표를 찾았 음을 의미합니다). 점수의 최소값과 루트에서 떨어진 노드 수 (일반적으로 현재 구성 또는 경로 찾기의 현재 위치)를 찾아 다음에 사용할 것을 선택합니다. 노드를 탐색 할 때마다 모든 하위 항목을이 목록에 추가 한 다음 가장 새로운 하위 항목을 선택하십시오.


3

추상 수준에서 A *는 다음과 같이 작동합니다.

  • 예를 들어 세상을 별개의 수의 연결된 노드로 취급합니다. 그리드 또는 그래프.
  • 해당 세계의 경로를 찾으려면 해당 공간 내에서 인접한 '노드'목록을 찾아야합니다.
  • 순진한 접근 방식은 다음과 같습니다. 시작 노드로 시작하여 끝 노드에서 끝나는 가능한 모든 노드 순열을 계산하고 가장 저렴한 노드를 선택합니다. 가장 작은 공간을 제외한 모든 공간에서 분명히 영원히 걸릴 것입니다.
  • 따라서 대체 접근법은 어떤 순열이 먼저 고려되어야하는지 추측하고 주어진 해를 구할 수 있는지 여부를 알기 위해 세계에 대한 약간의 지식을 사용하려고합니다. 이 추정을 휴리스틱이라고합니다.
  • A *는 허용 가능한 휴리스틱이 필요합니다 . 이것은 결코 과대 평가하지 않는다는 것을 의미합니다.
    • 길 찾기 문제에 대한 좋은 휴리스틱은 두 점 사이의 최단 경로가 직선임을 알기 때문에 유클리드 거리입니다. 이것은 실제 시뮬레이션에서 거리를 과대 평가하지 않습니다.
  • A *는 시작 노드로 시작하고 휴리스틱을 사용하여 다음 노드에서 시도 할 순열을 결정하여 해당 노드와 각 이웃 및 이웃의 이웃 등의 연속적인 순열을 시도합니다.
  • 각 단계에서 A *는 지금까지 가장 유망한 경로를보고, 지금까지 이동 한 거리와 그로부터 멀어 질 거리에 대한 휴리스틱의 추정치를 바탕으로 '최상'인 다음 이웃 노드를 선택합니다. 마디.
  • 휴리스틱은 결코 과대 평가하지 않으며 지금까지 이동 한 거리는 정확한 것으로 알려져 있기 때문에 항상 가장 낙관적 인 다음 단계를 선택합니다.
    • 다음 단계가 목표에 도달하면 마지막 위치에서 가장 짧은 경로를 찾았다는 것을 알 수 있습니다. 이것이 유효한 경로를 가장 낙관적으로 추측했기 때문입니다.
    • 목표에 도달하지 못하면 나중에 탐색 할 수있는 지점으로 남습니다. 알고리즘은 이제 다음으로 가장 유망한 가능성을 선택하므로 위의 논리가 여전히 적용됩니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.