Was sind die wichtigsten technischen Unterschiede zwischen Prolog und miniKanren in Bezug auf die Logikprogrammierung? [geschlossen]


122

Wenn ich mich über Logikprogrammierung informieren möchte, stolpere ich heutzutage immer über zwei "Hauptmethoden":

Was mich jetzt interessiert: Was sind die wichtigsten technischen Unterschiede zwischen den beiden? Sind sie in Ansatz und Implementierung sehr ähnlich oder verfolgen sie völlig unterschiedliche Ansätze bei der Logikprogrammierung? Aus welchen Bereichen der Mathematik stammen sie und auf welchen theoretischen Grundlagen?


3
Traurig zu sehen, dass diese Frage geschlossen ist. Wie die sehr überzeugende Antwort und die große Anzahl von Gegenstimmen zeigen, ist dies eine äußerst nützliche Frage. Ich habe für die Wiedereröffnung gestimmt ...
Nealmcb

@nealmcb Fragen, die einmal mit vielen Upvotes zum Thema gehörten, sind möglicherweise nicht mehr vorhanden. Die Anzahl der Upvotes ist nicht das, was sie als gültig oder nicht definiert definiert.
Tiago Martins Peres 24

Antworten:


280

Gestatten Sie mir zunächst, Ihnen ein Kompliment für Ihr feines pw0n1e-Symbol zu machen.

Diese Frage ist schwierig zu beantworten, vor allem, weil es so viele Varianten von miniKanren und Prolog gibt. miniKanren und Prolog sind wirklich Sprachfamilien, was es schwierig macht, ihre Funktionen oder sogar ihre Verwendung in der Praxis zu vergleichen. Aus diesem Grund nehmen Sie bitte alles, was ich sagen möchte, mit Vorsicht: Wenn ich sage, dass Prolog die Tiefensuche verwendet, beachten Sie, dass viele Prolog-Implementierungen andere Suchstrategien unterstützen und dass alternative Suchstrategien auch im Meta codiert werden können -Dolmetscherebene. Trotzdem haben miniKanren und Prolog unterschiedliche Designphilosophien und machen unterschiedliche Kompromisse.

Prolog ist eine der beiden klassischen Sprachen für die symbolische Programmierung künstlicher Intelligenz (die andere klassische Sprache ist Lisp). Prolog zeichnet sich durch die Implementierung symbolischer regelbasierter Systeme aus, in denen deklaratives Wissen in Logik erster Ordnung codiert ist. Die Sprache ist hinsichtlich Ausdruckskraft und Effizienz für diese Art von Anwendungen optimiert, manchmal auf Kosten der logischen Reinheit. Beispielsweise verwendet Prolog standardmäßig nicht die "Auftrittsprüfung" in der Vereinigung. Aus mathematischer / logischer Sicht ist diese Version der Vereinigung falsch. Die Ereignisprüfung ist jedoch teuer, und in den meisten Fällen ist das Fehlen der Ereignisprüfung kein Problem. Dies ist eine sehr pragmatische Entwurfsentscheidung, ebenso wie Prologs Verwendung der Tiefensuche und die Verwendung des Schnitts (!), um das Backtracking zu steuern. Ich bin mir sicher, dass diese Entscheidungen auf der Hardware der 1970er Jahre absolut notwendig waren und heute sehr nützlich sind, wenn Sie an großen Problemen arbeiten und große (oft unendliche!) Suchräume bearbeiten.

Prolog unterstützt viele "extralogische" oder "nicht logische" Funktionen, einschließlich Ausschneiden assertund retractProjektion von Variablen für die arithmetische Verwendungis, und so weiter. Viele dieser Funktionen erleichtern es, komplexe Kontrollabläufe auszudrücken und die globale Datenbank von Prolog mit Fakten zu manipulieren. Ein sehr interessantes Merkmal von Prolog ist, dass der Prolog-Code selbst in der globalen Datenbank der Fakten gespeichert ist und zur Laufzeit abgefragt werden kann. Dies macht es trivial, Meta-Interpreter zu schreiben, die das Verhalten des zu interpretierenden Prolog-Codes ändern. Beispielsweise ist es möglich, die Breitensuche in Prolog mit einem Meta-Interpreter zu codieren, der die Suchreihenfolge ändert. Dies ist eine äußerst leistungsfähige Technik, die außerhalb der Prolog-Welt nicht bekannt ist. 'The Art of Prolog' beschreibt diese Technik im Detail.

