diff --git a/LICENSE b/LICENSE index 89cf357..7f5c8c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 ITensor developers +Copyright (c) 2024 ITensor developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Project.toml b/Project.toml index 6d799de..1822f05 100644 --- a/Project.toml +++ b/Project.toml @@ -3,5 +3,11 @@ uuid = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" authors = ["ITensor developers and contributors"] version = "0.1.0" +[deps] +BroadcastMapConversion = "4a4adec5-520f-4750-bb37-d5e66b4ddeb2" +NamedDimsArrays = "60cbd0c0-df58-4cb7-918c-6f5607b73fde" + [compat] +BroadcastMapConversion = "0.1.2" +NamedDimsArrays = "0.3.0" julia = "1.10" diff --git a/README.md b/README.md index ad79005..12a10d1 100644 --- a/README.md +++ b/README.md @@ -9,21 +9,7 @@ ## Installation instructions -This package resides in the `ITensor/ITensorRegistry` local registry. -In order to install, simply add that registry through your package manager. -This step is only required once. -```julia -julia> using Pkg: Pkg - -julia> Pkg.Registry.add(url="https://github.com/ITensor/ITensorRegistry") -``` -or: -```julia -julia> Pkg.Registry.add(url="git@github.com:ITensor/ITensorRegistry.git") -``` -if you want to use SSH credentials, which can make it so you don't have to enter your Github ursername and password when registering packages. - -Then, the package can be added as usual through the package manager: +The package can be added as usual through the package manager: ```julia julia> Pkg.add("ITensorBase") @@ -32,10 +18,31 @@ julia> Pkg.add("ITensorBase") ## Examples ````julia -using ITensorBase: ITensorBase +using ITensorBase: ITensorBase, ITensor, Index ```` -Examples go here. +TODO: This should be `TensorAlgebra.qr`. + +````julia +using LinearAlgebra: qr +using NamedDimsArrays: NamedDimsArray, aligndims, dimnames, name, unname +using Test: @test +i = Index(2) +j = Index(2) +k = Index(2) +a = randn(i, j) +@test a[j[2], i[1]] == a[1, 2] +@test a[j => 2, i => 1] == a[1, 2] +a′ = randn(j, i) +b = randn(j, k) +c = a * b +@test unname(c, (i, k)) ≈ unname(a, (i, j)) * unname(b, (j, k)) +d = a + a′ +@test unname(d, (i, j)) ≈ unname(a, (i, j)) + unname(a′, (i, j)) +@test a ≈ aligndims(a, (j, i)) +q, r = qr(a, (i,)) +@test q * r ≈ a +```` --- diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..dbeebed --- /dev/null +++ b/TODO.md @@ -0,0 +1,54 @@ +- Logic around element type promotion, BangBang.jl syntax. +```julia +module MutableStorageArrays + +module NoBang +function setindex(a::AbstractArray, value, I::Int...) + a′ = similar(a, typeof(value)) + a′ .= a + a′[I...] = value + return a′ +end + +function setindex(a::AbstractArray, value, I...) + a′ = similar(a, eltype(value)) + a′ .= a + a′[I...] = value + return a′ +end +end + +function may(f!, args...) + if possible(f!, args...) + return f!(args...) + end + return pure(f!)(args...) +end + +implements(f!, x) = implements(f!, typeof(x)) +implements(f!, ::Type) = false + +function setindex!! end +setindex!!(a::AbstractArray, value, I...) = may(setindex!, a, value, I...) +implements(::typeof(setindex!), ::Type{<:AbstractArray}) = true +pure(::typeof(setindex!)) = NoBang.setindex +maymutate(::typeof(setindex!)) = setindex!! +function possible(::typeof(setindex!), a::AbstractArray, value, I::Int...) + return implements(setindex!, a) && promote_type(eltype(a), typeof(value)) <: eltype(a) +end +function possible(::typeof(setindex!), a::AbstractArray, value, I...) + return implements(setindex!, a) && promote_type(eltype(a), eltype(value)) <: eltype(a) +end + +struct MutableStorageArrayInterface <: AbstractArrayInterface end + +# Minimal interface. +function storage end +function setstorage! end + +@interface ::MutableStorageArrayInterface function Base.setindex!(a::AbstractArray, value, I...) + return setstorage!(a, storage(setindex!!(a, value, I...))) +end + +end +``` diff --git a/docs/Project.toml b/docs/Project.toml index b20b771..112f250 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,5 @@ [deps] -ITensorBase = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +ITensorBase = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" +NamedDimsArrays = "60cbd0c0-df58-4cb7-918c-6f5607b73fde" diff --git a/docs/make.jl b/docs/make.jl index 6cb83b0..ca23e61 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,9 +1,7 @@ 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") @@ -12,13 +10,9 @@ makedocs(; authors="ITensor developers and contributors", sitename="ITensorBase.jl", format=Documenter.HTML(; - canonical="https://ITensor.github.io/ITensorBase.jl", - edit_link="main", - assets=String[], + canonical="https://ITensor.github.io/ITensorBase.jl", edit_link="main", assets=String[] ), pages=["Home" => "index.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/examples/Project.toml b/examples/Project.toml index 7778d89..24d1d66 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -1,2 +1,4 @@ [deps] ITensorBase = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +NamedDimsArrays = "60cbd0c0-df58-4cb7-918c-6f5607b73fde" diff --git a/examples/README.jl b/examples/README.jl index a46da74..d1b16e9 100644 --- a/examples/README.jl +++ b/examples/README.jl @@ -9,25 +9,7 @@ # ## Installation instructions -# This package resides in the `ITensor/ITensorRegistry` local registry. -# In order to install, simply add that registry through your package manager. -# This step is only required once. -#= -```julia -julia> using Pkg: Pkg - -julia> Pkg.Registry.add(url="https://github.com/ITensor/ITensorRegistry") -``` -=# -# or: -#= -```julia -julia> Pkg.Registry.add(url="git@github.com:ITensor/ITensorRegistry.git") -``` -=# -# if you want to use SSH credentials, which can make it so you don't have to enter your Github ursername and password when registering packages. - -# Then, the package can be added as usual through the package manager: +# The package can be added as usual through the package manager: #= ```julia @@ -37,5 +19,23 @@ julia> Pkg.add("ITensorBase") # ## Examples -using ITensorBase: ITensorBase -# Examples go here. +using ITensorBase: ITensorBase, ITensor, Index +# TODO: This should be `TensorAlgebra.qr`. +using LinearAlgebra: qr +using NamedDimsArrays: NamedDimsArray, aligndims, dimnames, name, unname +using Test: @test +i = Index(2) +j = Index(2) +k = Index(2) +a = randn(i, j) +@test a[j[2], i[1]] == a[1, 2] +@test a[j => 2, i => 1] == a[1, 2] +a′ = randn(j, i) +b = randn(j, k) +c = a * b +@test unname(c, (i, k)) ≈ unname(a, (i, j)) * unname(b, (j, k)) +d = a + a′ +@test unname(d, (i, j)) ≈ unname(a, (i, j)) + unname(a′, (i, j)) +@test a ≈ aligndims(a, (j, i)) +q, r = qr(a, (i,)) +@test q * r ≈ a diff --git a/src/ITensorBase.jl b/src/ITensorBase.jl index e4c3616..1a348f3 100644 --- a/src/ITensorBase.jl +++ b/src/ITensorBase.jl @@ -1,5 +1,79 @@ module ITensorBase -# Write your package code here. +using BroadcastMapConversion: Mapped +using NamedDimsArrays: + NamedDimsArrays, + AbstractName, + AbstractNamedDimsArray, + AbstractNamedInteger, + AbstractNamedUnitRange, + AbstractNamedVector, + dename, + dimnames, + name, + named, + unname + +@kwdef struct IndexName <: AbstractName + id::UInt64 = rand(UInt64) + plev::Int = 0 + tags::Set{String} = Set{String}() + namedtags::Dict{Symbol,String} = Dict{Symbol,String}() +end +NamedDimsArrays.randname(n::IndexName) = IndexName() + +struct IndexVal{Value<:Integer} <: AbstractNamedInteger{Value,IndexName} + value::Value + name::IndexName +end + +# Interface +NamedDimsArrays.dename(i::IndexVal) = i.value +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 +end + +Index(length::Int) = Index(Base.OneTo(length), IndexName()) + +# Interface +# TODO: Overload `Base.parent` instead. +NamedDimsArrays.dename(i::Index) = i.value +NamedDimsArrays.name(i::Index) = i.name + +# Constructor +NamedDimsArrays.named(i::AbstractUnitRange, name::IndexName) = Index(i, name) + +struct NoncontiguousIndex{T,Value<:AbstractVector{T}} <: + AbstractNamedVector{T,Value,IndexName} + value::Value + name::IndexName +end + +# Interface +# TODO: Overload `Base.parent` instead. +NamedDimsArrays.dename(i::NoncontiguousIndex) = i.value +NamedDimsArrays.name(i::NoncontiguousIndex) = i.name + +# Constructor +NamedDimsArrays.named(i::AbstractVector, name::IndexName) = NoncontiguousIndex(i, name) + +abstract type AbstractITensor <: AbstractNamedDimsArray{Any,Any} end + +NamedDimsArrays.nameddimsarraytype(::Type{<:IndexName}) = ITensor + +Base.ndims(::Type{<:AbstractITensor}) = Any + +struct ITensor <: AbstractITensor + parent::AbstractArray + nameddimsindices +end +Base.parent(a::ITensor) = a.parent +NamedDimsArrays.nameddimsindices(a::ITensor) = a.nameddimsindices end diff --git a/test/Project.toml b/test/Project.toml index e9c291e..d9e7725 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,5 +1,8 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +ITensorBase = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +NamedDimsArrays = "60cbd0c0-df58-4cb7-918c-6f5607b73fde" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"