Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SymmetrySectors] Non-abelian fusion #1363

Merged
merged 210 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
210 commits
Select commit Hold shift + click to select a range
882617d
clean start for non-abelian on main
ogauthe Mar 25, 2024
11121c9
split fusion rules test
ogauthe Mar 25, 2024
703c2f1
rename chain axis_cat
ogauthe Mar 25, 2024
9b5eb7e
rename dimension quantum_dimension
ogauthe Mar 25, 2024
d4ef71a
rename test_category.jl test_simple_categories.jl
ogauthe Mar 25, 2024
1e402c6
Merge branch 'ITensor:main' into non-abelian_fusion
ogauthe Mar 25, 2024
11a762a
test inferred quantum_dimension
ogauthe Mar 25, 2024
10ff71b
Remove isempty, length, and getindex for CategoryProduct
emstoudenmire Mar 26, 2024
c64af63
rm GradedAxesSectorsExt
ogauthe Mar 25, 2024
e6c5c49
fix category name
ogauthe Mar 25, 2024
57738e6
remove ⊕
ogauthe Mar 26, 2024
33c87e7
Merge branch 'ITensor:main' into non-abelian_fusion
ogauthe Mar 27, 2024
8bdfd31
Merge branch 'ITensor:main' into non-abelian_fusion
ogauthe Mar 28, 2024
af6b20f
tensor_product for GradedUnitRange
ogauthe Mar 27, 2024
b84772f
fix pairing
ogauthe Mar 28, 2024
9f86bf5
typo
ogauthe Mar 28, 2024
256f275
do not define methods for unused Vector{<:AbstractCategory}
ogauthe Mar 28, 2024
7c575e0
test different categories cannot be fused
ogauthe Mar 28, 2024
f695c5f
define SymmetryStyle and fusion of CategoryProduct{Tuple}
ogauthe Mar 29, 2024
c7b8b50
use SymmetryStyle
ogauthe Mar 29, 2024
2508c61
fusion rules for NamedTuple
ogauthe Mar 30, 2024
e234a75
further investigate quantum_dimension type stability
ogauthe Apr 1, 2024
be3f351
improve type stability
ogauthe Apr 2, 2024
bb0d757
fix type stability for quantum_dimension
ogauthe Apr 2, 2024
6e6b10c
fix product of singlet
ogauthe Apr 2, 2024
667ea0f
pass Named Category Products, broken Ordered Products
ogauthe Apr 2, 2024
11434d6
trickier tests
ogauthe Apr 3, 2024
1830781
all test passing
ogauthe Apr 3, 2024
3ae8e46
def and use gradedisequal
ogauthe Apr 3, 2024
fc96238
test mixed GradedUnitRange - Category
ogauthe Apr 3, 2024
b71f9b2
delete files not supposed to be under git
ogauthe Apr 3, 2024
56de936
dispatch instead of test type
ogauthe Apr 4, 2024
34dc147
define fusion_product for CategoryProduct
ogauthe Apr 4, 2024
551db7a
rename label -> category_label
ogauthe Apr 5, 2024
7f54001
split tensor_product and fusion_product
ogauthe Apr 5, 2024
06febc1
simplify quantum_dimensions
ogauthe Apr 8, 2024
2396e5e
blockmergesortperm for dual
ogauthe Apr 8, 2024
dfa478d
remove unused functions
ogauthe Apr 8, 2024
0000e5c
add more comments
ogauthe Apr 9, 2024
57b3fc8
support julia 1.6
ogauthe Apr 10, 2024
c6f24f8
Swap Ordered Products and Named Category Products
ogauthe Apr 11, 2024
c0e8e8d
inline pack_named_tuple, adjust tests
ogauthe Apr 15, 2024
0e1869f
add comment on label type
ogauthe Apr 15, 2024
9b3419c
parametric U1 and SU{N}, remove SU2
ogauthe Apr 23, 2024
b0e71fe
typo
ogauthe Apr 23, 2024
20b80a5
Merge branch 'main' into non-abelian_fusion
ogauthe Apr 23, 2024
68662a5
improve display
ogauthe Apr 24, 2024
298338d
remove unused abstractgradedunitrange.jl
ogauthe Apr 24, 2024
598cd42
define blocklabels and gradedisequal for UnitRangeDual
ogauthe Apr 24, 2024
bc10ca0
def trivial(::CategoryProduct)
ogauthe Apr 25, 2024
60a5410
simplify SU{N}
ogauthe Apr 25, 2024
de95045
SU2 as a concrete type
ogauthe Apr 25, 2024
043d106
trivial(::AbstractCategory)
ogauthe May 1, 2024
63ab67e
avoid confusion between integer and tuple interfaces
ogauthe May 1, 2024
c4f10e0
define trivial(::AbstractUnitRange)
ogauthe May 2, 2024
d3e0f34
def isdual
ogauthe May 17, 2024
bc5a2b7
define block_boundaries
ogauthe May 22, 2024
5ddf8ea
Merge branch 'main' into non-abelian_fusion
ogauthe May 28, 2024
96e9992
define fusion_product(g1,g2,g3)
ogauthe May 29, 2024
ba863f1
remove unused dual(type)
ogauthe May 29, 2024
e618ed0
rename block_boundaries into block_dimensions
ogauthe May 29, 2024
27b03d9
use block_dimensions in quantum_dimension. Set quantum_dimension(Empt…
ogauthe May 29, 2024
c36654e
simplify istrivial
ogauthe May 29, 2024
7683df0
use iterator
ogauthe May 30, 2024
be768ab
single EmptyCategory type, act as trivial
ogauthe May 30, 2024
326ec5f
define categories_trivial
ogauthe May 30, 2024
d3cced6
categories_isequal
ogauthe May 30, 2024
00b2172
test sector() acts as trivial
ogauthe May 30, 2024
d30c320
fix new line in printing
ogauthe May 30, 2024
e738a11
Merge branch 'main' into non-abelian_fusion
ogauthe Jun 3, 2024
fc9bacb
sector with Type arg
ogauthe Jun 3, 2024
3bcde67
reorder file
ogauthe Jun 3, 2024
9c968b0
use @inferred_latest
ogauthe Jun 4, 2024
bf31a2e
clean categories_fusion_rule
ogauthe Jun 4, 2024
7d7e57d
dual blocklabels
ogauthe Jun 5, 2024
4dae197
fuse EmptyCategory
ogauthe Jun 6, 2024
aff0006
reorder file
ogauthe Jun 6, 2024
1aa1317
replace for loops with Iterators
ogauthe Jun 6, 2024
18763f6
used labelled
ogauthe Jun 6, 2024
951f08e
use mapreduce
ogauthe Jun 6, 2024
bd8e6e7
define fusion_product for non-abelian groups
ogauthe Jun 7, 2024
f366af7
add tests
ogauthe Jun 7, 2024
cbda58b
support OneToOne
ogauthe Jun 7, 2024
cdc4030
share more implementation
ogauthe Jun 7, 2024
1ef04c1
reorder file
ogauthe Jun 7, 2024
2bfe8dd
rigorous comparisons
ogauthe Jun 7, 2024
19df9ea
Merge branch 'main' into non-abelian_fusion
ogauthe Jun 10, 2024
a86e67e
Merge branch 'main' into non-abelian_fusion
ogauthe Jun 14, 2024
3b4e3cb
fix tests
ogauthe Jun 14, 2024
d42c017
define flip
ogauthe Jun 14, 2024
45e8cc6
show(::UnitRangeDual)
ogauthe Jun 14, 2024
43c8b4d
fix tensor_product(::dual)
ogauthe Jun 14, 2024
fb59499
adapt to BlockArrays 1.1
ogauthe Jun 18, 2024
b47fded
fix Vararg
ogauthe Jun 18, 2024
2193a93
Merge branch 'main' into non-abelian_fusion
ogauthe Jun 18, 2024
9a04046
remove unneeded method
ogauthe Jun 18, 2024
7397ba6
Merge branch 'main' into non-abelian_fusion
ogauthe Jul 2, 2024
e2548ee
add O(2) group
ogauthe Aug 15, 2024
b3a4e50
Merge branch 'main' into non-abelian_fusion
ogauthe Sep 5, 2024
f016ba1
Merge branch 'main' into non-abelian_fusion
ogauthe Sep 12, 2024
fbf0734
remove gradedisequal(::OneToOne)
ogauthe Sep 16, 2024
d9cd486
avoid mixing fusion_rule and fuse_blocklengths interfaces
ogauthe Sep 17, 2024
933c0d4
Merge branch 'main' into non-abelian_fusion
ogauthe Sep 17, 2024
de8759d
fix fuse_blocklengths(::EmptyCategory)
ogauthe Sep 17, 2024
cd58321
rm 'NDTensors/src/lib/Sectors/Project.toml'
ogauthe Sep 25, 2024
f9f3b5b
use do-block syntax
ogauthe Sep 25, 2024
a4954fb
remove GradedRange.
ogauthe Sep 25, 2024
c7820aa
isdual default to false
ogauthe Sep 25, 2024
3d65e28
fix unlabel type in trivial
ogauthe Sep 25, 2024
f19dc44
fix namespace
ogauthe Sep 25, 2024
2e29af1
fix comment typo
ogauthe Sep 25, 2024
5153333
add comments on O(2)
ogauthe Sep 25, 2024
de29e17
avoid using implementation detail
ogauthe Sep 25, 2024
f9e47ed
replace find_common/diff with categories_common/diff
ogauthe Sep 25, 2024
7b61766
simplify categories_isequal and categories_isless
ogauthe Sep 25, 2024
ad12d60
Revert "rm 'NDTensors/src/lib/Sectors/Project.toml'"
ogauthe Sep 25, 2024
8aeb097
explicit imports
ogauthe Sep 26, 2024
a4803f1
explicit import HalfInteger
ogauthe Sep 26, 2024
e8624e3
is_zero_even_or_odd(O2)
ogauthe Sep 26, 2024
9d54770
remove gradedisequal(OneToOne)
ogauthe Sep 26, 2024
f165066
add comment on convention
ogauthe Sep 26, 2024
94ae370
generic blockmergesort
ogauthe Sep 26, 2024
f417bec
fix import
ogauthe Sep 26, 2024
26daedf
define EmptyCategoryProduct alias
ogauthe Sep 26, 2024
c50f3cd
fix typo in comment
ogauthe Sep 26, 2024
6ea394c
generic blocksortperm/blockmergesortperm(a::AbstractUnitRange)
ogauthe Sep 26, 2024
b94f4e8
import at begining of file
ogauthe Sep 27, 2024
2684005
comment on map use
ogauthe Sep 27, 2024
0f485a2
clean-up categories_fusion_rule
ogauthe Sep 27, 2024
8abad01
split gradedisequal into labelled_isequal and space_isequal
ogauthe Sep 27, 2024
e93bfe2
rename to_graded_axis to_gradedrange
ogauthe Oct 2, 2024
fe5237a
remove outdated comment
ogauthe Oct 2, 2024
4cb7874
implicit tuple in CategoryProduct
ogauthe Oct 2, 2024
1855045
remove redundant isless
ogauthe Oct 2, 2024
737c5c2
use do-block syntax
ogauthe Oct 2, 2024
65dc71e
fix blockmergesort(g::UnitRangeDual)
ogauthe Oct 2, 2024
b4380b0
use NoLabel as default blocklabel
ogauthe Oct 2, 2024
a36f4d7
assert issorted
ogauthe Oct 2, 2024
f325011
unify handling of tensor_product(dual)
ogauthe Oct 2, 2024
77ef307
split shared and diff category
ogauthe Oct 2, 2024
b3e6008
generic blockaxes(::OneToOne)
ogauthe Oct 2, 2024
648bc28
rename EmptyCategory to EmptyCategoryStyle
ogauthe Oct 2, 2024
c14422a
use only 2 symmetry styles: Abelian and NotAbelian
ogauthe Oct 3, 2024
a566784
rename EmptyCategory to TrivialSector
ogauthe Oct 3, 2024
3ba966e
avoid sector
ogauthe Oct 3, 2024
a7a860d
add commennt
ogauthe Oct 3, 2024
0089c58
use NotAbelianStyle in categories_fusion_rule
ogauthe Oct 3, 2024
168c1ce
better variable name
ogauthe Oct 3, 2024
843fc2d
impose same type in shared
ogauthe Oct 3, 2024
7edaf03
remove sector, define TrivialSector()
ogauthe Oct 3, 2024
7b548bf
do not assume Tuple category type
ogauthe Oct 3, 2024
74c6e76
split shared_categories_fusion_rule methods
ogauthe Oct 3, 2024
8c19a1f
use mapreduce
ogauthe Oct 3, 2024
738d912
SymmetryStyle defined for types
ogauthe Oct 3, 2024
e63b3e0
fix test in Julia 1.6
ogauthe Oct 3, 2024
90cad20
simplify reduce_style
ogauthe Oct 3, 2024
22e9ac9
reorder file
ogauthe Oct 3, 2024
10ff55c
do not forbid empty NamedTuple
ogauthe Oct 3, 2024
d5630db
add comment
ogauthe Oct 3, 2024
4294dea
refactor label_fusion_rule
ogauthe Oct 3, 2024
6cc612f
categories_symmetrystyle
ogauthe Oct 4, 2024
f3f6b96
non-abelian interface in tensor_product
ogauthe Oct 4, 2024
7f98183
define TrivialSector
ogauthe Oct 4, 2024
9fac111
use mapreduce
ogauthe Oct 4, 2024
895e7ac
fix tests for julia 1.6
ogauthe Oct 4, 2024
d4794ed
rename Category to Sector
ogauthe Oct 4, 2024
692e08a
fusion_rule(::AbelianStyle to call fusion_rule(::NotAbelianStyle
ogauthe Oct 7, 2024
d0b81d9
rename Sectors to SymmetrySectors
ogauthe Oct 7, 2024
d84df4e
more tolerant on missing sectors
ogauthe Oct 7, 2024
2fe8bbc
factorize sym_sectors_insert_unspecified
ogauthe Oct 7, 2024
ddb62d5
rename sectors product_sectors
ogauthe Oct 8, 2024
d65bbbb
define abelian_label_fusion_rule
ogauthe Oct 9, 2024
97f7522
use list comprehension
ogauthe Oct 9, 2024
e21d7ac
simplify product_sectors_fusion_rule
ogauthe Oct 9, 2024
7461b11
fix tests for julia 1.6
ogauthe Oct 9, 2024
20acb54
explicit variable name
ogauthe Oct 10, 2024
21df582
inline factorize_gradedaxis
ogauthe Oct 10, 2024
ed52101
consistent type naming
ogauthe Oct 10, 2024
ede71b5
label_fusion_rule to return pair
ogauthe Oct 11, 2024
7407e83
remove debug print
ogauthe Oct 11, 2024
7a7f2b8
refactor recover_sector_product_type
ogauthe Oct 11, 2024
77df75d
remove julia1.6 specific @inferred_latest
ogauthe Oct 11, 2024
28299fd
Merge branch 'main' into non-abelian_fusion
ogauthe Oct 14, 2024
b322fca
fix tests
ogauthe Oct 14, 2024
5e9d0db
Merge branch 'main' into non-abelian_fusion
ogauthe Oct 14, 2024
df35a5f
sort TrivialSector as trivial for any Sector
ogauthe Oct 21, 2024
00fd5f8
use broadcast
ogauthe Oct 21, 2024
435f775
refactor shared_product_sectors_fusion_rule
ogauthe Oct 21, 2024
beba332
test more comparisons
ogauthe Oct 22, 2024
3f05a81
remove conflicting adjoint
ogauthe Oct 22, 2024
8901076
enforce U1(Int32(1)) == U1(1)
ogauthe Oct 22, 2024
8bd77e5
fix isless(U1)
ogauthe Oct 22, 2024
0589a4e
style
ogauthe Oct 22, 2024
abe14a4
defined set_sector_label
ogauthe Oct 22, 2024
15e1187
add test
ogauthe Oct 22, 2024
9c5b664
Merge branch 'main' into non-abelian_fusion
ogauthe Oct 22, 2024
5260dbd
inline empty edge cases
ogauthe Oct 24, 2024
5db5015
rename product_sectors to arguments
ogauthe Oct 24, 2024
6f6ae82
more compact
ogauthe Oct 24, 2024
02442b2
add more tests
ogauthe Oct 24, 2024
798bd10
compact arguments_isequal
ogauthe Oct 24, 2024
752efe0
more tests
ogauthe Oct 24, 2024
46ffcfb
generic case
ogauthe Oct 24, 2024
36c076f
generic arguments_product
ogauthe Oct 24, 2024
65453b6
better error messages
ogauthe Oct 24, 2024
c41c2fe
style
ogauthe Oct 24, 2024
f130f34
generic isless
ogauthe Oct 24, 2024
900321a
generic isequal
ogauthe Oct 24, 2024
3ba3ba9
avoid _argument_isless
ogauthe Oct 24, 2024
f8358fe
remove _arguments_isequal
ogauthe Oct 24, 2024
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 NDTensors/src/imports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ for lib in [
:MetalExtensions,
:BroadcastMapConversion,
:RankFactorization,
:Sectors,
:LabelledNumbers,
:GradedAxes,
:SymmetrySectors,
:TensorAlgebra,
:SparseArrayInterface,
:SparseArrayDOKs,
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 1 addition & 2 deletions NDTensors/src/lib/GradedAxes/src/GradedAxes.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module GradedAxes
include("blockedunitrange.jl")
include("gradedunitrange.jl")
include("fusion.jl")
include("dual.jl")
include("unitrangedual.jl")
include("../ext/GradedAxesSectorsExt/src/GradedAxesSectorsExt.jl")
include("fusion.jl")
end
2 changes: 2 additions & 0 deletions NDTensors/src/lib/GradedAxes/src/dual.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ using NDTensors.LabelledNumbers:
label_dual(x) = label_dual(LabelledStyle(x), x)
label_dual(::NotLabelled, x) = x
label_dual(::IsLabelled, x) = labelled(unlabel(x), dual(label(x)))

flip(g::AbstractGradedUnitRange) = dual(gradedrange(label_dual.(blocklengths(g))))
mtfishman marked this conversation as resolved.
Show resolved Hide resolved
75 changes: 44 additions & 31 deletions NDTensors/src/lib/GradedAxes/src/fusion.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using BlockArrays: AbstractBlockedUnitRange
using BlockArrays: AbstractBlockedUnitRange, blocklengths

# Represents the range `1:1` or `Base.OneTo(1)`.
struct OneToOne{T} <: AbstractUnitRange{T} end
OneToOne() = OneToOne{Bool}()
Base.first(a::OneToOne) = one(eltype(a))
Base.last(a::OneToOne) = one(eltype(a))
BlockArrays.blockaxes(g::OneToOne) = (Block.(g),) # BlockArrays default crashes for OneToOne{Bool}

# https://github.com/ITensor/ITensors.jl/blob/v0.3.57/NDTensors/src/lib/GradedAxes/src/tensor_product.jl
# https://en.wikipedia.org/wiki/Tensor_product
Expand All @@ -18,23 +19,25 @@ function tensor_product(
return foldl(tensor_product, (a1, a2, a3, a_rest...))
end

flip_dual(r::AbstractUnitRange) = r
flip_dual(r::UnitRangeDual) = flip(r)
function tensor_product(a1::AbstractUnitRange, a2::AbstractUnitRange)
return error("Not implemented yet.")
return tensor_product(flip_dual(a1), flip_dual(a2))
end

function tensor_product(a1::Base.OneTo, a2::Base.OneTo)
return Base.OneTo(length(a1) * length(a2))
end

function tensor_product(a1::OneToOne, a2::AbstractUnitRange)
function tensor_product(::OneToOne, a2::AbstractUnitRange)
return a2
end

function tensor_product(a1::AbstractUnitRange, a2::OneToOne)
function tensor_product(a1::AbstractUnitRange, ::OneToOne)
return a1
end

function tensor_product(a1::OneToOne, a2::OneToOne)
function tensor_product(::OneToOne, ::OneToOne)
return OneToOne()
end

Expand All @@ -45,27 +48,28 @@ function fuse_labels(x, y)
end

function fuse_blocklengths(x::Integer, y::Integer)
return x * y
# return blocked unit range to keep non-abelian interface
return blockedrange([x * y])
end

using ..LabelledNumbers: LabelledInteger, label, labelled, unlabel
function fuse_blocklengths(x::LabelledInteger, y::LabelledInteger)
return labelled(unlabel(x) * unlabel(y), fuse_labels(label(x), label(y)))
# return blocked unit range to keep non-abelian interface
return blockedrange([labelled(x * y, fuse_labels(label(x), label(y)))])
end

using BlockArrays: blockedrange, blocks
function tensor_product(a1::AbstractBlockedUnitRange, a2::AbstractBlockedUnitRange)
blocklengths = map(vec(collect(Iterators.product(blocks(a1), blocks(a2))))) do x
return mapreduce(length, fuse_blocklengths, x)
nested = map(Iterators.flatten((Iterators.product(blocks(a1), blocks(a2)),))) do it
return mapreduce(length, fuse_blocklengths, it)
end
return blockedrange(blocklengths)
new_blocklengths = mapreduce(blocklengths, vcat, nested)
return blockedrange(new_blocklengths)
end

function blocksortperm(a::AbstractBlockedUnitRange)
# TODO: Figure out how to deal with dual sectors.
# TODO: `rev=isdual(a)` may not be correct for symmetries beyond `U(1)`.
## return Block.(sortperm(nondual_sectors(a); rev=isdual(a)))
return Block.(sortperm(blocklabels(a)))
# convention: sort UnitRangeDual according to nondual blocks
function blocksortperm(a::AbstractUnitRange)
return Block.(sortperm(blocklabels(nondual(a))))
end

using BlockArrays: Block, BlockVector
Expand All @@ -82,25 +86,34 @@ end
# Used by `TensorAlgebra.splitdims` in `BlockSparseArraysGradedAxesExt`.
# Get the permutation for sorting, then group by common elements.
# groupsortperm([2, 1, 2, 3]) == [[2], [1, 3], [4]]
function blockmergesortperm(a::AbstractBlockedUnitRange)
# If it is dual, reverse the sorting so the sectors
# end up sorted in the same way whether or not the space
# is dual.
# TODO: Figure out how to deal with dual sectors.
# TODO: `rev=isdual(a)` may not be correct for symmetries beyond `U(1)`.
## return Block.(groupsortperm(nondual_sectors(a); rev=isdual(a)))
return Block.(groupsortperm(blocklabels(a)))
function blockmergesortperm(a::AbstractUnitRange)
return Block.(groupsortperm(blocklabels(nondual(a))))
end

# Used by `TensorAlgebra.splitdims` in `BlockSparseArraysGradedAxesExt`.
invblockperm(a::Vector{<:Block{1}}) = Block.(invperm(Int.(a)))

# Used by `TensorAlgebra.fusedims` in `BlockSparseArraysGradedAxesExt`.
function blockmergesortperm(a::GradedUnitRange)
# If it is dual, reverse the sorting so the sectors
# end up sorted in the same way whether or not the space
# is dual.
# TODO: Figure out how to deal with dual sectors.
# TODO: `rev=isdual(a)` may not be correct for symmetries beyond `U(1)`.
return Block.(groupsortperm(blocklabels(a)))
function blockmergesort(g::AbstractGradedUnitRange)
glabels = blocklabels(g)
gblocklengths = blocklengths(g)
new_blocklengths = map(sort(unique(glabels))) do la
return labelled(sum(gblocklengths[findall(==(la), glabels)]; init=0), la)
end
return gradedrange(new_blocklengths)
end

blockmergesort(g::UnitRangeDual) = flip(blockmergesort(flip(g)))
blockmergesort(g::AbstractUnitRange) = g

# fusion_product produces a sorted, non-dual GradedUnitRange
function fusion_product(g1, g2)
return blockmergesort(tensor_product(g1, g2))
end

fusion_product(g::AbstractUnitRange) = blockmergesort(g)
fusion_product(g::UnitRangeDual) = fusion_product(flip(g))

# recursive fusion_product. Simpler than reduce + fix type stability issues with reduce
function fusion_product(g1, g2, g3...)
return fusion_product(fusion_product(g1, g2), g3...)
end
mtfishman marked this conversation as resolved.
Show resolved Hide resolved
15 changes: 14 additions & 1 deletion NDTensors/src/lib/GradedAxes/src/gradedunitrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ using BlockArrays:
blockedrange,
BlockIndexRange,
blockfirsts,
blocklasts,
blockisequal,
blocklength,
blocklengths,
findblock,
findblockindex,
mortar
using Compat: allequal
using FillArrays: Fill
using ..LabelledNumbers:
LabelledNumbers, LabelledInteger, LabelledUnitRange, label, labelled, unlabel

Expand All @@ -37,6 +38,18 @@ function Base.OrdinalRange{T,T}(a::GradedOneTo{<:LabelledInteger{T}}) where {T}
return unlabel_blocks(a)
end

# == is just a range comparison that ignores labels. Need dedicated function to check equality.
struct NoLabel end
blocklabels(r::AbstractUnitRange) = Fill(NoLabel(), blocklength(r))

function labelled_isequal(a1::AbstractUnitRange, a2::AbstractUnitRange)
return blockisequal(a1, a2) && (blocklabels(a1) == blocklabels(a2))
end

function space_isequal(a1::AbstractUnitRange, a2::AbstractUnitRange)
return (isdual(a1) == isdual(a2)) && labelled_isequal(a1, a2)
end

# This is only needed in certain Julia versions below 1.10
# (for example Julia 1.6).
# TODO: Delete this once we drop Julia 1.6 support.
Expand Down
16 changes: 16 additions & 0 deletions NDTensors/src/lib/GradedAxes/src/unitrangedual.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ UnitRangeDual(a::AbstractUnitRange) = UnitRangeDual{eltype(a),typeof(a)}(a)
dual(a::AbstractUnitRange) = UnitRangeDual(a)
nondual(a::UnitRangeDual) = a.nondual_unitrange
dual(a::UnitRangeDual) = nondual(a)
flip(a::UnitRangeDual) = dual(flip(nondual(a)))
nondual(a::AbstractUnitRange) = a
isdual(::AbstractUnitRange) = false
isdual(::UnitRangeDual) = true
## TODO: Define this to instantiate a dual unit range.
## materialize_dual(a::UnitRangeDual) = materialize_dual(nondual(a))

Expand All @@ -16,6 +19,16 @@ Base.step(a::UnitRangeDual) = label_dual(step(nondual(a)))

Base.view(a::UnitRangeDual, index::Block{1}) = a[index]

function Base.show(io::IO, a::UnitRangeDual)
return print(io, UnitRangeDual, "(", blocklasts(a), ")")
end

function Base.show(io::IO, mimetype::MIME"text/plain", a::UnitRangeDual)
return Base.invoke(
show, Tuple{typeof(io),MIME"text/plain",AbstractArray}, io, mimetype, a
)
end

function Base.getindex(a::UnitRangeDual, indices::AbstractUnitRange{<:Integer})
return dual(getindex(nondual(a), indices))
end
Expand Down Expand Up @@ -92,6 +105,9 @@ BlockArrays.blockaxes(a::UnitRangeDual) = blockaxes(nondual(a))
BlockArrays.blockfirsts(a::UnitRangeDual) = label_dual.(blockfirsts(nondual(a)))
BlockArrays.blocklasts(a::UnitRangeDual) = label_dual.(blocklasts(nondual(a)))
BlockArrays.findblock(a::UnitRangeDual, index::Integer) = findblock(nondual(a), index)

blocklabels(a::UnitRangeDual) = dual.(blocklabels(nondual(a)))
mtfishman marked this conversation as resolved.
Show resolved Hide resolved

function BlockArrays.combine_blockaxes(a1::UnitRangeDual, a2::UnitRangeDual)
return dual(combine_blockaxes(dual(a1), dual(a2)))
end
Expand Down
2 changes: 1 addition & 1 deletion NDTensors/src/lib/GradedAxes/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Test: @testset
@testset "GradedAxes" begin
include("test_basics.jl")
include("test_tensor_product.jl")
include("test_dual.jl")
include("test_tensor_product.jl")
end
end
4 changes: 3 additions & 1 deletion NDTensors/src/lib/GradedAxes/test/test_basics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ using BlockArrays:
blocklength,
blocklengths,
blocks
using NDTensors.GradedAxes: GradedOneTo, GradedUnitRange, blocklabels, gradedrange
using NDTensors.GradedAxes:
GradedOneTo, GradedUnitRange, blocklabels, labelled_isequal, gradedrange
using NDTensors.LabelledNumbers: LabelledUnitRange, islabelled, label, labelled, unlabel
using Test: @test, @test_broken, @testset
@testset "GradedAxes basics" begin
Expand Down Expand Up @@ -40,6 +41,7 @@ using Test: @test, @test_broken, @testset
@test label(x) == "y"
end
@test isnothing(iterate(a, labelled(5, "y")))
@test labelled_isequal(a, a)
@test length(a) == 5
@test step(a) == 1
@test !islabelled(step(a))
Expand Down
62 changes: 57 additions & 5 deletions NDTensors/src/lib/GradedAxes/test/test_dual.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
@eval module $(gensym())
using BlockArrays: Block, blockaxes, blockfirsts, blocklasts, blocks, findblock
using NDTensors.GradedAxes: GradedAxes, UnitRangeDual, dual, gradedrange, nondual
using BlockArrays:
Block, blockaxes, blockfirsts, blocklasts, blocklength, blocklengths, blocks, findblock
using NDTensors.GradedAxes:
GradedAxes,
UnitRangeDual,
blocklabels,
blockmergesortperm,
blocksortperm,
dual,
flip,
space_isequal,
gradedrange,
isdual,
nondual
using NDTensors.LabelledNumbers: LabelledInteger, label, labelled
using Test: @test, @test_broken, @testset
struct U1
n::Int
end
GradedAxes.dual(c::U1) = U1(-c.n)
Base.isless(c1::U1, c2::U1) = c1.n < c2.n
@testset "dual" begin
a = gradedrange([U1(0) => 2, U1(1) => 3])
ad = dual(a)
@test eltype(ad) == LabelledInteger{Int,U1}
@test dual(ad) == a
@test nondual(ad) == a
@test nondual(a) == a

@test space_isequal(dual(ad), a)
@test space_isequal(nondual(ad), a)
@test space_isequal(nondual(a), a)
@test space_isequal(ad, ad)
@test !space_isequal(a, ad)
@test !space_isequal(ad, a)

@test isdual(ad)
@test !isdual(a)

@test blockfirsts(ad) == [labelled(1, U1(0)), labelled(3, U1(-1))]
@test blocklasts(ad) == [labelled(2, U1(0)), labelled(5, U1(-1))]
@test findblock(ad, 4) == Block(2)
Expand All @@ -34,5 +55,36 @@ GradedAxes.dual(c::U1) = U1(-c.n)
@test label(ad[[Block(2), Block(1)]][Block(1)]) == U1(-1)
@test ad[[Block(2)[1:2], Block(1)[1:2]]][Block(1)] == 3:4
@test label(ad[[Block(2)[1:2], Block(1)[1:2]]][Block(1)]) == U1(-1)
@test blocksortperm(a) == [Block(1), Block(2)]
@test blocksortperm(ad) == [Block(1), Block(2)]
@test blocklength(blockmergesortperm(a)) == 2
@test blocklength(blockmergesortperm(ad)) == 2
@test blockmergesortperm(a) == [Block(1), Block(2)]
@test blockmergesortperm(ad) == [Block(1), Block(2)]
end

@testset "flip" begin
a = gradedrange([U1(0) => 2, U1(1) => 3])
ad = dual(a)
@test space_isequal(flip(a), dual(gradedrange([U1(0) => 2, U1(-1) => 3])))
@test space_isequal(flip(ad), gradedrange([U1(0) => 2, U1(-1) => 3]))

@test blocklabels(a) == [U1(0), U1(1)]
@test blocklabels(dual(a)) == [U1(0), U1(-1)]
@test blocklabels(flip(a)) == [U1(0), U1(1)]
@test blocklabels(flip(dual(a))) == [U1(0), U1(-1)]
@test blocklabels(dual(flip(a))) == [U1(0), U1(-1)]

@test blocklengths(a) == [2, 3]
@test blocklengths(dual(a)) == [2, 3]
@test blocklengths(flip(a)) == [2, 3]
@test blocklengths(flip(dual(a))) == [2, 3]
@test blocklengths(dual(flip(a))) == [2, 3]

@test !isdual(a)
@test isdual(dual(a))
@test isdual(flip(a))
@test !isdual(flip(dual(a)))
@test !isdual(dual(flip(a)))
end
end
Loading
Loading