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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "GradedArrays"
uuid = "bc96ca6e-b7c8-4bb6-888e-c93f838762c2"
version = "0.15.4"
version = "0.15.5"
authors = ["ITensor developers <support@itensor.org> and contributors"]

[workspace]
Expand Down
22 changes: 22 additions & 0 deletions src/fusionarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,22 @@ function Base.adjoint(fa::FusionArray{<:Any, <:Any, 2})
)
end

# ============================ conj ============================
# Conjugate while keeping the codomain/domain split, unlike the `AbstractGradedArray` `conj.(a)`
# broadcast, which materializes into a fresh array and so lands at the all-codomain split. Fill a
# same-split destination (per-leg axes dualized) with a single `op = conj` permute-add over the
# identity biperm, so the TensorKit-backed transform folds in the leg-reversal fermion sign and the
# non-abelian recoupling that a bare block conjugation would drop.
function Base.conj(fa::FusionArray{<:Any, <:Any, <:Any, <:Any, NC, ND}) where {NC, ND}
dest = TensorAlgebra.similar_map(
fa, map(dual, axes_codomain(fa)), map(dual, axes_domain(fa))
)
TensorAlgebra.bipermutedimsopadd!(
dest, conj, fa, ntuple(identity, Val(NC)), ntuple(i -> NC + i, Val(ND)), true, false
)
return dest
end

# ============================ bare-matrix factorizations ============================
# Route the plain matrix forms (`MAK.svd_compact(m)`, etc.) through the matricizing `TensorAlgebra`
# factorizations, identical to the `AbelianGradedMatrix` methods in `matrixalgebrakit.jl` (which
Expand Down Expand Up @@ -360,6 +376,12 @@ function TensorAlgebra.similar_map(
) where {T}
return FusionArray{T}(undef, axes_codomain, axes_domain)
end
# Rank-0: the empty axes carry no sector type, so read it from the `FusionArray` prototype.
function TensorAlgebra.similar_map(
fa::FusionArray, ::Type{T}, axes_codomain::Tuple{}, axes_domain::Tuple{}
) where {T}
return FusionArray{T, sectortype(fa)}(undef, axes_codomain, axes_domain)
end

# Fill the reduced coupled-sector blocks in place, forwarding to the matricized `FusedGradedMatrix`
# (which fills via `eachblockstoredindex`). Construct with `FusionArray{T}(undef, …)` first.
Expand Down
45 changes: 43 additions & 2 deletions test/test_fusionarray.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using GradedArrays:
FusedGradedMatrix, FusionArray, SU2, SectorRange, U1, Z2, dual, gradedrange, isdual
using GradedArrays: FusedGradedMatrix, FusionArray, SU2, SectorRange, U1, Z2, dual,
gradedrange, isdual, ndims_codomain, ndims_domain
using LinearAlgebra: Diagonal
using Random: randn!
using TensorAlgebra: bipermutedims, contract, matricize, svd_compact
Expand Down Expand Up @@ -92,6 +92,47 @@ end
end
end

@testset "conj (split-preserving) ($G)" for (G, cod, dom) in (
(
"U1 (1,1)",
(gradedrange([U1(0) => 2, U1(1) => 1]),),
(gradedrange([U1(0) => 1, U1(1) => 2]),),
),
(
"SU2 (1,2)",
(gradedrange([SU2(0) => 1, SU2(1 // 2) => 2]),),
(
gradedrange([SU2(0) => 2, SU2(1 // 2) => 1]),
gradedrange([SU2(0) => 1, SU2(1 // 2) => 2]),
),
),
(
"fermion (2,1)",
(gradedrange([fP0 => 2, fP1 => 1]), gradedrange([fP0 => 1, fP1 => 2])),
(gradedrange([fP0 => 2, fP1 => 1]),),
),
)
a = randn_fusionarray(ComplexF64, cod, dom)
c = conj(a)
@test c isa FusionArray
# Split preserved (unlike the `conj.(a)` broadcast, which materializes all-codomain), per-leg
# axes dualized.
@test (ndims_codomain(c), ndims_domain(c)) == (ndims_codomain(a), ndims_domain(a))
@test axes(c) == map(dual, axes(a))
# Same tensor as the broadcast conj and an involution, compared at a common split via `≈` (a
# non-abelian double conj picks up recoupling round-off, so `==` is too strict).
@test c ≈ conj.(a)
@test conj(c) ≈ a
end

@testset "conj of a rank-0 FusionArray" begin
a = randn!(FusionArray{ComplexF64, U1}(undef, (), ()))
c = conj(a)
@test c isa FusionArray
@test ndims(c) == 0
@test c[] ≈ conj(a[])
end

@testset "contraction ($G)" for (G, i, j, k, l) in (
(
"U1", gradedrange([U1(0) => 2, U1(1) => 1]),
Expand Down