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
4 changes: 1 addition & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "ITensorBase"
uuid = "4795dd04-0d67-49bb-8f44-b89c448a1dc7"
version = "0.11.4"
version = "0.11.5"
authors = ["ITensor developers <support@itensor.org> and contributors"]

[workspace]
Expand All @@ -11,7 +11,6 @@ AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MatrixAlgebraKit = "6c742aac-3347-4629-af66-fc926824e5e4"
Expand Down Expand Up @@ -45,7 +44,6 @@ Accessors = "0.1.39"
Adapt = "4.1.1"
ArrayLayouts = "1.11"
Combinatorics = "1"
Compat = "4.16"
ConstructionBase = "1.6"
LinearAlgebra = "1.10"
MatrixAlgebraKit = "0.2, 0.3, 0.4, 0.5, 0.6"
Expand Down
19 changes: 7 additions & 12 deletions src/ITensorBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@ export AbstractNamedTensor, NamedTensor, AbstractITensor, ITensor, Index,
dimnames, dimnametype, domainnames, hascommoninds, id, inds, mapinds, named, nameddims,
noncommoninds, noprime, operator, prime, replaceinds, sim, similar_operator, state,
trycommonind, trynoncommonind, uniqueind, uniqueinds, unioninds, uniquename
using Compat: @compat
@compat public @names
@compat public IndexName, name, nametype, replacedimnames, setname, unnamed, unnamedtype
@compat public decoration,
emptytags,
gettag,
gettags,
hastag,
plev,
settags,
tags,
unsettags
if VERSION >= v"1.11.0-DEV.469"
eval(
Meta.parse(
"public @names, IndexName, name, nametype, replacedimnames, setname, space, unnamed, unnamedtype, decoration, emptytags, gettag, gettags, hastag, plev, settags, tags, unsettags"
)
)
end

# Named-array machinery (relocated from NamedDimsArrays.jl).
include("isnamed.jl")
Expand Down
47 changes: 28 additions & 19 deletions src/namedtensor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,10 @@ struct NamedTensor{DimName} <: AbstractNamedTensor{DimName}
# `axes`/algebra interface) can be the parent directly. See the TensorKit extension.
unnamed::Any
dimnames::Vector{DimName}
function NamedTensor{DimName}(unnamed, dimnames) where {DimName}
# Catch the common ITensors.jl-style mistake of passing indices (`NamedUnitRange`s
# such as `Index`) as the names. Checked before `collect(DimName, ...)`, which would
# otherwise fail with an opaque `convert` error when `DimName` is the dimension-name
# type (e.g. `ITensor`'s `IndexName`).
(
dimnames isa NamedUnitRange ||
any(dimname -> dimname isa NamedUnitRange, dimnames)
) && throw(
ArgumentError(
"The `NamedTensor`/`ITensor` constructor takes dimension names, not indices \
(`NamedUnitRange`s such as `Index`), got $(dimnames). To build a tensor from \
an array and indices, either index the array to inherit the space from the \
indices, as in `array[i, j]`, or attach only the names and take the space \
from the array, as in `ITensor(array, name.((i, j)))`."
)
)
dimnames = collect(DimName, dimnames)
# The sole inner constructor: enforces the representation invariants (one name per dimension,
# names distinct) on already-collected names. The outer constructors below normalize the
# inputs (strip index names, fix the eltype) and funnel through here.
global function _NamedTensor(unnamed, dimnames::Vector{DimName}) where {DimName}
TensorAlgebra.ndims(unnamed) == length(dimnames) ||
throw(ArgumentError("Number of named dims must match ndims."))
allunique(dimnames) ||
Expand All @@ -51,7 +37,30 @@ struct NamedTensor{DimName} <: AbstractNamedTensor{DimName}
end
end

