diff --git a/BDD/tp/BDDs2/tp1/tp11-12.sql b/BDD/tp/BDDs2/tp1/tp11-12.sql new file mode 100644 index 0000000..0e3d596 --- /dev/null +++ b/BDD/tp/BDDs2/tp1/tp11-12.sql @@ -0,0 +1,197 @@ +-- 1. Écrire une fonction nb_femmes_v1 (sans utiliser de curseur) qui retourne le nombre d’athlètes féminines concourant pour le pays dont le nom est passé en paramètre. +CREATE OR REPLACE FUNCTION nb_femmes_v1(nom_pays pays.nom%TYPE) +RETURNS INT AS $$ +BEGIN + return ( + SELECT COUNT(*) + FROM athlete a, pays p + WHERE p.nom = nom_pays AND p.code = a.pays AND a.sexe = 'F' + ); +END; +$$ LANGUAGE plpgsql; + +-- 2. Même question, mais la fonction nb_femmes_v2 devra utiliser un curseur. +CREATE OR REPLACE FUNCTION nb_femmes_v2(nom_pays pays.nom%TYPE) +RETURNS INT AS $$ +DECLARE + curs cursor FOR SELECT a.pays, a.paysNaiss + FROM athlete a, pays p + WHERE p.nom = nom_pays AND p.code = a.pays AND sexe = 'F'; + rec athlete.code%TYPE; + n INT := 0; +BEGIN + open curs; + fetch curs into rec; + while found loop + n = n + 1; + fetch curs into rec; + end loop; + close curs; + return n; +END; +$$ LANGUAGE plpgsql; + +-- 3. Vérifier que vos deux fonctions retournent bien le même résultat. Vous pouvez par exemple tester avec la France. +SELECT nb_femmes_v1('France'), nb_femmes_v2('France'); + +-- nb_femmes_v1 | nb_femmes_v2 +-- --------------+-------------- +-- 172 | 172 +-- (1 ligne) + + +-- 4. Modifier les deux fonctions précédentes pour ne compter que les athlètes féminines qui concourent pour un pays différent de leur pays de naissance. +CREATE OR REPLACE FUNCTION nb_femmes_v1(nom_pays pays.nom%TYPE) +RETURNS INT AS $$ +BEGIN + return ( + SELECT COUNT(*) + FROM athlete a, pays p + WHERE p.nom = nom_pays AND p.code = a.pays AND a.sexe = 'F' AND a.pays != a.paysNaiss + ); +END; +$$ LANGUAGE plpgsql; + +-- nbFemme2 + +CREATE OR REPLACE FUNCTION nb_femmes_v2(nom_pays pays.nom%TYPE) +RETURNS INT AS $$ +DECLARE + curs cursor FOR SELECT a.pays, a.paysNaiss + FROM athlete a, pays p + WHERE p.nom = nom_pays AND p.code = a.pays AND sexe = 'F'; + pays athlete.pays%TYPE; + paysNaiss athlete.paysNaiss%TYPE; + n INT := 0; +BEGIN + open curs; + fetch curs into pays, paysNaiss; + while found loop + if pays != paysNaiss then + n = n + 1; + end if; + fetch curs into pays, paysNaiss; + end loop; + close curs; + return n; +END; +$$ LANGUAGE plpgsql; + +-- 5. Vérifier que vos deux fonctions retournent bien le même résultat. +SELECT nb_femmes_v1('France'), nb_femmes_v2('France'); + +-- nb_femmes_v1 | nb_femmes_v2 +-- --------------+-------------- +-- 11 | 11 +-- (1 ligne) + + +-- 6. Ecrire un bloc PL/pgSQL anonyme permettant de mettre à jour le pays de naissance des athlètes pour lequel l’information n’est pas connue, en indiquant comme pays celui pour lequel ils concourent. Afficher un message à chaque modification. +DO $$ +DECLARE + curs cursor FOR SELECT pays + FROM athlete + WHERE paysNaiss IS NULL + FOR UPDATE; + athlete_pays athlete.pays%TYPE; +BEGIN + open curs; + fetch curs into athlete_pays; + while found loop + UPDATE athlete SET paysNaiss = athlete_pays WHERE CURRENT OF curs; + raise notice 'update'; + fetch curs into athlete_pays; + end loop; + close curs; +END; +$$ LANGUAGE plpgsql; + +-- 7. Pour pouvoir gérer l’affectation des chambres dans le village olympique, l’organisation a besoin de connaître les dates de présence de chaque athlète. Créer une table Present(#athlete, dateArrivee, dateDepart). +DROP TABLE IF EXISTS present; +CREATE TABLE IF NOT EXISTS present ( + athlete CHAR(6) PRIMARY KEY REFERENCES athlete(code), + dateArrivee DATE NOT NULL, + dateDepart DATE NOT NULL +); + +-- 8. Ecrire un bloc PL/pgSQL anonyme permettant de remplir la table Present +INSERT INTO present +SELECT + a.code, + (MIN(e.dateE) - 14) dateArrivee, + LEAST( + '2021-08-11', + MAX(e.dateE) + 1 + ( + CASE WHEN COUNT(r.medaille) >= 3 THEN 5 + WHEN COUNT(r.medaille) >= 1 THEN 3 + ELSE 0 + END + ) + ) dateDepart +FROM athlete a, pratiquer p, epreuve e, resultat r +WHERE p.athlete = a.code AND e.discipl = p.discipl AND r.athlete = a.code +GROUP BY a.code; + +-- INSERT 0 11644 + + +-- 9. Ecrire une fonction nbAth_jour qui prend en paramètre le nom d’un pays, un sexe et une date et retourne le nombre d’athlètes du pays et du sexe donnés présents au village olympique à la date donnée. +CREATE OR REPLACE FUNCTION nbAth_jour(nom_pays pays.nom%TYPE, sexe_athlete athlete.sexe%TYPE, date_presence DATE) +RETURNS INT AS $$ +BEGIN + return ( + SELECT COUNT(*) FROM present p, athlete a + WHERE a.code = p.athlete AND a.pays = (SELECT code FROM pays WHERE nom = nom_pays) + AND sexe = sexe_athlete + AND date_presence BETWEEN dateArrivee AND dateDepart + ); +END; +$$ LANGUAGE plpgsql; + +-- 10. Utiliser la fonction nbAth_jour pour savoir combien de chambres sont nécessaires pour la délégation française le 6 août 2021, sachant que les athlètes sont deux par chambre et qu’il n’y a pas de chambre mixte. +SELECT CEIL(nbAth_jour('France', 'F', '2021-08-06')::FLOAT / 2) + CEIL(nbAth_jour('France', 'M', '2021-08-06')::FLOAT / 2); + +-- ?column? +-- ---------- +-- 129 ou 56 ??? +-- (1 ligne) + + + +-- 11. Un virus circule. Ecrire une fonction confiner qui prend un paramètre (une date) et qui permet de repousser d’une semaine, si besoin, le départ des athlètes qui étaient présents au village olympique à la date donnée. La fonction devra retourner le nombre d’athlètes impactés +DROP FUNCTION confiner; +CREATE OR REPLACE FUNCTION confiner(date_confinement DATE) +RETURNS INT AS $$ +DECLARE + curs cursor FOR SELECT dateDepart + FROM present + WHERE date_confinement BETWEEN dateArrivee AND dateDepart + FOR UPDATE; + date_depart present.dateDepart%TYPE; + nb INT := 0; +BEGIN + open curs; + fetch curs into date_depart; + while found loop + -- UPDATE present SET dateDepart = GREATEST(date_confinement + 7, dateDepart) WHERE CURRENT OF curs; + if (date_confinement + 7) > date_depart then + UPDATE present SET dateDepart = (date_confinement + 7) WHERE CURRENT OF curs; + nb = nb + 1; + end if; + fetch curs into date_depart; + end loop; + close curs; + return nb; +END; +$$ LANGUAGE plpgsql; + +SELECT confiner('2021-07-27'); + +-- confiner +-- ---------- +-- 2869 +-- (1 ligne) + + +-- 12. Executer le script jo.sql pour annuler les modifications réalisées pendant ce tp. +\i jo.sql diff --git a/Maths/tp/Graphs/1_tp/TP1-IntroGraphes.pdf b/Maths/tp/Graphs/1_tp/TP1-IntroGraphes.pdf new file mode 100644 index 0000000..9b05196 Binary files /dev/null and b/Maths/tp/Graphs/1_tp/TP1-IntroGraphes.pdf differ diff --git a/Maths/tp/Graphs/1_tp/tp1.py b/Maths/tp/Graphs/1_tp/tp1.py new file mode 100644 index 0000000..f01da1f --- /dev/null +++ b/Maths/tp/Graphs/1_tp/tp1.py @@ -0,0 +1,190 @@ +import networkx as nx #pour la gestion des graphes +import matplotlib.pyplot as plt #pour l’affichage +#(on les renomme pour raccourcir le code) + +# Exo 1 + +G1 = nx.Graph() #cr ́ee un graphe non-orient ́e vide +G1.add_edge(0,1) #ajoute une arˆete entre les sommets 0 et 1 +G1.add_edges_from([(3,0),(3,4)]) #ajoute les arˆetes d’une liste donn ́ee +nx.add_path(G1,[1,2,3]) #ajoute les arˆetes du chemin 1-2-3 + +G1.add_node(6) #ajoute un sommet +G1.add_node("toto") +G1.add_edge("toto",6) + + +G1.remove_node(6) #Supprimez un sommet s de votre choix, puis r ́e-affichez le graphe. +print(G1.nodes) +print(G1.edges) + +nx.draw(G1, with_labels=True, pos=nx.circular_layout(G1), node_color='r', edge_color='b') +# ou +# dico_positions = {0:(0,0),1:(1,0),2:(0,1),3:(1,1),4:(0,-1),6:(-1,-1),"toto":(0,-1)} +# nx.draw(G1, with_labels=True, pos=dico_positions) + +# nx.draw(G1,with_labels=True) #on pr ́epare le dessin du graphe + +plt.show() #on affiche le dessin + +# Exo 2 + +H = nx.Graph() #cr ́ee un graphe non-orient ́e vide + +H.add_edges_from([(1,2),(2,3),(3,4),(4,5),(5,2),(4,6),(1,5)]) #ajoute les arˆetes d’une liste donn ́ee +# nx.add_path(G1,[1,2,3,4,5,2]) #ajoute les arˆetes du chemin 1-2-3 + +nx.draw(H, with_labels=True, pos=nx.circular_layout(H), node_color='r', edge_color='b') + +plt.show() #on affiche le dessin + +# 2. Ecrire le code qui permet d’afficher les salles directement connect ́ees `a la salle 5, en utilisant la m ́ethode H.edges qui renvoie la liste des arˆetes de H. (Attention : une arˆete entre i et j peut ˆetre stock ́ee sous forme (i,j) ou (j,i). + +def getArete(G, node): + aretes = G.edges + aretes = [arete for arete in aretes if node in arete] + return aretes + +print(getArete(H, 5)) + +H.add_edge(3, 5) + +print(getArete(H, 5)) + +# Exo 3 + +def nombre_sommets(G): + return len(G.nodes) + +def nombre_aretes(G): + return len(G.edges) + +def existe_arete(G, i, j): # renvoie si le couple i,j existe dans les aretes du graphe G + return (i, j) in G.edges or (j, i) in G.edges + +def voisins(G,s): #renvoie la liste des voisins du sommet s grace à la methode existe_arete + return [i for i in G.nodes if existe_arete(G, s, i)] + +def degre(G,s): # renvoie le degre (nombre de voisins) du sommet s + return len(voisins(G, s)) + +def degre_max(G): # renvoie le degre max du graphe G (celui qui à le plus de voisins) + return max([degre(G, s) for s in G.nodes]) + +def sommets_de_degre_max(G): # renvoie la liste des sommets de degre max du graphe G + return [s for s in G.nodes if degre(G, s) == degre_max(G)] + + +print(nombre_sommets(H)) +print(nombre_aretes(H)) +print(existe_arete(H, 1, 2)) +print(voisins(H, 1)) +print(degre(H, 1)) +print(degre_max(H)) +print(sommets_de_degre_max(H)) + + +# Exo 4 + +GO = nx.DiGraph() #on cr ́ee un graphe orient ́e +GO.add_edge(0,1) +GO.add_edge(1,0) +GO.add_edge(1,2) +GO.add_edge(3,2) +GO.add_edge(3,1) +nx.draw(GO,with_labels=True) #on pr ́epare le dessin du graphe +plt.show() #on affiche le dessin + + +def existe_arc(G, i, j): # renvoie si le couple i,j existe dans les aretes du graphe G + return (i, j) in G.edges + +def voisins_entrants(G,s): #renvoie la liste des voisins du sommet s grace à la methode existe_arete + return [i for i in G.nodes if existe_arc(G, i, s)] + +def degre_entrant(G,s): # renvoie le degre (nombre de voisins) du sommet s + return len(voisins_entrants(G, s)) + +def est_source(G,s): #renvoie si le sommet s est une source + return degre_entrant(G, s) == 0 + + +print(existe_arc(GO, 1, 2)) +print(voisins_entrants(GO, 1)) +print(degre_entrant(GO, 1)) +print(est_source(GO, 1)) + + +# Exo 6 + +F2 = nx.Graph() #cr ́ee un graphe non-orient ́e vide +F2.add_node("0-0") +F2.add_node("0-1") +F2.add_node("0-2") +F2.add_node("0-3") +F2.add_node("0-4") +F2.add_node("0-5") +F2.add_node("1-0") +F2.add_node("1-1") +F2.add_node("1-2") +F2.add_node("1-3") +F2.add_node("1-4") +F2.add_node("1-5") +F2.add_node("2-0") +F2.add_node("2-1") +F2.add_node("2-2") +F2.add_node("2-3") +F2.add_node("2-4") +F2.add_node("2-5") +F2.add_node("3-0") +F2.add_node("3-1") +F2.add_node("3-2") +F2.add_node("3-3") +F2.add_node("3-4") +F2.add_node("3-5") +F2.add_node("4-0") +F2.add_node("4-1") +F2.add_node("4-2") +F2.add_node("4-3") +F2.add_node("4-4") +F2.add_node("4-5") + +nx.add_path(F2,["1-0", "0-0", "0-1", "1-1", "1-2", "0-2", "0-3", "0-4"]) #ajoute les arˆetes du chemin +nx.add_path(F2,["1-2", "1-3", "1-4"]) +nx.add_path(F2,["1-3", "2-3", "2-2", "2-1", "3-1", "3-0", "2-0"]) +nx.add_path(F2,["2-2", "3-2", "3-3"]) +nx.add_path(F2,["3-2", "4-2", "4-1", "4-0"]) +nx.add_path(F2,["4-2", "4-3", "4-4", "3-4", "2-4", "2-5", "1-5", "0-5"]) +nx.add_path(F2,["2-5", "3-5", "4-5"]) + +# nx.add_path(F2,["1-0", "1-2", "0-4"]) +# nx.add_path(F2,["1-2", "1-3", "1-4"]) +# nx.add_path(F2,["1-3", "2-2", "2-0"]) +# nx.add_path(F2,["2-2", "3-2", "3-3"]) +# nx.add_path(F2,["3-2", "4-2", "4-0"]) +# nx.add_path(F2,["4-2", "2-5", "0-5"]) +# nx.add_path(F2,["2-5", "4-5"]) +# F2.add_edges_from([(3,0),(3,4)]) #ajoute les arˆetes d’une liste donn ́ee + +# dico_positions = {0:(0,0),1:(1,0),2:(0,1),3:(1,1),4:(0,-1),6:(-1,-1),"toto":(0,-1)} + +nx.draw(F2, with_labels=True) + +plt.show() #on affiche le dessin + +# c'est un arbre donc un seu chemin possible + +# Coder une fonction chemin(s) qui trouve un chemin depuis l’entr ́ee "4-0" vers un sommet s donn ́e (on peut r ́ep ́eter des cases). On affichera les cases parcourues lors de l’exploration. Lors de l’exploration du labyrinthe, on pourra se souvenir des sommets d ́ej`a parcourus. Un it ́erateur sur les voisins d’un sommet s est donn ́e par G.neighbors(s) (on obtient la liste des voisins avec list(G.neighbors(s))). + +def chemin(arrivee): + L = [] + L.append(arrivee) + while arrivee != (4,0): + for i in voisins(F2,arrivee): + if(existe_arete(F2,arrivee,i)): + arrivee = i + L.append(arrivee) + L.reverse() + return L + +print(chemin((4,1))) \ No newline at end of file diff --git a/Maths/tp/Graphs/2_tp/TP2-ArbresCouvrants.pdf b/Maths/tp/Graphs/2_tp/TP2-ArbresCouvrants.pdf new file mode 100644 index 0000000..25651fb Binary files /dev/null and b/Maths/tp/Graphs/2_tp/TP2-ArbresCouvrants.pdf differ diff --git a/Maths/tp/Graphs/2_tp/intro.py b/Maths/tp/Graphs/2_tp/intro.py new file mode 100644 index 0000000..ad3b393 --- /dev/null +++ b/Maths/tp/Graphs/2_tp/intro.py @@ -0,0 +1,249 @@ +import networkx as nx +import matplotlib.pyplot as plt + +import random #pour des nombres al ́eatoires + + + +G1 = nx.Graph() +G1.add_edge(0,1,weight=5) +G1.add_edge(0,2,weight=3) +G1.add_edge(0,3,weight=3) +G1.add_edge(0,4,weight=1) +G1.add_edge(1,2,weight=2) +G1.add_edge(2,3,weight=4) +G1.add_edge(3,4,weight=3) +G1.add_edge(3,5,weight=2) +G1.add_edge(4,5,weight=1) +dico_positions = {0:(0,0),1:(2,-1),2:(1.8,-3),3:(-0.3,-2),4:(-2,-1),5:(-2.5,-3)} +nx.draw(G1,dico_positions,with_labels=True) +2 +nx.draw_networkx_edge_labels(G1,dico_positions, +edge_labels=nx.get_edge_attributes(G1,"weight")) +plt.show() + + + +G2 = nx.Graph() +G2.add_edge("A", "B", weight=7) +G2.add_edge("A", "C", weight=8) +G2.add_edge("A", "J", weight=6) +G2.add_edge("B", "E", weight=4) +G2.add_edge("C", "I", weight=9) +G2.add_edge("C", "D", weight=5) +G2.add_edge("D", "E", weight=3) +G2.add_edge("D", "F", weight=5) +G2.add_edge("D", "G", weight=16) +G2.add_edge("E", "J", weight=3) +G2.add_edge("E", "K", weight=2) +G2.add_edge("F", "G", weight=8) +G2.add_edge("F", "H", weight=4) +G2.add_edge("G", "H", weight=12) +G2.add_edge("G", "J", weight=1) +G2.add_edge("G", "L", weight=12) +G2.add_edge("I", "J", weight=6) +G2.add_edge("K", "L", weight=10) +dico_positions2 = {"A":(0,0),"C":(2,0),"D":(4,0),"F":(6,0),"B":(1,-2),"E":(3,-2),"G":(5,-2),"H":(7,-2), "I":(1,-4), "J":(3,-4), "K":(5,-4), "L":(7,-4)} +nx.draw(G2, with_labels=True, pos=dico_positions2) +nx.draw_networkx_edge_labels(G2,dico_positions2, +edge_labels=nx.get_edge_attributes(G2,"weight")) +plt.show() + + + +def aretes_traversantes(G, S): + """ Renvoie la liste des arêtes traversantes de G pour S + Entrées : + G : un graphe + S : une liste de sommets + Sortie : + L : la liste des arêtes traversantes de G pour S + """ + L = [] + for i in S: + for j in G.edges(i): + if j not in S: + L.append(i,j) + return L + +# Impl ́ementer une version simplifi ́ee de l’algorithme de Prim qui ne se soucie pas des +# poids des arˆetes, avec une fonction algo prim simple(G) qui calcule un arbre couvrant +# de G (pas forc ́ement de poids minimal). Pour cela, `a chaque ́etape, l’algorithme prendra +# une arˆete quelconque parmi les arˆetes autoris ́ees et l’ajoutera `a l’arbre calcul ́e jusqu’`a +# pr ́esent. + +# La fonction renverra la liste des arˆetes de l’arbre couvrant. Tester avec les graphes G1 +# ou G2 des Figures 1 et 2, puis ́eventuellement avec des graphes al ́eatoires. +# Conseil : maintenir une liste sommets visites des sommets visit ́es et une liste des +# arˆetes s ́electionn ́ees. `A chaque ́etape il faudra consid ́erer toutes les arˆetes entre les som- +# mets visit ́es et les sommets non-visit ́es grˆace `a aretes traversantes(G,sommets visites). + +def algo_prim_simple(G): + """ Renvoie la liste des arêtes de l'arbre couvrant de G + Entrée : + G : un graphe + Sortie : + L : la liste des arêtes de l'arbre couvrant de G + """ + L = [] + sommets_visites = [] + sommets_non_visites = list(G.nodes()) + sommets_visites.append(sommets_non_visites[0]) + sommets_non_visites.remove(sommets_non_visites[0]) + while len(sommets_visites) != len(G.nodes()): + for i in sommets_visites: + for j in G.edges(i): + if j[1] not in sommets_visites: + L.append(j) + sommets_visites.append(j[1]) + sommets_non_visites.remove(j[1]) + break + return L, sum([G.get_edge_data(i[0],i[1])["weight"] for i in L]) + + +# Impl ́ementer l’algorithme de Prim au complet, par une fonction algo prim(G) qui +# renvoie la liste des arˆetes de l’arbre couvrant de poids minimal de G calcul ́e par l’algo- +# rithme. Tester. +# Algorithme de Prim : +# • Initialiser T avec +# { +# sommets : un sommet de G qu’on choisit +# arˆetes : aucune +# • R ́ep ́eter tant que T ne couvre pas tous les sommets : +# ⋆ Trouver toutes les arˆetes de G qui relient un sommet de T et un +# sommet ext ́erieur `a T +# ⋆ Parmi celles-ci, choisir une arˆete de poids le plus petit possible +# ⋆ Ajouter `a T cette arˆete et le sommet correspondant +# • S’arrˆeter d`es que tous les sommets de G sont dans T +# • Retourner T + +def algo_prim(G): + """ Renvoie la liste des arêtes de l'arbre couvrant de poids minimal de G + Entrée : + G : un graphe + Sortie : + L : la liste des arêtes de l'arbre couvrant de poids minimal de G + """ + L = [] + sommets_visites = [] + sommets_non_visites = list(G.nodes()) + sommets_visites.append(sommets_non_visites[0]) + sommets_non_visites.remove(sommets_non_visites[0]) + while len(sommets_visites) != len(G.nodes()): + arretes_traversantes = [] + for i in sommets_visites: + for j in G.edges(i): + if j[1] not in sommets_visites: + arretes_traversantes.append(j) + arrete_min = arretes_traversantes[0] + for i in arretes_traversantes: + if G.get_edge_data(i[0],i[1])["weight"] < G.get_edge_data(arrete_min[0],arrete_min[1])["weight"]: + arrete_min = i + L.append(arrete_min) + sommets_visites.append(arrete_min[1]) + sommets_non_visites.remove(arrete_min[1]) + # Return L et le poids total + return L, sum([G.get_edge_data(i[0],i[1])["weight"] for i in L]) + +# teste moi les algo precedents +print(algo_prim_simple(G1)) +print(algo_prim(G1)) +print(algo_prim_simple(G2)) +print(algo_prim(G2)) + + +# Exo 2 : Algorithme de Kruskal + +# Impl ́ementer l’algorithme de Kruskal, par une fonction algo kruskal(G) qui renvoie +# la liste des arˆetes de l’arbre couvrant de poids minimal de G calcul ́e par l’algorithme. +# Tester. +# Algorithme de Kruskal : +# • Initialiser T avec +# { +# sommets : tous les sommets de G +# arˆetes : aucune +# • Tant que T n’est pas un arbre couvrant : +# ⋆ Trouver une arˆete de poids minimal qui relie deux sommets de T +# ⋆ Ajouter `a T cette arˆete +# ⋆ Supprimer les arˆetes de T qui forment un cycle +# • S’arrˆeter d`es que T est un arbre couvrant +# • Retourner T + +def algo_kruskal(G): + """ Renvoie la liste des arêtes de l'arbre couvrant de poids minimal de G + Entrée : + G : un graphe + Sortie : + L : la liste des arêtes de l'arbre couvrant de poids minimal de G + """ + L = [] + sommets_visites = [] + sommets_non_visites = list(G.nodes()) + sommets_visites.append(sommets_non_visites[0]) + sommets_non_visites.remove(sommets_non_visites[0]) + while len(sommets_visites) != len(G.nodes()): + arretes_traversantes = [] + for i in sommets_visites: + for j in G.edges(i): + if j[1] not in sommets_visites: + arretes_traversantes.append(j) + arrete_min = arretes_traversantes[0] + for i in arretes_traversantes: + if G.get_edge_data(i[0],i[1])["weight"] < G.get_edge_data(arrete_min[0],arrete_min[1])["weight"]: + arrete_min = i + L.append(arrete_min) + sommets_visites.append(arrete_min[1]) + sommets_non_visites.remove(arrete_min[1]) + return L, sum([G.get_edge_data(i[0],i[1])["weight"] for i in L]) + +print(algo_kruskal(G1)) +print(algo_kruskal(G2)) + + +# Il existe un autre algorithme d’arbre couvrant de poids minimal, l’algorithme de Bor ̊uvka. Le +# comprendre et l’impl ́ementer. + +# Algorithme de Bor ̊uvka : +# F ← vide +# Tant que G n'est pas réduit à un sommet faire +# Détruire les boucles de G (*) +# Remplacer les arêtes multiples entre deux sommets par une seule dont le poids est le minimum +# Pour tout x, sommet de G, faire +# Trouver l'arête e_x de poids minimum adjacente à x +# F ← F union e_x +# Contracter e_x (**) +# fin pour +# fin tant que +# renvoyer F + +def algo_boruvka(G): + """ Renvoie la liste des arêtes de l'arbre couvrant de poids minimal de G + Entrée : + G : un graphe + Sortie : + L : la liste des arêtes de l'arbre couvrant de poids minimal de G + """ + L = [] + while len(G.nodes()) != 1: + # (*) Détruire les boucles de G + for i in G.edges(): + if i[0] == i[1]: + G.remove_edge(i[0],i[1]) + # Remplacer les arêtes multiples entre deux sommets par une seule dont le poids est le minimum + for i in G.edges(): + if len(G.edges(i[0],i[1])) > 1: + min = G.get_edge_data(i[0],i[1])["weight"] + for j in G.edges(i[0],i[1]): + if G.get_edge_data(j[0],j[1])["weight"] < min: + min = G.get_edge_data(j[0],j[1])["weight"] + for j in G.edges(i[0],i[1]): + if G.get_edge_data(j[0],j[1])["weight"] != min: + G.remove_edge(j[0],j[1]) + # Pour tout x, sommet de G, faire + for i in G.nodes(): + # Trouver l'arête e_x de poids minimum adjacente à x + min = 10000 + return L, sum([G.get_edge_data(i[0],i[1])["weight"] for i in L]) + +print(algo_boruvka(G1)) +print(algo_boruvka(G2)) \ No newline at end of file