Prolog:使用纯递归仅计算父节点的直接子节点

Prolog: count only direct child nodes of a parent using pure recursion

是否可以在 Prolog 中使用递归计算父节点的直接子节点数而无需 retract / aggregate 等?

例如,假设我们有以下内容:

parent(p1, child_node1).
parent(p1, child_node2).
parent(p1, child_node3).
parent(p1, child_node4).

parent(child_node1, another_node1).
parent(child_node1, another_node2).
parent(child_node2, another_node3).
parent(child_node2, another_node4).
parent(child_node3, another_node5).
parent(child_node3, another_node6).
parent(child_node4, another_node7).
parent(child_node4, another_node8).

我们如何使用 p14 个直接子节点的递归计数?

一个简单的解决方案是维护我们已经看到的 children 的列表,并且每次查询还不是该列表成员的 child。每次我们找到 child 时,我们递归并将 child 添加到列表中。如果我们再也找不到这样的 child,我们可以将结果与目前获得的 children.

统一起来
count_children(Parent, N) :-
    count_children(Parent, [], 0, N).

count_children(Parent, L, N0, N) :-
    (parent(Parent, C), \+member(C, L))
    -> (N1 is N0+1, count_children(Parent, [C|L], N1, N))
    ; N = N0.

例如:

?- count_children(p1, N).
N = 4.

?- count_children(child_node1, N).
N = 2.

?- count_children(child_node2, N).
N = 2.

?- count_children(child_node3, N).
N = 2.

?- count_children(child_node4, N).
N = 2.

?- count_children(another_node1, N).
N = 0.

如果parent不统一,则与第一个parent统一,得到第一个结果后停止:

?- count_children(P, N).
P = p1,
N = 4.

我把它留作练习,让它与所有可能的 parents 统一起来。