NamedTensor(unnamed, dims) = NamedTensor{eltype(dims)}(unnamed, dims)
# `dimnames` can hold plain names or indices (`NamedUnitRange`s such as `Index`): `name` maps an
# index to its name and is the identity on a plain name, so an index's space is ignored (the array
# carries the axes). A single bare index is rejected, since it is ambiguous as `dimnames` (a
# `NamedUnitRange` is itself an iterable of its range values). The two methods repeat this
# normalization rather than one delegating to the other, so each strips names exactly once.
function NamedTensor{DimName}(unnamed, dimnames) where {DimName}
dimnames isa NamedUnitRange && throw(
ArgumentError(
"Got a single index (`NamedUnitRange` such as `Index`) as the dimension names. \
Pass a tuple or vector, e.g. `ITensor(array, (i, j))`."
)
)
return _NamedTensor(unnamed, collect(DimName, name.(dimnames)))
end
# The dimension-name type is inferred from the names, so indices infer `IndexName`, not their type.
function NamedTensor(unnamed, dimnames)
dimnames isa NamedUnitRange && throw(
ArgumentError(
"Got a single index (`NamedUnitRange` such as `Index`) as the dimension names. \
Pass a tuple or vector, e.g. `ITensor(array, (i, j))`."
)
)
return _NamedTensor(unnamed, collect(name.(dimnames)))
end
NamedTensor(a::AbstractNamedTensor, inds) = throw(ArgumentError("Already named."))
NamedTensor(a::AbstractNamedTensor) = NamedTensor(unnamed(a), dimnames(a))

Expand Down
8 changes: 8 additions & 0 deletions src/namedunitrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ unnamed(i::NamedUnitRange) = i.value
name(i::NamedUnitRange) = i.name
unnamedtype(::Type{<:NamedUnitRange{<:Any, <:Any, Unnamed}}) where {Unnamed} = Unnamed

"""
space(i::NamedUnitRange)

The space of a named range `i`: its underlying (unnamed) range or axis object, with the name
dropped. Equal to [`unnamed`](@ref) for a `NamedUnitRange`.
"""
space(i::NamedUnitRange) = unnamed(i)

# Construct from a space, minting a fresh name of the requested flavor. The space is
# anything `to_range` accepts (an `Integer`, an existing range, or a sector-pair vector
# when GradedArrays is loaded), so `Index(2)`, `Index(1:3)`, and
Expand Down
16 changes: 10 additions & 6 deletions test/test_basics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,18 @@ using UUIDs: UUID
@test_throws ArgumentError NamedTensor(randn(elt, 4), (:i, :j))
@test_throws MethodError NamedTensor(randn(elt, 2, 2), :i, :j)

# The constructor takes names only, not indices, so passing indices (the
# ITensors.jl idiom) errors, whether as a tuple, a vector, or a single index.
# Passing indices as a tuple or vector builds the tensor, using only their names and
# taking the space from the array. A single bare index still errors (it is ambiguous).
i, j = Index.((2, 3))
@test_throws ArgumentError NamedTensor(randn(elt, 2, 2), Index.((2, 2)))
@test_throws ArgumentError ITensor(randn(elt, 2, 3), (i, j))
@test_throws ArgumentError ITensor(randn(elt, 2, 3), [i, j])
@test NamedTensor(randn(elt, 2, 3), (i, j)) isa ITensor
@test ITensor(randn(elt, 2, 3), (i, j)) isa ITensor
@test ITensor(randn(elt, 2, 3), [i, j]) isa ITensor
t = ITensor(randn(elt, 2, 3), (i, j))
@test issetequal(name.(inds(t)), name.((i, j)))
@test_throws ArgumentError ITensor(randn(elt, 2), i)
# The two supported constructions: index the array (inherit the space from the
# The space is taken from the array, not from the index (a mismatched index dim is ignored).
@test size(unnamed(ITensor(randn(elt, 2, 3), (i, Index(9))))) == (2, 3)
# The other supported constructions: index the array (inherit the space from the
# indices), or attach only the names (take the space from the array).
@test randn(elt, 2, 3)[i, j] isa ITensor
@test ITensor(randn(elt, 2, 3), name.((i, j))) isa ITensor
Expand Down
2 changes: 1 addition & 1 deletion test/test_exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ using Test: @test, @testset
:uniqueind, :uniqueinds, :unioninds, :uniquename,
]
publics = [
:IndexName, :name, :nametype, :replacedimnames, :setname, :unnamed,
:IndexName, :name, :nametype, :replacedimnames, :setname, :space, :unnamed,
:unnamedtype,
:decoration, :emptytags, :gettag, :gettags, :hastag, :plev, :settags, :tags,
:unsettags,
Expand Down
Loading