首页 > 解决方案 > 检查数字是否为三角形

问题描述

所以我有这个谓词三角形(N),其中 N 是一个数字,如果一个数字是一个三角形数字,这个谓词返回 true。

我的问题是,由于某种原因,我的谓词执行了一个无限循环,而不是仅仅将数字相加直到 N。

例子:

?-三角形(3)。3 对

它并没有结束。

所以基本上这是将数字的总和直到 3,但它在做一些我不明白的事情。

程序:

triangular(N) :- triangular(N,0).

triangular(N,AC) :- triangular(N,AC,N).

triangular(N,AC,0) :-  write(AC).

triangular(N,AC,CONT) :- NCONT is CONT - 1,
                         NAC is AC + NCONT,
                         triangular(N,NAC,NCONT).

标签: prologtriangular

解决方案


背景资料

Prolog 可以为您的查询搜索不止一种解决方案。

考虑这个程序:

human(alice).
human(bob).

当您查询时?- human(X).,Prolog 将搜索X与您的程序匹配的分配。它会告诉你解决方案X = alice。之后,您可以按 停止搜索.或按 继续搜索;。如果继续,Prolog 会找到X = bob. 之后它将停止,因为它已经用尽了所有可能的解决方案:

?- human(X).
X = alice .

?- human(X).
X = alice ;
X = bob.

您可以使用 cut 谓词控制搜索过程!。cut 谓词切断当前层中的替代路径。因此,如果您使用此规则扩展上述程序:

find_first_human(X) :- human(X), !.

运行查询?- find_first_human(X).只会输出X = alice.,而不会搜索进一步的答案。Prolog 知道human(X)可以通过多种方式解决,但随后!告诉 Prolog 忽略这些替代方案。

将此应用于您的程序

主要问题是您的最后一个triangle谓词不需要CONT > 0. 因此,当您查询 时?- triangle(3).,Prolog 最终会到达triangular(3,3,0).与您的write规则相匹配的 。如您所见,您的程序3按预期输出。但是,Prolog 然后发现有替代解决方案triangular(3,3,0),因此它提供您继续搜索。您可以按 停止.,或按 继续;。如果你继续,Prolog 将尝试最后一条规则triangularCONT并被解析为0。从而NCONT变成-1。然后这将进入一个无限循环,其中最后一条triangular规则被重复应用,递减无止境CONT

您可以通过使用trace.(可以再次禁用notrace.)来验证这一点:

?- trace.
?- triangular(3).
   Call: (8) triangular(3) ? creep
   Call: (9) triangular(3, 0) ? creep
   Call: (10) triangular(3, 0, 3) ? creep
...
   Call: (13) triangular(3, 3, 0) ? creep
   Call: (14) write(3) ? creep
3
   Exit: (14) write(3) ? creep
   Exit: (13) triangular(3, 3, 0) ? creep
...
true ;
   Redo: (13) triangular(3, 3, 0) ? creep
   Call: (14) _2076 is 0+ -1 ? creep
   Exit: (14) -1 is 0+ -1 ? creep
...

您可以通过将最后一条规则更改为:

triangular(N,AC,CONT) :- CONT > 0,
                         NCONT is CONT - 1,
                         NAC is AC + NCONT,
                         triangular(N,NAC,NCONT).

这禁止 Prolog 将规则应用于triangular(3,3,0). 当您使用修改后的程序运行查询时,Prolog 应该在到达时像以前一样?- triangular(3).写出. 之后,它检测到可能存在替代解决方案。如果您按,它会检测到最后一条规则不能应用,因为约束不成立。然后它停止搜索:3triangular(3,3,0);CONT > 0

?- triangular(3).
3
true ;
false.

我们可以使用!上一节中显示的剪切谓词进一步简化这一点,将write规则修改为:

triangular(N,AC,0) :-  write(AC), !.

这告诉 Prolog 不要为triangular(3,3,0). 当您运行查询?- triangular(3).时,Prolog 应该像以前一样写出3,然后退出而不进一步搜索:

?- triangular(3).
3
true.

推荐阅读