在prolog中断言并使用快速的LARGE数组

时间:2016-11-16 11:01:39

标签: arrays prolog swi-prolog

我正在使用仿函数在SWI-Prolog中使用arg / 3来获取随机访问数组。 我正在做的是将样本中的值加载到仿函数中,我创建并断言该数组以供将来使用。

加载后,随机访问确实是O(1),因为我已经使用time / 1进行了验证。问题是从断言加载仿函数需要花费大量时间(时间/ 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

1 个答案:

答案 0 :(得分:3)

在使用current_sample/1时,您会看到线性开销,因为在调用谓词时谓词的参数是复制。

有几种方法可以摆脱这种线性开销,将其转换为?(1)

一个好方法

良好的方法是带有整个数组,无论是显式还是隐式,都可以输出需要访问它的所有谓词。

您可以使用半色标记隐式执行此操作(请参阅),或编写您自己的自定义扩展规则。这类似于Haskell中的 monads

  

考虑这样做!

更糟糕的方式

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

  

避免这种情况!

一些原因:

  • 不便携
  • 它引入了全局状态,使您的谓词难以阅读和调试
  • 比仅仅使用其他参数来执行数组(隐式或显式)更有效率
  • 容易出错