웜홀 노드가있는 최단 경로를 찾는 방법은 무엇입니까? 이동합니다. 중간에

예

이것은 코드를 통해하고 싶은 일의 예입니다. 점프 포인트 검색을 사용하여 문제없이 녹색 노드에서 빨간색 노드로 쉽게 이동할 수 있으며 심지어 A *도 가능합니다. 그러나 날실로 어떻게 계산합니까?

이미지에서 파란색 경로를 취할 때 녹색 노드에서 빨간색 노드로 이동하는 데 8 번만 이동하면됩니다. 파란색 경로는 즉시 하나의 자주색 노드에서 다음 자주색 노드로 위치를 이동합니다. 중간에 2 이동 비용이 드는 공간은 이동하기 위해 이동해야하는 두 개의 경사 영역 사이의 지점입니다.

파란색 경로를 선택하는 것이 더 빠릅니다. 노란색 경로까지 절반 정도만 이동하면되지만 프로그래밍 방식으로 어떻게해야합니까?

이 문제를 해결하기 위해 사용할 수있는 그래프 주위에 여러 개의 자주색 “왜곡”이 있다고 가정하고 각 자주색 점이 휘는 위치와 그래프의 위치를 ​​정확히 알고 있습니다.

일부 자주색 날실은 양방향이며 일부는 그렇지 않습니다. 때로는 한쪽에서 날실 만 입력 할 수 있지만 뒤틀린 후에는 되돌아 갈 수 없습니다.

나는 해결책에 대해 생각하고 각 날실 점까지의 거리 (단방향 점 빼기)와 그 점 사이의 차이와 그 점에 가까운 점을 확인하여 문제를 계산할 수 있다고 결론지었습니다. .

프로그램은 어떻게 든 첫 번째 점프에서 걷는 대신 두 번째 워프를 취하는 것이 더 유리하다는 것을 알아 내야 할 것입니다. 따라서 6 개의 스팟을 이동 한 다음 뒤틀린 다음 나머지 8 단계를 발로 옮기는 대신 (워프를 전혀 사용하지 않는 것보다 빠름) 6 번의 이동을 수행 한 다음 두 번째로 2 번의 이동으로 이동합니다.

편집 : 파란색 경로가 실제로 8 대신 12 번 이동한다는 것을 알았지 만 질문은 동일합니다.



답변

대부분의 경로 찾기 알고리즘은 그리드가 아닌 그래프로 정의됩니다. 그래프에서, 다른 두 먼 노드 사이의 연결은 실제로 문제가되지 않습니다.

그러나 휴리스틱을 관리해야합니다. 웜홀의 경우 두 노드 사이의 최소 거리가 더 이상 유클리드 거리가 아니고 거리가 삼각형 부등식을 만족하지 않습니다. 이러한 휴리스틱은 A *에 허용되지 않습니다. 따라서 A *를 쉽게 사용할 수 없습니다.

물론 휴리스틱을 사용하지 않는 Dijkstra와 같은 경로 찾기 알고리즘은 여전히 ​​작동합니다. 이것은 너비 우선 검색과 비슷하며 추가 노력없이 웜홀을 선택합니다. 그러나 Dijkstra는 휴리스틱 스가 좋은 A *보다 많은 노드를 방문합니다. (Dijkstra는을 사용하여 A *와 같습니다 heuristic(x) = 0.)

나가는 모든 웜홀을 웜홀로 직접 처리하는 휴리스틱을 사용하면 A *가 효과가 있다고 생각합니다. 즉 휴리스틱은 다음과 같습니다.

def wormhole_heuristic(x):
  return min(euclidean_distance(x, g) for g in [goal, wormholes...])

매우 정확한 휴리스틱을 위해 웜홀 엔드 포인트에서 목표 또는 다음 웜홀까지의 거리를 (재귀 적으로) 추가 할 수 있습니다. 즉, 사전 계산으로 모든 웜홀과 목표를 포함하는 (완전히 연결된) 하위 그래프에서 경로 찾기를 수행 할 수 있습니다. 두 노드 사이의 거리는 유클리드 거리입니다. 웜홀의 수가 그리드의 도달 가능한 셀 수보다 훨씬 적은 경우에 유용 할 수 있습니다. 새로운 휴리스틱은 다음과 같습니다.

def wormhole_heuristic(x):
  direct = euclidean_distance(x, goal)
  via_wormhole = min(euclidean_distance(x, w) + wormhole_path_distance(w, goal) for w in wormholes)
  return min(direct, via_wormhole)

@Caleth가 의견에서 지적했듯이 이것은 모두 조정 가능하며 마지막 웜홀 출구와 목표 사이의 거리를 추가하여 웜홀 네트워크를 통해 전체 경로를 찾지 않고도 첫 번째 웜홀 휴리스틱을 향상시킬 수 있습니다. 우리는 어떤 웜홀 출구가 마지막에 사용 될지 알지 못하고 과대 평가해서는 안되므로 출구를 목표에 가장 가깝게 가정해야합니다.

def wormhole_heuristic(x):
  direct = euclidean_distance(x, goal)
  to_next_wormhole = min(euclidean_distance(x, w) for w in wormholes)
  from_last_wormhole = min(euclidean_distance(w.exit, goal) for w in wormholes)
  via_wormhole = to_next_wormhole + from_last_wormhole
  return min(direct, via_wormhole)


답변

좌표가있는 그리드에 6 개의 정점이있는 그래프가 있습니다.

A ( 0,0)
B ( 4,7)
C ( 7,4)
D (10,4)
E (16,2)
F (16,0)

해당 정점에 대해 완전한 그래프를 생성하고 MAX( ABS( x1 - x2 ), ABS( y1 - y2 ) )표준 모서리에 대한 비용과 웜홀에 대한 비용 인 각 모서리에 비용을 할당 할 수 있습니다 .

이것은 비용을 인접 행렬로 제공합니다.

   A  B  C  D  E  F
- -- -- -- -- -- --
A  -  7  7 10 16 16
B  7  -  0  6 12 12
C  7  0  -  3  9  9
D 10  6  3  -  0  6
E 16 12  9  0  -  2
F 16 12  9  6  2  -

단방향 왜곡이있는 경우 그래프 (또는 인접 행렬)에서 반대 방향이 아닌 해당 방향으로가는 가장자리 만 만듭니다.

그런 다음 Dijkstra의 알고리즘우선 순위 대기열 과 함께 사용할 수 있습니다 .

A각 인접 모서리 에서 시작 하여 우선 순위 큐로 푸시 하십시오 .

형식 : (경로 : 비용)

queue     = [ (A-B : 7), (A-C : 7), (A-D : 10), (A-E : 16), (A-F : 16) ]

항목이 대기열로 푸시 될 때-각 정점의 최소 비용을 추적하고 기존 최소 비용보다 비용이 저렴한 경우 대기열로의 경로 만 푸시합니다.

min-costs = { A: 0, B: 7, C: 7, D: 10, E: 16, F: 16 }

대기열에서 첫 번째 항목을 제거하고 비용이 여전히 최소 비용과 일치하는 경우 해당 경로와 인접한 모서리로 형성된 모든 복합 경로를 우선 순위 대기열로 다시 밉니다 (복합 경로의 비용이 기존 최소값보다 낮은 경우).

없애다: (A-B : 7)

  • 시도 (A-B-A : 14)-더 높은 비용으로 거부
  • 시도 (A-B-C : 7)-동일한 비용으로 거부
  • 시도 (A-B-D : 13)-더 높은 비용으로 거부
  • 시도 (A-B-E : 19)-더 높은 비용으로 거부
  • 시도 (A-B-F : 19)-더 높은 비용으로 거부

없애다 (A-C : 7)

  • 시도 (A-C-A : 14)-더 높은 비용으로 거부
  • 시도 (A-C-B : 7)-동일한 비용으로 거부
  • 시도 (A-C-D : 10)-동일한 비용으로 거부
  • 시도 (A-C-E : 16)-동일한 비용으로 거부
  • 시도 (A-C-F : 16)-동일한 비용으로 거부

없애다 (A-D : 10)

  • 시도 (A-D-A : 20)-더 높은 비용으로 거부
  • 시도 (A-D-B : 16)-더 높은 비용으로 거부
  • 시도 (A-D-C : 13)-더 높은 비용으로 거부
  • 시도 (A-D-E : 10)-대기열에 삽입
  • 시도 (A-D-F : 16)-동일한 비용으로 거부

이제 대기열은 다음과 같습니다.

queue     = [ (A-D-E : 10), (A-E : 16), (A-F : 16) ]
min-costs = { A: 0, B: 7, C: 7, D: 10, E: 10, F: 16 }

없애다 (A-D-E : 10)

  • 시도 (A-D-E-A : 26)-더 높은 비용으로 거부
  • 시도 (A-D-E-B : 22)-더 높은 비용으로 거부
  • 시도 (A-D-E-C : 19)-더 높은 비용으로 거부
  • 시도 (A-D-E-D : 10)-동일한 비용으로 거부
  • 시도 (A-D-E-F : 12)-대기열에 삽입

그런 다음 대기열은 다음과 같습니다.

queue     = [ (A-D-E-F : 12), (A-E : 16), (A-F : 16) ]
min-costs = { A: 0, B: 7, C: 7, D: 10, E: 10, F: 12 }

를 제거 (A-D-E-F : 12)하고 12의 비용으로 대상 노드에 도착했음을 찾으십시오.

참고 : 경로 (A-B-C-D-E-F), (A-C-D-E-F)(A-D-E-F)모든 12의 동일한 최소 비용을 가지고있다.


답변

모든 정점을 포함하는 행렬을 설정하고 Floyd-Wallenstein-Algorithm 또는 Bellman-Ford-Algorithm을 사용하십시오. 둘 다 모든 점 사이에 가능한 가장 짧은 경로를 가진 행렬을 만듭니다. 그런 다음 행렬을 반복하여 두 점을 연결하는 최단 경로를 찾을 수 있습니다. (문제는 비대칭 TSP와 동일합니다).


답변