IFT-2002

Informatique Théorique

H14 - cours 9


Julien Marcil - julien.marcil@ift.ulaval.ca

Cours précédents

Machine de Turing

Définition: Une machine de Turing consiste en un 7-tuple de la forme $(S, \Sigma, \Gamma, \delta, \iota, s_{\text{accepte}}, s_{\text{rejete}})$ où

  • $S$ est un ensemble fini d’états.
  • $\Sigma$ est l’alphabet d'entré.
  • $\Gamma$ est l’alphabet du ruban tel que $␣ \in \Gamma$ et $\Sigma \subseteq \Gamma$.
  • $\delta : S \times \Gamma \to S \times \Gamma \times \{L,R\}$ est la fonction de transition.
  • $\iota \in S$ est l’état initial.
  • $s_{\text{accepte}} \in S$ est l’état final acceptant.
  • $s_{\text{rejete}} \in S$ est l’état final rejetant et $s_{\text{accepte}} \neq s_{\text{rejete}}$

La thèse de Church-Turing

Les machines de Turing formalisent correctement la notion d'algorithme.

Aujourd'hui

  • Deux modèles calculatoires simples
    • Les programmes RÉPÉTER
    • Les programmes TANTQUE
  • La fonction d’Ackermann

Les programmes RÉPÉTER

Les programmes RÉPÉTER

  • Un nombre arbitrairement grand de registres est disponible: $r_0, r_1, \dots$
  • Chaque registre contient un entier positif ou nul
  • les registres sont implicitement initialisés à $0$ avant utilisation

Les instructions d'un
programmes RÉPÉTER

  • l’instruction $\rrset{r_i}{r_j}$ remplace le contenu du registre $r_i$ par celui de $r_j$
  • l’instruction $\rrinc{r_i}$ incrémente de $1$ le registre $r_i$
  • l’instruction $\rrrep{r_i}[\langle\mathtt{BLOC}\rangle]$ répète l'éxécution d’un bloc d’instructions $r_i$ fois
    • le nombre d’exécution de $\langle\mathtt{BLOC}\rangle$ est fixe une fois pour toutes avant l’entrée dans la boucle, que $r_i$ y soit modifié ou non

Les programmes RÉPÉTER

Un programme RÉPÉTER implante une fonction

$$ \begin{eqnarray} f : & \mathbb N \times \mathbb N \times \cdots \times \mathbb N & \to & \mathbb N \\ & (r_1, \ r_2, \ \dots, \ r_k) & \mapsto & r_0 \end{eqnarray} $$

Au debut de l’exécution, les registres $r_1$ à $r_k$ contiennent les arguments de $f$, et à la fin, $r_0$ contient $f(r_1, \dots, r_k)$.

Grammaire

$$ \begin{aligned} S \to & \langle\mathtt{INCRÉMENTATION}\rangle S \mid \lambda \mid \\ & \langle\mathtt{AFFECTATION}\rangle S \mid \langle\mathtt{RÉPÉTER}\rangle S \\ \langle\mathtt{INCRÉMENTATION}\rangle \to & \rrinc{V} \\ \langle\mathtt{AFFECTATION}\rangle \to & \rrset{V}{V} \\ \langle\mathtt{RÉPÉTER}\rangle \to & \rrrep{V}[S] \\ V \to & r_N \\ N \to & C \mid CN \\ C \to & 0 \mid 1 \mid 2 \mid 3 \mid 4 \mid 5 \mid 6 \mid 7 \mid 8 \mid 9 \end{aligned} $$

Opérations Arithmétiques

Il est assez facile de faire des programmes RÉPÉTER pour des opérations arithmétiques simples.

Addition

$\rrmacro{PLUS}{r_1, r_2} = r_1 + r_2$

$ \rrset{r_0}{r_1} \\ \rrrep{r_2}[ \\ \quad \rrinc{r_0} \\ ] $

Multiplication

$\rrmacro{MULT}{r_1, r_2} = r_1 \times r_2$

$ \rrrep{r_1}[ \\ \quad \rrrep{r_2}[ \\ \quad\quad \rrinc{r_0} \\ \quad ] \\ ] $

Exponentiation

$\rrmacro{EXP}{r_1, r_2} = r_1^{r_2}$

