Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在命题公式中返回原子的Prolog程序_Prolog - Fatal编程技术网

在命题公式中返回原子的Prolog程序

在命题公式中返回原子的Prolog程序,prolog,Prolog,我是prolog的新手,正在尝试编写一个程序,以一个格式良好的命题公式返回原子。例如,查询ats(and(q,imp(or(p,q),neg(p)))As.应该返回[p,q]作为As。下面是我的代码,它将公式返回为as。我不知道如何将中的单个F拆分为ats中的F1和wff中的F2,因此永远不会调用wff/2。请帮我从这里开始。谢谢 代码 logical_atom( A ) :- atom( A ), atom_codes( A, [AH|_] ),

我是prolog的新手,正在尝试编写一个程序,以一个格式良好的命题公式返回原子。例如,查询
ats(and(q,imp(or(p,q),neg(p)))As.
应该返回
[p,q]
作为
As。下面是我的代码,它将公式返回为
as
。我不知道如何将
中的
单个F
拆分为
ats
中的
F1
wff
中的
F2
,因此永远不会调用
wff/2
。请帮我从这里开始。谢谢

代码

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).                            
逻辑原子(A):- 原子(A), 原子|u码(A[AH|u]), 啊>=97, 啊=<122。 wff(A):-接地(A), 逻辑_原子(A)。 wff(负(A)):-接地(A),wff(A)。 wff(或(F1,F2)):- wff(F1), wff(F2)。 wff(和(F1,F2)):- wff(F1), wff(F2)。 wff(imp(F1,F2)):- wff(F1), wff(F2)。 ats(F,As):-wff(F),集合(F,逻辑_原子(F,As)。
>P>首先,考虑使用一个更干净的表示:目前,你不能用一个普通的函子来区分原子。例如,将它们包装在
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].

我将使用“univ”操作符
=../2
和显式递归来解决这个问题。请注意,此解决方案不会生成,并且“逻辑上不正确”,因为它不会大量处理带有孔的结构,因此如果条件重新排序,它将产生不同的结果。请参见下文@mat的评论

为了个人美学,我使用了剪切而不是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仅拆卸最外层),并在查找术语时与_prop/2的
atoms_
相互递归。如果它找到了原子,它只是将它们添加到结果中

% 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].

这应该是你想要的。它提取在任意序言项中发现的唯一原子集

不过,我将把它留给您来决定什么构成“格式良好的命题公式”,正如您在问题陈述中所说的那样(您可能想看看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
  .                              %
然后,在顶层,我们有一个简单的谓词,它接受任何[component]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!

谢谢你的回答,但我需要的问题,如?wff(和(q,imp(或(p,q),neg(p))),As)。直接给我一个唯一的原子列表。我已经在上面的代码片段中定义了我的atom。你可以简单地将它添加为谓词:
wff(F,as):-phrase(wff_atoms(F),As0),sort(As0,as)。
再次感谢,但请理解我是一个新手,我真的不理解prolog程序,我真的想保留我的逻辑原子谓词和我对格式良好的命题公式的定义。我只想知道F何时从ats变为F1和F2,以及如何填充原子集。我希望我的话听起来不会让人困惑。尤其是作为一个新手,目标是清晰的表示:它们让你通过它们的函子来区分不同的实体,这样你就可以使用模式匹配,你的谓词自然地在各个方向上工作,即使它们的参数是变量。例如,您最初发布的代码没有为查询
?-wff(a)。
找到单一的解决方案,尽管它可以选择无限多个原子来提供解决方案!如果你得到了一个不干净的表示,首先要把它转换成一个干净的表示!写代码<代码> WFFCHILL/2 ,然后在干净的表示上使用<代码> WFFEXORION//< 1 /代码>。不幸的是,这会产生错误的结果:例如,考虑代码< > -AfthsIOFOPROP(和(x,a),Ls),x= b,ls=[a,b] .<代码>,失败了。然而,当你简单地通过连接的交换性来交换前两个目标时,它是成功的。@mat我很感激你指出了缺点,但这取决于OP来决定它是否是错误的。在我看来,他们在做自己的变量替换过程,所以这可能是解析树的结果,虽然是一个Prolog新手,但它不太可能包含holes.OP,也很可能知道连词应该是一个交换谓词。@mat Prolog新手通常更了解这样一个事实,即程序是在机器上执行的,而不是由逻辑学家假设的。我相信,即使你比我更了解Prolog,我比OP更了解他们的问题,OP也比我们更了解他们的问题,更愿意看到几种方法,权衡利弊,做出明智的决定,解决方案一是错误的,因为边缘案例可能根本不属于它们的问题领域。@mat我编辑了答案,以使您的评论在前面的细节中明确。如果您看到一个明显的解决方案(如果不是太狭隘或太宽泛,可能是
atom(X);var(X)
),或者如果您不喜欢我的小册子,请告诉我,我会更新答案。