Prolog-参数没有充分实例化
我正在写一个小程序,计算列表中有多少元素不是数字。 这是我的密码:Prolog-参数没有充分实例化,prolog,arguments,clpfd,instantiation-error,Prolog,Arguments,Clpfd,Instantiation Error,我正在写一个小程序,计算列表中有多少元素不是数字。 这是我的密码: not_number([],0). not_number([X|T],R):- not(number(X)), R1 is R+1, not_number(T,R1). not_number([_|Tail],Result):- not_number(Tail,Result). 如果我执行这样的代码: ?- not_number([1,2,3,5], R). 我得到R=0(应该是
not_number([],0).
not_number([X|T],R):-
not(number(X)),
R1 is R+1,
not_number(T,R1).
not_number([_|Tail],Result):-
not_number(Tail,Result).
如果我执行这样的代码:
?- not_number([1,2,3,5], R).
我得到R=0(应该是这样的)
但如果我在列表中添加一个字符:
?- not_number([1,2,3,5,a], R).
然后我得到了这个错误:
ERROR: not_number/2: Arguments are not sufficiently instantiated
Exception: (10) not_number([a], _G247) ?
有人能解释一下代码的错误吗?我不熟悉prolog。您的问题是,在这样的算术计算中:
not_number(X, Y) :- not_number(X, Y, 0).
not_number([], Y, Y).
not_number([H|T], Y, Z) :-
\+ (number(H)),
Z1 is Z+1,
not_number(T, Y, Z1).
not_number([H|T], Y, Z) :-
number(H),
not_number(T, Y, Z).
cat(adam).
cat(eve).
A是B
右边(B)的一切都必须是已知的。没有变量
您可以这样做:
not_number(X, Y) :- not_number(X, Y, 0).
not_number([], Y, Y).
not_number([H|T], Y, Z) :-
\+ (number(H)),
Z1 is Z+1,
not_number(T, Y, Z1).
not_number([H|T], Y, Z) :-
number(H),
not_number(T, Y, Z).
cat(adam).
cat(eve).
(现在测试了这段代码,它可以工作了)
第三个参数是累加器。它计算有多少个非数字。当列表为空时,第三个参数与第二个参数统一,并成为正确答案
如果有机会,Prolog将遍历所有可能的路径。如果您这样做:
not_number(X, Y) :- not_number(X, Y, 0).
not_number([], Y, Y).
not_number([H|T], Y, Z) :-
\+ (number(H)),
Z1 is Z+1,
not_number(T, Y, Z1).
not_number([H|T], Y, Z) :-
number(H),
not_number(T, Y, Z).
cat(adam).
cat(eve).
然后问:
?- cat(X).
你可以得到两个答案:X=亚当和X=夏娃。
它也适用于您的代码:请注意,当列表的标题不是数字时,您仍然可以执行以下操作:
not_number([_|Tail],Result):-
not_number(Tail,Result).
这并不是你想要的答案。你必须切断那些你不感兴趣的路线。在这种情况下,我要补充一点
number(Head).
确保仅当列表中的元素不是数字时,才跳过该元素而不将计数器增加1
要强制Prolog查找其他结果,必须按键盘上的“;”(如本例中的亚当和夏娃)。此类问题的一般解决方案是使用约束 例如,如果您只使用约束,那么您的程序将完全按照预期工作。只需将
(is)/2
替换为(#=)/2
,即可获得全方位的整数算法:
示例查询及其结果:
?- not_number([1,2,3,5], R).
R = 0.
?非_数([1,2,3,5],R)。
R=0。
还请注意,我已将代码更改为使用ISO谓词
(\+)/1
,而不是not/1
,我正在编写此答案,因为目前为止最好的答案是by。我想让它显示为一个实际的答案
您的代码不起作用,因为您正在执行R1为R+1
的操作,而R
在not_number([X | t],R)
的情况下没有实例化。你的递归案例有点倒转。您要执行以下操作:
not_number([X|T],R):-
not(number(X)),
not_number(T,R1),
R is R1+1.
现在,
is的右侧在调用时被实例化。在我的例子中,而不是is
我必须使用=
而不是这个
X is AnotherVariable
我不得不写信
X = AnotherVariable
因为你正在做的R1是R+1
,而R
在不是[a],R]的情况下没有实例化。你的递归案例有点倒转。你想做的不是数字(T,R1),R是R1+1。也有很好的讨论是?-不是数字([A,A,B],N)。
有一个解决方案,N=-3
。我觉得不太对头,罪魁祸首<当然,代码>编号/1
,因为它混合了实例化测试和类型测试。解决方法:函子(X,\u,\u),\+number(X)
而不是\+number(X)
。或者,更好的是,如果使用正确的具体化测试谓词,非常正确。我建议必须是(nonvar,X)
。现在可以讨论这一点,因为OP报告的基本问题是通过使用声明性算法解决的。对,我没有注意到实际问题,因为我没有注意到这两个代码有多么相似。