Skip to content

Commit d080e79

Browse files
authored
insertunit and removeunit using Val (#224)
* insertunit and removeunit using Val * more homspace tests * improve tests and docs
1 parent 1e4972e commit d080e79

File tree

11 files changed

+225
-180
lines changed

11 files changed

+225
-180
lines changed

docs/src/lib/sectors.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Finally, these are used to define large manipulations of fusion-splitting tree p
113113
are then used in the index manipulation of `AbstractTensorMap` objects. The following methods
114114
defined on fusion splitting tree pairs have an associated definition for tensors.
115115
```@docs
116-
repartition
116+
repartition(::FusionTree{I,N₁}, ::FusionTree{I,N₂}, ::Int) where {I<:Sector,N₁,N₂}
117117
transpose(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
118118
braid(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple, ::IndexTuple, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
119119
permute(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}

docs/src/lib/spaces.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ isepimorphic
108108
isisomorphic
109109
```
110110

111+
Inserting trivial space factors or removing such factors for `ProductSpace` instances
112+
can be done with the following methods.
113+
```@docs
114+
insertleftunit(::ProductSpace, ::Val{i}) where {i}
115+
insertrightunit(::ProductSpace, ::Val{i}) where {i}
116+
removeunit(::ProductSpace, ::Val{i}) where {i}
117+
```
118+
111119
There are also specific methods for `HomSpace` instances, that are used in determining
112120
the resuling `HomSpace` after applying certain tensor operations.
113121

@@ -116,6 +124,7 @@ flip(W::HomSpace{S}, I) where {S}
116124
TensorKit.permute(::HomSpace{S}, ::Index2Tuple{N₁,N₂}) where {S,N₁,N₂}
117125
TensorKit.select(::HomSpace{S}, ::Index2Tuple{N₁,N₂}) where {S,N₁,N₂}
118126
TensorKit.compose(::HomSpace{S}, ::HomSpace{S}) where {S}
119-
insertleftunit(::HomSpace, ::Int)
120-
insertrightunit(::HomSpace, ::Int)
127+
insertleftunit(::HomSpace, ::Val{i}) where {i}
128+
insertrightunit(::HomSpace, ::Val{i}) where {i}
129+
removeunit(::HomSpace, ::Val{i}) where {i}
121130
```

docs/src/lib/tensors.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ Base.getindex(::AbstractTensorMap, ::Vararg{SliceIndex})
137137
Base.setindex!(::AbstractTensorMap, ::Any, ::Vararg{SliceIndex})
138138
```
139139

140+
The tensor data can also be filled with random numbers via
141+
```@docs
142+
Random.rand!
143+
Random.randn!
144+
Random.randexp!
145+
```
146+
140147
## `AbstractTensorMap` operations
141148

142149
The operations that can be performed on an `AbstractTensorMap` can be organized into the
@@ -171,14 +178,15 @@ type `add_transform!`, for additional expert-mode options that allows for additi
171178
scaling, as well as the selection of a custom backend.
172179

173180
```@docs
174-
permute(::AbstractTensorMap, ::Index2Tuple{N₁,N₂}; ::Bool) where {N₁,N₂}
175-
braid(::AbstractTensorMap, ::Index2Tuple, ::IndexTuple; ::Bool)
176-
transpose(::AbstractTensorMap, ::Index2Tuple; ::Bool)
177-
repartition(::AbstractTensorMap, ::Int, ::Int; ::Bool)
181+
permute(::AbstractTensorMap, ::Index2Tuple{N₁,N₂}) where {N₁,N₂}
182+
braid(::AbstractTensorMap, ::Index2Tuple, ::IndexTuple)
183+
transpose(::AbstractTensorMap, ::Index2Tuple)
184+
repartition(::AbstractTensorMap, ::Int, ::Int)
178185
flip(t::AbstractTensorMap, I)
179-
twist(::AbstractTensorMap, ::Int; ::Bool)
180-
insertleftunit(::AbstractTensorMap, ::Int)
181-
insertrightunit(::AbstractTensorMap, ::Int)
186+
twist(::AbstractTensorMap, ::Int)
187+
insertleftunit(::AbstractTensorMap, ::Val{i}) where {i}
188+
insertrightunit(::AbstractTensorMap, ::Val{i}) where {i}
189+
removeunit(::AbstractTensorMap, ::Val{i}) where {i}
182190
```
183191

184192
```@docs

src/spaces/homspace.jl

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -174,52 +174,58 @@ function compose(W::HomSpace{S}, V::HomSpace{S}) where {S}
174174
end
175175

176176
"""
177-
insertleftunit(W::HomSpace, i::Int=numind(W) + 1; conj=false, dual=false)
177+
insertleftunit(W::HomSpace, i=numind(W) + 1; conj=false, dual=false)
178178
179-
Insert a trivial vector space, isomorphic to the underlying field, at position `i`.
179+
Insert a trivial vector space, isomorphic to the underlying field, at position `i`,
180+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
180181
More specifically, adds a left monoidal unit or its dual.
181182
182-
See also [`insertrightunit`](@ref), [`removeunit`](@ref).
183+
See also [`insertrightunit`](@ref insertrightunit(::HomSpace, ::Val{i}) where {i}),
184+
[`removeunit`](@ref removeunit(::HomSpace, ::Val{i}) where {i}).
183185
"""
184-
@constprop :aggressive function insertleftunit(W::HomSpace, i::Int=numind(W) + 1;
185-
conj::Bool=false, dual::Bool=false)
186+
function insertleftunit(W::HomSpace, ::Val{i}=Val(numind(W) + 1);
187+
conj::Bool=false, dual::Bool=false) where {i}
186188
if i numout(W)
187-
return insertleftunit(codomain(W), i; conj, dual) domain(W)
189+
return insertleftunit(codomain(W), Val(i); conj, dual) domain(W)
188190
else
189-
return codomain(W) insertleftunit(domain(W), i - numout(W); conj, dual)
191+
return codomain(W) insertleftunit(domain(W), Val(i - numout(W)); conj, dual)
190192
end
191193
end
192194

193195
"""
194-
insertrightunit(W::HomSpace, i::Int=numind(W); conj=false, dual=false)
196+
insertrightunit(W::HomSpace, i=numind(W); conj=false, dual=false)
195197
196-
Insert a trivial vector space, isomorphic to the underlying field, after position `i`.
198+
Insert a trivial vector space, isomorphic to the underlying field, after position `i`,
199+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
197200
More specifically, adds a right monoidal unit or its dual.
198201
199-
See also [`insertleftunit`](@ref), [`removeunit`](@ref).
202+
See also [`insertleftunit`](@ref insertleftunit(::HomSpace, ::Val{i}) where {i}),
203+
[`removeunit`](@ref removeunit(::HomSpace, ::Val{i}) where {i}).
200204
"""
201-
@constprop :aggressive function insertrightunit(W::HomSpace, i::Int=numind(W);
202-
conj::Bool=false, dual::Bool=false)
205+
function insertrightunit(W::HomSpace, ::Val{i}=Val(numind(W));
206+
conj::Bool=false, dual::Bool=false) where {i}
203207
if i numout(W)
204-
return insertrightunit(codomain(W), i; conj, dual) domain(W)
208+
return insertrightunit(codomain(W), Val(i); conj, dual) domain(W)
205209
else
206-
return codomain(W) insertrightunit(domain(W), i - numout(W); conj, dual)
210+
return codomain(W) insertrightunit(domain(W), Val(i - numout(W)); conj, dual)
207211
end
208212
end
209213

210214
"""
211-
removeunit(P::HomSpace, i::Int)
215+
removeunit(P::HomSpace, i)
212216
213-
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`.
214-
For this to work, that factor has to be isomorphic to the field of scalars.
217+
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`, where `i`
218+
can be specified as an `Int` or as `Val(i)` for improved type stability.
219+
For this to work, the space at position `i` has to be isomorphic to the field of scalars.
215220
216-
This operation undoes the work of [`insertleftunit`](@ref) or [`insertrightunit`](@ref).
221+
This operation undoes the work of [`insertleftunit`](@ref insertleftunit(::HomSpace, ::Val{i}) where {i})
222+
and [`insertrightunit`](@ref insertrightunit(::HomSpace, ::Val{i}) where {i}).
217223
"""
218-
@constprop :aggressive function removeunit(P::HomSpace, i::Int)
224+
function removeunit(P::HomSpace, ::Val{i}) where {i}
219225
if i numout(P)
220-
return removeunit(codomain(P), i) domain(P)
226+
return removeunit(codomain(P), Val(i)) domain(P)
221227
else
222-
return codomain(P) removeunit(domain(P), i - numout(P))
228+
return codomain(P) removeunit(domain(P), Val(i - numout(P)))
223229
end
224230
end
225231

src/spaces/productspace.jl

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,14 @@ fuse(P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)
248248
"""
249249
insertleftunit(P::ProductSpace, i::Int=length(P) + 1; conj=false, dual=false)
250250
251-
Insert a trivial vector space, isomorphic to the underlying field, at position `i`.
251+
Insert a trivial vector space, isomorphic to the underlying field, at position `i`,
252+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
252253
More specifically, adds a left monoidal unit or its dual.
253254
254-
See also [`insertrightunit`](@ref), [`removeunit`](@ref).
255+
See also [`insertrightunit`](@ref insertrightunit(::ProductSpace, ::Val{i}) where {i}), [`removeunit`](@ref removeunit(::ProductSpace, ::Val{i}) where {i}).
255256
"""
256-
function insertleftunit(P::ProductSpace, i::Int=length(P) + 1;
257-
conj::Bool=false, dual::Bool=false)
257+
function insertleftunit(P::ProductSpace, ::Val{i}=Val(length(P) + 1);
258+
conj::Bool=false, dual::Bool=false) where {i}
258259
u = oneunit(spacetype(P))
259260
if dual
260261
u = TensorKit.dual(u)
@@ -266,15 +267,16 @@ function insertleftunit(P::ProductSpace, i::Int=length(P) + 1;
266267
end
267268

268269
"""
269-
insertrightunit(P::ProductSpace, i::Int=lenght(P); conj=false, dual=false)
270+
insertrightunit(P::ProductSpace, i=lenght(P); conj=false, dual=false)
270271
271-
Insert a trivial vector space, isomorphic to the underlying field, after position `i`.
272+
Insert a trivial vector space, isomorphic to the underlying field, after position `i`,
273+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
272274
More specifically, adds a right monoidal unit or its dual.
273275
274-
See also [`insertleftunit`](@ref), [`removeunit`](@ref).
276+
See also [`insertleftunit`](@ref insertleftunit(::ProductSpace, ::Val{i}) where {i}), [`removeunit`](@ref removeunit(::ProductSpace, ::Val{i}) where {i}).
275277
"""
276-
function insertrightunit(P::ProductSpace, i::Int=length(P);
277-
conj::Bool=false, dual::Bool=false)
278+
function insertrightunit(P::ProductSpace, ::Val{i}=Val(length(P));
279+
conj::Bool=false, dual::Bool=false) where {i}
278280
u = oneunit(spacetype(P))
279281
if dual
280282
u = TensorKit.dual(u)
@@ -288,12 +290,14 @@ end
288290
"""
289291
removeunit(P::ProductSpace, i::Int)
290292
291-
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`.
293+
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`, where `i`
294+
can be specified as an `Int` or as `Val(i)` for improved type stability.
292295
For this to work, that factor has to be isomorphic to the field of scalars.
293296
294-
This operation undoes the work of [`insertunit`](@ref).
297+
This operation undoes the work of [`insertleftunit`](@ref insertleftunit(::ProductSpace, ::Val{i}) where {i})
298+
and [`insertrightunit`](@ref insertrightunit(::ProductSpace, ::Val{i}) where {i}).
295299
"""
296-
function removeunit(P::ProductSpace, i::Int)
300+
function removeunit(P::ProductSpace, ::Val{i}) where {i}
297301
1 i length(P) || _boundserror(P, i)
298302
isisomorphic(P[i], oneunit(P[i])) || _nontrivialspaceerror(P, i)
299303
return ProductSpace{spacetype(P)}(TupleTools.deleteat(P.spaces, i))

src/spaces/vectorspaces.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ function Base.conj(V::ElementarySpace)
201201
return V
202202
end
203203

204+
# In the following, X can be a ProductSpace, a HomSpace or an AbstractTensorMap
205+
# TODO: should we deprecate those in the future?
206+
@constprop :aggressive function insertleftunit(X, i::Int; kwargs...)
207+
return insertleftunit(X, Val(i); kwargs...)
208+
end
209+
@constprop :aggressive function insertrightunit(X, i::Int; kwargs...)
210+
return insertrightunit(X, Val(i); kwargs...)
211+
end
212+
@constprop :aggressive function removeunit(X, i::Int; kwargs...)
213+
return removeunit(X, Val(i); kwargs...)
214+
end
215+
204216
# trait to describe the inner product type of vector spaces
205217
abstract type InnerProductStyle end
206218
struct NoInnerProduct <: InnerProductStyle end # no inner product

src/tensors/indexmanipulations.jl

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -292,81 +292,84 @@ See [`twist!`](@ref) for storing the result in place.
292292
"""
293293
twist(t::AbstractTensorMap, i; inv::Bool=false) = twist!(copy(t), i; inv)
294294

295+
# Methods which change the number of indices, implement using `Val(i)` for type inference
295296
"""
296-
insertleftunit(tsrc::AbstractTensorMap, i::Int=numind(t) + 1;
297+
insertleftunit(tsrc::AbstractTensorMap, i=numind(t) + 1;
297298
conj=false, dual=false, copy=false) -> tdst
298299
299-
Insert a trivial vector space, isomorphic to the underlying field, at position `i`.
300+
Insert a trivial vector space, isomorphic to the underlying field, at position `i`,
301+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
300302
More specifically, adds a left monoidal unit or its dual.
301303
302304
If `copy=false`, `tdst` might share data with `tsrc` whenever possible. Otherwise, a copy is always made.
303305
304-
See also [`insertrightunit`](@ref) and [`removeunit`](@ref).
306+
See also [`insertrightunit`](@ref insertrightunit(::AbstractTensorMap, ::Val{i}) where {i}),
307+
[`removeunit`](@ref removeunit(::AbstractTensorMap, ::Val{i}) where {i}).
305308
"""
306-
@constprop :aggressive function insertleftunit(t::AbstractTensorMap, i::Int=numind(t) + 1;
307-
copy::Bool=true, conj::Bool=false,
308-
dual::Bool=false)
309-
W = insertleftunit(space(t), i; conj, dual)
310-
tdst = similar(t, W)
311-
for (c, b) in blocks(t)
312-
copy!(block(tdst, c), b)
309+
function insertleftunit(t::AbstractTensorMap, ::Val{i}=Val(numind(t) + 1);
310+
copy::Bool=false, conj::Bool=false, dual::Bool=false) where {i}
311+
W = insertleftunit(space(t), Val(i); conj, dual)
312+
if t isa TensorMap
313+
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
314+
else
315+
tdst = similar(t, W)
316+
for (c, b) in blocks(t)
317+
copy!(block(tdst, c), b)
318+
end
319+
return tdst
313320
end
314-
return tdst
315-
end
316-
@constprop :aggressive function insertleftunit(t::TensorMap, i::Int=numind(t) + 1;
317-
copy::Bool=false, conj::Bool=false,
318-
dual::Bool=false)
319-
W = insertleftunit(space(t), i; conj, dual)
320-
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
321321
end
322322

323323
"""
324-
insertrightunit(tsrc::AbstractTensorMap, i::Int=numind(t);
324+
insertrightunit(tsrc::AbstractTensorMap, i=numind(t);
325325
conj=false, dual=false, copy=false) -> tdst
326326
327-
Insert a trivial vector space, isomorphic to the underlying field, after position `i`.
327+
Insert a trivial vector space, isomorphic to the underlying field, after position `i`,
328+
which can be specified as an `Int` or as `Val(i)` for improved type stability.
328329
More specifically, adds a right monoidal unit or its dual.
329330
330331
If `copy=false`, `tdst` might share data with `tsrc` whenever possible. Otherwise, a copy is always made.
331332
332-
See also [`insertleftunit`](@ref) and [`removeunit`](@ref).
333+
See also [`insertleftunit`](@ref insertleftunit(::AbstractTensorMap, ::Val{i}) where {i}),
334+
[`removeunit`](@ref removeunit(::AbstractTensorMap, ::Val{i}) where {i}).
333335
"""
334-
@constprop :aggressive function insertrightunit(t::AbstractTensorMap, i::Int=numind(t);
335-
copy::Bool=true, kwargs...)
336-
W = insertrightunit(space(t), i; kwargs...)
337-
tdst = similar(t, W)
338-
for (c, b) in blocks(t)
339-
copy!(block(tdst, c), b)
336+
function insertrightunit(t::AbstractTensorMap, ::Val{i}=Val(numind(t));
337+
copy::Bool=false, conj::Bool=false, dual::Bool=false) where {i}
338+
W = insertrightunit(space(t), Val(i); conj, dual)
339+
if t isa TensorMap
340+
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
341+
else
342+
tdst = similar(t, W)
343+
for (c, b) in blocks(t)
344+
copy!(block(tdst, c), b)
345+
end
346+
return tdst
340347
end
341-
return tdst
342-
end
343-
@constprop :aggressive function insertrightunit(t::TensorMap, i::Int=numind(t);
344-
copy::Bool=false, kwargs...)
345-
W = insertrightunit(space(t), i; kwargs...)
346-
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
347348
end
348349

349350
"""
350-
removeunit(tsrc::AbstractTensorMap, i::Int; copy=false) -> tdst
351+
removeunit(tsrc::AbstractTensorMap, i; copy=false) -> tdst
351352
352-
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`.
353+
This removes a trivial tensor product factor at position `1 ≤ i ≤ N`, where `i`
354+
can be specified as an `Int` or as `Val(i)` for improved type stability.
353355
For this to work, that factor has to be isomorphic to the field of scalars.
354356
355357
If `copy=false`, `tdst` might share data with `tsrc` whenever possible. Otherwise, a copy is always made.
356358
357-
This operation undoes the work of [`insertunit`](@ref).
359+
This operation undoes the work of [`insertleftunit`](@ref insertleftunit(::AbstractTensorMap, ::Val{i}) where {i})
360+
and [`insertrightunit`](@ref insertrightunit(::AbstractTensorMap, ::Val{i}) where {i}).
358361
"""
359-
@constprop :aggressive function removeunit(t::TensorMap, i::Int; copy::Bool=false)
360-
W = removeunit(space(t), i)
361-
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
362-
end
363-
@constprop :aggressive function removeunit(t::AbstractTensorMap, i::Int; copy::Bool=true)
364-
W = removeunit(space(t), i)
365-
tdst = similar(t, W)
366-
for (c, b) in blocks(t)
367-
copy!(block(tdst, c), b)
362+
function removeunit(t::AbstractTensorMap, ::Val{i}; copy::Bool=false) where {i}
363+
W = removeunit(space(t), Val(i))
364+
if t isa TensorMap
365+
return TensorMap{scalartype(t)}(copy ? Base.copy(t.data) : t.data, W)
366+
else
367+
tdst = similar(t, W)
368+
for (c, b) in blocks(t)
369+
copy!(block(tdst, c), b)
370+
end
371+
return tdst
368372
end
369-
return tdst
370373
end
371374

372375
# Fusing and splitting

src/tensors/tensor.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,14 @@ for randf in (:rand, :randn, :randexp, :randisometry)
194194
195195
Generate a tensor `t` with entries generated by `$randf`.
196196
197-
See also [`($randf)!`](@ref).
197+
See also [`Random.$(randf)!`](@ref).
198198
"""
199199
_docstr! = """
200200
$(randf)!([rng=default_rng()], t::AbstractTensorMap) -> t
201201
202202
Fill the tensor `t` with entries generated by `$(randf)!`.
203203
204-
See also [`($randf)`](@ref).
204+
See also [`Random.$(randf)`](@ref).
205205
"""
206206

207207
if randf != :randisometry
@@ -467,6 +467,8 @@ Return a view into the data slice of `t` corresponding to the splitting - fusion
467467
`(dims(codomain(t), f₁.uncoupled)..., dims(domain(t), f₂.uncoupled))` is returned which
468468
represents the slice of `block(t, c)` whose row indices correspond to `f₁.uncoupled` and
469469
column indices correspond to `f₂.uncoupled`.
470+
471+
See also [`Base.setindex!(::TensorMap{T,S,N₁,N₂}, ::Any, ::FusionTree{I,N₁}, ::FusionTree{I,N₂}) where {T,S,N₁,N₂,I<:Sector}`](@ref)
470472
"""
471473
@inline function Base.getindex(t::TensorMap{T,S,N₁,N₂},
472474
f₁::FusionTree{I,N₁},
@@ -503,7 +505,7 @@ Copies `v` into the data slice of `t` corresponding to the splitting - fusion t
503505
of size `(dims(codomain(t), f₁.uncoupled)..., dims(domain(t), f₂.uncoupled))` using
504506
`Base.copy!`.
505507
506-
See also [`Base.getindex(::TensorMap{T,S,N₁,N₂,I<:Sector}, ::FusionTree{I<:Sector,N₁}, ::FusionTree{I<:Sector,N₂})`](@ref)
508+
See also [`Base.getindex(::TensorMap{T,S,N₁,N₂}, ::FusionTree{I,N₁}, ::FusionTree{I,N₂}) where {T,S,N₁,N₂,I<:Sector}`](@ref)
507509
"""
508510
@propagate_inbounds function Base.setindex!(t::TensorMap{T,S,N₁,N₂},
509511
v,

0 commit comments

Comments
 (0)