2010-11-16 32 views
6

Estoy aprendiendo prolog y estoy leyendo un libro llamado Programming Prolog for Artificial Intelligence. Como práctica, quiero aprender cómo extender uno de los ejemplos en este libro. ¿Puede ayudarme alguien, por favor?Obteniendo la lista de soluciones en Prolog

Digamos que tienes estos hechos:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 

¿Cómo escribo un predicado prólogo que me daría una lista de bobs padres? Por ejemplo:

list_parents(bob, L). 

L = [pam, george] ; 
L = [george, pam] ; 
true. 

Respuesta

2

Prueba esto:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 
list_parents(A, Es, [X|Xs]) :- parent(X, A), \+ member(X, Es), list_parents(A, [X|Es], Xs). 
list_parents(A, Es, []). 

Eso era un método ineficiente, un mejor método necesitará una "soluciones" de predicados de orden superior.

list_parents (X, Ys): - soluciones (padres, [X, W], 1, Ys)

+1

He publicado una pregunta de seguimiento a la respuesta que se refiere el predicado "soluciones": https://stackoverflow.com/questions/47233986/higher-order- solutions-predicate – mrsteve

12

un todo-soluciones predicado LIKE findall/3 puede hacer el truco:

list_parents(P, L) :- 
    findall(Parent, parent(Parent, P), L). 

Simplemente put, findall/3 encuentra todas las vinculaciones para Parent en el objetivo 'backtrack-able' parent(Parent, P), y pone todas las vinculaciones de Parent en la lista L. Tenga en cuenta que esto no eliminará los duplicados, pero puede hacer un sort/2 a L antes de devolverlo para crear un conjunto. La ejecución de esta:

?- list_parents(bob, L). 
L = [pam, george]. 

Si usted no tiene findall/3 en su aplicación PROLOG, se puede hacer de forma manual como esto:

list_parents(P, L) :- 
    list_parents(P, [], L). 

list_parents(P, Acc, L) :- 
    parent(Parent, P), 
    \+ member(Parent, Acc), !, 
    list_parents(P, [Parent|Acc], L). 
list_parents(_, L, L). 

Esta versión envía las llamadas a list_parents/2 fuera a un acumulador-versión, list_parents/3. Este último intenta recopilar Parent enlaces también, siempre que no los hayamos visto antes (de ahí el \+ member cheque), y devuelve la lista donde no se pueden encontrar enlaces nuevos Parent acumulados en la lista Acc. La ejecución de esta nos da el mismo resultado que la primera opción:

?- list_parents(bob, L). 
L = [pam, george]. 
+1

'findall', eso es lo que intentaba hacer con Google –

+0

sharky, su implementación final no tiene en cuenta los elementos repetidos. Si tiene esto en la base de datos: 'parent (hannah, carl). padre (hannah, carl). parent (bob, carl) .' tus salidas de reglas [hannah, bob]. Pero si lo intentas con findall, obtienes [hannah, hannah, bob] –

Cuestiones relacionadas