Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fa91804
add styles
AFeuerpfeil Nov 12, 2025
1334fcb
start rewrite
AFeuerpfeil Nov 12, 2025
140005f
start defining the styles
AFeuerpfeil Nov 13, 2025
bd6ccdf
implement styles for states and operators and add tests
AFeuerpfeil Nov 14, 2025
5be03c3
Merge pull request #1 from AFeuerpfeil/pr-mpo-styles
AFeuerpfeil Nov 14, 2025
0896113
add include styles
AFeuerpfeil Nov 14, 2025
6350c96
fix InfiniteMPO test
AFeuerpfeil Nov 14, 2025
50793bf
dispatch styles on type and rename IsfiniteStyle to GeometryStyle
AFeuerpfeil Nov 14, 2025
7226788
readd Base.isfinite for AbstractMPS, MPO and MPOHamiltonian
AFeuerpfeil Nov 14, 2025
c206de8
add tests for styles of types
AFeuerpfeil Nov 14, 2025
07f579c
fix include order
AFeuerpfeil Nov 14, 2025
d278a3a
fix OperatorStyle for MPOHamiltonian
AFeuerpfeil Nov 14, 2025
ea5366c
Add WindowStyle and increase code coverage
AFeuerpfeil Nov 14, 2025
18b5ef2
fix test and hopefully also runic
AFeuerpfeil Nov 14, 2025
5af3060
more tests
AFeuerpfeil Nov 14, 2025
8f72c21
fix other tests
AFeuerpfeil Nov 14, 2025
9b7905c
make GeometryStyle names more descriptive
AFeuerpfeil Nov 15, 2025
bb74ee8
implement changes
AFeuerpfeil Nov 15, 2025
692f895
remove unnecessary Base.isfinite definitions, because it is already d…
AFeuerpfeil Nov 15, 2025
38db5da
fix braille tests
AFeuerpfeil Nov 15, 2025
5d1f975
addd
AFeuerpfeil Nov 17, 2025
abcf6a6
revert unnecessary changes
AFeuerpfeil Nov 17, 2025
0718f63
update style docs
lkdvos Nov 17, 2025
ffc50d5
fix formatting
lkdvos Nov 17, 2025
776748b
more formatting
lkdvos Nov 17, 2025
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
1 change: 1 addition & 0 deletions src/MPSKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ include("utility/multiline.jl")
include("utility/utility.jl") # random utility functions
include("utility/plotting.jl")
include("utility/linearcombination.jl")
include("utility/styles.jl")

# maybe we should introduce an abstract state type
include("states/abstractmps.jl")
Expand Down
1 change: 0 additions & 1 deletion src/operators/abstractmpo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ abstract type AbstractMPO{O} <: AbstractVector{O} end

# useful union types
const SparseMPO{O <: SparseBlockTensorMap} = AbstractMPO{O}
Base.isfinite(O::AbstractMPO) = isfinite(typeof(O))

