reorganisation rm

This commit is contained in:
Florent Madelaine 2024-02-15 00:06:25 +01:00
parent 0a84502bbd
commit a0aa4d5f2f
85 changed files with 0 additions and 122634 deletions

View File

@ -1,38 +0,0 @@
Cours de Florent.
# Information Theory
This is a general field of study that we could understand as covering a number of topics outlined below.
## Database theory
In particular the relational model, where data is stored in tables (like an excel table) and that can be queried efficiently. In practice, the standard is SQL and compliant system include ORACLE, Postgresql, Mysql etc. This goes back to the seventies for the theory with mature software since the late eighties. Most websites propose content that is constructed from data stored in such a database.
In the last 20 years, new models have arisen, in particular graph model that are better suited for data that is not necessrily regular and sometimes partial and where data is queried in a local fashion. The keyword NOSQL is used with mature system like MongoDB in use in the industry. The data is queried and stored differently. This kind of database model is used for example by software of the caisse d'allocation familiale (CAF) to search and detect for large scale fraud.
We shall try to give the intuition behind the relational model by studying and maniulating data stored in tables in csv format.
## Coding theory
When we store or transmit data, no system is perfect and some bits of information are incorrectly stred/retrieved or transmitted.
The purpose of this field is to come up with coding and decoding methods that allows to detect and correct errors with a high probablilty.
We shall provide an introduction with simple codes.
## Compression theory
When we store or transmit data, it makes sense to try to reduce the storage space or the transmission delay. We are looking for two algorithms : one that can code a chunk of data to some smaller sized chunk of data; and, a second one that can from the compressed data reconstruct (perfectly or not) the initial larger chunk of data.
When we can reconstruct the data, we are performing lossless compression, otherwise we speak of irreversible or lossy compression.
For example, jpg is an image format that allows to compress information with some loss of information, but when performed adequatly the human eye can not detect the loss of information.
We shall provide an introduction with simple methods.
## Regular expressions.
Regular expressions (regexp for short) provide an effective tool to define languages.
The correspondance with finite automata mean that it is possible to efficiently compile a regular expression into an automaton that recognises the corresponding language.
On Linux this is precisely what the command grep does.
We will explain how an automaton can be generated from a regexp and see how to use the grep command to solve riddles.

View File

@ -1,18 +0,0 @@
Cours de Pierre.
# Système de fichier, Codage et découverte du terminal. I/II
## Terminal à la linux
Installation Ubuntu sous windows (WSL, ubuntu via couche machine virtuelle hyperV).
https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux
Autres étudiants avec Mac et un shell ("BSD"?)
## Arborescence fichier
répertoire (noeuds internes) vs
Fichier (feuilles)
## Codage
Codage, en particulier binaire et ASCII.
Exemple avec les salles de la fac de droit en binaire.

View File

