Corrigé CCMP 2020
Partie SQLâïž
Q1. Proposez une requĂȘte SQL permettant de compter le nombre de maillages que contient le modĂšle du bateau.
Q2. Proposez une requĂȘte SQL permettant de rĂ©cupĂ©rer la liste des numĂ©ros des facettes (numero) du maillage nommĂ© « gouvernail ».
SELECT f.numero
FROM faces AS f
JOIN maillages_bateau AS m
ON f.maillage = m.id
WHERE m.nom = 'gouvernail';
Q3. Expliquez ce que renvoie la requĂȘte SQL suivante :
SELECT (MAX(x) - MIN(x))
FROM sommets AS s
JOIN faces AS f
JOIN maillages_bateau AS m
ON (s.id = f.s1 OR s.id = f.s2 OR s.id = f.s3) AND f.maillage = m.id
WHERE m.nom = "coque";
Cette requĂȘte calcule l'Ă©cart maximal (Ă©tendue) entre les abscisses \(x\) des sommets qui composent les facettes appartenant au maillage nommĂ© « coque ».
Q4 â Ă partir de la variable maillage_tetra, Ă©crire une expression Python permettant de rĂ©cupĂ©rer la coordonnĂ©e y du premier sommet de la premiĂšre facette.
Pour récupérer la coordonnée \(y\) du premier sommet de la premiÚre facette :
Cette expression accĂšde Ă la premiĂšre facette (maillage_tetra[0]
), puis au premier sommet de cette facette ([0]
), et enfin à la coordonnée \(y\) de ce sommet ([1]
).
Q5 â Ă quel Ă©lĂ©ment, sur la figure 2(a), correspond maillage_tetra[1] ?
maillage_tetra[1]
correspond à la facette définie par les trois sommets suivants :
- [0., 0., 0.] (point A)
- [0., 1., 0.] (point D)
- [1., 0., 0.] (point B)
Cette facette représente le triangle formé par les sommets A, B et D sur la figure 2(a). C'est à dire la face \(S_4\)
Q6 â On souhaite utiliser les fonctions de ce module depuis un autre fichier Python. ComplĂ©tez le code ci-dessous afin quâil fournisse le rĂ©sultat attendu :
Pour importer la fonction prod_scalaire
, le nom du module qui la précise est nécéssaire. as
permet l'abréviation (renommage).
voici la syntaxe:
from operations_vectorielles import prod_scalaire as ps
Q7 â Que fait la fonction mystere1 ?
La fonction mystere1
calcule le produit scalaire V.V
.
Elle renvoie donc la norme de V.
Q8 â CrĂ©er la fonction multiplie_scalaire
, prenant comme argument un flottant a et un vecteur V et renvoyant un nouveau vecteur correspondant Ă a \(\vec{V}\) .
Il faut multiplier chacune des coordonnées par le scalaire.
Q9 â ComplĂ©ter les lignes 4 et 5 permettant de calculer le barycentre.
Voici la fonction complétée
def barycentre ( F ):
G = [0 ,0 ,0]
for i in range (3): #Pour chaque point de F
point = F[i]
G = [ G[i] + point[i] / 3 for i in range(3)] # Chaque point de la face compte pour 1/3 dans le calcul du barycentre.
return G
Il est aussi possible d'utiliser les fonctions du module operations_vectorielles pour trouver les coordonnées du barycentre.
Q10 â Pour une facette F=(A,B,C) dâaire non-nulle, proposer une fonction normale, prenant comme argument une facette F et renvoyant le vecteur unitaire normal
def normale(F):
A, B, C = F # designent les points A,B,C et les vecteurs OA,OB,OC
AB = soustraction(B,A)
AC = soustraction(C,A)
pv = prod_vectoriel(AB,AC)
return multiplie_scalaire((sum([c** 2 for c in pv])**0.5,pv)
Q11 â Compte tenu de la reprĂ©sentation limitĂ©e des nombres rĂ©els en machine, deux sommets S1 et S2 supposĂ©s ĂȘtre au mĂȘme endroit peuvent avoir des coordonnĂ©es lĂ©gĂšrement diâ”Ă©rentes. Proposer une fonction sont_proches, prenant comme arguments deux sommets S1 et S2 (reprĂ©sentĂ©s par leur vecteur position) et un flottant positif eps, et qui renvoie True si S1 et S2 sont proches (i.e. si leur distance au sens de la norme Euclidienne est infĂ©rieure Ă eps) et False sinon.
En utiliasant la fonction mystere1
:
Q12 â Sous quelle condition la fonction mystere2 renvoie-t-elle True ?
La fonction mystere2
teste la distance du sommet S1 Ă tous les sommets de la liste L.
Elle retourne True
dĂšs que l'un des sommets est proche (Ă \(10^{-7}\) prĂšs) de S1.
Elle retourne False
sinon.
Q13 â Donner (sans justification) ce que renvoie mystere3(maillage_tetra), dans le cas oĂč maillage_tetra est la variable dĂ©finie prĂ©cĂ©demment.
Elle retourne : [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0]]
Q14 â Pour une liste L de longueur n, discuter la complexitĂ© de la fonction mystere2. En dĂ©duire la complexitĂ© de mystere3, pour un maillage contenant m facettes triangulaires. On distinguera le meilleur et le pire des cas.
- La complexité est proportionnelle au nombre de passages dans la boucle.
- Chaque itération de la boucle s'effectue en \(\mathcal{O}(1)\) (complexité constante pour la fonction
sont_proches
). Le reste du traitement est négligeable.
Meilleur cas :
- Si
S1
est proche du premier élément deL
, il n'y a qu'un seul passage dans la boucle. - Complexité : \(\mathcal{O}(1)\).
Pire cas :
- Si
S1
n'est proche d'aucun élément deL
ou seulement du dernier élément deL
, on parcourt la liste entiÚre. - Complexité : \(\mathcal{O}(n)\).
Complexité de mystere3
(pour un maillage contenant m facettes triangulaires)
Meilleur cas :
- Tous les sommets sont identiques.
- Le test de la ligne 12 s'effectue toujours en \(\mathcal{O}(1)\). Ce test est répété \(3m\) fois (3 sommets par facette).
- La ligne 13 n'est exécutée qu'une seule fois lors du premier passage dans les boucles.
- Complexité : \(\mathcal{O}(m)\).
Pire cas :
- Aucun sommet n'est proche d'un autre.
- La liste
res
croßt à chaque itération, et la complexité de chaque itération dépend demystere2
(pire cas : \(\mathcal{O}(n)\) oĂč \(n\) est la longueur deres
). - Il y a \(3m\) itérations au total.
- Complexité : \(\mathcal{O}(m^2)\).
Calcul du pire cas :âïž
Complexité = \(sum_{k=1}^{3m} k\) = \({3m(3m + 1)}/{2}\) \(\mathcal{O}(m^2)\)
Quel est lâespace occupĂ© en mĂ©moire vive par lâensemble des donnĂ©es (en Mo).
Formule de calculâïž
MĂ©moire = (350 Ă 200 Ă 200 Ă 64) / (8 Ă 1024ÂČ) â 107 Mo
Q16 â Ăcrire une fonction mat2str qui prend en argument une liste de listes (reprĂ©sentant un mat_h) et renvoie les donnĂ©es quâelle contient sous forme dâune chaıÌne de caractĂšres qui respecte le format suivant :
def mat2str(mat_h):
ch = ""
for i in range(len(mat_h)): # Parcours des lignes
for j in range(len(mat_h[i])): # Parcours des colonnes
ch += str(mat_h[i][j]) # conversion au format str de hij et concaténation à ch
if j != len(mat_h[i]) - 1: # si avant fin de ligne
ch += "; " # ajout ;
else:
ch += "\n" # sinon ajout retour Ă la ligne
return ch
Q17 â En sâappuyant sur mat2str, proposer un code Python qui permet de sauvegarder le contenu de liste_vagues dans un fichier nommĂ© fichier_vagues.txt (dans le rĂ©pertoire courant), en sĂ©parant la reprĂ©sentation de chaque mat_h par deux sauts de lignes consĂ©cutifs.
fichier = open("fichiers_vagues.txt", "w")
for mat_h in liste_vagues:
fichier.write(mat2str(mat_h))
fichier.write("\n\n") # Deux lignes séparent chaque mat_h
fichier.close()
Q18 â AprĂšs avoir dĂ©fini judicieusement les types des Ă©lĂ©ments contenus dans I, J puis N, estimer la taille (en octets) que prendra une matrice ayant p Ă©lĂ©ments non-nuls, au format « Coordinate Format », dans le fichier.
- Les éléments de
I
etJ
sont des entiers, ceux deN
sont des flottants. - HypothÚse : les entiers entre 0 et 199 sont codés en moyenne sur 2,45 caractÚres : (10 x 1 + 90 x 2 + 100 x 3) / 200
Calcul du nombre de caractĂšres :âïž
- Pour I et J : 3.45p (avec les séparateurs et retours à la ligne).
- Pour N : 16p.
- total : 22.90p
Taille en octets (ASCII) :âïž
22.90p
Q19 â En dĂ©duire Ă partir de combien dâĂ©lĂ©ments non-nuls il devient moins avantageux dâenregistrer une matrice creuse quâune matrice complĂšte classique.
La matrice classique occupe 320000 octets ( \(200^2\) x 8 octets) La matrice creuse occupe 22.90p
Ainsi dÚs que p est supérieur à 13973, la matrice creuse n'est plus avantageuse.
Cela corrspond Ă environ 35 % de la matrice (200 x 200).
Q20 â Proposer un code permettant de construire, pour un tableau mat_h donnĂ©, les listes Python I,J et N. On considĂ©rera nulles les hauteurs infĂ©rieures Ă \(10^{-3}\) (en valeur absolue).
I, J, N = [], [], []
for i in range(len(mat_h)):
for j in range(len(mat_h[i])):
if abs(mat_h[i][j]) > 1e-3:
I.append(i)
J.append(j)
N.append(mat_h[i][j])
Q21 â Proposer une fonction lister_FI prenant comme argument un maillage M et renvoyant la liste des facettes immergĂ©es (i.e dont le centre de gravitĂ© est sous la surface dĂ©finie par hauteur). On pourra utiliser les fonctions de la partie I.
def lister_FI(M):
L = []
for facette in M:
x, y, z = barycentre(facette)
if z < hauteur(x, y):
L.append(facette)
return L
Q22 â Proposer une fonction force_facette prenant en argument une facette F, et renvoyant le vecteur force appliquĂ© par lâeau sur cette facette. On pourra utiliser les fonctions dĂ©finies prĂ©cĂ©demment.
def force_facette(F):
rho, g = 1000, 9.81
S = aire(F)
n = normale(F)
x, y, z = barycentre(F)
p = rho * g * (hauteur(x, y) - z)
return multiplie_scalaire(-S * p, n)
Q23 â DĂ©finir la fonction resultante prenant comme argument une liste L de facettes (supposĂ©es immergĂ©es), renvoyant la somme des forces sur lâaxe ! \(\vec{z}\) de lâeau, appliquĂ©e sur lâensemble des surfaces.
def resultante(L):
res = 0.0
for F in L:
res += force_facette(F)[2] # le 3Ăšme elt de force_facette(F) est selon l'axe z
return res
Q24 â ComplĂ©ter la fonction fusion, prenant comme argument deux listes de facettes L1 et L2 (supposĂ©e chacune triĂ©e par aire dĂ©croissante) et renvoyant une nouvelle liste composĂ©e des facettes de L1 et L2 triĂ©es par aire dĂ©croissante.
def fusion(L1, L2):
L = []
while len(L1) != 0 and len(L2) != 0:
if aire(L1[0]) > aire(L2[0]):
L.append(L1.pop(0))
else:
L.append(L2.pop(0))
L += L1 + L2 # pour concaténer le reste de la liste non vide
return L
Q25 â ComplĂ©ter la fonction rĂ©cursive trier_facettes, prenant comme argument une liste de facettes L, et renvoyant une nouvelle liste de facettes triĂ©es dans lâordre des aires dĂ©croissantes, par la mĂ©thode du tri-fusion.
La fonction trier_facettes
est une implĂ©mentation rĂ©cursive de lâalgorithme de tri fusion (âmĂ©langeâ). Voici le code avec des explications :
def trier_facettes(L):
if len(L) <= 1:
return L
else:
m = len(L) // 2
L1 = trier_facettes(L[:m]) # Tri de la premiÚre moitié
L2 = trier_facettes(L[m:]) # Tri de la deuxiÚme moitié
return fusion(L1, L2) # Fusion des deux listes triées
Cet algorithme divise la liste en deux parties jusqu'Ă ce quâelles contiennent un seul Ă©lĂ©ment, puis les fusionne en respectant lâordre croissant. La fonction fusion
est supposĂ©e ĂȘtre prĂ©dĂ©finie.
Q26 â Aâ”ecter Ă une nouvelle variable grandesFacettes la liste des facettes de maillageG, privĂ©e de la moitiĂ© des facettes les plus petites (en cas de nombre impair dâĂ©lĂ©ments, on inclura la facette mĂ©diane).
Pour obtenir les grandes facettes Ă partir du maillage maillageG
, on suppose que les facettes sont triées par ordre décroissant selon leur taille. Le code suivant permet d'extraire les plus grandes facettes :
Ce code divise par deux la liste triée des facettes (en prenant la moitié supérieure).
Q27 â ComplĂ©ter les lignes 4 et 5 du code prĂ©cĂ©dent conformĂ©ment Ă la mĂ©thode dâEuler.
Les équations suivantes mettent à jour la position et la vitesse d'un objet soumis à des forces extérieures :
- Mise Ă jour de la position en fonction de la vitesse :
- Mise à jour de la vitesse en fonction des forces appliquées :
Dans ces expressions :
- `dt` est le pas de temps.
- `m` est la masse de l'objet.
- `resultante(facettes_immergees)` représente la somme des forces appliquées par les facettes immergées.
- `g` est l'accélération gravitationnelle (vecteur).