谓词顺序改变导致无限循环

Predicate order change causes infinite loop

所以我有一个适用于未实例化变量的谓词 nat_cset(N,Cs),它将自然数与计数集 Sn = {1,2,...,N} 相关联。

nat_cset_(0,Acc,Acc).
nat_cset_(N,Acc,Cs) :- N #> 0, N_1 #= N - 1,  nat_cset_(N_1, [N|Acc], Cs).
nat_cset(N,Cs) :- nat_cset_(N,[],Cs).

我注意到的一件事是以下查询 nat_cset(N,Cs), N = 6. 进入无限循环而 N = 6, nat_cset(N,Cs). 没有:

?- nat_cset(N,Cs), N = 6, false.
...
?- N = 6, nat_cset(N,Cs), false.
false

发生这种情况是因为在第二个查询中,prolog 应该只寻找 N = 6 的解决方案,而在第一个查询中,prolog 将搜索无限的解决方案,使得 N = 6。

我的问题是,这是 nat_cset/2 的 'adequate' 行为还是不需要的行为?我在某处读到,改变解决方案的谓词顺序使它不单调并消除了它的纯度,但与此同时我想不出一种方法来使 nat_cset/2 有任何不同。

抱歉这个菜鸟问题,很多概念对我来说都是新概念,我仍在尝试处理所有这些概念。

查询

?- nat_cset(N,Cs), N = 6, false.

具有完全相同的终止属性
?- nat_cset(N,Cs), false, N = 6.

所以目标 N = 6 在这种情况下对终止没有任何影响,1。只有加在前面才能影响终止。

作为 said, rather start with programs using successor-arithmetics 而不是 clpfd/clpz。它们要简单得多,并且仍然公开了理解故障切片所需的相关属性。


1 这假设 N = 6 总是终止,就像 Scryer 中的 clpz 和 SWI 中的 clpfd 一样。对于一般的协程,情况不一定如此。想想freeze(N, inf), N = 6.