Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 6 additions & 3 deletions .github/workflows/FormatCheck.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Format Check"
name: FormatCheck

on:
push:
Expand All @@ -7,8 +7,11 @@ on:
- 'master'
tags: '*'
pull_request:
branches:
- 'main'
- 'master'

jobs:
format-check:
formatcheck:
name: "Format Check"
uses: "QuantumKitHub/.github/.github/workflows/formatcheck.yml@main"
uses: "QuantumKitHub/QuantumKitHubActions/.github/workflows/FormatCheck.yml@main"
24 changes: 12 additions & 12 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ pages = [
]

makedocs(;
modules=[BlockTensorKit],
sitename="BlockTensorKit.jl",
authors="Lukas Devos",
warnonly=[:missing_docs, :cross_references],
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", nothing) == "true",
mathengine=MathJax(),
repolink="https://github.com/lkdvos/BlockTensorKit.jl.git",
modules = [BlockTensorKit],
sitename = "BlockTensorKit.jl",
authors = "Lukas Devos",
warnonly = [:missing_docs, :cross_references],
format = Documenter.HTML(;
prettyurls = get(ENV, "CI", nothing) == "true",
mathengine = MathJax(),
repolink = "https://github.com/lkdvos/BlockTensorKit.jl.git",
),
pages=pages,
pagesonly=true,
repo="github.com/lkdvos/BlockTensorKit.jl.git",
pages = pages,
pagesonly = true,
repo = "github.com/lkdvos/BlockTensorKit.jl.git",
)

deploydocs(; repo="github.com/lkdvos/BlockTensorKit.jl.git", push_preview=true)
deploydocs(; repo = "github.com/lkdvos/BlockTensorKit.jl.git", push_preview = true)
83 changes: 40 additions & 43 deletions src/auxiliary/sparsetensorarray.jl
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# SparseBlockTensorMap parent array
# ---------------------------------
struct SparseTensorArray{S,N₁,N₂,T<:AbstractTensorMap{<:Any,S,N₁,N₂},N} <:
AbstractArray{T,N}
data::Dict{CartesianIndex{N},T}
space::TensorMapSumSpace{S,N₁,N₂}
function SparseTensorArray{S,N₁,N₂,T,N}(
data::Dict{CartesianIndex{N},T}, space::TensorMapSumSpace{S,N₁,N₂}
) where {S,N₁,N₂,T,N}
struct SparseTensorArray{S, N₁, N₂, T <: AbstractTensorMap{<:Any, S, N₁, N₂}, N} <:
AbstractArray{T, N}
data::Dict{CartesianIndex{N}, T}
space::TensorMapSumSpace{S, N₁, N₂}
function SparseTensorArray{S, N₁, N₂, T, N}(
data::Dict{CartesianIndex{N}, T}, space::TensorMapSumSpace{S, N₁, N₂}
) where {S, N₁, N₂, T, N}
N₁ + N₂ == N || throw(
TypeError(
:SparseTensorArray,
SparseTensorArray{S,N₁,N₂,T,N₁ + N₂},
SparseTensorArray{S,N₁,N₂,T,N},
SparseTensorArray{S, N₁, N₂, T, N₁ + N₂},
SparseTensorArray{S, N₁, N₂, T, N},
),
)
return new{S,N₁,N₂,T,N}(data, space)
return new{S, N₁, N₂, T, N}(data, space)
end
end

function SparseTensorArray{S,N₁,N₂,T,N}(
::UndefInitializer, space::TensorMapSumSpace{S,N₁,N₂}
) where {S,N₁,N₂,T<:AbstractTensorMap{<:Any,S,N₁,N₂},N}
return SparseTensorArray{S,N₁,N₂,T,N}(Dict{CartesianIndex{N},T}(), space)
function SparseTensorArray{S, N₁, N₂, T, N}(
::UndefInitializer, space::TensorMapSumSpace{S, N₁, N₂}
) where {S, N₁, N₂, T <: AbstractTensorMap{<:Any, S, N₁, N₂}, N}
return SparseTensorArray{S, N₁, N₂, T, N}(Dict{CartesianIndex{N}, T}(), space)
end

