繁体   English   中英

Prolog中计算列表长度的不同方法

[英]Different ways of computing list length in Prolog

以下是 Prolog 中计算列表长度的 4 种不同方法:

:- use_module(library(clpz)).

list_length1([], 0).
list_length1([_|T], N) :-
    N #> 0,
    N1 #= N - 1,
    list_length1(T, N1).


list_length2(A, N) :-
    N #>= 0,
    list_length2(A, 0, N).

list_length2([], N, N).
list_length2([_|T], I, N) :-
    I #< N,
    I1 #= I + 1,
    list_length2(T, I1, N).


list_length3(A, N) :-
    list_length3(A, 0, N).

list_length3([], N, N).
list_length3([_|T], I, N) :-
    I1 is I + 1,
    list_length3(T, I1, N).


list_length4([], 0).
list_length4([_|T], N) :-
    list_length4(T, N0),
    N is N0 + 1.
  • list_length1 - 数学简单,适用于所有方向
  • list_length2 - 不知道这有什么用,通过类比创建
  • list_length3 - 上次调用优化,仅在一个方向上工作
  • list_length4 - 递归,单向工作

list_length2list_length4有什么优点吗?

list_length2 - 不知道这有什么用,通过类比创建

为了更好地理解版本 1 和 2 之间的区别,请考虑对谓词进行概括 粗略的概括。 只需添加事实list_length1(_,_). list_length2(_, _, _). 在他们的定义前面。 现在从声明的角度来看,这些定义变得毫无用处。 但是从程序的角度来看,我们现在得到了一些有用的提示:

?- list_length1("abc",N).
   true
;  clpz:(_A+1#=N), clpz:(N in 1..sup), clpz:(_A in 0..sup)
;  clpz:(_A+1#=N), clpz:(_B+1#=_A), clpz:(N in 2..sup), clpz:(_A in 1..sup), clpz:(_B in 0..sup)
;  clpz:(_A+1#=N), clpz:(_B+1#=_A), clpz:(_C+1#=_B), clpz:(N in 3..sup), clpz:(_A in 2..sup), clpz:(_B in 1..sup), clpz:(_C in 0..sup)
;  N = 3.
?- list_length2("abc",N).
   clpz:(N in 0..sup)
;  clpz:(N in 1..sup)
;  clpz:(N in 2..sup)
;  clpz:(N in 3..sup)
;  N = 3.

因此,版本 1 必须创建一系列微不足道的算术关系及其伴随的变量,这些变量与列表的长度成正比,这些变量将通过每次进一步的推理而更新,并且会在最后一刻崩溃,而版本 2 很满意单个域(在这种情况下是无限的)越来越受到每一步的约束。

(与I相关的操作实际上都是微不足道(is)/2计算。)

尝试?- list_length2(L,N), N = 10000.查看性能方面的差异。

理论上,版本 1 可以避免创建这些琐碎的关系并更新单个变量以避免中间变量,但到目前为止我还没有看到能够做到这一点的系统。 即使有这样的系统,版本 1 仍然会比版本 2 慢,后者只对单个变量感到满意。

list_length4有什么优点吗?

这个版本以非常昂贵、不必要的二次方方式产生答案。 对于list_length4(L, N)的每个进一步答案,它需要与L的长度成比例的时间。 尝试,例如?- list_length3(L,N), N = 10000.并将其与版本 4 进行比较。

为了数学上的简单明了,请考虑在您的程序中使用(#)/1 所以代替N #>= 0只需写#N #>= 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM