Skip to content

Commit e2e2984

Browse files
committed
Merge branch 'master' into test-rewrite
2 parents 97ab153 + ec40cea commit e2e2984

19 files changed

+226
-255
lines changed

Diff for: .appveyor.yml

-36
This file was deleted.

Diff for: .github/workflows/CI.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
os:
5151
- ubuntu-latest
5252
- macOS-latest
53-
# - windows-latest # run on AppVeyor instead
53+
- windows-latest
5454
arch:
5555
- x64
5656
- x86

Diff for: src/TensorKit.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export ZNSpace, Z2Space, Z3Space, Z4Space, U1Space, CU1Space, SU2Space
2323
export Vect, Rep # space constructors
2424
export CompositeSpace, ProductSpace # composite spaces
2525
export FusionTree
26-
export IndexSpace, TensorSpace, AbstractTensorMap, AbstractTensor, TensorMap, Tensor # tensors and tensor properties
26+
export IndexSpace, TensorSpace, TensorMapSpace
27+
export AbstractTensorMap, AbstractTensor, TensorMap, Tensor, TrivialTensorMap # tensors and tensor properties
2728
export TruncationScheme
2829
export SpaceMismatch, SectorMismatch, IndexError # error types
2930

Diff for: src/auxiliary/deprecate.jl

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import Base: eltype, transpose
2-
@deprecate eltype(T::Type{<:AbstractTensorMap}) scalartype(T)
3-
@deprecate eltype(t::AbstractTensorMap) scalartype(t)
1+
import Base: transpose
42

53
#! format: off
64
@deprecate permute(t::AbstractTensorMap, p1::IndexTuple, p2::IndexTuple; copy::Bool=false) permute(t, (p1, p2); copy=copy)

Diff for: src/fusiontrees/manipulations.jl

