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:
212
Dijkstra/algo.py
212
Dijkstra/algo.py
@@ -1,74 +1,150 @@
|
|||||||
# 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:
|
||||||
'A': [('B', 4), ('C', 2)],
|
graph (dict): Le graphe à parcourir sous forme de dictionnaire, où les clés sont les sommets
|
||||||
'B': [('C', 5), ('D', 10)],
|
et les valeurs sont des listes de tuples (voisin, poids).
|
||||||
'C': [('D', 3), ('E', 8)],
|
start (any): Le sommet de départ.
|
||||||
'D': [('E', 4), ('F', 11)],
|
|
||||||
'E': [('G', 6)],
|
|
||||||
'F': [('G', 2)],
|
|
||||||
'G': []
|
|
||||||
}
|
|
||||||
|
|
||||||
p = {}
|
Returns:
|
||||||
|
tuple: Un tuple contenant deux dictionnaires :
|
||||||
def chemin(predecesseur, debut, fin):
|
- Le premier associe à chaque sommet la distance minimale depuis le sommet de départ.
|
||||||
chemin = []
|
- Le second associe à chaque sommet (sauf le départ) son prédécesseur sur le chemin le plus court.
|
||||||
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)
|
|
||||||
|
|
||||||
|
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
|
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__":
|
if __name__ == "__main__":
|
||||||
distances, predecesseur = dijkstra(graph, 'A')
|
import doctest
|
||||||
print("Distances depuis A :", distances)
|
doctest.testmod(verbose=True)
|
||||||
print("Chemin le plus court de A à G :", chemin(predecesseur, 'A', 'G'))
|
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']}")
|
||||||
|
|
||||||
|
|||||||
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