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.

128 lines
5.0 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
#! H=nx.Graph() #cr ́ee un graphe
#! H.add_edge(0,1) #ajoute une arˆete entre les sommets 0 et 1
#! H.add_edges_from([(3,0),(3,4)]) #ajoute les arˆetes dune liste donn ́ee
#! H.add_node("toto") #ajoute un sommet nomm ́e "toto"
#! H.remove_node(s) #supprime le sommet s
#! H.nodes #sommets du graphe (attention, pour en faire
#! # une vraie liste Python, ́ecrire: list(H.nodes))
#! H.edges #arˆetes du graphe (attention, pour en faire
#! # une vraie liste Python, ́ecrire: list(H.edges))
#! H.edges(s) #les arˆetes qui touchent le sommet s
#! H.neighbors(s) #un it ́erateur sur les voisins du sommet s dans H
#! # pour obtenir une liste, ́ecrire: list(H.neighbors(s))
#! H.nodes[s]["attri"] #acc`ede `a lattribut nomm ́e "attri" du sommet s
#! # (tant en lecture quen ́ecriture)
#! # exemple: H.nodes[s]["attri"]=2
#! # ou alors print(H.nodes[s]["attri"])
# Exercice 1
##################################
##Un graphe pour tester Dijkstra
###################################
print("Un graphe pour tester Dijkstra")
G=nx.Graph()
G.add_nodes_from(["A","B","C","D","E","F","G","H","I","J"],distance=None)
print(G.nodes())
G.add_edges_from([("A", "B", {"weight": 4}),("A", "C", {"weight": 2}),
("A", "E", {"weight": 1}),("B", "F", {"weight": 3}),
("C", "G", {"weight": 1}),("C", "H", {"weight": 2}),
("D", "H", {"weight": 1}),("E", "J", {"weight": 5}),
("F", "I", {"weight": 2}),("I", "J", {"weight": 5}),
("H", "J", {"weight": 6})])
print(G.edges())
#########################
print(G.edges[("A","B")]["weight"])
print(G.nodes["A"]["distance"])
#########################
#? 1.
# On rappelle ci-dessous lalgorithme de Dijkstra qui calcule les distances `a un sommet
# source donn ́e :
# Algorithme de Dijkstra pour le graphe G `a partir du sommet source s
# • L repr ́esentera la fronti`ere. Contient initialement seulement s.
# • La valeur de distance d est initialis ́ee `a d(s)=0 et `a d(v)=∞ pour
# chaque autre sommet v
# • Une liste T contient les sommets qui ont ́et ́e compl`etement trait ́es.
# Initialement T est vide.
# • Tant que L nest pas vide :
# ⋆ choisir un sommet v dans L qui a une valeur de distance d(v)
# minimale
# ⋆ pour tout voisin w de v qui nest pas dans T :
# - si d(v) plus le poids p de larˆete (v,w) est inf ́erieur `a
# d(w), on fixe d(w)=d(v)+p
# - ajouter w `a L
# ⋆ enlever v de L, ajouter v `a T
# Impl ́ementez lalgorithme en suivant les ́etapes suivantes :
# 1. ́Ecrire une fonction mise_a_jour_voisin(G,n,v) qui met `a jour la distance du som-
# met v `a la source (v est suppos ́e voisin de n dans le graphe G) `a partir de celle du
# sommet n (en supposant que la distance du sommet n `a la source est un nombre)
def mise_a_jour_voisin(G,n,v):
G.nodes[v]["distance"]=G.edges[(n,v)]["weight"]
print(mise_a_jour_voisin(G,"A","B"))
# 2.
# Ecrire une fonction choix_prochain_sommet(G,L), qui renvoie le sommet de la fronti`ere
# L qui sera choisi pour la prochaine it ́eration de lalgorithme de Dijkstra.
def choix_prochain_sommet(G,L):
return min(L,key=lambda x:G.nodes[x]["distance"])
print(choix_prochain_sommet(G,["A","B","C","D","E","F","G","H","I","J"]))
# 3.
# Ecrire une fonction Dijkstra(G,s) qui d ́etermine les distances entre le sommet s et
# tous les autres sommets dans le graphe valu ́e G.
def Dijkstra(G,s):
L=[s]
G.nodes[s]["distance"]=0
while L!=[]:
v=choix_prochain_sommet(G,L)
for w in G.neighbors(v):
if w not in L:
if G.nodes[v]["distance"]+G.edges[(v,w)]["weight"]<G.nodes[w]["distance"]:
G.nodes[w]["distance"]=G.nodes[v]["distance"]+G.edges[(v,w)]["weight"]
L.append(w)
L.remove(v)
print(Dijkstra(G,"A"))
# 4.Coder et tester lalgorithme de Floyd-Warshall, rappel ́e ci-dessous :
# Algorithme de Floyd-Warshall pour le graphe G
# • Les sommets sont ordonn ́es : s1 ... sn avec n le nombre de sommets
# • On initialise une matrice D de taille n×n, o`u D(i, j) devra contenir la
# distance entre le sommet si et le sommet sj . Pour toute arˆete entre si et
# sj de poids pij , on fixe D(i, j) = pij , et pour tout i on fixe D(i, i) = 0.
# Dans les autres cas, on fixe D(i, j) = ∞.
# • Pour k allant de 1 `a n :
# • Pour i allant de 1 `a n :
# • Pour j allant de 1 `a n :
# D(i, j) = min{D(i, j), D(i, k) + D(k, j)}
# • Renvoyer D
# Pourquoi nest-t-il pas n ́ecessaire de copier la matrice D `a chaque ́etape ? V ́erifier que
# lalgorithme ne va pas ́ecraser des donn ́ees importantes en cours de route
def Floyd_Warshall(G):
n=len(G.nodes())
D=[[float("inf") for i in range(n)] for j in range(n)]
for i in range(n):
D[i][i]=0
for j in range(n):
if (i,j) in G.edges():
D[i][j]=G.edges[(i,j)]["weight"]
for k in range(n):
for i in range(n):
for j in range(n):
D[i][j]=min(D[i][j],D[i][k]+D[k][j])
return D
print(Floyd_Warshall(G))