diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml deleted file mode 100644 index 4c49a86..0000000 --- a/.JuliaFormatter.toml +++ /dev/null @@ -1,3 +0,0 @@ -# See https://domluna.github.io/JuliaFormatter.jl/stable/ for a list of options -style = "blue" -indent = 2 diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index 456fa05..0614de9 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -2,7 +2,7 @@ name: "CompatHelper" on: schedule: - - cron: 0 0 * * * + - cron: '0 0 * * *' workflow_dispatch: permissions: contents: write diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 3f78afc..1525861 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -1,11 +1,14 @@ name: "Format Check" on: - push: - branches: - - 'main' - tags: '*' - pull_request: + pull_request_target: + paths: ['**/*.jl'] + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + contents: read + actions: write + pull-requests: write jobs: format-check: diff --git a/.gitignore b/.gitignore index 10593a9..7085ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,10 @@ .vscode/ Manifest.toml benchmark/*.json +dev/ +docs/LocalPreferences.toml docs/Manifest.toml docs/build/ docs/src/index.md +examples/LocalPreferences.toml +test/LocalPreferences.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 88bc8b4..3fc4743 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ ci: - skip: [julia-formatter] + skip: [runic] repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -11,7 +11,7 @@ repos: - id: end-of-file-fixer exclude_types: [markdown] # incompatible with Literate.jl -- repo: "https://github.com/domluna/JuliaFormatter.jl" - rev: v2.1.6 +- repo: https://github.com/fredrikekre/runic-pre-commit + rev: v2.0.1 hooks: - - id: "julia-formatter" + - id: runic diff --git a/Project.toml b/Project.toml index 330d311..bf82db8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ITensorBase" uuid = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" authors = ["ITensor developers and contributors"] -version = "0.2.13" +version = "0.2.14" [deps] Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" diff --git a/docs/make.jl b/docs/make.jl index 7bf0ff8..1ef98f9 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,20 +1,20 @@ using ITensorBase: ITensorBase using Documenter: Documenter, DocMeta, deploydocs, makedocs -DocMeta.setdocmeta!(ITensorBase, :DocTestSetup, :(using ITensorBase); recursive=true) +DocMeta.setdocmeta!(ITensorBase, :DocTestSetup, :(using ITensorBase); recursive = true) include("make_index.jl") makedocs(; - modules=[ITensorBase], - authors="ITensor developers and contributors", - sitename="ITensorBase.jl", - format=Documenter.HTML(; - canonical="https://itensor.github.io/ITensorBase.jl", - edit_link="main", - assets=["assets/favicon.ico", "assets/extras.css"], - ), - pages=["Home" => "index.md", "Reference" => "reference.md"], + modules = [ITensorBase], + authors = "ITensor developers and contributors", + sitename = "ITensorBase.jl", + format = Documenter.HTML(; + canonical = "https://itensor.github.io/ITensorBase.jl", + edit_link = "main", + assets = ["assets/favicon.ico", "assets/extras.css"], + ), + pages = ["Home" => "index.md", "Reference" => "reference.md"], ) -deploydocs(; repo="github.com/ITensor/ITensorBase.jl", devbranch="main", push_preview=true) +deploydocs(; repo = "github.com/ITensor/ITensorBase.jl", devbranch = "main", push_preview = true) diff --git a/docs/make_index.jl b/docs/make_index.jl index 825edf5..bfbedf8 100644 --- a/docs/make_index.jl +++ b/docs/make_index.jl @@ -2,20 +2,20 @@ using Literate: Literate using ITensorBase: ITensorBase function ccq_logo(content) - include_ccq_logo = """ + include_ccq_logo = """ ```@raw html Flatiron Center for Computational Quantum Physics logo. Flatiron Center for Computational Quantum Physics logo. ``` """ - content = replace(content, "{CCQ_LOGO}" => include_ccq_logo) - return content + content = replace(content, "{CCQ_LOGO}" => include_ccq_logo) + return content end Literate.markdown( - joinpath(pkgdir(ITensorBase), "examples", "README.jl"), - joinpath(pkgdir(ITensorBase), "docs", "src"); - flavor=Literate.DocumenterFlavor(), - name="index", - postprocess=ccq_logo, + joinpath(pkgdir(ITensorBase), "examples", "README.jl"), + joinpath(pkgdir(ITensorBase), "docs", "src"); + flavor = Literate.DocumenterFlavor(), + name = "index", + postprocess = ccq_logo, ) diff --git a/docs/make_readme.jl b/docs/make_readme.jl index cd34fb2..3ada68b 100644 --- a/docs/make_readme.jl +++ b/docs/make_readme.jl @@ -2,20 +2,20 @@ using Literate: Literate using ITensorBase: ITensorBase function ccq_logo(content) - include_ccq_logo = """ + include_ccq_logo = """ Flatiron Center for Computational Quantum Physics logo. """ - content = replace(content, "{CCQ_LOGO}" => include_ccq_logo) - return content + content = replace(content, "{CCQ_LOGO}" => include_ccq_logo) + return content end Literate.markdown( - joinpath(pkgdir(ITensorBase), "examples", "README.jl"), - joinpath(pkgdir(ITensorBase)); - flavor=Literate.CommonMarkFlavor(), - name="README", - postprocess=ccq_logo, + joinpath(pkgdir(ITensorBase), "examples", "README.jl"), + joinpath(pkgdir(ITensorBase)); + flavor = Literate.CommonMarkFlavor(), + name = "README", + postprocess = ccq_logo, ) diff --git a/examples/README.jl b/examples/README.jl index 75996a4..a965586 100644 --- a/examples/README.jl +++ b/examples/README.jl @@ -1,5 +1,5 @@ # # ITensorBase.jl -# +# # [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://itensor.github.io/ITensorBase.jl/stable/) # [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://itensor.github.io/ITensorBase.jl/dev/) # [![Build Status](https://github.com/ITensor/ITensorBase.jl/actions/workflows/Tests.yml/badge.svg?branch=main)](https://github.com/ITensor/ITensorBase.jl/actions/workflows/Tests.yml?query=branch%3Amain) diff --git a/ext/ITensorBaseDiagonalArraysExt/ITensorBaseDiagonalArraysExt.jl b/ext/ITensorBaseDiagonalArraysExt/ITensorBaseDiagonalArraysExt.jl index 0550c27..59cd9cf 100644 --- a/ext/ITensorBaseDiagonalArraysExt/ITensorBaseDiagonalArraysExt.jl +++ b/ext/ITensorBaseDiagonalArraysExt/ITensorBaseDiagonalArraysExt.jl @@ -4,25 +4,25 @@ using DiagonalArrays: DiagonalArrays, δ, delta using ITensorBase: ITensor, Index # TODO: Define more generic definitions in `NamedDimsArraysDiagonalArraysExt`. -function DiagonalArrays.delta(elt::Type{<:Number}, is::Tuple{Index,Vararg{Index}}) - return ITensor(delta(elt, Int.(length.(is))), is) +function DiagonalArrays.delta(elt::Type{<:Number}, is::Tuple{Index, Vararg{Index}}) + return ITensor(delta(elt, Int.(length.(is))), is) end -function DiagonalArrays.δ(elt::Type{<:Number}, is::Tuple{Index,Vararg{Index}}) - return delta(elt, is) +function DiagonalArrays.δ(elt::Type{<:Number}, is::Tuple{Index, Vararg{Index}}) + return delta(elt, is) end -DiagonalArrays.delta(is::Tuple{Index,Vararg{Index}}) = delta(Bool, is) -DiagonalArrays.δ(is::Tuple{Index,Vararg{Index}}) = delta(is) +DiagonalArrays.delta(is::Tuple{Index, Vararg{Index}}) = delta(Bool, is) +DiagonalArrays.δ(is::Tuple{Index, Vararg{Index}}) = delta(is) function DiagonalArrays.delta(elt::Type{<:Number}, i1::Index, i_rest::Index...) - return delta(elt, (i1, i_rest...)) + return delta(elt, (i1, i_rest...)) end function DiagonalArrays.δ(elt::Type{<:Number}, i1::Index, i_rest::Index...) - return delta(elt, i1, i_rest...) + return delta(elt, i1, i_rest...) end function DiagonalArrays.delta(i1::Index, i_rest::Index...) - return delta((i1, i_rest...)) + return delta((i1, i_rest...)) end function DiagonalArrays.δ(i1::Index, i_rest::Index...) - return delta(i1, i_rest...) + return delta(i1, i_rest...) end end diff --git a/ext/ITensorBaseSparseArraysBaseExt/ITensorBaseSparseArraysBaseExt.jl b/ext/ITensorBaseSparseArraysBaseExt/ITensorBaseSparseArraysBaseExt.jl index e8eb709..dc2ff22 100644 --- a/ext/ITensorBaseSparseArraysBaseExt/ITensorBaseSparseArraysBaseExt.jl +++ b/ext/ITensorBaseSparseArraysBaseExt/ITensorBaseSparseArraysBaseExt.jl @@ -5,9 +5,9 @@ using NamedDimsArrays: dename using SparseArraysBase: SparseArraysBase, oneelement function SparseArraysBase.oneelement( - value, index::NTuple{N,Int}, ax::NTuple{N,Index} -) where {N} - return ITensor(oneelement(value, index, only.(axes.(dename.(ax)))), ax) + value, index::NTuple{N, Int}, ax::NTuple{N, Index} + ) where {N} + return ITensor(oneelement(value, index, only.(axes.(dename.(ax)))), ax) end end diff --git a/src/abstractitensor.jl b/src/abstractitensor.jl index ccc4d70..825cfe6 100644 --- a/src/abstractitensor.jl +++ b/src/abstractitensor.jl @@ -1,16 +1,16 @@ using MapBroadcast: Mapped using NamedDimsArrays: - NamedDimsArrays, - AbstractNamedDimsArray, - NamedDimsArray, - dename, - dimnames, - mapnameddimsindices, - nameddimsindices, - replacenameddimsindices, - setnameddimsindices - -abstract type AbstractITensor <: AbstractNamedDimsArray{Any,Any} end + NamedDimsArrays, + AbstractNamedDimsArray, + NamedDimsArray, + dename, + dimnames, + mapnameddimsindices, + nameddimsindices, + replacenameddimsindices, + setnameddimsindices + +abstract type AbstractITensor <: AbstractNamedDimsArray{Any, Any} end NamedDimsArrays.nameddimsarraytype(::Type{<:IndexName}) = ITensor @@ -23,16 +23,16 @@ using UnspecifiedTypes: UnspecifiedZero # TODO: Make this more general, maybe with traits `is_unallocated` # and `is_eltype_unspecified`. function specify_eltype(a::Zeros{UnspecifiedZero}, elt::Type) - return Zeros{elt}(axes(a)) + return Zeros{elt}(axes(a)) end function specify_eltype(a::AbstractArray, elt::Type) - return a + return a end # TODO: Use `adapt` to reach down into the storage. function specify_eltype!(a::AbstractITensor, elt::Type) - setdenamed!(a, specify_eltype(dename(a), elt)) - return a + setdenamed!(a, specify_eltype(dename(a), elt)) + return a end # Assume it is allocated. @@ -40,64 +40,64 @@ allocate!(a::AbstractArray) = a # TODO: Use `adapt` to reach down into the storage. function allocate!(a::AbstractITensor) - setdenamed!(a, allocate(dename(a))) - return a + setdenamed!(a, allocate(dename(a))) + return a end using DerivableInterfaces: @derive, @interface, AbstractArrayInterface abstract type AbstractAllocatableArrayInterface{N} <: AbstractArrayInterface{N} end struct AllocatableArrayInterface{N} <: AbstractAllocatableArrayInterface{N} end -AllocatableArrayInterface{M}(::Val{N}) where {M,N} = AllocatableArrayInterface{N}() +AllocatableArrayInterface{M}(::Val{N}) where {M, N} = AllocatableArrayInterface{N}() AllocatableArrayInterface(::Val{N}) where {N} = AllocatableArrayInterface{N}() AllocatableArrayInterface() = AllocatableArrayInterface{Any}() unallocatable(a::AbstractITensor) = NamedDimsArray(a) function setindex_allocatable!(a::AbstractArray, value, I...) - allocate!(specify_eltype!(a, typeof(value))) - # TODO: Maybe use `@interface interface(a) a[I...] = value`? - unallocatable(a)[I...] = value - return a + allocate!(specify_eltype!(a, typeof(value))) + # TODO: Maybe use `@interface interface(a) a[I...] = value`? + unallocatable(a)[I...] = value + return a end # TODO: Combine these by using `Base.to_indices`. @interface ::AbstractAllocatableArrayInterface function Base.setindex!( - a::AbstractArray, value, I::Int... -) - setindex_allocatable!(a, value, I...) - return a + a::AbstractArray, value, I::Int... + ) + setindex_allocatable!(a, value, I...) + return a end @interface ::AbstractAllocatableArrayInterface function Base.setindex!( - a::AbstractArray, value, I::AbstractNamedInteger... -) - setindex_allocatable!(a, value, I...) - return a + a::AbstractArray, value, I::AbstractNamedInteger... + ) + setindex_allocatable!(a, value, I...) + return a end -@derive AllocatableArrayInterface() (T=AbstractITensor,) begin - Base.setindex!(::T, ::Any, ::Int...) - Base.setindex!(::T, ::Any, ::AbstractNamedInteger...) +@derive AllocatableArrayInterface() (T = AbstractITensor,) begin + Base.setindex!(::T, ::Any, ::Int...) + Base.setindex!(::T, ::Any, ::AbstractNamedInteger...) end mutable struct ITensor <: AbstractITensor - parent::AbstractArray - nameddimsindices - function ITensor(parent::AbstractArray, dims) - # This checks the shapes of the inputs. - nameddimsindices = NamedDimsArrays.to_nameddimsindices(parent, dims) - return new(parent, nameddimsindices) - end + parent::AbstractArray + nameddimsindices + function ITensor(parent::AbstractArray, dims) + # This checks the shapes of the inputs. + nameddimsindices = NamedDimsArrays.to_nameddimsindices(parent, dims) + return new(parent, nameddimsindices) + end end Base.parent(a::ITensor) = getfield(a, :parent) NamedDimsArrays.nameddimsindices(a::ITensor) = getfield(a, :nameddimsindices) NamedDimsArrays.dename(a::ITensor) = parent(a) function ITensor(parent::AbstractArray, i1::Index, i_rest::Index...) - return ITensor(parent, (i1, i_rest...)) + return ITensor(parent, (i1, i_rest...)) end function ITensor(parent::AbstractArray) - return ITensor(parent, ()) + return ITensor(parent, ()) end using Accessors: @set @@ -105,46 +105,46 @@ setdenamed(a::ITensor, denamed) = (@set a.parent = denamed) setdenamed!(a::ITensor, denamed) = (a.parent = denamed) function ITensor(elt::Type, I1::Index, I_rest::Index...) - I = (I1, I_rest...) - # TODO: Use `FillArrays.Zeros`. - return ITensor(zeros(elt, length.(dename.(I))...), I) + I = (I1, I_rest...) + # TODO: Use `FillArrays.Zeros`. + return ITensor(zeros(elt, length.(dename.(I))...), I) end function ITensor(I1::Index, I_rest::Index...) - I = (I1, I_rest...) - return ITensor(Zeros{UnspecifiedZero}(length.(dename.(I))...), I) + I = (I1, I_rest...) + return ITensor(Zeros{UnspecifiedZero}(length.(dename.(I))...), I) end function ITensor() - return ITensor(Zeros{UnspecifiedZero}(), ()) + return ITensor(Zeros{UnspecifiedZero}(), ()) end inds(a::AbstractITensor) = nameddimsindices(a) setinds(a::AbstractITensor, inds) = setnameddimsindices(a, inds) function uniqueinds(a1::AbstractITensor, a_rest::AbstractITensor...) - return setdiff(inds(a1), inds.(a_rest)...) + return setdiff(inds(a1), inds.(a_rest)...) end function uniqueind(a1::AbstractITensor, a_rest::AbstractITensor...) - return only(uniqueinds(a1, a_rest...)) + return only(uniqueinds(a1, a_rest...)) end function commoninds(a1::AbstractITensor, a_rest::AbstractITensor...) - return intersect(inds(a1), inds.(a_rest)...) + return intersect(inds(a1), inds.(a_rest)...) end function commonind(a1::AbstractITensor, a_rest::AbstractITensor...) - return only(commoninds(a1, a_rest...)) + return only(commoninds(a1, a_rest...)) end function replaceinds(a::AbstractITensor, replacements::Pair...) - return replacenameddimsindices(a, replacements...) + return replacenameddimsindices(a, replacements...) end function replaceinds(f, a::AbstractITensor) - return replacenameddimsindices(f, a) + return replacenameddimsindices(f, a) end function mapinds(f, a::AbstractITensor) - return mapnameddimsindices(f, a) + return mapnameddimsindices(f, a) end prime(a::AbstractITensor) = replaceinds(prime, a) diff --git a/src/index.jl b/src/index.jl index 52e7b56..adf2089 100644 --- a/src/index.jl +++ b/src/index.jl @@ -1,37 +1,37 @@ using Accessors: @set using NamedDimsArrays: - NamedDimsArrays, - AbstractName, - AbstractNamedInteger, - AbstractNamedUnitRange, - AbstractNamedVector, - dename, - name, - randname, - setname + NamedDimsArrays, + AbstractName, + AbstractNamedInteger, + AbstractNamedUnitRange, + AbstractNamedVector, + dename, + name, + randname, + setname using Random: Random, AbstractRNG tagpairstring(pair::Pair) = repr(first(pair)) * "=>" * repr(last(pair)) -function tagsstring(tags::Dict{String,String}) - tagpairs = sort(collect(tags); by=first) - tagpair1, tagpair_rest = Iterators.peel(tagpairs) - return mapreduce(*, tagpair_rest; init=tagpairstring(tagpair1)) do tagpair - return "," * tagpairstring(tagpair) - end +function tagsstring(tags::Dict{String, String}) + tagpairs = sort(collect(tags); by = first) + tagpair1, tagpair_rest = Iterators.peel(tagpairs) + return mapreduce(*, tagpair_rest; init = tagpairstring(tagpair1)) do tagpair + return "," * tagpairstring(tagpair) + end end struct IndexName <: AbstractName - id::UInt64 - tags::Dict{String,String} - plev::Int + id::UInt64 + tags::Dict{String, String} + plev::Int end function IndexName( - rng::AbstractRNG=Random.default_rng(); - id::UInt64=rand(rng, UInt64), - tags=Dict{String,String}(), - plev::Int=0, -) - return IndexName(id, Dict{String,String}(tags), plev) + rng::AbstractRNG = Random.default_rng(); + id::UInt64 = rand(rng, UInt64), + tags = Dict{String, String}(), + plev::Int = 0, + ) + return IndexName(id, Dict{String, String}(tags), plev) end NamedDimsArrays.randname(rng::AbstractRNG, ::Type{<:IndexName}) = IndexName(rng) @@ -46,14 +46,14 @@ hastag(n::IndexName, tagname::String) = haskey(tags(n), tagname) gettag(n::IndexName, tagname::String) = tags(n)[tagname] gettag(n::IndexName, tagname::String, default) = get(tags(n), tagname, default) function settag(n::IndexName, tagname::String, tag::String) - newtags = copy(tags(n)) - newtags[tagname] = tag - return settags(n, newtags) + newtags = copy(tags(n)) + newtags[tagname] = tag + return settags(n, newtags) end function unsettag(n::IndexName, tagname::String) - newtags = copy(tags(n)) - delete!(newtags, tagname) - return settags(n, newtags) + newtags = copy(tags(n)) + delete!(newtags, tagname) + return settags(n, newtags) end setprime(n::IndexName, plev) = @set n.plev = plev @@ -62,17 +62,17 @@ noprime(n::IndexName) = setprime(n, 0) sim(n::IndexName) = randname(n) function Base.show(io::IO, i::IndexName) - idstr = "id=$(id(i) % 1000)" - tagsstr = !isempty(tags(i)) ? "|$(tagsstring(tags(i)))" : "" - primestr = primestring(plev(i)) - str = "IndexName($(idstr)$(tagsstr))$(primestr)" - print(io, str) - return nothing + idstr = "id=$(id(i) % 1000)" + tagsstr = !isempty(tags(i)) ? "|$(tagsstring(tags(i)))" : "" + primestr = primestring(plev(i)) + str = "IndexName($(idstr)$(tagsstr))$(primestr)" + print(io, str) + return nothing end -struct IndexVal{Value<:Integer} <: AbstractNamedInteger{Value,IndexName} - value::Value - name::IndexName +struct IndexVal{Value <: Integer} <: AbstractNamedInteger{Value, IndexName} + value::Value + name::IndexName end # Interface @@ -82,25 +82,25 @@ NamedDimsArrays.name(i::IndexVal) = i.name # Constructor NamedDimsArrays.named(i::Integer, name::IndexName) = IndexVal(i, name) -struct Index{T,Value<:AbstractUnitRange{T}} <: AbstractNamedUnitRange{T,Value,IndexName} - value::Value - name::IndexName +struct Index{T, Value <: AbstractUnitRange{T}} <: AbstractNamedUnitRange{T, Value, IndexName} + value::Value + name::IndexName end -function Index{T,Value}( - r::AbstractUnitRange{T}; kwargs... -) where {T,Value<:AbstractUnitRange{T}} - return Index{T,Value}(r, IndexName(; kwargs...)) +function Index{T, Value}( + r::AbstractUnitRange{T}; kwargs... + ) where {T, Value <: AbstractUnitRange{T}} + return Index{T, Value}(r, IndexName(; kwargs...)) end function Index{T}(r::AbstractUnitRange{T}; kwargs...) where {T} - return Index{T,typeof(r)}(r; kwargs...) + return Index{T, typeof(r)}(r; kwargs...) end function Index(r::AbstractUnitRange; kwargs...) - return Index{eltype(r)}(r; kwargs...) + return Index{eltype(r)}(r; kwargs...) end function Index(length::Int; kwargs...) - return Index(Base.OneTo(length); kwargs...) + return Index(Base.OneTo(length); kwargs...) end # TODO: Define for `NamedDimsArrays.NamedViewIndex`. @@ -134,32 +134,32 @@ NamedDimsArrays.name(i::Index) = i.name NamedDimsArrays.named(i::AbstractUnitRange, name::IndexName) = Index(i, name) function primestring(plev) - if plev < 0 - return " (warning: prime level $plev is less than 0)" - end - if plev == 0 - return "" - elseif plev > 3 - return "'$plev" - else - return "'"^plev - end + if plev < 0 + return " (warning: prime level $plev is less than 0)" + end + if plev == 0 + return "" + elseif plev > 3 + return "'$plev" + else + return "'"^plev + end end function Base.show(io::IO, i::Index) - lenstr = "length=$(dename(length(i)))" - idstr = "|id=$(id(i) % 1000)" - tagsstr = !isempty(tags(i)) ? "|$(tagsstring(tags(i)))" : "" - primestr = primestring(plev(i)) - str = "Index($(lenstr)$(idstr)$(tagsstr))$(primestr)" - print(io, str) - return nothing + lenstr = "length=$(dename(length(i)))" + idstr = "|id=$(id(i) % 1000)" + tagsstr = !isempty(tags(i)) ? "|$(tagsstring(tags(i)))" : "" + primestr = primestring(plev(i)) + str = "Index($(lenstr)$(idstr)$(tagsstr))$(primestr)" + print(io, str) + return nothing end -struct NoncontiguousIndex{T,Value<:AbstractVector{T}} <: - AbstractNamedVector{T,Value,IndexName} - value::Value - name::IndexName +struct NoncontiguousIndex{T, Value <: AbstractVector{T}} <: + AbstractNamedVector{T, Value, IndexName} + value::Value + name::IndexName end # Interface diff --git a/src/quirks.jl b/src/quirks.jl index 12a4414..111ba09 100644 --- a/src/quirks.jl +++ b/src/quirks.jl @@ -26,32 +26,32 @@ Base.Broadcast.extrude(a::AbstractITensor) = a filter_namedtuple(f, xs::NamedTuple) = xs[filter(k -> f(xs[k]), keys(xs))] function translate_factorize_kwargs(; - # MatrixAlgebraKit.jl/TensorAlgebra.jl kwargs. - orth=nothing, - rtol=nothing, - maxrank=nothing, - # ITensors.jl kwargs. - ortho=nothing, - cutoff=nothing, - maxdim=nothing, - kwargs..., -) - orth = Symbol(@something orth ortho :left) - rtol = @something rtol cutoff Some(nothing) - maxrank = @something maxrank maxdim Some(nothing) - trunc = (; rtol, maxrank) - # !isnothing(maxrank) && error("`maxrank` not supported yet.") - return filter_namedtuple(!isnothing, (; orth, trunc, kwargs...)) + # MatrixAlgebraKit.jl/TensorAlgebra.jl kwargs. + orth = nothing, + rtol = nothing, + maxrank = nothing, + # ITensors.jl kwargs. + ortho = nothing, + cutoff = nothing, + maxdim = nothing, + kwargs..., + ) + orth = Symbol(@something orth ortho :left) + rtol = @something rtol cutoff Some(nothing) + maxrank = @something maxrank maxdim Some(nothing) + trunc = (; rtol, maxrank) + # !isnothing(maxrank) && error("`maxrank` not supported yet.") + return filter_namedtuple(!isnothing, (; orth, trunc, kwargs...)) end using TensorAlgebra: TensorAlgebra, factorize function TensorAlgebra.factorize(a::AbstractITensor, codomain_inds, domain_inds; kwargs...) - return invoke( - factorize, - Tuple{AbstractNamedDimsArray,Any,Any}, - a, - codomain_inds, - domain_inds; - translate_factorize_kwargs(; kwargs...)..., - ) + return invoke( + factorize, + Tuple{AbstractNamedDimsArray, Any, Any}, + a, + codomain_inds, + domain_inds; + translate_factorize_kwargs(; kwargs...)..., + ) end diff --git a/test/runtests.jl b/test/runtests.jl index e2c9599..39c332d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,58 +6,60 @@ using Suppressor: Suppressor const pat = r"(?:--group=)(\w+)" arg_id = findfirst(contains(pat), ARGS) const GROUP = uppercase( - if isnothing(arg_id) - get(ENV, "GROUP", "ALL") - else - only(match(pat, ARGS[arg_id]).captures) - end, + if isnothing(arg_id) + get(ENV, "GROUP", "ALL") + else + only(match(pat, ARGS[arg_id]).captures) + end, ) "match files of the form `test_*.jl`, but exclude `*setup*.jl`" function istestfile(fn) - return endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") + return endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") end "match files of the form `*.jl`, but exclude `*_notest.jl` and `*setup*.jl`" function isexamplefile(fn) - return endswith(fn, ".jl") && !endswith(fn, "_notest.jl") && !contains(fn, "setup") + return endswith(fn, ".jl") && !endswith(fn, "_notest.jl") && !contains(fn, "setup") end @time begin - # tests in groups based on folder structure - for testgroup in filter(isdir, readdir(@__DIR__)) - if GROUP == "ALL" || GROUP == uppercase(testgroup) - for file in filter(istestfile, readdir(joinpath(@__DIR__, testgroup); join=true)) - @eval @safetestset $file begin - include($file) + # tests in groups based on folder structure + for testgroup in filter(isdir, readdir(@__DIR__)) + if GROUP == "ALL" || GROUP == uppercase(testgroup) + for file in filter(istestfile, readdir(joinpath(@__DIR__, testgroup); join = true)) + @eval @safetestset $file begin + include($file) + end + end end - end end - end - # single files in top folder - for file in filter(istestfile, readdir(@__DIR__)) - (file == basename(@__FILE__)) && continue # exclude this file to avoid infinite recursion - @eval @safetestset $file begin - include($file) + # single files in top folder + for file in filter(istestfile, readdir(@__DIR__)) + (file == basename(@__FILE__)) && continue # exclude this file to avoid infinite recursion + @eval @safetestset $file begin + include($file) + end end - end - # test examples - examplepath = joinpath(@__DIR__, "..", "examples") - for (root, _, files) in walkdir(examplepath) - contains(chopprefix(root, @__DIR__), "setup") && continue - for file in filter(isexamplefile, files) - filename = joinpath(root, file) - @eval begin - @safetestset $file begin - $(Expr( - :macrocall, - GlobalRef(Suppressor, Symbol("@suppress")), - LineNumberNode(@__LINE__, @__FILE__), - :(include($filename)), - )) + # test examples + examplepath = joinpath(@__DIR__, "..", "examples") + for (root, _, files) in walkdir(examplepath) + contains(chopprefix(root, @__DIR__), "setup") && continue + for file in filter(isexamplefile, files) + filename = joinpath(root, file) + @eval begin + @safetestset $file begin + $( + Expr( + :macrocall, + GlobalRef(Suppressor, Symbol("@suppress")), + LineNumberNode(@__LINE__, @__FILE__), + :(include($filename)), + ) + ) + end + end end - end end - end end diff --git a/test/test_aqua.jl b/test/test_aqua.jl index 562af36..17fe588 100644 --- a/test/test_aqua.jl +++ b/test/test_aqua.jl @@ -3,5 +3,5 @@ using Aqua: Aqua using Test: @testset @testset "Code quality (Aqua.jl)" begin - Aqua.test_all(ITensorBase; ambiguities=false, persistent_tasks=false) + Aqua.test_all(ITensorBase; ambiguities = false, persistent_tasks = false) end diff --git a/test/test_basics.jl b/test/test_basics.jl index 4528571..fb458e7 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -3,19 +3,19 @@ using BlockSparseArrays: BlockSparseArray using DiagonalArrays: δ, delta, diagview using GradedArrays: U1, dual, gradedrange using ITensorBase: - ITensorBase, - ITensor, - Index, - gettag, - hastag, - hasqns, - inds, - plev, - prime, - setprime, - settag, - tags, - unsettag + ITensorBase, + ITensor, + Index, + gettag, + hastag, + hasqns, + inds, + plev, + prime, + setprime, + settag, + tags, + unsettag using NamedDimsArrays: dename, name, named using SparseArraysBase: oneelement using LinearAlgebra: factorize @@ -23,171 +23,171 @@ using Test: @test, @test_broken, @test_throws, @testset const elts = (Float32, Float64, Complex{Float32}, Complex{Float64}) @testset "ITensorBase" begin - @testset "Basics" begin - elt = Float64 - i, j = Index.((2, 2)) - x = randn(elt, 2, 2) - for a in (ITensor(x, i, j), ITensor(x, (i, j))) - @test dename(a) == x - @test plev(i) == 0 - @test plev(prime(i)) == 1 - @test length(tags(i)) == 0 - a′ = prime(a) - @test dename(a′) == x - @test issetequal(inds(a′), (prime(i), prime(j))) - end + @testset "Basics" begin + elt = Float64 + i, j = Index.((2, 2)) + x = randn(elt, 2, 2) + for a in (ITensor(x, i, j), ITensor(x, (i, j))) + @test dename(a) == x + @test plev(i) == 0 + @test plev(prime(i)) == 1 + @test length(tags(i)) == 0 + a′ = prime(a) + @test dename(a′) == x + @test issetequal(inds(a′), (prime(i), prime(j))) + end - @test_throws ErrorException ITensor(randn(elt, 2, 2), Index.((2, 3))) - @test_throws ErrorException ITensor(randn(elt, 4), Index.((2, 2))) + @test_throws ErrorException ITensor(randn(elt, 2, 2), Index.((2, 3))) + @test_throws ErrorException ITensor(randn(elt, 4), Index.((2, 2))) - i, j = Index.((3, 4)) - a = randn(elt, i, j) - a′ = Array(a) - @test eltype(a′) === elt - @test a′ isa Matrix{elt} - @test a′ == dename(a) + i, j = Index.((3, 4)) + a = randn(elt, i, j) + a′ = Array(a) + @test eltype(a′) === elt + @test a′ isa Matrix{elt} + @test a′ == dename(a) - i, j = Index.((3, 4)) - a = randn(elt, i, j) - for a′ in (Array{Float32}(a), Matrix{Float32}(a)) - @test eltype(a′) === Float32 - @test a′ isa Matrix{Float32} - @test a′ == Float32.(dename(a)) - end + i, j = Index.((3, 4)) + a = randn(elt, i, j) + for a′ in (Array{Float32}(a), Matrix{Float32}(a)) + @test eltype(a′) === Float32 + @test a′ isa Matrix{Float32} + @test a′ == Float32.(dename(a)) + end - i, j, k = Index.((2, 2, 2)) - a = randn(elt, i, j, k) - b = randn(elt, k, i, j) - copyto!(a, b) - @test a == b - @test dename(a) == dename(b, (i, j, k)) - @test dename(a) == permutedims(dename(b), (2, 3, 1)) + i, j, k = Index.((2, 2, 2)) + a = randn(elt, i, j, k) + b = randn(elt, k, i, j) + copyto!(a, b) + @test a == b + @test dename(a) == dename(b, (i, j, k)) + @test dename(a) == permutedims(dename(b), (2, 3, 1)) - i = Index(2) - @test plev(i) == 0 - i = setprime(i, 2) - @test plev(i) == 2 + i = Index(2) + @test plev(i) == 0 + i = setprime(i, 2) + @test plev(i) == 2 - i = Index(2) - i = settag(i, "X", "x") - @test hastag(i, "X") - @test !hastag(i, "Y") - @test gettag(i, "X") == "x" - i = unsettag(i, "X") - @test isnothing(gettag(i, "X", nothing)) - @test !hastag(i, "X") - @test !hastag(i, "Y") + i = Index(2) + i = settag(i, "X", "x") + @test hastag(i, "X") + @test !hastag(i, "Y") + @test gettag(i, "X") == "x" + i = unsettag(i, "X") + @test isnothing(gettag(i, "X", nothing)) + @test !hastag(i, "X") + @test !hastag(i, "Y") - i = Index(Base.OneTo(2)) - @test length(i) == named(2, name(i)) - @test dename(length(i)) == 2 - @test dename(i) == 1:2 - @test plev(i) == 0 - @test length(tags(i)) == 0 + i = Index(Base.OneTo(2)) + @test length(i) == named(2, name(i)) + @test dename(length(i)) == 2 + @test dename(i) == 1:2 + @test plev(i) == 0 + @test length(tags(i)) == 0 - for i in ( - Index(2; tags=Dict(["X" => "Y"])), - Index(2; tags=["X" => "Y"]), - Index(2; tags=("X" => "Y",)), - Index(2; tags="X" => "Y"), - ) - @test Int(length(i)) == 2 - @test hastag(i, "X") - @test gettag(i, "X") == "Y" - @test plev(i) == 0 - @test length(tags(i)) == 1 + for i in ( + Index(2; tags = Dict(["X" => "Y"])), + Index(2; tags = ["X" => "Y"]), + Index(2; tags = ("X" => "Y",)), + Index(2; tags = "X" => "Y"), + ) + @test Int(length(i)) == 2 + @test hastag(i, "X") + @test gettag(i, "X") == "Y" + @test plev(i) == 0 + @test length(tags(i)) == 1 + end end - end - @testset "show" begin - id = rand(UInt64) - i = Index(2; id) - @test sprint(show, "text/plain", i) == "Index(length=2|id=$(id % 1000))" + @testset "show" begin + id = rand(UInt64) + i = Index(2; id) + @test sprint(show, "text/plain", i) == "Index(length=2|id=$(id % 1000))" - id = rand(UInt64) - i = Index(2; id, tags=["X" => "Y"]) - @test sprint(show, "text/plain", i) == "Index(length=2|id=$(id % 1000)|\"X\"=>\"Y\")" - end - @testset "delta" begin - i, j = Index.((2, 2)) - for a in ( - delta(i, j), - delta(Bool, i, j), - delta((i, j)), - delta(Bool, (i, j)), - δ(i, j), - δ(Bool, i, j), - δ((i, j)), - δ(Bool, (i, j)), - ) - @test eltype(a) === Bool - # TODO: Fix this. - @test_broken diagview(a) - @test diagview(dename(a)) == ones(2) + id = rand(UInt64) + i = Index(2; id, tags = ["X" => "Y"]) + @test sprint(show, "text/plain", i) == "Index(length=2|id=$(id % 1000)|\"X\"=>\"Y\")" + end + @testset "delta" begin + i, j = Index.((2, 2)) + for a in ( + delta(i, j), + delta(Bool, i, j), + delta((i, j)), + delta(Bool, (i, j)), + δ(i, j), + δ(Bool, i, j), + δ((i, j)), + δ(Bool, (i, j)), + ) + @test eltype(a) === Bool + # TODO: Fix this. + @test_broken diagview(a) + @test diagview(dename(a)) == ones(2) + end end - end - @testset "oneelement" begin - i = Index(3) - a = oneelement(i => 2) - @test a isa ITensor - @test ndims(a) == 1 - @test issetequal(inds(a), (i,)) - @test eltype(a) === Bool - @test a[1] == 0 - @test a[2] == 1 - @test a[3] == 0 + @testset "oneelement" begin + i = Index(3) + a = oneelement(i => 2) + @test a isa ITensor + @test ndims(a) == 1 + @test issetequal(inds(a), (i,)) + @test eltype(a) === Bool + @test a[1] == 0 + @test a[2] == 1 + @test a[3] == 0 - i = Index(3) - a = oneelement(Float32, i => 2) - @test a isa ITensor - @test ndims(a) == 1 - @test issetequal(inds(a), (i,)) - @test eltype(a) === Float32 - @test a[1] == 0 - @test a[2] == 1 - @test a[3] == 0 - end - @testset "hasqns" begin - i = Index(2) - j = Index(2) - a = ITensor(randn(2, 2), (i, j)) - @test !hasqns(i) - @test !hasqns(j) - @test !hasqns(a) + i = Index(3) + a = oneelement(Float32, i => 2) + @test a isa ITensor + @test ndims(a) == 1 + @test issetequal(inds(a), (i,)) + @test eltype(a) === Float32 + @test a[1] == 0 + @test a[2] == 1 + @test a[3] == 0 + end + @testset "hasqns" begin + i = Index(2) + j = Index(2) + a = ITensor(randn(2, 2), (i, j)) + @test !hasqns(i) + @test !hasqns(j) + @test !hasqns(a) - r = gradedrange([U1(0) => 2, U1(1) => 2]) - d = BlockSparseArray{Float64}(undef, r, dual(r)) - d[Block(1, 1)] = randn(2, 2) - d[Block(2, 2)] = randn(2, 2) - i = Index(r) - j = Index(dual(r)) - a = ITensor(d, (i, j)) - @test hasqns(i) - @test hasqns(j) - @test hasqns(a) - end - @testset "factorize" for elt in elts - i = Index(2) - j = Index(2) - a = randn(elt, i, j) - x, y = factorize(a, (i,)) - @test a ≈ x * y - @test x isa ITensor - @test y isa ITensor - @test i ∈ inds(x) - @test j ∈ inds(y) - @test eltype(x) === elt - @test eltype(y) === elt - @test Int.(Tuple(size(x))) == (2, 2) - @test Int.(Tuple(size(y))) == (2, 2) + r = gradedrange([U1(0) => 2, U1(1) => 2]) + d = BlockSparseArray{Float64}(undef, r, dual(r)) + d[Block(1, 1)] = randn(2, 2) + d[Block(2, 2)] = randn(2, 2) + i = Index(r) + j = Index(dual(r)) + a = ITensor(d, (i, j)) + @test hasqns(i) + @test hasqns(j) + @test hasqns(a) + end + @testset "factorize" for elt in elts + i = Index(2) + j = Index(2) + a = randn(elt, i, j) + x, y = factorize(a, (i,)) + @test a ≈ x * y + @test x isa ITensor + @test y isa ITensor + @test i ∈ inds(x) + @test j ∈ inds(y) + @test eltype(x) === elt + @test eltype(y) === elt + @test Int.(Tuple(size(x))) == (2, 2) + @test Int.(Tuple(size(y))) == (2, 2) - i = Index(2) - j = Index(2) - a = randn(elt, i) * randn(elt, j) - for kwargs in ((; rtol=1e-2), (; cutoff=1e-2)) - x, y = factorize(a, (i,); kwargs...) - @test a ≈ x * y - @test Int.(Tuple(size(x))) == (2, 1) - @test Int.(Tuple(size(y))) == (1, 2) + i = Index(2) + j = Index(2) + a = randn(elt, i) * randn(elt, j) + for kwargs in ((; rtol = 1.0e-2), (; cutoff = 1.0e-2)) + x, y = factorize(a, (i,); kwargs...) + @test a ≈ x * y + @test Int.(Tuple(size(x))) == (2, 1) + @test Int.(Tuple(size(y))) == (1, 2) + end end - end end