La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Information, Calcul, Communication

Présentations similaires


Présentation au sujet: "Information, Calcul, Communication"— Transcription de la présentation:

1 Information, Calcul, Communication
Ce videoclip produit par l’Ecole Polytechnique Fédérale de Lausanne fait partie de son cours d’introduction à l’information, à la communication, et au calcul. Il s’inscrit dans le 1er module du cours qui offre une 1ere approche des notions de calcul et d’information. Information, Calcul, Communication 1. Information & Calcul – Leçon 2: Conception des Algorithmes Clip 4: Récursion – Terminaison et exemple J. Sam, J-C. Chappelier, R. Boulic, commentaire: P. Janson

2 Plan de la leçon Introduction Approche descendante Sommaire
Divide & conquer Récursion Principe Exemple: les tours de Hanoï Terminaison Exemple: somme des N premiers nombres entiers Déroulement Exemple: tri par insertion Programmation dynamique Exemple: calcul du plus court chemin Sommaire Une des grandes questions concernant les algorithmes récursifs est celle de leur terminaison. Dans la mesure où l’exécution d’un tel algorithme déclenche l’exécution d’une ou plusieurs instances de ce même algorithme, on peut – et on doit même – se poser la question de la façon dont une telle récursion met fin à elle-même, sans quoi l’algorithme serait un cas pathologique qui n’aboutit jamais à rien de définitif. C’est je sujet du présent clip.

3 Schéma d’un algorithme récursif en général
Algorithme_récursif Entrée: données du problème Sortie: solution du problème De la façon la plus abstraite, un algorithme récursif obéit au schéma suivant: 1 Comme d’habitude on peut le représenter comme une table en trois parties. 2 La 1e partie définit son nom. 3 La 2e partie définit les données qu’il attend en entrée et la solution qu’on attend de lui en sortie. 4 La 3e partie définit le corps de l’algorithme, qui dans le cas d’un algorithme récursif, comprend au moins une invocation récursive de ce même algorithme. 5 Cette invocation récursive vise cependant à résoudre un problème similaire à l’original mais portant sur des données d’une complexité inférieure à celle du problème original dans l’espoir qu’une solution facile soit applicable dans ce cas plus simple. Algorithme_récursif Entrée: données du sous-problème Sortie: solution du sous-problème

4 Problème => condition de terminaison
Algorithme_récursif Entrée: … n … Sortie: Algorithme_récursif Entrée: … n-1 … Sortie: Algorithme_récursif Entrée: … n-2 … Sortie: Algorithme_récursif Entrée: … n-3 … Sortie: Tel que nous venons d’esquisser le schéma d’un algorithme récursif, il cache cependant le problème critique de sa terminaison. 1 En effet si notre algorithme original invoque une instance de lui-même … 2 … et cette instance fait de même … 3 … ainsi que la suivante … 4 … et toutes les autres … 5 ... on a en fait définit un algorithme qui n’en finit pas d’invoquer des sous-instances de lui-même lequelles ne fournissent jamais de résultats, ce qui ne mène donc jamais à une solution quelconque, même fausse. 6 Sans qu’on lui définisse une condition de terminaison, un algorithme récursif va se lancer dans une boucle infinie qui continue à invoquer des sous-instances sans jamais aboutir à une solution. Algorithme_récursif Entrée: … n-1 … Algorithme_récursif Entrée: … n-2 … Algorithme_récursif Entrée: … n-3 … Algorithme_récursif Entrée: … n-4 … risque d’invoquer à l’ infini des instances d’ … un algorithme récursif sans condition de terminaison …

