gpt4 book ai didi

prolog - 为什么SWI-Prolog只给出一种解决方案?

转载 作者:行者123 更新时间:2023-12-02 13:27:01 28 4
gpt4 key购买 nike

说实话,我是 Prolog 新手,所以请原谅我的无知。

我有一个简单的谓词来计算列表中原子的出现次数,如下所示:

count(L, B, C) :-
L = [], C = 0, !;
L = [H|T], H \= B, count(T, B, C), !;
L = [H|T], H = B, count(T, B, C1), C is C1 + 1.

以下查询返回正确的结果:

?- count([a, c, g, t], a, C).
C = 1.

?- count([a, c, g, t], c, C).
C = 1.

?- count([a, c, g, t], g, C).
C = 1.

?- count([a, c, g, t], t, C).
C = 1.

但是,如果我尝试找到所有可能的解决方案,它只会给出一个。

?- count([a, c, g, t], X, C).
X = a,
C = 1.

如何让它给出所有解决方案?我认为它可能与剪切操作符有关,但删除它似乎也不起作用。

最佳答案

削减确实是一个问题:尝试例如最通用的查询

?- count(Ls, L, C).

并且看到它只产生一个解决方案,尽管显然应该有无限多个,因为第一个参数可以是任意长度的列表。所以首先删除所有切口。另一个问题是(\=)/2,这不是一个真正的关系:只有当它的论点有根据时它才是合理的。使用更通用的谓词 dif/2 代替 (\=)/2,该谓词在 SWI-Prolog 以及其他系统中可用,并将其参数限制为不同的术语。然后,您的谓词将在各个方向上发挥作用。

编辑:我扩展了“在各个方向上可用”这一点。考虑以下版本的 list_term_count/3,它使用 将列表与该列表中术语出现的次数相关联。除了 dif/2 之外的约束:

list_term_count([], _, 0).
list_term_count([L|Ls], L, N) :-
list_term_count(Ls, L, N0),
N #= N0 + 1.
list_term_count([L|Ls], E, N) :-
dif(L, E),
list_term_count(Ls, E, N).

我们可以以最通用的方式使用它,即不指定所有参数,并获得正确的答案:

?- list_term_count(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 .

为了公平地枚举所有解决方案,我们可以使用length/2:

?- length(Ls, _), list_term_count(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 ;
Ls = [_G167],
N = 0,
dif(_G167, E) .

请注意 dif/2 约束,它作为剩余目标出现,并且在 N 时将列表的元素限制为与 E 不同是0。这就是我们表达无限组术语的方式,除了与 E 不同之外,这些术语不受任何其他方式的限制。

任何其他实例化模式也是可接受的。例如:

?- list_term_count([a], E, N).
E = a,
N = 1 ;
N = 0,
dif(E, a).

或者例如:

?- list_term_count([X], a, N).
X = a,
N = 1 ;
N = 0,
dif(X, a).

这种通用性是在程序中使用纯单调谓词的好处之一。使用纯粹的目标还允许我们非常自由地重新排序它们。

关于prolog - 为什么SWI-Prolog只给出一种解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18806739/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com