私はこのコードを使用して複数の順列を生成しようとしています:
:- 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
コードで何が起こるかというと、リストの長さはを呼び出すことによって暗黙的に設定され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] ?-
複数の順列が何を意味するのかは私にはわかりません。しかし、おそらくあなたのプログラムは制約から始まり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
して実際のソリューションを生成します。
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] ;