Es wurden enorme Anstrengungen unternommen, um die Prolog-Implementierungen zu verbessern, von denen die meisten auf der Warren Abstract Machine (WAM) basieren. Das WAM verwendet ein Nebenwirkungsmodell, bei dem logischen Variablen Werte destruktiv zugewiesen werden, wobei diese Nebeneffekte beim Zurückverfolgen rückgängig gemacht werden. Viele Funktionen können zu Prolog hinzugefügt werden, indem die Anweisungen des WAM erweitert werden. Ein Nachteil dieses Ansatzes besteht darin, dass Prolog-Implementierungspapiere ohne ein solides Verständnis des WAM schwer zu lesen sein können. Auf der anderen Seite haben Prolog-Implementierer ein gemeinsames Modell für die Erörterung von Implementierungsproblemen. Parallel zum Prolog wurde viel geforscht, was in den 1990er Jahren in Andorra Prolog gipfelte. Zumindest einige dieser Ideen leben in Ciao Prolog weiter. (Ciao Prolog steckt voller interessanter Ideen, von denen viele weit über den Prolog-Standard hinausgehen.)

Prolog hat eine schöne vereinheitlichungsbasierte Syntax im "Pattern Matching" -Stil, die zu sehr prägnanten Programmen führt. Prologen lieben ihre Syntax, genau wie Lisper ihre S-Ausdrücke lieben. Prolog hat auch eine große Bibliothek von Standardprädikaten. Aufgrund all der Technik, mit der das WAM schnell gemacht wurde, gibt es sehr leistungsfähige und ausgereifte Prolog-Implementierungen. Infolgedessen wurden viele große wissensbasierte Systeme vollständig in Prolog geschrieben.

miniKanren wurde als minimale logische Programmiersprache mit einer kleinen, leicht verständlichen und leicht hackbaren Implementierung entwickelt. miniKanren war ursprünglich in Scheme eingebettet und wurde in den letzten zehn Jahren auf Dutzende anderer Hostsprachen portiert. Die beliebteste miniKanren-Implementierung ist 'core.logic' in Clojure, das jetzt viele Prolog-ähnliche Erweiterungen und eine Reihe von Optimierungen enthält. Kürzlich wurde der Kern der miniKanren-Implementierung noch weiter vereinfacht, was zu einem winzigen "Mikrokernel" namens "microKanren" führte. Auf diesem microKanren-Kern kann dann miniKanren implementiert werden. Das Portieren von microKanren oder miniKanren in eine neue Hostsprache ist zu einer Standardübung für Programmierer geworden, die miniKanren lernen. Als Ergebnis,

Die Standardimplementierungen von miniKanren und microKanren enthalten keine Mutation oder andere Nebenwirkungen, mit einer einzigen Ausnahme: Einige Versionen von miniKanren verwenden die Zeigergleichheit zum Vergleich von Logikvariablen. Ich halte dies für einen "harmlosen Effekt", obwohl viele Implementierungen selbst diesen Effekt vermeiden, indem sie einen Zähler durch die Implementierung führen. Es gibt auch keine globale Faktendatenbank. Die Implementierungsphilosophie von miniKanren ist von der funktionalen Programmierung inspiriert: Mutationen und Effekte sollten vermieden werden, und alle Sprachkonstrukte sollten den lexikalischen Umfang berücksichtigen. Wenn Sie sich die Implementierung genau ansehen, können Sie sogar ein paar Monaden entdecken. Die Suchimplementierung basiert auf dem Kombinieren und Bearbeiten von Lazy Streams, wiederum ohne Mutation. Diese Implementierungsentscheidungen führen zu sehr unterschiedlichen Kompromissen als bei Prolog. In Prolog ist die variable Suche eine konstante Zeit, aber das Zurückverfolgen erfordert das Rückgängigmachen von Nebenwirkungen. In miniKanren ist die variable Suche teurer, aber das Backtracking ist "kostenlos". Tatsächlich gibt es in miniKanren kein Backtracking, da die Streams so behandelt werden.

Ein interessanter Aspekt der miniKanren-Implementierung ist, dass der Code von Natur aus threadsicher und - zumindest theoretisch - trivial parallelisierbar ist. Natürlich ist es nicht trivial, den Code zu parallelisieren, ohne ihn langsamer zu machen, da jedem Thread oder Prozess genügend Arbeit gegeben werden muss, um den Aufwand für die Parallelisierung auszugleichen. Dies ist jedoch ein Bereich der Implementierung von miniKanren, von dem ich hoffe, dass er mehr Aufmerksamkeit und Experimente erhält.

