【问题标题】:Declarative interpretation of a Prolog program that says if a list S is a sublist of another list LProlog 程序的声明式解释,说明列表 S 是否是另一个列表 L 的子列表
【发布时间】:2013-03-25 15:43:09
【问题描述】:

我是 Prolog 的新手,我正在为大学考试学习它,我们使用 SWI Prolog

我很难理解这个简单的程序是如何工作的

我有以下解决方案,但我在理解它的声明性含义时遇到了一些问题

读这本书,我觉得我有一些想法,但我不确定......

这是使用连接的解决方案:

sublist(S,L) :- conc(L1, L2, L),
            conc(S, L3, L2).

conc([],L,L).

conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3).

如果第三个列表是第一个和第二个列表的连接,则此解决方案使用另一个响应 TRUE 的小程序。

要说如果 L 的 S i 子列表必须为 TRUE,以下两个条件:

  1. L 必须是 L1 和 L2 的串联列表
  2. L2 必须是一个列表,它是 S(我的子列表,如果存在于 L 列表中)和另一个列表 L3
  3. 的串联

这是书的解释,但对我来说有点晦涩......

我已经试着去推理它并试图理解它的真正含义......

所以我认为,在某种程度上,它就像使用这个其他程序来搜索一个元素是否是列表的成员:

member2(X, [X|_]).

member2(X,[_|T]):- member2(X,T).

在这个程序中,我只是说如果 X 是列表顶部的元素(它的头部),那么 X 在列表中并且程序响应为真。否则,如果 X 元素不在列表顶部(或者它不是我的解决方案),我会尝试在此列表的 TAIL T 中搜索它。

回到子列表程序我觉得道理差不多

首先我将 L 列表分解为两个列表 L1 和 L2(使用 conc 程序)**

然后我检查一下S和L3的串联是否是L2列表。

如果展位这些条件为真,则 S 是 L 的子列表

我认为L1列表与我在成员程序中从列表中提取的X元素的作用相似。

由于子列表 S 可以从列表 L 的开头开始,因此 L1 可以是 [] 并且我可以在 L1=[] 和 L2 的串联中分解 L 并且我可以尝试在 S 中分解 L2和 L3。

如果我能做最后的分解,那么程序结束,我可以说 S 是原始列表 L 的子列表是真的

如果 conc(S, L3, L2) 不正确,则 ddo 回溯并采用另一个计算分支

我的声明式解释对吗?

我在这个例子中发现了很大的困难,我也试图找到一个程序解释(使用 Prolog shell 中的操作跟踪),但我有很大的问题,因为计算量对于一个简短的列表来说也是如此之大.. .

【问题讨论】:

  • 您介意使用拼写检查器吗?

标签: prolog declarative


【解决方案1】:

这本书的解释更具说明性,因为它没有调用 Prolog 的搜索机制。我可能会用更多的下划线来写这个:

sublist(S, L) :- append(_, Suffix, L), append(S, _, Suffix).

这至少让S和L2(改名为Suffix)的关系更清晰了一点。我们想说的是,这很难用声明性英语清楚地表达出来,如果有一个 L 的后缀称为 Suffix 并且 S 是 Suffix 的前缀,则 S 是 L 的子列表 .命名其他成分只会增加混乱。 Prolog 将在内部命名这些变量并与它们统一一些东西,因为它试图统一其他所有东西,但它不会与调用者共享该信息。尽管这些变量在某种意义上需要存在,但它们与您的公式没有密切关系,或者它们不会是单例。每当您收到单例变量警告时,请将变量替换为下划线。它会增加清晰度。

由于涉及的前缀和后缀可以是空列表,所以 S 可以是 L 的适当前缀或 L 的适当后缀,一切都会好起来的。

member/2 的声明式解读,供参考,如果 X 是列表的头部或 X 是列表尾部的成员,则 X 是列表的成员。仔细注意缺少的内容:提到检查、成功或失败,或者实际上是任何操作顺序。 如果 X 是尾部的成员或头部的成员,则说 X 是列表的成员同样具有声明性。 让计算机执行计算它必须按照一定的顺序进行,所以你必须按照正确的顺序告诉 Prolog 事情,否则它会进入无限循环,但这不是逻辑的一个方面,只是 Prolog。

正如我们多次讨论过的,当您调用 Prolog 的机制时,您不再处于声明式阅读中。因此,当您说“首先我分解...”时,您已经离开了声明性世界并进入了程序性世界。声明性世界没有步骤,即使 Prolog 必须按照特定顺序执行操作才能在现实生活中的计算机上执行计算。同样,在声明式阅读中,您不会检查事物,它们只是存在或不存在。 backtrack 这个词也不能作为陈述性阅读的一部分出现。在陈述性阅读中你应该使用的唯一“动词”是“存在”动词,“是”。

也就是说,您的 Prolog/程序读数完全正确。

【讨论】:

  • 我基于信任接受您的回复,现在我读得很好,并尝试完全理解您的解释:-)您认为当时这是正常的吗,因为我可以理解像这样的解决方案(长时间学习并有很多疑问)但我无法自己找到它? (我的意思是不看书)
  • 好吧,我不是 S.O. 上唯一的人。有话要说; CapelliC 和 false 都对我有数十年的经验,并且可能会纠正我,而且还有很多其他人。我会再等一会儿才能接受,但我很感激你信任我。 :) 是的,我认为这很正常,尤其是如果您有其他语言的编程经验。 Prolog 非常不同,需要很长时间才能开始理解。但我认为你走在了前面,练习会让你走得更远。继续做你正在做的事情! :)
  • 我接受你的回答,因为我已经快速阅读它并且我发现它很好,现在我正在学习它:-)
  • 我的电子邮件地址在我的个人资料中。如果你给我发一封电子邮件,我们可以更互动地来回做这件事,也许能让你更快地为考试做好准备。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多