List Prolog子列表关系

List Prolog子列表关系,list,prolog,sublist,difference-lists,List,Prolog,Sublist,Difference Lists,我正在读Ivan Bratko的《人工智能的Prolog编程》一书,我以前没有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),

我正在读Ivan Bratko的《人工智能的Prolog编程》一书,我以前没有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匹配?

这应该会有帮助;关键词/概念是
差异列表

摘自第2章“Prolog技术”(免费嵌入广告)

书中后面一点就是这个图像


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


“Prolog的应用程序”(免费嵌入ads)

出于比较目的,Logtalk库中使用的
子列表/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.

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

我感觉您在编写以下内容时非常接近:

我觉得奇怪,为什么我们不把列表分解成两个列表,然后检查其中一个列表是否与S匹配

只要将列表
L
分解为三个列表,您就可以:

  • L1
    是子列表(“前缀”)前面的列表
  • S
    是子列表本身,并且
  • L3
    是子列表(“后缀”)后面的列表
由于
conc/3
只能连接(或分解)两个列表,而不是三个-需要两个
conc/3
目标的连接


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

谢谢。我将对此进行研究。从技术上讲,尽管有一个术语是差异列表,
[a,b,c | X]-X
并不真正意味着
[a,b,c | X]
减去
X
,如图所示。术语的
-X
部分使用列表外部的显式变量访问列表的尾部。因此,您可能会在某个点将
[a,b,c | X]-X
L-T
统一起来。在这种情况下,
T
将是
L
的尾部。
[a,b,c | X]-X这个术语实际上包含了整个列表,
[a,b,c | X]
X
通常被称为孔。请看。虽然这是一个有价值的概念,但这个问题实际上不需要差异列表。因此,一个简单的答案可能会更有帮助。有趣的旁注:这是我多年来第一本无论是书名、作者还是ISBN都找不到的书。ISBN:
978-87-7681-476-2
conc(L1,L2,L)
正在将列表分解为两个列表;因此,建议的实现看起来像
子列表(S,L):-conc(z,S,L);conc(S,u,L)。
如果你用
子列表(S,[1,2,3,4])
查看该实现的输出,你会注意到
[2,3]
从未生成,但是你会得到所有子列表,从1开始,也从4结束。我理解。为什么要使用/3或/*后缀?请考虑使用二进制运算符表示3个数字的和。与加法一样,串联也是关联的。所以我们可以把
L1+S+L3=L
写成
(L1+S)+L3=L
或者(像上面那样)写成
L1+(S+L3)=L
@TolgaKarahan
/*
是一个算术指标:
length/2
是一个二元谓词(有两个参数),
append/3
是三元谓词(有三个参数)。相同的名称可以用来定义不同算术的谓词。是的,我注意到了。非常感谢。