2017-12-06 1 views
1

Lets ich Tatsachen annehmen, wie folgt:Wie kann man überprüfen, ob eine Variable etwas in Prädikat gibt

airport(nyc,'newyork'). 

Ich möchte wünschen, eine Nachricht anzuzeigen, wenn der Benutzer einen Flughafen gibt, der nicht existiert.

Mein Versuch:

isAirport(Air) :- 
     airport(Air,T), 
    (var(T) -> true 
     ; 
     write('Airport not found'), 
     fail 
    ). 

Doch dies scheint nicht zu funktionieren.

+0

Wenn Sie "airport (abc, _)" abfragen und "abc" ist kein Flughafen in der Datenbank, wird es einfach fehlschlagen. Sie müssen die Variable im zweiten Argument nicht überprüfen. In der Tat, 'airport (Air, T)' wird fehlschlagen und Ihre 'var (T)' wird nicht einmal aufgerufen, wenn 'Air' kein Flughafen ist. Prolog hat einige grundlegende Verhaltensweisen, die Sie lernen müssen, bevor Sie versuchen, ein vollständiges Programm zu schreiben. Sie sollten ein gutes Lehrbuch und/oder Tutorial durchgehen. – lurker

Antwort

2

Zuerst wollen wir mal sehen, was passiert, wenn Sie eine Verbindung abfragen (der Operator) zuerst:

?- airport(nyc, _), write('found!'). 
found! 
true. 

?- airport(abc, _), write('found!'). 
false. 

Das bedeutet, isAirport(abc) nicht direkt nach dem Versuch airport(abc,_) ohne Der Rest Ihres Prädikats wird ausgewertet. In vielen Fällen können Sie also ohne explizite erhalten, indem if-then-else-Konstrukt und nur etwas von der Form schreiben

predicate(X) :- 
    first_condition(X), 
    second_condition(X). 

und es wird nur gelingen, wenn beide Bedingungen für X erfüllt sind.

Falls Sie wirklich eine Benutzerschnittstelle erstellen möchten, ist dies ein wenig komplizierter, weil I/O von Natur aus nicht logisch ist, insbesondere wenn es sich um Backtracking handelt. Wir rufen normalerweise ein Programm auf, das sich so verhält, wie wir es von einer logischen Formel erwarten würden, und wenn es nicht-logische Konstrukte wie I/O enthält oder der cut-Operator ! heißt unrein.

Leider sind das if-then-else Konstrukt (-> und ;) und Negation (\+) über Schnitt implementiert und daher auch unrein. Zum Glück sind die meisten der Zeit, die Menschen ein bedingter wollen, ein reines disjunction genügt:

case(1,a). 
case(2,b). 

Wir haben eine automatische von der Ausführungsmechanismus von Prolog Verzweigung:

?- case(X,Y). 
X = 1, 
Y = a ; 
X = 2, 
Y = b. 

Aber manchmal wirklich wollen wir etwas das benötigt die unreinen Konstrukte, wie Benutzereingaben. Dann ist der einfachste Weg, um die schönen logischen Eigenschaften unseres Programms zu halten, ist die Aufgabe, in reine und unreinen zu trennen:

main :- 
    uinput(Data), 
    pure_predicate(Data, Result), 
    write(Result). 

Nachdem wir alle unreinen Teile getan haben, Data ist vereinigt mit den Benutzerdaten, die wir wollten.Schauen wir uns die Implementierung von uinput/1 einen Blick:

uinput(data(Airport,D-M-Y)) :- 
    format('~nAirport? '), 
    read(Airport), 
    (ground(Airport), airport(Airport, _)) 
    -> 
     (
      format('~nDay? '), 
      read(D), 
      format('~nMonth? '), 
      read(M), 
      format('~nYear? '), 
      read(Y), 
      (ground(D-M-Y), isDate(D-M-Y)) 
     -> 
     true 
     ; 
     throw(failure('unknown date')) 
     ) 
    ; 
    throw(failure('unknown airport')) 
    . 

Wir nacheinander Begriffe aus der Eingabe gelesen und eine Ausnahme auslösen, wenn wir es nicht verarbeiten kann. Damit das if-then-else-Konstrukt funktioniert, müssen wir besonders vorsichtig sein. Wenn wir die zwei Abfragen vergleichen:

