内置谓词的时间复杂度

时间:2017-09-29 12:21:05

标签: prolog

我一直在与prolog开展一个小项目。我注意到在删除内置谓词如append(?List1, ?List2, ?List1AndList2)subtract(+Set, +Delete, -Result)以支持其他替代方法([Head | List2]处理列表和单个元素时,编写自己的谓词以进行减法等。)

我想知道优化的内置谓词通常是如何在prolog中进行的?我读到减法的复杂性是|Delete|*|Set|,并且通过使用:

得到了相当大的增加
removeFriendsOfS(S, [Head | Tail], OutputAcc, Output) :-
    relation(S, Head),
    removeFriends(S, Tail, OutputAcc, Output), 
    !.

removeFriendsOfS(S, [Head | Tail], OutputAcc, Output) :-
    not(relation(S, Head)),
    removeFriends(S, Tail, [Head | OutputAcc], Output), 
    !.

是否建议编写自己的谓词而不是使用现有的谓词?我刚刚开始使用prolog,所以我还没那么有经验。

1 个答案:

答案 0 :(得分:2)

  

是否建议编写自己的谓词而不是使用现有谓词?

就像(可能)所有编程语言一样,通常在现有函数上编写自己的函数并不是一个好主意,因为:

  • 现有的有时在解释器中被硬编码,使它们更快;
  • 这些都经过了大量的测试,因此它们不太可能存在缺陷;
  • 大多数图书馆由专家构建:对效率,安全性,图论,计算机图形学有深入了解的人。因此,他们做出的决定在效率或其他标准方面可能并不是最好的,但在典型应用方面;和
  • 如果出现新规范,库将会更新,而您必须自己更新定制的算法。对于列表处理,这不太可能。但是,如果您要自己编写HTTP服务器,那么将来HTTP协议可能会更改您的应用程序已被弃用。

Result = [Head|Tail]优于append([Head], Tail, Result)的原因是因为,正如名称所示 - append/3两个列表附加到另一个列表中。由于Head不是列表,因此您在此处构建一个:通过编写[Head],您实际上已隐式编写[Head|[]]。因此,构建一个1元素列表(几乎)与构建一个cons [Head|Tail]一样昂贵。然后append/3将构建一个新的缺点,这也需要一些时间,而且呼叫本身也很昂贵。因此,在使用元素Tail添加列表Head时,[Head|Tail]是一种直接的方法。

removeFriendsOfS/3更快的原因是因为它除了subtract/3之外还有其它内容:它根据谓词过滤列表。 Prolog也有这个谓词exclude/3。例如:

:- use_module(library(apply)).

removeFriendsOfS(S, List, Out) :-
    exclude(relation(S), List, Out).

这适用于 O(n×k) k relations(S,X)查询的时间。