diff --git a/src/operators/mpo.jl b/src/operators/mpo.jl index ae16181fd..a8963c858 100644 --- a/src/operators/mpo.jl +++ b/src/operators/mpo.jl @@ -17,6 +17,8 @@ Matrix Product Operator (MPO) acting on a finite tensor product space with a lin """ const FiniteMPO{O} = MPO{O, Vector{O}} Base.isfinite(::Type{<:FiniteMPO}) = true +IsfiniteStyle(::FiniteMPO) = FiniteStyle() +OperatorStyle(::MPO) = MPOStyle() function FiniteMPO(Os::AbstractVector{O}) where {O} for i in eachindex(Os)[1:(end - 1)] @@ -37,6 +39,7 @@ Matrix Product Operator (MPO) acting on an infinite tensor product space with a """ const InfiniteMPO{O} = MPO{O, PeriodicVector{O}} Base.isfinite(::Type{<:InfiniteMPO}) = false +IsfiniteStyle(::InfiniteMPO) = InfiniteStyle() function InfiniteMPO(Os::AbstractVector{O}) where {O} for i in eachindex(Os) diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index 97f938609..9f2218968 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -31,9 +31,11 @@ operators in a form that is compatible with this constructor. struct MPOHamiltonian{TO <: JordanMPOTensor, V <: AbstractVector{TO}} <: AbstractMPO{TO} W::V end +OperatorStyle(::MPOHamiltonian) = HamiltonianStyle() const FiniteMPOHamiltonian{O <: MPOTensor} = MPOHamiltonian{O, Vector{O}} Base.isfinite(::Type{<:FiniteMPOHamiltonian}) = true +IsfiniteStyle(::FiniteMPOHamiltonian) = FiniteStyle() function FiniteMPOHamiltonian(Ws::AbstractVector{O}) where {O <: MPOTensor} for i in eachindex(Ws)[1:(end - 1)] @@ -45,6 +47,7 @@ end const InfiniteMPOHamiltonian{O <: MPOTensor} = MPOHamiltonian{O, PeriodicVector{O}} Base.isfinite(::Type{<:InfiniteMPOHamiltonian}) = false +IsfiniteStyle(::InfiniteMPOHamiltonian) = InfiniteStyle() function InfiniteMPOHamiltonian(Ws::AbstractVector{O}) where {O <: MPOTensor} for i in eachindex(Ws) diff --git a/src/states/abstractmps.jl b/src/states/abstractmps.jl index 6dd8a1341..0503a33be 100644 --- a/src/states/abstractmps.jl +++ b/src/states/abstractmps.jl @@ -15,7 +15,7 @@ const MPSTensor{S} = GenericMPSTensor{S, 2} # the usual mps tensors on which we """ MPSTensor([f, eltype], d::Int, left_D::Int, [right_D]::Int]) - MPSTensor([f, eltype], physicalspace::Union{S,CompositeSpace{S}}, + MPSTensor([f, eltype], physicalspace::Union{S,CompositeSpace{S}}, left_virtualspace::S, [right_virtualspace]::S) where {S<:ElementarySpace} Construct an `MPSTensor` with given physical and virtual spaces. @@ -201,7 +201,7 @@ TensorKit.sectortype(ψtype::Type{<:AbstractMPS}) = sectortype(site_type(ψtype) """ left_virtualspace(ψ::AbstractMPS, [pos=1:length(ψ)]) - + Return the virtual space of the bond to the left of sites `pos`. !!! warning diff --git a/src/states/finitemps.jl b/src/states/finitemps.jl index 44ac3fa64..969201eaf 100644 --- a/src/states/finitemps.jl +++ b/src/states/finitemps.jl @@ -312,6 +312,7 @@ function Base.similar(ψ::FiniteMPS{A, B}) where {A, B} end Base.isfinite(ψ::FiniteMPS) = true +IsfiniteStyle(::FiniteMPS) = FiniteStyle() Base.eachindex(ψ::FiniteMPS) = eachindex(ψ.AL) Base.eachindex(l::IndexStyle, ψ::FiniteMPS) = eachindex(l, ψ.AL) diff --git a/src/states/infinitemps.jl b/src/states/infinitemps.jl index 62c278afb..fbb1ffa4d 100644 --- a/src/states/infinitemps.jl +++ b/src/states/infinitemps.jl @@ -242,6 +242,7 @@ Base.length(ψ::InfiniteMPS) = length(ψ.AL) Base.eltype(ψ::InfiniteMPS) = eltype(typeof(ψ)) Base.eltype(::Type{<:InfiniteMPS{A}}) where {A} = A Base.isfinite(ψ::InfiniteMPS) = false +IsfiniteStyle(::InfiniteMPS) = InfiniteStyle() Base.copy(ψ::InfiniteMPS) = InfiniteMPS(copy(ψ.AL), copy(ψ.AR), copy(ψ.C), copy(ψ.AC)) function Base.copy!(ψ::InfiniteMPS, ϕ::InfiniteMPS) diff --git a/src/states/multilinemps.jl b/src/states/multilinemps.jl index 73f68fac6..38f712fc8 100644 --- a/src/states/multilinemps.jl +++ b/src/states/multilinemps.jl @@ -102,6 +102,7 @@ Base.eltype(t::MultilineMPS) = eltype(t[1]) Base.copy!(ψ::MultilineMPS, ϕ::MultilineMPS) = (copy!.(parent(ψ), parent(ϕ)); ψ) Base.isfinite(ψ::MultilineMPS) = false +IsfiniteStyle(::MultilineMPS) = InfiniteStyle() for f_space in (:physicalspace, :left_virtualspace, :right_virtualspace) @eval $f_space(t::MultilineMPS, i::Int, j::Int) = $f_space(t[i], j) diff --git a/src/states/quasiparticle_state.jl b/src/states/quasiparticle_state.jl index 87dbfc6e7..fd34c7fa0 100644 --- a/src/states/quasiparticle_state.jl +++ b/src/states/quasiparticle_state.jl @@ -208,6 +208,7 @@ end # gauge independent code const QP{S, T1, T2} = Union{LeftGaugedQP{S, T1, T2}, RightGaugedQP{S, T1, T2}} +# TODO: Remove FiniteQP and InfiniteQP in favor of styles. const FiniteQP{S <: FiniteMPS, T1, T2} = QP{S, T1, T2} const InfiniteQP{S <: InfiniteMPS, T1, T2} = QP{S, T1, T2} const MultilineQP{Q <: QP} = Multiline{Q} @@ -228,6 +229,8 @@ eachsite(state::QP) = eachsite(state.left_gs) istopological(qp::QP) = qp.left_gs !== qp.right_gs istrivial(qp::QP) = !istopological(qp) && isone(auxiliarysector(qp)) +IsfiniteStyle(qp::QP) = IsfiniteStyle(qp.left_gs) + Base.copy(a::QP) = copy!(similar(a), a) Base.copyto!(a::QP, b::QP) = copy!(a, b) function Base.copy!(a::T, b::T) where {T <: QP} diff --git a/src/utility/styles.jl b/src/utility/styles.jl index a358facee..f2ab8ad9f 100644 --- a/src/utility/styles.jl +++ b/src/utility/styles.jl @@ -1,9 +1,36 @@ +""" +`OperatorStyle` + +Holy trait used as a dispatch tag for operator representations. +Concrete subtypes (`MPOStyle` and `HamiltonianStyle`) indicate +whether an operator is stored as an MPO or as a Hamiltonian. +Use `OperatorStyle` in method signatures to select implementation- +specific code paths for different operator types. + +To opt a custom operator type into this dispatch scheme implement: +```julia +OperatorStyle(::T) where {T<:YourOperatorType} +``` +""" abstract type OperatorStyle end struct MPOStyle <: OperatorStyle end struct HamiltonianStyle <: OperatorStyle end +""" +`IsfiniteStyle` +Holy trait used as a dispatch tag to distinguish between finite +and infinite types. Concrete subtypes (`FiniteStyle` and +`InfiniteStyle`) indicate whether a system is finite or infinite. +Use `IsfiniteStyle` in method signatures to select implementation- +specific code paths for different types. + +To opt a custom type into this dispatch scheme implement: +```julia +IsfiniteStyle(::T) where {T<:YourType} +``` +""" abstract type IsfiniteStyle end struct FiniteStyle <: IsfiniteStyle end diff --git a/test/operators.jl b/test/operators.jl index 03fadeea4..8b09bbe06 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -10,6 +10,8 @@ module TestOperators using MPSKit using MPSKit: _transpose_front, _transpose_tail, C_hamiltonian, AC_hamiltonian, AC2_hamiltonian + using MPSKit: IsfiniteStyle, FiniteStyle, InfiniteStyle, OperatorStyle, MPOStyle, + HamiltonianStyle using TensorKit using TensorKit: ℙ using VectorInterface: One @@ -32,6 +34,10 @@ module TestOperators mpo₂ = FiniteMPO(O₂) mpo₃ = FiniteMPO(O₃) + @test IsfiniteStyle(mpo₁) == FiniteStyle() + @test OperatorStyle(mpo₁) == MPOStyle() + + @test @constinferred physicalspace(mpo₁) == fill(V, L) Vleft = @constinferred left_virtualspace(mpo₁) Vright = @constinferred right_virtualspace(mpo₂) @@ -81,6 +87,18 @@ module TestOperators end end + @testset "InfiniteMPO" begin + P = ℂ^2 + T = Float64 + + H1 = randn(T, P ← P) + H1 += H1' + H = InfiniteMPO(H1) + + @test IsfiniteStyle(H) == InfiniteStyle() + @test OperatorStyle(H) == MPOStyle() + end + @testset "MPOHamiltonian constructors" begin P = ℂ^2 T = Float64 @@ -109,6 +127,9 @@ module TestOperators H′ = FiniteMPOHamiltonian(map(Base.Fix1(collect, Any), Ws)) # without type info @test H ≈ H′ + @test IsfiniteStyle(H) == FiniteStyle() + @test OperatorStyle(H) == HamiltonianStyle() + # Infinite Ws = [Wmid] H = InfiniteMPOHamiltonian( @@ -119,6 +140,9 @@ module TestOperators H′ = InfiniteMPOHamiltonian(map(Base.Fix1(collect, Any), Ws)) # without type info @test all(parent(H) .≈ parent(H′)) + + @test IsfiniteStyle(H) == InfiniteStyle() + @test OperatorStyle(H) == HamiltonianStyle() end @testset "Finite MPOHamiltonian" begin diff --git a/test/states.jl b/test/states.jl index 7762b844c..b87f07500 100644 --- a/test/states.jl +++ b/test/states.jl @@ -9,6 +9,7 @@ module TestStates using Test, TestExtras using MPSKit using MPSKit: _transpose_front, _transpose_tail + using MPSKit: IsfiniteStyle, FiniteStyle, InfiniteStyle using MPSKit: TransferMatrix using TensorKit using TensorKit: ℙ @@ -25,6 +26,7 @@ module TestStates ψ = FiniteMPS(rand, elt, L, d, D) @test isfinite(ψ) + @test IsfiniteStyle(ψ) == FiniteStyle() @test @constinferred physicalspace(ψ) == fill(d, L) @test all(x -> x ≾ D, @constinferred left_virtualspace(ψ)) @test all(x -> x ≾ D, @constinferred right_virtualspace(ψ)) @@ -101,6 +103,8 @@ module TestStates ψ = InfiniteMPS([rand(elt, D * d, D), rand(elt, D * d, D)]; tol) @test !isfinite(ψ) + @test IsfiniteStyle(ψ) == InfiniteStyle() + @test physicalspace(ψ) == fill(d, 2) @test all(x -> x ≾ D, left_virtualspace(ψ)) @test all(x -> x ≾ D, right_virtualspace(ψ)) @@ -231,6 +235,8 @@ module TestStates ϕ₁ = LeftGaugedQP(rand, ψ) ϕ₂ = LeftGaugedQP(rand, ψ) + @test IsfiniteStyle(ϕ₁) == FiniteStyle() + @test @constinferred physicalspace(ϕ₁) == physicalspace(ψ) @test @constinferred left_virtualspace(ϕ₁) == left_virtualspace(ψ) @test @constinferred right_virtualspace(ϕ₁) == right_virtualspace(ψ) @@ -266,6 +272,8 @@ module TestStates ϕ₁ = LeftGaugedQP(rand, ψ) ϕ₂ = LeftGaugedQP(rand, ψ) + @test IsfiniteStyle(ϕ₁) == InfiniteStyle() + @test @constinferred physicalspace(ϕ₁) == physicalspace(ψ) @test @constinferred left_virtualspace(ϕ₁) == left_virtualspace(ψ) @test @constinferred right_virtualspace(ϕ₁) == right_virtualspace(ψ)