我是prolog的新手,我正在尝试编写一个程序,在一个形成良好的命题公式中返回atoms
。例如,查询ats(and(q, imp(or(p, q), neg(p))), As).
应该为[p,q]
返回As
。下面是我的代码,它将公式返回为As
。我不知道如何分割single F
中的ats
和F1
中的F2
以及wff
永远不会被调用的wff/2
。我需要帮助才能从这里开始。感谢。
CODE
logical_atom( A ) :-
atom( A ),
atom_codes( A, [AH|_] ),
AH >= 97,
AH =< 122.
wff(A):- ground(A),
logical_atom(A).
wff(neg(A)) :- ground(A),wff(A).
wff(or(F1,F2)) :-
wff(F1),
wff(F2).
wff(and(F1,F2)) :-
wff(F1),
wff(F2).
wff(imp(F1,F2)) :-
wff(F1),
wff(F2).
ats(F, As):- wff(F), setof(F, logical_atom(F), As).
答案 0 :(得分:3)
首先,考虑使用更清晰的表示:目前,您无法通过共同的仿函数区分原子。因此,请将它们包装在a(Atom)
。
其次,使用DCG描述格式良好的公式与其原子列表之间的关系,如:
wff_atoms(a(A)) --> [A].
wff_atoms(neg(F)) --> wff_atoms(F).
wff_atoms(or(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
wff_atoms(and(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
wff_atoms(imp(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
示例查询及其结果:
?- phrase(wff_atoms(and(a(q), imp(or(a(p), a(q)), neg(a(p))))), As).
As = [q, p, q, p].
答案 1 :(得分:1)
我使用&#34; univ&#34;来解决这个问题。 operator =../2
和显式递归。请注意,此解决方案不会生成,也不会在逻辑上正确无误。因为它不会慷慨地处理带孔的结构,所以如果重新排序条件会产生不同的结果。请参阅以下@ mat的评论。
我使用cut而不是if语句来表达个人美学;使用大型显式条件树肯定会找到更好的性能。我不确定你是否希望首先产生这样的谓词。
Univ非常方便,因为它可以让您像处理Lisp中的复杂s表达式一样处理Prolog术语:它将术语转换为原子列表。这使您可以将Prolog术语作为列表进行遍历,如果您不确定要处理的是什么,这将非常方便。它使我免于必须明确地查找你的布尔运算符。
atoms_of_prop(Prop, Atoms) :-
% discard the head of the term ('and', 'imp', etc.)
Prop =.. [_|PropItems],
collect_atoms(PropItems, AtomsUnsorted),
% sorting makes the list unique in Prolog
sort(AtomsUnsorted, Atoms).
辅助谓词collect_atoms/2
处理术语列表(univ仅拆除最外层),并在找到术语时与atoms_of_prop/2
相互递归。如果它找到原子,它只是将它们添加到结果中。
% base case
collect_atoms([], []).
% handle atoms
collect_atoms([A|Ps], [A|Rest]) :-
% you could replace the next test with logical_atom/1
atom(A), !,
collect_atoms(Ps, Rest).
% handle terms
collect_atoms([P|Ps], Rest) :-
compound(P), !, % compound/1 tests for terms
atoms_of_prop(P, PAtoms),
collect_atoms(Ps, PsAtoms),
append(PAtoms, PsAtoms, Rest).
% ignore everything else
collect_atoms([_|Ps], Rest) :- atoms_of_prop(Ps, Rest).
这适用于您的示例:
?- atoms_of_prop(ats(and(q, imp(or(p, q), neg(p))), As), Atoms).
Atoms = [p, q].
答案 2 :(得分:1)
这应该做你想要的。它提取任何任意序言中的唯一原子集。
我会告诉你,当你把它放在你的问题陈述中时,确定什么构成了“格式良好的命题公式”(你可能想看看DCG用于解析和验证)。
大部分工作都是通过这个“工人谓词”来完成的。它只是通过回溯一次一个地提取解析树中找到的任何原子并丢弃其他任何原子:
expression_atom( [T|_] , T ) :- % Case #1: head of list is an ordinary atom
atom(T) , % - verify that the head of the list is an atom.
T \= [] % - and not an empty list
. %
expression_atom( [T|_] , A ) :- % Case #2: head of listl is a compound term
compound(T) , % - verify that the head of the list is a compound term
T =.. [_|Ts] , % - decompose it, discarding the functor and keeping the arguments
expression_atom(Ts,A) % - recurse down on the term's arguments
. %
expression_atom( [_|Ts] , A ) :- % Finally, on backtracking,
expression_atom(Ts,A) % - we simply discard the head and recurse down on the tail
. %
然后,在顶层,我们有这个简单的谓词接受任何[复合] prolog术语,并通过setof/3
提取工作者谓词中找到的唯一原子集:
expression_atoms( T , As ) :- % To get the set of unique atoms in an arbitrary term,
compound(T) , % - ensure that's its a compound term,
T =.. [_|Ts] , % - decompose it, discarding the functor and keeping the arguments
setof(A,expression_atom(Ts,A),As) % - invoke the worker predicate via setof/3
. % Easy!