【问题标题】:Prolog sublist RelationProlog 子列表关系
【发布时间】:2019-01-25 17:28:53
【问题描述】:

我正在阅读 Ivan Bratko 的 Prolog Programming for Artificial Intelligence 一书,但我之前没有使用 Prolog 的经验。在书中,列表的子列表关系被表述为:

S is a sublist of L if:
1) L can be decomposed into two lists, L1 and L2, and
2) L2 can be decomposed into two lists, S and some L3.

关系如下:

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

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

我觉得奇怪为什么我们不只是将列表分解为两个列表并检查其中一个列表是否与 S 匹配?

【问题讨论】:

  • conc(L1, L2, L) 正在将列表分解为两个列表;因此,您建议的实现看起来像sublist(S, L) :- conc(_, S, L) ; conc(S, _, L). 如果您使用sublist(S, [1,2,3,4]) 查看该实现的输出,您会注意到永远不会生成[2,3],但是您会得到所有以 1 开头的子列表以及所有以 1 结尾的子列表4.

标签: list prolog sublist difference-lists


【解决方案1】:

我觉得你写的时候很亲近:

我觉得很奇怪,为什么我们不只是将列表分解为 两个 列表并检查其中一个列表是否与 S 匹配?

只需将列表 L 分解为 三个 列表即可:

  • L1 是在子列表(“前缀”)之前的列表,
  • S 是子列表本身,并且
  • L3 是子列表(“后缀”)之后的列表。

由于conc/3 只能连接(或分解)两个列表 - 而不是三个 - 两个 conc/3 目标的连接是必需的。

conc(L1,L2,L), conc(S,L3,L2)表示上述关系。

【讨论】:

  • 我明白了。为什么使用 /3 或 /* 后缀?
  • 考虑用二元运算符表示 3 个数字的总和。就像加法一样,串联是关联的。所以我们可以把L1 + S + L3 = L写成(L1 + S) + L3 = L或者(像上面一样)写成L1 + (S + L3) = L
  • @TolgaKarahan /* 是一个指标:length/2 是二元谓词(带有两个参数),append/3 是三元谓词(带有三个参数)。同名可用于定义具有不同参数的谓词。
  • 是的,我注意到了。谢谢。
【解决方案2】:

这应该会有所帮助;关键字/概念是difference list

来自Attila Csenki 的“Prolog 技术”,第 2 章(带有嵌入广告的免费 PDF

书中稍晚一点的是这张图片


书的第二部分实际上是一本单独的书,

Attila Csenki 的“Prolog 应用”(免费 PDF 嵌入广告)

【讨论】:

  • 谢谢。我会检查一下。
  • 从技术上讲,虽然一个术语是差异列表,但[a,b,c|X]-X 并不真正意味着[a,b,c|X] 减去X,如图所示。术语的-X 部分允许使用列表外部的显式变量访问列表的尾部。因此,您可能会在某个时候将[a,b,c|X]-XL-T 统一起来。在这种情况下,T 将是L 的尾部。 [a,b,c|X]-X 术语实际上包含了整个列表,[a,b,c|X]X 通常被称为hole。见Open Lists and Difference Lists
  • 虽然difference-lists 是一个有价值的概念,但这个问题实际上并不需要 差异列表。所以一个更简单的答案可能会更有帮助。
  • 有趣的旁注:这是多年来我在WolrdCat 找不到标题、作者或 ISBN 的第一本书。国际标准书号:978-87-7681-476-2
【解决方案3】:

为了比较,Logtalk库中使用的sublist/2谓词的定义是:

sublist(List, List).
sublist(Sublist, [Head| Tail]) :-
    sublist(Tail, Head, Sublist).

sublist(Sublist, _, Sublist).
sublist([Head| Tail], _, Sublist) :-
    sublist(Tail, Head, Sublist).
sublist([Head| Tail], Element, [Element| Sublist]) :-
    sublist(Tail, Head, Sublist).

IIRC,这是一个通用定义。一些示例调用可能是:

?- list::sublist(Sublist, [1,2,3]).
Sublist = [1, 2, 3] ;
Sublist = [2, 3] ;
Sublist = [3] ;
Sublist = [] ;
Sublist = [2] ;
Sublist = [1, 3] ;
Sublist = [1] ;
Sublist = [1, 2].

?- list::sublist([1,2], List).
List = [1, 2] ;
List = [_1376, 1, 2] ;
List = [_1376, _1382, 1, 2] ;
List = [_1376, _1382, _1388, 1, 2] ;
...

?- list::sublist(Sublist, List).
Sublist = List ;
List = [_1172|Sublist] ;
List = [_1172, _1178|Sublist] ;
List = [_1172, _1178, _1184|Sublist] .
...

更新

注意到问题中的定义和我的答案中的定义没有相同的语义。问题中的定义意味着连续的元素。例如

?- sublist(Sublist, [1,2,3]).
Sublist = [] ;
Sublist = [1] ;
Sublist = [1, 2] ;
Sublist = [1, 2, 3] ;
Sublist = [] ;
Sublist = [2] ;
Sublist = [2, 3] ;
Sublist = [] ;
Sublist = [3] ;
Sublist = [] ;
false.

此定义中的一个问题是多次生成空列表解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    相关资源
    最近更新 更多