function SparseTensorArray(
data::Dict{CartesianIndex{N},T}, space::TensorMapSumSpace{S,N₁,N₂}
) where {S,N₁,N₂,T,N}
return SparseTensorArray{S,N₁,N₂,T,N}(data, space)
data::Dict{CartesianIndex{N}, T}, space::TensorMapSumSpace{S, N₁, N₂}
) where {S, N₁, N₂, T, N}
return SparseTensorArray{S, N₁, N₂, T, N}(data, space)
end

Base.pairs(A::SparseTensorArray) = pairs(A.data)
Expand All @@ -41,29 +41,29 @@ TensorKit.space(A::SparseTensorArray) = A.space
Base.size(A::SparseTensorArray) = ntuple(i -> length(space(A)[i]), ndims(A))

@inline function Base.getindex(
A::SparseTensorArray{S,N₁,N₂,T,N}, I::Vararg{Int,N}
) where {S,N₁,N₂,T,N}
A::SparseTensorArray{S, N₁, N₂, T, N}, I::Vararg{Int, N}
) where {S, N₁, N₂, T, N}
@boundscheck checkbounds(A, I...)
return @inbounds get(A.data, CartesianIndex(I)) do
return fill!(similar(T, eachspace(A)[I...]), zero(scalartype(T)))
end
end
@inline function getindex!(
A::SparseTensorArray{S,N₁,N₂,T,N}, I::CartesianIndex{N}
) where {S,N₁,N₂,T,N}
A::SparseTensorArray{S, N₁, N₂, T, N}, I::CartesianIndex{N}
) where {S, N₁, N₂, T, N}
@boundscheck checkbounds(A, I)
return @inbounds get!(A.data, I) do
return fill!(similar(T, eachspace(A)[I]), zero(scalartype(T)))
end
end
@inline function getindex!(
A::SparseTensorArray{S,N₁,N₂,T,N}, I::Vararg{Int,N}
) where {S,N₁,N₂,T,N}
A::SparseTensorArray{S, N₁, N₂, T, N}, I::Vararg{Int, N}
) where {S, N₁, N₂, T, N}
return getindex!(A, CartesianIndex(I))
end
@inline function Base.setindex!(
A::SparseTensorArray{S,N₁,N₂,T,N}, v, I::Vararg{Int,N}
) where {S,N₁,N₂,T,N}
A::SparseTensorArray{S, N₁, N₂, T, N}, v, I::Vararg{Int, N}
) where {S, N₁, N₂, T, N}
@boundscheck begin
checkbounds(A, I...)
checkspaces(A, v, I...)
Expand All @@ -72,26 +72,26 @@ end
return A
end

function Base.delete!(A::SparseTensorArray, I::Vararg{Int,N}) where {N}
function Base.delete!(A::SparseTensorArray, I::Vararg{Int, N}) where {N}
return delete!(A.data, CartesianIndex(I))
end
Base.delete!(A::SparseTensorArray, I::CartesianIndex) = delete!(A.data, I)
Base.empty!(A::SparseTensorArray) = empty!(A.data)
function Base.haskey(A::SparseTensorArray, I::Vararg{Int,N}) where {N}
function Base.haskey(A::SparseTensorArray, I::Vararg{Int, N}) where {N}
return haskey(A.data, CartesianIndex(I))
end
Base.haskey(A::SparseTensorArray, I::CartesianIndex) = haskey(A.data, I)

function Base.similar(
::SparseTensorArray, ::Type{T}, spaces::TensorMapSumSpace{S,N₁,N₂}
) where {S,N₁,N₂,T<:AbstractTensorMap{<:Any,S,N₁,N₂}}
::SparseTensorArray, ::Type{T}, spaces::TensorMapSumSpace{S, N₁, N₂}
) where {S, N₁, N₂, T <: AbstractTensorMap{<:Any, S, N₁, N₂}}
N = N₁ + N₂
return SparseTensorArray{S,N₁,N₂,T,N}(Dict{CartesianIndex{N},T}(), spaces)
return SparseTensorArray{S, N₁, N₂, T, N}(Dict{CartesianIndex{N}, T}(), spaces)
end

