Prolog 计算谓词为 true 的次数

发布于 2024-11-08 08:00:04 字数 321 浏览 0 评论 0原文

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

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

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

我想构建类似的东西:

count(is_man(X), Count).

这个返回

Count = 2

我该怎么做?

I want to count the number of times a custom predicate is true.
For example, I have the following code:

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

X will return john, then if I press semicolon it will also return alex, then false.

I want to build something like:

count(is_man(X), Count).

And this to return

Count = 2

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雄赳赳气昂昂 2024-11-15 08:00:04

在 SWI-Prolog 中:

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

In SWI-Prolog:

aggregate_all(count, is_man(X), Count).
微暖i 2024-11-15 08:00:04

对于 ISO 标准 Prolog 解决方案,您可以使用 findall/3 生成所有解决方案的列表,然后将 Count 设置为结果列表的长度。按照您的建议,将其包装到用户定义的谓词 count/2 中可能有点棘手,因为我们需要在 a 中形成 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)).

For an ISO standard Prolog solution, you might use findall/3 to produce a list of all solutions, then set Count to the length of the resulting list. It could be a bit tricky to wrap this into a user-defined predicate count/2 as you propose, because we need to form the first argument of findall/3 in a way that accounts for any free (unbound) variables in the goal you want to pass as the first argument of count/2.

Many Prologs provide for "counters" or other forms of mutable global values, a nonstandard extension, that could be used in connection with a failure driven "loop" to make the same count. Slightly more cumbersome but sticking to the letter of the Prolog standard would be to use assert and retract to create your own "counter" by adjusting a dynamic fact.

An illustration of the latter approach follows. Making it "multithread safe" would require additional logic.

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)).
甜是你 2024-11-15 08:00:04

count(P,Count) :-
        findall(1,P,L),
        length(L,Count).

count(P,Count) :-
        findall(1,P,L),
        length(L,Count).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文