2015-05-22 9 views
5

Jeder Programmierer mit etwas Erfahrung in Prolog kennt die Vorteile der Verwendung unärer Notation für Zahlen. wenn wir eine Zahl als Liste von 1" durch Beispiel stellen (‚4‘ Liste ‚[1,1,1,1]‘ und so weiter), können wir definieren:Prolog: fehlende Funktion?

unary_succ(X,[1|X]). 

die folgenden Abfragen tun was erwartet wird:

?- X=[1,1],unary_succ(X,Y). 
X = [1, 1], 
Y = [1, 1, 1]. 

?- unary_succ(X,Y),X=[1,1]. 
X = [1, 1], 
Y = [1, 1, 1]. 

?- unary_succ(X,Y),Y=[1,1]. 
X = [1], 
Y = [1, 1]. 

auf diese Weise Aussage unary_succ (X, Y) „bindet“ X und Y in einer Weise, dass, wenn nach der Tat festgestellt wird, eine dieser Variablen auf einen Wert gebunden ist, der andere tut das.

Dieses Verhalten ist jedoch nicht möglich, wenn wir die interne Zahlendarstellung verwenden:

Meiner Meinung nach wird es sehr nützlich sein, dass frühere Aussagen und ähnliche das tun, was erwartet wird. Das heißt, wir müssen zwei Variablen so verknüpfen, dass, wenn einer von ihnen an einen Wert gebunden ist, der andere der zuvor festgelegten Regel folgt.

Meine Fragen sind:

a) einige einfache Möglichkeit, dass in Prolog zu tun.

b) Falls nicht möglich, jede andere Programmiersprache, die diese Funktion unterstützt?

Jeder Kommentar ist willkommen.

Danke an alle.

* Nachtrag I *

Ein weiteres Beispiel ist:

user_id(john,1234). 
user_id(tom,5678). 

und Anfragen:

X=john,user_id(X,Y). 
user_id(X,Y),X=john 

, die derzeit von Rückzieher gelöst werden.

+3

In SWI Prolog, ich denke, Sie können mit Clpfd Bibliothek tun. Sie können den Quellcode überprüfen, um zu sehen, wie er implementiert wird. – nhahtdh

+0

Hallo. Danke für deine Zusammenarbeit. Zu der Frage ein weiteres Beispiel zur Klärung hinzugefügt. –

+4

Ich zweite der CLP (FD) Vorschlag von @nhahtdh: Zumindest für Integer ist die Verwendung von CLP (FD) Constraints definitiv die relationale Lösung, nach der Sie suchen und die von allen wichtigen Prolog-Implementierungen bereitgestellt wird. Schreiben Sie einfach "X # = 2, Y # = X + 1" oder äquivalent "Y # = X + 1, X # = 2". – mat

Antwort

3

Dieses Thema ist bekannt als coroutining, und auf ziemlich allgemeine Weise zu lösen - afaik - erfordert eine Erweiterung des grundlegenden Prolog-Berechnungsmodells. Zum Glück sind die meisten Prologs solche Erweiterung haben ... Also, lassen Sie uns in SWISH versuchen, Ihre eigenen ‚reaktiven‘ Erweiterung zu bauen:

my_succ(X, Y) :- when((nonvar(X);nonvar(Y)), succ(X, Y)). 

bearbeiten nicht vollständig auf den Punkt, aber Jan hat auf SWI-Prolog-Mailingliste eine einfache Beispiel coroutining Anwendung:

?- freeze(X, writeln(X)), findall(X, between(1,3,X), Xs). 
1 
2 
3 
Xs = [1, 2, 3], 
freeze(X, writeln(X)). 
+0

Vielen Dank, ich wusste nicht, dass diese Aussage existiert. –

+2

'wenn/2' in SICStus (Ursprung), YAP und SWI existiert. – false

+3

+1 für die Erwähnung der Koroinierung im Allgemeinen. Dieses spezielle Beispiel ist meiner Ansicht nach jedoch nicht sehr glücklich, da "Y # = X + 1" mit CLP (FD) - Einschränkungen praktischer und viel passender gelöst wird. Ich schlage vor, dass Sie ein didaktisch wertvolleres Beispiel für "when/2" anstelle des aktuellen geben. – mat

4

Das Problem, das Sie beschreiben, besteht, solange die Antworten von einem Prolog-System Ersetzungen (syntaktischen) Antwort beschränkt sind. In Ihrem Beispiel würde das Ziel succ(X, Y) unendlich viele Antworten erfordern, um die gesamte Lösungsmenge zu beschreiben. Aus diesem Grund wird stattdessen eine instantiation_error ausgegeben.

Um dieses Problem anzugehen, müssen wir die Antworten erweitern. Daher enthalten die Antworten nicht nur Antwortsubstitutionen, sondern einige ausführlichere Methoden zur Beschreibung einiger Mengen.

library(clpfd) bietet Einschränkungen über Z (und vor allem endlichen Domänen).

?- use_module(library(clpfd)). 
?- Y #= X+1. 
X+1#=Y. 

Hinweis, dass solche Lösern für den allgemeinen Fall nicht sehr stark sind:

?- Y #= X+1, X #= Y+1. 
Y+1#=X, 
X+1#=Y. 

Sie können das System erwarten jedoch zum Scheitern verurteilt, erzeugt es eine Antwort, die im Wesentlichen die Abfrage angepasst. Zumindest die Antwort ist nicht falsch, denn es heißt einfach: Ja, es gibt eine Lösung zur Verfügung gestellt diese Beziehung gilt (was es nicht, ähnlich dem Kleingedruckten in Versicherungsverträge oder Garantiezertifikate).

when/2 ist auch als coroutining bekannt und ist in vielen Fällen schwächer als das, was Sie mit clpfd bekommen. Aber in einigen Fällen ist es für einige Implementierungen von clpfd stärker. Betrachten dif/2 die als when(?=(X,Y), X \== Y) ausgedrückt werden kann und

| ?- dif(X, Y), X = Y. 
no 

... während (in SICStus)

| ?- X #\= Y, X #= Y. 
Y #= X, 
Y #\= X, 
Y in inf..sup, 
X in inf..sup ? ; 
no 

library(clpq) einen Solver bietet, das stärker ist in vielen Situationen ist es fehlt jedoch ganzzahlige spezifische Einschränkungen wie mod/2 . In vielen Situationen ist es immer noch interessant zu verwenden, wie hier in SICStus: