거대한 그래프에 대한 Dijkstra의 알고리즘


15

Dijkstra에 매우 익숙하며 알고리즘에 대한 특정 질문이 있습니다. 거대한 그래프 (예 : 35 억 개의 노드 (모든 OpenStreetMap 데이터))가 있으면 그래프를 메모리에 넣을 수 없으므로 그래프가 데이터베이스의 디스크에 저장됩니다.

이러한 그래프에서 최단 경로를 계산할 수있는 라이브러리가 있습니다. 그들은 이것을 어떻게합니까? 더 구체적으로, Dijkstra의 알고리즘을 실행하기 위해 그래프의 필요한 부분을 어떻게로드합니까?

방문한 각 정점의 인접 목록을 가져 오려면 통계 데이터에 따라 10,000 개의 노드 당 약 1,500 개의 데이터베이스 쿼리가 필요하므로 그렇게하는 방식이 명확하지 않습니다. 너무 느릴 것입니다.

그들은 그걸 어떻게 햇어? 직접 구현하려고합니다.


2
그들이 Dijkstra를 사용하고 있습니까? 설명하는 상황에 더 적합한 다른 최단 경로 알고리즘이 많이 있습니다.
David Richerby

1
코드를 살펴 보셨습니까? 우리는 어떻게 알아야합니까? "데이터베이스 쿼리"-그래프 저장에 DBMS를 사용하지 않기를 바랍니다.
Raphael

@DavidRicherby 그래 난 확신, 봐 이 링크
dimitris93

2
"[순수한 C 코드를 조사하는 것은 지루한 과정이 아닐 것입니다." 그러나 이것이 코드의 기능을 아는 유일한 방법입니다. 그래서 당신은 우리에게 당신의 지루한 작업을하도록 요구하고 있습니다. 이것은 귀하의 질문에 대한 가장 큰 광고가 아닙니다.
David Richerby

1
@Shiro "어떻게하면 되나요?" 그것이 정말로 당신이 묻고 싶은 질문이 아니라면, 당신은 문구를 바꿔야합니다.
Raphael

답변:


6

이러한 그래프에서 최단 경로를 계산할 수있는 라이브러리가 있습니다. 그들은 이것을 어떻게합니까? 더 구체적으로, Dijkstra의 알고리즘을 실행하기 위해 그래프의 필요한 부분을 어떻게로드합니까?

DB, 디스크에서 읽을 사용자 정의 파일 형식 및 메모리 내 설정을 사용할 수 있습니다.

그러나 DB를 사용한 경험에 따르면 '간단한'연결 된 목록 형식을 기반으로 자신의 파일 형식을 작성하는 것보다 약 5-10 배 느리고 메모리가 훨씬 더 강합니다.

좋은 점은 오픈 소스 인 OSM을 사용하는 여러 소프트웨어 프레임 워크가 있으므로 여기 에서 코드를 직접 확인할 수 있습니다 . 에서 GraphHopper 오픈 소스 라우팅 엔진 은 메모리로부터 스위치에 아주 쉽다는 메모리에 설정하는 설정 (계 디스크) 맵핑 -이 동일한 형식을 사용. "mmap"설정은 메모리가 제한된 모바일 장치에서도 사용할 수 있으며 서버에 필요한 RAM이 있으면 후자가 훨씬 더 빠르게 수행됩니다. 예를 들어 월드 와이드 그래프 (> 100mio 노드)의 경우 약 8-10GB RAM과 계약 계층 구조를 통해 모든 속도를 높이려면 더 많은 RAM이 필요합니다. 원하는 모든 차량에 대해 대략 5-8GB가 더 큽니다.

형식은 매우 단순하며 기본적으로 필요한 몇 가지 트릭으로 필요한 데이터 만 저장하여 압축합니다. 자세한 내용은 여기를 참조 하십시오 . 면책 조항 : 저는 GraphHopper의 저자입니다.

다른 답변에 관해서 :

적용 가능한 Dijkstras 알고리즘은이 문제에 최적이 아닌 것으로 간주됩니다.

'정상적인'Dijkstra는 매우 합리적으로 수행 할 수 있으며 (3mio 노드와 같은 국가 전체 쿼리의 경우 1 미만) 이론 이론에서는 최적 이지만 생산 시나리오에서 빠르게 진행하려면 약간의 조정이 필요합니다. 그리고 Contraction Hierachies와 같은 기술은 양방향 수정을 사용하여 매우 잘 수행됩니다.

도로 네트워크는 계층적이고 평면입니다.

도로 네트워크는 자동차에만 계층 적이며 평면이 아닙니다 (교량, 터널 등).


