Lorem ipsum dolor sit agmet.
Bienvenue sur cet émulateur de machine de Turing en 2 dimension! Nous allons voir ensemble comment il fonctionne à travers une série de cas.
Vous n'êtes peut être pas familier du prinicpe de machine de Turing.
Un petit rappel s'impose donc. La machine dispose d'une bande de donnée composée de cellules où sont inscrits des symboles. Ainsi que d'un jeu d'instruction qui forme un programme. A chaque itération la machine effectue des actions. Ces dernières sont typiquement : changer l'état de la machine, déplacer le curseur de lecture de la bande de donnée, écrire sur la bande de donnée. Elle décide de quoi faire d'après son jeu d'instruction, cela peut varier selon l'état dans lequel elle se trouve, ou selon le symbole lut sur la bande de donnée. A partir ce mécanisme simple on peut reproduire le fonctionnement d'un ordinateur complexe.
Voilà pour le principe général, ici nous utiliserons une machine particulière. Nous utiliserons une bande de donnée à deux dimensions, c'est à dire que le curseur peut se déplacer horizontalement et verticalement. Il conviendra de parler de carte pour désigner une telle bande. Nous utiliserons une seconde carte pour coder le jeu d'instruction, elle est elle aussi parcourue par un curseur. La position du curseur déterminera ainsi l'état de la machine. La carte programme et la carte de donnée utilisent le même jeu de symbole.
Ce dernier est assez simple, il se compose de flèches codant pour le déplacement du curseur de la carte de donnée ( ), de flèches codant pour le déplacement du curseur de la carte d'instruction ( ), par défaut ce dernier se déplace de gauche à droite apès la lecture d'un symbole , et de symbole de couleur, n'ayant pas d'autre signification pour le programme qu'un déplacement par par défaut ( ... ). Ajoutons deux symboles plus complexes pour avoir une machine fonctionnelle. Un rond, ( ) le symbole conditionnel sa signification est liée au symbole qui le suit. Lorsque la machine arrive sur ce symbole, elle lit le symbole sur la carte de donnée, si c'est le même que le symbole suivant sur la carte programme, la machine passe sur le symbole gauche suivant, sinon elle passe sur le symbole en bas. Enfin la croix ( ) permet d'inscrire sur la carte de donnée un symbole.
Bien! Maintenant que l'on a les bases, penchons nous sur l'interface. Vous pouvez observer sur votre gauche les deux carte, la carte programme en haut et la carte donnée en bas. Vous pouvez naviguer dans ces carte via cliquer-glisser et ajuster le niveau de zoom avec la molette de la souris.
Manipulons à présent le panneau de monitoring, il se trouve tout à droite dans la boite à outils, selectionnez l'onglet monitoring. Vous pouvez y lancer la machine, la stopper, ou choisir l'execution pas à pas.
Pour réussir cet exercice, lancez la machine et observez le curseur programme se déplacer en fonction du symbole inscrit sur sa case.
Cet exercice à pour but de vous familiariser avec l'interface.
A vous maintenant! La carte programme de cet exercise est défectueuse, on voudrait que le curseur effectue des tours, comme précédement.
Voyons comment utiliser l'éditeur. Premièrement passez en mode édition en cliquant sur l'onglet de la boite à outils. Nous reviendrons plus tard sur les boutons avec une tête bizarre. Sachez tout d'abord que votre liberté d'action est restreinte pour cette exercice et que vous ne pouvez éditer que les cellules non grisées. Double cliquez sur l'une d'elle pour modifier son symbole. Un panneau devrait vous permettre de selectionner le symbole souhaité dans une liste.
Remarquez que tout symbole est lié à une touche et que vous pouvez rapidement écrire une ligne de symboles en vous servant de votre clavier. Validez la saisie au clavier avec la touche entré pour passer à la cellule suivante.
Lorsque vous avez complété le programme, testez le en mode monitoring.
On vous demande de vous servir des outils d'édition.
Même chose ici, le but est de compléter la boucle. Vous êtes cette fois invité à utiliser les outils avancés.
Prennez la première coupure, une manière rapide de tracer un chemin est d'utiliser l'outil de traçage de chemin . Vous le trouverez dans la boite à outils, dans l'onglet d'édition. Lorsque celui est sélectionné, faites un cliquer-glisser depuis un point vers un autre pour les relier par un chemin.
De même pour la seconde coupure, cependant avant d'utiliser l'outil vous aurez probablement besoin de nettoyer la zone de tout les symboles ( les chemins ne peuvent être tracés que sur des cases vides ). Pour cela utilisez l'effaceur de zone, lui aussi dans l'onglet édition. Selectionner une zone par cliquer glisser et relâchez pour effacer les symboles de la zone. Il ne vous reste qu'à tracer un chemin en évitant les cellules non modifiable.
Enfin pour la troisième coupure, vous aurez besoin de sauter par dessus une cellule ( on veut garder la forme de 8 ). Vous pouvez pour cela utiliser le symbole double déplacement ( ). C'est très utile pour que des chemins puissent se croiser. Remarquez que le traceur de chemin est capable d'utiliser ce symbole si il le faut.
Passons en revue les outils avancés
Vous en savez assez sur l'utilisation de l'interface. C'est maintenant le moment d'utiliser les instructions pour agir sur la bande de donnée.
Le but de cet exercice est de dessiner un carré violet autour de la cellule orange sur la carte de donnée. Vous n'avez accès à celle-ci que via les instructions donnée à la machine.
C'est à ce motif que l'on voudrait arriver.
Les instructions , , et seront utile pour déplacer le cureur de la carte de donnée.
Une fois sur la bonne cellule, utilisez la compinaison de symbole pour inscrire le symbole violet.
Répéter l'opération pour toutes les cellules du carré.
Pour cet exercie vous pouvez modifiez la position initial du curseur.
Jouons un peu avec l'instruction conditionnelle. Le but est de réécrire sur le chemin bleu pour le rendre vert. Pour ce faire il va falloir suivre le chemin.
L'approche proposée est la suivante, supposons que l'on se trouve sur une case verte, on va se déplacer sur les cases qui nous entoure pour tester laquelle est le prolongement du chemin. Pour ce faire on utilisera l'instruction conditionnelle , si la case de la carte de donnée est alors le curseur instruction se déplace à droite, sinon il se déplace vers le bas.
Lorsque l'on detecte une case bleu, on la repeint ( ). On boucle ensuite sur l'état initial pour reprendre la série d'instruction depuis la nouvelle case
Vous allez voir qu'il est possible de réalisez des opérations arithmétiques simples. Ici nous ferons l'addition de deux entiers.
Un entier est X est représenté par X cellules vertes consécutives. On placera une cellule bleu tout à gauche afin de nous servir de repère.
par exemple le nombre 4:
On place les deux entiers en colonne :
On souhaite qu'à la fin de l'exécution, le premier soit la somme des deux
4+2=6
On propose l'approche suivante : décrémenter de un le nombre de pas tout en incrémentant de un celui du haut, tant que le nombre du bas est différent de zéro.
Avant de nous attaquer à plus gros, abordons un concept utile : les effets de bords.
Nous ne voulons pas dégrader les données en entré lors de l'addition. Lors de l'exercice précédent, les entrées ( les deux entiers à additionner ) ne sont plus lisible à la fin du programme, le premier est remplacé par la somme et l'autres est égal à zéro.
Ce n'est plus ce que nous voulons, les entrées ne doivent pas être altérés, ou si elle le sont pendant le processus, les restaurer à la fin.
On place les deux entiers en colonne :
La dernière ligne doit contenir le résultat à la fin
A la fin du processus, on doit obtenir cela:
On se servira des mécanisme de l'exercice précédent. Plutot que de supprimer un à chaque itération, on marquera la cellule unité comme prise en compte en la peignant en orange.
Processus en cours
Il suffira de repeindre les cellules en bleu à la fin de l'execution
La procédure en détail est la suivante:
Notons que l'on pourrait repeindre le permier nombre dès qu'on l'a recopier, c'est à vous de voir
Nous avons toutes les cartes en main pour faire la multiplication de deux entiers.
Pour se faire nous allons nous allons décomposer l'opération en addition que nous savons déjà faire. Pour rappel 4*5 = 5 + 5 + 5 + 5.
Nous allons avoir besoin de faire l'addition plusieurs fois, c'est pourquoi il est important de restaurer les données à chaque itération comme on l'a vu précédement
Comme d'habitude, on place les deux entiers en entrée en colonne, et le résultat en dessous
On ne veut pas d'effet de bord à la fin du processus sur les entrées, alors pensez à repeindre les cellules si vous utilisez des marqueurs
La procédure en détail est la suivante:
Encore un petit jeu sur les entiers. On souhaite trier un ensemble d'entier.
Encore une fois on utilise la représentation en barre pour les entiers. On les place les uns en dessous des autres.
A la fin du processus, on souhaite que les entiers soient triés du plus gand au plus petit en commençant par le haut.
La solution que l'on se propose de mettre en oeuvre est quelque chose entre le tri par insertion et le bubble sort.
On a une opération atomique : comparer deux entiers consécutifs et échanger leurs places si ils ne sont pas correctement ordonnés. Essayez d'effectuer cette opération avant de passer à la suite. C'est en fait assez simple:
Prenez garde à bien prendre en compte le cas où l'entier est nul!
Bien une fois cela fait, il va falloir effectuer cette opération un certain nombre de fois de manière intelligente. Prenons 5 min pour y réfléchir ...
Comme souvent en programmation, on va chercher à diviser le problème.
Faisons l'hypothèse que l'on posséde une partition de la liste de taille n déjà trié, et l'entier n+1 en dessous. Il suffit d'effectuer la fameuse opération atomique sur les entier n et n+1, si les éléments sont bien placé rien ne se passe ( la partition n+1 est déjà ordonnée ) sinon le dernier élément va "remonter" d'un étage. On le compare alors avec l'entier au dessus de lui : n-1, au cas où il remonte suite à cette opération, on le compare au suivant, et ainsi de suite. Si on remonte jusqua l'élément le plus en haut, on est sur que la partition n+1 est ordonnée.
Génial ! et maintenant? On répéte la procédure avec l'élément suivant vers le bas jusqua ce qu'ils soient tous "remontés" ( comme des bulles dans une choppe de bière, d'ou le nom "bubble sort" )
Il nous reste à nous assurer que l'ypothèse de base soit vérifier, à savoir "la partition des n premiers éléments est ordonnée. Facile, on prend n=1!
Pour la mise en oeuvre de la solution, on propose de marquer la partition ordonnée afin de nous y retrouver. On remplace les case verte par des jaunes quand la partition est ordonné
Voila ce que cela donne quand l'algorithme est en cours d'éxécution
La partition des 5 premiers éléments est trié, on intégre le 6 élément en effectuant l'opération de comparaison et échange de position.
L'élément "remonte"
Vous avez déjà fait la multiplication, ca ne dvrait pas être bien dur!
Comme pour la multiplication, on va placer un entier A et un entier B l'un en dessous de l'autre. On souhaite que le 3e entier représente le quotient de la division de A par B, et le 4e entier soit le reste.
7 = 3 * 2 + 1
On va tout simplement ajouter une unité au quotient à chaque fois que l'on peut soustraire une fois le diviseur. On marquera les unités soustraites à chaque itération sur le dividande.
En détail:
On propose maintenant de se rapprocher du comportement d'un processeur en manipulant des nombre binaires.
Vous savez tous déjà probablement ce que c'est
La notation que nous utilisons tous les jours comporte 10 chiffres, 10 symboles différents. On utilise la base 10. On marque un symbole pour désigner un certain nombre de puissance de 10. 341 = 3 * 100 + 4 * 10 + 1 * 1 ou encore 3 * 10^2 + 4 * 10^1 + 1 * 10^0
Pour les binaires on utilise la base 2. Aussi
341 = 1 * 2^8 + 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 1^0
soit 1 * 256 + 0 * 128 + 1 * 64 + 0 * 32 + 1 * 16 + 0 * 8 + 1 * 4 + 0 * 2 + 1 * 1
Pourquoi ce choix? principalement parceque c'est facilement représentable par des grandeur physique ( 1 si un courant passe dans le fil, 0 sinon ). Nous allons le voir rend les calculs plus simples car aisément décomposable en étapes simples.
On utilise 2 couleurs, bleu et jaune pour représenter un nombre binaire. Jaune vaut 1 et bleu vaut 0. On lit de gauche à droite du bit le plus grand au plus petit. Pas besoin de marqueur de début. On codera les entiers sur 6 bits pour cet exercice, c'est à dire que l'on a 6 cellules.
On remarque que 63 est le plus grand nombre que l'on peut représenter avec ce système
L'addition binaire est relativement simple. On décompose la compléxité transversalement, c'est à dire que l'on va effectuer la même opération simple sur plusieurs fractions des données.
Dans notre cas, on va faire l'addition bit à bit. On se rend compte que pour additionner ensenble deux bits, il y a 3 cas de figures:
L'opération logique qui donne le résultat de l'addition est le xor, celle qui donne la retenue est le and logique.
Je pense que vous avez toutes les cartes en main pour faire cette opération, bonne chance!
Faisons la liaison avec les exercices précédents sur les entiers représentés en ligne
Ecrivons un programme qui converti un entier en base 2 en entier représenté en ligne
Le but est d'écrire le nombre en ligne comme dans les exercice précédent après la cellule verte.
On va parcourir les bits et ajouter la puissance de 2 correspondante si le bit est à 1
Il y a plusieurs étapes à aborder.
C'est un gros morceau mais si vous gardez les sous processus clairs, tout devrait bien s'emboiter!
C'est incroyable ce que la représentation binaire est plus compacte!
Bien! On en a fait de belles choses, avec un peu de patiente, on pourrait reproduire le comportement d'un Arithmetic Logic Unit, un composant élémentaire de processeur dédié aux opérations logiques. On pourrait même simulé un ordinateur!
Vous trouvez peut être que l'on va trop loin, après tout c'est votre ordinateur qui fait fonctionner ce programme et à forteriori qui simule le comportement d'un ordinateur.
A vrai nous ne sommes pas près de nous arreter! Nous allons créer une machine de Turing Universelle, une machine de Turing qui simule le comportement ... d'une machine de Turing!
Après tout la carte de donnée utilise les même symbole que celle d'instructions, écrivons les instructions d'un programme sur la carte de donnée et faisons en sorte que la carte d'instruction soit en mesure d'interpréter ce programme
Nous utiliserons un marqueur qui nous servira à symboliser le curseur des pseudo-instructions ( celles de la carte de donnée ), laisser une ligne vide entre chaque instruction pour le curseur nous facilitera beaucoup la tâche.
Il faudra teste quel est le symbole sous le marqueur, et agir en conséquence.
Si c'est une flèche de déplacement, c'est facile on déplace le marqueur/curseur en conséquence. Les instructions plus complexes demandent plus de réfléxion mais rien d'infranchissable
Je vous laisse chercher un peu, sinon vous pouvez toujours tester la solution.
J'ai repris l'exercice sur l'addition en ligne, vous n'avez qu'a lancer et contempler!