4. Récursion et recherche
4.1 Définir une base et une réduction
Une définition récursive comporte une ou plusieurs bases, résolues sans nouvel appel récursif, et une ou plusieurs règles récursives, qui ramènent le but à un sous-problème de même nature. Le nombre d’appels dépend de l’entrée et n’a pas à être fixé à l’avance.
La base peut être un fait, comme longueur([],0), ou une règle non récursive, comme le cas parent direct d’ancetre/2. Reconnaître un cas d’arrêt ne suffit pas : il faut que les appels progressent vers lui. Sur une liste finie, traiter la queue raccourcit l’entrée. Sur un graphe cyclique, suivre un arc ne garantit pas cette progression.
4.2 Recherche dans un graphe
Le graphe du cours possède les arcs 1→2, 2→3, 2→4, 3→4, 4→5 :
Code (prolog) · sélectionner pour copier
lien(1,2).
lien(2,3).
lien(2,4).
lien(3,4).
lien(4,5).
recherche(D,D).
recherche(D,A) :- lien(D,L), recherche(L,A).
Contrat : lien(D,L) indique un arc dirigé de D à L; recherche(D,A) signifie qu’A est accessible depuis D. La base accepte le trajet sans arc lorsque les deux nœuds sont identiques. Sinon, trouver un voisin L et résoudre le même problème depuis L.
Trace de recherche(1,5) :
| But courant | Opération | Sous-but de recherche suivant |
|---|---|---|
recherche(1,5) |
La base échoue; règle récursive et lien(1,2) |
recherche(2,5) |
recherche(2,5) |
Premier arc compatible : lien(2,3) |
recherche(3,5) |
recherche(3,5) |
lien(3,4) |
recherche(4,5) |
recherche(4,5) |
lien(4,5) |
recherche(5,5) |
recherche(5,5) |
Base, deux arguments identiques | Succès |
À chaque ligne, l’unification de lien(D,L) instancie aussi L dans recherche(L,A). Les occurrences de L de deux appels récursifs appartiennent toutefois à des appels différents : il faut raisonner comme si elles s’appelaient L1, L2, etc.
Le premier succès correspond à 1→2→3→4→5. En demandant une autre preuve, le moteur revient au choix non exploré lien(2,4), puis trouve 1→2→4→5. Le choix de la première route suit l’ordre des faits et le parcours en profondeur.
Le programme prouve l’accessibilité; il ne renvoie pas la liste des nœuds du trajet. Il ne mémorise pas non plus les nœuds visités. Sur un graphe cyclique, une branche peut boucler et empêcher d’atteindre une autre solution.
4.3 Relation d’ancêtre et convention des arguments
Pour suivre le PDF actuel, on adopte les contrats :
Code (text) · sélectionner pour copier
parent(P,X) : P est le parent de X.
ancetre(A,X) : A est un ancêtre de X, parent direct compris.
Code (prolog) · sélectionner pour copier
parent(pierre,sebastien).
parent(nathalie,sebastien).
parent(marie,nathalie).
parent(robert,nathalie).
ancetre(A,X) :- parent(A,X).
ancetre(A,X) :- parent(A,Y), ancetre(Y,X).
La première clause résout la relation pour un parent direct. La seconde dit : A est parent de Y et Y est ancêtre de X. Écrire une règle distincte pour une génération, puis deux, puis trois, etc., répéterait le même schéma et imposerait une limite artificielle. La récursion exprime ce schéma une fois.
Pour ancetre(A,sebastien), la base donne Pierre, puis Nathalie. La règle récursive trouve ensuite Marie, puisque Marie est parent de Nathalie et Nathalie parent de Sébastien, puis Robert. Dans cet exemple fini et cet ordre de clauses, les réponses sont donc Pierre, Nathalie, Marie, Robert. La base représente un lien de parenté : elle n’affirme pas que toute personne est son propre ancêtre.
Attention à l’ancienne version filmée. Vers 18:50, la vidéo définit au contraire parent(X,P) comme « P est parent de X » et attend les mêmes personnes à ancetre(sebastien,A). Elle conserve pourtant les faits écrits ci-dessus. Vers 20:10, elle donne :
Code (prolog) · sélectionner pour copier
ancetre(X,A) :- parent(X,A).
ancetre(X,A) :- parent(X,B), ancetre(B,A).
Avec ces faits, la requête filmée échoue : aucun fait ne commence par parent(sebastien,...). Les captures de la page 9 [accès au cours requis] et de la page 10 [accès au cours requis] documentent cette incohérence.
Deux conventions sont possibles, mais elles doivent rester cohérentes. Pour conserver la version enfant d’abord de la vidéo, il faudrait inverser tous les faits, par exemple parent(sebastien,pierre) et parent(nathalie,marie). Le programme principal de cette section conserve plutôt la version cohérente du PDF actuel. Un commentaire de contrat évite de confondre un problème d’ordre des arguments avec un problème de récursion.
Sur le forum, l’enseignante confirme qu’un prédicat déjà défini peut servir à en définir un autre : par exemple tante_oncle(X,Y) :- soeur_frere(X,P), parent(P,Y). avec des contrats compatibles. Une solution peut différer du corrigé; la vérifier reste nécessaire. Une restriction à l’examen sera précisée dans l’énoncé de la question.
Les clauses sont essayées dans l’ordre du maître. La première route vers 5 passe par 3; le retour arrière peut reprendre l’alternative 2→4. Le prédicat prouve l’accessibilité sans produire une liste de trajet.
Source : Ajout pédagogique du portail depuis le maître S07 du cours; aucune source brute diffusée. · 4. Récursion