Classes : 2 ING 01, 02, 03

Année universitaire : 2015/2016, 1er semestre
Préparé par : enseignant TD & TP : Nefissa KHIARI

Intelligence Artificielle et Systèmes Experts

TP n°1 : Prise en main de SWI-Prolog

Introduction
Prolog est l’un des principaux langages de programmation logique. A la différence de la
programmation impérative où le programme se présente comme une suite d’instructions (C, C++,
Java,…), Prolog est un langage de programmation déclarative où le programme se présente sous la
forme d’un certain nombre d’« affirmations sur le monde » formant une base de connaissances (sorte
de base de données déductive).
L’utilisation du programme se fera alors en interrogeant cette base de connaissances. Prolog
dispose d’un puissant « moteur d’inférences » lui permettant de déduire certains faits à partir de ceux
que contient sa base de connaissances.
Il existe plusieurs outils permettant de programmer en Prolog dont certains sont gratuits et d’autres
sont payants. Nous allons travailler avec SWI-Prolog qui est un outil gratuit disposant d’un débuggeur
graphique ainsi que de plusieurs solveurs de contraintes.
Ce premier TP a pour objectif de se familiariser avec le langage Prolog à travers une approche
expérimentale.

1. Installation et exécution
Commencer par installer prolog à partir du site http://www.swi-prolog.org/download/stable en
cliquant sur le lien SWI-Prolog 7.2.3 for Windows XP/Vista/7/8.
Pour éditer un programme en Prolog, il est possible d’utiliser l’éditeur Prolog en allant dans le
menu File -> Edit ou bien à partir de n’importe quel éditeur de texte. Le programme doit être ensuite
sauvegardé dans un fichier avec l’extension qui a été associée au compilateur SWI-Prolog au moment
de l’installation (par défaut .pl).
Pour exécuter un programme, il existe plusieurs manières :
-

-

double cliquer sur le fichier .pl (ce qui lance l’interpréteur Prolog)
o la compilation peut se faire à partir du menu de l’éditeur Prolog depuis Compile ->
Make.
lancer l’interpréteur Prolog et charger le programme :
o consult (chemin_du_programme). % en remplaçant les « \ » par des « / »
o [chemin_du_programme].
o La compilation peut se faire après modification du programme à partir du menu de
l’interpréteur Prolog depuis File -> Reload modified files.

Prolog indique alors qu’il a chargé et compilé le fichier et présente son invite de commande.
Welcome to SWI-Prolog (Multi-threaded, 32 bits, Version 7.2.3)
1