$ \rrinc{r_0} \\ \rrrep{r_2}[ \\ \quad \rrset{r_3}{r_4} \\ \quad \rrrep{r_0}[ \\ \quad\quad \rrrep{r_1}[ \\ \quad\quad\quad \rrinc{r_3} \\ \quad\quad ] \\ \quad ] \\ \quad \rrset{r_0}{r_3} \\ ] $

Sucre syntaxique

L'instruction $\rrinvoke{r_i}{PROC}{r_{j_1}, \dots, r_{j_k}}$ signifie que l’on doit substituer à cette ligne un bloc d’instructions qui a pour effet de remplacer le contenu du registre $r_i$ par la valeur calculee par $\rrmacro{PROC}{r_{j_1}, \dots, r_{j_k}}$, en renommant au besoin les variables qui apparaissent dans le code de la procédure $\mathtt{PROC}$.

Les appels recursifs ne sont pas permis.

Sucre syntaxique

L’instruction $\rrset{r_i}{k}$ signifie que l’on doit substituer à cette ligne $k$ incrémentations, ce qui aura pour effet d’affecter la constante $k$ au registre $r_i$

Partout, on peut mettre une constante $k$ au lieu d’utiliser une variable auxiliaire qu’on aurait incrémentée $k$ fois.

Exponentiation

$\rrmacro{EXP}{r_1, r_2} = r_1^{r_2}$

$ \rrset{r_0}{1} \\ \rrrep{r_2}[ \\ \quad \rrinvoke{r_0}{MULT}{r_0,r_1} \\ ] $

Opérations Arithmétiques

Est-il possible de faire n'importequel opérations arithmétiques avec des programmes RÉPÉTER?

Décrémentation

$\rrmacro{DEC}{r_1} = \max(0, r_1-1)$

$ \rrrep{r_1}[ \\ \quad \rrset{r_0}{r_2} \\ \quad \rrinc{r_2} \\ ] $

Soustraction

$\rrmacro{MOINS}{r_1, r_2} = \max(0, r_1-r_2)$

$ \rrset{r_0}{r_1} \\ \rrrep{r_2}[ \\ \quad \rrinvoke{r_0}{DEC}{r_0} \\ ] $

Factorielle

$\rrmacro{FACT}{r_1} = r_1 !$

$ \rrset{r_0}{1} \\ \rrrep{r_1}[ \\ \quad \rrinc{r_2} \\ \quad \rrinvoke{r_0}{MULT}{r_0, r_2} \\ ] $

Variables Booléennes

Nous adoptons les conventions syntaxiques suivantes :

  • $\rrtrue$ pour la constante $1$
  • $\rrfalse$ pour la constante $0$

Pour évaluer $\langle\mathtt{BLOC}\rangle$ conditionnellement à la valeur booléennes $r_i$ on répète $\langle\mathtt{BLOC}\rangle$ $r_i$ fois.

L’instruction $\rrif{r_i}[\langle\mathtt{BLOC}\rangle]$ sera mise pour $\rrrep{r_i}[\langle\mathtt{BLOC}\rangle]$.

Et

$\rrmacro{ET}{r_1, r_2} = r_1 \land r_2$

$ \rrinvoke{r_0}{MULT}{r_1, r_2} $

Negation

$\rrmacro{NEG}{r_1} = \neg r_1$

$ \rrinvoke{r_0}{MOINS}{1, r_1} $

Ou

$\rrmacro{OU}{r_1, r_2} = r_1 \lor r_2$ $= \neg(\neg r_1 \land \neg r_2)$

$ \rrinvoke{r_1}{NEG}{r_1} \\ \rrinvoke{r_2}{NEG}{r_2} \\ \rrinvoke{r_0}{ET}{r_1, r_2} \\ \rrinvoke{r_0}{NEG}{r_0} \\ $

Plus grand que

$\rrmacro{PG?}{r_1, r_2} = (r_1 \gt r_2)$

$ \rrinvoke{r_3}{MOINS}{r_1, r_2} \\ \rrrep{r_3}[ \\ \quad \rrset{r_0}{\rrtrue} \\ ] $

Opérations Arithmétiques

Regardons d'autres opérations arithmétiques plus complèxes.

Division

$\rrmacro{DIV}{r_1, r_2} = \big\lfloor \frac{r_1}{r_2} \big\rfloor$

