我有这个生成子集的序言代码。
subset([], []).
subset([E|Tail], [E|NTail]):-
subset(Tail, NTail).
subset([_|Tail], NTail):-
subset(Tail, NTail).
该代码有效,但我不知道该怎么做。我试图使用跟踪来逐步找到它的解决方案,但我根本不理解。
如果有人可以逐步引导我了解prolog如何找到它,例如
这样的简单查询的解决方案subset([1,2,3],X).
那将是最有帮助的。
答案 0 :(得分:2)
Prolog试图证明subset([1,2,3],X).
是事实。通过尝试查看是否有任何谓词支持该目标来实现此目的。
最初,它尝试subset([], []).
-失败,因为[1,2,3]
无法与[]
统一。
然后尝试subset([E|Tail], [E|NTail]):- subset(Tail, NTail).
。它可以与头部统一,因此现在尝试证明尾巴。它试图证明subset([2,3], NTail)
。
这导致证明subset([3], NTail)
(不同的NTail
),然后证明subset([], NTail)
(再次证明NTail
)。现在,它以subset([], []).
成功-终止深度优先搜索,然后继续进行调用堆栈的构建,建立X
的结果-[1|[2|[3|[]]]]
或[1, 2, 3]
结果是,目标?- subset([1,2,3],X).
成功了[1, 2, 3]
。
现在,如果您要求Prolog提供第二个答案,则它将查看成功的最后一个谓词,并假定失败。这就是目标subset([], NTail)
。没有可以成功实现该目标的谓词,因此它又退了一步。用subset([3], NTail)
证明了subset([E|Tail], [E|NTail]):- subset(Tail, NTail).
,但现在它会假设失败了,因此继续进行并尝试subset([_|Tail], NTail):- subset(Tail, NTail).
成功,并有效地丢弃了3
,因此像以前一样继续继续证明目标。最终得到[1, 2]
。
如果您要求Prolog给出另一个答案,它将继续使用这种方法,返回并找到成功的最后一件事情,并假设它失败并继续。
最终您会得到以下结果:
[1, 2, 3] [1, 2] [1, 3] [1] [2, 3] [2] [3] []