需要帮助理解Prolog的追加/ 3和逆/ 2和跟踪输出(Need help understandi

2019-10-30 05:20发布

这是个问题

发现价值A.


inverse([],[]).

inverse([H|T],D) :-
  inverse(T,Z),
  append(Z,[H],D).

append([],X,X).

append([X|L],M,[X|N]) :-
  append(L,M,N).

这就是答案:

普莱舍帮助我理解这一点!

Answer 1:

您发布显示一些不寻常或者很老的Prolog Prolog的代码对列表中的图像,尤其是使用的[H:T]现在进行的[H|T]注意从变化:|<=是更常见的为:-

要了解Prolog的代码更容易从下往上开始。 我将不包括统一或反向链接在本作将详细程度将需要的章节值得在这里。

第一谓词理解是附加/ 3 。 通常你不会看到对于给定的,因为它是一个内置的谓词追加的代码,但在这里它被赋予。

追加/ 3有三个参数,这些都是列表。 前两个被附加到一起以形成所述第三。

?- append_01([],[],R).
R = [].

?- append_01([a],[],R).
R = [a].

?- append_01([],[a],R).
R = [a].

?- append_01([a],[b],R).
R = [a, b].

但Prolog的谓词可以有其他的方式 ,可以将值绑定到其他编程语言,如怎样才算输入参数的操作

?- append(X,[b],[a,b]).
X = [a] ;
false.

?- append_01([a],Y,[a,b]).
Y = [b].

?- append(X,Y,[a,b]).
X = []    , Y = [a, b] ;
X = [a]   , Y = [b]    ;
X = [a, b], Y = []     ;
false.

或者可以只用于验证的参数

?- append([a],[b],[a,b]).
true.

?- append([a],[c],[a,b]).
false.

接着是其在Prolog中更通常被称为谓词逆/ 2 反转/ 2 ,并再次源代码在这里给出。

这只是需要一个列表,并逆转了,比如

?- inverse([],X).
X = [].

?- inverse([a],X).
X = [a].

?- inverse([a,b],X).
X = [b, a].

然而,这个版本的源代码不会在其他模式,比如做好

?- inverse(X,[]).
X = [] ;

Action (h for help) ? abort
% Execution Aborted

但不要紧,回答这个问题。


你贴什么接下来的部分是查询的执行一丝

?- inverse([[1,2,3],[5,4]],A).

为了使用跟踪您的代码,因为没有进行追加/ 3内置的谓词我不得不重新命名谓语。 下面是我使用的代码。

inverse([],[]).

inverse([H|T],D) :-
  inverse(T,Z),
  append_01(Z,[H],D).

append_01([],X,X).

append_01([X|L],M,[X|N]) :-
  append_01(L,M,N).

使用SWI-Prolog的

设置跟踪

?- visible(+all),leash(-all). 

启动跟踪

trace.

执行查询

[trace] ?- inverse([[1,2,3],[5,4]],A).

回报

   Call: (8) inverse([[1, 2, 3], [5, 4]], _7548)
   Unify: (8) inverse([[1, 2, 3], [5, 4]], _7548)
   Call: (9) inverse([[5, 4]], _7794)
   Unify: (9) inverse([[5, 4]], _7794)
   Call: (10) inverse([], _7794)
   Unify: (10) inverse([], [])
   Exit: (10) inverse([], [])
   Call: (10) append_01([], [[5, 4]], _7802)
   Unify: (10) append_01([], [[5, 4]], [[5, 4]])
   Exit: (10) append_01([], [[5, 4]], [[5, 4]])
   Exit: (9) inverse([[5, 4]], [[5, 4]])
   Call: (9) append_01([[5, 4]], [[1, 2, 3]], _7548)
   Unify: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4]|_7792])
   Call: (10) append_01([], [[1, 2, 3]], _7792)
   Unify: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
   Exit: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
   Exit: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4], [1, 2, 3]])
   Exit: (8) inverse([[1, 2, 3], [5, 4]], [[5, 4], [1, 2, 3]])
A = [[5, 4], [1, 2, 3]].

我不会解释一丝细节其他SO Q&A做那 。


您发布的跟踪还具有比利用生成的更详细trace ,例如绑定 (θ)。

要查看绑定使用gtrace / 0

?- gtrace.
% The graphical front-end will be used for subsequent tracing
true.

然后执行查询

[trace]?- inverse([[1,2,3],[5,4]],A).

和按空格键单个步骤。 你将不得不用它做实验,以了解它是如何工作的; 据我所知有关于如何使用它没有发过文件。


从OP评论:

有从字母数字和符号THETA一些替换,使我很难理解。

而绑定(θ)是更具体的逻辑语言 ,数字也可见于基于堆栈的功能的语言 ,见德布鲁因索引 。 此外,而不是写使用竖线分隔符( - )绑定,我更喜欢使用(↦)所看到这里 。

该线1-4只是再次陈述的源代码。

通常与跟踪目标是科维处决(呼叫)的树形结构,但这些行,除非你知道的Prolog如何工作,真的很难看到有一个树形结构。

与过杆的线是为了帮助理解正在发生的事情,但如果你只是按照执行(呼叫)的流量,那么你可能会发现像我一样,他们只是会造成混乱,可以忽略。

在你的评论中所指出的Res(_,_)是指在跟踪以前行。 等线6个RE(5,2)可以被理解为第6行是从管线5和然后调用线2的呼叫的结果。

所述unifications或绑定(θ)是展示作为作为集。 我不完全知道什么是超级亚脚本数字代表,但他们显然与德布鲁因索引。 你必须问你的老师讲解的超级子脚本。

尝试几次只是文字来解释这之后,我终于祭出使用Microsoft Visio中做到这一点的图形树这是更容易,更快,更准确。

即使是没有必要的,我加了从SWI-Prolog的输出路线追踪到图像,然后只放置在相应的地方电话线路中的树,这样,如果你想你们两个可以关联。 我这样做是为自己的检查,以确保它是正确的。

如果有几个错字的错误我不会感到惊讶,因为我不得不重做了很多次的部分,可以很容易理解。 希望我实现了这个目标。



文章来源: Need help understanding Prolog append/3 and inverse/2 and trace output