Pourquoi l'algorithme de Dijkstra fonctionne-t-il?

Je comprends ce qu'est l'algorithme de Dijkstra, mais je ne comprends pas pourquoi cela fonctionne.

Lors de la sélection du sommet suivant à examiner, pourquoi l'algorithme de Dijkstra sélectionne-t-il celui avec le plus petit poids? Pourquoi ne pas simplement sélectionner un sommet arbitrairement, puisque l'algorithme visite tous les sommets de toute façon?

32
demandé sur nbro 2010-05-18 15:17:27

7 réponses

Vous pouvez penser à L'algorithme de Djikstra comme un algorithme de remplissage d'eau (c'est-à-dire une recherche en largeur taillée). À chaque étape, l'objectif est de couvrir plus de l'ensemble du graphique avec le chemin le moins coûteux possible. Supposons que vous ayez des sommets au bord de la zone que vous avez remplie, et que vous les listiez en termes de distance:

v0 <= v1 <= v2 <= v3 ...

Pourrait-il y avoir un moyen moins cher d'arriver à vertex v1? Si c'est le cas, le chemin doit passer par v0, car aucun sommet non testé ne peut être plus proche. Si vous examinez vertex v0 pour voir où vous pouvez vous rendre, en vérifiant si un chemin à travers v0 est moins cher (à un autre sommet à deux pas).

Si vous éliminez le problème de cette façon, vous êtes assuré que vos distances sont toutes minimales, car vous vérifiez toujours exactement ce sommet qui pourrait conduire à un chemin le plus court. Soit vous trouvez ce chemin le plus court, soit vous l'excluez, et passez au sommet suivant. Ainsi, vous êtes assuré de consommer un sommet par étape.

Et vous arrêtez sans faire plus de travail que nécessaire, car vous vous arrêtez lorsque votre sommet de destination occupe la fente" je suis le plus petit " v0.

, regardons un bref exemple. Supposons que nous essayons d'obtenir de 1 à 12 par multiplication, et le coût entre les nœuds est le nombre par lequel vous devez multiplier. (Nous limiterons les sommets aux nombres de 1 à 12.)

Nous commençons par 1, et nous pouvons atteindre n'importe quel autre nœud en multipliant par cette valeur. Donc noeud 2 a coût 2, 3 d'un coût de 3, ... 12 coût 12 si vous allez en une seule étape.

Maintenant, un chemin à travers 2 pourrait (sans connaître la structure) arriver à 12 le plus rapide s'il y avait un lien libre de 2 à 12. Il n'y en a pas, mais s'il y en avait, ce serait le plus rapide. Nous vérifions donc 2. Et nous constatons que nous pouvons obtenir de 4 coût 2, à 6 pour 3, et ainsi de suite. Nous avons donc un tableau des coûts comme ceci:

3  4  5  6  7  8  9 10 11 12 // Vertex
3  4  5  5  7  6  9  7 11  8 // Best cost to get there so far.

Ok, maintenant peut-être que nous pouvons arriver à 12 de 3 gratuitement! Amélioration de la vérification. Et nous constatons que 3*2==6 de sorte que le coût de 6 est le coût de 3 plus 2, et 9 plus 3, et 12 plus 4.

4  5  6  7  8  9 10 11 12
4  5  5  7  6  6  7 11  7

D'accord. Maintenant, nous testons 4, et on voit qu'on peut obtenir à 8 pour un supplément de 2, et 12 pour un supplément de 3. Encore une fois, le coût pour arriver à 12 n'est donc pas supérieur à 4+3 = 7:

5  6  7  8  9 10 11 12
5  5  7  6  8  7 11  7

Maintenant, nous essayons 5 et 6--aucune amélioration jusqu'à présent. Ce qui nous laisse avec

7  8  9 10 11 12
7  6  8  7 11  7

Maintenant, pour la première fois, nous voyons que le coût d'accès à 8 est inférieur au coût d'accès à 7, donc nous ferions mieux de vérifier qu'il n'y a pas de moyen gratuit d'accéder à 12 à partir de 8. Il n'y a pas-il n'y a aucun moyen d'y arriver avec des entiers-donc nous le jetons.

7  9 10 11 12
7  8  7 11  7

Et maintenant nous voyons que 12 est aussi bon marché que n'importe quel chemin laissé, donc le coût pour atteindre 12 doit être 7. Si nous avions gardé une trace du chemin le moins cher jusqu'à présent (seulement remplacer le chemin quand c'est strictement mieux), nous trouverions que 3*4 est le premier moyen le moins cher de frapper 12.

19
répondu Rex Kerr 2013-02-17 18:25:48

L'algorithme de Dijkstra sélectionne le sommet avec le moindre coût de chemin jusqu'à présent, car un chemin à travers un autre sommet est au moins aussi coûteux qu'un chemin à travers le sommet avec le moins de coût de chemin.

Visiter n'importe quel autre sommet, donc, si c'est plus coûteux (ce qui est tout à fait possible) nécessiterait de visiter non seulement cet autre sommet, mais aussi celui avec le moins de coût de chemin jusqu'à présent, donc vous devriez visiter plus de Sommets avant de trouver le chemin le plus court. En fait, vous serait la fin de la avec l'algorithme Bellman-Ford Si vous avez fait cela.

Je devrais aussi ajouter que le Sommet n'a pas de poids, c'est le bord qui a un poids. La clé pour un sommet donné est le coût du chemin le plus court trouvé jusqu'à ce sommet à partir du sommet source.

5
répondu Michael Aaron Safyan 2015-08-15 14:27:05

La raison pour laquelle l'algorithme de Dijsktra fonctionne comme il le fait est en partie car il exploite le fait que le chemin le plus court entre le nœud u et w qui inclut le point v contient également le chemin le plus court de u à v et de v à w. S'il existait quelque chose de plus court entre u et v, alors ce ne serait pas le chemin le plus court.

Pour vraiment comprendre pourquoi l'algorithme de Dijkstra fonctionne, regardez dans les bases de la programmation dynamique , semble difficile mais c'est vraiment assez facile de comprendre les principes.

3
répondu Grembo 2015-08-15 14:28:54

Il aime gourmand strategy.My l'anglais n'est pas good.It traduit par google.Si vous ne comprenez pas,je suis vraiment désolé.

Algorithme de Dijkstra, A G de S à tous les sommets de la longueur de chemin la plus courte. Nous supposons que chaque sommet de G dans V a reçu un drapeau L (V), c'est soit un nombre, soit ∞. Supposons que P est l'ensemble des sommets de G, P contient S, pour satisfaire:

A) Si V est P, alors L (V) de V S à la longueur du chemin le plus court, et l'existence D'un tel V de S à la chemin le plus court: chemin sur les sommets dans P dans

B) Si V N'appartient pas à P, alors L (V) de S à V satisfait aux restrictions suivantes sur la longueur du chemin le plus court: V est le seul chemin P N'appartient pas au sommet.

