layout | title |
---|---|
post |
Induction et récursion |
Induction et récursion sont deux concepts intimement liés, deux facettes d'une même idée. Dans l'usage courant, les deux mots sont employés de façon parfois interchangeable, et en tout cas avec une frontière assez floue ; c'est pour cela qu'on a pris le parti de traiter les deux concepts dans un même page.
Formellement, l'induction est une technique de preuve mathématique employée pour démontrer des théorèmes sur les nombres naturels ou sur d'autres structures infinies munies d'un ordre bien fondé (souvent, des structures définies récursivement). De façon encore plus formelle, l'induction est donnée comme un axiome d'un [système de preuve](Logique mathématique), c'est le cas, par exemple, du [système axiomatique de Peano](Entiers de Peano).
D'un autre côté, la récursion est une technique de définition et construction d'objets mathématiques (fonctions, ensembles, etc.).
Ce que les deux concepts ont en commun, c'est l'idée d'étudier les
propriétés d'un objet (par exemple, une propriété d'un entier
Dans sa forme la plus simple, le principe d'induction est une technique de preuve qui permet de prouver qu'un [prédicat](Calcul des prédicats) est vrai pour tous les entiers. Une preuve par induction (on dit aussi preuve par récurrence) procède en deux étapes :
- On démontre que le prédicat est vrai pour un nombre fini de cas initiaux ;
- On démontre que si le prédicat est vrai pour un cas quelconque, alors il est vrai aussi pour le cas suivant.
On peut faire remonter son origine aux mathématiques classiques, par exemple l'argument d'Euclide prouvant qu'il existe une infinité de nombre premiers est une forme implicite d'induction. Pascal a été l'un des premiers mathématiciens à en donner une définition explicite, mais une formalisation rigoureuse n'est apparue qu'au 19e siècle dans les travaux de Peano, Boole, etc.
Soit
Il existe plusieurs formes équivalentes du principe d'induction. La plus commune, aussi appelée induction faible ou simple, procède en deux étapes :
- Un cas de base (aussi appelé initialisation), où on démontre
le prédicat
$$P(0)$$ ; - Un cas récursif (ou hérédité, ou pas inductif), où on
démontre le prédicat
$$P(n)\Rightarrow P(n+1)$$ .
De ces deux lemmes, le principe d'induction déduit
L'induction forte est une autre forme d'induction couramment utilisée. Dans une preuve par induction forte il suffit de démontrer que
-
$$\forall k < n. P(k)$$ implique$$P(n)$$
pour déduire la vérité du prédicat
Note : Le cas de base de l'induction forte est implicitement contenu dans sa définition. En effet lorsque
On donne ici deux exemples classiques de preuves par induction.
Soit
Preuve. Le cas de base est immédiat, en effet on obtient 0 à droite et à gauche de l'égal. Pour prouver l'hérédité, on suppose que
et on essaye de montrer que
Or
et par hypothèse de récurrence on peut remplacer la somme sur la droite par
Soit
Preuve. On vérifie aisément que pour
où la dernière égalité découle de l'hypothèse de récurrence. Ceci est égal à
ce qui conclut la preuve.
L'application du principe d'induction n'est pas restreinte aux entiers, en effet il peut être appliqué à tout ordre bien fondé. La propriété fondamentale des ordres bien fondés, à savoir qu'il n'existe pas de chaîne descendante infinie, garantit que toute preuve par induction se termine après un nombre fini d'étapes. Ce type d'induction est parfois appelé induction structurelle, il est spécialement utile pour raisonner sur des structures de données tels les arbres, les listes, etc.
Formellement, soit
alors on peut conclure par induction que
Preuve. La preuve découle de l'hypothèse de bonne fondation. De
on déduit que
Supposons que
ce qui contredit l'hypothèse de bonne fondation de
voir aussi Entiers de Peano.
Le principe d'induction peut être prouvé sous une hypothèse de bonne fondation, comme nous l'avons fait dans la section précédente. En ce qui concerne les entiers, on préfère souvent d'énonce le principe d'induction comme un [axiome](Logique mathématique), c'est à dire comme une vérité évidente qui ne nécessite pas de démonstration.
C'est le cas, notamment, dans le [système axiomatique de Peano](Entiers de Peano), où le principe d'induction constitué l'un des neuf axiomes définissant les entiers.
Le principe d'induction peut être exprimé par un schema d'axiomes du premier ordre, i.e. par une infinité de prédicats de la forme
avec un axiome pour chaque prédicat
Il peut aussi être exprimé par un prédicat du second ordre, i.e. par un prédicat où on s'autorise à quantifier les prédicats
La différence entre les deux formulations est trop subtile pour être abordée dans ce cours, mais il est bon de savoir qu'elle a des conséquences importantes.
Les axiomes d'induction sont équivalents à la bonne fondation, c'est à dire que sur tout ensemble sur lequel on impose un axiome d'induction on peut construire un ordre bien fondé (et inversement, comme cela a été montré dans la section précédente).
La récursion est une technique de définition d'objets mathématiques. Comme pour l'induction, on définit récursivement (ou inductivement) une famille d'objets en deux étapes:
- On donne un nombre fini de définitions explicites d'objets de base ;
- On définit tous les autres objets en fonction d'objets plus petits définis précédemment.
Par exemple, la définition des entiers selon les
[axiomes de Peano](Entiers de Peano) peut être vue comme une
construction récursive de l'ensemble
Les constructions récursives que l'on rencontre le plus souvent définissent des fonctions sur les entiers ou sur d'autres structures dotées d'un ordre bien fondé.
Une fonction de
- par un cas de base (ou cas particulier) qui donne une valeur pour la fonction à un entier fixé (en général
$$0$$ ou$$1$$ ): par exemple$$f(0) = 1$$ ; - par un cas inductif (ou cas général) qui définit la valeur à un entier
$$n$$ en fonction de sa valeur à un ou plusieurs entiers plus petit: par exemple$$f(n) = f(n-1) + n$$ .
La fonction factorielle
-
$$0! = 1$$ , -
$$n! = (n-1)! \cdot n$$ pour$$n>0$$ .
La suite de Fibonacci est un exemple de définition récursive basée non seulement sur la valeur de la fonction à
-
$$F(0) = 0$$ , -
$$F(1) = 1$$ , -
$$F(n) = F(n-1) + F(n-2)$$ pour$$n>1$$ .
La suite de Fibonacci apparaît régulièrement en mathématiques, allez voir sa page Wikipedia est un bon point de départ pour se faire une culture là dessus. Régulièrement, on trouve même des biologistes, des historiens et toute autre sorte de savants qui prétendent, à raison ou à tort, avoir rencontré la suite de Fibonacci dans leurs études. Cette page Wikipedia vous donnera quelques idées.
Les nombres de Catalan sont un autre exemple de définition récursive basée non seulement sur la valeur de la fonction à
-
$$C(0) = 1$$ , -
$$C(n+1) = \sum_{i=0}^n C(i) \cdot C(n-i)$$ pour$$n>0$$ .
Les nombres de Catalan apparaissent aussi très fréquemment, dès que l'on travaille avec des arbres binaires. On peut montrer l'égalité suivante
La fonction exponentielle est définie de la façon suivante:
-
$$\exp(0) = 1$$ , -
$$\exp(n) = e\cdot\exp(n-1)$$ pour$$n>0$$ .
Cependant, une autre définition tout à fait légitime est:
-
$$\exp(0) = 1$$ , -
$$\exp(n) = \exp(n/2)^2$$ si$$n>0$$ est pair, -
$$\exp(n) = e\cdot\exp(\lfloor n/2\rfloor)^2$$ si$$n$$ est impair.
Cette deuxième définition a un intérêt algorithmique, puisque elle est à la base de l'algorithme d'exponentiation binaire.
L'indicatrice d'Euler, généralement notée
Si
Plus généralement, si
Ces deux dernières égalités peuvent être prises comme définition récursive de
On peut définir des fonctions ou des propriétés récursives sur autre chose que les entiers. Les chaînes de caractères, par exemple, s'y prêtent très bien.
Une chaine de caractères est palindrome si elle se lit de la même façon de gauche à droite et de droite à gauche. Par exemple, abba et radar sont palindromes. On peut définir la palindromie de la façon suivante:
- La chaîne vide est palindrome,
- toute chaîne d'un seul caractère est palindrome,
- si
$$S$$ est un palindrome, alors$$xSx$$ est palindrome pour tout caractère$$x$$ .
On s'intéresse aux chaînes de caractères dans lesquelles les parenthèses ouvrantes et fermantes sont bien distribuées. Par exemple,
- La chaîne vide est bien parenthésée,
- si
$$A$$ et$$B$$ sont bien parenthésées, alors$$AB$$ est bien parenthésée, - si
$$A$$ est bien parenthésée, alors$$(A)$$ est bien parenthésée.
Exercice: On peut démontrer que le nombre d'expressions bien parenthésées contenant exactement
De manière intuitive, une fonction (ou une propriété) récursive est une fonction qui est définie en termes d'elle même. Ceci ne suffit pas à définir correctement une fonction, car par exemple l'égalité
Formellement, une fonction récursive peut être définie sur tout ensemble muni d'un ordre bien fondé, ou de façon équivalente en présence d'un axiome d'induction.
Soit
Nota bene: Cette définition définition n'impose pas que
Exercice: Pour chacune des fonction récursives définies précédemment, trouvez l'ordre bien fondé qui garantit la cohérence de la définition.
Exercice: Démontrez par Induction que toute fonction bien définie à une valeur unique à chaque élément de
La récursivité est tellement omniprésente en mathématiques, que tous les langages de programmation modernes permettent d'écrire des programmes récursifs, c'est à dire des programmes qui s'appellent eux mêmes.
L'exemple suivant, écrit en Python définit une fonction qui calcule la factorielle
def fact(n):
if n < 0:
raise Error
elif n == 0:
return 1
else:
return n * fact(n-1)
En imitant la définition récursive de l'exponentielle, on peut écrire une fonction qui calcule
def exp(c, n):
if n < 0:
return 1 / exp(c, -n)
elif n == 0:
return 1
else:
return c * exp(c, n-1)
Le principe diviser pour régner est l'un des outils fondamentaux en algorithmique. L'idée consiste à résoudre un problème en le coupant en deux sous-problèmes de taille à peu près égale, qu'on résout de façon récursive. Ce principe permet souvent d'obtenir des gains d'efficacité considérables.
En utilisant la seconde définition récursive pour l'exponentielle, on peut ré-écrire la fonction précédente de la manière suivante
def bin_exp(c, n):
if n < 0:
return 1 / bin_exp(c, -n)
elif n == 0:
return 1
else:
tmp = bin_exp(c, n // 2)
tmp *= tmp
if n % 2 == 1:
tmp *= c
return tmp
Un appel d'une fonction à elle même est dit un appel récursif. Si on compte combien d'appels récursifs ont lieu lors d'un appel à exp(2,10)
on vérifie que celui-ci appelle exp(2,9)
, qui appelle exp(2,8)
et ainsi de suite, pour un total de 10 appels. D'un autre côté un appel à bin_exp(2,10)
engendre un appel à bin_exp(2,5)
, puis à binexp(2,2)
, puis à bin_exp(2,1)
et enfin à bin_exp(2,0)
, pour un total de 4 appels. En général, exp
fera bin_exp
en fera seulement
L'algorithme bin_exp
est appelé exponentiation binaire, à cause du lien avec l'écriture de
Exercice: Étudiez le rapport entre l'exponentiation binaire et l'écriture de for
ou while
et pas d'appels récursifs).
Allez voir cet exercice