我可以轻松编写一个谓词来从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示例中那样使用递归,但对于这样的公式?
欢迎任何想法:)。感谢。
答案 0 :(得分: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].
您可能希望扩展它以处理叶节点中的数字和变量。
答案 1 :(得分: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。