2009-04-07 14 views
5

Gibt es eine einfache Möglichkeit, eine Abfrage in Prolog nur jedes Ergebnis einmal zurückgeben?eindeutige Ergebnisse von Prolog

zum Beispiel Ich versuche, so etwas wie:

deadly(Xn) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xn)), safe(Xp). 
deadly(Xp) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xp)), safe(Xn). 

deadly(X). 

und bekommen

X = 5 

X = 5 

X = 5 

X = 5 

.... 

Nichts für mich usefull.

Antwort

1

Es ist schwer, ohne mehr von Ihrem Code zu sagen, aber Sie suchen wahrscheinlich für den Schnitt Operator (!). Wenn Sie die Definition von foo zu stellen, ich (oder jemand anderes, folgt) kann in der Lage sein, eine detaillierte/spezifische Antwort zu geben.

+0

jedes Mal, die ich benutzt habe! es hat die Auswertung total gestoppt und ich möchte jeden Wert, den Prolog findet, aber nur einmal pro Wert. (Ich werde versuchen, meinen Fall zu reduzieren) – BCS

+1

Es ist eine Frage von wann und wo es zu verwenden ist. Zu sagen "niemals wieder hierher zu kommen" hat eine völlig andere Bedeutung vor oder nach der ersten Erfassung der Daten. – MarkusQ

3

Wenn ich mich richtig erinnere gibt es ein Prädikat Lösungen (oder ähnlich, es ist schon eine Weile her, seit ich Prolog programmiert), die einzigartige Lösungen in einer Liste erfasst.

Edit:setof/3 ist der, an den ich dachte. Danke, Kaarel.

+0

findall/3, bagof/3, SETOF/3 – Kaarel

4

Eine Sache, die Sie tun können, ist setof/3 auf das Prädikat anzuwenden, die die Lösungen erzeugt. Aber beachten Sie, dass durch die Anwendung setof/3sort/2 auf das Ergebnis von bagof/3 geliefert implementiert ist (zumindest ist dies der Fall in SWI-Prolog). Also, wenn Ihr Solution Generator für immer anschaltet, dann wird setof/3 niemals angewendet ...

Also würde ich sagen, dass versuchen, so zu programmieren, dass Duplikate nicht erzeugt werden, dh indem man den Schnitt (!) Wo sinnvoll macht .

+0

Wenn ich remembercorrectly, SETOF nur dann sinnvoll ist, wenn die Abfrage eine endliche Lösung Größe hat, und er weiß, dass es fertig ist. Sonst könnte es einfach immer eine 5 bekommen und sagen, Nee, schon verstanden, und wieder schauen und eine ANDERE 5 ... Endlosschleife bekommen. –

+0

Danke. Ich habe die Antwort ein wenig aktualisiert. – Kaarel

3

Ein anderer Ansatz besteht darin, Lösungen zu memotisieren.

:- dynamic seen/1. 

% Call this always before calling deadly_wrapper/1 
clear_seen :- 
    retractall(seen(_)). 

% This wrapper calls deadly/1 but remembers 
% the solution using assert/1, and fails 
% if the solution has been "seen" before. 
deadly_wrapper(X) :- 
    deadly(X), 
    (
     seen(X) 
    -> 
     fail 
    ; 
     assert(seen(X)) 
    ). 


% This is for testing. 
deadly(1). 
deadly(1). 
deadly(1). 
deadly(5). 
deadly(1). 
deadly(1). 

Falls Ihr Prolog Tabling unterstützt, wird es noch einfacher. Beispieldatei:

:- table deadly/1. 

deadly(1). 
deadly(1). 
deadly(5). 
deadly(1). 
deadly(5). 

Beispiel Ausführung mit XSB:

$ xsb 
[xsb_configuration loaded] 
[sysinitrc loaded] 

XSB Version 3.2 (Kopi Lewak) of March 15, 2009 
[x86_64-unknown-linux-gnu; mode: optimal; engine: slg-wam; 
scheduling: local; word size: 64] 

| ?- [deadly_tab]. 
[Compiling ./deadly_tab] 
[deadly_tab compiled, cpu time used: 0.0100 seconds] 
[deadly_tab loaded] 

yes 
| ?- deadly(X). 

X = 5; 

X = 1; 

no 
| ?- 
+0

Ich würde sagen "Memoize", anstatt "auswendig zu lernen". –