提出一种具有类BDD结构的任意形状位矩阵换位算法

时间:2017-02-15 13:19:10

标签: algorithm matrix bit-manipulation transpose binary-decision-diagram

我们认为位矩阵(n x m)是包含n行的大小为m的常规数组整数。

我看过Hacker's Delight和其他来源,我发现的算法相当专业:方形矩阵的大小为2,8x8,32x32,64x64(这是正常的,因为机器是这样构建的)。

我想到了一种更通用的算法(对于任意n和m),在更糟糕的情况下,它是预期的复杂度(我认为),但是对于包含大多数相似列的矩阵,或者比这些更多的零,算法似乎更有趣(在极端情况下,如果矩阵一遍又一遍地包含相同的线,则它是线性的)。它遵循一种二元决策图操作。

输出不是转置矩阵,而是压缩转置矩阵:对列表(V,L),其中L是int_m,表示转置矩阵的行(通过设置相应位置的位)包含int_n V.没有出现在任何一对中的转置矩阵的行用0填充。

例如,对于矩阵

1010111
1111000
0001010

有转置

110
010
110
011
100
101
100

算法输出 (010,0100000)(011,0001000)(100,0000101)(101,0000010)(110,1010000) 一个读取对(100,0000101),意思是“值100放在转置矩阵的第5行和第7行”。

这是算法(用伪OCaml / C编写)和上面例子中算法进展的图片。

我们将根据三元组(index_of_current_line,V,L)运行,类型为(int, int_n, int_m),其中int_n是n位宽整数的类型,int只是一个足够宽的机器来容纳n。 该函数获取这些三元组的列表,矩阵,行数和输出的累加器(对的列表(int_m,int_n))并在某个时刻返回该累加器。

list of (int_n, int_m) transpose(list of triple t, 
                                int_m[n] mat, 
                                int n,  
                                list of (int_n, int_m) acc)

转置功能的第一个调用是

transpose([(0, 0, 2^m-1)], mat, n, []).

取“&”,“|” “xor”是通常的逐位操作

transpose(t, mat, n, acc) =
 match t with 
  | [] -> (* the list is empty, we're done *)
    return acc
  | (i, v, l)::tt -> 
    let colIn = mat[i] & l in
    (* colIn contains the positions that were set in the parent's mask "l" 
     and that are also set in the line "i" *)
    match colIn with
    |0 -> (* None of the positions are set in both, do not branch *)
     if (i<n) then (* not done with the matrix, simply move to next line *)
      transpose((i+1,v,l)::tt,mat,n,acc)
     else (* we reached the end of the matrix, we're at a leaf *)
       if (v>0) then
         transpose(tt,mat,n,(v,l)::acc)
       else  (* We ignore the null values and continue *)
         transpose(tt,mat,n,acc)
     |_ -> (* colIn is non null, ie some of the positions set at the parent
              mask "l" are also set in this line. If ALL the positions are, we 
              do not branch either. If only some of them are and some of them
              are not, we branch *)
         (* First, update v *)
        let vv = v | (2^(n-i-1)) in
         (* Then get the mask for the other branch *)
        let colOut = colIn xor l in, 
        match colOut with
        | 0 -> (* All are in, none are out, no need to branch *)
            if (i<n) then
                transpose((i+1,vv,colIn)::tt,mat,n,acc)
            else (* we reached the end of the matrix, we're at a leaf *)             
               transpose(tt,mat,n,(vv,colIn)::acc)
        | _ -> (* Some in, some out : now we branch *)
            if (i<n) then 
               transpose((i+1,vv,colIn)::(i+1,v,colOut)::tt,mat,n,acc)
            else 
             if (v>0) then
               transpose(tt,mat,n,(vv,colIn)::(v,colOut)::acc)
             else
               transpose(tt,mat,n,(vv,colIn)::acc)

enter image description here

请注意,如果矩阵比它更宽,它甚至更快(例如,如果n = 3且m = 64)

我的问题是: 这有趣和/或有用吗?我重新发明轮子了吗? “几乎为零”的矩阵或“小差异线”矩阵是否足以让人感兴趣?

PS:如果看起来不清楚,请告诉我,我会改写任何需要的东西!

0 个答案:

没有答案