# By default, define things in terms of parent
Base.size(mpo::AbstractMPO, args...) = size(parent(mpo), args...)
Expand Down
4 changes: 4 additions & 0 deletions src/operators/mpo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ end
Matrix Product Operator (MPO) acting on a finite tensor product space with a linear order.
"""
const FiniteMPO{O} = MPO{O, Vector{O}}
Base.isfinite(O::MPO) = isfinite(typeof(O))
Base.isfinite(::Type{<:FiniteMPO}) = true
GeometryStyle(::Type{<:FiniteMPO}) = FiniteStyle()
OperatorStyle(::Type{<:MPO}) = MPOStyle()

function FiniteMPO(Os::AbstractVector{O}) where {O}
for i in eachindex(Os)[1:(end - 1)]
Expand All @@ -37,6 +40,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
GeometryStyle(::Type{<:InfiniteMPO}) = InfiniteStyle()

function InfiniteMPO(Os::AbstractVector{O}) where {O}
for i in eachindex(Os)
Expand Down
4 changes: 4 additions & 0 deletions src/operators/mpohamiltonian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ operators in a form that is compatible with this constructor.
struct MPOHamiltonian{TO <: JordanMPOTensor, V <: AbstractVector{TO}} <: AbstractMPO{TO}
W::V
end
Base.isfinite(mpo::MPOHamiltonian) = isfinite(typeof(mpo))
OperatorStyle(::MPOHamiltonian) = HamiltonianStyle()

const FiniteMPOHamiltonian{O <: MPOTensor} = MPOHamiltonian{O, Vector{O}}
Base.isfinite(::Type{<:FiniteMPOHamiltonian}) = true
GeometryStyle(::Type{<:FiniteMPOHamiltonian}) = FiniteStyle()

function FiniteMPOHamiltonian(Ws::AbstractVector{O}) where {O <: MPOTensor}
for i in eachindex(Ws)[1:(end - 1)]
Expand All @@ -45,6 +48,7 @@ end

const InfiniteMPOHamiltonian{O <: MPOTensor} = MPOHamiltonian{O, PeriodicVector{O}}
Base.isfinite(::Type{<:InfiniteMPOHamiltonian}) = false
GeometryStyle(::Type{<:InfiniteMPOHamiltonian}) = InfiniteStyle()

function InfiniteMPOHamiltonian(Ws::AbstractVector{O}) where {O <: MPOTensor}
for i in eachindex(Ws)
Expand Down
5 changes: 3 additions & 2 deletions src/states/abstractmps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -173,6 +173,7 @@ abstract type AbstractFiniteMPS <: AbstractMPS end

Base.eltype(ψ::AbstractMPS) = eltype(typeof(ψ))
VectorInterface.scalartype(T::Type{<:AbstractMPS}) = scalartype(site_type(T))
Base.isfinite(ψ::AbstractMPS) = isfinite(typeof(ψ))

function Base.checkbounds(ψ::AbstractMPS, i)
return Base.checkbounds(Bool, ψ, i) || throw(BoundsError(ψ, i))
Expand Down Expand Up @@ -201,7 +202,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
Expand Down
3 changes: 2 additions & 1 deletion src/states/finitemps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ function Base.similar(ψ::FiniteMPS{A, B}) where {A, B}
return FiniteMPS{A, B}(similar(ψ.ALs), similar(ψ.ARs), similar(ψ.ACs), similar(ψ.Cs))
end

Base.isfinite(ψ::FiniteMPS) = true
Base.isfinite(::Type{<:FiniteMPS}) = true
GeometryStyle(::Type{<:FiniteMPS}) = FiniteStyle()

Base.eachindex(ψ::FiniteMPS) = eachindex(ψ.AL)
Base.eachindex(l::IndexStyle, ψ::FiniteMPS) = eachindex(l, ψ.AL)
Expand Down
3 changes: 2 additions & 1 deletion src/states/infinitemps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ Base.size(ψ::InfiniteMPS, args...) = size(ψ.AL, args...)
Base.length(ψ::InfiniteMPS) = length(ψ.AL)
Base.eltype(ψ::InfiniteMPS) = eltype(typeof(ψ))
Base.eltype(::Type{<:InfiniteMPS{A}}) where {A} = A
Base.isfinite(ψ::InfiniteMPS) = false
Base.isfinite(::Type{<:InfiniteMPS}) = false
GeometryStyle(::Type{<:InfiniteMPS}) = InfiniteStyle()

Base.copy(ψ::InfiniteMPS) = InfiniteMPS(copy(ψ.AL), copy(ψ.AR), copy(ψ.C), copy(ψ.AC))
function Base.copy!(ψ::InfiniteMPS, ϕ::InfiniteMPS)
Expand Down
2 changes: 1 addition & 1 deletion src/states/multilinemps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Base.convert(::Type{InfiniteMPS}, st::MultilineMPS) = only(st)
Base.eltype(t::MultilineMPS) = eltype(t[1])
Base.copy!(ψ::MultilineMPS, ϕ::MultilineMPS) = (copy!.(parent(ψ), parent(ϕ)); ψ)

Base.isfinite(ψ::MultilineMPS) = false
Base.isfinite(::Type{<:MultilineMPS}) = false

for f_space in (:physicalspace, :left_virtualspace, :right_virtualspace)
@eval $f_space(t::MultilineMPS, i::Int, j::Int) = $f_space(t[i], j)
Expand Down
3 changes: 3 additions & 0 deletions src/states/quasiparticle_state.jl
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ 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}

GeometryStyle(::Type{<:QP{S, T1, T2}}) where {S, T1, T2} = GeometryStyle(S)

TensorKit.spacetype(::Union{QP{S}, Type{<:QP{S}}}) where {S} = spacetype(S)
TensorKit.sectortype(::Union{QP{S}, Type{<:QP{S}}}) where {S} = sectortype(S)

Expand Down
6 changes: 6 additions & 0 deletions src/utility/multiline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ function Base.repeat(A::Multiline, rows::Int, cols::Int)
return Multiline(outer)
end

# Style
# ----------------

OperatorStyle(::Type{Multiline{T}}) where {T} = OperatorStyle(T)
GeometryStyle(::Type{Multiline{T}}) where {T} = GeometryStyle(T)

# VectorInterface
# ---------------
VectorInterface.scalartype(::Type{Multiline{T}}) where {T} = scalartype(T)
Expand Down
42 changes: 42 additions & 0 deletions src/utility/styles.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
`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
OperatorStyle(x) = OperatorStyle(typeof(x))
OperatorStyle(T::Type) = throw(MethodError(OperatorStyle, T)) # avoid stackoverflow if not defined

struct MPOStyle <: OperatorStyle end
struct HamiltonianStyle <: OperatorStyle end


"""
`GeometryStyle`

