Prolog回溯:参数没有充分实例化

Prolog回溯:参数没有充分实例化,prolog,backtracking,instantiation-error,Prolog,Backtracking,Instantiation Error,我有以下问题: 生成长度为2*n+1的所有子字符串,这些子字符串由0、1或-1的值组成,因此a1=…、a2n+1=0和| a(i+1)-ai |=1或2,对于每个1,您进行了什么查询?您是否尝试过进行跟踪以查看失败的地方?顺便说一下,CLPFD是GNUProlog的一部分(它不被认为是一个外部库),并且是Prolog的一个基本部分。你确定你不能使用它吗?我使用SWI Prolog,我甚至不允许使用基本的已经生成的函数,如“member”,我必须生成自己的版本。当我尝试运行genAll(2):ER

我有以下问题:


生成长度为2*n+1的所有子字符串,这些子字符串由0、1或-1的值组成,因此a1=…、a2n+1=0和| a(i+1)-ai |=1或2,对于每个1,您进行了什么查询?您是否尝试过进行
跟踪
以查看失败的地方?顺便说一下,CLPFD是GNUProlog的一部分(它不被认为是一个外部库),并且是Prolog的一个基本部分。你确定你不能使用它吗?我使用SWI Prolog,我甚至不允许使用基本的已经生成的函数,如“member”,我必须生成自己的版本。当我尝试运行genAll(2):ERROR:is/2:参数没有充分实例化时,我得到了这个结果。我相信“valid”谓词有问题,但我不知道如何修复它。您需要执行
跟踪
。我对查询
genAll(3)
进行了
trace
,最终失败的语句是,
1是abs(_698-3)
,它将失败并出现实例化错误。使用CLPFD和
#=
可以避免此问题。您从堆栈溢出复制的代码设计为使用CLPFD。很遗憾,我不能使用CLPFD。我对查询
genAll(2)
进行了
trace
,并且在
1 is abs(_G2700-3)
时失败。跟踪将显示它是如何到达那里的。这就是
trace
所做的。你需要仔细研究这个逻辑,看看发生了什么。如果需要,尝试一个更简单的案例,如
genAll(1)
,如果这是一个有效的案例。
change(0).
change(1).
change(-1).

%gets the last element from a list
lastE([X],X).
lastE([_|L],X) :-
    last(L,X).

%checks if |N-M|=1 or 2
calc(N,M) :-
    (  1 is abs(N-M)
    ;  2 is abs(N-M),
       ! 
    ).

%generates all lists of length N with values -1,0,1
generate([],0) :-
!.
generate([H|T],N):-
    change(H),
    N1 is N-1,
    generate(T,N1).

%validates a list to be correct (last element=0, |a(i+1) - ai| = 1 or 2)
valid(L) :-
   valid(L,_,3).

valid([E],_,_) :-
    lastE([E],0).
valid([H|[H1|T]],_,3) :-
    valid([H1|T],H,H1).
valid([_|[H1|T]],N,M) :-
    calc(N,M),
    valid([H1|T],M,H1).
genAll(N) :-
    N1 is 2*N,
    N2 is N1+1,
    generate(L1,N2),
    valid(L1),
    write('['),
printl(L1).

printl([]) :-
    write(']').
printl([0|T]) :-
    write('0 '),
    printl(T).
printl([1|T]) :-
    write('1 '),
   printl(T).
printl([-1|T]) :-
    write('-1 '),
printl(T).