【问题标题】:Fast implementation of BWT in Lua在 Lua 中快速实现 BWT
【发布时间】:2016-05-14 15:18:24
【问题描述】:
local function fShallowCopy(tData)
    local tOutput = {}
    for k,v in ipairs(tData) do
        tOutput[k] = v
    end
    return tOutput
end

local function fLexTblSort(tA,tB) --sorter for tables
    for i=1,#tA do 
        if tA[i]~=tB[i] then 
            return tA[i]<tB[i]
        end
    end 
    return false 
end

function fBWT(tData)

    --setup--
    local iSize = #tData
    local tSolution = {}
    local tSolved = {}


    --key table--
    for n=1,iSize do 
        tData[iSize] = fRemove(tData,1)
        tSolution[n] = fShallowCopy(tData)
    end
    table.sort(tSolution,fLexTblSort)


    --encode output--
    for i=1,iSize do
        tSolved[i] = tSolution[i][iSize]
    end


    --finalize--
    for i=1,iSize do
        if fIsEqual(tSolution[i],tData) then
            return i,tSolved
        end
    end
    return false
end

以上是我目前在 Lua 中实现 BWT 编码的代码。问题是由于表的大小和循环的长度,它需要很长时间才能运行。对于 1000 个字符的输入,平均编码时间约为 1.15 秒。有没有人有关于制作更快的 BWT 编码功能的建议?

最大的减速似乎出现在 fLexTblSort 和 fShallowCopy。我也将两者都包含在 BWT 函数之上。

【问题讨论】:

    标签: lua compression burrows-wheeler-transform


    【解决方案1】:

    如果我没看错,如果排序是快速排序,您的算法具有复杂性O(n^2 log n)。比较器函数 fLexTblSortO(n) 本身用于您比较的每一对值。

    当我检查几年前的实施时,我看到了可能的改进空间。您创建tData 的所有可能旋转,这也需要很多时间。我只使用了单个数据块,并且只存储了特定旋转的起始位置。您还使用了很多可以缩小到更少的循环。

    我的实现是用 C 语言实现的,但这个概念也可以在 Lua 中使用。您的 Lua 和 C 之间的一些混合伪代码中的想法。

    function fBWT(tData)
    
      local n = #tData
      local tSolution = {}
      for(i = 0; i < n; i++)
        tSolution[i] = i;
    
      --table.sort(tSolution, fLexTblSort)
      quicksort(tData, n, tSolution, 0, n)
    
      for(i = 0; i < n; i++){
        tSolved[i] = tData[(tSolution[i]+n-1)%n];
        if( tSolution[i] == 0 )
            I = i;
      }
    
      return I, tSolved
    end
    

    您还需要自己的排序函数,因为该标准没有为这种魔法提供足够的灵活性。快速排序是个好主意(你可能会避免一些争论,但我只粘贴了我使用的 C 版本):

    void swap(int array[], int left, int right){
        int tmp = array[right]; 
        array[right] = array[left];
        array[left] = tmp;         
    }
    
    void quicksort(uint8_t data[], int length, int array[], int left, int right){
        if(left < right){ 
            int boundary = left;
            for(int i = left + 1; i < right; i++){ 
                if( offset_compare(data, length, array, i, left) < 0 ){
                    swap(array, i, ++boundary);
                }
            }
            swap(array, left, boundary);
            quicksort(data, length, array, left, boundary);
            quicksort(data, length, array, boundary + 1, right);
        }     
    }
    

    最后一步是你自己的比较器函数(类似于你原来的函数,但在旋转,同样在 C 中):

    /**
     *  compare one string (fixed length) with different rotations.
     */
    int offset_compare(uint8_t *data, int length, int *array, int first, int second){
        int res;
        for(int i = 0; i < length; i++){
            res = data[(array[first]+i)%length] - data[(array[second]+i)%length];
            if( res != 0 ){
                return res;
            }
        }
        return 0;
    }
    

    这是我几年前提出的基本想法,对我有用。如果有不清楚的地方或错误,请告诉我。

    【讨论】:

    • 虽然这是一个非常出色的解决方案,但遗憾的是它似乎并没有解决问题。您的快速排序和比较器功能与我的旧功能的运行时间相同。仍然感谢您的帮助!我想它也不能移植到 Lua。
    • 是的。 Lua 比 C 慢一些。如果你追求性能,你可以尝试在 C 中实现压缩并将函数导出到 Lua。它可能会变得更快。还取决于您的 Lua 实现,如果它确实一遍又一遍地复制表,或者使用单个引用作为 C 版本。
    • 不幸的是,在这个项目中使用另一种语言不是一个选项。我可能只需要将 BWT 编码从我的压缩中取出并遭受压缩损失的小损失
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多