@ -1,71 +0,0 @@
Cours de Florent.
# Information Theory
## Coding theory
When we store or transmit data, no system is perfect and some bits of information are incorrectly stred/retrieved or transmitted.
The purpose of this field is to come up with coding and decoding methods that allows to detect and correct errors with a high probablilty.
We shall provide an introduction with simple codes.
## Topics covered on the board
* Binary symmetric channel
* Coding and decoding one bit to obtain arbitrary error
* example for a probability of error of 1/6
repeating 3 times, repeating 5 times.
This is essentially a practical version of Shannon's noisy-channel coding theorem.
[Details here](https://en.wikipedia.org/wiki/Binary_symmetric_channel)
So in a nutshell, we can tranform a binary symmetric channel with this repetition trick into a binary symmetric chanel with an arbitrary low error rate.
It is not very practical because, it is achieved at a very high cost in terms of transmited of information compared with the actual information we wish to send.We shall therefore look for cheaper alternatives.
## Detection
If we are ready to forget about correction and concentrate on detection there is a very simple trick.
We transmit some bits of information $b_1\ldots b_n$ with *one additionnal bit*
$c$ that is computed via a very simple method from these bits, that is a certain function $f$ of $n$ arguments such that $f(b_1\ldots b_n)=c$.
At reception of some word $b'_1\ldots b'_nc'$ we check whether $f(b'_1\ldots b'_n)=c'$. If it does we assume that there is no error (we might be wrong here), it it does not we assume that there is an error and ask for retransmission of this message (we are correct here).
This is used for low level transmission of information, in particular for ascii characters (since we tend to use powers of 2 when transmitting and storing information and we have one available bit when storing the 7 bits of the ascii encoding).
[Details here](https://en.wikipedia.org/wiki/Parity_bit)
## Correction
We shall consider a last example which allows to detect and correct 1 error, and the algorithm to do this is quite simple.
Assume that we have 9 bits of information. We write this bits in the form of a 3 times 3 matrix. We add 7 redundant bits, one at the end of each line, one at the bottom of each column, and one in the bottom right corner. Each redundant bit is the sum modulo 2 of the corresponding column / line.
With this scheme we can detect 2 errors, but not correct them as there might be up to three codewords that are the nearest to a received message with 2 errors.
We can always correct 1 error by recomputing the redundant data and compare it to the received data.
In particular, if the error is within the information part, the line / column of the bit to correct lies at the intersection of the line and colmun where the two redundant bits differ.
We call this informally the matrix code below.
## Hamming distance, Minimal distance of a code.
Drawing on the board.
Example for the repeating 3 times code.
## Comparing codes.
Examples with :
* Repetition code (1 bit of information, 2 redundant bits). Detects 2 errors, corrects 1.
* parity code (7 bits of information, 1 parity bit). Detects 1 error, corrects none.
* matrix code (9 bits of information, 7 redundant bits). Detects 2 errors, corrects 1.
## Conclusion.
Very quick discussion of linear code.
Importance of encoding, detecting and correcting schemes that are efficient.

Binary file not shown.

View File

@ -1,362 +0,0 @@
Cours de Florent.
# Système de fichier, Codage et découverte du terminal II/II
## Éditeur et fichier texte
Qu'on programme ou qu'on prépare un mail, il faut éditer un fichier texte.
Ce texte va transiter sur le réseau ou être stocké dans un fichier selon un code bien choisi.
Le code ASCII est inspiré de code pour le télégraphe, comme le code Baudot (1870) : c'est un standard américain initialement pour teleprinter (Bell lab 1961). Il comporte en plus des codes pour des caractères imprimables (chiffres, lettres minuscules et majuscules latines, etc) de nombreux codes pour des opérations spécifiques au mécanisme de communication d'un teleprinter maintenant obsolètes.
[Code Baudot](https://en.wikipedia.org/wiki/Baudot_code)
[ASCII](https://en.wikipedia.org/wiki/ASCII)
### digression
L'ordre des charactères induit par la valeur de leur code ASCII est utilisé pour trier du texte ASCII.
> ASCII-code order is also called ASCIIbetical order
Trier, stocker, indexer et chercher de l'information sont des tâches essentielles qu'on automatise dès la fin du XIXe siècle.
Pour automatiser le recensement américain (le census de 1880 a demandé 8 ans...), Herman Hollerith met au point une machine electro-mécanique manipulant des cartes perforées et flottant dans des bains de mercure. Son entreprise et 4 autres forment un conglomérat qui deviendra IBM en 1924.
[Machines à tabuler](https://en.wikipedia.org/wiki/Tabulating_machine)
### Et si notre alphabet est plus grand?
Pour tester un clavier, ou exhiber une fonte, on peut en anglais écrire.
> The quick brown fox jumps over the lazy dog
En français, on pourra utiliser
> Dès Noël, où un zéphyr haï me vêt de glaçons würmiens, je dîne dexquis rôtis de bœuf au kir, à laÿ dâge mûr, &cætera.
[tester un clavier](https://fr.wikipedia.org/wiki/The_quick_brown_fox_jumps_over_the_lazy_dog)
De nombreux pays vont donc étendre/changer le code ASCII pour y introduire leurs symboles (par exemple les accents en français) avec un soucis d'internationalisation.
En effet, le code ascii ne peut pas facilement accommoder tous les alphabets même si on se restreint aux alphabets latins ou grecs car nous avons seulement 7 bits soit 2^7=128 codes.
On ajoute donc un bit de plus pour permettre d'échanger des données textuelles "internationales".
[ISO/IEC 8859](https://en.wikipedia.org/wiki/ISO/IEC_8859)
Il y a en fait 15 variantes selon les besoins de langues avec des besoins proches.
Un des plus connu, adapté pour le français, est la version 1
[latin-1](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
Ces systèmes restent trop limités car ni vraiment adapté pour de la typographie, ni applicable pour tous les alphabets en usage.
Depuis 2008, le standard est l'UTF-8 (sur le web initialement).
C'est une abbréviation de
> Unicode Transformation Format 8-bit
où Unicode signifie
> Universal Coded Character Set
Une idée intéressante de ce code est qu'on va utiliser un **nombre variable de bytes** (entre 1 et 4).
Typiquement ce qu'on codait en ASCII prendra 1 byte, toutes les langues couvertes par la norme ISO 8859 pourront coder leurs caractères avec au plus 2 bytes, les caractères fréquents de CJK avec 3 bytes et le reste avec 4 permet de coder des symboles moins fréquents (de math, des emoji etc).
[UTF-8](https://en.wikipedia.org/wiki/UTF-8)
## Discussion au tableau de UTF-8
Calcul du nombre de symboles qu'on peut coder.
Perte de place pour les symboles codés par 1 bloc, 2 blocs, 3 blocs, 4 blocs.
évocation du changement de pratique autres systèmes de codage vs UTF-8 (graphiques sur wikipedia).
### Détails techniques de WSL
Le système de fichier linux WSL est monté dans le système windows.
On peut a priori transférer des fichiers vers windows mais pas l'inverse.
Linux ne permet a priori pas d'accéder au système de fichier windows.
Attention. si vous réinstallez WSL vous allez écraser votre home et tout le travail fait sous linux.
[Où est le home linux sous WSL](https://superuser.com/questions/1185033/what-is-the-home-directory-on-windows-subsystem-for-linux)
Vous pouvez lancer dans l'explorateur de fichier windows le home linux en saisissant dans votre terminal linux la commande suivante.
```bash
explorer.exe .
```
Si vous avez installé WSL sans créer de compte utilisateur, vous êtes l'administrateur système linux, connu sous le nom de root. L'invite du terminal indique un dièse \#
Pas de danger vous ne pouvez rien casser dans le système windows.
Par contre par défaut vous êtes dans ... system32 le répertoire système de windows.
Le système winos ne vous laisse pas écrire de fichier à cet endroit.
Il faut vous placer ailleur, par exemple en saisissant la commande suivante.
```bash
cd
```
### explication au tableau de la navigation
_ .. pour revenir en arrière
_ . pour là où on est
_ ~ pour votre home linux
_ / pour la racine du système de fichier linux.
Question ontologique de l'oeuf ou la poule: qui est le .. de / ?
### exercice
1. Ouvrez un terminal.
1. Créer un répertoire folderA (commande mkdir).
1. Placez vous dans ce répertoire (commande cd, pour change directory).
1. Créer un fichier vide grapevine.txt (commande touch).
1. Ouvrez le avec un éditeur de texte (par exemple gedit ou emacs voir nano ou vim).
1. Copiez dans ce fichier un texte de votre choix avec de nombreux caractères qui ne sont pas codable en ascii.
1. Sauvez le.
1. Envoyez un mail avec en pièce jointe ce fichier à votre voisine ou voisin de table.
1. Ouvrez le fichier de votre voisin, sauvez le sous le nom grapevine2.txt et testez si vous pouvez lire le fichier correctement avec votre éditeur.
Parfois votre éditeur ne détectera pas correctement et automatiquement le codage.
Vous pouvez dans certains cas forcer ce codage (e.g. dans emacs Options-Multilingual environment).
### exercice
la commande suivante permet de revenir dans le répertoire parent.
```bash
cd ..
```
Complétez votre arborescence pour arriver à celle-ci.
```
folderA
grapevine.txt
grapevine2.txt
folderAA
toto.txt
titi.txt
folderB
toto.txt
folderC
tata.txt
```
NB. vous pouvez le faire sans utiliser un éditeur ni un logiciel de naviguation de fichier graphique. Seulement en ligne de commande.
La commande
```bash
man
```
permet d'avoir accès au manuel.
testez par exemple
```bash
man ls
```
lisez cette documentation pour chercher l'option qui permet un affichage récursif.
**Correction Indicative**
```bash
mkdir folderA
mkdir folderB
mkdir folderC
cd folderA/
touch grapevine.txt
mkdir folderAA
cd folderAA/
touch toto.txt
touch titi.txt
cd ../
cd ..
cd folderB
touch toto.txt
cd ..
cd folderC/
touch tata.txt
cd ..
ls -R
history | cut -c 8-
```
NB. la dernière commande permet d'enlever les numéros de l'historique.
Le | (on dit pipe) permet d'envoyer le résultat de history dans la commande cut.
La commande cut avec ces options permet d'enlever le numéro de l'historique.
C'est d'ailleurs avec cette commande que j'ai fabriqué la correction indicative ci-dessus.
### exercice
Dans un second temps vous pouvez créer un lien / ou créer un raccourci avec votre système de naviguation de fichier graphique (probablement nautilus sous ubuntu) de grapevine.txt dans le répertoire folderC.
Vous pouvez aussi vous placer vous dans folderC et écrire en ligne de commande
```bash
ln -s ../folderA/grapevine.txt
```
Selon votre configuration en revenant en arrière et en faisant à nouveau un ls avec l'option permettant l'affichage récursif vous allez voir le nom du grapevin.txt sous une couleur différente de l'original.
Nous allons d'abord chercher dans le manuel ce que fait l'option -l de ls
```bash
man ls
```
puis nous allons tester sur notre lien en faisant
```bash
ls -l
```
Je n'ai pas traité en cours les parties ci-dessous.
Vous pouvez ouvrir chaque section en cliquant sur le triangle.
<details><summary>Zoom sur les briques élémentaires du système de fichier</summary>
<p>
### exercice
L'arbre de notre système de fichier est fabriqué à partir de 2 éléments.
1. une feuille de l'arbre = des données stockées à une certaine adresse dans la mémoire
2. un noeud interne de l'arbre = des données stockées à une certaine adresse dans la mémoire qui associe un nom (de fichier ou de répertoire) à un élément de type 1. ou 2. identifiable par le système. En gros le fichier correspondant à un répertoire est une sorte de *livret de famille*.
En pratique, le système utilise une structure de donnée particulière à la fois pour les fichiers et les répertoires (puisqu'il s'agit dans les deux cas de fichiers) qui s'appelle un [inode](https://en.wikipedia.org/wiki/Inode).
En pratique vous pouvez utiliser l'option suivante pour affichier les numéros des inode.
```bash
ls -i
```
### exercice pour aller encore plus loin
Nous avons évoqué les liens symboliques qui sont des raccourcis.
Littéralement c'est juste un fichier texte un peu spécial qui contient comme données la chaîne de caractère du fichier vers lequel on pointe.
Donc quand on a fait ci-dessus.
```bash
ln -s ../folderA/grapevine.txt
```
On a fabriqué un fichier raccourci spécial qui contient essentiellement l'information
```bash
../folderA/grapevine.txt
```
Si vous utilisez la même commande mais en omettant l'option -s vous êtes en train de définir un nouveau nom pour l'inode du fichier grapevine.txt
Donc la métaphore de l'arbre n'est pas tout à fait correcte puisque par plusieurs chemins dans les répertoires il est possible d'atteindre le même fichier.
La commande de suppression de fichier rm (pour remove) ne supprime pas vraiment l'inode, elle va juste effacer le nom du fichier (et la référence vers l'inode associé à ce nom) dans le répertoire.
[Détails sur stackoverflow](https://stackoverflow.com/questions/185899/what-is-the-difference-between-a-symbolic-link-and-a-hard-link)
NB. Je n'ai pas testé sous WSL puisque je n'ai pas windows. Il serait amusant de regarder ce qui arrive aux fichiers linux avec plusieurs noms quand on les regarde en vue détaillée dans l'explorateur de fichier de windows. A priori NTFS a une notion compatible
</p>
</details>
### Commandes utilisées jusqu'à présent
```bash
mkdir
cd
touch
ls
ln
```
<details><summary>Manipuler du texte avec la commande tr</summary>
<p>
## Manipulation de fichier
Pour simplifier un texte, par exemple pour l'indexer ou pour normaliser un nom dans une base de données il est fréquent qu'on bascule un mot en majuscule.
Nous allons travailler avec la commande tr qui permet de faire de tel changement caractère par caractère.
Par exemple ceci permet de transformer les minuscules en majuscule.
```bash
tr '[a-z]' '[A-Z]'
```
La commande tr attend un flux textuel en entrée et transmet un flux textuel en sortie.
On parle de filtre pour ce genre de commande.
On ne peut pas a priori lui passer de fichier en paramètre.
Il faut *rediriger* le contenu du fichier vers la commande.
```bash
tr '[a-z]' '[A-Z]' < grapevine.txt
```
Par défaut le résultat apparaît à l'écran.
On peut rediriger ce résultat dans un fichier en utilisant >
```bash
tr '[a-z]' '[A-Z]' < grapevine.txt > grapevineUp.txt
```
Vous pouvez consulter le contenu d'un fichier directement en utilisant la commande more
```bash
more grapevineUp.txt
```
Attention toutefois avec > car le contenu du fichier si il existe est écrasé.
Il existe une variante utile >> qui écrit à la fin du fichier.
C'est utilisé par exemple pour créer des fichiers de log.
### exercice
Redirigez le résultat de la commande history dans un fichier de sauveguarde myFirstDayWithTheCommandLine.txt.
```bash
history > myFirstDayWithTheCommandLine.txt
```
Vous pouvez consulter ce fichier en utilisant more.
Vous pouvez voir le haut du fichier en faisant head, la fin du fichier en faisant tail.
## Code de césar
Cherchez à appliquer le code de césar (rot13) à un fichier contenant du texte non accentué (i.e. ascii historique).
Envoyez le par mail à votre voisin.
Ce dernier doit le décoder.
```bash
tr '[A-Z]' '[N-ZA-M]'
```
</p>
</details>
## droit d'accès
chmod
Il s'agit de la commande permettant de changer les droits pour un fichier.
## Bonus : jouons avec le pipe
1. installer fortune
1. installer cowsay
```bash
echo moooooo | cowsay
```
```bash
fortune
```
```bash
fortune | cowsay
```
## Bonus : sl
1. installer sl (dans le terminal de votre collègue quand il va boire un café)
1. demandez lui de vous montrer comment ls fonctionne très rapidement (il va probalement écrire sl au lieu de ls à un moment)

View File

@ -1,65 +0,0 @@
Cours de Florent.
# Information Theory
## A quick introduction to regular expressions.
Regular expressions (regexp for short) provide an effective tool to define languages.
The correspondance with finite automata mean that it is possible to efficiently compile a regular expression into an automaton that recognises the corresponding language.
On Linux this is precisely what the command grep does.
We will explain how an automaton can be generated from a regexp and see how to use the grep command to solve riddles.
### Ingredients of classical regexp.
```
the letters of the alphabet
+ means or
used as L1 + L2 where L1 and L2 are two languages
means a word of L1 or a word of L2.
denotes the union of the languages
. means concatenation
used as L1.L2
means a word of L1 followed by a word of L2
* means repetition 0 or more times
used as L*
means the empty word epsilon (0 repetition) or one or more words of L one after another
equivalent to epsilon + L + L.L + L.L.L + L.L.L.L + ...
```
### Construction : from regexp to automaton
We allow for automaton that allow transitions labelled with epsilon.
Then we show how to do without them.
Details on the board.
Note that JFLAP proposes an activity for this construction.
There is also an inverse transformation from automaton to regexp, also available on JFLAP.
This shows that languages defined by a regexp and languages recognized by a finite automaton form the same class of languages, commonly known as regular languages.
### grep
We shall in fact use the extended regular expressions of grep.
Use the command egrep or grep -e.
See the manual of grep for the syntax.
### Some additionnal commands
* tr to replace a character by another
* grep to search for some regular expression line by line
* wc to count words (or characters)
* sort to sort the lines of a file
### Exercise
Wordle.
Demo.

View File

@ -1,127 +0,0 @@
Cours de Florent.
# Calculer en théorie et en pratique I/III
Dans la prochaine séquence de cours, nous allons tenter de répondre à la question suivante.
C'est quoi un ordinateur?
Cette question s'apparente à celle que ce sont posés philosophes et mathématiciens de Leibnitz à Turing en passant par Hilbert.
Qu'est-ce qu'une question à laquelle on peut répondre de manière mécanique par un calcul?
Nous allons explorer rapidement ce sujet en évoquant à la fois des modèles théoriques et des explication sur l'architecture matérielle et le fonctionnement d'ordinateurs modernes.
## Calcul Matériel.
Initialement, les "computer" sont des humains, qui s'aident de divers mécanisme pour faire des calculs rapidement en essayant de faire le moins d'erreurs possibles, par exemple avec un boulier ou des cordes nouées.
Les premières machines à calculer sont mécaniques et peuvent être discrètes (nombre fini de position avec par exemple des roues crantées) ou continues (position continue sur un astrolabe ou une table à tracer pour calculer des intégrales).
Les machines modernes possèdent différents composants electroniques et ce sont les transistors qui permettent de passer d'une information analogique/continue
> quelle est la puissance du courant?
à une information discrète, oui ou non, qu'on peut interpréter comme 0 ou 1.
> est-ce-que le courant dépasse un certain seuil?
On peut à l'aide de quelques composants de base faire des calculs sur ces valeurs 0 ou 1. On parle alors de calcul Booléen (du nom du logicien Boole).
### circuit booléen
consiste en
1. des entrées contenant des valeurs booléennes.
1. des portes logiques permettant de calculer
* le ET binaire (&)
* le OU binaire (v)
* la négation NON unaire (-)
1. des "cables" pour relier ces portes
1. des sorties correspondant à la sortie du calcul.
Au tableau
* table du ET
* table du OU
* table du NON
### exercices
1. Écrire la table de Non de x ou y.
1. Décrire un circuit permettant de tester si deux entrée x et y sont égales.
Le circuit doit renvoyer 1 si c'est le cas et 0 sinon.
NB. on peut noter cette opération <-> ou
2. Même question pour le circuit qui permet de calculer le XOR (Ou eXclusif).
3. Même question pour le circuit permettant de calculer la majorité de trois arguments
### Digression : le schéma de chiffrement de Vernam
Il s'agit d'un schéma très simple et incassable à moins de connaître la clé secrète.
L'inconvénient est qu'il faut fabriquer et partager avec son destinataire une clé secrète aussi longue que le message. On parle aussi de "one time pad" en anglais.
Pendant la seconde guerre mondiale, à Bletchley Park, des opératrices fabriquaient de telles clés mais en quantité trop réduite. Une tentative de mécanisation pour pallier à ce soucis a permis de générer des clés rapidement mais qui avaient une différence avec les véritables clés.
>
"Enoch, why are you . . . here?"
"Oh. I am here, in a larger sense, because Mrs. Tenney, the vicars wife, has become sloppy, and forgotten to close her eyes when she takes the balls out of the bingo machine."
Neal Stephenson. Cryptonomicon.
[Discussion sur stackexchange](https://crypto.stackexchange.com/questions/25214/has-human-generated-entropy-ever-been-a-real-problem)
Nous allons mettre en oeuvre ce chiffrement.
1. Tout d'abord le message à chiffrer M, qu'on suppose encodable en ASCII est transformé en un séquence de 0 et de 1 qu'on note B.
1. La clé secrète S est une série de 0 et de 1 de même longueur.
1. On additionne "modulo 2" B à S pour obtenir le message chiffré C (c'est le XOR de tout à l'heure).
1. On transmet le message chiffré C au destinataire.
1. La destinataire reçoit C.
1. Pour décoder, elle procède de même mais à l'envers.
* ajout de S à C
* découpage en bloc de 7 bits
* décodage ASCII
[page du code ASCII](https://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange)
NB. pour faire plus proche de la réalité, on préfixe le code ASCII d'un 0 pour obtenir un octet.
### exercice
Nous allons mettre en oeuvre ce chiffrement pour le mot BINGO.
Fabriquez au préalable une clé de la taille adapté
(vous pouvez par exemple tirer à pile ou face successivement).
Pour simplifier, vous pouvez le faire avec OK.
Réfléchissez à une mise en oeuvre pratique sur papier.
## Retour à nos circuits.
Nous allons maintenant mettre en oeuvre des circuits pour faire des opérations arithmétiques.
1. Même question pour un circuit qui réalise une somme "modulo 2"
NB. c'est le chiffrement de Vernam.
1. Même question pour un circuit qui réalise une somme en binaire.
Pour ce second circuit on s'autorise une porte de duplication notée D qui prend en entrée x et a deux sorties valant toutes deux x.
### Indication.
Pour rappel en binaire 1+1 vaut 10; 1+0 comme 0+1 valent 1; et, 0+0 vaut 0.
**Exemple**
```
0110
0111
====
...1
..01 retenue 1
.101 retenue 1
1101 Fin
```
### Indication 2
2 questions rhétoriques :
* Comment faire la retenue?
* Comment calcule la somme dans la même colonne?

View File

@ -1,61 +0,0 @@
Cours de Florent.
# Information Theory
## A quick introduction to compression
When we store or transmit data, it makes sense to try to reduce the storage space or the transmission delay. We are looking for two algorithms : one that can code a chunk of data to some smaller sized chunk of data; and, a second one that can from the compressed data reconstruct (perfectly or not) the initial larger chunk of data.
When we can reconstruct the data, we are performing lossless compression, otherwise we speak of irreversible or lossy compression.
We shall provide an introduction with simple methods.
## Image compression
If the data repeats locally some symbols, for example long sequences of white symbols in some black and white image, we may gain a lot of space if we describe the sequence using a number for the length of the sequence together with the repeated symbol.
This so called run length encoding was used for early file images before the gif format appeared.
The gif formal itself uses also another compression method known as LSW.
In contrast with the above where there is no loss of information, let us cite the jpg format which aims at compressing data with loss of indormation, but when performed adequatly the human eye can not detect the loss of information.
If you are interested in patent controversy, which seems to be an american sport, there are historical examples with both the gif and jpg format.
* (run length encoding)[https://en.wikipedia.org/wiki/Run-length_encoding]
* (gif)[https://en.wikipedia.org/wiki/GIF]
* (LSW)[https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch]
* (jpg)[https://en.wikipedia.org/wiki/JPEG]
## a digression : vectorial graphics format.
So far we mentionned only so called *raster graphics* formats, i.e. rectangles of pixels.
There is an alternative, in particular for artifical images : icons, diagrams, maps etc.
In contrast in a *vectorial format*, rather than describing the image, the file will describe in a mini language a recipe explaining how to draw it.
This means in particular that on a screen : the image can be zoomed to an arbitrary precision.
One format which includes as an essential component this idea is the SVG format, now a standard on the web. Basically an SVG file looks similar to an html file (it is an XML file).
Just like HTML, this XML text format allows also many manipulation by scripting techniques via the so called Document Object Model (DOM). For example, to highlight part of the image if something is selected.
You may draw some svg pictures instead of coding using for example inkscape.
* (svg)[https://en.wikipedia.org/wiki/SVG]
* (tutorial and examples on w3 schools)[https://www.w3schools.com/graphics/tryit.asp?filename=trysvg_myfirst]
## A first concrete example of compression : image and run length encoding
(activité informatique débranché irem clermont)[http://www.irem.univ-bpclermont.fr/Images-numeriques]
## Variable length encoding : Hufman code.
(Hufman)[https://en.wikipedia.org/wiki/Huffman_coding]
## Archive
(tar)["https://en.wikipedia.org/wiki/Tar_(computing)"]
## Backup
(rsync)[https://en.wikipedia.org/wiki/Rsync]

View File

@ -1,26 +0,0 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\catcode `:\active
\catcode `;\active
\catcode `!\active
\catcode `?\active
\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
\global\let\oldcontentsline\contentsline
\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global\let\oldnewlabel\newlabel
\gdef\newlabel#1#2{\newlabelxx{#1}#2}
\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\ifx\hyper@anchor\@undefined
\let\contentsline\oldcontentsline
\let\newlabel\oldnewlabel
\fi}
\fi}
\global\let\hyper@last\relax
\gdef\HyperFirstAtBeginDocument#1{#1}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\babel@aux{french}{}
\@writefile{toc}{\contentsline {paragraph}{\IeC {\'e}tape 1 (au tableau)}{1}{Doc-Start}\protected@file@percent }
\@writefile{toc}{\contentsline {paragraph}{\IeC {\'e}tape 2 (au tableau)}{1}{Doc-Start}\protected@file@percent }
\@writefile{toc}{\contentsline {paragraph}{\IeC {\'e}tape 3 : compression}{1}{Doc-Start}\protected@file@percent }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
Ceci est un fichier texte pour tester la commande diff.
Vous pouvez consulter le manuel de la commande diff en écrivant.
man diff
Ici j'ajoute une ligne qui sera absente du fichier file2.txt
Pour faire la différence entre deux fichiers on peut faire :
diff --color file1.txt file2.txt

View File

@ -1,24 +0,0 @@
Ceci est un fichier texte pour tester la commande diff.
Vous pouvez consulter le manuel de la commande diff en écrivant.
man diff
Je peux écrire le résultat (la page de manuel de diff) en écrivant
man diff >> file2.txt
Comme c'est un peu long, à la place j'ai utilisé
man diff | head >> file2.txt
GNU(1) User Commands GNU(1)
NAME
GNU diff - compare files line by line
SYNOPSIS
diff [OPTION]... FILES
DESCRIPTION
Compare FILES line by line.

View File

@ -1,168 +0,0 @@
A mouse took a stroll through the deep dark wood. A fox saw
the mouse and the mouse looked good. “Where are you going
to, little brown mouse? Come and have lunch in my
underground house.”
étape 1 au tableau on compte la fréquence des lettres.
Le moins fréquent est à traiter en premier.
étape 2 au tableau on construit l'arbre de Huffman.
étape 3 : compression.
On note les labels de la racine vers la feuille qui est le code de chaque lettre.
A devient : 0100
(j'écris _ pour l'espace)
_ devient : 111
m devient : 10 101
o devient : 100
u devient : 0 111
s devient : 10 111
e devient : 001
_ devient : 111
t devient : 000 1
o devient : 100
o devient : 100
k devient : 101 001
_ devient : 111
a devient : ????
_ devient : 111
%:-+-+-+- Engendré par : http://math.et.info.free.fr/TikZ/Arbre/
\begin{center}
% Racine à Gauche, développement vers la droite
\begin{tikzpicture}[xscale=1,yscale=1]
% Styles (MODIFIABLES)
\tikzstyle{fleche}=[->,>=latex,thick]
\tikzstyle{noeud}=[fill=yellow,circle,draw]
\tikzstyle{feuille}=[fill=yellow,circle,draw]
\tikzstyle{etiquette}=[midway,fill=white,draw]
% Dimensions (MODIFIABLES)
\def\DistanceInterNiveaux{3}
\def\DistanceInterFeuilles{2}
% Dimensions calculées (NON MODIFIABLES)
\def\NiveauA{(0)*\DistanceInterNiveaux}
\def\NiveauB{(1.875)*\DistanceInterNiveaux}
\def\NiveauC{(3.625)*\DistanceInterNiveaux}
\def\NiveauD{(5.25)*\DistanceInterNiveaux}
\def\NiveauE{(6.75)*\DistanceInterNiveaux}
\def\NiveauF{(8.125)*\DistanceInterNiveaux}
\def\NiveauG{(9.375)*\DistanceInterNiveaux}
\def\NiveauH{(10.5)*\DistanceInterNiveaux}
\def\NiveauI{(11.5)*\DistanceInterNiveaux}
\def\InterFeuilles{(-1)*\DistanceInterFeuilles}
% Noeuds (MODIFIABLES : Styles et Coefficients d'InterFeuilles)
\node[noeud] (R) at ({\NiveauA},{(13.5)*\InterFeuilles}) {$Tous$};
\node[noeud] (Ra) at ({\NiveauB},{(3.5)*\InterFeuilles}) {$$};
\node[noeud] (Raa) at ({\NiveauC},{(1)*\InterFeuilles}) {$$};
\node[noeud] (Raaa) at ({\NiveauD},{(0.5)*\InterFeuilles}) {$$};
\node[feuille] (Raaaa) at ({\NiveauE},{(0)*\InterFeuilles}) {$H$};
\node[feuille] (Raaab) at ({\NiveauE},{(1)*\InterFeuilles}) {$T$};
\node[feuille] (Raab) at ({\NiveauD},{(2)*\InterFeuilles}) {$E$};
\node[noeud] (Rab) at ({\NiveauC},{(5)*\InterFeuilles}) {$$};
\node[noeud] (Raba) at ({\NiveauD},{(4)*\InterFeuilles}) {$$};
\node[feuille] (Rabaa) at ({\NiveauE},{(3)*\InterFeuilles}) {$A$};
\node[noeud] (Rabab) at ({\NiveauE},{(4.5)*\InterFeuilles}) {$$};
\node[feuille] (Rababa) at ({\NiveauF},{(4)*\InterFeuilles}) {$W$};
\node[feuille] (Rababb) at ({\NiveauF},{(5)*\InterFeuilles}) {$G$};
\node[noeud] (Rabb) at ({\NiveauD},{(6.5)*\InterFeuilles}) {$$};
\node[feuille] (Rabba) at ({\NiveauE},{(6)*\InterFeuilles}) {$D$};
\node[feuille] (Rabbb) at ({\NiveauE},{(7)*\InterFeuilles}) {$U$};
\node[noeud] (Rb) at ({\NiveauB},{(17.5)*\InterFeuilles}) {$$};
\node[noeud] (Rba) at ({\NiveauC},{(10.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbaa) at ({\NiveauD},{(8)*\InterFeuilles}) {$O$};
\node[noeud] (Rbab) at ({\NiveauD},{(11)*\InterFeuilles}) {$$};
\node[noeud] (Rbaba) at ({\NiveauE},{(10)*\InterFeuilles}) {$$};
\node[noeud] (Rbabaa) at ({\NiveauF},{(9.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbabaaa) at ({\NiveauG},{(9)*\InterFeuilles}) {$.$};
\node[feuille] (Rbabaab) at ({\NiveauG},{(10)*\InterFeuilles}) {$K$};
\node[feuille] (Rbabab) at ({\NiveauF},{(11)*\InterFeuilles}) {$M$};
\node[noeud] (Rbabb) at ({\NiveauE},{(12.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbabba) at ({\NiveauF},{(12)*\InterFeuilles}) {$L$};
\node[feuille] (Rbabbb) at ({\NiveauF},{(13)*\InterFeuilles}) {$S$};
\node[noeud] (Rbb) at ({\NiveauC},{(20.5)*\InterFeuilles}) {$$};
\node[noeud] (Rbba) at ({\NiveauD},{(20)*\InterFeuilles}) {$$};
\node[noeud] (Rbbaa) at ({\NiveauE},{(16.5)*\InterFeuilles}) {$$};
\node[noeud] (Rbbaaa) at ({\NiveauF},{(16)*\InterFeuilles}) {$$};
\node[noeud] (Rbbaaaa) at ({\NiveauG},{(14.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbbaaaaa) at ({\NiveauH},{(14)*\InterFeuilles}) {$Y$};
\node[feuille] (Rbbaaaab) at ({\NiveauH},{(15)*\InterFeuilles}) {$"$};
\node[noeud] (Rbbaaab) at ({\NiveauG},{(17)*\InterFeuilles}) {$Nœud36$};
\node[noeud] (Rbbaaaba) at ({\NiveauH},{(16.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbbaaabaa) at ({\NiveauI},{(16)*\InterFeuilles}) {$F$};
\node[feuille] (Rbbaaabab) at ({\NiveauI},{(17)*\InterFeuilles}) {$X$};
\node[feuille] (Rbbaaabb) at ({\NiveauH},{(18)*\InterFeuilles}) {$B$};
\node[feuille] (Rbbaab) at ({\NiveauF},{(19)*\InterFeuilles}) {$N$};
\node[noeud] (Rbbab) at ({\NiveauE},{(23)*\InterFeuilles}) {$$};
\node[feuille] (Rbbaba) at ({\NiveauF},{(20)*\InterFeuilles}) {$R$};
\node[noeud] (Rbbabb) at ({\NiveauF},{(23.5)*\InterFeuilles}) {$$};
\node[noeud] (Rbbabba) at ({\NiveauG},{(22.5)*\InterFeuilles}) {$$};
\node[noeud] (Rbbabbaa) at ({\NiveauH},{(21.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbbabbaaa) at ({\NiveauI},{(21)*\InterFeuilles}) {$P$};
\node[feuille] (Rbbabbaab) at ({\NiveauI},{(22)*\InterFeuilles}) {$V$};
\node[noeud] (Rbbabbab) at ({\NiveauH},{(23.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbbabbaba) at ({\NiveauI},{(23)*\InterFeuilles}) {$?$};
\node[feuille] (Rbbabbabb) at ({\NiveauI},{(24)*\InterFeuilles}) {$,$};
\node[noeud] (Rbbabbb) at ({\NiveauG},{(25.5)*\InterFeuilles}) {$$};
\node[feuille] (Rbbabbba) at ({\NiveauH},{(25)*\InterFeuilles}) {$C$};
\node[feuille] (Rbbabbbb) at ({\NiveauH},{(26)*\InterFeuilles}) {$I$};
\node[feuille] (Rbbb) at ({\NiveauD},{(27)*\InterFeuilles}) {$espace$};
% Arcs (MODIFIABLES : Styles)
\draw[fleche] (R)--(Ra) node[etiquette] {$0$};
\draw[fleche] (Ra)--(Raa) node[etiquette] {$0$};
\draw[fleche] (Raa)--(Raaa) node[etiquette] {$0$};
\draw[fleche] (Raaa)--(Raaaa) node[etiquette] {$0$};
\draw[fleche] (Raaa)--(Raaab) node[etiquette] {$1$};
\draw[fleche] (Raa)--(Raab) node[etiquette] {$1$};
\draw[fleche] (Ra)--(Rab) node[etiquette] {$1$};
\draw[fleche] (Rab)--(Raba) node[etiquette] {$0$};
\draw[fleche] (Raba)--(Rabaa) node[etiquette] {$0$};
\draw[fleche] (Raba)--(Rabab) node[etiquette] {$1$};
\draw[fleche] (Rabab)--(Rababa) node[etiquette] {$0$};
\draw[fleche] (Rabab)--(Rababb) node[etiquette] {$A$};
\draw[fleche] (Rab)--(Rabb) node[etiquette] {$1$};
\draw[fleche] (Rabb)--(Rabba) node[etiquette] {$0$};
\draw[fleche] (Rabb)--(Rabbb) node[etiquette] {$1$};
\draw[fleche] (R)--(Rb) node[etiquette] {$1$};
\draw[fleche] (Rb)--(Rba) node[etiquette] {$0$};
\draw[fleche] (Rba)--(Rbaa) node[etiquette] {$0$};
\draw[fleche] (Rba)--(Rbab) node[etiquette] {$1$};
\draw[fleche] (Rbab)--(Rbaba) node[etiquette] {$0$};
\draw[fleche] (Rbaba)--(Rbabaa) node[etiquette] {$0$};
\draw[fleche] (Rbabaa)--(Rbabaaa) node[etiquette] {$0$};
\draw[fleche] (Rbabaa)--(Rbabaab) node[etiquette] {$1$};
\draw[fleche] (Rbaba)--(Rbabab) node[etiquette] {$1$};
\draw[fleche] (Rbab)--(Rbabb) node[etiquette] {$1$};
\draw[fleche] (Rbabb)--(Rbabba) node[etiquette] {$0$};
\draw[fleche] (Rbabb)--(Rbabbb) node[etiquette] {$1$};
\draw[fleche] (Rb)--(Rbb) node[etiquette] {$1$};
\draw[fleche] (Rbb)--(Rbba) node[etiquette] {$0$};
\draw[fleche] (Rbba)--(Rbbaa) node[etiquette] {$0$};
\draw[fleche] (Rbbaa)--(Rbbaaa) node[etiquette] {$0$};
\draw[fleche] (Rbbaaa)--(Rbbaaaa) node[etiquette] {$0$};
\draw[fleche] (Rbbaaaa)--(Rbbaaaaa) node[etiquette] {$0$};
\draw[fleche] (Rbbaaaa)--(Rbbaaaab) node[etiquette] {$1$};
\draw[fleche] (Rbbaaa)--(Rbbaaab) node[etiquette] {$1$};
\draw[fleche] (Rbbaaab)--(Rbbaaaba) node[etiquette] {$0$};
\draw[fleche] (Rbbaaaba)--(Rbbaaabaa) node[etiquette] {$0$};
\draw[fleche] (Rbbaaaba)--(Rbbaaabab) node[etiquette] {$1$};
\draw[fleche] (Rbbaaab)--(Rbbaaabb) node[etiquette] {$1$};
\draw[fleche] (Rbbaa)--(Rbbaab) node[etiquette] {$1$};
\draw[fleche] (Rbba)--(Rbbab) node[etiquette] {$1$};
\draw[fleche] (Rbbab)--(Rbbaba) node[etiquette] {$0$};
\draw[fleche] (Rbbab)--(Rbbabb) node[etiquette] {$1$};
\draw[fleche] (Rbbabb)--(Rbbabba) node[etiquette] {$0$};
\draw[fleche] (Rbbabba)--(Rbbabbaa) node[etiquette] {$0$};
\draw[fleche] (Rbbabbaa)--(Rbbabbaaa) node[etiquette] {$0$};
\draw[fleche] (Rbbabbaa)--(Rbbabbaab) node[etiquette] {$1$};
\draw[fleche] (Rbbabba)--(Rbbabbab) node[etiquette] {$1$};
\draw[fleche] (Rbbabbab)--(Rbbabbaba) node[etiquette] {$0$};
\draw[fleche] (Rbbabbab)--(Rbbabbabb) node[etiquette] {$1$};
\draw[fleche] (Rbbabb)--(Rbbabbb) node[etiquette] {$1$};
\draw[fleche] (Rbbabbb)--(Rbbabbba) node[etiquette] {$0$};
\draw[fleche] (Rbbabbb)--(Rbbabbbb) node[etiquette] {$1$};
\draw[fleche] (Rbb)--(Rbbb) node[etiquette] {$1$};
\end{tikzpicture}
\end{center}
%:-+-+-+-+- Fin

View File

@ -1,70 +0,0 @@
<?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="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="dessin.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.2965909"
inkscape:cx="226.3979"
inkscape:cy="548.57143"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1874"
inkscape:window-height="1136"
inkscape:window-x="46"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<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="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<ellipse
style="opacity:0.28999999;fill:#55d400;fill-opacity:1;stroke-width:0.26458332"
id="path815"
cx="67.646141"
cy="132.01686"
rx="34.384239"
ry="29.69084" />
<rect
style="opacity:0.28999999;fill:#55d400;fill-opacity:1;stroke-width:0.26458332"
id="rect817"
width="55.300468"
height="51.627373"
x="68.360352"
y="86.001167" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,260 +0,0 @@
Cours de Florent.
# Calculer en théorie et en pratique II/III
Dans cette séquence de cours, nous tentons de répondre à la question suivante.
C'est quoi un ordinateur?
Cette question s'apparente à celle que ce sont posés philosophes et mathématiciens de Leibnitz à Turing en passant par Hilbert.
Qu'est-ce qu'une question à laquelle on peut répondre de manière mécanique par un calcul?
Nous avons vu une approximation de calcul théorique basé sur le calcul booléen et des portes logiques qui sont implémentable avec des composants electroniques, permettant de réaliser divers opérations comme l'addition bit à bit (schéma de Vernam en cryptographie), la majorité ou encore l'addition avec retenue.
Aujourd'hui nous poursuivons avec un modèle théorique, qui est celui de l'**automate fini**, un modèle assez restreint de machine. L'adjectif fini s'applique à la mémoire de la machine qui est finie.
Nous verrons plus tard un modèle plus général avec une mémoire arbitrairement grande : la machine deTuring.
## Le modèle d'automate fini.
* La machine va lire en entrée un mot sur un alphabet A de taille finie (on peut par exemple imaginer qu'il s'agit d'un mot en binaire et l'alphabet A serait par exemple composé des symboles 0 et 1).
* La machine possède plusieurs états. Intuitivement, chaque état code pour ce qu'on stocke dans la mémoire finie de la machine.
* Certains états sont dit **acceptant**.
* Un état spécial est celui dans lequel la machine débute son calcul. C'est l'**état initial**.
* La machine va "manger" le mot d'entrée lettre par lettre et passe d'un état à l'autre selon ce que son **programme** lui dicte.
* Quand toutes les lettres sont lues, si l'état dans lequel la machine se trouve est acceptant, la machine répond OUI (elle **accepte** le mot) sinon elle répond NON (elle **rejette** le mot).
* L'ensemble des mots sur l'alphabet A qui sont acceptés par la machine forme le *langage reconnu par l'automate*.
### Le programme de l'automate.
On peut l'écrire dans un tableur, sous forme d'une succession fini de lignes avec trois colonnes.
La première colonne est l'état actuel, la seconde colonne est la lettre lue, la troisième colonne est le nouvel état.
Pour un état donné q et une lettre lue x, l'automate va se placer dans un état donné q' (il est possible que q et q' soit le même état).
Si le programme est incomplet et que le tableur n'explique pas comment faire, on arrête le calcul et on rejette le mot.
Si le tableur n'est pas ambigu et que on n'a jamais deux lignes indiquant pour la même paire de lettre lue et d'état un nouvel état différent, on dit que l'automate est **déterministe**.
Sinon l'automate n'est pas déterministe -- on dit aussi **non-déterministe** -- et on considère que la machine peut choisir une action du tableur parmi celles qui sont listées.
Pour un automate non déterministe, on considère qu'un mot est accepté si il existe un calcul qui accepte.
Analogie : vous cherchez à sortir d'un labyrinthe, il y a de nombreux chemins possibles. Si il en existe un vers la sortie alors vous pouvez gagner au jeu du labyrinthe.
## Exemples avec JFLAP.
JFLAP est un logiciel de simulation de machines théoriques qui permet de définir, manipuler, exécuter et transformer des machines. En pratique c'est une archive jar.
Une archive jar est un programme codé dans le langage java que vous pouvez exécuter.
L'archive se compose de divers fichiers, dont un fichier principal, des librairies etc.
Pour utiliser le logiciel, vous devez commencer par installer java.
Suivez les recommandations de votre système d'exploitation.
Ensuite, il vous suffit souvent de double-cliquer sur l'archive jar.
Vous pouvez aussi en ligne de commande sous linux écrire.
```bash
java -jar <nom de l'archive jar>
```
Sur les machines virtuelles,
### Prise en main de JFlap.
1. Lancez JFLAP et ouvrez [l'automate sauvegardé ici](https://www.lacl.fr/fmadelaine/Download/M1Droit/Automates/TP2NDA.jff)
2. Allez dans le menu *Input* et choisissez *Step by State*. Entrez le mot **babb** et observez la simulation des exécutions parallèles étape par étape en appuyant sur *step*.
3. Testez ensuite avec le mot **baaa**.
4. Relancez les tests ci-dessus. Cette fois essayez les autres
options.
* *Reset* permet de revenir au début du calcul
* *Trace* après sélection en bas d'une exécution permet
de montrer cette exécution depuis le début.
* *Remove* élimine l'exécution sélectionnée
* *Freeze*/*Thaw* permet de mettre en pause ou de
reprendre une exécution (on perd la synchronisation)
5. Vous pouvez aussi tester sans les étapes avec *Fast Run*
voir plusieurs entrées en même temps avec
*Multiple Run* (tous les deux dans le menu *Input*).
Faites le par exemple pour les deux mots précédents.
6. Pour information, *Step with closure* fait la même chose
que *step by State* sauf pour les automates ayant des
transitions avec le mot-vide (mais on ne les considère pas dans
ce cours).
### Hello World
Votre but est de créer l'automate dessiné ci-dessous.
![images/HelloWorldAutomate.jpg]
1. Cliquez sur *File* puis *New*.
2. JFLAP permet de gérer différents modèles de calcul. Nous allons
nous en tenir aux automates finis. Cliquez sur *Finite Automaton*.
Vous avez accès à une nouvelle fenêtre en mode éditeur.
* Cliquez sur le petit cercle avec un q à l'intérieur, puis sur
le canevas pour ajouter des états.
* Les deux derniers boutons permettent de faire du undo/redo.
* La flèche fine permet d'ajouter une transition entre 1 ou 2
états (ne pas oublier de mettre une lettre).
* La flèche plus épaisse à gauche permet de sélectionner,
déplacer, éditer les propriétés des différents éléments (par
exemple de faire un état initial).
* La tête de mort permet de détruire des états ou des transitions.
### Exercices
Dessinez les automates qui reconnaissent :
(pour l'alphabet $\{a,b\}$)
1. les mots de 2 lettres;
2. les mots contenant exactement 2 a;
3. les mots contenant 2 a consécutifs;
4. les mots commençant par b;
5. les mots se terminant par bab;
6. le langage réduit au mot vide;
(pour l'alphabet $\{a,b,c\}$)
7. les mots qui contiennent $aabcc$;
8. les mots de taille multiple de 3;
9. les mots de la forme abcabcabc... (une ou plusieurs successions des 3 lettres abc);
10. les mots dont la première lettre est égale à la dernière.
<details><summary>Calcul modulaire en base 2</summary>
<p>
### Compter avec les automates
On ne le verra pas dans ce cours, mais il est possible d'établir que le modèle des automates ne permet pas de compter. Par exemple, on ne peut pas lire une expression avec des parenthèses et vérifier qu'il y a autant de parenthèses ouvrantes que de parenthèses fermantes. On ne peut pas non plus vérifier que les parenthèses correspondent bien. Ainsi ce modèle n'est pas suffisant pour vérifier par exemple qu'une chaîne de caractères est un programme suivant un syntaxe fixée du C.
Par contre, on peut compter facilement modulo N, puisque celà revient à se souvenir d'un nombre fini de cas.
NB. modulo N veut dire qu'on manipule des nombres en faisant des sommes, des produits, etc mais en s'intéressant uniquement au reste de la division par N du résultat. Ça semble abstrait au premier abord, mais c'est ce que vous faites quand vous calculez le numéro d'un mois avec N=12.
Par exemple 3 mois après novembre c'est février : soit 11+3 = 2 modulo 12.
Imaginons que notre automate lise un mot sur l'alphabet 0,1 représentant en binaire un nombre et qu'on souhaite tester si ce nombre est un multiple de 3.
#### Retour sur la notation binaire
En décimal, si j'ajoute 0 à droite d'un mot décimal w qui représente le nombre n alors le mot décimal w0 (w suivi d'un 0) représente n fois 10.
En binaire, c'est similaire mais en remplaçant 10 par 2 dans la phrase ci-dessus.
Donc w0 représente 2n.
Si j'écris w1 c'est le nombre représenté par w0 plus 1, soit 2n+1.
On peut utiliser cette relation pour déduire des propriétés de divisibilité par trois des nombres représentés par w0 ou w1 en fonction de celle du nombre n représenté par w.
Si n est divisible par trois, il s'écrit sous la forme 3k pour un certain k.
* 2n vaut dans ce cas 2*3k qui est encore divisible par 3 (reste nul, soit 0 modulo 3).
* 2n+1 vaut dans ce cas 2(3k)+1 (reste 1, soit 1 modulo 3).
On peut procéder de même pour les 2 autres cas.
Si le reste de la division de n par trois vaut 1, il s'écrit sous la forme 3k+1 pour un certain k.
* 2n vaut dans ce cas 2(3k+1)=2.3k+2 (reste 2, soit 2 modulo 3).
* 2n+1 vaut dans ce cas 2(3k+1)+1=2.3k+3=3(2k+1) (reste 0, soit 0 modulo 3).
##### Exercice
Procédez de même lorsque le reste de la division de n par trois vaut 2.
En déduire un automate qui lit un mot en binaire et accepte celui-ci exactement lorsque le nombre représenté est divisible par trois.
(indication : il faut un état par reste possible).
</p>
</details>
## Le modèle de la machine de Turing
Nous allons maintenant nous pencher sur un modèle de machine qui
semble au premier abord n'être que légèrement différent de celui des
automates. D'une part, on va pouvoir revenir en arrière sur le mot, et
d'autre part on va pouvoir écrire ce qui permet d'avoir une mémoire
arbitrairement grande.
Ces deux changements permettent
d'obtenir *in fine* un modèle très riche puisque *n'importe quelle
procédure de calcul connue à l'heure actuelle* peut être traduite
théoriquement par une machine de Turing.
Il est important de noter que le programme reste fini.
![images/turingMachine.png]
Il y a beaucoup de ressources sur Alan Turing disponibles en ligne, en
particulier depuis son centenaire en 2012. Vous pouvez trouver (ses
articles originaux et ses brouillons)[http://www.turingarchive.org/].
C'est un mathématicien qui a eu une influente forte en informatique,
malgré une vie trop courte (1912-1954). En droit britannique, (une loi porte son nom)[https://en.wikipedia.org/wiki/Alan_Turing_law}]
### Turing avec JFLAP
Dans le menu choisissez **Machine de Turing**. L'éditeur graphique vous permet de créer rapidement le programme d'une machine de Turing. Les cercles sont les états de la machine (comme pour les automates). Un clic droit permet de rendre initial un état, ou final des états. Un état final correspond ici en fait à un état acceptant. La machine s'arrête si il n'y a pas de transition appropriée (en
rejetant si l'état dans laquelle elle se trouve n'est pas final).
Dans la suite on utilise l'alphabet 0,1 en plus du blanc (ressemblant à un carré pour JFLAP).
Notez que le ruban est infini à gauche et à droite pour JFLAP. Il y a
de nombreuses variations possibles pour la machine de Turing qui ne
font pas de différence notable, par exemple un ruban fini à gauche, un ruban à 2 dimensions etc.
Un point technique avec JFLAP. Si vous voulez fabriquer une transition
qui écrit un blanc (un carré) pour une transition, il suffit de ne rien
saisir dans cette cellule pour la transition et d'appuyer sur entrée.
#### Exercice
On suppose que l'alphabet est 0,1
1. Écrire un programme qui lit les caractères du mot d'entrée de
la gauche vers la droite et s'arrête en acceptant.
1. Même question pour un programme qui accepte si et seulement si
la première et la dernière lettre sont les mêmes.
1. Même question pour les mots qui sont des \textsl{palindromes}
(exemple de palindrome en français KAYAK). On peut dans un premier
temps ne gérer correctement que les mots qui sont de longueur
paire.
#### Indications + correction indicative
Pour les palindromes pairs, de la forme w suivi de w renversé, *on ne peut pas se souvenir dans nos états* du début du mot w qui est arbitrairement grand et donc pour un mot
assez grand forcément plus grand que le nombre (fini) d'états de notre
machine.
Si on disposez d'une machine de Turing à **2 rubans**, on pourrait :
recopier le premier ruban sur le second; ramener la tête de lecture du
premier ruban tout à gauche; puis décaler la tête du premier ruban
vers la droite et celle du second ruban vers la gauche en vérifiant
une par une que les lettres sont identiques.
Comme nous ne disposons que d'un ruban, la seule mémoire non bornée à
notre disposition est l'unique ruban. L'idée consiste donc à vérifier
l'un après l'autre les couples de lettres suivantes : (première
lettre, dernière lettre) puis (seconde lettre, avant-dernière lettre)
etc.
Si nous avions **deux têtes** il suffirait de placer notre seconde tête à
la fin du mot et de procéder comme dans la version à 2 rubans.
Puisqu'on a une seule tête, cette dernière va devoir faire des
aller-retours. Il va falloir marquer d'une manière ou d'une autre les
lettres qu'on a vu pour éviter de repasser au même endroit.
L'exemple ci-dessous enlève tout simplement les lettres en cours de
vérification.
![images/TuringPalindromePair.jpg]
## La thèse de Church Turing.
**Pour tout modèle raisonnable de calcul, on obtient la même notion de ce qui est calculable.**
Arguments en faveur de cette thèse
* Théorie générales des fonctions récursives (Gödel, Herbrand
1933).
* lambda-calcul (Church, 1936).
* Machines de Turing (Turing, 1936).
* Trois modèles équivalents (Church 1936, Turing 1937).
* Machines de Post (1936).
* Machines de Turing avec plusieurs rubans (Minsky).
* Machines à compteurs.
* Machines à registre.
* etc.

View File

@ -1,361 +0,0 @@
Cours de Florent.
# Calculer en théorie et en pratique III/III
Dans cette séquence de cours, nous tentons de répondre à la question suivante.
C'est quoi un ordinateur?
Cette question s'apparente à celle que ce sont posés philosophes et mathématiciens de Leibnitz à Turing en passant par Hilbert.
Qu'est-ce qu'une question à laquelle on peut répondre de manière mécanique par un calcul?
Nous avons vu une approximation de calcul théorique basé sur le calcul booléen et des portes logiques qui sont implémentable avec des composants electroniques, permettant de réaliser divers opérations comme l'addition bit à bit (schéma de Vernam en cryptographie), la majorité ou encore l'addition avec retenue.
Nous avons poursuivi avec un modèle théorique, qui est celui de l'**automate fini**, un modèle assez restreint de machine : l'adjectif fini s'applique à la mémoire de la machine qui est finie.
Nous avons entrevu le modèle plus général avec une mémoire arbitrairement grande **la machine de Turing** et évoqué la thèse de Church-Turing qui stipule que tout modèle de calcul raisonnable est équivalent à ce modèle de la machine de Turing.
Toutefois, le modèle de la machine de Turing reste assez éloigné d'une machine réelle et nous allons maintenant présenter rapidement un modèle simplifié de machine basé sur le modèle de Von Neumann, puis pratiquer l'assembleur avec la Machine Virtuelle à Pile (MVàP).
## Programme vs données
Dans le modèle de Turing, le programme est externe et guide la machine qui travaille sur le contenu du ruban qu'on peut voir comme la donnée.
Dès 1936, Turing montre qu'en fait on peut construire une machine **universelle** qui lit sur son ruban le programme et les données sur lesquelles il faut lancer le calcul de ce programme.
C'est cette idée de "programme qu'on va charger" qu'on retrouve dans le modèle de Von Neumann.
## Le modèle de Von Neumann
* L'unité de Mémoire contient des *données* et *des insructions*
* Le processeur se compose d'une *unité de contrôle* et d'une *unité arithmétique et logique*.
* La communication avec l'extérieur se fait par des dispositifs d'entrée-sortie.
Pour plus de détails, voir [wikipedia](https://en.wikipedia.org/wiki/Von_Neumann_architecture)
## Zoom sur *l'unité arithmétique et logique*
Essentiellement un circuit au sens de ce qu'on a évoqué lors du dernier cours.
En pratique les entrées/sorties sont découpées en 2 dimensions : une partie **contrôle** et une partie **données**.
* [Image](https://commons.wikimedia.org/wiki/File:ALU_block.gif)
* [wikipedia](https://en.wikipedia.org/wiki/Arithmetic_logic_unit)
* [Symboles circuit](https://en.wikipedia.org/wiki/Electronic_symbol)
## Zoom sur la mémoire
La mémoire peut être vue comme une pyramide.
* En haut très peu de place, mais de la mémoire très rapide, ce sont des *registres*.
* Au milieu, de la mémoire assez rapide, c'est la *mémoire vive* (la RAM) qui n'est pas persistante et quand on étend la machine, le contenu de la mémoire n'est pas conservé.
* En bas, de la mémoire plutôt lente, mais persistante, typiquement le *disque dur*.
En pratique il existe des mécanismes de *cache*, en particulier entre les registres et la RAM.
Il y a d'autres ingrédients qui permettent de limiter l'emprunte en mémoire d'un programme (adresses virtuelles, paging) voir de suspendre une exécution et de recopier le programme en train de calculer dans le disque (swapping).
* [Image](images/4-hierarchy.jpg)
* [Jeu du paging](https://en.wikisource.org/wiki/Paging)
* [Cache vs paging](https://stackoverflow.com/questions/4429025/caches-vs-paging)
## la Machine Virtuelle à Pile (MVàP).
Normalement dans une machine il faudrait expliquer comment les calculs sont poussés vers les registres et l'ALU.
Nous allons travailler avec un modèle simplifié qui cache cet aspect et dans laquelle la mémoire est une pile.
Par ailleurs la machine possèdes deux registres.
* PC (pour Program counter) qui contient le numéro de la ligne d'instruction en cours
* FC (pour frame pointer) qui est un mécanisme permettant de faire des appels de fonctions mais qu'on n'utilisera pas car c'est un peu plus technique à utiliser.
La machine accepte plusieurs instructions.
```
PUSHI n # pousse l'entier n sur la pile et passe à l'instruction suivante
POP # décale le sommet de la pile d'un et passe à l'instruction suivante
ADD # ajoute les 2 entiers au sommet de la pile, décale le sommet de la pile de 2
# écrit le résultat en haut de la pile et passe à l'instruction suivante
SUB # même chose pour la soustraction
MUL # même chose pour la multiplication
DIV # même chose pour la division
READ # lecture d'un entier qui est poussé en haut de la pile
WRITE # écriture de l'entier en haut de la pile
HALT # fin du programme
LABEL x # définition d'une ancre vers laquelle on peut sauter
JUMP x # Saut vers le label (prochaine instruction à la ligne du label)
JUMPF x # Instruction suivante si le haut de la pile est différent de 0
# Instruction x sinon.
INF # Mange deux entiers.
# Remplace par l'entier 1 si le premier inférieur au second et par 0 sinon.
# Passe à l'instruction suivante
INFEQ # idem plus petit ou égal
SUP # idem plus grand
SUPEQ # idem plus grand ou égal
EQUAL # idem égal
NEQ # idem différent
# Autres instructions qu'on verra plus tard.
PUSHG a # empile en haut de la pile l'entier stocké à l'adresse a de la pile
STOREG a # dépile et stocke à l'adresse a de la pile l'entier en haut de la pile
# Autres instructions qu'on ne verra probablement pas plus tard.
CALL x # Appel du code stocké au label x
RETURN # Retour dans le code appellant.
PUSHL a # analogue de PUSHG pour des variables locales (utilise FP)
STOREL a # analogue de STOREG
```
L'ordre des opérations est naturel, si on voit la pile de côté, bas à gauche, haut à droite. Une opération qui mange deux arguments prendra l'avant dernier argument comme premier argument et le dernier comme second argument.
### Un premier exemple
```
PUSHI 11
PUSHI 6
PUSHI 15
MUL
SUB
PUSHI 5
ADD
PUSHI 12
ADD
PUSHI 9
PUSHI 4
MUL
PUSHI 7
MUL
ADD
WRITE
POP
HALT
```
Une fois assemblé, le code devient :
```
Adr | Instruction
-----+---------------
0 | PUSHI 11
2 | PUSHI 6
4 | PUSHI 15
6 | MUL
7 | SUB
8 | PUSHI 5
10 | ADD
11 | PUSHI 12
13 | ADD
14 | PUSHI 9
16 | PUSHI 4
18 | MUL
19 | PUSHI 7
21 | MUL
22 | ADD
23 | WRITE
24 | POP
25 | HALT
```
La MVàP, en mode debug, écrit à chaque pas :
* la valeur du compteur de programme (pc) ;
* l'instruction à cette adresse ;
* la valeur du « frame pointer » (toujours 0, quand il n'y a pas d'appel de fonction) ;
* le contenu de la pile ;
* la hauteur de la pile.
Le début de l'exécution donne la trace suivante :
```
pc | | fp pile
====================================================
0 | PUSHI 11 | 0 [ ] 0 # On empile 11
2 | PUSHI 6 | 0 [ 11 ] 1 # On empile 6
4 | PUSHI 15 | 0 [ 11 6 ] 2 # On empile 15
6 | MUL | 0 [ 11 6 15 ] 3 # On dépile et multiplie 6*15, on empile le résultat
7 | SUB | 0 [ 11 90 ] 2 # On dépile et soustrait 90 à 11, on empile le résultat.
8 | PUSHI 5 | 0 [ -79 ] 1 # On empile 5.
etc
```
### Exercice
Continuez l'exécution.
### Exercice
Vérifier votre calcul manuel en lançant la machine.
Il faut avoir java installé sur votre machine ou utiliser proxmox.
Il faut utiliser les deux fichiers jar qui sont dans le répertoire MVaP
Le fichier ```MVaP/ALIRE``` contient la marche à suivre.
### Variables globales
On peut réserver de l'espace en bas de la pile et associer à une variable sa position pour mémoriser des valeurs.
```
PUSHI 1 # Il faut initialement pousser une valeur ( par exemple 1)
... # Du code qui génère des choses dans la pile et une valeur en haut de la pile, par exemple 42
STOREG 0 # stocke 42 à l'adresse 0 de la pile (le 1 est remplacé par 42)
... # Du code qui fait des choses et qui tout à coup a besoin de connaître la valeur stockée
PUSHG 0 # empile 42 en haut de la pile.
```
### Exemple
Imaginons qu'on souhaite faire du code qui :
* déclare une variable i
* lui affecte la valeur 6
* plus tard souhaite l'incrémenter.
```
PUSHI 1 # i habite à l'adresse 0
...
PUSHI 6
STOREG 0
...
PUSHI 1
PUSHG 0
ADD
STOREG 0
```
### Boucles
Imaginons qu'on souhaite faire une boucle tant que
```
Tant que test :
quelque chose
La suite
```
Il faut utiliser des labels pour délimiter
* la partie test suivie de la décision de rentrer dans la boucle ou de sortir
* la partie interne à la boucle (quelque chose)
* la partie qui suit la boucle (La suite).
```
LABEL 0
# le test qui va laisser une valeur 0 ou 1 en haut de la pile
JUMPF 1 # saut conditionnel vers le label 1 si le test est Faux sinon continue
# quelque chose
JUMP 0
LABEL 1
#La suite
```
### Exercice
Produire du code MVàP qui correspond au code python suivant.
```python
j = 1
i = 0
i = j
while i < 10:
i += 1
print(i)
```
Testez votre code avec la MVàP.
### Exercice
Produire du code MVàP qui s'inspire du code suivant et simule la lecture et le stockage d'un tableau avant de vider la pile.
La version ci-dessous ne vide pas la pile.
```
# Boucle While
LABEL 19
# le test qui va laisser une valeur 0 ou 1 en haut de la pile
# PUSHI 0 # pour faux, donc je saute après
# PUSHI 1 # pour vrai, donc je ne saute pas.
READ # on demande à l'utilisateur
JUMPF 18 # saut conditionnel vers le label 1 si le test est Faux sinon continue
# quelque chose
READ
# Fin du quelque chose
JUMP 19
LABEL 18
#La suite
PUSHI 666
WRITE
POP
# Fin de la suite.
HALT
```
### Exercice
Produire du code MVàP qui correspond au code python suivant.
```python
# integer inputs (input returns a string that needs casting as an int)
m = int(input())
n = int(input())
if (m < n) :
m = n
else :
n = m
print m
print n
```
### Réutiliser du code.
Si on a du code qu'on veut réutiliser plusieurs fois,
* on peut l'isoler entre un label et un jump
* on peut sauter vers le label
* malheureusement on ne peut pas sauter à la fin vers plusieurs endroits différents
* on pourrait faire des tests successifs avec des JUMP et des JUMPF pour sauter au bon endroit
* par contre on ne peut pas réutiliser le code un nombre arbitraire de fois.
Solution : on sauve dans un registre l'endroit dans lequel on doit retourner
Le plus simple consiste à utiliser le haut de la pile.
Par contre il faut dans ce cas une instruction pour la MVàP qui permette d'écrire en haut de la pile la position actuelle du pc (c'est une partie du rôle de CALL) et il faut une instruction qui soit l'analogue de HALT pour un bloc et permette de retourner le pc à la valeur antérieure à l'appel (c'est une partie du rôle de RETURN).
Avec cette idée on peut faire un appel à une fonction qui ne prend pas de paramètre et ne retourne pas de valeur.
On peut communiquer avec le reste du programme via une variable globale.
### Exemple
On peut ainsi par exemple faire une fonction qui mutliplie par 2 une variable globale.
On appelle 3 fois la fonction et on affiche le résultat à chaque fois.
```
PUSHI 1 # variable globale i habite à l'adresse 0
JUMP 1
LABEL 0 # Notre Fonction
PUSHG 0
PUSHI 2
MUL
STOREG 0
RETURN # Fin de Notre Fonction
...
LABEL 1 # Main
CALL 0 # appel 1
PUSHG 0
WRITE
CALL 0 # appel 2
PUSHG 0
WRITE
CALL 0 # appel3
PUSHG 0
WRITE
```
## Autres Exercices
Il faut pour chaque exercice produire et tester du code MVàP qui réaliser le calcul ou le programme demandé.
### Exercice
</