5 Schéma d’un algorithme récursif avec terminaison
Entrée: données du problème {X} Sortie: solution du problème {Y} Pour s’assurer qu’un algorithme récursif se termine après un nombre fini d’auto-invocations, il faut impérativement que son schéma dispose d’une condition explicite de terminaison. 1 Revoyons donc dans ce sens notre algorithme récursif original. 2 Appelons {X} l’ensemble des données qu’on lui fournit en entrée. Et appelons {Y} l’ensemble des données formant la solution qu’il fournit en sortie. 3 Quelque part dans le corps de notre algorithme doit figurer un test d’une ou plusieurs conditions portant sur tout ou partie des données en entrée {X}. Ce test se trouve souvent, comme ici, en tête du corps de l’algorithme vu qu’il consiste typiquement à identifier le (ou un des) problèmes simples pour le- ou lesquels il existe une solution triviale. 4 Si ce test est positif, l’algorithme applique en effet cette solution triviale pour produire en sortie les données {Y} en fonction des données en entrée {X}. Dans ce cas, l’algorithme se termine sans invoquer aucune instance simplifiée de lui-même. 5 Si par contre ce test est négatif, l’algorithme procède de façon à réduire le problème donné à un problème plus simple à résoudre pour lequel il peut invoquer récursivement une ou plusieurs instances de lui-même sur des ensembles de données réduits {X’} dans le but d’obtenir des solutions partielles {Y’} qui pourront à terme être combinées pour fournir la solution escomptée {Y} au problème original. Si terminaison{X} alors {Y} <- … sinon Algorithme_récursif Entrée: données du sous-problème {X’} Sortie: solution du sous-problème {Y’}

6 Exemple: somme des n premiers nombres entiers
Approche récursive habituelle: => Si je peux le faire pour n, je peux le faire pour n+1: S(n+1) = S(n) + (n+1) NB: Le recours à la récursion et le problème de sa terminaison se présentent dans le calcul de toute entité définie par une telle équation récurrente Prenons à présent un exemple concret d’algorithme récursif pour saisir son déroulement et sa terminaison: le problème de la somme des n premiers nombres entiers positifs. 1 Selon l’approche récursive habituelle, … 2 … nous faisons l’hypothèse que si l’on peut résoudre le problème pour n nombres, on peut le résoudre pour n+1 nombres selon la formule S(n+1) = S(n) + (n+1) 3 Notez au passage que le recours à la récursion et le problème de sa terminaison se présentent dans le calcul de toute entité qui est définie par une équation récurrente telle que celle donnée dans le présent exemple.

7 Algorithme récursif pour la somme des n premiers entiers
Somme_des_premiers_entiers Entrée: n Sortie: S(n) Voyons maintenant comment convertir cette formule récursive en algorithme … 1 … selon notre formalisme habituel en trois parties. 2 Appelons cet algorithme Somme_des_premiers_entiers 3 Fournissons-lui en entrée le nombre n d’entiers positifs à additionner et stipulons que nous attendons en sortie la somme de ces n premiers nombres. 4 La fameuse condition de terminaison correspond au cas trivial où n est nul. Par mesure de sécurité, il est sage d’étendre ce test au cas pathologique où n serait négatif. Cela ne devrait pas arriver mais on veut s’assurer que l’algorithme se termine même si on lui fournit en entrée une valeur de n insensée. 5 Si on se trouve dans le cas trivial, la solution pour S(0) est évidemment 0. (On aurait éventuellement pu distinguer le cas n=0 du cas n<0 et produire dans ce dernier cas un résultat égal à -1 par exemple, histoire de souligner une erreur quand le problème n’a pas de sens quand n<0.) 6 Dans tous les autres cas (c.à.d. quand n>0) l’algorithme s’invoque récursivement en espérant obtenir une solution au problème dans un cas plus simple, en l’occurrence le calcul de la somme m des n-1 premiers nombres entiers. 7 Et dans ce cas, par inférence, la somme S(n) est évidemment égale à l’addition de n à m. Si n≤0 alors S(n) <- 0 sinon S(n) <- n + m Somme_premiers_entiers Entrée: n-1 Sortie: m

