我是 Prolog 的新手,我正在为大学考试学习它,我们使用 SWI Prolog
我有一些问题要理解这个简单的程序如何工作,如果列表 S 是列表 L 的子列表,则说 TRUE ,否则说谓词是 FALSE。
我有以下解决方案,但我有一些问题要理解它的声明性含义
读这本书,我想我有一些想法,但我不确定......
这是使用连接的解决方案:
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,以下两个条件:
- L 必须是一个列表,它是 L1 和 L2 的串联
- L2 必须是一个列表,它是S(我的子列表,如果存在于 L 列表中)和另一个列表 L3的串联
这是书的解释,但对我来说只是有点晦涩...
我试图对此进行推理并尝试理解真正深刻的含义......
所以我认为,在某种程度上,它就像使用这个其他程序来搜索一个元素是否是列表的成员:
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 和 L3 中分解 L2。
如果我能做最后的分解,那么程序结束,我可以说 S 是原始列表 L 的子列表是真的
如果conc(S, L3, L2)不正确,则 ddo 回溯并采用另一个计算分支
我的声明式解释是否正确?
我在这个例子中发现了很大的困难,我也试图找到一个程序解释(使用 Prolog shell 中的操作跟踪)但我有很大的问题,因为计算量对于一个简短的列表来说也是如此之大......