2016-04-02 12 views
0

Ich habe den folgenden Prolog-Code. Der Link Prädikat bezieht sich auf eine andere Datei verschiedene Verbindungen enthalten, wie zum Beispiel:Prolog-Schleifensteuerung funktioniert nicht wie erwartet

link(b,brown,j) 

ich das Mitglied Prädikat bin mit dem Looping in dieser Route Programm zu steuern, um zu versuchen. Die Idee ist, wenn ich vorher in einer bestimmten Position war, wird das Programm nicht versuchen, diesen Weg zu gehen.

Wenn ich jedoch versuche, das Programm zu verfolgen, um herauszufinden, wo es falsch läuft, wenn es überprüft, ob die Position ein Mitglied in der Positionsliste ist, ist die erste Position bereits in der Liste, also versucht das Programm immer eine andere Route nach diesem Zeitpunkt, wenn es nicht sollte. Weiß jemand, wie man das repariert?

member(X,[X|_]). 
member(X,[_|Xs]):- member(X,Xs). 

route(X,X,[X],_). 
route(X,Z,[X|Path],Positions):- 
    link(X,Colour,Y), 
    \+member([Y,Colour],Positions),    
    route(Y,Z,Path,[[Y,Colour]|Positions]), 
    !. 
+0

Bitte, beschädige nicht Ihre Frage. Wenn ein Problem mit diesem Beitrag besteht, können Sie einen Moderator benachrichtigen, indem Sie das benutzerdefinierte Flag erhöhen. – Tunaki

+0

Sie haben nicht das Recht, Ihre eigenen Inhalte zu löschen, sobald sie gepostet wurden. Bitte verzichten Sie auf weitere Selbstversuchsversuche. – Magisch

Antwort

3

Einige kleinere Kommentare zuerst: Sie brauchen diesen Schnitt überhaupt nicht. Wenn Sie das Prädikat wirklich auf genau eine Antwort beschränken möchten, tun Sie dies am oberen Ende mit once/1. Das ist nicht nur konzeptionell sauberer, es ist noch effizienter.

Das andere Problem, das Sie hatten, hängt mit der unsicheren Negation von Prolog zusammen. Wenn Sie versehentlich ein zu allgemeines Ziel übergeben, wird die Negation immer fehlschlagen. Mit anderen Worten: Negation ist in Prolog als nächstes gebrochen. Es gibt zwei Möglichkeiten: Entweder einen Fehler für solche Fälle oder einfach eine bessere Definition wie non_member/2 verwenden.

Mal sehen, was mit non_member/2 an Ort und Stelle geschehen wäre:

link(b,brown,j). 

route(X,X,[X],_). 
route(X,Z,[X|Path],Positions):- 
    link(X,Colour,Y), 
    % \+member([Y,Colour],Positions), 
    non_member([Y,Colour],Positions), 
    route(Y,Z,Path,[[Y,Colour]|Positions]). 

non_member(E, Es) :- 
    maplist(dif(E), Es). 

| ?- route(X,Y,Path,Rs). 
    Y = X, Path = [X] 
; X = b, Y = j, Path = "bj", Rs = [] 
; X = b, Y = j, Path = "bj", Rs = [_A], 
    dif([j,brown],_A) 
; X = b, Y = j, Path = "bj", Rs = [_A,_B], 
    dif([j,brown],_A), 
    dif([j,brown],_B) 
; X = b, Y = j, Path = "bj", Rs = [_A,_B,_C], 
    dif([j,brown],_A), 
    dif([j,brown],_B), 
    dif([j,brown],_C) 
; X = b, Y = j, Path = "bj", Rs = [_A,_B,_C,_D], 
    dif([j,brown],_A), 
    dif([j,brown],_B), 
    dif([j,brown],_C), 
    dif([j,brown],_D) 
; X = b, Y = j, Path = "bj", Rs = [_A,_B,_C,_D,_E], 
    dif([j,brown],_A), 
    dif([j,brown],_B), 
    dif([j,brown],_C), 
    dif([j,brown],_D), 
    dif([j,brown],_E) 
; ... 

So können alle Antworten beschreiben die gleiche Path = "bj" (Kurzform für [b,j]). Aber das letzte Argument ist jetzt eine Liste von Elementen, die sich alle von [j,brown] unterscheiden müssen. So wäre die beste gewesen:

route(X, Y, Path) :- 
    route(X, Y, Path, []). 

Und hier ist eine alternative Definition Wiederverwendung path/4. Ich bin nicht wirklich sicher, was Sie mit diesen Farben meinen. Dennoch:

clink(X-_, Y-Color) :- 
    link(X, Color, Y). 

route(X, Y, Path) :- 
    path(clink, Path, X-none, Y-_). 

oder noch kürzer mit library(lambda):

route(X, Y, Path) :- 
    path(\ (Xl,_)^(Yl^C)^clink(Xl,C,Yl), Path, X-none, Y-_). 
Verwandte Themen