2016-11-16 88 views
0

我在SWI-Prolog中使用仿函数来获取使用arg/3的随机访问数组。 我在做什么是从一个样本加载值到一个仿函数我创建并断言该数组以供将来使用。在序言中声明和使用快速,大型的阵列

加载后,随机访问确实是O(1),因为我已经使用time/1进行了验证。问题是从断言中加载函数需要很多时间(time/1表明它在数组大小上是线性的)。 有没有什么办法可以加快这个速度?使用current_sample/1时,因为谓词的参数是从数据库中拷贝当谓语被称为

:- dynamic 
    current_sample/1. 

xrange(L,R,X):- 
    L < R, 
    (X = L; 
    X1 is L+1, xrange(X1,R,X) 
    ). 


arraybase_from_list__set_arg_from_list([], _, _). 
arraybase_from_list__set_arg_from_list([Head|Tail], I, ResArray):- 
    I1 is I+1, 
    nb_setarg(I1, ResArray, Head), 
    arraybase_from_list__set_arg_from_list(Tail, I1, ResArray). 

arraybase_from_list(List, ResArray):- 
    length(List, L), 
    functor(ResArray, custom_array_data, L), 
    arraybase_from_list__set_arg_from_list(List, 0, ResArray). 


test_array_create(N):- % Creates a dummy array of squares of numbers fromo [0,N) 
    findall(X2, (xrange(0,N,X), X2 is X*X), XList), 
    arraybase_from_list(XList, Arr), 
    assert(current_sample(Arr)). 

test_array_get(I,V):- % Unifies V with Ith element of Current sample 
    I0 is I+1, 
    current_sample(Arr), % Take turns timing this 
    arg(I0, Arr, V). % And then timing this 

回答

2

你看到线性开销:为再现

最少的代码。

有几种方法来摆脱这种线性开销,把它变成풪(1)

一个好办法

一个的方式来做到这一点是携全体阵列周围,或隐或显,throghout需要访问它的谓语。

您可以使用semicontext符号做它含蓄地(见),或编写自定义的扩展规则。这与Haskell中的monads类似。

请考虑这样做!


一个更糟糕的方式

一个更糟糕,只在表面上更简单的方法是使用全局变量而不是全球数据库存储术语。

避免这种情况!

一些原因:

  • 不是便携式
  • 介绍了全局状态,使您的谓语难以阅读和调试
  • 显著比更有效只需使用附加参数来通过(隐式或显式地)传递数组
  • 容易出错
+0

谢谢 不幸的是我有一点紧张的时间,所以我要在这里使用全局变量的简单的解决方案。 DCG是我不久将要拿起的东西。 – 2bigpigs

+1

谢谢你花时间告诉我这个! – mat