2009-04-07 18 views
5

¿Hay una manera fácil de hacer una consulta en prolog solo devolver cada resultado una vez?resultados únicos de prolog

por ejemplo estoy intentando algo como:

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

y conseguir

X = 5 

X = 5 

X = 5 

X = 5 

.... 

Por no muy útil para mí.

Respuesta

1

Es difícil decirlo sin más código, pero probablemente esté buscando el operador de corte (!). Si desea publicar la definición de foo, es posible que yo (u otra persona que le sigue) pueda dar una respuesta detallada/específica.

+0

cada vez que he usado! ha detenido por completo la evaluación y quiero que cada valor que encuentre el prólogo, pero solo una vez por valor. (Probaré y reduciré mi caso) – BCS

+1

Es una cuestión de cuándo y dónde usarlo. Decir "nunca más volver aquí" tiene un significado totalmente diferente antes o después de la primera captura de datos. – MarkusQ

3

Si mal no recuerdo hay una solución de predicados (o similar, hace tiempo que programé Prolog) que reúne soluciones únicas en una lista.

Edit:setof/3 es en el que estaba pensando. Gracias, Kaarel.

+0

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

4

Una cosa que puede hacer es aplicar setof/3 al predicado que genera las soluciones. Pero tenga en cuenta que setof/3 se implementa aplicando sort/2 al resultado entregado por bagof/3 (al menos este es el caso en SWI-Prolog). Entonces, si su generador de soluciones se enciende para siempre, entonces setof/3 nunca se aplicará ...

Entonces yo diría que trate de programar para que los duplicados no se generen, es decir, usando el corte (!) Donde tenga sentido .

+0

Si recuerdo correctamente, setof solo es útil si la consulta tiene un tamaño de solución finito, y sabe que ya está hecho. De lo contrario, podría seguir obteniendo un 5, diciendo: No, ya lo consiguió, y mirando de nuevo, y obteniendo OTROS 5 ... ciclo infinito. –

+0

Gracias. He actualizado la respuesta un poco. – Kaarel

3

Otro enfoque es memorizar soluciones.

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

En caso de que su Prolog sea compatible con la presentación, se vuelve aún más simple. archivo Ejemplo:

:- table deadly/1. 

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

Ejemplo de ejecución 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

Yo diría "memorizar", en lugar de "memorizar". –