【问题标题】:How to concatenate matrices in diagonal form in Julia如何在 Julia 中以对角线形式连接矩阵
【发布时间】:2021-05-15 16:17:19
【问题描述】:

我有一个矩阵A,我想构建一个块对角矩阵M as

A 0 ⋯ 0
0 A ⋯ 0
⋮ ⋮ ⋱ ⋮
0 0 ⋯ A

其中0s 是与A 大小相同且填充零的矩阵。有没有方便的方法来做到这一点?

换句话说,有没有相当于 Python 的 linalg.block_diag(来自 scipy)?

【问题讨论】:

    标签: matrix julia concatenation diagonal


    【解决方案1】:

    您可以使用 SparseArrays.jl 标准库中的 blockdiag。例如:

    julia> using SparseArrays
    
    julia> A = sparse(rand(3,2)) # A must be sparse for blockdiag
    3×2 SparseMatrixCSC{Float64, Int64} with 6 stored entries:
     0.465226  0.473656
     0.230678  0.391924
     0.928409  0.772551
    
    julia> M = blockdiag(A, A, A)
    9×6 SparseMatrixCSC{Float64, Int64} with 18 stored entries:
     0.465226  0.473656   ⋅         ⋅         ⋅         ⋅
     0.230678  0.391924   ⋅         ⋅         ⋅         ⋅
     0.928409  0.772551   ⋅         ⋅         ⋅         ⋅
      ⋅         ⋅        0.465226  0.473656   ⋅         ⋅
      ⋅         ⋅        0.230678  0.391924   ⋅         ⋅
      ⋅         ⋅        0.928409  0.772551   ⋅         ⋅
      ⋅         ⋅         ⋅         ⋅        0.465226  0.473656
      ⋅         ⋅         ⋅         ⋅        0.230678  0.391924
      ⋅         ⋅         ⋅         ⋅        0.928409  0.772551
    

    如果你真的需要 M 密集,你可以把它转换回来

    julia> Matrix(M)
    9×6 Matrix{Float64}:
     0.465226  0.473656  0.0       0.0       0.0       0.0
     0.230678  0.391924  0.0       0.0       0.0       0.0
     0.928409  0.772551  0.0       0.0       0.0       0.0
     0.0       0.0       0.465226  0.473656  0.0       0.0
     0.0       0.0       0.230678  0.391924  0.0       0.0
     0.0       0.0       0.928409  0.772551  0.0       0.0
     0.0       0.0       0.0       0.0       0.465226  0.473656
     0.0       0.0       0.0       0.0       0.230678  0.391924
     0.0       0.0       0.0       0.0       0.928409  0.772551
    

    【讨论】:

    【解决方案2】:

    您可以使用cat 执行此操作,给它两个维度:

    julia> A = [1 2; 3 4]
    2×2 Matrix{Int64}:
     1  2
     3  4
    
    julia> cat(A, A', reverse(A); dims=(1,2))
    6×6 Matrix{Int64}:
     1  2  0  0  0  0
     3  4  0  0  0  0
     0  0  1  3  0  0
     0  0  2  4  0  0
     0  0  0  0  4  3
     0  0  0  0  2  1
    

    【讨论】:

      【解决方案3】:

      如果您不想为矩阵和 0 的副本分配额外空间,可以使用我编写的以下结构,它模拟 block-diagonal matrix

      struct BlockDiagonalMatrix{T} <: AbstractMatrix{T}
          matrix::AbstractMatrix{T}
          repeats::Integer
      
          BlockDiagonalMatrix(mat::AbstractMatrix{T}, repeats) where {T} = new{T}(mat, repeats)
      end
      
      Base.IndexStyle(::Type{BlockDiagonalMatrix}) = IndexLinear()
      Base.size(bdm::BlockDiagonalMatrix) = size(bdm.matrix) .* bdm.repeats
      function Base.getindex(bdm::BlockDiagonalMatrix{T}, i) where {T}
          bdm_height = size(bdm, 1)
      
          i -= 1  # Math is slightly simpler when indexing is 0-based
          i_col, i_row = divrem(i, bdm_height)
      
          block_height, block_width = size(bdm.matrix)
          block_col = fld(i_col, block_width)
          block_row = fld(i_row, block_height)
      
          if block_row == block_col
              inner_mat_col = 1 + (i_col % block_width)  # convert back to 1-based
              inner_mat_row = 1 + (i_row % block_height)
              return bdm.matrix[inner_mat_row, inner_mat_col]
          else
              return zero(T)
          end
      end
      

      现在,这模拟了完整的块对角矩阵,同时仅使用了一个数组的存储。事实上,即使是漂亮的印刷品也是免费的。

      julia> bdm = BlockDiagonalMatrix([1 2; 3 4; 5 6], 4)
      12×8 BlockDiagonalMatrix{Int64}:
       1  2  0  0  0  0  0  0
       3  4  0  0  0  0  0  0
       5  6  0  0  0  0  0  0
       0  0  1  2  0  0  0  0
       0  0  3  4  0  0  0  0
       0  0  5  6  0  0  0  0
       0  0  0  0  1  2  0  0
       0  0  0  0  3  4  0  0
       0  0  0  0  5  6  0  0
       0  0  0  0  0  0  1  2
       0  0  0  0  0  0  3  4
       0  0  0  0  0  0  5  6
      
      julia> bdm = BlockDiagonalMatrix([1.0 2.0], 4)
      4×8 BlockDiagonalMatrix{Float64}:
       1.0  2.0  0.0  0.0  0.0  0.0  0.0  0.0
       0.0  0.0  1.0  2.0  0.0  0.0  0.0  0.0
       0.0  0.0  0.0  0.0  1.0  2.0  0.0  0.0
       0.0  0.0  0.0  0.0  0.0  0.0  1.0  2.0
      

      您可以了解有关如何实现自定义数组类型 here 的更多信息 - 实现内置 Array 提供的全部功能只需很少的工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-15
        • 2018-05-09
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        相关资源
        最近更新 更多