Skip to content

More convenient syntax for merging blocks #359

Open
@mtfishman

Description

@mtfishman

It would be nice to have a more convenient/compact syntax for merging adjacent blocks. Right now you can do that by indexing with new axes that have a new blocking structure (see the related discussion #347), but that requires a lot of work to be done "by hand" by the user to determine the new block sizes.

From what I can tell, the best way to do this right now is:

 julia> using BlockArrays

julia> a = BlockArray(randn(8, 8), [2, 2, 2, 2], [2, 2, 2, 2])
4×4-blocked 8×8 BlockMatrix{Float64}:
 -0.0707114  -1.679060.138973    0.544946-0.134462   0.6112722.18339    -0.883239
 -0.68735     0.857573-0.0080504   3.64798-0.471002   1.57178-0.0149043   0.903188
 ───────────────────────┼─────────────────────────┼──────────────────────────┼───────────────────────
 -0.0604537   0.2315461.18174     0.208313-1.72071    0.879961-0.366364   -0.73705 
  1.08236    -2.60451.76942     1.0568-1.85228    1.83546-1.06417     0.930053
 ───────────────────────┼─────────────────────────┼──────────────────────────┼───────────────────────
 -1.02677    -0.354130.671171    0.3176931.12187   -0.09320430.125758   -1.45183 
  0.328434   -1.46481-1.93467    -0.866749-0.923225  -1.20646-1.13039    -0.715379
 ───────────────────────┼─────────────────────────┼──────────────────────────┼───────────────────────
  1.34041    -0.5744960.273291    1.57875-0.635733  -0.00893333-0.554791   -0.625784
  0.396603   -0.569414-0.898214   -1.756611.02851   -0.392836-0.942213    0.627758

julia> a[blockedrange([4, 4]), blockedrange([4, 4])]
2×2-blocked 8×8 BlockMatrix{Float64}:
 -0.0707114  -1.67906    0.138973    0.544946-0.134462   0.611272     2.18339    -0.883239
 -0.68735     0.857573  -0.0080504   3.64798-0.471002   1.57178     -0.0149043   0.903188
 -0.0604537   0.231546   1.18174     0.208313-1.72071    0.879961    -0.366364   -0.73705 
  1.08236    -2.6045     1.76942     1.0568-1.85228    1.83546     -1.06417     0.930053
 ──────────────────────────────────────────────┼───────────────────────────────────────────────
 -1.02677    -0.35413    0.671171    0.3176931.12187   -0.0932043    0.125758   -1.45183 
  0.328434   -1.46481   -1.93467    -0.866749-0.923225  -1.20646     -1.13039    -0.715379
  1.34041    -0.574496   0.273291    1.57875-0.635733  -0.00893333  -0.554791   -0.625784
  0.396603   -0.569414  -0.898214   -1.756611.02851   -0.392836    -0.942213    0.627758

as discussed in #347. A proposal for a more convenient syntax would be:

julia> r = BlockVector(Block.(1:4), [2, 2])
2-blocked 4-element BlockVector{Block{1, Int64}, Vector{BlockRange{1, Tuple{UnitRange{Int64}}}}, Tuple{BlockedUnitRange{Vector{Int64}}}}:
 Block(1)
 Block(2)
 ────────
 Block(3)
 Block(4)

julia> a[r, r]
2×2-blocked 8×8 BlockMatrix{Float64}:
 -0.0707114  -1.67906    0.138973    0.544946-0.134462   0.611272     2.18339    -0.883239
 -0.68735     0.857573  -0.0080504   3.64798-0.471002   1.57178     -0.0149043   0.903188
 -0.0604537   0.231546   1.18174     0.208313-1.72071    0.879961    -0.366364   -0.73705 
  1.08236    -2.6045     1.76942     1.0568-1.85228    1.83546     -1.06417     0.930053
 ──────────────────────────────────────────────┼───────────────────────────────────────────────
 -1.02677    -0.35413    0.671171    0.3176931.12187   -0.0932043    0.125758   -1.45183 
  0.328434   -1.46481   -1.93467    -0.866749-0.923225  -1.20646     -1.13039    -0.715379
  1.34041    -0.574496   0.273291    1.57875-0.635733  -0.00893333  -0.554791   -0.625784
  0.396603   -0.569414  -0.898214   -1.756611.02851   -0.392836    -0.942213    0.627758

(which doesn't work right now). Writing out BlockVector(Block.(1:4), [2, 2]) is a bit annoying, but the idea is that it expresses the intent better: the user doesn't have to deal with any of the block lengths themselves, they just express which blocks should get merged together. This is analogous to the block version of indexing with blockedrange([2, 2]) in order to define a new blocking structure. Perhaps it even warrants a devoted syntax like blockedblockrange([2, 2]) for constructing BlockVector(Block.(1:4), [2, 2]) (or a devoted type BlockedBlockRange).

Related to #184, one could imagine generalizing this to something like BlockVector([Block(1), Block(3), Block(2), Block(4)], [2, 2]), which would be a fused operation for permuting blocks along an axis and then merging adjacent blocks. We would have many applications for that kind of operation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions