如何根据行修改矩阵的行(制作Haar矩阵)

时间:2018-12-01 00:49:55

标签: r algorithm matrix wavelet

我正在编写一个程序包,该程序包需要制作非常大的Haar矩阵( $ 2 ^ {28} \约270 $ 百万行和列)。例如:

$$ H_2 = \ begin {bmatrix} 1&1 \\ 1&-1 \ end {bmatrix} $$

$$ H_4 = \ begin {bmatrix} 1&1&1&1 \\ 1&1&-1&-1 \\ 1&-1&0&0 \\ 0&0&1&-1 \ end {bmatrix} $$

(请注意,维度始终是2的幂)

我编写了一个函数,该函数将使用Kroneker产品构建任意大小(2 ^ J)的Haar矩阵。

$$ H_ {2N} = \ begin {bmatrix} H_ {N} \ otimes [1,1] \\ I_ {N} \ otimes [1,-1] \ end {bmatrix} $$

但是,这种算法的迭代性质在内存方面非常浪费,并且在R中花费了很长时间。

谢谢,特定行的值应该为正或负的表达式可以用封闭形式给出,如下所示:


  • 对于给定值 $ J $ ,初始化尺寸为 $ 2 ^ J \ times的零矩阵2 ^ J $

  • 将第一行设置为全部。

  • 对于所有其他行,任何给定行中的非零数字序列的width
      $$ 2 ^ {J-\ lfloor \ log_2(row-1)\ rfloor} $$

  • 上述组的start位置是
    $$ \ text {width} * \ left((row-1)-2 ^ {\ lfloor \ log_2(row -1)\ rfloor} \ right)$$

因此

  • positiveOneStart = width *(row-1-2 ^ floor(log({row-1,2)))+ 1
  • finalOnePosition =(start + width / 2-1)
  • negativeOneStart = finalOnePosition +1
  • finalNegativeOnePosition = positiveOneStart + width-1

我编写了以下两个函数:

rowFill <- function(row, H){

  if(row == 1){
    H[row, ] <<- 1
  }else{
    (log2row <- 2^floor(log(row - 1, 2)))
    (width <- dimension / log2row %>%
      round())
    (width <- suppressWarnings(as.integer(width)))

    (start = width * (row - 1 - 2^floor(log(row - 1, 2))) + 1 %>%
      round())
    (startOnes <- as.integer(start))

    (endOnes <- startOnes + width/2 -1)

    (startNegOnes <-  endOnes + 1)

    (endNegOnes <- startOnes + width - 1)

    H[row, startOne:endOnes] <<- (1)
    H[row, startNegOnes:endNegOnes] <<- (-1)
  }
}

当我在循环中使用上述想法填充行时,它似乎工作正常。

library(purrr)

J = 3
dimension <- 2^J 
row <- 1:(dimension)
H = Matrix::Matrix(0, nrow = dimension, ncol = dimension) %>% methods::as("dgCMatrix")

H[1,] <- 1

for(row in 2:2^J){
width <- dimension / 2^floor(log(row - 1, 2)) %>%
  round()
width <- suppressWarnings(as.integer(width))

start = width * (row - 1 - 2^floor(log(row - 1, 2))) + 1 %>%
  round()
start <- as.integer(start)

endOnes <- start + width/2 -1

startNegOnes <-  endOnes + 1

endNegOnes <- start + width - 1

H[row,start:endOnes] <- 1
H[row,startNegOnes:endNegOnes] <- -1

}

H

有效!

8 x 8 sparse Matrix of class "dgCMatrix"

[1,] 1  1  1  1  1  1  1  1
[2,] 1  1  1  1 -1 -1 -1 -1
[3,] 1  1 -1 -1  .  .  .  .
[4,] .  .  .  .  1  1 -1 -1
[5,] 1 -1  .  .  .  .  .  .
[6,] .  .  1 -1  .  .  .  .
[7,] .  .  .  .  1 -1  .  .
[8,] .  .  .  .  .  .  1 -1

但是,我要避免循环,因为我正在处理一个 $ 2 ^ {28} $ (非常大)的矩阵,并且可以将它们循环非常慢。因此,我想尝试使用purrr包函数walk来将H矩阵修改为副作用:

haarFill <- function(J){
  dimension <- 2^J 
  row <- 1:(dimension)
  H = Matrix::Matrix(0, nrow = dimension, ncol = dimension) %>% methods::as("dgCMatrix")
  walk(.x = row, .f = rowFill, H)
}

但是,这不能给我想要的结果:

8 x 8 sparse Matrix of class "dgCMatrix"

[1,] 1  1  1  1  1  1  1  1
[2,] .  .  .  1 -1 -1 -1 -1
[3,] .  1 -1 -1  1  .  .  .
[4,] .  .  .  .  1  1 -1 -1
[5,] 1 -1  1  1  1  .  .  .
[6,] .  .  1 -1  1  .  .  .
[7,] .  .  .  .  1 -1  .  .
[8,] .  .  .  .  1  1  1 -1

谁能帮我看看有什么问题吗?我已经对该单元进行了单元测试,直到死亡,但似乎无法弄清楚错误在哪里。

0 个答案:

没有答案