Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • algorithmique/cours
  • aurelien.boyer/cours
  • jeremy.meissner/cours
  • radhwan.hassine/cours
  • yassin.elhakoun/cours-algo
  • gaspard.legouic/cours
  • joachim.bach/cours
  • gabriel.marinoja/algo-cours
  • loic.lavorel/cours
  • iliya.saroukha/cours
  • costanti.volta/cours
  • jacquesw.ndoumben/cours
12 results
Select Git revision
  • master
1 result
Show changes
Showing
with 19634 additions and 9 deletions
---
title: "Arbres quaternaires, compression et Barnes-Hut"
date: "2022-04-06"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Le cours précédent
## Questions
* Structure de données d'un arbre quaternaire?
. . .
```C
typedef struct _node {
int info;
struct _node *child[4];
} node;
```
. . .
* Dessin d'un noeud d'arbre quaternaire (avec correspondance `node`)?
. . .
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
id0((" "))-->|"child[0]"| id1(("info"));
id0-->|"child[1]"| id2(("info"));
id0-->|"child[2]"| id3(("info"));
id0-->|"child[3]"| id4(("info"));
```
# Le cours précédent
## Questions
* Comment faire la symétrie d'axe horizontal?
. . .
```C
arbre symétrie(arbre)
si !est_feuille(arbre)
échanger(arbre.enfant[0], arbre.enfant[2])
échanger(arbre.enfant[1], arbre.enfant[4])
pour i de 0 à 3
symétrie(arbre.enfant[i])
retourne arbre
```
# Compression sans perte (1/N)
## 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/N)
## Que devient l'arbre suivant?
![](figs/quad_img_simple.svg)
. . .
## Arbre compressé
![](figs/quad_img_simple_comp.svg)
# Compression sans perte (3/N)
* Si un noeud a tous ses enfants égaux:
* Donner la valeur au noeud,
* 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/N)
\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/N)
\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/N)
## 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/N)
## 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/N)
## 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/N)
## 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 (6/N)
## 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 noeud (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_sans_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 noeuds 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 noeud.
* Deux corps dans le noeud ID.
* On crée un nouveau noeud.
::::
:::
# 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 noeuds 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 noeud `n` en partant de la racine.
* Si le noeud `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 noeuds dans les quadrants appropriés.
## Remarque
* Il faut stocker les coordonnées des quadrants.
* Un noeud a un comportement différent s'il est interne ou externe.
# Algorithme d'insertion
## Structure de données
```C
struct node
etoile e // externe: pour stocker
etoile sup_etoile // interne: pour stocker m, x
quadrant q // coordonnées du quadrant
node enfants[4]
```
## Remarque:
* On fait une simplification "moche": `sup_etoile` pourrait juste avoir une masse et une position.
# Algorithme d'insertion
\footnotesize
## Algorithme d'insertion, pseudo-code (15min, matrix)
. . .
```C
rien insertion_etoile(arbre, e)
si (!est_vide(arbre) && dans_le_quadrant(arbre.q, e.x)) {
si (est_feuille(arbre))
si (!contient_etoile(arbre))
arbre.e = e
sinon
// on crée enfants et arbre.sup_etoile est initialisée
subdivision_arbre(arbre, e)
pour enfant dans arbre.enfants
insertion_etoile(enfant, arbre.e)
pour enfant dans arbre.enfants
insertion_etoile(enfant, e)
destruction(arbre.e)
sinon
maj_masse_cdm(arbre.sup_etoile, e)
pour enfant dans arbre.enfants
insertion_etoile(enfant, e)
```
# Utilisation de l'arbre
* L'arbre est rempli: comment on calcule la force sur le corps 1?
* Parcours de l'arbre:
* si la distance entre 1 et le centre de masse est suffisante, on utilise la masse totale et centre de masse pour calculer la force.
* sinon, on continue le parcours
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_1.png)
* Le cadrant ID ne contient que `1`, rien à faire.
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_2.png)
* Le cadrant SG ne contient `5` corps.
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_3.png)
* La distance entre `1` et le centre de masse de SG est `d`.
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_4.png)
* La distance entre `1` et le centre de masse de SG est `d`.
* Est-ce que `d` est assez grand?
* On va comparer avec la distance `d` avec la taille du quadrant `s`.
# Critère $\theta$
* On compare $d=||\vec x_1-\vec x_{cm}||$ avec $s$ la taille du quadrant.
* Le domain est assez éloigné si
$$
\frac{s}{d}<\theta,
$$
* $\theta$ est la valeur de seuil.
* Une valeur typique est $\theta=0.5$, donc la condition devient
$$
d>2s.
$$
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_4.png)
* Ici $d<2s$, domaine rejeté.
* ON descend dans l'arbre.
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_5.png)
* `s` est plus petit, mais....
* Cela ne suffit pas $d<2s$, domaine rejeté.
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_6.png)
* Les noeuds sont des feuilles, on calcule la force.
* On ajoute la force qu'ils exercent sur `1`.
# Algorithme pour le calcul de la force
Pour calculer la force sur un corps `c`, on parcourt l'arbre en commençant par la racine:
* Si le noeud `n` est une feuille et n'est pas `c`, on ajoute la force dûe à `n` sur `c`;
* Sinon si $s/d<\theta$, on traite `n` comme une feuille et on ajoute la force dûe à `n` sur `c`;
* Sinon on continue sur les enfants récursivement.
## Cotinuous notre exemple précédent!
# Calcul de la force
## Calcul de la force sur `1`
![](figs/force_7.png)
* Il y a deux corps dans le quadrant vert.
* Quel est le critère pour remplacer les étoiles par leur centre de masse?
. . .
* Et oui! $d>2s$ on peut remplacer les étoiles par leur centre de masse!
# Algorithme du calcul de force
## Écrire le psuedo-code du calcul de la force
\footnotesize
```C
rien maj_force_sur_etoile(arbre, e, theta)
si est_vide(arbre)
retourne
si est_feuille(arbre) && contient_etoile(arbre) && dans_le_quadrant(arbre.q, e.x)
maj_force(e, arbre.e)
sinon si noeud_assez_loin(arbre, e, theta)
maj_force(e, arbre.sup_etoile)
sinon
pour enfant dans enfants
maj_force_sur_etoile(enfant, e, theta)
```
---
title: "B-Arbres"
date: "2022-04-13"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# 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 noeuds par page et l'arbre comporte $10^6$ noeuds:
* 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 noeuds
![Arbre divisé en pages de 3 noeuds](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 noeud les clés sont **triées**.
* Chaque page contient au plus $n$ noeuds: check;
* Chaque noeud 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 2.](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 noeud à 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 2.](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 2.](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.
# Les B-arbres
## Structure de données
* Chaque page a une contrainte de remplissage, par rapport à l'ordre de l'arbre;
* Un noeud (page) est composé d'un tableau de clés/pointeurs vers les enfants;
```
P_0 | K_1 | P_1 | K_2 | | P_i | K_{i+1} | | P_{m-1} | K_m | P_m
```
* `P_0`, ..., `P_m` pointeurs vers enfants;
* `K_1`, ..., `K_m` les clés.
* Il y a `m+1` pointeurs mais `m` clés.
* Comment faire pour gérer l'insertion?
# Les B-arbres
## Faire un dessin de la structure de données (3min matrix)?
. . .
![Strcture d'une page de B-arbre d'ordre 2.](figs/barbres_struct.png)
1. On veut un tableau de `P_i, K_i => struct`;
2. `K_0` va être en "trop";
3. Pour simplifier l'insertion dans une page, on ajoute un élément de plus.
# Les B-arbres
## L'insertion cas noeud pas plein, insertion `4`?
![](figs/barbres_insert_easy.svg){width=50%}
. . .
## Solution
![](figs/barbres_insert_easy_after.svg){width=50%}
# Les B-arbres
## L'insertion cas noeud pas plein, insertion `N`
* On décale les éléments plus grand que `N`;
* On insère `N` dans la place "vide";
* Si la page n'est pas pleine, on a terminé.
# Les B-arbres
## L'insertion cas noeud plein, insertion `2`?
![](figs/barbres_insert_hard_before.svg){width=50%}
. . .
## Solution
![](figs/barbres_insert_hard_during.svg){width=50%}
# Les B-arbres
## L'insertion cas noeud plein, promotion `3`?
![](figs/barbres_insert_hard_during.svg){width=50%}
. . .
## Solution
![](figs/barbres_insert_hard_after.svg)
# Les B-arbres
## L'insertion cas noeud plein, insertion `N`
* On décale les éléments plus grand que `N`;
* On insère `N` dans la place "vide";
* Si la page est pleine:
* On trouve la valent médiance `M` de la page (quel indice?);
* On crée une nouvelle page de droite;
* On copie les valeur à droite de `M` dans la nouvelle page;
* On promeut `M` dans la page du dessus;
* On connecte le pointeur de gauche de `M` et de droite de `M` avec l'ancienne et la nouvelle page respectivement.
# Les B-arbres
## Pseudo-code structure de données (3min, matrix)?
. . .
```C
struct page
entier ordre, nb
element tab[2*ordre + 2]
```
```C
struct element
int clé
page pg
```
# Les B-arbres
\footnotesize
## Les fonctions utilitaires (5min matrix)
```C
booléen est_feuille(page) // la page est elle une feuille?
entier position(page, valeur) // à quelle indice on insère?
booléen est_dans_page(page, valeur) // la valeur est dans la page
```
. . .
```C
booléen est_feuille(page)
retourne (page.tab[0].pg == vide)
entier position(page, valeur)
i = 0
tant que i < page.nb && val >= page.tab[i+1].clef
i += 1
retourne i
booléen est_dans_page(page, valeur)
i = position(page, valeur)
retourne (page.nb > 0 && page.tab[i].val == valeur)
```
# Les B-arbres
\footnotesize
## Les fonctions utilitaires (5min matrix)
```C
page nouvelle_page(ordre) // creer une page
rien liberer_memoire(page) // liberer tout un arbre!
```
. . .
```C
page nouvelle_page(ordre)
page = allouer(page)
page.ordre = ordre
page.nb = 0
page.tab = allouer(2*ordre+2)
retourner page
rien liberer_memoire(page)
si est_feuille(page)
liberer(page.tab)
liberer(page)
sinon
pour fille dans page.tab
liberer_memoire(fille)
liberer(page.tab)
liberer(page)
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
page recherche(page, valeur) // retourner la page contenant
// la valeur ou vide
```
. . .
```C
page recherche(page, valeur)
si est_dans_page(page, valeur)
retourne page
sinon si est_feuille(page)
retourne vide
sinon
recherche(page.tab[position(page, valeur)], valeur)
```
# Les B-arbres
## Les fonctions
```C
page inserer_valeur(page, valeur) // inserer une valeur
```
. . .
```C
page inserer_valeur(page, valeur)
element = nouvel_element(valeur)
// on change element pour savoir s'il faut le remonter
inserer_element(page, element)
si element.page != vide && page.nb > 2*page.ordre
// si on atteint le sommet!
page = ajouter_niveau(page, element)
retourne page
```
# Les B-arbres
## Les fonctions
```C
rien inserer_element(page, element) // inserer un element et voir s'il remonte
```
. . .
```C
rien inserer_element(page, element)
si est_feuille(page)
placer(page, element)
sinon
sous_page = page.tab[position(page, element)].page
inserer_element(sous_page, element)
// un element a été promu
si element.page != vide
placer(page, element)
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
rien placer(page, element) // inserer un élément
```
. . .
```C
rien placer(page, element)
pos = position(page, element.clé)
pour i de 2*page.ordre à pos+1
page.tab[i+1] = page.tab[i]
page.tab[pos+1] = element
page.nb += 1
si page.nb > 2*page.ordre
scinder(page, element)
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
rien scinder(page, element) // casser une page et remonter
```
. . .
```C
rien scinder(page, element)
new_page = new_page(page.ordre)
new_page.nb = page.ordre
pour i de 0 à ordre inclu
new_page.tab[i] = page.tab[i+ordre+1]
element.clé = page.tab[ordre+1].clé
element.page = new_page
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
page ajouter_niveau(page, element) // si on remonte à la racine...
// on doit créer une nouvelle racine
```
. . .
```C
page ajouter_niveau(page, element)
tmp = nouvelle_page(page.ordre)
tmp.tab[0].page = page
tmp.tab[1].clé = element.clé
tmp.tab[1].page = element.page
retourne tmp
```
<!-- # Les B-arbres -->
<!-- ## Structure de données en C (3min, matrix) -->
<!-- . . . -->
<!-- ```C -->
<!-- typedef struct _page { -->
<!-- int order, nb; -->
<!-- struct _element *tab; -->
<!-- } page; -->
<!-- ``` -->
<!-- ```C -->
<!-- typedef struct element { -->
<!-- int key; -->
<!-- struct _page *pg; -->
<!-- } element; -->
<!-- ``` -->
---
title: "B-Arbres"
date: "2022-05-03"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Rappel: Les B-arbres
## Pourquoi utiliser un B-arbre?
. . .
## À quoi ressemble un B-arbre?
. . .
## Qu'est-ce qu'un 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.
# Rappel: Les B-arbres
## Quelques propriétés
* Dans chaque noeud les clés sont **triées**.
* Chaque page contient au plus $n$ noeuds: check;
* Chaque noeud 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
## Exercice: insérer `22, 45, 50, 5, 32, 55, 60, 41` dans l'arbre d'ordre 2
![](figs/barbres_ex1.png)
. . .
![](figs/barbres_ex5.png)
# 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:
1. On décale les éléments plus grand que `N`;
2. On insère `N` dans la place "vide";
3. On trouve la valeur médiane `M` de la page (quel indice?);
4. On crée une nouvelle page de droite;
5. On copie les valeur à droite de `M` dans la nouvelle page;
6. On promeut `M` dans la page du dessus;
7. On connecte le pointeur de gauche de `M` et de droite de `M` avec l'ancienne et la nouvelle page respectivement.
# Les B-arbres
## Pseudo-code structure de données (3min, matrix)?
. . .
```C
struct page
entier ordre, nb
element tab[2*ordre + 2]
```
```C
struct element
int clé
page pg
```
# Les B-arbres
\footnotesize
## Les fonctions utilitaires (5min matrix)
```C
booléen est_feuille(page) // la page est elle une feuille?
entier position(page, valeur) // à quelle indice on insère?
booléen est_dans_page(page, valeur) // la valeur est dans la page
```
. . .
```C
booléen est_feuille(page)
retourne (page.tab[0].pg == vide)
entier position(page, valeur)
i = 0
tant que i < page.nb && val >= page.tab[i+1].clef
i += 1
retourne i
booléen est_dans_page(page, valeur)
i = position(page, valeur)
retourne (page.nb > 0 && page.tab[i].clef == valeur)
```
# Les B-arbres
\footnotesize
## Les fonctions utilitaires (5min matrix)
```C
page nouvelle_page(ordre) // creer une page
rien liberer_memoire(page) // liberer tout un arbre!
```
. . .
```C
page nouvelle_page(ordre)
page = allouer(page)
page.ordre = ordre
page.nb = 0
page.tab = allouer(2*ordre+2)
retourner page
rien liberer_memoire(page)
si est_feuille(page)
liberer(page.tab)
liberer(page)
sinon
pour fille dans page.tab
liberer_memoire(fille)
liberer(page.tab)
liberer(page)
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
page recherche(page, valeur) // retourner la page contenant
// la valeur ou vide
```
. . .
```C
page recherche(page, valeur)
si est_dans_page(page, valeur)
retourne page
sinon si est_feuille(page)
retourne vide
sinon
recherche(page.tab[position(page, valeur)], valeur)
```
# Les B-arbres
## Les fonctions
```C
page inserer(page, valeur) // inserer une valeur
```
. . .
```C
page inserer(page, valeur)
element = nouvel_element(valeur)
// on change element pour savoir s'il faut le remonter
inserer_element(page, element)
si element != vide && element.page != vide
// si on atteint le sommet
page = ajouter_niveau(page, element)
retourne page
```
# Les B-arbres
## Les fonctions
```C
// inserer un element et voir s'il remonte
rien inserer_element(page, element)
```
. . .
```C
rien inserer_element(page, element)
si est_feuille(page)
placer(page, element)
sinon
sous_page = page.tab[position(page, element)].page
inserer_element(sous_page, element)
si element != vide && element.page != vide
placer(page, element)
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
rien placer(page, element) // inserer un élément
```
. . .
```C
rien placer(page, element)
i = position(page, element.clef)
pour i de 2*page.ordre à i+1
page.tab[i+1] = page.tab[i]
page.tab[i+1] = element
page.nb += 1
si page.nb > 2*page.ordre
scinder(page, element)
sinon
element = vide
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
rien scinder(page, element) // casser une page et remonter
```
. . .
```C
rien scinder(page, element)
new_page = new_page(page.ordre)
new_page.nb = page.ordre
pour i de 0 à ordre inclu
new_page.tab[i] = page.tab[i+ordre+1]
element.clef = page.tab[ordre+1].clé
element.page = new_page
```
# Les B-arbres
## Les fonctions (5min matrix)
```C
page ajouter_niveau(page, element) // si on remonte à la racine...
// on doit créer une nouvelle racine
```
. . .
```C
page ajouter_niveau(page, element)
tmp = nouvelle_page(page.ordre)
tmp.tab[0].page = page
tmp.tab[1].clef = element.clef
tmp.tab[1].page = element.page
retourne tmp
```
# Les B-arbres: suppression
## Cas simplissime
![Suppression de 25.](figs/barbres_ordre2_supp1.svg){width=80%}
. . .
![25 supprimé, on décale juste 27.](figs/barbres_ordre2_supp2.svg){width=80%}
# Les B-arbres: suppression
## Cas simple
![Suppression de 27.](figs/barbres_ordre2_supp2.svg){width=60%}
. . .
* On retire 27, mais....
* Chaque page doit avoir au moins 2 éléments.
* On doit déplacer des éléments dans une autre feuille! Mais comment?
. . .
![La médiane de la racine descend, fusion de 20 à gauche, et suppression à droite.](figs/barbres_ordre2_supp3.svg){width=60%}
# Les B-arbres: suppression
## Cas moins simple
![Suppression de 5.](figs/barbres_ordre2_supp4.svg){width=60%}
. . .
* Un élément à droite, comment on fait?
* Remonter `7`, serait ok si racine, mais... c'est pas forcément.
* On redistribue les feuilles.
. . .
![Descente de `3`, remontée médiane des feuilles `2`, .](figs/barbres_ordre2_supp5.svg){width=60%}
# Les B-arbres: suppression
## Cas ultra moins simple
![Suppression de 3.](figs/barbres_ordre2_supp6.svg){width=60%}
. . .
* `7` seul:
* Fusionner les feuilles et redistribuer, comment?
. . .
![Descendre `-1`, déplacer `7` à gauche, et décaler les éléments de droite au milieu.](figs/barbres_ordre2_supp7.svg){width=60%}
# Les B-arbres: suppression
## Cas ultra moins simple
![On a pas fini...](figs/barbres_ordre2_supp7.svg){width=60%}
. . .
* `8` est seul, c'est plus un B-arbre :
* Fusionner le niveau 2 et redistribuer, comment?
. . .
![Fusionner `8`, `17`, `22` et descendre `12`.](figs/barbres_ordre2_supp8.svg){width=40%}
. . .
* La profondeur a diminué de 1.
# Les B-arbres: suppression
## Algorithme pour les feuilles!
* Si la clé est supprimée d'une feuille:
* Si on a toujours `n` (ordre de l'arbre) clés dans la feuille on décale simplement les clés.
* Sinon on combine (récursivement) avec le noeud voisin et on descend la clé médiane.
# Les B-arbres: suppression
## Cas non-feuille!
![Suppression de 8.](figs/barbres_ordre2_supp9.svg){width=60%}
. . .
* On sait comment effacer une valeur d'une feuille, donc?
. . .
![Échanger le `8` avec le plus grand du sous-arbre de gauche.](figs/barbres_ordre2_supp10.svg){width=60%}
* Ensuite?
# Les B-arbres: suppression
## Cas non-feuille!
![Suppression de 8.](figs/barbres_ordre2_supp10.svg){width=60%}
. . .
* On sait comment effacer une valeur d'une feuille!
. . .
![Yaka enlever le 8 de la feuille comme avant!](figs/barbres_ordre2_supp11.svg){width=60%}
# Les B-arbres: suppression
## Algorithme pour les non-feuilles!
* Si la clé est supprimée d'une page qui n'est pas une feuille:
* On échange la valeur avec la valeur de droite de la page de gauche
* On supprime comme pour une feuille!
## Et maintenant des exos par millions!
<!-- # Les B-arbres -->
<!-- ## Structure de données en C (3min, matrix) -->
<!-- . . . -->
<!-- ```C -->
<!-- typedef struct _page { -->
<!-- int order, nb; -->
<!-- struct _element *tab; -->
<!-- } page; -->
<!-- ``` -->
<!-- ```C -->
<!-- typedef struct element { -->
<!-- int key; -->
<!-- struct _page *pg; -->
<!-- } element; -->
<!-- ``` -->
---
title: "Graphes - Généralités"
date: "2022-05-03"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Historique
**Un mini-peu d'histoire...**
## L. Euler et les 7 ponts de Koenigsberg:
* Existe-t-il une promenade sympa, passant **une seule fois** par les 7 ponts et revenant au point de départ?
![Les ponts c'est beau. Source: Wikipédia, <https://bit.ly/37h0yOG>](figs/Konigsberg_bridges.png){width=50%}
. . .
* Réponse: ben non!
# Utilisation quotidienne
## Réseau social
![Source, Wikipedia: <https://bit.ly/3kG6cgo>](figs/Social_Network.svg){width=40%}
* Chaque sommet est un individu.
* Chaque trait une relation d'amitié.
* Miam, Miam, Facebook.
# Utilisation quotidienne
## Moteurs de recherche
![Source, Wikipedia: <https://bit.ly/3kG6cgo>](figs/PageRanks-Example.svg){width=40%}
* Sommet est un site.
* Liens sortants;
* Liens entrants;
* Notion d'importance d'un site: combien de liens entrants, pondérés par l'importance du site.
* Miam, Miam, Google (PageRank).
# Introduction
## Définition, plus ou moins
* Un graphe est un ensemble de sommets, reliés par des lignes ou des flèches.
![Deux exemples de graphes.](figs/ex_graphes.png)
* Des sommets (numérotés 1 à 6);
* Connectés ou pas par des traits ou des flèches!
# Généralités
## Définitions
* Un **graphe** $G(V, E)$ est constitué
* $V$: un ensemble de sommets;
* $E$: un ensemble d'arêtes.
* Une **arête** relie une **paire** de sommets de $V$.
## Remarques
* Il y a **au plus** une arête $E$ par paire de sommets de $V$.
* La **complexité** d'un algorithme dans un graphe se mesure en terme de $|E|$ et $|V|$, le nombre d'éléments de $E$ et $V$ respectivement.
# Généralités
## Notations
* Une arête d'un graphe **non-orienté** est représentée par une paire **non-ordonnée** $(u,v)=(v,u)$, avec $u,v\in V$.
* Les arêtes ne sont pas orientées dans un graphe non-orienté (elles sont bi-directionnelles, peuvent être parcourues dans n'importe quel ordre).
## Exemple
::: columns
:::: column
![Un graphe non-orienté.](figs/ex_graphe_non_oriente.svg)
::::
:::: column
## Que valent $V$, $|V|$, $E$, et $|E|$?
. . .
\begin{align*}
V&=\{1, 2, 3, 4\},\\
|V|&=4,\\
E&=\{(1,2),(2,3),(2,4),(4,1)\},\\
|E|&=4.
\end{align*}
::::
:::
# Généralités
## Notations
* Une arête d'un graphe **orienté** est représentée par une paire **ordonnée** $(u,v)\neq(v,u)$, avec $u,v\in V$.
* Les arêtes sont orientées dans un graphe orienté (étonnant non?).
## Exemple
::: columns
:::: column
![Un graphe non-orienté.](figs/ex_graphe_oriente.svg)
::::
:::: column
## Que valent $V$, $|V|$, $E$, et $|E|$?
. . .
\begin{align*}
V&=\{1, 2, 3, 4\},\\
|V|&=4,\\
E&=\{(1,2),(2,3),(2,4),(4,1),(4,2)\},\\
|E|&=5.
\end{align*}
::::
:::
# Généralités
## Définition
* Le somme $v$ est **adjacent** au sommet $u$, si et seulement si $(u,v)\in E$;
* Si un graphe non-orienté contient une arête $(u,v)$, $v$ est adjacent à $u$ et $u$ et adjacent à $v$.
## Exemple
::: columns
:::: column
![Sommet $a$ adjacent à $c$, $c$ adjacent à $a$.](figs/ex_adj_non_or.svg){width=80%}
::::
:::: column
![Sommet $a$ adjacent à $c$.](figs/ex_adj_or.svg){width=80%}
::::
:::
# Généralités
## Définition
* Un **graphe pondéré** ou **valué** est un graphe dont chaque arête a un
poids associé, habituellement donné par une fonction de pondération $w:E\rightarrow\mathbb{R}$.
## Exemples
![Graphe pondéré orienté (gauche) et non-orienté (droite).](figs/ex_graph_pond.pdf){width=80%}
# Généralités
## Définition
* Dans un graphe $G(V,E)$, une **chaîne** reliant un sommet $u$ à un sommet $v$ est une suite d'arêtes entre les sommets, $w_0$, $w_1$, ..., $w_k$, telles que
$$
(w_i, w_{i+1})\in E,\quad u=w_0,\quad v=w_k,\quad \mbox{pour }0\leq i< k,
$$
avec $k$ la longueur de la chaîne (le nombre d'arêtes du chemin).
## Exemples
![Illustration d'une chaîne, ou pas chaîne dans un graphe.](figs/ex_graphe_chaine.pdf){width=80%}
# Généralités
## Définition
* Une **chaîne élémentaire** est une chaîne dont tous les sommets sont distincts, sauf les extrémités qui peuvent être égales
## Exemples
![Illustration d'une chaîne élémentaire.](figs/ex_graphe_chaine_elem.pdf){width=80%}
# Généralités
## Définition
* Une **boucle** est une arête $(v,v)$ d'un sommet vers lui-même.
## Exemples
![Illustration d'une boucle.](figs/ex_graphe_boucle.pdf){width=40%}
# Généralités
## Définition
* Un graphe non-orienté est dit **connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts.
## Exemples
\
::: columns
:::: column
![Graphe connexe. Source, Wikipédia: <https://bit.ly/3yiUzUv>](figs/graphe_connexe.svg){width=80%}
::::
:::: column
![Graphe non-connexe avec composantes connexes. Source, Wikipédia: <https://bit.ly/3KJB76d>](figs/composantes_connexes.svg){width=60%}
::::
:::
# Généralités
## Définition
* Un graphe orienté est dit **fortement connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts.
## Exemples
\
::: columns
:::: column
![Graphe fortement connexe.](figs/ex_graph_fort_connexe.pdf){width=60%}
::::
:::: column
![Composantes fortement connexes. Source, Wikipédia: <https://bit.ly/3w5PL2l>](figs/composantes_fortement_connexes.svg){width=100%}
::::
:::
# Généralités
## Définition
* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\leq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes.
* Pour un graphe *orienté* on parle de **circuit**.
* Un graphe sans cycles est dit **acyclique**.
## Exemples
![Illustration de cycles, ou pas.](figs/ex_graphe_cycle.pdf){width=100%}
# Question de la mort
* Qu'est-ce qu'un graphe connexe acyclique?
. . .
* Un arbre!
# Représentations
* La complexité des algorithmes sur les graphes s'expriment en fonction du nombre de sommets $V$, et du nombre d'arêtes $E$:
* Si $|E|\sim |V|^2$, on dit que le graphe est **dense**.
* Si $|E|\sim |V|$, on dit que le graphe est **peu dense**.
* Selon qu'on considère des graphes denses ou peu denses, différentes structure de données peuvent être envisagées.
## Question
* Comment peut-on représenter un graphe informatiquement? Des idées (réflexion de quelques minutes)?
. . .
* Matrice/liste d'adjacence.
# Matrice d'adjacence
* Soit le graphe $G(V,E)$, avec $V=\{1, 2, 3, ..., n\}$;
* On peut représenter un graphe par une **matrice d'adjacence**, $A$, de dimension $n\times n$ définie par
$$
A_{ij}=\left\{ \begin{array}{ll}
1 & \mbox{si } i,j\in E,\\
0 & \mbox{sinon}.
\end{array} \right.
$$
::: columns
:::: column
## Exemple
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---4;
2---5;
4---5;
5---3;
```
::::
:::: column
\footnotesize
## Quelle matrice d'adjacence?
. . .
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 1 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
4 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 1 | 0
```
::::
:::
# Matrice d'adjacence
## Remarques
* Zéro sur la diagonale.
* La matrice d'un graphe non-orienté est symétrique
$$
A_{ij}=A_{ji}, \forall i,j\in[1,n]
$$.
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---4;
2---5;
4---5;
5---3;
```
::::
:::: column
\footnotesize
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 1 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
4 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 1 | 0
```
::::
:::
# Matrice d'adjacence
* Pour un graphe orienté (digraphe)
::: columns
:::: column
## Exemple
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
2-->1;
1-->4;
2-->5;
5-->2;
4-->5;
5-->3;
```
::::
:::: column
\footnotesize
## Quelle matrice d'adjacence?
. . .
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 0 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 0
---||---|---|---|---|---
4 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 0 | 0
```
::::
:::
* La matrice d'adjacence n'est plus forcément symétrique
$$
A_{ij}\neq A_{ji}.
$$
# Stockage
* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe orienté?
. . .
* $\mathcal{O}(|V|^2)$.
* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe non-orienté?
. . .
* $\mathcal{O}(|V|-1)|V|/2$.
# Considérations d'efficacité
* Dans quel type de graphes la matrice d'adjacence est utile?
. . .
* Dans les graphes denses.
* Pourquoi?
. . .
* Dans les graphes peu denses, la matrice d'adjacence est essentiellement composée de `0`.
## Remarque
* Dans la majorité des cas, les grands graphes sont peu denses.
* Comment représenter un graphe autrement?
# La liste d'adjacence (non-orienté)
* Pour chaque sommet $v\in V$, stocker les sommets adjacents à $v$-
* Quelle structure de données pour la liste d'adjacence?
. . .
* Tableau de liste chaînée, vecteur (tableau dynamique), etc.
::: columns
:::: column
## Exemple
![Un graphe non-orienté.](figs/ex_graph_adj.pdf){width=80%}
::::
:::: column
## Quelle liste d'adjacence?
. . .
![La liste d'adjacence.](figs/ex_graph_list_adj.pdf)
::::
:::
# La liste d'adjacence (orienté)
::: columns
:::: column
## Quelle liste d'adjacence pour...
* Matrix (2min)
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
0-->1;
0-->2;
1-->2;
3-->0;
3-->1;
3-->2;
```
::::
:::: column
```
```
::::
:::
# Complexité
## Stockage
* Quelle espace est nécessaire pour stocker une liste d'adjacence (en fonction de $|E|$ et $|V|$)?
. . .
$$
\mathcal{O}(|E|)
$$
* Pour les graphes *non-orientés*: $\mathcal{O}2|E|$.
* Pour les graphes *orientés*: $\mathcal{O}|E|$.
## Définition
* Le **degré** d'un sommet $v$, est le nombre d'arêtes incidentes du sommet (pour les graphes orientés on a un degré entrant ou sortant).
* Comment on retrouve le degré de chaque sommet avec la liste d'adjacence?
. . .
* C'est la longueur de la liste chaînée.
# Parcours
* Beaucoup d'applications nécessitent de parcourir des graphes:
* Trouver un chemin d'un sommet à un autre;
* Trouver si le graphe est connexe;
* Il existe *deux* parcours principaux:
* en largeur (Breadth-First Search);
* en profondeur (Depth-First Search).
* Ces parcours créent *un arbre* au fil de l'exploration (si le graphe est non-connexe cela crée une *forêt*, un ensemble d'arbres).
# Illustration: parcours en largeur
![Le parcours en largeur.](figs/parcours_larg.pdf){width=80%}
# Exemple
## Étape par étape (blanc non-visité)
![Initialisation.](figs/parcours_larg_0.pdf){width=50%}
## Étape par étape (gris visité)
![On commence en `x`.](figs/parcours_larg_1.pdf){width=50%}
# Exemple
## Étape par étape
![On commence en `x`.](figs/parcours_larg_1.pdf){width=50%}
## Étape par étape (vert à visiter)
![Vister `w`, `t`, `y`.](figs/parcours_larg_2.pdf){width=50%}
# Exemple
## Étape par étape
![Vister `w`, `t`, `y`.](figs/parcours_larg_2.pdf){width=50%}
## Étape par étape
![`w`, `t`, `y` visités. `u`, `s` à visiter.](figs/parcours_larg_3.pdf){width=50%}
# Exemple
## Étape par étape
![`w`, `t`, `y` visités. `u`, `s` à visiter.](figs/parcours_larg_3.pdf){width=50%}
## Étape par étape
![`u`, `s`, visités. `r` à visiter.](figs/parcours_larg_4.pdf){width=50%}
# Exemple
## Étape par étape
![`u`, `s`, visités. `r` à visiter.](figs/parcours_larg_4.pdf){width=50%}
## Étape par étape
![`r` visité. `v` à visiter.](figs/parcours_larg_5.pdf){width=50%}
# Exemple
## Étape par étape
![`r` visité. `v` à visiter.](figs/parcours_larg_5.pdf){width=50%}
## Étape par étape
![The end. Plus rien à visiter!](figs/parcours_larg_6.pdf){width=50%}
# En faisant ce parcours...
::: columns
:::: column
## Du parcours de l'arbre
![](figs/parcours_larg_6.pdf){width=100%}
::::
:::: column
## Quel arbre est créé par le parcours (2min)?
. . .
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
0[x]-->1[w];
0-->2[t];
0-->3[y];
2-->9[u];
1-->4[s];
4-->5[r];
5-->6[v];
```
::::
:::
## Remarques
* Le parcours dépend du point de départ dans le graphe.
* L'arbre sera différent en fonction du noeud de départ, et de l'ordre de parcours des voisins d'un noeud.
# Le parcours en largeur
## L'algorithme, idée générale (3min, matrix)?
. . .
```C
v = un sommet du graphe
i = 1
pour sommet dans graphe et sommet non-visité
visiter(v, sommet, i) // marquer sommet à distance i visité
i += 1
```
## Remarque
* `i` est la distance de plus cours chemin entre `v` et les sommets en cours de visite.
# Le parcours en largeur
## L'algorithme, pseudo-code (3min, matrix)?
* Comment garder la trace de la distance?
. . .
* Utilisation d'une **file**
. . .
```C
initialiser(graphe) // tous sommets sont non-visités
file = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
tant que !est_vide(file)
v = défiler(file)
file = visiter(v, file)
```
## Que fait visiter?
```
file visiter(sommet, file)
sommet = visité
pour w = chaque arête de sommet
si w != visité
file = enfiler(file, w)
retourne file
```
# Exercice (5min)
## Appliquer l'algorithme sur le graphe
![](figs/parcours_larg_0.pdf){width=50%}
* En partant de `v`, `s`, ou `u` (par colonne de classe).
* Bien mettre à chaque étape l'état de la file.
# Complexité du parcours en largeur
## Étape 1
* Extraire un sommet de la file;
## Étape 2
* Traîter tous les sommets adjacents.
## Quelle est la complexité?
. . .
* Étape 1: $\mathcal{O}(|V|)$,
* Étape 2: $\mathcal{O}(2|E|)$,
* Total: $\mathcal{O}(|V| + |2|E|)$.
# Exercice
* Établir la liste d'adjacence et appliquer l'algorithme de parcours en largeur au graphe
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---3;
1---4;
2---3;
2---6;
3---6;
3---4;
3---5;
4---5;
```
# Illustration: parcours en profondeur
![Le parcours en profondeur. À quel parcours d'arbre cela ressemble-t-il?](figs/parcours_prof.pdf){width=80%}
# Parcours en profondeur
## Idée générale
* Initialiser les sommets comme non-lus
* Visiter un sommet
* Pour chaque sommet visité, on visite un sommet adjacent s'il est pas encore visité récursivement.
## Remarque
* La récursivité est équivalent à l'utilisation d'une **pile**.
# Parcours en profondeur
## Pseudo-code (5min)
. . .
```C
initialiser(graphe) // tous sommets sont non-visités
pile = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
tant que !est_vide(pile)
v = dépiler(pile)
pile = visiter(v, pile)
```
## Que fait visiter?
. . .
```C
pile visiter(sommet, pile)
sommet = visité
pour w = chaque arête de sommet
si w != visité
pile = empiler(pile, w)
retourne pile
```
# Exercice
* Établir la liste d'adjacence et appliquer l'algorithme de parcours en profondeur au graphe
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---3;
1---4;
2---3;
2---6;
3---6;
3---4;
3---5;
4---5;
```
# Interprétation des parcours
* Un graphe vu comme espace d'états (sommet: état, arête: action);
* Labyrinthe;
* Arbre des coups d'un jeu.
. . .
* BFS (Breadth-First) ou DFS (Depth-First) parcourent l'espace des états à la recherche du meilleur mouvement.
* Les deux parcourent *tout* l'espace;
* Mais si l'arbre est grand, l'espace est gigantesque!
. . .
* Quand on a un temps limité
* BFS explore beaucoup de coups dans un futur proche;
* DFS explore peu de coups dans un futur lointain.
---
title: "Graphes - Plus court chemin"
date: "2022-05-03"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Questions
* Qu'est-ce qu'un graphe? Un graphe orienté? Un graphe pondéré?
. . .
* Ensemble de sommets et arêtes, avec une direction, possédant une pondération.
* Comment représenter un graphe informatiquement?
. . .
* Liste ou matrice d'adjacence.
* Quels sont les deux parcours que nous avons vus?
. . .
* Parcours en largeur et profondeur.
* Donner l'idée générale des deux parcours.
# Illustration: plus courts chemins
![Illustration de plus court chemin de `s` à `t`.](figs/courts_chemin_intro.pdf)
# Plus courts chemins
## Contexte: les réseaux (informatique, transport, etc.)
* Graphe orienté;
* Source: sommet `s`;
* Destination: sommet `t`;
* Les arêtes ont des poids (coût d'utilisation, distance, etc.);
* Le coût d'un chemin est la somme des poids des arêtes d'un chemin.
## Problème à résoudre
* Quel est le plus court chemin entre `s` et `t`.
# Exemples d'application de plus court chemin
## Devenir riches!
* On part d'un tableau de taux de change entre devises.
* Quelle est la meilleure façon de convertir l'or en dollar?
![Taux de change.](figs/taux_change.pdf){width=80%}
. . .
* 1kg d'or => 327.25 dollars
* 1kg d'or => 208.1 livres => 327 dollars
* 1kg d'or => 455.2 francs => 304.39 euros => 327.28 dollars
# Exemples d'application de plus court chemin
## Formulation sous forme d'un graphe: Comment (3min)?
![Taux de change.](figs/taux_change.pdf){width=80%}
# Exemples d'application de plus court chemin
## Formulation sous forme d'un graphe: Comment (3min)?
![Graphes des taux de change.](figs/taux_change_graphe.pdf){width=60%}
* Un sommet par devise;
* Une arête orientée par transaction possible avec le poids égal au taux de change;
* Trouver le chemin qui maximise le produit des poids.
. . .
## Problème
* On aimerait plutôt avoir une somme...
# Exemples d'application de plus court chemin
## Conversion du problème en plus court chemin
* Soit `taux(u, v)` le taux de change entre la devise `u` et `v`.
* On pose `w(u,w)=-log(taux(u,v))`
* Trouver le chemin poids minimal pour les poids `w`.
![Graphe des taux de change avec logs.](figs/taux_change_graphe_log.pdf){width=60%}
* Cette conversion se base sur l'idée que
$$
\log(u\cdot v)=\log(u)+\log(v).
$$
# Applications de plus courts chemins
## Quelles applications voyez-vous?
. . .
* Déplacement d'un robot;
* Planificaiton de trajet / trafic urbain;
* Routage de télécommunications;
* Réseau électrique optimal;
* ...
# Plus courts chemins à source unique
* Soit un graphe, $G=(V, E)$, une fonction de pondération $w:E\rightarrow\mathbb{R}$, et un sommet $s\in V$
* Trouver pour tout sommet $v\in V$, le chemin de poids minimal reliant $s$ à $v$.
* Algorithmes standards:
* Dijkstra (arêtes de poids positif seulement);
* Bellman-Ford (arêtes de poids positifs ou négatifs, mais sans cycles).
* Comment résoudre le problèmes si tous les poids sont les mêmes?
. . .
* Un parcours en largeur!
# Algorithme de Dijkstra
## Comment chercher pour un plus court chemin?
. . .
```
si distance(u,v) > distance(u,w) + distance(w,v)
on passe par w plutôt qu'aller directement
```
# Algorithme de Dijkstra
## Idée générale
* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres.
* Tous les noeuds sont marqués non-visités.
* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud.
* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité).
* Continuer avec le noeud à la distance la plus faible.
* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie.
# Algorithme de Dijkstra
## Pseudo-code (5min, matrix)
. . .
```C
tab dijkstra(graph, s, t)
pour chaque v dans graphe
distance[v] = infini
q = ajouter(q, v)
distance[s] = 0
tant que non_vide(q)
u = min(q, distance) // plus petite distance dans q
si u == t
retourne distance
q = remove(q, u)
// voisin de u encore dans q
pour chaque v dans voisinage(u, q)
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
retourne distance
```
# Algorithme de Dijkstra
* Cet algorithme, nous donne le plus court chemin mais...
* ne nous donne pas le chemin!
## Comment modifier l'algorithme pour avoir le chemin?
. . .
* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu!
* On a besoin d'un tableau `précédent`.
## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix)
# Algorithme de Dijkstra
```C
tab, tab dijkstra(graph, s, t)
pour chaque v dans graphe
distance[v] = infini
précédent[v] = indéfini
q = ajouter(q, v)
distance[s] = 0
tant que non_vide(q)
u = min(q, distance) // plus petite distance dans q
si u == t
retourne distance
q = remove(q, u)
// voisin de u encore dans q
pour chaque v dans voisinage(u, q)
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
précédent[v] = u
retourne distance, précédent
```
# Algorithme de Dijkstra
## Comment reconstruire un chemin ?
. . .
```C
pile parcours(précédent, s, t)
sommets = vide
u = t
// on a atteint t ou on ne connait pas de chemin
si u != s && précédent[u] != indéfini
tant que vrai
sommets = empiler(sommets, u)
u = précédent[u]
si u == s // la source est atteinte
retourne sommets
retourne sommets
```
# Algorithme de Dijkstra
::: columns
:::: column
![Initialisation.](figs/dijkstra_0.png)
::::
:::: column
. . .
![1 visité, `D[2]=1`, `D[4]=3`.](figs/dijkstra_1.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est 2.](figs/dijkstra_1.png)
::::
:::: column
. . .
![2 visité, `D[3]=2`, `D[7]=3`.](figs/dijkstra_2.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est 3.](figs/dijkstra_2.png)
::::
:::: column
. . .
![3 visité, `D[7]=3` inchangé, `D[6]=6`.](figs/dijkstra_3.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est 4 ou 7.](figs/dijkstra_3.png)
::::
:::: column
. . .
![4 visité, `D[7]=3` inchangé, `D[5]=9`.](figs/dijkstra_4.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est `7`.](figs/dijkstra_4.png)
::::
:::: column
. . .
![7 visité, `D[5]=7`, `D[6]=6` inchangé.](figs/dijkstra_5.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est 6.](figs/dijkstra_5.png)
::::
:::: column
. . .
![`6` visité, `D[5]=7` inchangé.](figs/dijkstra_6.png)
::::
:::
# Algorithme de Dijkstra
::: columns
:::: column
![Plus court est 5 et c'est la cible.](figs/dijkstra_6.png)
::::
:::: column
. . .
![The end, tous les sommets ont été visités.](figs/dijkstra_7.png)
::::
:::
# Algorithme de Dijkstra amélioré
## On peut améliorer l'algorithme
* Avec une file de priorité!
## Une file de priorité est
* Une file dont chaque élément possède une priorité,
* Elle existe en deux saveurs: `min` ou `max`:
* File `min`: les éléments les plus petits sont retirés en premier.
* File `max`: les éléments les plus grands sont retirés en premier.
* On regarde l'implémentation de la `max`.
## Comment on fait ça?
. . .
* On insère les éléments à haute priorité tout devant dans la file!
# Les files de priorité
## Trois fonction principales
```C
booléen est_vide(élément) // triviale
élément enfiler(élément, data, priorité)
data défiler(élément)
rien modifier_priorité(élément, data, priotié)
nombre priorité(data) // utilitaire
```
## Pseudo-implémentation: structure (1min)
. . .
```C
struct élément
data
priorité
élément suivant
```
# Les files de priorité
## Pseudo-implémentation: enfiler (2min)
. . .
```C
élément enfiler(élément, data, priorité)
n_élément = créer_élément(data, priorité)
si est_vide(élément)
retourne n_élément
si priorité(d) > priorité(e.d)
n_élément.suivant = élément
retourne n_élément
sinon
tmp = élément
préc = élément
tant que !est_vide(tmp) && priorité < tmp.priorité
préc = tmp
tmp = tmp.suivant
prev.suivant = n_élément
n_élément.suivant = tmp
retourne élément
```
# Les files de priorité
## Pseudo-implémentation: défiler (2min)
. . .
```C
data, élément défiler(élément)
si est_vide(élément)
retourne AARGL!
sinon
tmp = élément.data
n_élément = élément.suivant
libérer(élément)
retourne tmp, n_élément
```
# Algorithme de Dijkstra avec file de priorité min
```C
distance, précédent dijkstra(graphe, s, t):
distance[source] = 0
fp = file_p_vide()
pour v dans sommets(graphe)
si v != s
distance[v] = infini
précédent[v] = indéfini
fp = enfiler(fp, v, distance[v])
tant que !est_vide(fp)
u, fp = défiler(fp)
pour v dans voisinage de u
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
précédent[v] = u
fp = changer_priorité(fp, v, n_distance)
retourne distance, précédent
```
# Algorithme de Dijkstra avec file
\footnotesize
```C
distance dijkstra(graphe, s, t)
---------------------------------------------------------
pour v dans sommets(graphe)
O(V) si v != s
distance[v] = infini
O(V) fp = enfiler(fp, v, distance[v]) // notre impl est nulle
------------------O(V * V)-------------------------------
tant que !est_vide(fp)
O(1) u, fp = défiler(fp)
---------------------------------------------------------
O(E) pour v dans voisinage de u
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
O(V) fp = changer_priorité(fp, v, n_distance)
---------------------------------------------------------
retourne distance
```
* Total: $\mathcal{O}(|V|^2+|E|\cdot |V|)$:
* Graphe dense: $\mathcal{O}(|V|^3)$
* Graphe peu dense: $\mathcal{O}(|V|^2)$
# Algorithme de Dijkstra avec file
## On peut faire mieux
* Avec une meilleure implémentation de la file de priorité:
* Tas binaire: $\mathcal{O}(|V|\log|V|+|E|\log|V|)$.
* Tas de Fibonnacci: $\mathcal{O}(|V|+|E|\log|V|)$
* Graphe dense: $\mathcal{O}(|V|^2\log|V|)$.
* Graphe peu dense: $\mathcal{O}(|V|\log|V|)$.
# Algorithme de Dijkstra (exercice, 5min)
![L'exercice.](figs/dijkstra_exo.png){width=60%}
* Donner la liste de priorité, puis...
## A chaque étape donner:
* Le tableau des distances à `a`;
* Le tableau des prédécessueurs;
* L'état de la file de priorité.
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 1.](figs/dijkstra_ex_0.png)
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 2.](figs/dijkstra_ex_1.png)
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 3.](figs/dijkstra_ex_2.png)
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 4.](figs/dijkstra_ex_3.png)
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 5.](figs/dijkstra_ex_4.png)
# Algorithme de Dijkstra (corrigé)
![Le corrigé partie 6.](figs/dijkstra_ex_5.png)
# Limitation de l'algorithme de Dijkstra
## Que se passe-t-il pour?
![Exemple.](figs/exemple_neg.png){width=50%}
## Quel est le problème?
. . .
* L'algorithme n'essaiera jamais le chemin `s->x->y->v` et prendra direct `s->v`.
* Ce problème n'apparaît que s'il y a des poids négatifs.
......@@ -17,22 +17,27 @@ patat:
# Questions
* Qu'est-ce qu'un graphe? Un graphe orienté? Un graphe pondéré?
* A quoi sert l'algorithme de Dijkstra?
. . .
* Ensemble de sommets et arêtes, avec une direction, possédant une pondération.
* Comment représenter un graphe informatiquement?
* A trouver le plus court chemin entre un sommet, $s$, d'un graphe pondéré et tous les autres sommets.
* Quelle est la limitation de l'algorithme de Dijkstra?
. . .
* Liste ou matrice d'adjacence.
* Quels sont les deux parcours que nous avons vus?
* Les poids doivent être positifs.
* Résumer les étapes de l'algorithme de Dijkstra.
. . .
* Parcours en largeur et profondeur.
* Donner l'idée générale des deux parcours.
* `distance[source] = 0`, `ditance[reste]=inf`;
* enfiler tous les sommets, `distance <=> priorité`;
* tant qu'il y a des sommets dans la file:
* u = défiler;
* pour tous les sommets `v` dans le voisinage de `u`;
* mettre à jour `distance[v]` (priorité et précédence) si `distance[v] > distance[u] + w(u,v)`.
# Plus cours chemin pour toute paire de sommets
......@@ -438,7 +443,7 @@ $$
. . .
* Moralité: si le chemin est plus court en passant par $k$, alors il faut qu'il soit le prédécesseur!
* Moralité: si le chemin est plus court en passant par $k$, alors il faut utiliser son prédécesseur!
# Algorithme de Floyd--Warshall
......@@ -545,4 +550,227 @@ $$
## Appliquer l'algorithme de Floyd--Warshall au graphe suivant
![The exorcist.](figs/floyd_exercice.png)
![The exorcist.](figs/floyd_exercice.png){width=50%}
* Bien indiquer l'état de $D$ et $P$ à chaque étape!
* Ne pas oublier de faire la matrice d'adjacence évidemment...
# La suite
* Sans transition.... la suite!
# Trouver un réseau électrique pour
![Ces maisons n'ont pas d'électricité.](figs/arbre_couvrant_vide.png)
# Solution: pas optimale
![Le réseau simple, mais nul.](figs/arbre_couvrant_mal.png)
* La longueur totale des câbles est super longue!
# Solution: optimale
![Le meilleur réseau.](figs/arbre_couvrant_bien.png)
# Formalisation: Les arbres couvrants
## Application: minimisation des coûrs
* Équipement d'un lotissement avec des lignes électriques/téléphoniques, des canalisations, ...
. . .
* Pour réduire les coûts, on cherche à minimiser la longueur totale des câbles/tuyaux.
. . .
* Les lignes/tuyaux forment un *arbre couvrant*.
. . .
* La meilleure option est un *arbre couvrant minimal*.
# Formalisation: Les arbres couvrants
* Qu'est-ce qu'un arbre couvrant? Des idées? De quel objet on part? Où va-t-on?
. . .
* Un arbre couvrant d'un graphe non-orienté et connexe est:
* un arbre inclu dans le graphe qui connecte tous les sommets du graphe.
. . .
![Exemple d'arbres couvrants d'un graphe connexe.](figs/arbre_couvrant_exemples.png)
# Arbres couvrants
* Quels algorithmes que nous avons déjà vus permettent de construire des arbres couvrants?
. . .
* Les parcours en largeur et en profondeur!
. . .
![Graphe, et parcours comme arbres couvrants.](figs/arbres_couvrants_parcours.png)
# Arbres couvrants minimaux
* Un *arbre couvrant minimal* est un sous-graphe d'un graphe non-orienté pondéré $G(V,E)$, tel quel:
* C'est un arbre (graphe acyclique);
* Il couvre tous les sommets de $G$ et contient $|V|-1$ arêtes;
* Le coût total associé aux arêtes de l'arbre est minimum parmi tous les arbres couvrants possibles.
. . .
* Est-il unique?
. . .
* Pas forcément.
# Arbres couvrants minimaux
* Comment générer un arbre couvrant minimal?
![Un graphe, connexe, non-orienté, pondéré, et son arbre couvrant minimal.](figs/arbre_couvrant_minimal_exemple.png)
# Algorithme de Prim
::: columns
:::: column
## Un exemple
![Le graphe de départ.](figs/prim_0.png)
::::
:::: column
## On part de `e` (au hasard)
![Le sommet `e` est couvert.](figs/prim_1.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_1.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `e->d`
![Le sommet `d` est couvert.](figs/prim_2.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_2.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `d->a`
![Le sommet `a` est couvert.](figs/prim_3.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_3.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `d->c`
![Le sommet `c` est couvert.](figs/prim_4.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_4.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `e->b`
![Le sommet `b` est couvert.](figs/prim_5.png)
::::
:::
* Game over!
---
title: "Graphes - Arbres couvrants"
date: "2022-05-03"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Questions
* A quoi sert l'algorithme de Floyd--Warshall?
. . .
* A trouver le plus court chemin entre n'importe quelle paire de sommets d'un graphe pondéré.
* Quelle est la limitation de l'algorithme de Dijkstra n'est pas présente pour l'algorithme de Floyd--Warshall?
. . .
* Les poids peuvent être négatifs.
* Qu'est-ce qu'un *arbre couvrant minimal*?
. . .
* Un arbre couvrant minimal d'un graphe non-orienté et connexe est:
* un arbre inclu dans le graphe qui connecte tous les sommets du graphe et dont le poids total des arêtes est minimal.
# Arbres couvrants minimaux
* Comment générer un arbre couvrant minimal?
![Un graphe, connexe, non-orienté, pondéré, et son arbre couvrant minimal.](figs/arbre_couvrant_minimal_exemple.png)
# Algorithme de Prim
::: columns
:::: column
## Un exemple
![Le graphe de départ.](figs/prim_0.png)
::::
:::: column
## On part de `e` (au hasard)
![Le sommet `e` est couvert.](figs/prim_1.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_1.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `e->d`
![Le sommet `d` est couvert.](figs/prim_2.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_2.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `d->a`
![Le sommet `a` est couvert.](figs/prim_3.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_3.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `d->c`
![Le sommet `c` est couvert.](figs/prim_4.png)
::::
:::
# Algorithme de Prim
::: columns
:::: column
## On choisit comment?
![Quelle arête choisir?](figs/prim_4.png)
. . .
* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
::::
:::: column
. . .
## L'arête `e->b`
![Le sommet `b` est couvert.](figs/prim_5.png)
::::
:::
* Game over!
# Algorithme de Prim
## Structures de données
* Dans quoi allons nous stocker les sommets?
. . .
* File de priorité min.
* Autre chose?
. . .
* Tableau des distances (comme pour Dijkstra).
* Autre chose?
. . .
* Tableau des parents (presque comme pour Dijkstra).
* Autre chose?
. . .
* Non.
# Algorithme de Prim
## Initialisation: Pseudo-code (2min)
. . .
```C
file_priorité, distance, parent initialisation(graphe)
r = aléatoire(graphe)
distance[r] = 0
parent[r] = indéfini
fp = file_p_vide()
pour v dans sommets(graphe)
si v != r
distance[v] = infini
parent[v] = indéfini
fp = enfiler(fp, v, distance[v])
retourne fp, distance, parent
```
# Algorithme de Prim
## Algorithme: Pseudo-code (5min)
. . .
```C
sommets, parent prim(file_priorité, distance, parent)
sommets = vide
tant que !est_vide(file_priorité)
u, fp = défiler(file_priorité)
sommets = insérer(sommets, u)
pour v dans voisinage de u et pas dans sommets
// ou dans file_priorité
si w(u, v) < distance[v]
parent[w] = u
distance[w] = w(u, v)
fp = changer_priorité(fp, w, w(u, v))
retourne sommets, parent
```
# Exemple d'algorithme de Prim
::: columns
:::: {.column width="40%"}
## Un exemple
![Étape 1.](figs/prim_1.png)
::::
:::: column
```
FP | e | d | b | c | a |
----------------------------------
D | 0 | inf | inf | inf | inf |
| e | d | b | c | a |
----------------------------------
P | - | - | - | - | - |
```
## Devient?
. . .
```
FP | d | b | c | a |
----------------------------
D | 4 | 5 | 5 | inf |
| e | d | b | c | a |
----------------------------------
P | - | e | e | e | - |
```
::::
:::
# Exemple d'algorithme de Prim
::: columns
:::: {.column width="40%"}
## Un exemple
![Étape 2.](figs/prim_2.png)
::::
:::: column
```
FP | d | b | c | a |
----------------------------
D | 4 | 5 | 5 | inf |
| e | d | b | c | a |
----------------------------------
P | - | e | e | e | - |
```
## Devient?
. . .
```
FP | a | c | b |
----------------------
D | 2 | 4 | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
::::
:::
# Exemple d'algorithme de Prim
::: columns
:::: {.column width="40%"}
## Un exemple
![Étape 3.](figs/prim_3.png)
::::
:::: column
```
FP | a | c | b |
----------------------
D | 2 | 4 | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
## Devient?
. . .
```
FP | c | b |
----------------
D | 4 | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
::::
:::
# Exemple d'algorithme de Prim
::: columns
:::: {.column width="40%"}
## Un exemple
![Étape 4.](figs/prim_4.png)
::::
:::: column
```
FP | c | b |
----------------
D | 4 | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
## Devient?
. . .
```
FP | b |
----------
D | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
::::
:::
# Exemple d'algorithme de Prim
::: columns
:::: {.column width="40%"}
## Un exemple
![Étape 5.](figs/prim_4.png)
::::
:::: column
```
FP | b |
----------
D | 5 |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
## Devient?
. . .
```
FP |
----
D |
| e | d | b | c | a |
----------------------------------
P | - | e | e | d | d |
```
::::
:::
# Exercice: algorithme de Prim
## Appliquer l'algorithme de Prim à (15min):
![En démarrant du sommet $V_1$.](figs/prim_exercice.png)
# Exercice: algorithme de Prim
## Solution
![](figs/prim_solution.png)
# Complexité de l'algorithme de Prim
\footnotesize
```C
file_priorité, distance, parent initialisation(graphe)
// choix r et initialisation
pour v dans sommets(graphe)
O(|V|) // initialisation distance et parent
fp = enfiler(fp, v, distance[v])
retourne fp, distance, parent
sommets, parent prim(file_priorité, distance, parent)
sommets = vide
tant que !est_vide(file_priorité)
O(|V|) u, fp = défiler(file_priorité)
sommets = insérer(sommets, u)
pour v dans voisinage de u et pas dans sommets
O(|E|) si w(u, v) < distance[v]
// màj dista + parent
O(|V|) fp = changer_priorité(fp, w, w(u, v))
retourne sommets, parent
```
* $O(|V|)+O(|E|)+O(|V|^2)=O(|E|+|V|^2)$
* Remarque: $O(|E|)$ n'est pas mutliplié par $O(|V|)$, car les arêtes parcourues qu'une fois en **tout**.
# Algorithme de Kruskal
* On ajoute les arêtes de poids minimal:
* si cela ne crée pas de cycle;
* on s'arrête quand on a couvert tout le graphe.
. . .
* Comment on fait ça?
. . .
* Faisons un exemple pour voir.
# Algorithme de Kruskal: exemple
::: columns
:::: column
## Un exemple
![Le graphe de départ.](figs/kruskal_0.png)
::::
:::: column
## On part de `(a, d)` (poids le plus faible)
![Les sommets `a, d` sont couverts.](figs/kruskal_1.png)
::::
:::
# Algorithme de Kruskal: exemple
::: columns
:::: column
## On continue avec `(c, d)`
![On aurait pu choisir `(d, e)` aussi.](figs/kruskal_1.png)
::::
:::: column
## Résultat
![Les sommets `a, d, c` sont couverts.](figs/kruskal_2.png)
::::
:::
# Algorithme de Kruskal: exemple
::: columns
:::: column
## On continue avec `(d, e)`
![Le poids de `(d, e)` est le plus bas.](figs/kruskal_2.png)
::::
:::: column
## Résultat
![Les sommets `a, d, c, e` sont couverts.](figs/kruskal_3.png)
::::
:::
# Algorithme de Kruskal: exemple
::: columns
:::: column
## On continue avec `(b, e)`
![Le poids de `(b, e)` est le plus bas.](figs/kruskal_3.png)
::::
:::: column
## Résultat
![Les sommets `a, d, c, e, b` sont couverts.](figs/kruskal_4.png)
::::
:::
# Algorithme de Kruskal: exemple
::: columns
:::: column
## Mais pourquoi pas `(c, e)`?
![Le poids de `(b, e)` ou `(a,c)` est le même.](figs/kruskal_3.png)
::::
:::: column
## Résultat: un cycle
![Les sommets `a, d, c, e` sont couverts.](figs/kruskal_cycle.png)
::::
:::
* Comment faire pour empêcher l'ajout de `(c, e)` ou `(a, c)`?
. . .
* Si les deux sommets sont déjà couverts nous sommes sauvés (presque)!
# Algorithme de Kruskal
## L'initialisation
* Créer un ensemble de sommets pour chaque de sommet du graphe ($V_1$, $V_2$, ...):
* $V_1=\{v_1\}$, $V_2=\{v_2\}$, ...
* S'il y a $n$ sommets, il y a $n$ $V_i$.
* Initialiser l'ensemble $A$ des arêtes "sûres" constituant l'arbre couvrant minimal, $A=\emptyset$.
* Initialiser l'ensemble des sommets couverts $F=\emptyset$
* Trier les arêtes par poids croissant dans l'ensemble $E$.
## Mise à jour
* Tant qu'il reste plus d'un $V_i$:
* Pour $(u,v)\in A$ à poids minimal:
* Retirer $(u,v)$ de $A$,
* Si $u\in V_i$ et $v\in V_j$ avec $V_i\cap V_j=\emptyset$:
* Ajouter $(u,v)$ à $A$;
* Fusionner $U$ et $V$ dans $F$.
# Algorithme de Kruskal: exemple
::: columns
:::: column
![Couvrir cet arbre bon sang!](figs/kruskal_enonce.png)
::::
:::: column
::::
:::
# Algorithme de Kruskal: solution
![La solution!](figs/kruskal_solution.png)
# Algorithme de Kruskal: exercice
::: columns
:::: column
![Couvrir cet arbre bon sang!](figs/kruskal_exercice.png)
::::
:::: column
::::
:::
# Algorithme de Kruskal: solution
![La solution!](figs/kruskal_solution_exercice.png)
---
title: "Introduction aux algorithmes"
date: "2021-10-06"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Quelques algorithmes simples
## Quelques algorithmes supplémentaires
* Remplissage d'un tableau et recherche de la valeur minimal
* Anagrammes
* Palindromes
* Crible d'ératosthène
# Collections: tableaux statiques
* Objets de même type: leur nombre est **connu à la compilation**;
* Stockés contigüement en mémoire (très efficace);
```C
#define SIZE 10
int entiers[] = {2, 1, 4, 5, 7}; // taille 5, initialisé
int tab[3]; // taille 3, non initialisé
float many_floats[SIZE]; // taille 10, non initialisé
```
* Les indices sont numérotés de `0` à `taille-1`;
```C
int premier = entier[0]; // premier = 2
int dernier = entier[4]; // dernier = 7
```
* Les tableaux sont **non-initialisés** par défaut;
* Les bornes ne sont **jamais** vérifiées.
```C
int indetermine_1 = tab[1]; // undefined behavior
int indetermine_2 = entiers[5]; // UB
```
# Remarques
* Depuis `C99` possibilité d'avoir des tableaux dont la taille est *inconnue à
la compilation*;
```C
int size;
scanf("%d", &size);
char string[size];
```
. . .
* Considéré comme une mauvaise pratique: que se passe-t-il si `size == 1e9`?
* On préfère utiliser l'allocation **dynamique** de mémoire pour ce genre de
cas-là (spoiler du futur du cours).
# Initialisation
* Les variables ne sont **jamais** initialisées en `C` par défaut.
* Question: Que contient le tableau suivant?
```C
double tab[4];
```
. . .
* Réponse: On en sait absolument rien!
* Comment initialiser un tableau?
. . .
```C
#define SIZE 10
double tab[SIZE];
for (int i = 0; i < SIZE; ++i) {
tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0;
// tab[i] contient un double dans [-5;5]
}
```
# Recherche du minimum dans un tableau (1/2)
## Problématique
Trouver la valeur minimale contenue dans un tableau et l'indice de l'élément le plus petit.
## Écrire un pseudo-code résolvant ce problème (groupe de 3), 2min
. . .
```C
index = 0
min = tab[0]
for i in [1; SIZE] {
if min > tab[i] {
min = tab[i]
index = i
}
}
```
# Recherche du minimum dans un tableau (2/2)
## Implémenter ce bout de code en C (groupe de 3), 4min
. . .
```C
int index = 0;
float min = tab[0];
for (int i = 1; i < SIZE; ++i) {
if min > tab[i] {
min = tab[i];
index = i;
}
}
```
# Tri par sélection (1/2)
## Problématique
Trier un tableau par ordre croissant.
## Idée d'algorithme
```C
ind = 0
boucle (ind < SIZE-1) {
Trouver le minimum du tableau, tab_min[ind:SIZE].
Échanger tab_min avec tab[ind]
ind += 1
}
```
# Tri par sélection (2/2)
## Implémentation par groupe de 3
* Initialiser aléatoirement un tableau de `double` de taille 10;
* Afficher le tableau;
* Trier par sélection le tableau;
* Afficher le résultat trié;
* Vérifier algorithmiquement que le résultat est bien trié.
# Un type de tableau particulier
## Les chaînes de caractères
```C
string = tableau + char + magie noire
```
# Le type `char`{.C}
- Le type `char`{.C} est utilisé pour représenter un caractère.
- C'est un entier 8 bits signé.
- En particulier:
- Écrire
```C
char c = 'A';
```
- Est équivalent à:
```C
char c = 65;
```
- Les fonctions d'affichage interprètent le nombre comme sa valeur ASCII.
# Chaînes de caractères (strings)
- Chaîne de caractère `==` tableau de caractères **terminé par la valeur** `'\0'`{.C} ou `0`{.C}.
## Exemple
```C
char *str = "HELLO !";
char str[] = "HELLO !";
```
Est représenté par
| `char` | `H` | `E` | `L` | `L` | `O` | | `!` | `\0`|
|---------|------|------|------|------|------|------|------|-----|
| `ASCII` | `72` | `69` | `76` | `76` | `79` | `32` | `33` | `0` |
. . .
## A quoi sert le `\0`?
. . .
Permet de connaître la fin de la chaîne de caractères (pas le cas des autres
sortes de tableaux).
# Syntaxe
```C
char name[5];
name[0] = 'P'; // = 70;
name[1] = 'a'; // = 97;
name[2] = 'u'; // = 117;
name[3] = 'l'; // = 108;
name[4] = '\0'; // = 0;
char name[] = {'P', 'a', 'u', 'l', '\0'};
char name[5] = "Paul";
char name[] = "Paul";
char name[100] = "Paul is not 100 characters long.";
```
# Fonctions
- Il existe une grande quantités de fonction pour la manipulation de chaînes de caractères dans `string.h`.
- Fonctions principales:
```C
// longueur de la chaîne (sans le \0)
size_t strlen(char *str);
// copie jusqu'à un \0
char *strcpy(char *dest, const char *src);
// copie len char
char *strncpy(char *dest, const char *src, size_t len);
// compare len chars
int strncmp(char *str1, char *str2, size_t len);
// compare jusqu'à un \0
int strcmp(char *str1, char *str2);
```
- Pour avoir la liste complète: `man string`.
. . .
## Quels problèmes peuvent se produire avec `strlen`, `strcpy`, `strcmp`?
# Les anagrammes
## Définition
Deux mots sont des anagrammes l'un de l'autre quand ils contiennent les mêmes
lettres mais dans un ordre différent.
## Exemple
| `t` | `u` | `t` | `u` | `t` | `\0` | ` ` | ` ` |
|------|------|------|------|------|------|------|-----|
| `t` | `u` | `t` | `t` | `u` | `\0` | ` ` | ` ` |
## Problème: Trouvez un algorithme pour déterminer si deux mots sont des anagrammes.
# Les anagrammes
## Il suffit de:
1. Trier les deux mots.
2. Vérifier s'ils contiennent les mêmes lettres.
## Implémentation en live (offerte par HepiaVPN)
```C
int main() { // pseudo C
tri(mot1);
tri(mot2);
if egalite(mot1, mot2) {
// anagrammes
} else {
// pas anagrammes
}
}
```
<!-- TODO: Live implémentation hors des cours? -->
# Les palindromes
Mot qui se lit pareil de droite à gauche que de gauche à droite:
. . .
* rotor, kayak, ressasser, ...
## Problème: proposer un algorithme pour détecter un palindrome
. . .
## Solution 1
```C
while (first_index < last_index {
if (mot[first_index] != mot [last_index]) {
return false;
}
first_index += 1;
last_index -= 1;
}
return true;
```
. . .
## Solution 2
```C
mot_tmp = revert(mot);
return mot == mot_tmp;
```
# Crible d'Ératosthène
Algorithme de génération de nombres premiers.
## Exercice
* À l'aide d'un tableau de booléens,
* Générer les nombres premiers plus petits qu'un nombre $N$
## Pseudo-code
* Par groupe de trois, réfléchir à un algorithme.
## Programme en C
* Implémenter l'algorithme et le poster sur le salon `Element`.
---
title: "Introduction aux algorithmes"
date: "2021-10-13"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Crible d'Ératosthène: solution
\footnotesize
```C
#include <stdio.h>
#include <stdbool.h>
#define SIZE 51
int main() {
bool tab[SIZE];
for (int i=0;i<SIZE;i++) {
tab[i] = true;
}
for (int i = 2; i < SIZE; i++) {
if (tab[i]) {
printf("%d ", i);
int j = i;
while (j < SIZE) {
j += i;
tab[j] = false;
}
}
}
printf("\n");
}
```
# Réusinage de code (refactoring)
## Le réusinage est?
. . .
* le processus de restructuration d'un programme:
* en modifiant son design,
* en modifiant sa structure,
* en modifiant ses algorithmes
* mais en **conservant ses fonctionalités**.
. . .
## Avantages?
. . .
* Amélioration de la lisibilité,
* Amélioration de la maintenabilité,
* Réduction de la complexité.
. . .
## "Make it work, make it nice, make it fast", Kent Beck.
. . .
## Exercice:
* Réusiner le code se trouvant sur
[Cyberlearn](https://cyberlearn.hes-so.ch/mod/resource/view.php?id=1627712).
# Tableau à deux dimensions (1/4)
## Mais qu'est-ce donc?
. . .
* Un tableau où chaque cellule est un tableau.
## Quels cas d'utilisation?
. . .
* Tableau à double entrée;
* Image;
* Écran (pixels);
* Matrice (mathématique);
# Tableau à deux dimensions (2/4)
## Exemple: tableau à 3 lignes et 4 colonnes d'entiers
+-----------+-----+-----+-----+-----+
| `indices` | `0` | `1` | `2` | `3` |
+-----------+-----+-----+-----+-----+
| `0` | `7` | `4` | `7` | `3` |
+-----------+-----+-----+-----+-----+
| `1` | `2` | `2` | `9` | `2` |
+-----------+-----+-----+-----+-----+
| `2` | `4` | `8` | `8` | `9` |
+-----------+-----+-----+-----+-----+
## Syntaxe
```C
int tab[3][4]; // déclaration d'un tableau 4x3
tab[2][1]; // accès à la case 2, 1
tab[2][1] = 14; // assignation de 14 à la position 2, 1
```
# Tableau à deux dimensions (3/4)
## Exercice: déclarer et initialiser aléatoirement un tableau `50x100`
. . .
```C
#define NX 50
#define NY 100
int tab[NX][NY];
for (int i = 0; i < NX; ++i) {
for (int j = 0; j < NY; ++j) {
tab[i][j] = rand() % 256; // 256 niveaux de gris
}
}
```
## Exercice: afficher le tableau
. . .
```C
for (int i = 0; i < NX; ++i) {
for (int j = 0; j < NY; ++j) {
printf("%d ", tab[i][j]);
}
printf("\n");
}
```
# Tableau à deux dimensions (4/4)
## Attention
* Les éléments ne sont **jamais** initialisés.
* Les bornes ne sont **jamais** vérifiées.
```C
int tab[3][2] = { {1, 2}, {3, 4}, {5, 6} };
printf("%d\n", tab[2][1]); // affiche?
printf("%d\n", tab[10][9]); // affiche?
printf("%d\n", tab[3][1]); // affiche?
```
# La couverture de la reine
* Aux échecs la reine peut se déplacer horizontalement et verticalement
* Pour un échiquier `5x6`, elle *couvre* les cases comme ci-dessous
+-----+-----+-----+-----+-----+-----+-----+
| ` ` | `0` | `1` | `2` | `3` | `4` | `5` |
+-----+-----+-----+-----+-----+-----+-----+
| `0` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `1` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `2` | `*` | `*` | `R` | `*` | `*` | `*` |
+-----+-----+-----+-----+-----+-----+-----+
| `3` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `4` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
## Exercice
* En utilisant les conditions, les tableaux à deux dimensions, et des
`char` uniquement.
* Implémenter un programme qui demande à l'utilisateur d'entrer les
coordonnées de la reine et affiche un tableau comme ci-dessus pour un
échiquier `8x8`.
## Poster le résultat sur `Element`
# Types énumérés (1/2)
* Un **type énuméré**: ensemble de *variantes* (valeurs constantes).
* En `C` les variantes sont des entiers numérotés à partir de 0.
```C
enum days {
monday, tuesday, wednesday,
thursday, friday, saturday, sunday
};
```
* On peut aussi donner des valeurs "custom"
```C
enum days {
monday = 2, tuesday = 8, wednesday = -2,
thursday = 1, friday = 3, saturday = 12, sunday = 9
};
```
* S'utilise comme un type standard et un entier
```C
enum days d = monday;
(d + 2) == tuesday + tuesday; // true
```
# Types énumérés (2/2)
* Très utile dans les `switch ... case`{.C}
```C
enum days d = monday;
switch (d) {
case monday:
// trucs
break;
case tuesday:
printf("0 ou 1\n");
break;
}
```
* Le compilateur vous prévient qu'il en manque!
# Utilisation des types énumérés
## Réusiner votre couverture de la reine avec des `enum`
# Représentation des nombres (1/2)
* Le nombre `247`.
## Nombres décimaux: Les nombres en base 10
+--------+--------+--------+
| $10^2$ | $10^1$ | $10^0$ |
+--------+--------+--------+
| `2` | `4` | `7` |
+--------+--------+--------+
$$
247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
$$
# Représentation des nombres (2/2)
* Le nombre `11110111`.
## Nombres binaires: Les nombres en base 2
+-------+-------+-------+-------+-------+-------+-------+-------+
| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
+-------+-------+-------+-------+-------+-------+-------+-------+
| `1` | `1` | `1` | `1` | `0` | `1` | `1` | `1` |
+-------+-------+-------+-------+-------+-------+-------+-------+
$$
1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
+1\cdot 2^1 +1\cdot 2^0
$$
. . .
$$
= 247.
$$
# Conversion de décimal à binaire (1/2)
## Convertir 11 en binaire?
. . .
* On décompose en puissances de 2 en partant de la plus grande possible
```
11 / 8 = 1, 11 % 8 = 3
3 / 4 = 0, 3 % 4 = 3
3 / 2 = 1, 3 % 2 = 1
1 / 1 = 1, 1 % 1 = 0
```
* On a donc
$$
1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
2^0=11.
$$
# Conversion de décimal à binaire (2/2)
## Convertir un nombre arbitraire en binaire: 247?
* Par groupe établir un algorithme.
. . .
## Algorithme
1. Initialisation
```C
num = 247
while (2^N < num) {
N += 1
}
```
. . .
2. Boucle
```C
while (N >= 0) {
bit = num / 2^N
num = num % 2^N
N += 1
}
```
# Les additions en binaire
Que donne l'addition `1101` avec `0110`?
* L'addition est la même que dans le système décimal
```
1101 8+4+0+1 = 13
+ 0110 + 0+4+2+0 = 6
------- -----------------
10011 16+0+0+2+1 = 19
```
* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
* Que se passe-t-il donc ici?
. . .
## Dépassement de capacité: le nombre est "tronqué"
* `10011 (19) -> 0011 (3)`.
* On fait "le tour"."
# Entier non-signés minimal/maximal
* Quel est l'entier non-signé maximal représentable avec 4 bit?
. . .
$$
(1111)_2 = 8+4+2+1 = 15
$$
* Quel est l'entier non-signé minimal représentable avec 4 bit?
. . .
$$
(0000)_2 = 0+0+0+0 = 0
$$
* Quel est l'entier non-signé min/max représentable avec N bit?
. . .
$$
0\mbox{ et }2^N-1.
$$
* Donc `uint32_t?` maximal est?
. . .
$$
4294967295
$$
# Les multiplications en binaire (1/2)
Que donne la multiplication de `1101` avec `0110`?
* L'addition est la même que dans le système décimal
```
1101 13
* 0110 * 6
--------- --------------
0000 78
11010
110100
+ 0000000
--------- --------------
1001110 64+0+0+8+4+2+0
```
# Les multiplications en binaire (2/2)
## Que fait la multiplication par 2?
. . .
* Décalage de un bit vers la gauche!
```
0110
* 0010
---------
0000
+ 01100
---------
01100
```
. . .
## Que fait la multiplication par $2^N$?
. . .
* Décalade de $N$ bits vers la gauche!
# Entiers signés (1/2)
Pas de nombres négatifs encore...
## Comment faire?
. . .
## Solution naïve:
* On ajoute un bit de signe (le bit de poids fort):
```
00000010: +2
10000010: -2
```
## Problèmes?
. . .
* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
* Les additions différentes que pour les non-signés (très grave)
```
00000010 2
+ 10000100 + -4
---------- ----
10000110 = -6 != -2
```
# Entiers signés (2/2)
## Beaucoup mieux
* Complément à un:
* on inverse tous les bits: `1001 => 0110`.
## Encore un peu mieux
* Complément à deux:
* on inverse tous les bits,
* on ajoute 1 (on ignore les dépassements).
. . .
* Comment écrit-on `-4` en 8 bits?
. . .
```
4 = 00000100
________
-4 => 00000100
11111011
+ 00000001
----------
11111100
```
# Le complément à 2 (1/2)
## Questions:
* Comment on écrit `+0` et `-0`?
* Comment calcule-t-on `2 + (-4)`?
* Quel est le complément à 2 de `1000 0000`?
. . .
## Réponses
* Comment on écrit `+0` et `-0`?
```
+0 = 00000000
-0 = 11111111 + 00000001 = 100000000 => 00000000
```
* Comment calcule-t-on `2 + (-4)`?
```
00000010 2
+ 11111100 + -4
---------- -----
11111110 -2
```
* En effet
```
11111110 => 00000001 + 00000001 = 00000010 = 2.
```
# Le complément à 2 (1/2)
## Quels sont les entiers représentables en 8 bits?
. . .
```
01111111 => 127
10000000 => -128 // par définition
```
## Quels sont les entiers représentables sur $N$ bits?
. . .
$$
-2^{N-1} ... 2^{N-1}-1.
$$
## Remarque: dépassement de capacité en `C`
* Comportement indéfini!
<!-- # TODO --
<!-- ## Entiers, entiers non-signés -->
<!-- ## Complément à 1, 2 -->
<!-- ## Nombres à virgule flottante, simple/double précision -->
# Types composés: `struct`{.C} (1/6)
## Fractions
* Numérateur: `int num`;
* Dénominateur: `int denom`.
## Addition
```C
int num1 = 1, denom1 = 2;
int num2 = 1, denom2 = 3;
int num3 = num1 * denom2 + num2 * denom1;
int denom3 = denom1 * denom2;
```
## Pas super pratique....
# Types composés: `struct`{.C} (2/6)
## On peut faire mieux
* Plusieurs variables qu'on aimerait regrouper dans un seul type: `struct`{.C}.
```C
struct fraction { // déclaration du type
int32_t num, denom;
}
struct fraction frac; // déclaration de frac
```
# Types composés: `struct`{.C} (3/6)
## Simplifications
- `typedef`{.C} permet de définir un nouveau type.
```C
typedef unsinged int uint;
typedef struct fraction fraction_t;
typedef struct fraction {
int32_t num, denom;
} fraction_t;
```
- L'initialisation peut aussi se faire avec
```C
fraction_t frac = {1, -2}; // num = 1, denom = -2
fraction_t frac = {.denom = 1, .num = -2};
fraction_t frac = {.denom = 1}; // argl! .num non initialisé
fraction_t frac2 = frac; // copie
```
# Types composés: `struct`{.C} (4/6)
## Pointeurs
- Comme pour tout type, on peut avoir des pointeurs vers un `struct`{.C}.
- Les champs sont accessible avec le sélecteur `->`{.C}
```C
fraction_t *frac; // on crée un pointeur
frac->num = 1; // seg fault...
frac->denom = -1; // mémoire pas allouée.
```
![La représentation mémoire de
`fraction_t`.](figs/pointer_struct.svg){width=50%}
# Types composés: `struct`{.C} (5/6)
## Initialisation
- Avec le passage par **référence** on peut modifier un struct *en place*.
- Les champs sont accessible avec le sélecteur `->`{.C}
```C
void fraction_init(fraction_t *frac,
int32_t re, int32_t im)
{
// frac a déjà été allouée
frac->num = frac;
frac->denom = denom;
}
int main() {
fraction_t frac; // on alloue une fraction
fraction_init(&frac, 2, -1); // on l'initialise
}
```
# Types composés: `struct`{.C} (6/6)
## Initialisation version copie
* On peut allouer une fraction, l'initialiser et le retourner.
* La valeur retournée peut être copiée dans une nouvelle structure.
```C
fraction_t fraction_create(int32_t re, int32_t im) {
fraction_t frac;
frac.num = re;
frac.denom = im;
return frac;
}
int main() {
// on crée une fraction et on l'initialise
// en copiant la fraction créé par fraction_create
// deux allocation et une copie
fraction_t frac = fraction_create(2, -1);
}
```
<!-- # TODO jusqu'aux vacances -->
<!-- * Refactorisation -->
<!-- * Tris et complexité -->
<!-- * Récursivité -->
---
title: "Représentation des nombres et récursivité"
date: "2021-10-20"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Représentation des nombres (1/2)
* Le nombre `247`.
## Nombres décimaux: Les nombres en base 10
+--------+--------+--------+
| $10^2$ | $10^1$ | $10^0$ |
+--------+--------+--------+
| `2` | `4` | `7` |
+--------+--------+--------+
$$
247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
$$
# Représentation des nombres (2/2)
* Le nombre `11110111`.
## Nombres binaires: Les nombres en base 2
+-------+-------+-------+-------+-------+-------+-------+-------+
| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
+-------+-------+-------+-------+-------+-------+-------+-------+
| `1` | `1` | `1` | `1` | `0` | `1` | `1` | `1` |
+-------+-------+-------+-------+-------+-------+-------+-------+
$$
1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
+1\cdot 2^1 +1\cdot 2^0
$$
. . .
$$
= 247.
$$
# Conversion de décimal à binaire (1/2)
## Convertir 11 en binaire?
. . .
* On décompose en puissances de 2 en partant de la plus grande possible
```
11 / 8 = 1, 11 % 8 = 3
3 / 4 = 0, 3 % 4 = 3
3 / 2 = 1, 3 % 2 = 1
1 / 1 = 1, 1 % 1 = 0
```
* On a donc
$$
1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
2^0=11.
$$
# Conversion de décimal à binaire (2/2)
## Convertir un nombre arbitraire en binaire: 247?
* Par groupe établir un algorithme.
. . .
## Algorithme
1. Initialisation
```C
num = 247
while (2^N < num) {
N += 1
}
```
. . .
2. Boucle
```C
while (N >= 0) {
bit = num / 2^N
num = num % 2^N
N += 1
}
```
# Les additions en binaire
Que donne l'addition `1101` avec `0110`?
* L'addition est la même que dans le système décimal
```
1101 8+4+0+1 = 13
+ 0110 + 0+4+2+0 = 6
------- -----------------
10011 16+0+0+2+1 = 19
```
* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
* Que se passe-t-il donc ici?
. . .
## Dépassement de capacité: le nombre est "tronqué"
* `10011 (19) -> 0011 (3)`.
* On fait "le tour"."
# Entier non-signés minimal/maximal
* Quel est l'entier non-signé maximal représentable avec 4 bit?
. . .
$$
(1111)_2 = 8+4+2+1 = 15
$$
* Quel est l'entier non-signé minimal représentable avec 4 bit?
. . .
$$
(0000)_2 = 0+0+0+0 = 0
$$
* Quel est l'entier non-signé min/max représentable avec N bit?
. . .
$$
0\mbox{ et }2^N-1.
$$
* Donc `uint32_t?` maximal est?
. . .
$$
4294967295
$$
# Les multiplications en binaire (1/2)
Que donne la multiplication de `1101` avec `0110`?
* L'addition est la même que dans le système décimal
```
1101 13
* 0110 * 6
--------- --------------
0000 78
11010
110100
+ 0000000
--------- --------------
1001110 64+0+0+8+4+2+0
```
# Les multiplications en binaire (2/2)
## Que fait la multiplication par 2?
. . .
* Décalage de un bit vers la gauche!
```
0110
* 0010
---------
0000
+ 01100
---------
01100
```
. . .
## Que fait la multiplication par $2^N$?
. . .
* Décalage de $N$ bits vers la gauche!
# Entiers signés (1/2)
Pas de nombres négatifs encore...
## Comment faire?
. . .
## Solution naïve:
* On ajoute un bit de signe (le bit de poids fort):
```
00000010: +2
10000010: -2
```
## Problèmes?
. . .
* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
* Les additions différentes que pour les non-signés (très grave)
```
00000010 2
+ 10000100 + -4
---------- ----
10000110 = -6 != -2
```
# Entiers signés (2/2)
## Beaucoup mieux
* Complément à un:
* on inverse tous les bits: `1001 => 0110`.
## Encore un peu mieux
* Complément à deux:
* on inverse tous les bits,
* on ajoute 1 (on ignore les dépassements).
. . .
* Comment écrit-on `-4` en 8 bits?
. . .
```
4 = 00000100
________
-4 => 00000100
11111011
+ 00000001
----------
11111100
```
# Le complément à 2 (1/2)
## Questions:
* Comment on écrit `+0` et `-0`?
* Comment calcule-t-on `2 + (-4)`?
* Quel est le complément à 2 de `1000 0000`?
. . .
## Réponses
* Comment on écrit `+0` et `-0`?
```
+0 = 00000000
-0 = 11111111 + 00000001 = 100000000 => 00000000
```
* Comment calcule-t-on `2 + (-4)`?
```
00000010 2
+ 11111100 + -4
---------- -----
11111110 -2
```
* En effet
```
11111110 => 00000001 + 00000001 = 00000010 = 2.
```
# Le complément à 2 (1/2)
## Quels sont les entiers représentables en 8 bits?
. . .
```
01111111 => 127
10000000 => -128 // par définition
```
## Quels sont les entiers représentables sur $N$ bits?
. . .
$$
-2^{N-1} ... 2^{N-1}-1.
$$
## Remarque: dépassement de capacité en `C`
* Comportement indéfini!
# Nombres à virgule (1/3)
## Comment manipuler des nombres à virgule?
$$
0.1 + 0.2 = 0.3.
$$
Facile non?
. . .
## Et ça?
```C
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
float a = atof(argv[1]);
float b = atof(argv[2]);
printf("%.10f\n", (double)(a + b));
}
```
. . .
## Que se passe-t-il donc?
# Nombres à virgule (2/3)
## Nombres à virgule fixe
+-------+-------+-------+-------+-----+----------+----------+----------+----------+
| $2^3$ | $2^2$ | $2^1$ | $2^0$ | `.` | $2^{-1}$ | $2^{-2}$ | $2^{-3}$ | $2^{-4}$ |
+-------+-------+-------+-------+-----+----------+----------+----------+----------+
| `1` | `0` | `1` | `0` | `.` | `0` | `1` | `0` | `1` |
+-------+-------+-------+-------+-----+----------+----------+----------+----------+
## Qu'est-ce ça donne en décimal?
. . .
$$
2^3+2^1+\frac{1}{2^2}+\frac{1}{2^4} = 8+2+0.5+0.0625=10.5625.
$$
## Limites de cette représentation?
. . .
* Tous les nombres `> 16`.
* Tous les nombres `< 0.0625`.
* Tous les nombres dont la décimale est pas un multiple de `0.0625`.
# Nombres à virgule (3/3)
## Nombres à virgule fixe
* Nombres de $0=0000.0000$ à $15.9375=1111.1111$.
* Beaucoup de "trous" (au moins $0.0625$) entre deux nombres.
## Solution partielle?
. . .
* Rajouter des bits.
* Bouger la virgule.
# Nombres à virgule flottante (1/2)
## Notation scientifique
* Les nombres sont représentés en terme:
* Une mantisse
* Une base
* Un exposant
$$
\underbrace{22.1214}_{\mbox{nombre}}=\underbrace{221214}_{\mbox{mantisse}}\cdot
{\underbrace{10}_{\mbox{base}}}{\overbrace{^{-4}}^{\mbox{exp.}}},
$$
. . .
On peut donc séparer la représentation en 2:
* La mantisse
* L'exposant
# Nombres à virgule flottante (2/2)
## Quel est l'avantage?
. . .
On peut représenter des nombres sur énormément d'ordres de grandeur avec un
nombre de bits fixés.
## Différence fondamentale avec la virgule fixe?
. . .
La précision des nombres est **variable**:
* On a uniquement un nombre de chiffres **significatifs**.
$$
123456\cdot 10^{23}+ 123456\cdot 10^{-23}.
$$
## Quel inconvénient y a-t-il?
. . .
Ce mélange d'échelles entraîne un **perte de précision**.
# Nombres à virgule flottante simple précision (1/4)
Aussi appelés *IEEE 754 single-precision binary floating point*.
![Nombres à virgule flottante 32 bits. Source:
[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format#/media/File:Float_example.svg)](figs/Float_example_bare.svg)
## Spécification
* 1 bit de signe,
* 8 bits d'exposant,
* 23 bits de mantisse.
$$
(-1)^{b_{31}}\cdot 2^{(b_{30}b_{29}\dots b_{23})_{2}-127}\cdot (1.b_{22}b_{21}\dots b_{0})_{2},
$$
## Calculer la valeur décimale du nombre ci-dessus
# Nombres à virgule flottante simple précision (2/4)
![Un exercice de nombres à virgule flottante 32 bits. Source:
[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format#/media/File:Float_example.svg)](figs/Float_example.svg)
. . .
\begin{align}
\mbox{exposant}&=\sum_{i=0}^7 b_{23+i}2^i=2^2+2^3+2^4+2^5+2^6=124-127,\\
\mbox{mantisse}&=1+\sum_{i=1}^{23}b_{23-i}2^{-i}=1+2^{-2}=1.25,\\
&\Rightarrow (-1)^0\cdot 2^{-3}\cdot 1.25=0.15625
\end{align}
# Nombres à virgule flottante simple précision (3/4)
## Quel nombre ne peux pas être vraiment représenté?
. . .
## Zéro: exception pour l'exposant
* Si l'exposant est `00000000` (zéro)
$$
(-1)^{\mbox{sign}}\cdot 2^{-126}\cdot 0.\mbox{mantisse},
$$
* Sinon si l'exposant est `00000001` à `11111110`
$$
\mbox{valeur normale},
$$
* Sinon `11111111` donne `NaN`.
# Nombres à virgule flottante simple précision (4/4)
## Quels sont les plus petits/grands nombres positifs représentables?
. . .
\begin{align}
0\ 0\dots0\ 0\dots01&=2^{-126}\cdot 2^{-23}=1.4...\cdot
10^{-45},\\
0\ 1\dots10\ 1\dots1&=2^{127}\cdot (2-2^{-23})=3.4...\cdot
10^{38}.
\end{align}
## Combien de chiffres significatifs en décimal?
. . .
* 24 bits ($23 + 1$) sont utiles pour la mantisse, soit $2^{24}-1$:
* La mantisse fait $\sim2^{24}\sim 10^7$, ou encore
* Ou encore $\sim \log_{10}(2^{24})\sim 7$,
* Environ **sept** chiffres significatifs.
# Nombres à virgule flottante double précision (64bits)
## Spécification
* 1 bit de signe,
* 11 bits d'exposant,
* 52 bits de mantisse.
. . .
## Combien de chiffres significatifs?
* La mantisse fait $\sim 2^{53}\sim10^{16}$,
* Ou encore $\sim \log_{10}(2^{53})\sim 16$,
* Environ **seize** chiffres significatifs.
## Plus petit/plus grand nombre représentable?
. . .
* Plus petite mantisse et exposant: $\sim 2^{-52}\cdot 2^{-1022}\sim 4\cdot 10^{-324}$,
* Plus grande mantisse et exposant: $\sim 2\cdot 2^{1023}\sim \cdot 1.8\cdot 10^{308}$.
# Précision finie (1/3)
## Erreur de représentation
* Les nombres réels ont potentiellement un **nombre infini** de décimales
* $1/3=0.\overline{3}$,
* $\pi=3.1415926535...$.
* Les nombres à virgule flottante peuvent en représenter qu'un **nombre
fini**.
* $1/3\cong 0.33333$, erreur $0.00000\overline{3}$.
* $\pi\cong3.14159$, erreur $0.0000026535...$.
On rencontre donc des **erreurs de représentation** ou **erreurs
d'arrondi**.
. . .
## Et quand on calcule?
* Avec deux chiffres significatifs
\begin{align}
&8.9+(0.02+0.04)=8.96=9.0,\\
&(8.9+0.02)+0.04=8.9+0.04=8.9.
\end{align}
. . .
## Même pas associatif!
# Précision finie (2/3)
## Erreur de représentation virgule flottante
$$
(1.2)_{10} = 1.\overline{0011}\cdot 2^0\Rightarrow 0\ 01111111\
00110011001100110011010.
$$
Erreur d'arrondi dans les deux derniers bits et tout ceux qui viennent
ensuite
$$
\varepsilon_2 = (00000000000000000000011)_2.
$$
Ou en décimal
$$
\varepsilon_{10} = 4.76837158203125\cdot 10^{-8}.
$$
# Précision finie (3/3)
## Comment définir l'égalité de 2 nombres à virgule flottante?
. . .
Ou en d'autres termes, pour quel $\varepsilon>0$ (appelé `epsilon-machine`) on a
$$
1+\varepsilon = 1,
$$
pour un nombre à virgule flottante?
. . .
Pour un `float` (32 bits) la différence est à
$$
2^{-23}=1.19\cdot 10^{-7},
$$
Soit la précision de la mantisse.
## Comment le mesurer (par groupe)?
. . .
```C
float eps = 1.0;
while ((float)1.0 + (float)0.5 * eps != (float)1.0) {
eps = (float)0.5 * eps;
}
printf("eps = %g\n", eps);
```
# Erreurs d'arrondi
Et jusqu'ici on a encore pas fait d'arithmétique!
## Multiplication avec deux chiffres significatifs, décimal
$$
(1.1)_{10}\cdot (1.1)_{10}=(1.21)_{10}=(1.2)_{10}.
$$
En continuant ce petit jeu:
$$
\underbrace{1.1\cdot 1.1\cdots 1.1}_{\mbox{10 fois}}=2.0.
$$
Alors qu'en réalité
$$
1.1^{10}=2.5937...
$$
Soit une erreur de près de 1/5e!
. . .
## Le même phénomène se produit (à plus petite échelle) avec les `float` ou
`double`.
# Exemple de récursivité (1/2)
## La factorielle
```C
int factorial(int n) {
if (n > 1) {
return n * factorial(n - 1);
} else {
return 1;
}
}
```
. . .
## Que se passe-t-il quand on fait `factorial(4)`?
. . .
## On empile les appels
+----------------+----------------+----------------+----------------+
| | | | `factorial(1)` |
+----------------+----------------+----------------+----------------+
| | | `factorial(2)` | `factorial(2)` |
+----------------+----------------+----------------+----------------+
| | `factorial(3)` | `factorial(3)` | `factorial(3)` |
+----------------+----------------+----------------+----------------+
| `factorial(4)` | `factorial(4)` | `factorial(4)` | `factorial(4)` |
+----------------+----------------+----------------+----------------+
# Exemple de récursivité (2/2)
## La factorielle
```C
int factorial(int n) {
if (n > 1) {
return n * factorial(n - 1);
} else {
return 1;
}
}
```
. . .
## Que se passe-t-il quand on fait `factorial(4)`?
. . .
## On dépile les calculs
+----------------+----------------+----------------+----------------+
| `1` | | | |
+----------------+----------------+----------------+----------------+
| `factorial(2)` | `2 * 1 = 2` | | |
+----------------+----------------+----------------+----------------+
| `factorial(3)` | `factorial(3)` | `3 * 2 = 6` | |
+----------------+----------------+----------------+----------------+
| `factorial(4)` | `factorial(4)` | `factorial(4)` | `4 * 6 = 24` |
+----------------+----------------+----------------+----------------+
# La récursivité (1/4)
## Formellement
* Une condition de récursivité - qui *réduit* les cas successifs vers...
* Une condition d'arrêt - qui retourne un résultat
## Pour la factorielle, qui est qui?
```C
int factorial(int n) {
if (n > 1) {
return n * factorial(n - 1);
} else {
return 1;
}
}
```
# La récursivité (2/4)
## Formellement
* Une condition de récursivité - qui *réduit* les cas successifs vers...
* Une condition d'arrêt - qui retourne un résultat
## Pour la factorielle, qui est qui?
```C
int factorial(int n) {
if (n > 1) { // Condition de récursivité
return n * factorial(n - 1);
} else { // Condition d'arrêt
return 1;
}
}
```
# La récursivité (3/4)
## Exercice: trouver l'$\varepsilon$-machine pour un `double`
. . .
```C
double epsilon_machine(double eps) {
if (1.0 + eps != 1.0) {
return epsilon_machine(eps / 2.0);
} else {
return eps;
}
}
```
# La récursivité (4/4)
## Exercice: que fait ce code récursif?
```C
void recurse(int n) {
printf("%d ", n % 2);
if (n / 2 != 0) {
recurse(n / 2);
} else {
printf("\n");
}
}
recurse(13);
```
. . .
```C
binaire(13): n = 13, n % 2 = 1, n / 2 = 6,
binaire(6): n = 6, n % 2 = 0, n / 2 = 3,
binaire(3): n = 3, n % 2 = 1, n / 2 = 1,
binaire(1): n = 1, n % 2 = 1, n / 2 = 0.
// affiche: 1 1 0 1
```
---
title: "Récursivité et complexité"
date: "2021-11-03"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# La récursivité (1/2)
* Code récursif
```C
int factorial(int n) {
if (n > 1) { // Condition de récursivité
return n * factorial(n - 1);
} else { // Condition d'arrêt
return 1;
}
}
```
. . .
* Code impératif
```C
int factorial(int n) {
int f = 1;
for (int i = 1; i < n; ++i) {
f *= i;
}
return f;
}
```
# Exercice: réusinage et récursivité (1/4)
## Réusiner le code du PGCD avec une fonction récursive
## Étudier l'exécution
```C
42 = 27 * 1 + 15
27 = 15 * 1 + 12
15 = 12 * 1 + 3
12 = 3 * 4 + 0
```
# Exercice: réusinage et récursivité (2/4)
## Réusiner le code du PGCD avec une fonction récursive
## Étudier l'exécution
```C
42 = 27 * 1 + 15 | PGCD(42, 27)
27 = 15 * 1 + 12 | PGCD(27, 15)
15 = 12 * 1 + 3 | PGCD(15, 12)
12 = 3 * 4 + 0 | PGCD(12, 3)
```
# Exercice: réusinage et récursivité (3/4)
## Réusiner le code du PGCD avec une fonction récursive
## Étudier l'exécution
```C
42 = 27 * 1 + 15 | PGCD(42, 27)
27 = 15 * 1 + 12 | PGCD(27, 15)
15 = 12 * 1 + 3 | PGCD(15, 12)
12 = 3 * 4 + 0 | PGCD(12, 3)
```
## Effectuer l'empilage - dépilage
. . .
```C
PGCD(12, 3) | 3
PGCD(15, 12) | 3
PGCD(27, 15) | 3
PGCD(42, 27) | 3
```
# Exercice: réusinage et récursivité (4/4)
## Écrire le code
. . .
```C
int pgcd(int n, int m) {
if (n % m > 0) {
return pgcd(m, n % m);
} else {
return m;
}
}
```
# La suite de Fibonacci (1/2)
## Règle
$$
\mathrm{Fib}(n) = \mathrm{Fib}(n-1) + \mathrm{Fib}(n-2),\quad
\mathrm{Fib}(0)=0,\quad \mathrm{Fib}(1)=1.
$$
## Exercice: écrire la fonction $\mathrm{Fib}$ en récursif et impératif
. . .
## En récursif (6 lignes)
```C
int fib(int n) {
if (n > 1) {
return fib(n - 1) + fib(n - 2);
}
return n;
}
```
# La suite de Fibonacci (2/2)
## Et en impératif (11 lignes)
```C
int fib_imp(int n) {
int fib0 = 1;
int fib1 = 1;
int fib = n == 0 ? 0 : fib1;
for (int i = 2; i < n; ++i) {
fib = fib0 + fib1;
fib0 = fib1;
fib1 = fib;
}
return fib;
}
```
# Exponentiation rapide ou indienne (1/4)
## But: Calculer $x^n$
* Algorithme naîf et impératif
```C
int pow(x, n) {
if (0 == n) {
return 1;
}
for (int i = 1; i < n; ++i) {
x *= x;
}
return x;
}
```
. . .
* Complexité? Combien de multiplication en fonction de `n`?
# Exponentiation rapide ou indienne (2/4)
* Algorithme naïf et récursif
```C
int pow(x, n) {
if (n != 0) {
return x * pow(x, n-1);
} else {
return 1;
}
}
```
# Exponentiation rapide ou indienne (3/4)
## Exponentiation rapide ou indienne de $x^n$
* Écrivons $n=\sum_{i=0}^{d-1}b_i 2^i,\ b_i=\{0,1\}$ (écriture binaire sur $d$ bits, avec
$d\sim\log_2(n)$).
*
$$
x^n={x^{2^0}}^{b_0}\cdot {x^{2^1}}^{b_1}\cdots {x^{2^{d-1}}}^{b_{d-1}}.
$$
* On a besoin de $d$ calculs pour les $x^{2^i}$.
* On a besoin de $d$ calculs pour évaluer les produits de tous les termes.
## Combien de calculs en terme de $n$?
. . .
* $n$ est représenté en binaire avec $d$ bits $\Rightarrow d\sim\log_2(n)$.
* il y a $2\log_2(n)\sim \log_2(n)$ calculs.
# Exponentiation rapide ou indienne (4/4)
## Le vrai algorithme
* Si n est pair: calculer $\left(x^{n/2}\right)^2$,
* Si n est impair: calculer $x \cdot \left(x^{(n-1)/2}\right)^2$.
## Exercice: écrire l'algorithme récursif correspondant
. . .
```C
double pow(double x, int n) {
if (1 == n) {
return x;
} else if (n % 2 == 0) {
return pow(x, n / 2) * pow(x, n/2);
} else {
return x * pow(x, (n-1));
}
}
```
# Efficacité d'un algorithmique
Comment mesurer l'efficacité d'un algorithme?
. . .
* Mesurer le temps CPU,
* Mesurer le temps d'accès à la mémoire,
* Mesurer la place prise mémoire,
. . .
Dépendant du **matériel**, du **compilateur**, des **options de compilation**,
etc!
## Mesure du temps CPU
```C
#include <time.h>
struct timespec tstart={0,0}, tend={0,0};
clock_gettime(CLOCK_MONOTONIC, &tstart);
// some computation
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("computation about %.5f seconds\n",
((double)tend.tv_sec + 1e-9*tend.tv_nsec) -
((double)tstart.tv_sec + 1e-9*tstart.tv_nsec));
```
# Programme simple: mesure du temps CPU
## Preuve sur un [petit exemple](../source_codes/complexity/sum.c)
```bash
source_codes/complexity$ make bench
RUN ONCE -O0
the computation took about 0.00836 seconds
RUN ONCE -O3
the computation took about 0.00203 seconds
RUN THOUSAND TIMES -O0
the computation took about 0.00363 seconds
RUN THOUSAND TIMES -O3
the computation took about 0.00046 seconds
```
Et sur votre machine les résultats seront **différents**.
. . .
## Conclusion
* Nécessité d'avoir une mesure indépendante du/de la
matériel/compilateur/façon de mesurer/météo.
# Analyse de complexité algorithmique (1/4)
* On analyse le **temps** pris par un algorithme en fonction de la **taille de
l'entrée**.
## Exemple: recherche d'un élément dans une liste triée de taille N
```C
int sorted_list[N];
bool in_list = is_present(N, sorted_list, elem);
```
* Plus `N` est grand, plus l'algorithme prend de temps sauf si...
. . .
* l'élément est le premier de la liste (ou à une position toujours la même).
* ce genre de cas pathologique ne rentre pas en ligne de compte.
# Analyse de complexité algorithmique (2/4)
## Recherche linéaire
```C
bool is_present(int n, int tab[], int elem) {
for (int i = 0; i < n; ++i) {
if (tab[i] == elem) {
return true;
} else if (elem < tab[i]) {
return false;
}
}
return false;
}
```
* Dans le **meilleurs des cas** il faut `1` comparaison.
* Dans le **pire des cas** (élément absent p.ex.) il faut `n`
comparaisons.
. . .
La **complexité algorithmique** est proportionnelle à `N`: on double la taille
du tableau $\Rightarrow$ on double le temps pris par l'algorithme.
# Analyse de complexité algorithmique (3/4)
## Recherche dichotomique
```C
bool is_present_binary_search(int n, int tab[], int elem) {
int left = 0;
int right = n - 1;
while (left <= right) {
int mid = (right + left) / 2;
if (tab[mid] < elem) {
left = mid + 1;
} else if (tab[mid] > elem) {
right = mid - 1;
} else {
return true;
}
}
return false;
}
```
# Analyse de complexité algorithmique (4/4)
## Recherche dichotomique
![Source:
[Wikipédia](https://upload.wikimedia.org/wikipedia/commons/a/aa/Binary_search_complexity.svg)](figs/Binary_search_complexity.svg){width=80%}
. . .
* Dans le **meilleurs de cas** il faut `1` comparaison.
* Dans le **pire des cas** il faut $\log_2(N)+1$ comparaisons
. . .
## Linéaire vs dichotomique
* $N$ vs $\log_2(N)$ comparaisons logiques.
* Pour $N=1000000$: `1000000` vs `21` comparaisons.
# Notation pour la complexité
## Constante de proportionnalité
* Pour la recherche linéaire ou dichotomique, on a des algorithmes qui sont
$\sim N$ ou $\sim \log_2(N)$
* Qu'est-ce que cela veut dire?
. . .
* Temps de calcul est $t=C\cdot N$ (où $C$ est le temps pris pour une
comparaisons sur une machine/compilateur donné)
* La complexité ne dépend pas de $C$.
## Le $\mathcal{O}$ de Leibnitz
* Pour noter la complexité d'un algorithme on utilise le symbole
$\mathcal{O}$ (ou "grand Ô de").
* Les complexités les plus couramment rencontrées sont
. . .
$$
\mathcal{O}(1),\quad \mathcal{O}(\log(N)),\quad \mathcal{O}(N),\quad
\mathcal{O}(\log(N)\cdot N), \quad \mathcal{O}(N^2), \quad
\mathcal{O}(N^3).
$$
# Ordres de grandeur
\begin{table}[!h]
\begin{center}
\caption{Valeurs approximatives de quelques fonctions usuelles de complexité.}
\medskip
\begin{tabular}{|c|c|c|c|c|}
\hline
$\log_2(N)$ & $\sqrt{N}$ & $N$ & $N\log_2(N)$ & $N^2$ \\
\hline\hline
$3$ & $3$ & $10$ & $30$ & $10^2$ \\
\hline
$6$ & $10$ & $10^2$ & $6\cdot 10^2$ & $10^4$ \\
\hline
$9$ & $31$ & $10^3$ & $9\cdot 10^3$ & $10^6$ \\
\hline
$13$ & $10^2$ & $10^4$ & $1.3\cdot 10^5$ & $10^8$ \\
\hline
$16$ & $3.1\cdot 10^2$ & $10^5$ & $1.6\cdot 10^6$ & $10^{10}$ \\
\hline
$19$ & $10^3$ & $10^6$ & $1.9\cdot 10^7$ & $10^{12}$ \\
\hline
\end{tabular}
\end{center}
\end{table}
# Quelques exercices (1/3)
## Complexité de l'algorithme de test de primalité naïf?
```C
for (i = 2; i < sqrt(N); ++i) {
if (N % i == 0) {
return false;
}
}
return true;
```
. . .
## Réponse
$$
\mathcal{O}(\sqrt{N}).
$$
# Quelques exercices (2/3)
## Complexité de trouver le minimum d'un tableau?
```C
min = MAX;
for (i = 0; i < N; ++i) {
if (tab[i] < min) {
min = tab[i];
}
}
return min;
```
. . .
## Réponse
$$
\mathcal{O}(N).
$$
# Quelques exercices (3/3)
## Complexité du tri par sélection?
```C
ind = 0
while (ind < SIZE-1) {
min = find_min(tab[ind:SIZE]);
swap(min, tab[ind]);
ind += 1
}
```
. . .
## Réponse
### `min = find_min`
$$
(N-1)+(N-2)+...+2+1=\sum_{i=1}^{N-1}i=N\cdot(N-1)/2=\mathcal{O}(N^2).
$$
## Finalement
$$
\mathcal{O}(N^2\mbox{ comparaisons}) + \mathcal{O}(N\mbox{
swaps})=\mathcal{O}(N^2).
$$
---
title: "Tris"
date: "2021-11-10"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Tri par insertion (1/3)
## But
* trier un tableau par ordre croissant
## Algorithme
Prendre un élément du tableau et le mettre à sa place parmis les éléments déjà
triés du tableau.
![Tri par insertion d'un tableau d'entiers](figs/tri_insertion.svg)
# Tri par insertion (2/3)
## Exercice: Proposer un algorithme
. . .
```C
void tri_insertion(int N, int tab[N]) {
for (int i = 1; i < N; i++) {
int tmp = tab[i];
int pos = i;
while (pos > 0 && tab[pos - 1] > tmp) {
tab[pos] = tab[pos - 1];
pos = pos - 1;
}
tab[pos] = tmp;
}
}
```
# Tri par insertion (3/3)
## Question: Quelle est la complexité?
. . .
* Parcours de tous les éléments ($N-1$ passages dans la boucle)
* Placer: en moyenne $i$ comparaisons et affectations à l'étape $i$
* Moyenne: $\mathcal{O}(N^2)$
. . .
* Pire des cas, liste triée à l'envers: $\mathcal{O}(N^2)$
* Meilleurs des cas, liste déjà triée: $\mathcal{O}(N)$
# L'algorithme à la main
## Exercice *sur papier*
* Trier par insertion le tableau `[5, -2, 1, 3, 10]`
```C
```
# Tri rapide ou quicksort (1/8)
## Idée: algorithme `diviser pour régner` (`divide-and-conquer`)
* Diviser: découper un problème en sous problèmes;
* Régner: résoudre les sous-problèmes (souvent récursivement);
* Combiner: à partir des sous problèmes résolu, calculer la solution.
## Le pivot
* Trouver le **pivot**, un élément qui divise le tableau en 2, tels que:
1. Éléments à gauche sont **plus petits** que le pivot.
2. Élements à droite sont **plus grands** que le pivot.
# Tri rapide ou quicksort (2/8)
## Algorithme `quicksort(tableau)`
1. Choisir le pivot et l'amener à sa place:
* Les éléments à gauche sont plus petits que le pivot.
* Les éléments à droite sont plus grand que le pivot.
2. `quicksort(tableau_gauche)` en omettant le pivot.
3. `quicksort(tableau_droite)` en omettant le pivot.
4. S'il y a moins de deux éléments dans le tableau, le tableau est trié.
. . .
Compris?
. . .
Non c'est normal, faisons un exemple.
# Tri rapide ou quicksort (3/8)
Deux variables sont primordiales:
```C
int low, high; // les indices min/max des tableaux à trier
```
![Un exemple de quicksort.](figs/quicksort.svg)
# Tri rapide ou quicksort (4/8)
Deux variables sont primordiales:
```C
int low, high; // les indices min/max des tableaux à trier
```
## Pseudocode: quicksort
```C
void quicksort(array, low, high) {
if (more than 1 elems) {
pivot_ind = partition(array, low, high);
if (something left of pivot)
quicksort(array, low, pivot_ind - 1);
if (something right of pivot)
quicksort(array, pivot_ind + 1, high);
}
}
```
# Tri rapide ou quicksort (5/8)
## Pseudocode: partition
```C
int partition(array, low, high) {
pivot = array[high]; // choix arbitraire
i = low;
j = high-1;
while i < j {
en remontant i trouver le premier élément > pivot;
en descendant j trouver le premier élément < pivot;
swap(array[i], array[j]);
// les plus grands à droite
// mettre les plus petits à gauche
}
// on met le pivot "au milieu"
swap(array[i], array[pivot]);
return i; // on retourne l'indice pivot
}
```
# Tri rapide ou quicksort (6/8)
## Exercice: implémenter les fonctions `quicksort` et `partition`
. . .
```C
void quicksort(int size, int array[size], int first,
int last)
{
if (first < last) {
int midpoint = partition(size, array, first, last);
if (first < midpoint - 1) {
quicksort(size, array, first, midpoint - 1);
}
if (midpoint + 1 < last) {
quicksort(size, array, midpoint + 1, last);
}
}
}
```
# L'algorithme à la main
## Exercice *sur papier*
* Trier par tri rapide le tableau `[5, -2, 1, 3, 10, 15, 7, 4]`
```C
```
# Tri rapide ou quicksort (7/8)
\footnotesize
## Exercice: implémenter les fonctions `quicksort` et `partition`
```C
int partition(int size, int array[size], int first, int last) {
int pivot = array[last];
int i = first - 1, j = last;
do {
do {
i++;
} while (array[i] < pivot && i < j);
do {
j--;
} while (array[j] > pivot && i < j);
if (j > i) {
swap(&array[i], &array[j]);
}
} while (j > i);
swap(&array[i], &array[last]);
return i;
}
```
# Tri rapide ou quicksort (8/8)
## Quelle est la complexité du tri rapide?
. . .
* Pire des cas plus: $\mathcal{O}(N^2)$
* Quand le pivot sépare toujours le tableau de façon déséquilibrée ($N-1$
éléments d'un côté $1$ de l'autre).
* $N$ boucles et $N$ comparaisons $\Rightarrow N^2$.
* Meilleur des cas (toujours le meilleur pivot): $\mathcal{O}(N\cdot \log_2(N))$.
* Chaque fois le tableau est séparé en $2$ parties égales.
* On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot
\log_2(N)$.
* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$.
# Tri à bulle (1/4)
## Algorithme
* Parcours du tableau et comparaison des éléments consécutifs:
- Si deux éléments consécutifs ne sont pas dans l'ordre, ils sont échangés.
* On recommence depuis le début du tableau jusqu'à avoir plus d'échanges à
faire.
## Que peut-on dire sur le dernier élément du tableau après un parcours?
. . .
* Le plus grand élément est **à la fin** du tableau.
* Plus besoin de le traiter.
* A chaque parcours on s'arrête un élément plus tôt.
# Tri à bulle (2/4)
## Exemple
![Tri à bulles d'un tableau d'entiers](figs/tri_bulles.svg)
# Tri à bulle (3/4)
## Exercice: écrire l'algorithme (poster le résultat sur matrix)
. . .
```C
void bubble_sort(int size, int array[]) {
for i in [size-1, 1] {
sorted = true;
for j in [0, i-1] {
if (array[j] > array[j+1]) {
swap(array[j], array[j+1]);
sorted = false;
}
}
if (sorted) {
return;
}
}
}
```
# Tri à bulle (4/4)
## Quelle est la complexité du tri à bulles?
. . .
* Dans le meilleurs des cas:
* Le tableau est déjà trié: $\mathcal{O}(N)$ comparaisons.
* Dans le pire des cas, $N\cdot (N-1)/2\sim\mathcal{O}(N^2)$:
$$
\sum_{i=1}^{N-1}i\mbox{ comparaison et }3\sum_{i=1}^{N-1}i \mbox{ affectations
(swap)}\Rightarrow \mathcal{O}(N^2).
$$
* En moyenne, $\mathcal{O}(N^2)$ ($N^2/2$ comparaisons).
# L'algorithme à la main
## Exercice *sur papier*
* Trier par tri à bulles le tableau `[5, -2, 1, 3, 10, 15, 7, 4]`
```C
```
---
title: "Backtracking et piles"
date: "2021-11-17"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# L'algorithme du PPCM *récursif* (1/3)
## Exemple d'algorithme pour le calcul
```C
PPCM(36, 90):
36 < 90 // 36 + 36
72 < 90 // 72 + 36
108 > 90 // 90 + 90
108 < 180 // 108 + 36
144 < 180 // 144 + 36
180 = 180 // The End!
```
. . .
* On incrémente de 36 à gauche et de 90 à droite jusqu'à ce que les deux
soient égaux.
# L'algorithme du PPCM *récursif* (2/3)
## Rappel de l'algorithme
```C
// on cherche i*m == j*m (i,j aussi petits que possibles)
int ppcm(int m, int n) {
int mult_m = m, mult_n = n;
while (mult_m != mult_n) {
if (mult_m > mult_n) {
mult_n += n;
} else {
mult_m += m;
}
}
return mult_m;
}
```
. . .
## Écrire l'algorithme *récursif* du PPCM (matrix)
# L'algorithme du PPCM *récursif* (3/3)
## Pseudo-code
- Algorithme du PPCM de deux nombres `n` et `m`
- `ppcm(mult_n,mult_m) = ppcm(mult_n + n, mult_m)`
si `mult_n < mult_m` (récursivité)
- `ppcm(mult_n,mult_m) = ppcm(mult_n, mult_m + m)`
si `mult_n > mult_m` (récursivité)
- `ppcm(mult_n,mult_m) = mult_n`
si `mult_n = mult_m` (condition d’arrêt)
# Problème des 8-reines
* Placer 8 reines sur un échiquier de $8 \times 8$.
* Sans que les reines ne puissent se menacer mutuellement (92 solutions).
## Conséquence
* Deux reines ne partagent pas la même rangée, colonne, ou diagonale.
* Donc chaque solution a **une** reine **par colonne** ou **ligne**.
## Généralisation
* Placer $N$ reines sur un échiquier de $N \times
N$.
- Exemple de **backtracking** (retour en arrière) $\Rightarrow$ récursivité.
![Problème des 8-reines. Source:
[wikipedia](https://fr.wikipedia.org/wiki/Problème_des_huit_dames)](./figs/fig_recursivite_8_reines.png){width=35%}
# Problème des 2-reines
![Le problème des 2 reines n'a pas de solution.](figs/2reines.svg){width=50%}
# Comment trouver les solutions?
* On pose la première reine sur la première case disponible.
* On rend inaccessibles toutes les cases menacées.
* On pose la reine suivante sur la prochaine case non-menacée.
* Jusqu'à ce qu'on puisse plus poser de reine.
* On revient alors en arrière jusqu'au dernier coup où il y avait plus qu'une
possibilité de poser une reine.
* On recommence depuis là.
. . .
* Le jeu prend fin quand on a énuméré *toutes* les possibilités de poser les
reines.
# Problème des 3-reines
![Le problème des 3 reines n'a pas de solution non plus.](figs/3reines.svg)
# Problème des 4-reines
![Le problème des 4 reines a une solution.](figs/4reines.svg)
# Problème des 4-reines, symétrie
![Le problème des 4 reines a une autre solution (symétrie
horizontale).](figs/4reines_sym.svg)
# Problème des 5 reines
## Exercice: Trouver une solution au problème des 5 reines
* Faire une capture d'écran / une photo de votre solution et la poster sur
matrix.
```C
```
# Quelques observations sur le problème
* Une reine par colonne au plus.
* On place les reines sur des colonnes successives.
* On a pas besoin de "regarder en arrière" (on place "devant" uniquement).
* Trois étapes:
* On place une reine dans une case libre.
* On met à jour le tableau.
* Quand on a plus de cases libres on "revient dans le temps" ou c'est qu'on
a réussi.
# Le code du problème des 8 reines (1/N)
## Quelle structure de données?
. . .
Une matrice de booléens fera l'affaire:
```C
bool board[n][n];
```
## Quelles fonctionalités?
. . .
```C
// Pour chaque ligne placer la reine sur toutes les colonnes
// et compter les solutions
void nbr_solutions(board, column, counter);
// Copier un tableau dans un autre
void copy(board_in, board_out);
// Placer la reine à li, co et rendre inaccessible devant
void placer_devant(board, li, co);
```
# Le code du problème des 8 reines (2/N)
## Le calcul du nombre de solutions
```C
// Calcule le nombre de solutions au problème des <n> reines
nbr_solutions(board, column, count)
// pour chaque ligne
// si la case libre
// si column < n - 1
// copier board dans un "new" board,
// y poser une reine
// et mettre à jour ce "new" board
// nbr_solutions(new_board, column+1, count)
// sinon
// on a posé la n-ème et on a gagné
// count += 1
```
# Le code du problème des 8 reines (3/N)
## Le calcul du nombre de solutions
```C
// Placer une reine et mettre à jour
placer_devant(board, ligne, colonne)
// board est occupé à ligne/colonne
// toutes les cases des colonnes
// suivantes sont mises à jour
```
# Le code du problème des 8 reines (4/N)
## Compris? Alors écrivez le code et postez le!
. . .
## Le nombre de solutions
\footnotesize
```C
// Calcule le nombre de solutions au problème des <n> reines
void nb_sol(int n, bool board[n][n], int co, int *ptr_cpt) {
for (int li = 0; li < n; li++) {
if (board[li][co]) {
if (co < n-1) {
bool new_board[n][n]; // alloué à chaque nouvelle tentative
copy(n, board, new_board);
prises_devant(n, new_board, li, co);
nb_sol(n, new_board, co+1, ptr_cpt);
} else {
*ptr_cpt = (*ptr_cpt)+1;
}
}
}
}
```
# Le code du problème des 8 reines (5/N)
\footnotesize
## Placer devant
```C
// Retourne une copie du tableau <board> complété avec les positions
// prises sur la droite droite par une reine placée en <board(li,co)>
void prises_devant(int n, bool board[n][n], int li, int co) {
board[li][co] = false; // position de la reine
for (int j = 1; j < n-co; j++) {
// horizontale et diagonales à droite de la reine
if (j <= li) {
board[li-j][co+j] = false;
}
board[li][co+j] = false;
if (li+j < n) {
board[li+j][co+j] = false;
}
}
}
```
# Les piles (1/N)
## Qu'est-ce donc?
* Structure de données abstraite...
. . .
* de type `LIFO` (*Last in first out*).
![Une pile où on ajoute A, puis B avant de les retirer. Source:
[Wikipedia](https://upload.wikimedia.org/wikipedia/commons/e/e1/Stack_%28data_structure%29_LIFO.svg)](figs/Stack.svg){width=70%}
## Des exemples de la vraie vie
. . .
* Pile d'assiettes, de livres, ...
* Adresses visitées par un navigateur web.
* Les calculatrices du passé (en polonaise inverse).
* Les boutons *undo* de vos éditeurs de texte (aka *u* dans vim).
# Les piles (2/N)
## Fonctionnalités
. . .
1. Empiler (push): ajouter un élément sur la pile.
2. Dépiler (pop): retirer l'élément du sommet de la pile et le retrouner.
3. Liste vide? (is_empty?).
. . .
4. Jeter un oeil (peek): retourner l'élément du sommet de la pile (sans le dépiler).
5. Nombre d'éléments (length).
## Comment faire les 4,5 à partir de 1 à 3?
. . .
4. Dépiler l'élément, le copier, puis l'empiler à nouveau.
5. Dépiler jusqu'à ce que la pile soit vide, puis empiler à nouveau.
. . .
## Existe en deux goûts
* Pile avec ou sans limite de capacité (à concurrence de la taille de la
mémoire).
# Les piles (3/N)
## Implémentation
* Jusqu'ici on n'a pas du tout parlé d'implémentation (d'où le nom de structure
abstraite).
* Pas de choix unique d'implémentation.
## Quelle structure de données allons nous utiliser?
. . .
Et oui vous avez deviné: un tableau!
## La structure: de quoi avons-nous besoin (pile de taille fixe)?
. . .
```C
#define MAX_CAPACITY 500
typedef struct _stack {
int data[MAX_CAPACITY]; // les données
int top; // indice du sommet
} stack;
```
# Les piles (4/N)
## Initialisation
. . .
```C
void stack_init(stack *s) {
s->top = -1;
}
```
## Est vide?
. . .
```C
bool stack_is_empty(stack s) {
return s.top == -1;
}
```
## Empiler (ajouter un élément au sommet)
. . .
```C
void stack_push(stack *s, int val) {
s->top += 1;
s->data[s->top] = val;
}
```
# Les piles (5/N)
## Dépiler (enlever l'élément du sommet)
. . .
```C
int stack_pop(stack *s) {
s->top -= 1;
return s->data[s->top+1];
}
```
## Jeter un oeil (regarder le sommet)
. . .
```C
int stack_peek(stack *s) {
return s->data[s->top];
}
```
## Voyez-vous des problèmes potentiels avec cette implémentation?
. . .
* Empiler avec une pile pleine.
* Dépiler avec une pile vide.
* Jeter un oeil au sommet d'une pile vide.
---
title: "Piles et files d'attente"
date: "2021-11-25"
patat:
eval:
tai:
command: fish
fragment: false
replace: true
ccc:
command: fish
fragment: false
replace: true
images:
backend: auto
---
# Les piles (1/5)
## Qu'est-ce donc?
* Structure de données abstraite...
. . .
* de type `LIFO` (*Last in first out*).
![Une pile où on ajoute A, puis B avant de les retirer. Source:
[Wikipedia](https://upload.wikimedia.org/wikipedia/commons/e/e1/Stack_%28data_structure%29_LIFO.svg)](figs/Stack.svg){width=70%}
## Des exemples de la vraie vie
. . .
* Pile d'assiettes, de livres, ...
* Adresses visitées par un navigateur web.
* Les calculatrices du passé (en polonaise inverse).
* Les boutons *undo* de vos éditeurs de texte (aka *u* dans vim).
# Les piles (2/5)
## Fonctionnalités
. . .
1. Empiler (push): ajouter un élément sur la pile.
2. Dépiler (pop): retirer l'élément du sommet de la pile et le retrouner.
3. Liste vide? (is_empty?).
. . .
4. Jeter un oeil (peek): retourner l'élément du sommet de la pile (sans le dépiler).
5. Nombre d'éléments (length).
## Comment faire les 4,5 à partir de 1 à 3?
. . .
4. Dépiler l'élément, le copier, puis l'empiler à nouveau.
5. Dépiler jusqu'à ce que la pile soit vide, puis empiler à nouveau.
. . .
## Existe en deux goûts
* Pile avec ou sans limite de capacité (à concurrence de la taille de la
mémoire).
# Les piles (3/5)
## Implémentation
* Jusqu'ici on n'a pas du tout parlé d'implémentation (d'où le nom de structure
abstraite).
* Pas de choix unique d'implémentation.
## Quelle structure de données allons nous utiliser?
. . .
Et oui vous avez deviné: un tableau!
## La structure: de quoi avons-nous besoin (pile de taille fixe)?
. . .
```C
#define MAX_CAPACITY 500
typedef struct _stack {
int data[MAX_CAPACITY]; // les données
int top; // indice du sommet
} stack;
```
# Les piles (4/5)
## Initialisation
. . .
```C
void stack_init(stack *s) {
s->top = -1;
}
```
## Est vide?
. . .
```C
bool stack_is_empty(stack s) {
return s.top == -1;
}
```
## Empiler (ajouter un élément au sommet)
. . .
```C
void stack_push(stack *s, int val) {
s->top += 1;
s->data[s->top] = val;
}
```
# Les piles (5/5)
## Dépiler (enlever l'élément du sommet)
. . .
```C
int stack_pop(stack *s) {
s->top -= 1;
return s->data[s->top+1];
}
```
## Jeter un oeil (regarder le sommet)
. . .
```C
int stack_peek(stack *s) {
return s->data[s->top];
}
```
## Quelle est la complexité de ces opérations?
. . .
## Voyez-vous des problèmes potentiels avec cette implémentation?
. . .
* Empiler avec une pile pleine.
* Dépiler avec une pile vide.
* Jeter un oeil au sommet d'une pile vide.
# Gestion d'erreur, level 0
* Il y a plusieurs façon de traiter les erreur:
* Ne rien faire (laisser la responsabilité à l'utilisateur).
* Faire paniquer le programme (il plante plus ou moins violemment).
* Utiliser des codes d'erreurs.
## La panique
* En C, on a les `assert()` pour faire paniquer un programme.
# Assertions (1/3)
```C
#include <assert.h>
void assert(int expression);
```
## Qu'est-ce donc?
- Macro permettant de tester une condition lors de l'exécution d'un programme:
- Si `expression == 0`{.C} (condition fausse), `assert()`{.C} affiche un message d'erreur sur `stderr`{.C} et termine l'exécution du programme.
- Sinon l'exécution se poursuit normalement.
- Peuvent être désactivés à la compilation avec `-DNDEBUG` (équivalent à `#define
NDEBUG`)
## À quoi ça sert?
- Permet de réaliser des tests unitaires.
- Permet de tester des conditions catastrophiques d'un programme.
- **Ne permet pas** de gérer les erreurs.
# Assertions (2/3)
<!-- \footnotesize -->
## Exemple
```C
#include <assert.h>
void stack_push(stack *s, int val) {
assert(s->top < MAX_CAPACITY-1);
s->top += 1;
s->data[s->top] = val;
}
int stack_pop(stack *s) {
assert(s->top >= 0);
s->top -= 1;
return s->data[s->top+1];
}
int stack_peek(stack *s) {
assert(s->top >= 0);
return s->data[s->top];
}
```
# Assertions (3/3)
## Cas typiques d'utilisation
- Vérification de la validité des pointeurs (typiquement `!= NULL`{.C}).
- Vérification du domaine des indices (dépassement de tableau).
## Bug vs. erreur de *runtime*
- Les assertions sont là pour détecter les bugs (erreurs d'implémentation).
- Les assertions ne sont pas là pour gérer les problèmes externes au programme (allocation mémoire qui échoue, mauvais paramètre d'entrée passé par l'utilisateur, ...).
. . .
- Mais peuvent être pratiques quand même pour ça...
- Typiquement désactivées dans le code de production.
# La pile dynamique
## Comment modifier le code précédent pour avoir une taille dynamique?
. . .
```C
// alloue une zone mémoire de size octets
void *malloc(size_t size);
// change la taille allouée à size octets (contiguïté garantie)
void *realloc(void *ptr, size_t size);
```
## Et maintenant?
. . .
```C
stack_create(); // crée une pile avec une taille par défaut
// vérifie si la pile est pleine et réalloue si besoin
stack_push();
// vérifie si la pile est vide/trop grande
// et réalloue si besoin
stack_pop();
```
## Exercice: ouvrir un repo/issues pour l'implémentation
* Oui-oui cela est une introduction au développement collaboratif (et
hippie).
# Le tri à deux piles (1/N)
## Cas pratique
![Un exemple de tri à deux piles](figs/tri_piles.svg){width=70%}
# Le tri à deux piles (2/N)
## Exercice: formaliser l'algorithme
. . .
## Algorithme de tri nécessitant 2 piles (G, D)
Soit `tab` le tableau à trier:
```C
Pour tous les i = 0 à N-1
tant que (tab[i] > que le sommet de G) {
dépiler G dans D
}
tant que (tab[i] < que le sommet de D) {
dépiler de D dans G
}
empiler tab[i] sur G
dépiler tout D dans G
tab est trié dans G
```
# Le tri à deux piles (3/N)
## Exercice: trier le tableau `[2, 10, 5, 20, 15]`
```C
```
# La calculatrice (1/8)
## Vocabulaire
```C
2 + 3 = 2 3 +,
```
`2` et `3` sont les *opérandes*, `+` l'*opérateur*.
. . .
## La notation infixe
```C
2 * (3 + 2) - 4 = 6.
```
## La notation postfixe
```C
2 3 2 + * 4 - = 6.
```
## Exercice: écrire `2 * 3 * 4 + 2` en notation `postfixe`
. . .
```C
2 3 4 * * 2 + = (2 * (3 * 4)) + 2.
```
# La calculatrice (2/8)
## De infixe à post-fixe
* Une *pile* est utilisée pour stocker *opérateurs* et *parenthèses*.
* Les opérateurs on des *priorités* différentes.
```C
^ : priorité 3
* / : priorité 2
+ - : priorité 1
( ) : priorité 0 // pas un opérateur mais bon
```
# La calculatrice (3/8)
## De infixe à post-fixe: algorithme
* On lit l'expression infixe de gauche à droite.
* On examine le prochain caractère de l'expression infixe.
* Si opérande, le placer dans l'expression du résultat.
* Si parenthèse le mettre dans la pile (priorité 0).
* Si opérateur, comparer sa priorité avec celui du sommet de la pile:
* Si sa priorité est plus élevée, empiler.
* Sinon dépiler l'opérateur de la pile dans l'expression du résultat et
recommencer jusqu'à apparition d'un opérateur de priorité plus faible
au sommet de la pile (ou pile vide).
* Si parenthèse fermée, dépiler les opérateurs du sommet de la pile et les
placer dans l'expression du résultat, jusqu'à ce qu'une parenthèse
ouverte apparaisse au sommet, dépiler également la parenthèse.
* Si il n'y a pas de caractère dans l'expression dépiler tous les
opérateurs dans le résultat.
# La calculatrice (4/8)
## De infixe à post-fixe: exemple
```C
Infixe Postfixe Pile Priorité
((A*B)/D-F)/(G+H) Vide Vide Néant
(A*B)/D-F)/(G+H) Vide ( 0
A*B)/D-F)/(G+H) Vide (( 0
*B)/D-F)/(G+H) A (( 0
B)/D-F)/(G+H) A ((* 2
)/D-F)/(G+H) AB ((* 2
/D-F)/(G+H) AB* ( 0
D-F)/(G+H) AB* (/ 2
-F)/(G+H) AB*D (/ 2
F)/(G+H) AB*D/ (- 1
)/(G+H) AB*D/F (- 1
/(G+H) AB*D/F- Vide Néant
```
# La calculatrice (5/8)
## De infixe à post-fixe: exemple
```C
Infixe Postfixe Pile Priorité
((A*B)/D-F)/(G+H) Vide Vide Néant
--------------------------------------------------------
/(G+H) AB*D/F- Vide Néant
(G+H) AB*D/F- / 2
G+H) AB*D/F- /( 0
+H) AB*D/F-G /( 0
H) AB*D/F-G /(+ 1
) AB*D/F-GH /(+ 1
Vide AB*D/F-GH+ / 2
Vide AB*D/F-GH+/ Vide Néant
```
# La calculatrice (6/8)
\footnotesize
## Exercice: écrire le code et le poster sur matrix
* Quelle est la signature de la fonction?
. . .
```C
char *infix_to_postfix(char* infix) { // init and alloc stack and postfix
for (size_t i = 0; i < strlen(infix); ++i) {
if (is_operand(infix[i])) {
// we just add operands in the new postfix string
} else if (infix[i] == '(') {
// we push opening parenthesis into the stack
stack_push(&s, infix[i]);
} else if (infix[i] == ')') {
// we pop everything into the postfix
} else if (is_operator(infix[i])) {
// this is an operator. We add it to the postfix based
// on the priority of what is already in the stack and push it
}
}
// pop all the operators from the s at the end of postfix
// and end the postfix with `\0`
return postfix;
}
```
# La calculatrice (7/8)
## Évaluation d'expression postfixe: algorithme
* Chaque *opérateur* porte sur les deux opérandes qui le précèdent.
* Le *résultat d'une opération* est un nouvel *opérande* qui est remis au
sommet de la pile.
## Exemple
```C
2 3 4 + * 5 - = ?
```
* On parcours de gauche à droite:
```C
Caractère lu Pile opérandes
2 2
3 2, 3
4 2, 3, 4
+ 2, (3 + 4)
* 2 * 7
5 14, 5
- 14 - 5 = 9
```
# La calculatrice (8/8)
## Évaluation d'expression postfixe: algorithme
1. La valeur d'un opérande est *toujours* empilée.
2. L'opérateur s'applique *toujours* au 2 opérandes au sommet.
3. Le résultat est remis au sommet.
## Exercice: écrire l'algorithme (et poster sur matrix)
```C
bool evaluate(char *postfix, double *val) { // init stack
for (size_t i = 0; i < strlen(postfix); ++i) {
if (is_operand(postfix[i])) {
stack_push(&s, postfix[i]);
} else if (is_operator(postfix[i])) {
double rhs = stack_pop(&s);
double lhs = stack_pop(&s);
stack_push(&s, op(postfix[i], lhs, rhs);
} }
return stack_pop(&s);
}
```
version: "3.3"
services:
slides:
#To use dockerfile : build: .
image: omalaspinas/pandoc:latest
environment:
USER: 1000
GROUP: 1000
container_name: slides
volumes:
- ./:/data
# entrypoint: ["make", "all"]
working_dir: /data
# user: "$(id -u):$(id -g)"
File moved
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="95.24704mm"
height="95.24704mm"
viewBox="0 0 95.24704 95.24704"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="2reines.svg">
<defs
id="defs2">
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="371.08618"
inkscape:cy="90.967382"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1884"
inkscape:window-height="1052"
inkscape:window-x="36"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid815"
originx="-18.680396"
originy="-59.695988" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-18.680395,-142.05697)">
<g
id="g1101"
transform="translate(-31.537804,-47.306706)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<g
id="g916"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5"
transform="translate(47.37352)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2"
transform="translate(0,47.37352)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0"
transform="translate(47.37352,47.37352)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8"
inkscape:connector-curvature="0" />
</g>
<text
id="text975"
y="224.14017"
x="65.009895"
style="font-size:30.53443909px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="224.14017"
x="65.009895"
id="tspan973"
sodipodi:role="line">R</tspan></text>
</g>
<path
style="fill:#999999;stroke:none;stroke-width:1.88976383;stroke-miterlimit:4;stroke-dasharray:none"
d="m 252.28925,627.12968 v -88 h 88 88 v 88 88 h -88 -88 z"
id="path1411"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
<path
style="fill:#999999;stroke:none;stroke-width:1.88976383;stroke-miterlimit:4;stroke-dasharray:none"
d="m 73.289246,806.12968 v -88 h 88.000004 88 v 88 88 h -88 -88.000004 z"
id="path1413"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
<path
style="fill:#999999;stroke:none;stroke-width:1.88976383;stroke-miterlimit:4;stroke-dasharray:none"
d="m 252.28925,806.12968 v -88 h 88 88 v 88 88 h -88 -88 z"
id="path1415"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
</g>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="622.69006mm"
height="483.61014mm"
viewBox="0 0 622.69006 483.61014"
version="1.1"
id="svg8"
inkscape:version="1.1.1 (3bf5ae0, 2021-09-20)"
sodipodi:docname="3reines.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2">
<linearGradient
id="linearGradient8201"
inkscape:swatch="solid">
<stop
style="stop-color:#0000ff;stop-opacity:1;"
offset="0"
id="stop8199" />
</linearGradient>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-2"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-1"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-9"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-9"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-4"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-91"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-4-2"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-91-6"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-4-0"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-91-61"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-5"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-4"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-6"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-5"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-6-4"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-5-5"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend-6-4-5"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1126-5-5-4"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.28160454"
inkscape:cx="1786.1928"
inkscape:cy="1001.4043"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1080"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0">
<inkscape:grid
type="xygrid"
id="grid815"
originx="214.03458"
originy="259.13096" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(214.03461,-74.306759)">
<g
transform="translate(263.19023,150.28325)"
id="g916-8-5-7-3"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4-7-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7-1-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65-1-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6-5-7"
inkscape:connector-curvature="0" />
</g>
<path
inkscape:connector-curvature="0"
id="path2570-2"
d="m 314.1462,363.58369 v -23.38608 h 23.199 23.19898 v 23.38608 23.38608 h -23.19898 -23.199 z"
style="fill:#ff00ff;stroke:none;stroke-width:0.707107;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g3353"
transform="translate(0,-65.767613)">
<g
transform="translate(-31.537804,-47.306706)"
id="g916"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5"
transform="translate(15.835716,-47.306706)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2"
transform="translate(-31.537804,0.066814)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0"
transform="translate(15.835716,0.066814)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8"
inkscape:connector-curvature="0" />
</g>
<text
id="text975"
y="176.83347"
x="33.472092"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="176.83347"
x="33.472092"
id="tspan973"
sodipodi:role="line">R</tspan></text>
<path
transform="scale(0.26458333)"
inkscape:connector-curvature="0"
id="path1411"
d="m 252.28925,627.12968 v -88 h 88 88 v 88 88 h -88 -88 z"
style="fill:#999999;stroke:none;stroke-width:1.88976;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="scale(0.26458333)"
inkscape:connector-curvature="0"
id="path1413"
d="m 73.289246,806.12968 v -88 h 88.000004 88 v 88 88 h -88 -88.000004 z"
style="fill:#999999;stroke:none;stroke-width:1.88976;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="scale(0.26458333)"
inkscape:connector-curvature="0"
id="path1415"
d="m 252.28925,806.12968 v -88 h 88 88 v 88 88 h -88 -88 z"
style="fill:#999999;stroke:none;stroke-width:1.88976;stroke-miterlimit:4;stroke-dasharray:none" />
<g
transform="translate(63.209236,-47.306706)"
id="g916-8"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(63.209236,0.066814)"
id="g916-8-6"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(63.209236,47.440334)"
id="g916-8-2"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(15.835716,47.440334)"
id="g916-8-5"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-31.537804,47.440334)"
id="g916-8-9"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2"
inkscape:connector-curvature="0" />
</g>
<path
transform="matrix(0.26458333,0,0,0.26458333,18.680395,142.05697)"
inkscape:connector-curvature="0"
id="path2160"
d="M 2.3208456,448.70207 V 360.31372 H 90.35564 178.39043 v 88.38835 88.38835 H 90.35564 2.3208456 Z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,18.680395,142.05697)"
inkscape:connector-curvature="0"
id="path2162"
d="m 360.11688,448.70207 v -88.38835 h 88.38834 88.38835 v 88.38835 88.38835 h -88.38835 -88.38834 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,18.680395,142.05697)"
inkscape:connector-curvature="0"
id="path2164"
d="M 360.11688,90.552486 V 2.5176919 h 88.38834 88.38835 V 90.552486 178.58728 h -88.38835 -88.38834 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
d="m 175.3264,147.60845 h 76.33218"
id="path2406"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-6)"
d="m 252.65801,170.86683 c -21.03189,20.03865 -44.52297,28.90844 -76.33218,0"
id="path2406-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<g
id="g3435"
transform="translate(0,-65.767613)">
<g
transform="translate(215.81671,-49.289308)"
id="g916-7"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-68"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-4"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5-3"
transform="translate(263.19023,-49.289308)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2-0"
transform="translate(215.81671,-1.915786)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0-6"
transform="translate(263.19023,-1.915786)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8-5"
inkscape:connector-curvature="0" />
</g>
<text
id="text975-0"
y="174.85088"
x="280.8266"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="174.85088"
x="280.8266"
id="tspan973-4"
sodipodi:role="line">R</tspan></text>
<path
inkscape:connector-curvature="0"
id="path1411-8"
d="m 314.10605,163.94547 v -23.28334 h 23.28333 23.28333 v 23.28334 23.28333 h -23.28333 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path1413-7"
d="m 266.74563,211.30588 v -23.28333 h 23.28333 23.28334 v 23.28333 23.28334 h -23.28334 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path1415-1"
d="m 314.10605,211.30588 v -23.28333 h 23.28333 23.28333 v 23.28333 23.28334 h -23.28333 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<g
transform="translate(310.56375,-49.289308)"
id="g916-8-7"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-72"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-61"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(310.56375,-1.915786)"
id="g916-8-6-0"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3-9"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(310.56375,45.457733)"
id="g916-8-2-4"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5-1"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(263.19023,45.457733)"
id="g916-8-5-7"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6-5"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(215.81671,45.457733)"
id="g916-8-9-9"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2-7"
inkscape:connector-curvature="0" />
</g>
<path
inkscape:connector-curvature="0"
id="path2160-3"
d="m 266.64897,258.79346 v -23.38608 h 23.29254 23.29253 v 23.38608 23.38609 h -23.29253 -23.29254 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2162-6"
d="m 361.31583,258.79346 v -23.38608 h 23.38609 23.38608 v 23.38608 23.38609 h -23.38608 -23.38609 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2164-5"
d="m 361.31583,164.03305 v -23.29254 h 23.38609 23.38608 v 23.29254 23.29254 h -23.38608 -23.38609 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<text
id="text975-0-9"
y="269.5979"
x="328.20013"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="269.5979"
x="328.20013"
id="tspan973-4-4"
sodipodi:role="line">R</tspan></text>
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2570"
d="m 935.21025,259.65895 v -88.38834 h 87.68125 87.6812 v 88.38834 88.38835 h -87.6812 -87.68125 z"
style="fill:#ff00ff;stroke:none;stroke-width:2.67253;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<g
transform="translate(215.81671,55.536212)"
id="g916-7-6"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-8-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-68-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-8-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-4-5"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5-3-6"
transform="translate(263.19023,55.536212)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6-1-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2-4-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9-9-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1-2-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2-0-7"
transform="translate(215.81671,102.90973)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7-6-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0-8-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93-9-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6-2-6"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0-6-0"
transform="translate(263.19023,102.90973)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62-6-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6-4-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1-9-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8-5-1"
inkscape:connector-curvature="0" />
</g>
<text
id="text975-0-8"
y="279.67639"
x="280.8266"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="279.67639"
x="280.8266"
id="tspan973-4-7"
sodipodi:role="line">R</tspan></text>
<path
inkscape:connector-curvature="0"
id="path1411-8-9"
d="m 314.10605,268.77099 v -23.28334 h 23.28333 23.28333 v 23.28334 23.28333 h -23.28333 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path1413-7-2"
d="m 266.74563,316.1314 v -23.28333 h 23.28333 23.28334 v 23.28333 23.28334 h -23.28334 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path1415-1-0"
d="m 314.10605,316.1314 v -23.28333 h 23.28333 23.28333 v 23.28333 23.28334 h -23.28333 -23.28333 z"
style="fill:#999999;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" />
<g
transform="translate(310.56375,55.536212)"
id="g916-8-7-2"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-2-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-72-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-2-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-61-9"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(310.56375,102.90973)"
id="g916-8-6-0-2"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1-6-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0-1-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6-5-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3-9-7"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(310.56375,150.28325)"
id="g916-8-2-4-3"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0-9-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6-0-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1-9-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5-1-9"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(215.81671,150.28325)"
id="g916-8-9-9-8"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3-7-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74-7-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5-6-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2-7-3"
inkscape:connector-curvature="0" />
</g>
<path
inkscape:connector-curvature="0"
id="path2160-3-6"
d="M 266.64897,363.61898 V 340.2329 h 23.29254 23.29253 v 23.38608 23.38609 h -23.29253 -23.29254 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2162-6-1"
d="M 361.31583,363.61898 V 340.2329 h 23.38609 23.38608 v 23.38608 23.38609 h -23.38608 -23.38609 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2164-5-0"
d="m 361.31583,268.85857 v -23.29254 h 23.38609 23.38608 v 23.29254 23.29254 h -23.38608 -23.38609 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<text
id="text975-0-9-6"
y="327.0499"
x="375.57367"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="327.0499"
x="375.57367"
id="tspan973-4-4-3"
sodipodi:role="line">R</tspan></text>
<g
id="g3243"
transform="translate(220.74134,159.60116)">
<g
transform="translate(-252.27914,66.331489)"
id="g916-6"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-43"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-38"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-60"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5-4"
transform="translate(-204.90562,66.331489)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6-88"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9-97"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1-7"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2-64"
transform="translate(-252.27914,113.70501)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7-30"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6-9"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0-2"
transform="translate(-204.90562,113.70501)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62-54"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8-9"
inkscape:connector-curvature="0" />
</g>
<text
id="text975-4"
y="337.84518"
x="-187.26924"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="337.84518"
x="-187.26924"
id="tspan973-6"
sodipodi:role="line">R</tspan></text>
<g
transform="translate(-157.5321,66.331489)"
id="g916-8-47"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-8"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-157.5321,113.70501)"
id="g916-8-6-12"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3-68"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-157.5321,161.07853)"
id="g916-8-2-0"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5-51"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-204.90562,161.07853)"
id="g916-8-5-1"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7-85"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6-6"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-252.27914,161.07853)"
id="g916-8-9-4"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2-86"
inkscape:connector-curvature="0" />
</g>
<path
inkscape:connector-curvature="0"
id="path2160-2"
d="m -201.44688,374.41425 v -23.38608 h 23.29254 23.29253 v 23.38608 23.38609 h -23.29253 -23.29254 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2931"
d="m -1013.057,875.65803 v -88.03479 h 88.03476 88.03479 v 88.03479 88.0348 h -88.03479 -88.03476 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2933"
d="M -1191.955,517.50845 V 429.1201 h 88.0347 88.0348 v 88.38835 88.38834 h -88.0348 -88.0347 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2935"
d="M -1013.057,517.50845 V 429.1201 h 88.03476 88.03479 v 88.38835 88.38834 h -88.03479 -88.03476 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2937"
d="m -1013.057,696.40646 v -88.38834 h 88.03476 88.03479 v 88.38834 88.38835 h -88.03479 -88.03476 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path2939"
d="m -834.15902,696.40646 v -88.38834 h 88.38835 88.38835 v 88.38834 88.38835 h -88.38835 -88.38835 z"
style="fill:#999999;stroke:none;stroke-width:1.33626;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<g
id="g3188"
transform="translate(147.80005,39.11606)">
<g
transform="translate(68.016668,186.81659)"
id="g916-6-2"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-43-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-3-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-38-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-60-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5-4-9"
transform="translate(115.39018,186.81659)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6-88-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2-8-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9-97-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1-7-1"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2-64-3"
transform="translate(68.016668,234.19011)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7-30-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0-3-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93-0-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6-9-3"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0-2-4"
transform="translate(115.39018,234.19011)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62-54-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6-0-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1-5-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8-9-1"
inkscape:connector-curvature="0" />
</g>
<text
id="text975-4-9"
y="458.33029"
x="133.02655"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="458.33029"
x="133.02655"
id="tspan973-6-6"
sodipodi:role="line">R</tspan></text>
<g
transform="translate(162.7637,186.81659)"
id="g916-8-47-9"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-7-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-5-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-4-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-8-0"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(162.7637,234.19011)"
id="g916-8-6-12-5"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1-8-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0-9-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6-3-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3-68-0"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(162.7637,281.56363)"
id="g916-8-2-0-0"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0-2-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6-1-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1-0-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5-51-6"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(115.39018,281.56363)"
id="g916-8-5-1-7"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7-85-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65-0-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6-6-8"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(68.016668,281.56363)"
id="g916-8-9-4-7"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3-6-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74-2-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5-5-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2-86-9"
inkscape:connector-curvature="0" />
</g>
<path
inkscape:connector-curvature="0"
id="path2160-2-9"
d="m 118.84893,494.89935 v -23.38608 h 23.29254 23.29253 v 23.38608 23.38609 h -23.29253 -23.29254 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2931-6"
d="m 166.21913,494.89273 v -23.29254 h 23.29253 23.29254 v 23.29254 23.29254 h -23.29254 -23.29253 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2933-0"
d="m 118.8857,400.13232 v -23.38608 h 23.29251 23.29255 v 23.38608 23.38608 H 142.17821 118.8857 Z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2935-2"
d="m 166.21913,400.13232 v -23.38608 h 23.29253 23.29254 v 23.38608 23.38608 h -23.29254 -23.29253 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2937-7"
d="m 166.21913,447.46575 v -23.38608 h 23.29253 23.29254 v 23.38608 23.38609 h -23.29254 -23.29253 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2939-6"
d="m 213.55255,447.46575 v -23.38608 h 23.38609 23.38608 v 23.38608 23.38609 h -23.38608 -23.38609 z"
style="fill:#999999;stroke:none;stroke-width:0.353553;stroke-miterlimit:4;stroke-dasharray:none" />
<text
id="text975-4-1"
y="410.95676"
x="227.77359"
style="font-size:30.5344px;line-height:1.25;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"><tspan
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
y="410.95676"
x="227.77359"
id="tspan973-6-3"
sodipodi:role="line">R</tspan></text>
<path
transform="matrix(0.26458333,0,0,0.26458333,113.96132,142.72311)"
inkscape:connector-curvature="0"
id="path3130"
d="m 378.34352,1330.2028 v -87.6812 h 86.26703 86.26703 v 87.6812 87.6813 h -86.26703 -86.26703 z"
style="fill:#ff00ff;stroke:none;stroke-width:5.34506;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-2)"
d="m 171.1667,486.61542 h 76.33218"
id="path2406-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-4)"
d="m -56.263672,372.99614 53.9749995,53.975"
id="path2406-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-4-0)"
d="m 186.6875,221.41972 53.975,53.975"
id="path2406-0-5"
inkscape:connector-curvature="0" />
<g
id="g3941"
transform="translate(92.79598,-105.08797)">
<g
transform="translate(-357.04879,160.62418)"
id="g916-6-5"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-43-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-3-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-38-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-60-4"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-5-4-8"
transform="translate(-309.67527,160.62418)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-6-88-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-2-8-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-9-97-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-1-7-9"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-2-64-6"
transform="translate(-357.04879,207.9977)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-7-30-10"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-0-3-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-93-0-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-6-9-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g916-0-2-2"
transform="translate(-309.67527,207.9977)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-62-54-05"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-6-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-1-5-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-8-9-9"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-262.30175,160.62418)"
id="g916-8-47-8"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-7-38"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-5-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-4-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-8-09"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-262.30175,207.9977)"
id="g916-8-6-12-1"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-1-8-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-0-9-62"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-6-3-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-3-68-4"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-262.30175,255.37122)"
id="g916-8-2-0-4"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-0-2-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-6-1-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-1-0-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-5-51-60"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-309.67527,255.37122)"
id="g916-8-5-1-5"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-4-0-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-7-85-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-65-0-94"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-6-6-3"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-357.04879,255.37122)"
id="g916-8-9-4-5"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,189.61368 h 47.37352"
id="path821-4-3-6-1"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.468199,236.9872 h 47.37352"
id="path821-3-5-74-2-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 50.468199,236.9872 V 189.61368"
id="path821-6-7-0-5-5-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 97.841719,236.9872 V 189.61368"
id="path821-6-7-3-3-2-86-3"
inkscape:connector-curvature="0" />
</g>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-4-2)"
d="m -56.263672,269.68508 53.974997,-53.975"
id="path2406-0-4"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-6-4)"
d="m 219.29526,294.07918 c -29.04126,-0.70233 -51.92384,-11.04113 -53.975,-53.975"
id="path2406-6-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-6-4-5)"
d="M 20.815017,230.22996 C 20.112689,259.27122 9.7738871,282.1538 -33.159978,284.20497"
id="path2406-6-2-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.