2009-04-07 15 views
5

C'è un modo semplice per fare una query in prolog restituire solo ogni risultato una volta?risultati unici da prolog

per esempio sto cercando qualcosa di simile:

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). 

e ottenere

X = 5 

X = 5 

X = 5 

X = 5 

.... 

Per non utile per me.

risposta

1

È difficile dire senza altro codice, ma probabilmente stai cercando l'operatore di taglio (!). Se si desidera pubblicare la definizione di foo, I (o qualcun altro che segue) potrebbe essere in grado di fornire una risposta dettagliata/specifica.

+0

ogni volta che ho usato! ha completamente fermato la valutazione e voglio che ogni valore rilevato da Prolog, ma solo una volta per valore. (Proverò a ridurre il mio caso) – BCS

+1

È questione di quando e dove usarlo. Dire "non tornare mai più qui" ha un significato completamente diverso prima o dopo la prima acquisizione dei dati. – MarkusQ

3

Se ricordo correttamente c'è una soluzione di predicato (o simile, è passato un po 'di tempo da quando ho programmato Prolog) che raccoglie soluzioni uniche in una lista.

Modifica:setof/3 è quello a cui stavo pensando. Grazie, Kaarel.

+0

findall/3, bagof/3, setof/3 – Kaarel

4

Una cosa che si può fare è applicare setof/3 al predicato che genera le soluzioni. Notare che setof/3 viene implementato applicando sort/2 al risultato consegnato da bagof/3 (almeno questo è il caso in SWI-Prolog). Quindi, se il tuo generatore di soluzioni va avanti all'infinito, allora setof/3 non sarà mai applicato ...

Quindi direi che prova a programmare in modo che i duplicati non vengano generati, cioè utilizzando il taglio (!) Dove ha senso .

+0

Se ricordo male, setof è utile solo se la query ha una dimensione finita della soluzione e sa che è fatta. Altrimenti, potrebbe solo continuare a ottenere un 5, dicendo: No, l'hai già ottenuto, e guardando di nuovo, e ottenendo UN ALTRO 5 ... ciclo infinito. –

+0

Grazie. Ho aggiornato la risposta un po '. – Kaarel

3

Un altro approccio è quello di memorizzare le soluzioni.

:- 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). 

Nel caso in cui il tuo Prolog supporti la presentazione, allora diventa ancora più semplice. File Esempio:

:- table deadly/1. 

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

Esempio di esecuzione con 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

Direi "memoize", piuttosto che "memorize". –