2016-11-16 38 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