diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 83647881f..d7fd0da07 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -120,6 +120,7 @@ include("operators/projection.jl") include("operators/timedependence.jl") include("operators/multipliedoperator.jl") include("operators/lazysum.jl") +include("operators/show.jl") include("transfermatrix/transfermatrix.jl") include("transfermatrix/transfer.jl") diff --git a/src/operators/abstractmpo.jl b/src/operators/abstractmpo.jl index 550f674d5..5ea9ca739 100644 --- a/src/operators/abstractmpo.jl +++ b/src/operators/abstractmpo.jl @@ -82,80 +82,6 @@ function remove_orphans!(mpo::SparseMPO; tol=eps(real(scalartype(mpo)))^(3 / 4)) return mpo end -# Show -# ---- -function Base.show(io::IO, ::MIME"text/plain", W::AbstractMPO) - L = length(W) - println(io, L == 1 ? "single site " : "$L-site ", typeof(W), ":") - context = IOContext(io, :typeinfo => eltype(W), :compact => true) - return show(context, W) -end - -Base.show(io::IO, mpo::AbstractMPO) = show(convert(IOContext, io), mpo) -function Base.show(io::IOContext, mpo::AbstractMPO) - charset = (; top="┬", bot="┴", mid="┼", ver="│", dash="──") - limit = get(io, :limit, false)::Bool - half_screen_rows = limit ? div(displaysize(io)[1] - 8, 2) : typemax(Int) - L = length(mpo) - - # used to align all mposite infos regardless of the length of the mpo (100 takes up more space than 5) - npad = floor(Int, log10(L)) - mpoletter = mpo isa MPOHamiltonian ? "W" : "O" - isfinite = (mpo isa FiniteMPO) || (mpo isa FiniteMPOHamiltonian) - - !isfinite && println(io, "╷ ⋮") - for site in reverse(1:L) - if site < half_screen_rows || site > L - half_screen_rows - if site == L && isfinite - println(io, charset.top, " $mpoletter[$site]: ", - repeat(" ", npad - floor(Int, log10(site))), mpo[site]) - elseif (site == 1) && isfinite - println(io, charset.bot, " $mpoletter[$site]: ", - repeat(" ", npad - floor(Int, log10(site))), mpo[site]) - else - println(io, charset.mid, " $mpoletter[$site]: ", - repeat(" ", npad - floor(Int, log10(site))), mpo[site]) - end - elseif site == half_screen_rows - println(io, " ", "⋮") - end - end - !isfinite && println(io, "╵ ⋮") - return nothing -end - -function braille(H::SparseMPO) - isfinite = (H isa FiniteMPO) || (H isa FiniteMPOHamiltonian) - dash = "🭻" - stride = 2 #amount of dashes between braille - L = length(H) - - brailles = Vector{Vector{String}}(undef, L) - buffer = IOBuffer() - for (i, W) in enumerate(H) - BlockTensorKit.show_braille(buffer, W) - brailles[i] = split(String(take!(buffer))) - end - - maxheight = maximum(length.(brailles)) - - for i in 1:maxheight - line = "" - line *= ((i == 1 && !isfinite) ? ("... " * dash) : " ") - line *= (i > 1 && !isfinite) ? " " : "" - for (j, braille) in enumerate(brailles) - line *= (checkbounds(Bool, braille, i) ? braille[i] : - repeat(" ", length(braille[1]))) - if j < L - line *= repeat(((i == 1) ? dash : " "), stride) - end - end - line *= ((i == 1 && !isfinite) ? (dash * " ...") : " ") - println(line) - end - return nothing -end - # Linear Algebra # -------------- Base.:+(mpo::AbstractMPO) = scale(mpo, One()) diff --git a/src/operators/show.jl b/src/operators/show.jl new file mode 100644 index 000000000..b3b74dff5 --- /dev/null +++ b/src/operators/show.jl @@ -0,0 +1,90 @@ +# AbstractMPO +# ----------- +function Base.show(io::IO, ::MIME"text/plain", W::AbstractMPO) + L = length(W) + println(io, L == 1 ? "single site " : "$L-site ", typeof(W), ":") + context = IOContext(io, :typeinfo => eltype(W), :compact => true) + return show(context, W) +end + +Base.show(io::IO, mpo::AbstractMPO) = show(convert(IOContext, io), mpo) +function Base.show(io::IOContext, mpo::AbstractMPO) + charset = (; top="┬", bot="┴", mid="┼", ver="│", dash="──") + limit = get(io, :limit, false)::Bool + half_screen_rows = limit ? div(displaysize(io)[1] - 8, 2) : typemax(Int) + L = length(mpo) + + # used to align all mposite infos regardless of the length of the mpo (100 takes up more space than 5) + npad = floor(Int, log10(L)) + mpoletter = mpo isa MPOHamiltonian ? "W" : "O" + isfinite = (mpo isa FiniteMPO) || (mpo isa FiniteMPOHamiltonian) + + !isfinite && println(io, "╷ ⋮") + for site in reverse(1:L) + if site < half_screen_rows || site > L - half_screen_rows + if site == L && isfinite + println(io, charset.top, " $mpoletter[$site]: ", + repeat(" ", npad - floor(Int, log10(site))), mpo[site]) + elseif (site == 1) && isfinite + println(io, charset.bot, " $mpoletter[$site]: ", + repeat(" ", npad - floor(Int, log10(site))), mpo[site]) + else + println(io, charset.mid, " $mpoletter[$site]: ", + repeat(" ", npad - floor(Int, log10(site))), mpo[site]) + end + elseif site == half_screen_rows + println(io, " ", "⋮") + end + end + !isfinite && println(io, "╵ ⋮") + return nothing +end + +# braille +# ------- +""" + braille(io::IO, H::Union{SparseMPO, MPOHamiltonian}) + braille(H::Union{SparseMPO, MPOHamiltonian}) + +Prints a compact, human-readable "braille" visualization of a sparseMPO or MPOHamiltonian. +Each site of the MPO is represented as a block of Unicode braille characters, with sites separated by dashes. +This visualization is useful for quickly inspecting the structure and sparsity pattern of MPOs. + +# Arguments +- `io::IO`: The output stream to print to (e.g., `stdout`). +- `H::Union{SparseMPO, MPOHamiltonian}`: The `SparseMPO` or `MPOHamiltonian` to visualize. + +If called without an `io` argument, output is printed to `stdout`. +""" +function braille(io::IO, H::Union{SparseMPO,MPOHamiltonian}) + dash = "🭻" + stride = 2 #amount of dashes between braille + L = length(H) + + brailles = Vector{Vector{String}}(undef, L) + buffer = IOBuffer() + for (i, W) in enumerate(H) + BlockTensorKit.show_braille(buffer, W) + brailles[i] = split(String(take!(buffer))) + end + + maxheight = maximum(length.(brailles)) + + for i in 1:maxheight + line = "" + line *= ((i == 1 && !isfinite(H)) ? ("... " * dash) : " ") + line *= (i > 1 && !isfinite(H)) ? " " : "" + for (j, braille) in enumerate(brailles) + line *= (checkbounds(Bool, braille, i) ? braille[i] : + repeat(" ", length(braille[1]))) + if j < L + line *= repeat(((i == 1) ? dash : " "), stride) + end + end + line *= ((i == 1 && !isfinite(H)) ? (dash * " ...") : " ") + println(io, line) + end + return nothing +end + +braille(H::Union{SparseMPO,MPOHamiltonian}) = braille(stdout, H) diff --git a/test/other.jl b/test/other.jl index 658c2fd93..0306f1888 100644 --- a/test/other.jl +++ b/test/other.jl @@ -63,4 +63,34 @@ end end end +@testset "braille" begin + # Infinite Hamiltonians and MPOs + # ------------------------------- + H = transverse_field_ising() + buffer = IOBuffer() + braille(buffer, H) + output = String(take!(buffer)) + check = "... 🭻⎡⠉⢀⎤🭻 ...\n ⎣⠀⢀⎦ \n" + @test output == check + + O = make_time_mpo(H, 1.0, TaylorCluster(3, false, false)) + braille(buffer, O) + output = String(take!(buffer)) + check = "... 🭻⎡⡏⠉⠒⠔⎤🭻 ...\n ⎣⡇⠀⠀⡂⎦ \n" + @test output == check + + # Finite Hamiltonians and MPOs + # ---------------------------- + H = transverse_field_ising(; L=4) + braille(buffer, H) + output = String(take!(buffer)) + check = " ⎡⠉⠀⎤🭻🭻⎡⠉⢀⎤🭻🭻⎡⠉⢀⎤🭻🭻⎡⡀⠀⎤ \n ⎣⠀⠀⎦ ⎣⠀⢀⎦ ⎣⠀⢀⎦ ⎣⡀⠀⎦ \n" + @test output == check + + O = make_time_mpo(H, 1.0, TaylorCluster(3, false, false)) + braille(buffer, O) + output = String(take!(buffer)) + check = " ⎡⠉⠉⎤🭻🭻⎡⠍⠉⠤⠠⎤🭻🭻⎡⡏⠉⠒⠔⎤🭻🭻⎡⡇⠀⎤ \n ⎣⠀⠀⎦ ⎣⡂⠀⠀⠂⎦ ⎣⡇⠀⠀⡂⎦ ⎣⡇⠀⎦ \n" + @test output == check +end end