?- between(1,3,X), write(X). 
1 
X = 1 ; 
2 
X = 2 ; 
3 
X = 3. 

und

?- between(1,3,X) -> write(X); false. 
1 
X = 1. 

können Sie sehen, dass die if-then-else verliert Lösungen. Dies bedeutet, dass wir sicherstellen müssen, dass unser Zustand deterministisch ist. Es ist schon eine gute Idee, nach einem Benutzereingabebegriff zu suchen, der geerdet werden soll, denn ohne Variablen gibt es nur einen Lösungsbegriff. Dennoch kann ein Aufruf an eines der Datenprädikate airport/1 und isDate/1 den gleichen Begriff mehrmals generieren oder gar nicht beenden. In diesem speziellen Fall müssen wir nur noch dafür sorgen, dass jeder Flughafen einen eindeutigen Namen für die Verknüpfung hat, können wir auch Termine ohne Wiederholung erzeugen:

airport(nyc, 'New York City'). 
airport(wdc, 'Washington DC'). 

isDate(X-Y-Z) :- 
    between(1,31,X), 
    between(1,12,Y), 
    between(1970,2100,Z). 

Ein weiterer Trick, bei der Umsetzung von uinput ist, dass wir nur mit true gelingen, wenn Wir haben alles validiert. Der einzige Effekt von ist jetzt, dass Data mit dem initialisiert wird, was auch immer der Benutzer eingegeben hat.

Wenn wir eine Dummy-Implementierung der tatsächlichen Umsetzung geben, können wir versuchen bereits die Umsetzung oursevles:

pure_predicate(_Data, Result) :- 
    % here goes the actual stuff 
    Result='we have found something awesome'. 

Auf der Aufforderung wir das reine Prädikat ohne Probleme verwenden können:

?- pure_predicate(someinputdata,Y). 
Y = 'we have computed something awesome'. 

On Andererseits können wir auch das vollständige Prädikat wie folgt verwenden:

?- main(_). 

Airport? wdc. 

Day? |: 1. 

Month? |: 2. 

Year? |: 2000. 
we have found something awesome 
true. 

Da wir lesen, müssen wir Prolog Terme eingeben und mit einem Punkt . beenden, aber alles hat wie erwartet funktioniert.

Fall In der Benutzereingabe fehlschlägt, erhalten wir:

?- main(_). 

Airport? bla(X). 

ERROR: Unhandled exception: failure('unknown airport') 

Bitte beachten Sie, dass wir nur durch diese Schwierigkeiten gingen zum Scheitern verurteilt tatsächlich früh und eine Benutzermeldung in diesem Fall geben. Für die eigentliche Berechnung ist dies völlig unnötig.

1

Im folgenden Code Sie falsche Annahme machen, dass T, falls ungebunden bleiben, wenn Flughafen nicht in der Datenbank zu finden:

airport(Air, T) 

Was tatsächlich passiert ist, wird der Anruf zum Flughafen (Air, T) Lassen Sie isAirport (Air) sofort fehlschlagen und Ihr var (T) und andere Teile werden überhaupt nicht ausgeführt. Statt

diesen Code Versuchen:

isAirport(Air) :- 
    airport(Air, _T), ! ; write('Airport not found'), fail. 
+0

was ist!?. Ich habe die Dokumentation online gelesen und das gefunden! schneidet das Vorhergesagte. Können Sie die letzte Aussage näher ausführen? – patzi

+0

Betrachten Sie die Abfrage isAirport (nyc), dh die Abfrage, die erfolgreich sein soll, weil airport (nyc, 'newyork') in der Datenbank ist. Wenn Sie es ausführen, wird Prolog feststellen, dass "NYC" tatsächlich in der Datenbank ist und "True" drucken wird. Wenn Sie jedoch Prolog nach weiteren Lösungen fragen (wenn Sie in der Konsole ";" eingeben), wird Prolog versuchen, einen alternativen Zweig der isAirport (Air) -Definition auszuführen, dh "write ('Airport not found'), fail "Teil, und das ist nicht was wir wollen. Deswegen benutzen wir!, Was Prolog sagt, dass es aufhören soll, nach alternativen Lösungen in isAirport (Air) zu suchen. –

+0

Bitte beachten Sie, dass dies eine sehr grobe Erklärung ist! - Ich schlage vor, durch ausführlichere Tutorials zu gehen, wie! funktioniert. –

Verwandte Themen