$ \rrrep{r_1}[ \\ \quad \rrinvoke{r_3}{PLUS}{r_3, r_2} \\ \quad \rrinvoke{r_4}{PG?}{r_3, r_1} \\ \quad \rrinvoke{r_4}{NEG}{r_4} \\ \quad \rrif{r_4} [ \\ \quad\quad \rrinc{r_0} \\ \quad ] \\ ] $

Modulo

$\rrmacro{MOD}{r_1, r_2} = r_1~\text{mod}~r_2$

$ \rrinvoke{r_0}{DIV}{r_1, r_2} \\ \rrinvoke{r_0}{MULT}{r_0, r_2} \\ \rrinvoke{r_0}{MOINS}{r_1, r_0} $

Test de primalité

$\rrmacro{PREMIER?}{r_1} = (r_1 \in \mathbb P$)

$ \rrset{r_0}{\rrfalse} \\ \rrinvoke{r_5}{PG?}{r_1, 1} \\ \rrif{r_5} [\\ \quad \rrset{r_0}{\rrtrue} \\ \quad \rrset{r_3}{1} \\ \quad \rrinvoke{r_2}{MOINS}{r_1, 2} \\ \quad \rrrep{r_2} [\\ \quad\quad \rrinc{r_3} \\ \quad\quad \rrinvoke{r_4}{MOD}{r_1, r_3} \\ \quad\quad \rrinvoke{r_5}{PG?}{1, r_4} \\ \quad\quad \rrif{r_5} [ \rrset{r_0}{\rrfalse} ] \\ \quad ] \\ ] $

Prochain nombre premier

$\rrmacro{PREMIERSUIV}{r_1} =$ le plus petit nombre premier plus grand que $r_1$

$ \rrinvoke{r_2}{PLUS}{r_1, 1} \\ \rrinvoke{r_2}{MULT}{r_2, 2} \\ \rrset{r_3}{\rrtrue} \\ \rrrep{r_2} [\\ \quad \rrinc{r_1} \\ \quad \rrinvoke{r_4}{PREMIER?}{r_1} \\ \quad \rrinvoke{r_4}{ET}{r_3, r_4} \\ \quad \rrif{r_4} [\\ \quad\quad \rrset{r_0}{r_1} \\ \quad\quad \rrset{r_3}{\rrfalse} \\ \quad ] \\ ] $

$k$-ème nombre premier

$\rrmacro{PREMIERK}{r_1} =$ le $r_1$-ème nombre premier

$ \rrrep{r_1} [\\ \quad \rrinvoke{r_0}{PREMIERSUIV}{r_0} \\ ] $

tableau

Un tableau d’entiers est un $k$-tuple $(a_1, a_2, \dots, a_k)$ que nous stockons dans un registre $r_j$.

Codage de Gödel

Il est possible d'encoder le $k$-tuple $(a_1, a_2, \dots, a_k)$ où $a_i \in \mathbb N$ dans un entier.

Soit $p_n$ le $n$-ième nombre premier. Le $k$-tuple $(a_1, a_2, \dots, a_k)$ est représenté sant ambiguïté par l'entier

$$p_1^{a_1}p_2^{a_2} \cdots p_k^{a_k}$$

Exemples

$ \begin{eqnarray} (1, 1, 1) & = & 2^1 3^1 5^1 & = & 30 \\ (2, 1, 1, 1) & = & 2^2 3^1 5^1 7^1 & = & 420 \\ (2, 0, 4, 3, 0, 3) & = & 2^2 3^0 5^4 7^3 11^0 13^3 & = & 1883927500 \end{eqnarray} $

Extraction d’un élément d’un tableau

$\rrmacro{TABLVAL}{r_1,r_2} =$ le $r_2$-ème élément du tableau $r_1$

$ \rrinvoke{r_3}{PREMIERK}{r_2} \\ \rrset{r_4}{r_3} \\ \rrrep{r_1} [\\ \quad \rrinvoke{r_5}{MOD}{r_1, r_4} \\ \quad \rrinvoke{r_5}{PG?}{1, r_5} \\ \quad \rrif{r_5} [\\ \quad\quad \rrinc{r_0} \\ \quad\quad \rrinvoke{r_4}{MULT}{r_3, r_4} \\ \quad ] \\ ] $

Assignation d’un élément dans un tableau

