mirror of
https://github.com/Fare-spec/cours.git
synced 2025-12-07 10:50:36 +00:00
Auto commit
This commit is contained in:
206
Dijkstra/algo.py
206
Dijkstra/algo.py
@@ -1,6 +1,141 @@
|
||||
# https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||
def dijkstra(graph: dict, start: any) -> tuple:
|
||||
"""
|
||||
L'algorithme de Dijkstra pour trouver les plus courts chemins depuis un sommet de départ.
|
||||
|
||||
graph = {
|
||||
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)],
|
||||
@@ -8,67 +143,8 @@ graph = {
|
||||
'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']}")
|
||||
|
||||
p = {}
|
||||
|
||||
def chemin(predecesseur, debut, fin):
|
||||
chemin = []
|
||||
courant = fin
|
||||
while courant != debut:
|
||||
chemin.insert(0, courant)
|
||||
courant = predecesseur.get(courant)
|
||||
if courant is None:
|
||||
return None
|
||||
chemin.insert(0, debut)
|
||||
return chemin
|
||||
|
||||
|
||||
def initialisation(G, debut):
|
||||
distances = {key: float('inf') for key in G}
|
||||
distances[debut] = 0
|
||||
return distances
|
||||
|
||||
|
||||
def trouve_min(Q, distances):
|
||||
mini = float('inf')
|
||||
sommet = None
|
||||
for s in Q:
|
||||
if distances[s] < mini:
|
||||
mini = distances[s]
|
||||
sommet = s
|
||||
return sommet
|
||||
|
||||
def poid(s1, s2):
|
||||
for voisin, poids in graph[s1]:
|
||||
if voisin == s2:
|
||||
return poids
|
||||
return float('inf')
|
||||
|
||||
def distances_update(s1, s2, distances, predecesseur):
|
||||
poids = poid(s1, s2)
|
||||
if distances[s2] > distances[s1] + poids:
|
||||
distances[s2] = distances[s1] + poids
|
||||
predecesseur[s2] = s1
|
||||
|
||||
def dijkstra(G, debut='A'):
|
||||
distances = initialisation(G, debut)
|
||||
predecesseur = {}
|
||||
Q = set(G.keys())
|
||||
|
||||
while Q:
|
||||
s1 = trouve_min(Q, distances)
|
||||
if s1 is None:
|
||||
break
|
||||
Q.remove(s1)
|
||||
|
||||
for voisin, _ in G[s1]:
|
||||
if voisin in Q:
|
||||
distances_update(s1, voisin, distances, predecesseur)
|
||||
|
||||
return distances, predecesseur
|
||||
|
||||
if __name__ == "__main__":
|
||||
distances, predecesseur = dijkstra(graph, 'A')
|
||||
print("Distances depuis A :", distances)
|
||||
print("Chemin le plus court de A à G :", chemin(predecesseur, 'A', 'G'))
|
||||
|
||||
46
Dijkstra/fonctions.md
Normal file
46
Dijkstra/fonctions.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Dijkstra
|
||||
## Fonctions
|
||||
### `dijkstra(graph: dict, start: any) -> tuple`
|
||||
- **Paramètres :**
|
||||
- `graph` : Dictionnaire représentant le graphe. Chaque clé est un noeud et sa valeur est une liste de tuples `(voisin, poids)`.
|
||||
- `start` : Le noeud de départ.
|
||||
- **Retourne :**
|
||||
- Un tuple contenant :
|
||||
- `distances` : Un dictionnaire associant à chaque noeud la distance minimale depuis `start`.
|
||||
- `predecesseur` : Un dictionnaire associant à chaque noeud son prédécesseur dans le chemin le plus court.
|
||||
|
||||
---
|
||||
### `reconstruct_chemin(predecesseur: dict, start: any, end: any) -> list`
|
||||
|
||||
- **Paramètres :**
|
||||
- `predecesseur` : Dictionnaire des prédécesseurs.
|
||||
- `start` : Le noeud de départ.
|
||||
- `end` : Le noeud d'arrivée.
|
||||
- **Retourne :**
|
||||
- Une liste représentant le chemin le plus court de `start` à `end`.
|
||||
Si aucun chemin n'est trouvé, la fonction renvoie une liste vide.
|
||||
|
||||
---
|
||||
### `solutions_dijkstra(graph: dict, start: any) -> dict`
|
||||
|
||||
- **Paramètres :**
|
||||
- `graph` : Dictionnaire représentant le graphe.
|
||||
- `start` : Le noeud de départ.
|
||||
- **Retourne :**
|
||||
- Un dictionnaire où chaque clé est un noeud du graphe et la valeur associée est un sous-dictionnaire contenant :
|
||||
- `"distance"` : La distance minimale depuis `start`.
|
||||
- `"chemin"` : Le chemin le plus court sous forme de liste de noeuds None si pas trouver.
|
||||
|
||||
---
|
||||
## Utilisation
|
||||
Le graphe doit être défini sous forme de dictionnaire. Exemple :
|
||||
```python
|
||||
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': []
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user