Quelle est l'implémentation de Dijkstra la plus rapide que vous connaissez (en C ++)?
Je l'ai fait récemment joindre la 3ème version de Dijkstra algorithme de plus court chemin de la source unique dans mon projet.
Je me rends compte qu'il existe de nombreuses implémentations différentes qui varient fortement dans la performance et aussi à faire varier la qualité du résultat dans les grands graphes. Avec mon jeu de données (> 100.000 sommets) le moteur d'exécution varie de 20 minutes à quelques secondes. Th chemins les plus courts aussi varier de 1 à 2%.
Qui est la meilleure application que vous connaissez?
EDIT:
Mes Données est un réseau hydraulique, avec 1 à 5 sommets par nœud. Son comparable à un plan de rue. J'ai fait quelques modifications à un déjà permis une accélération de l'algorithme à l'aide d'une liste triée de tous les autres nœuds) et maintenant de trouver les mêmes résultats en une fraction de temps. J'ai cherché quelque chose pour un certain temps. Je me demande si une telle application existe déjà.
Je ne peux pas expliquer les légères différences dans les résultats. Je sais que Dijkstra n'est pas heuristique, mais toutes les implémentations semblent corrects. La plus rapide des solutions ont les résultats les plus courts chemins. J'utilise la double précision de mathématiques exclusivement.
EDIT 2:
J'ai trouvé que les différences dans le chemin trouvé, en effet, sont de ma faute. J'avais inséré un traitement spécial à certains sommets (valable uniquement dans un seul sens) et j'ai oublié que dans les autres de la mise en œuvre.
MAIS je suis encore plus surpris que Dijkstra peut être accéléré de manière spectaculaire par la modification suivante:
En général, un algorithme de Dijkstra contient une boucle comme:
MyListType toDoList; //List sorted by smallest distance
InsertAllNodes(toDoList);
while(! toDoList.empty())
{
MyNodeType *node = *toDoList.first();
toDoList.erase(toDoList.first());
...
}
Si vous changer un peu, et il fonctionne de la même façon, mais se comporte mieux:
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);
}
}
Il semble, que cette modification réduit le moment de l'exécution par un ordre pas de grandeur, mais un ordre de l'exposant. Il réduit mon runtime formulaire de 30 Secondes à moins de 2. Je ne trouve pas cette modification dans toute la littérature. Il est aussi très clair que la raison se trouve dans la liste triée. insérer/effacer effectue bien pire avec 100.000 éléments avec une main pleine de.
RÉPONSE:
Après beaucoup de recherches sur google, j'ai trouvé moi-même. La réponse est clairement:
boost graph lib. Incroyable - je n'avais pas trouvé ça pendant un bon moment. Si tu penses qu'il n'y a pas de variation de la performance entre les implémentations de Dijkstra, voir wikipedia.
source d'informationauteur RED SOFT ADAIR | 2009-06-02
Vous devez vous connecter pour publier un commentaire.
Meilleures implémentations connues pour les réseaux routiers (>1 million de nœuds) de la requête fois exprimé dans microsecondes. Voir pour plus de détails, le 9 DIMACS de mise en Œuvre(2006). Notez que ce ne sont pas simplement Dijkstra, bien sûr, que le but était d'obtenir des résultats rapides.
Peut-être que je ne suis pas répondre à votre question. Mon point est pourquoi pour utilisation Dijkstra, quand il y a à peu près plus d'algorithmes efficaces pour votre problème. Si votre graphique capable de réaliser la forme triangulaire de la propriété (c'est un euclidienne graphique)
|ab| +|bc| > |ac|
(la distance du nœud a vers le nœud b plus la distance du nœud b vers le nœud c est plus grand que la distance du nœud a vers le nœud c) on peut alors appliquer l'algorithme A*.
Cet algorithme est assez efficace. Sinon, envisagez l'utilisation d'heuristiques.
La mise en œuvre n'est pas le problème majeur. L'algorithme utilisé n'importe.
Deux points que je voudrais faire:
1) Dijkstra vs*
L'algorithme de Dijkstra est un algorithme de programmation dynamique, pas une heuristique. A* est une heuristique car elle utilise également une fonction heuristique (permet de dire que h(x) ) pour "estimer" la proximité d'un point x est arriver à la fin du point. Cette information est exploitée dans des décisions ultérieures de nœuds à explorer les prochaines.
Pour les cas comme un Euclidienne graphique, puis Un* fonctionne bien parce que l'heuristique de la fonction est facile à définir (on peut simplement utiliser la distance Euclidienne, par exemple). Cependant, pour les non Euclidienne de graphiques, il peut être plus difficile de définir la fonction heuristique, et une définition erronée peut conduire à une non-optimal.
Par conséquent, dijkstra a l'avantage par rapport à Un* qui est que cela fonctionne pour n'importe quel graphique général (à l'exception d'Un* en étant plus rapide dans certains cas). Il se pourrait bien que certaines implémentations de l'utilisation de ces algorithmes de façon interchangeable, aboutissant à des résultats différents.
2) L'algorithme de dijkstra (et d'autres comme Un*) utiliser une file d'attente de priorité pour obtenir le prochain nœud à explorer. Une bonne mise en œuvre peut utiliser un tas plutôt que d'une file d'attente, et encore mieux on peut utiliser un tas de fibonacci. Cela pourrait expliquer les différents temps d'exécution.
La dernière fois que j'ai vérifié, l'Algorithme de Dijkstra retourne une solution optimale.
Tous les "vrais" des implémentations de Dijkstra doivent retourner le même résultat à chaque fois.
De même, l'analyse asymptotique nous montre que des petites optimisations pour particulier implémentations ne vont pas affecter les performances de façon significative la taille de l'image augmente.
Va dépendre de beaucoup de choses. Comment bien savez-vous à propos de vos données d'entrée? Est-il dense ou clairsemée? Que va changer les versions de l'algorithme sont les plus rapides.
Si c'est dense, il suffit d'utiliser une matrice. Si son éparses, vous voudrez peut-être regarder plus efficace des structures de données pour trouver le plus proche de vertex. Si vous avez plus d'informations à propos de votre ensemble de données que juste le graphe de connectivité, puis voir si un algorithme différent serait mieux travailler comme Une*.
Problème est, il n'y a pas "une le plus rapide" version de l'algorithme.