질문이 하나 더 있습니다. NodeID에서 가장 가까운 노드를 어떻게 찾 latitude/longitude습니까? 최단 경로 A-> B를 계산하는 데 필요합니다. 또한 모든 평방 미터에 노드가 포함되어 있지 않기 때문에 A와 B가 노드로 존재하지 않을 수도 있습니다. 우리는 A와 B의 2 가까운 NodeIDs 찾을 필요가 그래서
dimitris93

이는 예를 들어 GraphHopper의 반경이 ~ 500m 인 셀에 NodeID를 효율적으로 저장하는 일종의 쿼드 트리 인 LocationIndexTree에서 수행됩니다. 아무것도 발견되지 않으면 반경을 특정 정도로 확장합니다. 이론 상으로는 간단하게 들리지만 영역을 가로 질러 가장자리가있을 수 있으므로 매우 복잡합니다. 영역을 만들고 쿼리 할 때 효율적이어야합니다.
Karussell

가장 가까운 이웃을 검색 할 때 KD-Trees가 더 효율적이지 않습니까? KD-Tree 대신 QuadTrees를 선택한 이유는 무엇입니까? 현재 라우팅 엔진에 KD-Tree를 구현하고 있습니다. QuadTrees를 구현하기 시작했지만 KD-Trees는 동일하지만 코딩하기 쉽고 가장 가까운 이웃을 쿼리하는 것이 더 빠르다는 것을 알았 기 때문에 중단했습니다. 내가 잘못 ?
dimitris93

쿼드 트리를 사용할 때 스토리지 박스를 명시 적으로 저장하지 않아도 스토리지 이점을 얻을 수 있으며, 이는 내 유스 케이스에 더 중요합니다 (또한 쿼드 트리가 더 쉽다는 것을 알았습니다). 쿼리 속도는 문제가되지 않습니다. 실제로 누군가는 그러한 시도를 연구했으며 다른 구현을 능가했습니다. KD 나무, 그러나 나는 모두 특정 구현에 달려 있다고 가정합니다.
Karussell

스탠포드 에서이 PDF의 9 페이지를 보면 KD-Trees에서 가장 가까운 이웃을 검색 할 때 경계 상자를 전혀 알 필요가 없습니다. 또 다른 점은 모든 점을 미리 알고 있기 때문에 균형 잡힌 높이의 나무를 만들 수 있다는 것입니다. quadtrees가 kd-trees에 비해 어떤 이점이 있다고 여전히 긍정적입니까?
dimitris93

2

우선 순위 대기열에 인접한 모든 모서리를 넣을 필요는 없습니다. Dijkstra의 알고리즘에 "거짓말"하고 정점에 입사하는 가장 짧은 정점 v, 즉 w를 스택에서 빼냅니다. 그런 다음 v가 대기열에서 풀릴 때 "oops"라고 말하면 실수를하고 정점 w에 가장 가까운 다음 정점도 부여해야합니다. 이 방법을 사용하면 올바른 솔루션을 얻을 수 있으며 대기열 크기는 많은 것 대신 하나의 사건 정점으로 크게 줄어 듭니다. 그러나 필요할 때 항상 다음으로 가장 가까운 정점을주기 위해 발생률을 추적해야합니다. 의견 중 하나는 도로 네트워크가 평면이며 올바르지 않다고 주장했다. 실제로, 한 연구에 따르면 평면적이지 않다는 것이 밝혀졌습니다. 많은 비평면을 유발하는 도시를 통해 다리를 통해 교차하는 모든 고속도로를 생각하십시오.


0