8 Récursion & terminaison de la somme des n premiers entiers
Somme_1ers_entiers Entrée: 3 Sortie: Si 3≤0 alors S(3) <- 0 sinon S(3) <- 3 + m? Somme_1ers_entiers Entrée: 2 Sortie: Si 2≤0 alors S(2) <- 0 sinon S(2) <- 2 + m? Somme_1ers_entiers Entrée: 1 Sortie: Si 1≤0 alors S(1) <- 0 sinon S(1) <- 1 + m? Somme_1ers_entiers Entrée: 0 Sortie: Si 0≤0 alors S(0) <- 0 sinon S(0) <- 0 + m? 6 3 1 Simulons alors le déroulement et la terminaison de l’exécution de cet algorithme dans le cas où n=3. 1 L’invocation principale de l’algorithme va commencer par comparer n (c.à.d. 3) à 0. Le test est étant négatif, il n’exécute pas la branche grisée «alors» mais au contraire la branche «sinon» 2 Celle-ci invoque alors l’algorithme récursivement avec cette fois n=2. Cette 2e invocation commence aussi par comparer n (c.à.d. cette fois 2) à 0. Le test étant toujours négatif, il n’exécute pas la branche grisée «alors» 3 Celle-ci invoque alors à nouveau l’algorithme avec cette fois n=1. Cette 3e invocation commence à nouveau par comparer n (c.à.d. cette fois 1) à 0. 4 Celle-ci invoque une 4e fois l’algorithme avec cette fois n=0. Cette 4e invocation commence une fois de plus par comparer n (c.à.d. cette fois 0) à 0. Le test étant cette fois-ci positif, il laisse de côté la branche grisée «sinon» mais exécute au contraire la branche «alors» qui met S(0) à 0 5 Ainsi se termine la récursion qui fournit donc S(0)=0 comme résultat de la 4e invocation. 6 Ce résultat est alors renvoyé à la 3e invocation. 7 Celle-ci achève alors sa branche «sinon» en assignant à S(1) la valeur n+m = 1+0 = 1. 8 Elle fournit donc comme résultat en sortie S(1)=1. 9 Ce résultat est alors renvoyé à la 2e invocation. 10 Celle-ci achève alors sa branche «sinon» en assignant à S(2) la valeur n+m = 2+1 = 3. 11 Elle fournit donc comme résultat en sortie S(2)=3. 12 Ce résultat est alors renvoyé à la 1e invocation. 13 Celle-ci achève alors sa branche «sinon» en assignant à S(3) la valeur n+m = 3+3 = 6. 14 Elle fournit donc comme résultat en sortie S(3)=6. 15 Ce résultat est donc la réponse au problème original. Somme_1ers_entiers Entrée: 2 Sortie: Somme_1ers_entiers Entrée: 1 Sortie: Somme_1ers_entiers Entrée: 0 Sortie: Somme_1ers_entiers Entrée: Sortie: 3 1 S(3) < S(2) < S(1) < => S(3) = 6

9 Observation importante
Certaines fonctions calculables sous une forme récursive peuvent aussi bien être calculées de façon non-récursive Par exemple, la somme des n premiers entiers : S(n+1) = (n+1) + S(n) peut aussi bien être calculée de façon itérative plutôt que récursive S(n) = ∑ i Il existe même parfois une formule analytique encore plus pratique S(n) = ½ n(n+1) Notons à ce stade que cet exemple nous a bien servi à illustrer le déroulement et la terminaison d’un algorithme récursif. Ceci dit, certaines fonctions qui peuvent être calculées de façon récursive pourraient tout aussi bien être calculées autrement. 1 Par exemple, la somme des n premiers entiers, que nous venons de calculer récursivement … 2 … pourrait tout aussi bien être calculée de façon itérative comme la somme des valeurs d’un compteur i variant de 1 à n. 3 Pour certaines de ces fonctions il peut même exister une formule de calcul analytique. Ainsi, quand on y réfléchit, la somme des n premiers entiers n’est rien d’autre que n fois la valeur moyenne des nombres allant de 1 à n, c.à.d. (n fois 1+n) divisé par 2 (n ou n+1 étant nécessairement divisible par 2). Un tel calcul analytique est souvent infiniment plus pratique que tout calcul itératif ou récursif 4 Pourquoi? ………………………………………………………………………………………………………….. ... parce qu’itération ou récursion sont nécessairement d’une complexité O(n) alors qu’une formule analytique a beaucoup de chance d’être d’une complexité O(1). n i=1 (pourquoi?)


Télécharger ppt "Information, Calcul, Communication"

Présentations similaires


Annonces Google