Prolog répond à une question sur des faits
Prolog est un langage de programmation logique : un programme y est une liste de faits, et l’exécuter revient à poser une question. Il sert à chercher des réponses dans des données sans écrire de boucle.
Un fichier peut dire que Tom est un parent d’Ann. Vous demandez ensuite : qui sont les enfants de Tom ? Prolog cherche seul. Dans le labo, le fichier facts.pl contient cinq faits de ce genre.
À la fin de cette leçon
Remarque
Je peux énoncer des faits et poser une question à Prolog.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Fait | une chose que le programme déclare vraie | parent(tom, ann). |
| Prédicat | le nom d’une relation, avant les parenthèses | parent |
| Atome | un nom fixe, qui commence par une minuscule | tom |
| Variable | un nom qui commence par une majuscule et attend une valeur | X |
| Requête | une question posée à Prolog | parent(tom, X) |
| Unification | chercher les valeurs qui rendent deux termes identiques |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un fait déclare qu’une chose est vraie
Un fait s’écrit parent(tom, ann). et se lit « Tom est un parent d’Ann ». Le mot parent est le prédicat, le nom de la relation.
Les mots tom et ann sont des atomes : des noms fixes, écrits en minuscules. Le point final est obligatoire. Prolog ne lit pas les faits comme des données à parcourir, mais comme des vérités sur lesquelles il peut raisonner.
Le fichier facts.pl du labo
% facts.pl : un fait dit que quelque chose est vrai.
parent(tom, ann).
parent(tom, ben).
parent(ann, cat).
parent(ben, dan).
parent(ben, eve).
colour(red).
colour(green).
colour(blue).
Ce que les outils affichent est en anglais
Dans ce labo, Prolog est le programme swipl. Tout ce qu’il écrit vient des fichiers et de lui : les noms des personnes, les mots true et false, les erreurs. Tout cela reste en anglais.
La commande docker exec prolog lance swipl dans la machine du labo. Le premier Run compte les lignes de facts.pl qui commencent par parent.
Combien de faits parent ?
docker exec prolog grep -c "^parent" facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une requête interroge les faits
Une requête est une question. Si elle ne contient que des atomes, la réponse est oui ou non : parent(ann, cat).
Si elle contient une variable, Prolog cherche les valeurs qui la rendent vraie : parent(X, ben) demande qui est un parent de Ben. Pour écrire la réponse, les Runs suivants passent le but à swipl avec -g. Avec -t halt, swipl s’arrête ensuite. Le fichier facts.pl est chargé en dernier.
Ann est-elle un parent de Cat ?
docker exec prolog swipl -q -g "(parent(ann, cat) -> write(yes) ; write(no)), nl" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Cat est-elle un parent d’Ann ?
docker exec prolog swipl -q -g "(parent(cat, ann) -> write(yes) ; write(no)), nl" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Qui est un parent de Ben ?
docker exec prolog swipl -q -g "forall(parent(X, ben), (write(X), nl))" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Qui sont les enfants de Ben ?
docker exec prolog swipl -q -g "forall(parent(ben, X), (write(X), nl))" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Tous les couples parent et enfant
docker exec prolog swipl -q -g "findall(X-Y, parent(X, Y), L), write(L), nl" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
L’unification essaie chaque fait dans l’ordre
Pour répondre, Prolog compare la requête à chaque fait, du premier au dernier. C’est l’unification.
Deux atomes s’unifient s’ils sont identiques. Une variable s’unifie avec n’importe quoi et prend cette valeur. Si la même variable apparaît deux fois, elle doit prendre la même valeur aux deux endroits.
Exemple travaillé : parent(X, ben)
| Fait essayé | Correspond ? | Valeur de X |
|---|---|---|
| parent(tom, ann) | Non : ann n’est pas ben | aucune |
| parent(tom, ben) | Oui | tom |
| parent(ann, cat) | Non : cat n’est pas ben | aucune |
| parent(ben, dan) | Non : dan n’est pas ben | aucune |
| parent(ben, eve) | Non : eve n’est pas ben | aucune |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Deux termes qui s’unifient
docker exec prolog swipl -q -g "f(A, b) = f(a, B), write(A-B), nl" -t haltAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Deux termes qui ne s’unifient pas
docker exec prolog swipl -q -g "(f(a) = g(a) -> write(oui) ; write(non)), nl" -t haltAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
La même variable deux fois
docker exec prolog swipl -q -g "findall(X, parent(X, X), L), write(L), nl" -t halt facts.plAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Erreur fréquente
Attention
Beaucoup de gens pensent que X est une variable de Python, qu’on range puis qu’on change. En Prolog, = ne range rien : il demande si deux termes peuvent être rendus identiques. Une variable qui a pris une valeur la garde pendant toute la réponse.
Pour aller plus loin
Dans le labo, ouvrez le terminal et tapez docker exec -it prolog swipl -q facts.pl. Le prompt de Prolog attend vos questions : tapez parent(tom, X). puis appuyez sur la touche point-virgule pour la réponse suivante.
Quittez avec halt.. Ajoutez ensuite deux faits à vous dans une copie du fichier et posez une question qui les utilise.