我想訪問列表排列,並把它作爲參數傳遞給其它功能。如何訪問序言中的列表排列?
這是排列碼:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
我想訪問列表排列,並把它作爲參數傳遞給其它功能。如何訪問序言中的列表排列?
這是排列碼:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
首先,讓我們來重新定義你的謂詞所以他們沒有做任何不必要的I/O:
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
現在,你有可能是什麼被認爲是「純粹」的置換函數:
?- perm([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [1, 3, 2] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
因此,假設你有一個max_heap功能是獲得一個列表Ø f值並生成一棵樹。我會讓你擔心,所以我們就斷定它的存在,被稱爲max_heap/2
並讓你有一種方式來顯示這個誘人叫display_heap/1
進一步斷定。 「採取的」排列「發送」它作爲參數傳遞給這些函數,你其實是在說數學-ESE:假設P是X的排列,讓我們與它max_heap並顯示它。或者,假設P是X的一個排列,H是從X做了最大堆,讓我們顯示H:
show_heaps(List) :- perm(List, P), max_heap(P, H), display_heap(H).
這是說同樣的事情,我的英語句子:假設P是列表的排列,然後H是它的堆表示,然後顯示它。從技術上來說,display_heap/1
仍然是一個謂詞,對於給定的堆可能是真或假。在實踐中,它永遠是正確的,如果你運行這個你還是得打;
反覆說,給我另一種解決辦法,除非你使用一個故障驅動迴路或extralogical謂詞像findall/3
,使所有的解決方案被發現。
編輯:讓我們討論故障驅動循環和findall/3
。首先讓我添加一些新的謂詞,因爲我不確切知道你在做什麼,但對我們的目的來說並不重要。
double([X|Xs], [Y|Ys]) :- Y is X*2, double(Xs, Ys).
double([],[]).
showlist(Xs) :- print(Xs).
所以現在我有一個謂語double/2
雙打在列表中的值和打印在標準輸出列表中的謂語showlist/1
。我們可以試一下,像這樣:
?- perm([1,2,3], X), double(X, Y), showlist(Y).
[2,4,6]
X = [1, 2, 3],
Y = [2, 4, 6] ;
[4,2,6]
X = [2, 1, 3],
Y = [4, 2, 6] ;
[4,6,2]
X = [2, 3, 1],
Y = [4, 6, 2] ;
[2,6,4]
X = [1, 3, 2],
Y = [2, 6, 4] ;
[6,2,4]
X = [3, 1, 2],
Y = [6, 2, 4] ;
[6,4,2]
X = [3, 2, 1],
Y = [6, 4, 2] ;
false.
當你鍵入;
你說,「還是?」到Prolog。換句話說,你在說「還有什麼?」實際上,你告訴Prolog,這不是我想要的答案,試着找到我另一個我更喜歡的答案。您可以形式化過程具有故障驅動循環:
?- perm([1,2,3], X), double(X, Y), showlist(Y), fail.
[2,4,6][4,2,6][4,6,2][2,6,4][6,2,4][6,4,2]
false.
所以,現在你看穿double/2
在經歷從每個排列輸出那裏,然後Prolog的報假。這就是一種方式,這樣的事情:
show_all_heaps(List) :- perm(List, X), double(X, Y), showlist(Y), nl, fail.
show_all_heaps(_).
看看這是如何工作的:
?- show_all_heaps([1,2,3]).
[2,4,6]
[4,2,6]
[4,6,2]
[2,6,4]
[6,2,4]
[6,4,2]
true.
另一種選擇是使用findall/3
,它看起來是這樣的:
?- findall(Y, (perm([1,2,3], X), double(X, Y)), Ys).
Ys = [[2, 4, 6], [4, 2, 6], [4, 6, 2], [2, 6, 4], [6, 2, 4], [6, 4, 2]].
使用這個解決你的問題可能超出了你正在做的任何作業的範圍。
我沒有'理解你的意思「,除非你使用失敗驅動的循環或像findall/3這樣的extralogical謂詞來使所有的解決方案都找到。 – zahraTZ 2012-02-03 21:00:54
我在回答中加入了一些解釋。 – 2012-02-05 04:50:41
我們可以根據same_length/2
和select/3
這樣定義list_permutation/2
:
:- use_module(library(lists),[same_length/2,select/3]).
list_permutation(As,Bs) :-
same_length(As,Bs), % redundant goal helps termination
list_permutation_(As,Bs).
list_permutation_([],[]).
list_permutation_([A|As],Bs0) :-
select(A,Bs0,Bs),
list_permutation_(As,Bs).
感謝same_length/2
,下面兩個查詢的1,2普遍終止:
?- list_permutation([1,2,3],Ys).
Ys = [1,2,3]
; Ys = [1,3,2]
; Ys = [2,1,3]
; Ys = [3,1,2]
; Ys = [2,3,1]
; Ys = [3,2,1]
; false.
?- list_permutation(Xs,[1,2,3]).
Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
到目前爲止,太好了。但是,如果有重複的列表項,答案序列是什麼樣的?
?- list_permutation([1,1,1],Ys).
Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; false.
5/6答案是多餘的!我們可以做什麼?我們只需使用selectd/3
而不是select/3
!
list_permuted(As,Bs) :- same_length(As,Bs), list_permuted_(As,Bs). list_permuted_([],[]). list_permuted_([A|As],Bs0) :- selectd(A,Bs0,Bs), % use selectd/3, not select/3 list_permuted_(As,Bs).
讓我們重新運行上面給出5個冗餘解決方案的查詢!
?- list_permuted([1,1,1],Ys).
Ys = [1,1,1]
; false.
?- list_permuted(Xs,[1,1,1]).
Xs = [1,1,1]
; false.
更好!所有多餘的答案都消失了。
讓我們比較解決方案的一些示例情況下設置:
?- _Xs = [1,2,1,1,2,1,1,2,1], setof(Ys,list_permutation(_Xs,Ys),Yss), setof(Ys,list_permuted(_Xs,Ys),Yss), length(Yss,N). N = 84, Yss = [[1,1,1,1,1,1,2,2,2],[1,1,1,1,1,2,1,2,2],[...|...]|...].
OK!經驗運行時測量如何處理尺寸稍大的問題?
我們使用call_time/2
來測量以毫秒爲單位的運行時間T_ms
。
?- call_time(\+ (list_permutation([1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 8110.
?- call_time(\+ (list_permuted( [1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 140.
行!並且通過適當編譯if_/3
和(=)/3
,list_permuted/2
更快!
腳註1:使用SICStus Prolog的版本4.3.2(x86_64的-Linux的glibc2.12)。
腳註2:爲了便於閱讀,由Prolog頂層給出的答案已經過後處理。
請更清楚地解釋您的問題。你在跑什麼不起作用?你想看到什麼,但沒有看到,或看到你不想看到? – 2012-02-03 19:56:31
我想從用戶那裏得到一個數字列表,並顯示所有最大堆樹,所以我需要列表的排列並將它作爲參數發送給最大堆函數(對不起,因爲我的英文不好) – zahraTZ 2012-02-03 20:04:35