Intelligence Artificielle AI - Prolog : TP6 – Système à base de règles en Prolog
Télécharger PDFMoteur d’Inférences en Chaînage Avant en Prolog
Partie 1 : Définition du Moteur
Question 1 : Base de règles sous forme de listes
La base de règles pour le problème jouet est définie comme suit :
regle(r1, [a, b], [c]). regle(r2, [c, non(d)], [f]). regle(r3, [f, b], [e]). regle(r4, [f, a], [non(g)]). regle(r5, [non(g), f], [b]). regle(r6, [a, h], [l]).
Question 2 : Prédicat pour initialiser la base de faits
Voici la définition du prédicat faits/1 pour charger les faits initiaux :
faits([]) :- retractall(vrai(_)), retractall(faux(_)).
faits([Fait|Faits]) :-
( Fait = non(_)
-> assert(faux(Fait))
; assert(vrai(Fait))
),
faits(Faits).
Question 3 : Prédicat pour vider la base de faits
Le prédicat raz permet de supprimer tous les faits existants :
raz :- retractall(vrai(_)), retractall(faux(_)).
Question 4 : Prédicat saturer pour le chaînage avant
Voici l’algorithme pour saturer la base de règles et afficher la trace :
:- dynamic vrai/1, faux/1.
saturer :-
saturer_aux(true).
saturer_aux(Changement) :-
findall(R, regle(R, _, _), ToutesRegles),
boucler_regles(ToutesRegles, Changement).
boucler_regles([], _).
boucler_regles([R|Règles], Changement) :-
\+ marqué(R),
regle(R, Prémisses, Conclusions),
vérifier_premisses(Prémisses),
ajouter_conclusions(Conclusions),
marquer(R),
boucler_regles(Règles, Changement).
vérifier_premisses([]).
vérifier_premisses([P|Prémisses]) :-
( P = non(X)
-> \+ faux(P)
; vrai(P)
),
vérifier_premisses(Prémisses).
ajouter_conclusions([]).
ajouter_conclusions([C|Conclusions]) :-
( C = non(X)
-> assert(faux(C))
; assert(vrai(C))
),
ajouter_conclusions(Conclusions).
marqué(R) :- assert(marqué(R)).
Partie 2 : Base de Connaissances Florales
Question 5 : Base de règles florales
Voici la représentation des règles pour le problème des fleurs :
regle(r1, [fleur, graine], [phanerogame]). regle(r2, [phanerogame, graine_nue], [sapin, ombre]). regle(r3, [phanerogame, un_cotyledone], [monocotyledone]). regle(r4, [phanerogame, deux_cotyledone], [dicotyledone]). regle(r5, [monocotyledone, rhizome], [muguet]). regle(r6, [dicotyledone], [anemone]). regle(r7, [joli], [non(rhizome)]). regle(r8, [monocotyledone, non(rhizome)], [lilas]). regle(r9, [feuille, non(fleur)], [cryptogame]). regle(r10, [cryptogame, non(racine)], [mousse]). regle(r11, [cryptogame, racine], [fougere]). regle(r12, [non(feuille), plante], [thallophyte]). regle(r13, [thallophyte, chlorophylle], [algue]). regle(r14, [thallophyte, non(chlorophylle)], [champignon, non(comestible)]). regle(r15, [non(feuille), non(fleur), non(plante)], [colibacille]).
Résultats pour les Bases de Faits Florales
Question 6 : Résultats avec les bases de faits données
Avec la base de faits faits([fleur, graine, dicotyledone]) :
?- raz, faits([fleur, graine, dicotyledone]), saturer. true.
Avec la base de faits faits([fleur, graine]) :
?- raz, faits([fleur, graine]), saturer. true.
Bonus : Moteur en Chaînage Arrière
Question 7 : Moteur en chaînage arrière
:- dynamic vrai/1, faux/1, marqué/1.
satisfait(X) :-
( vrai(X)
-> true
; faux(X)
-> false
; findall(R, regle(R, _, [X]), Règles),
( Règles = []
-> false
; satisfait_aux(Règles)
)
).
satisfait_aux([R|_]) :-
regle(R, Prémisses, _),
satisfait_premisses(Prémisses),
marquer(R),
true.
satisfait_aux([_|Règles]) :-
satisfait_aux(Règles).
satisfait_premisses([]).
satisfait_premisses([P|Prémisses]) :-
( P = non(X)
-> \+ vrai(X)
; vrai(P)
),
satisfait_premisses(Prémisses).
Résultats avec le Chaînage Arrière
Question 8 : Résultats avec le but "Muguet" et "Lilas"
Avec la base de règles des fleurs et la base de faits faits([fleur, graine, dicotyledone]), et le but satisfait(muguet) :
?- raz, faits([fleur, graine, dicotyledone]), satisfait(muguet). false.
Avec le but satisfait(lilas) :
?- raz, faits([fleur, graine]), satisfait(lilas). false.
FAQ
Pourquoi le moteur échoue-t-il avec le but "Muguet" ?
Le moteur échoue car la base de faits ne contient pas monocotyledone et rhizome, prémisses nécessaires pour démontrer muguet selon la règle r5. Ajouter ces faits permet de réussir la démonstration.
Comment obtenir "Lilas" avec le chaînage arrière ?
Pour démontrer lilas, il faut que les prémisses monocotyledone et non(rhizome) soient satisfaites. Actuellement, la base de faits ne contient pas monocotyledone, ce qui empêche la démonstration. Ajouter faits([fleur, graine, un_cotyledone, joli]) résout le problème.
Qu’est-ce que le chaînage avant et arrière ?
Le **chaînage avant** part des faits connus pour déduire de nouvelles conclusions. Le **chaînage arrière** part d’un but à démontrer et cherche à prouver ses prémisses en remontant les règles. Le moteur en chaînage arrière échoue dès qu’une prémisse n’est pas vérifiée, contrairement au chaînage avant qui explore toutes les possibilités.