Séance du 23 janvier
|
@ -12,7 +12,12 @@
|
||||||
\newlabel{eq:condArete}{{1}{3}}
|
\newlabel{eq:condArete}{{1}{3}}
|
||||||
\@writefile{toc}{\contentsline {paragraph}{preuve :}{3}}
|
\@writefile{toc}{\contentsline {paragraph}{preuve :}{3}}
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Mise en pratique : graphe de Gabriel et de voisinage relatif}{3}}
|
\@writefile{toc}{\contentsline {section}{\numberline {2}Mise en pratique : graphe de Gabriel et de voisinage relatif}{3}}
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {3}Triangulation de Delaunay}{4}}
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Création de graphe de Gabriel et de voisinage relatif}{3}}
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Pratique}{4}}
|
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Graphe de gabriel\relax }}{4}}
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Aspect théorique}{4}}
|
\newlabel{fig:2_4_gabriel}{{2}{4}}
|
||||||
\@writefile{toc}{\contentsline {part}{III\hspace {1em}Algorithme de Dijkstra pour la recherche du plus court chemin}{4}}
|
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Graphe de voisinage realtif\relax }}{5}}
|
||||||
|
\newlabel{fig:2_4_gvr}{{3}{5}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3}Triangulation de Delaunay}{6}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Pratique}{6}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Aspect théorique}{6}}
|
||||||
|
\@writefile{toc}{\contentsline {part}{III\hspace {1em}Algorithme de Dijkstra pour la recherche du plus court chemin}{6}}
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
\select@language {french}
|
\select@language {french}
|
||||||
\contentsline {figure}{\numberline {1}{\ignorespaces Différentes positions possible de points par rapport à $A$ et $B$\relax }}{3}
|
\contentsline {figure}{\numberline {1}{\ignorespaces Différentes positions possible de points par rapport à $A$ et $B$\relax }}{3}
|
||||||
|
\contentsline {figure}{\numberline {2}{\ignorespaces Graphe de gabriel\relax }}{4}
|
||||||
|
\contentsline {figure}{\numberline {3}{\ignorespaces Graphe de voisinage realtif\relax }}{5}
|
||||||
|
|
|
@ -64,7 +64,35 @@ Réciproquement, si tous les points de $\mathcal{V}$ sont à l'extérieur du cer
|
||||||
}
|
}
|
||||||
|
|
||||||
\section{Mise en pratique : graphe de Gabriel et de voisinage relatif}
|
\section{Mise en pratique : graphe de Gabriel et de voisinage relatif}
|
||||||
Questions 2.4 2.5 2.6
|
\subsection{Création de graphe de Gabriel et de voisinage relatif}
|
||||||
|
\begin{figure}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=1\linewidth]{images/2_4_gabriel}
|
||||||
|
\caption{Graphe de gabriel}
|
||||||
|
\label{fig:2_4_gabriel}
|
||||||
|
\end{figure}
|
||||||
|
\begin{figure}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=1\linewidth]{images/2_4_gvr}
|
||||||
|
\caption{Graphe de voisinage realtif}
|
||||||
|
\label{fig:2_4_gvr}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
En traçant les graphes de Gabriel (figure \ref{fig:2_4_gabriel}) et de voisinage relatif (figure \ref{fig:2_4_gvr}), on observe que le second est inclus dans le premier.
|
||||||
|
|
||||||
|
\subsection{Génération d'un réseau}
|
||||||
|
En combinant la génération de graphe de Gabriel et de voisinage relatif, on peut générer un réseau routier, comme le montre la figure \ref{fig:2_5}.
|
||||||
|
|
||||||
|
\begin{figure}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=1\linewidth]{images/2_5}
|
||||||
|
\caption{Réseau généré}
|
||||||
|
\label{fig:2_5}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{Temps de génération d'un réseau}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section{Triangulation de Delaunay}
|
\section{Triangulation de Delaunay}
|
||||||
\subsection{Pratique}
|
\subsection{Pratique}
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
\contentsline {section}{\numberline {1}Condition pour un graphe de Gabriel}{3}
|
\contentsline {section}{\numberline {1}Condition pour un graphe de Gabriel}{3}
|
||||||
\contentsline {paragraph}{preuve :}{3}
|
\contentsline {paragraph}{preuve :}{3}
|
||||||
\contentsline {section}{\numberline {2}Mise en pratique : graphe de Gabriel et de voisinage relatif}{3}
|
\contentsline {section}{\numberline {2}Mise en pratique : graphe de Gabriel et de voisinage relatif}{3}
|
||||||
\contentsline {section}{\numberline {3}Triangulation de Delaunay}{4}
|
\contentsline {subsection}{\numberline {2.1}Création de graphe de Gabriel et de voisinage relatif}{3}
|
||||||
\contentsline {subsection}{\numberline {3.1}Pratique}{4}
|
\contentsline {section}{\numberline {3}Triangulation de Delaunay}{6}
|
||||||
\contentsline {subsection}{\numberline {3.2}Aspect théorique}{4}
|
\contentsline {subsection}{\numberline {3.1}Pratique}{6}
|
||||||
\contentsline {part}{III\hspace {1em}Algorithme de Dijkstra pour la recherche du plus court chemin}{4}
|
\contentsline {subsection}{\numberline {3.2}Aspect théorique}{6}
|
||||||
|
\contentsline {part}{III\hspace {1em}Algorithme de Dijkstra pour la recherche du plus court chemin}{6}
|
||||||
|
|
BIN
compte_rendu/images/2_5.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
compte_rendu/images/2_6_lin.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
compte_rendu/images/4_6.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
compte_rendu/images/4_7_cout.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
compte_rendu/images/4_7_graphe.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
compte_rendu/images/4_8_simple.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
compte_rendu/images/4_9.png
Normal file
After Width: | Height: | Size: 30 KiB |
91
graphe.py
|
@ -4,6 +4,7 @@ import numpy as np
|
||||||
|
|
||||||
import triangulation
|
import triangulation
|
||||||
import tas
|
import tas
|
||||||
|
import stack
|
||||||
|
|
||||||
|
|
||||||
class Graphe:
|
class Graphe:
|
||||||
|
@ -21,7 +22,7 @@ class Graphe:
|
||||||
self.nom = nom
|
self.nom = nom
|
||||||
self.sommets = []
|
self.sommets = []
|
||||||
self.aretes = []
|
self.aretes = []
|
||||||
self.cout = None, Graphe.Cout.TEMPS
|
self.cout = Graphe.Cout.TEMPS
|
||||||
self.arrivee = None
|
self.arrivee = None
|
||||||
|
|
||||||
def renomme(self, nom):
|
def renomme(self, nom):
|
||||||
|
@ -55,6 +56,8 @@ class Graphe:
|
||||||
"""
|
"""
|
||||||
a = Arete(s1, s2, longueur, v_moyenne, self)
|
a = Arete(s1, s2, longueur, v_moyenne, self)
|
||||||
self.aretes.append(a)
|
self.aretes.append(a)
|
||||||
|
s1.aretes.add(a)
|
||||||
|
s2.aretes.add(a)
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def n(self):
|
def n(self):
|
||||||
|
@ -303,18 +306,19 @@ class Graphe:
|
||||||
minCout = sys.float_info.max
|
minCout = sys.float_info.max
|
||||||
matrice = self.matriceCout(tournee)
|
matrice = self.matriceCout(tournee)
|
||||||
cout = 0
|
cout = 0
|
||||||
visite = [False]*len(tournee)
|
visite = [False] * len(tournee)
|
||||||
visite[0] = True
|
visite[0] = True
|
||||||
itineraire = [0]
|
itineraire = [0]
|
||||||
|
|
||||||
def backtrack():
|
def backtrack():
|
||||||
nonlocal meilleurItineraire, minCout, matrice, cout, visite, itineraire
|
nonlocal meilleurItineraire, minCout, matrice, cout, visite, itineraire
|
||||||
if cout < minCout:
|
if cout < minCout:
|
||||||
if len(itineraire)==len(tournee):
|
if len(itineraire) == len(tournee):
|
||||||
if cout + matrice[0, itineraire[-1]] < minCout:
|
if cout + matrice[0, itineraire[-1]] < minCout:
|
||||||
minCout = cout + matrice[0, itineraire[-1]]
|
minCout = cout + matrice[0, itineraire[-1]]
|
||||||
meilleurItineraire = [tournee[x] for x in itineraire]
|
meilleurItineraire = [tournee[x] for x in itineraire]
|
||||||
else:
|
else:
|
||||||
for i,sommet_visite in enumerate(visite):
|
for i, sommet_visite in enumerate(visite):
|
||||||
if not sommet_visite:
|
if not sommet_visite:
|
||||||
visite[i] = True
|
visite[i] = True
|
||||||
indicePrec = itineraire[-1]
|
indicePrec = itineraire[-1]
|
||||||
|
@ -328,12 +332,82 @@ class Graphe:
|
||||||
return minCout, meilleurItineraire
|
return minCout, meilleurItineraire
|
||||||
|
|
||||||
def traceItineraire(self, itineraire):
|
def traceItineraire(self, itineraire):
|
||||||
for i,x in enumerate(itineraire):
|
for i, x in enumerate(itineraire):
|
||||||
x.nom = "s" + str(i)
|
x.nom = "s" + str(i)
|
||||||
suivant = itineraire[(i+1)%len(itineraire)]
|
suivant = itineraire[(i + 1) % len(itineraire)]
|
||||||
c,_ = self.astar(x, suivant)
|
c, _ = self.astar(x, suivant)
|
||||||
self.colorieChemin(c, (0.8, 0.1, 0.8))
|
self.colorieChemin(c, (0.8, 0.1, 0.8))
|
||||||
|
|
||||||
|
def Prim(self):
|
||||||
|
for s in self.sommets:
|
||||||
|
s.selection = False
|
||||||
|
for a in self.aretes:
|
||||||
|
a.selection = False
|
||||||
|
aretes = tas.Tas(lambda x: -x.cout)
|
||||||
|
for a in self.sommets[0].aretes:
|
||||||
|
aretes.ajoute(a)
|
||||||
|
self.sommets[0].selection = True
|
||||||
|
arbre = []
|
||||||
|
ptot = 0
|
||||||
|
while not aretes.empty():
|
||||||
|
a = aretes.pop()
|
||||||
|
s1, s2 = a.s1, a.s2
|
||||||
|
if not s1.selection or not s2.selection:
|
||||||
|
a.selection = True
|
||||||
|
ptot += a.cout
|
||||||
|
if not s1.selection:
|
||||||
|
s1.selection = True
|
||||||
|
for a_1 in s1.aretes:
|
||||||
|
aretes.ajoute(a_1)
|
||||||
|
if not s2.selection:
|
||||||
|
s2.selection = True
|
||||||
|
for a_2 in s2.aretes:
|
||||||
|
aretes.ajoute(a_2)
|
||||||
|
return ptot
|
||||||
|
|
||||||
|
def colorieSelection(self, couleur=(0.1, 0.6, 0.2)):
|
||||||
|
"""Colorie les sommets et arêtes avec le drapeau `selection` à True."""
|
||||||
|
for s in self.sommets:
|
||||||
|
if s.selection:
|
||||||
|
s.couleur = couleur
|
||||||
|
for s in self.aretes:
|
||||||
|
if s.selection:
|
||||||
|
s.couleur = couleur
|
||||||
|
|
||||||
|
def grapheDeCout(self, tournee):
|
||||||
|
g = Graphe("Graphe de cout de " + self.nom)
|
||||||
|
for s in tournee:
|
||||||
|
s_a = g.ajouteSommet(s.x(), s.y())
|
||||||
|
s_a.image = s
|
||||||
|
s.image = s_a
|
||||||
|
|
||||||
|
for i, s in enumerate(g.sommets):
|
||||||
|
self.dijkstraAvecTas(s.image)
|
||||||
|
for s_v in g.sommets[i:]:
|
||||||
|
d = sum((a.cout for a in self.cheminOptimal(s_v.image)))
|
||||||
|
g.connecte(s, s_v, d, 1)
|
||||||
|
return g
|
||||||
|
|
||||||
|
def tourneeApproximative(self, tournee):
|
||||||
|
g_cout = self.grapheDeCout(tournee)
|
||||||
|
g_cout.Prim()
|
||||||
|
pile = stack.Stack()
|
||||||
|
pile.add(tournee[0].image)
|
||||||
|
tournee[0].image.selection = False
|
||||||
|
chemin = [tournee[0]]
|
||||||
|
while not pile.empty():
|
||||||
|
actuel = pile.pop()
|
||||||
|
fils = list(filter(lambda x: x.selection, actuel.aretes))
|
||||||
|
if fils:
|
||||||
|
a = fils.pop()
|
||||||
|
a.selection = False
|
||||||
|
nouveau = a.voisin(actuel)
|
||||||
|
nouveau.selection = False
|
||||||
|
chemin.append(nouveau.image)
|
||||||
|
pile.add(actuel)
|
||||||
|
pile.add(nouveau)
|
||||||
|
return chemin
|
||||||
|
|
||||||
|
|
||||||
class Sommet:
|
class Sommet:
|
||||||
"""Implémente un sommet de graphe."""
|
"""Implémente un sommet de graphe."""
|
||||||
|
@ -352,6 +426,8 @@ class Sommet:
|
||||||
self.cumul = None
|
self.cumul = None
|
||||||
self.precedent = None
|
self.precedent = None
|
||||||
self.graphe = graphe
|
self.graphe = graphe
|
||||||
|
self.selection = False
|
||||||
|
self.image = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def minCumulRestant(self):
|
def minCumulRestant(self):
|
||||||
|
@ -409,6 +485,7 @@ class Arete:
|
||||||
self.v_moyenne = v_moyenne
|
self.v_moyenne = v_moyenne
|
||||||
self.couleur = couleur
|
self.couleur = couleur
|
||||||
self.graph = graph
|
self.graph = graph
|
||||||
|
self.selection = False
|
||||||
|
|
||||||
def voisin(self, s):
|
def voisin(self, s):
|
||||||
"""Retourne le sommet voisin de s dans l'arête.
|
"""Retourne le sommet voisin de s dans l'arête.
|
||||||
|
|
22
stack.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
class Stack:
|
||||||
|
class StackElem:
|
||||||
|
def __init__(self, elt, prec):
|
||||||
|
self.elt = elt
|
||||||
|
self.prec = prec
|
||||||
|
|
||||||
|
def __init__(self, elts=[]):
|
||||||
|
self.first = None
|
||||||
|
for e in elts:
|
||||||
|
self.add(e)
|
||||||
|
|
||||||
|
def add(self, e):
|
||||||
|
se = self.StackElem(e, self.first)
|
||||||
|
self.first = se
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
e = self.first.elt
|
||||||
|
self.first = self.first.prec
|
||||||
|
return e
|
||||||
|
|
||||||
|
def empty(self):
|
||||||
|
return self.first is None
|
82
test.py
|
@ -6,6 +6,7 @@ Donc pour la question 3_4 : `python3 test.py 3_4`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import random
|
||||||
|
|
||||||
import graphe
|
import graphe
|
||||||
import graphique
|
import graphique
|
||||||
|
@ -101,7 +102,7 @@ def chronometre(fonctionTest, fonctionPreparation, parametres):
|
||||||
def testQuestion2_6():
|
def testQuestion2_6():
|
||||||
"""Mesure la performance de graphe.reseau"""
|
"""Mesure la performance de graphe.reseau"""
|
||||||
prepare = lambda p : graphe.pointsAleatoires(p, 10)
|
prepare = lambda p : graphe.pointsAleatoires(p, 10)
|
||||||
valeurs_n = np.arange(1, 200)
|
valeurs_n = list(map(int, np.logspace(1, 2.7, 100)))
|
||||||
temps = chronometre(graphe.reseau, prepare, valeurs_n)
|
temps = chronometre(graphe.reseau, prepare, valeurs_n)
|
||||||
pl.close('all')
|
pl.close('all')
|
||||||
pl.title("Mesure du temps d'exécution de `reseau`.")
|
pl.title("Mesure du temps d'exécution de `reseau`.")
|
||||||
|
@ -347,6 +348,85 @@ def testQuestion4_2():
|
||||||
graphique.affiche(g, (0, 0), 10.)
|
graphique.affiche(g, (0, 0), 10.)
|
||||||
|
|
||||||
|
|
||||||
|
def testQuestion4_3():
|
||||||
|
"""Mesure le temps de calcul."""
|
||||||
|
g = graphe.reseauRapide(graphe.pointsAleatoires(1000, 1000))
|
||||||
|
prepare = lambda p : random.sample(g.sommets, p)
|
||||||
|
valeurs_n = list(map(int, np.linspace(1, 15, 10)))
|
||||||
|
temps = chronometre(g.voyageurDeCommerceNaif, prepare, valeurs_n)
|
||||||
|
pl.close('all')
|
||||||
|
pl.title("Temps d'exécution pour le voyageur de commerce.")
|
||||||
|
pl.plot(valeurs_n, temps)
|
||||||
|
pl.xlabel("n (nombre de points de la tournée)")
|
||||||
|
pl.ylabel("temps")
|
||||||
|
pl.show()
|
||||||
|
pl.title("Temps d'exécution pour le voyageur de commerce.")
|
||||||
|
pl.loglog(valeurs_n, temps)
|
||||||
|
pl.xlabel("n (nombre de points de la tournée)")
|
||||||
|
pl.ylabel("temps")
|
||||||
|
pl.show()
|
||||||
|
|
||||||
|
|
||||||
|
def testQuestion4_6():
|
||||||
|
g = graphe.pointsAleatoires(30, 30)
|
||||||
|
|
||||||
|
graphe.reseauRapide(g)
|
||||||
|
g.fixeTempsCommeCout()
|
||||||
|
g.renomme("Algorithme de Prim (cout=temps)")
|
||||||
|
p = g.Prim()
|
||||||
|
print("Poids de prim:", p)
|
||||||
|
g.colorieSelection()
|
||||||
|
graphique.affiche(g, (0, 0), 10.)
|
||||||
|
|
||||||
|
|
||||||
|
def testQuestion4_7():
|
||||||
|
g = graphe.pointsAleatoires(30, 30)
|
||||||
|
|
||||||
|
graphe.reseauRapide(g)
|
||||||
|
g.fixeTempsCommeCout()
|
||||||
|
g.renomme("Graphe de test (cout=temps)")
|
||||||
|
tournee = [g.sommets[i] for i in (0, 1, 2, 7)]
|
||||||
|
g1 = g.grapheDeCout(tournee)
|
||||||
|
graphique.affiche(g, (0, 0), 10., blocage=False)
|
||||||
|
graphique.affiche(g1, (0, 0), 10.)
|
||||||
|
|
||||||
|
|
||||||
|
def testQuestion4_8():
|
||||||
|
g = graphe.pointsAleatoires(30, 30)
|
||||||
|
|
||||||
|
graphe.reseauRapide(g)
|
||||||
|
g.fixeTempsCommeCout()
|
||||||
|
g.renomme("Graphe de test (cout=temps)")
|
||||||
|
g1 = copy.deepcopy(g)
|
||||||
|
print("Tournée 0, 1, 2, 7")
|
||||||
|
tournee = [g.sommets[i] for i in (0, 1, 2, 7)]
|
||||||
|
iti = g.tourneeApproximative(tournee)
|
||||||
|
g.traceItineraire(iti)
|
||||||
|
tournee = [g1.sommets[i] for i in (0, 1, 2, 7)]
|
||||||
|
cout,iti = g1.voyageurDeCommerceNaif(tournee)
|
||||||
|
g1.traceItineraire(iti)
|
||||||
|
graphique.affiche(g, (0, 0), 10., blocage=False)
|
||||||
|
graphique.affiche(g1, (0, 0), 10.)
|
||||||
|
|
||||||
|
|
||||||
|
def testQuestion4_9():
|
||||||
|
"""Mesure le temps de calcul."""
|
||||||
|
g = graphe.reseauRapide(graphe.pointsAleatoires(1000, 1000))
|
||||||
|
prepare = lambda p : random.sample(g.sommets, p)
|
||||||
|
valeurs_n = list(map(int, np.logspace(1, 2, 30)))
|
||||||
|
temps = chronometre(g.tourneeApproximative, prepare, valeurs_n)
|
||||||
|
pl.close('all')
|
||||||
|
pl.title("Temps d'exécution pour le voyageur de commerce approximatif.")
|
||||||
|
pl.plot(valeurs_n, temps)
|
||||||
|
pl.xlabel("n (nombre de points de la tournée)")
|
||||||
|
pl.ylabel("temps")
|
||||||
|
pl.show()
|
||||||
|
pl.title("Temps d'exécution pour le voyageur de commerce approximatif.")
|
||||||
|
pl.loglog(valeurs_n, temps)
|
||||||
|
pl.xlabel("n (nombre de points de la tournée)")
|
||||||
|
pl.ylabel("temps")
|
||||||
|
pl.show()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
n = sys.argv[1]
|
n = sys.argv[1]
|
||||||
if n in ('--help', '-h'):
|
if n in ('--help', '-h'):
|
||||||
|
|