Nous pouvons utiliser l'induction pour prouver P algorithme Dijkstra en ligne avec la définition ci-dessus de la collection:

1) Lorsque le nombre d'éléments de P = 1, P correspond à la première étape de l'algorithme, P = (S), est clairement satisfaite.

2) Supposons que P est k, le nombre d'éléments, p satisfaire la définition ci-dessus, voir l'algorithme ci-dessous la troisième étape

3) P Dans et le premier à savoir n'est pas marqué avec le Sommet minimum U, marqué comme L (U), peut être prouvé de S à U de U en dehors du chemin le plus court, en plus de P ne contient pas les éléments n'appartiennent pas.

Parce que s'il y a en dehors des autres sommets sauf U, alors le chemin le plus court vers S, P1, P2 ... Pn, Q1, Q2 ... Qn, U (P1, P2 ... Pn est P; Q1, Q2,... Qn n'appartient pas à P), de la nature de B) La longueur du chemin le plus court L (Q1) + chemin (Q1, U)> L (U).

Qui est supérieur à S, P1, P2 ... Pn, U de la longueur du canal L (U), n'est pas le chemin le plus court. Par conséquent, de la S à L'U de U en dehors du chemin le plus court, en plus de P ne contient pas les éléments n'appartiennent pas à U de S à la longueur du chemin le plus court de la L (U) est donnée.