Base.@propagate_inbounds function Base.copyto!(
t::SparseTensorArray, v::SubArray{T,N,A}
) where {T,N,A<:SparseTensorArray}
t::SparseTensorArray, v::SubArray{T, N, A}
) where {T, N, A <: SparseTensorArray}
undropped_parentindices = map(Base.parentindices(v)) do I
I isa Base.ScalarIndex ? (I:I) : I
end
Expand All @@ -108,8 +108,8 @@ Base.@propagate_inbounds function Base.copyto!(
end

Base.@propagate_inbounds function Base.copyto!(
t::SubArray{T,N,A}, v::SparseTensorArray
) where {T,N,A<:SparseTensorArray}
t::SubArray{T, N, A}, v::SparseTensorArray
) where {T, N, A <: SparseTensorArray}
undropped_parentindices = map(Base.parentindices(t)) do I
I isa Base.ScalarIndex ? (I:I) : I
end
Expand All @@ -126,11 +126,9 @@ Base.@propagate_inbounds function Base.copyto!(
end

Base.@propagate_inbounds function Base.copyto!(
dest::SparseTensorArray,
Rdest::CartesianIndices,
src::SparseTensorArray,
Rsrc::CartesianIndices,
)
dest::SparseTensorArray, Rdest::CartesianIndices,
src::SparseTensorArray, Rsrc::CartesianIndices,
)
isempty(Rdest) && return dest
if size(Rdest) != size(Rsrc)
throw(
Expand Down Expand Up @@ -174,10 +172,9 @@ function _newindices(I::Tuple, indices::Tuple)
end

function Base._unsafe_getindex(
::IndexCartesian,
t::SparseTensorArray{S,N₁,N₂,T,N},
I::Vararg{Union{Real,AbstractArray},N},
) where {S,N₁,N₂,T,N}
::IndexCartesian,
t::SparseTensorArray{S, N₁, N₂, T, N}, I::Vararg{Union{Real, AbstractArray}, N},
) where {S, N₁, N₂, T, N}
dest = similar(t, eltype(t), space(eachspace(t)[I...]))
indices = Base.to_indices(t, I)
for (k, v) in t.data
Expand Down
95 changes: 47 additions & 48 deletions src/linalg/factorizations.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
using TensorKit: QR, QRpos, QL, QLpos, SVD, SDD, Polar, LQ, LQpos, RQ, RQpos

function TK.leftorth!(
t::AbstractBlockTensorMap;
alg::Union{QR,QRpos,QL,QLpos,SVD,SDD,Polar}=QRpos(),
atol::Real=zero(float(real(scalartype(t)))),
rtol::Real=if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
InnerProductStyle(t) === EuclideanInnerProduct() ||
throw_invalid_innerproduct(:leftorth!)
t::AbstractBlockTensorMap;
alg::Union{QR, QRpos, QL, QLpos, SVD, SDD, Polar} = QRpos(),
atol::Real = zero(float(real(scalartype(t)))),
rtol::Real = if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:leftorth!)
if !iszero(rtol)
atol = max(atol, rtol * norm(t))
end
I = sectortype(t)
dims = TK.SectorDict{I,Int}()
dims = TK.SectorDict{I, Int}()

# compute QR factorization for each block
if !isempty(TK.blocks(t))
Expand Down Expand Up @@ -59,22 +58,22 @@ function TK.leftorth!(t::SparseBlockTensorMap; kwargs...)
end

