Plusieurs modes de représentation peuvent être implémentés pour stocker des graphes : matrices d’adjacence (ou sommet-sommet), listes des voisins, des successeurs ou des prédécesseurs. Lors de cette séance nous allons écrire les classes réalisant ces implémentations.
Structure de graphe basée sur une liste d’adjacence
-
Écrire le code de la méthode
__init__de la classeSommetdont la spécification est :1 2 3 4def __init__(self: Sommet, val: str) -> None: """ Initialisation d'un sommet. """Remarque : La classe
Sommetpossède deux attributs :valreprésente la valeur du sommet ou son étiquette. Cet attribut est de type chaîne de caractères (str) ;adjreprésente la liste des sommets adjacents au sommet, instance de la classe. Cet attribut référence une liste de sommets ; lors de l’initialisation d’un sommet il doit référencer une liste vide.
Réponse
|
|
-
Ajouter au code de la classe
Sommetla re-définition de la méthode__repr__donnée ci-dessous :1 2 3 4 5 6 7 8def __repr__(self: Sommet) -> str: rep = str(self.val) + " : [" for i, sommet in enumerate(self.adj): rep += str(sommet.val) if i < len(self.adj) - 1: rep += ", " rep += "]" return repCette méthode permet de représenter un sommet sous la forme d’une chaîne de caractères.
-
Tester la définition de la classe
Sommeten ajoutant les lignes de code suivantes au fichier :1 2 3 4 5 6 7 8if __name__ == "__main__": s1 = Sommet("a") s2 = Sommet("b") s3 = Sommet("c") s1.adj.append(s2) s1.adj.append(s3) print(s1) print(s2) -
Écrire le code de la méthode
__init__de la classeGraphedont la spécification est :1 2 3 4 5 6 7 8 9def __init__(self: Graphe, valeurs: str = "") -> None: """ La liste des sommets peut être passée dans une chaîne de caractères. Chaque sommet doit alors être séparé du précédent par une virgule. Hypothèse : chaque sommet n'est présent qu'une seule fois dans valeurs. """Remarque : La classe
Sommetpossède un seul attribut,sommets. Ce dernier référence une liste d’objets de typeSommet. Cette liste est initialement :-
Soit vide,
-
Soit constituée des sommets passés en argument lors de l’initialisation d’un objet de type
Graphe.
-
Réponse
|
|
-
Ajouter au code de la classe
Graphela re-définition de la méthode__repr__donnée ci-dessous :1 2 3 4 5 6 7 8 9 10 11 12def __repr__(self: Graphe) -> str: """ Représentation du graphe sous forme d'une chaîne de caractères. """ rep = "{" for i, sommet in enumerate(self.sommets): rep += repr(sommet) if i < len(self.sommets) - 1: # Ajout de la virgule sauf dernier tour rep += ', ' rep += "}" return repCette méthode permet de représenter un graphe sous la forme d’une chaîne de caractères.
-
Tester la définition de la classe
Grapheà l’aide du code suivant, sous les lignes de code de la question 3 :1 2g1 = Graphe("a,b,c,d") print(g1) -
Écrire le code de la méthode
existe_sommetdont la spécification est :1 2 3 4def existe_sommet(self: Graphe, s: str) -> bool: """ Vérifie que le sommet s existe bien dans le graphe. """
Réponse
|
|
-
Tester le code précédent en ajoutant les instructions suivantes, à la fin du fichier :
1 2print(f"Sommet g présent dans le graphe : {g1.existe_sommet('g')}") print(f"Sommet a présent dans le graphe : {g1.existe_sommet('a')}") -
Écrire le code de la méthode
ajout_sommetdont la spécification est :1 2 3 4 5 6 7def ajout_sommet(self: Graphe, val: str) -> None: """ Ajout du sommet de valeur val au graphe. Si le sommet est déjà présent dans le graphe une exception est levée. """
Réponse
|
|
-
Tester le code précédent en ajoutant les instructions suivantes, à la fin du fichier :
1 2g1.ajout_sommet("e") print(g1) -
Écrire le code de la méthode
recuperation_sommetdont la spécification est :1 2 3 4 5 6def recuperation_sommet(self: Graphe, s: str) -> Sommet: """ Récupère l'objet de type sommet, présent dans la liste sommets, dont la valeur/étiquette est s. Lève une exception si le sommet n'existe pas. """
Remarque : Cette méthode simplifie l’écriture des méthodes suivantes.
Réponse
|
|
-
Écrire le code de la fonction
existe_aretedont la spécification est :1 2 3 4 5 6 7def existe_arête(self, s1: str, s2: str) -> bool: """ Détermine si l'arête {s1, s2} existe dans le graphe. Ne vérifie pas l'existence de l'arête {s2, s1}. Lève une exception si l'un des sommets n'existe pas. """
Réponse
|
|
-
Écrire le code de la fonction
ajout_aretedont la spécification est :1 2 3 4 5 6 7 8def ajout_arete(self: Graphe, s1: str, s2: str) -> None: """ Ajoute l'arête (ou l'arc) {s1, s2} au graphe. Si les sommets n'existent pas, on lève une exception. Si l'arête existe déjà, on lève une exception. Ne crée pas l'arête {s2, s1}. """
Réponse
|
|
-
Tester le code précédent en ajoutant les instructions suivantes, à la fin du fichier :
1 2 3 4 5 6 7g1.ajout_arete("a", "b") g1.ajout_arete("b", "a") g1.ajout_arete("a", "e") # g1.ajout_arete("a", "b") g1.ajout_arete("c", "e") g1.ajout_arete("e", "c") print(g1) -
Écrire le code de la fonction
est_non_orientedont la spécification est :1 2 3 4def est_non_oriente(self: Graphe) -> bool: """ Détermine si le graphe est non orienté. """
Réponse
|
|
-
Tester le code précédent en ajoutant les instructions suivantes, à la fin du fichier :
1 2 3print(f"Le graphe est non orienté : {g1.est_non_oriente()}") g1.ajout_arete("e", "a") print(f"Le graphe est non orienté : {g1.est_non_oriente()}") -
On souhaite maintenant écrire le code de la fonction
construction_matricedont la spécification est :1 2 3 4def construction_matrice(self: Graphe) -> list[list[int]]: """ Construction de la matrice sommet - sommet du graphe. """Compléter le code suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23def construction_matrice(self: Graphe) -> list[list[int]]: """ Construction de la matrice sommet - sommet du graphe. """ val_sommets_ordonnees = sorted([sommet.val for sommet in self.sommets]) matrice = ..... # Initialisation de la matrice for nom_sommet in val_sommets_ordonnees: # Récupération de l'objet de type sommet associé au nom sommet = ..... # Récupération des noms des sommets adjacents nom_sommets_adjacents = [ sommet_adj.val for sommet_adj in sommet.adj] ligne_matrice = ..... # Initialisation de la ligne de la matrice for i in range(len(val_sommets_ordonnees)): if val_sommets_ordonnees[i] in nom_sommets_adjacents: ...... else: ...... ..... # Ajout de la ligne à la matrice return matrice
Réponse
|
|
-
Tester le code précédent en ajoutant les instructions suivantes, à la fin du fichier :
1print(f"Matrice : {g1.construction_matrice()}") -
Écrire le code de la méthode
representation_matricedont la spécification est :1 2 3 4 5def representation_matrice(self: Graphe) -> str: """ Retourne une chaîne de caractères qui permet un affichage classique de la matrice (lignes x colonnes). """Tester le code.
Réponse
|
|
Extensions possibles
Il est possible de compléter la classe en définissant les méthodes suivantes :
-
taille, de spécification :1 2 3 4def taille(self: Graphe) -> int: """ Retourne le nombre de sommets dans le graphe. """ -
rend_non_oriente, de spécification :1 2 3 4 5 6def rend_non_oriente(self: Graphe) -> None: """ Assure que pour toute arête {s1, s2} il existe une arête {s2, s1}. Si ce n'est pas le cas, cette arête est créée. """ -
suppression_arete, de spécification :1 2 3 4 5def suppression_arete(self: Graphe, s1: str, s2: str) -> None: """ Supprime l'arête {s1, s2} si elle existe, lève une exception dans le cas contraire. """ -
suppression_sommet, de spécification :1 2 3 4 5 6 7 8def suppression_sommet(self: Graphe, s: str) -> None: """ Supprime le sommet s s'il existe, lève une exception dans le cas contraire. S'assure avant la suppression du sommet que toute arrête dans laquelle il intervient est supprimée. """