Holy trait used as a dispatch tag to distinguish between different
geometry (currently finite and infinite). Concrete subtypes
(`FiniteStyle` and `InfiniteStyle`) indicate whether a system is
finite or infinite. Use `GeometryStyle` in method signatures to
select implementation-specific code paths for different types.

To opt a custom type into this dispatch scheme implement:
```julia
GeometryStyle(::T) where {T<:YourType}
```
"""
abstract type GeometryStyle end
GeometryStyle(x) = GeometryStyle(typeof(x))
GeometryStyle(T::Type) = throw(MethodError(GeometryStyle, T)) # avoid stackoverflow if not defined

struct FiniteStyle <: GeometryStyle end
struct InfiniteStyle <: GeometryStyle end
40 changes: 40 additions & 0 deletions test/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module TestOperators
using MPSKit
using MPSKit: _transpose_front, _transpose_tail, C_hamiltonian, AC_hamiltonian,
AC2_hamiltonian
using MPSKit: GeometryStyle, FiniteStyle, InfiniteStyle, OperatorStyle, MPOStyle,
HamiltonianStyle
using TensorKit
using TensorKit: ℙ
using VectorInterface: One
Expand All @@ -32,6 +34,14 @@ module TestOperators
mpo₂ = FiniteMPO(O₂)
mpo₃ = FiniteMPO(O₃)

@test isfinite(mpo₁)
@test isfinite(typeof(mpo₁))
@test GeometryStyle(typeof(mpo₁)) == FiniteStyle()
@test GeometryStyle(mpo₁) == FiniteStyle()
@test OperatorStyle(typeof(mpo₁)) == MPOStyle()
@test OperatorStyle(mpo₁) == MPOStyle()


@test @constinferred physicalspace(mpo₁) == fill(V, L)
Vleft = @constinferred left_virtualspace(mpo₁)
Vright = @constinferred right_virtualspace(mpo₂)
Expand Down Expand Up @@ -81,6 +91,22 @@ module TestOperators
end
end

@testset "InfiniteMPO" begin
P = ℂ^2
T = Float64

H1 = randn(T, P ← P)
H1 += H1'
H = InfiniteMPO([H1])

@test !isfinite(H)
@test !isfinite(typeof(H))
@test GeometryStyle(typeof(H)) == InfiniteStyle()
@test GeometryStyle(H) == InfiniteStyle()
@test OperatorStyle(typeof(H)) == MPOStyle()
@test OperatorStyle(H) == MPOStyle()
end

@testset "MPOHamiltonian constructors" begin
P = ℂ^2
T = Float64
Expand Down Expand Up @@ -109,6 +135,13 @@ module TestOperators
H′ = FiniteMPOHamiltonian(map(Base.Fix1(collect, Any), Ws)) # without type info
@test H ≈ H′

@test isfinite(H)
@test isfinite(typeof(H))
@test GeometryStyle(typeof(H)) == FiniteStyle()
@test GeometryStyle(H) == FiniteStyle()
@test OperatorStyle(typeof(H)) == HamiltonianStyle()
@test OperatorStyle(H) == HamiltonianStyle()

# Infinite
Ws = [Wmid]
H = InfiniteMPOHamiltonian(
Expand All @@ -119,6 +152,13 @@ module TestOperators

H′ = InfiniteMPOHamiltonian(map(Base.Fix1(collect, Any), Ws)) # without type info
@test all(parent(H) .≈ parent(H′))

@test !isfinite(H)
@test !isfinite(typeof(H))
@test GeometryStyle(typeof(H)) == InfiniteStyle()
@test GeometryStyle(H) == InfiniteStyle()
@test OperatorStyle(typeof(H)) == HamiltonianStyle()
@test OperatorStyle(H) == HamiltonianStyle()
end

@testset "Finite MPOHamiltonian" begin
Expand Down
14 changes: 14 additions & 0 deletions test/states.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module TestStates
using Test, TestExtras
using MPSKit
using MPSKit: _transpose_front, _transpose_tail
using MPSKit: GeometryStyle, FiniteStyle, InfiniteStyle
using MPSKit: TransferMatrix
using TensorKit
using TensorKit: ℙ
Expand All @@ -25,6 +26,9 @@ module TestStates
ψ = FiniteMPS(rand, elt, L, d, D)

@test isfinite(ψ)
@test isfinite(typeof(ψ))
@test GeometryStyle(typeof(ψ)) == FiniteStyle()
@test GeometryStyle(ψ) == FiniteStyle()
@test @constinferred physicalspace(ψ) == fill(d, L)
@test all(x -> x ≾ D, @constinferred left_virtualspace(ψ))
@test all(x -> x ≾ D, @constinferred right_virtualspace(ψ))
Expand Down Expand Up @@ -100,7 +104,11 @@ module TestStates

ψ = InfiniteMPS([rand(elt, D * d, D), rand(elt, D * d, D)]; tol)

@test !isfinite(typeof(ψ))
@test !isfinite(ψ)
@test GeometryStyle(typeof(ψ)) == InfiniteStyle()
@test GeometryStyle(ψ) == InfiniteStyle()

@test physicalspace(ψ) == fill(d, 2)
@test all(x -> x ≾ D, left_virtualspace(ψ))
@test all(x -> x ≾ D, right_virtualspace(ψ))
Expand Down Expand Up @@ -231,6 +239,9 @@ module TestStates
ϕ₁ = LeftGaugedQP(rand, ψ)
ϕ₂ = LeftGaugedQP(rand, ψ)

@test GeometryStyle(ϕ₁) == FiniteStyle()
@test GeometryStyle(typeof(ϕ₂)) == FiniteStyle()

@test @constinferred physicalspace(ϕ₁) == physicalspace(ψ)
@test @constinferred left_virtualspace(ϕ₁) == left_virtualspace(ψ)
@test @constinferred right_virtualspace(ϕ₁) == right_virtualspace(ψ)
Expand Down Expand Up @@ -266,6 +277,9 @@ module TestStates
ϕ₁ = LeftGaugedQP(rand, ψ)
ϕ₂ = LeftGaugedQP(rand, ψ)

@test GeometryStyle(ϕ₁) == InfiniteStyle()
@test GeometryStyle(typeof(ϕ₂)) == InfiniteStyle()

@test @constinferred physicalspace(ϕ₁) == physicalspace(ψ)
@test @constinferred left_virtualspace(ϕ₁) == left_virtualspace(ψ)
@test @constinferred right_virtualspace(ϕ₁) == right_virtualspace(ψ)
Expand Down
Loading