miniKanren verwendet die Ereignisprüfung zur Vereinheitlichung und verwendet anstelle der Tiefensuche eine vollständige Verschachtelungssuche. Die Interleaving-Suche benötigt mehr Speicher als die Tiefensuche, kann jedoch in einigen Fällen Antworten finden, in denen die Tiefensuche für immer divergiert / wiederholt wird. miniKanren tut unterstützen ein paar extra-logische Operatoren --- conda, conduund projectzum Beispiel. condaund condukann verwendet werden, um den Schnitt von Prolog zu simulieren, und projectkann verwendet werden, um den Wert zu erhalten, der einer logischen Variablen zugeordnet ist.

Die Anwesenheit von conda, condu, undproject--- und die Möglichkeit, die Suchstrategie einfach zu ändern --- ermöglicht es Programmierern, miniKanren als eingebettete Prolog-ähnliche Sprache zu verwenden. Dies gilt insbesondere für Benutzer von Clojures 'core.logic', das viele Prolog-ähnliche Erweiterungen enthält. Diese "pragmatische" Verwendung von miniKanren scheint den größten Teil der Verwendung von miniKanren in der Industrie zu erklären. Programmierer, die einer vorhandenen Anwendung in Clojure, Python oder JavaScript ein wissensbasiertes Argumentationssystem hinzufügen möchten, sind im Allgemeinen nicht daran interessiert, ihre gesamte Anwendung in Prolog neu zu schreiben. Das Einbetten einer kleinen Logikprogrammiersprache in Clojure oder Python ist viel ansprechender. Eine eingebettete Prolog-Implementierung würde für diesen Zweck vermutlich genauso gut funktionieren.

Neben der Verwendung von miniKanren als pragmatische Programmiersprache für eingebettete Logik, die Prolog ähnelt, wird miniKanren für die Erforschung der "relationalen" Programmierung verwendet. Das heißt, beim Schreiben von Programmen, die sich eher als mathematische Beziehungen als als mathematische Funktionen verhalten. In Schema kann die appendFunktion beispielsweise zwei Listen anhängen und eine neue Liste zurückgeben: Der Funktionsaufruf (append '(a b c) '(d e))gibt die Liste zurück (a b c d e). Wir können jedoch auch appendals Drei-Stellen-Beziehung und nicht als Zwei-Argument-Funktion behandeln. Der Aufruf (appendo '(a b c) '(d e) Z)würde dann die logische Variable Zder Liste zuordnen (a b c d e). Natürlich wird es interessanter, wenn wir logische Variablen an anderen Positionen platzieren. Der Ruf (appendo X '(d e) '(a b c d e))verbindet Xmit (a b c), während der Anruf(appendo X Y '(a b c d e))assoziiert Xund Ymit Listenpaaren, die, wenn sie angehängt werden, gleich sind (a b c d e). Zum Beispiel sind X= (a b)und Y= (c d e)ein solches Wertepaar. Wir können auch schreiben (appendo X Y Z), die unendlich viele Tripel von Listen produzieren X, Yund Zso , dass das Anhängen Xzu Yerzeugt Z.

Diese relationale Version von appendkann leicht in Prolog ausgedrückt werden und wird in der Tat in vielen Prolog-Tutorials gezeigt. In der Praxis verwenden komplexere Prolog-Programme in der Regel mindestens einige zusätzliche logische Merkmale, z. B. "Ausschneiden", die die Fähigkeit beeinträchtigen, das resultierende Programm als Beziehung zu behandeln. Im Gegensatz dazu wurde miniKanren explizit entwickelt, um diesen Stil der relationalen Programmierung zu unterstützen. Neuere Versionen von miniKanren Unterstützung haben für symbolische Einschränkung Lösung ( symbolo, numbero,absento, Ungleichheitsbeschränkungen, nominale Logikprogrammierung), um das Schreiben nicht trivialer Programme als Relationen zu erleichtern. In der Praxis verwende ich niemals eine der extralogischen Funktionen von miniKanren und schreibe alle meine miniKanren-Programme als Relationen. Die interessantesten relationalen Programme sind die relationalen Interpreter für eine Teilmenge des Schemas. Diese Dolmetscher verfügen über viele interessante Fähigkeiten, z. B. das Generieren einer Million Schema-Programme, die anhand der Liste ausgewertet werden (I love you), oder das triviale Generieren von Quines (Programme, die sich selbst bewerten).

miniKanren macht eine Reihe von Kompromissen, um diesen relationalen Programmierstil zu ermöglichen, die sich stark von den Kompromissen unterscheiden, die Prolog macht. Im Laufe der Zeit hat miniKanren mehr symbolische Einschränkungen hinzugefügt und sich zu einer symbolisch orientierten Programmiersprache für Constraint Logic entwickelt. In vielen Fällen machen es diese symbolischen Einschränkungen praktisch, die Verwendung von extralogischen Operatoren wie conduund zu vermeiden project. In anderen Fällen reichen diese symbolischen Einschränkungen nicht aus. Eine bessere Unterstützung für symbolische Einschränkungen ist ein aktiver Bereich der miniKanren-Forschung, zusammen mit der umfassenderen Frage, wie größere und komplexere Programme als Beziehungen geschrieben werden können.

Kurz gesagt, sowohl miniKanren als auch Prolog haben interessante Funktionen, Implementierungen und Verwendungen, und ich denke, es lohnt sich, die Ideen aus beiden Sprachen zu lernen. Es gibt auch andere sehr interessante Logikprogrammiersprachen wie Mercury, Curry und Gödel, von denen jede ihre eigene Sicht auf die Logikprogrammierung hat.

Ich werde mit ein paar miniKanren-Ressourcen enden:

Die Hauptwebsite von miniKanren: http://minikanren.org/

Ein Interview über relationale Programmierung und miniKanren, einschließlich eines Vergleichs mit Prolog: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

Prost,

--Wille


9
Entschuldigen Sie, wenn ich gerade umgehauen bin. Ich habe gerade die ersten Gedankenexperimente in Logik und Constraint-basierter Programmierung gestartet und das ist die Antwort, die ich bekomme. :) Eigentlich hatte ich, wie Sie auch in Ihrer Antwort erwähnt haben, einen starken Verdacht, dass die Berechnung der Logik ein perfekter Kandidat für die Implementierung als Monade war. Es stellt sich heraus, dass es sich eher um ein MonadPlus handelt, und es gibt tatsächlich eine Papier- und Referenzimplementierung von Ihrem Kollegen Friedman! Also lese ich das und spiele jetzt damit, irgendwelche Gedanken darüber?
Profpatsch

