mesureDeHoule
January 20, 2021
[1]: import matplotlib.pyplot as plt
1 Partie I. Stockage interne des données
[2]: import numpy as np
1.1 Q1
On ne compte pas la première ligne. Il y a 8 caractères de 1 octet chacun (=8 bits) donc 8 octets par ligne.
La fréquence est 2Hz donc on saisit deux lignes par seconde.
En 20 minutes il y a
[3]: 20*60*2# nb de lignes en 20 minutes
[3]: 2400
[4]: no=20*60*2*8#octets saisis en 20 minutes print('{} octets, {} ko'.format(no, no/1000))
19200 octets, 19.2 ko Complément
Faisons une expérience. Dans un fichier texte, on a écrit ceci [5]: #lire le contenu de donnees.txt; ce n'est pas du Python
%cat donnees.txt blabla; kjhjh; 5456 +0.4256
+0.3174 -0.0825 +0.4256
+0.3174 -0.0825
[6]: f = open('donnees.txt','rb')# ça c'est du Python l1 = f.readline()
l2 = f.readline()# la 2eme ligne
print(len(l2))# il y a bien 8 octets sur la ligne f.close()
8
[7]: 3600*434 [7]: 1562400
1.2 Q2
On fait 20 minutes de prélèvement toutes les demi-heures, donc deux enregistrements par heure, 48 par jours pendant 15 jours
[8]: nbe=48*15#nb enregistrements nbe
[8]: 720
[131]: nto=nbe*no#nombre total d'octets saisis en 15 jours nto, nto/10**9, nto/10**6
[131]: (13824000, 0.013824, 13.824)
Une campagne consomme0.014×109 octets donc moins que un Go (lequel vaut 109 octets). Donc la carte mémoire est suffisante.
1.3 Q3
On ne stocke que 7 octets (un chiffre pour 1 octet), pas 8. Donc on gagne un pour 8, un huitième de mémoire
[10]: 1/8
[10]: 0.125
On gagne donc 12.5% de 13824000 octets soit [11]: 13824000/8
[11]: 1728000.0
A peu près 2Mo de gain de place.
1.4 Q4
Les données se trouvent dans le répertoire de travail sous forme d’un fichierdonnees.txt.
Proposer une suite d’instructions permettant de créer à partir de ce fichier une liste de flottants liste_niveaux contenant les valeurs du niveau de la mer.
[12]: def recup(fich):
f=open(fich,"r")
l=f.readlines()[1:]#on ne tient pas compte de la 1ere ligne return [float(d) for d in l]
[13]: recup("donnees.txt")
[13]: [0.4256, 0.3174, -0.0825, 0.4256, 0.3174, -0.0825]
1.5 Rappels : lecture/écriture
Rappels sur les méthodes des objets d’entrée-sortie : [14]: f=open("essai.txt",'w')#écriture avec écrasement
f.write("un\n") f.write("deux\n") f.close()
f=open("essai.txt",'r')#lecture print(f.readlines())
f.close()
['un\n', 'deux\n']
[15]: f=open("essai.txt",'a')#écriture avec ajout à la fin f.write("un\n")
f.write("deux\n") f.close()
f=open("essai.txt",'r')#lecture print(f.readlines())
f.close()
['un\n', 'deux\n', 'un\n', 'deux\n']
2 Partie II. Analyse “vague par vague”
2.1 Q5
Pour le signal représenté sur la Figure 2, que valent approximativement H1 ,H2 etH3 [16]: h1=6-(-3)#
h2=7-(-2)# max_{t\in[Z1,Z2]}n(t)-min_{t\in[Z2,Z3]}n(t) h3=5-(-1.5)# max_{t\in[Z2,Z3]}n(t)-min_{t\in[Z3,Z4]}n(t) h1,h2,h3# en mètres
[16]: (9, 9, 6.5) [17]: T1=15.5-4
T2=28.5-15.5
T1,T2# en secondes [17]: (11.5, 13.0)
2.2 Q6
Proposer une fonction moyenne
[18]: #création d'un horodate aléatoire pour les tests import random as rd
liste_niveaux=[rd.random()*(-1)**rd.randint(0,1) for i in range(20)]
liste_niveaux[:5]#pour voir [18]: [-0.48582096159839905,
0.7071680584880793, -0.3314732417043347, 0.9789544984188214, -0.6101904220867811]
[19]: def moyenne(t):#V1 r=0
for e in t:
r+=e
return r/len(t) moyenne(liste_niveaux) [19]: -0.14730640773691261 [20]: def moyenne(t):#V2
return sum(t)/len(t)
[21]: moyenne([10,15,12]) [21]: 12.333333333333334
2.3 Q7
Pour calculer l’intégrale, il nous faut connaître le pas. La fréquence d’échantillonage est de 2Hz c’est à dire un pas de 0.5s.
Considérons le trapèze formé des 4 points (tk,0); (tk, f(tk); (tk+1, f(tk+1); (tk+1,0).
Son aire algébrique est la moyenne de celle des rectangles de som- mets (tk,0); (tk,max(f(tk, f(tk+1)); (tk+1,max(f(tk, f(tk+1)); (tk+1,0) et (tk,0); (tk,min(f(tk, f(tk+1)); (tk+1,min(f(tk, f(tk+1)); (tk+1,0). Elle vaut donc
(tk+1−tk)f(tk+1) +f(tk)) 2
Il y a un trapèze de moins que de points dans la liste liste_niveaux.
[22]: def integrale_precise(ln):
h,r=0.5,0
for i in range(len(ln)-1):
r+=(ln[i]+ln[i+1])/2 return h*r
[23]: l = [1, -1, -2, 2, -2, -1, 6, 4, -2, -5]
integrale_precise(l) [23]: 1.0
[24]: def integrale_precise(ln):# V2; avec un peu moins de calculs h,r=0.5,0
r = (ln[0]+ln[-1]/2)/2
for i in range(1,len(ln)-1):
r += ln[i]
return h*r [25]: integrale_precise(l) [25]: 1.625
La valeur moyenne deη sur [0, T]est définie par
m= 1 T
∫ T
t=0
η(t)dt
[26]: def moyenne_precise(ln):
h=0.5
T=len(ln)*0.5# A priori T vaut 20 minutes soit 1200 secondes return integrale_precise(ln)/T
2.4 Q8
On a supposé qu’aucun point n’était égal à la moyenne [27]: def first(t,m):
"""retourne le premier indice tel que t[i]>m et t[i+1]<m"""
n=len(t)
for i in range(len(t)-1):
if t[i]>m and t[i+1]<m:
return i
return -1 # on n'a pas trouvé i
def ind_premier_pzd(liste_niveaux):
m=moyenne(liste_niveaux) return first(liste_niveaux,m)
[28]: first([1, -1, -2, 2, -2, -1, 6, 4, -2, -5],0) [28]: 0
[29]: first([-1, -2, 2, -2, -1, 6, 4, -2, -5],0) [29]: 2
2.5 Q9
La complexité O(1) dans le meileur cas nous interdit de retourner la liste au préalable ou de la parcourir depuis le début : on commence par la fin !
[30]: def last(t,m):#O(n) n=len(t)
for i in range(1,n):
if t[-i]<m and t[-i-1]>m:
return n-i-1 return -2
def ind_dernier_pzd(liste_niveaux):
m=moyenne_precise(liste_niveaux)#O(n) return last(t,m)
[31]: last([1, -1, -2, 2, -2, -1, 6, 4, -2, -5],0) [31]: 7
[32]: last([1, -1, -2, -2, -2, -1, 6, 4],0) [32]: 0
[33]: last([-1, -1, -2, -2, -2, -1, 6, 4],0) [33]: -2
2.6 Q10
Compléter
def construction_successeurs(liste_niveaux):
n = len(liste_niveaux) successeurs = []
m = moyenne(liste_niveaux) for i in range(n-1):
if # À compléter
# À compléter return successeurs
[34]: def construction_successeurs(ln) : n=len ( ln )
successeurs =[]
m=moyenne ( ln )
for i in range ( n -1):
if ln[i]>m and ln[i+1]<m:
successeurs.append(i+1) return successeurs
[35]: construction_successeurs([1, -1, -2, 2, -2, -1, 6, 4, -2, -5]) [35]: [1, 4, 8]
[36]: moyenne([1, -1, -2, 2, -2, -1, 6, 4, -2, -5]) [36]: 0.0
2.7 Q11
[41]: def decompose_vague(ln):
les_succ=construction_successeurs(ln) r=[]
for i in range(len(les_succ)-1):
r.append(ln[les_succ[i]: les_succ[i+1]]) return r
[42]: ln =[1, -1, -2, 2, -2, -1, 6, 4, -2, -5]
decompose_vague(ln)
[42]: [[-1, -2, 2], [-2, -1, 6, 4]]
[43]: p=ind_premier_pzd(ln) ln[:p+1]
[43]: [1]
2.8 Q12
La principale difficulté est ici de respecter la définition de hauteur de vague : c’est la différence entre la hauteur maximum de la vague précédente et le minimum de la suivante.
On ne compare donc pas les maximums et minimums d’une même vague.
La hauteur de la dernière vague n’est pas définie par le sujet : on ne la calcule pas. Mais celle de la première vague est évaluée.
[117]: def proprietes(ln):
v=decompose_vague(ln)
H1=max(ln[:v[0]])-min(v[0])#1ere hauteur traitée à part T1=len(v[0])*0.5#1ere période
r=[[H1,T1]]
for i in range(len(v)-1):
v1,v2=v[i],v[i+1]#2 vagues successives
H=max(v1)-min(v2)#hauteur de la vague selon def page 2 T=0.5*len(v2)#période de la vague selon def page 2 r.append([H,T])
#noter qu'on n'a pas la hauteur de la dernière vague4 return r
[118]: ln =[1, -1, -2, 2, -2, -1, 6, 4, -2, -5]
proprietes(ln)
[118]: [[3, 1.5], [4, 2.0]]
3 III Contrôle des données
3.1 Q13
[119]: def hm(liste_niveaux):
prop = proprietes(liste_niveaux) # Détermination des propriétés des vagues return max([p[0] for p in prop])
[120]: hm(ln) [120]: 4
4 Q14
La bouclewhile fait le partitionnement. En sortie de boucle, les éléments plus petits que le pivot sont à gauche, les plus grands, à droite.
Dans cette version du tri rapide, le partitionnement gère deux indicesi, j. L’indiceiprogresse vers la droite,jvers la gauche. L’invariant maintenu dans la boucle principale est que à gauche deiil n’y ait que des éléments plus petits que le pivot, à droite dej que des éléments plus grands. Lorsqu’on a identifié deux tels éléments, on échange leurs places, ce qui fait que le nombre d’éléments qui ne sont pas à leur place diminue à chaque fois (et cela assure la terminaison).
Si i > j, le pivot n’a sur sa gauche que des éléments plus petits que lui et sur sa droite que des éléments plus grands. On peut donc sortir de la boucle principale : la position du pivot est trouvée.
Il reste à appliquer le tri rapide au sous-tableau à gauche de la première valeur inférieure au pivot et symétriquement à droite s’ils existent (d’où les tests g<jeti<d).
Le pivot est pris égal au premier élément de la portion de liste étudiée, c’est la seule chose qu’il fallait compléter. Au premier appel, i= 0 etj=|l| −1.
Enfin, le code proposé est une procédure qui trie une partie de la liste, celle qui est située en tre les indicesg etd.
[121]: from random import randint [122]: def triRapide ( l , g , d ) :
p=l[randint(g,d)][0]# le pivot, toute valeur entre les cases g et d i=g
j=d
while True :
while i<=d and l[ i ] [ 0 ] < p:
#chercher le 1er indice (en partant de la gauche) d'une hauteur >=p
i=i +1
while j>=g and l [ j ] [ 0 ] > p :
#chercher le premier indice (en partant de la droite) d'une hauteur␣
,→<=p
j=j-1 if i >j :
"""
à gauche de j : les points plus petits que le pivot à droite de i : ceux plus grands
entre i et j : les points égaux au pivot """
break if i <j :
#à gauche, on met les points plus petits que p
#à droite, les plus grands l[ i ] ,l[ j ]= l[ j ] , l[ i ] i=i +1
j=j -1
print(l,i-1,j+1) if g<j :
triRapide ( l , g , j ) if i <d :
triRapide ( l , i , d) [123]: l=[[10,1],[4,5],[6,8],[12,11],\
[3,9],[1,8],[10,5],[15,5],[9,8],[34,0]]
print(l)
triRapide(l,0,len(l)-1) print(l)
[[10, 1], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [9, 8], [34, 0]]
[[9, 8], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [10, 1], [34, 0]] 0 8
[[9, 8], [4, 5], [6, 8], [10, 5], [3, 9], [1, 8], [12, 11], [15, 5], [10, 1], [34, 0]] 3 6
[[1, 8], [4, 5], [6, 8], [10, 5], [3, 9], [9, 8], [12, 11], [15, 5], [10, 1], [34, 0]] 0 5
[[1, 8], [4, 5], [6, 8], [9, 8], [3, 9], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]] 3 5
[[1, 8], [3, 9], [6, 8], [9, 8], [4, 5], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]] 1 4
[[1, 8], [3, 9], [4, 5], [9, 8], [6, 8], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]] 2 4
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]] 3 4
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]] 9 9
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [12, 11], [10, 1], [15, 5], [34, 0]] 7 8
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [10, 1], [12, 11], [15, 5], [34, 0]] 6 7
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [10, 1], [12, 11], [15, 5], [34, 0]]
[124]: sum((i+1 for i in range(3))) [124]: 6
5 Q 15
Voir après la définition de triInsertion. On insère un test en début de fonction qui calcule la différence entre detg. Si celle-ci est plus petite que 15, on appelle le tri par Insertion.
6 Q16
Rappel du sujet
Compléter :
def triInsertion(liste,g,d):
for i in range(g+1,d+1):
j = i-1
tmp = liste[i]
while # À compléter
liste[j+1] = tmp
Dans la boucle while, on décale toutes les cases d’un cran vers la droite. Tout se passe comme si on maintenait un ‘trou’ décalé vers la gauche pendant la boucle whilepuis bouché en sortie de boucle avec la dernière instructionliste[j+1] = tmp.
[125]: def triInsertion(l,g,d):# version donnée par le sujet
#tri la liste entre les indices g,d inclus
print("entree TriI :{},{},{}".format(l[g:d+1],g,d))# pour les tests for i in range(g+1,d+1):# donné par le sujet
j=i-1#donné par le sujet tmp=l[i]# donné par le sujet
while l[j][0]>tmp[0] and j>=g: #complété à partir d'ici l[j+1]=l[j]
j=j-1
l[j+1]=tmp
print("Sortie TriI :{},{},{}".format(l[g:d+1],g,d))# pour les tests [126]: l=[[10,0],[5,0],[7,0],[2,0],[6,0],[0,0]]
print(l)
triInsertion(l,1,4) l
[[10, 0], [5, 0], [7, 0], [2, 0], [6, 0], [0, 0]]
entree TriI :[[5, 0], [7, 0], [2, 0], [6, 0]],1,4 Sortie TriI :[[2, 0], [5, 0], [6, 0], [7, 0]],1,4 [126]: [[10, 0], [2, 0], [5, 0], [6, 0], [7, 0], [0, 0]]
Ce code de Tri par insertion est certes efficace (une seule opération d’écriture dans la boucle interne contre deux dans le code de mon cours) mais la lignel[j+1]=tmp a troublé certains d’entre vous.
Pour coller plus à mon cours, on pouvait écrire des échanges pendant la boucle et supprimer la dernière instruction :
[54]: def triInsertion(l,g,d):# version plus proche du cours
#tri la liste entre les indices g,d inclus
print("entree TriI :{},{},{}".format(l[g:d+1],g,d)) for i in range(g+1,d+1):# donné par le sujet
j=i-1#donné par le sujet tmp=l[i]# donné par le sujet
while l[j][0]>tmp[0] and j>=g: #complété à partir d'ici l[j+1],l[j]=l[j],l[j+1]
j=j-1
print("Sortie TriI :{},{},{}".format(l[g:d+1],g,d)) [55]: l=[[10,0],[5,0],[7,0],[2,0],[6,0],[0,0]]
print(l)
triInsertion(l,1,4) l
[[10, 0], [5, 0], [7, 0], [2, 0], [6, 0], [0, 0]]
entree TriI :[[5, 0], [7, 0], [2, 0], [6, 0]],1,4 Sortie TriI :[[2, 0], [5, 0], [6, 0], [7, 0]],1,4 [55]: [[10, 0], [2, 0], [5, 0], [6, 0], [7, 0], [0, 0]]
7 Q 15 (retour)
Pour mes tests, je choisis 3 et non 15 (valeur indiquée par le sujet) comme seuil d’appel : c’est plus facile à tester !
On observe que dès que la portion d eliste à trier est plus petite que 3, c’est effectivement le tri par insertion qui termine le travail amorcé par le tri rapide.
[56]: def triRapide ( l , g , d, e=3 ) : if d-g<e:
"""
on serait tenté de mettre d-g<=e mais ce ce serait oublier qu'alors on traiterait les indices g,g+1,..,g+e
c'est à dire (e+1) indices
"""
triInsertion(l,g,d) else:
print("entree TriR :{},{},{}".format(l,g,d)) i,j=g,d
p=l[randint(g,d)][0]
while True :
while i<=d and l[ i ] [ 0 ] < p:
#chercher le 1er indice d'une hauteur d-g>=p i=i +1
while j>=g and l [ j ] [ 0 ] > p :
#chercher le dernier indice d'une hauteur <=p j=j-1
if i >j :
#le pivot devrait être entre i et j break
if i <j :
#à gauche, on met les points plus petits que p
#à droite, les plus grands l[ i ] ,l[ j ]= l[ j ] , l[ i ] i=i +1
j=j -1 if g<j :
triRapide ( l , g , j ) if i <d :
triRapide ( l , i , d) [57]: l=[[10,1],[4,5],[6,8],[12,11],\
[3,9],[1,8],[10,5],[15,5],[9,8],[34,0]]
print(l)
triRapide(l,0,len(l)-1) print(l)
[[10, 1], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [9, 8], [34, 0]]
entree TriR :[[10, 1], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [9, 8], [34, 0]],0,9
entree TriR :[[9, 8], [4, 5], [6, 8], [10, 5], [3, 9], [1, 8], [12, 11], [15, 5], [10, 1], [34, 0]],0,5
entree TriR :[[1, 8], [4, 5], [6, 8], [3, 9], [10, 5], [9, 8], [12, 11], [15, 5], [10, 1], [34, 0]],0,3
entree TriI :[[4, 5], [6, 8], [3, 9]],1,3 Sortie TriI :[[3, 9], [4, 5], [6, 8]],1,3 entree TriI :[[10, 5], [9, 8]],4,5
Sortie TriI :[[9, 8], [10, 5]],4,5
entree TriR :[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [12, 11], [15, 5], [10, 1], [34, 0]],6,9
entree TriI :[[15, 5], [12, 11], [34, 0]],7,9 Sortie TriI :[[12, 11], [15, 5], [34, 0]],7,9
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [10, 1], [12, 11], [15, 5], [34, 0]]
[58]: # seconde version
def triRapide ( l , g , d, e=3 ) :
print("entree TriR :{},{},{}".format(l,g,d)) i,j=g,d
p=l[randint(g,d)][0]
while True :
while i<=d and l[ i ] [ 0 ] < p:
#chercher le 1er indice d'une hauteur d-g>=p i=i +1
while j>=g and l [ j ] [ 0 ] > p :
#chercher le dernier indice d'une hauteur <=p j=j-1
if i >j :
#le pivot devrait être entre i et j break
if i <j :
#à gauche, on met les points plus petits que p
#à droite, les plus grands l[ i ] ,l[ j ]= l[ j ] , l[ i ] i=i +1
j=j -1 if g<j :
if j-g<15:
triInsertion(l,g,j) else:
triRapide ( l , g , j ) if i <d :
if d-i<15:
triInsertion(l,i,d) else:
triRapide ( l , i , d) [59]: l=[[10,1],[4,5],[6,8],[12,11],\
[3,9],[1,8],[10,5],[15,5],[9,8],[34,0]]
print(l)
triRapide(l,0,len(l)-1) print(l)
[[10, 1], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [9, 8], [34, 0]]
entree TriR :[[10, 1], [4, 5], [6, 8], [12, 11], [3, 9], [1, 8], [10, 5], [15, 5], [9, 8], [34, 0]],0,9
entree TriI :[[9, 8], [4, 5], [6, 8], [10, 5], [3, 9], [1, 8]],0,5 Sortie TriI :[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5]],0,5 entree TriI :[[12, 11], [15, 5], [10, 1], [34, 0]],6,9
Sortie TriI :[[10, 1], [12, 11], [15, 5], [34, 0]],6,9
[[1, 8], [3, 9], [4, 5], [6, 8], [9, 8], [10, 5], [10, 1], [12, 11], [15, 5], [34, 0]]
8 Q17
La variance est la moyenne des carrés moins le carré de la moyenne,selon KH.
[60]: def kh(t):
"""variance par Koenig Huyghens"""
m2=moyenne([e**2 for e in t]) m=moyenne(t)
return m2-m**2 def ecartType(t):
return kh(t)**0.5 [61]: t=[1,2,3]
m2=moyenne([e**2 for e in t]) m=moyenne(t)
kh(t),m2,m
[61]: (0.666666666666667, 4.666666666666667, 2.0)
8.1 Q17
Dans l’algorithme proposé,
def skewness(liste_hauteurs):
n = len(liste_hauteurs)
et3 = (ecartType(liste_hauteurs))**3 S = 0
for i in range(n):
S += (liste_hauteurs[i] - moyenne(liste_hauteurs))**3
S = n/(n-1)/(n-2) * S/et3 return S
pour une liste de longueur n, le calcul de la moyenne (en O(n)) se fait à chaque passage dans la boucle, donc en O(n2).
Le calculer une fois pour toute avant la boucle, ramène le calcul à unO(n) [62]: #comprendre les divisions successives :
6/2/3
[62]: 1.0
[63]: def skewness(lh):
n=len(lh)
e3=(ecartType(lh))**3 m=moyenne(lh)
S=0
for i in range(n):
S+=(lh[i]-m)**3 S=n/(n-1)/(n-2)*S/e3 return S
8.2 Q18
Non, pas de différence de type de complexité pour Skewness et Kurtosis : elles sont toutes les deux en O(n).
En effet, la seule boucle dans leur code est celle qu’il faut pour évaluer la somme :
• une différence suivi d’une élévation d’un nombre au cube pour Skewness pour chaque passage dans la boucle : donc O(1)par passage
• une différence suivi d’une élévation d’un nombre à la puissance 4 pour Kurtosis pour chaque passage dans la boucle : doncO(1)par passage
Les autres opérations(hors boucles) dans les deux fonctions sont enO(1)
9 Partie IV BDD
IL FAUT EXPLIQUER LES REQUÊTES LONGUES !!
[64]: import sqlite3
conn = sqlite3.connect('houle.db') [65]: #curseur
c = conn.cursor()
9.1 Construction d’une base pour les tests [66]: rq="""
DROP TABLE if EXISTS Bouee;
CREATE TABLE IF NOT EXISTS Bouee (idBouee INT PRIMARY KEY,
nomSite TEXT NOT NULL, localisation TEXT NOT NULL, typeCapteur TEXT NOT NULL, frequence REAL NOT NULL );
"""
# Create table c.executescript(rq)
# Insert a row of data rq="""
INSERT INTO Bouee VALUES (831,'Porquerolles','Mediterranee','DTWND',2.00)
"""
c.execute(rq) rq="""
INSERT INTO Bouee VALUES (291,'Les pierres noires',"Mer d\'Iroise",'DTWD',1.28)
"""
c.execute(rq)
rq="""
INSERT INTO Bouee VALUES (456,'Saint-Pierre',"Ocean Indien",'DTND',2.35)
"""
c.execute(rq) conn.commit()
[67]: rq="select * from Bouee"
c.execute(rq) t=c.fetchall() for e in t:
print(e)
(831, 'Porquerolles', 'Mediterranee', 'DTWND', 2.0)
(291, 'Les pierres noires', "Mer d'Iroise", 'DTWD', 1.28) (456, 'Saint-Pierre', 'Ocean Indien', 'DTND', 2.35)
[68]: rq="""
DROP TABLE if EXISTS Campagne;
CREATE TABLE IF NOT EXISTS Campagne
(idCampagne INT PRIMARY KEY, idBouee INT NOT NULL,
debutCampagne TEXT NOT NULL, finCampagne TEXT NOT NULL,
FOREIGN KEY(idBouee) REFERENCES Bouee(idBouee) );
"""
# Create table c.executescript(rq)
# Insert a row of data rq="""
INSERT INTO Campagne VALUES (08301,831,'2010-01-01','2010-01-15')
"""
c.execute(rq) rq="""
INSERT INTO Campagne VALUES (02911,291,'2005-10-15','2005-10-18')
"""
c.execute(rq) conn.commit()
[100]: #une fonction d'affichage des résultats de requête def affiche(req):
c.execute(req) t=c.fetchall() for e in t:
print(e)
[101]: rq="select * from Campagne"
affiche(rq)
(8301, 831, '2010-01-01', '2010-01-15') (2911, 291, '2005-10-15', '2005-10-18') [102]: rq="""
DROP TABLE if EXISTS Tempete;
CREATE TABLE IF NOT EXISTS Tempete (idCampagne INT PRIMARY KEY,
idBouee INT NOT NULL,
debutTempete TEXT NOT NULL, finTempete TEXT NOT NULL, Hmax REAL NOT NULL,
FOREIGN KEY(idBouee) REFERENCES Bouee(idBouee) );
"""
# Create table c.executescript(rq)
# Insert a row of data rq="""
INSERT INTO Tempete VALUES (083010,831,'2010-01-07','2010-01-09',5.3)
"""
c.execute(rq) rq="""
INSERT INTO Tempete VALUES (029012,291,'2005-10-16','2005-10-18',8.5)
"""
c.execute(rq) rq="""
INSERT INTO Tempete VALUES (02989,831,'2010-09-16','2010-09-17',10.5)
"""
c.execute(rq) conn.commit()
[103]: rq="select * from Tempete"
affiche(rq)
(83010, 831, '2010-01-07', '2010-01-09', 5.3) (29012, 291, '2005-10-16', '2005-10-18', 8.5) (2989, 831, '2010-09-16', '2010-09-17', 10.5)
9.2 Q19
a) Quels sont le numéro d’identification et le nom de site des bouées localisées en Méditerrannée ?
SELECT idBouee, nomSite FROM Bouee WHERE localisation='Mediterranee'
[104]: #test Python/SQL
rq="""SELECT idBouee, nomSite FROM Bouee WHERE localisation='Mediterranee'
"""
affiche(rq)
(831, 'Porquerolles')
b) Quel est le numéro d’identification des bouées où il n’y a pas eu de tempêtes ? SELECT idBouee FROM Bouee WHERE idBouee
NOT IN (select idBouee from Tempete)
ou (valable en SQLite) : SELECT idBouee FROM Bouee EXCEPT
SELECT idBouee FROM Tempete [105]: #test Python/SQL
rq="""SELECT idBouee FROM Bouee WHERE idBouee NOT IN (select idBouee from Tempete)"""
affiche(rq) (456,)
[106]: #test Python/SQL
rq="""SELECT idBouee FROM Bouee EXCEPT
SELECT idBouee FROM Tempete"""
affiche(rq) (456,)
c) Pour chaque nom de site, quelle est la hauteur maximale enregistrée lors d’une tempête ?
Les motspour chaque site doivent faire penser à une aggrégation (Group BY) On fait une jointure naturelle (SQLite)
SELECT nomSite, MAX(Hmax) FROM Bouee NATURAL JOIN Tempete
GROUP BY nomSite
ou bien, si on ne dispose pas du NATURAL JOIN(MySQL):
SELECT nomSite, MAX(Hmax) FROM Bouee AS B JOIN Tempete AS T
ON T.idBouee = B.idBouee GROUP BY nomSite
[107]: #test Python/SQL
rq="""SELECT nomSite, MAX(Hmax) FROM BOUEE NATURAL JOIN Tempete
GROUP BY nomSite
"""
affiche(rq)
('Les pierres noires', 8.5) ('Porquerolles', 10.5) [109]: #test Python/SQL
rq="""SELECT nomSite, MAX(Hmax) FROM Bouee AS B JOIN Tempete AS T
ON T.idBouee = B.idBouee GROUP BY nomSite
"""
affiche(rq)
('Les pierres noires', 8.5) ('Porquerolles', 10.5)
d) déterminer les sites qui ont subi au moins deux tempêtes.
Il s’agit de compter les tempêtes PAR (doncGROUP BY) nom de site SELECT nomSite from Bouee
NATURAL JOIN Tempete GROUP BY idBouee HAVING COUNT(*)>1
LeNATURAL JOINenSQLITEme permet d’éviter d’écrire le critère de jointure suridBoueepuisqu’il est … naturel !
[110]: #test Python/SQL
rq="""SELECT nomSite from Bouee NATURAL JOIN Tempete
GROUP BY idBouee HAVING COUNT(*)>1
"""
affiche(rq) ('Porquerolles',)
e) Donner l’identiant et la durée de la campagne de mesure la plus courte [96]: #test Python/SQL
rq = """SELECT julianday('2010-01-15')-julianday('2009-12-30')"""
affiche (rq) (16.0,)
De façon inélégante, on calcule la différence entre la date de fin et de début et on ne sélectionne que les lignes dont cette différence est la plus petite :
SELECT idCampagne, julianday(finCampagne)-julianday(debutCampagne) AS D FROM Campagne
WHERE D = (SELECT MIN(julianday(finCampagne)-julianday(debutCampagne)) FROM Campagne) De façon plus concise, en utilisant finement la syntaxe SQL :
SELECT idCampagne, MIN(julianday(finCampagne)-julianday(debutCampagne)) FROM Campagne
[80]: #test Python/SQL rq = """
SELECT idCampagne, MIN(julianday(finCampagne)-julianday(debutCampagne)) FROM Campagne
"""
affiche(rq) (2911, 3.0) [81]: #test Python/SQL
rq = """
SELECT idCampagne, julianday(finCampagne)-julianday(debutCampagne) AS D FROM Campagne
WHERE D = (SELECT MIN(julianday(finCampagne)-julianday(debutCampagne)) FROM␣
,→Campagne)
"""
affiche(rq) (2911, 3.0)
Dernière version qui ne tient pas compte du fait que, peut-être, il y a plusieurs campagnes de durées minimales :
[82]: #test Python/SQL rq = """
SELECT idCampagne, MIN(julianday(finCampagne)-julianday(debutCampagne)) AS D FROM Campagne GROUP BY idCampagne
ORDER BY D DESC LIMIT 1
"""
affiche(rq) (8301, 14.0)
10 Q20
Pour calculer une TFD de n éléments, on évalue deux TFD (P et I) de N/2 éléments. Puis on recombine les deux listes obtenues (listeP contenant lesPk, liste I contenant lesIk) pour calculer les N éléments de X.
Comme il faut :
• constituer les moitiés de listes contenant les éléments pairs et impairs,
• faire un nombre fixe d’opérations pour chaque indice entre 0 et N−1 pour constituerX, PosonsN = 2k. La complexité est majorée par un multiple de la suite(CN)définie par la récurrence CN = 2CN/2+N (déjà étudiée pour le tri fusion). Elle est enO(Nlog2N)comme vu dans le cours pour le tri fusion. Et ça suffit comme preuve.
Mais si on ne s’en souvient plus, alors calculons :
CN = 2CN/2+N = 2CN/2+ 1N
= 2(2CN/4+N/2) +N
= 22CN/22+ 2N
= . . .
= 2kC1+kN
= C1N +Nlog2N =O(Nlog2N)
11 Q21
En python, le nombre complexe de carré 1 usuellement notéi en mathématiques, est noté1j.
[83]: 1j**2, np.exp(2*1j*np.pi/3)
[83]: ((-1+0j), (-0.4999999999999998+0.8660254037844387j)) [84]: from numpy import pi, exp, zeros, sin, cos, linspace [85]: import numpy as np
[86]: def tfd(x):# V1 avec tableaux numpy N=len(x)
if N==1:
return x
pairs=x[::2]#les indices pairs impairs=x[1::2]#les indices impairs
X=zeros(N,dtype=complex)# le tableau résultat w, wk = exp(-2*pi*1j/N), 1 # omega, omega^0 P=tfd(pairs)#les p_k
I=tfd(impairs)#les i_k for k in range(N//2):
X[k]=P[k]+wk*I[k]
X[k+N//2]=P[k]-wk*I[k]
wk=wk*w # w**k return X
[87]: def tfd(x):# V2 avec des listes N=len(x)
if N==1:
return x
pairs=[x[i] for i in range(N) if i%2==0]#les indices pairs impairs=[x[i] for i in range(N) if i%2==1]#les indices impairs X=[0]*N
w,wk=exp(-2*pi*1j/N),1 P=tfd(pairs)#les p_k I=tfd(impairs)#les i_k
for k in range(N//2):
X[k]=P[k]+wk*I[k]
X[k+N//2]=P[k]-wk*I[k]
wk=wk*w return X [88]: 1j**2
[88]: (-1+0j)
[89]: f1,f2,f3=10,30,100
t=linspace(0,1,2**10)#longueur : puissance de de deux s1,s2,s3=sin(2*pi*f1*t),3*cos(2*pi*f2*t),-5*sin(2*pi*f3*t) x=s1+s2+s3
X=tfd(x) X[:6]
[89]: [3.0000000000001084,
(3.0034727638307794-0.04328773018535386j), (3.013973751095296-0.09277602840312374j), (3.0317652365262227-0.15604349691598984j), (3.0573401773777173-0.24411287163028234j), (3.0915459771711546-0.3755521335346603j)]
[90]: fig,ax=plt.subplots() plt.plot(t,x)
plt.xlabel("temps en seconde") plt.ylabel("signal")
plt.show()
[91]: X[-10:-5]
[91]: [(19.052426335646032+510.8365837251951j), (3.411819858233947+4.160726381048761j), (3.2726108834669594+1.7426157471852197j), (3.1934827939724304+0.9596729320971129j), (3.1358950070238882+0.5864043533696062j)]
[92]: np.abs(X[:6])
[92]: array([3. , 3.00378469, 3.01540133, 3.03577832, 3.06707027, 3.11427294])
On calcule le module de chaque élément du tableau retourné par TFD. On trace la courbe avec en abscisse, les indices des cases de la TFD, et en ordonné les modules calculés.
Les indices des cases correspondent à des fréquences. En effet, on a pris210 temps entre 0 et 1.
[93]: plt.plot(np.abs(X[:len(x)//2])) plt.xlabel("fréquneces en Hz") plt.ylabel("tfd")
plt.xlim(0,150) plt.show()
12 Tests Réponses étudiants
[116]: req = """SELECT localisation, Bouee.idBouee FROM Tempete, Bouee WHERE Bouee.idBouee = Tempete.idBouee
EXCEPT
SELECT DISTINCT localisation, Bouee.idBouee FROM Tempete, Bouee WHERE Bouee.idBouee = Tempete.idBouee
"""
affiche(req) [127]: 48*19200
[127]: 921600
[129]: #test Python/SQL
rq="""SELECT idBouee FROM Bouee NOT IN Tempete"""
affiche(rq)
␣
,→---
OperationalError Traceback (most recent call␣
,→last)
<ipython-input-129-fb904259f3c8> in <module>
2 rq="""SELECT idBouee FROM Bouee 3 NOT IN Tempete"""
----> 4 affiche(rq)
<ipython-input-100-d8d41e949e5a> in affiche(req)
1 #une fonction d'affichage des résultats de requête 2 def affiche(req):
----> 3 c.execute(req) 4 t=c.fetchall() 5 for e in t:
OperationalError: near "IN": syntax error
[133]: 15*24 [133]: 360
[ ]: