通过corecursion解决Prolog中的动态编程问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过corecursion解决Prolog中的动态编程问题相关的知识,希望对你有一定的参考价值。
我想在Prolog中通过problem解决以下动态编程corecursion。但我仍然坚持做一个广泛的第一次搜索,我想以一种纠正的方式实现:
有一层n层楼的电梯,一次只能上2层,一层下3层。使用动态编程编写一个函数,该函数将计算电梯从楼层i到楼层j所需的步数。
我已经决定了一个懒惰的列表表示。一个懒惰的列表只是一个Prolog闭包C,可以调用它来产生一个头部和尾部的新闭包。
一个流的示例:
one(1, one).
然后可以简单地将Haskell take谓词编码如下:
take(0, _, L) :- !, L = [].
take(N, C, [X|L]) :- N > 0,
call(C, X, D),
M is N-1,
take(M, D, L).
这是一个示例运行:
?- take(5, one, X).
X = [1, 1, 1, 1, 1].
?- take(10, one, X).
X = [1, 1, 1, 1, 1, 1, 1, 1, 1|...].
在这个共同递归的Prolog solution中,我们需要两个构建块。
一个构建块是一种在Prolog中以递归方式枚举搜索树的方法。我们采用Prolog闭包术语应该带有路径的议程以及应该扩展的节点的想法。然后我们可以从只包含根的议程开始:
% tree(-Path, -LazyPaths)
tree(H, T) :-
tree([[]], H, T).
要存档广度优先枚举,我们将在议程结尾附加新的扩展路径,从而追加节点。这可以通过简单的列表追加谓词调用来完成,因此缺少的定义如下所示。在完整的二叉树路径中,节点总是扩展两次:
% tree(+Paths, -Path, -LazyPaths)
tree([X|Y], X, tree(Z)) :-
append(Y, [[0|X],[1|X]], Z).
这是一个示例运行:
?- take(5, tree, L).
L = [[],[0],[1],[0,0],[1,0]]
?- take(10, tree, L).
L = [[],[0],[1],[0,0],[1,0],[0,1],[1,1],[0,0,0],[1,0,0],[0,1,0]]
在评估者问题的情况下,我们将有一个路径,因此节点扩展不会总是导致两个后继者。如果我们处于k级,电梯可以达到k + 2或k-3级,只要电梯停留在建筑物内。因此,我们读到了一个共同递归的谓词步骤,它模拟了电梯的所有可能路径:
?- take(5, steps(7,[[2]]), L).
L = [[2],[4,2],[1,4,2],[6,4,2],[3,1,4,2]]
?- take(10, steps(7,[[2]]), L).
L = [[2],[4,2],[1,4,2],[6,4,2],[3,1,4,2],[3,6,4,2],
[5,3,1,4,2],[5,3,6,4,2],[2,5,3,1,4,2],[7,5,3,1,4,2]]
最后一个障碍和第二个构建块是在Prolog中获取Haskell dropWhile。我们没有针对一个谓词,该谓词为布尔条件采用Prolog闭包项参数,而是仅提供枚举惰性列表元素的谓词,并且谓词的用户可以在Prolog延续中进行过滤。
% drop_while(+LazyList, -Element)
drop_while(C, P) :-
call(C, Q, T),
(P = Q; drop_while(T, P)).
如果我们将所有内容组合在一起,我们会得到一个共同重复的Prolog解决方案,除了以广度优先顺序计算结果之外,甚至可以通过回溯计算所有无限解决方案问题的解决方案:
?- elevator(7,2,6,L), length(L,N).
L = [6,4,2],
N = 3 ;
L = [6,4,2,5,3,1,4,2],
N = 8 ;
L = [6,4,7,5,3,1,4,2],
N = 8
以上是关于通过corecursion解决Prolog中的动态编程问题的主要内容,如果未能解决你的问题,请参考以下文章