2010-10-17 27 views
1

我可以很容易地編寫一個謂詞來從Prolog中的給定列表中獲取唯一的元素,例如,序言:從命題公式獲得獨特的原子

no_doubles([], []). 
no_doubles([H|T], F) :- 
member(H, T), 
no_doubles(T, F). 
no_doubles([H|T], [H|F]) :- 
\+ member(H, T), 
no_doubles(T, F). 

但是,你怎麼能做同樣的事情,但除了普通列表之外,即不是[a,b,c ...]之類的東西?所以在我的情況下,我想爲命題公式提取獨特的原子,例如unique_atoms(和(x,和(X,Y)中,z),[X,Y,Z])。滿意。你使用遞歸就像在我的no_doubles例子中,但是對於像這樣的公式?

任何想法都歡迎:)。謝謝。

回答

1
?- setof(X, member(X,[a,b,c,a,b,c]), L). 
L = [a, b, c]. 

?- sort([a,b,c,a,b,c], L). 
L = [a, b, c]. 

命題公式:

get_atoms(X,[X]) :- 
    atom(X). 
get_atoms(and(P,Q),Atoms) :- 
    get_atoms(P,Left), 
    get_atoms(Q,Right), 
    append(Left,Right,Atoms). 

等優化必要時可使用差異表。

unique_atoms(P,UniqueAtoms) :- get_atoms(P,Atoms), sort(Atoms,UniqueAtoms). 

更直接的方法是使用sets

+0

感謝larsmans,你的get_atoms謂詞給了我一個粗略的想法,我應該做什麼,現在我已經解決了我的問題,所以謝謝你:)。我也會查看你發佈的鏈接謝謝。 – ale 2010-10-17 13:57:41

2

因此,您需要處理一個通用術語(即樹結構)並獲取其原子葉節點的列表,而不需要重複。結果列表是否必須具有特定的順序(例如深度優先從左到右),還是這不重要?

如果您可以選擇在公式中使用變量而不是原子,則可以使用(SWI-Prolog)內建term_variables/2(例如,

?- term_variables(and(X, and(X, Y), Z), Vars). 
Vars = [X, Y, Z]. 

否則,你必須去與類似的解決方案:

term_atoms(Term, AtomSet) :- 
    term_to_atomlist(Term, AtomList), 
    list_to_set(AtomList, AtomSet). 


term_to_atomlist(Atom, [Atom]) :- 
    atom(Atom), 
    !. 

term_to_atomlist(Term, AtomList) :- 
    compound(Term), 
    Term =.. [_ | SubTerms], 
    terms_to_atomlist(SubTerms, AtomList). 


terms_to_atomlist([], []). 

terms_to_atomlist([Term | Terms], AtomList) :- 
    term_to_atomlist(Term, AtomList1), 
    terms_to_atomlist(Terms, AtomList2), 
    append(AtomList1, AtomList2, AtomList). 

用例:

?- term_atoms(f(x^a1+a3*a3/a4)='P'-l, Atoms). 
Atoms = [x, a1, a3, a4, 'P', l]. 

您可能希望把它擴大到處理的葉片數和變量節點。