Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GradedArrays"
uuid = "bc96ca6e-b7c8-4bb6-888e-c93f838762c2"
authors = ["ITensor developers <[email protected]> and contributors"]
version = "0.4.2"
version = "0.4.3"

[deps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
Expand All @@ -11,6 +11,7 @@ DerivableInterfaces = "6c5e35bf-e59e-4898-b73c-732dcc4ba65f"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
HalfIntegers = "f0d1745a-41c9-11e9-1dd9-e5d34d218721"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MatrixAlgebraKit = "6c742aac-3347-4629-af66-fc926824e5e4"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SplitApplyCombine = "03a91e81-4c3e-53e1-a0a4-9c0c8f19dd66"
TensorProducts = "decf83d6-1968-43f4-96dc-fdb3fe15fc6d"
Expand All @@ -24,12 +25,13 @@ GradedArraysTensorAlgebraExt = "TensorAlgebra"

[compat]
BlockArrays = "1.6.0"
BlockSparseArrays = "0.5"
BlockSparseArrays = "0.5.2"
Compat = "4.16.0"
DerivableInterfaces = "0.4.4"
FillArrays = "1.13.0"
HalfIntegers = "1.6.0"
LinearAlgebra = "1.10.0"
MatrixAlgebraKit = "0.1.2"
Random = "1.10.0"
SplitApplyCombine = "1.2.3"
TensorAlgebra = "0.3.2"
Expand Down
1 change: 1 addition & 0 deletions src/GradedArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ include("sector_product.jl")

include("fusion.jl")
include("gradedarray.jl")
include("factorizations.jl")

export SU2,
U1,
Expand Down
75 changes: 75 additions & 0 deletions src/factorizations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using BlockArrays: blocks
using BlockSparseArrays:
BlockSparseArrays,
BlockSparseMatrix,
BlockPermutedDiagonalAlgorithm,
BlockPermutedDiagonalTruncationStrategy,
diagview,
eachblockaxis,
mortar_axis
using LinearAlgebra: Diagonal
using MatrixAlgebraKit: MatrixAlgebraKit, svd_compact!, svd_full!, svd_trunc!

function BlockSparseArrays.similar_output(
::typeof(svd_compact!),
A::GradedMatrix,
s_axis::AbstractUnitRange,
alg::BlockPermutedDiagonalAlgorithm,
)
u_axis = s_axis
flx = flux(A)
axs = eachblockaxis(s_axis)
# TODO: Use `gradedrange` constructor.
v_axis = mortar_axis(
map(axs) do ax
return sectorrange(dual(sector(ax)) ⊗ flx, ungrade(ax))
end,
)
U = similar(A, axes(A, 1), dual(u_axis))
T = real(eltype(A))
S = BlockSparseMatrix{T,Diagonal{T,Vector{T}}}(undef, (u_axis, dual(v_axis)))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that this is not very general (for example it would be bad on GPU), probably it should be factored out into a similar_diagonal_blocks function or something like that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is more or less why I had an original function _similar_S there to specialize on, since I don't think we really have the infrastructure right now to make that work.
The only thing I can come up with is trying to get type inference to tell us what the output type of initialize_output would be on the blocktypes of the input, but that also seems somewhat brittle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it would be nice to come up with a good code pattern for this. I think promote_op on initialize_output of the input blocktypes could be a good general fallback definition, and then we could use similar(a, BlockType(...)) once we define that.

Vt = similar(A, v_axis, axes(A, 2))
return U, S, Vt
end

function BlockSparseArrays.similar_output(
::typeof(svd_full!),
A::GradedMatrix,
s_axis::AbstractUnitRange,
alg::BlockPermutedDiagonalAlgorithm,
)
U = similar(A, axes(A, 1), dual(s_axis))
T = real(eltype(A))
S = similar(A, T, (s_axis, axes(A, 2)))
Vt = similar(A, dual(axes(A, 2)), axes(A, 2))
return U, S, Vt
end

const TGradedUSVᴴ = Tuple{<:GradedMatrix,<:GradedMatrix,<:GradedMatrix}

function BlockSparseArrays.similar_truncate(
::typeof(svd_trunc!),
(U, S, Vᴴ)::TGradedUSVᴴ,
strategy::BlockPermutedDiagonalTruncationStrategy,
indexmask=MatrixAlgebraKit.findtruncated(diagview(S), strategy),
)
ax = axes(S, 1)
counter = Base.Fix1(count, Base.Fix1(getindex, indexmask))
s_lengths = map(counter, blocks(ax))
s_sectors = sectors(ax) .=> s_lengths
s_sectors_filtered = filter(>(0) ∘ last, s_sectors)
s_axis = gradedrange(s_sectors_filtered)
u_axis = s_axis
flx = flux(S)
axs = eachblockaxis(s_axis)
# TODO: Use `gradedrange` constructor.
v_axis = mortar_axis(
map(axs) do ax
return sectorrange(dual(sector(ax)) ⊗ flx, ungrade(ax))
end,
)
Ũ = similar(U, axes(U, 1), dual(u_axis))
S̃ = similar(S, u_axis, dual(v_axis))
Ṽᴴ = similar(Vᴴ, v_axis, axes(Vᴴ, 2))
return Ũ, S̃, Ṽᴴ
end
38 changes: 31 additions & 7 deletions src/gradedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ using BlockSparseArrays:
AnyAbstractBlockSparseArray,
BlockSparseArray,
blocktype,
eachblockstoredindex,
sparsemortar
using LinearAlgebra: Adjoint
using TypeParameterAccessors: similartype, unwrap_array_type
Expand Down Expand Up @@ -41,13 +42,17 @@ function similar_blocksparse(
elt::Type,
axes::Tuple{AbstractGradedUnitRange,Vararg{AbstractGradedUnitRange}},
)
# TODO: Probably need to unwrap the type of `a` in certain cases
# to make a proper block type.
return BlockSparseArray{
elt,length(axes),similartype(unwrap_array_type(blocktype(a)), elt, axes)
}(
undef, axes
)
blockaxistypes = map(axes) do axis
return eltype(Base.promote_op(eachblockaxis, typeof(axis)))
end
similar_blocktype = Base.promote_op(similar, blocktype(a), Type{elt}, Tuple{blockaxistypes...})
return BlockSparseArray{elt,length(axes),similar_blocktype}(undef, axes)
end

function Base.similar(
a::AbstractArray, elt::Type, axes::Tuple{SectorOneTo,Vararg{SectorOneTo}}
)
return similar(a, elt, Base.OneTo.(length.(axes)))
end

function Base.similar(
Expand Down Expand Up @@ -120,6 +125,25 @@ end

ungrade(a::GradedArray) = sparsemortar(blocks(a), ungrade.(axes(a)))

function flux(a::GradedArray{<:Any,N}, I::Vararg{Block{1},N}) where {N}
sects = ntuple(N) do d
return flux(axes(a, d), I[d])
end
return ⊗(sects...)
end
function flux(a::GradedArray{<:Any,N}, I::Block{N}) where {N}
return flux(a, Tuple(I)...)
end
function flux(a::GradedArray)
sect = nothing
for I in eachblockstoredindex(a)
sect_I = flux(a, I)
isnothing(sect) || sect_I == sect || throw(ArgumentError("Inconsistent flux."))
sect = sect_I
end
return sect
end

# Copy of `Base.dims2string` defined in `show.jl`.
function dims_to_string(d)
isempty(d) && return "0-dimensional"
Expand Down
14 changes: 10 additions & 4 deletions src/gradedunitrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ using BlockArrays:
combine_blockaxes,
findblock,
mortar
using BlockSparseArrays: BlockSparseArrays, blockedunitrange_getindices
using BlockSparseArrays:
BlockSparseArrays, blockedunitrange_getindices, eachblockaxis, mortar_axis
using Compat: allequal

# ==================================== Definitions =======================================
Expand Down Expand Up @@ -60,7 +61,7 @@ end

# ===================================== Accessors ========================================

eachblockaxis(g::GradedUnitRange) = g.eachblockaxis
BlockSparseArrays.eachblockaxis(g::GradedUnitRange) = g.eachblockaxis
ungrade(g::GradedUnitRange) = g.full_range

sector_multiplicities(g::GradedUnitRange) = sector_multiplicity.(eachblockaxis(g))
Expand All @@ -69,12 +70,12 @@ sector_type(::Type{<:GradedUnitRange{<:Any,SUR}}) where {SUR} = sector_type(SUR)

# ==================================== Constructors ======================================

function mortar_axis(geachblockaxis::AbstractVector{<:SectorOneTo})
function BlockSparseArrays.mortar_axis(geachblockaxis::AbstractVector{<:SectorOneTo})
brange = blockedrange(length.(geachblockaxis))
return GradedUnitRange(geachblockaxis, brange)
end

function mortar_axis(gaxes::AbstractVector{<:GradedOneTo})
function BlockSparseArrays.mortar_axis(gaxes::AbstractVector{<:GradedOneTo})
return mortar_axis(mapreduce(eachblockaxis, vcat, gaxes))
end

Expand Down Expand Up @@ -102,6 +103,11 @@ function sectors(g::AbstractGradedUnitRange)
return sector.(eachblockaxis(g))
end

function flux(a::AbstractGradedUnitRange, I::Block{1})
sect = sector(a[I])
return isdual(a) ? dual(sect) : sect
end

function map_sectors(f, g::GradedUnitRange)
return GradedUnitRange(map_sectors.(f, eachblockaxis(g)), ungrade(g))
end
Expand Down
Loading