【问题标题】:Need help understanding Prolog append/3 and inverse/2 and trace output需要帮助理解 Prolog append/3 和 inverse/2 并跟踪输出
【发布时间】:2018-12-17 14:50:29
【问题描述】:

这是问题

求值 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).

这就是答案:

请帮助我理解这一点!

【问题讨论】:

  • 你了解统一的工作原理吗?
  • 对不起,我下次会小心的。
  • 我不知道如何将图像转换为代码。
  • 我第一次做关于 prolog 的练习,我不知道从哪里开始。
  • @WillNess 仅供参考。当我需要在文档中插入特殊字符并且编辑器不支持富字符搜索选项时,我使用Shapecatcher。使用它你可以绘制字符,然后它会返回字符、名称,甚至是它的 Unicode 代码。一旦你使用它几次,你就不会害怕再次使用特殊的章程,只有糟糕的编辑。好的部分是,一旦您经常找到您想要的字符,只需将其粘贴到您的文档中即可。

标签: algorithm prolog logic-programming


【解决方案1】:

您发布的 Prolog 代码图像显示了一些不寻常或非常旧的 Prolog,特别是列表中 [H:T] 的使用现在已完成为 [H|T],请注意从 :| 的更改,并且<= 更常见于 :-

要理解 Prolog 代码,从下往上开始会更容易。我不会在此介绍unificationbackward chaining,因为要达到那种详细程度需要在这里值得一章。

第一个要理解的谓词是append/3。通常你永远不会看到给出的附加代码,因为它是一个内置的谓词,但这里给出了它。

Append/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 谓词可以有其他 modes 操作,可以将值绑定到其他编程语言中被视为输入参数的值,例如

?- 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.

接下来是谓词inverse/2,在Prolog中更常见的是reverse/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).

为了在您的代码中使用跟踪,因为有一个用于 append/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 that 那样解释跟踪的细节。


您发布的跟踪也比使用trace 生成的更详细,例如bindings (θ)。

要查看绑定,请使用gtrace/0

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

然后执行查询

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

然后按空格键单步。您将不得不尝试它以了解它是如何工作的; AFAIK 没有发布关于如何使用它的文档。


来自 OP 评论:

从字母到数字和 theta 符号的一些替换让我难以理解。

虽然绑定 (θ) 更特定于 logic languages,但这些数字也可以在基于堆栈的 functional languages 中看到,请参阅 De Bruijn index。此外,我更喜欢使用 (↦),而不是使用垂直行分隔符 (---) 编写绑定,如 here 所示。

第 1 -4 行只是再次说明的源代码。

通常使用跟踪的目标是传达执行(调用)的树结构,但是除非您知道 Prolog 是如何工作的,否则这些行很难看出存在树结构。

带有横线的线条旨在帮助了解正在发生的事情,但是如果您只是按照执行(调用)的流程,那么您可能会像我一样发现它们只会引起混乱并且可以忽略。

您在 cmets 中指出,Res(_,_) 指的是跟踪中的前几行。所以第 6 行的 Res(5,2) 可以被解读为第 6 行是第 5 行调用的结果,然后调用第 2 行。

统一或绑定 (θ) 显示为集合。我不确定超级和子脚本数字代表什么,但它们显然与 De Bruijn 索引相关联。您将不得不请您的老师解释超级脚本和子脚本。

在尝试用文字解释了好几次之后,我终于求助于使用 Microsoft Visio 来做图形树,它更容易、更快、更准确。

即使不需要,我还是将 SWI-Prolog 的线路跟踪输出添加到图像中,然后只将调用线路放置在树中的相应位置,这样如果您想将两者关联起来,您可以。我为自己做了检查以确保它是正确的。

如果有一些拼写错误,我不会感到惊讶,因为我必须多次重做部分内容以使其易于理解。希望我实现了这个目标。

【讨论】:

  • 我的老师要求我展示我的练习,就像我发布的第二张图片一样。还有一些我不明白的步骤。
  • 他是一位老老师,他教我们用老方法做作业。
  • 我老师的电话------inverse是inverse的负数,RES(5, 2)表示连接第5步和第2步。
  • 我的老师告诉我们要了解计算机对 Prolog 的作用,而不是程序的运行方式。
  • 我了解 Prolog 的工作原理,但我的数学老师强迫我们用数学术语来解决它。幸运的是,我能够通过解决“否定命题”(我的老师这样称呼它)来解决它。我的老师希望学生了解机器如何与 Prolog 一起工作,但是以否定证明的形式(从下到上),它与您向我解释的内容略有相反。 XD
猜你喜欢
  • 2021-10-23
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 1970-01-01
相关资源
最近更新 更多