$\rrmacro{TABLASS}{r_1,r_2,r_3} =$ le tableau $r_1$ où $r_2$-ème élément est remplacé par $r_3$

$ \rrinvoke{r_4}{TABLVAL}{r_1,r_2} \\ \rrinvoke{r_5}{PREMIERK}{r_2} \\ \rrinvoke{r_6}{EXP}{r_5,r_4} \\ \rrinvoke{r_0}{DIV}{r_1,r_6} \\ \rrinvoke{r_7}{EXP}{r_5,r_3} \\ \rrinvoke{r_0}{MULT}{r_0,r_7} $

Puissance des programmes RÉPÉTER

Il semble que les programmes RÉPÉTER peuvent calculer des fonctions complexes.

Peut-on calculer toutes les fonctions à valeurs entières avec un programme RÉPÉTER?

Primitives Récursives

Définition: Les fonctions calculables par un programme RÉPÉTER sont appelées primitives récursives.

Notation

Pour une fonction $f : \mathbb N \to \mathbb N$, et un entier $n$, on note :

$$ \begin{align} f^{\langle 0 \rangle}(x) & = x \\ f^{\langle 1 \rangle}(x) & = f(x) \\ f^{\langle 2 \rangle}(x) & = f(f(x)) \\ & \vdots \\ f^{\langle n \rangle}(x) & = \underbrace{f(f(\cdots f(x) \cdots))}_{n~\text{fois}} \\ \end{align} $$

Remarque

Soit $k, n \in \mathbb N$ et $k \le n$

$$f^{\langle n \rangle}(x) = f^{\langle n-k \rangle}\big(f^{\langle k \rangle}(x)\big)$$

Remarque

Soit $n, u \in \mathbb N$.

$$\big(f^{\langle n \rangle}\big)^{\langle u \rangle}(x) = f^{\langle nu \rangle}(x)$$

Boucles imbriquées

Définition: Soit la fonction $B_i : \mathbb N \to \mathbb N$ pour $i \ge 0$

$$ B_i(x) = \begin{cases} 1 & \text{si}~i=0, x=0 \\ 2 & \text{si}~i=0, x=1 \\ x+2 & \text{si}~i=0, x \gt 1 \\ {B_{i-1}}^{\langle x \rangle}(1) & \text{si}~i \gt 0 \end{cases} $$

Exemples

$$ \begin{eqnarray}{} B_0(x) & = & x+2 \quad & \text{si}~x \gt 1 \\ B_1(x) & = & 2x & \text{si}~x \gt 0 \\ B_2(x) & = & 2^x & \text{si}~x \ge 0 \\ B_3(x) & = & \underbrace{2^{2^{2^{\cdots}}}}_{n~\text{fois}} & \text{si}~x \gt 0 \\ \end{eqnarray} $$

Remarques

Il est clair que plus $i$ est grand, plus $B_i$ est une fonction qui croît rapidement.

  • La valeur de $B_3(5)$ compte 19729 chiffres.
  • La valeur de $B_3(6)$ compte plus de chiffres que le nombre d’atomes dans l’univers.
  • La fonction $B_3$ croît très rapidement, mais ce n’est rien si on la compare à $B_4$.
  • Le taux de croissance de la fonction $B_{100}$ dépasse l’entendement...

Lemme

Pour tout $i \gt 0$, $B_i$ est calculables par un programme RÉPÉTER.

Preuve

$\rrmacro{B[0]}{r_1} = B_0(r_1)$

$ \rrinvoke{r_0}{PLUS}{r_1,1} \\ \rrinvoke{r_2}{PG?}{r_0,2} \\ \rrif{r_2} [\\ \quad \rrinc{r_0} \\ ] $

Preuve (suite)

Pour un $i > 0$ fixé, $\rrmacro{B[i]}{r_1} = B_i(r_1)$

$ \rrinc{r_0} \\ \rrrep{r_1} [\\ \quad \rrinvoke{r_0}{B[i-1]}{r_0} \\ ] $

Remarques

On remarque que le programme $\mathtt{B[i]}$ compte exactement $i$ boucles $\mathtt{répéter}$ et la profondeur d’imbrication est aussi $i$.

Théorème

Propriétés de la famille des fonctions $B_i$

  1. ${B_i}^{\langle k \rangle}(x)$ est croissant en $i$, $x$ et $k$.
  2. ${B_i}(2x) \le {B_i}^{\langle 2 \rangle}(x) \quad$ pour $i \gt 0$, $x \ge 0$.
  3. ${B_0}^{\langle \lceil \frac{y}{2} \rceil + 1 \rangle}(x) \ge y+x \quad$ pour $i, x, y \ge 0$.
  4. ${B_i}^{\langle y \rangle}(x) \le B_{i+1}(y+x) \quad$ pour $i, x, y \ge 0$.


Preuve: Tous les énoncés du théorème peuvent être facilement prouvés par induction sur $i$.

Nombre maximal
d’imbrications

Définition: Pour tout programme RÉPÉTER, $\mathcal B(\mathtt{P})$ est le nombre maximal d’imbrications des boucles de $\mathtt{P}$.

Valeur maximale
des registres

Définition: On note $\mathcal M(\mathtt{P}, r_1, \dots, r_k)$ la valeur maximale des registres $r_1, \dots, r_k$ après l'exécution de $\mathtt{P}$.

Théorème

Pour tout programme RÉPÉTER, si $\mathcal B(\mathtt{P}) = i$, alors il existe un entier $s$ tel que

$$ \forall_{r_1, \dots, r_k \in \mathbb N} \ \mathcal M(\mathtt{P}, r_1, \dots, r_k) \le {B_i}^{\langle s \rangle}\big(\max(r_1, \dots, r_k)\big) $$

Corollaire

Pour tout $i \ge 0$ il existe une fonction qui n’est pas calculable par un programme RÉPÉTER avec une profondeur de boucle $i$, mais qui est calculable par un programme avec une profondeur de boucle $i + 1$.

La fonction d’Ackermann

Définition: En 1926, Wilhelm Ackermann définit la fonction à deux variables suivante

$$ A(i,x) = \begin{cases} 1 & \text{si}~x=0 \\ 2 & \text{si}~i=0, x=1 \\ x+2 & \text{si}~i=0, x \gt 1 \\ A(i-1,A(i,x-1)) & \text{si}~i \gt 0, x \gt 0 \end{cases} $$

Lemme

$$ \forall_{i \in \mathbb N} \ \forall_{x \in \mathbb N} \ A(i,x) = B_i(x) $$

Preuve. Le lemme sera prouvé par induction d’abord sur $i$ et en suite sur $x$.

Théorème

La fonction d’Ackermann n’est pas calculable par un programme RÉPÉTER.

Donc Ackermann n’est pas primitive récursive.

Remarque

La fonction $F(x) = A(x, x)$ croît plus rapidement que n’importe quelle des fonctions $B_i(x)$.

Remarque

Un programme RÉPÉTER ne peut pas entrer dans une boucle infinie, son execution se termine toujours.

Les programmes TANTQUE

Les programmes TANTQUE

Les programmes TANTQUE sont semblables aux programmes RÉPÉTER

  • Un nombre arbitrairement grand de registres est disponible: $r_0, r_1, \dots$
  • Chaque registre contient un entier positif ou nul
  • les registres sont implicitement initialisés à $0$ avant utilisation
  • l’instruction $\rrset{r_i}{r_j}$ remplace le contenu du registre $r_i$ par celui de $r_j$
  • l’instruction $\rrinc{r_i}$ incrémente de $1$ le registre $r_i$

Les instructions d'un
programmes TANTQUE

Les programmes TANTQUE sont semblables aux programmes RÉPÉTER, mais les boucles sont differentes:

  • l’instruction $\rrwhile{r_i \ne r_j}[\langle\mathtt{BLOC}\rangle]$ répète l'éxécution d’un bloc d’instructions tant que les valeurs des registres $r_i$ et $r_j$ diffèrent
    • l’inegalité est réévaluée à chaque itération et les valeurs de $r_i$ et $r_j$ peuvent changer

Les programmes TANTQUE

Un programme TANTQUE implante une fonction

$$ \begin{eqnarray} f : & \mathbb N \times \mathbb N \times \cdots \times \mathbb N & \to & \mathbb N \cup \{ \uparrow \} \\ & (r_1, \ r_2, \ \dots, \ r_k) & \mapsto & \begin{cases} r_0 & \text{si le programme s’arrête} \\ \uparrow & \text{si le programme boucle a l’infini} \\ \end{cases} \end{eqnarray} $$

