检查数字是否为三角形

时间:2020-04-17 21:52:02

标签: prolog triangular

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

我的问题是由于某种原因,我的谓词会进行无限循环,而不仅仅是将数字求和直到N。

示例:

?-三角形(3)。 3 是

它并没有结束。

因此,基本上,这是将数字的总和增加到3,但是我所做的事情我不理解。

程序:

Microsoft SQL Server

1 个答案:

答案 0 :(得分:0)

背景信息

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谓词将切断当前层中的替代路径。因此,如果您使用以下规则扩展上述程序:

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将尝试使用triangular的最后一条规则,并将CONT解析为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)。当您使用修改后的程序运行查询?- triangular(3).时,Prolog应该在到达3时像以前一样写出triangular(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.