From 1cf22bc94e17e9b6071f8e335759de4761e46e85 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 1 Nov 2025 08:35:22 -0400 Subject: [PATCH 01/20] setup benchmarks --- .../MPSKitBenchmarks/MPSKitBenchmarks.jl | 55 +++++++++++++++++++ benchmark/Project.toml | 8 +++ 2 files changed, 63 insertions(+) create mode 100644 benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl create mode 100644 benchmark/Project.toml diff --git a/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl new file mode 100644 index 000000000..ff4a4e108 --- /dev/null +++ b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl @@ -0,0 +1,55 @@ +module MPSKitBenchmarks + +using BenchmarkTools +using MPSKit +using TOML + +BenchmarkTools.DEFAULT_PARAMETERS.seconds = 20.0 +BenchmarkTools.DEFAULT_PARAMETERS.samples = 10000 +BenchmarkTools.DEFAULT_PARAMETERS.time_tolerance = 0.15 +BenchmarkTools.DEFAULT_PARAMETERS.memory_tolerance = 0.01 + +const PARAMS_PATH = joinpath(@__DIR__, "etc", "params.json") +const SUITE = BenchmarkGroup() +const MODULES = Dict{String, Symbol}( + "derivatives" => :Derivatives +) + +load!(id::AbstractString; kwargs...) = load!(SUITE, id; kwargs...) + +function load!(group::BenchmarkGroup, id::AbstractString; tune::Bool = false) + modsym = MODULES[id] + modpath = joinpath(dirname(@__FILE__), id, "$(modsym).jl") + Core.eval(@__MODULE__, :(include($modpath))) + mod = Core.eval(@__MODULE__, modsym) + modsuite = @invokelatest getglobal(mod, :SUITE) + group[id] = modsuite + if tune + results = BenchmarkTools.load(PARAMS_PATH)[1] + haskey(results, id) && loadparams!(modsuite, results[id], :evals) + end + return group +end + +loadall!(; kwargs...) = loadall!(SUITE; kwargs...) + +function loadall!(group::BenchmarkGroup; verbose::Bool = true, tune::Bool = false) + for id in keys(MODULES) + if verbose + print("loading group $(repr(id))... ") + time = @elapsed load!(group, id, tune = false) + println("done (took $time seconds)") + else + load!(group, id; tune = false) + end + end + if tune + results = BenchmarkTools.load(PARAMS_PATH)[1] + for (id, suite) in group + haskey(results, id) && loadparams!(suite, results[id], :evals) + end + end + return group +end + +end diff --git a/benchmark/Project.toml b/benchmark/Project.toml new file mode 100644 index 000000000..891d982fa --- /dev/null +++ b/benchmark/Project.toml @@ -0,0 +1,8 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" +MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" +TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" From fb2d90cff63d7d813c428a10ea21632c05ddc673 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 1 Nov 2025 08:36:27 -0400 Subject: [PATCH 02/20] add main entry point --- benchmark/benchmarks.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 benchmark/benchmarks.jl diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 000000000..1e89b2161 --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,17 @@ +# Load benchmark code +include("MPSKitBenchmarks/MPSKitBenchmarks.jl") +const SUITE = MPSKitBenchmarks.SUITE + +# Populate benchmarks +# Detect if user supplied extra arguments to load only specific modules +# e.g. julia benchmarks.jl --modules=linalg,tensornetworks +modules_pattern = r"(?:--modules=)(\w+)" +arg_id = findfirst(contains(modules_pattern), ARGS) +if isnothing(arg_id) + MPSKitBenchmarks.loadall!() +else + modules = split(only(match(modules_pattern, ARGS[arg_id]).captures[1]), ",") + for m in modules + MPSKitBenchmarks.load!(m) + end +end From e04bd7a0d4f41af6f4836c093399f901a8e5c97d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 1 Nov 2025 08:44:12 -0400 Subject: [PATCH 03/20] add Utility module --- benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl | 2 ++ benchmark/MPSKitBenchmarks/utils/BenchUtils.jl | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 benchmark/MPSKitBenchmarks/utils/BenchUtils.jl diff --git a/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl index ff4a4e108..079560584 100644 --- a/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl @@ -4,6 +4,8 @@ using BenchmarkTools using MPSKit using TOML +include("utils/BenchUtils.jl") + BenchmarkTools.DEFAULT_PARAMETERS.seconds = 20.0 BenchmarkTools.DEFAULT_PARAMETERS.samples = 10000 BenchmarkTools.DEFAULT_PARAMETERS.time_tolerance = 0.15 diff --git a/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl new file mode 100644 index 000000000..ab184d795 --- /dev/null +++ b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl @@ -0,0 +1,3 @@ +module BenchUtils + +end From 917da4cce49d8c9a8c9c49480e4e2376794b4052 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 2 Nov 2025 16:05:23 -0500 Subject: [PATCH 04/20] start setting up benchmark suite --- .../MPSKitBenchmarks/MPSKitBenchmarks.jl | 4 +- .../derivatives/AC2_benchmarks.jl | 85 +++++++++++++++++++ .../derivatives/DerivativesBenchmarks.jl | 17 ++++ .../MPSKitBenchmarks/utils/BenchUtils.jl | 24 ++++++ src/MPSKit.jl | 1 + src/algorithms/derivatives/derivatives.jl | 28 ++++++ .../derivatives/hamiltonian_derivatives.jl | 40 ++++----- src/algorithms/fixedpoint.jl | 26 +++--- 8 files changed, 194 insertions(+), 31 deletions(-) create mode 100644 benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl create mode 100644 benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl diff --git a/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl index 079560584..c70a01f70 100644 --- a/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/MPSKitBenchmarks.jl @@ -14,9 +14,11 @@ BenchmarkTools.DEFAULT_PARAMETERS.memory_tolerance = 0.01 const PARAMS_PATH = joinpath(@__DIR__, "etc", "params.json") const SUITE = BenchmarkGroup() const MODULES = Dict{String, Symbol}( - "derivatives" => :Derivatives + "derivatives" => :DerivativesBenchmarks ) +include("derivatives/DerivativesBenchmarks.jl") + load!(id::AbstractString; kwargs...) = load!(SUITE, id; kwargs...) function load!(group::BenchmarkGroup, id::AbstractString; tune::Bool = false) diff --git a/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl new file mode 100644 index 000000000..8c9a602ff --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl @@ -0,0 +1,85 @@ +struct AC2Spec{S <: ElementarySpace} # <: BenchmarkSpec + physicalspaces::NTuple{2, S} + mps_virtualspaces::NTuple{3, S} + mpo_virtualspaces::NTuple{3, SumSpace{S}} + nonzero_keys::NTuple{2, Vector{Tuple{Int, Int}}} +end + +function AC2Spec(mps, mpo; site = length(mps) ÷ 2) + physicalspaces = (physicalspace(mps, site), physicalspace(mps, site + 1)) + mps_virtualspaces = (left_virtualspace(mps, site), right_virtualspace(mps, site), right_virtualspace(mps, site + 1)) + mpo_virtualspaces = (left_virtualspace(mpo, site), right_virtualspace(mpo, site), right_virtualspace(mpo, site + 1)) + ks = ( + map(x -> (x.I[1], x.I[4]), nonzero_keys(mpo[site])), + map(x -> (x.I[1], x.I[4]), nonzero_keys(mpo[site])), + ) + return AC2Spec(physicalspaces, mps_virtualspaces, mpo_virtualspaces, ks) +end + +# Benchmarks +# ---------- +function MPSKit.MPO_AC2_Hamiltonian(spec::AC2Spec{S}; T::Type = Float64) where {S} + GL = randn(T, spec.mps_virtualspaces[1] ⊗ spec.mpo_virtualspaces[1]' ← spec.mps_virtualspaces[1]) + GR = randn(T, spec.mps_virtualspaces[3] ⊗ spec.mpo_virtualspaces[3] ← spec.mps_virtualspaces[3]) + W1 = JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.physicalspaces[1] ⊗ spec.mpo_virtualspaces[2]) + for (r, c) in spec.nonzero_keys[1] + r == c == 1 && continue + r == size(W1, 1) && c == size(W1, 4) && continue + W1[r, 1, 1, c] = randn!(W1[r, 1, 1, c]) + end + W2 = JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[2] ⊗ spec.physicalspaces[2] ← spec.physicalspaces[2] ⊗ spec.mpo_virtualspaces[3]) + for (r, c) in spec.nonzero_keys[2] + r == c == 1 && continue + r == size(W2, 1) && c == size(W2, 4) && continue + W2[r, 1, 1, c] = randn!(W2[r, 1, 1, c]) + end + + return MPSKit.MPO_AC2_Hamiltonian(GL, W1, W2, GR) +end + +function contraction_benchmark(spec::AC2Spec; T::Type = Float64) + AA = randn(T, spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]') + H_eff = MPSKit.MPO_AC2_Hamiltonian(spec; T) + H_prep, x_prep = MPSKit.prepare_operator!!(H_eff, AA) + init() = randn!(similar(x_prep)) + + return @benchmarkable $H_prep * x setup = (x = $init()) +end + +function preparation_benchmark(spec::AC2Spec; T::Type = Float64) + init() = randn(T, spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]') + H_eff = MPSKit.MPO_AC2_Hamiltonian(spec; T) + + return @benchmarkable begin + O′, x′ = MPSKit.prepare_operator!!($H_eff, x) + y = MPSKit.unprepare_operator!!(x′, O′, x) + end setup = (x = $init()) +end + +# Converters +# ---------- +function tomlify(spec::AC2Spec) + return Dict( + "physicalspaces" => collect(tomlify.(spec.physicalspaces)), + "mps_virtualspaces" => collect(tomlify.(spec.mps_virtualspaces)), + "mpo_virtualspaces" => collect(tomlify.(spec.mpo_virtualspaces)), + "nonzero_keys" => collect(map(Base.Fix1(map, collect), spec.nonzero_keys)) + ) +end + +function untomlify(::Type{AC2Spec}, x) + physicalspaces = Tuple(map(untomlify, x["physicalspaces"])) + mps_virtualspaces = Tuple(map(untomlify, x["mps_virtualspaces"])) + mpo_virtualspaces = Tuple(map(untomlify, x["mpo_virtualspaces"])) + nonzero_keys = Tuple(map(Base.Fix1(map, Base.Fix1(map, Tuple)), x["nonzero_keys"])) + return AC2Spec(physicalspaces, mps_virtualspaces, mpo_virtualspaces, nonzero_keys) +end + +function Base.convert(::Type{AC2Spec{S₁}}, spec::AC2Spec{S₂}) where {S₁, S₂} + return S₁ === S₂ ? spec : AC2Spec( + S₁.(spec.physicalspaces), + S₁.(spec.mps_virtualspaces), + SumSpace{S₁}.(spec.mpo_virtualspaces), + spec.nonzero_keys + ) +end diff --git a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl new file mode 100644 index 000000000..41d3b1941 --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl @@ -0,0 +1,17 @@ +module DerivativesBenchmarks + +export AC2Spec + +using BenchmarkTools +using TensorKit +using BlockTensorKit +using MPSKit +using ..BenchUtils +import ..BenchUtils: tomlify, untomlify + +const SUITE = BenchmarkGroup() + +include("AC2_benchmarks.jl") + + +end diff --git a/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl index ab184d795..c16f28ef1 100644 --- a/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl +++ b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl @@ -1,3 +1,27 @@ module BenchUtils +export tomlify, untomlify + +using TensorKit +using BlockTensorKit +using TOML + +tomlify(x::VectorSpace) = string(x) +untomlify(::Type{<:VectorSpace}, x) = eval(Meta.parse(x)) + + +# Type piracy but oh well +TensorKit.ComplexSpace(V::ElementarySpace) = ComplexSpace(dim(V), isdual(V)) + +function TensorKit.U1Space(V::SU2Space) + dims = TensorKit.SectorDict{U1Irrep, Int}() + for c in sectors(V), m in (-c.j):(c.j) + u1 = U1Irrep(m) + dims[u1] = get(dims, u1, 0) + 1 + end + return U1Space(dims; dual = isdual(V)) +end + +BlockTensorKit.SumSpace{S}(V::SumSpace) where {S} = SumSpace(map(S, V.spaces)) + end diff --git a/src/MPSKit.jl b/src/MPSKit.jl index cd465643d..7b18a31c6 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -65,6 +65,7 @@ using MatrixAlgebraKit: TruncationStrategy, PolarViaSVD, LAPACK_SVDAlgorithm using BlockTensorKit using BlockTensorKit: TensorMapSumSpace using TensorOperations +using TensorOperations: AbstractBackend, DefaultBackend, DefaultAllocator using KrylovKit using KrylovKit: KrylovAlgorithm using OptimKit diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 1f3980e37..1e65c3f15 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -213,3 +213,31 @@ const DerivativeOrMultiplied{D <: DerivativeOperator} = Union{MultipliedOperator (x::LazySum{<:DerivativeOrMultiplied})(y, t::Number) = sum(O -> O(y, t), x) (x::LazySum{<:DerivativeOrMultiplied})(y) = sum(O -> O(y), x) Base.:*(h::LazySum{<:Union{DerivativeOrMultiplied}}, v) = h(v) + +# Operator preparation +# -------------------- +""" + prepare_operator!!(O, x, [backend], [allocator]) -> O′, x′ + +Given an operator and vector, try to construct a more efficient representation of that operator for repeated application. +This should always be used in conjunction with [`unprepare_operator!!`](@ref). +""" +function prepare_operator!!( + O, x, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + return O, x +end + +""" + unprepare_operator!!(y, O, x, [backend], [allocator]) -> y′ + +Given the result `y` of applying a prepared operator `O` on vectors like `x`, undo the preparation work on the vector, and clean up the operator. +This should always be used in conjunction with [`prepare_operator!!`](@ref). +""" +function unprepare_operator!!( + y, O, x, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + return y +end diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index b922205f8..2b4f67235 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -75,13 +75,13 @@ const _HAM_MPS_TYPES = Union{ InfiniteMPS{<:MPSTensor}, } -function AC_hamiltonian( - site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, - above::_HAM_MPS_TYPES, envs +function prepare_operator!!( + O::MPO_AC_Hamiltonian{<:Any, <:JordanMPOTensor, <:Any}, x::MPSTensor, + backend::AbstractBackend, allocator ) - GL = leftenv(envs, site, below) - GR = rightenv(envs, site, below) - W = operator[site] + GL = O.leftenv + W = only(O.operators) + GR = O.rightenv # starting if nonzero_length(W.C) > 0 @@ -117,7 +117,7 @@ function AC_hamiltonian( end # not_started - if isfinite(operator) && site == length(operator) + if size(W, 4) == 1 not_started = missing elseif !ismissing(starting) I = id(storagetype(GR[1]), physicalspace(W)) @@ -128,7 +128,7 @@ function AC_hamiltonian( end # finished - if isfinite(operator) && site == 1 + if size(W, 1) == 1 finished = missing elseif !ismissing(ending) I = id(storagetype(GL[end]), physicalspace(W)) @@ -142,19 +142,20 @@ function AC_hamiltonian( A = W.A continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) - return JordanMPO_AC_Hamiltonian( + O′ = JordanMPO_AC_Hamiltonian( onsite, not_started, finished, starting, ending, continuing ) + + return O′, x end -function AC2_hamiltonian( - site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, - above::_HAM_MPS_TYPES, envs +function prepare_operator!!( + O::MPO_AC2_Hamiltonian{<:Any, <:JordanMPOTensor, <:JordanMPOTensor, <:Any}, x::MPOTensor, + backend::AbstractBackend, allocator ) - GL = leftenv(envs, site, below) - GR = rightenv(envs, site + 1, below) - W1 = operator[site] - W2 = operator[site + 1] + GL = O.leftenv + W1, W2 = O.operators + GR = O.rightenv # starting left - continuing right if nonzero_length(W1.C) > 0 && nonzero_length(W2.A) > 0 @@ -256,7 +257,7 @@ function AC2_hamiltonian( end # finished - if isfinite(operator) && site + 1 == length(operator) + if size(W2, 4) == 1 II = missing elseif !ismissing(IC) I = id(storagetype(GR[1]), physicalspace(W2)) @@ -271,7 +272,7 @@ function AC2_hamiltonian( end # unstarted - if isfinite(operator) && site == 1 + if size(W1, 1) == 1 EE = missing elseif !ismissing(BE) I = id(storagetype(GL[end]), physicalspace(W1)) @@ -289,7 +290,8 @@ function AC2_hamiltonian( # TODO: MPODerivativeOperator code reuse + optimization AA = (GL[2:(end - 1)], W1.A, W2.A, GR[2:(end - 1)]) - return JordanMPO_AC2_Hamiltonian(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + O′ = JordanMPO_AC2_Hamiltonian(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + return O′, x end # Actions diff --git a/src/algorithms/fixedpoint.jl b/src/algorithms/fixedpoint.jl index 81e7c69d9..941bde769 100644 --- a/src/algorithms/fixedpoint.jl +++ b/src/algorithms/fixedpoint.jl @@ -8,26 +8,30 @@ Compute the fixedpoint of a linear operator `A` using the specified eigensolver fixedpoint is assumed to be unique. """ function fixedpoint(A, x₀, which::Symbol, alg::Lanczos) - vals, vecs, info = eigsolve(A, x₀, 1, which, alg) + A′, x₀′ = prepare_operator!!(A, x₀) + vals, vecs, info = eigsolve(A′, x₀′, 1, which, alg) - if info.converged == 0 + info.converged == 0 && @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" - end - return vals[1], vecs[1] + λ = vals[1] + v = unprepare_operator!!(vecs[1], A′, x₀) + + return λ, v end function fixedpoint(A, x₀, which::Symbol, alg::Arnoldi) - TT, vecs, vals, info = schursolve(A, x₀, 1, which, alg) + A′, x₀′ = prepare_operator!!(A, x₀) + TT, vecs, vals, info = schursolve(A′, x₀′, 1, which, alg) - if info.converged == 0 + info.converged == 0 && @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" - end - if size(TT, 2) > 1 && TT[2, 1] != 0 - @warnv 1 "non-unique fixedpoint detected" - end + size(TT, 2) > 1 && TT[2, 1] != 0 && @warnv 1 "non-unique fixedpoint detected" + + λ = vals[1] + v = unprepare_operator!!(vecs[1], A′, x₀) - return vals[1], vecs[1] + return λ, v end function fixedpoint(A, x₀, which::Symbol; kwargs...) From c150ab63dd7e53ce6ea0a52a25c88a3be1f8c9aa Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 2 Nov 2025 17:11:31 -0500 Subject: [PATCH 05/20] add heisenberg script --- .../scripts/setup_heisenberg.jl | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl diff --git a/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl new file mode 100644 index 000000000..58031ae1d --- /dev/null +++ b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl @@ -0,0 +1,81 @@ +using TensorKit +using MPSKit +using MPSKit.BlockTensorKit: nonzero_keys +using MPSKit.BlockTensorKit +using MPSKitModels +using TOML + +include(joinpath(@__DIR__, "..", "MPSKitBenchmarks.jl")) +using .MPSKitBenchmarks +# MPSKitBenchmarks.load!("derivatives") +using .MPSKitBenchmarks.DerivativesBenchmarks: AC2Spec +using .MPSKitBenchmarks.BenchUtils: tomlify + +# Utility functions +# ---------------- +# setup "product state" -> ⨂^N |↑↓ - ↓↑⟩ +function initial_state(H) + @assert iseven(length(H)) + @assert allequal(physicalspace(H)) + + pspace = physicalspace(H, 1) + A = rand(oneunit(pspace) ⊗ pspace^2 ← oneunit(pspace)) + As = MPSKit.decompose_localmps(A) + return FiniteMPS(repeat(As, length(H) ÷ 2)) +end + +function generate_spaces(H, alg; D_min = 2, D_steps = 5) + # compute maximal spaces + psi_init = initial_state(H) + psi, = find_groundstate(psi_init, H, alg) + + D_max = maximum(dim, left_virtualspace(psi)) + Ds = round.(Int, logrange(D_min, D_max, D_steps)) + + return map(Ds) do D + mps = changebonds(psi, SvdCut(; trscheme = truncrank(D))) + return AC2Spec(mps, H) + end +end + +# Parameters +# ---------- +T = Float64 +spin = 1 + +D_max = 10_000 + +D_steps = 10 +D_min = 3 + + +# FiniteChain +# ----------- +L = 100 +lattice = FiniteChain(L) + +symmetry = SU2Irrep +alg = DMRG2(; + maxiter = 10, tol = 1.0e-12, + alg_eigsolve = (; tol = 1.0e-5, dynamic_tols = false, maxiter = 3), + trscheme = truncrank(D_max) +) + +H = heisenberg_XXX(T, symmetry, lattice; spin); +specs_su2 = generate_spaces(H, alg; D_min, D_steps) + +specs_triv = filter!(convert.(AC2Spec{ComplexSpace}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 1000 +end + +specs_u1 = filter!(convert.(AC2Spec{U1Space}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 5000 +end + +specs = vcat(specs_triv, specs_u1, specs_su2) + +output_file = joinpath(@__DIR__, "heisenberg_NN_specs.toml") +open(output_file, "w") do io + TOML.print(io, Dict("specs" => tomlify.(specs))) +end +@info("Spaces written to $output_file") From fd3de810e49b9a85cd358e6f0c99d1a8e969bc0b Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 2 Nov 2025 17:28:54 -0500 Subject: [PATCH 06/20] add test suites --- .../derivatives/DerivativesBenchmarks.jl | 21 +++ .../derivatives/heisenberg_NN.toml | 150 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml diff --git a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl index 41d3b1941..0dd7cccca 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl @@ -3,6 +3,7 @@ module DerivativesBenchmarks export AC2Spec using BenchmarkTools +using TOML using TensorKit using BlockTensorKit using MPSKit @@ -11,7 +12,27 @@ import ..BenchUtils: tomlify, untomlify const SUITE = BenchmarkGroup() +const allparams = Dict( + "heisenberg_NN" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_NN_specs.toml")) +) + include("AC2_benchmarks.jl") +T = Float64 + +suite_init = addgroup!(SUITE, "AC2_preparation") +suite_apply = addgroup!(SUITE, "AC2_contraction") + +for (model, params) in allparams + g_prep = addgroup!(suite_init, model) + g_contract = addgroup!(suite_apply, model) + specs = untomlify.(AC2Spec, params["specs"]) + + for spec in specs + name = benchname(spec) + g_prep[name] = preparation_benchmark(spec; T) + g_contract[name] = contraction_benchmark(spec; T) + end +end end diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml new file mode 100644 index 000000000..0d96ee0c4 --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml @@ -0,0 +1,150 @@ +[[specs]] +mps_virtualspaces = ["ℂ^1", "ℂ^3", "ℂ^1"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^9", "ℂ^7", "ℂ^9"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^12", "ℂ^12", "ℂ^12"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^21", "ℂ^21", "ℂ^21"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^29", "ℂ^24", "ℂ^29"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^44", "ℂ^44", "ℂ^44"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^65", "ℂ^63", "ℂ^65"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["ℂ^81", "ℂ^96", "ℂ^81"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 1, 2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 4, 2 => 3)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 3)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 7, 2 => 5, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[[specs]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 5, 1 => 10, 2 => 8, 3 => 3)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] From c9727dfa3744d303d1ae5046be47418534cea992 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 2 Nov 2025 18:12:26 -0500 Subject: [PATCH 07/20] small updates --- .../derivatives/AC2_benchmarks.jl | 15 ++- .../derivatives/DerivativesBenchmarks.jl | 17 +-- .../derivatives/heisenberg_NN.toml | 106 +++++++++--------- .../scripts/setup_heisenberg.jl | 17 ++- 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl index 8c9a602ff..f302a0435 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl @@ -16,18 +16,20 @@ function AC2Spec(mps, mpo; site = length(mps) ÷ 2) return AC2Spec(physicalspaces, mps_virtualspaces, mpo_virtualspaces, ks) end +benchname(spec::AC2Spec) = dim(spec.mps_virtualspaces[1]), dim(spec.mpo_virtualspaces[1]) + # Benchmarks # ---------- function MPSKit.MPO_AC2_Hamiltonian(spec::AC2Spec{S}; T::Type = Float64) where {S} GL = randn(T, spec.mps_virtualspaces[1] ⊗ spec.mpo_virtualspaces[1]' ← spec.mps_virtualspaces[1]) GR = randn(T, spec.mps_virtualspaces[3] ⊗ spec.mpo_virtualspaces[3] ← spec.mps_virtualspaces[3]) - W1 = JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.physicalspaces[1] ⊗ spec.mpo_virtualspaces[2]) + W1 = MPSKit.JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.physicalspaces[1] ⊗ spec.mpo_virtualspaces[2]) for (r, c) in spec.nonzero_keys[1] r == c == 1 && continue r == size(W1, 1) && c == size(W1, 4) && continue W1[r, 1, 1, c] = randn!(W1[r, 1, 1, c]) end - W2 = JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[2] ⊗ spec.physicalspaces[2] ← spec.physicalspaces[2] ⊗ spec.mpo_virtualspaces[3]) + W2 = MPSKit.JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[2] ⊗ spec.physicalspaces[2] ← spec.physicalspaces[2] ⊗ spec.mpo_virtualspaces[3]) for (r, c) in spec.nonzero_keys[2] r == c == 1 && continue r == size(W2, 1) && c == size(W2, 4) && continue @@ -68,10 +70,11 @@ function tomlify(spec::AC2Spec) end function untomlify(::Type{AC2Spec}, x) - physicalspaces = Tuple(map(untomlify, x["physicalspaces"])) - mps_virtualspaces = Tuple(map(untomlify, x["mps_virtualspaces"])) - mpo_virtualspaces = Tuple(map(untomlify, x["mpo_virtualspaces"])) - nonzero_keys = Tuple(map(Base.Fix1(map, Base.Fix1(map, Tuple)), x["nonzero_keys"])) + to_space = Base.Fix1(untomlify, VectorSpace) + physicalspaces = Tuple(map(to_space, x["physicalspaces"])) + mps_virtualspaces = Tuple(map(to_space, x["mps_virtualspaces"])) + mpo_virtualspaces = Tuple(map(to_space, x["mpo_virtualspaces"])) + nonzero_keys = Tuple(map(Base.Fix1(map, Tuple), x["nonzero_keys"])) return AC2Spec(physicalspaces, mps_virtualspaces, mpo_virtualspaces, nonzero_keys) end diff --git a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl index 0dd7cccca..017e08d9f 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl @@ -13,7 +13,7 @@ import ..BenchUtils: tomlify, untomlify const SUITE = BenchmarkGroup() const allparams = Dict( - "heisenberg_NN" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_NN_specs.toml")) + "heisenberg_NN" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_NN.toml")) ) include("AC2_benchmarks.jl") @@ -26,12 +26,15 @@ suite_apply = addgroup!(SUITE, "AC2_contraction") for (model, params) in allparams g_prep = addgroup!(suite_init, model) g_contract = addgroup!(suite_apply, model) - specs = untomlify.(AC2Spec, params["specs"]) - - for spec in specs - name = benchname(spec) - g_prep[name] = preparation_benchmark(spec; T) - g_contract[name] = contraction_benchmark(spec; T) + for (symmetry, specs) in params + g_prep_sym = addgroup!(g_prep, symmetry) + g_contract_sym = addgroup!(g_contract, symmetry) + for spec_dict in specs + spec = untomlify(AC2Spec, spec_dict) + name = benchname(spec) + g_prep_sym[name] = preparation_benchmark(spec; T) + g_contract_sym[name] = contraction_benchmark(spec; T) + end end end diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml index 0d96ee0c4..ad1412195 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml @@ -1,150 +1,152 @@ -[[specs]] +[[Trivial]] mps_virtualspaces = ["ℂ^1", "ℂ^3", "ℂ^1"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] +[[Trivial]] mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] +[[Trivial]] +mps_virtualspaces = ["ℂ^4", "ℂ^7", "ℂ^4"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^9", "ℂ^7", "ℂ^9"] +[[Trivial]] +mps_virtualspaces = ["ℂ^12", "ℂ^12", "ℂ^12"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^12", "ℂ^12", "ℂ^12"] +[[Trivial]] +mps_virtualspaces = ["ℂ^21", "ℂ^21", "ℂ^21"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^21", "ℂ^21", "ℂ^21"] +[[Trivial]] +mps_virtualspaces = ["ℂ^29", "ℂ^31", "ℂ^29"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^29", "ℂ^24", "ℂ^29"] +[[Trivial]] +mps_virtualspaces = ["ℂ^53", "ℂ^56", "ℂ^53"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^44", "ℂ^44", "ℂ^44"] +[[Trivial]] +mps_virtualspaces = ["ℂ^81", "ℂ^88", "ℂ^81"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^65", "ℂ^63", "ℂ^65"] +[[Trivial]] +mps_virtualspaces = ["ℂ^81", "ℂ^148", "ℂ^81"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] -mps_virtualspaces = ["ℂ^81", "ℂ^96", "ℂ^81"] +[[Trivial]] +mps_virtualspaces = ["ℂ^81", "ℂ^243", "ℂ^81"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] -[[specs]] + +[["Irrep[U₁]"]] mps_virtualspaces = ["Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] +[["Irrep[U₁]"]] mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] +[["Irrep[U₁]"]] mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] +[["Irrep[U₁]"]] mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 6, 1 => 5, -1 => 5, 2 => 4, -2 => 4, 3 => 3, -3 => 3, 4 => 2, -4 => 2, 5 => 1, -5 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[[specs]] + +[["Irrep[SU₂]"]] mps_virtualspaces = ["Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] +[["Irrep[SU₂]"]] mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 1, 2 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 4, 2 => 3)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 2, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 3)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 4, 2 => 3)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 3)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 5, 3 => 1)", "Rep[SU₂](0 => 3, 1 => 7, 2 => 5, 3 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 5, 3 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 4, 1 => 10, 2 => 8, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 7, 2 => 5, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 2)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 6, 1 => 12, 2 => 11, 3 => 6, 4 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] -[[specs]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 5, 1 => 10, 2 => 8, 3 => 3)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 6, 1 => 15, 2 => 15, 3 => 10, 4 => 4, 5 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] diff --git a/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl index 58031ae1d..9842959d5 100644 --- a/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl +++ b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl @@ -1,7 +1,8 @@ using TensorKit +using TensorKit: type_repr using MPSKit -using MPSKit.BlockTensorKit: nonzero_keys -using MPSKit.BlockTensorKit +using BlockTensorKit +using BlockTensorKit: nonzero_keys using MPSKitModels using TOML @@ -51,7 +52,7 @@ D_min = 3 # FiniteChain # ----------- -L = 100 +L = 10 lattice = FiniteChain(L) symmetry = SU2Irrep @@ -74,8 +75,14 @@ end specs = vcat(specs_triv, specs_u1, specs_su2) -output_file = joinpath(@__DIR__, "heisenberg_NN_specs.toml") +output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_NN.toml") open(output_file, "w") do io - TOML.print(io, Dict("specs" => tomlify.(specs))) + TOML.print( + io, Dict( + type_repr(Trivial) => tomlify.(specs_triv), + type_repr(U1Irrep) => tomlify.(specs_u1), + type_repr(SU2Irrep) => tomlify.(specs_su2) + ) + ) end @info("Spaces written to $output_file") From 5b9a510a6080d7165d75aa6e5ca324f441265bcb Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 3 Nov 2025 07:25:07 -0500 Subject: [PATCH 08/20] update scripts --- .../derivatives/DerivativesBenchmarks.jl | 5 +- .../derivatives/heisenberg_coulomb.toml | 132 ++++++++++++++++++ .../derivatives/heisenberg_cylinder.toml | 132 ++++++++++++++++++ ...{heisenberg_NN.toml => heisenberg_nn.toml} | 72 ++++------ .../derivatives/heisenberg_nnn.toml | 132 ++++++++++++++++++ .../scripts/setup_heisenberg.jl | 129 ++++++++++++++++- .../MPSKitBenchmarks/utils/BenchUtils.jl | 4 +- 7 files changed, 552 insertions(+), 54 deletions(-) create mode 100644 benchmark/MPSKitBenchmarks/derivatives/heisenberg_coulomb.toml create mode 100644 benchmark/MPSKitBenchmarks/derivatives/heisenberg_cylinder.toml rename benchmark/MPSKitBenchmarks/derivatives/{heisenberg_NN.toml => heisenberg_nn.toml} (64%) create mode 100644 benchmark/MPSKitBenchmarks/derivatives/heisenberg_nnn.toml diff --git a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl index 017e08d9f..db1cf8ecb 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl @@ -13,7 +13,10 @@ import ..BenchUtils: tomlify, untomlify const SUITE = BenchmarkGroup() const allparams = Dict( - "heisenberg_NN" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_NN.toml")) + "heisenberg_nn" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_nn.toml")), + "heisenberg_nnn" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_nnn.toml")), + "heisenberg_cylinder" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_cylinder.toml")), + "heisenberg_coulomb" => TOML.parsefile(joinpath(@__DIR__, "heisenberg_coulomb.toml")) ) include("AC2_benchmarks.jl") diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_coulomb.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_coulomb.toml new file mode 100644 index 000000000..0a945aced --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_coulomb.toml @@ -0,0 +1,132 @@ +[[Trivial]] +mps_virtualspaces = ["ℂ^1", "ℂ^3", "ℂ^1"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^7", "ℂ^7", "ℂ^7"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^19", "ℂ^19", "ℂ^19"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^40", "ℂ^40", "ℂ^40"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^76", "ℂ^76", "ℂ^76"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^140", "ℂ^143", "ℂ^140"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^272", "ℂ^274", "ℂ^272"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^498 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] + +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 7, 1 => 5, -1 => 5, 2 => 1, -2 => 1)", "Rep[U₁](0 => 7, 1 => 5, -1 => 5, 2 => 1, -2 => 1)", "Rep[U₁](0 => 7, 1 => 5, -1 => 5, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 14, 1 => 10, -1 => 10, 2 => 3, -2 => 3)", "Rep[U₁](0 => 14, 1 => 10, -1 => 10, 2 => 3, -2 => 3)", "Rep[U₁](0 => 14, 1 => 10, -1 => 10, 2 => 3, -2 => 3)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 24, 1 => 18, -1 => 18, 2 => 7, -2 => 7, 3 => 1, -3 => 1)", "Rep[U₁](0 => 24, 1 => 18, -1 => 18, 2 => 7, -2 => 7, 3 => 1, -3 => 1)", "Rep[U₁](0 => 24, 1 => 18, -1 => 18, 2 => 7, -2 => 7, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 42, 1 => 32, -1 => 32, 2 => 14, -2 => 14, 3 => 3, -3 => 3)", "Rep[U₁](0 => 43, 1 => 33, -1 => 33, 2 => 14, -2 => 14, 3 => 3, -3 => 3)", "Rep[U₁](0 => 42, 1 => 32, -1 => 32, 2 => 14, -2 => 14, 3 => 3, -3 => 3)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 80, 1 => 62, -1 => 62, 2 => 28, -2 => 28, 3 => 6, -3 => 6)", "Rep[U₁](0 => 80, 1 => 63, -1 => 63, 2 => 28, -2 => 28, 3 => 6, -3 => 6)", "Rep[U₁](0 => 80, 1 => 62, -1 => 62, 2 => 28, -2 => 28, 3 => 6, -3 => 6)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>166, 1=>166, -1=>166) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] + +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 4, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 4, 1 => 7, 2 => 3)", "Rep[SU₂](0 => 4, 1 => 7, 2 => 3)", "Rep[SU₂](0 => 4, 1 => 7, 2 => 3)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 6, 1 => 11, 2 => 6, 3 => 1)", "Rep[SU₂](0 => 6, 1 => 11, 2 => 6, 3 => 1)", "Rep[SU₂](0 => 6, 1 => 11, 2 => 6, 3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 10, 1 => 18, 2 => 11, 3 => 3)", "Rep[SU₂](0 => 10, 1 => 19, 2 => 11, 3 => 3)", "Rep[SU₂](0 => 10, 1 => 18, 2 => 11, 3 => 3)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 18, 1 => 34, 2 => 22, 3 => 6)", "Rep[SU₂](0 => 17, 1 => 35, 2 => 22, 3 => 6)", "Rep[SU₂](0 => 18, 1 => 34, 2 => 22, 3 => 6)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 28, 1 => 58, 2 => 43, 3 => 14, 4 => 1)", "Rep[SU₂](0 => 30, 1 => 59, 2 => 43, 3 => 13, 4 => 1)", "Rep[SU₂](0 => 28, 1 => 58, 2 => 43, 3 => 14, 4 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 41, 1 => 84, 2 => 64, 3 => 26, 4 => 11, 5 => 6, 6 => 3)", "Rep[SU₂](0 => 34, 1 => 71, 2 => 63, 3 => 30, 4 => 12, 5 => 6, 6 => 3, 7 => 1)", "Rep[SU₂](0 => 40, 1 => 83, 2 => 62, 3 => 29, 4 => 12, 5 => 7, 6 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]], [[1, 1], [3, 3], [2, 2], [2, 3], [1, 2], [1, 3]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>166) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_cylinder.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_cylinder.toml new file mode 100644 index 000000000..bd1e55b79 --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_cylinder.toml @@ -0,0 +1,132 @@ +[[Trivial]] +mps_virtualspaces = ["ℂ^3", "ℂ^1", "ℂ^3"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^3", "ℂ^4", "ℂ^3"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^16", "ℂ^12", "ℂ^16"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^43", "ℂ^41", "ℂ^45"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^110", "ℂ^104", "ℂ^110"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^269", "ℂ^267", "ℂ^266"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^668", "ℂ^669", "ℂ^669"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1 ⊞ ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] + +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 1, -2 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 13, 1 => 9, -1 => 9, 2 => 5, -2 => 5, 3 => 1, -3 => 1)", "Rep[U₁](0 => 11, 1 => 10, -1 => 10, 2 => 4, -2 => 4, 3 => 1, -3 => 1)", "Rep[U₁](0 => 13, 1 => 9, -1 => 9, 2 => 6, -2 => 6, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 26, 1 => 22, -1 => 22, 2 => 13, -2 => 13, 3 => 6, -3 => 6, 4 => 1, -4 => 1)", "Rep[U₁](0 => 26, 1 => 21, -1 => 21, 2 => 12, -2 => 12, 3 => 5, -3 => 5, 4 => 1, -4 => 1)", "Rep[U₁](0 => 26, 1 => 22, -1 => 22, 2 => 13, -2 => 13, 3 => 6, -3 => 6, 4 => 1, -4 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 59, 1 => 53, -1 => 53, 2 => 32, -2 => 32, 3 => 14, -3 => 14, 4 => 5, -4 => 5, 5 => 1, -5 => 1)", "Rep[U₁](0 => 61, 1 => 51, -1 => 51, 2 => 35, -2 => 35, 3 => 12, -3 => 12, 4 => 4, -4 => 4, 5 => 1, -5 => 1)", "Rep[U₁](0 => 58, 1 => 52, -1 => 52, 2 => 32, -2 => 32, 3 => 14, -3 => 14, 4 => 5, -4 => 5, 5 => 1, -5 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 140, 1 => 121, -1 => 121, 2 => 83, -2 => 83, 3 => 41, -3 => 41, 4 => 14, -4 => 14, 5 => 4, -5 => 4, 6 => 1, -6 => 1)", "Rep[U₁](0 => 145, 1 => 131, -1 => 131, 2 => 83, -2 => 83, 3 => 38, -3 => 38, 4 => 9, -4 => 9, 5 => 1, -5 => 1)", "Rep[U₁](0 => 141, 1 => 122, -1 => 122, 2 => 83, -2 => 83, 3 => 40, -3 => 40, 4 => 14, -4 => 14, 5 => 4, -5 => 4, 6 => 1, -6 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 328, 1 => 293, -1 => 293, 2 => 204, -2 => 204, 3 => 107, -3 => 107, 4 => 43, -4 => 43, 5 => 11, -5 => 11, 6 => 1, -6 => 1)", "Rep[U₁](0 => 344, 1 => 298, -1 => 298, 2 => 206, -2 => 206, 3 => 102, -3 => 102, 4 => 37, -4 => 37, 5 => 8, -5 => 8, 6 => 1, -6 => 1)", "Rep[U₁](0 => 329, 1 => 293, -1 => 293, 2 => 203, -2 => 203, 3 => 108, -3 => 108, 4 => 43, -4 => 43, 5 => 11, -5 => 11, 6 => 1, -6 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 771, 1 => 692, -1 => 692, 2 => 495, -2 => 495, 3 => 283, -3 => 283, 4 => 124, -4 => 124, 5 => 41, -5 => 41, 6 => 8, -6 => 8, 7 => 1, -7 => 1)", "Rep[U₁](0 => 787, 1 => 704, -1 => 704, 2 => 493, -2 => 493, 3 => 275, -3 => 275, 4 => 118, -4 => 118, 5 => 36, -5 => 36, 6 => 8, -6 => 8, 7 => 1, -7 => 1)", "Rep[U₁](0 => 771, 1 => 692, -1 => 692, 2 => 495, -2 => 495, 3 => 282, -3 => 282, 4 => 124, -4 => 124, 5 => 41, -5 => 41, 6 => 8, -6 => 8, 7 => 1, -7 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] + +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](1 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1, 2 => 1, 3 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 1, 2 => 1, 3 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 4, 1 => 4, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 1, 1 => 6, 2 => 3, 3 => 1)", "Rep[SU₂](0 => 4, 1 => 3, 2 => 5, 3 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 4, 1 => 9, 2 => 7, 3 => 5, 4 => 1)", "Rep[SU₂](0 => 5, 1 => 9, 2 => 7, 3 => 4, 4 => 1)", "Rep[SU₂](0 => 4, 1 => 9, 2 => 7, 3 => 5, 4 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 6, 1 => 21, 2 => 18, 3 => 9, 4 => 4, 5 => 1)", "Rep[SU₂](0 => 10, 1 => 16, 2 => 23, 3 => 8, 4 => 3, 5 => 1)", "Rep[SU₂](0 => 6, 1 => 20, 2 => 18, 3 => 9, 4 => 4, 5 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 19, 1 => 38, 2 => 42, 3 => 27, 4 => 10, 5 => 3, 6 => 1)", "Rep[SU₂](0 => 14, 1 => 48, 2 => 45, 3 => 29, 4 => 8, 5 => 1)", "Rep[SU₂](0 => 19, 1 => 39, 2 => 43, 3 => 26, 4 => 10, 5 => 3, 6 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 35, 1 => 89, 2 => 97, 3 => 64, 4 => 32, 5 => 10, 6 => 1)", "Rep[SU₂](0 => 46, 1 => 92, 2 => 104, 3 => 65, 4 => 29, 5 => 7, 6 => 1)", "Rep[SU₂](0 => 36, 1 => 90, 2 => 95, 3 => 65, 4 => 32, 5 => 10, 6 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 79, 1 => 197, 2 => 212, 3 => 159, 4 => 83, 5 => 33, 6 => 7, 7 => 1)", "Rep[SU₂](0 => 83, 1 => 211, 2 => 218, 3 => 157, 4 => 82, 5 => 28, 6 => 7, 7 => 1)", "Rep[SU₂](0 => 79, 1 => 197, 2 => 213, 3 => 158, 4 => 83, 5 => 33, 6 => 7, 7 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 169, 1 => 427, 2 => 488, 3 => 380, 4 => 217, 5 => 92, 6 => 29, 7 => 6, 8 => 1)", "Rep[SU₂](0 => 185, 1 => 432, 2 => 510, 3 => 380, 4 => 210, 5 => 89, 6 => 26, 7 => 6)", "Rep[SU₂](0 => 168, 1 => 426, 2 => 489, 3 => 380, 4 => 217, 5 => 92, 6 => 29, 7 => 6, 8 => 1)"] +nonzero_keys = [[[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]], [[1, 1], [10, 10], [7, 7], [6, 6], [9, 9], [8, 8], [5, 5], [2, 10], [3, 10], [4, 10], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_nn.toml similarity index 64% rename from benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml rename to benchmark/MPSKitBenchmarks/derivatives/heisenberg_nn.toml index ad1412195..1e508e53a 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_NN.toml +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_nn.toml @@ -1,152 +1,132 @@ [[Trivial]] -mps_virtualspaces = ["ℂ^1", "ℂ^3", "ℂ^1"] +mps_virtualspaces = ["ℂ^3", "ℂ^1", "ℂ^3"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^4", "ℂ^4", "ℂ^4"] +mps_virtualspaces = ["ℂ^7", "ℂ^7", "ℂ^7"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^4", "ℂ^7", "ℂ^4"] +mps_virtualspaces = ["ℂ^16", "ℂ^16", "ℂ^16"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^12", "ℂ^12", "ℂ^12"] +mps_virtualspaces = ["ℂ^44", "ℂ^44", "ℂ^44"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^21", "ℂ^21", "ℂ^21"] +mps_virtualspaces = ["ℂ^108", "ℂ^108", "ℂ^108"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^29", "ℂ^31", "ℂ^29"] +mps_virtualspaces = ["ℂ^271", "ℂ^271", "ℂ^271"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [[Trivial]] -mps_virtualspaces = ["ℂ^53", "ℂ^56", "ℂ^53"] -nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] -mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] -physicalspaces = ["ℂ^3", "ℂ^3"] -[[Trivial]] -mps_virtualspaces = ["ℂ^81", "ℂ^88", "ℂ^81"] -nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] -mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] -physicalspaces = ["ℂ^3", "ℂ^3"] -[[Trivial]] -mps_virtualspaces = ["ℂ^81", "ℂ^148", "ℂ^81"] -nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] -mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] -physicalspaces = ["ℂ^3", "ℂ^3"] -[[Trivial]] -mps_virtualspaces = ["ℂ^81", "ℂ^243", "ℂ^81"] +mps_virtualspaces = ["ℂ^661", "ℂ^667", "ℂ^669"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] physicalspaces = ["ℂ^3", "ℂ^3"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)"] -nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] -mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] -physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] -[["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)", "Rep[U₁](0 => 2, 1 => 1, -1 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)", "Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)", "Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)", "Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)", "Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2, 2 => 1, -2 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)", "Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)", "Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)", "Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)", "Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 4, 1 => 3, -1 => 3, 2 => 2, -2 => 2, 3 => 1, -3 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 153, 1 => 130, -1 => 130, 2 => 79, -2 => 79, 3 => 33, -3 => 33, 4 => 10, -4 => 10, 5 => 2, -5 => 2)", "Rep[U₁](0 => 157, 1 => 133, -1 => 133, 2 => 80, -2 => 80, 3 => 33, -3 => 33, 4 => 8, -4 => 8, 5 => 1, -5 => 1)", "Rep[U₁](0 => 159, 1 => 134, -1 => 134, 2 => 80, -2 => 80, 3 => 32, -3 => 32, 4 => 8, -4 => 8, 5 => 1, -5 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 307, 1 => 273, -1 => 273, 2 => 194, -2 => 194, 3 => 114, -3 => 114, 4 => 58, -4 => 58, 5 => 24, -5 => 24, 6 => 6, -6 => 6, 7 => 1, -7 => 1)", "Rep[U₁](0 => 317, 1 => 280, -1 => 280, 2 => 194, -2 => 194, 3 => 110, -3 => 110, 4 => 53, -4 => 53, 5 => 20, -5 => 20, 6 => 5, -6 => 5, 7 => 1, -7 => 1)", "Rep[U₁](0 => 313, 1 => 278, -1 => 278, 2 => 196, -2 => 196, 3 => 114, -3 => 114, 4 => 56, -4 => 56, 5 => 20, -5 => 20, 6 => 4, -6 => 4)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[U₁]"]] -mps_virtualspaces = ["Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)", "Rep[U₁](0 => 6, 1 => 5, -1 => 5, 2 => 4, -2 => 4, 3 => 3, -3 => 3, 4 => 2, -4 => 2, 5 => 1, -5 => 1)", "Rep[U₁](0 => 5, 1 => 4, -1 => 4, 2 => 3, -2 => 3, 3 => 2, -3 => 2, 4 => 1, -4 => 1)"] +mps_virtualspaces = ["Rep[U₁](0 => 987, 1 => 830, -1 => 830, 2 => 432, -2 => 432, 3 => 161, -3 => 161, 4 => 77, -4 => 77, 5 => 28, -5 => 28, 6 => 7, -6 => 7, 7 => 1, -7 => 1)", "Rep[U₁](0 => 701, 1 => 635, -1 => 635, 2 => 478, -2 => 478, 3 => 303, -3 => 303, 4 => 162, -4 => 162, 5 => 70, -5 => 70, 6 => 22, -6 => 22, 7 => 4, -7 => 4)", "Rep[U₁](0 => 987, 1 => 830, -1 => 830, 2 => 431, -2 => 431, 3 => 161, -3 => 161, 4 => 77, -4 => 77, 5 => 28, -5 => 28, 6 => 7, -6 => 7, 7 => 1, -7 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)"] +mps_virtualspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 1)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)", "Rep[SU₂](0 => 1, 1 => 2, 2 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 2)"] +mps_virtualspaces = ["Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)", "Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)", "Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 4, 2 => 3)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 2, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 4, 2 => 3)"] +mps_virtualspaces = ["Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)", "Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)", "Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 5, 3 => 1)", "Rep[SU₂](0 => 3, 1 => 7, 2 => 5, 3 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 5, 3 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 23, 1 => 51, 2 => 46, 3 => 23, 4 => 8, 5 => 2)", "Rep[SU₂](0 => 24, 1 => 53, 2 => 47, 3 => 25, 4 => 7, 5 => 1)", "Rep[SU₂](0 => 25, 1 => 54, 2 => 48, 3 => 24, 4 => 7, 5 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 4, 1 => 10, 2 => 8, 3 => 2)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 34, 1 => 79, 2 => 80, 3 => 56, 4 => 34, 5 => 18, 6 => 5, 7 => 1)", "Rep[SU₂](0 => 37, 1 => 86, 2 => 84, 3 => 57, 4 => 33, 5 => 15, 6 => 4, 7 => 1)", "Rep[SU₂](0 => 35, 1 => 82, 2 => 82, 3 => 58, 4 => 36, 5 => 16, 6 => 4)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 6, 1 => 12, 2 => 11, 3 => 6, 4 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 157, 1 => 398, 2 => 271, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)", "Rep[SU₂](0 => 66, 1 => 157, 2 => 175, 3 => 141, 4 => 92, 5 => 48, 6 => 18, 7 => 4)", "Rep[SU₂](0 => 157, 1 => 399, 2 => 270, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] [["Irrep[SU₂]"]] -mps_virtualspaces = ["Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)", "Rep[SU₂](0 => 6, 1 => 15, 2 => 15, 3 => 10, 4 => 4, 5 => 1)", "Rep[SU₂](0 => 3, 1 => 6, 2 => 6, 3 => 3, 4 => 1)"] +mps_virtualspaces = ["Rep[SU₂](0 => 1196, 1 => 1678, 2 => 483, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)", "Rep[SU₂](0 => 603, 1 => 1213, 2 => 280, 3 => 237, 4 => 153, 5 => 76, 6 => 28, 7 => 7, 8 => 1)", "Rep[SU₂](0 => 1198, 1 => 1646, 2 => 502, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)"] nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] diff --git a/benchmark/MPSKitBenchmarks/derivatives/heisenberg_nnn.toml b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_nnn.toml new file mode 100644 index 000000000..1e508e53a --- /dev/null +++ b/benchmark/MPSKitBenchmarks/derivatives/heisenberg_nnn.toml @@ -0,0 +1,132 @@ +[[Trivial]] +mps_virtualspaces = ["ℂ^3", "ℂ^1", "ℂ^3"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^7", "ℂ^7", "ℂ^7"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^16", "ℂ^16", "ℂ^16"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^44", "ℂ^44", "ℂ^44"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^108", "ℂ^108", "ℂ^108"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^271", "ℂ^271", "ℂ^271"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] +[[Trivial]] +mps_virtualspaces = ["ℂ^661", "ℂ^667", "ℂ^669"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)", "(ℂ^1 ⊞ ℂ^3 ⊞ ℂ^1)"] +physicalspaces = ["ℂ^3", "ℂ^3"] + +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)", "Rep[U₁](0 => 3, 1 => 2, -1 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)", "Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)", "Rep[U₁](0 => 6, 1 => 4, -1 => 4, 2 => 1, -2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)", "Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)", "Rep[U₁](0 => 12, 1 => 10, -1 => 10, 2 => 5, -2 => 5, 3 => 1, -3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)", "Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)", "Rep[U₁](0 => 32, 1 => 25, -1 => 25, 2 => 11, -2 => 11, 3 => 2, -3 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)", "Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)", "Rep[U₁](0 => 71, 1 => 58, -1 => 58, 2 => 31, -2 => 31, 3 => 10, -3 => 10, 4 => 1, -4 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 153, 1 => 130, -1 => 130, 2 => 79, -2 => 79, 3 => 33, -3 => 33, 4 => 10, -4 => 10, 5 => 2, -5 => 2)", "Rep[U₁](0 => 157, 1 => 133, -1 => 133, 2 => 80, -2 => 80, 3 => 33, -3 => 33, 4 => 8, -4 => 8, 5 => 1, -5 => 1)", "Rep[U₁](0 => 159, 1 => 134, -1 => 134, 2 => 80, -2 => 80, 3 => 32, -3 => 32, 4 => 8, -4 => 8, 5 => 1, -5 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 307, 1 => 273, -1 => 273, 2 => 194, -2 => 194, 3 => 114, -3 => 114, 4 => 58, -4 => 58, 5 => 24, -5 => 24, 6 => 6, -6 => 6, 7 => 1, -7 => 1)", "Rep[U₁](0 => 317, 1 => 280, -1 => 280, 2 => 194, -2 => 194, 3 => 110, -3 => 110, 4 => 53, -4 => 53, 5 => 20, -5 => 20, 6 => 5, -6 => 5, 7 => 1, -7 => 1)", "Rep[U₁](0 => 313, 1 => 278, -1 => 278, 2 => 196, -2 => 196, 3 => 114, -3 => 114, 4 => 56, -4 => 56, 5 => 20, -5 => 20, 6 => 4, -6 => 4)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] +[["Irrep[U₁]"]] +mps_virtualspaces = ["Rep[U₁](0 => 987, 1 => 830, -1 => 830, 2 => 432, -2 => 432, 3 => 161, -3 => 161, 4 => 77, -4 => 77, 5 => 28, -5 => 28, 6 => 7, -6 => 7, 7 => 1, -7 => 1)", "Rep[U₁](0 => 701, 1 => 635, -1 => 635, 2 => 478, -2 => 478, 3 => 303, -3 => 303, 4 => 162, -4 => 162, 5 => 70, -5 => 70, 6 => 22, -6 => 22, 7 => 4, -7 => 4)", "Rep[U₁](0 => 987, 1 => 830, -1 => 830, 2 => 431, -2 => 431, 3 => 161, -3 => 161, 4 => 77, -4 => 77, 5 => 28, -5 => 28, 6 => 7, -6 => 7, 7 => 1, -7 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))", "(Rep[U₁](0=>1) ⊞ Rep[U₁](0=>1, 1=>1, -1=>1) ⊞ Rep[U₁](0=>1))"] +physicalspaces = ["Rep[U₁](0 => 1, 1 => 1, -1 => 1)", "Rep[U₁](0 => 1, 1 => 1, -1 => 1)"] + +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](0 => 1)", "Rep[SU₂](1 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)", "Rep[SU₂](0 => 1, 1 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 3, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 1)", "Rep[SU₂](0 => 2, 1 => 3, 2 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)", "Rep[SU₂](0 => 2, 1 => 5, 2 => 4, 3 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)", "Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)", "Rep[SU₂](0 => 7, 1 => 14, 2 => 9, 3 => 2)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)", "Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)", "Rep[SU₂](0 => 13, 1 => 27, 2 => 21, 3 => 9, 4 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 23, 1 => 51, 2 => 46, 3 => 23, 4 => 8, 5 => 2)", "Rep[SU₂](0 => 24, 1 => 53, 2 => 47, 3 => 25, 4 => 7, 5 => 1)", "Rep[SU₂](0 => 25, 1 => 54, 2 => 48, 3 => 24, 4 => 7, 5 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 34, 1 => 79, 2 => 80, 3 => 56, 4 => 34, 5 => 18, 6 => 5, 7 => 1)", "Rep[SU₂](0 => 37, 1 => 86, 2 => 84, 3 => 57, 4 => 33, 5 => 15, 6 => 4, 7 => 1)", "Rep[SU₂](0 => 35, 1 => 82, 2 => 82, 3 => 58, 4 => 36, 5 => 16, 6 => 4)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 157, 1 => 398, 2 => 271, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)", "Rep[SU₂](0 => 66, 1 => 157, 2 => 175, 3 => 141, 4 => 92, 5 => 48, 6 => 18, 7 => 4)", "Rep[SU₂](0 => 157, 1 => 399, 2 => 270, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] +[["Irrep[SU₂]"]] +mps_virtualspaces = ["Rep[SU₂](0 => 1196, 1 => 1678, 2 => 483, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)", "Rep[SU₂](0 => 603, 1 => 1213, 2 => 280, 3 => 237, 4 => 153, 5 => 76, 6 => 28, 7 => 7, 8 => 1)", "Rep[SU₂](0 => 1198, 1 => 1646, 2 => 502, 3 => 84, 4 => 49, 5 => 21, 6 => 6, 7 => 1)"] +nonzero_keys = [[[1, 1], [3, 3], [2, 3], [1, 2]], [[1, 1], [3, 3], [2, 3], [1, 2]]] +mpo_virtualspaces = ["(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))", "(Rep[SU₂](0=>1) ⊞ Rep[SU₂](1=>1) ⊞ Rep[SU₂](0=>1))"] +physicalspaces = ["Rep[SU₂](1 => 1)", "Rep[SU₂](1 => 1)"] diff --git a/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl index 9842959d5..e1587648e 100644 --- a/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl +++ b/benchmark/MPSKitBenchmarks/scripts/setup_heisenberg.jl @@ -12,6 +12,9 @@ using .MPSKitBenchmarks using .MPSKitBenchmarks.DerivativesBenchmarks: AC2Spec using .MPSKitBenchmarks.BenchUtils: tomlify +# needed to make parsing correct +BlockTensorKit.SUMSPACE_SHOW_LIMIT[] = typemax(Int) + # Utility functions # ---------------- # setup "product state" -> ⨂^N |↑↓ - ↓↑⟩ @@ -50,9 +53,44 @@ D_steps = 10 D_min = 3 -# FiniteChain -# ----------- -L = 10 +# NN +# -- +L = 100 +lattice = FiniteChain(L) + +symmetry = SU2Irrep +alg = DMRG2(; + maxiter = 10, tol = 1.0e-12, + alg_eigsolve = (; tol = 1.0e-5, dynamic_tols = false, maxiter = 3), + trscheme = truncrank(D_max) +) + +H = heisenberg_XXX(T, symmetry, lattice; spin); +specs_su2 = generate_spaces(H, alg; D_min, D_steps) + +specs_triv = filter!(convert.(AC2Spec{ComplexSpace}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 1000 +end + +specs_u1 = filter!(convert.(AC2Spec{U1Space}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 5000 +end + +output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_nn.toml") +open(output_file, "w") do io + TOML.print( + io, Dict( + type_repr(Trivial) => tomlify.(specs_triv), + type_repr(U1Irrep) => tomlify.(specs_u1), + type_repr(SU2Irrep) => tomlify.(specs_su2) + ) + ) +end +@info("Spaces written to $output_file") + +# NNN +# --- +L = 100 lattice = FiniteChain(L) symmetry = SU2Irrep @@ -62,6 +100,10 @@ alg = DMRG2(; trscheme = truncrank(D_max) ) +SS = S_exchange(T, symmetry; spin) +H = @mpoham sum(next_nearest_neighbours(lattice)) do (i, j) + return SS{i, j} +end H = heisenberg_XXX(T, symmetry, lattice; spin); specs_su2 = generate_spaces(H, alg; D_min, D_steps) @@ -73,9 +115,86 @@ specs_u1 = filter!(convert.(AC2Spec{U1Space}, specs_su2)) do spec dim(spec.mps_virtualspaces[1]) < 5000 end -specs = vcat(specs_triv, specs_u1, specs_su2) +output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_nnn.toml") +open(output_file, "w") do io + TOML.print( + io, Dict( + type_repr(Trivial) => tomlify.(specs_triv), + type_repr(U1Irrep) => tomlify.(specs_u1), + type_repr(SU2Irrep) => tomlify.(specs_su2) + ) + ) +end +@info("Spaces written to $output_file") + +# FiniteCylinder +# -------------- +rows = 6 +cols = 12 +lattice = FiniteCylinder(rows, rows * cols) + +symmetry = SU2Irrep +alg = DMRG2(; + maxiter = 10, tol = 1.0e-12, + alg_eigsolve = (; tol = 1.0e-5, dynamic_tols = false, maxiter = 3), + trscheme = truncrank(D_max) +) + +H = heisenberg_XXX(T, symmetry, lattice; spin); +specs_su2 = generate_spaces(H, alg; D_min, D_steps) + +specs_triv = filter!(convert.(AC2Spec{ComplexSpace}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 1000 +end + +specs_u1 = filter!(convert.(AC2Spec{U1Space}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 5000 +end + +output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_cylinder.toml") +open(output_file, "w") do io + TOML.print( + io, Dict( + type_repr(Trivial) => tomlify.(specs_triv), + type_repr(U1Irrep) => tomlify.(specs_u1), + type_repr(SU2Irrep) => tomlify.(specs_su2) + ) + ) +end +@info("Spaces written to $output_file") + +# Coulomb +# ------- +L = 30 +symmetry = SU2Irrep +SS = S_exchange(T, symmetry; spin) +lattice = fill(space(SS, 1), L) +terms = [] +for i in 1:(L - 1), j in (i + 1):L + push!(terms, (i, j) => SS / abs(i - j)) +end +H = FiniteMPOHamiltonian(lattice, terms...); +H = changebonds(H, SvdCut(; trscheme = truncrank(500))); + +D_max = 1_000 +symmetry = SU2Irrep +alg = DMRG2(; + maxiter = 10, tol = 1.0e-12, + alg_eigsolve = (; tol = 1.0e-5, dynamic_tols = false, maxiter = 3), + trscheme = truncrank(D_max) +) + +specs_su2 = generate_spaces(H, alg; D_min, D_steps) + +specs_triv = filter!(convert.(AC2Spec{ComplexSpace}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 500 +end + +specs_u1 = filter!(convert.(AC2Spec{U1Space}, specs_su2)) do spec + dim(spec.mps_virtualspaces[1]) < 500 +end -output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_NN.toml") +output_file = joinpath(@__DIR__, "..", "derivatives", "heisenberg_coulomb.toml") open(output_file, "w") do io TOML.print( io, Dict( diff --git a/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl index c16f28ef1..3db7f8592 100644 --- a/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl +++ b/benchmark/MPSKitBenchmarks/utils/BenchUtils.jl @@ -6,7 +6,7 @@ using TensorKit using BlockTensorKit using TOML -tomlify(x::VectorSpace) = string(x) +tomlify(x::VectorSpace) = sprint(show, x; context = :limited => false) untomlify(::Type{<:VectorSpace}, x) = eval(Meta.parse(x)) @@ -17,7 +17,7 @@ function TensorKit.U1Space(V::SU2Space) dims = TensorKit.SectorDict{U1Irrep, Int}() for c in sectors(V), m in (-c.j):(c.j) u1 = U1Irrep(m) - dims[u1] = get(dims, u1, 0) + 1 + dims[u1] = get(dims, u1, 0) + dim(V, c) end return U1Space(dims; dual = isdual(V)) end From 4a29ddbbc547b459f32b2326360faac288504f24 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 3 Nov 2025 09:22:09 -0500 Subject: [PATCH 09/20] Precomputed derivatives I --- src/MPSKit.jl | 1 - .../derivatives/hamiltonian_derivatives.jl | 336 ------------------ src/algorithms/derivatives/mpo_derivatives.jl | 51 +++ 3 files changed, 51 insertions(+), 337 deletions(-) delete mode 100644 src/algorithms/derivatives/hamiltonian_derivatives.jl diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 7b18a31c6..20214813d 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -141,7 +141,6 @@ include("environments/lazylincocache.jl") include("algorithms/fixedpoint.jl") include("algorithms/derivatives/derivatives.jl") include("algorithms/derivatives/mpo_derivatives.jl") -include("algorithms/derivatives/hamiltonian_derivatives.jl") include("algorithms/derivatives/projection_derivatives.jl") include("algorithms/expval.jl") include("algorithms/toolbox.jl") diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl deleted file mode 100644 index 2b4f67235..000000000 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ /dev/null @@ -1,336 +0,0 @@ -""" - JordanMPO_AC_Hamiltonian{O1,O2,O3} - -Efficient operator for representing the single-site derivative of a `MPOHamiltonian` sandwiched between two MPSs. -In particular, this operator aims to make maximal use of the structure of the `MPOHamiltonian` to reduce the number of operations required to apply the operator to a tensor. -""" -struct JordanMPO_AC_Hamiltonian{O1, O2, O3} <: DerivativeOperator - D::Union{O1, Missing} # onsite - I::Union{O1, Missing} # not started - E::Union{O1, Missing} # finished - C::Union{O2, Missing} # starting - B::Union{O2, Missing} # ending - A::O3 # continuing - function JordanMPO_AC_Hamiltonian( - onsite, not_started, finished, starting, ending, continuing - ) - # obtaining storagetype of environments since these should have already mixed - # the types of the operator and state - gl = continuing[1] - S = spacetype(gl) - M = storagetype(gl) - O1 = tensormaptype(S, 1, 1, M) - O2 = tensormaptype(S, 2, 2, M) - return new{O1, O2, typeof(continuing)}( - onsite, not_started, finished, starting, ending, continuing - ) - end - function JordanMPO_AC_Hamiltonian{O1, O2, O3}( - onsite, not_started, finished, starting, ending, continuing - ) where {O1, O2, O3} - return new{O1, O2, O3}(onsite, not_started, finished, starting, ending, continuing) - end -end - -""" - JordanMPO_AC2_Hamiltonian{O1,O2,O3,O4} - -Efficient operator for representing the single-site derivative of a `MPOHamiltonian` sandwiched between two MPSs. -In particular, this operator aims to make maximal use of the structure of the `MPOHamiltonian` to reduce the number of operations required to apply the operator to a tensor. -""" -struct JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4} <: DerivativeOperator - II::Union{O1, Missing} # not_started - IC::Union{O2, Missing} # starting right - ID::Union{O1, Missing} # onsite right - CB::Union{O2, Missing} # starting left - ending right - CA::Union{O3, Missing} # starting left - continuing right - AB::Union{O3, Missing} # continuing left - ending right - AA::O4 # continuing left - continuing right - BE::Union{O2, Missing} # ending left - DE::Union{O1, Missing} # onsite left - EE::Union{O1, Missing} # finished - function JordanMPO_AC2_Hamiltonian(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - # obtaining storagetype of environments since these should have already mixed - # the types of the operator and state - gl = AA[1] - S = spacetype(gl) - M = storagetype(gl) - O1 = tensormaptype(S, 1, 1, M) - O2 = tensormaptype(S, 2, 2, M) - O3 = tensormaptype(S, 3, 3, M) - return new{O1, O2, O3, typeof(AA)}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - end - function JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4}( - II, IC, ID, CB, CA, AB, AA, BE, DE, EE - ) where {O1, O2, O3, O4} - return new{O1, O2, O3, O4}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - end -end - -# Constructors -# ------------ -const _HAM_MPS_TYPES = Union{ - FiniteMPS{<:MPSTensor}, - WindowMPS{<:MPSTensor}, - InfiniteMPS{<:MPSTensor}, -} - -function prepare_operator!!( - O::MPO_AC_Hamiltonian{<:Any, <:JordanMPOTensor, <:Any}, x::MPSTensor, - backend::AbstractBackend, allocator - ) - GL = O.leftenv - W = only(O.operators) - GR = O.rightenv - - # starting - if nonzero_length(W.C) > 0 - GR_2 = GR[2:(end - 1)] - @plansor starting_[-1 -2; -3 -4] ≔ W.C[-1; -3 1] * GR_2[-4 1; -2] - starting = only(starting_) - else - starting = missing - end - - # ending - if nonzero_length(W.B) > 0 - GL_2 = GL[2:(end - 1)] - @plansor ending_[-1 -2; -3 -4] ≔ GL_2[-1 1; -3] * W.B[1 -2; -4] - ending = only(ending_) - else - ending = missing - end - - # onsite - if nonzero_length(W.D) > 0 - if !ismissing(starting) - @plansor starting[-1 -2; -3 -4] += W.D[-1; -3] * removeunit(GR[end], 2)[-4; -2] - onsite = missing - elseif !ismissing(ending) - @plansor ending[-1 -2; -3 -4] += removeunit(GL[1], 2)[-1; -3] * W.D[-2; -4] - onsite = missing - else - onsite = W.D - end - else - onsite = missing - end - - # not_started - if size(W, 4) == 1 - not_started = missing - elseif !ismissing(starting) - I = id(storagetype(GR[1]), physicalspace(W)) - @plansor starting[-1 -2; -3 -4] += I[-1; -3] * removeunit(GR[1], 2)[-4; -2] - not_started = missing - else - not_started = removeunit(GR[1], 2) - end - - # finished - if size(W, 1) == 1 - finished = missing - elseif !ismissing(ending) - I = id(storagetype(GL[end]), physicalspace(W)) - @plansor ending[-1 -2; -3 -4] += removeunit(GL[end], 2)[-1; -3] * I[-2; -4] - finished = missing - else - finished = removeunit(GL[end], 2) - end - - # continuing - A = W.A - continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) - - O′ = JordanMPO_AC_Hamiltonian( - onsite, not_started, finished, starting, ending, continuing - ) - - return O′, x -end - -function prepare_operator!!( - O::MPO_AC2_Hamiltonian{<:Any, <:JordanMPOTensor, <:JordanMPOTensor, <:Any}, x::MPOTensor, - backend::AbstractBackend, allocator - ) - GL = O.leftenv - W1, W2 = O.operators - GR = O.rightenv - - # starting left - continuing right - if nonzero_length(W1.C) > 0 && nonzero_length(W2.A) > 0 - @plansor CA_[-1 -2 -3; -4 -5 -6] ≔ W1.C[-1; -4 2] * W2.A[2 -2; -5 1] * - GR[2:(end - 1)][-6 1; -3] - CA = only(CA_) - else - CA = missing - end - - # continuing left - ending right - if nonzero_length(W1.A) > 0 && nonzero_length(W2.B) > 0 - @plansor AB_[-1 -2 -3; -4 -5 -6] ≔ GL[2:(end - 1)][-1 2; -4] * W1.A[2 -2; -5 1] * - W2.B[1 -3; -6] - AB = only(AB_) - else - AB = missing - end - - # middle - if nonzero_length(W1.C) > 0 && nonzero_length(W2.B) > 0 - if !ismissing(CA) - @plansor CA[-1 -2 -3; -4 -5 -6] += W1.C[-1; -4 1] * W2.B[1 -2; -5] * - removeunit(GR[end], 2)[-6; -3] - CB = missing - elseif !ismissing(AB) - @plansor AB[-1 -2 -3; -4 -5 -6] += removeunit(GL[1], 2)[-1; -4] * - W1.C[-2; -5 1] * W2.B[1 -3; -6] - CB = missing - else - @plansor CB_[-1 -2; -3 -4] ≔ W1.C[-1; -3 1] * W2.B[1 -2; -4] - CB = only(CB_) - end - else - CB = missing - end - - # starting right - if nonzero_length(W2.C) > 0 - if !ismissing(CA) - I = id(storagetype(GR[1]), physicalspace(W1)) - @plansor CA[-1 -2 -3; -4 -5 -6] += (I[-1; -4] * W2.C[-2; -5 1]) * - GR[2:(end - 1)][-6 1; -3] - IC = missing - else - @plansor IC[-1 -2; -3 -4] ≔ W2.C[-1; -3 1] * GR[2:(end - 1)][-4 1; -2] - end - else - IC = missing - end - - # ending left - if nonzero_length(W1.B) > 0 - if !ismissing(AB) - I = id(storagetype(GL[end]), physicalspace(W2)) - @plansor AB[-1 -2 -3; -4 -5 -6] += GL[2:(end - 1)][-1 1; -4] * - (W1.B[1 -2; -5] * I[-3; -6]) - BE = missing - else - @plansor BE[-1 -2; -3 -4] ≔ GL[2:(end - 1)][-1 2; -3] * W1.B[2 -2; -4] - end - else - BE = missing - end - - # onsite left - if nonzero_length(W1.D) > 0 - if !ismissing(BE) - @plansor BE[-1 -2; -3 -4] += removeunit(GL[1], 2)[-1; -3] * W1.D[-2; -4] - DE = missing - elseif !ismissing(AB) - I = id(storagetype(GL[end]), physicalspace(W2)) - @plansor AB[-1 -2 -3; -4 -5 -6] += removeunit(GL[1], 2)[-1; -4] * - (W1.D[-2; -5] * I[-3; -6]) - DE = missing - # TODO: could also try in CA? - else - DE = only(W1.D) - end - else - DE = missing - end - - # onsite right - if nonzero_length(W2.D) > 0 - if !ismissing(IC) - @plansor IC[-1 -2; -3 -4] += W2.D[-1; -3] * removeunit(GR[end], 2)[-4; -2] - ID = missing - elseif !ismissing(CA) - I = id(storagetype(GR[1]), physicalspace(W1)) - @plansor CA[-1 -2 -3; -4 -5 -6] += (I[-1; -4] * W2.D[-2; -5]) * - removeunit(GR[end], 2)[-6; -3] - ID = missing - else - ID = only(W2.D) - end - else - ID = missing - end - - # finished - if size(W2, 4) == 1 - II = missing - elseif !ismissing(IC) - I = id(storagetype(GR[1]), physicalspace(W2)) - @plansor IC[-1 -2; -3 -4] += I[-1; -3] * removeunit(GR[1], 2)[-4; -2] - II = missing - elseif !ismissing(CA) - I = id(storagetype(GR[1]), physicalspace(W1) ⊗ physicalspace(W2)) - @plansor CA[-1 -2 -3; -4 -5 -6] += I[-1 -2; -4 -5] * removeunit(GR[1], 2)[-6; -3] - II = missing - else - II = transpose(removeunit(GR[1], 2)) - end - - # unstarted - if size(W1, 1) == 1 - EE = missing - elseif !ismissing(BE) - I = id(storagetype(GL[end]), physicalspace(W1)) - @plansor BE[-1 -2; -3 -4] += removeunit(GL[end], 2)[-1; -3] * I[-2; -4] - EE = missing - elseif !ismissing(AB) - I = id(storagetype(GL[end]), physicalspace(W1) ⊗ physicalspace(W2)) - @plansor AB[-1 -2 -3; -4 -5 -6] += removeunit(GL[end], 2)[-1; -4] * I[-2 -3; -5 -6] - EE = missing - else - EE = removeunit(GL[end], 2) - end - - # continuing - continuing - # TODO: MPODerivativeOperator code reuse + optimization - AA = (GL[2:(end - 1)], W1.A, W2.A, GR[2:(end - 1)]) - - O′ = JordanMPO_AC2_Hamiltonian(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - return O′, x -end - -# Actions -# ------- -function (H::JordanMPO_AC_Hamiltonian)(x::MPSTensor) - y = zerovector(x) - - ismissing(H.D) || @plansor y[-1 -2; -3] += x[-1 1; -3] * H.D[-2; 1] - ismissing(H.E) || @plansor y[-1 -2; -3] += H.E[-1; 1] * x[1 -2; -3] - ismissing(H.I) || @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.I[1; -3] - ismissing(H.C) || @plansor y[-1 -2; -3] += x[-1 2; 1] * H.C[-2 -3; 2 1] - ismissing(H.B) || @plansor y[-1 -2; -3] += H.B[-1 -2; 1 2] * x[1 2; -3] - - GL, A, GR = H.A - if nonzero_length(A) > 0 - @plansor y[-1 -2; -3] += GL[-1 5; 4] * x[4 2; 1] * A[5 -2; 2 3] * GR[1 3; -3] - end - - return y -end - -function (H::JordanMPO_AC2_Hamiltonian)(x::MPOTensor) - y = zerovector(x) - ismissing(H.II) || @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 -4] * H.II[-3; 1] - ismissing(H.IC) || @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 2] * H.IC[-4 -3; 2 1] - ismissing(H.ID) || @plansor y[-1 -2; -3 -4] += x[-1 -2; -3 1] * H.ID[-4; 1] - ismissing(H.CB) || @plansor y[-1 -2; -3 -4] += x[-1 1; -3 2] * H.CB[-2 -4; 1 2] - ismissing(H.CA) || @plansor y[-1 -2; -3 -4] += x[-1 1; 3 2] * H.CA[-2 -4 -3; 1 2 3] - ismissing(H.AB) || @plansor y[-1 -2; -3 -4] += x[1 2; -3 3] * H.AB[-1 -2 -4; 1 2 3] - ismissing(H.BE) || @plansor y[-1 -2; -3 -4] += x[1 2; -3 -4] * H.BE[-1 -2; 1 2] - ismissing(H.DE) || @plansor y[-1 -2; -3 -4] += x[-1 1; -3 -4] * H.DE[-2; 1] - ismissing(H.EE) || @plansor y[-1 -2; -3 -4] += x[1 -2; -3 -4] * H.EE[-1; 1] - - GL, A1, A2, GR = H.AA - if nonzero_length(A1) > 0 && nonzero_length(A2) > 0 - # TODO: there are too many entries here, this could be further optimized - @plansor y[-1 -2; -3 -4] += GL[-1 7; 6] * x[6 5; 1 3] * A1[7 -2; 5 4] * - A2[4 -4; 3 2] * GR[1 2; -3] - end - - return y -end diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 12b030b1e..32e91b7c6 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -105,3 +105,54 @@ function (h::MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTen h.operators[2][7 -6; 4 5] * τ[5 -5; 2 3] return y isa AbstractBlockTensorMap ? only(y) : y end + +# prepared operators +# ------------------ +struct PrecomputedDerivative{ + T <: Number, S <: ElementarySpace, N₁, N₂, N₃, N₄, + T1 <: AbstractTensorMap{T, S, N₁, N₂}, T2 <: AbstractTensorMap{T, S, N₃, N₄}, + B <: AbstractBackend, A, + } <: DerivativeOperator + leftenv::T1 + rightenv::T2 + backend::B + allocator::A +end + +const PrecomputedACDerivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 2, 1} +const PrecomputedAC2Derivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 3, 2} + +function prepare_operator!!( + H::MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, + x::MPSTensor, + backend::AbstractBackend, allocator + ) + @plansor backend = backend allocator = allocator begin + GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] + end + return PrecomputedDerivative(TensorMap(GL_O), TensorMap(H.rightenv), backend, allocator), x +end + +function prepare_operator!!( + H::MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTensor}, + x::MPOTensor, + backend::AbstractBackend, allocator + ) + @plansor backend = backend allocator = allocator begin + GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] + O_GR[-1 -2 -3; -4 -5] := H.operators[2][-3 -5; -2 1] * H.rightenv[-1 1; -4] + end + return PrecomputedDerivative(TensorMap(GL_O), TensorMap(O_GR), backend, allocator), x +end + +function (H::PrecomputedDerivative)(x::MPSTensor) + return @plansor backend = H.backend allocator = H.allocator begin + y[-1 -2; -3] ≔ H.leftenv[-1 -2 4; 1 2] * x[1 2; 3] * H.rightenv[3 4; -3] + end +end + +function (H::PrecomputedAC2Derivative)(x::MPOTensor) + return @plansor backend = H.backend allocator = H.allocator begin + y[-1 -2; -3 -4] ≔ H.leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * H.rightenv[3 4 5; -3 -4] + end +end From bbda4fda7341b78909a7db8cd8c9fcd6c082a134 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 3 Nov 2025 11:36:56 -0500 Subject: [PATCH 10/20] Precomputed derivatives II --- src/algorithms/derivatives/mpo_derivatives.jl | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 32e91b7c6..11af18cef 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -130,7 +130,12 @@ function prepare_operator!!( @plansor backend = backend allocator = allocator begin GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] end - return PrecomputedDerivative(TensorMap(GL_O), TensorMap(H.rightenv), backend, allocator), x + leftenv = TensorMap(GL_O) + rightenv = TensorMap(H.rightenv) + BraidingStyle(sectortype(rightenv)) === NoBraiding() || + (rightenv = braid(rightenv, ((2, 1), (3,)), (1, 2, 3))) + + return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x end function prepare_operator!!( @@ -142,17 +147,59 @@ function prepare_operator!!( GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] O_GR[-1 -2 -3; -4 -5] := H.operators[2][-3 -5; -2 1] * H.rightenv[-1 1; -4] end - return PrecomputedDerivative(TensorMap(GL_O), TensorMap(O_GR), backend, allocator), x + leftenv = TensorMap(GL_O) + rightenv = TensorMap(O_GR) + BraidingStyle(sectortype(rightenv)) === NoBraiding() || + (rightenv = braid(rightenv, ((3, 1, 2), (4, 5)), (1, 2, 3, 4, 5))) + return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x end function (H::PrecomputedDerivative)(x::MPSTensor) - return @plansor backend = H.backend allocator = H.allocator begin - y[-1 -2; -3] ≔ H.leftenv[-1 -2 4; 1 2] * x[1 2; 3] * H.rightenv[3 4; -3] + bstyle = BraidingStyle(sectortype(x)) + return _precontracted_ac_derivative(bstyle, x, H.leftenv, H.rightenv, H.backend, H.allocator) +end + +function _precontracted_ac_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) + return @planar backend = backend allocator = allocator begin + y[-1 -2; -3] ≔ leftenv[-1 -2 4; 1 2] * x[1 2; 3] * rightenv[3 4; -3] + end +end +function _precontracted_ac_derivative(::Bosonic, x, leftenv, rightenv, backend, allocator) + return @tensor backend = backend allocator = allocator begin + y[-1 -2; -3] ≔ leftenv[-1 -2 4; 1 2] * x[1 2; 3] * rightenv[4 3; -3] + end +end +function _precontracted_ac_derivative(::BraidingStyle, x, leftenv, rightenv, backend, allocator) + @planar backend = backend allocator = allocator begin + tmp[-1 -2 -3; -4] := leftenv[-1 -2 -3; 1 2] * x[1 2; -4] + end + tmp2 = braid(tmp, ((1, 2), (3, 4)), (1, 2, 4, 3)) + return @planar backend = backend allocator = allocator begin + y[-1 -2; -3] ≔ tmp2[-1 -2; 1 2] * rightenv[1 2; -3] end end function (H::PrecomputedAC2Derivative)(x::MPOTensor) - return @plansor backend = H.backend allocator = H.allocator begin - y[-1 -2; -3 -4] ≔ H.leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * H.rightenv[3 4 5; -3 -4] + bstyle = BraidingStyle(sectortype(x)) + return _precontracted_ac2_derivative(bstyle, x, H.leftenv, H.rightenv, H.backend, H.allocator) +end + +function _precontracted_ac2_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) + return @planar backend = backend allocator = allocator begin + y[-1 -2; -3 -4] ≔ leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * rightenv[3 4 5; -3 -4] + end +end +function _precontracted_ac2_derivative(::Bosonic, x, leftenv, rightenv, backend, allocator) + return @tensor backend = backend allocator = allocator begin + y[-1 -2; -3 -4] ≔ leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * rightenv[5 3 4; -3 -4] + end +end +function _precontracted_ac2_derivative(::BraidingStyle, x, leftenv, rightenv, backend, allocator) + @planar backend = backend allocator = allocator begin + tmp[-1 -2 -3; -4 -5] := leftenv[-1 -2 -3; 1 2] * x[1 2; -4 -5] + end + tmp2 = braid(tmp, ((1, 2), (3, 4, 5)), (1, 2, 5, 3, 4)) + return @planar backend = backend allocator = allocator begin + y[-1 -2; -3 -4] := tmp2[-1 -2; 1 2 3] * rightenv[1 2 3; -3 -4] end end From 0f7d54660cf13ad16b85e84f9847466f49ca4f7f Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 3 Nov 2025 13:35:29 -0500 Subject: [PATCH 11/20] Precomputed derivatives III --- src/algorithms/derivatives/mpo_derivatives.jl | 107 +++++++++++------- 1 file changed, 66 insertions(+), 41 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 11af18cef..5a4bed915 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -119,23 +119,25 @@ struct PrecomputedDerivative{ allocator::A end -const PrecomputedACDerivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 2, 1} -const PrecomputedAC2Derivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 3, 2} +const PrecomputedACDerivative{T, S} = PrecomputedDerivative{T, S, 2, 1, 2, 1} function prepare_operator!!( H::MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, x::MPSTensor, backend::AbstractBackend, allocator ) - @plansor backend = backend allocator = allocator begin - GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] - end - leftenv = TensorMap(GL_O) - rightenv = TensorMap(H.rightenv) - BraidingStyle(sectortype(rightenv)) === NoBraiding() || - (rightenv = braid(rightenv, ((2, 1), (3,)), (1, 2, 3))) + F_left = fuser(scalartype(x), codomain(x)...) + x′ = F_left * x + + leftenv = left_precontract_derivative(H.leftenv, H.operators[1], F_left, backend, allocator) + rightenv = right_precontract_derivative(H.rightenv, backend, allocator) + + return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x′ +end - return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x +function unprepare_operator!!(y::MPSBondTensor, ::PrecomputedACDerivative, x::MPSTensor) + F_left = fuser(scalartype(x), codomain(x)...) + return F_left' * y end function prepare_operator!!( @@ -143,63 +145,86 @@ function prepare_operator!!( x::MPOTensor, backend::AbstractBackend, allocator ) - @plansor backend = backend allocator = allocator begin - GL_O[-1 -2 -3; -4 -5] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] - O_GR[-1 -2 -3; -4 -5] := H.operators[2][-3 -5; -2 1] * H.rightenv[-1 1; -4] - end - leftenv = TensorMap(GL_O) - rightenv = TensorMap(O_GR) - BraidingStyle(sectortype(rightenv)) === NoBraiding() || - (rightenv = braid(rightenv, ((3, 1, 2), (4, 5)), (1, 2, 3, 4, 5))) - return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x + F_left = fuser(scalartype(x), codomain(x)...) + F_right = fuser(scalartype(x), domain(x)...) + x′ = F_left * x * F_right' + + leftenv = left_precontract_derivative(H.leftenv, H.operators[1], F_left, backend, allocator) + rightenv = right_precontract_derivative(H.rightenv, H.operators[2], F_right, backend, allocator) + + return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x′ +end + +function unprepare_operator!!(y::MPSBondTensor, ::PrecomputedDerivative, x::MPOTensor) + F_left = fuser(scalartype(x), codomain(x)...) + F_right = fuser(scalartype(x), domain(x)...) + return F_left' * y * F_right end -function (H::PrecomputedDerivative)(x::MPSTensor) +function (H::PrecomputedDerivative)(x::MPSBondTensor) bstyle = BraidingStyle(sectortype(x)) return _precontracted_ac_derivative(bstyle, x, H.leftenv, H.rightenv, H.backend, H.allocator) end -function _precontracted_ac_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) - return @planar backend = backend allocator = allocator begin - y[-1 -2; -3] ≔ leftenv[-1 -2 4; 1 2] * x[1 2; 3] * rightenv[3 4; -3] - end -end function _precontracted_ac_derivative(::Bosonic, x, leftenv, rightenv, backend, allocator) return @tensor backend = backend allocator = allocator begin - y[-1 -2; -3] ≔ leftenv[-1 -2 4; 1 2] * x[1 2; 3] * rightenv[4 3; -3] + y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[3 2; -2] end end function _precontracted_ac_derivative(::BraidingStyle, x, leftenv, rightenv, backend, allocator) - @planar backend = backend allocator = allocator begin - tmp[-1 -2 -3; -4] := leftenv[-1 -2 -3; 1 2] * x[1 2; -4] + return @planar backend = backend allocator = allocator begin + y[-1; -2] := leftenv[-1 2; 1] * x[1; 3] * τ'[3 2; 4 5] * rightenv[4 5; -2] end - tmp2 = braid(tmp, ((1, 2), (3, 4)), (1, 2, 4, 3)) +end +function _precontracted_ac_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) return @planar backend = backend allocator = allocator begin - y[-1 -2; -3] ≔ tmp2[-1 -2; 1 2] * rightenv[1 2; -3] + y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] end end -function (H::PrecomputedAC2Derivative)(x::MPOTensor) - bstyle = BraidingStyle(sectortype(x)) - return _precontracted_ac2_derivative(bstyle, x, H.leftenv, H.rightenv, H.backend, H.allocator) +left_precontract_derivative(arg, args...) = _left_precontract_derivative(BraidingStyle(sectortype(arg)), arg, args...) +function _left_precontract_derivative(::BraidingStyle, leftenv, operator, F, backend, allocator) + @planar backend = backend allocator = allocator begin + GL_O[-1 -2 -3; -4 -5] := leftenv[-1 1; -4] * operator[1 -2; -5 -3] + end + return @planar backend = backend allocator = allocator begin + leftenv[-1 -2; -3] := F[-1; 3 4] * TensorMap(GL_O)[3 4 -2; 1 2] * F'[1 2; -3] + end end -function _precontracted_ac2_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) +right_precontract_derivative(arg, args...) = _right_precontract_derivative(BraidingStyle(sectortype(arg)), arg, args...) +_right_precontract_derivative(::NoBraiding, rightenv, backend, allocator) = TensorMap(rightenv) +function _right_precontract_derivative(::Bosonic, rightenv, backend, allocator) + return @tensor backend = backend allocator = allocator begin + rightenv[-2 -1; -3] := TensorMap(rightenv)[-1 -2; -3] + end +end +function _right_precontract_derivative(::BraidingStyle, rightenv, backend, allocator) return @planar backend = backend allocator = allocator begin - y[-1 -2; -3 -4] ≔ leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * rightenv[3 4 5; -3 -4] + rightenv[-1 -2; -3] := τ[-1 -2; 1 2] * TensorMap(rightenv)[1 2; -3] end end -function _precontracted_ac2_derivative(::Bosonic, x, leftenv, rightenv, backend, allocator) +function _right_precontract_derivative(::NoBraiding, rightenv, operator, F, backend, allocator) + @planar backend = backend allocator = allocator begin + O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] + end + return @planar backend = backend allocator = allocator begin + rightenv[-1 -2; -3] := F[-1; 3 4] * TensorMap(O_GR)[3 4 -2; 1 2] * F'[1 2; -3] + end +end +function _right_precontract_derivative(::Bosonic, rightenv, operator, F, backend, allocator) + @tensor backend = backend allocator = allocator begin + O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] + end return @tensor backend = backend allocator = allocator begin - y[-1 -2; -3 -4] ≔ leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * rightenv[5 3 4; -3 -4] + rightenv[-2 -1; -3] := F[-1; 3 4] * TensorMap(O_GR)[3 4 -2; 1 2] * F'[1 2; -3] end end -function _precontracted_ac2_derivative(::BraidingStyle, x, leftenv, rightenv, backend, allocator) +function _right_precontract_derivative(::BraidingStyle, rightenv, operator, F, backend, allocator) @planar backend = backend allocator = allocator begin - tmp[-1 -2 -3; -4 -5] := leftenv[-1 -2 -3; 1 2] * x[1 2; -4 -5] + O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] end - tmp2 = braid(tmp, ((1, 2), (3, 4, 5)), (1, 2, 5, 3, 4)) return @planar backend = backend allocator = allocator begin - y[-1 -2; -3 -4] := tmp2[-1 -2; 1 2 3] * rightenv[1 2 3; -3 -4] + rightenv[-1 -2; -3] := τ[-1 -2; 5 6] * F[5; 3 4] * TensorMap(O_GR)[3 4 6; 1 2] * F'[1 2; -3] end end From b5f68cdb157a9a8d8e8e920b20d48eb86af83f88 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 4 Nov 2025 11:05:23 -0500 Subject: [PATCH 12/20] add plot script --- .gitignore | 1 + benchmark/Project.toml | 2 + benchmark/plot_results.jl | 300 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 303 insertions(+) create mode 100644 benchmark/plot_results.jl diff --git a/.gitignore b/.gitignore index b0acbe33b..8e2b6fec5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ Manifest.toml .vscode .DS_Store **/dev/ +benchmark/results diff --git a/benchmark/Project.toml b/benchmark/Project.toml index 891d982fa..5719a0f6c 100644 --- a/benchmark/Project.toml +++ b/benchmark/Project.toml @@ -2,6 +2,8 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" diff --git a/benchmark/plot_results.jl b/benchmark/plot_results.jl new file mode 100644 index 000000000..1fa2af692 --- /dev/null +++ b/benchmark/plot_results.jl @@ -0,0 +1,300 @@ +using JSON +using DataFrames +using CairoMakie +using Statistics + +# Loading in the data +# ------------------- +resultdir = joinpath(@__DIR__, "results") +resultfile(i) = "results_MPSKit@bench$i.json" + +df_contract = let df = DataFrame( + :version => Int[], :model => String[], :symmetry => String[], + :D => Int[], :V => Int[], :memory => Int[], :allocs => Int[], :times => Vector{Int}[] + ) + + for version in 0:3 + result = JSON.parsefile(joinpath(resultdir, resultfile(version))) + for (model, model_res) in result.data.derivatives.data.AC2_contraction.data + for (symmetry, sym_res) in model_res.data + for (DV, bench) in sym_res.data + D, V = eval(Meta.parse(DV))::Tuple{Int, Int} + + push!( + df, + (version, model, symmetry, D, V, bench.memory, bench.allocs, collect(Int, bench.times)) + ) + end + end + end + end + df +end +df_prep = let df = DataFrame( + :version => Int[], :model => String[], :symmetry => String[], + :D => Int[], :V => Int[], :memory => Int[], :allocs => Int[], :times => Vector{Int}[] + ) + + for version in 0:3 + result = JSON.parsefile(joinpath(resultdir, resultfile(version))) + for (model, model_res) in result.data.derivatives.data.AC2_preparation.data + for (symmetry, sym_res) in model_res.data + for (DV, bench) in sym_res.data + D, V = eval(Meta.parse(DV))::Tuple{Int, Int} + + push!( + df, + (version, model, symmetry, D, V, bench.memory, bench.allocs, collect(Int, bench.times)) + ) + end + end + end + end + df +end + +# Plotting the results +# -------------------- +fontsize = 20 +estimator = median + +f_times = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "Δt (μs)", yscale = log10) + @assert !isnothing(df_data) + for (k, v) in pairs(groupby(df_data, :version)) + Ds = v[!, :D] + times = estimator.(v[!, :times]) ./ 1.0e3 + I = sortperm(Ds) + scatterlines!(ax, Ds[I], times[I]; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "times"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f +end +save(joinpath(resultdir, "bench_times.png"), f_times) + +f_times_relative = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "Δt / Δt₀") + hlines!([1], color = :red) + @assert !isnothing(df_data) + + df_v = groupby(df_data, :version) + + v = get(df_v, (; version = 0), nothing) + Ds = v[!, :D] + times = estimator.(v[!, :times]) + I = sortperm(Ds) + times₀ = times[I] + + for (k, v) in pairs(groupby(df_data, :version)) + k.version == 0 && continue + Ds = v[!, :D] + I = sortperm(Ds) + times = estimator.(v[!, :times])[I] + scatterlines!(ax, Ds[I], times ./ times₀; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "times"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f +end +save(joinpath(resultdir, "bench_times_relative.png"), f_times_relative) + +f_allocs = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "allocs", yscale = log10) + @assert !isnothing(df_data) + for (k, v) in pairs(groupby(df_data, :version)) + Ds = v[!, :D] + allocs = estimator.(v[!, :allocs]) + I = sortperm(Ds) + scatterlines!(ax, Ds[I], allocs[I]; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "allocs"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f +end +save(joinpath(resultdir, "bench_allocs.png"), f_allocs) + +f_memory = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "memory (KiB)", yscale = log10) + @assert !isnothing(df_data) + for (k, v) in pairs(groupby(df_data, :version)) + Ds = v[!, :D] + memory = estimator.(v[!, :memory]) ./ (2^10) + I = sortperm(Ds) + scatterlines!(ax, Ds[I], memory[I]; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "memory"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f +end +save(joinpath(resultdir, "bench_memory.png"), f_allocs) + +f_memory_relative = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "memory / memory₀") + hlines!([1], color = :red) + @assert !isnothing(df_data) + + df_v = groupby(df_data, :version) + + v = get(df_v, (; version = 0), nothing) + Ds = v[!, :D] + times = estimator.(v[!, :memory]) + I = sortperm(Ds) + times₀ = times[I] + + for (k, v) in pairs(groupby(df_data, :version)) + k.version == 0 && continue + Ds = v[!, :D] + I = sortperm(Ds) + times = estimator.(v[!, :memory])[I] + scatterlines!(ax, Ds[I], times ./ times₀; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "memory (relative)"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f +end +save(joinpath(resultdir, "bench_memory_relative.png"), f_memory_relative) + + +# Including preparation times +# --------------------------- +for n_applications in [3, 10, 30] + f_times_relative = let f = Figure(; size = (1400, 1400)) + models = ["heisenberg_nn", "heisenberg_nnn", "heisenberg_cylinder", "heisenberg_coulomb"] + symmetries = ["Trivial", "Irrep[U₁]", "Irrep[SU₂]"] + + + df_model = groupby(df_contract, [:model, :symmetry]) + dfp_model = groupby(df_prep, [:model, :symmetry]) + for row in eachindex(models), col in eachindex(symmetries) + df_data = get(df_model, (; model = models[row], symmetry = symmetries[col]), nothing) + dfp_data = get(dfp_model, (; model = models[row], symmetry = symmetries[col]), nothing) + ax = Axis(f[row, col], xscale = log10, xlabel = "D", ylabel = "Δt / Δt₀") + hlines!([1], color = :red) + @assert !isnothing(df_data) && !isnothing(dfp_data) + + df_v = groupby(df_data, :version) + dfp_v = groupby(dfp_data, :version) + + v = get(df_v, (; version = 0), nothing) + Ds = v[!, :D] + times = estimator.(v[!, :times]) + I = sortperm(Ds) + times₀ = n_applications .* times[I] + + vp = get(dfp_v, (; version = 0), nothing) + Ds = vp[!, :D] + times = estimator.(vp[!, :times]) + I = sortperm(Ds) + times₀ .+= times[I] + + df_data_v = groupby(dfp_data, :version) + for (k, v) in pairs(groupby(df_data, :version)) + k.version == 0 && continue + Ds = v[!, :D] + I = sortperm(Ds) + times = n_applications .* estimator.(v[!, :times])[I] + + vp = get(df_data_v, (; k.version), nothing) + @assert !isnothing(vp) + Ds = vp[!, :D] + I = sortperm(Ds) + times .+= estimator.(vp[!, :times][I]) + + scatterlines!(ax, Ds[I], times ./ times₀; label = "v$(k.version)") + end + axislegend(ax, position = :lt) + end + + Label(f[0, 0], "times"; fontsize) + for (row, model) in enumerate(models) + Label(f[row, 0], model; rotation = pi / 2, fontsize, tellheight = false, tellwidth = false) + end + for (col, symmetry) in enumerate(symmetries) + Label(f[0, col], symmetry; fontsize, tellheight = false, tellwidth = false) + end + + f + end + save(joinpath(resultdir, "bench_prep_times_relative_n=$n_applications.png"), f_times_relative) +end From 946cc633e2d1af896f7e460aa62720b155e68b92 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 14 Dec 2025 08:14:24 -0500 Subject: [PATCH 13/20] Precomputed derivatives IV Revert "Precomputed derivatives III" This reverts commit d704ccf12d6027e30750878527620a1d555259fa. Precomputed derivatives IV Precomputed derivatives V reduce test terminal clutter update plots script playing around with more kernels remove piracy rework jordanmpo small fix --- benchmark/Project.toml | 2 + benchmark/plot_results.jl | 6 +- src/MPSKit.jl | 2 + src/algorithms/derivatives/derivatives.jl | 26 +- .../derivatives/hamiltonian_derivatives.jl | 365 ++++++++++++++++++ src/algorithms/derivatives/mpo_derivatives.jl | 178 +++++---- src/algorithms/fixedpoint.jl | 16 +- src/utility/multiline.jl | 4 +- src/utility/utility.jl | 109 +++++- test/algorithms.jl | 2 +- 10 files changed, 581 insertions(+), 129 deletions(-) create mode 100644 src/algorithms/derivatives/hamiltonian_derivatives.jl diff --git a/benchmark/Project.toml b/benchmark/Project.toml index 5719a0f6c..c1f0ff408 100644 --- a/benchmark/Project.toml +++ b/benchmark/Project.toml @@ -4,7 +4,9 @@ BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +MKL = "33e6dc65-8f57-5167-99aa-e5a354878fb2" MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" +TensorKitManifolds = "11fa318c-39cb-4a83-b1ed-cdc7ba1e3684" diff --git a/benchmark/plot_results.jl b/benchmark/plot_results.jl index 1fa2af692..ce3857d62 100644 --- a/benchmark/plot_results.jl +++ b/benchmark/plot_results.jl @@ -8,12 +8,14 @@ using Statistics resultdir = joinpath(@__DIR__, "results") resultfile(i) = "results_MPSKit@bench$i.json" +versions = [0, 1, 2, 3, 5] + df_contract = let df = DataFrame( :version => Int[], :model => String[], :symmetry => String[], :D => Int[], :V => Int[], :memory => Int[], :allocs => Int[], :times => Vector{Int}[] ) - for version in 0:3 + for version in versions result = JSON.parsefile(joinpath(resultdir, resultfile(version))) for (model, model_res) in result.data.derivatives.data.AC2_contraction.data for (symmetry, sym_res) in model_res.data @@ -35,7 +37,7 @@ df_prep = let df = DataFrame( :D => Int[], :V => Int[], :memory => Int[], :allocs => Int[], :times => Vector{Int}[] ) - for version in 0:3 + for version in versions result = JSON.parsefile(joinpath(resultdir, resultfile(version))) for (model, model_res) in result.data.derivatives.data.AC2_preparation.data for (symmetry, sym_res) in model_res.data diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 20214813d..ec9c05ae9 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -60,6 +60,7 @@ using Compat: @compat # ------- using TensorKit using TensorKit: BraidingTensor +using TensorKit: TupleTools as TT using MatrixAlgebraKit using MatrixAlgebraKit: TruncationStrategy, PolarViaSVD, LAPACK_SVDAlgorithm using BlockTensorKit @@ -141,6 +142,7 @@ include("environments/lazylincocache.jl") include("algorithms/fixedpoint.jl") include("algorithms/derivatives/derivatives.jl") include("algorithms/derivatives/mpo_derivatives.jl") +include("algorithms/derivatives/hamiltonian_derivatives.jl") include("algorithms/derivatives/projection_derivatives.jl") include("algorithms/expval.jl") include("algorithms/toolbox.jl") diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 1e65c3f15..a3008c872 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -217,27 +217,15 @@ Base.:*(h::LazySum{<:Union{DerivativeOrMultiplied}}, v) = h(v) # Operator preparation # -------------------- """ - prepare_operator!!(O, x, [backend], [allocator]) -> O′, x′ + prepare_operator!!(O, [backend], [allocator]) -> O′ Given an operator and vector, try to construct a more efficient representation of that operator for repeated application. This should always be used in conjunction with [`unprepare_operator!!`](@ref). """ -function prepare_operator!!( - O, x, - backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() - ) - return O, x -end - -""" - unprepare_operator!!(y, O, x, [backend], [allocator]) -> y′ +prepare_operator!!(O, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = O -Given the result `y` of applying a prepared operator `O` on vectors like `x`, undo the preparation work on the vector, and clean up the operator. -This should always be used in conjunction with [`prepare_operator!!`](@ref). -""" -function unprepare_operator!!( - y, O, x, - backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() - ) - return y -end +# to make benchmark scripts run +prepare_operator!!(O, x::AbstractTensorMap, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = + prepare_operator!!(O, backend, allocator), x +unprepare_operator!!(y, O, x, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = + y diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl new file mode 100644 index 000000000..534553580 --- /dev/null +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -0,0 +1,365 @@ +const _HAM_MPS_TYPES = Union{ + FiniteMPS{<:MPSTensor}, + WindowMPS{<:MPSTensor}, + InfiniteMPS{<:MPSTensor}, +} + +# Single site derivative +# ---------------------- +""" + JordanMPO_AC_Hamiltonian{O1,O2,O3} + +Efficient operator for representing the single-site derivative of a `MPOHamiltonian` sandwiched between two MPSs. +In particular, this operator aims to make maximal use of the structure of the `MPOHamiltonian` to reduce the number of operations required to apply the operator to a tensor. +""" +struct JordanMPO_AC_Hamiltonian{O1, O2, O3} <: DerivativeOperator + D::Union{O1, Missing} # onsite + I::Union{O1, Missing} # not started + E::Union{O1, Missing} # finished + C::Union{O2, Missing} # starting + B::Union{O2, Missing} # ending + A::Union{O3, Missing} # continuing +end + +function AC_hamiltonian( + site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian, above::_HAM_MPS_TYPES, envs + ) + @assert below === above "JordanMPO assumptions break" + GL = leftenv(envs, site, below) + GR = rightenv(envs, site, below) + W = operator[site] + return JordanMPO_AC_Hamiltonian(GL, W, GR) +end + +function JordanMPO_AC_Hamiltonian(GL::MPSTensor, W::JordanMPOTensor, GR::MPSTensor) + # onsite + D = nonzero_length(W.D) > 0 ? only(W.D) : missing + + # not started + I = size(W, 4) == 1 ? missing : removeunit(GR[1], 2) + + # finished + E = size(W, 1) == 1 ? missing : removeunit(GL[end], 2) + + # starting + C = if nonzero_length(W.C) > 0 + GR_2 = GR[2:(end - 1)] + @plansor starting[-1 -2; -3 -4] ≔ W.C[-1; -3 1] * GR_2[-4 1; -2] + only(starting) + else + missing + end + + # ending + B = if nonzero_length(W.B) > 0 + GL_2 = GL[2:(end - 1)] + @plansor ending[-1 -2; -3 -4] ≔ GL_2[-1 1; -3] * W.B[1 -2; -4] + only(ending) + else + missing + end + + # continuing + A = MPO_AC_Hamiltonian(GL[2:(end - 1)], W.A, GR[2:(end - 1)]) + + # obtaining storagetype of environments since these should have already mixed + # the types of the operator and state + S = spacetype(GL) + M = storagetype(GL) + O1 = tensormaptype(S, 1, 1, M) + O2 = tensormaptype(S, 2, 2, M) + O3 = typeof(A) + + # specialization for nearest neighbours + nonzero_length(W.A) == 0 && (A = missing) + + return JordanMPO_AC_Hamiltonian{O1, O2, O3}(D, I, E, C, B, A) +end + +function prepare_operator!!( + H::JordanMPO_AC_Hamiltonian{O1, O2, O3}, backend::AbstractBackend, allocator + ) where {O1, O2, O3} + C = H.C + B = H.B + + # onsite + D = if !ismissing(C) + Id = TensorKit.id(storagetype(W.D), space(C, 2)) + @plansor C[-1 -2; -3 -4] += W.D[-1; -3] * Id[-4; -2] + missing + elseif !ismissing(B) + Id = TensorKit.id(storagetype(W.D), space(B, 1)) + @plansor B[-1 -2; -3 -4] += Id[-1; -3] * W.D[-2; -4] + missing + else + W.D + end + + # not_started + I = if !ismissing(C) + Id = id(storagetype(W.I), space(C, 1)) + @plansor C[-1 -2; -3 -4] += I[-1; -3] * H.I[-4; -2] + missing + else + H.I + end + + # finished + E = if !ismissing(B) + Id = id(storagetype(W.I), space(B, 2)) + @plansor B[-1 -2; -3 -4] += H.E[-1; -3] * Id[-2; -4] + missing + else + H.E + end + + A = ismissing(H.A) ? H.A : prepare_operator!!(H.A, backend, allocator) + + O3′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O3, typeof(backend), typeof(allocator)}) + return JordanMPO_AC_Hamiltonian{O1, O2, O3′}(D, I, E, C, B, A) +end + + +# Two site derivative +# ------------------- +""" + JordanMPO_AC2_Hamiltonian{O1,O2,O3,O4} + +Efficient operator for representing the single-site derivative of a `MPOHamiltonian` sandwiched between two MPSs. +In particular, this operator aims to make maximal use of the structure of the `MPOHamiltonian` to reduce the number of operations required to apply the operator to a tensor. +""" +struct JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4} <: DerivativeOperator + II::Union{O1, Missing} # not_started + IC::Union{O2, Missing} # starting right + ID::Union{O1, Missing} # onsite right + CB::Union{O2, Missing} # starting left - ending right + CA::Union{O3, Missing} # starting left - continuing right + AB::Union{O3, Missing} # continuing left - ending right + AA::Union{O4, Missing} # continuing left - continuing right + BE::Union{O2, Missing} # ending left + DE::Union{O1, Missing} # onsite left + EE::Union{O1, Missing} # finished +end + +function AC2_hamiltonian( + site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian, above::_HAM_MPS_TYPES, envs + ) + @assert below === above "JordanMPO assumptions break" + GL = leftenv(envs, site, below) + GR = rightenv(envs, site + 1, below) + W1, W2 = operator[site], operator[site + 1] + return JordanMPO_AC2_Hamiltonian(GL, W1, W2, GR) +end + +function JordanMPO_AC2_Hamiltonian(GL::MPSTensor, W1::JordanMPOTensor, W2::JordanMPOTensor, GR::MPSTensor) + # not started + II = size(W2, 4) == 1 ? missing : transpose(removeunit(GR[1], 2)) + + # finished + EE = size(W1, 1) == 1 ? missing : removeunit(GL[end], 2) + + # starting right + IC = if nonzero_length(W2.C) > 0 + @plansor IC_[-1 -2; -3 -4] ≔ W2.C[-1; -3 1] * GR[2:(end - 1)][-4 1; -2] + only(IC_) + else + missing + end + + # onsite left + DE = nonzero_length(W1.D) > 0 ? only(W1.D) : missing + + # onsite right + ID = nonzero_length(W2.D) > 0 ? only(W2.D) : missing + + # starting left - ending right + CB = if nonzero_length(W1.C) > 0 && nonzero_length(W2.B) > 0 + @plansor CB_[-1 -2; -3 -4] ≔ W1.C[-1; -3 1] * W2.B[1 -2; -4] + only(CB_) + else + missing + end + + # starting left - continuing right + CA = if nonzero_length(W1.C) > 0 && nonzero_length(W2.A) > 0 + @plansor CA_[-1 -2 -3; -4 -5 -6] ≔ W1.C[-1; -4 2] * W2.A[2 -2; -5 1] * + GR[2:(end - 1)][-6 1; -3] + only(CA_) + else + missing + end + + # continuing left - ending right + AB = if nonzero_length(W1.A) > 0 && nonzero_length(W2.B) > 0 + @plansor AB_[-1 -2 -3; -4 -5 -6] ≔ GL[2:(end - 1)][-1 2; -4] * W1.A[2 -2; -5 1] * + W2.B[1 -3; -6] + only(AB_) + else + missing + end + + # ending left + BE = if nonzero_length(W1.B) > 0 + @plansor BE_[-1 -2; -3 -4] ≔ GL[2:(end - 1)][-1 2; -3] * W1.B[2 -2; -4] + only(BE_) + else + missing + end + + # continuing - continuing + AA = MPO_AC2_Hamiltonian(GL[2:(end - 1)], W1.A, W2.A, GR[2:(end - 1)]) + + S = spacetype(GL) + M = storagetype(GL) + O1 = tensormaptype(S, 1, 1, M) + O2 = tensormaptype(S, 2, 2, M) + O3 = tensormaptype(S, 3, 3, M) + O4 = typeof(AA) + + if nonzero_length(W1.A) == 0 && nonzero_length(W2.A) == 0 + AA = missing + else + mask1 = falses(size(W1.A, 1), size(W1.A, 4)) + for I in nonzero_keys(W1.A) + mask1[I[1], I[4]] = true + end + + mask2 = falses(size(W2.A, 1), size(W2.A, 4)) + for I in nonzero_keys(W2.A) + mask2[I[1], I[4]] = true + end + + mask_left = transpose(mask1) * trues(size(mask1, 1)) + mask_right = mask2 * trues(size(mask2, 2)) + all(iszero, mask_left .* mask_right) && (AA = missing) + end + + return JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + +end + +function prepare_operator!!( + H::JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4}, backend::AbstractBackend, allocator + ) where {O1, O2, O3, O4} + + CA = H.CA + AB = H.AB + + CB = if !ismissing(CA) && !ismissing(H.CB) + Id = TensorKit.id(storagetype(H.CB), space(CA, 3)) + @plansor CA[-1 -2 -3; -4 -5 -6] += H.CB[-1 -2; -4 -5] * Id[-3; -6] + missing + elseif !ismissing(AB) && !ismissing(H.CB) + + else + H.CB + end + + # starting right + IC = if !ismissing(CA) && !ismissing(H.IC) + Id = TensorKit.id(storagetype(H.IC), space(CA, 1)) + @plansor CA[-1 -2 -3; -4 -5 -6] += Id[-1; -4] * H.IC[ -2 -3; -5 -6] + missing + else + H.IC + end + + # ending left + BE = if !ismissing(AB) && !ismissing(H.BE) + Id = TensorKit.id(storagetype(H.BE), space(AB, 3)) + @plansor AB[-1 -2 -3; -4 -5 -6] += H.BE[-1 -2; -4 -5] * Id[-3; -6] + missing + else + H.BE + end + + # onsite left + DE = if !ismissing(BE) && !ismissing(H.DE) + Id = TensorKit.id(storagetype(H.DE), space(BE, 1)) + @plansor BE[-1 -2; -3 -4] += Id[-1; -3] * H.DE[-2; -4] + missing + elseif !ismissing(AB) && !ismissing(H.DE) + Id1 = id(storagetype(H.DE), space(AB, 1)) + Id2 = id(storagetype(H.DE), space(AB, 3)) + @plansor AB[-1 -2 -3; -4 -5 -6] += Id1[-1; -4] * H.DE[-2; -5] * Id2[-3; -6] + missing + # TODO: could also try in CA? + else + H.DE + end + + # onsite right + ID = if !ismissing(IC) && !ismissing(H.ID) + Id = TensorKit.id(storagetype(H.ID), space(IC, 2)) + @plansor IC[-1 -2; -3 -4] += H.ID[-1; -3] * Id[-2; -4] + missing + elseif !ismissing(CA) && !ismissing(H.ID) + Id1 = TensorKit.id(storagetype(H.ID), space(CA, 1)) + Id2 = TensorKit.id(storagetype(H.ID), space(CA, 3)) + @plansor CA[-1 -2 -3; -4 -5 -6] += Id1[-1; -4] * H.ID[-2; -5] * Id2[-3; -6] + missing + else + H.ID + end + + # finished + II = if !ismissing(IC) && !ismissing(H.II) + I = id(storagetype(H.II), space(IC, 1)) + @plansor IC[-1 -2; -3 -4] += I[-1; -3] * H.II[-2; -4] + II = missing + elseif !ismissing(CA) && !ismissing(H.II) + I = id(storagetype(H.II), space(CA, 1) ⊗ space(CA, 2)) + @plansor CA[-1 -2 -3; -4 -5 -6] += I[-1 -2; -4 -5] * H.II[-3; -6] + II = missing + else + H.II + end + + # unstarted + EE = if !ismissing(BE) && !ismissing(H.EE) + I = id(storagetype(H.EE), space(BE, 2)) + @plansor BE[-1 -2; -3 -4] += H.EE[-1; -3] * I[-2; -4] + EE = missing + elseif !ismissing(AB) && !ismissing(H.EE) + I = id(storagetype(H.EE), space(AB, 2) ⊗ space(AB, 3)) + @plansor AB[-1 -2 -3; -4 -5 -6] += H.EE[-1; -4] * I[-2 -3; -5 -6] + EE = missing + else + H.EE + end + + O4′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O4, typeof(backend), typeof(allocator)}) + AA = prepare_operator!!(H.AA, backend, allocator) + + return JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4′}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) +end + +# Actions +# ------- +function (H::JordanMPO_AC_Hamiltonian)(x::MPSTensor) + y = ismissing(H.A) ? zerovector(x) : H.A(x) + + ismissing(H.D) || @plansor y[-1 -2; -3] += x[-1 1; -3] * H.D[-2; 1] + ismissing(H.E) || @plansor y[-1 -2; -3] += H.E[-1; 1] * x[1 -2; -3] + ismissing(H.I) || @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.I[1; -3] + ismissing(H.C) || @plansor y[-1 -2; -3] += x[-1 2; 1] * H.C[-2 -3; 2 1] + ismissing(H.B) || @plansor y[-1 -2; -3] += H.B[-1 -2; 1 2] * x[1 2; -3] + + return y +end + +function (H::JordanMPO_AC2_Hamiltonian)(x::MPOTensor) + y = ismissing(H.AA) ? zerovector(x) : H.AA(x) + + ismissing(H.II) || @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 -4] * H.II[-3; 1] + ismissing(H.IC) || @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 2] * H.IC[-4 -3; 2 1] + ismissing(H.ID) || @plansor y[-1 -2; -3 -4] += x[-1 -2; -3 1] * H.ID[-4; 1] + ismissing(H.CB) || @plansor y[-1 -2; -3 -4] += x[-1 1; -3 2] * H.CB[-2 -4; 1 2] + ismissing(H.CA) || @plansor y[-1 -2; -3 -4] += x[-1 1; 3 2] * H.CA[-2 -4 -3; 1 2 3] + ismissing(H.AB) || @plansor y[-1 -2; -3 -4] += x[1 2; -3 3] * H.AB[-1 -2 -4; 1 2 3] + ismissing(H.BE) || @plansor y[-1 -2; -3 -4] += x[1 2; -3 -4] * H.BE[-1 -2; 1 2] + ismissing(H.DE) || @plansor y[-1 -2; -3 -4] += x[-1 1; -3 -4] * H.DE[-2; 1] + ismissing(H.EE) || @plansor y[-1 -2; -3 -4] += x[1 -2; -3 -4] * H.EE[-1; 1] + + return y +end diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 5a4bed915..254f489eb 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -119,112 +119,108 @@ struct PrecomputedDerivative{ allocator::A end -const PrecomputedACDerivative{T, S} = PrecomputedDerivative{T, S, 2, 1, 2, 1} +const PrecomputedACDerivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 2, 1} +const PrecomputedAC2Derivative{T, S} = PrecomputedDerivative{T, S, 3, 2, 3, 2} function prepare_operator!!( - H::MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, - x::MPSTensor, + H::MPO_C_Hamiltonian{<:MPSTensor, <:MPSTensor}, backend::AbstractBackend, allocator ) - F_left = fuser(scalartype(x), codomain(x)...) - x′ = F_left * x - - leftenv = left_precontract_derivative(H.leftenv, H.operators[1], F_left, backend, allocator) - rightenv = right_precontract_derivative(H.rightenv, backend, allocator) - - return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x′ + leftenv = _transpose_tail(TensorMap(H.leftenv)) + rightenv = TensorMap(H.rightenv) + return PrecomputedDerivative(leftenv, rightenv, backend, allocator) end +function prepare_operator!!( + H::MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, + backend::AbstractBackend, allocator + ) + @plansor backend = backend allocator = allocator begin + GL_O[-1 -2; -4 -5 -3] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] + end + leftenv = fuse_legs(TensorMap(GL_O), 0, 2) + rightenv = TensorMap(H.rightenv) -function unprepare_operator!!(y::MPSBondTensor, ::PrecomputedACDerivative, x::MPSTensor) - F_left = fuser(scalartype(x), codomain(x)...) - return F_left' * y + return PrecomputedDerivative(leftenv, rightenv, backend, allocator) end function prepare_operator!!( H::MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTensor}, - x::MPOTensor, backend::AbstractBackend, allocator ) - F_left = fuser(scalartype(x), codomain(x)...) - F_right = fuser(scalartype(x), domain(x)...) - x′ = F_left * x * F_right' - - leftenv = left_precontract_derivative(H.leftenv, H.operators[1], F_left, backend, allocator) - rightenv = right_precontract_derivative(H.rightenv, H.operators[2], F_right, backend, allocator) - - return PrecomputedDerivative(leftenv, rightenv, backend, allocator), x′ -end - -function unprepare_operator!!(y::MPSBondTensor, ::PrecomputedDerivative, x::MPOTensor) - F_left = fuser(scalartype(x), codomain(x)...) - F_right = fuser(scalartype(x), domain(x)...) - return F_left' * y * F_right -end - -function (H::PrecomputedDerivative)(x::MPSBondTensor) - bstyle = BraidingStyle(sectortype(x)) - return _precontracted_ac_derivative(bstyle, x, H.leftenv, H.rightenv, H.backend, H.allocator) -end - -function _precontracted_ac_derivative(::Bosonic, x, leftenv, rightenv, backend, allocator) - return @tensor backend = backend allocator = allocator begin - y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[3 2; -2] - end -end -function _precontracted_ac_derivative(::BraidingStyle, x, leftenv, rightenv, backend, allocator) - return @planar backend = backend allocator = allocator begin - y[-1; -2] := leftenv[-1 2; 1] * x[1; 3] * τ'[3 2; 4 5] * rightenv[4 5; -2] + @plansor backend = backend allocator = allocator begin + GL_O[-1 -2; -4 -5 -3] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] + O_GR[-1 -2 -3; -4 -5] := H.operators[2][-3 -5; -2 1] * H.rightenv[-1 1; -4] end -end -function _precontracted_ac_derivative(::NoBraiding, x, leftenv, rightenv, backend, allocator) - return @planar backend = backend allocator = allocator begin - y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] + leftenv = fuse_legs(GL_O isa TensorMap ? GL_O : TensorMap(GL_O), 0, 2) + rightenv = fuse_legs(O_GR isa TensorMap ? O_GR : TensorMap(O_GR), 2, 0) + return PrecomputedDerivative(leftenv, rightenv, backend, allocator) +end + + +function (H::PrecomputedDerivative)(x::AbstractTensorMap) + R_fused = fuse_legs(H.rightenv, 0, 2) + x_fused = fuse_legs(x, numout(x), numin(x)) + + # xR = matrix_contract(R_fused, x_fused, 1, One(), H.backend, H.allocator; transpose = true) + + TC = TensorOperations.promote_contract(scalartype(x_fused), scalartype(R_fused)) + xR = TensorOperations.tensoralloc_contract(TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator) + + structure_xR = TensorKit.fusionblockstructure(space(xR)) + structure_R = TensorKit.fusionblockstructure(space(R_fused)) + + xblocks = blocks(x_fused) + for ((f₁, f₂), i1) in structure_xR.fusiontreeindices + sz, str, offset = structure_xR.fusiontreestructure[i1] + xr = TensorKit.Strided.StridedView(xR.data, sz, str, offset) + + u = first(f₁.uncoupled) + x = TensorKit.Strided.StridedView(xblocks[u]) + isempty(x) && (zerovector!(xr); continue) + + if haskey(structure_R.fusiontreeindices, (f₁, f₂)) + @inbounds i = structure_R.fusiontreeindices[(f₁, f₂)] + @inbounds sz, str, offset = structure_R.fusiontreestructure[i] + r = TensorKit.Strided.StridedView(R_fused.data, sz, str, offset) + + # if sz[2] < sz[3] + # for k in axes(r, 2) + # C = xr[:, k, :] + # B = r[:, k, :] + # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + # end + # else + # for k in axes(r, 3) + # C = xr[:, :, k] + # B = r[:, :, k] + # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + # end + # end + + TensorOperations.tensorcontract!( + xr, x, ((1,), (2,)), false, + r, ((1,), (2, 3)), false, ((1, 2), (3,)), One(), Zero(), H.backend, H.allocator + ) + else + zerovector!(xr) + end end -end -left_precontract_derivative(arg, args...) = _left_precontract_derivative(BraidingStyle(sectortype(arg)), arg, args...) -function _left_precontract_derivative(::BraidingStyle, leftenv, operator, F, backend, allocator) - @planar backend = backend allocator = allocator begin - GL_O[-1 -2 -3; -4 -5] := leftenv[-1 1; -4] * operator[1 -2; -5 -3] - end - return @planar backend = backend allocator = allocator begin - leftenv[-1 -2; -3] := F[-1; 3 4] * TensorMap(GL_O)[3 4 -2; 1 2] * F'[1 2; -3] - end + LxR = H.leftenv * xR + return TensorMap{scalartype(LxR)}(LxR.data, codomain(H.leftenv) ← domain(H.rightenv)) end -right_precontract_derivative(arg, args...) = _right_precontract_derivative(BraidingStyle(sectortype(arg)), arg, args...) -_right_precontract_derivative(::NoBraiding, rightenv, backend, allocator) = TensorMap(rightenv) -function _right_precontract_derivative(::Bosonic, rightenv, backend, allocator) - return @tensor backend = backend allocator = allocator begin - rightenv[-2 -1; -3] := TensorMap(rightenv)[-1 -2; -3] - end -end -function _right_precontract_derivative(::BraidingStyle, rightenv, backend, allocator) - return @planar backend = backend allocator = allocator begin - rightenv[-1 -2; -3] := τ[-1 -2; 1 2] * TensorMap(rightenv)[1 2; -3] - end -end -function _right_precontract_derivative(::NoBraiding, rightenv, operator, F, backend, allocator) - @planar backend = backend allocator = allocator begin - O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] - end - return @planar backend = backend allocator = allocator begin - rightenv[-1 -2; -3] := F[-1; 3 4] * TensorMap(O_GR)[3 4 -2; 1 2] * F'[1 2; -3] - end -end -function _right_precontract_derivative(::Bosonic, rightenv, operator, F, backend, allocator) - @tensor backend = backend allocator = allocator begin - O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] - end - return @tensor backend = backend allocator = allocator begin - rightenv[-2 -1; -3] := F[-1; 3 4] * TensorMap(O_GR)[3 4 -2; 1 2] * F'[1 2; -3] - end -end -function _right_precontract_derivative(::BraidingStyle, rightenv, operator, F, backend, allocator) - @planar backend = backend allocator = allocator begin - O_GR[-1 -2 -3; -4 -5] := operator[-3 -5; -2 1] * rightenv[-1 1; -4] - end - return @planar backend = backend allocator = allocator begin - rightenv[-1 -2; -3] := τ[-1 -2; 5 6] * F[5; 3 4] * TensorMap(O_GR)[3 4 6; 1 2] * F'[1 2; -3] - end +const _ToPrepare = Union{ + MPO_C_Hamiltonian{<:MPSTensor, <:MPSTensor}, + MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, + MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTensor}, +} + +function prepare_operator!!(H::Multiline{<:_ToPrepare}, backend::AbstractBackend, allocator) + return Multiline(map(x -> prepare_operator!!(x, backend, allocator), parent(H))) end + +fixedpoint(A::Union{_ToPrepare, Multiline{<:_ToPrepare}}, x₀, which::Symbol, alg::Lanczos) = + fixedpoint(prepare_operator!!(A), x₀, which, alg) +fixedpoint(A::Union{_ToPrepare, Multiline{<:_ToPrepare}}, x₀, which::Symbol, alg::Arnoldi) = + fixedpoint(prepare_operator!!(A), x₀, which, alg) diff --git a/src/algorithms/fixedpoint.jl b/src/algorithms/fixedpoint.jl index 941bde769..fa29f80b2 100644 --- a/src/algorithms/fixedpoint.jl +++ b/src/algorithms/fixedpoint.jl @@ -8,30 +8,22 @@ Compute the fixedpoint of a linear operator `A` using the specified eigensolver fixedpoint is assumed to be unique. """ function fixedpoint(A, x₀, which::Symbol, alg::Lanczos) - A′, x₀′ = prepare_operator!!(A, x₀) - vals, vecs, info = eigsolve(A′, x₀′, 1, which, alg) + vals, vecs, info = eigsolve(A, x₀, 1, which, alg) info.converged == 0 && @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" - λ = vals[1] - v = unprepare_operator!!(vecs[1], A′, x₀) - - return λ, v + return vals[1], vecs[1] end function fixedpoint(A, x₀, which::Symbol, alg::Arnoldi) - A′, x₀′ = prepare_operator!!(A, x₀) - TT, vecs, vals, info = schursolve(A′, x₀′, 1, which, alg) + TT, vecs, vals, info = schursolve(A, x₀, 1, which, alg) info.converged == 0 && @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" size(TT, 2) > 1 && TT[2, 1] != 0 && @warnv 1 "non-unique fixedpoint detected" - λ = vals[1] - v = unprepare_operator!!(vecs[1], A′, x₀) - - return λ, v + return vals[1], vecs[1] end function fixedpoint(A, x₀, which::Symbol; kwargs...) diff --git a/src/utility/multiline.jl b/src/utility/multiline.jl index a1c861ff1..ebcff438f 100644 --- a/src/utility/multiline.jl +++ b/src/utility/multiline.jl @@ -12,7 +12,7 @@ See also: [`MultilineMPS`](@ref) and [`MultilineMPO`](@ref) struct Multiline{T} data::PeriodicArray{T, 1} function Multiline{T}(data::AbstractVector{T}) where {T} - @assert allequal(length.(data)) "All lines must have the same length" + # @assert allequal(length.(data)) "All lines must have the same length" return new{T}(data) end end @@ -22,7 +22,7 @@ Multiline(data::AbstractVector{T}) where {T} = Multiline{T}(data) # ----------------------- Base.parent(m::Multiline) = m.data Base.size(m::Multiline) = (length(parent(m)), length(parent(m)[1])) -Base.size(m::Multiline, i::Int) = getindex(size(m), i) +Base.size(m::Multiline, i::Int) = i == 1 ? length(parent(m)) : i == 2 ? length(parent(m)[1]) : error() Base.length(m::Multiline) = prod(size(m)) function Base.axes(m::Multiline, i::Int) return i == 1 ? axes(parent(m), 1) : diff --git a/src/utility/utility.jl b/src/utility/utility.jl index 49cb96648..cae1a2dbd 100644 --- a/src/utility/utility.jl +++ b/src/utility/utility.jl @@ -8,8 +8,8 @@ function _transpose_as(t1::AbstractTensorMap, t2::AbstractTensorMap; copy::Bool return repartition(t1, numout(t2), numin(t2); copy) end -_mul_front(C, A) = _transpose_front(C * _transpose_tail(A)) -_mul_tail(A, C) = A * C +_mul_front(C, A) = matrix_contract(A, C, 1; transpose = true) # _transpose_front(C * _transpose_tail(A)) +_mul_tail(A, C) = matrix_contract(A, C, numind(A)) # A * C function _similar_tail(A::AbstractTensorMap) cod = _firstspace(A) @@ -149,3 +149,108 @@ function check_unambiguous_braiding(V::VectorSpace) return check_unambiguous_braiding(Bool, V) || throw(ArgumentError("cannot unambiguously braid $V")) end + +""" + matrix_contract( + A::AbstractTensorMap, B::AbstractTensorMap{T, S, 1, 1}, i::Int, + α::Number = One(), + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator(); + transpose::Bool = false + ) + +Compute the tensor contraction `α * A * B`, where the (1, 1) - tensor `B` is attached to index `i` of `A`. +Whenever `transpose = true`, this contraction (lazily) uses `transpose(B)` instead. + +See also [`matrix_contract!`](@ref). +""" +function matrix_contract( + A::AbstractTensorMap, B::AbstractTensorMap{<:Any, <:Any, 1, 1}, i::Int, + α::Number = One(), backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator(); + transpose::Bool = false + ) + if i <= numout(A) + cod = ProductSpace(TT.setindex(codomain(A).spaces, space(B, transpose ? 1 : 2), i)) + dom = domain(A) + else + cod = codomain(A) + dom = ProductSpace(TT.setindex(domain(A).spaces, space(B, transpose ? 1 : 2)', i - numout(A))) + end + T = TensorOperations.promote_contract(scalartype(A), scalartype(B), scalartype(α)) + C = similar(A, T, cod ← dom) + return matrix_contract!(C, A, B, i, α, Zero(), backend, allocator; transpose) +end + +""" + matrix_contract!( + C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap{T, S, 1, 1}, i::Int, + α::Number = One(), β::Number = Zero(), + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator(); + transpose::Bool = false + ) + +Compute the tensor contraction `C ← β * C + α * A * B`, where the (1, 1) - tensor `B` is attached to index `i` of `A`, +and the result is added into `C`. Whenever `transpose = true`, this contraction (lazily) uses `transpose(B)` instead. + +See also [`matrix_contract`](@ref). +""" +function matrix_contract!( + C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap{<:Any, <:Any, 1, 1}, i::Int, + α::Number = One(), β::Number = Zero(), + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator(); + transpose::Bool = false + ) + + @boundscheck for k in 1:numind(C) + numin(C) == numin(A) && numout(C) == numout(A) || throw(ArgumentError("Invalid number of dimensions")) + if k == i + space(C, k) == space(B, transpose ? 1 : 2) || throw(SpaceMismatch()) + space(A, k) == space(B, transpose ? 2 : 1)' || throw(SpaceMismatch()) + else + space(C, k) == space(A, k) || throw(SpaceMismatch()) + end + end + + N, N₁ = numind(C), numout(C) + pA = (TT.deleteat(ntuple(identity, N), i), (i,)) + pB = transpose ? ((2,), (1,)) : ((1,), (2,)) + pAB = TensorKit._canonicalize(TT.insertafter(ntuple(identity, N - 1), i - 1, (N,)), C) + + Bblocks = blocks(B) + for ((f₁, f₂), c) in subblocks(C) + uncoupled_i = i <= N₁ ? f₁.uncoupled[i] : f₂.uncoupled[i - N₁] + transpose && (uncoupled_i = dual(uncoupled_i)) + if TensorKit.hasblock(B, uncoupled_i) + a = A[f₁, f₂] + b = Bblocks[uncoupled_i] + TensorOperations.tensorcontract!(c, a, pA, false, b, pB, false, pAB, α, β, backend, allocator) + else + scale!(c, β) + end + end + + return C +end + +@inline fuse_legs(x::TensorMap, N₁::Int, N₂::Int) = fuse_legs(x, Val(N₁), Val(N₂)) +function fuse_legs(x::TensorMap, ::Val{N₁}, ::Val{N₂}) where {N₁, N₂} + ((0 <= N₁ <= numout(x)) && (0 <= N₂ <= numin(x))) || throw(ArgumentError("invalid fusing scheme")) + init = one(spacetype(x)) + + cod = if N₁ > 1 + cod_spaces = codomain(x).spaces + fuse(prod(TT.getindices(cod_spaces, ntuple(identity, N₁)))) ⊗ + prod(TT.getindices(cod_spaces, ntuple(i -> i + N₁, numout(x) - N₁)); init) + else + codomain(x) + end + + dom = if N₂ > 1 + dom_spaces = domain(x).spaces + dom = fuse(prod(TT.getindices(dom_spaces, ntuple(identity, N₂)); init)) ⊗ + prod(TT.getindices(domain(x).spaces, ntuple(i -> i + N₂, numin(x) - N₂)); init) + else + domain(x) + end + + return TensorMap{scalartype(x)}(x.data, cod ← dom) +end diff --git a/test/algorithms.jl b/test/algorithms.jl index 207857951..5e41213f9 100644 --- a/test/algorithms.jl +++ b/test/algorithms.jl @@ -338,7 +338,7 @@ module TestAlgorithms H = force_planar(heisenberg_XXX(Trivial, Float64; spin = 1 // 2, L)) ψ = FiniteMPS(rand, Float64, L, ℙ^2, ℙ^4) E = expectation_value(ψ, H) - ψ₀, = find_groundstate(ψ, H) + ψ₀, = find_groundstate(ψ, H; verbosity = verbosity_conv) E₀ = expectation_value(ψ₀, H) @testset "Finite $(alg isa TDVP ? "TDVP" : "TDVP2")" for alg in algs From b90c4e795c7de7f1b6ae22a0be592693f22181c7 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 16 Dec 2025 16:43:21 -0500 Subject: [PATCH 14/20] rework benchmarks --- .../derivatives/AC2_benchmarks.jl | 47 +++++++++++++------ .../derivatives/DerivativesBenchmarks.jl | 6 ++- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl index f302a0435..b7aeb8e68 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/AC2_benchmarks.jl @@ -20,9 +20,10 @@ benchname(spec::AC2Spec) = dim(spec.mps_virtualspaces[1]), dim(spec.mpo_virtuals # Benchmarks # ---------- -function MPSKit.MPO_AC2_Hamiltonian(spec::AC2Spec{S}; T::Type = Float64) where {S} +function MPSKit.AC2_hamiltonian(spec::AC2Spec{S}; T::Type = Float64) where {S} GL = randn(T, spec.mps_virtualspaces[1] ⊗ spec.mpo_virtualspaces[1]' ← spec.mps_virtualspaces[1]) GR = randn(T, spec.mps_virtualspaces[3] ⊗ spec.mpo_virtualspaces[3] ← spec.mps_virtualspaces[3]) + W1 = MPSKit.JordanMPOTensor{T, S}(undef, spec.mpo_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.physicalspaces[1] ⊗ spec.mpo_virtualspaces[2]) for (r, c) in spec.nonzero_keys[1] r == c == 1 && continue @@ -35,27 +36,45 @@ function MPSKit.MPO_AC2_Hamiltonian(spec::AC2Spec{S}; T::Type = Float64) where { r == size(W2, 1) && c == size(W2, 4) && continue W2[r, 1, 1, c] = randn!(W2[r, 1, 1, c]) end + H = InfiniteMPOHamiltonian(PeriodicVector([W1, W2])) + + A = PeriodicVector( + [ + randn(T, spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[2]), + randn(T, spec.mps_virtualspaces[2] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3]), + ] + ) + C = PeriodicVector( + [ + randn(T, spec.mps_virtualspaces[2] ← spec.mps_virtualspaces[2]), + randn(T, spec.mps_virtualspaces[3] ← spec.mps_virtualspaces[3]), + ] + ) + psi = InfiniteMPS{eltype(A), eltype(C)}(A, A, C, A) - return MPSKit.MPO_AC2_Hamiltonian(GL, W1, W2, GR) + GLs, GRs = MPSKit.initialize_environments(psi, H, psi) + envs = MPSKit.InfiniteEnvironments(GLs, GRs) + + return MPSKit.AC2_hamiltonian(1, psi, H, psi, envs) end function contraction_benchmark(spec::AC2Spec; T::Type = Float64) - AA = randn(T, spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]') - H_eff = MPSKit.MPO_AC2_Hamiltonian(spec; T) - H_prep, x_prep = MPSKit.prepare_operator!!(H_eff, AA) - init() = randn!(similar(x_prep)) - - return @benchmarkable $H_prep * x setup = (x = $init()) + V = spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]' + H_eff = MPSKit.AC2_hamiltonian(spec; T) + return @benchmarkable $H_eff * x setup = x = randn($T, $V) end function preparation_benchmark(spec::AC2Spec; T::Type = Float64) - init() = randn(T, spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]') - H_eff = MPSKit.MPO_AC2_Hamiltonian(spec; T) + V = spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]' + H_eff = MPSKit.AC2_hamiltonian(spec; T) + return @benchmarkable MPSKit.prepare_operator!!($H_eff) +end - return @benchmarkable begin - O′, x′ = MPSKit.prepare_operator!!($H_eff, x) - y = MPSKit.unprepare_operator!!(x′, O′, x) - end setup = (x = $init()) +function prepared_benchmark(spec::AC2Spec; T::Type = Float64) + V = spec.mps_virtualspaces[1] ⊗ spec.physicalspaces[1] ← spec.mps_virtualspaces[3] ⊗ spec.physicalspaces[2]' + H_eff = MPSKit.AC2_hamiltonian(spec; T) + H_prep = MPSKit.prepare_operator!!(H_eff) + return @benchmarkable $H_prep * x setup = x = randn($T, $V) end # Converters diff --git a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl index db1cf8ecb..0b423dcf2 100644 --- a/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl +++ b/benchmark/MPSKitBenchmarks/derivatives/DerivativesBenchmarks.jl @@ -25,18 +25,22 @@ T = Float64 suite_init = addgroup!(SUITE, "AC2_preparation") suite_apply = addgroup!(SUITE, "AC2_contraction") +suite_prepped = addgroup!(SUITE, "AC2_prepared") for (model, params) in allparams g_prep = addgroup!(suite_init, model) + g_prepped = addgroup!(suite_prepped, model) g_contract = addgroup!(suite_apply, model) for (symmetry, specs) in params g_prep_sym = addgroup!(g_prep, symmetry) g_contract_sym = addgroup!(g_contract, symmetry) + g_prepped_sym = addgroup!(g_prepped, symmetry) for spec_dict in specs spec = untomlify(AC2Spec, spec_dict) name = benchname(spec) - g_prep_sym[name] = preparation_benchmark(spec; T) g_contract_sym[name] = contraction_benchmark(spec; T) + g_prep_sym[name] = preparation_benchmark(spec; T) + g_prepped_sym[name] = prepared_benchmark(spec; T) end end end From c9db523d604969274255c7e6fac55d12a63bea2b Mon Sep 17 00:00:00 2001 From: lkdvos Date: Tue, 16 Dec 2025 17:00:37 -0500 Subject: [PATCH 15/20] temporary revert --- .../derivatives/hamiltonian_derivatives.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index 534553580..80e7650da 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -113,9 +113,11 @@ function prepare_operator!!( H.E end - A = ismissing(H.A) ? H.A : prepare_operator!!(H.A, backend, allocator) + # O3′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O3, typeof(backend), typeof(allocator)}) + # A = ismissing(H.A) ? H.A : prepare_operator!!(H.A, backend, allocator) + O3′ = O3 + A = H.A - O3′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O3, typeof(backend), typeof(allocator)}) return JordanMPO_AC_Hamiltonian{O1, O2, O3′}(D, I, E, C, B, A) end @@ -328,8 +330,10 @@ function prepare_operator!!( H.EE end - O4′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O4, typeof(backend), typeof(allocator)}) - AA = prepare_operator!!(H.AA, backend, allocator) + # O4′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O4, typeof(backend), typeof(allocator)}) + # AA = ismissing(H.AA) ? H.AA : prepare_operator!!(H.AA, backend, allocator) + O4′ = O4 + AA = H.AA return JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4′}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) end From 5d5af38e5ad4c25b2f09cf5cb8234f58c578f384 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 16 Dec 2025 17:08:35 -0500 Subject: [PATCH 16/20] Avoid copy in matrix contract This reverts commit c9db523d604969274255c7e6fac55d12a63bea2b. --- .../derivatives/hamiltonian_derivatives.jl | 12 +++---- src/algorithms/derivatives/mpo_derivatives.jl | 36 +++++++++---------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index 80e7650da..5015575e5 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -113,10 +113,8 @@ function prepare_operator!!( H.E end - # O3′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O3, typeof(backend), typeof(allocator)}) - # A = ismissing(H.A) ? H.A : prepare_operator!!(H.A, backend, allocator) - O3′ = O3 - A = H.A + O3′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O3, typeof(backend), typeof(allocator)}) + A = ismissing(H.A) ? H.A : prepare_operator!!(H.A, backend, allocator) return JordanMPO_AC_Hamiltonian{O1, O2, O3′}(D, I, E, C, B, A) end @@ -330,10 +328,8 @@ function prepare_operator!!( H.EE end - # O4′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O4, typeof(backend), typeof(allocator)}) - # AA = ismissing(H.AA) ? H.AA : prepare_operator!!(H.AA, backend, allocator) - O4′ = O4 - AA = H.AA + O4′ = Core.Compiler.return_type(prepare_operator!!, Tuple{O4, typeof(backend), typeof(allocator)}) + AA = prepare_operator!!(H.AA, backend, allocator) return JordanMPO_AC2_Hamiltonian{O1, O2, O3, O4′}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) end diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 254f489eb..2d1144d37 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -183,24 +183,24 @@ function (H::PrecomputedDerivative)(x::AbstractTensorMap) @inbounds sz, str, offset = structure_R.fusiontreestructure[i] r = TensorKit.Strided.StridedView(R_fused.data, sz, str, offset) - # if sz[2] < sz[3] - # for k in axes(r, 2) - # C = xr[:, k, :] - # B = r[:, k, :] - # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - # end - # else - # for k in axes(r, 3) - # C = xr[:, :, k] - # B = r[:, :, k] - # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - # end - # end - - TensorOperations.tensorcontract!( - xr, x, ((1,), (2,)), false, - r, ((1,), (2, 3)), false, ((1, 2), (3,)), One(), Zero(), H.backend, H.allocator - ) + if TensorOperations.isblascontractable(r, ((1,), (2, 3))) && + TensorOperations.isblasdestination(xr, ((1,), (2, 3))) + C = TensorKit.Strided.sreshape(xr, size(xr, 1), size(xr, 2) * size(xr, 3)) + B = TensorKit.Strided.sreshape(r, size(r, 1), size(r, 2) * size(r, 3)) + LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + elseif sz[2] < sz[3] + for k in axes(r, 2) + C = xr[:, k, :] + B = r[:, k, :] + LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + end + else + for k in axes(r, 3) + C = xr[:, :, k] + B = r[:, :, k] + LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + end + end else zerovector!(xr) end From eca22fd44148c043c0fd983a46e227611888167c Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 16 Dec 2025 23:04:51 -0500 Subject: [PATCH 17/20] Add buffer allocator --- src/MPSKit.jl | 1 + src/algorithms/derivatives/derivatives.jl | 6 +- src/algorithms/derivatives/mpo_derivatives.jl | 99 ++++++++++--------- src/utility/allocator.jl | 67 +++++++++++++ 4 files changed, 124 insertions(+), 49 deletions(-) create mode 100644 src/utility/allocator.jl diff --git a/src/MPSKit.jl b/src/MPSKit.jl index ec9c05ae9..96ed23cb4 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -99,6 +99,7 @@ include("utility/logging.jl") using .IterativeLoggers include("utility/iterativesolvers.jl") +include("utility/allocator.jl") include("utility/styles.jl") include("utility/periodicarray.jl") include("utility/windowarray.jl") diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index a3008c872..4eac14c40 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -222,10 +222,10 @@ Base.:*(h::LazySum{<:Union{DerivativeOrMultiplied}}, v) = h(v) Given an operator and vector, try to construct a more efficient representation of that operator for repeated application. This should always be used in conjunction with [`unprepare_operator!!`](@ref). """ -prepare_operator!!(O, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = O +prepare_operator!!(O, backend::AbstractBackend = DefaultBackend(), allocator = GrowingBuffer()) = O # to make benchmark scripts run -prepare_operator!!(O, x::AbstractTensorMap, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = +prepare_operator!!(O, x::AbstractTensorMap, backend::AbstractBackend = DefaultBackend(), allocator = GrowingBuffer()) = prepare_operator!!(O, backend, allocator), x -unprepare_operator!!(y, O, x, backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator()) = +unprepare_operator!!(y, O, x, backend::AbstractBackend = DefaultBackend(), allocator = GrowingBuffer()) = y diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 2d1144d37..91220767a 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -134,9 +134,11 @@ function prepare_operator!!( H::MPO_AC_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPSTensor}, backend::AbstractBackend, allocator ) + cp = checkpoint(allocator) @plansor backend = backend allocator = allocator begin GL_O[-1 -2; -4 -5 -3] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] end + reset!(allocator, cp) leftenv = fuse_legs(TensorMap(GL_O), 0, 2) rightenv = TensorMap(H.rightenv) @@ -147,10 +149,13 @@ function prepare_operator!!( H::MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTensor}, backend::AbstractBackend, allocator ) + cp = checkpoint(allocator) @plansor backend = backend allocator = allocator begin GL_O[-1 -2; -4 -5 -3] := H.leftenv[-1 1; -4] * H.operators[1][1 -2; -5 -3] O_GR[-1 -2 -3; -4 -5] := H.operators[2][-3 -5; -2 1] * H.rightenv[-1 1; -4] end + reset!(allocator, cp) + leftenv = fuse_legs(GL_O isa TensorMap ? GL_O : TensorMap(GL_O), 0, 2) rightenv = fuse_legs(O_GR isa TensorMap ? O_GR : TensorMap(O_GR), 2, 0) return PrecomputedDerivative(leftenv, rightenv, backend, allocator) @@ -158,55 +163,62 @@ end function (H::PrecomputedDerivative)(x::AbstractTensorMap) - R_fused = fuse_legs(H.rightenv, 0, 2) + allocator = H.allocator + cp = checkpoint(allocator) + + R_fused = fuse_legs(H.rightenv, 0, numin(x)) x_fused = fuse_legs(x, numout(x), numin(x)) - # xR = matrix_contract(R_fused, x_fused, 1, One(), H.backend, H.allocator; transpose = true) TC = TensorOperations.promote_contract(scalartype(x_fused), scalartype(R_fused)) xR = TensorOperations.tensoralloc_contract(TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator) - structure_xR = TensorKit.fusionblockstructure(space(xR)) - structure_R = TensorKit.fusionblockstructure(space(R_fused)) - - xblocks = blocks(x_fused) - for ((f₁, f₂), i1) in structure_xR.fusiontreeindices - sz, str, offset = structure_xR.fusiontreestructure[i1] - xr = TensorKit.Strided.StridedView(xR.data, sz, str, offset) - - u = first(f₁.uncoupled) - x = TensorKit.Strided.StridedView(xblocks[u]) - isempty(x) && (zerovector!(xr); continue) - - if haskey(structure_R.fusiontreeindices, (f₁, f₂)) - @inbounds i = structure_R.fusiontreeindices[(f₁, f₂)] - @inbounds sz, str, offset = structure_R.fusiontreestructure[i] - r = TensorKit.Strided.StridedView(R_fused.data, sz, str, offset) - - if TensorOperations.isblascontractable(r, ((1,), (2, 3))) && - TensorOperations.isblasdestination(xr, ((1,), (2, 3))) - C = TensorKit.Strided.sreshape(xr, size(xr, 1), size(xr, 2) * size(xr, 3)) - B = TensorKit.Strided.sreshape(r, size(r, 1), size(r, 2) * size(r, 3)) - LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - elseif sz[2] < sz[3] - for k in axes(r, 2) - C = xr[:, k, :] - B = r[:, k, :] - LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - end - else - for k in axes(r, 3) - C = xr[:, :, k] - B = r[:, :, k] - LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - end - end - else - zerovector!(xr) - end - end + matrix_contract!(xR, R_fused, x_fused, 1, One(), Zero(), H.backend, H.allocator; transpose = true) + + # structure_xR = TensorKit.fusionblockstructure(space(xR)) + # structure_R = TensorKit.fusionblockstructure(space(R_fused)) + + # xblocks = blocks(x_fused) + # for ((f₁, f₂), i1) in structure_xR.fusiontreeindices + # sz, str, offset = structure_xR.fusiontreestructure[i1] + # xr = TensorKit.Strided.StridedView(xR.data, sz, str, offset) + + # u = first(f₁.uncoupled) + # x = TensorKit.Strided.StridedView(xblocks[u]) + # isempty(x) && (zerovector!(xr); continue) + + # if haskey(structure_R.fusiontreeindices, (f₁, f₂)) + # @inbounds i = structure_R.fusiontreeindices[(f₁, f₂)] + # @inbounds sz, str, offset = structure_R.fusiontreestructure[i] + # r = TensorKit.Strided.StridedView(R_fused.data, sz, str, offset) + + # if TensorOperations.isblascontractable(r, ((1,), (2, 3))) && + # TensorOperations.isblasdestination(xr, ((1,), (2, 3))) + # C = TensorKit.Strided.sreshape(xr, size(xr, 1), size(xr, 2) * size(xr, 3)) + # B = TensorKit.Strided.sreshape(r, size(r, 1), size(r, 2) * size(r, 3)) + # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + # elseif sz[2] < sz[3] + # for k in axes(r, 2) + # C = xr[:, k, :] + # B = r[:, k, :] + # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + # end + # else + # for k in axes(r, 3) + # C = xr[:, :, k] + # B = r[:, :, k] + # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) + # end + # end + # else + # zerovector!(xr) + # end + # end LxR = H.leftenv * xR + TensorOperations.tensorfree!(xR, H.allocator) + + reset!(allocator, cp) return TensorMap{scalartype(LxR)}(LxR.data, codomain(H.leftenv) ← domain(H.rightenv)) end @@ -219,8 +231,3 @@ const _ToPrepare = Union{ function prepare_operator!!(H::Multiline{<:_ToPrepare}, backend::AbstractBackend, allocator) return Multiline(map(x -> prepare_operator!!(x, backend, allocator), parent(H))) end - -fixedpoint(A::Union{_ToPrepare, Multiline{<:_ToPrepare}}, x₀, which::Symbol, alg::Lanczos) = - fixedpoint(prepare_operator!!(A), x₀, which, alg) -fixedpoint(A::Union{_ToPrepare, Multiline{<:_ToPrepare}}, x₀, which::Symbol, alg::Arnoldi) = - fixedpoint(prepare_operator!!(A), x₀, which, alg) diff --git a/src/utility/allocator.jl b/src/utility/allocator.jl new file mode 100644 index 000000000..f9dc1a482 --- /dev/null +++ b/src/utility/allocator.jl @@ -0,0 +1,67 @@ +@static if isdefined(Core, :Memory) + BufType = Memory{UInt8} +else + BufType = Vector{UInt8} +end + +const DEFAULT_SIZEHINT = 2^20 # 1MB + +mutable struct GrowingBuffer + buffer::BufType + offset::UInt + function GrowingBuffer(; sizehint = DEFAULT_SIZEHINT) + buffer = BufType(undef, sizehint) + return new(buffer, zero(UInt)) + end +end + +Base.length(buffer::GrowingBuffer) = length(buffer.buffer) +Base.pointer(buffer::GrowingBuffer) = pointer(buffer.buffer) + buffer.offset + +function Base.sizehint!(buffer::GrowingBuffer, n::Integer; shrink::Bool = false) + n > 0 || throw(ArgumentError("invalid new buffer size")) + buffer.offset == 0 || error("cannot resize a buffer that is not fully reset") + + n = shrink ? max(n, length(buffer)) : n + n = Int(Base.nextpow(2, n)) + + @static if isdefined(Core, :Memory) + buffer.buffer = BufType(undef, n) + else + sizehint!(buffer.buffer, n) + end + return buffer +end + +checkpoint(buffer) = zero(UInt) +reset!(buffer, checkpoint::UInt = zero(UInt)) = buffer + +checkpoint(buffer::GrowingBuffer) = buffer.offset + +function reset!(buffer::GrowingBuffer, checkpoint::UInt = zero(UInt)) + if iszero(checkpoint) && buffer.offset > length(buffer) + # full reset - check for need to grow + newlength = Base.nextpow(2, buffer.offset) # round to nearest larger power of 2 + buffer.offset = checkpoint + sizehint!(buffer, newlength) + else + buffer.offset = checkpoint + end + return buffer +end + +# Allocating +# ---------- +function TensorOperations.tensoralloc( + ::Type{A}, structure, ::Val{istemp}, buffer::GrowingBuffer + ) where {A <: AbstractArray, istemp} + T = eltype(A) + if istemp + ptr = convert(Ptr{T}, pointer(buffer)) + buffer.offset += prod(structure) * sizeof(T) + buffer.offset < length(buffer) && + return Base.unsafe_wrap(Array, ptr, structure) + end + return A(undef, structure) +end +TensorOperations.tensorfree!(::AbstractArray, ::GrowingBuffer) = nothing From 8ea9103f5e0df741d7269c7839b62f39d529f033 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 16 Dec 2025 23:28:54 -0500 Subject: [PATCH 18/20] clean up code --- src/algorithms/derivatives/mpo_derivatives.jl | 42 +------- src/utility/utility.jl | 100 +++++++++++++++++- 2 files changed, 99 insertions(+), 43 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 91220767a..27131df85 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -173,47 +173,7 @@ function (H::PrecomputedDerivative)(x::AbstractTensorMap) TC = TensorOperations.promote_contract(scalartype(x_fused), scalartype(R_fused)) xR = TensorOperations.tensoralloc_contract(TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator) - matrix_contract!(xR, R_fused, x_fused, 1, One(), Zero(), H.backend, H.allocator; transpose = true) - - # structure_xR = TensorKit.fusionblockstructure(space(xR)) - # structure_R = TensorKit.fusionblockstructure(space(R_fused)) - - # xblocks = blocks(x_fused) - # for ((f₁, f₂), i1) in structure_xR.fusiontreeindices - # sz, str, offset = structure_xR.fusiontreestructure[i1] - # xr = TensorKit.Strided.StridedView(xR.data, sz, str, offset) - - # u = first(f₁.uncoupled) - # x = TensorKit.Strided.StridedView(xblocks[u]) - # isempty(x) && (zerovector!(xr); continue) - - # if haskey(structure_R.fusiontreeindices, (f₁, f₂)) - # @inbounds i = structure_R.fusiontreeindices[(f₁, f₂)] - # @inbounds sz, str, offset = structure_R.fusiontreestructure[i] - # r = TensorKit.Strided.StridedView(R_fused.data, sz, str, offset) - - # if TensorOperations.isblascontractable(r, ((1,), (2, 3))) && - # TensorOperations.isblasdestination(xr, ((1,), (2, 3))) - # C = TensorKit.Strided.sreshape(xr, size(xr, 1), size(xr, 2) * size(xr, 3)) - # B = TensorKit.Strided.sreshape(r, size(r, 1), size(r, 2) * size(r, 3)) - # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - # elseif sz[2] < sz[3] - # for k in axes(r, 2) - # C = xr[:, k, :] - # B = r[:, k, :] - # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - # end - # else - # for k in axes(r, 3) - # C = xr[:, :, k] - # B = r[:, :, k] - # LinearAlgebra.BLAS.gemm!('N', 'N', one(TC), x, B, zero(TC), C) - # end - # end - # else - # zerovector!(xr) - # end - # end + mul_front!(xR, x_fused, R_fused, One(), Zero(), H.backend, H.allocator) LxR = H.leftenv * xR TensorOperations.tensorfree!(xR, H.allocator) diff --git a/src/utility/utility.jl b/src/utility/utility.jl index cae1a2dbd..aebf44713 100644 --- a/src/utility/utility.jl +++ b/src/utility/utility.jl @@ -8,8 +8,8 @@ function _transpose_as(t1::AbstractTensorMap, t2::AbstractTensorMap; copy::Bool return repartition(t1, numout(t2), numin(t2); copy) end -_mul_front(C, A) = matrix_contract(A, C, 1; transpose = true) # _transpose_front(C * _transpose_tail(A)) -_mul_tail(A, C) = matrix_contract(A, C, numind(A)) # A * C +_mul_front(C, A) = mul_front(C, A) # _transpose_front(C * _transpose_tail(A)) +_mul_tail(A, C) = mul_tail(A, C) # A * C function _similar_tail(A::AbstractTensorMap) cod = _firstspace(A) @@ -231,6 +231,102 @@ function matrix_contract!( return C end +function mul_front( + A::AbstractTensorMap, B::AbstractTensorMap, + α::Number, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + cod = prod(i -> i == 1 ? space(A, 1) : space(B, i), 1:numout(B)) + dom = domain(B) + T = TensorOperations.promote_contract(scalartype(A), scalartype(B), scalartype(α)) + C = similar(A, T, cod ← dom) + return mul_front!(C, A, B, α, Zero(), backend, allocator) +end + +function mul_front!( + C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap, + α::Number, β::Number, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + (numin(C) == numin(B) && numout(C) == numout(B) && numin(A) == numout(A) == 1) || + throw(SpaceMismatch()) + + numout(B) == 1 && return mul!(C, A, B, α, β) + + cp = checkpoint(allocator) + + Ablocks = blocks(A) + Bstructure = TensorKit.fusionblockstructure(space(B)) + for ((f₁, f₂), c) in subblocks(C) + # fetch A block + u = first(f₁.uncoupled) + a = Ablocks[u] + isempty(a) && (scale!(c, β); continue) + + # fetch B block + haskey(Bstructure.fusiontreeindices, (f₁, f₂)) || (scale!(c, β); continue) + b = B[f₁, f₂] + + tensorcontract!( + c, + a, ((1,), (2,)), false, + b, ((1,), ntuple(i -> i + 1, numind(B) - 1)), false, + (ntuple(identity, numout(C)), ntuple(i -> i + numout(C), numin(C))), + α, β, backend, allocator + ) + end + + return reset!(allocator, cp) +end + +function mul_tail( + A::AbstractTensorMap, B::AbstractTensorMap, + α::Number, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + cod = codomain(A) + dom = prod(i -> i == 1 ? domain(B)[1] : domain(A)[i], 1:numin(A)) + T = TensorOperations.promote_contract(scalartype(A), scalartype(B), scalartype(α)) + C = similar(A, T, cod ← dom) + return mul_tail!(C, A, B, α, Zero(), backend, allocator) +end + +function mul_tail!( + C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap, + α::Number, β::Number, + backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() + ) + (numin(C) == numin(A) && numout(C) == numout(A) && numin(B) == numout(B) == 1) || + throw(SpaceMismatch()) + + numin(A) == 1 && return mul!(C, A, B, α, β) + + cp = checkpoint(allocator) + + Astructure = TensorKit.fusionblockstructure(space(A)) + Bblocks = blocks(B) + for ((f₁, f₂), c) in subblocks(C) + # fetch B block + u = first(f₂.uncoupled) + b = Bblocks[u] + isempty(b) && (scale!(c, β); continue) + + # fetch A block + haskey(Astructure.fusiontreeindices, (f₁, f₂)) || (scale!(c, β); continue) + a = A[f₁, f₂] + + tensorcontract!( + c, + a, (ntuple(identity, numind(A) - 1), (1,)), false, + b, ((1,), (2,)), false, + (ntuple(identity, numout(C)), ntuple(i -> i + numout(C), numin(C))), + α, β, backend, allocator + ) + end + + return reset!(allocator, cp) +end + @inline fuse_legs(x::TensorMap, N₁::Int, N₂::Int) = fuse_legs(x, Val(N₁), Val(N₂)) function fuse_legs(x::TensorMap, ::Val{N₁}, ::Val{N₂}) where {N₁, N₂} ((0 <= N₁ <= numout(x)) && (0 <= N₂ <= numin(x))) || throw(ArgumentError("invalid fusing scheme")) From 733c761fdee9dca910806225d2b12b066bc71cc1 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 17 Dec 2025 08:44:27 -0500 Subject: [PATCH 19/20] small fixes --- src/algorithms/derivatives/mpo_derivatives.jl | 4 +++- src/utility/utility.jl | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 27131df85..4c315f04d 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -171,7 +171,9 @@ function (H::PrecomputedDerivative)(x::AbstractTensorMap) TC = TensorOperations.promote_contract(scalartype(x_fused), scalartype(R_fused)) - xR = TensorOperations.tensoralloc_contract(TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator) + xR = TensorOperations.tensoralloc_contract( + TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator + ) mul_front!(xR, x_fused, R_fused, One(), Zero(), H.backend, H.allocator) diff --git a/src/utility/utility.jl b/src/utility/utility.jl index aebf44713..d561666b9 100644 --- a/src/utility/utility.jl +++ b/src/utility/utility.jl @@ -233,7 +233,7 @@ end function mul_front( A::AbstractTensorMap, B::AbstractTensorMap, - α::Number, + α::Number = One(), backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) cod = prod(i -> i == 1 ? space(A, 1) : space(B, i), 1:numout(B)) @@ -245,7 +245,7 @@ end function mul_front!( C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap, - α::Number, β::Number, + α::Number = One(), β::Number = Zero(), backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) (numin(C) == numin(B) && numout(C) == numout(B) && numin(A) == numout(A) == 1) || @@ -281,7 +281,7 @@ end function mul_tail( A::AbstractTensorMap, B::AbstractTensorMap, - α::Number, + α::Number = One(), backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) cod = codomain(A) @@ -293,7 +293,7 @@ end function mul_tail!( C::AbstractTensorMap, A::AbstractTensorMap, B::AbstractTensorMap, - α::Number, β::Number, + α::Number = One(), β::Number = Zero(), backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) (numin(C) == numin(A) && numout(C) == numout(A) && numin(B) == numout(B) == 1) || From be48fca2b976baa78163c9228ad1fd0dd1e8d9b7 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 17 Dec 2025 21:33:27 -0500 Subject: [PATCH 20/20] some more fixes --- src/algorithms/derivatives/mpo_derivatives.jl | 7 +++---- src/utility/utility.jl | 6 ++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 4c315f04d..30c8e1f38 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -169,16 +169,15 @@ function (H::PrecomputedDerivative)(x::AbstractTensorMap) R_fused = fuse_legs(H.rightenv, 0, numin(x)) x_fused = fuse_legs(x, numout(x), numin(x)) - TC = TensorOperations.promote_contract(scalartype(x_fused), scalartype(R_fused)) xR = TensorOperations.tensoralloc_contract( - TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), H.allocator + TC, x_fused, ((1,), (2,)), false, R_fused, ((1,), (2, 3)), false, ((1, 2), (3,)), Val(true), allocator ) - mul_front!(xR, x_fused, R_fused, One(), Zero(), H.backend, H.allocator) + mul_front!(xR, x_fused, R_fused, One(), Zero(), H.backend, allocator) LxR = H.leftenv * xR - TensorOperations.tensorfree!(xR, H.allocator) + TensorOperations.tensorfree!(xR, allocator) reset!(allocator, cp) return TensorMap{scalartype(LxR)}(LxR.data, codomain(H.leftenv) ← domain(H.rightenv)) diff --git a/src/utility/utility.jl b/src/utility/utility.jl index d561666b9..d4ce0f6cf 100644 --- a/src/utility/utility.jl +++ b/src/utility/utility.jl @@ -275,8 +275,9 @@ function mul_front!( α, β, backend, allocator ) end + reset!(allocator, cp) - return reset!(allocator, cp) + return C end function mul_tail( @@ -324,7 +325,8 @@ function mul_tail!( ) end - return reset!(allocator, cp) + reset!(allocator, cp) + return C end @inline fuse_legs(x::TensorMap, N₁::Int, N₂::Int) = fuse_legs(x, Val(N₁), Val(N₂))