Prolog 所有正因子之和

Prolog 所有正因子之和,prolog,Prolog,查询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

查询
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).
上面的程序有什么问题


谢谢你的帮助

我不会向您演示如何编写除数和函数,因为它不会很有指导意义。相反,我可以尝试向您展示如何理解您的
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
其中
\u G350
Y
,是一个未实例化的变量

问题是像
(>)/2
(以及像
(+)/2
(*)/2
等)这样的算术谓词要求要比较的两个变量都实例化。您不能这样查询:

?- 12 > X

并且期望Prolog引擎找到所有到
X
的绑定,使得
X
小于12。因此,你需要重新思考你解决这个问题的方法,记住你只能用数字来做算术,不能用数字和变量来做。

我不打算告诉你如何编写除数和函数,因为这不是很有启发性。相反,我可以尝试向您展示如何理解您的
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
其中
\u G350
Y
,是一个未实例化的变量

问题是像
(>)/2
(以及像
(+)/2
(*)/2
等)这样的算术谓词要求要比较的两个变量都实例化。您不能这样查询:

?- 12 > X

并且期望Prolog引擎找到所有到
X
的绑定,使得
X
小于12。因此,您需要重新思考解决问题的方法,并记住,您只能使用数字进行算术运算,而不能使用数字和变量。

对于完整的声明性算术,您可以按照前面的建议使用CLP(FD)。例如,在SWI Prolog中,当我简单地将(is)/2替换为(#=)/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.

因此,很明显,程序太具体了,请检查您是否忘记描述一个重要案例。

对于完整的声明性算术,您可以按照前面的建议使用CLP(FD)。例如,在SWI Prolog中,当我简单地将(is)/2替换为(#=)/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.
因此,很明显,程序太具体了,请检查您是否忘记描述一个重要案例。

我认为您需要使用而不是原始算术,因为Prolog不够聪明,无法在给定这些约束条件的范围内猜测数字。我认为您需要使用而不是原始算术,因为Prolog不够聪明,无法在给定这些约束条件的范围内猜测数字。