diff --git a/docs/src/MPSandMPO.md b/docs/src/MPSandMPO.md index 7c62000c0f..4671ca96be 100644 --- a/docs/src/MPSandMPO.md +++ b/docs/src/MPSandMPO.md @@ -42,8 +42,8 @@ hasqns(::ITensors.AbstractMPS) ## Obtaining and finding indices ```@docs -common_siteind(::ITensors.AbstractMPS, ::ITensors.AbstractMPS, ::Int) -common_siteinds(::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +siteinds(::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS, ::Int) +siteinds(::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS, ::Int) findsite findsites firstsiteinds @@ -54,8 +54,6 @@ siteinds(::MPS) siteind(::MPO, ::Int) siteinds(::MPO) siteinds(::ITensors.AbstractMPS, ::Int) -unique_siteind(::ITensors.AbstractMPS, ::ITensors.AbstractMPS, ::Int) -unique_siteinds(::ITensors.AbstractMPS, ::ITensors.AbstractMPS) ``` ## Priming and tagging @@ -63,18 +61,60 @@ unique_siteinds(::ITensors.AbstractMPS, ::ITensors.AbstractMPS) ```@docs prime(::ITensors.AbstractMPS) prime!(::ITensors.AbstractMPS) +prime(::typeof(linkinds), ::ITensors.AbstractMPS) +prime!(::typeof(linkinds), ::ITensors.AbstractMPS) +prime(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +prime!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +prime(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +prime!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) setprime(::ITensors.AbstractMPS) setprime!(::ITensors.AbstractMPS) +setprime(::typeof(linkinds), ::ITensors.AbstractMPS) +setprime!(::typeof(linkinds), ::ITensors.AbstractMPS) +setprime(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +setprime!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +setprime(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +setprime!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) noprime(::ITensors.AbstractMPS) noprime!(::ITensors.AbstractMPS) +noprime(::typeof(linkinds), ::ITensors.AbstractMPS) +noprime!(::typeof(linkinds), ::ITensors.AbstractMPS) +noprime(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +noprime!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +noprime(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +noprime!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) addtags(::ITensors.AbstractMPS) addtags!(::ITensors.AbstractMPS) +addtags(::typeof(linkinds), ::ITensors.AbstractMPS) +addtags!(::typeof(linkinds), ::ITensors.AbstractMPS) +addtags(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +addtags!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +addtags(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +addtags!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) removetags(::ITensors.AbstractMPS) removetags!(::ITensors.AbstractMPS) +removetags(::typeof(linkinds), ::ITensors.AbstractMPS) +removetags!(::typeof(linkinds), ::ITensors.AbstractMPS) +removetags(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +removetags!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +removetags(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +removetags!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) replacetags(::ITensors.AbstractMPS) replacetags!(::ITensors.AbstractMPS) +replacetags(::typeof(linkinds), ::ITensors.AbstractMPS) +replacetags!(::typeof(linkinds), ::ITensors.AbstractMPS) +replacetags(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +replacetags!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +replacetags(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +replacetags!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) settags(::ITensors.AbstractMPS) settags!(::ITensors.AbstractMPS) +settags(::typeof(linkinds), ::ITensors.AbstractMPS) +settags!(::typeof(linkinds), ::ITensors.AbstractMPS) +settags(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +settags!(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +settags(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) +settags!(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS) ``` ## Operations diff --git a/src/ITensors.jl b/src/ITensors.jl index 9e90e96204..d6fbee3e28 100644 --- a/src/ITensors.jl +++ b/src/ITensors.jl @@ -84,6 +84,7 @@ include("qn/qnitensor.jl") # MPS/MPO # include("mps/abstractmps.jl") +include("mps/deprecated.jl") include("mps/mps.jl") include("mps/mpo.jl") include("mps/sweeps.jl") diff --git a/src/broadcast.jl b/src/broadcast.jl index 9446aadaa9..d6cb4ab420 100644 --- a/src/broadcast.jl +++ b/src/broadcast.jl @@ -5,17 +5,26 @@ BroadcastStyle(::Type{<:IndexSet}) = Style{IndexSet}() -broadcastable(t::IndexSet) = t +BroadcastStyle(::AbstractArrayStyle{0}, b::Style{IndexSet}) = b +BroadcastStyle(a::AbstractArrayStyle, ::Style{IndexSet}) = a +BroadcastStyle(a::Style{Tuple}, ::Style{IndexSet}) = a -# This is required for speed and type stability -# (not sure why, but I guess the default is slow) instantiate(bc::Broadcasted{Style{IndexSet}, Nothing}) = bc +function instantiate(bc::Broadcasted{Style{IndexSet}}) + check_broadcast_axes(bc.axes, bc.args...) + return bc +end + +broadcastable(t::IndexSet) = t + +indexset_or_tuple(t::Tuple{Vararg{<:Index}}) = IndexSet(t) +indexset_or_tuple(t) = t -function Base.copy(bc::Broadcasted{Style{IndexSet}}) - dim = axes(bc) - length(dim) == 1 || throw(DimensionMismatch("IndexSet only supports one dimension")) - N = length(dim[1]) - return IndexSet(ntuple(k -> bc[k], Val(N))) +@inline function copy(bc::Broadcasted{Style{IndexSet}}) + dim = axes(bc) + length(dim) == 1 || throw(DimensionMismatch("tuple only supports one dimension")) + N = length(dim[1]) + return indexset_or_tuple(ntuple(k -> @inbounds(_broadcast_getindex(bc, k)), Val(N))) end # diff --git a/src/imports.jl b/src/imports.jl index 3c2788fbc0..2d7f41ec68 100644 --- a/src/imports.jl +++ b/src/imports.jl @@ -32,6 +32,7 @@ import Base: keys, lastindex, length, + map, map!, ndims, push!, @@ -45,11 +46,13 @@ import Base: import Base.Broadcast: # types + AbstractArrayStyle, Broadcasted, BroadcastStyle, DefaultArrayStyle, Style, # functions + _broadcast_getindex, broadcasted, broadcastable, instantiate diff --git a/src/indexset.jl b/src/indexset.jl index 7a6ec19de0..1224b9aa40 100644 --- a/src/indexset.jl +++ b/src/indexset.jl @@ -969,9 +969,18 @@ end swaptags(is::IndexSet, tags1, tags2, args...; kwargs...) = swaptags(fmatch(args...; kwargs...), is, tags1, tags2) -replaceinds(is::IndexSet, rep_inds::Pair{ <: Index, <: Index}...) = +replaceinds(is::IndexSet, rep_inds::Pair{<: Index, <: Index}...) = replaceinds(is, zip(rep_inds...)...) +replaceinds(is::IndexSet, rep_inds::Vector{Pair{<: Index, <: Index}}) = + replaceinds(is, rep_inds...) + +replaceinds(is::IndexSet, rep_inds::Tuple{Vararg{Pair{<: Index, <: Index}}}) = + replaceinds(is, rep_inds...) + +replaceinds(is::IndexSet, rep_inds::Pair) = + replaceinds(is, Tuple(first(rep_inds)) .=> Tuple(last(rep_inds))) + # Check that the QNs are all the same hassameflux(i1::Index, i2::Index) = (dim(i1) == dim(i2)) diff --git a/src/mps/abstractmps.jl b/src/mps/abstractmps.jl index dd1ad793ff..f086b17d83 100644 --- a/src/mps/abstractmps.jl +++ b/src/mps/abstractmps.jl @@ -148,9 +148,7 @@ macro preserve_ortho(ψ, block) end end -function setindex!(M::AbstractMPS, - T::ITensor, - n::Integer; +function setindex!(M::AbstractMPS, T::ITensor, n::Integer; set_limits::Bool = true) if set_limits (n <= leftlim(M)) && setleftlim!(M,n-1) @@ -185,7 +183,6 @@ iterate(M::AbstractMPS, state) = iterate(data(M), state) """ linkind(M::MPS, j::Integer) - linkind(M::MPO, j::Integer) Get the link or bond Index connecting the @@ -217,47 +214,51 @@ function dense(ψ::AbstractMPS) end """ - unique_siteind[s](A::MPO, B::MPS, j::Integer) - unique_siteind[s](A::MPO, B::MPO, j::Integer) + siteinds(uniqueinds, A::MPO, B::MPS, j::Integer; kwargs...) + siteinds(uniqueind, A::MPO, B::MPS, j::Integer; kwargs...) Get the site index (or indices) of MPO `A` that is unique to `A` (not shared with MPS/MPO `B`). """ -function unique_siteinds(A::AbstractMPS, B::AbstractMPS, j::Integer) +function siteinds(f::Union{typeof(uniqueinds), typeof(uniqueind)}, + A::AbstractMPS, B::AbstractMPS, j::Integer; kwargs...) N = length(A) - N == 1 && return uniqueinds(A[j], B[j]) - j == 1 && return uniqueinds(A[j], A[j+1], B[j]) - j == N && return uniqueinds(A[j], A[j-1], B[j]) - return uniqueinds(A[j], A[j-1], A[j+1], B[j]) + N == 1 && return f(A[j], B[j]; kwargs...) + j == 1 && return f(A[j], A[j+1], B[j]; kwargs...) + j == N && return f(A[j], A[j-1], B[j]; kwargs...) + return f(A[j], A[j-1], A[j+1], B[j]; kwargs...) end """ - unique_siteinds(A::MPO, B::MPS) - unique_siteinds(A::MPO, B::MPO) + siteinds(uniqueinds, A::MPO, B::MPS) + siteinds(uniqueind, A::MPO, B::MPO) Get the site indices of MPO `A` that are unique to `A` (not shared with MPS/MPO `B`), as a `Vector{<:Index}`. """ -function unique_siteinds(A::AbstractMPS, B::AbstractMPS) - return [unique_siteind(A, B, j) for j in eachindex(A)] +function siteinds(f::Union{typeof(uniqueinds), typeof(uniqueind)}, + A::AbstractMPS, B::AbstractMPS; kwargs...) + return [siteinds(f, A, B, j; kwargs...) for j in eachindex(A)] end """ - common_siteind(A::MPO, B::MPS, j::Integer) - common_siteind(A::MPO, B::MPO, j::Integer) + siteinds(commoninds, A::MPO, B::MPS, j::Integer; kwargs...) + siteinds(commonind, A::MPO, B::MPO, j::Integer; kwargs...) -Get the site index of MPO `A` that is shared with MPS/MPO `B`. +Get the site index (or indices) of the `j`th MPO tensor of `A` that is shared with MPS/MPO `B`. """ -function common_siteind(A::AbstractMPS, B::AbstractMPS, j::Integer) - return commonind(A[j], B[j]) +function siteinds(f::Union{typeof(commoninds), typeof(commonind)}, + A::AbstractMPS, B::AbstractMPS, j::Integer; kwargs...) + return f(A[j], B[j]; kwargs...) end """ - common_siteinds(A::MPO, B::MPS) - common_siteinds(A::MPO, B::MPO) + siteinds(commoninds, A::MPO, B::MPS; kwargs...) + siteinds(commonind, A::MPO, B::MPO; kwargs...) -Get the site indices of MPO `A` that are shared with MPS/MPO `B`, as a `Vector{<:Index}`. +Get a vector of the site index (or indices) of MPO `A` that is shared with MPS/MPO `B`. """ -function common_siteinds(A::AbstractMPS, B::AbstractMPS) - return [common_siteind(A, B, j) for j in eachindex(A)] +function siteinds(f::Union{typeof(commoninds), typeof(commonind)}, + A::AbstractMPS, B::AbstractMPS; kwargs...) + return [siteinds(f, A, B, j) for j in eachindex(A)] end keys(ψ::AbstractMPS) = keys(data(ψ)) @@ -295,6 +296,12 @@ findsite(ψ::AbstractMPS, is) = findfirst(hascommoninds(is), ψ) findsite(ψ::AbstractMPS, s::Index) = findsite(ψ, IndexSet(s)) +# +# TODO: Maybe make: +# findall(f::Function, siteindsM::Tuple{typeof(siteinds), ::AbstractMPS}) +# findall(siteindsM::Tuple{typeof(siteinds), <:AbstractMPS}, is) = +# findall(hassameinds(is), siteindsM) +# """ findsites(M::Union{MPS, MPO}, is) @@ -316,42 +323,40 @@ findsites(M, (s[4]', s[4])) == [4] findsites(M, (s[4]', s[3])) == [3, 4] ``` """ -findsites(ψ::ITensors.AbstractMPS, is) = +findsites(ψ::AbstractMPS, is) = findall(hascommoninds(is), ψ) -findsites(ψ::ITensors.AbstractMPS, s::Index) = - findsites(ψ, IndexSet(s)) +findsites(ψ::AbstractMPS, s::Index) = + findsites(ψ, IndexSet(s)) -# TODO: depracate in favor of findsite. +# +# TODO: Maybe make: +# findfirst(f::Function, siteindsM::Tuple{typeof(siteinds), ::AbstractMPS}) +# findfirst(siteindsM::Tuple{typeof(siteinds), <:AbstractMPS}, is) = +# findfirst(hassameinds(is), siteindsM) +# """ findfirstsiteind(M::MPS, i::Index) - findfirstsiteind(M::MPO, i::Index) Return the first site of the MPS or MPO that has the site index `i`. """ -function findfirstsiteind(ψ::AbstractMPS, - s::Index) - return findfirst(hasind(s), ψ) -end +findfirstsiteind(ψ::AbstractMPS, s::Index) = + findfirst(hasind(s), ψ) # TODO: depracate in favor of findsite. """ - findfirstsiteind(M::MPS, is) - - findfirstsiteind(M::MPO, is) + findfirstsiteinds(M::MPS, is) + findfirstsiteinds(M::MPO, is) Return the first site of the MPS or MPO that has the site indices `is`. """ -function findfirstsiteinds(ψ::AbstractMPS, - s) - return findfirst(hasinds(s), ψ) -end +findfirstsiteinds(ψ::AbstractMPS, s) = + findfirst(hasinds(s), ψ) """ - firstsiteind(M::Union{MPS,MPO}, j::Integer; kwargs...) siteind(::typeof(first), M::Union{MPS,MPO}, j::Integer; kwargs...) Return the first site Index found on the MPS or MPO @@ -374,9 +379,6 @@ function siteind(::typeof(first), M::AbstractMPS, j::Integer; return si end -firstsiteind(M::AbstractMPS, j::Integer; kwargs...) = - siteind(first, M, j; kwargs...) - """ siteinds(M::Union{MPS, MPO}}, j::Integer; kwargs...) @@ -427,8 +429,8 @@ function replaceinds!(::typeof(linkinds), M::AbstractMPS, return M end -replaceinds(::typeof(linkinds), M::ITensors.AbstractMPS, - l̃s::Vector{<:Index}) = replaceinds!(linkinds, copy(M), l̃s) +replaceinds(::typeof(linkinds), M::AbstractMPS, l̃s::Vector{<:Index}) = + replaceinds!(linkinds, copy(M), l̃s) # TODO: change kwarg from `set_limits` to `preserve_ortho` function map!(f::Function, M::AbstractMPS; set_limits::Bool = true) @@ -439,7 +441,7 @@ function map!(f::Function, M::AbstractMPS; set_limits::Bool = true) end # TODO: change kwarg from `set_limits` to `preserve_ortho` -Base.map(f::Function, M::AbstractMPS; set_limits::Bool = true) = +map(f::Function, M::AbstractMPS; set_limits::Bool = true) = map!(f, copy(M); set_limits = set_limits) for fname in (:dag, :prime, :setprime, :noprime, :addtags, :removetags, @@ -449,7 +451,6 @@ for fname in (:dag, :prime, :setprime, :noprime, :addtags, :removetags, @eval begin """ $($fname)(M::MPS, args...; kwargs...) - $($fname)(M::MPO, args...; kwargs...) Apply $($fname) to all ITensors of an MPS/MPO, returning a new MPS/MPO. @@ -463,7 +464,6 @@ for fname in (:dag, :prime, :setprime, :noprime, :addtags, :removetags, """ $($fname_bang)(M::MPS, args...; kwargs...) - $($fname_bang)(M::MPO, args...; kwargs...) Apply $($fname) to all ITensors of an MPS/MPO in-place. @@ -495,7 +495,7 @@ function check_hascommoninds(::typeof(siteinds), A::AbstractMPS, B::AbstractMPS) end end -function map_linkinds!(f::Function, M::AbstractMPS) +function map!(f::Function, ::typeof(linkinds), M::AbstractMPS) for i in eachindex(M)[1:end-1] l = linkind(M, i) if !isnothing(l) @@ -507,48 +507,42 @@ function map_linkinds!(f::Function, M::AbstractMPS) return M end -# Change to: -# map(f::Function, ::typeof(linkinds), M::AbstractMPS) -map_linkinds(f::Function, M::AbstractMPS) = map_linkinds!(f, copy(M)) +map(f::Function, ::typeof(linkinds), M::AbstractMPS) = map!(f, linkinds, copy(M)) -# Change to: -# map!(f::Function, ::typeof(commoninds), ::typeof(siteinds), -# M::AbstractMPS) -function map_common_siteinds!(f::Function, M1::AbstractMPS, - M2::AbstractMPS) +function map!(f::Function, ::typeof(siteinds), ::typeof(commoninds), + M1::AbstractMPS, M2::AbstractMPS) length(M1) != length(M2) && error("MPOs/MPSs must be the same length") for i in eachindex(M1) - s = common_siteind(M1, M2, i) - if !isnothing(s) - s̃ = f(s) - M1[i, set_limits = false] = replaceind(M1[i], s, s̃) - M2[i, set_limits = false] = replaceind(M2[i], s, s̃) + s = siteinds(commoninds, M1, M2, i) + if !isempty(s) + s̃ = f.(s) + @preserve_ortho (M1, M2) begin + M1[i] = replaceinds(M1[i], s .=> s̃) + M2[i] = replaceinds(M2[i], s .=> s̃) + end end end return M1, M2 end -function map_common_siteinds(f::Function, M1::AbstractMPS, - M2::AbstractMPS) - return map_common_siteinds!(f, copy(M1), copy(M2)) -end - -function map_unique_siteinds!(f::Function, M1::AbstractMPS, - M2::AbstractMPS) +function map!(f::Function, ::typeof(siteinds), ::typeof(uniqueinds), + M1::AbstractMPS, M2::AbstractMPS) length(M1) != length(M2) && error("MPOs/MPSs must be the same length") for i in eachindex(M1) - s = unique_siteind(M1, M2, i) - if !isnothing(s) - s̃ = f(s) - M1[i, set_limits = false] = replaceind(M1[i], s, s̃) + s = siteinds(uniqueinds, M1, M2, i) + if !isempty(s) + @preserve_ortho M1 begin + M1[i] = replaceinds(M1[i], s .=> f.(s)) + end end end return M1 end -function map_unique_siteinds(f::Function, M1::AbstractMPS, - M2::AbstractMPS) - return map_unique_siteinds!(f, copy(M1), M2) +function map(f::Function, ffilter::typeof(siteinds), + fsubset::Union{typeof(commoninds), typeof(uniqueinds)}, + M1::AbstractMPS, M2::AbstractMPS) + return map!(f, ffilter, fsubset, copy(M1), copy(M2)) end function hassameinds(::typeof(siteinds), M1::AbstractMPS, M2::AbstractMPS) @@ -569,93 +563,71 @@ end for fname in (:sim, :prime, :setprime, :noprime, :addtags, :removetags, :replacetags, :settags) - fname_linkinds = Symbol(fname, :_linkinds) - fname_linkinds_inplace = Symbol(fname_linkinds, :!) - fname_common_siteinds = Symbol(fname, :_common_siteinds) - fname_common_siteinds_inplace = Symbol(fname_common_siteinds, :!) - fname_unique_siteinds = Symbol(fname, :_unique_siteinds) - fname_unique_siteinds_inplace = Symbol(fname_unique_siteinds, :!) - + fname! = Symbol(fname, :!) @eval begin """ - $($fname_linkinds)(M::MPS, args...; kwargs...) - - $($fname_linkinds)(M::MPO, args...; kwargs...) + $($fname)(linkinds, M::MPS, args...; kwargs...) + $($fname)(linkinds, M::MPO, args...; kwargs...) Apply $($fname) to all link indices of an MPS/MPO, returning a new MPS/MPO. The ITensors of the MPS/MPO will be a view of the storage of the original ITensors. """ - $fname_linkinds(M::AbstractMPS, args...; kwargs...) = - map_linkinds(i -> $fname(i, args...; kwargs...), M) + $fname(ffilter::typeof(linkinds), M::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), ffilter, M) """ - $($fname_linkinds)!(M::MPS, args...; kwargs...) - - $($fname_linkinds)!(M::MPO, args...; kwargs...) + $($fname)!(linkinds, M::MPS, args...; kwargs...) + $($fname)!(linkinds, M::MPO, args...; kwargs...) Apply $($fname) to all link indices of the ITensors of an MPS/MPO in-place. """ - $fname_linkinds_inplace(M::AbstractMPS, args...; kwargs...) = - map_linkinds!(i -> $fname(i, args...; kwargs...), M) + $(fname!)(ffilter::typeof(linkinds), M::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), ffilter, M) """ - $($fname_common_siteinds)(M1::MPO, M2::MPS, args...; kwargs...) - - $($fname_common_siteinds)(M1::MPO, M2::MPO, args...; kwargs...) + $($fname)(siteinds, commoninds, M1::MPO, M2::MPS, args...; kwargs...) + $($fname)(siteinds, commoninds, M1::MPO, M2::MPO, args...; kwargs...) Apply $($fname) to the site indices that are shared by `M1` and `M2`. Returns new MPSs/MPOs. The ITensors of the MPSs/MPOs will be a view of the storage of the original ITensors. """ - function $fname_common_siteinds(M1::AbstractMPS, - M2::AbstractMPS, - args...; - kwargs...) - return map_common_siteinds(i -> $fname(i, args...; - kwargs...), M1, M2) - end + $fname(ffilter::typeof(siteinds), fsubset::typeof(commoninds), M1::AbstractMPS, + M2::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), ffilter, fsubset, M1, M2) """ - $($fname_common_siteinds)!(M1::MPO, M2::MPS, args...; kwargs...) - - $($fname_common_siteinds)!(M1::MPO, M2::MPO, args...; kwargs...) + $($fname)!(siteinds, commoninds, M1::MPO, M2::MPS, args...; kwargs...) + $($fname)!(siteinds, commoninds, M1::MPO, M2::MPO, args...; kwargs...) Apply $($fname) to the site indices that are shared by `M1` and `M2`. Returns new MPSs/MPOs. Modifies the input MPSs/MPOs in-place. """ - $fname_common_siteinds_inplace(M1::AbstractMPS, M2::AbstractMPS, - args...; kwargs...) = - map_common_siteinds!(i -> $fname(i, args...; kwargs...), M1, M2) + $(fname!)(ffilter::typeof(siteinds), fsubset::typeof(commoninds), M1::AbstractMPS, + M2::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), ffilter, fsubset, M1, M2) """ - $($fname_unique_siteinds)(M1::MPO, M2::MPS, args...; kwargs...) + $($fname)(siteinds, uniqueinds, M1::MPO, M2::MPS, args...; kwargs...) Apply $($fname) to the site indices of `M1` that are not shared with `M2`. Returns new MPSs/MPOs. The ITensors of the MPSs/MPOs will be a view of the storage of the original ITensors. """ - function $fname_unique_siteinds(M1::AbstractMPS, - M2::AbstractMPS, - args...; - kwargs...) - return map_unique_siteinds(i -> $fname(i, args...; - kwargs...), M1, M2) - end + $fname(ffilter::typeof(siteinds), fsubset::typeof(uniqueinds), M1::AbstractMPS, + M2::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), ffilter, fsubset, M1, M2) """ - $($fname_unique_siteinds)!(M1::MPO, M2::MPS, args...; kwargs...) + $($fname)!(siteinds, uniqueinds, M1::MPO, M2::MPS, args...; kwargs...) Apply $($fname) to the site indices of `M1` that are not shared with `M2`. Modifies the input MPSs/MPOs in-place. """ - function $fname_unique_siteinds_inplace(M1::AbstractMPS, - M2::AbstractMPS, - args...; - kwargs...) - return map_unique_siteinds!(i -> $fname(i, args...; - kwargs...), M1, M2) - end + $(fname!)(ffilter::typeof(siteinds), fsubset::typeof(uniqueinds), M1::AbstractMPS, + M2::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), ffilter, fsubset, M1, M2) end end @@ -703,7 +675,7 @@ function _log_or_not_dot(M1::MPST, M2::MPST, loginner::Bool; throw(DimensionMismatch("inner: mismatched lengths $N and $(length(M2))")) end M1dag = dag(M1) - sim_linkinds!(M1dag) + sim!(linkinds, M1dag) siteindsM1dag = siteinds(all, M1dag) siteindsM2 = siteinds(all, M2) if any(n -> length(n) > 1, siteindsM1dag) || @@ -771,9 +743,8 @@ For now, `make_inds_match` is only supported for MPSs. See also `logdot`/`loginner`. """ -function dot(M1::MPST, M2::MPST; kwargs...) where {MPST <: AbstractMPS} - return _log_or_not_dot(M1, M2, false; kwargs...) -end +dot(M1::MPST, M2::MPST; kwargs...) where {MPST <: AbstractMPS} = + _log_or_not_dot(M1, M2, false; kwargs...) """ logdot(A::MPS, B::MPS; make_inds_match = true) @@ -900,8 +871,7 @@ println() inner(ψ₃, ψ₁) + 2 * inner(ψ₃, ψ₂) + inner(ψ₃, ψ₃) ``` """ -function +(ψ⃗::MPST...; - cutoff = 1e-15, kwargs...) where {MPST <: AbstractMPS} +function +(ψ⃗::MPST...; cutoff = 1e-15, kwargs...) where {MPST <: AbstractMPS} Nₘₚₛ = length(ψ⃗) @assert all(ψᵢ -> length(ψ⃗[1]) == length(ψᵢ), ψ⃗) @@ -976,8 +946,7 @@ add(A::T, B::T; Add multiple MPS/MPO with each other, with some optional truncation. """ -function Base.sum(ψ⃗::Vector{T}; - kwargs...) where {T <: AbstractMPS} +function sum(ψ⃗::Vector{T}; kwargs...) where {T <: AbstractMPS} length(ψ⃗) == 0 && return T() length(ψ⃗) == 1 && return A[1] return +(ψ⃗...; kwargs...) @@ -1000,9 +969,7 @@ bond indices is performed. Afterward, tensors Either modify in-place with `orthogonalize!` or out-of-place with `orthogonalize`. """ -function orthogonalize!(M::AbstractMPS, - j::Int; - kwargs...) +function orthogonalize!(M::AbstractMPS, j::Int; kwargs...) while leftlim(M) < (j-1) (leftlim(M) < 0) && setleftlim!(M, 0) b = leftlim(M)+1 @@ -1045,7 +1012,6 @@ end """ truncate!(M::MPS; kwargs...) - truncate!(M::MPO; kwargs...) Perform a truncation of all bonds of an MPS/MPO, @@ -1071,6 +1037,12 @@ function truncate!(M::AbstractMPS; kwargs...) return M end +function truncate(ψ0::AbstractMPS; kwargs...) + ψ = copy(ψ0) + truncate!(ψ; kwargs...) + return ψ +end + contract(A::AbstractMPS, B::AbstractMPS; kwargs...) = *(A, B; kwargs...) @@ -1155,15 +1127,9 @@ end # TODO: add a version that determines the sites # from common site indices of ψ and A """ - setindex!(ψ::Union{MPS, MPO}, - A::ITensor, - r::UnitRange{Int}; - orthocenter::Int = last(r), - perm = nothing, - kwargs...) - + setindex!(ψ::Union{MPS, MPO}, A::ITensor, r::UnitRange{Int}; + orthocenter::Int = last(r), perm = nothing, kwargs...) replacesites!([...]) - replacesites([...]) Replace the sites in the range `r` with tensors made @@ -1181,8 +1147,7 @@ Optionally, permute the order of the sites with `perm`. """ function setindex!(ψ::MPST, A::ITensor, r::UnitRange{Int}; orthocenter::Integer = last(r), - perm = nothing, - kwargs...) where {MPST <: AbstractMPS} + perm = nothing, kwargs...) where {MPST <: AbstractMPS} # Replace the sites of ITensor ψ # with the tensor A, splitting up A # into MPS tensors @@ -1275,7 +1240,6 @@ _number_inds(sites) = sum(_number_inds(s) for s in sites) """ MPS(A::ITensor, sites; ) - MPO(A::ITensor, sites; ) Construct an MPS/MPO from an ITensor `A` by decomposing it site @@ -1287,8 +1251,7 @@ by site according to the site indices `sites`. - `cutoff`: the desired truncation error at each link. - `maxdim`: the maximum link dimension. """ -function (::Type{MPST})(A::ITensor, sites; - leftinds = nothing, +function (::Type{MPST})(A::ITensor, sites; leftinds = nothing, orthocenter::Integer = length(sites), kwargs...) where {MPST <: AbstractMPS} N = length(sites) @@ -1377,8 +1340,7 @@ end # Helper function for permuting a vector for the # movesites function. -function _movesite(ns::Vector{Int}, - n1n2::Pair{Int, Int}) +function _movesite(ns::Vector{Int}, n1n2::Pair{Int, Int}) n1, n2 = n1n2 n1 == n2 && return copy(ns) r = n1:n2-1 @@ -1406,8 +1368,8 @@ end # TODO: make a permutesites(::MPS/MPO, perm) # function that takes a permutation of the sites # p(1:N) for N sites -function movesites(ψ::AbstractMPS, - nsns′::Vector{Pair{Int, Int}}; kwargs...) +function movesites(ψ::AbstractMPS, nsns′::Vector{Pair{Int, Int}}; + kwargs...) ns = first.(nsns′) ns′ = last.(nsns′) ψ = copy(ψ) @@ -1424,8 +1386,7 @@ function movesites(ψ::AbstractMPS, end # TODO: call the Vector{Pair{Int, Int}} version -function movesites(ψ::AbstractMPS, - ns, ns′; kwargs...) +function movesites(ψ::AbstractMPS, ns, ns′; kwargs...) ψ = copy(ψ) N = length(ns) @assert N == length(ns′) @@ -1458,12 +1419,8 @@ to false. # Arguments - `move_sites_back::Bool = true`: after the ITensor is applied to the MPS or MPO, move the sites of the MPS or MPO back to their original locations. """ -function product(o::ITensor, - ψ::AbstractMPS, - ns = findsites(ψ, o); - move_sites_back::Bool = true, - apply_dag::Bool = false, - kwargs...) +function product(o::ITensor, ψ::AbstractMPS, ns = findsites(ψ, o); + move_sites_back::Bool = true, apply_dag::Bool = false, kwargs...) N = length(ns) ns = sort(ns) diff --git a/src/mps/deprecated.jl b/src/mps/deprecated.jl new file mode 100644 index 0000000000..8f498fb382 --- /dev/null +++ b/src/mps/deprecated.jl @@ -0,0 +1,56 @@ + +unique_siteind(A::AbstractMPS, B::AbstractMPS, j::Integer) = + siteinds(uniqueind, A, B, j) + +unique_siteinds(A::AbstractMPS, B::AbstractMPS, j::Integer) = + siteinds(uniqueinds, A, B, j) + +unique_siteinds(A::AbstractMPS, B::AbstractMPS) = + siteinds(uniqueind, A, B) + +common_siteind(A::AbstractMPS, B::AbstractMPS, j::Integer) = + siteinds(commonind, A, B, j) + +common_siteinds(A::AbstractMPS, B::AbstractMPS, j::Integer) = + siteinds(commoninds, A, B, j) + +common_siteinds(A::AbstractMPS, B::AbstractMPS) = + siteinds(commoninds, A, B) + +firstsiteind(M::AbstractMPS, j::Integer; kwargs...) = + siteind(first, M, j; kwargs...) + +map_linkinds!(f::Function, M::AbstractMPS) = map!(f, linkinds, M) + +map_linkinds(f::Function, M::AbstractMPS) = map(f, linkinds, M) + +map_common_siteinds!(f::Function, M1::AbstractMPS, M2::AbstractMPS) = + map!(f, siteinds, commoninds, M1, M2) + +map_common_siteinds(f::Function, M1::AbstractMPS, M2::AbstractMPS) = + map(f, siteinds, commoninds, M1, M2) + +map_unique_siteinds!(f::Function, M1::AbstractMPS, M2::AbstractMPS) = + map!(f, siteinds, uniqueinds, M1, M2) + +map_unique_siteinds(f::Function, M1::AbstractMPS, M2::AbstractMPS) = + map(f, siteinds, uniqueinds, M1, M2) + +for fname in (:sim, :prime, :setprime, :noprime, :addtags, :removetags, + :replacetags, :settags) + @eval begin + $(Symbol(fname, :_linkinds))(M::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), linkinds, M) + $(Symbol(fname, :_linkinds!))(M::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), linkinds, M) + $(Symbol(fname, :_common_siteinds))(M1::AbstractMPS, M2::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), siteinds, commoninds, M1, M2) + $(Symbol(fname, :_common_siteinds!))(M1::AbstractMPS, M2::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), siteinds, commoninds, M1, M2) + $(Symbol(fname, :_unique_siteinds))(M1::AbstractMPS, M2::AbstractMPS, args...; kwargs...) = + map(i -> $fname(i, args...; kwargs...), siteinds, uniqueinds, M1, M2) + $(Symbol(fname, :_unique_siteinds!))(M1::AbstractMPS, M2::AbstractMPS, args...; kwargs...) = + map!(i -> $fname(i, args...; kwargs...), siteinds, uniqueinds, M1, M2) + end +end + diff --git a/src/mps/mpo.jl b/src/mps/mpo.jl index 3e4c965e02..8f606d863e 100644 --- a/src/mps/mpo.jl +++ b/src/mps/mpo.jl @@ -152,7 +152,7 @@ Get a Vector of IndexSets of all the site indices of M. siteinds(M::MPO; kwargs...) = siteinds(all, M; kwargs...) siteinds(Mψ::Tuple{MPO, MPS}, n::Int; kwargs...) = - unique_siteinds(Mψ[1], Mψ[2], n; kwargs...) + siteinds(uniqueinds, Mψ[1], Mψ[2], n; kwargs...) function nsites(Mψ::Tuple{MPO, MPS}) M, ψ = Mψ @@ -202,7 +202,7 @@ function dot(y::MPS, A::MPO, x::MPS; N = length(A) check_hascommoninds(siteinds, A, x) ydag = dag(y) - sim_linkinds!(ydag) + sim!(linkinds, ydag) if !hassameinds(siteinds, y, (A, x)) sAx = siteinds((A, x)) if any(s -> length(s) > 1, sAx) @@ -220,9 +220,8 @@ function dot(y::MPS, A::MPO, x::MPS; if make_inds_match replace_siteinds!(ydag, sAx) end - else - check_hascommoninds(siteinds, A, y) end + check_hascommoninds(siteinds, A, y) O = ydag[1] * A[1] * x[1] for j in 2:N O = O * ydag[j] * A[j] * x[j] @@ -402,21 +401,21 @@ function _contract_densitymatrix(A::MPO, ψ::MPS; kwargs...)::MPS mindim::Int = max(get(kwargs,:mindim,1), 1) normalize::Bool = get(kwargs, :normalize, false) - any(i -> isnothing(i), common_siteinds(A, ψ)) && error("In `contract(A::MPO, x::MPS)`, `A` and `x` must share a set of site indices") + any(i -> isempty(i), siteinds(commoninds, A, ψ)) && error("In `contract(A::MPO, x::MPS)`, `A` and `x` must share a set of site indices") # In case A and ψ have the same link indices - A = sim_linkinds(A) + A = sim(linkinds, A) ψ_c = dag(ψ) A_c = dag(A) # To not clash with the link indices of A and ψ - sim_linkinds!(A_c) - sim_linkinds!(ψ_c) - sim_common_siteinds!(A_c, ψ_c) + sim!(linkinds, A_c) + sim!(linkinds, ψ_c) + sim!(siteinds, commoninds, A_c, ψ_c) # A version helpful for making the density matrix - simA_c = sim_unique_siteinds(A_c, ψ_c) + simA_c = sim(siteinds, uniqueinds, A_c, ψ_c) # Store the left environment tensors E = Vector{ITensor}(undef, n-1) @@ -430,26 +429,23 @@ function _contract_densitymatrix(A::MPO, ψ::MPS; kwargs...)::MPS ρ = E[n-1] * R * simR_c l = linkind(ψ, n-1) ts = isnothing(l) ? "" : tags(l) - s = unique_siteind(A, ψ, n) - s̃ = unique_siteind(simA_c, ψ_c, n) - Lis = IndexSet(s) - Ris = IndexSet(s̃) - F = eigen(ρ, Lis, Ris; ishermitian=true, - tags=ts, - kwargs...) + Lis = siteinds(uniqueinds, A, ψ, n) + Ris = siteinds(uniqueinds, simA_c, ψ_c, n) + F = eigen(ρ, Lis, Ris; ishermitian = true, + tags = ts, kwargs...) D, U, Ut = F.D, F.V, F.Vt l_renorm, r_renorm = F.l, F.r ψ_out[n] = Ut R = R * dag(Ut) * ψ[n-1] * A[n-1] simR_c = simR_c * U * ψ_c[n-1] * simA_c[n-1] for j in reverse(2:n-1) - s = unique_siteind(A, ψ, j) - s̃ = unique_siteind(simA_c, ψ_c, j) + s = siteinds(uniqueinds, A, ψ, j) + s̃ = siteinds(uniqueinds, simA_c, ψ_c, j) ρ = E[j-1] * R * simR_c l = linkind(ψ, j-1) ts = isnothing(l) ? "" : tags(l) - Lis = IndexSet(s, l_renorm) - Ris = IndexSet(s̃, r_renorm) + Lis = IndexSet(s..., l_renorm) + Ris = IndexSet(s̃..., r_renorm) F = eigen(ρ, Lis, Ris; ishermitian=true, tags=ts, kwargs...) diff --git a/test/indexset.jl b/test/indexset.jl index 275c120acd..865c93a73b 100644 --- a/test/indexset.jl +++ b/test/indexset.jl @@ -258,11 +258,74 @@ using Compat end @testset "broadcasting" begin - I = IndexSet(i, j) + x = Index([QN(n) => 1 for n in 0:1], "x") + y = Index([QN(n) => 2 for n in 0:1], "y") + I = IndexSet(x, y) + + # prime J = prime.(I) - @test J isa IndexSet - @test i' ∈ J - @test j' ∈ J + @inferred broadcast(prime, I) + @test J isa IndexSet{2} + @test x' ∈ J + @test y' ∈ J + + # prime 2 + J = prime.(I, 2) + @inferred broadcast(prime, I, 2) + @test J isa IndexSet{2} + @test x'' ∈ J + @test y'' ∈ J + + # tag + J = addtags.(I, "t") + @inferred broadcast(addtags, I, "t") + @test J isa IndexSet{2} + @test addtags(x, "t") ∈ J + @test addtags(y, "t") ∈ J + + # dag + J = dag.(I) + @inferred broadcast(dag, I) + @test J isa IndexSet{2} + @test x ∈ J + @test y ∈ J + @test dir(J[1]) == -dir(I[1]) + @test dir(J[2]) == -dir(I[2]) + + # dir + dirsI = dir.(I) + @inferred broadcast(dir, I) + @test dirsI isa Tuple{ITensors.Arrow,ITensors.Arrow} + @test dirsI == (ITensors.Out, ITensors.Out) + + # dims + dimsI = dim.(I) + @inferred broadcast(dim, I) + @test dimsI isa Tuple{Int, Int} + @test dimsI == (2, 4) + + # pairs + J = prime.(I) + pairsI = I .=> J + @inferred broadcast(=>, I, J) + @test pairsI isa Tuple{<:Pair, <:Pair} + @test pairsI == (x => x', y => y') + + pairsI = I .=> 1 + @inferred broadcast(=>, I, 1) + @test pairsI isa Tuple{<:Pair, <:Pair} + @test pairsI == (x => 1, y => 1) + + pairsI = I .=> (1, 2) + @inferred broadcast(=>, I, (1, 2)) + @test pairsI isa Tuple{<:Pair, <:Pair} + @test pairsI == (x => 1, y => 2) + + pairsI = I .=> [1, 2] + @inferred broadcast(=>, I, [1, 2]) + @test pairsI isa Vector{<:Pair} + @test pairsI == [x => 1, y => 2] + end end diff --git a/test/mpo.jl b/test/mpo.jl index 2a166e6d5e..beca3a041d 100644 --- a/test/mpo.jl +++ b/test/mpo.jl @@ -61,7 +61,7 @@ end @testset "norm MPO" begin A = randomMPO(sites) - Adag = ITensors.sim_linkinds(dag(A)) + Adag = sim(linkinds, dag(A)) A² = ITensor(1) for j = 1:N A² *= Adag[j] * A[j] @@ -79,7 +79,7 @@ end for j in 1:N A[j] .*= j end - Adag = ITensors.sim_linkinds(dag(A)) + Adag = sim(linkinds, dag(A)) A² = ITensor(1) for j = 1:N A² *= Adag[j] * A[j] diff --git a/test/mps.jl b/test/mps.jl index 14ffba8aa2..82cefe1721 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -173,7 +173,7 @@ include(joinpath(pkgdir(ITensors), "examples", "gate_evolution", "qubit.jl")) @testset "norm MPS" begin psi = randomMPS(sites,10) - psidag = ITensors.sim_linkinds(dag(psi)) + psidag = sim(linkinds, dag(psi)) psi² = ITensor(1) for j = 1:N psi² *= psidag[j] * psi[j] @@ -191,7 +191,7 @@ include(joinpath(pkgdir(ITensors), "examples", "gate_evolution", "qubit.jl")) for j in 1:N psi[j] .*= j end - psidag = ITensors.sim_linkinds(dag(psi)) + psidag = sim(linkinds, dag(psi)) psi² = ITensor(1) for j = 1:N psi² *= psidag[j] * psi[j] @@ -633,16 +633,16 @@ end @testset "[first]siteind[s](::MPS/MPO, j::Int)" begin s = siteinds("S=1/2", 5) ψ = randomMPS(s) - @test firstsiteind(ψ, 3) == s[3] + @test siteind(first, ψ, 3) == s[3] @test siteind(ψ, 4) == s[4] @test isnothing(siteind(ψ, 4; plev = 1)) @test siteinds(ψ, 3) == IndexSet(s[3]) @test siteinds(ψ, 3; plev = 1) == IndexSet() M = randomMPO(s) - @test noprime(firstsiteind(M, 4)) == s[4] - @test firstsiteind(M, 4; plev = 0) == s[4] - @test firstsiteind(M, 4; plev = 1) == s[4]' + @test noprime(siteind(first, M, 4)) == s[4] + @test siteind(first, M, 4; plev = 0) == s[4] + @test siteind(first, M, 4; plev = 1) == s[4]' @test siteind(M, 4) == s[4] @test siteind(M, 4; plev = 0) == s[4] @test siteind(M, 4; plev = 1) == s[4]'