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
8 changes: 3 additions & 5 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.14.2"
version = "0.15.0"
authors = ["ITensor developers <support@itensor.org> and contributors"]

[workspace]
Expand All @@ -18,7 +18,6 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
TensorAlgebra = "68bd88dc-f39d-4e12-b2ca-f046b68fcc6a"
TermInterface = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"
WrappedUnions = "325db55a-9c6c-5b90-b1a2-ec87e7a38c44"
Expand All @@ -45,18 +44,17 @@ Adapt = "4.1.1"
ArrayLayouts = "1.11"
Combinatorics = "1"
ConstructionBase = "1.6"
GradedArrays = "0.16.4"
GradedArrays = "0.16.5"
LinearAlgebra = "1.10"
MatrixAlgebraKit = "0.2, 0.3, 0.4, 0.5, 0.6"
Mooncake = "0.4.202, 0.5"
OMEinsumContractionOrders = "1.3"
Random = "1.10"
SimpleTraits = "0.9.4"
TensorAlgebra = "0.21"
TensorAlgebra = "0.21.1"
TensorKit = "0.17"
TensorKitSectors = "0.3.9"
TermInterface = "2"
TupleTools = "1.6"
UUIDs = "1.10"
VectorInterface = "0.6"
WrappedUnions = "0.3"
Expand Down
4 changes: 2 additions & 2 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ path = ".."

[compat]
Documenter = "1"
ITensorBase = "0.14"
ITensorBase = "0.15"
ITensorFormatter = "0.2.27"
Literate = "2"
MatrixAlgebraKit = "0.2, 0.3, 0.4, 0.5, 0.6"
TensorAlgebra = "0.21"
TensorAlgebra = "0.21.1"
Test = "1.10"
28 changes: 14 additions & 14 deletions docs/src/dev_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ stable user-facing API. For the stable user-facing API, see the [User Interface]

A concrete tensor type subtypes [`AbstractNamedTensor`](@ref). [`NamedTensor`](@ref)
is the built-in implementation, and [`ITensor`](@ref) is the `NamedTensor` with dimension
names that are [`IndexName`](@ref)s. Its `NamedTensor(array, dimnames)` constructor pairs an array of
any kind with its dimension names directly. User code usually builds one by calling an array constructor on indices or by
names that are [`IndexName`](@ref)s. Its `NamedTensor(array, names)` constructor pairs an array of
any kind with its dimension names directly, and a name given as an index also asserts that
dimension's space. A second form, `NamedTensor(array, codomain_inds, domain_inds)`, splits the
dimensions into a codomain and a domain group, as a map from the domain to the codomain.
User code usually builds one by calling an array constructor on indices or by
indexing an array (see [Constructors](@ref)) rather than calling it. The underlying
named-range model has [`NamedUnitRange`](@ref) as the named-range type that a tensor's
dimensions are ([`Index`](@ref) is the flavor keyed by an index name).
Expand All @@ -26,25 +29,22 @@ NamedUnitRange

## Named array operations

Construct named objects with [`named`](@ref) and [`nameddims`](@ref), recover their parts
with [`name`](@ref), [`unnamed`](@ref), and [`dimnames`](@ref), and query their types with
[`dimnametype`](@ref), [`nametype`](@ref), and [`unnamedtype`](@ref). [`setname`](@ref) and
[`replacedimnames`](@ref) rename, and [`aligndims`](@ref) and [`aligneddims`](@ref) reorder a
tensor's dimensions by name (a copy and a view, respectively).
Construct named objects with the [`NamedTensor`](@ref) and [`NamedUnitRange`](@ref)
constructors, recover their parts with [`name`](@ref), [`unnamed`](@ref), and
[`names`](@ref), and query their types with [`nametype`](@ref) and
[`unnamedtype`](@ref). [`setname`](@ref) changes a single object's name (the whole-tensor
form is [`rename`](@ref), on the [User Interface](@ref) page), and [`align`](@ref) and
[`aligned`](@ref) reorder a tensor's dimensions by name (a copy and a view, respectively).

```@docs; canonical=false
named
nameddims
name
unnamed
dimnames
dimnametype
names
nametype
unnamedtype
setname
replacedimnames
aligndims
aligneddims
align
aligned
```

