Refonte du cours en 12 séances alignées sur le programme officiel

This commit is contained in:
2026-07-24 00:07:01 +02:00
parent 66376ea912
commit fdac54ba92
32 changed files with 5831 additions and 722 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python
#-*-coding:UTF-8-*-
#************************************************************************
# Transcription du graphe sous forme de liste de listes
#************************************************************************
graphe = [
[0 ,4 ,2 ,99,99,99,99,99],
[4 ,0 ,6 ,99,5 ,99,99,99],
[2 ,6 ,0 ,3 ,99,99,99,5 ],
[99,99,3 ,0 ,99,3 ,4 ,1 ],
[99,5 ,99,99,0 ,2 ,99,99],
[99,99,99,3 ,2 ,0 ,7 ,99],
[99,99,99,4 ,99,7 ,0 ,10],
[99,99,5 ,1 ,99,99,10,0 ]
]
def distance(Noeud_A, Noeud_B) -> int:
#************************************************************************
# Donne la distance entre deux noeuds adjacents Noeud_A et Noeud_B
# Entrée : Le noeud de départ
# Sortie : la liste des noeuds adjacents
#************************************************************************
# on vérifie que les valeurs de départ et arrivée sont bien des entiers
assert type(Noeud_A) == int, "la valeur départ n'est pas un entier"
assert type(Noeud_B) == int, "la valeur départ n'est pas un entier"
assert graphe[Noeud_A][Noeud_B] != 99, "les noeuds ne sont pas adjacent"
# On retourne la distance entre les deux noeuds
return(graphe[Noeud_A][Noeud_B])
def determine_adjacents(noeud) -> list:
#************************************************************************
# A partir d'un noeud en entrée, la fonction donne la liste des noeuds adjacents
# Entrée : Le noeud de départ
# Sortie : la liste des noeuds adjacents
#************************************************************************
# On sélectionne la ligne contenant les noeuds adjacent par rapport a notre point de départ
ligne = graphe[noeud]
# on détermine le nombre de noeuds adjacents pour ce point
nb_adjacent = len(ligne)-ligne.count(99)-ligne.count(0)
# Puis on crée la variable parcours sous forme de liste de listes
liste_adjacents = [[] for i in range(0,nb_adjacent)]
a = 0
for i in range(0,len(ligne)):
if (ligne[i] != 0 and ligne[i] != 99):
liste_adjacents[a].append(noeud)
liste_adjacents[a].append(i)
a += 1
# On retourne la liste des noeuds adjacents
return(liste_adjacents)
def recursive2(liste) -> list:
#************************************************************************
# La fonction récursive établit la liste exhaustive des chemins possibles
# Entrée : La liste de chemins déja établie
# Sortie : la liste de chemins jusqu'au noeuds suivants
#************************************************************************
sommets_adjacents = []
# On détermine le nombre d'arcs adjacents aux noeuds
for i in range(0,len(liste)): # on boucle dans notre liste existante
for element in determine_adjacents(liste[i][-1]): # pour chaque sommet dans la liste des adjacents
if element not in sommets_adjacents: # si le sommets n'est pas encore dans notre liste
sommets_adjacents.append(element) # alors on le rajoute
# On identifie les chemins qu'on doit créer, en ignorant les chemins:
# - où on revient sur un noeud déja visité
# - déja existant dans la liste
# Puis on renseigne les chemins possibles
entrees_a_supprimer = [] # On va garder en mémoire les entrées a supprimer
for i in range(0,len(liste)) : # on boucle dans notre liste existante
if liste[i][-1] != arrivée: # on ignore les chemins menant déja au point d'arrivée
for j in range(0,len(sommets_adjacents)): # on boucle dans la liste qu'on vient d'obtenir
if (sommets_adjacents[j][0] == liste[i][-1] and
sommets_adjacents[j][-1] != liste[i][0] and
sommets_adjacents[j][-1] not in liste[i]
):
liste.append(liste[i] + sommets_adjacents[j][1:len(sommets_adjacents)])
entrees_a_supprimer.append(i) # On va garder en mémoire les entrées a supprimer
for i in range(0,len(entrees_a_supprimer)): # avant de retourner notre résultat on supprime les entrées superflus
del liste[entrees_a_supprimer[i]-i]
return(liste)
#********************************************************************************
# Début du programme principal
#********************************************************************************
# on définit un point de départ et d'arrivée
départ = 0
arrivée = 6
# On détermine le nombre d'arcs partant de notre sommet départ
liste_arcs_départs = determine_adjacents(départ)
# Construction de la liste de chemins possibles
for i in range(0,len(graphe)):
liste_arcs_départs = recursive2(liste_arcs_départs)
# On imprime le nombre de chemins et les chemins possibles
print("Il y a",len(liste_arcs_départs),"chemins possibles:",liste_arcs_départs)
# On identifie le chemin le plus court
this_distance = 0
court_distance = 9999
court_chemin =[]
for element in liste_arcs_départs:
this_distance = 0
for i in range(0,len(element)-1):
this_distance += distance(element[i],element[i+1])
if this_distance < court_distance:
court_distance = this_distance
court_chemin = element
# Ecrivez votre réponse à la question 6.1 ici
print("Le chemin le plus court est:", court_chemin)
print("La distance a parcourir est:", court_distance)
# Déclaration des variables en fonction des itérations (1, 3 et 5)
chemins_it1 = [[0, 1], [0, 2]]
chemins_it3 = [[0, 1, 2, 3], [0, 1, 2, 7], [0, 1, 4, 5], [0, 2, 1, 4], [0, 2, 3, 5], [0, 2, 3, 6], [0, 2, 3, 7], [0, 2, 7, 3], [0, 2, 7, 6]]
chemins_it5 = [[0, 2, 3, 6], [0, 2, 7, 6], [0, 1, 2, 3, 6], [0, 1, 2, 7, 6], [0, 1, 4, 5, 6], [0, 2, 3, 5, 6], [0, 2, 3, 7, 6], [0, 2, 7, 3, 6], [0, 1, 2, 3, 5, 4], [0, 1, 2, 3, 5, 6], [0, 1, 2, 3, 7, 6], [0, 1, 2, 7, 3, 5], [0, 1, 2, 7, 3, 6], [0, 1, 4, 5, 3, 2], [0, 1, 4, 5, 3, 6], [0, 1, 4, 5, 3, 7], [0, 2, 1, 4, 5, 3], [0, 2, 1, 4, 5, 6], [0, 2, 3, 5, 4, 1], [0, 2, 7, 3, 5, 4], [0, 2, 7, 3, 5, 6]]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,210 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Séance 7 — Implémentation de l'algorithme de Dijkstra\n",
"VERSION ELEVE\n",
"\n",
"On reprend ici l'intuition et le pseudo-code vus en Séance 6 pour les traduire en Python, sur le même graphe (circuits courts en Bretagne)."
],
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5- Implémentation de l'algorithme de Dijkstra\n",
" ### Travail à faire 6: Les données à traiter\n",
"Le graphe sera sous forme d'une liste de liste, comme dans la 1ère partie \"méthode par force brute\". \n",
" 1- Reprenez cette liste et insérez la ci-dessous. \n",
" 2- La fonction 'Dijkstra' est documentée (en rouge), complétez les trois assertions permettant de s'assurer de l'intégrité des données à traiter. Puis tester ces insertions avec 'dijkstra(\"A\",0)', puis 'dijkstra(Graphe,\"A\")', puis 'dijkstra(Graphe,8)' et enfin 'dijkstra(Graphe,0) qui est la bonne écriture d'appel pour cette fonction.\n",
" 3- Expliquer pourquoi '0' est saisi pour le paramètre 's-debut'?"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# la structure de données pour le Graphe est la liste de liste de la 1ère partie: \n",
"Graphe = "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) ... , \"Graphe doit être de type liste\"\n",
" assert type(s_debut) ... , \" s_debut doit être un entier \"\n",
" assert s_debut in [ ... ], \"s_debut doit être dans la plage d'indice de Graphe\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 7: Initialisation de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, compléter les deux lignes manquantes de la partie \"Algo: initialisation\" du script, ci-dessous."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" #Algo: Initialisation\n",
" infini=float(\"inf\") # définition d'une valeur infinie\n",
" predecesseurs = [-1 for sommet in range(len(Graphe))] # initialisation des prédecesseurs à non parcouru (-1)\n",
" predecesseurs[s_debut] = 0 # sauf le sommet de départ qui est le prédécesseur de lui-même\n",
" ... # initialisation des poids à l'infini\n",
" ... # sauf le sommet de départ de poids nul\n",
" E_sommets = [i for i in range(len(Graphe))] # initialisation de l'ensemble des sommets du graphe\n",
" E_calcules = [] # création de la liste des calculés, vide au départ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 8: Partie \"Mise à jour, poids et prédécesseur du plus proche voisin\" de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, complétez l'implémentation de la structure conditionnelle de la partie \"Algo: Mise à jour, poids et prédécesseur du plus proche voisin\" du script de la boucle principale, ci-dessous. \n",
" Pour cela, répondez au QCM4 ci-dessous, puis placez la structure de code choisie dans le script de la boucle principale situé plus bas."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$QCM4:$ Parmi les quatres extraits de script ci-dessous, un seul convient:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse1\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] = 0:\n",
" poids[s_voisin] = poids[s_mini] - Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse2\n",
"if poids[s_voisin] < poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_mini] = s_voisin "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse3\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse4\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] or Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_mini] = poids[s_voisin] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "#Algo: boucle principale\n while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n\n # Algo: recherche d'un sommet de distance minimale\n poids_local = infini #\n s_mini = -1 # \n for s in E_sommets: # \n if poids[s] < poids_local: # \n poids_local = poids[s] # \n s_mini = s # \n #----------> Algo: fin de recherche d'un sommet de distance minimale\n\n E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n\"\"\" Partie du script à compléter ci-dessous à partir du choix effectué au QCM4\"\"\"\n #Algo: mise à jour poids et prédécesseur du plus proche voisin\n ... # si le chemin st plus court et il y a existance d'un arc:\n ... # mise à jour du poids du plus proche voisin\n ... # mise à jour du prédécesseur du plus proche voisin\n #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n#---------->fin de boucle principale"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 9: Partie \"Recherche dun sommet de distance minimale \" de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, commenter chaque ligne du script proposé pour la partie \"Algo: Recherche dun sommet de distance minimale\" de façon à bien expliquer la solution implémentée pour obtenir le sommet \"actuel\" de poids minimal ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "#Algo: boucle principale\n while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n\n # Algo: recherche d'un sommet de distance minimale\n poids_local = infini #\n s_mini = -1 # \n for s in E_sommets: # \n if poids[s] < poids_local: # \n poids_local = poids[s] # \n s_mini = s # \n #----------> Algo: fin de recherche d'un sommet de distance minimale\n\n E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n\n #Algo: mise à jour poids et prédécesseur du plus proche voisin\n if ... and Graphe[s_mini][s_voisin] !=0: # si le chemin st plus court et il y a existance d'un arc:\n ... # mise à jour du poids du plus proche voisin\n ... # mise à jour du prédécesseur du plus proche voisin\n #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n#---------->fin de boucle principale"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 10: la fonction Dijkstra complète\n",
" Reconstituer ci dessous le script complet de la fonction 'dijkstra' et en effectuer le test. Si le test n'est pas probant, recherchez d'éventuelles erreurs flagrantes, et, si nécessaire appelez l'enseignant pour débloquer la situation. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \n",
"\n",
"# le sommet s_debut choisi ici est \"A\", d'indice 0 dans E_sommets\n",
"dijkstra(Graphe,0)== ([0, 2, 1, 3, 7, 5, 4, 6], [0, 4, 2, 5, 9, 8, 9, 6], [0, 0, 0, 2, 1, 3, 3, 3])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -0,0 +1,685 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Séance 7 — Implémentation de l'algorithme de Dijkstra\n",
"VERSION corrigée\n",
"\n",
"On reprend ici l'intuition et le pseudo-code vus en Séance 6 pour les traduire en Python, sur le même graphe (circuits courts en Bretagne)."
],
"metadata": {}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5- Implémentation de l'algorithme de Dijkstra\n",
" ### Travail à faire 6: Les données à traiter\n",
"Le graphe sera sous forme d'une liste de liste, comme dans la 1ère partie \"méthode par force brute\". \n",
" 1- Reprenez cette liste et insérez la ci-dessous. \n",
" 2- La fonction 'Dijkstra' est documentée (en rouge), complétez les trois assertions permettant de s'assurer de l'intégrité des données à traiter. Puis tester ces insertions avec 'dijkstra(\"A\",0)', puis 'dijkstra(Graphe,\"A\")', puis 'dijkstra(Graphe,8)' et enfin 'dijkstra(Graphe,0) qui est la bonne écriture d'appel pour cette fonction.\n",
" 3- Expliquer pourquoi '0' est saisi pour le paramètre 's-debut'?"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# la structure de données pour le Graphe est la liste de liste de la 1ère partie: \n",
"Graphe = "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) ... , \"Graphe doit être de type liste\"\n",
" assert type(s_debut) ... , \" s_debut doit être un entier \"\n",
" assert s_debut in [ ... ], \"s_debut doit être dans la plage d'indice de Graphe\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf6-1 :** il suffit de recopier la lsite de liste de la 1ère partie de l'évaluation"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# la structure de données pour le Graphe est la liste de liste de la 1ère partie: \n",
"Graphe = [[0, 4, 2, 0, 0, 0, 0, 0 ],\n",
" [4, 0, 6, 0, 5, 0, 0, 0 ],\n",
" [2, 6, 0, 3, 0, 0, 0, 5 ],\n",
" [0, 0, 3, 0, 0, 3, 4, 1 ],\n",
" [0, 5, 0, 0, 0, 2, 0, 0 ],\n",
" [0, 0, 0, 3, 2, 0, 7, 0 ],\n",
" [0, 0, 0, 4, 0, 7, 0, 10],\n",
" [0, 0, 5, 1, 0, 0, 10, 0]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf6-2 :** \n",
" Les trois premieres vérifications mettent en évidence le retour de chacune des trois assertions ( 'Graphe' n'est pas de type 'list'; 's_debut' n'est pas de type 'int'; 's_debut' n'est pas un entier entre 0 et 7, puisque 'Graphe' est une liste de 8 éléments). La quatrième vérification ne crée pas d'AssertionError."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "AssertionError",
"evalue": "Graphe doit être de type liste",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-3-d14470863b64>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 15\u001b[1;33m \u001b[0mdijkstra\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"A\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-3-d14470863b64>\u001b[0m in \u001b[0;36mdijkstra\u001b[1;34m(Graphe, s_debut)\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;34m'predecesseurs'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mliste\u001b[0m \u001b[0mdes\u001b[0m \u001b[0msommets\u001b[0m \u001b[0mprédécesseur\u001b[0m \u001b[0mde\u001b[0m \u001b[0mchaque\u001b[0m \u001b[0msommet\u001b[0m \u001b[0mrangés\u001b[0m \u001b[0mdans\u001b[0m \u001b[0ml\u001b[0m\u001b[1;34m'ordre d'\u001b[0m\u001b[0mexploration\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \"\"\"\n\u001b[1;32m---> 11\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mlist\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Graphe doit être de type liste\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 12\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms_debut\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\" s_debut doit être un entier \"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionError\u001b[0m: Graphe doit être de type liste"
]
}
],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'obtention des plus courts chemins,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'obtention des plus courts chemins,\n",
" 'predecesseurs', liste des sommets \"prédécesseur de chaque sommet\" rangés dans l'ordre d'obtention des plus courts chemins,\n",
" \"\"\"\n",
" assert type(Graphe) == list, \"Graphe doit être de type liste\"\n",
" assert type(s_debut) == int, \" s_debut doit être un entier \"\n",
" assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n",
" \n",
"dijkstra(\"A\",0)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "AssertionError",
"evalue": " s_debut doit être un entier ",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-4-4268aa1c9000>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 15\u001b[1;33m \u001b[0mdijkstra\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m\"A\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-4-4268aa1c9000>\u001b[0m in \u001b[0;36mdijkstra\u001b[1;34m(Graphe, s_debut)\u001b[0m\n\u001b[0;32m 10\u001b[0m \"\"\"\n\u001b[0;32m 11\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mlist\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Graphe doit être de type liste\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms_debut\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\" s_debut doit être un entier \"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 13\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionError\u001b[0m: s_debut doit être un entier "
]
}
],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) == list, \"Graphe doit être de type liste\"\n",
" assert type(s_debut) == int, \" s_debut doit être un entier \"\n",
" assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n",
" \n",
"dijkstra(Graphe,\"A\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "AssertionError",
"evalue": "s_debut doit être dans la plage d'indice de Graphe",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-6-c0b62074927f>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 15\u001b[1;33m \u001b[0mdijkstra\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m8\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-6-c0b62074927f>\u001b[0m in \u001b[0;36mdijkstra\u001b[1;34m(Graphe, s_debut)\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mlist\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Graphe doit être de type liste\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[1;32massert\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms_debut\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\" s_debut doit être un entier \"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[0ms_debut\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"s_debut doit être dans la plage d'indice de Graphe\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[0mdijkstra\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mGraphe\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m8\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionError\u001b[0m: s_debut doit être dans la plage d'indice de Graphe"
]
}
],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) == list, \"Graphe doit être de type liste\"\n",
" assert type(s_debut) == int, \" s_debut doit être un entier \"\n",
" assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n",
" \n",
"dijkstra(Graphe,8)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) == list, \"Graphe doit être de type liste\"\n",
" assert type(s_debut) == int, \" s_debut doit être un entier \"\n",
" assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n",
" \n",
"dijkstra(Graphe,0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf6-3 :** \n",
" La quatrième vérification n'ayant pas créé d'AssertionError, elle valide à priori l'appel de la fonction 'dijkstra' avec les bons paramètres. La valeur '0' correspond au premier sommet du graphe dans la structure de liste de liste qui est la liste [0, 4, 2, 0, 0, 0, 0, 0 ] indiquant bien que le sommet A a un arc de distance 4 avec B et un arc avec C de distance 2."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 7: Initialisation de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, compléter les deux lignes manquantes de la partie \"Algo: initialisation\" du script, ci-dessous."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" #Algo: Initialisation\n",
" infini=float(\"inf\") # définition d'une valeur infinie\n",
" predecesseurs = [-1 for sommet in range(len(Graphe))] # initialisation des prédecesseurs à non parcouru (-1)\n",
" predecesseurs[s_debut] = 0 # sauf le sommet de départ qui est le prédécesseur de lui-même\n",
" ... # initialisation des poids à l'infini\n",
" ... # sauf le sommet de départ de poids nul\n",
" E_sommets = [i for i in range(len(Graphe))] # initialisation de l'ensemble des sommets du graphe\n",
" E_calcules = [] # création de la liste des calculés, vide au départ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf7 :** \n",
" Les deux lignes manquantes sont de la même forme que les deux précédentes en remplaçant la variable 'predecesseurs' par la variable 'poids' de type liste, et la valeur '-1' par 'infini' ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
"#Algo: Initialisation\n",
" infini=float(\"inf\") # définition d'une valeur infinie\n",
" predecesseurs = [-1 for sommet in range(len(Graphe))] # initialisation des prédecesseurs à non parcouru (-1)\n",
" predecesseurs[s_debut] = 0 # sauf le sommet de départ qui est le prédécesseur de lui-même\n",
" poids = [infini for sommet in range(len(Graphe))] # initialisation des poids à l'infini\n",
" poids[s_debut] = 0 # sauf le sommet de départ de poids nul\n",
" E_sommets = [i for i in range(len(Graphe))] # initialisation de l'ensemble des sommets du graphe\n",
" E_calcules = [] # création de la liste des calculés, vide au départ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 8: Partie \"Mise à jour, poids et prédécesseur du plus proche voisin\" de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, complétez l'implémentation de la structure conditionnelle de la partie \"Algo: Mise à jour, poids et prédécesseur du plus proche voisin\" du script de la boucle principale, ci-dessous. \n",
" Pour cela, répondez au QCM4 ci-dessous, puis placez la structure de code choisie dans le script de la boucle principale situé plus bas."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$QCM4:$ Parmi les quatres extraits de script ci-dessous, un seul convient:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse1\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] = 0:\n",
" poids[s_voisin] = poids[s_mini] - Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse2\n",
"if poids[s_voisin] < poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_mini] = s_voisin "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse3\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Réponse4\n",
"if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] or Graphe[s_mini][s_voisin] != 0:\n",
" poids[s_mini] = poids[s_voisin] + Graphe[s_mini][s_voisin] \n",
" predecesseurs[s_voisin] = s_mini "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Algo: boucle principale\n",
" while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n",
"\n",
" # Algo: recherche d'un sommet de distance minimale\n",
" poids_local = infini #\n",
" s_mini = -1 # \n",
" for s in E_sommets: # \n",
" if poids[s] < poids_local: # \n",
" poids_local = poids[s] # \n",
" s_mini = s # \n",
" #----------> Algo: fin de recherche d'un sommet de distance minimale\n",
"\n",
" E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n",
" E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n",
" for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n",
"\"\"\" Partie du script à compléter ci-dessous à partir du choix effectué au QCM4\"\"\"\n",
" #Algo: mise à jour poids et prédécesseur du plus proche voisin\n",
" ... # si le chemin st plus court et il y a existance d'un arc:\n",
" ... # mise à jour du poids du plus proche voisin\n",
" ... # mise à jour du prédécesseur du plus proche voisin\n",
" #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n",
"#---------->fin de boucle principale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf8 :** \n",
" La bonne réponse au QCM4 est la 3. D'ou le script complété ci-dessous."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Algo: boucle principale\n",
" while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n",
"\n",
" # Algo: recherche d'un sommet de distance minimale\n",
" poids_local = infini #\n",
" s_mini = -1 # \n",
" for s in E_sommets: # \n",
" if poids[s] < poids_local: # \n",
" poids_local = poids[s] # \n",
" s_mini = s # \n",
" #----------> Algo: fin de recherche d'un sommet de distance minimale\n",
"\n",
" E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n",
" E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n",
" for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n",
"\"\"\" Partie du script complété ci-dessous à partir de la réponse 3 du QCM4\"\"\"\n",
" #Algo: mise à jour poids et prédécesseur du plus proche voisin\n",
" if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] !=0: # si le chemin est plus court et il y a existance d'un arc:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] # mise à jour du poids du plus proche voisin\n",
" predecesseurs[s_voisin] = s_mini # mise à jour du prédécesseur du plus proche voisin\n",
" #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n",
"#---------->fin de boucle principale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 9: Partie \"Recherche dun sommet de distance minimale \" de l'algorithme\n",
" En reprenant les éléments de l'algorithme fournis au Taf2 et au Taf4, commenter chaque ligne du script proposé pour la partie \"Algo: Recherche dun sommet de distance minimale\" de façon à bien expliquer la solution implémentée pour obtenir le sommet \"actuel\" de poids minimal ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Algo: boucle principale\n",
" while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n",
"\n",
" # Algo: recherche d'un sommet de distance minimale\n",
" poids_local = infini #\n",
" s_mini = -1 # \n",
" for s in E_sommets: # \n",
" if poids[s] < poids_local: # \n",
" poids_local = poids[s] # \n",
" s_mini = s # \n",
" #----------> Algo: fin de recherche d'un sommet de distance minimale\n",
"\n",
" E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n",
" E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n",
" for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n",
"\n",
" #Algo: mise à jour poids et prédécesseur du plus proche voisin\n",
" if ... and Graphe[s_mini][s_voisin] !=0: # si le chemin st plus court et il y a existance d'un arc:\n",
" ... # mise à jour du poids du plus proche voisin\n",
" ... # mise à jour du prédécesseur du plus proche voisin\n",
" #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n",
"#---------->fin de boucle principale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf9 :** \n",
" Les commentaires doivent mettre en évidence le rôle et l'initialisation des variables locales à cette partie du script, les conditions de la boucle fort et du test conditionnel ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Algo: boucle principale\n",
" while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n",
"\n",
" # Algo: recherche d'un sommet de distance minimale\n",
" poids_local = infini # initialisation du poids en cours de calcul à une valeur infinie\n",
" s_mini = -1 # initialisation du sommet de poids minimal à 'non défini'\n",
" for s in E_sommets: # Pour chaque sommet non définitivement calculés:\n",
" if poids[s] < poids_local: # Si le poids du sommet actuel est inférieur au poids local:\n",
" poids_local = poids[s] # le poids local est remplacé par la valeur (inférieure) du sommet actuel\n",
" s_mini = s # le sommet de poids minimal est le sommet actuel\n",
" #----------> Algo: fin de recherche d'un sommet de distance minimale\n",
"\n",
" E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n",
" E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n",
" for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n",
"\n",
" #Algo: mise à jour poids et prédécesseur du plus proche voisin\n",
" if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] !=0: # si le chemin est plus court et il y a existance d'un arc:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] # mise à jour du poids du plus proche voisin\n",
" predecesseurs[s_voisin] = s_mini # mise à jour du prédécesseur du plus proche voisin\n",
" #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n",
"#---------->fin de boucle principale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Travail à faire 10: la fonction Dijkstra complète\n",
" Reconstituer ci dessous le script complet de la fonction 'dijkstra' et en effectuer le test. Si le test n'est pas probant, recherchez d'éventuelles erreurs flagrantes, et, si nécessaire appelez l'enseignant pour débloquer la situation. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \n",
"\n",
"# le sommet s_debut choisi ici est \"A\", d'indice 0 dans E_sommets\n",
"dijkstra(Graphe,0)== ([0, 2, 1, 3, 7, 5, 4, 6], [0, 4, 2, 5, 9, 8, 9, 6], [0, 0, 0, 2, 1, 3, 3, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Réponse Taf10 :** \n",
" La présence de la documentation de la fonction et des assertions est un plus dans la reconstitution de la fonction.\n",
"L'accompagnement au bon fonctionnement du programme final se fera au prix de malus suivant le niveau d'aide apportée et le type d'erreur corrigé."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def dijkstra(Graphe, s_debut):\n",
" \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n",
" paramètres :\n",
" 'Graphe', un graphe sous forme d'une liste de liste,\n",
" 's_debut' un sommet de départ.\n",
" renvoie:\n",
" 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n",
" 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n",
" 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n",
" \"\"\"\n",
" assert type(Graphe) == list, \"Graphe doit être de type liste\"\n",
" assert type(s_debut) == int, \" s_debut doit être un entier \"\n",
" assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n",
" \n",
" #Algo: Initialisation\n",
" infini=float(\"inf\") # définition d'une valeur infinie\n",
" predecesseurs = [-1 for sommet in range(len(Graphe))] # initialisation des prédecesseurs à non parcouru (-1)\n",
" predecesseurs[s_debut] = 0 # sauf le sommet de départ qui est le prédécesseur de lui-même\n",
" poids = [infini for sommet in range(len(Graphe))] # initialisation des poids à l'infini\n",
" poids[s_debut] = 0 # sauf le sommet de départ de poids nul\n",
" E_sommets = [i for i in range(len(Graphe))] # initialisation de l'ensemble des sommets du graphe\n",
" E_calcules = [] # création de la liste des calculés, vide au départ\n",
" \n",
" #Algo: boucle principale\n",
" while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n",
"\n",
" # Algo: recherche d'un sommet de distance minimale\n",
" poids_local = infini # initialisation du poids en cours de calcul à une valeur infinie\n",
" s_mini = -1 # initialisation du sommet de poids minimal à 'non défini'\n",
" for s in E_sommets: # Pour chaque sommet non définitivement calculés:\n",
" if poids[s] < poids_local: # Si le poids du sommet actuel est inférieur au poids local:\n",
" poids_local = poids[s] # le poids local est remplacé par la valeur (inférieure) du sommet actuel\n",
" s_mini = s # le sommet de poids minimal est le sommet actuel\n",
" #----------> Algo: fin de recherche d'un sommet de distance minimale\n",
"\n",
" E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n",
" E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n",
" for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n",
"\n",
" #Algo: mise à jour poids et prédécesseur du plus proche voisin\n",
" if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] !=0: # si le chemin est plus court et il y a existance d'un arc:\n",
" poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] # mise à jour du poids du plus proche voisin\n",
" predecesseurs[s_voisin] = s_mini # mise à jour du prédécesseur du plus proche voisin\n",
" #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n",
" #---------->fin de boucle principale\n",
" return E_calcules, poids, predecesseurs\n",
" \n",
" # le sommet s_debut choisi ici est \"A\", d'indice 0 dans E_sommets\n",
"dijkstra(Graphe,0)== ([0, 2, 1, 3, 7, 5, 4, 6], [0, 4, 2, 5, 9, 8, 9, 6], [0, 0, 0, 2, 1, 3, 3, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Optionnel, Travail à faire 11: Complexité expérimentale\n",
" En utilisant le script complet de la fonction 'dijkstra', effectuer la mesure de temps d'éxécution dans plusieurs situations pour évaluer expérimentalement le coût de cet algorithme. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "from random import randint\n\ndef dijkstra(Graphe, s_debut):\n \"\"\" fonction: calculer les plus courts chemins à partir d'un sommet de départ vers chacun des autres sommets\n paramètres :\n 'Graphe', un graphe sous forme d'une liste de liste,\n 's_debut' un sommet de départ.\n renvoie:\n 'E_calcules', liste des sommets rangés dans l'ordre d'exploration,\n 'poids', liste des poids de chaque sommet rangés dans l'ordre d'exploration,\n 'predecesseurs', liste des sommets prédécesseur de chaque sommet rangés dans l'ordre d'exploration,\n \"\"\"\n assert type(Graphe) == list, \"Graphe doit être de type liste\"\n assert type(s_debut) == int, \" s_debut doit être un entier \"\n assert s_debut in [i for i in range(len(Graphe))], \"s_debut doit être dans la plage d'indice de Graphe\"\n\n#Algo: Initialisation\n infini=float(\"inf\") # définition d'une valeur infinie\n predecesseurs = [-1 for sommet in range(len(Graphe))] # initialisation des prédecesseurs à non parcouru (-1)\n predecesseurs[s_debut] = 0 # sauf le sommet de départ qui est le prédécesseur de lui-même\n poids = [infini for sommet in range(len(Graphe))] # initialisation des poids à l'infini\n poids[s_debut] = 0 # sauf le sommet de départ de poids nul\n E_sommets = [i for i in range(len(Graphe))] # initialisation de l'ensemble des sommets du graphe\n E_calcules = [] # création de la liste des calculés, vide au départ\n#---------->fin d'initialisation\n#Algo: boucle principale\n while E_sommets: # Tant que tous les sommets ne sont pas définitivement calculés:\n\n # Algo: recherche d'un sommet de distance minimale\n poids_local = infini # initialisation du poids en cours de calcul à une valeur infinie\n s_mini = -1 # initialisation du sommet de poids minimal à 'non défini'\n for s in E_sommets: # Pour chaque sommet non définitivement calculés:\n if poids[s] < poids_local: # Si le poids du sommet actuel est inférieur au poids local:\n poids_local = poids[s] # le poids local est remplacé par la valeur (inférieure) du sommet actuel\n s_mini = s # le sommet de poids minimal est le sommet actuel\n\n #----------> Algo: fin de recherche d'un sommet de distance minimale\n\n E_sommets.remove(s_mini) # retrait du dernier sommet calculé à l'ensemble des sommets non définitivement calculés\n E_calcules.append(s_mini) # ajout du dernier sommet calculé à la liste des sommets définitivement calculés\n for s_voisin in E_sommets: # Pour chaque sommet voisin du dernier sommet calculé :\n\n #Algo: mise à jour poids et prédécesseur du plus proche voisin\n if poids[s_voisin] > poids[s_mini] + Graphe[s_mini][s_voisin] and Graphe[s_mini][s_voisin] !=0: # si le chemin est plus court et il y a existance d'un arc:\n poids[s_voisin] = poids[s_mini] + Graphe[s_mini][s_voisin] # mise à jour du poids du plus proche voisin\n predecesseurs[s_voisin] = s_mini # mise à jour du prédécesseur du plus proche voisin\n #----------> fin de mise à jour du poids et du prédécesseur du plus proche voisin\n#---------->fin de boucle principale\n\n return E_calcules, poids, predecesseurs\n\ndef matrice(i,j): # fonction qui génère une liste de 'i' liste de 'j' éléments \n # avec des valeurs entières aléatoires entre 0 et 20\n return [[randint(0,20) for q in range(0,j)] for p in range(0,i)]\n\nfor n_elt in range(6,20,1): # test de durée d'éxécution de la fonction 'dijkstra' pour des graphes de 6 à 20 sommets\n M = matrice(n_elt, n_elt)\n %timeit dijkstra(M,0)"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Constatation et interrogation:\n",
"\n",
"En doublant le nombre $n$ de sommets du graphe, on constate approximativement un doublement du temps d'éxécution $T$ de cette implémentation de l'algorithme de Dijkstra. Pour les étudiantes ayant fait l'annexe optionnelle sur la complexité théorique : ceci n'est pas en accord avec le calcul théorique qui y est fait. Cherchez l'erreur (?)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 100 graphes de 6 sommets pour une durée de 0.015600100000000339 secondes.\n",
" 100 graphes de 7 sommets pour une durée de 0.015600100000000339 secondes.\n",
" 100 graphes de 8 sommets pour une durée de 0.031200200000000677 secondes.\n",
" 100 graphes de 9 sommets pour une durée de 0.046800300000001016 secondes.\n",
" 100 graphes de 10 sommets pour une durée de 0.031200200000000677 secondes.\n",
" 100 graphes de 11 sommets pour une durée de 0.031200200000000677 secondes.\n",
" 100 graphes de 12 sommets pour une durée de 0.046800300000001016 secondes.\n",
" 100 graphes de 13 sommets pour une durée de 0.062400400000001355 secondes.\n",
" 100 graphes de 14 sommets pour une durée de 0.046800300000001016 secondes.\n",
" 100 graphes de 15 sommets pour une durée de 0.062400400000001355 secondes.\n",
" 100 graphes de 16 sommets pour une durée de 0.0780005000000017 secondes.\n",
" 100 graphes de 17 sommets pour une durée de 0.09360060000000203 secondes.\n",
" 100 graphes de 18 sommets pour une durée de 0.09360060000000203 secondes.\n",
" 100 graphes de 19 sommets pour une durée de 0.10920070000000237 secondes.\n"
]
}
],
"source": [
"def matrice(i,j):\n",
" return [[randint(0,20) for q in range(0,j)] for p in range(0,i)]\n",
"\n",
"#import timeit\n",
"import time\n",
"for n_elt in range(6,20,1):\n",
" t1 = time.process_time()\n",
" for i in range(100):\n",
" M = matrice(n_elt, n_elt)\n",
" dijkstra(M, 0)\n",
" t2 = time.process_time()\n",
" print(\" 100 graphes de \", n_elt,\" sommets pour une durée de \", t2-t1, \" secondes.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}