我怎么知道clpfd程序的计算复杂度是什么?

时间:2019-03-04 00:19:28

标签: prolog clpfd

例如,说我有这个程序(仅在swi-prolog中测试过):

:- use_module(library(clpfd)).
:- use_module(library(lists)).

% Sorted has the same elements as List and is also sorted
clpfd_sort(List, Sorted) :-
  same_length(List, Sorted),
  chain(Sorted, #=<),
  permutation(List, Sorted).

在哪里可以找到有关clpfd如何工作的足够信息,以了解这是否是有效的解决方案?要求这样一个简单的解决方案为n lg(n)可能有点贪婪,但就我所知,它就是10^n

我看过诸如this之类的资源,它们都在解释clpfd的魔力方面做得很出色,但是没有一个人对如何实现它产生足够的了解。哪些程序将快速运行,哪些程序将运行缓慢。 clpfd显然使用属性来挂钩统一吗?我对属性的了解还不足以知道这对我编写的程序的复杂性意味着什么。我可以找到某个地方吗?

2 个答案:

答案 0 :(得分:1)

实验示例:

:- use_module(library(clpfd)).
:- use_module(library(lists)).

call_time(G,T) :-
   statistics(runtime,[T0|_]),
   G,
   statistics(runtime,[T1|_]),
   T is T1 - T0.

% Sorted has the same elements as List and is also sorted
clpfd_sort(List):-
  same_length(List, Sorted),
  chain(Sorted, #=<),
  permutation(List, Sorted).

item_goal(I,clpfd_sort(I)).

n_randoms_times(NumberOfExperiments,Random_Lists,Times) :- 
  numlist(1,NumberOfExperiments,Experiment_Sizes),
  maplist(numlist(1),Experiment_Sizes,ExperimentLists),
  maplist(random_permutation,ExperimentLists,Random_Lists),
  maplist(item_goal,Random_Lists,Goals),
  maplist(call_time,Goals,Times).

测试:

?- n_randoms_times(15,R,T),write(T).
[0,0,0,1,1,1,2,5,4,3,16,34,43,115,246]

当我们将列表的大小加1时,时间似乎增加了一倍...

答案 1 :(得分:0)

解决Prolog或clpfd程序复杂性的最佳方法是避免内部的实际机制,并首先专注于具体答案或一组答案。毕竟,如果这样的分析已经表明O很大,那么任何进一步的细节都是徒劳的,就像您的程序中那样。

考虑n个相等数字的列表。在这种情况下,我们将获得n个有效排列。因此,最坏情况下的复杂度至少为O(n!)。这似乎足以重新考虑您的方法。

在这种情况下,最好的办法是考虑将整数列表直接与实际列表相关联的约束。如果我的记忆确实对我有帮助,那么可以在Prolog IV的背景下实现。