查询sum(X,Y)
将回答X的所有正除数的总和(不包括X本身)
比方说,sum(12,Y)
将回答Y=16
,因为1,2,3,4,6是12的除数。
我打算实现以下prolog程序,但它失败了,说某些变量没有实例化。
sum(X,Y) :- f(X,Y,1).
f(X,Y,F) :- X>Y,X>F, 0 is X mod F, F1 is F+1, f(X,Y1,F1), Y is F+Y1.
f(X,Y,F) :- X>Y,X>F, not(0 is X mod F), F1 is F+1, f(X,Y,F1).
上述程序的问题是什么?
谢谢你的帮助!
答案 0 :(得分:2)
我不打算向您展示如何编写sum_of_divisors函数,因为它不会很有启发性。相反,我可以尝试向您展示如何理解您的sum(12,Y)
查询出了什么问题。
让我们看看错误:
?- sum(12, Y).
ERROR: >/2: Arguments are not sufficiently instantiated
Exception: (8) f(12, _G215, 1) ? a
% Execution Aborted
查询后
?- sum(12, Y).
Prolog引擎读取sum(X,Y) :- f(X,Y,1).
,因此它评估第二个谓词:
f(X,Y,F)
其中X = 12
,F = 1
和Y
未绑定。所以它尝试这个:
:- X>Y
是
12 > _G350
其中_G350
是Y
,一个未实例化的变量。
问题是算术谓词如(>)/2
(以及(+)/2
和(*)/2
等)要求将要比较的变量实例化。你不能这样查询:
?- 12 > X
并期望Prolog引擎找到X
的所有绑定,使X
小于12.所以你需要重新思考问题的方法,并记住你能做到算术只有NUMBERS,而不是数字和变量。
答案 1 :(得分:2)
对于完整的声明性算术,您可以使用已建议的CLP(FD)。例如,在SWI-Prolog中,当我简单地用(#=)/ 2等替换(is)/ 2来概括原始算术运算以便它们也可以处理两边的变量时,我得到:
:- use_module(library(clpfd)).
sum(X,Y) :- f(X,Y,1).
f(X,Y,F) :- X#>Y,X#>F, 0 #= X mod F, F1 #= F+1, f(X,Y1,F1), Y #= F+Y1.
f(X,Y,F) :- X#>Y,X#>F, 0 #\= X mod F, F1 #= F+1, f(X,Y,F1).
现在您的示例查询产生:
?- sum(12, Y).
false.
很明显,该程序过于具体,请检查您是否忘记描述重要案例。