Séance du 9/01
6
compte_rendu/compte_rendu.aux
Normal file
|
@ -0,0 +1,6 @@
|
|||
\relax
|
||||
\select@language{french}
|
||||
\@writefile{toc}{\select@language{french}}
|
||||
\@writefile{lof}{\select@language{french}}
|
||||
\@writefile{lot}{\select@language{french}}
|
||||
\@writefile{toc}{\contentsline {part}{I\hspace {1em}Objectifs de ce TL}{3}}
|
1
compte_rendu/compte_rendu.lof
Normal file
|
@ -0,0 +1 @@
|
|||
\select@language {french}
|
BIN
compte_rendu/compte_rendu.pdf
Normal file
BIN
compte_rendu/compte_rendu.synctex.gz
Normal file
|
@ -0,0 +1,25 @@
|
|||
\documentclass[french]{article}
|
||||
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{arrows,automata}
|
||||
\usepackage{MyPack2}
|
||||
|
||||
\usepackage{diagbox}
|
||||
|
||||
\geometry{top=2cm, bottom=2cm, left=2cm, right=2cm}
|
||||
\title{Étude de laboratoire - ASD}
|
||||
\author{Binôme A11 \\ \bsc{Simon} Léo, \bsc{Levy--Falk} Hugo \\ Supélec, promo 2020}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\clearpage
|
||||
\listoffigures
|
||||
\newpage
|
||||
\initPage{TL - ASD}{\today}{\bsc{Simon}, \bsc{Levy--Falk}}
|
||||
|
||||
\part{Objectifs de ce TL}
|
||||
|
||||
\end{document}
|
2
compte_rendu/compte_rendu.toc
Normal file
|
@ -0,0 +1,2 @@
|
|||
\select@language {french}
|
||||
\contentsline {part}{I\hspace {1em}Objectifs de ce TL}{3}
|
BIN
compte_rendu/images/3_2_carburant.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
compte_rendu/images/3_2_temps.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
compte_rendu/images/3_4_chemin.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
compte_rendu/images/3_5_liste.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
compte_rendu/images/3_5_tas.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
compte_rendu/images/3_6.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
compte_rendu/images/dijkstra_lin.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
compte_rendu/images/dijkstra_log.png
Normal file
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
156
graphe.py
|
@ -1,10 +1,15 @@
|
|||
import random
|
||||
import triangulation
|
||||
import tas
|
||||
|
||||
|
||||
class Graphe:
|
||||
"""Implémente un graphe non orienté."""
|
||||
|
||||
class Cout:
|
||||
CARBURANT = 0
|
||||
TEMPS = 1
|
||||
|
||||
def __init__(self, nom):
|
||||
"""Initialise un graphe vide.
|
||||
|
||||
|
@ -13,6 +18,7 @@ class Graphe:
|
|||
self.nom = nom
|
||||
self.sommets = []
|
||||
self.aretes = []
|
||||
self.cout = Graphe.Cout.TEMPS
|
||||
|
||||
def renomme(self, nom):
|
||||
"""Renome le graphe
|
||||
|
@ -43,7 +49,7 @@ class Graphe:
|
|||
|
||||
:return: L'arête créée.
|
||||
"""
|
||||
a = Arete(s1, s2, longueur, v_moyenne)
|
||||
a = Arete(s1, s2, longueur, v_moyenne, self)
|
||||
self.aretes.append(a)
|
||||
return a
|
||||
|
||||
|
@ -67,10 +73,11 @@ class Graphe:
|
|||
|
||||
:param dest: instance de Afficheur.
|
||||
"""
|
||||
dest.renomme(self.nom)
|
||||
for s in self.sommets:
|
||||
dest.changeCouleur(s.couleur)
|
||||
dest.tracePoint((s.x(), s.y()))
|
||||
dest.traceTexte((s.x(), s.y()), 'v'+str(s.num))
|
||||
dest.traceTexte((s.x(), s.y()), 'v' + str(s.num))
|
||||
|
||||
for a in self.aretes:
|
||||
dest.changeCouleur(a.couleur)
|
||||
|
@ -111,6 +118,123 @@ class Graphe:
|
|||
a.couleur = (1., 1., 0.)
|
||||
return a
|
||||
|
||||
def dijkstra(self, depart=None):
|
||||
"""Calcule les plus courts chemins depuis le sommet `depart` (attention,
|
||||
effets de bord).
|
||||
|
||||
:param depart: Sommet de départ.
|
||||
"""
|
||||
for s in self.sommets:
|
||||
s.cumul = None
|
||||
s.precedent = None
|
||||
sommets = [depart or self.sommets[0]]
|
||||
sommets[0].cumul = 0
|
||||
while sommets:
|
||||
i, s = min(enumerate(sommets), key=lambda x: x[1].cumul)
|
||||
sommets.pop(i)
|
||||
for arete in s.aretes:
|
||||
voisin = arete.voisin(s)
|
||||
if voisin.cumul is None: # cumul infini
|
||||
sommets.append(voisin)
|
||||
if voisin.cumul is None or s.cumul + arete.cout < voisin.cumul:
|
||||
voisin.cumul = s.cumul + arete.cout
|
||||
voisin.precedent = arete
|
||||
|
||||
def dijkstraAvecTas(self, depart=None):
|
||||
"""Calcule les plus courts chemins depuis le sommet `depart` (attention,
|
||||
effets de bord).
|
||||
|
||||
:param depart: Sommet de départ.
|
||||
"""
|
||||
for s in self.sommets:
|
||||
s.cumul = None
|
||||
s.precedent = None
|
||||
sommets = tas.Tas(lambda x: -x.cumul)
|
||||
depart = depart or self.sommets[0]
|
||||
depart.cumul = 0
|
||||
depart.cle = sommets.ajoute(depart)
|
||||
while not sommets.empty():
|
||||
s = sommets.pop()
|
||||
for arete in s.aretes:
|
||||
voisin = arete.voisin(s)
|
||||
inf = voisin.cumul is None
|
||||
if inf or s.cumul + arete.cout < voisin.cumul:
|
||||
voisin.cumul = s.cumul + arete.cout
|
||||
if inf: # cumul infini
|
||||
voisin.cle = sommets.ajoute(voisin)
|
||||
else:
|
||||
sommets.actualise(voisin.cle)
|
||||
voisin.precedent = arete
|
||||
|
||||
def dijkstraPartiel(self, depart, arrivee):
|
||||
"""Calcule les plus courts chemins depuis le sommet `depart` vers
|
||||
`arrivee` (attention, effets de bord).
|
||||
|
||||
:param depart: Sommet de départ.
|
||||
"""
|
||||
for s in self.sommets:
|
||||
s.cumul = None
|
||||
s.precedent = None
|
||||
sommets = tas.Tas(lambda x: -x.cumul)
|
||||
depart = depart or self.sommets[0]
|
||||
depart.cumul = 0
|
||||
depart.cle = sommets.ajoute(depart)
|
||||
while not sommets.empty():
|
||||
s = sommets.pop()
|
||||
for arete in s.aretes:
|
||||
voisin = arete.voisin(s)
|
||||
inf = voisin.cumul is None
|
||||
if inf or s.cumul + arete.cout < voisin.cumul:
|
||||
voisin.cumul = s.cumul + arete.cout
|
||||
if inf: # cumul infini
|
||||
voisin.cle = sommets.ajoute(voisin)
|
||||
else:
|
||||
sommets.actualise(voisin.cle)
|
||||
voisin.precedent = arete
|
||||
|
||||
def traceArbreDesChemins(self):
|
||||
"""Change la couleur des chemins optimaux en violet-rose
|
||||
(252, 17, 189) et le départ en bleu (10, 98, 252).
|
||||
"""
|
||||
for s in self.sommets:
|
||||
if s.precedent:
|
||||
s.precedent.couleur = (252/255, 17/255, 189/255)
|
||||
if not s.cumul: # sommet de départ
|
||||
s.couleur = (10/255, 98/255, 252/255)
|
||||
|
||||
def fixeCarburantCommeCout(self):
|
||||
"""Fixe le carburant pour cout lors du calcul de plus court chemin."""
|
||||
self.cout = Graphe.Cout.CARBURANT
|
||||
|
||||
def fixeTempsCommeCout(self):
|
||||
"""Fixe le temps pour cout lors du calcul de plus court chemin."""
|
||||
self.cout = Graphe.Cout.TEMPS
|
||||
|
||||
def cheminOptimal(self, arrivee):
|
||||
"""Donne le chemin optimal pour aller à `arrivee` depuis le point
|
||||
de départ donné à `dijkstra`.
|
||||
|
||||
:param arrivee: Sommet d'arrivee
|
||||
|
||||
:return: le chemin (liste des arêtes)
|
||||
"""
|
||||
chemin = []
|
||||
suivant = arrivee
|
||||
while suivant.cumul:
|
||||
chemin.append(suivant.precedent)
|
||||
suivant = suivant.precedent.voisin(suivant)
|
||||
chemin.reverse()
|
||||
return chemin
|
||||
|
||||
def colorieChemin(self, chemin, c):
|
||||
"""Colorie le chemin.
|
||||
|
||||
:param chemin: une liste d'arrêtes
|
||||
:param c: une couleur
|
||||
"""
|
||||
for a in chemin:
|
||||
a.couleur = c
|
||||
|
||||
|
||||
class Sommet:
|
||||
"""Implémente un sommet de graphe."""
|
||||
|
@ -125,6 +249,9 @@ class Sommet:
|
|||
self.pos = pos
|
||||
self.num = num
|
||||
self.couleur = couleur
|
||||
self.aretes = set()
|
||||
self.cumul = None
|
||||
self.precedent = None
|
||||
|
||||
def __str__(self):
|
||||
return "v{} (x = {} km y = {} km)".format(
|
||||
|
@ -138,7 +265,7 @@ class Sommet:
|
|||
|
||||
:param v: Point de calcul de la distance.
|
||||
"""
|
||||
return ((self.x()-v.x())**2 + (self.y()-v.y())**2)**(1/2)
|
||||
return ((self.x() - v.x())**2 + (self.y() - v.y())**2)**(1 / 2)
|
||||
|
||||
def x(self):
|
||||
"""Retourne l'abcisse de x."""
|
||||
|
@ -152,7 +279,8 @@ class Sommet:
|
|||
class Arete:
|
||||
"""Implémente une arête de graphe."""
|
||||
|
||||
def __init__(self, s1, s2, longueur, v_moyenne, couleur=(0., 0., 0.)):
|
||||
def __init__(
|
||||
self, s1, s2, longueur, v_moyenne, graph, couleur=(0., 0., 0.)):
|
||||
"""Initialise une arête.
|
||||
|
||||
:param s1: sommet 1.
|
||||
|
@ -160,12 +288,16 @@ class Arete:
|
|||
:param longueur: longueur de l'arête.
|
||||
:param v_moyenne: vitesse moyenne sur l'arête.
|
||||
:param couleur: couleur de l'arête.
|
||||
:param graph: le graphe de l'arête.
|
||||
"""
|
||||
self.s1 = s1
|
||||
self.s2 = s2
|
||||
s1.aretes.add(self)
|
||||
s2.aretes.add(self)
|
||||
self.longueur = longueur
|
||||
self.v_moyenne = v_moyenne
|
||||
self.couleur = couleur
|
||||
self.graph = graph
|
||||
|
||||
def voisin(self, s):
|
||||
"""Retourne le sommet voisin de s dans l'arête.
|
||||
|
@ -177,6 +309,16 @@ class Arete:
|
|||
else:
|
||||
return self.s1
|
||||
|
||||
@property
|
||||
def cout(self):
|
||||
"""Retourne le cout de l'arête."""
|
||||
if self.graph.cout is Graphe.Cout.TEMPS:
|
||||
return self.longueur / self.v_moyenne
|
||||
elif self.graph.cout is Graphe.Cout.CARBURANT:
|
||||
return self.longueur
|
||||
else:
|
||||
return 1
|
||||
|
||||
def __str__(self):
|
||||
return " v{v1}, v{v2} (long. = {lon} km vlim. = {v} km/h)".format(
|
||||
v1=str(self.s1.num),
|
||||
|
@ -195,7 +337,7 @@ def pointsAleatoires(n, L):
|
|||
"""
|
||||
g = Graphe("Graphe aléatoire")
|
||||
for _ in range(n):
|
||||
x, y = random.uniform(-L/2, L/2), random.uniform(-L/2, L/2)
|
||||
x, y = random.uniform(-L / 2, L / 2), random.uniform(-L / 2, L / 2)
|
||||
g.ajouteSommet(x, y)
|
||||
return g
|
||||
|
||||
|
@ -207,8 +349,8 @@ def test_gabriel(g, v1, v2):
|
|||
:param v1: Premier sommet.
|
||||
:param v2: Deuxième sommet.
|
||||
"""
|
||||
milieu = Sommet(((v1.x()+v2.x())/2, (v1.y()+v2.y())/2), -1)
|
||||
rayon = v1.distance(v2)/2
|
||||
milieu = Sommet(((v1.x() + v2.x()) / 2, (v1.y() + v2.y()) / 2), -1)
|
||||
rayon = v1.distance(v2) / 2
|
||||
ajoute = True
|
||||
for v3 in g.sommets:
|
||||
if v3 in [v1, v2]:
|
||||
|
|
|
@ -30,7 +30,7 @@ class Afficheur(qtgui.QWidget):
|
|||
self.centre = np.array(centre)
|
||||
self.crayon = None
|
||||
self.sujet = sujet
|
||||
self.setStyleSheet("background-color: gray")
|
||||
self.setStyleSheet("background-color: white")
|
||||
self.center = np.array(Afficheur.size) / 2.
|
||||
self.setGeometry(Afficheur.coord[0] + screen.x(), Afficheur.coord[1] + screen.y(), Afficheur.size[0], Afficheur.size[1])
|
||||
Afficheur.coord += Afficheur.decalage
|
||||
|
@ -151,7 +151,7 @@ class Afficheur(qtgui.QWidget):
|
|||
qtgui.QApplication.quit()
|
||||
L = 100.;
|
||||
x = 20; y = 20;
|
||||
self.crayon.setPen('white')
|
||||
self.crayon.setPen('black')
|
||||
msg = '{0:.2f} km'.format(L / self.ech)
|
||||
l = self.crayon.fontMetrics().boundingRect(msg).width()
|
||||
self.crayon.drawText(x + (L-l)/2, y-2, msg);
|
||||
|
|
10
tas.py
|
@ -1,5 +1,6 @@
|
|||
# coding: utf-8
|
||||
|
||||
|
||||
class Tas:
|
||||
class Element:
|
||||
def __init__(self, valeur, priorite, index):
|
||||
|
@ -25,7 +26,7 @@ class Tas:
|
|||
if(elt.index == 0):
|
||||
return None
|
||||
else:
|
||||
return self.L[(elt.index-1) // 2]
|
||||
return self.L[(elt.index - 1) // 2]
|
||||
|
||||
def __fils_gauche(self, elt):
|
||||
i = 2 * elt.index + 1
|
||||
|
@ -100,8 +101,10 @@ class Tas:
|
|||
# Tri de tâches par ordre chronologique #
|
||||
#########################################
|
||||
|
||||
|
||||
class Tache:
|
||||
'''Tache devant être effectuée avant une date limite'''
|
||||
|
||||
def __init__(self, jour, nom):
|
||||
self.jour = jour
|
||||
self.nom = nom
|
||||
|
@ -111,6 +114,7 @@ class Tache:
|
|||
def __str__(self):
|
||||
return self.nom + " ({})".format(self.jour)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Le niveau de priorité d'un événement x est -x.jour : on trie donc les événements par ordre chronologique
|
||||
|
@ -121,7 +125,7 @@ if __name__ == "__main__":
|
|||
T = Tas(calculePriorite)
|
||||
|
||||
# Ajoute des événements au tas
|
||||
evts = [ Tache(5, "T1"), Tache(10, "T2"), Tache(5, "T3"), Tache(3, "T4")]
|
||||
evts = [Tache(5, "T1"), Tache(10, "T2"), Tache(5, "T3"), Tache(3, "T4")]
|
||||
for evt in evts:
|
||||
evt.cle = T.ajoute(evt)
|
||||
|
||||
|
@ -132,5 +136,3 @@ if __name__ == "__main__":
|
|||
# Retirons dans l'ordre chronologie les éléments du tas
|
||||
while(not T.empty()):
|
||||
print(T.pop())
|
||||
|
||||
|
||||
|
|
126
test.py
|
@ -1,3 +1,12 @@
|
|||
"""Test des fonctions du TL.
|
||||
|
||||
Pour tester la question x_y : `python3 test.py x_y`.
|
||||
|
||||
Donc pour la question 3_4 : `python3 test.py 3_4`.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import graphe
|
||||
import graphique
|
||||
import copy
|
||||
|
@ -5,7 +14,6 @@ import numpy as np
|
|||
import matplotlib.pyplot as pl
|
||||
import time
|
||||
|
||||
|
||||
def creerGrapheFigure1():
|
||||
""" Crée le graphe de la figure 1 """
|
||||
g = graphe.Graphe("Graphe de la figure 1")
|
||||
|
@ -159,7 +167,115 @@ def testQuestion2_9():
|
|||
pl.show()
|
||||
|
||||
|
||||
def testQuestion3_1():
|
||||
"""Trace le plus court chemin avec dijkstra."""
|
||||
g = graphe.pointsAleatoires(30, 30)
|
||||
g.renomme("Dijkstra")
|
||||
|
||||
graphe.reseauRapide(g)
|
||||
g.dijkstra(g.sommets[0])
|
||||
g.traceArbreDesChemins()
|
||||
graphique.affiche(g, (0, 0), 10.)
|
||||
|
||||
|
||||
def testQuestion3_2():
|
||||
"""Trace le plus court chemin avec dijkstra."""
|
||||
g = graphe.pointsAleatoires(30, 30)
|
||||
g.renomme("Dijkstra")
|
||||
|
||||
graphe.reseauRapide(g)
|
||||
g.fixeTempsCommeCout()
|
||||
g.dijkstra(g.sommets[0])
|
||||
g.traceArbreDesChemins()
|
||||
g.renomme("Temps")
|
||||
graphique.affiche(g, (0, 0), 10., blocage=False)
|
||||
g.fixeCarburantCommeCout()
|
||||
g.dijkstra(g.sommets[0])
|
||||
g.traceArbreDesChemins()
|
||||
g.renomme("Carburant")
|
||||
graphique.affiche(g, (0, 0), 10.)
|
||||
|
||||
|
||||
def testQuestion3_3():
|
||||
"""Mesure le temps d'exécution de Dijkstra."""
|
||||
prepare = lambda p : graphe.reseauRapide(graphe.pointsAleatoires(p, 100))
|
||||
valeurs_n = list(map(lambda x: int(x), np.logspace(1, 4, 10)))
|
||||
temps = chronometre(graphe.Graphe.dijkstra, prepare, valeurs_n)
|
||||
pl.close('all')
|
||||
pl.title("Temps d'exécution en fonction de la taille du graphe.")
|
||||
pl.plot(valeurs_n, temps, label='reseau')
|
||||
pl.legend(loc='best')
|
||||
pl.xlabel("n")
|
||||
pl.ylabel("temps")
|
||||
pl.show()
|
||||
pl.title("Temps d'exécution en fonction de la taille du graphe.")
|
||||
pl.loglog(valeurs_n, temps, label='reseau')
|
||||
pl.legend(loc='best')
|
||||
pl.xlabel("n")
|
||||
pl.ylabel("temps")
|
||||
pl.show()
|
||||
|
||||
|
||||
def testQuestion3_4():
|
||||
"""Trace le plus court chemin avec dijkstra."""
|
||||
g = graphe.pointsAleatoires(30, 30)
|
||||
g.renomme("Plus court chemin")
|
||||
|
||||
graphe.reseauRapide(g)
|
||||
g.fixeTempsCommeCout()
|
||||
g.dijkstra(g.sommets[0])
|
||||
c = g.cheminOptimal(g.sommets[-1])
|
||||
g.colorieChemin(c, (0.,1.,0.))
|
||||
g.renomme("Temps")
|
||||
graphique.affiche(g, (0, 0), 10.)
|
||||
|
||||
|
||||
def testQuestion3_5():
|
||||
"""Trace le plus court chemin avec dijkstra."""
|
||||
g = graphe.pointsAleatoires(30, 30)
|
||||
g.fixeTempsCommeCout()
|
||||
|
||||
graphe.reseauRapide(g)
|
||||
g.dijkstra(g.sommets[0])
|
||||
g.traceArbreDesChemins()
|
||||
g.renomme("Liste")
|
||||
graphique.affiche(g, (0, 0), 10., blocage=False)
|
||||
g.dijkstraAvecTas(g.sommets[0])
|
||||
g.traceArbreDesChemins()
|
||||
g.renomme("Tas")
|
||||
graphique.affiche(g, (0, 0), 10.)
|
||||
|
||||
|
||||
def testQuestion3_6():
|
||||
"""Compare Dijkstra avec et sans tas."""
|
||||
prepare = lambda p : graphe.reseauRapide(graphe.pointsAleatoires(p, 10))
|
||||
valeurs_n = list(map(lambda x: int(x), np.logspace(1, 3, 10)))
|
||||
temps1 = chronometre(graphe.Graphe.dijkstra, prepare, valeurs_n)
|
||||
temps2 = chronometre(graphe.Graphe.dijkstraAvecTas, prepare, valeurs_n)
|
||||
pl.close('all')
|
||||
pl.title("Comparaison du temps d'exécution de `dijkstra` et `dijkstraAvecTas`.")
|
||||
pl.plot(valeurs_n, temps1, label='Dijkstra')
|
||||
pl.plot(valeurs_n, temps2, label='Dijkstra avec tas')
|
||||
pl.legend(loc='best')
|
||||
pl.xlabel("n")
|
||||
pl.ylabel("temps")
|
||||
pl.show()
|
||||
pl.title("Comparaison du temps d'exécution de `reseau` et `reseauRapide`.")
|
||||
pl.loglog(valeurs_n, temps1, label='Dijkstra')
|
||||
pl.loglog(valeurs_n, temps2, label='Dijkstra avec tas')
|
||||
pl.legend(loc='best')
|
||||
pl.xlabel("n")
|
||||
pl.ylabel("temps")
|
||||
pl.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
n = sys.argv[1]
|
||||
if n in ('--help', '-h'):
|
||||
print(__doc__)
|
||||
else:
|
||||
print('Question ', n)
|
||||
locals()['testQuestion'+n]()
|
||||
# testQuestion1_2()
|
||||
# testQuestion1_3()
|
||||
# testQuestion1_4()
|
||||
|
@ -169,4 +285,10 @@ def testQuestion2_9():
|
|||
# testQuestion2_6()
|
||||
# testQuestion2_7()
|
||||
# testQuestion2_8()
|
||||
testQuestion2_9()
|
||||
# testQuestion2_9()
|
||||
# testQuestion3_1()
|
||||
# testQuestion3_2()
|
||||
# testQuestion3_3()
|
||||
# testQuestion3_4()
|
||||
# testQuestion3_5()
|
||||
# testQuestion3_6()
|
||||
|
|