2012-04-15 17 views
4

替換列表的元素我有一個謂語variablize/3是獲得一個列表,並替換每個項目,反過來,有一個變量,例如:在序言

 
% ?- variablize([a,b,c], X, L). 
% L = [[X, b, c], [a, X, c], [a, b, X]] 

現在我要擴展這個謂詞接受變量列表,例如:

 
% ?- variablize([a,b,c], [X,Y], L). 
% L = [[X, Y, c], [X, b, Y], [a, X, Y]] 

到目前爲止我的代碼是:

 
replace_at([_|Tail], X, 1, [X|Tail]). 
replace_at([Head|Tail], X, N, [Head|R]) :- M is N - 1, replace_at(Tail, X, M, R). 

replace_each([], _, _, [], _). 
replace_each([_|Next], Orig, X, [Res|L], N) :- 
    replace_at(Orig, X, N, Res), 
    M is N + 1, 
    replace_each(Next, Orig, X, L, M). 

variablize(I, X, L) :- replace_each(I, I, X, L, 1). 

任何指針?我是否擴展replace_at/4以擁有應該跳過的索引列表?

+1

這是非常不尋常的寫到哪nonvariable項由變量替換謂詞。你能解釋爲什麼你需要這個嗎?大多數情況下,相反地構建術語要有效得多。 – false 2012-04-16 18:18:05

+0

@false我將它用於基本的NLP。用戶可以輸入'變量'('[employees,of,acme]')而不是模型中的術語('[employees,of,company]'),因此我可以建議該單詞的'type'類型搜索數據庫索引。我是這個初學者,所以我沒有做任何愚蠢的事情嗎? – Radek 2012-04-16 22:24:11

+1

它確實在你的上下文中有意義。然而,你的程序中必須有很多'var/1''nonvar/1'測試。你可以(也許)避免其中的一些。 – false 2012-04-16 22:33:15

回答

2

實施variablize/3

variablize(I, X, L) :- 
    bagof(R, U^select(U, I, X, R), L). 

提出作爲證據的簡化,內置基於的方式,而不是select/4,我們可以有一個分發/ 3應用於X的元素替換,當X成爲名單。選擇/ 4可以通過這種方式

myselect(B, I, X, R) :- 
    append(A, [B|C], I), append(A, [X|C], R). 

來實現,並且這種形式很方便,因爲我們有部分輸入列表I權,在這裏我想你需要分發尚存變數。然後在X元素遞歸應該做的:

distribute(I, [X|Xs], L) :- 
    append(A, [_|C], I), 
    distribute(C, Xs, R), 
    append(A, [X|R], L). 
distribute(I, [], I). 

分發/ 3的行爲是這樣的:

?- distribute([a,b,c,d],[1,2],X). 
X = [1, 2, c, d] ; 
X = [1, b, 2, d] ; 
X = [1, b, c, 2] ; 
X = [a, 1, 2, d] ; 
X = [a, 1, c, 2] ; 
X = [a, b, 1, 2] ; 
false. 

從而

variablize_l(I, X, L) :- 
    bagof(R, distribute(I, X, R), L). 

給我們:

?- variablize_l([a,b,c],[X,Y],L). 
L = [[X, Y, c], [X, b, Y], [a, X, Y]]. 

Ë DIT

我最初寫這個方式,從列表構造分離分佈相這裏的證據:

replace_v([_|T], X, [X|T]). 
replace_v([L|T], X, [L|R]) :- 
    replace_v(T, X, R). 
variablize(I, X, L) :- 
    bagof(E, replace_v(I, X, E), L). 
+0

謝謝@chac!我將學習分發/ 3更多並使用write/1輸出Prolog中的所有樹。 – Radek 2012-04-15 15:40:04

0
variablize(L1,L2,L) :- 
    append(L1,L2,L3), 
    length(L1,Len1), 
    length(L2,Len2), 
    findall(L4,(combination(L3,Len1,L4),var_count(L4,Len2)),L). 

combination(X,1,[A]) :- 
    member(A,X). 
combination([A|Y],N,[A|X]) :- 
    N > 1, 
    M is N - 1, 
    combination(Y,M,X). 
combination([_|Y],N,A) :- 
    N > 1, 
    combination(Y,N,A). 

var_count([],0). 
var_count([V|R],N) :- 
    var(V), 
    var_count(R,N1), 
    N is N1 + 1, 
    !. 
var_count([A|R],N) :- 
    var_count(R,N).