Skip to content

Commit bc22b8d

Browse files
committed
explicit flip of domain tree
1 parent 6b68a54 commit bc22b8d

File tree

4 files changed

+32
-14
lines changed

4 files changed

+32
-14
lines changed

src/fusion_trees/fusiontree.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# compatibility with TensorKit conventions?
55

66
using GradedUnitRanges:
7-
AbstractGradedUnitRange, GradedUnitRanges, fusion_product, isdual, sector_type
7+
AbstractGradedUnitRange, GradedUnitRanges, flip, fusion_product, isdual, sector_type
88
using SymmetrySectors: ×, AbstractSector, SectorProduct, SymmetrySectors, arguments, trivial
99
using TensorAlgebra: flatten_tuples
1010

@@ -80,6 +80,15 @@ Base.length(::SectorFusionTree{<:Any,N}) where {N} = N
8080

8181
# GradedUnitRanges interface
8282
GradedUnitRanges.sector_type(::Type{<:SectorFusionTree{S}}) where {S} = S
83+
function GradedUnitRanges.flip(f::SectorFusionTree)
84+
return SectorFusionTree(
85+
dual.(leaves(f)),
86+
.!arrows(f),
87+
dual(root_sector(f)),
88+
dual.(branch_sectors(f)),
89+
outer_multiplicity_indices(f),
90+
)
91+
end
8392

8493
# SymmetrySectors interface
8594
function SymmetrySectors.:×(f1::SectorFusionTree, f2::SectorFusionTree)

src/fusiontensor/array_cast.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ end
165165

166166
function contract_singlet_projector(f1::SectorFusionTree, f2::SectorFusionTree)
167167
f1_array = convert(Array, f1)
168-
f2_array = convert(Array, f2)
168+
f2_array = convert(Array, flip(f2))
169169
N_CO = length(f1)
170170
N_DO = length(f2)
171171
return contract(

src/fusiontensor/base_interface.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ Base.Array(ft::FusionTensor) = Array(to_array(ft))
3838

3939
# adjoint is costless: dual axes, swap codomain and domain, take data_matrix adjoint.
4040
# data_matrix coeff are not modified (beyond complex conjugation)
41-
transpose_mapping(d::Dict) = Dict([reverse(k) => transpose_mapping(v) for (k, v) in d])
41+
function transpose_mapping(d::Dict)
42+
return Dict([reverse(flip.(k)) => transpose_mapping(v) for (k, v) in d])
43+
end
4244
function transpose_mapping(b::BlockIndexRange{2})
4345
new_block = Block(reverse(Tuple(Block(b))))
4446
return new_block[reverse(b.indices)...]

src/fusiontensor/fusiontensor.jl

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using GradedUnitRanges:
99
blocklabels,
1010
blockmergesort,
1111
dual,
12+
flip,
1213
gradedrange,
1314
isdual,
1415
map_blocklabels,
@@ -71,7 +72,7 @@ function BlockArrays.findblock(ft::FusionTensor, f1::SectorFusionTree, f2::Secto
7172
# find outer block corresponding to fusion trees
7273
@assert typeof((f1, f2)) === keytype(trees_block_mapping(ft))
7374
b1 = find_sector_block.(leaves(f1), codomain_axes(ft))
74-
b2 = find_sector_block.(leaves(f2), dual.(domain_axes(ft)))
75+
b2 = find_sector_block.(leaves(f2), domain_axes(ft))
7576
return Block(b1..., b2...)
7677
end
7778
# TBD move to GradedUnitRanges? rename findfirst_sector?
@@ -137,16 +138,24 @@ function FusionTensor(mat::AbstractMatrix, legs::BlockedTuple{2})
137138
return ft
138139
end
139140

141+
function flip_domain(nonflipped_col_axis, nonflipped_trees_to_ranges)
142+
col_axis = dual(nonflipped_col_axis)
143+
domain_trees_to_ranges_mapping = Dict(
144+
map(((tree, v),) -> flip(tree) => v, collect(nonflipped_trees_to_ranges))
145+
)
146+
return col_axis, domain_trees_to_ranges_mapping
147+
end
148+
140149
# empty matrix
141150
function FusionTensor(elt::Type, raw_legs::BlockedTuple{2})
142151
S, legs = sanitize_axes(raw_legs)
143152

144-
row_axis, codomain_trees_to_ranges_mapping = fuse_axes(S, first(blocks(legs)))
145-
nondual_col_axis, domain_trees_to_ranges_mapping = fuse_axes(S, dual.(last(blocks(legs))))
153+
row_axis, codomain_trees_to_ranges = fuse_axes(S, first(blocks(legs)))
154+
col_axis, domain_trees_to_ranges = flip_domain(fuse_axes(S, dual.(last(blocks(legs))))...)
146155

147-
mat = initialize_data_matrix(elt, row_axis, nondual_col_axis)
156+
mat = initialize_data_matrix(elt, row_axis, col_axis)
148157
tree_to_block_mapping = intersect_codomain_domain(
149-
codomain_trees_to_ranges_mapping, domain_trees_to_ranges_mapping
158+
codomain_trees_to_ranges, domain_trees_to_ranges
150159
)
151160
return FusionTensor(mat, legs, tree_to_block_mapping)
152161
end
@@ -170,9 +179,7 @@ function fusion_trees_external_multiplicities(
170179
)
171180
end
172181

173-
function block_fusion_trees_external_multiplicities(
174-
it::NTuple{N,AbstractUnitRange}
175-
) where {N}
182+
function block_fusion_trees_external_multiplicities(it::Tuple{Vararg{AbstractUnitRange}})
176183
block_sectors = only.(blocklabels.(it))
177184
block_mult = prod(length.(it))
178185
return build_trees(block_sectors, isdual.(it)) .=> block_mult
@@ -206,7 +213,7 @@ function intersect_codomain_domain(
206213
return Dict(
207214
map(
208215
Iterators.filter(
209-
t -> root_sector(first(t[1])) == root_sector(first(t[2])),
216+
t -> root_sector(first(first(t))) == dual(root_sector(first(t[2]))),
210217
Iterators.product(codomain_trees_to_ranges_mapping, domain_trees_to_ranges_mapping),
211218
),
212219
) do t
@@ -218,11 +225,11 @@ end
218225
function initialize_data_matrix(
219226
elt::Type{<:Number},
220227
mat_row_axis::AbstractGradedUnitRange,
221-
nondual_col_axis::AbstractGradedUnitRange,
228+
mat_col_axis::AbstractGradedUnitRange,
222229
)
223230
# non-abelian fusion trees have float eltype: need compatible type
224231
promoted = promote_type(elt, fusiontree_eltype(sector_type(mat_row_axis)))
225-
mat = BlockSparseArray{promoted}(mat_row_axis, dual(nondual_col_axis))
232+
mat = BlockSparseArray{promoted}(mat_row_axis, mat_col_axis)
226233
initialize_allowed_sectors!(mat)
227234
return mat
228235
end

0 commit comments

Comments
 (0)