ITensor / ITensor/BlockSparseArrays.jl
[BlockSparseArrays] BlockSparseArray functionality
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 3
- Forks
- 3
- Avg merge
- 14m
- Merged PRs (30d)
- 3
Description
This issue lists functionalities and feature requests for BlockSparseArray.
using LinearAlgebra
using NDTensors.BlockSparseArrays: BlockSparseArray
a = BlockSparseArray{Float64}([2, 3], [2, 3]);
Bugs
-
LinearAlgebra.Adjoint{T,<:BlockSparseArray{T}}returns aBlockedArrayin certain slicing operations (https://github.com/ITensor/BlockSparseArrays.jl/issues/2). - Fix
cat(::BlockSparseArray, ::BlockSparseArray)for dual axes (followup to ITensor/ITensors.jl#1579).
Feature requests
- Allow the syntax
BlockSparseArray{Float64}([U1(0) => 2, U1(1) => 3], [U1(0) => 2, U1(1) => 3])which could implicitly create axes withGradedUnitRangeinternally. - Use
NestedPermutedDimsArrayinstead ofSparsePermutedDimsArrayBlocks(similar to how we are removingSparseAdjointBlocks/SparseTransposeBlocksin ITensor/ITensors.jl#1580). Started in ITensor/ITensors.jl#1589, ITensor/ITensors.jl#1590. - An alternative design to ITensor/ITensors.jl#1589 would be to redefine
NestedPermutedDimsArrayas aPermutedDimsArraywrapping aMappedArraywhere the map and inverse map convert toPermutedDimsArray, that would be good to explore so we don't have to support all of theNestedPermutedDimsArrayscode, which is mostly just a copy ofBase.PermutedDimsArraysanyway. - If slices are just blockwise, like
b = @view a[Block.(1:2), [Block(2), Block(1)], defineblocks(b)as@view blocks(a)[1:2, [2, 1]], as opposed to using the more generalSparseSubArrayBlocksin those cases. Like the newNestedPermutedDimsArray, in principleSparseSubArrayBlockscould be replaced by aNestedSubArraytype that defines the slicing behavior of the array storing the blocks and also the slicing of the blocks themselves, but that might be overkill and the concept is very particular to block arrays. But maybeSubArrayof theblockscould still be used to simplify the code logic inSparseSubArrayBlocks. - Constructor from
Dictionaryshould check block sizes (https://github.com/ITensor/BlockSparseArrays.jl/issues/2). - Blockwise linear algebra operations like
svd,qr, etc. See ITensor/BlockSparseArrays.jl#3. These are well defined if the block sparse matrix has a block structure (i.e. the sparsity pattern of the sparse array of arraysblocks(a)) corresponding to a generalized permutation matrix. Probably they should be called something likeblock_svd,block_eigen,block_qr, etc. to distinguish that they are meant to be used on block sparse matrices with those structures (and error if they don't have that structure). See ^linalg for a prototype of a blockwise QR. See also BlockDiagonals.jl for an example in Julia of blockwise factorizations, they use a naming schemesvd_blockwise,eigen_blockwise, etc. The slicing operation introduced in ITensor/ITensors.jl#1489 will be useful for performing block-wise truncated factorizations. - Define
storedblockview(a, ::Block)to get the view of a stored block, which would allow avoiding wrapping the block in a view. Also definegetstoredindex(a, ::Block). - Change the behavior of slicing with non-blocked ranges (such as
a[1:2, 1:2]) to output non-blocked arrays, and define@blocked a[1:2, 1:2]to explicitly preserve blocking. See the discussion in https://github.com/JuliaArrays/BlockArrays.jl/issues/347. - Reconsider the design of how duality is stored in graded unit ranges (graded axes), for example storing it at the level of the sector labels with a new
SectorDualtype and/or as a boolean flag. - Display non-initialized blocks differently from zero-initialized blocks, currently they both print as zeros.
Fixed
- Rename
SparseArrayInterfacetoSparseArraysBaseand moveSparseArrayDOKsinto the newSparseArraysBase. (Fixed in ITensor/ITensors.jl#1591, ITensor/ITensors.jl#1592.) - Constructors like
BlockSparseArray{Float64,2,Matrix{Float64}}([2, 3], [2, 3]),BlockSparseArray{Float64,2}([2, 3], [2, 3]),BlockSparseMatrix{Float64}([2, 3], [2, 3])are not defined. (Fixed by ITensor/ITensors.jl#1586.) - Rename
block_nstoredtoblock_stored_lengthandnstoredtostored_length. (Fixed by ITensor/ITensors.jl#1585.) - Rename
BlockSparseArrayLiketoAnyAbstractBlockSparseArray, which is the naming convention used in other Julia packages for a similar concept[^anygpuarray]. - Implement direct sums/concatenations of block sparse arrays that preserve and make use of block sparsity. This could be done by overloading
Base.catand related functions. (Implemented in ITensor/ITensors.jl#1579.) - Fix issues with nested slices like
@views a[[Block(2), Block(1)], [Block(2), Block(1)]][2:4, 2:4]in Julia 1.11 (see tests marked as broken in ITensor/ITensors.jl#1539). (Fixed in ITensor/ITensors.jl#1575.) - Support for blocks that are on GPU. (Partially addressed in ITensor/ITensors.jl#1560 but more work is needed, we can track issues individually from now on.)
- Better support for blocks that are not
Array, for exampleDiagonalArrays.DiagonalArray,SparseArrayDOKs.SparseArrayDOK,LinearAlgebra.Diagonal, etc.BlockSparseArraycan have blocks that are AbstractArray subtypes, however some operations don't preserve those types properly (i.e. implicitly convert toArrayblocks) or don't work. (Partially addressed in ITensor/ITensors.jl#1560 but more work is needed, we can track issues individually from now on.) - Cannot create zero dimension array (
BlockSparseArray{Float64}()fails). (Fixed in ITensor/ITensors.jl#1574.) -
permutedimscrashes for some block sparse arrays (https://github.com/ITensor/BlockSparseArrays.jl/issues/2). (Fixed in ITensor/ITensors.jl#1574.) -
copy(adjoint)does not preserve dual axes. (Fixed in ITensor/ITensors.jl#1574.) -
block_stored_indices(::LinearAlgebra.Adjoint{T, BlockSparseArray})does not transpose its indices. (Matt: I don't see an issue here, the values ofblock_stored_indices(a')are the nonzero/stored block locations, thekeysofblock_stored_indices(a')are an implementation detail and should not be used.) -
LinearAlgebra.norm(a)crashes whenacontainsNaN. - Slicing a
BlockSparseArraythat hasGradedUnitRangeaxes (as opposed toGradedOneTo) fails. - Sub-slices of multiple blocks sometimes fails with a dual axis..
-
a[:, :]creates an array with ill behaved axes (it should just be equivalent tocopy(a)). Also triggers display error. - Printing a
BlockSparseArraytriggersBoundsErrorin some rare contexts (https://github.com/ITensor/BlockSparseArrays.jl/issues/2). - Automatically initializing a block when only a slice is used (this should work if you make sure to use a view, see https://github.com/ITensor/BlockSparseArrays.jl/issues/2).
- Implement slicing syntax for merging blocks, i.e. https://github.com/JuliaArrays/BlockArrays.jl/issues/359.
-
a = BlockSparseArray{Float64}([2, 3], [2, 3]); @view a[Block(1, 1)]returns aSubArraywhere the last type parameter which marks whether or not the slice supports faster linear indexing isfalse, while it should betrueif that is the case for that block ofa(this is addressed by ITensor/ITensors.jl#1513,@view a[Block(1, 1)]no longer outputs aSubArray, but rather either the block data directly or aBlockViewobject if the block doesn't exist yet). -
TensorAlgebra.contractfails when called withview(::BlockSparseArray, ::Block)orreshape(view(::BlockSparseArray, ::Block), ...). As a workaround it will work if you useview!/@view!instroduced in ITensor/ITensors.jl#1498. - Fix tests that are marked as broken in https://github.com/ITensor/ITensors.jl/blob/main/NDTensors/src/lib/BlockSparseArrays/test/test_basics.jl.
-
a = BlockSparseArray{Float64}([2, 3], [2, 3]); b = @view a[Block.(1:2), Block.(1:2)]; b[Block(1, 1)] = randn(2, 2)doesn't set the blockBlock(1, 1)(it remains uninitialized, i.e. structurally zero). I think the issue is that@view b[Block(1, 1)]makes two layers ofSubArraywrappers instead of flattening down to a single layer, and those two layers are not being dispatched on properly (in general we only catch if something is aBlockSparseArrayor aBlockSparseArraywrapped in a single wrapper layer). - Compatibility issues with
BlockArraysv1.1, see CI for ITensor/ITensors.jl#1363. Fixed by ITensor/ITensors.jl#1503. - Rewrite GradedAxes using BlockArrays v1[^blockarrays_v1].
-
r = gradedrange([U1(0) => 1]); a = BlockSparseArray{Float64}(r, r); size(view(a, Block(1,1))[1:1,1:1])returns a tuple ofLabelledIntegerinstead ofInt(see discussion, keep it that way at least for now). -
r = gradedrange([U1(0) => 1]); a = BlockSparseArray{Float64}(dual(r), r); @view(a[Block(1, 1)])[1:1, 1:1]and other combinations ofduallead to method ambiguity errors. - Implement slicing syntax for slicing multiple subsets of blocks, i.e. https://github.com/JuliaArrays/BlockArrays.jl/issues/358.
-
dualis not preserved when adding/subtractingBlockSparseArrays, i.e.g = gradedrange([U1(0) => 1]); m = BlockSparseArray{Float64}(dual(g), g); isdual(axes(m + m, 1))should betruebut isfalse. - Error printing views of blocks of BlockSparseArray with GradedUnitRange axes, i.e.
r = gradedrange([U1(0) => 1]); a = BlockSparseArray{Float64}(r, r); @view a[Block(1, 1)]. - Change the design of slicing with unit ranges, i.e.
a[2:4, 2:4], by usingBlockArrays.BlockSlice. - Fix
a[Block(2), Block(2)] = randn(3, 3). - Fix
a[Block(2, 2)] .= 1. - Fix
@view(a[Block(1, 1)])[1:1, 1:1] = 1. - Throw error if
a[Block(1, 1)] = bifsize(a[Block(1, 1)]) != size(b). - Fix matrix multiplication of
BlockSparseMatrixinvolving dual axes. - Fix matrix multiplication involving adjointed
BlockSparseMatrix, i.e.a' * aanda * a', with and without dual axes. - Take the dual of the axes in
adjoint(::BlockSparseMatrix). Can be implemented by overloadingaxes(::Adjoint{<:Any,<:AbstractBlockSparseMatrix}). -
show(::Adjoint{<:Any,<:BlockSparseMatrix})andshow(::Transpose{<:Any,<:BlockSparseMatrix))are broken. - fix
eachindex(::BlockSparseArray)involving dual axes. - Fix [Hermitian] transposed
BlockSparseMatrix, i.e.a'(in progress in^adjoint). -
Base.similar(a::BlockSparseArray, eltype::type)andBase.similar(a::BlockSparseArray, eltype::type, size::NTuple{N,AbstractUnitRange})do not seteltype - Make
copy(::BlockSparseArray)copy the blocks. - Slicing with
a[1:2, 1:2]is not implemented yet and needs to be implemented (in progress in^slicing). - Function for accessing a list of initialized blocks. Currently you can use
stored_indices(blocks(a)))to get a list ofBlockcorresponding to initialized/stored blocks. Ideally there would be shorthands for this likeblock_stored_indices(a)(in progress in^slicing). - Function for accessing the number of initialized blocks. Currently you can use
nstored(blocks(a))to get the number of initialized/stored blocks. Ideally there would be shorthands for this likeblock_nstored(a)(in progress in^slicing). - In place operations
.*=and./=, such asa .*= 2, are broken (in progress in[^1]). -
Base.:*(::BlockSparseArray, x::Number)andBase.:/(::BlockSparseArray, x::Number)are not defined -
Base.:*(::ComplexF64, ::BlockSparseArray{Float64})does not change data type for empty array and crashes ifacontains data.
[^blockarrays_v1]: https://github.com/ITensor/ITensors.jl/pull/1452, https://github.com/JuliaArrays/BlockArrays.jl/pull/255
[^anygpuarray]: https://github.com/JuliaGPU/GPUArrays.jl/blob/v11.1.0/lib/GPUArraysCore/src/GPUArraysCore.jl#L27, https://github.com/JuliaGPU/CUDA.jl/blob/v5.4.2/src/array.jl#L396
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
This is a broad tracker for BlockSparseArray, covering multiple unchecked bugs and feature requests rather than one scoped change. Start by selecting a single unchecked item, then read the linked issue or reference, such as NDTensors/src/lib/BlockSparseArrays/test/test_basics.jl where mentioned. Done means the selected behavior is implemented and its relevant tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- data
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100