U est ajouté à P sous la forme P ', clairement P' pour répondre à la nature du A).

Prendre V n'appartient pas à P ', n'appartient évidemment pas à V P, puis de S à V sauf le chemin le plus court et rencontrer tous les sommets en dehors de V dans P' dans le chemin il y a deux possibilités, I) contient U, ii) ne contient pas U.

Sur i) S, P1, P2 ... Pn, U, V = L (U) + W (U, V)

Ii) S, P1, P2 ... Pn, V = L (V)

Évidemment, les deux sont donnés dans le plus petit V de S pour répondre à l'accès minimum et l'addition extérieure à tous les sommets sont V P 'de longueur.

La troisième étape à l'algorithme donné en P ' avec K + 1 éléments et répondre à la A), B).

Par la proposition d'induction peut permettre.

Ici la source.

0
répondu WaterCow101 2010-05-18 11:59:17

Il vérifie d'abord le chemin avec le poids le plus bas car il est le plus probable (sans informations supplémentaires) de réduire le nombre de chemins vérifiés. Par exemple:

a->b->c     cost is 20
a->b->d     cost is 10
a->b->d->e  cost is 12

Si le but est d'aller de a à e, nous n'avons même pas besoin de vérifier le coût de:

a->b->c->e

Parce que nous savons que c'est au moins 20 donc nous savons que ce n'est pas optimal car il y a déjà un autre chemin avec un coût de 12. Vous pouvez maximiser cet effet en vérifiant d'abord les poids les plus bas. C'est la même?) de la façon dont minimax fonctionne dans les échecs et d'autres jeux pour réduire le facteur de ramification de l'arbre de jeu.

0
répondu phkahler 2010-05-18 16:38:25

L'algorithme de Dijsktra est un algorithme gourmand qui suit l'heuristique de résolution de problèmes de faire le choix localement optimal à chaque étape avec l'espoir de trouver un optimum global.

0
répondu Ernest 2011-12-16 03:50:24

Pour comprendre le concept de base de cet algorithme, j'ai écrit ce code pour vous. Il y a une explication de la façon dont cela fonctionne.

graph = {}

graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["finish"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["finish"] = 5
graph["finish"] = {}

infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["finish"] = infinity
print "The weight of each node is: ", costs

parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["finish"] = None

processed = []

def find_lowest_cost_node(costs):
    lowest_cost = float("inf")
    lowest_cost_node = None
    for node in costs:
        cost = costs[node]
        if cost < lowest_cost and node not in processed:
            lowest_cost = cost
            lowest_cost_node = node
    return lowest_cost_node

node = find_lowest_cost_node(costs)
print "Start: the lowest cost node is", node, "with weight",\
    graph["start"]["{}".format(node)]

while node is not None:
    cost = costs[node]
    print "Continue execution ..."
    print "The weight of node {} is".format(node), cost
    neighbors = graph[node]
    if neighbors != {}:
        print "The node {} has neighbors:".format(node), neighbors
    else:
        print "It is finish, we have the answer: {}".format(cost)
    for neighbor in neighbors.keys():
        new_cost = cost + neighbors[neighbor]
        if costs[neighbor] > new_cost:
            costs[neighbor] = new_cost
            parents[neighbor] = node
    processed.append(node)
    print "This nodes we researched:", processed
    node = find_lowest_cost_node(costs)
    if node is not None:
        print "Look at the neighbor:", node

# to draw graph
import networkx
G = networkx.Graph()
G.add_nodes_from(graph)
G.add_edge("start", "a", weight=6)
G.add_edge("b", "a", weight=3)
G.add_edge("start", "b", weight=2)
G.add_edge("a", "finish", weight=1)
G.add_edge("b", "finish", weight=5)

import matplotlib.pyplot as plt
networkx.draw(G, with_labels=True)
plt.show()
0
répondu Alexandr Zhytenko 2018-04-20 10:04:29