所以我有一个谓词triangle(N),其中N是一个数字,如果数字是一个三角数,则该谓词返回true。
我的问题是由于某种原因,我的谓词会进行无限循环,而不仅仅是将数字求和直到N。
示例:
?-三角形(3)。 3 是
它并没有结束。
因此,基本上,这是将数字的总和增加到3,但是我所做的事情我不理解。
程序:
Microsoft SQL Server
答案 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.