## Experimental
Expand Down
9 changes: 7 additions & 2 deletions docs/src/user_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ see the [Reference](@ref).
An [`ITensor`](@ref) labels its dimensions by name, and an [`Index`](@ref) is a named
dimension. Get a tensor's indices with [`inds`](@ref), make distinct copies of an index with
[`prime`](@ref) and [`noprime`](@ref), and mint a fresh unique name with [`uniquename`](@ref).
Relabel a tensor's indices with [`rename`](@ref), which takes either a set of replacements or a
function to apply to every name, and leaves the data and the spaces untouched.

```@docs; canonical=false
Index
inds
prime
noprime
rename
uniquename
```

Expand Down Expand Up @@ -93,8 +96,10 @@ intermediates:
2 .* a .+ 3 .* c
```

Non-linear broadcasting (functions of one or more tensors, such as `sin.(a)` or `a .^ 2`) is
experimental and incompletely supported, and is subject to change.
Broadcasting is linear-only. A sum of tensors, a scalar multiple and `conj` are supported,
and anything else throws, including `sin.(a)`, `a .^ 2`, `a .* b` and the scalar shift `a .+ 1`.
The same applies to `map`, which broadcasts. To apply a general function, unname the tensor,
broadcast over the array, and name the result.

## Factorizations

Expand Down
2 changes: 1 addition & 1 deletion examples/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ MatrixAlgebraKit = "6c742aac-3347-4629-af66-fc926824e5e4"
path = ".."

[compat]
ITensorBase = "0.14"
ITensorBase = "0.15"
MatrixAlgebraKit = "0.2, 0.3, 0.4, 0.5, 0.6"
4 changes: 2 additions & 2 deletions ext/ITensorBaseAdaptExt/ITensorBaseAdaptExt.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module ITensorBaseAdaptExt

using Adapt: Adapt, adapt
using ITensorBase: AbstractNamedTensor, dimnames, nameddims, unnamed
using ITensorBase: AbstractNamedTensor, NamedTensor, names, unnamed

function Adapt.adapt_structure(to, a::AbstractNamedTensor)
return nameddims(adapt(to, unnamed(a)), dimnames(a))
return NamedTensor(adapt(to, unnamed(a)), names(a))
end

end
22 changes: 11 additions & 11 deletions ext/ITensorBaseGradedArraysExt.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module ITensorBaseGradedArraysExt

using GradedArrays: SectorRange
using ITensorBase: ITensorBase, name, nameddims, uniquename, unnamed
using ITensorBase: ITensorBase, NamedTensor, name, uniquename, unnamed
using Random: AbstractRNG, default_rng
using TensorKitSectors: Sector

Expand All @@ -14,10 +14,10 @@ const NamedUnitRange = ITensorBase.NamedUnitRange

# Name the delegated result: the physical-leg names followed by a fresh name for the dangling aux
# leg, minted of the legs' name type (not hardcoded to `IndexName`).
function nameddims_aux(a, codomain, domain)
dimnames = name.((codomain..., domain...))
aux_name = uniquename(eltype(dimnames))
return nameddims(a, (dimnames..., aux_name))
function namedtensor_aux(a, codomain, domain)
names = name.((codomain..., domain...))
aux_name = uniquename(eltype(names))
return NamedTensor(a, (names..., aux_name))
end

# Three signature groups, each carrying a named physical axis so overloading `Base` is not piracy:
Expand All @@ -33,7 +33,7 @@ for S in (Sector, SectorRange)
domain::Tuple{Vararg{NamedUnitRange}}
)
a = Base.$f(rng, elt, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
function Base.$f(
rng::AbstractRNG, c::$S,
Expand Down Expand Up @@ -71,7 +71,7 @@ for S in (Sector, SectorRange)
domain::Tuple{Vararg{NamedUnitRange}}
)
a = Base.$f(elt, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
function Base.$f(
c::$S, codomain::Tuple{NamedUnitRange, Vararg{NamedUnitRange}},
Expand All @@ -86,7 +86,7 @@ for S in (Sector, SectorRange)
domain::Tuple{Vararg{NamedUnitRange}}
)
a = Base.fill(value, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
# Codomain-only: the domain-omitted form, equivalent to an empty domain.
for f in (:rand, :randn)
Expand Down Expand Up @@ -140,7 +140,7 @@ for S in (Sector, SectorRange)
codomain::Tuple{}, domain::Tuple{NamedUnitRange, Vararg{NamedUnitRange}}
)
a = Base.$f(rng, elt, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
function Base.$f(
rng::AbstractRNG, c::$S,
Expand Down Expand Up @@ -175,7 +175,7 @@ for S in (Sector, SectorRange)
codomain::Tuple{}, domain::Tuple{NamedUnitRange, Vararg{NamedUnitRange}}
)
a = Base.$f(elt, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
function Base.$f(
c::$S, codomain::Tuple{},
Expand All @@ -190,7 +190,7 @@ for S in (Sector, SectorRange)
domain::Tuple{NamedUnitRange, Vararg{NamedUnitRange}}
)
a = Base.fill(value, c, unnamed.(codomain), unnamed.(domain))
return nameddims_aux(a, codomain, domain)
return namedtensor_aux(a, codomain, domain)
end
end

Expand Down
10 changes: 5 additions & 5 deletions ext/ITensorBaseMooncakeExt/ITensorBaseMooncakeExt.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
module ITensorBaseMooncakeExt

using ITensorBase: AbstractNamedTensor, NamedUnitRange, dimnames, dimnames_setdiff, inds,
name, nameperm, to_inds, uniquename
using ITensorBase: AbstractNamedTensor, NamedUnitRange, inds, name, nameperm, names,
names_setdiff, to_inds, uniquename
using Mooncake: Mooncake, @zero_derivative, DefaultCtx

Mooncake.tangent_type(::Type{<:NamedUnitRange}) = Mooncake.NoTangent

@zero_derivative DefaultCtx Tuple{typeof(nameperm), Any, Any, Any}
# `dimnames(::NamedTensor)` returns the stored names `Vector` directly, so its output
# `names(::NamedTensor)` returns the stored names `Vector` directly, so its output
# aliases a field, where `@zero_derivative` is documented to be incorrect. Let
# Mooncake differentiate it through the underlying `getfield`, whose built-in rule
# preserves the aliasing (the names are non-differentiable, so the result is zero).
@zero_derivative DefaultCtx Tuple{typeof(dimnames), Any, Any}
@zero_derivative DefaultCtx Tuple{typeof(dimnames_setdiff), Any, Any}
@zero_derivative DefaultCtx Tuple{typeof(names), Any, Any}
@zero_derivative DefaultCtx Tuple{typeof(names_setdiff), Any, Any}
@zero_derivative DefaultCtx Tuple{typeof(inds), Any}
@zero_derivative DefaultCtx Tuple{typeof(inds), Any, Any}
@zero_derivative DefaultCtx Tuple{typeof(name), Any}
Expand Down
7 changes: 0 additions & 7 deletions ext/ITensorBaseTensorKitExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ function ITensorBase.NamedUnitRange(unnamed::ElementarySpace, name)
return ITensorBase.NamedUnitRange{typeof(name), Int, typeof(unnamed)}(unnamed, name)
end

# `conj(index)` lowers to `named(conj(space), name)`, and `trivialrange` mints a fresh axis via
# `namedunitrange(space, name)`, so both must rebuild a `NamedUnitRange` over the space rather than
# fall through to the generic (array-shaped) `Named`. `named` delegates to `namedunitrange`, as the
# core `AbstractUnitRange` path does.
ITensorBase.namedunitrange(r::ElementarySpace, name) = ITensorBase.NamedUnitRange(r, name)
ITensorBase.named(r::ElementarySpace, name) = ITensorBase.namedunitrange(r, name)

# The flat length of a space-backed axis is its total (dense) dimension, so `size`/`length`
# of a `TensorMap`-backed ITensor report dense dimensions.
function Base.length(r::NamedUnitRange{<:Any, <:Any, <:ElementarySpace})
Expand Down
12 changes: 5 additions & 7 deletions src/ITensorBase.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
module ITensorBase

export AbstractNamedTensor, NamedTensor, AbstractITensor, ITensor, Index,
NamedUnitRange, aligndims, aligneddims, apply, commonind, commoninds,
dimnames, dimnametype, hascommoninds, id, inds, inputaxes, inputinds, inputnames,
mapinds,
named, nameddims, noncommonind, noncommoninds, noprime, operator, outputaxes,
outputinds,
outputnames, prime, replaceinds, sim,
NamedUnitRange, align, aligned, apply, commonind, commoninds,
hascommoninds, id, inds, inputaxes, inputinds, inputnames,
nametype, noncommonind, noncommoninds, noprime, operator,
outputaxes, outputinds, outputnames, prime, rename, sim,
similar_operator, state,
trycommonind, trynoncommonind, tryuniqueind, uniqueind, uniqueinds, unioninds,
uniquename
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"
"public @names, IndexName, name, names, setname, space, unnamed, unnamedtype, decoration, emptytags, gettag, gettags, hastag, plev, settags, tags, unsettags"
)
)
end
Expand Down
32 changes: 20 additions & 12 deletions src/abstractnamedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,11 @@ const AbstractNamedMatrix{Name, UnnamedT} = AbstractNamedArray{Name, UnnamedT, 2
unnamed(a::AbstractNamedArray) = throw(MethodError(unnamed, Tuple{typeof(a)}))
name(a::AbstractNamedArray) = throw(MethodError(name, Tuple{typeof(a)}))

# This can be customized to output different named array types,
# such as `namedarray(a::AbstractArray, name::IndexName) = Index(a, name)`.
namedarray(a::AbstractArray, name) = NamedArray(a, name)

# Shorthand.
named(a::AbstractArray, name) = namedarray(a, name)
to_named(a::AbstractArray, name) = NamedArray(a, name)

# Derived interface.
# TODO: Use `Accessors.@set`?
setname(a::AbstractNamedArray, name) = namedarray(unnamed(a), name)
setname(a::AbstractNamedArray, name) = NamedArray(unnamed(a), name)

# `Name` leads, so `nametype` reads it from the abstract type. The wrapped
# container type lives only on the concrete subtypes, so `unnamedtype` is defined
Expand All @@ -42,7 +37,9 @@ function Base.:(==)(a1::AbstractNamedArray, a2::AbstractNamedArray)
end
Base.hash(a::AbstractNamedArray, h::UInt) = hash_named(:NamedArray, a, h)

getindex_named(a::AbstractArray, I...) = named(getindex(unnamed(a), I...), name(a))
# The slice can be an element, a range, or a general array depending on `I` and on what
# the parent is, so the named type it takes is only known at runtime.
getindex_named(a::AbstractArray, I...) = to_named(getindex(unnamed(a), I...), name(a))

# Array funcionality.
Base.size(a::AbstractNamedArray) = size(unnamed(a))
Expand All @@ -69,20 +66,31 @@ Base.isempty(a::AbstractNamedArray) = isempty(unnamed(a))
## Base.iterate(a::AbstractNamedArray) = isempty(a) ? nothing : (first(a), first(a))
## function Base.iterate(a::AbstractNamedArray, i)
## i == last(a) && return nothing
## next = named(unnamed(i) + unnamed(step(a)), name(a))
## next = Named(unnamed(i) + unnamed(step(a)), name(a))
## return (next, next)
## end

function uniquename(rng::AbstractRNG, a::AbstractNamedArray)
return named(unnamed(a), uniquename(rng, name(a)))
return setname(a, uniquename(rng, name(a)))
end

# Show as the constructor call that rebuilds the value, so the output round-trips. A
# `NamedOneTo` (the common case, since it is what a tensor dimension of a plain array is)
# prints through `NamedOneTo`, the spelling that builds one from a length.
function Base.show(io::IO, a::AbstractNamedArray)
print(io, "named(", unnamed(a), ", ", repr(name(a)), ")")
if a isa NamedOneTo
print(io, "NamedOneTo(", length(unnamed(a)), ", ", repr(name(a)), ")")
else
print(io, nameof(typeof(a)), "(", unnamed(a), ", ", repr(name(a)), ")")
end
return nothing
end
function Base.show(io::IO, mime::MIME"text/plain", a::AbstractNamedArray)
print(io, "named(\n")
if a isa NamedOneTo
show(io, a)
return nothing
end
print(io, nameof(typeof(a)), "(\n")
show(io, mime, unnamed(a))
print(io, ",\n ", repr(name(a)), ")")
return nothing
Expand Down
Loading
Loading