Séance du 9/01

This commit is contained in:
Klafyvel 2018-01-09 17:53:28 +01:00
parent 4e5bea7322
commit 3c48f975b2
23 changed files with 434 additions and 134 deletions

View 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}}

View file

@ -0,0 +1 @@
\select@language {french}

Binary file not shown.

Binary file not shown.

View 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}

View file

@ -0,0 +1,2 @@
\select@language {french}
\contentsline {part}{I\hspace {1em}Objectifs de ce TL}{3}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
compte_rendu/images/3_6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

156
graphe.py
View file

@ -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]:

View file

@ -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
View file

@ -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
View file

@ -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()