使用ERROR生成SWI-Prolog结果中的动态大小排列:超出全局堆栈

时间:2012-03-05 02:45:56

标签: prolog clpfd

我正在尝试使用此代码生成多个排列:

:- use_module(library(clpfd)).

p(N, Indexes) :-
    M in 1..N,
    M #=< N,
    length(Indexes, M),
    Indexes ins 1..N.

它会返回所有结果,但最终会与ERROR: Out of global stack

崩溃

3 个答案:

答案 0 :(得分:5)

您的代码中发生的事情是通过调用length/2隐式设置列表的长度。这将从长度为0的列表开始,该列表将M绑定到0,这反过来唤醒约束M in 1..N,该约束失败。接下来,它返回一个长度为1的列表,该列表成功,然后回溯一个长度为2的列表,该列表再次成功。之后,进入length/2的任何进一步回溯都将返回更长和更长的列表,但唤醒M in 1..N将始终失败,直到列表变得如此之大以至于内存不足。

您需要做的是将选择点放在length/2调用之前而不是放在其中,例如,替换

M #=< N,

(无论如何,这是一个多余的约束)

indomain(M),

这会给你:

[debug] [1]  ?- p(2,I).
I = [_G3025],
_G3025 in 1..2 ;
I = [_G3102, _G3105],
_G3102 in 1..2,
_G3105 in 1..2.

[debug] [1]  ?- 

答案 1 :(得分:3)

我不清楚你的意思是多重排列。但是,您的程序可能以between/3开头,然后包含all_different/1约束。

p(N, Indices) :-
    between(1,N,M), % or maybe rather between(0,N,M).
    length(Indices, M),
    Indices ins 1..N,
    all_different(Indices).

然后,使用labeling/2生成实际解决方案。

答案 2 :(得分:1)

由于twinterer已经回答了问题,我只是添加了一种更简单的方法来获得(正确的)排列(可能有用吗?):

permutations_n(N, P) :-
  numlist(1, N, L),
  permutation(L, P).

试验:

?- permutations_n(3, X).
X = [1, 2, 3] ;
X = [1, 3, 2] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
相关问题