Au debut de l’exécution, les registres $r_1$ à $r_k$ contiennent les arguments de $f$, et à la fin, $r_0$ contient $f(r_1, \dots, r_k)$.

Remarque

Contrairement aux programmes RÉPÉTER, un programme TANTQUE peut ne jamais s’arrêter, par exemple :

$\rrmacro{BOUCLE}{r_1} = \uparrow$

$ \rrinc{r_1} \\ \rrwhile{r_1 \ne r_0}[\ ] \\ $

Lemme

Tout programme RÉPÉTER peut être simulé par un programme TANTQUE.

Preuve

Il suffit de remplacer les boucles de la forme

$\rrrep{r_i} [\dots]$

par (où $r_j$ et $r_k$ sont des registres non utilisés)

$ \rrset{r_k}{r_i} \\ \rrwhile{r_j \ne r_k} [ \\ \quad \dots \\ \quad \rrinc{r_j} \\ ] $

Sucre syntaxique

On se permettra d’utiliser les instructions $\mathtt{répéter}$ dans les programmes TANTQUE.

On peut donc recycler comme des programmes TANTQUE tous les programmes RÉPÉTER que nous avons vus.

Ackermann est calculable par un programme TANTQUE

Nous allons exhiber un programme TANTQUE qui implante la fonction d’Ackermann

$\rrmacro{ACKERMANN}{r_1, r_2} = A(r_1, r_2)$

$ \rrset{r_3}{1} \\ \rrinc{r4} \quad \rrinvoke{r_3}{TABLASS}{r_3, r_4, r_1} \\ \rrinc{r4} \quad \rrinvoke{r_3}{TABLASS}{r_3, r_4, r_2} \\ \rrwhile{r_4 \ne 1} [ \\ \quad \rrinvoke{r_5}{DEC}{r_4} \quad \rrinvoke{r_7}{TABLEVAL}{r_3, r_5} \\ \quad \rrset{r_6}{r_4} \quad\quad\quad \rrinvoke{r_8}{TABLEVAL}{r_3, r_6} \\ \quad \rrinvoke{r_9}{PG?}{r_8, 0} \quad \rrinvoke{r_{10}}{NEG}{r_9} \\ \quad \rrinvoke{r_{11}}{PG?}{r_7, 0} \quad \rrinvoke{r_{12}}{NEG}{r_{11}} \\ \quad \rrinvoke{r_{13}}{PG?}{r_8, 1} \quad \rrinvoke{r_{14}}{NEG}{r_{13}} \\ \quad \rrif{r_{10}} [\\ \quad\quad \rrinvoke{r_4}{DEC}{r_4} \\ \quad\quad \rrinvoke{r_3}{TABLASS}{r_3, r_4, 1} \\ \quad ] \\ $ $ \quad \rrif{r_{9}} [\\ \quad\quad \rrif{r_{12}} [\\ \quad\quad\quad \rrif{r_{14}} [ \rrinvoke{r_4}{DEC}{r_4} \ \rrinvoke{r_3}{TABLASS}{r_3, r_4, 2} ] \\ \quad\quad\quad \rrif{r_{15}} [ \\ \quad\quad\quad\quad \rrinvoke{r_{15}}{PLUS}{r_8,2} \quad \rrinvoke{r_4}{DEC}{r_4} \\ \quad\quad\quad\quad \rrinvoke{r_3}{TABLASS}{r_3, r_4, r_{15}} \\ \quad\quad\quad ] \\ \quad\quad ] \\ \quad\quad \rrif{r_{11}} [\\ \quad\quad\quad \rrinvoke{r_{15}}{DEC}{r_7} \quad \rrinvoke{r_3}{TABLASS}{r_3, r_5, r_{15}} \\ \quad\quad\quad \rrinvoke{r_3}{TABLASS}{r_3, r_6, r_{7}} \quad \rrinvoke{r_{15}}{DEC}{r_8} \\ \quad\quad\quad \rrinc{r_4} \quad \rrinvoke{r_3}{TABLASS}{r_3, r_4, r_{15}} \\ \quad\quad ] \\ \quad ] \\ ] \\ \rrinvoke{r_0}{TABLVAL}{r_3, r_4} $