通过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中的动态编程问题的主要内容,如果未能解决你的问题,请参考以下文章

如何通过Prolog将字符串连接到列表中的多个元素?

列表中的唯一元素(Prolog)

解决Prolog中的谜题

通过 DCG 在 Prolog 中的镜头,可能与否?

Prolog:获取包含给定整数的子列表

尝试使用prolog将变量分配/提取到列表列表中的不同元素