• Aucun résultat trouvé

IFT3330 Initiation à l'intelligence artificielle TP2 Le système expert présenté à M. Philippe Langlais par Nicola Grenon GREN30077303 (grenonni) le lundi 20 novembre 2006

N/A
N/A
Protected

Academic year: 2022

Partager "IFT3330 Initiation à l'intelligence artificielle TP2 Le système expert présenté à M. Philippe Langlais par Nicola Grenon GREN30077303 (grenonni) le lundi 20 novembre 2006"

Copied!
1
0
0

Texte intégral

(1)

IFT3330

Initiation à l'intelligence artificielle

TP2

Le système expert

présenté à M. Philippe Langlais

par

Nicola Grenon

GREN30077303 (grenonni)

le lundi 20 novembre 2006

(2)

Résumé de tâche (Introduction)

Nous avions à produire un système de traitement des inférences ou, autrement dit, un système expert. Au moyen d'un fichier texte nous pouvons lui fournir une liste de règles ainsi qu'une liste de questions que le système pourra poser à l'utilisateur dans le cas de l'indécidabilité de la question originalement posée au système. La décidabilité de la fameuse question (et éventuellement la valeur obtenue) sont déterminées de deux manières distinctes, à savoir un chaînage avant ou un chaînage arrière. Finalement le système explique le processus suivi pour conclure en précisant l'arbre de preuves

Méthodologie employée

Pour écrire le programme, j'ai employé le langage Java, ce qui m'a permis de modulariser chacun des objets manipulés, à savoir les Fait, les Regle, la base d'information (KB) et la Question. Le gros avantage d'utiliser un langage objet dans ce contexte était de pouvoir déléguer l'analyse de la situation à l'élément comme tel. Par exemple, une fois qu'une «Question» est établie, il est simple de lui demander si la conjonction ou la disjonction des faits en son sein est réalisée ou pas d'un seul appel.

Je ne veux pas m'étendre sur les vertus des langages objets, mon point est plutôt de souligner qu'il est utile de pouvoir dégager tout ce qu'on peut du cœur du code où loge l'algorithme de travail. Il est déjà difficile de penser à tous les effets de bord qui peuvent survenir, alors pouvoir écrire un code presque en langage courrant permet de mieux s'y retrouver.

Ayant deux programmes à écrire, un pour le chaînage avant et l'autre pour le chaînage arrière, il était évident que beaucoup de code serait réutilisé. C'est pourquoi le fichier structures.java contient les classes pour les objets précédemment mentionnés, alors que forward.java et backward.java contiennent respectivement les méthodes main de chaque algorithme. Lorsqu'on approfondi un peu, on remarque que dans ces deux fichiers, la plus grande partie du code se répète. Bien sûr il aurait été possible de repousser dans une classe bibon des fonctions utilitaires et réduire la duplication de code, mais c'eut été très artificiel. La vraie solution, à mon avis, eut été d'avoir la flexibilité d'appeler les deux algorithmes à partir d'un même main. À ce moment tout

(3)

aurait pu être mis en commun à l'exception explicite de la fonction statique chainage qui définit la manière de procéder.

En ce qui a trait aux différentes classes développées, il est également intéressant de noter que grâce à la partie statique de celles-ci, il est bien plus facile de gérer une liste éliminant les doublons. En effet, pour les règles et les faits, j'ai pu ainsi m'assurer qu'on pouvait appeler en tout temps un constructeur statique qui lui se chargerait de localiser l'objet appelé ou d'en créer un réellement.

Notons finalement que la classe KB sert principalement de wrapper en liant les deux listes précédemment mentionnées à une série d'utilitaires. La façon de procéder pour implémenter le programme ne permettrait pas actuellement de gérer plusieurs bases de connaissances en même temps, par contre il serait possible de répondre à plusieurs questions simultanément puisque cet objet est purement dynamique.

Problèmes et solutions

Au niveau de la programmation comme telle, un problème important qui s'est posé est lié au besoin de retracer le chemin parcouru pour établir notre preuve et l'afficher une fois le chemin parcouru en éliminant l'affichage des preuves inutiles.

Comme j'en ai parlé dans la méthodologie, en ajoutant des fonctionnalités internes à l'objet Fait, en l'occurrence simplement un lien vers la règle d'inférence utilisée pour en déduire la valeur, on peut sans difficulté retracer le chemin parcouru le moment venu en parcourrant l'arbre.

Comme je l'ai mentionné un peu plus haut, un gros problème au niveau de l'implémentation était de pouvoir y voir clair au moment de l'écriture du code des deux algorithmes principaux. En ayant relégué à l'intérieur des objets traités le gros du travail, tout est plus simple. Par exemple, j'ai codé les Regle de telle sorte qu'elle aient la faculté de s'évaluer elle-même sur demande. C'est-à-dire que la règle ayant la liste des faits formant ses prémices, si elle est une conjonction ou une disjonction et un lien vers le fait pouvant être conclu, elle peut sur demande vérifier l'état de toutes les prémices et dire si oui ou non elle peut conclure (et éventuellement de quelle façon).

