我想使用此代碼生成多個排列的:生成SWI-Prolog的動態大小排列結果與出錯:全球棧
:- 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
我想使用此代碼生成多個排列的:生成SWI-Prolog的動態大小排列結果與出錯:全球棧
:- 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] ?-
謝謝,它解決了我的問題,但我不明白爲什麼;)你有任何鏈接爲什麼'M'變爲0的文檔?我也試着用'M#> ='這也是多餘的,並沒有幫助。我認爲'M ins 1..N'就像循環,但我認爲它只會在我們強迫它在域中時變成循環。 – 2012-03-05 09:06:01
@Łukasz:M **從0開始**,因爲很明顯twinterer(謝謝!+1)解釋。試試這個查詢:? - length(X,Y)。 – CapelliC 2012-03-05 10:21:25
@Łukasz:'M ins 1..N'不是一個循環,它是一個限制'M'的域在1和N之間的約束。作爲一個約束,它被暫停,直到M的邊界改變,當它被喚醒並檢查其一致性時。 「長度/ 2」不是一個約束,即不考慮變量「M」的域。使用無實際意義的變量調用'length/2'將會返回一個空列表。這將'M'綁定到0,這會改變'M'域的邊界,從而喚醒發佈在'M'上的約束。然後約束檢查它的一致性並失敗,因爲0不在域中。 – twinterer 2012-03-05 13:17:24
作爲交流者已經回答到的問題,我只需要添加一個簡單的方法來獲得(正確)排列(可能是有用的?):
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] ;
它您可以通過重複排列的意思是,我不清楚。但是可能你的程序應該從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
來生成實際的解決方案。
條件'M#=
CapelliC
2012-03-05 06:55:51
是的,但是使用跟蹤我看到的序言並沒有結束循環,所以我認爲這可以幫助,但它didn 't – 2012-03-05 08:48:46