function TK.leftnull!(
t::BlockTensorMap;
alg::Union{QR,QRpos,SVD,SDD}=QRpos(),
atol::Real=zero(float(real(scalartype(t)))),
rtol::Real=if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
t::BlockTensorMap;
alg::Union{QR, QRpos, SVD, SDD} = QRpos(),
atol::Real = zero(float(real(scalartype(t)))),
rtol::Real = if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
InnerProductStyle(t) === EuclideanInnerProduct() ||
throw_invalid_innerproduct(:leftnull!)
if !iszero(rtol)
atol = max(atol, rtol * norm(t))
end
I = sectortype(t)
dims = SectorDict{I,Int}()
dims = SectorDict{I, Int}()

# compute QR factorization for each block
V = codomain(t)
Expand Down Expand Up @@ -104,22 +103,22 @@ end
TK.leftnull!(t::SparseBlockTensorMap; kwargs...) = leftnull!(BlockTensorMap(t); kwargs...)

function TK.rightorth!(
t::AbstractBlockTensorMap;
alg::Union{LQ,LQpos,RQ,RQpos,SVD,SDD,Polar}=LQpos(),
atol::Real=zero(float(real(scalartype(t)))),
rtol::Real=if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
t::AbstractBlockTensorMap;
alg::Union{LQ, LQpos, RQ, RQpos, SVD, SDD, Polar} = LQpos(),
atol::Real = zero(float(real(scalartype(t)))),
rtol::Real = if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
InnerProductStyle(t) === EuclideanInnerProduct() ||
throw_invalid_innerproduct(:rightorth!)
if !iszero(rtol)
atol = max(atol, rtol * norm(t))
end
I = sectortype(t)
dims = TK.SectorDict{I,Int}()
dims = TK.SectorDict{I, Int}()

# compute LQ factorization for each block
if !isempty(TK.blocks(t))
Expand Down Expand Up @@ -162,22 +161,22 @@ function TK.rightorth!(t::SparseBlockTensorMap; kwargs...)
end

function TK.rightnull!(
t::BlockTensorMap;
alg::Union{LQ,LQpos,SVD,SDD}=LQpos(),
atol::Real=zero(float(real(scalartype(t)))),
rtol::Real=if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
t::BlockTensorMap;
alg::Union{LQ, LQpos, SVD, SDD} = LQpos(),
atol::Real = zero(float(real(scalartype(t)))),
rtol::Real = if (alg ∉ (SVD(), SDD()))
zero(float(real(scalartype(t))))
else
eps(real(float(one(scalartype(t))))) * iszero(atol)
end,
)
InnerProductStyle(t) === EuclideanInnerProduct() ||
throw_invalid_innerproduct(:rightnull!)
if !iszero(rtol)
atol = max(atol, rtol * norm(t))
end
I = sectortype(t)
dims = SectorDict{I,Int}()
dims = SectorDict{I, Int}()

# compute LQ factorization for each block
V = domain(t)
Expand Down Expand Up @@ -206,16 +205,16 @@ function TK.rightnull!(
end
TK.rightnull!(t::SparseBlockTensorMap; kwargs...) = rightnull!(BlockTensorMap(t); kwargs...)

function TK.tsvd!(t::AbstractBlockTensorMap; trunc=TK.NoTruncation(), p::Real=2, alg=SDD())
function TK.tsvd!(t::AbstractBlockTensorMap; trunc = TK.NoTruncation(), p::Real = 2, alg = SDD())
return TK._tsvd!(t, alg, trunc, p)
end
function TK.tsvd!(t::SparseBlockTensorMap; kwargs...)
return tsvd!(BlockTensorMap(t); kwargs...)
end

function TK._tsvd!(
t::BlockTensorMap, alg::Union{SVD,SDD}, trunc::TruncationScheme, p::Real=2
)
t::BlockTensorMap, alg::Union{SVD, SDD}, trunc::TruncationScheme, p::Real = 2
)
# early return
if isempty(blocksectors(t))
truncerr = zero(real(scalartype(t)))
Expand All @@ -234,10 +233,10 @@ function TK._tsvd!(
return U, Σ, V⁺, truncerr
end

function TK._compute_svddata!(t::AbstractBlockTensorMap, alg::Union{SVD,SDD})
function TK._compute_svddata!(t::AbstractBlockTensorMap, alg::Union{SVD, SDD})
InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:tsvd!)
I = sectortype(t)
dims = SectorDict{I,Int}()
dims = SectorDict{I, Int}()
generator = Base.Iterators.map(TK.blocks(t)) do (c, b)
U, Σ, V = TK.MatrixAlgebra.svd!(b, alg)
dims[c] = length(Σ)
Expand Down Expand Up @@ -266,7 +265,7 @@ function TK._empty_svdtensors(t::AbstractBlockTensorMap)
T = scalartype(t)
S = spacetype(t)
I = sectortype(t)
dims = SectorDict{I,Int}()
dims = SectorDict{I, Int}()
W = S(dims)

U = similar(t, codomain(t) ← W)
Expand Down
Loading
Loading