Я недавно приложил 3-ю версию алгоритма Дейкстры для кратчайшего пути из одного источника в мой проект.
Я понимаю, что существует множество различных реализаций, которые сильно различаются по производительности, а также по качеству результата в больших графах. С моим набором данных (> 100 000 вершин) время выполнения варьируется от 20 минут до нескольких секунд. Кратчайшие пути также варьируются на 1-2%.
Какую лучшую реализацию вы знаете?
EDIT:
Мои данные - это гидравлическая сеть с 1-5 вершинами на узел. Это сопоставимо с картой улиц. Я сделал некоторые изменения в уже ускоренном алгоритме (используя отсортированный список для всех оставшихся узлов) и теперь нашел те же результаты за долю времени. Я искал такую вещь довольно давно. Интересно, такая реализация уже существует.
Я не могу объяснить небольшие различия в результатах. Я знаю, что Дейкстра не эвристический, но все реализации кажутся правильными. Более быстрые решения дают результаты с более короткими путями. Я использую исключительно математику двойной точности.
РЕДАКТИРОВАТЬ 2:
Я узнал, что различия в найденном пути действительно являются моей ошибкой. Я вставил специальную обработку для некоторых вершин (действует только в одном направлении) и забыл об этом в другой реализации.
НО Я все еще более чем удивлен, что Дейкстра может быть значительно ускорена следующим изменением:
В общем случае алгоритм Дейкстры содержит цикл, подобный следующему:
MyListType toDoList; // List sorted by smallest distance
InsertAllNodes(toDoList);
while(! toDoList.empty())
{
MyNodeType *node = *toDoList.first();
toDoList.erase(toDoList.first());
...
}
Если вы немного измените это, он работает так же, но работает лучше:
MyListType toDoList; // List sorted by smallest distance
toDoList.insert(startNode);
while(! toDoList.empty())
{
MyNodeType *node = *toDoList.first();
toDoList.erase(toDoList.first());
for(MyNeigborType *x = node.Neigbors; x != NULL; x++)
{
...
toDoList.insert(x->Node);
}
}
Кажется, что эта модификация сокращает время выполнения на порядок не величины, а порядка экспоненты. Это уменьшило мою рабочую форму с 30 секунд до менее 2. Я не могу найти эту модификацию ни в одной литературе. Также очень ясно, что причина кроется в отсортированном списке. Вставка / стирание работает намного хуже с 100.000 элементов, которые заполнены рукой.
ОТВЕТ:
После долгих поисков я нашел это сам. Ответ очевиден:
увеличить граф lib . Удивительно - я не нашел это в течение долгого времени. Если вы думаете, что между реализациями Dijkstra нет различий в производительности, см. wikipedia .