我无法理解如何返回与某个人相关的所有人的清单。所以,如果我说亲戚(A,B),A就是一个人而B就是与该人有关的所有人的名单。我可以编写协助这样做所需的任何其他规则。这是我到目前为止所拥有的。
man(joe).
man(tim).
man(milan).
man(matt).
man(eugene).
woman(mary).
woman(emily).
woman(lily).
woman(rosie).
woman(chris).
parent(milan, mary).
parent(tim, milan).
parent(mary, lily).
parent(mary, joe).
parent(mary, matt).
parent(chris, rosie).
parent(eugene, mary).
parent(eugene, chris).
cousins(A, B) :- parent(C, A), parent(D, B), parent(E, C), parent(E, D), not(parent(C, B)), not(parent(D, A)), A \=B.
paternalgrandfather(A, C) :- man(A), man(B), parent(B, C), parent(A, B).
sibling(A, B) :- parent(C, A), parent(C, B), A \= B.
有人可以指导我如何做到这一点吗?感谢。
答案 0 :(得分:0)
我认为你应该使用内置的谓词findall / 3和sort / 2来避免重复
它会沿着这些方向发展:
relatives(Person, Relatives):-
findall(Relative, is_relative(Person, Relative), LRelatives),
sort(LRelatives, Relatives).
is_relative(Person, Relative):-
(cousins(Person, Relative) ; paternalgrandfather(Person, Relative) ; sibling(Person, Relative)).
您可能希望向is_relative添加更多子句以获得更多关系。
答案 1 :(得分:0)
我认为你应该专注于'真正的'关系,即parent(Old,Jung)
,其他谓词在这里是无关紧要的。显而易见的假设是parent/2
中出现的原子是标识符(即名称是唯一的)。从这张图看来,这里的所有人都是亲戚:
那么你的问题应该等同于在父关系中找到所有连接的顶点。您可以实现深度优先访问,传递受访节点列表以避免循环(请注意,您需要返回父母和孩子们!),类似
relatives(Person, Relatives) :-
relatives([], Person, [Person|Relatives]).
relatives(Visited, Person, [Person|Relatives]) :-
findall(Relative, immediate(Person, Visited, R), Immediates),
... find relatives of immediates and append all in relatives.
immediate(Person, Visited, R) :-
(parent(Person, R) ; parent(R, Person)),
\+ member(R, Visited).
看看您是否可以完成此代码段。请注意,relatives / 3中的参数顺序选择为easy maplist / 3。
如果您愿意学习更高级的代码,SWI-Prolog library(ugraph)会提供reachable(+Vertex, +Graph, -Vertices)
谓词,在基于列表的图表表示中执行此操作。
此处用于获取图片的SWI-Prolog代码段(要提供给dot
的文件):
graph(Fact2) :-
format('digraph ~s {~n', [Fact2]),
forall(call(Fact2, From, To), format(' ~s -> ~s;~n', [From, To])),
format('}\n').
你可以这样打电话:
?- tell('/tmp/parent.gv'),graph(parent),told.
然后在命令行dot -Tjpg /tmp/parent.gv | display