Quelles sont les principales différences techniques entre Prolog et miniKanren, en ce qui concerne la programmation logique? [fermé]


124

Quand je veux lire sur la programmation logique, je trébuche toujours sur deux façons «principales» de le faire de nos jours:

  • miniKanren , un minilangage introduit dans The Reasoned Schemer et populaire en ce moment grâce à core.logic .
  • Prolog , le premier "grand" langage de programmation logique.

Ce qui m'intéresse maintenant: quelles sont les principales différences techniques entre les deux? Sont-ils très similaires dans leur approche et leur mise en œuvre, ou adoptent-ils des approches complètement différentes de la programmation logique? De quelles branches des mathématiques proviennent-ils et quels sont les fondements théoriques?


3
Triste de voir cette question close. Comme le démontrent la réponse très convaincante et le grand nombre de votes positifs, c'est une question parfaitement utile. J'ai voté pour la réouverture ....
nealmcb

Les questions @nealmcb qui étaient autrefois sur le sujet avec de nombreux votes positifs pourraient ne plus l'être, le montant des votes positifs n'est pas ce qui le définit comme valide ou non.
Tiago Martins Peres 李大仁

Réponses:


281

Tout d'abord, permettez-moi de vous féliciter pour votre belle icône pw0n1e.

C'est une question délicate à répondre, en grande partie parce qu'il existe de nombreuses variantes de miniKanren et Prolog. miniKanren et Prolog sont vraiment des familles de langues, ce qui rend difficile la comparaison de leurs caractéristiques, voire de leur utilisation dans la pratique. Pour cette raison, veuillez prendre tout ce que je suis sur le point de dire avec prudence: si je dis que Prolog utilise la recherche en profondeur d'abord, sachez que de nombreuses implémentations de Prolog prennent en charge d'autres stratégies de recherche, et que des stratégies de recherche alternatives peuvent également être encodées à la méta -niveau de l'interprète. Pourtant, miniKanren et Prolog ont des philosophies de conception différentes et font des compromis différents.

Prolog est l'un des deux langages classiques de programmation en intelligence artificielle symbolique (l'autre langage classique étant Lisp). Prolog excelle dans la mise en œuvre de systèmes basés sur des règles symboliques dans lesquels la connaissance déclarative est codée en logique du premier ordre. Le langage est optimisé pour l'expressivité et l'efficacité pour ces types d'applications, parfois au détriment de la pureté logique. Par exemple, par défaut, Prolog n'utilise pas le "contrôle d'occurrence" dans l'unification. D'un point de vue mathématique / logique, cette version de l'unification est incorrecte. Cependant, la vérification des événements est coûteuse et, dans la plupart des cas, l'absence de vérification des événements n'est pas un problème. Il s'agit d'une décision de conception très pragmatique, tout comme l'utilisation par Prolog de la recherche en profondeur d'abord et l'utilisation de la coupe (!) pour contrôler le retour en arrière. Je suis sûr que ces décisions étaient absolument nécessaires lors de l'exécution sur le matériel des années 1970, et sont aujourd'hui très utiles pour travailler sur de gros problèmes et pour gérer d'énormes espaces de recherche (souvent infinis!).

Prolog prend en charge de nombreuses fonctionnalités "extra-logiques" ou "non logiques", y compris la coupe assertet la retractprojection de variables pour l'arithmétique en utilisantis, et ainsi de suite. Beaucoup de ces fonctionnalités facilitent l'expression de flux de contrôle complexes et la manipulation de la base de données globale de faits de Prolog. Une caractéristique très intéressante de Prolog est que le code Prolog est lui-même stocké dans la base de données globale des faits et peut être interrogé au moment de l'exécution. Cela rend facile d'écrire des méta-interprètes qui modifient le comportement du code Prolog en cours d'interprétation. Par exemple, il est possible d'encoder la recherche en largeur d'abord dans Prolog à l'aide d'un méta-interpréteur qui change l'ordre de recherche. C'est une technique extrêmement puissante qui n'est pas bien connue en dehors du monde Prolog. «The Art of Prolog» décrit cette technique en détail.

