====== Mini projet CHR ====== Ce projet a pour objectif de construire un moteur d'unification typée pour des termes de logique du premier ordre dans le langage CHR au dessus de Prolog. Il est à rendre pour le 28 février 2015 par mail à [[emmanuel.coquery@univ-lyon1.fr]]. ==== Ressources ==== On rappelle qu'il est possible d'utiliser l'interpréteur CHR en ligne disponible [[http://dtai.cs.kuleuven.be/CHR/webchr.shtml|ici]], ressources disponibles [[http://dtai.cs.kuleuven.be/CHR/|ici]]. [[http://www.doc.gold.ac.uk/~mas02gw/prolog_tutorial/prologpages/|Tutoriel Prolog]] ===== Termes et types ===== Les termes de logique, ainsi que les types, seront représentés par des termes Prolog manipulés en CHR. Un terme sera représenté comme suit (selon sa sorte): * une variable: ''var(//nom//)'' où ''//nom//'' sera le nom de la variable; * une constante ''const(//nom//)'' où nom sera le nom de la constante; * un symbole de fonction appliqué à des termes ''fonct(//symb//,//liste//)'' où ''//liste//'' = ''[//t1//, ... ,//tn//]'' est la liste Prolog des termes passés en arguments au symbole de fonction ''//symb//''. Un type sera; * soit ''t(//nom//)'' (types de primitifs de base, où ''//nom//'' peut être //e.g.// int, string, float, ...); * soit ''fleche(//liste//,//res//)'' où ''//liste//'' est une liste Prolog de types et ''//res//'' est un type. Les types primitifs seront ceux des variables, des constantes et des termes, alors que les types flèche seront ceux des symboles de fonction (''//liste//'' est la liste des types des arguments et ''//res//'' est le type résultat) Attention à ne pas confondre la notion de terme et de variable en Prolog (e.g. ''X'' est une variable en Prolog) avec les termes et les variables définis ci-dessus où la variable de logique //x// est représentée par ''var('x')'' ===== Unification simple ===== On commencera par implémenter l'[[http://en.wikipedia.org/wiki/Unification_%28computer_science%29#A_unification_algorithm|algorithme de Martelli et Montanari]] expliqué en cours. On pourra utiliser les contraintes CHR suivantes: * ''unif/2'' représentera une équation entre deux termes. * ''unif_list/2'' représentera deux listes de termes à unifier. On générera une contrainte ''unif/2'' pour chaque paire de termes à unifier. Par exemple unif_list([t1,t2,t3],[t4,t5,t6]) se simplifiera en 3 contraintes ''unif(t1,t4)'', ''unif(t2,t5)'' et ''unif(t3,t6)''. * ''eliminate/2'' représentera une substitution à appliquer sur les équations courantes. Remarque: cette contrainte est utilisée pour le codage de la règle //eliminate// de l'algorithme. La substitution ne doit pas s'appliquer sur l'équation d'où elle provient (dans la règle, la substitution est appliquée sur G et pas sur x=t) Voici, à titre d'exemple, le codage de deux règles: swap et delete % delete % supprime une équation si elle demande d'unifier les mêmes termes logiques unif(T,T) <=> true. % swap % T est un terme, var(Y) est une variable % la garde T \= var(Z) impose que T ne soit pas unifiable en Prolog avec var(Z), % ce qui impose que T ne soit pas une variable logique unif(T,var(Y)) <=> T \= var(Z) | unif(var(Y),T). **Exemple** La contrainte suivante: unif(funct (plus , [ var(x), funct(plus, [var(x), const(b)]) ] ), funct(plus, [ funct(plus, [const(a), var(y)]), var(z) ] ) ) doit se transformer en: unif(var(x), funct(plus, [const(a), var(y)]) ), unif(var(z), funct(plus, [funct(plus, [const(a), var(y)]), const(b) ] ) ) ===== Typage ===== Pour procéder au typage des termes, on se donne les contraintes CHR suivantes: * ''type_constante/2'': associe un type à une constante. On supposera que le type associé à une constante est un type primitif. * ''type_symb_fonction/2'': associe un type (fleche) à un symbole de fonction. * ''type/2'': associe un type primitif à un terme. * ''type_check/1'': demande à trouver et vérifier le type du terme logique passé en argument Définir des règles CHR pour le typage en vous appuyant sur les remarques suivantes: * un même terme logique ne peut pas avoir deux types différents * si un terme est une constante, son type est donné par la contrainte CHR ''type_constante'' * si un terme est une application d'un symbole de fonction //''f''// à des arguments ''//t1, ... , tn//'', son type peut être déduit du type de ''//f//''. De même, les types de ''//t1, ... , tn//'' sont imposés par le type de ''//f//'' * si un terme est une variable, son type est imposé par son utilisation **Exemple** Les contraintes suivantes: type_constante(a, t(int)), type_constante(b, t(int)), type_symb_fonction(plus, fleche([t(int),t(int)],t(int))), check( fonct(plus, [ fonct(plus, [ const(a), const(b) ] ), const(b) ]) ) Doivent se transformer en % contraintes inchangées type_constante(a, t(int)), type_constante(b, t(int)), type_symb_fonction(plus, fleche([t(int),t(int)],t(int))), % nouvelles contraintes type(fonct(plus, [ fonct(plus, [ const(a), const(b) ] ), const(b) ]), t(int)), type(fonct(plus, [ const(a), const(b) ] ), t(int)), type(const(a), t(int)), type(const(b), t(int)) **Exemple** Les contraintes suivantes: type_constante(a, t(string)), type_constante(b, t(int)), type_symb_fonction(plus, fleche([t(int),t(int)],t(int))), check( fonct(plus, [ const(a), const(b) ] ) ) Doivent se transformer en ''false'' **Exemple** Les contraintes suivantes: type_constante(a, t(int)), type_symb_fonction(plus, fleche([t(int),t(int)],t(int))), check( fonct(plus, [ fonct(plus, [ const(a), var(b) ] ), var(b) ]) ) Doivent se transformer en % contraintes inchangées type_constante(a, t(int)), type_symb_fonction(plus, fleche([t(int),t(int)],t(int))), % nouvelles contraintes type(fonct(plus, [ fonct(plus, [ const(a), const(b) ] ), const(b) ]), t(int)), type(fonct(plus, [ const(a), const(b) ] ), t(int)), type(const(a), t(int)), type(var(b), t(int)) **Exemple** Les contraintes suivantes: type_symb_fonction(concat, fleche([t(string),t(string)],t(string))), type_symb_fonction(i2s, fleche([t(int)],t(string))), check( fonct(concat, [ var(x), fonct(i2s, [var(x)]) ] ) ) Doivent se transformer en ''false'' ===== Unification typée ===== Combiner les deux solveurs précédents pour qu'une unification qui rend égaux deux termes de types différents échoue.