prolog - 检查数字是否为三角形
问题描述
所以我有这个谓词三角形(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).
解决方案
背景资料
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 将尝试最后一条规则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)
. 当您使用修改后的程序运行查询时,Prolog 应该在到达时像以前一样?- triangular(3).
写出. 之后,它检测到可能存在替代解决方案。如果您按,它会检测到最后一条规则不能应用,因为约束不成立。然后它停止搜索: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.
推荐阅读
- informatica - 如何连接多个表并将某个列(在具有不同值的所有表中重复)放入具有一列的单个目标表中
- python - Pytorch:掩码膨胀/扩展
- php - 尝试将 Laravel 从版本 6 升级到 7 时出现问题
- asp.net-core - 激活服务工作者时重新发送请求
- javascript - 如何使丰富的嵌入使用用户的显示颜色 discord.js
- angular - Angular 10 升级:为什么对抽象(组件)类使用 @Directive() 而不是 @Component()?
- python - Scrapy在选择器之外获取文本
- python - tkiner 如何从条目中获取文本并使其全局化
- python - 为什么在 Rossum API 中上传文档时出现此错误,提示解包值太多(预期为 2)?
- php - PHP - .htaccess 问题 $_SERVER['PATH_INFO'] 为空