获取Prolog中的解决方案列表

use*_*034 9 prolog

我正在学习prolog,我正在读一本名为Programming Prolog for Artificial Intelligence的书.作为练习,我想学习如何扩展本书中的一个例子.有人可以帮忙吗?

说你有这些事实:

parent(pam, bob). %pam is a parent of bob
parent(george, bob). %george is a parent of bob
Run Code Online (Sandbox Code Playgroud)

我怎么写一个prolog谓词会给我一个bobs父母的名单?例如:

list_parents(bob, L).

L = [pam, george] ;
L = [george, pam] ;
true.
Run Code Online (Sandbox Code Playgroud)

sha*_*rky 17

一个全解决方案谓词findall/3可能会成功:

list_parents(P, L) :-
    findall(Parent, parent(Parent, P), L).
Run Code Online (Sandbox Code Playgroud)

简而言之,在"可追溯"目标中findall/3查找所有绑定,并将所有绑定放入列表中.请注意,这不会删除重复的,但你可以做,以恢复它来创建一组之前.执行此:Parentparent(Parent, P)ParentLsort/2L

?- list_parents(bob, L).
L = [pam, george].
Run Code Online (Sandbox Code Playgroud)

如果你没有findall/3PROLOG实现,你可以像这样手动完成:

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).
Run Code Online (Sandbox Code Playgroud)

此版本将调用发送到list_parents/2累加器版本,list_parents/3.后者也尝试收集Parent绑定,只要我们之前没有看到它们(因此\+ member检查),并返回列表,其中没有找到Parent累积到列表中的新绑定Acc.执行此操作会给我们与第一个选项相同的结果:

?- list_parents(bob, L).
L = [pam, george].
Run Code Online (Sandbox Code Playgroud)


Min*_*ang 2

尝试这个:

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, []).
Run Code Online (Sandbox Code Playgroud)

这是一种低效的方法,更好的方法将需要“解决方案”高阶谓词。

list_parents(X, Ys) :- 解决方案(父项, [X, W], 1, Ys)