mirror of
https://github.com/Fare-spec/cours.git
synced 2025-12-07 10:50:36 +00:00
151 lines
4.6 KiB
Python
151 lines
4.6 KiB
Python
def dijkstra(graph: dict, start: any) -> tuple:
|
|
"""
|
|
L'algorithme de Dijkstra pour trouver les plus courts chemins depuis un sommet de départ.
|
|
|
|
Args:
|
|
graph (dict): Le graphe à parcourir sous forme de dictionnaire, où les clés sont les sommets
|
|
et les valeurs sont des listes de tuples (voisin, poids).
|
|
start (any): Le sommet de départ.
|
|
|
|
Returns:
|
|
tuple: Un tuple contenant deux dictionnaires :
|
|
- Le premier associe à chaque sommet la distance minimale depuis le sommet de départ.
|
|
- Le second associe à chaque sommet (sauf le départ) son prédécesseur sur le chemin le plus court.
|
|
|
|
Exemples:
|
|
>>> graph = {
|
|
... 'A': [('B', 4), ('C', 2)],
|
|
... 'B': [('C', 5), ('D', 10)],
|
|
... 'C': [('D', 3), ('E', 8)],
|
|
... 'D': [('E', 4), ('F', 11)],
|
|
... 'E': [('G', 6)],
|
|
... 'F': [('G', 2)],
|
|
... 'G': []
|
|
... }
|
|
>>> distances, predecesseur = dijkstra(graph, 'A')
|
|
>>> distances['A']
|
|
0
|
|
>>> distances['B']
|
|
4
|
|
>>> distances['C']
|
|
2
|
|
>>> distances['D']
|
|
5
|
|
>>> distances['E']
|
|
9
|
|
>>> distances['F']
|
|
16
|
|
>>> distances['G']
|
|
15
|
|
>>> predecesseur['B']
|
|
'A'
|
|
>>> predecesseur['C']
|
|
'A'
|
|
>>> predecesseur['D']
|
|
'C'
|
|
>>> predecesseur['E']
|
|
'D'
|
|
>>> predecesseur['F']
|
|
'D'
|
|
>>> predecesseur['G']
|
|
'E'
|
|
"""
|
|
distances, predecesseur, unvisited = {}, {}, {}
|
|
for sommet in graph:
|
|
distances[sommet] = float('inf')
|
|
unvisited[sommet] = distances[sommet]
|
|
distances[start] = 0
|
|
while unvisited:
|
|
current = min(unvisited, key=unvisited.get)
|
|
del unvisited[current]
|
|
for voisin, poid in graph[current]:
|
|
new_distance = distances[current] + poid
|
|
if new_distance < distances[voisin]:
|
|
distances[voisin] = new_distance
|
|
predecesseur[voisin] = current
|
|
if voisin in unvisited:
|
|
unvisited[voisin] = new_distance
|
|
return distances, predecesseur
|
|
|
|
|
|
def reconstruire_chemin(predecesseur: dict, start: any, end: any) -> list:
|
|
"""reconstruit le chemin grace au predecesseur
|
|
|
|
Args:
|
|
predecesseur (dict): les predecesseurs
|
|
start (any): le debut
|
|
end (any): la fin
|
|
|
|
Returns:
|
|
list: renvoie une liste contenant le chemin le plus court (si aucun trouver alors renvoie liste vide)
|
|
Examples:
|
|
>>> pred = {'B': 'A', 'C': 'A', 'D': 'C', 'E': 'D', 'F': 'D', 'G': 'E'}
|
|
>>> reconstruire_chemin(pred, 'A', 'F')
|
|
['A', 'C', 'D', 'F']
|
|
>>> reconstruire_chemin(pred, 'A', 'G')
|
|
['A', 'C', 'D', 'E', 'G']
|
|
"""
|
|
chemin = [end]
|
|
current = end
|
|
while current != start:
|
|
if current not in predecesseur:
|
|
return []
|
|
current = predecesseur[current]
|
|
chemin.append(current)
|
|
chemin.reverse()
|
|
return chemin
|
|
|
|
def solutions_dijkstra(graph: dict, start: any) -> dict:
|
|
"""elle renvoie le dictionnaire des noeud et distances grace au chemin
|
|
|
|
Args:
|
|
graph (dict): le graphe
|
|
start (any): le debut
|
|
|
|
Returns:
|
|
dict: contenant les noeuds et leurs distances
|
|
Exemples:
|
|
>>> graph = {
|
|
... 'A': [('B', 4), ('C', 2)],
|
|
... 'B': [('C', 5), ('D', 10)],
|
|
... 'C': [('D', 3), ('E', 8)],
|
|
... 'D': [('E', 4), ('F', 11)],
|
|
... 'E': [('G', 6)],
|
|
... 'F': [('G', 2)],
|
|
... 'G': []
|
|
... }
|
|
>>> sol = solutions_dijkstra(graph, 'A')
|
|
>>> sol['F']
|
|
{'distance': 16, 'chemin': ['A', 'C', 'D', 'F']}
|
|
>>> sol['G']
|
|
{'distance': 15, 'chemin': ['A', 'C', 'D', 'E', 'G']}
|
|
"""
|
|
distances, predecesseur = dijkstra(graph, start)
|
|
solutions = {}
|
|
for sommet in graph:
|
|
if sommet == start:
|
|
chemin = [start]
|
|
else:
|
|
chemin = reconstruire_chemin(predecesseur, start, sommet)
|
|
if not chemin:
|
|
chemin = None
|
|
solutions[sommet] = {"distance": distances[sommet], "chemin": chemin}
|
|
return solutions
|
|
|
|
if __name__ == "__main__":
|
|
import doctest
|
|
doctest.testmod(verbose=True)
|
|
graph = {
|
|
'A': [('B', 4), ('C', 2)],
|
|
'B': [('C', 5), ('D', 10)],
|
|
'C': [('D', 3), ('E', 8)],
|
|
'D': [('E', 4), ('F', 11)],
|
|
'E': [('G', 6)],
|
|
'F': [('G', 2)],
|
|
'G': []
|
|
}
|
|
solution = solutions_dijkstra(graph, 'A')
|
|
for sommet, info in solution.items():
|
|
print(f"sommet: {sommet} ----- Distance: {info['distance']} ------- chemin: {info['chemin']}")
|
|
|