D'énormes efforts ont été déployés pour améliorer les implémentations de Prolog, dont la plupart sont basées sur la Warren Abstract Machine (WAM). Le WAM utilise un modèle à effets secondaires dans lequel des valeurs sont affectées de manière destructive à des variables logiques, ces effets secondaires étant annulés lors du retour en arrière. De nombreuses fonctionnalités peuvent être ajoutées à Prolog en étendant les instructions du WAM. Un inconvénient de cette approche est que les documents d'implémentation Prolog peuvent être difficiles à lire sans une solide compréhension du WAM. D'autre part, les implémenteurs de Prolog ont un modèle commun pour discuter des problèmes d'implémentation. De nombreuses recherches ont été menées en parallèle avec Prolog, aboutissant à Andorra Prolog dans les années 1990. Au moins certaines de ces idées se perpétuent dans Ciao Prolog. (Ciao Prolog regorge d'idées intéressantes, dont beaucoup vont bien au-delà du standard Prolog.)

Prolog a une belle syntaxe de style "pattern-matching" basée sur l'unification qui donne des programmes très succincts. Les prologues aiment leur syntaxe, tout comme les lispers aiment leurs s-expressions. Prolog dispose également d'une grande bibliothèque de prédicats standard. En raison de toute l'ingénierie nécessaire pour rendre le WAM rapide, il existe des implémentations Prolog très performantes et matures. En conséquence, de nombreux grands systèmes basés sur la connaissance ont été entièrement écrits en Prolog.

miniKanren a été conçu comme un langage de programmation logique minimal, avec une implémentation petite, facilement compréhensible et facilement piratable. miniKanren était à l'origine intégré à Scheme et a été porté dans des dizaines d'autres langues hôtes au cours de la dernière décennie. L'implémentation miniKanren la plus populaire est 'core.logic' dans Clojure, qui a maintenant de nombreuses extensions de type Prolog et un certain nombre d'optimisations. Récemment, le cœur de l'implémentation de miniKanren a été encore plus simplifié, résultant en un minuscule «micro noyau» appelé «microKanren». miniKanren peut alors être implémenté sur ce noyau microKanren. Le portage de microKanren ou miniKanren vers une nouvelle langue hôte est devenu un exercice standard pour les programmeurs qui apprennent miniKanren. Par conséquent,

Les implémentations standard de miniKanren et microKanren ne contiennent aucune mutation ou autres effets secondaires, à une seule exception: certaines versions de miniKanren utilisent l'égalité de pointeur pour la comparaison des variables logiques. Je considère cela comme un «effet bénin», bien que de nombreuses implémentations évitent même cet effet en passant un compteur à travers l'implémentation. Il n'y a pas non plus de base de données mondiale de faits. La philosophie d'implémentation de miniKanren est inspirée de la programmation fonctionnelle: les mutations et les effets doivent être évités, et toutes les constructions de langage doivent respecter la portée lexicale. Si vous regardez attentivement la mise en œuvre, vous pourriez même apercevoir quelques monades. L'implémentation de la recherche est basée sur la combinaison et la manipulation de flux paresseux, encore une fois sans utiliser de mutation. Ces choix d'implémentation conduisent à des compromis très différents de ceux de Prolog. Dans Prolog, la recherche de variables est en temps constant, mais le retour en arrière nécessite l'annulation des effets secondaires. Dans miniKanren, la recherche de variables est plus coûteuse, mais le retour en arrière est «gratuit». En fait, il n'y a pas de retour en arrière dans miniKanren, en raison de la façon dont les flux sont gérés.

Un aspect intéressant de l'implémentation miniKanren est que le code est intrinsèquement thread-safe et - au moins en théorie - trivialement parallélisable. Bien sûr, paralléliser le code sans le ralentir n'est pas anodin, étant donné que chaque thread ou processus doit avoir suffisamment de travail pour compenser la surcharge de la parallélisation. Pourtant, c'est un domaine de la mise en œuvre de miniKanren qui, je l'espère, recevra plus d'attention et d'expérimentation.

miniKanren utilise la vérification d'occurrence pour l'unification et utilise une recherche entrelacée complète au lieu d'une recherche en profondeur d'abord. La recherche entrelacée utilise plus de mémoire que la recherche en profondeur, mais peut trouver des réponses dans certains cas où la recherche en profondeur diverge / boucle pour toujours. miniKanren ne soutenir quelques opérateurs extra-logiques --- conda, conduet project, par exemple. condaet condupeut être utilisé pour simuler la coupe de Prolog, et projectpeut être utilisé pour obtenir la valeur associée à une variable logique.

La présence de conda, conduetproject--- et la possibilité de modifier facilement la stratégie de recherche --- permet aux programmeurs d'utiliser miniKanren comme un langage de type Prolog intégré. Cela est particulièrement vrai pour les utilisateurs de 'core.logic' de Clojure, qui comprend de nombreuses extensions de type Prolog. Cette utilisation «pragmatique» de miniKanren semble représenter la majorité de l'utilisation de miniKanren dans l'industrie. Les programmeurs qui souhaitent ajouter un système de raisonnement basé sur la connaissance à une application existante écrite en Clojure ou Python ou JavaScript ne sont généralement pas intéressés par la réécriture de l'ensemble de leur application dans Prolog. L'intégration d'un petit langage de programmation logique dans Clojure ou Python est beaucoup plus attrayante. Une implémentation Prolog intégrée fonctionnerait tout aussi bien à cette fin, vraisemblablement.

En plus de l'utilisation de miniKanren comme langage de programmation logique embarqué pragmatique similaire dans l'esprit de Prolog, miniKanren est utilisé pour la recherche en programmation «relationnelle». Autrement dit, en écrivant des programmes qui se comportent comme des relations mathématiques plutôt que comme des fonctions mathématiques. Par exemple, dans Scheme, la appendfonction peut ajouter deux listes, renvoyant une nouvelle liste: l'appel de fonction (append '(a b c) '(d e))renvoie la liste (a b c d e). Nous pouvons cependant également traiter appendcomme une relation à trois places plutôt que comme une fonction à deux arguments. L'appel (appendo '(a b c) '(d e) Z)associerait alors la variable logique Zà la liste (a b c d e). Bien sûr, les choses deviennent plus intéressantes lorsque nous plaçons des variables logiques dans d'autres positions. L'appel (appendo X '(d e) '(a b c d e))s'associe Xavec (a b c), tandis que l'appel(appendo X Y '(a b c d e))associés Xet Yavec des paires de listes qui, une fois ajoutées, sont égales à (a b c d e). Par exemple X= (a b)et Y= (c d e)sont une de ces paires de valeurs. On peut aussi écrire (appendo X Y Z), qui produira une infinité de triplets de listes X, Yet de Ztelle sorte que annexant Xà Yproduit Z.

Cette version relationnelle de appendpeut être facilement exprimée dans Prolog, et est en fait montrée dans de nombreux tutoriels Prolog. En pratique, les programmes Prolog plus complexes ont tendance à utiliser au moins quelques fonctionnalités extra-logiques, telles que couper, qui empêchent de traiter le programme résultant comme une relation. En revanche, miniKanren est explicitement conçu pour prendre en charge ce style de programmation relationnelle. Des versions plus récentes de miniKanren ont le soutien à la résolution de contrainte symbolique ( symbolo, numbero,absento, contraintes de diségalité, programmation logique nominale) pour faciliter l'écriture de programmes non triviaux sous forme de relations. En pratique, je n'utilise jamais aucune des fonctionnalités extra-logiques de miniKanren, et j'écris tous mes programmes miniKanren sous forme de relations. Les programmes relationnels les plus intéressants sont les interprètes relationnels pour un sous-ensemble de Scheme. Ces interprètes ont de nombreuses capacités intéressantes, telles que la génération d'un million de programmes Scheme qui évaluent à la liste (I love you), ou la génération triviale de quines (programmes qui s'évaluent eux-mêmes).

miniKanren fait un certain nombre de compromis pour permettre ce style de programmation relationnel, qui sont très différents des compromis que Prolog fait. Au fil du temps, miniKanren a ajouté plus de contraintes symboliques, devenant vraiment un langage de programmation de logique de contrainte orienté symboliquement. Dans de nombreux cas, ces contraintes symboliques permettent d'éviter d'utiliser des opérateurs extra-logiques comme conduet project. Dans d'autres cas, ces contraintes symboliques ne sont pas suffisantes. Un meilleur support des contraintes symboliques est un domaine actif de la recherche miniKanren, avec la question plus large de la manière d'écrire des programmes plus grands et plus complexes sous forme de relations.

En bref, miniKanren et Prolog ont des fonctionnalités, des implémentations et des utilisations intéressantes, et je pense que cela vaut la peine d'apprendre les idées des deux langues. Il existe également d'autres langages de programmation logique très intéressants, tels que Mercury, Curry et Gödel, chacun ayant sa propre vision de la programmation logique.

Je terminerai par quelques ressources miniKanren:

Le site Web principal de miniKanren: http://minikanren.org/

Une interview que j'ai donnée sur la programmation relationnelle et miniKanren, y compris une comparaison avec Prolog: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

À votre santé,

--Volonté


9
Excusez-moi si je suis époustouflé maintenant. Je viens de commencer les premières expériences de pensée en programmation logique et basée sur les contraintes et c'est la réponse que j'obtiens. :) En fait, comme vous l'avez mentionné dans votre réponse, aussi, j'avais une forte suspicion que le calcul logique était un candidat parfait à mettre en œuvre en tant que Monade; il s'avère qu'il s'agit plutôt d'un MonadPlus et qu'il existe effectivement une implémentation papier et de référence par votre collègue Friedman! Alors je lis ça et je joue avec maintenant, des pensées à ce sujet?
Profpatsch

4
Je soupçonne que vous trouverez également l'article et le code microKanren intéressants: webyrd.net/scheme-2013/papers/HemannMuKanren2013.pdf et github.com/jasonhemann/microKanren
William E. Byrd

5
De plus, j'organise un cours hebdomadaire miniKanren sur Google Hangouts, les dimanches à 15h, heure de l'Est (GMT -5: 00). Je tweet toujours le lien de mon compte Twitter @webyrd, si vous souhaitez nous rejoindre. Les précédents hangouts enregistrés sont à l' adresse
William E. Byrd

2
Je pense que c'est fondamentalement la même monade de recherche que dans l'article '05. Voir aussi 'Embedding Prolog in Haskell' de Seres and Spivey: spivey.oriel.ox.ac.uk/~mike/silvija/seres_haskell99.pdf
William E. Byrd

1
@ WilliamE.Byrd - Réponse géniale! En supposant qu'il y en ait une, quelle est la meilleure implémentation miniKanren qui peut être intégrée dans un programme C / C ++? De plus, miniKanren a-t-il la nature générative de Prolog? Autrement dit, la possibilité de laisser une variable dans une expression non fondée et le moteur de base générera toutes les valeurs possibles pour la variable non fondée étant donné les relations actuelles déclarées par le programme?
Robert Oschler

4

Réponse provisoire:

AFAIK, "The Reasoned Schemer" a introduit la programmation logique de base dans une syntaxe Scheme-y et un style de programmation fonctionnelle, en ajoutant notamment les objectifs constants "#u" (fail) et "#s" (suceeed) aux valeurs booléennes "#t "et" #f ". Il a utilisé la même approche de la programmation logique que Prolog: Unification et recherche de retour en arrière. Je verrai si j'ai le temps de récupérer ce livre sur mon étagère pendant le week-end. La branche des mathématiques est une logique de premier ordre de forme restreinte, dans ce cas les clauses de Horn et la résolution Unfication. Voir: Logique computationnelle: souvenirs du passé et défis pour l'avenir de John Alan Robinson et Les premières années de la programmation logique de Robert Kowalski pour un démarrage à froid.


3
Qu'est-ce que ces deux citations ont à voir avec Kanren ou MiniKanren?
false

2
Voir la dernière question: "De quelles branches des mathématiques proviennent-elles et quels sont les fondements théoriques?"
Frank Shearar
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.