You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import random as rd
# G=nx.Graph()
# G.add_edges_from([(1,2),(1,5),(2,3),(2,5),(3,4),(4,5),(4,6),(5,0)])
# nx.draw(G,with_labels=True)
# plt.show()
#############################
G=nx.Graph()
G.add_edges_from([(1,2),(1,5),(2,3),(2,5),(3,4),(4,5),(4,6),(5,0)])
nx.draw(G,with_labels=True)
plt.show()
#############################
H=nx.Graph()
H.add_nodes_from([1,2,3,4,5,6,7,8,9,10,11])
H.add_edges_from([(1,2),(1,5),(2,3),(2,5),(4,6),(5,0),(8,11),(9,8),(10,8)])
nx.draw(H,with_labels=True)
plt.show()
#############################
#######################
ArbreBin=nx.Graph()
ArbreBin.add_edges_from([(1,2),(1,5),(3,4),(4,5),(4,6),(5,0)])
# dessin ́e comme ceci
nx.draw(ArbreBin,with_labels=True)
plt.show()
# ou comme cela
# dico_pos_arbre = {1:(0,0),2:(-1,-1),5:(2,-1),0:(1,-2),4:(3,-2),3:(2,-3), 6:(4,-3)}
# nx.draw(ArbreBin,dico_pos_arbre,with_labels=True)
plt.show()
######################
####################################
## primitives des files
####################################
##enfiler
def ajouter_file(F,v):
F.append(v)
return
##d ́efiler
def enlever_tete_file(F):
del F[0]
return;
##regarder la valeur en tˆete de file
def valeur_tete_file(F):
return F[0]
##tester si la file est vide
def est_file_vide(F):
return len(F)==0
## petit test sur les files :
def test_file():
F=[]
ajouter_file(F,5)
print(F)
ajouter_file(F,3)
print(F)
ajouter_file(F,8)
ajouter_file(F,2)
print(F)
enlever_tete_file(F)
print("on a enlev ́e la tete")
print(F)
if est_file_vide(F) : print("PB : la file est vide")
else : print("en tete de file : " + str(valeur_tete_file(F)))
enlever_tete_file(F)
enlever_tete_file(F)
enlever_tete_file(F)
if est_file_vide(F) : print("OK : la file est vide")
else : print("PB : la file nest pas vide")
return
####################################
## primitives des piles
####################################
##empiler
def ajouter_pile(P,v):
P.append(v)
return
##d ́epiler
def enlever_sommet_pile(P):
del P[len(P)-1] # ou alors P.pop()
return;
##regarder
def valeur_sommet_pile(P):
return P[len(P)-1]
##tester
def est_pile_vide(P):
return len(P)==0
## petit test sur les piles :
def test_pile():
P=[]
ajouter_pile(P,5)
ajouter_pile(P,3)
ajouter_pile(P,8)
ajouter_pile(P,2)
print(P)
enlever_sommet_pile(P)
print("on a enlev ́e le sommet")
print(P)
if est_pile_vide(P) : print("la pile est vide")
else : print("au sommet : " + str(valeur_sommet_pile(P)))
enlever_sommet_pile(P)
enlever_sommet_pile(P)
enlever_sommet_pile(P)
if est_pile_vide(P) : print("OK : la pile est vide")
else : print("PB : la pile nest pas vide")
return
########### parcours en largeur ##############
def parcours_largeur(G,s):
visites = [] # sommets vus (compl`etement ou juste dans la fronti`ere)
F = [] # la fronti`ere
visites.append(s)
ajouter_file(F,s)
while(not est_file_vide(F)):
v = valeur_tete_file(F)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in G.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_file(F,u)
trouve = True # voisin de v non deja visite trouv ́e
break
if not trouve :
enlever_tete_file(F)
return visites
print(parcours_largeur(G,1))
# Une autre solution :
def parcours_largeur(H,s):
visites=[]
F=[]
visites.append(s)
ajouter_file(F,s)
while not est_file_vide(F):
v = valeur_tete_file(F)
L = [t for t in H.neighbors(v) if t not in visites]
if len(L) != 0:
visites.append(L[0])
ajouter_file(F,L[0])
else:
enlever_tete_file(F)
return visites
print(parcours_largeur(G,1))
########### parcours en profondeur ##############
def parcours_profondeur(G,s):
visites = []
P = [] # la fronti`ere
visites.append(s)
ajouter_pile(P,s)
while(not est_pile_vide(P)):
v = valeur_sommet_pile(P)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in G.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_pile(P,u)
trouve = True # voisin de v non deja visite trouv ́e
break
if not trouve :
enlever_sommet_pile(P)
return visites
print(parcours_profondeur(G,1))
# Une autre solution :
def parcours_profondeur(H,s):
visites=[]
P=[]
visites.append(s)
ajouter_pile(P,s)
while not est_pile_vide(P):
v = valeur_sommet_pile(P)
L = [t for t in H.neighbors(v) if t not in visites]
6
if len(L) != 0:
visites.append(L[0])
ajouter_pile(P,L[0])
else:
enlever_sommet_pile(P)
return visites
print(parcours_profondeur(G,1))
# ! TP 4
# ? Exercice 1
# Ecrire une fonction est_connexe(G) qui determine si un graph G est connexe, en utlisant un des deux algorithmes de parcours vus en semaine 3 (voir solution sur moodle)
def est_connexe(G):
return len(parcours_largeur(G,1)) == len(G.nodes())
# Ecrire une fonction composantes connexes(G) qui calcule et retourne la liste des composantes connexes d'un graph G
def composantes_connexes(G):
visites = []
composantes = []
for s in G.nodes():
if s not in visites:
composantes.append(parcours_largeur(G,s))
visites.extend(parcours_largeur(G,s))
return composantes
# Tester les deux fonctions précédentes avec les graphes G et H
print("=========================== Exo 1 ===========================")
print(est_connexe(G))
print(est_connexe(H))
print(composantes_connexes(G))
print(composantes_connexes(H))
# ? Exercice 2
# Ecrire une fonction distances(G,s) qui, pour un graphe G connexe et un sommet s donn ́es, calcule la distance (en nombre darˆetes) entre s et chaque sommet de G. Cette fonction retourne un dictionnaire associant une distance `a chaque sommet. Pour cela, comme vu en cours, on modifie le parcours en largeur.
def distances(G,s):
visites = []
F = []
distances = {}
visites.append(s)
ajouter_file(F,s)
distances[s] = 0
while(not est_file_vide(F)):
v = valeur_tete_file(F)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in G.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_file(F,u)
distances[u] = distances[v] + 1
trouve = True # voisin de v non deja visite trouv ́e
break
if not trouve :
enlever_tete_file(F)
return distances
print("=========================== Exo 2 ===========================")
print(distances(G,1))
print(distances(H,1))
# (optionnel) ́Ecrire une fonction affiche plus courts chemins a partir de(G,s) qui,
# pour un graphe G connexe et un sommet s donn ́es, affiche pour chaque sommet du
# graphe un plus court chemin `a partir de s.
# Cette fonction appellera la fonction plus courts chemins(G,s) qui calcule pour chaque
# sommet son pr ́ed ́ecesseur (le sommet par lequel il est d ́ecouvert lors du parcours `a par-
# tir de s).
# Exemple : affiche plus courts chemins a partir de(G,1) (avec G de lexercice
# pr ́ec ́edent) donnera :
# 1
# 2 <- 1
# 5 <- 1
# 3 <- 2 <- 1
# 4 <- 5 <- 1
# 6 <- 4 <- 5 <- 1
# 0 <- 5 <- 1
def affiche_plus_courts_chemins_a_partir_de(G,s):
distance = distances(G,s)
for i in range(len(G.nodes())):
chemin = str(i)
j = i
while j != s:
j = distance[j]
chemin = str(j) + " <- " + chemin
print(chemin)
affiche_plus_courts_chemins_a_partir_de(G,1)
# ? Exercice 3
# Un arbre binaire est un arbre qui poss`ede une unique racine (un sommet particulier) et
# o`u chaque sommet a au plus deux sommets voisins sp ́eciaux, appel ́es ses fils. Sil a deux fils,
# lun est le fils gauche et lautre est le fils droit. Un sommet est appel ́e le p`ere de son fils. Ainsi,
# chaque sommet de larbre binaire a au maximum trois voisins (deux fils et un p`ere). La racine
# na pas de p`ere, et les feuilles sont les sommets sans fils.
# Dans cet exercice, on sint ́eresse au parcours en profondeur dun arbre binaire T `a partir de
# sa racine r. Un certain traitement doit ˆetre effectu ́e une fois et une seule sur chaque sommet
# au cours de ce parcours. Ici, le traitement consiste simplement `a afficher le nom du sommet.
# Vous pourrez tester vos programmes sur larbre ArbreBin ci-dessous, dont la racine est le
# sommet 1.
# #######################
# ArbreBin=nx.Graph()
# ArbreBin.add_edges_from([(1,2),(1,5),(3,4),(4,5),(4,6),(5,0)])
# # dessin ́e comme ceci
# nx.draw(ArbreBin,with_labels=True)
# plt.show()
# # ou comme cela
# dico_pos_arbre = {1:(0,0),2:(-1,-1),5:(2,-1),0:(1,-2),4:(3,-2),3:(2,-3), 6:(4,-3)}
# nx.draw(ArbreBin,dico_pos_arbre,with_labels=True)
# plt.show()
# #######################
# Ecrire une fonction qui affiche le nom de chaque sommet au moment o`u il est ajout ́e `a la pile. Ce type de parcours en profondeur dun arbre binaire sappelle un parcours pr ́efixe.
def parcours_prefixe(T,r):
visites = []
P = []
visites.append(r)
ajouter_pile(P,r)
while(not est_pile_vide(P)):
v = valeur_sommet_pile(P)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in T.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_pile(P,u)
trouve = True # voisin de v non deja visite trouv ́e
break
if not trouve :
enlever_sommet_pile(P)
return visites
print("=========================== Exo 3 ===========================")
print(parcours_prefixe(ArbreBin,1))
# Ecrire une fonction qui affiche le nom de chaque sommet au moment o`u il est supprim ́e
# de la pile. Ce type de parcours en profondeur dun arbre binaire sappelle un parcours
# postfixe.
def parcours_postfixe(T,r):
visites = []
P = []
visites.append(r)
ajouter_pile(P,r)
while(not est_pile_vide(P)):
v = valeur_sommet_pile(P)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in T.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_pile(P,u)
trouve = True # voisin de v non deja visite trouv ́e
break
if not trouve :
enlever_sommet_pile(P)
print(v)
return visites
print("=========================== Exo 3 ===========================")
print(parcours_postfixe(ArbreBin,1))
# Ecrire une fonction qui affiche le nom de chaque sommet la premi`ere fois quon le
# rencontre sil na quun fils et la deuxi`eme fois sil en a deux. Ce type de parcours en
# profondeur dun arbre binaire sappelle un parcours infixe.
def parcours_infixe(T,r):
visites = []
P = []
visites.append(r)
ajouter_pile(P,r)
while(not est_pile_vide(P)):
v = valeur_sommet_pile(P)
trouve = False # voisin de v non deja visite pas encore trouv ́e
for u in T.neighbors(v):
if (u not in visites) :
visites.append(u)
ajouter_pile(P,u)
trouve = True # voisin de v non deja visite trouv ́e
break
if len(list(T.neighbors(v))) == 1:
print(v)
if not trouve :
enlever_sommet_pile(P)
if len(list(T.neighbors(v))) == 2:
print(v)
return visites
print("=========================== Exo 3 ===========================")
print(parcours_infixe(ArbreBin,1))