4
Ich vermute, Sie würden auch das Papier und den Code von microKanren interessant finden: webyrd.net/scheme-2013/papers/HemannMuKanren2013.pdf und github.com/jasonhemann/microKanren
William E. Byrd

5
Außerdem organisiere ich einen wöchentlichen MiniKanren-Kurs in Google Hangouts, sonntags um 15 Uhr Eastern Time (GMT -5: 00). Ich twittere immer den Link von meinem @webyrd Twitter-Konto, wenn Sie sich uns anschließen möchten. Zuvor aufgezeichnete Hangouts sind unter: youtube.com/playlist?list=PLO4TbomOdn2cks2n5PvifialL8kQwt0aW
William E. Byrd

2
Ich denke, es ist im Grunde die gleiche Suchmonade wie in der Zeitung von 2005. Siehe auch 'Prolog in Haskell einbetten
William E. Byrd

1
@ WilliamE.Byrd - Super Antwort! Angenommen, es gibt eine, was ist die beste miniKanren-Implementierung, die in ein C / C ++ - Programm eingebettet werden kann? Hat miniKanren auch den generativen Charakter von Prolog? Das heißt, die Fähigkeit, eine Variable in einem Ausdruck ungeerdet zu lassen, und die Kern-Engine generiert alle möglichen Werte für die ungeschliffene Variable angesichts der aktuellen vom Programm deklarierten Beziehungen.
Robert Oschler

4

Vorläufige Antwort:

AFAIK, "The Reasoned Schemer", führte die grundlegende Logikprogrammierung in einer Scheme-y-Syntax und einem funktionalen Programmierstil ein und fügte den booleschen Werten "#t" insbesondere die konstanten Ziele "#u" (fehlgeschlagen) und "#s" (suceeed) hinzu "und" #f ". Es wurde der gleiche Ansatz für die Logikprogrammierung verwendet wie bei Prolog: Unification and Backtracking Search. Ich werde sehen, ob ich über das Wochenende etwas Zeit habe, um dieses Buch aus meinem Regal zu holen. Der Zweig der Mathematik ist eine eingeschränkte Form der Logik erster Ordnung, in diesem Fall der Horn-Klauseln und der Resolution Unfication. Siehe: Computerlogik: Erinnerungen an die Vergangenheit und Herausforderungen für die Zukunft von John Alan Robinson und Die frühen Jahre der Logikprogrammierung von Robert Kowalski für einen Kaltstart.


3
Was haben diese beiden Zitate mit Kanren oder MiniKanren zu tun?
falsch

2
Siehe die letzte Frage: "Aus welchen Zweigen der Mathematik kommen sie und was sind die theoretischen Grundlagen?"
Frank Shearar
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.