L'appel de la valeur d'un Fait a nécessité un petit peu de créativité. En effet, quelque chose qui par nature devait être vrai ou faux présentait mal comment fournir

(4)

une réponse du type «on ne sait pas encore» ou «indéterminé». Pour cela il aurait fallu soit utiliser un double test (.getDetermine et .getValeur), soit une valeur moins indicative comme un int. Or, en utilisant un objet Boolean, j'ai pu conserver la logique de la chose tout en ayant un troisième choix: «null», pour indiquer l'indétermination.

Quand est venu le temps de coder l'algorithme de chaînage avant, la structure employée se prêtait naturellement à cette idée. Le code fut donc simple et direct: on testes en boucle toutes les règles tant qu'il y en a une qui change d'état et qu'on a pas trouvé de solution. Or, pour le chaînage arrière, l'autodétermination des règles restait utile, mais il a fallu intégrer une nouvelle façon de penser pour se déplacer «à reculons». En ajoutant un vecteur frange qui contient toutes les règles déjà accédée (et indirectement la liste des faits rencontrés), on peut alors suivre l'idée du chaînage arrière sans trop de peine. Le fait que les faits continuent à conserver un lien vers la règle les ayant inféré permet de garder une méthode simple d'affichage subséquent de la preuve. Il a fallu toutefois faire attention de n'ajouter que des éléments neufs dans la frange par une fonction d'exclusion.

Le dernier problème notable rencontré concerne plus le format du problème que sa logique d'implémentation. En effet, le format des fichiers de base ne garantissait pas une cohérence au niveau de la syntaxe, il a donc fallu adapter le code en y ajoutant une multitude de précautions. [Il y a des espaces doubles à certains endroits, des lignes vides avec des espaces, etc.] Comme ce n'était pas le cas des fichiers plus simples, cela a entraîné une bonne dose de débogage suite à des problèmes mystérieux...

Discussion et idées (Conclusion)

Je finirai en disant que les processus de chaînage sont somme toute relativement simples, mais que leur implémentation correcte nécessite une large dose de patience afin d'en prévoir tous les aléas. Le gros du problème est (comme c'est souvent le cas) dans la préparation d'un bon plan d'attaque plus que dans le codage lui- même.

J'en ai parlé plus haut, mais selon moi un meilleur codage aurait pu être accompli n'eut été de l'obligation de séparer les codes en deux main distincts.

(5)

Les échantillons fournis ne m'ont pas permis de voir si dans les faits l'implémentation d'une ou l'autre des solutions était plus efficace. On pourrait toutefois ajouter quelques délais dans le déroulement du programme afin d'en faire une analyse comparative, mais selon moi ce serait sans grand intérêt sans avoir accès à une bien plus grande base de connaissance préalable. Je me risquerai toutefois à proposer que le chaînage avant serait ici plus efficace vue la manière dont ma structure est bâtie.

Ceci parce que le chaînage arrière m'a obligé à introduire plusieurs vérification d'existence ce que je n'avais pas à faire dans le cas contraire. Je parle ici de vérifier la présence d'un élément dans la frange déjà à l'étude. Une solution aurait pu être d'utiliser une pile de transfert pour stocker les règles à analyser, mais comme on retire les règles de ce tampon en fonction des faits que l'on veut prouver plutôt que par un ordre prioritaire, le problème eut été équivalent. En conclusion donc, le chaînage avant, en Java du moins et avec les structures autonomes définies comme je les ai écrites, me semble plus intéressant.

Finalement, il aurait pu être intéressant, en admettant que le calcul de la résolvabilité d'une règle ait un poids significatif, de prioriser les questions supplémentaires que le système pose à l'utilisateur. Par exemple, dans un chaînage arrière, en reconnaissant si l'élément se trouve seul comme manquant à une ou des règles...

Références

Documents relatifs

Donc: vote, électeur, carte d'identité, liste électorale, élection, liste des élections, liste d'émargement, option de vote....

Le logiciel affiche un message d'information, ferme la session et après quelques secondes réinitialise l'écran.. 

Le logiciel affiche un message d'information, ferme la session et après quelques secondes réinitialise l'écran.

Il n'est pas clair ici si en allant dans cette section si on quittera le site vers une page publicisée externe ou si on restera dans une sous-section du site

Il faut éviter tout ce qui peut rendre désagréable son utilisation pour un utilisateur qui n'est pas rémunéré, ne pas présumer d'aucune habileté en ce qui a trait au commerce

- Pour les boutons des catégories et des items, comme ils sont nombreux, nous avons à tout le moins utilisé un arrangement aligné, mais surtout avec de gros boutons facile à

- L'usager peut entrer autant de messages qu'il veut pour les responsables et ce, en tout temps (même au milieu d'une facture!). Ce qui est aussi vrai pour l'arrêt de

Il faut toutefois noter que pour la souris et le touchscreen, il faudrait prévoir soit un clavier numérique, soit ajouter à l'interface un petit clavier tel que celui-ci en haut ou