Requêtes A partir de l’invite de commande. enfant(adam).pl puis ouvrir.enfant(cyrine). Un tel fichier s’appelle base de faits parce qu’il regroupe des faits que l’on déclare être vrais. 1 ?% chemin_programme compiled 0. En cas de problème.00 sec. Si tout va bien Prolog doit répondre : true. lina). cyrine). entrer le code suivant en respectant la casse (Il ne faut pas mettre de majuscules en début des noms. En cas d’erreur de syntaxe. vérifier la syntaxe.enfant(lina). maitresse(maya).apropos(Word). Base de faits Dans un fichier texte. Sauvegarder en .swi-prolog.org for details. 11 clauses 2. et revenir à l’invite de commande. donneJouets(anas. Tester la requête : ?. donneJouets(adam. Entrer : ?. C’est l’hypothèse du monde clos. fille(lina).Copyright (c) 1990-2015 University of Amsterdam. and you are welcome to redistribute it under certain conditions. lina). 3.help(Topic). VU Amsterdam SWI-Prolog comes with ABSOLUTELY NO WARRANTY. Nous verrons pourquoi par la suite) et en terminant chaque ligne par un point. For help. en particulier l’existence de point à la fin de chaque fait et requête et l’inexistence de majuscule en début des noms. donneJouets(lina. celle-ci sera signalée à la première ligne de l’invite de commande. 2 . enfant(cyrine). il est possible de poser des questions appelées « requêtes » dans la terminologie Prolog. This is free software. or ?. Que répond Prolog ? On constate donc que Prolog considère que tout ce qu’il ne peut pas déduire de la base de faits est faux (même si à nos yeux cela semble vrai). enfant(anas). donneJouets(cyrine. use ?. anas). Tester les autres faits de la base de connaissance. Please visit http://www.

et revient à l’invite de commande. Si on veut voir les alternatives restantes. . X = anas . Prolog a identifié X comme étant une variable. En ayant trouvé une. . mais comme il a constaté qu’il pourrait y avoir d’autre s possibilités. il l’affiche. .fille(X).chat(minou). 4. . 3. r. mais au fait qu’il commence par une majuscule. Ceci n’est pas dû à son nom. (ou n. ou c) et Prolog arrêtera sa recherche. barre d’espacement ou tabulation) et Prolog continuera sa recherche en faisant « un retour arrière » (ou backtracking) au point 2 jusqu’à ce qu’il n’y ait plus d’autre solution. 2. Relevons que les « propriétés » définies dans la base de faits s’appellent des prédicats. On aurait tout aussi bien pu entrer Var. 5. Essayer maintenant de répondre aux questions suivantes : - A qui Adam donne ses jouets ? - Qui donne ses jouets à Lina ? 3 . taper . taper : ?. X = cyrine. Il existe alors une différence entre la situation où on se trouve face à une « propriété » connue mais dont on ne sait pas si elle est vraie ou fausse. HELLO. . il attend l’avis de l’utilisateur (notez l’absence de point après cette première réponse ). Lina ! Maintenant. Taper un espace ou un « . et la situation où on se trouve face à une « propriété » inconnue. Prolog répond : X = adam Et ne revient pas immédiatement à l’invite de commande. taper entrée (ou a. . 4. Ce dialogue pourrait se lire : – Connais-tu un X qui soit une fille? – Oui. . .ou Linda. Si cette information suffit. Prolog répond : X = lina. Que s’est-il passé ? 1. Prolog affiche : X = adam . Il a cherché une affectation de la variable X permettant de vérifier l’affirmation enfant(X). On comprend maintenant pourquoi il ne fallait pas mettre de majuscules aux noms propres. Variables Tapez la requête : ?. .Tester encore : ?. » jusqu’à ce que Prolog revienne à l’invite de commande.enfant(X).

mais aussi Anas et Lina. Conjonction Nous nous sommes pour l’instant limités à satisfaire un seul but à la fois.pl. enfant(cyrine). il nous manque un ingrédient essentiel : les règles. cela nous donne quelque chose comme : X est triste si X donne ses jouets à Y et Y donne ses jouets à Z . cyrine). Prolog vous répondra quelque chose comme Call: (8) triste(_G478) ? . Dans le cas particulier. Entrer : ?. triste(X). Prolog essaiera de tous les satisfaire simultanément. 7. triste(X) :. donneJouets(anas. donneJouets(lina. À la suite des lignes existantes dans le fichier .5.donneJouets(X. ce qui signifie qu’il a projet d’appeler le prédicat triste avec une variable comme argument. Débogage Pour comprendre ce qui se passe.enfant(X). Règles Jusque là. fille(lina). Ainsi : ?. lina). Si tout se passe normalement. mais en demandant en plus une trace d’exécution. Enregistrez votre fichier. Prolog ressemble à une sorte de base de données. mais en moins pratique et plus lent ! Pour en faire un langage de programmation.) est vraie si la partie droite est vérifiée. lina). À noter que le nouveau prédicat triste est cette fois défini par une règle et non par un fait. Stockez cette information dans un coin de votre tête. . 6. et : ?. ?. donneJouets(X. Ceci va donc lancer la requête triste(X). ce qui est bien légitime. enfant(adam). La dernière ligne est une règle et signifie que la partie gauche (avant le :. Prolog vous proposera bien plus de réponses que prévu : non seulement Adam et Cyrine sont tristes. donneJouets(cyrine. nous y reviendrons plus tard). relancez Prolog sur cette nouvelle base et essayez de l’interroger sur l’existence d’un enfant triste (Si vous êtes attentifs. enfant(anas). mais on peut aussi tenter de les combiner : si l’on entre plusieurs buts séparés par des virgules. nous allons utiliser les capacités de débogage de SWI-Prolog. vous remarquerez un avertissement à la compilation de cette nouvelle base.Y). enfant(X). Pour continuer l’exécution : tapez la barre 4 . Nous donne heureusement false. donneJouets(adam.maitresse(X).trace. cyrine). rajoutez une ligne pour obtenir le résultat suivant : maitresse(maya). donneJouets(Y.triste(X).Z). anas). Nous donne bien le X = adam que nous espérions.

tapez simplement nodebug (ou noguitracer dans le cas du deboggeur graphique).Z). SWI-Prolog (dans sa version pour Windows seulement) propose aussi une version graphique du débogueur. parent(X. vous pouvez donc corriger la dernière ligne de votre programme pour exiger que les valeurs de X et Z soient différentes : triste(X) :. Une fenêtre apparaît vous permettant de suivre l’exécution de votre programme. Dans votre éditeur. Testez votre nouvelle base : les enfants qui se partagent les jouets ne sont plus tristes. Si vous désirez retrouver votre invite de commande habituelle. 9.).Y) fils(X.donneJouets(X. Recharger de nouveau ce programme. jusqu’à la fin de l’exécution. puis relancez la commande ci-dessus. 2. X\=Z. donneJouets(Y. Exercice Arbre généalogique 1. Rajouter une règle signifiant que deux enfants partageant leurs jouets avec un tierce enfant sont jaloux l’un de l’autre. Continuez à suivre pas à pas l’exécution de votre programme en frappant la barre d’espacement chaque fois que nécessaire.Y) : X est père de Y.Y) 5 . mais rien n’empêche que ces variables prennent la même valeur (comme d’ailleurs dans les autres langages de programmation). De manière générale. Prolog restera en mode debug.Y) : X est prédicat de Y. Correction du programme Notre problème revient au fait que nous avons employé des noms de variables différents pour X et Z. des règles pour définir les prédicats suivants : a) b) enfant(X. Ecrire une série de faits définissant les prédicats homme. on convient que prédicat(X. Dans le menu “Debug” choisissez “Graphical Debugger” (ou tapez simplement guitracer. femme(X) : X est une femme.d’espacement (ou enter). femme et parent pour modéliser cet arbre.Y). Avec : homme(X) : X est un homme.Y) : X est un parent (père ou mère) de Y. pere(X. Avezvous maintenant compris la faute dans notre programme ? 8.Y) : X est mere de Y. ce moment-là. Rajouter à votre base. mere(X.

Y) 3.Y) petit_enfant(X. Introduire une règle récursive pour définir le prédicat : ancetre(X.c) d) e) f) g) h) i) j) k) l) m) fille(X.Y) oncle(X.Y) grand_mere(X. Ceci peut provenir de plusieurs raisons : 1.Y) frere(X. peu importe la valeur de cette variable.Y).Y) grand_pere(X. Erreur de raisonnement en définissant une variable qui ne servira pas plus loin.pere(X.Variable anonyme On veut écrire un prédicat traduisant le fait d’être un père sans s’intéresser à l’enfant.Y) grand_parent(X. cette règle génère l’avertissement suivant : Warning: chemin_du_programme : numero_de_ligne : Singleton variables: [Y] Le fait de ne pas générer d’erreur montre que Prolog accepte de définir deux prédicats de même nom mais de signatures différentes.Y) petite_fille(X.Y) sœur(X.Y) petit_fils(X. Besoin d’une variable pour des raisons syntaxiques. Ce qui est le cas ici. 3. pere(X) :. 6 . Faute de frappe dans le nom d’une variable. 2. 5. Par exemple : a) b) c) d) e) f) Quels sont les frères d’Anas ? Quels sont les sœurs de Mahdi ? Quels sont les enfants de Nadia ? Selima a-t-elle des neveux ? Quels sont les oncles de Sondos ? quelles sont les personnes qui sont des grand-parents ? 4. L’avertissement signifie que la variable Y n’apparaît qu’une seule fois dans la dernière règle. Tester vos règles au fur et à mesure.Y) : X est l’ancêtre de Y s’il est parent de Y ou le parent de l’un de ses ancêtres.Y) tante(X. Tester la règle en répondant par exemple aux questions : a) Saleh est-il un ancêtre de Sondos ? b) Quels sont les arrières-grand-parents de Baligh ? 10. En rechargeant le programme.

répondra true dès qu’on trouve deux personnes – n’importe lesquelles – dont l’une est le père de l’autre. En rechargeant le programme.X). il est d’usage de signaler à Prolog que la variable en question n’est là que comme « placeholder » en utilisant la variable anonyme.pere(X. Par exemple : ?._). alors que : ?.Si l’on est sûr d’être au 3ème cas._). Remarque chaque occurrence de la variable anonyme est indépendante.pere(_. qui se résume à un soulignement (_).pere(X. ce qui devra retourner un false . 7 . le warning disparait. cherchera une personne qui est son propre père. La règle précédente devient alors pere(X) :.