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 classeSommet
dont la spécification est :1 2 3 4
def __init__(self: Sommet, val: str) -> None: """ Initialisation d'un sommet. """
Remarque : La classe
Sommet
possède deux attributs :val
représente la valeur du sommet ou son étiquette. Cet attribut est de type chaîne de caractères (str
) ;adj
repré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
Sommet
la re-définition de la méthode__repr__
donnée ci-dessous :1 2 3 4 5 6 7 8
def __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 rep
Cette 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
Sommet
en ajoutant les lignes de code suivantes au fichier :1 2 3 4 5 6 7 8
if __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 classeGraphe
dont la spécification est :1 2 3 4 5 6 7 8 9
def __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
Sommet
possè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
Graphe
la re-définition de la méthode__repr__
donnée ci-dessous :1 2 3 4 5 6 7 8 9 10 11 12
def __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 rep
Cette 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 2
g1 = Graphe("a,b,c,d") print(g1)
-
Écrire le code de la méthode
existe_sommet
dont la spécification est :1 2 3 4
def 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 2
print(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_sommet
dont la spécification est :1 2 3 4 5 6 7
def 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 2
g1.ajout_sommet("e") print(g1)
-
Écrire le code de la méthode
recuperation_sommet
dont la spécification est :1 2 3 4 5 6
def 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_arete
dont la spécification est :1 2 3 4 5 6 7
def 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_arete
dont la spécification est :1 2 3 4 5 6 7 8
def 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 7
g1.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_oriente
dont la spécification est :1 2 3 4
def 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 3
print(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_matrice
dont la spécification est :1 2 3 4
def 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 23
def 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 :
1
print(f"Matrice : {g1.construction_matrice()}")
-
Écrire le code de la méthode
representation_matrice
dont la spécification est :1 2 3 4 5
def 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 4
def taille(self: Graphe) -> int: """ Retourne le nombre de sommets dans le graphe. """
-
rend_non_oriente
, de spécification :1 2 3 4 5 6
def 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 5
def 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 8
def 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. """