더 효율적인 변형이 "유사한"것으로 간주 될 수 있지만 적용 가능한 Dijkstras 알고리즘은이 문제에 대해 최적이 아닌 것으로 간주됩니다. 다양한 단순화가 있습니다. 도로 네트워크는 계층 적이고 평면 입니다. 기본 접근 방식은 다음과 같습니다. 이 지역은 일반적으로 "도로 네트워크의 경로 계획"으로 알려져 있습니다.

  • 인접 목록 데이터에서 그래프 구조를 "컴파일"할 수 있습니다. 이것은 당신이 인용 한 라이브러리 인 SpatiaLite 의 접근법입니다 . 이러한 그래프 구조는 그래프 위치가 이진 인코딩 된 정수 등으로 표현되는 압축 된 이진 형식으로 저장되므로 그래프 표시 및 조작은 모든 도로 이름 등을 저장하는 것보다 훨씬 적은 공간을 차지합니다. SpatiaLite 알고리즘이 "온라인"이 아니며 메모리에서 완전히 실행됩니다.

  • 병렬 / 분산 알고리즘이 있습니다. Scalable GPU Graph Traversal / Merrill, Garland, Grimshaw를 참조하십시오 .

  • 이 질문은 클라이언트-서버 용어, 즉 "쿼리"를 사용합니다. 알고리즘은 클라이언트-서버 의미에서 데이터베이스를 "쿼리"하여 실행되지 않습니다. SQL과 같은 고급 쿼리 언어는 데이터베이스에 대한 인터페이스이며 최소 경로 계산 요청을 전송하는 데 사용될 수 있지만 알고리즘에서 내부적으로 사용되지는 않습니다. 일반적으로 알고리즘은 "데이터베이스 내부", 즉 "서버 측"전체에서 실행됩니다. 따라서 데이터베이스 쿼리에서 최단 경로 알고리즘을 작성하는 것은 소규모 네트워크에는 가능하지만 중간 규모 / 대규모 네트워크에는 적합하지 않습니다.

  • 적은 비율의 추정이 수용 될 수있는 또 다른 접근법이 있습니다. 기본 아이디어는 노드 사이의 거리 색인을 유지하는 것입니다. 예를 들어 , 큰 그래프에서 가장 짧은 경로의 빠르고 정확한 추정 / Gubichev, Bedathur, Seufert, Weikum 참조

  • 이 (235p!) 박사 논문이 특히 적용 가능합니다. 도로 네트워크 / 슐트의 경로 계획

  • 일부 알고리즘은 이러한 많은 아이디어를 사용하고 다른 알고리즘은 고도로 조정되고 독점적이며 경쟁적인 영업 비밀을 준수합니다. 예를 들어 구글. 이 주제에 오해의 소지가있는 매체가있을 수 있습니다. 예를 들어 Google지도를 가능하게하는 단순하고 우아한 알고리즘 Google은 인용없이 Dijkstras 알고리즘을 사용합니다.


1
Google지도는 확실히 Dijskstra보다 나은 것으로 업그레이드되었습니다. 모든 중급 유능한 개발자는 로드맵에 A *를 사용하지만 이전 작업에서 Google 엔진이 100ms 미만의 웨이 포인트를 통해 2500km의 경로를 다시 계획 할 수 있음을 알게되었습니다. A *에는 너무 빠르므로 ArcFlags와 같은 것을 사용할 가능성이 큽니다.
MSalters

Karussell의 답변은 논쟁의 여지가 없을 것으로 예상했지만 "해당되는 Dijkstras 알고리즘은이 문제에 대해 최적이 아닌 것으로 간주된다"는이 개시 문장에 도전합니다. Schultes 논문에 대한 주장에 대한 강력한지지가있다 (이전부터).이 분야에 대한 매우 포괄적이고 최근의 조사이기도하며 "계층 적 및 평면적" "근사"도 설명한다. 불행히도 커서 검색에 대한 공개 문헌의 실제 Google 알고리즘에 대한 표시는없는 것 같습니다.
vzn

-2

이와 같은 매우 큰 데이터 세트에서 이러한 빠른 결과를 얻으려면 경로 압축과 함께 조합 찾기 데이터 구조 를 사용하는 것이 가장 좋습니다 . 그러나 Djikstra의 알고리즘 만 사용하여 최적화하려는 경우 그래프의 각 노드에 어떤 정보가 있는지 알려줍니다. 1,500 개의 쿼리를 모두 수행 할 필요는 없습니다.

예를 들어 다음 예를 고려하십시오. 2 명의 배우 (베이컨 번호) 사이의 분리 정도를 찾으려고 노력하고 가장 가중치가 적은 경로 (가장 최신 영화를 사용하는 경로)를 찾고 싶습니다. 이제라는 함수가 있다고 가정 해 봅시다 shortestPath(actor A, actor B);. 다음 시나리오를 고려하십시오.

액터 A가 1970 년 이후로 연기하고 액터 B가 2000 년 이후로 연기 한 경우, 그 정보를 감안할 때 액터 B의 첫 번째 영화에서 시작하여 액터 A로가는 길을 찾는 것이 훨씬 더 논리적입니다. 배우 A가 연기 한 모든 영화를 반복하는 것에 반대합니다.

따라서 주요 포인트는 Djikstra 알고리즘의 최적화가 실제로 데이터 세트가 무엇인지에 달려 있다는 것입니다. 알고리즘 최적화에 도움이되도록 데이터 세트의 내용에 대한 자세한 정보를 제공해야합니다.

편집 : 같은 국가에서 두 도시 사이의 최단 경로를 찾으려고하고 있으며이 나라가 아르헨티나보다 더 긴 경우 국가의 경도와 위도에 따라 쿼리를 수행 할 수 있다고 가정 해 봅시다 . 경계. 그런 다음 수평이 아닌 수직을 사용하여 경도를 사용하여 횡단을 시작할 수 있습니다. 종종 예외 처리가 필요하지만 일반적인 아이디어를 얻습니다.


1
Dijkstra에서 Union-Find를 어떻게 사용합니까?
Raphael

데이터는 공간 데이터, 위도 및 경도입니다. 나는 그것이 분명하다고 생각했다.
dimitris93
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.