From a659fffb6040260cbc198fd799bcf740b3b2cda6 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Mon, 29 Apr 2024 18:40:23 +0200 Subject: [PATCH] maj 2024 --- slides/cours_21.md | 746 ------------------------------- slides/cours_22.md | 1052 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1052 insertions(+), 746 deletions(-) create mode 100644 slides/cours_22.md diff --git a/slides/cours_21.md b/slides/cours_21.md index 18e4d0d..fa2120f 100644 --- a/slides/cours_21.md +++ b/slides/cours_21.md @@ -491,749 +491,3 @@ void qt_to_matrix(node *qt, int nb_li, int nb_co, int matrix[nb_li][nb_co]) } ``` -# Transformations avec un arbre quaternaire - -## A faire - -* Symétrie axiale (horizontale/verticale). -* Rotation quart de cercle (gauche/droite). -* Compression. - -# La symétrie verticale - -## Que donne la symétrie verticale de - -``` - SG=0 | SD=1 - 21 | 12 | 4 | 4 - 9 | 7 | 4 | 4 ------------------ - 1 | 1 | 0 | 31 - 1 | 1 | 3 | 27 - IG=2 | ID=3 -``` - -. . . - -``` - SG=0 | SD=1 - 4 | 4 | 12 | 21 - 4 | 4 | 7 | 9 ------------------- - 31 | 0 | 1 | 1 - 27 | 3 | 1 | 1 - IG=2 | ID=3 -``` - -# La symétrie d'axe vertical - -## Comment faire sur une matrice (3min, matrix)? - -. . . - -\footnotesize - -```C -matrice symétrie(matrice) - pour i de 0 à nb_colonnes(matrice) / 2 - pour j de 0 à nb_lignes(matrice) - échanger(matrice[i][j], matrice[nb_colonnes(matrice)-1-i][j]) - retourne matrice -``` - -# La symétrie d'axe vertical - -## Comment faire sur un arbre? - -* Faire un dessin de l'arbre avant/après (5min, matrix) - - ``` - SG=0 | SD=1 SG=0 | SD=1 - 21 | 12 | 4 | 4 4 | 4 | 12 | 21 - 9 | 7 | 4 | 4 4 | 4 | 7 | 9 - ----------------- => ---------------- - 1 | 1 | 0 | 31 31 | 0 | 1 | 1 - 1 | 1 | 3 | 27 27 | 3 | 1 | 1 - IG=2 | ID=3 IG=2 | ID=3 - ``` - -* Écrire le pseudo-code (3min, matrix) - -. . . - -\footnotesize - -```C -arbre symétrie(arbre) - si !est_feuille(arbre) - échanger(arbre.enfant[0], arbre.enfant[1]) - échanger(arbre.enfant[2], arbre.enfant[3]) - pour i de 0 à 3 - symétrie(arbre.enfant[i]) - retourne arbre -``` - -# La symétrie d'axe horizontal - -* Trivial de faire l'axe horizontal (exercice à la maison) - -# Rotation d'un quart de cercle - -## Comment faire sur un arbre? - -* Faire un dessin de l'arbre avant/après (5min, matrix) - - ``` - SG=0 | SD=1 SG=0 | SD=1 - 21 | 12 | 4 | 4 4 | 4 | 31 | 27 - 9 | 7 | 4 | 4 4 | 4 | 0 | 3 - ----------------- => ----------------- - 1 | 1 | 0 | 31 12 | 7 | 1 | 1 - 1 | 1 | 3 | 27 21 | 9 | 1 | 1 - IG=2 | ID=3 IG=2 | ID=3 - - ``` - -* Écrire le pseudo-code (3min, matrix) - -. . . - -```C -rien rotation_gauche(arbre) - si !est_feuille(arbre) - échange_cyclique_gauche(arbre.enfant) - pour i de 0 à 3 - rotation_gauche(arbre.enfant[i]) -``` - -# Rotation d'un quart de cercle - -\footnotesize - -## Comment faire sur un arbre? - -``` - SG=0 | SD=1 SG=0 | SD=1 - 21 | 12 | 4 | 4 4 | 4 | 31 | 27 - 9 | 7 | 4 | 4 4 | 4 | 0 | 3 ------------------ => ----------------- - 1 | 1 | 0 | 31 12 | 7 | 1 | 1 - 1 | 1 | 3 | 27 21 | 9 | 1 | 1 - IG=2 | ID=3 IG=2 | ID=3 -``` - -* Écrire le vrai (5min, matrix) - -. . . - -```C -void rotate(node *qt) { - if (!is_leaf(qt)) { - node *tmp = qt->child[2]; - qt->child[2] = qt->child[0]; - qt->child[0] = qt->child[1]; - qt->child[1] = qt->child[3]; - qt->child[3] = tmp; - for (int i=0;i < 4; i++) { - rotate(qt->child[i]); - } - } -} -``` - -# Compression sans perte (1/5) - -## Idée générale - -* Regrouper les pixels par valeur - -``` - SG=0 | SD=1 SG=0 | SD=1 - 21 | 12 | 4 | 4 21 | 12 | 4 - 9 | 7 | 4 | 4 9 | 7 | ------------------ => ----------------- - 1 | 1 | 0 | 31 1 | 0 | 31 - 1 | 1 | 3 | 27 | 3 | 27 - IG=2 | ID=3 IG=2 | ID=3 -``` - -* Comment faire? - -# Compression sans perte (2/5) - -## Que devient l'arbre suivant? - - - -. . . - -## Arbre compressé - - - -# Compression sans perte (3/5) - -* Si un nœud a tous ses enfants égaux: - * Donner la valeur au nœud, - * Supprimer les enfants. -* Remonter jusqu'à la racine. - -## Écrire le pseudo-code (5min, matrix) - -. . . - -```C -rien compression_sans_pertes(arbre) - si !est_feuille(arbre) - pour i de 0 à 3 - compression_sans_pertes(arbre.enfant[i]) - si derniere_branche(arbre) - valeur, toutes_égales = valeur_enfants(arbre) - si toutes_egales - arbre.info = valeur - detruire_enfants(arbre) -``` - -# Compression sans perte (4/5) - -\footnotesize - -## Écrire le code C (5min, matrix) - -. . . - -```C -void lossless_compression(node *qt) { - if (!is_leaf(qt)) { - for (int i = 0; i < CHILDREN; i++) { - lossless_compression(qt->child[i]); - } - if (is_last_branch(qt)) { - int val = -1; - if (last_value(qt, &val)) { - qt->info = val; - for (int i = 0; i < 4; ++i) { - free(qt->child[i]); - qt->child[i] = NULL; - } - } - } - } -} -``` - -# Compression sans perte (5/5) - -\footnotesize - -```C -bool is_last_branch(node *qt) { - for (int i = 0; i < 4; ++i) { - if (!is_leaf(qt)) { - return false; - } - } - return true; -} -bool last_value(node *qt, int *val) { - int info = qt->child[0]; - for (int i = 1; i < 4; ++i) { - if (info != qt->child[i]) { - return false; - } - } - *val = info; - return true; -} -``` - - -# Compression avec perte (1/5) - -## Idée générale - -* Regrouper les pixels par valeur sous certaines conditions - -``` - SG=0 | SD=1 SG=0 | SD=1 - 21 | 12 | 4 | 3 21 | 12 | 4 - 9 | 7 | 4 | 4 9 | 7 | ------------------ => ------------------ - 1 | 1 | 0 | 31 1 | 0 | 31 - 2 | 1 | 3 | 27 | 3 | 27 - IG=2 | ID=3 IG=2 | ID=3 -``` - -* On enlève si l'écart à la moyenne est "petit"? - -# Compression avec perte (2/5) - -## Que devient l'arbre suivant si l'écart est petit? - - - -. . . - -## Arbre compressé - - - -# Compression avec perte (3/5) - -## Comment mesurer l'écart à la moyenne? - -. . . - -* Avec l'écart-type - -\begin{equation*} -\mu = \frac{1}{4}\sum_{i=0}^{3} p[i],\quad \sigma = \sqrt{\frac{1}{4}\sum_{i=0}^3 (\mu-p[i]) -^2} = \sqrt{\frac{1}{4}\left(\sum_{i=0}^3p[i]^2\right)-\mu^2} -\end{equation*} - -## Que devient l'algorithme? - -. . . - -* Si $\sigma<\theta$, $\theta$ est la **tolérance**: - * Remplacer la valeur du pixel par la moyenne des enfants. - * Remonter les valeurs dans l'arbre. - -## Quelle influence de la valeur de $\theta$ sur la compression? - -. . . - -* Plus $\theta$ est grand, plus l'image sera compressée. - -# Compression avec perte (4/5) - -## Que devient l'arbre avec $\theta=0.5$? - - - -. . . - - - -# Compression avec perte (5/5) - -## Modifications sur la structure de données? - -. . . - -* On stocke la moyenne, et la moyenne des carrés. - -```C -struct noeud - flottant moyenne, moyenne_carre - node enfants[4] -``` - -* Comment on calcule `moyenne` et `moyenne_carre` sur chaque nœud (pseudo-code)? - -# Calcul de la moyenne - -## Pseudo-code (5min, matrix) - -. . . - -```C -rien moyenne(arbre) { - si !est_feuille(arbre) - pour enfant dans arbre.enfants - moyenne(enfant) - pour enfant dans arbre.enfants - arbre.moyenne += enfant.moyenne - arbre.moyenne_carre += enfant.moyenne_carre - arbre.moyenne /= 4 - arbre.moyenne_carre /= 4 -``` - -# La compression avec pertes - -\footnotesize - -## Pseudo-code (5min, matrix) - -. . . - -```C -rien compression_avec_pertes(arbre, theta) - si !est_feuille(arbre) - pour i de 0 à 3 - compression_avec_pertes(arbre.enfant[i]) - si derniere_branche(arbre) - si racine(arbre.moyenne_carre - arbre.moyenne^2) < theta - detruire_enfants(arbre) -``` - -## Le code en entier - -```C -arbre = matrice_à _arbre(matrice) -moyenne(arbre) -compression_avec_pertes(arbre) -``` - -# La dynamique des corps célestes - -## Slides très fortement inspirés du cours de J. Latt, Unige - -## Simulation du problème à $N$-corps - -* Prédiction du mouvement d'un grand nombre de corps célestes. -* Modélisation: - * On se limite aux étoiles; - * Chaque étoile est caractérisée par un point (coordonnées) et une masse; - * On simule en deux dimensions. - * Interactions uniquement par les lois de la gravitation Newtonienne (oui-oui c'est de la **physique**!). - - -# Les équations du mouvement - -## Mouvement de la $i$-ème étoile - -* Algorithme de Verlet ($t_{n+1}=t_n+\delta t$) - - $$ - \vec x_i(t_{n+1})= 2\vec x_i(t_n)-\vec x_i(t_{n-1})+\vec a_i(t_n)\delta t^2. - $$ - -## Force de gravitation - -* $\vec a_i(t_n)=\vec F_i/m_i$. -* Sur l'étoile $i$, la force résultante est donnée par - - $$ - \vec F_i=\sum_{j=1,j\neq i}^N \vec F_{ij}. - $$ - avec - $$ - \vec F_{ij}=\frac{G m_i m_j(\vec x_j-\vec x_i)}{||\vec x_j-\vec x_i||^3}. - $$ - -# Algorithme du problème à $n$-corps - -## Pseudo-code: structure de données - -```C -struct étoile - flottant m - vec x, x_precedent, f -``` - -## Pseudo-code: itération temporelle - -```C -rien iteration_temporelle(étoiles, dt) - pour étoile_une dans étoiles - étoile_une.f = 0 - pour étoile_deux dans étoiles - si (étoile_un != étoile_deux) - étoile_une.f += - force(étoile_une, étoile_deux) - pour étoile dans étoiles - étoile.x, étoile.x_precedent = - verlet(étoile.x, étoile.x_precedent, - étoile.f / étoile.m, dt) -``` - -# Algorithme du problème à $n$-corps - -## Complexité - -* Complexité de chacune des parties? - -. . . - -* $\mathcal{O}(N^2)$, $\mathcal{O}(N)$. - -## En temps CPU pour **une itération** - -\footnotesize - -* Si temps pour $N=1$ on calcule en $1\mu s$: - -+--------+-------+-------+-----------+ -| N | N^2 | t [s] | t [réel] | -+--------+-------+-------+-----------+ -| 10 | 10^2 | 1e-4 | | -+--------+-------+-------+-----------+ -| 10^4 | 10^8 | 1e+2 | ~1min | -+--------+-------+-------+-----------+ -| 10^6 | 10^12 | 1e+6 | ~11j | -+--------+-------+-------+-----------+ -| 10^9 | 10^18 | 1e+12 | ~30k ans | -+--------+-------+-------+-----------+ -| 10^11 | 10^22 | 1e+16 | ~300M ans | -+--------+-------+-------+-----------+ - -* Typiquement il y a des milliers-millions d'itérations. -* Il y a $10^{11}$ étoiles dans la galaxie. -* Houston we have a problem. - -# Question - -## Comment faire mieux, des idées? - -. . . - -* Si un groupe d'étoiles est suffisamment loin, on le modélise comme un corps unique situé en son centre de masse. -* Exemple: Si on simule plusieurs galaxies, on considère chaque galaxie comme un corps unique! -* Un arbre quaternaire est une structure parfaite pour regrouper les étoiles. - -# Le cas à 10 corps - -::: columns - -:::: {.column width=50%} - -## Illustration: le cas à 10 corps - -{width=60%} - -:::: - -:::: {.column width=50%} - -## Problématique - -* On veut calculer la force sur $1$. - -:::: - -::: - -. . . - - -::: columns - -:::: {.column width=50%} - -## Illustration: le cas à 10 corps - -{width=60%} - - -:::: - -:::: {.column width=50%} - -## Résultat - -* Calcul et somme des forces venant des $9$ autre corps. - -:::: - -::: - -# Le cas à 10 corps - -::: columns - -:::: {.column width=50%} - -## Réduction d'un groupe à un seul corps - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Idée - -* On accélère le calcul en traitant un groupe comme un seul corps. -* Fonctionne uniquement si le groupe est assez loin. -* Autrement l'approximation est trop grossière. - -:::: - -::: - -# Solution: l'arbre quaternaire - -## Corps célestes - arbre - - - -* On omet les nœuds vides pour éviter la surcharge. -* La numérotation est: - * 0: ID - * 1: SD - * 2: IG - * 3: SG - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Insertion corps 1 - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Arbre, niveau 1 - -{width=100%} - -* Quadrant ID. -* La feuille est vide, on insère. - -:::: - -::: - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Insertion corps 2 - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Arbre, niveau 1 - -{width=100%} - -* Quadrant SD. -* La feuille est vide, on insère. - -:::: - -::: - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Insertion corps 3 (1/N) - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Arbre, niveau 1 - -{width=100%} - -* Quadrant SD. -* La feuille est prise par 2. - -:::: - -::: - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Insertion corps 3 (2/N) - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Arbre, niveau 2 - -{width=100%} - -* On crée un nouveau nœud. -* Deux corps dans le nœud ID. -* On crée un nouveau nœud. - -:::: - -::: - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Insertion corps 3 (3/N) - -{width=100%} - -:::: - -:::: {.column width=50%} - -## Arbre, niveau 3 - -{width=100%} - -* 2 va dans ID. -* 3 va dans SG. -* C'est des feuilles vides, tout va bien. - -:::: - -::: - -# Exemple d'insertion - -::: columns - -:::: {.column width=50%} - -## Que fait-on avec les nœuds intérieurs? - -* On les utilise pour: - * stocker la masse totale; - * stocker le centre de masse. - -\begin{align} -m&=m_2+m_3,\\ -\vec x &= \frac{m_2\vec x_2+m_3\vec x_3}{m}. -\end{align} - -## Chaque feuille contient **une étoile** - -:::: - -:::: {.column width=50%} - -## Arbre - -{width=100%} - -:::: - -::: - -# Résumé - -* Insertion du corps `c` dans le nœud `n` en partant de la racine. -* Si le nœud `n` - * ne contient pas de corps, on y dépose `c`, - * est interne, on met à jour masse et centre de masse. `c` est inséré récursivement dans le bon quadrant. - * est externe, on subdivise `n`, on met à jour la masse et centre de masse, on insère récursivement les deux nœuds dans les quadrants appropriés. - -## Remarque - -* Il faut stocker les coordonnées des quadrants. -* Un nœud a un comportement différent s'il est interne ou externe. - - diff --git a/slides/cours_22.md b/slides/cours_22.md new file mode 100644 index 0000000..fd865fb --- /dev/null +++ b/slides/cours_22.md @@ -0,0 +1,1052 @@ +--- +title: "Arbres quaternaires" +date: "2024-05-30" +--- + +# Rappel sur ls arbres quaternaires + +## Définition? + +. . . + +* Arbre dont chaque nœud a 4 enfants ou aucun. + +## Utilisation dans ce cours? + +. . . + +* Stockage/compression d'image +* Chaque pixel correspond à une feuille +* Des portions de l'image peuvent être compressées sans/avec perte + + + +# Transformations avec un arbre quaternaire + +## A faire + +* Symétrie axiale (horizontale/verticale). +* Rotation quart de cercle (gauche/droite). +* Compression. + +# La symétrie verticale + +## Que donne la symétrie verticale de + +``` + SG=0 | SD=1 + 21 | 12 | 4 | 4 + 9 | 7 | 4 | 4 +----------------- + 1 | 1 | 0 | 31 + 1 | 1 | 3 | 27 + IG=2 | ID=3 +``` + +. . . + +``` + SG=0 | SD=1 + 4 | 4 | 12 | 21 + 4 | 4 | 7 | 9 +------------------ + 31 | 0 | 1 | 1 + 27 | 3 | 1 | 1 + IG=2 | ID=3 +``` + +# La symétrie d'axe vertical + +## Comment faire sur une matrice (3min, matrix)? + +. . . + +\footnotesize + +```C +matrice symétrie(matrice) + pour i de 0 à nb_colonnes(matrice) / 2 + pour j de 0 à nb_lignes(matrice) + échanger(matrice[i][j], matrice[nb_colonnes(matrice)-1-i][j]) + retourne matrice +``` + +# La symétrie d'axe vertical + +## Comment faire sur un arbre? + +* Faire un dessin de l'arbre avant/après (5min, matrix) + + ``` + SG=0 | SD=1 SG=0 | SD=1 + 21 | 12 | 4 | 4 4 | 4 | 12 | 21 + 9 | 7 | 4 | 4 4 | 4 | 7 | 9 + ----------------- => ---------------- + 1 | 1 | 0 | 31 31 | 0 | 1 | 1 + 1 | 1 | 3 | 27 27 | 3 | 1 | 1 + IG=2 | ID=3 IG=2 | ID=3 + ``` + +* Écrire le pseudo-code (3min, matrix) + +. . . + +\footnotesize + +```C +arbre symétrie(arbre) + si !est_feuille(arbre) + échanger(arbre.enfant[0], arbre.enfant[1]) + échanger(arbre.enfant[2], arbre.enfant[3]) + pour i de 0 à 3 + symétrie(arbre.enfant[i]) + retourne arbre +``` + +# La symétrie d'axe horizontal + +* Trivial de faire l'axe horizontal (exercice à la maison) + +# Rotation d'un quart de cercle + +## Comment faire sur un arbre? + +* Faire un dessin de l'arbre avant/après (5min, matrix) + + ``` + SG=0 | SD=1 SG=0 | SD=1 + 21 | 12 | 4 | 4 4 | 4 | 31 | 27 + 9 | 7 | 4 | 4 4 | 4 | 0 | 3 + ----------------- => ----------------- + 1 | 1 | 0 | 31 12 | 7 | 1 | 1 + 1 | 1 | 3 | 27 21 | 9 | 1 | 1 + IG=2 | ID=3 IG=2 | ID=3 + + ``` + +* Écrire le pseudo-code (3min, matrix) + +. . . + +```C +rien rotation_gauche(arbre) + si !est_feuille(arbre) + échange_cyclique_gauche(arbre.enfant) + pour i de 0 à 3 + rotation_gauche(arbre.enfant[i]) +``` + +# Rotation d'un quart de cercle + +\footnotesize + +## Comment faire sur un arbre? + +``` + SG=0 | SD=1 SG=0 | SD=1 + 21 | 12 | 4 | 4 4 | 4 | 31 | 27 + 9 | 7 | 4 | 4 4 | 4 | 0 | 3 +----------------- => ----------------- + 1 | 1 | 0 | 31 12 | 7 | 1 | 1 + 1 | 1 | 3 | 27 21 | 9 | 1 | 1 + IG=2 | ID=3 IG=2 | ID=3 +``` + +* Écrire le vrai (5min, matrix) + +. . . + +```C +void rotate(node *qt) { + if (!is_leaf(qt)) { + node *tmp = qt->child[2]; + qt->child[2] = qt->child[0]; + qt->child[0] = qt->child[1]; + qt->child[1] = qt->child[3]; + qt->child[3] = tmp; + for (int i=0;i < 4; i++) { + rotate(qt->child[i]); + } + } +} +``` + +# Compression sans perte (1/5) + +## Idée générale + +* Regrouper les pixels par valeur + +``` + SG=0 | SD=1 SG=0 | SD=1 + 21 | 12 | 4 | 4 21 | 12 | 4 + 9 | 7 | 4 | 4 9 | 7 | +----------------- => ----------------- + 1 | 1 | 0 | 31 1 | 0 | 31 + 1 | 1 | 3 | 27 | 3 | 27 + IG=2 | ID=3 IG=2 | ID=3 +``` + +* Comment faire? + +# Compression sans perte (2/5) + +## Que devient l'arbre suivant? + + + +. . . + +## Arbre compressé + + + +# Compression sans perte (3/5) + +* Si un nœud a tous ses enfants égaux: + * Donner la valeur au nœud, + * Supprimer les enfants. +* Remonter jusqu'à la racine. + +## Écrire le pseudo-code (5min, matrix) + +. . . + +```C +rien compression_sans_pertes(arbre) + si !est_feuille(arbre) + pour i de 0 à 3 + compression_sans_pertes(arbre.enfant[i]) + si derniere_branche(arbre) + valeur, toutes_égales = valeur_enfants(arbre) + si toutes_egales + arbre.info = valeur + detruire_enfants(arbre) +``` + +# Compression sans perte (4/5) + +\footnotesize + +## Écrire le code C (5min, matrix) + +. . . + +```C +void lossless_compression(node *qt) { + if (!is_leaf(qt)) { + for (int i = 0; i < CHILDREN; i++) { + lossless_compression(qt->child[i]); + } + if (is_last_branch(qt)) { + int val = -1; + if (last_value(qt, &val)) { + qt->info = val; + for (int i = 0; i < 4; ++i) { + free(qt->child[i]); + qt->child[i] = NULL; + } + } + } + } +} +``` + +# Compression sans perte (5/5) + +\footnotesize + +```C +bool is_last_branch(node *qt) { + for (int i = 0; i < 4; ++i) { + if (!is_leaf(qt)) { + return false; + } + } + return true; +} +bool last_value(node *qt, int *val) { + int info = qt->child[0]; + for (int i = 1; i < 4; ++i) { + if (info != qt->child[i]) { + return false; + } + } + *val = info; + return true; +} +``` + + +# Compression avec perte (1/5) + +## Idée générale + +* Regrouper les pixels par valeur sous certaines conditions + +``` + SG=0 | SD=1 SG=0 | SD=1 + 21 | 12 | 4 | 3 21 | 12 | 4 + 9 | 7 | 4 | 4 9 | 7 | +----------------- => ------------------ + 1 | 1 | 0 | 31 1 | 0 | 31 + 2 | 1 | 3 | 27 | 3 | 27 + IG=2 | ID=3 IG=2 | ID=3 +``` + +* On enlève si l'écart à la moyenne est "petit"? + +# Compression avec perte (2/5) + +## Que devient l'arbre suivant si l'écart est petit? + + + +. . . + +## Arbre compressé + + + +# Compression avec perte (3/5) + +## Comment mesurer l'écart à la moyenne? + +. . . + +* Avec l'écart-type + +\begin{equation*} +\mu = \frac{1}{4}\sum_{i=0}^{3} p[i],\quad \sigma = \sqrt{\frac{1}{4}\sum_{i=0}^3 (\mu-p[i]) +^2} = \sqrt{\frac{1}{4}\left(\sum_{i=0}^3p[i]^2\right)-\mu^2} +\end{equation*} + +## Que devient l'algorithme? + +. . . + +* Si $\sigma<\theta$, $\theta$ est la **tolérance**: + * Remplacer la valeur du pixel par la moyenne des enfants. + * Remonter les valeurs dans l'arbre. + +## Quelle influence de la valeur de $\theta$ sur la compression? + +. . . + +* Plus $\theta$ est grand, plus l'image sera compressée. + +# Compression avec perte (4/5) + +## Que devient l'arbre avec $\theta=0.5$? + + + +. . . + + + +# Compression avec perte (5/5) + +## Modifications sur la structure de données? + +. . . + +* On stocke la moyenne, et la moyenne des carrés. + +```C +struct noeud + flottant moyenne, moyenne_carre + node enfants[4] +``` + +* Comment on calcule `moyenne` et `moyenne_carre` sur chaque nœud (pseudo-code)? + +# Calcul de la moyenne + +## Pseudo-code (5min, matrix) + +. . . + +```C +rien moyenne(arbre) { + si !est_feuille(arbre) + pour enfant dans arbre.enfants + moyenne(enfant) + pour enfant dans arbre.enfants + arbre.moyenne += enfant.moyenne + arbre.moyenne_carre += enfant.moyenne_carre + arbre.moyenne /= 4 + arbre.moyenne_carre /= 4 +``` + +# La compression avec pertes + +\footnotesize + +## Pseudo-code (5min, matrix) + +. . . + +```C +rien compression_avec_pertes(arbre, theta) + si !est_feuille(arbre) + pour i de 0 à 3 + compression_avec_pertes(arbre.enfant[i]) + si derniere_branche(arbre) + si racine(arbre.moyenne_carre - arbre.moyenne^2) < theta + detruire_enfants(arbre) +``` + +## Le code en entier + +```C +arbre = matrice_à _arbre(matrice) +moyenne(arbre) +compression_avec_pertes(arbre) +``` + +# La dynamique des corps célestes + +## Slides très fortement inspirés du cours de J. Latt, Unige + +## Simulation du problème à $N$-corps + +* Prédiction du mouvement d'un grand nombre de corps célestes. +* Modélisation: + * On se limite aux étoiles; + * Chaque étoile est caractérisée par un point (coordonnées) et une masse; + * On simule en deux dimensions. + * Interactions uniquement par les lois de la gravitation Newtonienne (oui-oui c'est de la **physique**!). + + +# Les équations du mouvement + +## Mouvement de la $i$-ème étoile + +* Algorithme de Verlet ($t_{n+1}=t_n+\delta t$) + + $$ + \vec x_i(t_{n+1})= 2\vec x_i(t_n)-\vec x_i(t_{n-1})+\vec a_i(t_n)\delta t^2. + $$ + +## Force de gravitation + +* $\vec a_i(t_n)=\vec F_i/m_i$. +* Sur l'étoile $i$, la force résultante est donnée par + + $$ + \vec F_i=\sum_{j=1,j\neq i}^N \vec F_{ij}. + $$ + avec + $$ + \vec F_{ij}=\frac{G m_i m_j(\vec x_j-\vec x_i)}{||\vec x_j-\vec x_i||^3}. + $$ + +# Algorithme du problème à $n$-corps + +## Pseudo-code: structure de données + +```C +struct étoile + flottant m + vec x, x_precedent, f +``` + +## Pseudo-code: itération temporelle + +```C +rien iteration_temporelle(étoiles, dt) + pour étoile_une dans étoiles + étoile_une.f = 0 + pour étoile_deux dans étoiles + si (étoile_un != étoile_deux) + étoile_une.f += + force(étoile_une, étoile_deux) + pour étoile dans étoiles + étoile.x, étoile.x_precedent = + verlet(étoile.x, étoile.x_precedent, + étoile.f / étoile.m, dt) +``` + +# Algorithme du problème à $n$-corps + +## Complexité + +* Complexité de chacune des parties? + +. . . + +* $\mathcal{O}(N^2)$, $\mathcal{O}(N)$. + +## En temps CPU pour **une itération** + +\footnotesize + +* Si temps pour $N=1$ on calcule en $1\mu s$: + ++--------+-------+-------+-----------+ +| N | N^2 | t [s] | t [réel] | ++--------+-------+-------+-----------+ +| 10 | 10^2 | 1e-4 | | ++--------+-------+-------+-----------+ +| 10^4 | 10^8 | 1e+2 | ~1min | ++--------+-------+-------+-----------+ +| 10^6 | 10^12 | 1e+6 | ~11j | ++--------+-------+-------+-----------+ +| 10^9 | 10^18 | 1e+12 | ~30k ans | ++--------+-------+-------+-----------+ +| 10^11 | 10^22 | 1e+16 | ~300M ans | ++--------+-------+-------+-----------+ + +* Typiquement il y a des milliers-millions d'itérations. +* Il y a $10^{11}$ étoiles dans la galaxie. +* Houston we have a problem. + +# Question + +## Comment faire mieux, des idées? + +. . . + +* Si un groupe d'étoiles est suffisamment loin, on le modélise comme un corps unique situé en son centre de masse. +* Exemple: Si on simule plusieurs galaxies, on considère chaque galaxie comme un corps unique! +* Un arbre quaternaire est une structure parfaite pour regrouper les étoiles. + +# Le cas à 10 corps + +::: columns + +:::: {.column width=50%} + +## Illustration: le cas à 10 corps + +{width=60%} + +:::: + +:::: {.column width=50%} + +## Problématique + +* On veut calculer la force sur $1$. + +:::: + +::: + +. . . + + +::: columns + +:::: {.column width=50%} + +## Illustration: le cas à 10 corps + +{width=60%} + + +:::: + +:::: {.column width=50%} + +## Résultat + +* Calcul et somme des forces venant des $9$ autre corps. + +:::: + +::: + +# Le cas à 10 corps + +::: columns + +:::: {.column width=50%} + +## Réduction d'un groupe à un seul corps + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Idée + +* On accélère le calcul en traitant un groupe comme un seul corps. +* Fonctionne uniquement si le groupe est assez loin. +* Autrement l'approximation est trop grossière. + +:::: + +::: + +# Solution: l'arbre quaternaire + +## Corps célestes - arbre + + + +* On omet les nœuds vides pour éviter la surcharge. +* La numérotation est: + * 0: ID + * 1: SD + * 2: IG + * 3: SG + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Insertion corps 1 + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Arbre, niveau 1 + +{width=100%} + +* Quadrant ID. +* La feuille est vide, on insère. + +:::: + +::: + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Insertion corps 2 + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Arbre, niveau 1 + +{width=100%} + +* Quadrant SD. +* La feuille est vide, on insère. + +:::: + +::: + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Insertion corps 3 (1/N) + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Arbre, niveau 1 + +{width=100%} + +* Quadrant SD. +* La feuille est prise par 2. + +:::: + +::: + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Insertion corps 3 (2/N) + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Arbre, niveau 2 + +{width=100%} + +* On crée un nouveau nœud. +* Deux corps dans le nœud ID. +* On crée un nouveau nœud. + +:::: + +::: + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Insertion corps 3 (3/N) + +{width=100%} + +:::: + +:::: {.column width=50%} + +## Arbre, niveau 3 + +{width=100%} + +* 2 va dans ID. +* 3 va dans SG. +* C'est des feuilles vides, tout va bien. + +:::: + +::: + +# Exemple d'insertion + +::: columns + +:::: {.column width=50%} + +## Que fait-on avec les nœuds intérieurs? + +* On les utilise pour: + * stocker la masse totale; + * stocker le centre de masse. + +\begin{align} +m&=m_2+m_3,\\ +\vec x &= \frac{m_2\vec x_2+m_3\vec x_3}{m}. +\end{align} + +## Chaque feuille contient **une étoile** + +:::: + +:::: {.column width=50%} + +## Arbre + +{width=100%} + +:::: + +::: + +# Résumé + +* Insertion du corps `c` dans le nœud `n` en partant de la racine. +* Si le nœud `n` + * ne contient pas de corps, on y dépose `c`, + * est interne, on met à jour masse et centre de masse. `c` est inséré récursivement dans le bon quadrant. + * est externe, on subdivise `n`, on met à jour la masse et centre de masse, on insère récursivement les deux nœuds dans les quadrants appropriés. + +## Remarque + +* Il faut stocker les coordonnées des quadrants. +* Un nœud a un comportement différent s'il est interne ou externe. + +# Les B-arbres + +\Huge + +Les B-arbres + + +# Les B-arbres + +## Problématique + +* Grands jeux de données (en 1970). +* Stockage dans un arbre, mais l'arbre tiens pas en mémoire. +* Regrouper les sous-arbres en **pages** qui tiennent en mémoire. + +## Exemple + +* 100 nœuds par page et l'arbre comporte $10^6$ nœuds: + * Recherche B-arbre: $\log_{100}(10^6)=3$; + * Recherche ABR: $\log_2(10^6)=20$. +* Si on doit lire depuis le disque: $10\mathrm{ms}$ par recherche+lecture: + * $30\mathrm{ms}$ (lecture beaucoup plus rapide que recherche) vs $200\mathrm{ms}=0.2\mathrm{s}$. + +## Remarques + +* On sait pas ce que veut dire `B`: Bayer, Boeing, Balanced? +* Variante plus récente B+-arbres. + +# Les B-arbres + +## Illustration, arbre divisé en pages de 3 nœuds + + + +. . . + +## Utilisation + +* Bases de données (souvent très grandes donc sur le disque); +* Système de fichier. + +# Les B-arbres + +## Avantages + +* Arbres moins profonds; +* Diminue les opération de rééquilibrage; +* Complexité toujours en $\log(N)$; + +. . . + +## Définition: B-arbre d'ordre $n$ + +* Chaque page d'un arbre contient au plus $2\cdot n$ *clés*; +* Chaque page (excepté la racine) contient au moins $n$ clés; +* Chaque page qui contient $m$ clés contient soit: + * $0$ descendants; + * $m+1$ descendants. +* Toutes les pages terminales apparaissent au même niveau. + +# Les B-arbres + +## Est-ce un B-arbre? + + + +. . . + +## Oui! + +* Dans chaque nœud les clés sont **triées**. +* Chaque page contient au plus $n$ nœuds: check; +* Chaque nœud avec $m$ clés a $m+1$ descendants; +* Toutes les feuilles apparaissent au même niveau. + +# Les B-arbres + +## Exemple de recherche: trouver `32` + + + +. . . + +* Si `n` plus petit que la 1e clé ou plus grand que la dernière descendre. +* Sinon parcourir (par bissection ou séquentiellement) jusqu'à trouver ou descendre entre 2 éléments. + +# Les B-arbres + +## La recherche de la clé `C` algorithme + +0. En partant de la racine. +1. Si on est dans une feuille: + * Si la `C` est dans une page, retourner la page; + * Sinon c'est perdu. +2. Sinon: + * Tant que `C > page` passer à la page suivante + * Descendre + +# Les B-arbres + +## Disclaimer + +* Inspiration de <https://en.wikipedia.org/wiki/B-tree> + +## Exemples d'insertion: `1` + + + +. . . + +* L'arbre est vide, on insère juste dans la première page. + +# Les B-arbres + +## Exemples d'insertion: `2` + + + +. . . + +* La première page est pas pleine, on insère dans l'ordre (après 1). + +# Les B-arbres + +## Exemples d'insertion: `3` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `3` + +{width=50%} + +. . . + +* La page est pleine, on crée deux enfants. +* On choisit, `2`, la médiane de `1, 2, 3` et il est inséré à la racine. +* `1` descend à gauche, `3` descend à droite. + +# Les B-arbres + +## Exemples d'insertion: `4` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `4` + +{width=50%} + +. . . + +* On pourrait insérer à droite de `2`, mais... ça ferait 2 parents pour 2 enfants (mais `m` parents => `m+1` enfants ou `0`); +* On descend à droite (`4 > 2`); +* On insère à droite de `3`. + +# Les B-arbres + +## Exemples d'insertion: `5` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `5` + + + +. . . + +* On descend à droite (on peut pas insérer à la racine comme pour `4`); +* On dépasse la capacité de l'enfant droite; +* `4`, médiane de `3, 4, 5`, remonte à la racine; +* On crée un nouveau nœud à droite de `4`; +* La règle `m => m+1` est ok. + +# Les B-arbres + +## Exemples d'insertion: `6` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `6` + + + +. . . + +* `6 > 4` on descend à droite; +* `6 > 5` et on a à la place à droite, on insère. + +# Les B-arbres + +## Exemples d'insertion: `7` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `7` + +{width=50%} + +. . . + +* `7 > 4` on descend à droite; +* `7 > 6` mais on a dépassé la capacité; +* `6` est la médiane de `5, 6, 7`, remonte à la racine; +* `5` reste à gauche, `7` à droite, mais `6` fait dépasser la capacité de la racine; +* `4` est la médiane de `2, 4, 6`, `4` remonte, `2` reste à gauche, `6` à droite. + +# Les B-arbres + +## L'algorithme d'insertion + +0. Rechercher la feuille (la page a aucun enfant) où insérer; +1. Si la page n'est pas pleine insérer dans l'ordre croissant. +2. Si la page est pleine, on sépare la page en son milieu : + 1. On trouve la médiane, `M`, de la page; + 2. On met les éléments `< M` dans la page de gauche de `M` et les `> M` dans la page de droite de `M`; + 3. `M` est insérée récursivement dans la page parent. + +# Les B-arbres + +## Exercice: insérer `22, 45, 50` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + + +# Les B-arbres + +## Exercice: insérer `5` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice: insérer `32, 55, 60` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice: insérer `41` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice (matrix, 15min) + +* Insérer 20, 40, 10, 30, 15, 35, 7, 26, 18, 22, 5, 42, 13, 46, 27, 8, 32, 38, 24, 45, 25, 2, 14, 28, 32, 41, +* Dans un B-arbre d'ordre 2. + -- GitLab