{ "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 d’un 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 d’un 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 }