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?
-
-![](figs/quad_img_simple.svg)
-
-. . . 
-
-## Arbre compressé
-
-![](figs/quad_img_simple_comp.svg)
-
-# 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?
-
-![](figs/quad_img_simple_variation.svg)
-
-. . . 
-
-## Arbre compressé
-
-![](figs/quad_img_simple_comp_loss.svg)
-
-# 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$?
-
-![L'arbre original.](figs/quad_img_simple_variation.svg)
-
-. . .
-
-![Arbre compressé.](figs/quad_img_simple_comp_avg.svg)
-
-# 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
-
-![](figs/nbody_bare.png){width=60%}
-
-::::
-
-:::: {.column width=50%}
-
-## Problématique
-
-* On veut calculer la force sur $1$.
-
-::::
-
-:::
-
-. . .
-
-
-::: columns
-
-:::: {.column width=50%}
-
-## Illustration: le cas à 10 corps
-
-![](figs/nbody_n2.png){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
-
-![](figs/nbody_group.png){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
-
-![](figs/nbody_qt_withtree.png)
-
-* 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
-
-![](figs/corps1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre1.png){width=100%}
-
-* Quadrant ID.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 2
-
-![](figs/corps2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre2.png){width=100%}
-
-* Quadrant SD.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (1/N)
-
-![](figs/corps3_1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre3_1.png){width=100%}
-
-* Quadrant SD.
-* La feuille est prise par 2.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (2/N)
-
-![](figs/corps3_2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 2
-
-![](figs/arbre3_2.png){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)
-
-![](figs/corps3_3.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 3
-
-![](figs/arbre3_3.png){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
-
-![](figs/arbre3_3.png){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?
+
+![](figs/quad_img_simple.svg)
+
+. . . 
+
+## Arbre compressé
+
+![](figs/quad_img_simple_comp.svg)
+
+# 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?
+
+![](figs/quad_img_simple_variation.svg)
+
+. . . 
+
+## Arbre compressé
+
+![](figs/quad_img_simple_comp_loss.svg)
+
+# 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$?
+
+![L'arbre original.](figs/quad_img_simple_variation.svg)
+
+. . .
+
+![Arbre compressé.](figs/quad_img_simple_comp_avg.svg)
+
+# 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
+
+![](figs/nbody_bare.png){width=60%}
+
+::::
+
+:::: {.column width=50%}
+
+## Problématique
+
+* On veut calculer la force sur $1$.
+
+::::
+
+:::
+
+. . .
+
+
+::: columns
+
+:::: {.column width=50%}
+
+## Illustration: le cas à 10 corps
+
+![](figs/nbody_n2.png){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
+
+![](figs/nbody_group.png){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
+
+![](figs/nbody_qt_withtree.png)
+
+* 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
+
+![](figs/corps1.png){width=100%}
+
+::::
+
+:::: {.column width=50%}
+
+## Arbre, niveau 1
+
+![](figs/arbre1.png){width=100%}
+
+* Quadrant ID.
+* La feuille est vide, on insère.
+
+::::
+
+:::
+
+# Exemple d'insertion
+
+::: columns
+
+:::: {.column width=50%}
+
+## Insertion corps 2
+
+![](figs/corps2.png){width=100%}
+
+::::
+
+:::: {.column width=50%}
+
+## Arbre, niveau 1
+
+![](figs/arbre2.png){width=100%}
+
+* Quadrant SD.
+* La feuille est vide, on insère.
+
+::::
+
+:::
+
+# Exemple d'insertion
+
+::: columns
+
+:::: {.column width=50%}
+
+## Insertion corps 3 (1/N)
+
+![](figs/corps3_1.png){width=100%}
+
+::::
+
+:::: {.column width=50%}
+
+## Arbre, niveau 1
+
+![](figs/arbre3_1.png){width=100%}
+
+* Quadrant SD.
+* La feuille est prise par 2.
+
+::::
+
+:::
+
+# Exemple d'insertion
+
+::: columns
+
+:::: {.column width=50%}
+
+## Insertion corps 3 (2/N)
+
+![](figs/corps3_2.png){width=100%}
+
+::::
+
+:::: {.column width=50%}
+
+## Arbre, niveau 2
+
+![](figs/arbre3_2.png){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)
+
+![](figs/corps3_3.png){width=100%}
+
+::::
+
+:::: {.column width=50%}
+
+## Arbre, niveau 3
+
+![](figs/arbre3_3.png){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
+
+![](figs/arbre3_3.png){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
+
+![Arbre divisé en pages de 3 nœuds](figs/barbres_page3.png)
+
+. . .
+
+## 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?
+
+![B-arbre d'ordre 2.](figs/barbres_exemple.png)
+
+. . .
+
+## 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`
+
+![B-arbre d'ordre 2.](figs/barbres_exemple.png)
+ 
+. . .
+
+* 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`
+
+![B-arbre d'ordre 1.](figs/barbres_1.svg)
+ 
+. . .
+
+* L'arbre est vide, on insère juste dans la première page.
+
+# Les B-arbres
+
+## Exemples d'insertion: `2`
+
+![B-arbre d'ordre 1. Nombre pages max = 2.](figs/barbres_2.svg)
+ 
+. . .
+
+* La première page est pas pleine, on insère dans l'ordre (après 1).
+
+# Les B-arbres
+
+## Exemples d'insertion: `3`
+
+![B-arbre d'ordre 1.](figs/barbres_2.svg){width=50%}
+
+* Comment on insère (1min de réflexion avant de donner une réponse!)?
+
+# Les B-arbres
+
+## Exemples d'insertion: `3`
+
+![B-arbre d'ordre 1. Nombre pages max = 2.](figs/barbres_3.svg){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`
+
+![B-arbre d'ordre 1.](figs/barbres_3.svg){width=50%}
+ 
+* Comment on insère (1min de réflexion avant de donner une réponse!)?
+
+# Les B-arbres
+
+## Exemples d'insertion: `4`
+
+![B-arbre d'ordre 1. Nombre enfants 0 ou 2.](figs/barbres_4.svg){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`
+
+![B-arbre d'ordre 1.](figs/barbres_4.svg){width=50%}
+ 
+* Comment on insère (1min de réflexion avant de donner une réponse!)?
+
+# Les B-arbres
+
+## Exemples d'insertion: `5`
+
+![B-arbre d'ordre 1.](figs/barbres_5.svg)
+ 
+. . .
+
+* 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`
+
+![B-arbre d'ordre 1.](figs/barbres_5.svg){width=50%}
+ 
+* Comment on insère (1min de réflexion avant de donner une réponse!)?
+
+# Les B-arbres
+
+## Exemples d'insertion: `6`
+
+![B-arbre d'ordre 1.](figs/barbres_6.svg)
+ 
+. . .
+
+* `6 > 4` on descend à droite;
+* `6 > 5` et on a à la place à droite, on insère.
+
+# Les B-arbres
+
+## Exemples d'insertion: `7`
+
+![B-arbre d'ordre 1.](figs/barbres_6.svg){width=50%}
+ 
+* Comment on insère (1min de réflexion avant de donner une réponse!)?
+
+# Les B-arbres
+
+## Exemples d'insertion: `7`
+
+![B-arbre d'ordre 1.](figs/barbres_7.svg){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)
+
+![](figs/barbres_ex1.png)
+
+. . .
+
+![](figs/barbres_ex2.png)
+
+
+# Les B-arbres
+
+## Exercice: insérer `5` dans l'arbre d'ordre 2 (3min matrix)
+
+![](figs/barbres_ex2.png)
+
+. . .
+
+![](figs/barbres_ex3.png)
+
+# Les B-arbres
+
+## Exercice: insérer `32, 55, 60` dans l'arbre d'ordre 2 (3min matrix)
+
+![](figs/barbres_ex3.png)
+
+. . .
+
+![](figs/barbres_ex4.png)
+
+# Les B-arbres
+
+## Exercice: insérer `41` dans l'arbre d'ordre 2 (3min matrix)
+
+![](figs/barbres_ex4.png)
+
+. . .
+
+![](figs/barbres_ex5.png)
+
+# 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