Prolog 计算谓词为 true 的次数

问题描述 投票:0回答:3

我想计算自定义谓词为真的次数。 例如,我有以下代码:

is_man(john).
is_man(alex).
?:-is_man(X).

X
将返回
john
,然后如果我按分号它也会返回
alex
,然后
false

我想构建类似的东西:

count(is_man(X), Count).

这个要回归

Count = 2

我该怎么做?

prolog aggregate-functions
3个回答
41
投票

在 SWI-Prolog 中:

aggregate_all(count, is_man(X), Count).

注意。第一个参数

count
是特殊模板之一:

模板值

count
sum(X)
max(X)
min(X)
max(X,W)
min(X,W)
是增量处理的,而不是使用 findall/3 并在恒定内存中运行。


13
投票

对于 ISO 标准 Prolog 解决方案,您可以使用 findall/3 生成所有解决方案的列表,然后将 Count 设置为结果列表的长度。 按照您的建议,将其包装到用户定义的谓词 count/2 中可能有点棘手,因为我们需要以考虑任何自由(未绑定)变量的方式形成 findall/3 的第一个参数在目标中,您希望作为 count/2 的第一个参数传递。

许多 Prolog 提供“计数器”或其他形式的可变全局值(一种非标准扩展),可以与故障驱动的“循环”结合使用以进行相同的计数。 稍微麻烦一点但坚持 Prolog 标准的字母是使用 assertretract 通过调整动态事实来创建自己的“计数器”。

后一种方法的说明如下。 使其“多线程安全”需要额外的逻辑。

count(Goal,_) :-
    setGoalCount(0),
    call(Goal),
    incGoalCount(1),
    fail.              /* or false in some Prologs */
count(_,Count) :-
    getGoalCount(Count).

setGoalCount(_) :-
    retract(getGoalCount(_)),
    fail.
setGoalCount(X) :-
    assert(getGoalCount(X)).

incGoalCount(Y) :-
    retract(getGoalCount(X)),
    !,
    Z is X + Y,
    assert(getGoalCount(Z)).

10
投票

count(P,Count) :-
        findall(1,P,L),
        length(L,Count).
© www.soinside.com 2019 - 2024. All rights reserved.