定义逻辑程序

时间:2015-07-12 13:17:43

标签: prolog

目的是实现谓词noDupl/2

此谓词的第一个参数是要分析的列表,第二个参数是不重复的数字列表。

我无法理解下面的代码,当我编译它时,它给出了一条错误消息,contained是未定义的过程,但是作为提示我写的是我们可以用作预定义的谓词containednotContained。我想我需要定义containednotContained

noDupl(XS, Res):-
   help( XS, [],Res).

help([],_,[]).
help([X|XS],Seen,[X|Res]):-
   notContained(X,XS),
   notContained(X,Seen), 
   help(XS, [X|Seen], Res).
help([X|XS],Seen,Res):-
   contained(X,Seen),
   help(XS, Seen, Res).
help([X|XS],Seen,Res):-
   contained(X,XS),
   help(XS, [X|Seen], Res).

有人可以解释一下这个问题。

3 个答案:

答案 0 :(得分:3)

缺少的定义可能是:

memberd/2

(我喜欢将这些关系称为non_member/2:-。)

您给出的定义扩展了与目前为止考虑的元素的额外参数的关系。

要理解每个子句的含义,请按箭头方向从右向左阅读(是1970年代X的ASCII编码。让我们采取第一条规则:

  

前提是XS不是X的元素,而是   提供,Seen不是help(X, [X|Seen], Res)的元素,而是   提供,help([X|XS],Seen,[X|Res])为真,


  然后X为真。

换句话说,如果Seen既不在访问过的元素XS列表中,也不在尚未访问的元素?- noDupl([a,a,a],U). U = [] ; U = [] ; false. 中,那么它不具有重复。

有点难以理解的是,你提供的条款是否相互排斥 - 严格来说,这不是你的关注,只要你只对声明性属性感兴趣,但这是一个好主意。避免这种裁员。

这是一个案例,其中显示了这样的冗余:

?- noDupl([a,a,a], U).
U = [].

理想情况下,系统会给出一个确定的答案:

{{1}}

就个人而言,我不喜欢把事情分成太多的情况。基本上,我们可以有两个:它是重复的,它没有。

有可能提供一个正确的定义,并且仍然可以完全确定可能存在确定性的情况 - 例如当第一个参数是"充分实例化时#34; (包括地面清单)。让我们看一下这个方向是否有一些答案。

答案 1 :(得分:2)

我已为您注释了您的代码:

noDupl( XS , Res ) :- % Res is the [unique] set of element from the bag XS
  help( XS, [],Res)    % if invoking the helper succeeds.
  .                    %

help( []     , _    , []      ) .  % the empty list is unique.
help( [X|XS] , Seen , [X|Res] ) :- % A non-empty list is unique, if...
   notContained(X,XS),             % - its head (X) is not contained in its tail (XS), and
   notContained(X,Seen),           % - X has not already been seen, and
   help(XS, [X|Seen], Res).        % - the remainder of the list is unique.
help( [X|XS] , Seen , Res ) :-     % otherwise...
   contained(X,Seen) ,             % - if X has been seen,
   help(XS, Seen, Res).            % - we discard it and recurse down on the tail.
help([X|XS],Seen,Res):-            % otherwise...
   contained(X,XS),                % - if X is in the tail of the source list, 
   help(XS, [X|Seen], Res).        % - we discard it (but add it to 'seen').

您的contained/2和notContained / 2`谓词可能被定义为:

contained( X , [X|_]  ) :- ! .
contained( X , [Y|Ys] ) :- X \= Y , contained( X , Ys ) .

not_contained( _ , [] ) .
not_contained( X , [Y|Ys] ) :- X \= Y , not_contained(X,Ys) .

现在,我可能在您的代码中遗漏了一些内容,但其中存在大量冗余。你可以简单地写这样的东西(使用内置插件member/2reverse/2):

no_dupes( List , Unique ) :- no_dupes( Bag , [] , Set ) .

no_dupes( [] , V , S ) .      % if we've exhausted the bag, the list of visited items is our set (in reverse order of the source)
  reverse(V,S)                % - reverset it 
  .                           % - to put our set in source order
no_dupes( [X|Xs] , V , S ) :- % otherwise ...
  ( member(X,V) ->            % - if X is already in the set, 
    V1 = V                    % -   then we discard X
  ; V1 = [X|V]                % -   else we add X to the set 
  ) ,                         % And...
  no_dupes( Xs , V1 , S )     % we recurse down on the remainder
  .                           % Easy!

答案 2 :(得分:2)

这可以用纯粹高效的方式完成吗? ,使用 tpartition/4(=)/3就像这样:

dups_gone([]    ,[]).
dups_gone([X|Xs],Zs0) :-
   tpartition(=(X),Xs,Ts,Fs),
   if_(Ts=[], Zs0=[X|Zs], Zs0=Zs),
   dups_gone(Fs,Zs).

一些示例地面查询(所有这些查询都是确定性的):

?- dups_gone([a,a,a],Xs).
Xs = [].

?- dups_gone([a,b,c],Xs).
Xs = [a, b, c].

?- dups_gone([a,b,c,b],Xs).
Xs = [a, c].

?- dups_gone([a,b,c,b,a],Xs).
Xs = [c].

?- dups_gone([a,b,c,b,a,a,a],Xs).
Xs = [c].

?- dups_gone([a,b,c,b,a,a,a,c],Xs).
Xs = [].

这也适用于更一般的查询。考虑:

?- length(Xs,N), dups_gone(Xs,Zs).
  N = 0, Xs = [],            Zs = []
; N = 1, Xs = [_A],          Zs = [_A]
; N = 2, Xs = [_A,_A],       Zs = []
; N = 2, Xs = [_A,_B],       Zs = [_A,_B],    dif(_A,_B)
; N = 3, Xs = [_A,_A,_A],    Zs = []
; N = 3, Xs = [_A,_A,_B],    Zs = [_B],       dif(_A,_B)
; N = 3, Xs = [_A,_B,_A],    Zs = [_B],       dif(_A,_B)
; N = 3, Xs = [_B,_A,_A],    Zs = [_B],       dif(_A,_B), dif(_A,_B)
; N = 3, Xs = [_A,_B,_C],    Zs = [_A,_B,_C], dif(_A,_B), dif(_A,_C), dif(_B,_C)
; N = 4, Xs = [_A,_A,_A,_A], Zs = [] 
...