+7-9
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,12 @@ function bendright(f₁::FusionTree{I,N₁}, f₂::FusionTree{I,N₂}) where {I<
253253
isdual2 = (f₂.isdual..., !(f₁.isdual[N₁]))
254254
inner2 = N₂ > 1 ? (f₂.innerlines..., c) : ()
255255

256+
coeff₀ = sqrtdim(c) * isqrtdim(a)
257+
if f₁.isdual[N₁]
258+
coeff₀ *= conj(frobeniusschur(dual(b)))
259+
end
256260
if FusionStyle(I) isa MultiplicityFreeFusion
257-
coeff = sqrtdim(c) * isqrtdim(a) * Bsymbol(a, b, c)
258-
if f₁.isdual[N₁]
259-
coeff *= conj(frobeniusschur(dual(b)))
260-
end
261+
coeff = coeff₀ * Bsymbol(a, b, c)
261262
vertices2 = N₂ > 0 ? (f₂.vertices..., nothing) : ()
262263
f₂′ = FusionTree(uncoupled2, a, isdual2, inner2, vertices2)
263264
return SingletonDict((f₁′, f₂′) => coeff)
@@ -266,11 +267,8 @@ function bendright(f₁::FusionTree{I,N₁}, f₂::FusionTree{I,N₂}) where {I<
266267
Bmat = Bsymbol(a, b, c)
267268
μ = N₁ > 1 ? f₁.vertices[end] : 1
268269
for ν in 1:size(Bmat, 2)
269-
coeff = sqrtdim(c) * isqrtdim(a) * Bmat[μ, ν]
270+
coeff = coeff₀ * Bmat[μ, ν]
270271
iszero(coeff) && continue
271-
if f₁.isdual[N₁]
272-
coeff *= conj(frobeniusschur(dual(b)))
273-
end
274272
vertices2 = N₂ > 0 ? (f₂.vertices..., ν) : ()
275273
f₂′ = FusionTree(uncoupled2, a, isdual2, inner2, vertices2)
276274
if @isdefined newtrees
@@ -332,7 +330,7 @@ function foldright(f₁::FusionTree{I,N₁}, f₂::FusionTree{I,N₂}) where {I<
332330
vertices = N₁ <= 2 ? () : Base.tail(Base.tail(fl′.vertices))
333331
fl = FusionTree{I}(uncoupled, coupled, isdual, inner, vertices)
334332
for (fr, coeff2) in insertat(fc, 2, f₂)
335-
coeff = factor * coeff1 * coeff2
333+
coeff = factor * coeff1 * conj(coeff2)
336334
if (@isdefined newtrees)
337335
newtrees[(fl, fr)] = get(newtrees, (fl, fr), zero(coeff)) +
338336
coeff

Diff for: src/spaces/cartesianspace.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""
2-
struct CartesianSpace <: ElementarySpace{ℝ}
2+
struct CartesianSpace <: ElementarySpace
33
44
A real Euclidean space `ℝ^d`, which is therefore self-dual. `CartesianSpace` has no
55
additonal structure and is completely characterised by its dimension `d`. This is the
66
vector space that is implicitly assumed in most of matrix algebra.
77
"""
8-
struct CartesianSpace <: ElementarySpace{ℝ}
8+
struct CartesianSpace <: ElementarySpace
99
d::Int
1010
end
1111
CartesianSpace(d::Integer=0; dual=false) = CartesianSpace(Int(d))
@@ -28,8 +28,10 @@ function CartesianSpace(dims::AbstractDict; kwargs...)
2828
end
2929
end
3030

31+
field(::Type{CartesianSpace}) =
3132
InnerProductStyle(::Type{CartesianSpace}) = EuclideanProduct()
3233

34+
Base.conj(V::CartesianSpace) = V
3335
isdual(V::CartesianSpace) = false
3436

3537
# convenience constructor

Diff for: src/spaces/complexspace.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""
2-
struct ComplexSpace <: ElementarySpace{ℂ}
2+
struct ComplexSpace <: ElementarySpace
33
44
A standard complex vector space ℂ^d with Euclidean inner product and no additional
55
structure. It is completely characterised by its dimension and whether its the normal space
66
or its dual (which is canonically isomorphic to the conjugate space).
77
"""
8-
struct ComplexSpace <: ElementarySpace{ℂ}
8+
struct ComplexSpace <: ElementarySpace
99
d::Int
1010
dual::Bool
1111
end
@@ -29,6 +29,7 @@ function ComplexSpace(dims::AbstractDict; kwargs...)
2929
end
3030
end
3131

32+
field(::Type{ComplexSpace}) =
3233
InnerProductStyle(::Type{ComplexSpace}) = EuclideanProduct()
3334

3435
# convenience constructor

Diff for: src/spaces/deligne.jl

+24-10
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,66 @@ The Deligne tensor product also works in the type domain and for sectors and ten
1212
group representations, we have `Rep[G₁] ⊠ Rep[G₂] == Rep[G₁ × G₂]`, i.e. these are the
1313
natural representation spaces of the direct product of two groups.
1414
"""
15-
(V₁::VectorSpace, V₂::VectorSpace) = (V₁ one(V₂)) (one(V₁) V₂)
15+
function (V₁::VectorSpace, V₂::VectorSpace)
16+
field(V₁) == field(V₂) || throw_incompatible_fields(V₁, V₂)
17+
return (V₁ one(V₂)) (one(V₁) V₂)
18+
end
1619

17-
# define deligne products with empty tensor product: just add a trivial sector of the type of the empty space to each of the sectors in the non-empty space
18-
function (V::GradedSpace, P₀::ProductSpace{<:ElementarySpace{ℂ},0})
20+
# define deligne products with empty tensor product: just add a trivial sector of the type
21+
# of the empty space to each of the sectors in the non-empty space
22+
function (V::GradedSpace, P₀::ProductSpace{<:ElementarySpace,0})
23+
field(V) == field(P₀) || throw_incompatible_fields(V, P₀)
1924
I₁ = sectortype(V)
2025
I₂ = sectortype(P₀)
2126
return Vect[I₁ I₂](ifelse(isdual(V), dual(c), c) one(I₂) => dim(V, c)
2227
for c in sectors(V); dual=isdual(V))
2328
end
2429

25-
function (P₀::ProductSpace{<:ElementarySpace{ℂ},0}, V::GradedSpace)
30+
function (P₀::ProductSpace{<:ElementarySpace,0}, V::GradedSpace)
31+
field(P₀) == field(V) || throw_incompatible_fields(P₀, V)
2632
I₁ = sectortype(P₀)
2733
I₂ = sectortype(V)
2834
return Vect[I₁ I₂](one(I₁) ifelse(isdual(V), dual(c), c) => dim(V, c)
2935
for c in sectors(V); dual=isdual(V))
3036
end
3137

32-
function (V::ComplexSpace, P₀::ProductSpace{<:ElementarySpace{ℂ},0})
38+
function (V::ComplexSpace, P₀::ProductSpace{<:ElementarySpace,0})
39+
field(V) == field(P₀) || throw_incompatible_fields(V, P₀)
3340
I₂ = sectortype(P₀)
3441
return Vect[I₂](one(I₂) => dim(V); dual=isdual(V))
3542
end
3643

37-
function (P₀::ProductSpace{<:ElementarySpace{ℂ},0}, V::ComplexSpace)
44+
function (P₀::ProductSpace{<:ElementarySpace,0}, V::ComplexSpace)
45+
field(P₀) == field(V) || throw_incompatible_fields(P₀, V)
3846
I₁ = sectortype(P₀)
3947
return Vect[I₁](one(I₁) => dim(V); dual=isdual(V))
4048
end
4149

42-
function (P::ProductSpace{<:ElementarySpace{ℂ},0},
43-
P₀::ProductSpace{<:ElementarySpace{ℂ},0})
50+
function (P::ProductSpace{<:ElementarySpace,0}, P₀::ProductSpace{<:ElementarySpace,0})
51+
field(P) == field(P₀) || throw_incompatible_fields(P, P₀)
4452
I₁ = sectortype(P)
4553
I₂ = sectortype(P₀)
4654
return one(Vect[I₁ I₂])
4755
end
4856

49-
function (P::ProductSpace{<:ElementarySpace{ℂ}}, P₀::ProductSpace{<:ElementarySpace{ℂ},0})
57+
function (P::ProductSpace{<:ElementarySpace}, P₀::ProductSpace{<:ElementarySpace,0})
58+
field(P) == field(P₀) || throw_incompatible_fields(P, P₀)
5059
I₁ = sectortype(P)
5160
I₂ = sectortype(P₀)
5261
S = Vect[I₁ I₂]
5362
N = length(P)
5463
return ProductSpace{S,N}(map(V -> V P₀, tuple(P...)))
5564
end
5665

57-
function (P₀::ProductSpace{<:ElementarySpace{ℂ},0}, P::ProductSpace{<:ElementarySpace{ℂ}})
66+
function (P₀::ProductSpace{<:ElementarySpace,0}, P::ProductSpace{<:ElementarySpace})
67+
field(P₀) == field(P) || throw_incompatible_fields(P₀, P)
5868
I₁ = sectortype(P₀)
5969
I₂ = sectortype(P)
6070
S = Vect[I₁ I₂]
6171
N = length(P)
6272
return ProductSpace{S,N}(map(V -> P₀ V, tuple(P...)))
6373
end
74+
75+
@noinline function throw_incompatible_fields(P₁, P₂)
76+
throw(ArgumentError("Deligne products require spaces over the same field: $(field(P₁))$(field(P₂))"))
77+
end

Diff for: src/spaces/generalspace.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""
2-
struct GeneralSpace{𝕜} <: ElementarySpace{𝕜}
2+
struct GeneralSpace{𝕜} <: ElementarySpace
33
44
A finite-dimensional space over an arbitrary field `𝕜` without additional structure.
55
It is thus characterized by its dimension, and whether or not it is the dual and/or
66
conjugate space. For a real field `𝕜`, the space and its conjugate are the same.
77
"""
8-
struct GeneralSpace{𝕜} <: ElementarySpace{𝕜}
8+
struct GeneralSpace{𝕜} <: ElementarySpace
99
d::Int
1010
dual::Bool
1111
conj::Bool
@@ -29,6 +29,7 @@ isconj(V::GeneralSpace) = V.conj
2929

3030
Base.axes(V::GeneralSpace) = Base.OneTo(dim(V))
3131

32+
field(::Type{GeneralSpace{𝕜}}) where {𝕜} = 𝕜
3233
InnerProductStyle(::Type{<:GeneralSpace}) = NoInnerProduct()
3334

3435
dual(V::GeneralSpace{𝕜}) where {𝕜} = GeneralSpace{𝕜}(dim(V), !isdual(V), isconj(V))

Diff for: src/spaces/gradedspace.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
struct GradedSpace{I<:Sector, D} <: ElementarySpace{ℂ}
2+
struct GradedSpace{I<:Sector, D} <: ElementarySpace
33
dims::D
44
dual::Bool
55
end
@@ -24,7 +24,7 @@ and should typically be of no concern.
2424
The concrete type `GradedSpace{I,D}` with correct `D` can be obtained as `Vect[I]`, or if
2525
`I == Irrep[G]` for some `G<:Group`, as `Rep[G]`.
2626
"""
27-
struct GradedSpace{I<:Sector,D} <: ElementarySpace{ℂ}
27+
struct GradedSpace{I<:Sector,D} <: ElementarySpace
2828
dims::D
2929
dual::Bool
3030
end
@@ -84,6 +84,7 @@ Base.hash(V::GradedSpace, h::UInt) = hash(V.dual, hash(V.dims, h))
8484

8585
# Corresponding methods:
8686
# properties
87+
field(::Type{<:GradedSpace}) =
8788
InnerProductStyle(::Type{<:GradedSpace}) = EuclideanProduct()
8889
function dim(V::GradedSpace)
8990
return reduce(+, dim(V, c) * dim(c) for c in sectors(V);

Diff for: src/spaces/homspace.jl

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ function Base.getindex(W::TensorMapSpace{<:IndexSpace,N₁,N₂}, i) where {N₁
4343
return i <= N₁ ? codomain(W)[i] : dual(domain(W)[i - N₁])
4444
end
4545

46-
function (dom::TensorSpace{S}, codom::TensorSpace{S}) where {S<:ElementarySpace}
47-
return HomSpace(ProductSpace(codom), ProductSpace(dom))
46+
function (codom::ProductSpace{S}, dom::ProductSpace{S}) where {S<:ElementarySpace}
47+
return HomSpace(codom, dom)
4848
end
49-
50-
function (codom::TensorSpace{S}, dom::TensorSpace{S}) where {S<:ElementarySpace}
49+
function (codom::S, dom::S) where {S<:ElementarySpace}
5150
return HomSpace(ProductSpace(codom), ProductSpace(dom))
5251
end
52+
(codom::VectorSpace, dom::VectorSpace) = (promote(codom, dom)...)
53+
(dom::VectorSpace, codom::VectorSpace) = (codom, dom)
5354

5455
function Base.show(io::IO, W::HomSpace)
5556
if length(W.codomain) == 1

Diff for: src/spaces/productspace.jl

+19-16
Original file line numberDiff line numberDiff line change
@@ -177,21 +177,11 @@ Base.hash(P::ProductSpace, h::UInt) = hash(P.spaces, h)
177177

178178
# Default construction from product of spaces
179179
#---------------------------------------------
180-
(V₁::S, V₂::S) where {S<:ElementarySpace} = ProductSpace((V₁, V₂))
181-
function (P1::ProductSpace{S}, V₂::S) where {S<:ElementarySpace}
182-
return ProductSpace(tuple(P1.spaces..., V₂))
183-
end
184-
function (V₁::S, P2::ProductSpace{S}) where {S<:ElementarySpace}
185-
return ProductSpace(tuple(V₁, P2.spaces...))
186-
end
180+
(V::Vararg{S}) where {S<:ElementarySpace} = ProductSpace(V)
181+
(P::ProductSpace) = P
187182
function (P1::ProductSpace{S}, P2::ProductSpace{S}) where {S<:ElementarySpace}
188-
return ProductSpace(tuple(P1.spaces..., P2.spaces...))
183+
return ProductSpace{S}(tuple(P1.spaces..., P2.spaces...))
189184
end
190-
(P::ProductSpace{S,0}, ::ProductSpace{S,0}) where {S<:ElementarySpace} = P
191-
(P::ProductSpace{S}, ::ProductSpace{S,0}) where {S<:ElementarySpace} = P
192-
(::ProductSpace{S,0}, P::ProductSpace{S}) where {S<:ElementarySpace} = P
193-
(V::ElementarySpace) = ProductSpace((V,))
194-
(P::ProductSpace) = P
195185

196186
# unit element with respect to the monoidal structure of taking tensor products
197187
"""
@@ -205,14 +195,12 @@ Base.one(V::VectorSpace) = one(typeof(V))
205195
Base.one(::Type{<:ProductSpace{S}}) where {S<:ElementarySpace} = ProductSpace{S,0}(())
206196
Base.one(::Type{S}) where {S<:ElementarySpace} = ProductSpace{S,0}(())
207197

208-
Base.convert(::Type{<:ProductSpace}, V::ElementarySpace) = ProductSpace((V,))
209198
Base.:^(V::ElementarySpace, N::Int) = ProductSpace{typeof(V),N}(ntuple(n -> V, N))
210199
Base.:^(V::ProductSpace, N::Int) = (ntuple(n -> V, N)...)
211200
function Base.literal_pow(::typeof(^), V::ElementarySpace, p::Val{N}) where {N}
212201
return ProductSpace{typeof(V),N}(ntuple(n -> V, p))
213202
end
214-
Base.convert(::Type{S}, P::ProductSpace{S,0}) where {S<:ElementarySpace} = oneunit(S)
215-
Base.convert(::Type{S}, P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)
203+
216204
fuse(P::ProductSpace{S,0}) where {S<:ElementarySpace} = oneunit(S)
217205
fuse(P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)
218206

@@ -255,3 +243,18 @@ Base.eltype(P::ProductSpace) = eltype(typeof(P))
255243

256244
Base.IteratorEltype(::Type{<:ProductSpace}) = Base.HasEltype()
257245
Base.IteratorSize(::Type{<:ProductSpace}) = Base.HasLength()
246+
247+
Base.reverse(P::ProductSpace) = ProductSpace(reverse(P.spaces))
248+
249+
# Promotion and conversion
250+
# ------------------------
251+
function Base.promote_rule(::Type{S}, ::Type{<:ProductSpace{S}}) where {S<:ElementarySpace}
252+
return ProductSpace{S}
253+
end
254+
255+
# ProductSpace to ElementarySpace
256+
Base.convert(::Type{S}, P::ProductSpace{S,0}) where {S<:ElementarySpace} = oneunit(S)
257+
Base.convert(::Type{S}, P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)
258+
259+
# ElementarySpace to ProductSpace
260+
Base.convert(::Type{<:ProductSpace}, V::S) where {S<:ElementarySpace} = (V)

0 commit comments

Comments
 (0)