我是 Prolog 的初学者,有两个要求:
f(1) = 1
f(x) = 5x + x^2 + f(x - 1)
规则:
f(1,1).
f(X,Y) :-
Y is 5 * X + X * X + f(X-1,Y).
询问:
f(4,X).
输出:
ERROR: is/2: Arguments are not sufficiently instantiated
如何添加 f(X-1) 的值?
我是 Prolog 的初学者,有两个要求:
f(1) = 1
f(x) = 5x + x^2 + f(x - 1)
规则:
f(1,1).
f(X,Y) :-
Y is 5 * X + X * X + f(X-1,Y).
询问:
f(4,X).
输出:
ERROR: is/2: Arguments are not sufficiently instantiated
如何添加 f(X-1) 的值?
这可以通过使用辅助变量轻松解决。
例如,考虑:
f(1, 1)。 f(X,Y):- Y #= 5*X + X^2 + T1 , T2 #= X - 1, f(T2,T1)。
这是您给出的规则的直接翻译,使用辅助变量T1
并T2
分别代表部分表达式f(X-1)和X-1。正如@BallpointBen 正确指出的那样,仅使用术语本身是不够的,因为这些术语与其算术评估不同。特别是,-(2,1)
不是整数, 1
但2 - 1 #= 1
确实成立!
根据您的 Prolog 系统,您当前可能仍需要导入库以使用谓词(#=)/2
,它表示整数表达式的相等性。
您的示例查询现在已经产生了一个解决方案:
?- f(4, X)。 X = 75。
请注意,在这种情况下,谓词不会普遍终止:
?- f(4, X), 错误。 不终止
我们可以很容易地通过一个额外的约束来做到这一点:
f(1, 1)。 f(X,Y):- X #> 1 , Y #= 5*X + X^2 + T1, T2 #= X - 1, f(T2,T1)。
现在我们有:
?- f(4, X)。 X = 75 ; 错误的。
请注意,我们可以将其用作真正的关系,在最一般的情况下也是如此:
?- f(X, Y)。 X = Y,Y = 1; X = 2, Y = 15 ; X = 3, Y = 39 ; X = 4, Y = 75 ; 等等
基于较低级别算术的版本通常仅涵盖此类查询实例的非常有限的子集。因此,我建议您使用(#=)/2
而不是(is)/2
. 尤其是初学者,使用(is)/2
起来太难理解了。以 实例化错误下提交的许多相关问题作为证据,并查看clpfd以获取声明性解决方案。
问题是您试图评估 f(X-1,Y) 就好像它是一个数字,但当然它是一个可能为真或假的谓词。经过一番修修补补,我找到了这个解决方案:
f(1,1).
f(X,Y) :- X > 0, Z is X-1, f(Z,N), Y is 5*X + X*X + N.
诀窍是让它找到自己的方式f(1,N)
,而不用评估任何东西;然后通过满足让结果冒泡Y is 5*X + X*X + N
。在 Prolog 中,顺序对于它的搜索很重要。它需要满足f(Z,N)
才能具有N
for 语句的值Y is 5*X + X*X + N
。
另外,请注意X > 0
避免无限递归的条件。