From 9e973369129d10697a4f58b311eed42fc2b2816a Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Feb 2025 07:15:50 -0500 Subject: [PATCH 01/46] make derivatives it's own folder --- src/algorithms/{ => derivatives}/derivatives.jl | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/algorithms/{ => derivatives}/derivatives.jl (100%) diff --git a/src/algorithms/derivatives.jl b/src/algorithms/derivatives/derivatives.jl similarity index 100% rename from src/algorithms/derivatives.jl rename to src/algorithms/derivatives/derivatives.jl From d622805bb115f3976a0c56d1bf51bf496ad49bb6 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Feb 2025 16:35:14 -0500 Subject: [PATCH 02/46] Rewrite single-site hamiltonian --- src/MPSKit.jl | 4 +- src/algorithms/derivatives/derivatives.jl | 186 ++++++++---------- .../derivatives/hamiltonian_derivatives.jl | 140 +++++++++++++ src/algorithms/derivatives/mpo_derivatives.jl | 100 ++++++++++ 4 files changed, 325 insertions(+), 105 deletions(-) create mode 100644 src/algorithms/derivatives/hamiltonian_derivatives.jl create mode 100644 src/algorithms/derivatives/mpo_derivatives.jl diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 095da99b1..8effb23aa 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -131,7 +131,9 @@ include("environments/multiple_envs.jl") include("environments/lazylincocache.jl") include("algorithms/fixedpoint.jl") -include("algorithms/derivatives.jl") +include("algorithms/derivatives/mpo_derivatives.jl") +include("algorithms/derivatives/hamiltonian_derivatives.jl") +include("algorithms/derivatives/derivatives.jl") include("algorithms/expval.jl") include("algorithms/toolbox.jl") include("algorithms/grassmann.jl") diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index f75000885..4bac98c2e 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -1,61 +1,39 @@ # Given a state and it's environments, we can act on it -""" - Draft operators -""" -struct MPO_∂∂C{L,R} - leftenv::L - rightenv::R -end - -struct MPO_∂∂AC{O,L,R} - o::O - leftenv::L - rightenv::R -end - -struct MPO_∂∂AC2{O,L,R} - o1::O - o2::O - leftenv::L - rightenv::R -end - -const DerivativeOperator = Union{MPO_∂∂C,MPO_∂∂AC,MPO_∂∂AC2} - -Base.:*(h::Union{MPO_∂∂C,MPO_∂∂AC,MPO_∂∂AC2}, v) = h(v); +const DerivativeOperator = Union{MPO_∂∂C,MPO_∂∂AC,MPO_∂∂AC2,JordanMPO_∂∂AC} +# TODO: do we still need this? (h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv); (h::MPO_∂∂AC)(x) = ∂AC(x, h.o, h.leftenv, h.rightenv); (h::MPO_∂∂AC2)(x) = ∂AC2(x, h.o1, h.o2, h.leftenv, h.rightenv); (h::DerivativeOperator)(v, ::Number) = h(v) # draft operator constructors -function ∂∂C(pos::Int, mps, operator, envs) - return MPO_∂∂C(leftenv(envs, pos + 1, mps), rightenv(envs, pos, mps)) -end -function ∂∂C(row::Int, col::Int, mps, operator::MultilineMPO, envs) - return ∂∂C(col, mps[row], operator[row], envs[row]) -end - -function ∂∂AC(pos::Int, mps, operator, envs) - return MPO_∂∂AC(operator[pos], leftenv(envs, pos, mps), rightenv(envs, pos, mps)) -end +# function ∂∂C(pos::Int, mps, operator, envs) +# return MPO_∂∂C(leftenv(envs, pos + 1, mps), rightenv(envs, pos, mps)) +# end +# function ∂∂C(row::Int, col::Int, mps, operator::MultilineMPO, envs) +# return ∂∂C(col, mps[row], operator[row], envs[row]) +# end + +# function ∂∂AC(pos::Int, mps, operator, envs) +# return MPO_∂∂AC(operator[pos], leftenv(envs, pos, mps), rightenv(envs, pos, mps)) +# end function ∂∂AC(row::Int, col::Int, mps, operator::MultilineMPO, envs) return ∂∂AC(col, mps[row], operator[row], envs[row]) end -function ∂∂AC(col::Int, mps, operator::MultilineMPO, envs) - return MPO_∂∂AC(operator[:, col], leftenv(envs, col, mps), rightenv(envs, col, mps)) -end - -function ∂∂AC2(pos::Int, mps, operator, envs) - return MPO_∂∂AC2(operator[pos], operator[pos + 1], leftenv(envs, pos, mps), - rightenv(envs, pos + 1, mps)) -end -function ∂∂AC2(col::Int, mps, operator::MultilineMPO, envs) - return MPO_∂∂AC2(operator[:, col], operator[:, col + 1], leftenv(envs, col, mps), - rightenv(envs, col + 1, mps)) -end +# function ∂∂AC(col::Int, mps, operator::MultilineMPO, envs) +# return MPO_∂∂AC(operator[:, col], leftenv(envs, col, mps), rightenv(envs, col, mps)) +# end + +# function ∂∂AC2(pos::Int, mps, operator, envs) +# return MPO_∂∂AC2(operator[pos], operator[pos + 1], leftenv(envs, pos, mps), +# rightenv(envs, pos + 1, mps)) +# end +# function ∂∂AC2(col::Int, mps, operator::MultilineMPO, envs) +# return MPO_∂∂AC2(operator[:, col], operator[:, col + 1], leftenv(envs, col, mps), +# rightenv(envs, col + 1, mps)) +# end function ∂∂AC2(row::Int, col::Int, mps, operator::MultilineMPO, envs::MultilineEnvironments) return ∂∂AC2(col, mps[row], operator[row], envs[row]) end @@ -65,66 +43,66 @@ end ∂∂AC(pos::CartesianIndex, mps, operator, envs) = ∂∂AC(Tuple(pos)..., mps, operator, envs) ∂∂AC2(pos::CartesianIndex, mps, operator, envs) = ∂∂AC2(Tuple(pos)..., mps, operator, envs) -function ∂AC(x::MPSTensor{S}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, - rightenv::MPSTensor{S})::typeof(x) where {S} - @plansor y[-1 -2; -3] := leftenv[-1 5; 4] * x[4 2; 1] * operator[5 -2; 2 3] * - rightenv[1 3; -3] - return y isa BlockTensorMap ? only(y) : y -end -function ∂AC(x::MPSTensor{S}, operator::Number, leftenv::MPSTensor{S}, - rightenv::MPSTensor{S})::typeof(x) where {S} - @plansor y[-1 -2; -3] := operator * (leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * - rightenv[1 7; -3]) -end -function ∂AC(x::GenericMPSTensor{S,3}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, - rightenv::MPSTensor{S})::typeof(x) where {S} - @plansor y[-1 -2 -3; -4] ≔ leftenv[-1 7; 6] * x[6 4 2; 1] * operator[7 -2; 4 5] * - τ[5 -3; 2 3] * rightenv[1 3; -4] -end +# function ∂AC(x::MPSTensor{S}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, +# rightenv::MPSTensor{S})::typeof(x) where {S} +# @plansor y[-1 -2; -3] := leftenv[-1 5; 4] * x[4 2; 1] * operator[5 -2; 2 3] * +# rightenv[1 3; -3] +# return y isa BlockTensorMap ? only(y) : y +# end +# function ∂AC(x::MPSTensor{S}, operator::Number, leftenv::MPSTensor{S}, +# rightenv::MPSTensor{S})::typeof(x) where {S} +# @plansor y[-1 -2; -3] := operator * (leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * +# rightenv[1 7; -3]) +# end +# function ∂AC(x::GenericMPSTensor{S,3}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, +# rightenv::MPSTensor{S})::typeof(x) where {S} +# @plansor y[-1 -2 -3; -4] ≔ leftenv[-1 7; 6] * x[6 4 2; 1] * operator[7 -2; 4 5] * +# τ[5 -3; 2 3] * rightenv[1 3; -4] +# end # mpo multiline -function ∂AC(x::AbstractVector, opp, leftenv, rightenv) - return circshift(map(∂AC, x, opp, leftenv, rightenv), 1) -end - -function ∂AC(x::MPSTensor, ::Nothing, leftenv, rightenv) - return _transpose_front(leftenv * _transpose_tail(x * rightenv)) -end - -function ∂AC2(x::MPOTensor, operator1::MPOTensor, operator2::MPOTensor, leftenv, rightenv) - @plansor toret[-1 -2; -3 -4] := leftenv[-1 7; 6] * x[6 5; 1 3] * - operator1[7 -2; 5 4] * - operator2[4 -4; 3 2] * - rightenv[1 2; -3] - return toret isa BlockTensorMap ? only(toret) : toret -end -function ∂AC2(x::MPOTensor, ::Nothing, ::Nothing, leftenv, rightenv) - @plansor y[-1 -2; -3 -4] := x[1 -2; 2 -4] * leftenv[-1; 1] * rightenv[2; -3] -end -function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, - operator2::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor)::typeof(x) - @plansor y[-1 -2 -3; -4 -5 -6] ≔ leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * - rightenv[1 3; -4] * - operator1[11 -2; 8 9] * τ[9 -3; 6 7] * - operator2[7 -6; 4 5] * τ[5 -5; 2 3] -end - -function ∂AC2(x::AbstractVector, opp1, opp2, leftenv, rightenv) - return circshift(map(∂AC2, x, opp1, opp2, leftenv, rightenv), 1) -end - -function ∂C(x::MPSBondTensor, leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1; -2] := leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] - return y isa BlockTensorMap ? only(y) : y -end - -function ∂C(x::MPSBondTensor, leftenv::MPSBondTensor, rightenv::MPSBondTensor) - @plansor toret[-1; -2] := leftenv[-1; 1] * x[1; 2] * rightenv[2; -2] -end - -function ∂C(x::AbstractVector, leftenv, rightenv) - return circshift(map(t -> ∂C(t...), zip(x, leftenv, rightenv)), 1) -end +# function ∂AC(x::Vector, opp, leftenv, rightenv) +# return circshift(map(∂AC, x, opp, leftenv, rightenv), 1) +# end + +# function ∂AC(x::MPSTensor, ::Nothing, leftenv, rightenv) +# return _transpose_front(leftenv * _transpose_tail(x * rightenv)) +# end + +# function ∂AC2(x::MPOTensor, operator1::MPOTensor, operator2::MPOTensor, leftenv, rightenv) +# @plansor toret[-1 -2; -3 -4] := leftenv[-1 7; 6] * x[6 5; 1 3] * +# operator1[7 -2; 5 4] * +# operator2[4 -4; 3 2] * +# rightenv[1 2; -3] +# return toret isa BlockTensorMap ? only(toret) : toret +# end +# function ∂AC2(x::MPOTensor, ::Nothing, ::Nothing, leftenv, rightenv) +# @plansor y[-1 -2; -3 -4] := x[1 -2; 2 -4] * leftenv[-1; 1] * rightenv[2; -3] +# end +# function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, +# operator2::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor)::typeof(x) +# @plansor y[-1 -2 -3; -4 -5 -6] ≔ leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * +# rightenv[1 3; -4] * +# operator1[11 -2; 8 9] * τ[9 -3; 6 7] * +# operator2[7 -6; 4 5] * τ[5 -5; 2 3] +# end + +# function ∂AC2(x::Vector, opp1, opp2, leftenv, rightenv) +# return circshift(map(∂AC2, x, opp1, opp2, leftenv, rightenv), 1) +# end + +# function ∂C(x::MPSBondTensor, leftenv::MPSTensor, rightenv::MPSTensor) +# @plansor y[-1; -2] := leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] +# return y isa BlockTensorMap ? only(y) : y +# end + +# function ∂C(x::MPSBondTensor, leftenv::MPSBondTensor, rightenv::MPSBondTensor) +# @plansor toret[-1; -2] := leftenv[-1; 1] * x[1; 2] * rightenv[2; -2] +# end + +# function ∂C(x::Vector, leftenv, rightenv) +# return circshift(map(t -> ∂C(t...), zip(x, leftenv, rightenv)), 1) +# end # downproject for approximate function c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl new file mode 100644 index 000000000..d2abcc40d --- /dev/null +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -0,0 +1,140 @@ +""" + struct JordanMPO_ +""" +struct JordanMPO_∂∂AC{O1,O2,O3} + onsite::Union{O1,Missing} + not_started::Union{O1,Missing} + finished::Union{O1,Missing} + starting::Union{O2,Missing} + ending::Union{O2,Missing} + continuing::O3 +end +function JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) + tensor = coalesce(onsite, not_started, finished, starting, ending) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + O1 = tensormaptype(S, 1, 1, M) + O2 = tensormaptype(S, 2, 2, M) + return JordanMPO_∂∂AC{O1,O2,typeof(continuing)}(onsite, not_started, finished, starting, + ending, continuing) +end + +Base.:*(H::JordanMPO_∂∂AC, x) = H(x) + +function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) + GL = leftenv(envs, pos, mps) + GR = rightenv(envs, pos, mps) + W = operator[pos] + + # starting + if !isfinite(operator) || pos < length(operator) + C = W[1, 1, 1, 2:(end - 1)] + GR_2 = GR[2:(end - 1)] + if nonzero_length(C) > 0 && nonzero_length(GR_2) > 0 + @plansor starting_[-1 -2; -3 -4] ≔ removeunit(C, 1)[-4; -2 1] * + GR_2[-1 1; -3] + starting = only(starting_) + norm(starting) + else + starting = missing + end + else + starting = missing + end + + # ending + if !isfinite(operator) || pos > 1 + B = W[2:(end - 1), 1, 1, end] + GL_2 = GL[2:(end - 1)] + if nonzero_length(B) > 0 && nonzero_length(GL_2) > 0 + @plansor ending_[-1 -2; -3 -4] ≔ removeunit(B, 4)[1 -2; -4] * + GL_2[-1 1; -3] + ending = nonzero_length(ending_) > 0 ? only(ending_) : missing + else + ending = missing + end + else + ending = missing + end + + # onsite + if haskey(W, CartesianIndex(1, 1, 1, lastindex(W, 4))) + if !ismissing(starting) + D = removeunit(W[1, 1, 1, end], 4) + @plansor starting[-1 -2; -3 -4] += GL[1][-1 1; -3] * D[1 -2; -4] + onsite = missing + elseif !ismissing(ending) + D = removeunit(W[1, 1, 1, end], 1) + @plansor ending[-1 -2; -3 -4] += D[-4; -2 1] * GR[end][-1 1; -3] + onsite = missing + else + onsite = removeunit(removeunit(W[1, 1, 1, end], 4), 1) + end + else + onsite = missing + end + + # not_started + if (!isfinite(operator) || pos > 1) && !ismissing(starting) + I = id(storagetype(GR[1]), physicalspace(W)) + @plansor starting[-1 -2; -3 -4] += removeunit(GR[1], 2)[-1; -3] * I[-4; -2] + not_started = missing + else + not_started = removeunit(GR[1], 2) + end + + # finished + if (!isfinite(operator) || pos < length(operator)) && !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[2:(end - 1), 1, 1, 2:(end - 1)] + continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) + + tensor = coalesce(onsite, not_started, finished, starting, ending) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + O1 = tensormaptype(S, 1, 1, M) + O2 = tensormaptype(S, 2, 2, M) + + return JordanMPO_∂∂AC{O1,O2,typeof(continuing)}(onsite, not_started, finished, starting, + ending, continuing) +end + +function (H::JordanMPO_∂∂AC)(x::MPSTensor) + y = zerovector!(similar(x)) + + if !ismissing(H.onsite) + @plansor y[-1 -2; -3] += x[-1 1; -3] * H.onsite[-2; 1] + end + + if !ismissing(H.finished) + @plansor y[-1 -2; -3] += H.finished[-1; 1] * x[1 -2; -3] + end + + if !ismissing(H.not_started) + @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.not_started[1; -3] + end + + if !ismissing(H.starting) + @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[1 2; -3 -2] + end + + if !ismissing(H.ending) + @plansor y[-1 -2; -3] += H.ending[-1 -2; 1 2] * x[1 2; -3] + end + + GL, A, GR = H.continuing + 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 diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl new file mode 100644 index 000000000..b216445c4 --- /dev/null +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -0,0 +1,100 @@ +""" + struct MPO_∂∂ACN{L,O<:Tuple,R} + +Effective local operator obtained from taking the partial derivative of an MPS-MPO-MPS sandwich. +""" +struct MPO_∂∂ACN{L,O<:Tuple,R} + leftenv::L + operators::O + rightenv::R +end + +const MPO_∂∂C{L,R} = MPO_∂∂ACN{L,Tuple{},R} +MPO_∂∂C(GL, GR) = MPO_∂∂ACN(GL, (), GR) +const MPO_∂∂AC{L,O,R} = MPO_∂∂ACN{L,Tuple{O},R} +MPO_∂∂AC(GL, O, GR) = MPO_∂∂ACN(GL, (O,), GR) +const MPO_∂∂AC2{L,O₁,O₂,R} = MPO_∂∂ACN{L,Tuple{O₁,O₂},R} +MPO_∂∂AC2(GL, O1, O2, GR) = MPO_∂∂ACN(GL, (O1, O2), GR) + +# Constructors +# ------------ +function ∂∂C(pos::Int, mps, operator, envs) + return MPO_∂∂C(leftenv(envs, pos + 1, mps), rightenv(envs, pos, mps)) +end +function ∂∂AC(pos::Int, mps, operator, envs) + return MPO_∂∂AC(leftenv(envs, pos, mps), operator[pos], rightenv(envs, pos, mps)) +end +function ∂∂AC2(pos::Int, mps, operator, envs) + return MPO_∂∂AC2(leftenv(envs, pos, mps), operator[pos], operator[pos + 1], + rightenv(envs, pos + 1, mps)) +end + +# Multiline +for ∂∂_ in (:∂∂C, :∂∂AC, :∂∂AC2) + @eval function $∂∂_(pos::Int, mps, operator::MultilineMPO, envs) + Hs = map(Base.Fix1($∂∂_, pos), mps, operator, envs) + return Multiline(Hs) + end +end + +# Properties +# ---------- +function TensorKit.domain(H::MPO_∂∂ACN) + V_l = right_virtualspace(H.leftenv) + V_r = left_virtualspace(H.rightenv) + V_o = prod(physicalspace, H.O; init=one(V_l)) + return V_l ⊗ V_o ⊗ V_r +end +function TensorKit.codomain(H::MPO_∂∂ACN) + V_l = left_virtualspace(H.leftenv) + V_r = right_virtualspace(H.rightenv) + V_o = prod(physicalspace, H.O; init=one(V_l)) + return V_l ⊗ V_o ⊗ V_r +end + +# Actions +# ------- +Base.:*(H::MPO_∂∂ACN, x) = H(x) + +# ∂C +function (H::MPO_∂∂C{<:MPSBondTensor,<:MPSBondTensor})(x::MPSBondTensor) + @plansor y[-1; -2] ≔ H.leftenv[-1; 1] * x[1; 2] * H.rightenv[2; -2] +end +function (H::MPO_∂∂C{<:MPSTensor,<:MPSTensor})(x::MPSBondTensor) + @plansor y[-1; -2] ≔ H.leftenv[-1 3; 1] * x[1; 2] * H.rightenv[2 3; -2] +end + +# ∂AC +function (H::MPO_∂∂AC{<:MPSBondTensor,Nothing,<:MPSBondTensor})(x::MPSTensor) + @plansor y[-1 -2; -3] ≔ H.leftenv[-1; 1] * x[1 -2; 2] * H.rightenv[2; -3] +end +function (H::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::MPSTensor) + @plansor y[-1 -2; -3] ≔ H.leftenv[-1 5; 4] * x[4 2; 1] * H.operators[1][5 -2; 2 3] * + H.rightenv[1 3; -3] +end +function (H::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::GenericMPSTensor{S,3}) where {S} + @plansor y[-1 -2 -3; -4] ≔ H.leftenv[-1 7; 6] * x[6 4 2; 1] * H.operators[1][7 -2; 4 5] * + τ[5 -3; 2 3] * H.rightenv[1 3; -4] +end + +# ∂AC2 +function (H::MPO_∂∂AC2{<:MPSBondTensor,Nothing,Nothing,<:MPSBondTensor})(x::MPOTensor) + @plansor y[-1 -2; -3 -4] ≔ H.leftenv[-1; 1] * x[1 -2; 2 -4] * H.rightenv[2 -3] +end +function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::MPOTensor) + @plansor contractcheck = true y[-1 -2; -3 -4] ≔ H.leftenv[-1 7; 6] * x[6 5; 1 3] * + H.operators[1][7 -2; 5 4] * + H.operators[2][4 -4; 3 2] * + H.rightenv[1 2; -3] +end +function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::AbstractTensorMap{<:Any,<:Any,3,3}) + @plansor y[-1 -2 -3; -4 -5 -6] ≔ H.leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * + H.rightenv[1 3; -4] * + H.operators[1][11 -2; 8 9] * τ[9 -3; 6 7] * + H.operators[2][7 -6; 4 5] * τ[5 -5; 2 3] +end + +# Multiline +function (H::Multiline{<:MPO_∂∂ACN})(x::Vector) + return circshift!(broadcast(parent(H), x), 1) +end From 1779716d872de324304e0bd49d64a627b5586dd7 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 15 Feb 2025 18:20:18 -0500 Subject: [PATCH 03/46] Add benchmark script --- benchmarks/Project.toml | 7 +++ benchmarks/heisenberg_benchmarks.jl | 84 ++++++++++++++++++++++++++++ results.png | Bin 0 -> 63903 bytes results_SU2Irrep.png | Bin 0 -> 48061 bytes results_Trivial.png | Bin 0 -> 54617 bytes results_U1Irrep.png | Bin 0 -> 51901 bytes 6 files changed, 91 insertions(+) create mode 100644 benchmarks/Project.toml create mode 100644 benchmarks/heisenberg_benchmarks.jl create mode 100644 results.png create mode 100644 results_SU2Irrep.png create mode 100644 results_Trivial.png create mode 100644 results_U1Irrep.png diff --git a/benchmarks/Project.toml b/benchmarks/Project.toml new file mode 100644 index 000000000..5f5e53b78 --- /dev/null +++ b/benchmarks/Project.toml @@ -0,0 +1,7 @@ +[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" +TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" diff --git a/benchmarks/heisenberg_benchmarks.jl b/benchmarks/heisenberg_benchmarks.jl new file mode 100644 index 000000000..21d3f1f4b --- /dev/null +++ b/benchmarks/heisenberg_benchmarks.jl @@ -0,0 +1,84 @@ +using LinearAlgebra: BLAS +using BenchmarkTools +using TensorKit, MPSKit, MPSKitModels +using CairoMakie + +BLAS.set_num_threads(1) + +# Parameters +L = 60 +T = ComplexF64 +sval = 1e-10 +symmetry = SU2Irrep +bench_iter = 5 + +# derived +@assert iseven(L) +lattice = FiniteChain(L) +alg = DMRG2(; trscheme=truncdim(2048), tol=1e-8, verbosity=MPSKit.VERBOSE_ITER) + +# Initialize MPS +H = heisenberg_XXX(T, symmetry, lattice; spin=1 // 2) + +function init_mps(H) + T = scalartype(H) + P = physicalspace.(Ref(H), 1:length(H)) + V = repeat([P[1], fuse(P[1]^2)], (length(H) ÷ 2)) + return FiniteMPS(rand, T, P, V[1:(end - 1)]) +end + +psi = init_mps(H); +psi, = find_groundstate(psi, H, alg); + +# Benchmark +site = L ÷ 2 +Ds = reverse([2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]) +times_sparsempo = let ψ = copy(psi), H = FiniteMPO(parent(H)) + times = map(Ds) do D + ψ = changebonds(ψ, SvdCut(; trscheme=truncdim(D))) + envs = environments(ψ, H) + h_ac = MPSKit.∂∂AC(site, ψ, H, envs) + ac = ψ.AC[site] + if bench_iter <= 0 + t = @belapsed $h_ac($ac) + else + ts = map(1:bench_iter) do i + return @elapsed h_ac(ac) + end + t = minimum(ts) + end + @info "Benchmark MPO:" D t + return t + end +end + +times_jordanmpo = let ψ = copy(psi) + times = map(Ds) do D + ψ = changebonds(ψ, SvdCut(; trscheme=truncdim(D))) + envs = environments(ψ, H) + h_ac = MPSKit.∂∂AC(site, ψ, H, envs) + ac = ψ.AC[site] + if bench_iter <= 0 + t = @belapsed $h_ac($ac) + else + ts = map(1:bench_iter) do i + return @elapsed h_ac(ac) + end + t = minimum(ts) + end + @info "Benchmark Jordan MPO:" D t + return t + end +end + +# Plot results +# ------------ +f = let f = Figure(; title="Absolute time of local application") + ax = f[1, 1] = Axis(f; xlabel="D", ylabel="time (s)", xscale=log10, yscale=log10) + positions = Ds + lines!(positions, times_sparsempo; label="Sparse MPO") + lines!(positions, times_jordanmpo; label="Jordan MPO") + f[1, 2] = Legend(f, ax, "Operators"; framevisible=false) + f +end +save("results_$symmetry.png", f) diff --git a/results.png b/results.png new file mode 100644 index 0000000000000000000000000000000000000000..5c7b217c50ee98213decf4387ce6df1b99e85e4b GIT binary patch literal 63903 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

DkiK!hZJ2ty}U5yhQ~CiM#rx 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

@jXYgKPY{c3xcrdb^2n~< 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�pfrj^01TQSMWCJkJmWoai8s^sEQ#sv)V zpF2Bg;?Hv$Nb%SMq8%|-fHv|$H=FDEH^@c`e9|0ju(^PA-#D!Al6zl)c48Z_xPuYO z-tc!&%w}a1PjW!?MoI63sUGZ0)Lr|XQXR-d8T;K9`!9p^^2Lj@yKZ07`I|ZjPM$;v z_&RJv?T6n{%8n36(JMa`d{xo(=FJ-f&OYq6(LzH@`@lOhJG{+O1*F&ZIM$bjoPpyQ zH|ka^#@Gg(T4~*zSyrZ#7@X0LplN~f4wT`553TD4E!F7Bm$h(QOnA;FLEn`WK97t% z1UGvriwpkbN-P7E-*t6$ux|D84PHh^-!wF205W(Q8c`4v+qo%?0kiW@ z*b;?bq8D7MK`Ea4+&S2dF2m#T@i~He8?YRLPZue*`3j#bbK(8z1@B-0v;}2JIJ}Q4-~}54q41L9A~w_8~eLi>uPjT z;r(RZ?L{Cg0aB40u3M_Ga$y?*xu(0PwF2k8*q=6@rHBT_*4Vf>u;LM+Tfi4P0xt(_ zqwe_OzH~+M$s(6FI}yzU!Hm2-J1{bUweKO*H>GOCHw5X0Pc1FDd`?uY@U z0!&Qs&n_l=$iDi)3y1L?d5D^U4mZdV^X@T40&@zmQ0oKn3vgP3TFafQJjXPfNieUY zHL|q7@-0NF`{Io7XTy;G*K%{)1Tqdp95E$@g_ia`$P2)^GdQTfM_WD+2jX5yz~LUw z4=7S;ZUf5!}1Db^jbQ&p{DJugbp{X{)Ia|~;TI!S`D!yJ?edJBP7oXi%aG2+F0;^V!9B_BQd zjsgwVipt7jL;0D#oEmpBYYSK3wZtuYO&@lR)itltA$gA<@nj>-HTixX$*HL>@57hx zIq4lZ8}k%MGFrdIU)pQW#G!BJyCcDc0lQJ7*@-!c_noAia# zgX%T__`X`;muZmeF#I`^(pY#7g9x&4IBM`5SHH;{5t!bZ?dxcbUFwBX{74t`u4low9s~EHN{-gZu(*f>ZuALE zVpdEIb{ZrM7X#uuLZNXMAtAq0$g~Tt8uqz@sP3gF_8~ zv3k0ViHV7WL$Xj6Y)KpKJkd=PVg78JPW&uP(^3t$6+PELWdk#4VR06(yBbB*h@kqg zHSF52Do2drhdt^)p(0*IQC}S*hiFFuyB`r{$DCEVZr=~Kp8(Exaq)SdIAr*^%xnU+ zpi{-0;T2NCIyMlW+HI@cwx*AE2Br~n9ZzXs1EGT;EheUg$Y4>!%a$HAcPDjqzXCJt zon&x4_wvYL!w${!m*bvn^tLI9l%C}~TTc&e=blkIn`O)x)78o^OMBAu^78ugDDOyC zB_%$y$}u(4n%aJYtmwaSJO09V2keEg<)5_F!UA49sMhPE$|MYyA5IO$emRYut|=$r zr|O@HklNYZrvz=FoN?D4W2*Ie{l$Oy)O=Yl|C>azp1P&$39yrBFOY--jrAZi!cz8! zVrJLD>P=gJ|5SXTh&vPpiBUx46(4A~`q|(WP z=P?eUW3L@QaYEDPJ8#$ZvnL25z$6>Q;nmfT@B!n_8&j2y`)BtFlC|6bO^UTsVnh9IC`+xM;sztbyg=Qcbt-Q+;3Fth$`=M7u!(@?2>hT}0BP5D4 zyQ4#@(u&JYP*Bl~nL0YI7Xwelp`U%2XoOd9_~d?&1BfexhsxAlTL?iys|1zg zuL=>yB8FoCBMC(JOsHw731AbE*T>UJaIyw*!c>24Xgr+-1way&ANYuURM`EtXmxMa zdPM&ON2w2ifDG$QZh|{t6G*6CjHHbwb+<4ZDbt~j&8PygwWe=-k$(VEW=s8r z04!JVt0sr}ypA+tdhXN-%cB0Suj6h!vE^67DU)yl2}2&-dfLhjbu*cInv3R5P}jwk zL(Q8i7QF1Qdo(aj^8RgQq|isIZlL!&auG8x)tEWc`rTR2JF0zwU@>MDa~Tp_e!k!7 zj0{IRySN*O4k>CY4(Tp_ca|)$B$%`7bBFf8B(9!F(k7BXOQxfPLlpq+x{S7L0DhlbzURsVGmU6kMDQ$96$fYMu>byw3sLA{GaFb%hYF4=padQT*VZ0@ zuQG_)~;T{D5g#i*XO%?co2hv zF@83uTS$`*9y=*9@m^-l{fIHpF)%IO=>vmA+lM|rhKQyk{1~qCk)2JJU9#fh9xVEv zR-~mSC!bCqNK8rDq@Su*4fr-RKbe!$&a`&V$?55{8qE ztiHZ`bddy}N44bj50E?e*LH7uy=y*1$8Ckkkpm^x*-@CVhh>L*!gBoR6rb7t{x{(9@0-2S_ zGx_`WjaCuj_vGMuT_)XN%hNaus7<(kihXl|x$kJaN*YBKit9pD!R}ED4p&wVu8JKh zGSLdj9KlQwb#jR!j5#Fghkj#LQ8s;^GW6zi=biQ^Q&Zy9<~VKPrg%1hoh|DuFE7WT zz$-m;+VttIP@J^0&zHJm`h-ujrW)F{^Vh|UCY(aG8yLK$--=vgf%6#w99CsiGTUBD zJN6TE$Szp#bwB&%+LeBaxjtBns2w|Kuben>;<*fFpaaU3rw3Rr(7mIG1+4DcCsT>0 tOa`yJGsWnL@=`VbGt>P4@5hYW6)FGLxcRRUdu)W^u{5_a%QamW^#>(vV8H+Y literal 0 HcmV?d00001 diff --git a/results_SU2Irrep.png b/results_SU2Irrep.png new file mode 100644 index 0000000000000000000000000000000000000000..8b168328cd99381c3f48c121f7a24ca425b99d29 GIT binary patch literal 48061 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≺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

k7 zw<+BACut*W(~xS=dlsyf`QCi=rUmUpMM-IGV-pes?xZe4*th&Ue#I2f#Lr_K4+(o4 z$fZ;P7+%bke%5oLic2NeBdw1|2F8~v7zvpjwln#*zz*@{i+b*vhZo}Q!y3SQetc|4 zx>C>8$@kmQD6!jKbt(5V&1Bx&>;JecO5jK6IzqGj-1CVw@3Yf}XP-uCSKAAhopuio z+-7LfAHIV7gbnYUy80_nA}G5~>;<2V{)jMz*+L$K&W?r6wVaCcN++-&!H@*+y(9Gk z#$*D@ANe7(J1o(v;6|?AxKVI+b|c~ZcZ!p!d3yAWMddfpBBVTqY1!W1jw+Ur>Qgtz zqd0KvELc3dt^(ZU*jQI`{~#0uG;wvp4uV4+XKLEfC3I%SQP4Q=`!O)i<6VVnMJXT( z(7+HpD2L_b+}xAQEDjeVfStPNJz}%>M?Lkmw3^#fnsrjoZZaQkMlF{$&wi`Qmn(cC zznY&nJ)qIB5Bz3vVc=hxXVtfIAvyW>eQ#MFA6$-ii=Q@#GHmXnyk#t z5x#T=|4<_A!98&V7NH|Y)NdbCvv;|MfoZg|jK+!qEsXAL!RxjM3sj3Ya@o2kq@`^p zRU1DKg|0ZkwYp~JuS_q>#3yt5E@mGd29mTqDykq(c{KaYkCqR+Wq5l$w3^vSup94x zH!C&Hv~4cTJhhCC@1r(Z=FgnBt zx2f+4L-}oTIQjK803wJC!4tcxSvos4E%!)Ko>0GZhnMsPt9u9QzH{2Ti7#Vdy=Q!K zW3>M{`@n-9`7(N;TM0*Vw^{cU(q}h(a#y-sbd|gYYo#Un6zqHeIAU$BKS(ez!21$S z$GmIT#~IMx1WHh)+p?SnGoTsgkDP$O0C<7w-#2cH$FaeQi${O%KhEMXCKeuRiiM7y z*aLeM2p7fl-Ty~e#p9OvdySSh0QYr#N*_h&#M{B?>8UAekM$#uqocPG`3|a|oC50~ z!QVqpOG29^?JA|%fAOU zc5e%5wuglz&4CE-J?LPWT{kHmPe&kV?538BPHFrS`26AwGEl&4#CoWnBs;;uaoO5h zR77N~JtyIgYg*~_iGZLW`i>u*M~(!}1fH9P7S7ouY@oin!Zv@*Wnsq3v~aJy3sFRY2T_11sf1;#91dk&jE2|XE zMd8T=d_lm*f1qJcpsjKjWrvbhFkSHNncA<$c@zjB9Fd{q9uH4E2tEo=xOVcKkHl_f zkOp4bRAKUGvN1AlRf%Rr`1Sm*3>r*~i}G1JbDIdytkjI7aT*?OxT*E~T#6LhY~i2a z{b+lpIzot*l{NRpAvBh)(+qM~R{pGJq?MaU5*qmdn7~lT73Wc^eTSbB)y6AV%a+m7 zgQKKN$<*#@!DEPXO+zzKtQN4UyyA(bV-^W2>+AJtn@KR-)OyG=C{{GnImY>06_s-0nkfrC{NgwtxBK zhe>!3Pe`x?6H{>Mt;<)h(h^uoeHM@NFj2v_P)H$;OWtaL3LB^x4}LkzZ3g9+`y7-w zgF`|nq}0@|LK6|Z3oFT$UrTw{>tf~!!dp0tQ;M~0bWGY8VSO$1gvy2G&VsiDIrg@lbgNCAe)hG(*|Z&D*7 zn0dB%K-VQrm~6oM+GG4dTJ5MRKYZv==y-NkR*Z-PmsMMxhQa0zbs^+Bvje`{VZfQ1 zpQrL19Ua|&=01j`c`qa>arY%>!F$j_ufys4oUvx`tsyM(scu_Um%rTT^=xpS1veN)kUoya+KOYW88&w|E)DX8h2r~aD z6088f0#+O#av5ifqvTHY>5+Hc-AkA|puoBJcmw09VnG~jGlUq4p#a&mytK4e!u8jW zAHYDQ>jrm!alq67gnm5I4cR4pv06{=5(%#q1JT1#fR@-Z7&7ijhbRVq$ZLFfrxJvBa8X89h1SWbtR!f{l zm^!ST0M1Bre}{^r{uVAT+_it@ju+ffKHoOW5*M!~-kL0SKYLp~O^O!X-=``*wFmTb zHZT4?)+|x7a~)Zsf(;wW1FpbCQL!4y0J_m|ikO+2PQ#x6=@Bh8HP+2{P-J8sIyg$* zMu_F4=hMD7`>2qxFjQ-i>pv=h^e()%mo3`9j2YP6(gJ>!ZwNVQJrpCfVEBV{8RUU} zV|I472fS#fyd3OF3tTy*>rJ9c5KOcteV76OE!AeP?655SxaVgyybp#x0`1&`Dm^u*ZI^!?YbgW?lf((>|_C&KtI z9V3r!KzoHr=`7dFqM`_r&jlX?d_tZwfcb!>aVPWmV>O{1y|Yf#sa79X&DI9{fefCG zqiFQmdHFHjjk-sc0=}Gpk25YU@wekUI)i1J&^|OmX?VGASK8`&6#nHjy;4ZlVJ*%& zAcGSqPTi40VamSxiMc+8(%91qs^3!1V;-;kzW3}w3cJGbk0xKTYeswD<(?+ut~>17 z?V@1tyqHSByxBVBl{eQ`%?7ym~ z4{Q5&{;`n>t{DH1`^Q-A#9bGh-gcB}^L()4R6|u3b#43y&nzh?U}-P)|Gk}?;?jAs zy-9&{QKzdiqKh^5sM*kI?|f0N8(3gnZ@wjZ;l!!EAVQ^U@2_3Xo|_E5ONYz$+ZOJ< z?ag%~FZiy^-_L*9jd%#3(4zD%+h_l3DG#hwV0C(bjGE#}G2SX;Lj1B!-2JPm0a2uT zG_t!U1F0T^{$kV9bVe$C`zEK$Yv@TVP~%+xUb-q25PF9Df3oepWBrizT7U})2Jf+1 z`BEo8aJsMYuK@J>TA!JztfuEpmzDh^cuD&(@g;Qj zUQes~zk1Zkwa?i5aWkr%+D*S`T>b8IFFJ;5CWxl$yyN>*$lJfc%7#W_(^-{&ENVRc5PI zp?0&^2^-0`uXyW*PL_ofRC$&-_GhR1kp*ZA_G_VT>emhF?@N3+iOYVqx>Vfl=k}wwXAFZB|f8dW32lle?9xaRM(eh)S0OWq2%<| zz%oK~^q4G3)YFmMEr)TVa(b!ATzW9~2C_{=ST zvUXiY*EX^TFnm`ejkhK%l5^u?FNQ={fBspFOjIoDlDZ?f#e70VX|lwv+34^gxBqO!1E zHu-tlZRwNwSoUa?-IbX10sZTdOpd-jocWrrDc+CJgv? z<(0t|`qDzB4u9GuDkdMFgUNjoSNXUy8qhh~=Ny_|9%&yv^!MiKJT5pvwAtg9mW%1M zmT-$ps$=c?g_EV_%dL6SerTX7C4@$ao4-<;md z!#?0;@xU`_(-Bd;WfHI6!64{2f|m6e9v8GH+iU{Hu^WX0Uede zx2H#^TeW$-ajzUtkf(8XHJqQ0Ok!qD|Fn_DO}F5un_HCY$_STDU#~eqSWBQ^t5)G+ zY3EdbGTyDq-1B`(b=#v_&24$=;Wm}AGC0uSMDeGX>#xa?^d$S{r*}w}cFhhqUT|A# zyK{(Z=Cjaowb_G)t1_u(c*>bPiswVfXGHkp8A;9lT}oL`Tle=on{i9hci*tQV|eqX zz30a|M9;Hvo2v+Z5EeoY)U`u+J*{(jvwtNI?a{(P7%R1`tEB~ziVuDtz-fiefi{(6 z&+f@qL`WPg=-(!Xu_VgSw_eJrUHjK=Vc}waI;Nn4+3glzqs$9sDv!NzX_`Jgc$;2> z|2mJ`*BuZ3qoF3G#^`ql$P;h%)`tJQ_BR?I1^xe=<_?|rf3+*&jJ9{6O{B}utqUh} z7N-X)2CC4`miR#aM#~gsc|x+q#K|A@K_@eAwZ6)HqH(P+4hK6HJ?Txq=f=K0q*bi6 zr)TY|K4AJt?bwphncvjbyOE zF>T|f8P@6z3KsTg`7k*)k>5IEN-o%ITd=HB%_Ikl<;%)C+0Mx(x-D0P|GeGt?B~bR z(Kh|j>Df{;HJfX<7fYBrvf%x^8Z*o|(fQrG?Y*)SS^QI!vK->o67y;$nx+Xq@DYy* zmfrDt)Uhd!Py25Vxp-|KKBPqch>-c6-~DWv9h!YRf@C85M+{y@Bv)ZdFI=Vwv*~AD zIGNRQ(x5zk?UALR_pawBdYyd9vj&B{6IkzT#%(1A31)c28NtG|Ug9_ak+ExEPTS|T zK}sQq|I_vQn%b8IEaLXpKJ~N8JEdN|5@XGDa>lSjKy&u`)UE8u%(S&{xBL$azAP-c z`hfB3Qq@$?LO;V9gWiUe@Sr>C(M)qiI!lT&4D>E9kIp6Q?m{DfB8uL(fr5y;F-=*1 zLZ$b2$NlvS{oBO%NFICRmlKq3JhZ@lhEq&dCWnh$4CIz_QWJN4@+Os%YeFvyZm;IJ z-%>1Im@w?&yzS4@yfJ#uDT9C~ZxfAHg+2%il1pdpIJ%SalB@?`&n%C=Vb6BI)pbk7 zxcHgrBau%M53}!I_+0gXc{{z$Lfk8z6T4Z-i`s}~ALYAy5AD}K)wk95@v}39OnowE zB^R^kV~XxbqfMf1zCI=ol!vDM6&{y}Zy}@(k>m98_${ltWn)`yVHKHkrlt~QIfLJH zocw6aJp*luU4BlJi^pN0g6ZE_ks-kH9oxC9i%TgU*&Qjy1(|y!Z7%2(FKn(#7QCNa zq|?2&d^At+mG*2%SWkh25zr9a^O#cw!>cJ{8~2Yq%>s+&qNQ)rboKvhY1fjQyy7Ar zSaw#1F+@0NLQA7&ZQfdvo3N!>)4O10j9AzCWaF=$Vn6-(#AJJz1k1L#OewXACkHTy zN?I$9U0$2Hc34H%Zci7m?p~veDP9@t5;KsIIm$U7o&MBz?Xm`a za9P|tHf8)QYyWe4&S*LJR`jd$KXXNe6oih4=8!9@h4$CaKXV=h|65VNUC=8$&g5Rq z+o!Z`u7x-US~uiFIQB&T^%N!(rJ`Lb=!iG%D9+0|%l zmuG$-m-7~kVdB63F9I=J+MKLu$N3=N=CO^uU3IqXk14jevL!9ThohaJ&9KYX@dKrt zcRIb2&Z_We2RD0iJLQ9t6+7~>)Hjm@tfkO0zG(f~=Cl3mXSwP*+QV>1|vEUn0 zo7swPbQa;P$=T0Ye!&)gpRI$p+gwSH;OgrfUm04Rxo%RpdW^f^2)X1_9q|zj?vxi- zaO2PaCN1&ncX|!RTh}gr z9u%;%F`*4-a4smJ|7gs`Zj#F}f6IVz%Q1qW$Nb&*@J(#=%?~>x*WuQ$Fg3a8-h5pu zZ<=tXMdp&4(NK~6>~-nE4<;;zYtJwp@IXrIi_k5LcXO6ZOV5mxxjQVscJuMwJ!HnK z^M6;>=Krm#R9@UhQ2iLK;cD!xv8_a+@eNhA2q$HoCar?Nw5NlEx^6C(z9g1&pWw47 zCJ~5~Hu(UrEnX=7{I%Ywus+Gys5|Q`ciX%|?)0ecQN$1B+=(WHDK5RHx)W<-b?yzv zI=X6|aUSO7cf(8P%G__Mt=4!Lwca^orpk5gSMiS|4@Q+8^fo0D55$d*;7l4KmF$vE zKhm^~$}Xn#-5zRRpIVdKHfIMTZwnt4)vDdW+j$|c&;HQpPI_gf#pZV}cN~jN-$?9x z4{#^5&uweC<<6C7R_yFfKb{}68x@I@WleBsxp1l8Xz-bDi&T!!)1S6mb>AgdEPFgou=YqNo8GNBUub47`s0y`c1T+3fx3<5?_)~XpXr5Yde;bZ z3ki!d;v&f-G3fiH9!%uU>t=TtWE#_44VfF-CLTO?v?@8hI#2z4L-1$mEL-+xPsjY< zy)%y`h8iWw(wD^?QAAmVTF?FU*zCM+SXPJ8@vr20p(P)=jWwBkIpIDVEQ}`5N zcJ+2r4!IPBv2Uc#3aJ<^+!#!7C``j?k^Zlq3SdZHm>Xh99FuI=c)BL<0N^ZWxfX9; z3mPq$r-+u`%?6T-R-K)03+5R`lP|AUTWbou!^9apcR5QN*fQ(t#ES0Kd}+0c?fG(m^9i1DdE{c6O-sZ4dRrAauGsnewfy9k&kr`k6lw+J&OggF8-N{tn%Tu_wMvLiFr4v!!z`L_>lunjZ-SrF}X0#;hNW_ExW+*Y~#G&$wekfAoW}J$1NEuE^SBdQ@SV zk=}whx@Zl47FuR?0Fay!^F#{ z?`rii-%y6pA=C8t=+ox9wYgdK^FTsNADEp|D0+`nDVj|pX+!-ZBL2TYHs@Z=ZjHOL zz5bgSagfHdr<#YKT0HOV{e`-uIJs~6T25$I@A0Rc4SMJ!nsv=Oh`Qq^%wK<{tmW#j zRPHQsaoXAWExh5OZuda%s-Jt%W8vzrGh0kaFc5J!OtaW9xOg@g?} zii#MU+9=EM&f@QcO37a4=Eh&@`Eu0}-fzTKlL8ou#Tk0X?attUNY4n)A_+lK?t>b- z_3*22Ffg2|%q2_6j8_-hpo)_%9|Z-`xyK3a<*q9Q4vR^k?K zL^DSPJpO*>%YJjt{WYXK=;ziDnII$Cb=Q%x7+jX?VDwFYka{4p2e&i(=+xzY zBSAp%w2ym7O8C#R6Z4s2*Ze&q9!P)f9?H^Yn8_)rPDT9ux5wRimP&^L=2JNFGR0`R zQCVQf_60f&lE&CCaqm#7Q1*8qQYG>@Iu!AWiFMf(#{Rw9EHsAGC{uN_zoI&1srcFY z2Fnlh^{HtcU9`ospCuh_W>$m^$CxDg-ILdOmpUCPRus~fF=?z*-hIUItj3HN;!vG> zUzvouwiDQVNZ+Wqn}T0nEr+ZOt3NgU$Op&KkrmM>)n&Iwivw}A(!!tDKqtoW5792; zuLs-N{{Bh`fZ4*~hhz&18qxB8Wjc0s3H34Pjs=e}->d`$Jx)yeFNf{T=K@Q*e^<_WZrl{&4u)o5` z#Pe{fa;NbxTlINV!jNTU7;WguB3X1Op1>4Ysqjcg>q~e>(bqVu;|h5^#jGM4vaH&K zaH-tx57j+f`sas3nWFQ`(*uc66)W-46VFQeZcO_Fkl&xTC z`*_qbt9szb+I}6+{)UeCVKBV^?zeDRIHe)C(qW*6J_!Dd0xO3l7kb?b*DK*agQNL1 zggc$*`l0n|;e!2)Wy?Q&1?9gpWeCCyjdmV^NI^Der?1B05e0NHog}$GioxQ8#hzR#r164!b>qIoD_^7Piw9fwMV`Z^D@KNM*_>a2R!+A`q`7B%ys_glY*qujAc zvathd0K-+=rewcLlg;;}(ZV+M{*j6Qr@XI@s%mTB-4=2{6r=gp(%q$i zfPjQ_w{H4KN-CX#w6sWxNGV83i*$G2cWu9KjNjk)-oNf;oS|n7Tyw28*PQQs<9VN_ zcC+i*z{k-Qi${K6()04#rn%zfcoyiQb${0_Ooxr&f8FZ1egCJsrNf98{hZUqFanLl zoCmAH#i@R@65=GKLW^~x9s{EC2R8dwu7Wg^RhM~E+NNQ6>&g+MNgh%kogl`dbRY@O zxDtMhdBz{rt_CS==%}LwPNpPp2^E#^0QaQiwQ?Db0Xm4oX9Il6UG@ro=2>}p9WyE< znSYiX%MN^IcZ!_JV*|y-l}$V%+^%d(@5WZwN?y!Yzq{Fe<;`U_$mY=h`m-N7=%v!} zmL7_{nC7-ND(drmF@SNf<+CasLXIHjl-ls`rzC7>J3G?Vmh1*Mc0;Gj!1aHM$gj44 z9kH%iCaGLlrG-jwlKoY2Zgq7)*vm1f61d`emeHLSZNAuIGqEzA>3{vc)!{c)g&AAf zO#50R$5wIX^395$m6VCuDs$bfJimSMl0rw8F9(VNZVeoVauP)YshCx9w-QDNPlHpf zXX@^U%aw|DvIUNiRlb3e7Js0YZ-7gExq_g%N=d!Epx~Ry9f}h|7Tb$7r=}wUw`B{{;<-hIQhn<6p0WR8}M=Lqfxos9T_VwYcmlm0Gts(mqM;~tJ; z1wpRC1ks8T~F*q}3zG5zFKxiyH2o@)((yh+GlQ?eUDXJ@Ygx1Y- zeoM0ICOPxSrlKLO*q<+Fh;0-Lhlhk{Orpe;{e;p!P7$xuDP z5B7qOJgmWA1=JI+z}Q!jq|5(SZ>( z00s!e9}=yBzyW}oAnq(94yr0Z764T|5((F%^|r7s+&+iK4+rfB=M=lgQx;iozy0bA9$+srKH@zSVS`kop=Ht&bWIU1wj~8`LQ(>V;kjQ8r1sqp&n4L=hFB#=y~q zaJs`yp|ciPvKP#r2!Y-SU=t+G&Rek8;R)AF#OVj7Y_zww?_9*G_;`F|>Xi4Gz9%?t zd|_O~P+UA362>Fk?DzPP0APkG;4~dH5daE;oSXxIUN`Ne^t{8vvki(kHPhh&p`AE= zT6tNWgDz{uRU=N<_uu1X(QBRFdDkLz%x!GUhnxB$y1?sG&Ehzc6FF@uuWmtt=^JOo zHR+C4YE~6$vS99^(PR|Bh~S9S8rVQzCx8f^^Xm3zpR=HaM+V@?PSeUpJ0yuOvRiSb z8Zt=XYoNRT#0lvd^tRbOZ)J4w>cftD2SydNhXW6ej?!Lcp9I+-CS5;|7-wxpJ~U)_ zlql40uhe(0(DtC)yX`5=jg@~@v z3O5_OeL26*7n8gE)A$+G{zy2eg&)LVuvR`-xI5re(bM7wZv-KN5` zA^(F1!VrgLk$ziz+cZ`lfUv|e>bl}iSa{^zeRHvXa)#nV5h1oM~%S&XFC4ZYc@ z%?geo*9?zVQ?Aj$(su5f!*}1|X;AcQPUyM3Ug#tzih3VzJSb-GL5w|q9)UM*t0J<( z?&h@~4$*dpS%K*f`MLx_o?6GITf!f;0?Quf+D~GX+AsfI)n?j}Bb3O&DSiWw&IhmH z>+OSvz*E%=#^16M-FaNWKuET$HL_&EGNmSF)ni0lV4R~iouUZrGBtsGz#eVl<=CU= zli?h^G(BbM++3zVc=V}+;f^8q*I!D8T-90M(8ZQ5Fps`4+ zt~2UN%D*8xIps}zJ|HRGY8t{jmUJ3j=qXM+!Y#?Tn_`5$iU6*P9#;MB>D3#)Te>OM zpz(l+;`{yQQ}oM7nuk-%VS`q0Nyn)a!+`#YL!Nc%4SVnq_S0=Bo?ZNheH;_{lVsa9Gno-$?y7IEjP>G=|bu`-tlGUJ?-2Xh(r>U z;GRkomyf0o^^4d$w{e z83anjKZ+?n{#x=&v%Z^o`_)%QcV0P{_3sM)y2=;AGA_s_;lF$(;{%Rm;broG)xHUp=qzsrYV_fUx> z3OlcAkX9&H;VkefIr+qmUolG(8>48N(K;sbZhvnxafr1ql#>@Y1fAf z43@#jr6^eLY_AttbrYub5>!8~#rX+IjBV_1-8yXY*BNv2Qq6lDmg#ooKKUhe&sP%7 zCPj;IlrvZOVy_j4i^DRXmC!dhJX4q~(VM+egSSh)$@W0M?)-@VIo)4FmD-TA{5OD) zSm#4?)mr2S_eu;?>_^Bgv9>?Q<^ya=V6q;FBZQM@sKo zfLHwP74z37v)-S15+L>fQ{+%cPQ=xcaXIOUyudiJ?@$es{kI-}C=qoT^%?-f36Jsp zdUgkSfvq-}Yl9zs^_?n^Y(L;BYPu+Hc}AY?WYX=_HxO7|GPYdXewqg~zJ@_g$O8#E zMRP^UEEIcTgpE-NS$n)=y7JFYw~3$EC1h-MIBaz~Y;`>f;!-_p85P;Td+6j{7!l=G zPcpK>fCS|zH6JltwJ1o}Jgw@2|7NPXwhv|1hv!s&QBCzFeHMJ`dgz~$`7GbILzV}D%~Srs`luzmC=)A9zJcXLua^v6nyy6|J@5z{IzF{I_7nsoFRNJN| zBZ{gkG@iQ$NqVe>;UmDKvt@xIQ-^(Wh!=ke>%jizdH#9ze zvr-w(pr4z4c*#n;lD+1$I2W7N6yhtImtru?42~0_Z>oi`*)dy5rU0J+wdL${^c^qo z<7Ua&#*`;m^IbIG@a0$OrvHXKRek4m@-o|7BgT3Bj21W8mK@pZ@4A?jgS}OlKef?q zdh+*;pl&A4tazi=tHIK>(7rePCcN6%mpY z!y*0txkc7yZS_#6L1uxUtFUvql>xa{7p^V&koUZk1Coj-c8a~Q%_^E!qTXBSay;<9 z^1<8wV$J7?OXh{Nt80H01~{%(3zLqo7q#Lb7hi;n6Kc^mJ7ZJo?!hIS!2`?ARmZ7# zaq;pp123hI?=0%|eD3A=q0Hg?qsfj;=BJ?6PDc%37e)h`3l*sVfP$L1u8ga^2oVt! z1GQ_4T$T+6zU$3en+>&V=*Y>$y_9~alRYmbp3z!z`%;$#)E z%wKtXk`=KmU-W2xGX;124nzRuph;cc2|xQ^XZ{T*e+9Ku(deuWGO5A?33V+eN-Y;*N=k&XjNObHW89JBdfa@=J!!8*Y2?!fB$ zr)yab0~084_fbJt(x-TQcM!q3q+SOgjba9YmtCc|D!CEYUX(taa7xdX;XFEV;kGUN zHA<&dGNP8Nv)2R#vJ{;E&If=`y1wuy{gX!A!dN$*=y18Krm9e5IH+1n`o|ZOn(Lcp zQ-u4QgBbERRowzRrpA|$0*F!!@&Kbo3(+Ybo!;hq{2An?bK{jRwud(irDQ$WkvTot z$J&xpNxghKtS!kgA`wgKYgt~nCmq!J_0jz3-Ey<(=vx92Wa8}d;M=4F;^CO3xD6jd zIjTf(-QH2IU8QB*Uc&H7N}=*z{n2sFzBfyJj85G&hML(OUP74H?Fm(HRGL0yyT4X6 zypNb39*Y?~KK*+vK8KW2T7r8McSDqg| z#Qr)|9DYsuIkN_j{1Ti`uv7;eA;+O$WsRInD1W3DS8qFX@_GNE`sxEBWur()4?|(* z?~_5ugF+|4!tA1@beavu7==4tilNOqxwKU;dOdmX z{nwkb03mK4OlIKMq!6hK_ya*0ra#g6!X-TQgV=4xgH%CHzW0gtR%+sG#39}}RNvi8 z^9iu)s0jjBaWtFWQPcLx@#a>3hJkm4rDI4j6gN>8NQn6*y-MTPpOND#uh)ae`+Jvn zsi=^pVTu%%ITHW_@Kj)IfMaT8Jh5k=2&t2x`m~TzV5Y-js5Nx zcaRY$$M%xke~5ctADKG%ulKFggiH~pkAhrUdLEihmbUQsMc{OoFB zgkJtiZ(GGyBlEeekai=hTS!d>snGr0oatmW5LWn4Nr3vUD%Z&0jfxNN*JpilE+n|2 zL9*{(Oml{l)1~D6=3Ch8^E)R9;c{BeUJ!xfw~A~BP<^>ESf2(P)}zWnV_x(*sl$m{ z+1gdMIWi)M+uJ?_{?~2Ekw=oInM&;(;E?o-zQ(*++P>aImOz~F*FwcY%$4K$IYn^x zC^he%p*Wb{wh#NUzX93+M{JHKa&^4zknd;Lb4@9N*j3R)*34J^_i7E8;v9LkaiUqj z)XDGHk@!En(Xgd&`6<@h84gBXyvL6o%xhq9WiaNAk;+9c>*uzqjgXK+S#ZNt4?nagll@aSW{3TZh7)RyKE796vDvRxJ#yAfYQVgV$FJpB1V*FB$`+C>mdcST(d5 z2@TL!k^4=J2;{r$cc$ecu(%N}^DLtZDkOb!15S@KeK$`0LqZy;Zd*JOXU$E%{_qbA zR}l8wV30M;Bk|$!(_SRU%7~85h;@9)#`&KrImQI}wb%#qbo*XQ~Qjb$_TL6i_X0KKBB=vm5Zpqg$xt|^*6?nhYyxo5>Og~N9KDYwD z=kKi%Ae*F$=c{D=moG;_WVX1OAEz5^+24b#3?`p5l#1=fx^m|>+Ezpici{1t-Vr%J-c($;a&+luvf!Eiigg>}c0aezNc zm9lN+u3z>+*tmrMYPBE*6iJo8wVFci4^X3`{Yw5R&uyZuU1ab-hIhR&n$j6d8a(EQ zupzY_{sj_$iq34(YN@1uuiYOj>04lCiuc*pt7?*<8c_#+{s3DP( zWn|wAas}#!jlC2tBqK-FU?T4gEm9=FT%eGkXRYS^Wp=x#<5VoeYQo0PIXQE8GoWOR zlLdSHQ#^bwKB?5mjq7ZRz727RBs zJSB^p+nhaar2c3M9hn?-61e;xQ zddm~=q?q59@KD76au4QDjkn8%VU(UR1*jv8^w33fU>5~?yA&XxNayOqO(Iy5b?b2K z)8xzyH<$9vMR1N6O6T8~I98(Ah1>(iPnIk!U49lh+Lcvt-` zS4$S7ll%R`em2;*=s=wglqNtnL?gf4V`Gp@$==-Joz+NU=HlBPzs!SB zqmtHginlQ5GIEjFw^SlU9uF$SAlz=xcU|)08HJ`wXQ%c&kyoQtGu*HhqDmPOi4&>b zfT2LCvn=3E0_b4u-2;DUGJWed1b-sU!9dsyWU)XC$@G=qx}X7Sq|l8-E$qPuC2gZ( z;L9q1aPIP|Wam|fLXP%&4%@lI4GP&8H5mn(R$-FYuw(b%sK%RwIwn-%7i8J1ev<^+ z0!s;KCK-Ns?3+a`WWxrOgMs7*A9sc=yC?6hKwl*^F9QLpL6N5TH&diEJxgxr!NtJv z=hw|(03k%iZ_kRgm3AABlOJzZ*6c|?ewGD7d;wluna|=}G&4itOlQ#OTkfGnN=gEly#6*52Oo>6-NVz9-3ITy z$yeD1PRr#3(8r!2mjw@#51d0#-G%l%i~hVAjNn$!Lr}Eh%QvJ1HX+~u1JuB%Z4&`t z1wf-Jfy-DDI$?nfUaZ_y4QdTQ9~UmsR*n{ zfoP*u?ib?-AqF%|5cJGhLBrs_TS&``cKSFFTuw?#`dVKE8%l2^ge;=W>Z8K?QjZy{ z^m}T5Gl7?EWf=~fyi_m)d4>VrCR;#60qv1{6zqsFy+j7^S|a^v#hdSS$|-?461vl8 zzr{~)y8*;}Bkrqikr|WJY?J)?bSjC|sH zZfZ&LD&nPWlU`3&mecX?_<>XVq-22mE(N^rC9+9c3Q(D?pTCyPw~<;_<^WYB^miy( z5!>Y`+Rt-SvM*&64Wk&LB}mFIS81m<)Hcow1q%| zAtNW}P&10Y^W<}Y`)b{8pNI>?#i3PThyNCJgED5BcR3;FclZAD)-k2$>jNbRn%4zg zdVcep>)n|Mh5uC&m&?LEZKAiR0Zs%Zri{G2md}IDm4jipwn{ee?`a+2p70rIliAcm}nR`Xq?8pGdG*L9mmQL z74(YGg73Ka>p4=Mq;?a$Krv7h`c3`cvb#vctENdj^7H->myl#qeg+=b6ej}O^v`yF z7xMLnc5(1EV!NCBmSZ3*!?S!et&!lRUU$Z~G+jj8^mF7iBEf2HZ#iMLD9I}0M##v@ z{Ei9%e_8$&+11FqYL&e2kWvu zzWy{Zd9lh2tuw8ea7v3lhf@AmD_&=yYKG=bV9*g<{|V|I^Zr1(qG`ka?ktoH!O9R^ z2VPiW)ogc_pSLWJPp~Jv==+CsN1gO>dL__23@ezNjO-`u=D|ea!zFH_c2Gn7o*D9B z9@Q&GbJ|E>|4Xr!|3^myyE)P%bE2o$K_&4-1o3&2s0|*Rm_q08LAE4<2s54qQdJ%x zk|wI!>=GadewjnYIy^Uaq%wKbxPNL#!dBmxxEVBtLt4rPj>2}~AkDynDPs9hU1wGa zPqIKt=8E9jCm;Vb@K<#FK z*Bd^Vke%=Q_AkE+qyakL{}wUhME+uXA}2eQ4a=i7yXg_aAg6-Vx4+H;a)%2TB|d)S zJ6B4#@oaM9b$|Ww=F#Eo#fSp3<>s4QG1sKbbekqCveFd=^&w#ZS;<~?T$}3oEWr98 zpfE<=$9LjSfcVi65CDMkY5Z^Xx%FwBzEc~uv+Y^BJj{Z?b-t}Sn^mjR`Xcp)&E^XX zy402jH^AwGI#c{~qMElDj4jS0@#Ahf_rwxYFdBVCu33|tD%vP>TF(#hpI_kOS7*$A zm{GW$LpjfNBY9dQOHNTau9%%fbw_AsXNbxL6C1N_b5@-Wr1!)DhX(+`q_1!w0!0rn z>afMm9o#%zZCj*x_i~~gKSvm1veQNh7#d#JvN4jF9HKu+$qy!mmhsR$E8))*p@U~i z!-GnRj!q7%t&7CO1RC7t)T#HR1)SOij_xA~p(Q-muc~I(U{sbV;EX2Bgwjk5Zrq=} zovxkLMB*=od4b1_?3|3em6=zH;i)a}>IF&Xodm$Z;3enW&1>MawQXna3RYsZ`|0Lc zF#m8#UQ%0SSQ9%R6A;Br?Dl?sFpG2QD*>PQ=v6&AkIU3mdn0@I>DLtu=>^+|w@r1o z%^;XUv4C6G)iRVsYFEskax4gsqeKjaG;Sv+GYLH=hLc^yucizmFZlE<>7)QNc<}Rp z9Q(2qPfM~i{@(BxR5S2wHIU)b&IA(f5tvE9|K7+`!X;V`=f7=aJy^Qhe4!zk^tD|s zeU<(;v?0O~2`LKYdGD^^J%zrWAX&cKuq9DM5n>poG`G!j`y$xMNKVHIR?z!|q=--$ z$eD?s=gD{}1C>?$!?MSaura4w?R_wqjiZ;h`r-7GpHlB1JTHxLnyg-2-SkOtH8Dnc zJ6muq0?*}4p=65upos4Z_-C@6XQ_AOX#+aSd}Lv$f29aw&FP9@yvD0+OF#Ue^#Yng zbUvsN#AxircdK%@-7Dsyw6^5?HEfG%Pf#Jq?&YGd zoyw+T;_3`-4jjWyR4sbw6LjRY`LS=u2Z;s7nX$Xd+cTCAj^+8`hB>}h|2gdIv03e+ zNM6?rZYPN<(3)ztg8USTY=Kd@dI57VzXsQce1%%eb*iY?r|(5Xi<>Eukr*O}nJIve zd9~}x!@{@uljO{%HAdkvhKY$r6}M;nPwV=~F+p zD`i|e6&blB3bw=Y80LnZvh={^OEr3OkxYN`>N((FpcKUEnx$JR8#K3RRE(~Y%KE{e zT+&%@&cmZ{Ne9y#aE*{!mh>X47nLM{N2kD2vF`}^LikY%cw55OuzH^u)Ce@C~> zq4=bN)2>k?(;>RtDuCUogqbArKSH}u?+$<-tq&BHfISF&FiEpB3iQB#NP>64|3OIL zmC|>AEWoT97>og^60tvBXHm0$&cNRSTSx|??*F5|nG>=ol93@$k5OZE$iDMo0!YXI z*56OL?xTEk9s@N12sT#!dJ)q5z$f@UAXdSn172ruaO$K&ufb7+pH6&+bPzB_K&b#s zqXQYzQ6cQrIpEJD9W%;z<+<;l0}ST%%b+y>9*C*HZMt_KU&&XB#`Sk*oB_z{0F@4K zG!?ZNx$e)zG0MGp?7%+Z4IC8f#cedDTCCv7{HnBhoAvB;uT2Ev6Pk4UGZ-fi6OvET zaORQT)(8b=HGqA=T(j%|ZnObB;dIHc`=HYdLbr$v#m$p)aT8-vCX zVb{2(AT9x-0AOER1%CB&R|Nl!iZXV%i|U0AiHQtwHTwXr2Xa`~07RJ!;^hG^ z2GYF>#irnaYZ|yd_3-eJkqPcJT^uf7q_U}1o_xz$4*)eb-HPi1=?&SV04x6*7G|zm zb)_%Sx_TZwhY~GT^i{k-;APocD(%k7%p?Hqy}T8$9Tb2Qq4RlE7kWxw68 z3Ecl;r?O5r2(^IN14DGvz-2Pfq8%4AvJAW|e{u&rHrg5C6;6OSMH|RO(Rq1DgylTy zH~`DXZMf1B!EejG;Y@wn5o;A3GM>IblVel2tpOS+z=~F3GoF&1oE#mk*4}$&f)zf* zBPA`Zy=;-=`98}rAP`|z&B8na%BgJm#0nU}dEB!SzDYus(9WPSEb{!=42%VQk62x6 zW;QmVmIQe7P!PJmb}1`6y8+ zUi5LI&L{qy?-wn=X9a=sejvr%^QZ>~#F;;TG)}0Y5i#vdPB{=cu7N5Mpq=ZF%57lo z18;i@8^UT9&j3eCAsbY|?%k_|*b@C6C^uD)(21SAKyWCd5RrqxtAV*p7(^t2?vMS{ z`zoHl z_PK37Knbdo%phR>Z-;<4g=A)*(ZL^zw)@(2Nj#RZ^^YOKZX3M|RH(;UZ$XvKqyZy_ z88?QgjPZoOb|f`$#kM zN}n@e^FhH|$l4A7iO>PTvTK0)G*pt*k{E=tcmpy=)q3onwIEc0z18h)#el4gj7!w_ zw>~B!eH0M+Em*=V>pgu!REKlv+B=&ZCN!`)C4h)ay9T@7N2Sw^esxWK$6xaL)ehjU zf9dD|ewMLfGuMXQF?Ylhw=Al2g4Brm11IsZJ;LPx4vQ4g9}=&Ji&5K#gTQ-5RDIO{}~UF0k?uu$x=! zu&kVe2Zj#L^;=g$3^LQK3-pvH0L!G=74_WgyhnA{oD!R&54@tw)%l6 zH7p3w(=vecM$KxyuJ~Pf_doGwf;8O{rHB; zIK4yEB@Q(H1C>WNl~$XLTyKh3;S=$$)3)3o^jk~Q4_#yDC|gtty+LyN?h${>v(A4u z#~rGU*;B@CM7+DI0!lZx1jYvz7nTIOTg}$01{0HKU1jzKP=W#vaHSE#SMgdfv5JD# zU`0R((PUOMyo4V3IYAwj#@(UO?*fq>gjkS$0%{n^W>82$R0szQy@lL*HBDhlfeCwa z^jf;Nl-)wyYP7l>NRZ0Qw-asZpIKWA1E3UWFF}0?Buj70J@voB|1t>Ei$(t&vV3 zpow9d{6Wq`Gt>|Ee-)B*tm%#3LW^mpfWHP3I{0C97xXck;tx>Tht*p`9w;`+%qX|_ z#paFG5R0&X+Y=%*Q^r{rNvoL#m(-9yzyO}}+ z6TyF;E@KKz%<)>&m77Ljfg#xiY5{t+F383tCo=R{ZvmqEO&UTp8p*zZ;ueVG0IlYL zf%|iCfdDvt3}+c=xM>z>y*_?O^}LV|oUXkdi>N1wZ=wqb{=`g*yXF(qr*`C0tvP6BZT*{HTb~ z9a+fJ>#+{nYB#6@8OOLNa;yO5KexJSV{V>PRMhQGc5MKl*KY3ai=fr~Ek0_Om6JUL z@5qoC@kN6+UMqv=C;kt_%m26kltY3{(}tiv#&3@?jz9J)kmRF^tW)&ycvY#hmyWNH4&UN-`vSi?@Z3qp@k1k5A5_aZ?u4w7Fbio1wm}nwfih8I`qc*$3{RlJrn}=Z${uBl#-Yqp-)gUP}I2> z!-DZ(gvWaXk5>$f6qED*J#u<%rd;^@Z09f23VT4aA4aRvS|5JKrr~jJ;==1A>FvP} zbm%OFQj$^Kph5X~2Y>^7n_% z^3V(R9T0v2WgrwKPLU;ni(RBu9RQ&aO@kTwf9B7V3zTov0a`}@9o|5$)r^BQx^5$8C^nE1-eO5omkcn1c9;Yvv&6=ATO1u)o+ z&;MKpKM};&%>^H~-bqU!VOP-qiM8pWFxVrQ6!N9AL+tv5y$j*OX!DM9S*ogtH>}Uu zw=W0#IXV2A@vGv*e`{w8u)BT{y*aJ1$heCl1xAQARNft=C1c3 ziw5?lh3`K*uMt&K*&*Wy3(Q;d#-k`2F+ErvREopm4!wbm=ObxqnzQ<-A?h(5opbFZ zuk9)~c}*IxQ0&f4<@+_F{}<@y|L?(iV+@Ag-itcQlTw?j=uU0b&QbyvWdikxCuM^9 zdlJW5L7Md6np_A=2Q7g?$7{;>AX5@vP@LW&ayqykl;4w*z15RSuQyqBaNN?o^48g@)-keJa0l-dPJNQo-h_&UlpW zgT&(NRPQhO{V4s(ebV^>c3&KuQPcbIu~D!8=M4%wnY;Klf6O!-+#AjN z5!d55Wf1?ya?1GsWAmq@EnVt;qEdg`3mVwfOUR4p13rhvqEU9==bezh%=>v;#JwuW zui0r9v{OzOVDW8S!-KwDF2Lg1_#~_OwV!hS9JO~Ga5&rOSC2dh!fMdKINg%j!H(1{sy~J74Pfrd*aY*xP^o^UaejAuErwreLh#LCj_hyWE(IJCczTf z|1O~SV=+wgLoVa)D&juDdhBF*@1TsnGFU(n| zo+Wxscm?DAU9E26o9Nv!v&HeO4}X$-wapw`YIO2Pm0_0Dm=_r8J=py-e4D^+Oy68b zQE0ciy6V^Gijcj5#p~{OF?PpIP%c-0(2t86qKk?Vh-rRaaS>7g(?MR_#^w(P0p>i{ zrQBkApJU2G=%e{$U*YDyCNKAf7UMnlgulo9Jf)%Ea5T%nIVdXTNN03=DDI*pSE z7DkP+zT0?)B!^By=>8c~)SfS;O!I+xCg*)v7!UNX4Vj1Emvql2+kWly!+Y5s=bDFt zw5)R4DGi+OVMbIQ?0dpx@%$QpGMw z6)B>1*lk{0q3Zt-QjsIZoXC%CMcO*qhKU?p5ci4ZwHyqWHgQv+GqOfPXLJu9Rk+xb zQAt))MU5zJyx~?+EnPi211)fZIfLJt^;?ef**6>S!7DQ~wr6{_$yDzuKmt%e0;omn z{SKWnC%f7+N3rGU{Ia*V&4fQp1p8OUfp%EHlwkhl#IzrK2fL#)`=RRDYGBvQryAkw zZ;ALPfqwlNc2^q()sIfn8W%rIah3{FOg{Z>tQvC%#&93AzJhsh`BjSvdOYf*d06}|{3A#@WGq}g3Y6pi3bXueq0QGDS3A+;kb&RgCLXuj8SKo;2G9FJ2I_tl zQ_Hkc#zV$0sEz#Sh2`R=8WCtq0}LE?03B~bw~R*F)(rZ!I7TX*F^|CF!;b6&n=2z0jS-y8iBT{=ScqD7S>)dro8G;{xI+m&X*5{odl;TF1dh{j9PwBtY!e^eZ!cRvZK(J?AlT9>bl6^@G)iAYTKC&X;%dX*@m*2 zuDMjD!Q!Y$J`T*WnHM#pFIjv!xw^Vp94ixg!EMY71iYxP$}QJE>)!9|^k0)e+Z#r#CNV)8 zY=boD&d{7rX5T%vKa+K1aZxDxmy6>WEwJvaYwml^qI57=#w)*?(;oG;x<4*|#@C0_ zhSF(fuTyYB3;03a<<3A;j0qn?hm>qw7S-P`2Yzf&{59_?NQsFbC0n1KE)9Gm3n}XC zq;p~?9j;Ctm4wL;LI)sBRB)trS-O=w9v4oBh<-9>VZ?Em)eJfBHwnlBzG;iR>ayL+ zf8EAF2(OlLc9XB><86WL`_dgc0*2CWXKdz?Weft{jEHM^W9f}^r{%ej29Iw;{*h5b zY%aj+&^&rQNDhhch@JYf>Y|=v1pKGL4RR1+S`L$qB)&!S{bL(=CK2)Wg|;@|0In(s z59fC<8Wgv!Ul#9c4ucPn3*Px z&C4>04jU)5*TipT$zZ|It!cdO32ZoX7e`YT;}uqxmX?x|k^m~zo$pEmVSt=2RV<6e zGEHXNe*Re(I}NENFJbg_gg|DFv!@YMr*~&Nj&`YG!sEPLH;PTu*HVE5Var z#sx3J)z>C2W@ieZM<(+$_)z5xpwC}IF5C|3p-ja5m%pBmzODV5nk7SuIb;a@U@X&~V zc`=sga}yi;Xk(0vk=P`(RX;XbkA>}V&+c$}8=lOM~4Aj)rLPA2EoQGay=0<(rrJmMlOG^G;%dbbz1#rc? z%$1pqAs_R{%5~m?O;=oyVhz{UTetLTL22nS`UA7pu$C=7tl*|e9P8+@t=Rcm=y7h7(hK9N)xi_WdXv$4@m2Zad zuGT-Yq+%*Ro~8^HZb)td>*SAAe*{I}P4_Z;d$UB|fy&viUd1^`8EVU~aq@@x^nQM3 zqbfG)P5yKPo08A2<3q9S=J-i7nFae)TMU52x#g2i)Kj&IiPNbOI;+F^x^cX=X|i!n z)b>~~_bD~k7khqE?H!!UMPnepWZo%-RQ2Y>Y{(0jOvhoyQ|R(|4yT2Xh$!G8N88e# zn7BBTZe5K*dpKft$HBa6CC&3LNmmS)#d1%Q>)D~ei8QChWbC(Zwx`;I`MUKlJqWrD zb=@uwT#qIq!ot|!{qpf8pc9vni0BQ%0zO)1W3N$Y7d4!fBxL)jh}EZEhl*L`03MD@(xaVglzg=znqZSaNfjZtuyonr8_e> z@cFmFp~a(B<@k4gRang-e=Y3=PzpGWmKdvQ+YUzPqDe_eRBs6p!C)#=|8_nVHOyt) z2l$F&{rs?tNt+A_#kcUeCC?Xpd}l3GZu~7Cozl(aM!mDAYxzPahdn(#FFkGrPzj-% z{D?9$GY7L1ju#f>gf5h4E4P}co}KoH;=AtmN%0oA=9-=5`ckDM*vQY%w(9*QyW<7qrVP-E8F_2zu{Iye$0%r7 z?#|S?o;{I^cRAZA@4s~oMjyU(I3eH`I&w>M5a(>}Q@fD|2%8D@qRTeCWSpjIHI80E zw*{={B|m&f^C>azU)-;a(6aVTGxpM3AFtdSuRr6Oa!FZpvbNrhWYL!$;Xt1|op;;CL3)zDXCs|nPJ;Ob$2!?S=l!f*B0KnzPkKwaMp2B z*=|B&K+f|uiM_{@$9mqUduh+9R?F_XFww$N`j`0X@o_EGKe&u1IYfJhv9YnJ`fgx3 z58YDU~auIZ|wFw97|KwIV51u!3ySi&0x;TfA@R5i_3xNolGFf^Zb$mPL5T z@t9uYC%&4a_&MhnK~gobc^{vif#E(pqFu!*3I^MziNQ0hzm!hqxk|TxCIoapjZOc# z#q;y$NKqXf9bfFoE!@kA+o=Gh;M7!EwZ!65CNLpXIrBKHG;a+0!e9u(pYLqfhB&a9RLeeMy?KIDkT+y#qScJrL>&srIFXk%bwmCi)&0zzXoHt?zvr2WxE!=b-D4U zaBjc0+J1{uD5MZLB2gR;NS5Y?A19^#gLKPR7IYXjEC*l0GC(0gXR|e_eObeQ@zl?P zJqQ@%k|fs`z9lpI?PKJ3{RtoMe53EYaM<+CJ2SU|`w|5oA0L~ImBkgAobIn6taqA7 zK)}#_$qIvI<$!wQ%(a^ZZuO_cSag(cqvjCi{^~RK0)aWO_SL~`|KGrr?%ciWZ;`-i z&{ky7j-20Vp;9Hr1JW%Ei~s1KGUHlG&o>_}H2*xx4|7+t?2IK45fPbmT#BO>^*TQs zvjDH&051e3zS}u?*6myY3FKfi>UlIsdJP~3aksLk>A#;L7(ad%94yXU61>)0-33bgv`jUCzEzi-K=&1au>Bz@}qmbX~W-HzdSA6$Az52V|!g@R}f6Yxrp1&UiRn2=q!VT>Yb0@3$^_c&Fj zQ>En^EbL1t7pS>O&z{WuHjKgZ_epC#^BDEKrM5=W0{|HYG^n>R?2qrAJV8+o@*GBg z7#v)@28+E0!G*9?iMm&k0IUR$&U~6XD^aAthFLzrV7U+Bo3dvP2QN|aHcDflnufH? zmI7g@qTnqMCoDqse0;{o3(c>}N|k|=#A52Buz>WsvGB-vIs`z*R~us*w&bve5e#-B z^%45YVmu; zmXAQu8sy5JoykPIEa)*JNO-NUGTy~4SFuK2S1S`)==WbC5m6W%mbx?;z_)0+4Ny{L zkyUB$#KR2Pn=o#C%+8$tmoK#57&VSw6^6O*VE}4s2^+^&Y7<}Q31sj?I4UtfA9WaD z$ZpeEftvJ!fEn)quG_JncoxAmSQi;ajm`55XKqud*GO{CjYevUSUVkMnDAhuJ~$d~ z3vAXq@uzk%JVLIv{h%5d0NM}3gC2`5KO-^idb;Z;>HjcE?!YvQ7Y~*g2EA?iyh9DO z9P^n5@vgrF|5iD^&9?P*SQZ22k87|7M_@5Q7f*h~QdQOTrUoQK$EgK)6!0$mBXk`P z$1o!TH^oDDbx;e^J{AT!qYh+#2A`0HiXr>wFJ5kl+#rXykp8 ze!lS=Z8J((gD2*!QMip9esrJLDJ-4&6JW}FBcA$;tkm)o`fuc19fZi1^pYvj|fElX;$l}6ip*{WlY%Ej+TrH(L|K_G;~Uri4ND4@8UT&jGu zMk+>^&2cdc3P20e{{ZF3FnI@IFwEO**WE5UjrSfbksR`*hD^J(#o7{wbe{V0Y_ay} zq>p<*9T*!v_cVWC-#Ml>z2htCT{VNR+baoe8bb=W*GJa4Tv<5xiT%>+7bNfdVZ1bW z9d^t}ISZD&{a^DKEH-Ybf@7A%*mvx9!@rC?VmfeR1)BYp?3k=T5E*nK6Sf@x!r@&f zD+!0kq`AJRa82|Wz73mRa!AAmX#ipDxLG*$IC4)kf~%@Tp#<`ZJHk+PfWy=*Hn6Kp6q4Ucpd#>nh1T?RE?9c*($h_z58oPP|)AJqPT0J#p=x( zVZY%Cm{UoU_`XBd9C zw^sS7`{UX%X> z48z@aq1qK3*Do-OvOs#_`%8Pib zh^G;GwucqjsfY54J7$o`_!CHC-MQFvStWgjiZHV4Bt`cf-RU*W6XG)EH2fu{OZ5EE zeU@=dDiXO&L9W87{r}_H$Fur)Q+E$r2 zDnQr*m_8`JH6+jCzpp7a&F8r)w^#$Q)KHM}i7r~Px%&ox=FVaoe3W;0HD4<@U@+~v zdmrTgZ^guPTnEMj1SjqVyOm|I@aM&Yjd`3c7kx>Xe1QtdKIdS`l z4fmOlG(o4M)>e3-!po0)%4n~AdcMoc^Ej%=m?r;Q#i5~tw{E!Kh1jqLjhZSJ5cq@S zNP+=NCSgBk(^9;>KxcT)-w;~WH*Ow>sGwPVlQ}Ze9>1fsT$AXwxW6;^dMrC1@ z&ioL^?Cdi{{e@!|{(n0#h89GAizjf^x6QjbvhN&Fy+mCggWX8+z4F$-@r1x1< zX~*yEHG~r5PTudmxIv72eOndM`tzB|ZZ1P2C**grfF6KsvUp`_4bC_)Y14SHk8xggU-c5_DUQGiTirlV~Z-zIjnnB&H2zvtG$2$WFp1oB_> zT5o>Y69XbY$&KxXVF;I`-|xMv#D*qampy3$c2OR*TIeq30ekKP?ab}e(SB4SJ1E~j z=6}G-H*Y#u?dHBqI$~VTDxTRsW1zaXGMG)t*Nxc^*T?`4iuJo_+@+aGrmV6$;p470 z4Rra;vwM2Ik6=)=*_M!VD;Ho9kV9s9R!puAi`&MwC4Cn2NVqjnDQ-p&llO;SUGFRO zb*HPScJX|wF4x2hE2C41blEeLv>wMQ{oE8NbyV!&JOoGzMc{_~3fEJ>{kj6~_sUd3 zA8MQU4(xr;Z$CbHqPvMkv1Rmr^^s0D4!j3ZR;*CQoL1G*DPp6hl|X{7gVL=sB?^h! z5MtcR1fMkEb$@xw^Om&6kt_9Rqpmrp@-G2*6k{X`l}K>KC3H@Vh2u;Hy#NL1i7|og z)n@R10YHydaeR3=k^5;C$*|&S48*-`PyRu9cU_Mp6Bx`lT*#S)cAA-eP4GVWNxC<3 znptAUe3&Rk2(%0tKHumDN6-BXI;zXJsv492{`S#((zVg$Iiy*fK_Xbrf~^{MB;eSm zwIEey>_Xsav-y9()BK(6_y>^naLYj_l2!Ax{phNUP8+}{v(afh*=iYE1lIn~k}ta6 z75K~?ToejsDb6mK2iTx@s%To<&9F^b0O;?;xuMJ~Vn#{J56M;A8d2Rnj+5i2KTpKQ zVORl$4J?cVqnjtDs1KhckQxL3xSp=2WzEsc7c7P5EZCDxy1?PRB4d}jYU3urO59Np z6imDmQ+e1keEaEt5t!Qg``&t{hXb)Q!KxkL6)B@&aSXuD$m-i24|0ur+l8+)x!fn- z3!>hO+82y_!!iDNSMSYv5z!I{$9>=>kY{0fIm#+Wu7&?aYMTJ5#ok%qDWldmz5)^9 z(6{CtF{C{g2>xV*K%}6BXpxUmbPZR5wvoGMeE;3UjxG)Kur4vKos$Z?e;m_Yn86Pb zIZEJT0T?uA#<~QkM;*X?jPesL?TdLtbpP{ZBbyVDwb~e^$G6l?I?-p#LriVmWcs&N zZXzV}tL}3H$Xye0FmHZ`o{T$$$X5Q9v@(U4vZam;%}@Pr-B_KvXM6Iz)1b+p>AEl} z#H`AHoBwa-^x*qX<|Imb+nui7zV#ls)ZYe-N-H=vx!2tU!5^vft`1C6cx6x6TzJ;v zd5nACs?9I3UDrR$#03nb2QXLRZ*aFqa~nd3(R;uC$GIl=llMDxEtp!h}(O#fSJ2Z2?y1Rx>`S7P*=DR8h+254&nxVKCU*Y2za`m{9} zBX4#8_M$K5(0*b}9paF8oAZ4a&sPr^nd|8_%;K%BTzaP+;G%)d4`V4GjOp4w2h1Ym zN#6!Oeff86(ewqt>XVEnfwftMt4ISmX5R3VwN5(5ho%n)=cFMaJfTD?PwMD$+F3l5 zwp1zhn3KWil#$}xVj+=EUkOCox>$k555l!;H2KHB7X2VX_c;`EgbnsV3GwXEz{jWG zJcf-wPs2yrHktKJfxY=qkpl2HSSjYZ z;D4);hB*QLU`!RFL=hOl+w)3lsuwNTmtJnHjk~GSlsdM>&UAKboVbtNqJVd%I6b#S zmM8;a95c`$Oslv&=-r_fqrFTN{Dg&C3Awc1D5p=+T-d1u_Jc3TIklHujHDB9*|iT$h@-oWqmLx z24$2j5!Z`8X1gx@O%wzy;aX>*shSPRJgD=#C*JH?v7SZntv0q)Zp9OD6qJfWB^M~D z+CoC=rsr}zsRIy#A_2S1M1}3OS^Vy_lxAE#DvQV4-cb|fmDPCz_5z9l^2Ykshx)n} z97`+{WM6!;(>diTU%05ZOZX@GOA1f8S>rnWr$0s?syX#C*#@l3I~e2+o&2=yL%0V_mQ<_W5M2gG z-RX1VGWib0_I^H$k9f~#cOX$-O(%2SXwE zC(m>9SjGY`s6e}q3Afz!PtxiOjJ$b-22+edb9P|ysnE!?Ee;n?#O#;K#}zB|kost$ z%3S_s;5;F2TxnM}pehaKJ~AJE%;QyXeENs2n*Kxr4)3Jwy%6YisJ#aJMu^`7#JD-} zLcBvKAy%6n!690fpL~7*k@>5@uC$9&-magTU82%<$+*_Jp8iMs3jyW6Uu+; zjl4s*@s;B;YToC&jz%OrN0cRw>TM*b{+BLln~XIP=c%{UE;fl)QH@DIcjy~l z+=_hH1=pS$(!vzBU0)y{IN=RbaoFo9g^CeMnRoGX@4k zGL?npR*UkB!lOtZZqw2A8LL52ZE&C@wbPQDr%N3?B^PXm1QJ z4ExfsQ+dsKvJr?RDu=5QHuh;g+&^QyN+`1dFEbsB5ryQ8?T-0{O)bQI^<*vTtDf%h zeb@}s1?iY&Y1=%M!`U6fLP6C{;yRJz!8JgUgm1xv|70WvS!^brY_z>(v9TZWV?lWN z+|*`&o@gfrk+)0G)Rpjv^ZwfBQtu+oS*@W`!?RcSWTr&_f|Fw?Qv_nRz|Q*w1tYDqvu4u*n|54THQnBZ_r z;lbaOU#gQPV+c^%ESjZa{cBp>6(jE>d34bsK7aoG=xOJo0B9>=W6TzBXewH7UZPf}dt`05 zmdT-bx%a`eYfP{;wvq2@7|Jt%?%{=UHIuS=u>JNIjuUebe)5PGkEF4idWyq?h$o%_ zlghjOksS$4O86<{X%+HEE_IG$!CLU!RwGLRU+&tSoET=$Z@EmxRf!y^Za_@lqtuO za}^gkfFEY@cfQu1D%8>gbUPy>GAft^9pJy1-KBP1@0Ov;XM%`x?Tu|NbJJ8_g-R6F zN$n%6a1e;m(#6oDG=H z3VF-}bDg>b^?zK{knA#o560`PO7DT_qdggZd$J?_|>L;$j=wp)-z?In^m7sw55bkpAp&Umym4!2^ez7mQe-n>fQp5{Uz zq8XFVoZq1!l9rzA@{0Txkjd$wWkSeQhynE3sV2sg^lS3sjMXKDY^^Za5bO51qqWEv<%zVJJmTE)%I3|^5_r6IcfC4^QlYg?A!Fg@n|R^Xt>eaB4Y2a(TOE{>t$O{+ z-dQkl;Ks?$$X_aZeu@5GSzUmh(}(olwRu8icV5A!f;5fhG*N5eo%sZ4fzRi0{o@i5 zzCIsNVm1kgcb<4Supy{=o_>xV{l;m&Vva)ZR4op(XXkOsHTC%Sp@swux~R>ry5V}h z*(QKE0_Ut!ke1kE*pw!cKaX%4Rf*3JS&$HZ|FurG&RN<}#kul~Ya%Pi0m zn4TMK*%d(CCnMV5>7-zn&LJm+w+6a3Y|s1o&}5lOwx3~qlo^UD=}z<6n9vCZSZwpFJ{kW&It+Zazv^L_)5^5(C)pqQHPd4>TUObsCQ1`U0C3~B^ke~6b4Dll?FX3O zu3jqsZ|LOvPw4byDS9)>TqS|j;$Xh}kyX(aXa&RKKSJz+VhlsNZ{ZmYV|rdhnQxD5 z?Ay8l6C~jZlL`%E$2}`rX(I~yD+&(X#Q%N94C(7>2`Dj2!47#bB_JO|?jj3xkB zDka%i4DI&5TSnY}FveAI8IW}Y^dcVuBYCS$7Fyhb28A@3?6X8_34nT2ZL;jjF))_| z-U%n4bW8^AIT#isv47k1?eYDcRcIDzW9_rta{nvawV0e%e zL;$t1*f+-SyTE;MtkG6uv@d1vGExu*=X}F|u=yNrg)9RIr~q0WGavoTX>RxzR*Vu7 z+5dj@>miBC-8XR=B1E)|4C7aoK0ZbO(!gVstRBJK5zz7rIpYaC9T36S`;2UApsWnk z+#TCQ?{jOqL8zMC%(DH~2bTUuo^|86Ud*4^6?7u2?Kb=Z12-pY&-8-?h>3~Qz!Z?$ zaG^^#m>#Tht@5$)4RAU*B?ghBWIQ1M*!sTMFXDR?#9Xoe#=cz;QRj?+^nCMGT}Ra+)7*A1eUYmvE|_$MDEHs8{h<@qAbwalKF+Gosq|MGZi z^G_11L7g6VjUgxEoVQU?QQZPZ<3y@jQ2#eb=+dD#S&RyOJd>wg4Tc1Acpt*l2A&CR zp6Z<`zzdB>bM)dKiffvzB>KG1|6A&?rJ*cC#~?eQ7pHzMLB?g?(cWHtwpkt5HRpc- z+L>VNfXjS5gYyAQt)JO<1sXi+lGB}-Phk8AXtSL=_YH|CE~P*rvPHaSxd8S$$o+dHC9eZ))><*)^*p|M&!RJfi!x$?LXxysi zY4JF0PlMr)grs|$W91edku3fs%$zulHMC%mr*v3{jMrxQ1YO-60CqR7hP-p<4j3J< zoo@JKKj}!v$!YheKri(Y%$%o!gttAihHpsXC)ruxKGMiHVwQR$qx&tq_E4&Jy1?g; z=&E<=RRq*+e)U7c)3Pn>siEK_7M4Qk2&R>l6~wG1_s^d{Sy@@}$hlvb{wbKBpD)yJ z3Ew<>^5lt*?Vt+cUGYeoT*BmcsnEU&kg06qFVHPPd`eI^n$6oThk!DJS3zv=dv5F0 zP90R!N&l_sG9Kp?IV5Ie82$WwyFXnHXjIf2Pex7-%r7XVy_S-blamG={~)gJZI@YJ zI!@C+@>N@tIqJo^n&nLDMeiHjuYnmUhmF$VSN1|Mcg17$S?|?zz>hE=d_>Ezt-0o< zB^l<{$l)aT+#J{-f~W?NEevMB^a~r?-ZxbpQeGP)Q`7aiAR+XkhuiUtw@UUK-{0B! zb-Ygd%iG(QF`Yw|s3nW~3r++=WcWZ;$8jNyd1a(HJ>_vX|6WI{ccoTdIHRVH>%kyu zsS6rg0MBZ;2r|GDwJ18CKj3k$HGhEUD>m*3707W26rVh_=QqwqB8#!bY~sE{4c7ZR zdrIO;ii+{Bha)I{ht2Uygkp+#fCQE6{`^=Brx~y1bc1n!8lzT4L1N+~dio59;p3e- zHda>I`fM=2VUQ3L)4s5BEwKiWBwwRU`gg|> zibAYLT|V4*nJ5PCDq0Uy>9RZ+z2tHJBL|N))ThFM7p%eY6*g_X)-Zy)YOi_=zgr{xChc~iF> zX@HMU#m3{(kAtVxG$?E9kdP2C!_g9$zID+ebg732d_d@EYqH#8YI=GaxUvP9lS70g zBwVc*cju`WFCLCn-g^NHt8U^`)P*{&y47`JM_zycrB?{6`TllG3l+G`sa}kYaWT{L zbBdp+h)9QXF;S0OxUy4Zl$4aDq#*LByZos%>Ph_Jyj9Efp(Ap!GsfG~b75g&rAiRk zzT3sxbE-pEFgTKM&;?GeOW?Nr>*0fe0p*y^H!e@u z<8uNL+NB+b?%}GKZ?jaZSvR7XFC5PIFAejJowTL>FE{7@oECcJ%Ohi1B0iT_ zNw5oD4Zu`lWz*A)nIb@cB++knWv1fm*Lx`X=g*(-!1kbNH@|i;iXj(;6;I7JjOoCm z74}iX>`HNx0sq#b{PA4r5XmDnRrL~NH(}=#@zjCYz{q*X!93S~t(P7-G}rX*-8%+$ zV%W3`7;9N{ZP^uj%I7$2Ai^Hckq6Pif$=}P+k{=Sl3XAGAd@}0hZ_d+rpbn3wn9&UVL zTEiSca9L?%3%I?&8;tOZFLfzd)`8#7K$*R5e2D=}d|vn22mOOZh>L}o5Xa)?lI=70yK>t3##^k-%~72p;d~1%iJr7H_5mTq#DTA zbzA>ahyZg|VQ?C8Xeu!KO|H|ypsMr1>cZX$u)xEH8~7Pr|G>BhYj9hs@_65Ng#!9e zp)r{XJC}sKRo(uaBsys$-s*2bEKduDvFaU879#K|`MFVx9qPp&I-@zVj}JlmWY(&9 z!Og9v#|dj#x!=FH84b|2MeX-Xp9&`sJi=;EStjDB5rNxj)Mk_r%_PsEmVIy1Zp;kK zT&fg*aC25?i0S0iZ~g*iC!y)c+qZ9HVPO>(7J`Yh+NF5sitE%cWlqWj!Sm3A5l=8f zai3tS zK+A-IXMY%3U2^iEN@WYbq^*_>so)Y?B*tfUibt0m8)vQ zRl};k$M`2>N@bAjh7Nz4^0OgDzXH(JJ&W#Xw&nc#0W<{P91qN-gz~EI9Fa}(!>!)<-!&H$ z2dL2C?cQQ1$OZx~#|4cu8QRr$ErArwRm+IMr0H_##SDuJwAG;4d;+@0F)SterS~FM zk!^&VS2fGiBL73|5ZA(Jrm4owkFG9{>RUtUwnmDV!nDmsOB~k=Tf_s&jf<_&RBaCc zT$lfLUbpn8UD_^s&wrTXN+R?@sUzWE+J_UOeR#9&6=JX(JpYuLX@ZeA`;AeR*-1vt zvT^j;Mkt-!B|vl_oNE6VX&VPHW+-3Rq6^Z)?3?(+;$H18P(Xg!*%QbN)S9>ta7s_HVK+!zaVG@;QP^%xUX)LPL9=>v)6Hje z(&5ifR+nyZzL=QU(tR-FnU(dJqL_?+vcAAGaByG!Y`ob>zm?~j97z#9R!F$Yu9v}lvY z7f)oOL7b!m!>%9QS-DR^K|w?WhI^Ik(HGz% z!NqnXKJDd#n*XOPuPe)ndx8lT00Lm+Qz}#3U0S zFl!;ElQ3%f@#IdwqF{j3rDTXu$hvKJcA&m3C|AHEM-Kd19?AkW@hq;pt#nPy?KiGp z@7lguYrW7Gs@n*nc1*ck9B=7yvjnB%cK~bC>!<72@~VLkwjPDY#<~Ez3;TnYrIKCt zuE{SHzizkfng3CqMrqbD;Sh+WG1!E}#CB^#8(XX5Ai0AKr%%cAaUkPWVJXuV26384Cd~uLad@wOobc#lf&#W*TA_ zC_Z1UaCR#sJv|+={jJ0JcOZU&UwifX^>eHImO00TZ>pCE`EC~z5fKk8K&b^P!Do~F z3%Gxp{7Hnsl;Z5Cxq9NNbVN(b3`IApE@8YtG5Z0dx1?BK0oML2n4m6oB!1@qmZEl6rbG z-c)F#P2AhJqXe7}lSIA24Vlx8@~P%uE2Se5U5Xg7uqc<7s6+m9rrr9t~O7}(_8o~r-gSMlfZon z2-Dcv*_oSf{)=@Nfk1SOrOU=e$HZvPQfNRkzw(Y7vhB{6KZsFv#nS8G7TVyV!t0|C z`89IC?gck^d0byTcti0|gXb%0>1XlXP6wW$a^GLe$T03if>C+d$QLty&+?Xs^QXY| zlBpC4{Jq2EjdcO z>Dk!_R&4x!htNu+&vzvD4!5_r!CX1GpE3j<0!a^qf2PfB0L)L85}0>dgajr>OHKTb zfNg`a-Pz2@$Ov3v0zM8R6!o56LbvKHUp6sBWh*P1C$NAkSJ0)|k}T3gXegE7X?V=G z7oC2nk5N~_b{7F4HRNx75sFaq``yZsi3GcBLir{<(g3P;-mFY_=%2CVKN?3h#Q<4| zgTc*$S$vM#^`ds!x{liZmG!amd>#@)!mvNVlz>nH;40QdT1#tuQiw=Z2F_!%+|x=$ zq@m-9hRkn zK;{vT+=~xSr9cNsx)0?fdoL`d|J+iqNr zT46E>*K|}@SL+jo!i1{B*xSX@TQUlM$?QZo;bH+q1>&Y~xV{woN5s&tJja}TUu~rv z$ATumT9X{3$H{~*okGi$Q|-%YshSOo)xlhm`t;Qqd&hVjkMO_Fhm+2-3JSsV6{8Mb zcoYmMaV6-#P#-|DfC+q(2M->AauI}UDk|o<%^|VZufNPY0Oo~NH8&>*g!tm(V&7$u ziz_QDPft&&aKKF=G5Ai%ZYy+A7NHOQ%>uZf zM<_4jv9H0wFOeXkfeUJVav->dbioXi$$~m^C}{ZjoIyEH!mLC1&&^V|yQTVvq^!Jl z>uR>{QBkC!_wFmm%E}IYF8JuMxVQ*JRI9M0PUwz^eg5=mC5R<}W%4lsaSl+0tKddg zy>E@WDBz=E*50b}b?az`z1E`Y+Fq`NlEWYiEUeyCtF1G66TXedOqVCOjHqMd;<{sb z8p)?BQFKB=x~i(>qro6q_KnSCY0uKf$xDH(!HPXPI@;FOmX+m3lCt`zFvTY6At^|+ zw#RrGH8n1P?g=r-Kn?)*CtkoA+@3o*J3Bi*9$0vS!@o z?NK@FOgTV*e5UZAAQpKYp=iF9{BHN@*bGeA!wQ80<^H=T`2g71g9~Vl_(IBj)*w!V z@G!Z$UI6H?LP1kI9}*lAqNu3&lbj7p|2ta)hzYN_L~;_Q&}T9sxPjz6ePd&qef%k# z6HgxW?K!isumG{b>ojz9;={szkpp)cV9_;*jEn?S1F&vf1qB6w>wwN5_Wus9)X>tZ zaXvC%2@K4=UFImjb0q_p&3BUkzV8~8Rr{KNds!V~)iM5p7dt>8D(~+X+O-_S0 z!dCtnkR?FTOV^spgIc@?j;t>|p-$K69vn_BAWBboM?gS;=ZZ#qub8;cfImtkts{3R zN1Z0BC)@M=^-v#ve*VWz)*_;!B+u0zjf6pLn4~IcoRAw@`yEX($jZ=FO_0tt%S?kW zKgh_)q|&{}o(LUzRZ#h!osn?^I4(%n4uJV7%~i(1!O_yv0zn2M9X}p@1D9c?cgrfQ zS2N!xNxnuVM1Dl~XGcGD%9T<7xpf}<2r)~aVa#j#j*lE>g0iwhfP+g*N_wTi_E?Z=xWgAF%3gDY-z=3a)Yf`SWMn zf#1!|O==<#wZ8aHZ5&xS_BAwl7Z!>Bligi*g&e6 zkdP1%s0G2!4V32{slc9fDlC(L1@Kccv$86N+{Xt6OFMIYjKdQ94`5o(s>?>u~t?(pDgc+<`JtP4^PxaqS}-D zVIShQBGF&^f)w<&oyrOUV5~-q6 z3gi!A4x-?D;@AqX)%#ml;9_M5ZLs8HV_{uJ6l!mI*=Pm!5nqm;5a5@jaI*Ws#l(peVq_Eko{{i>JcEGmP)zv{%KRG#RZEbaQbaW9E z;^P||9<~R_li}(H@MgTyfxj(>QM%Sxd2+Wc1;qZt?9**4fByp1| zUP&bFOtmNNQ_w8t7+BYtyTbxAy5@yXMM*}+XEDjYvblF3RB%&nSFXy+VYRicj9gZ> zwiESk^{=1(1ThKg=1nyXjaLa;mDZ{G`S~Elbx;76fV^_PKEl@erU9Rojg8OkvZlj< zkB?7RSNB6OgFYyRLY&e8?-IpstXOJ4XUPrVN|n<=7GOy_XtA(70cQ8|^kf;dTJ>pP zhzDK?Q0fbo%rw_*V9oYZuJ#LUM6{_xXF+%p=fM|4iu zKe_icT4-Cf{#BBX&k$besh*AMhg=1dN#;ik-CcF>X%|WE2g_bf4dgBrQNWdH1O&7n z-FrYr_KYFf`mE*0SyXh`w{L*xcmY}@&z||WFO-4TfiM7EA#bIg#lm8%5;b+@ss`#I zaM2q4lKE6!Tzq_9Ztg`ZU4o=sf9v$#2^x(~N=owd^aL3XT-XC3;eAzy^xfOHgZG^+ zt*!fddNMfI!M2*3n;Gcoxp{bS$+^Ea&VV=9I_!wBiZ7M|RrdDwf_faJQ2_1391RuK z)lbe(_6iCLKp|mkYYU*gp`l?bUSkk$kk8HQKiVUh9r<-MG&I!JqrlUdnZ_V+nW(#s zy<*oE`Tbn}aCcXu+Rm)BzP;*qXXgYE9>lfr@o^@tik<>EC&}@RJ6E^vi+mLoBl=gz zIlj5}8FjKCg>3>OdE)m5F%h+G7aijcJ%r-G%8=c;$v$P6oa8@ixLbw~Uk!f#I^mEw zVq8U=0*I0TfB&&+dyCrQmx#XM;VIzrE-vT4d2aDu<`(Ocu6A7v`9D${Bx&P7Z%6vFDu|;k8>xi+MlUeej^e{E?E{O8jH+B|_{yv8z4fzdZ3miTz>mgX_l@ zo(ybMs@vuSaI1>ZT6+j~!Ajn*(|ryO4yKch{c0X+4T3lU0Rf2d`ucOAS%hG_2{Q_A z!%8+z_mF<(i5#e{9m*@@G?jQv^(*Ni5^VV7xzD{KqcCQ*p~?y}n>({2_(OZ9Py3pwV^7 z$%tb8uRM-No7#xJ{(dr+cQ;WVn!k`D34!z7_x*DR+;e~URrqndH3NNlm>iP$*2AlV z&(BF_A{uvk;>}oPkBI4iRX6|L5h0e1jmNqd^Kgg33Fdu3yLhScAa|BGS*_VHl`3X z;V|!=_$Z70k{*>aVTjM$djlri|CX`+9cMjo{Qrlp_W;N8kKcy1XqTOpl95?vMMb(r zM##)a$q1!nWh)dZLiQe+QFgMTP+6H7A!LVykoBII-~V}@_j!-wy^r6~Q9thczOL{0 z^ZktTJU^eS%wcvd`oZhh$6A~#>+6+-ej$w^CBfSn8GXDE1~a{u^MuDF#)X5**JrdP z>rvlcAyWyqQC3W^o(2D@)T0TM-$qe|bWss;#Z<;Bbmk2~;Bx z@L!%NF!uBt%daInW!KHT>(@M=+4Y9WUyu8lKSy);0NJ%BpE53D!^w6< z2pnF)d=li9L7*^?O{=M>ys_+g7cOinMpD5xdshnkYW6-g^b6fB#M)PSrg-L4q?=tr z>}NZOH@-58>PvT^?uMVYnfeZ=QP0iIJ^%K+x%oI4>AL!Q;?nVRa{v7>W|fOC@BW#7 zVC;ODvXjZ|j_pJ>j>u4K^yoqYu^Vp^E}CvPD0MWxaU&N29zJ=1f4k~5`+V#WIR0hBu|1wV$LdP z5%}*A_#UD2z2fj2Gzx%HH;~0Zhq`3V&CUG|2pR%R%gV}9qK=G0E<*a)er#`qM1b7K z!I`&uS!rq9-PuyU!OztO-j0}EFLL)b5w|@lRuzBn#C0)x8(_N+Jc1|;n~EbZtwdd8 zyIdHNDf~Wi(miesPHNlc2MDDJY;>!x%q6j#o>RYConbr;q^!bY+vWBx~I6cmq6yXVi3Zqe zipbj5pgsTXo8ORfE+&^y>^^Y(+Iup)52y$qttvmlCL=KN{pnS5#xFP)_FK29zMQEE zyKy_^%qR)h_-EsnS9F#8e%^A}U&DNdxzkw6)WvQvKzZZm_qMYtZzg+R9;j6vYc(9K z!p@m+n2tO{pTE;j?x2RrX=xngoBOM(s;o9%dIH~|U#YB=*42%ijQhcg84l;ArICm6 z@bEl+`t((1W_?{9FzpL+5H-fFeKd@)6=3Ih{nWe5oF_JXD)oI;Zv_v+_j@9Iw`s}$ zJJY#`f-EBK`Sa%hmJwi;hgaM;Z2=Zog9#$JRKcgiPTc8*-}dqT(2w~&ObiTdLMKn2 zM8(%sH-m%>0*zxuBB;H9$7{Ll2(1NxkzY_S)mOg$y~x^PEMN^$9J3-oo22ICT>e)Q z9o+-|p`@hb=bLizkf&Jp)z!I?NQ?e((#QU<0f?hr=~zgA`9c5n9-lG_Y><@8t)6%J zi1mtMsR;?qnYt&et*tqWf6vY`2^oDtp3&hKAc|rFRRvyzDGKPPyS(xDS8iWNE+TL6 zrM9*<{nCXC7o?=#gNsD1d+p90uwAw3h5W~k#R}edl$$$?n@4Jf3Qbwrzlf2JuE6Ls zm4rkwVh{PhWTxFz5Fw_f9J*RD9;sS4v(vOTyI`{8ne15~FXO7iOyM__iZymJCck>L zg{;0ABXHJdW7oY&Y`nY~P#y(`gy73L+1X!&h9WI3#;uTS7Jv5x`F+E}z3lAlY|eTY z=s_37=-AlmLM#E+awvoV!F=GIkeJA&9D~}IZ#A&FxtTyY#ciK>1Meq(D=#k(B^&Zs z{K>18_4e)C{i=$JbpUJdT5q%O`1;f0^G$F+W@c&e@rOfw6=}(&vS_uoCr9tiqIu%| zDa~VQ-KEQG();HN8!pE^-7ksktG;=l%2$RB=Q;po5q!YU)1kGib1lk`cQZ7@6?=Po zW0cUPnA2C3l%7?oTuI8z)YsM?9T|cALQyGWeUAV5@!ufekrM(0d-?KZo1dzd7QyVb z%>q-7MnoK{4Mn|+dj22KCpiHCu0KK5u_qw9VdxQ1a)p1EC4#YMpG<2lD zpOTT0M^Zwvv#}T-Y&Z3NYU9I$S;o;tNkdmkO78K_G~EUx0x1c(TJFkE=j)TI5X$(?5Tb|f_wU`k z!@_AV7#StWvF8*NXliOUeEtl$L*CiBBqt{)GjkI4q{SCqoP+7_ML|ev0|MeRGkf5p zamphhu-eVb!y}KWKPdb2^4Jq#ao>yW8^3>d2J00l*x%p(;K2icoB)1-s6u2kj>E0g zCv9Z(6Wkp#O;pW*i(!W%qM{RXTLOg~{`>@>z{(o?QX#`2pyCz%{M;PSVTM- ztH|m>)+H5gChEsi9T-EFV0e414U8J#q)&r0fERPFe;{{pSsHC-H&He;On~)LSEs5b zqLuX{yDMU;VfKBHOLdh^1VKhmpL-ys!C5~zV7(;faGtU7PW?+eA=#P6vVA*-NxdRSj z2Id~Nocw%R9}-Y0qYJpm7ex_)fkK$x6ux|vo4Y<%vV45~7(6=wq(FvO85zYe6mi#- zn3xz+Yoe_G+qVl!R(&N7YPQ-^Qe@N@a8F3}y>E8r7&mXhN_&6$_%SKO^pvv?wSkt&XL{YClCy!_Koc;d40!oyK1dPR-GQyq`0V(x_ zg@uJld1wEJ#{kd%WJ{#)J$U-v>P5N`AZG*DXI|Jw*+k?}lifAU!nuCHkpR>aXffsdRF4yW9qR%o z3eXnL4YcbER|iea5a3I=WA9XW6}6O0EP{rf1qF7lu4_=$3^znCtMaM;fklmzp>@fFzxMtN~@?n}yd zfmk1r)m(2(!WR*k!O}1jFp%l;^)j<9D2UAYN)J*7YRZw)pL`c?VQCAd?eLSkgs`11 zSFAw#sQPuP)MN54*^ezeUJ2fH3CV6*PuRXC_fUxCre$P+lwW`ph{}gF(Vp3zedBRt zWOquet2pp-^Fo?0i$kFXI99LqiU!8VzeG7K{*HhASQgR)91?)Rhq$G4k-=tbe+TA_ z^C~yIW661qU{!&R6S)}#T_(wb7`8`@`x6s`qp`hr&+r`|qAwzm=ZF3%pu8YQ>po%E z068JCyM|*4spe&s`|FK05M?6EY;9}X$0CjZzkB#6=2)3D#<;Bhv&9-<+5MPKWC=(r zK1xY3y?ggJAOnbYIjnsyZYKiPLh(gjzKt&ndamFa7P!=nqWRkpC;T?JXD|=D_U_Fx zIIzbr-}AVbSV-dtJP>3Xq4~R+Bwbf9@+>GSO7H4bf!RJ*BwN|F*BK~Q0>cK8I)X>K z%9Hdt+RY{*_GPMRjpa$Q-{;bnjQyNq#8$2A_q0;C?_K@zCYV?2N!7p}CNXt&b!3+R zm3r1BqZ>Dbp+kh}`X3NX2=N;M86L!boFoF{0M_WoD9Qs#EmGV%yJ8gWCQ}wzzvhe! z!7pBDLYy|<%6&GLm72N*B<+|4CYI@5xw4IdLbz6q0VwAoHeFrai(+ylq+>v&Oq)|Y zJ-6blutAb;5~6~lNF#6$l`7U4DvRkKKlZb*ltL8iFHbC43FIBf!%)-?b3b)=cmMd2 z1dtk~WvlDsfdRwtc^|kTIANq*rUf^3Kx^dGLqSRvkdt!{!0E(+!?_BV91FRMwH3Al z9`hmm!{5rcIDsT~I$wv=2Xk)#WY7+XF!(#~^{sA(-6^qXwGKH<%xaI%)r)EwBPOUe z+(WLlrE8#wJ%zFrF&uRn;>iUPkqiU`0FKHH2!Mp$7mL9i?hrKE{IZt7?5zQZ2f#&b z+O#S3n1KnEG!AfbgM3@z_dp~6#u2SO#4zw?pf`fHQb<<;;j>3~hCeQITDau+6A-_b zbbMJ^nGt=$+ zr>x`*BySjnnaA#RU8mbkz5X)zOtvqLjjxv#7-=nb9M080jM%jPXxstm0zT&M;=4$Q6*#1RiKuR^&w*e~Y2 zDdRmjPjvhD{~oSq8djjC4ThhreVVpGvG(Mdsqw4MkG04SKSd&ndxK;ckbMXi!t(pu zh>!vy(QC{sEa7?b0G78=`j8S}0|=CFLk<|-cXVujv0rG&)I23F?kluF;X&~8NLgUE z%Rua3x>YJB>)c)uy-xlu@satF>->jp?%q{VQ{(03g^Z<-s750m2{I|7BxcvYgL!BX z9si02U44p3NuP$IB6}5-GpoHWs!$bpjFDc)S-xs=IYqFD(P87MWjf-XlSjwpWn>V> z@EQVr1XK>g3_pPd!$~K=mDxr~2vDRQ@3wt^RAJ-(sjiNXmp7=+o|c{-RPrkJ9?T%j z8Z#QDdPMb#rqxHwVeQc2{+L18t?SnXAqONTa{_;dxx&E?*7)~9<;UNz zQQY3x-MtJKiUh-OxB}|}2I;KT07*@)1;3^6NYKB%rDftWZ#YL9tC6|+mlyW~j2IM~ zny`rNb1kWb=)Mr9fQ;2tzdAHDl!BaGzWllEEwSW2(40^W;v^+2hC@174u^ppkE)5t zUxkEF$ThCKLHPkJrrI!yj4bntomEwu9rQ1RcEW#;(|;^-MrtbRJ|`e*ICC+QZZVOO5*F=z zE-o&~mlOev+%PnRn3B7NY_Ko#v_np8Y^=Y3BjCOG`CefRqacp$vkyGx85M#o(nYBw(m?p{VH6eb4kL-BZismD_K~=3&pBX9l7B$ z5?jFB(&*@@c@4z)lmR%>N)F?&I%*?FRLrYbaAgwSW z72yf=HMrsPq`=`{@X92_HI3=zZy!H=@TeWayB~Ra9-olWP**>ju4Bdm;}&#CE-zoF zXz4w#|pAV#DD2$1cWx)&~V`0XQm z@5kalc;|x22Jv<(-_$A7UpKF%YbBAobY?pdFz5^+(hZ2@C#8r)Y4j#sB7~!&E*Xjny?YzJZgr{@l>u7fx6E z<%?m%+<2R>H-U3VOQ-jmBhN<^13>s{xrGBT2Rs3Zgji7L*hF{()Uz3U{#l@1G`1P(*~d<@b{&%85|xDE713Wfwhu!-MSvpHq-XJgVc^pwrqxb#59; z)jmH*rVH9`h;k9y>IZ(8#iarVBA}=}pE^1gM`GP#P^O&a&rIy`1IaB@BFRdi+l)j7%mPDxci&X{J|M* zesG9~XB;OK$iKY2Jig2H0;()Rn*g93z7u(}KI9+K(b013NG&C7MpXcp0R{?zII=u8 zvbcB|DN9&pAo!5`q56~pms?kIyn07G&Ey#+k#o!*iwSFc_o z%(cX3>~fo3z%8ot)*c4TD@@Yy#{ue!iUvP7$zz3H#aV4}W%}Iq)+?1%#l@*Vlr9Xe8^*H9c`f z9l_vxe0gAFnfwhue@Ahf=GVzdC*`~eKy12L%)-v#0l?a?2fp|8)cCWyVW)@z)krC^ zw76`fs1x6da-Th`hoTY>Rd~I*2hcg(EHf&RO0Qjtw}~975lA_NjLje3>fvAZM9l=b zCbYd!JXlyv;AR?P&gjBLB8Y%)K79DFV(xu5fFQkZu5Y0f>>e>fnL{WoWc`>gDk}b* zxetm92-A2=N+Z6vt01_?{YQU)6Zm!9BY-IpVd0kd@85sR=X=dhqWZ!${aal8Ug97OMIlJ^#t|k) zMz{!A7a{x(u?di2o>@N|Z{`S41#l4P4p!zLD6b*^f_MAjqYgb|^9i2L>uX zeDJvm0s<#VMXSaU+_PBElP?iYYoaapo)ai~WBusM^rQ4usY47K>|k!Sj`SjOU^XE^ z!6j%)hcfE+l1cHZX$xpu9r<%&-RLue|H10VoShR8fF01tJ@m<+wDE=Q_`>jQ2{=BV zFjQOH=GgFL)NFj(()6-ge#_-kBA;EQ?K@qTR5B~cE^_@--r!#&jrR|9zHuOMuIh%A*$j9OYlqYa*79SaFq z7S?OSf28R#=Bl1Mt^6g@VM^my_X4%YJ9ByPwaf2f8H!a!B@C}$u{yf37Ygr9q~AhH zX5hNyRfQ;_-ihPC0Q52TdpgKt!V2Hs3oQXQn^PGz#_5V!#( zlFa?z4gSM*4Gm}S{ve}7ue1p?nK+}bUka8Y(V%_=_O!V~?sKGr7`u3J*wSTL4YL|; z#og^Kk`hgKHaNJQvN7r_03O4wKDqIA=~eFFujy@M2Y`~7Ne?{2A} zq4t>9pjjzZ=lXZ7gCJsl7@(SgAdH<2n@or&p8d4F&>w1Q;FUxxWMH1bGsSEnT=<&d z@dr!2`mjTiIU@aAt)Fg)B{qXWM+v=ORYqo;E><(|8pM-@cPdf(1WQv|n}peR9|>}@ zX;r&%;?3}Xq^K9Z>=(cnL>++ZV7YGJy4A6B3t8OIjz+$Je|}|LySi!i<-459fBo&e zdVFug7*_0gny1h|-&a8}on(95YX@>6s7eMPJ2iEXlCr|^02vwoBPsUYwWDR)>EEt3*Cd5Y2i2J09Wc*f>L`ci zP?`kMqmjgZHa5ZXlgl~zseB&Zd5)Itzq0)%y``?gAMM(@`Nj=&*oa9Q-SPYFN-lNj z%~B1~NCX_*mch)_^jk*-a2~ZCr#K9vce(rb$`3=sHx)FpzYKHE zZL_`cKP(0G109On5llW0v}_`akjM^OTV`_@%l8hHKWv?>EZZ}v=4fZ}?I{=e(DOGU zrR>i1|Fid%*Bqcz$bAu}`>(BNf1f8zU4G~Hm*?x&@2JyrY!l1y%9pEp-R`rEgOrri zw`GG7_c{kU@oU|2YLD71SvsxlVZwhebk#`Oj}o-wHGV3|XnH-X53p9=jpJ~6R?3c_k|3)#)RfwNysmOW2Db*gbr`!vL7UC?nl z-B$=3Cad~>C)F+=xhk8yCo^|9j{MDQN?OKwB_(>GUA*h+>OlHz*SIjTOQYyVpHy&@ z$>f4mZ)NRunf1s6dADEN4$Q`sD(Vh@j61E)kSSLj>9nrK#^xv8ZFP9`%yy0VFE>m3 zS9iNdy=Of}=5BH*@y$x4@9R4xBS8ZpYLCbZcB-l$KVD1RIH!vTU|xu=fZfs60~ofw zy&VFNTNLxxl|uIe=P-DC_kp*FNbfgOg-e&R25Y2u?(E3jM3(u@>+75Yy}?MxpYUV1 zyUbYDzgMJr2o$U4-+yT(OZe!YSCFM4SFZMB!FczzLLb&M2%$vn1&|DIq|(YwGvwIC zj`KW}RwtvNf;e&{QHLDo9b*Y1pl@UHZ9!*$19I@_9EHQ=Ka^w0(NcF8rs1mI7=0 z>&CjRrtj<88apetzx}u}kf6mBcB6iZx5zxd6d=Mi85B;a*sfl^+9D}_;zX!}V~eDY z4s=eM?aTSXxHFx%cdzq%AaQ5+*tKid%VR*rG$Nr-hq!@g)x#|Va2$s|47rQY7UWzg zVV!_6erABi4NE<|K()a{1|kjBD|7Cwt{y&8Ud~xL9M}X53g3>JAwNVAx+hR+LLwr} zf`+7^ZRBK!_6c|JI@Y314s=36s2T;E(6M8UA3hv`YF1Zw*}$dnnN)8EC0K9jCMbO&%q5HS z(c7*xUDl!%xW}$p%kAWJ(1(M6Kaod11$QdCix9&-w*b&wkef^GTQ$-c``T=`+Lw=Q zZ5raH8Aq^U_!_~Q|6jTg!v?&(ai&pvFJvp<*{pQtd1&<5*F1?GH11L9wHIyni&VWNeZ$jw~>02IZNFzn`(cnfdtEqv{hsp(gZ%2Wq zMa1yZ`2uT6Oh~|w(B22MkA;~ThQlSS$WDdShKdmR!*FM3XTe-h(bK1Z7KHHtRdBx5 zCH8;OfqjPNU$NRaR-N<%^q zu(ce}&sZ553I}oPVa5E$RiK*KU)F;M1+2^PnUDZun1Sz4Meyv=(JYjhoUjJ1E)biL zx&xE}pr{KA7tpjfvBnQ}%ox2EuuO3Hc*09=orXziDs=m3^=!}5*InqAmvi0hyte$L z4<#x-nge8~gb)DI;TIWQ2H(5E>@!Cc8d=KP)I{h2bbDf|&Q3qQ3}D* z1MV{X0qci9g;An3LX3fXg=_oL&=7;74TNPzvYlvlULI8HyZ7!r>$bLnTGc2^XhH@Y ztj=^=5r~xIr{YUX&sYz`8Pz>dWQmAC0eJ&YZ~}dTSYS4}qaTmiVXqp1j-B{_GHr5*`Oc?^^|)4aQOkNofNfx$_CWM0^g(;(EHlf#=#aKmxr_*%~ThYZ*QTT?9AoD@F9JDxUt90 z79{X-KZk~BSy|Tys&;8gCUczX^^z4m5^skq=xc+yI`n6}FT6o>#pKH$iQi z^&t0gqzT!j`Q3YE+Sll_JoEo5(ry?&XIUR5O}}}7q%!WJkNo96efwMgMtE+9Gri*y zY3)IJsjj1wo|I&Rcmh^HzM=TtyMvfIk=uB7*PcCRpnd@8B(R$P>(?*LegR5A9Voo{ z!8P0u$>{oZtC0p47@0sQadI)5Bz$TY>F4ycG6^71Xs6&wq<`xxBa*;lAac>5mWIs> zn>NVhoMR*KCP249%Gub?3P{GHzZ#|jKoLVBUTRg7Z{5ny$qBo$C_j&;N<0{f-6a{5 zX#g~R3FcL75V9Rt|2!q1Jp6KlUbF4_UZE~k-_VdXQP`@Eywmt!>lSqOEZpd8IK>(P z`Id9%C5555;#E_-umeW*C~;nIXt(@8`pJ+$P6s!TGXPhb#>s+02QY{+l{A}Sv!oBO zVC)2&PN}19+dXdZMp+U2V@^9tNIMn|KY?U$a%hPA`?k# zmhT^4&X!>1@?JY3JlgbO(Y;uo=^3MM!8vL|i9JmeSrN=yG8g;e$5=Dsn&RUvHPA{3 zHPZ%)>lpl@e{Q-@l9Lnh_JmLtH#UECYZ=-!}7sOcZ$%CO`60>@8E5!?K!QJLOtTu)Ag*8SrwO^4|(ugQ_ zKXt0Iqgj`Sc0`VyEdhy=h6Kokr{3wDo`A}QOa}%ApozYicK-4BY#Z_8$-YBWJ|H}% zCnlIsV?n$U7N!kfT{4ou|;wgw3+0M_A|VoeT!GCe2{*_Mc|!k5#veITeCplhUDk&WRn} z_rze80`W=eY;b5OJw3f}W|0Ng*idp-*40Te6PLugx~utvUebpt(;!qjdQ{zs_xA1E z;lj8^^s1rpADC)4yfR`v+#-B4y7_e!%G6s{Cu&+-UvSS13=V#Xx~|iPun>49tJB?a zVXB^a1)zZ~gTd9S2M-)Lx+=Z&z!SJZ(;4M26GbCqe`ROtgjDrKUn0LbVX`3DtZ6JE za!tHxy@5Fqx!9*j(9$=}%sM;N)qK=VLZg!|o=5tfUkD9R$U)6rCW=;8GdQv7EYDxO zU|%)HzYw0zpFa-{7OdtPYb zWWl-u0Sit7b-;f-%Q_Wdr`3PhI9`uTadop+?UFHMYgW|||8?EX$JB0ZAP&6|tp!uhn@&)@&`%Tz@VOxFU2zMpbwaS^nT>@!9U+XogN+QoMK zL0PYL^5r?thy2Hre0i-_a*;iYu zz)l6J9@_60J@!EWWE4>e6lEFgLUZWVGUqFz3P$3;Fc1WB?PBbIL7CH9PgM3cyW%-j zoWp9}V_!zm=?6RaJ_>3Su?lJdjT%VsAVTrGQaS$XR|$qVT-Z5`LRgi|o&2wO;@#oS z=UQgd_LCO>7Z7wPLuAVP(6K1OP5kUY>{$c(0L&gq-dS8L8Wj%h2k(m@8s&{vGJzfj z!%xo-TUuHYVnt|jV7QnNc+=97C_JIl67o8aFl%w`no8&hAXFPH2BHz%1_*knvpvho z)`*b@;K*`vgdh(YtDZqqMgP4b>G-ep^#q`dR0yS#6I4);N+GYtA%P_4Qq;-o#>S$C zAGe$6TMSy++Z$j6fuSKAWmLf8(1sM+XM}{HWMMbm`dKSXk|bgbW`8 z=~30-4DuGdjL1{d(}}TqfbX#u&loS39!59%%>(`6GQy2zI|oW*52$NtYD<1+6|n?r z_@5TQ(aU!my|Bl|#l@jD6v;O#0u;dJW6duiZV>Vi6%oP6 z331eqXfZs)$M*`y6u1SpR2O}t5DnD*fL`~exw+7;vl%&gd2vEC(k?l`DrXNsxmBUShWYP0FRHn zc2IS`2zkI{PjMl-B`Ms5AP^Xb24(qgPV8tVmK|n662Z`#aE1RvSiI6NE`Ts}yfMWO z&lg4eDhY=S#0>eiZ9ph6LJh7O`j8VR3c1yiTj!`lsF_iC+U@>rb&`26Wj{T|{Qqh? z44y4ls;@P;SR`wZ9JBl9MNV>xNG9gUfoqm3E?h@bcO~C){P34AWPeCX<&AdP>M?c)VuvU{7|N}wI!&P^RKIy9{*(;P}}(=ItacCCj_f_#XP z0J_QKh+zb&86AZjrVkxzHeXiz^ChVfUcs;MHhRxmuD9Rre6nYJYWmU~OLZLF8d=^w zLO*{t?&+}-hVc1Fw=W;w777*XJBE)tuljVh#&AaPELwM+R{w2DL_;$7t-Sy*TaS8c z{qCOqnfto=3D4H%k!SfDrgLJ^Erp53Ot1Fd)&!axrvWr~UQb3}*N%YjudxuS@+;vo zv}X^S$zDx*WK1I;tEKtFZ?yTZZ*OvJCj<9ARpI2N4GfNqfw-n#>L(xl2m4U+-xEEp zmaL;#XcuAdcj|bCGR1kNQfiiKdfj~T<1WXj-u~nnw3@bzSXDX68&WEB}4~Crrd?= zOG{sE?ySG~UB@;yn@ZP`Gh=s`hw+RwN!ul<=&P|3>{19*^Lj+Pm?QNw$Ip6!>^Zb_p2Jlc<3>9MM_wc zn`V`A^{>(XX?g8OQrNVISeh?Trq9OKvr$n8Jo%i$*h7aI2w2I}#3t2WR@a>Iky7`4 z5aB%=>%zfP%g&aiBhmAq#{0M=hPtZkVfQ5a8igvY!7FL?;HO!Iy5O_N(&&VHn$%g^ z40TEaf9unh=n{QJQ*mnAeCWbdp(fsP`goh+C5l;j9$e!QT+7TdlR28LDzn za_3t$+jM-gBjFAA_F$PlCGOMo4eu$u!L&!+chi+^YqQ(72@%HkaHp~?-!Az3~F zvH#%^$`}QV-4x1w$CvkI<3u{Q($w{pdM*>cWbs>7fG%W16__{#nX@*85L#ZNHCsVx6?pA5-7b-v2%L+Z;wegA0nr&>tS3bfe zi1~aRC=dK|iTn@tdKTXiJ+I17ewOsH(MepX?if3p%x#6qvy!%^CN__+(!{{=<_KE$+;S7%xD_`2?@@R5%vAHUDPK8YbgS%FhOT9`Tb3yy3C zqjiwj_7-kF`tQCjPQpSHcIqK@bm!RajmJr3C_ip=iWp7j&Zasjq6X8IXZw4+rmM7o zH-8LGO<0@y?Sx6%_!PZF!P)Em=^g8Gf%KukqA%*c;otgRrR+$rdM`^IY&x=jD(E8{ z+hsw9m)Dp1yD4#CMYxCqpt_x8SpM<5uIiN&Y&i+Jz8QOuH*4BXn4D}c=t<3b^kwJw zWdHp-Tdm6aZmC`&r?k@8V@q-HNTv7qj!r>air9hle6(}o{U+qF01@{Sr(T|56NZvV^5Uod zUB>iY>D=7AM_)-+SAXs4?NFBu4&EL=v|(=$%0N93Z+JSY=RR&e;t0%CMOivv(cxZi z{ijzGl;NsZ+W2QxP4;b#BfEAQdV41(rAaJ` zJkCJBC$R%WGM`HQIYFgw(SCD)_Hg>UoQE04k!S;|?#dHxuEtyShAxiOQn{M?+5Tfu zZ!Iu60srGZybE{VnyPom@h|7d1*7)1-*qoaa?-bmPh{*Xw3Mh$?(r75twE#8O%w6( z&8SjYpWd)`{T~HU-?9HJ^%Y^;S8y1nNv3^I>)tU%>#HArUX=cR=;VQN1DdW{n&>U@ zW!678kA^X?LD)_lvJ*4{B?KkLfaJqf2=zUn%Xj!A7XKxd~sNccG;6OZVF6 zeTIEKJ`Dm{mZ~?w9%f_3I}4`UF9ii}-(=+drEmC5xV#}HWm?$N);FtulipZyoz2+x zOfNY;*I>>2XHE~wA3e5m`%0TkJX-CtLT*=g~{!alvM3u8lUscyTGRPKCRn1K&#I3Ra4C&$+mlKl2%`Q!cKI$ zV~%pOGhcQb`}&wj_M3;^FLpbciLbG4m}}lq9NCD{@0Zt*ci_BQUN9L7p2^tz#wMCPNW#^lBKx+j?ZTj<|NQB_M;|myHqIR#vVAG*dCru%3r55BpMG)e zIOQDwD?tU#_M4*TYdQ|R>t>1^PnB=b%H-H`sPJuP;g>1HQOXA#EXWvRp_coKdS$)!&`}?RyU3Nqj zy*XV=C*hjoWTd4#Y>=x0kVM1BSv()Q;Kn8gt;73Y(!MDF%a4Xe?4kzv}J5TPXeUa|26ZQ6{Ot<+Gm|?Qmi>mKV_%LTx`<6JeYO6@0!$w!1}t2@!QY$ey8P-EREx@ znZMs2(X88t7~v_n^Sb^?C^viT`_5c@?~eY5@#t-~74+K=-d!8_#B<)8S!(3vOCR84 zGdf=kzbRCFVi|s*P3YpXmQ69aV3U}2CMSgry$!2T=E}e_^Vu;RiX~3OrhM<0kPxm$s!ZR3lEe5_3bEdJC`r|^%Qb|{swKYyO4LbO{?hW zI9AbW5p|Ta5(W{XsfHkPF-_z*F;M?oIZ@N5#5kHms0_Vn#$v&CtH-|IyYKn(#{4dt z&=dGe9Z+rc*YBAj{@p2lO1#1H)q2&Yk&gy%@)sX-4%lXu*Bxw#nx4L<@QL4j)X*Dd?)+r@U>JEg-B z7E|TxYrCHK=?w1Kx-aHlc3(jvhd^KF)nBH1b-U6PO9Q#mGG>%r%0~}1VAg#>dOFA@VUs!)o|TWR=>Ecd)j|kofYp^R4)}7m z9J4VCLumn&<%LVB$}j-~i_6{breMQSR4^7V3Gs=L-s$-NrIP77PC2VdC#k zR+j9quBqv>s$m)W0KGda$ky~|(0F`oT6$JhX$yx~F!B< zO<=~=Vzhnlm9yW$DS{)Jem9X-iz%+n3dhdW_&=PbRBy9dUma`HSWfS%Fc%Y5_O6pV zdu2%|FaiGw2PRI^S>D>-8X#qMsee3Zq^&#B|7qP@eZp@XkjJuNCSD_ENIRdzl>YRc z@il{lHcuwWe!AuKCI`S@U6r6xc<3s}HQw#02fBcfG50aMmLUE3`Zm#5GHvhuJLS)6 zDgJ8D4K}{@38!-AIR$Hy&i!{=;u7QfidKf>3Z+PO+59XneP1PTl&YzQy?*}!enqi) z6Qx;GLRFeBhF?Kcr7u9>OXG*?4A%aH3Qv7F&zG(>zUOI7p^Jmv12N_%?jeJ3`PmV? zEDN(CG!7GIBg-CETmvcb*~oC`VVcE)Gn0~K7f2tCvi~mHUpG_v`Lm7>y701z{eNIv zE3R%B1XWdehlgyQ%HS%OnY}Y*07mAocVwVV11&e`G?`ta28QD@o|b~X1Ka8|F!m+k zsl-+FO0!cv4~oxzUh9_&7b{7$`17%@I;)u~v@Bct{P6>rEvQQ4#l5wMdz%G+ak5$M zgAg|XvBH3zEjdX^q{XcBpLhiX_HNw_RW=@NGEakVhsl}m(&$-HD|S#^vK)yAC5Vpj z(~)N~+)h8TTlw9(izWV)%4m_6>DlmmJKT8H-EJ<0sPzA970csv}$TSXS1o z?~5!sFo7!+)yA9lsc z#U3?-X>XaNzy4z$$-k2&p*l_*u-(_}Z)T6IjZ&KgjeE<{9Gv8?~5mCtF= z1|UR~JH5FxVU#tyRr-ZfpR94QiFxfz=t?bBpC)mB-K7_OyYH0ilh9L#hdiiStpYE^ zM0gH1JmVmv&Ag3+=@RYs^aZy(hvw$!uHS(sJ9u5crCeMYi)Gv_W&fagiVM;<2`fLmzHgt$hPmO7MJe8=7Lv3YlT)mxSC2}^y_mel8{R* zt*${y<6CtPW1nB4^#z{amVs8|l+G`P->=(-ZvT#7<2UK~9xb-rQ)s#=m_wJ#qBgr{ z-BO`QomiB(sD$+NUIuB^;|ES-mPPH5ypmFW_xXt&5gAp|$FTLP$@*i(<9!zP(MM@1 zWdc5bD{#A|!drU2O}OG3F)@WR$md9JD$}_;6+T`)n_r${GqeynK9+t=MliO17yA83 z>=-?0H@k^`7)+UKxumFQn_>T}4C@;|`-G+B`fDfV6gkz9$;@ARV6enpc>mMW{Kq?c z*bK$E*UQps!+KXPZUPTU-p;#s>nI{u&S{VsYdXu{7TSMP zpHklLDK7d$K-(dM@ve_IN4)hdf75w9j*jdSuIstjeD^O&fx2dalXt>t^5@nR5UYsu zSNEj-%+F&TJZw)m#IOH&{Nz;LRKqqP88p(KM>T?HVsAV3N1o|=W7@LVI6c{Oh*P>x zovh)J)A~wIG#Bd`)^ASlILe~S@SHIzjia91Wgf&i_LcD8$!u(Tnp zNf~seQ}BnrY8~O8$V@LB_FOCLbTM4)?xQbSWuv++>}DhT`tT&;6`o;?F(tZuK1H#iuy}j4jK}!#j{Y-rc*>@M>TWm-7B+ zQ@@{|nH1kJnOxb!o-tQ-OQ$RR-FBv@dnZ+Q()WEUwjMmWacSo7C-toU$7a-SHIB>? zHq(GX+wUCKCVJeKZWR}NFS}kBxGZqdnl#R|<9!j2&cd75*L=N?hKzbXVC6Ac)7niY zsFl&3|;s1rp-d`$52BQdyGu=)PXM4KFCpU)H$0bPINW_S|7o&*x*a zd!mah>&rIZUc6RLr}o%hg!@TZ8d=oi0i~dlqFNb}BAx8;GAGjs3Uaczs|ouP{C*v~ zt1o(Evav=!uYa*tN2x5N_L;lmXQ#Pt*vn1W3uhDy6B|Y*x%063w@?ZHzT+0>vulpA2~vjmPyeztj-(-WQrTGI zs_h6L#?f+=^>q)A+C&rgzYELEAF=!)zPPvV=dP_XN!M?E99fu~Y7)6RtwPoi)EBNX zx0={>&t}=`@7%;Zp6f>@!0fd@-}s-s)B2l3ys7DI&8G#;Kf8qHUG!;31~HpN{=I>= zFnv>~w>Fh{)!&F$_COw0wjA|Lbx7w43RydCHg@TDN4DxOn2Z_Kop0EhU8;F&{$&sO z*%Gu9sK{MY!;WltCUY{c{i1yP)!k0GO+3wC&hO`_r=ojSbdtL(86JSXGJ3WzC)VIw z$e=)sxz9+rAgbdXSc1SBR^~GckNpdnn;v}-7hCyJ5EGzjDZRb*#)D=LuZ*cSL|DtG z=GOijZe|a5v-fo+a)dkOoX*07HwHF7ysl z`ci&pTqyZOV>@9H^A>GLM6 zm!)U$QNuGhr#Nz&Oov1NV>dPKoe6jCkCKs9;!*D-(=D$O6HV^eENx~R@Xm7;A0BY! ze_OVFJB6`i`Bc~Pg97Hh>D$&Kk5>`gm1(4-QtZW;nP)3F-Bf4;E@V^sA~&@#k3#y_ zN@lQ@oG|a!9Fo|z+8g6qx^X9y@%smy6<5WU{deW6YmkzRFSioAAIzMID-b=TQo`ld z*|w47c?ww3m!@u*jPFs;lPA)7;9{0v+_AIx5Ti6GSzc)G5w_h$ZBr`cxo-g_FFic6 z^qK@%m>0_o3nuU^bh1`FJiX!Eq14{>rjYQ7dwKoupC)9V$8j1O-_aLdAf?Q0+l1J?!4<6 z*UMH|;R)J3&#`tg{{1F_LEoviSPR;e+7q{i|4siLw)h}%Oy23n|I^)s{gLaDsh3?;avAoB0K+-TM8}QX+8qkvC*lW49<70{t$MmU@vdmNN~X` z@(Nwmzu!*j=;ikU13`B$tCd;H&h>^l$X#+wAXEO(>POv!KNsq;O1Ezh%IY^E?S+vE z5q;q38n96+bop4*N?ZHAeOcL$X8!xZosfwg0-IaWD6_Z}-EL&_ypTpU0 znb(`*(-Rtb`^2aL`i*)OX01tA5{NLYy;SABtVuapQuF?C?heN=vDV$lGk*zb7&9yJ zkz>#g+C+Pfcor+l1;McQS^q_0^sY;}!5=q_{*wzJNfcw`2Sv*oZ(bK)v`O(<3ArdX zEs)zL_Mr1U&hbN^B~~AQ<3f6W0^PgvCL(WdeG{MDBZP-F`KDd)^gq|P4T3=QX(;BxUPXOhwFx!d;7NbDc`4d zdd&9PUR`c=m_8JdrJx2DY0Y=x+hcN@TVK7b@$6rlet7Qub8ICHKvhC{`+^QN*GrGu z(#OwjJE|TKE@k-6mCUyfm-@z~KHt0Ec9?x1Utv=!Ne#_T z<0jSj`mMztd0Muf8jrT&i_^;_M+RA~_b&oPQN3d-GrcoyV7AJhnh;_4`*r1~GJT1p zb=p462V;Z5_4aFy4&OJJ;?#){TGFGo`x(*16h=F^qE(6?u*HZw{t!F{f)TCR2U*Qg z!8Hnia7{Kr*Jyevezva)COwl^oOD+fXy`faNsdxC!WBM#WMtKvH?CDRVTqsit*x7u zBJn25IGL{gxDSI_ckHehn+CmGD|BhZkY#?k5n}Z5Tej8F3FE75-%dQS3@UL9d=ahy z%RzYd21@(NJUb0~Qw!Br(ETO5kH8K&naz@vRqL`le|eQbwAVp=$eAfX4Cgh z27F-YrV7&4eN)Sx@<|jLkB8Gq9Nqc*>QKr3tZ{lJVw`)q#M(piE;!Ygicou!>+h$9 z-J=S8Whqj3B8eBTX1~0mow>Z=JbdT!t!5+l6dwAKU8o{Yrs<$TvEOeN#|6Zi#o-}r z9~o6|EOTIKRLg4^R=oC#{88rm{D#@WNPJ--Lu=Vduel9Pyt#k6gI9 zuaDS&zFWwn=+C-qv~%WDBsFt?n(H(%`&o~~$)m7rp{%=hk@qDvpB8N?nY_T7e`yT} z6W8ZAURh3U*IUl3_4AH+cJTR0*+5cEr(zaS;$OH-y?tSHDPTPhx2@K&?^`~x9uAfq zI+0iZ>QpSr?2PJ2UKC6Wo-M~mo}DCy5caYQX0Rr%`BBmz@*>a6Rji-|L*SiP}z&84_I?K#1z%h;Wn1?*R zO|*<`nZ;C&zgSOYnYePU=y(nJwlo)M`~aDL!JfB2_y0%B2r^hNOOThZuXoB69NY_{ zJheMh%DcY3cVLOQ^ai|Izc<%u+;eD7*!FsU;Bok5c_mk&dUrx6Ffw`VFQ?lznYNtQ z3E!HisGLAl$%&(AGTC5@X{_YjS9N=Z)WNyOd*?G*kF3Ze#mu&aZS$7bpk;(Nc)w^^x;kA(gS<^4PfyP$m`_`*Fz_s=o(yt`gbsh* zuEKgsSdEj7U=U7gXDu%XqC>?;%U@1Wc!&@iUOt=v3AF#cK<^(ZAwjWbDJoq?c7!e^ z@vn;czKqNfXM=_D_lAq}F9!crG1;P%tgTm?MN~{r3PKEWa+ia%Al~nS7P(N5u(NCw z#vkPE-7=kK3N0>Y1BeF~UgF@WtV)anO40#HRpbM{%yk3pa(V(~6On=qJsXIIp%@Y+ zFOzcl%bL@Q9Yn(f2YwxkAQl!SbwA!(Z&2Xr_PX&kl>94u=i(%m>@(cRP}gPdb%8IR zF8Qf0(`C$4Tdh_O>P%&vOz{#k_kB*81=?yL`%b(XbXC~@H8Bz>KD#<6IVolljI6U? zEVQtva`)RF2`+ofzumg9{V_gTbqoFJm7=*;KJ&OU`Ek4b*#O6=%ia8RnZt+!z=I7S z&tFFs7M&=U+;5U8`y^>a;P8SlRM4;I-AgFcX_$}da*9uXRG7OTWYKvJ1afp5=OdVmqA0WBG1`N)(CKh1#{f_R(Ip6#=YO~ z4MT|ytj8Yf#C_qSPP@B<(fUtZqt}no{ry+hO+Ws)q1yjsqXHjfY#Iw)dM~BqWN)f_ z>rdtS8xQ?A!!+jB&1{szO-AW&H+f7)<;HI*F@M1bmIw-B4KVpnvUu-eavpszRJ?vXNfvhnlJg&$ zc(k9uKc!G?;EPeVbIb&KN7J$aMv6d9^M+3@=P%s6IUYpX7boo>VT>_c%Eb_-YpD^e zld$Ym!g2kp{k>?Pi+iNU%iz)HFvdVKmdKpH!#nJC7=tywV>rnvxmE*rJ`2Zk$%sLX zm$@#u>matxQ+ypFS-%6ad|+9Do;*`%P~nN1KxAU1Je$`E+Zq$r5+mxxQJU|uwM6Qu zG8L|eK+F0ST9qD6Jk1AxJ->nH5%nMJ>*#Vy57~-|#dE<+0yka>5f@3QiFOksSgtwF zt6&HskEexGjCS7ufRf$EnAAV|mN(yX=7c*We7KF;hyYy_YT( zPF6SF5OvQ^T!{7;HTfm~$8pdnS9nbCr4?yn|43=Am9G}8(_!^s{5L-?70>RL zAGi%;ulLc$S=2Z21B4EPk!g%m{C*BOtN95F@J$|JyQ*sXK@>c_hc&Y6D zA~pN$#59NZb7T9ny5D;6fz?e~zn;VNQt|xUzVO(kp)EC!CZJ*6%IE!cfWGD5=R9~m z$6!+`7uX=)rmQQl-P+x3_$#*YFZn7a16;LKYZZ@#@K?nWV}WCzTjbf^=ZIeT_1qH* zfU94LeV>b$yL(M&){4QeOy@Co)5qlltVLQ51>h_Fzgna(tR2cF3i(zwtnqApHfmhm zC6ybmu;=~G?@LVIJovQ)LZogqSNK0TMT6nSFT6R_3 z-CHr-YJ4tK=CLUbODwlR`pyC?@>d{c^*I(lLvK}BX7;lO&iFyeu5?KcD$2T{ecb z;l%)km?%~?B*P)t&RIO^2ByxJ2j5z@T1@eu_Q??2NeRSGw4x+}R)(z0)66Ys<7qw` zZig==Z}5BM3JiGENok1>x)!!MG;LW$Gssutf);>)**4)0#|w<=M#mJqW~YFiI`B7p zKFy2@gPBWXs@51qwJlqyxUJE#P zUirLwKl%;J7+DpUh8>zRW7@a*xV+kO4Smr#k*<1_Myo-Q#-b%`MH4Ny4d0&Pk_+6& zNLasn_wEC*TOu7Eu;i$U>K)++D{ceejlukBRZi#S3w(eKdp)HQHDt$EO|GHj-qK!* z<-1jOl-UnZFD4Mm30zoCHOcY`_MT1jnEDdD59u6EKvP8_<~hP<`L+6rQY>oQ!7S#D zLLA^@DuCz;$gxO($N{+&#uM9nhGN4W&VgB8``1;@E>aZ+cCP+O6#dd0**-lvN5Drx zUkQ%TZ@AwlBx7Jl14*y<;ov}dr0E0mK+E(OSU?r4+n}BM-fJzWE7M`t5FqlNSz)_TDAo&WVvrllF4QNsO zIV2Bk)s5UtCB=h%@i(`ZSRtbY=Gi^0|4(PD)RW<*cYX`OntXxcEm+Srp|?0MDO*grfj6X zV-~p%x3>YOD67d`RuRN`IqB&-`gekrXOfFn&@0gy@Rw#oPymQwvfUR2z6&V6LXHTE zfl@gMlc@SX0Q~JW=eYVKi49h{tfPC|1&_zOXvWUVe$50eV&R(s&jaT#7FDiq-@hNf ztYkEpE+h+jNJqe;irW`--4GzMhB|l%TrP^IJm!Glmo_~RN07_nJP24de(39P!v^rZ z>hT;3f5PW2*B;UZSi)Xfio^|TE330f0XE>>%SWM6-O#$_Y~E8{?A%{L+L>aCD%qKj zr-B12ao;G8Gzr`{zK>Se1=b1VQ8YFF)6)ZPoI+rz5nP2)1)m>fEU`}3K<-5jkkG%l z7OLMz+Ch>7Br&7>_c8;CdU}k%;PP2;%6p2jJ*z#-*a=9NX7* z6s4zsyY;g)f402jK%Cnuk8k_3pL{^?D-AErcF$|b$vU_^@Xt5m?pdw+_uFn(DumgN z@Qz{BS$$dmZz@7}Pi#?xSGj@C+j}|>fmDiH-aeqb^^QG7y2(&|N*%aHbC5cNM=McM z_U6tuNJcsSqI#+dxghdMo28e^FnH2;c2~&>Sx7KT)Mz>rCq}!UYsf7XTyj1*hNeWn zyUn-8m_`#Jxbj3^Ko%m*u{7OSoE)X);Z27gJlGod+`Qp+bW8Bxqit133=QkS*$hhK z`>Cm}av3>DZ}PW!YE!XF;VTbsO1WbFfgg+6+xe>>TiDZd=!xOm?C)$F*LbWJcu;!n z6aKpqI-(D`RHG*%ghjWjnps)h?-&lI({b!1Cryp+Ntr!--^erGb|AM-tNLYg-hS?B zP~}!n8S^?CE_um$XTyczxZ#$)Z!NmFT)PxO6)-XrUe4C$kjKh1DLc0{kmOes9nb0* z);oOo;eRzMtZH&m;7A7N`O(#?SNp}!_evyx-gZqFZtg8R&m@`0g~vyr&S(}i4!!N( z-;uadd+t(Aqlt&|Mp}iTWBkt={-L>ralt9W75Up8j-)@vd8P)_q4w-wVh>Z>p|U8+ z{>W;;wtnJA5HJfG01?*PYtp(RdDqqK1F_M1I6!cD)WDcD`NV^}vChg{wG(4qbU*D3 zyzJxvO8PCEH}AIl_#H)Uf4}t{+Mlo9uV2HDSnqLgZ(%_iUBN>I>b*?dcKr+rmFa1wWE2d@dOCP*Vl%`EKRxl0uDMJ0R(B@81q| zIDn9x#(>nz2F8`Ymo5Q<0zCl`ANz-IafrjA>+L)GGr$gRr zs@*p~ldW*!5Kb_s1HHW$k^M9f z!`+38jp~@38W*RKt(W|kdft5sGlyIE20H40P$)fO6RSpkI->>us)MY;P&mqWzUYUgRm$mZ+7va>ACjA5GL!ev(vp zX^~UBF91#&=NyMxLnNU%Ltz0_Xh*m>(g#o$$;~a8{QQdklJ--!tv`F7xhSu^6FaK5 zrrb*R+Xk2j+2vx|N^+0jgQ%GAGTx}YQtNrJYctp+Z(-e zHGS#Dt$S1B>DqI2yL4?;^Z>~r$r|Sx_buM?Q!;2}3sZ;tklR+yi->8&E@@fwkBOnz zwIYNy1ZyuO@12|RuYazjM$DFYA65VD&nDjg5V9~;-rc+!<_4dpri-0+VB+107@Y)i_EiN$MNb?#}vs5?^_}eev*PBgp2PCd5~d zDLj$iGoM9$D*a}Kem!IIqfPa5^`U6L`4>V-4ter>h`c1N$Ppcve&a2Qc9I>@`)lhj zjQtE|Iu&+2dq3RTBh{KY^LG2->M_2hKV*%I&h#tYG3`zt*`R<%MCT-5^fk?zBbFBnsxt!ajXcj*btNT&p92WC8PO3 zh?+;@-MM-(P)OZ$sNHequ8E(?##-)UUY~rj$9W4`oQ#=%{r^L>G z<$Snyjm0@}y}wAO;31Sv*KI#pF0>f> zfd26?kBhm-jk>PiM=?Xv9ON$Zb=V2pkJXKjET$t3wx2Yvxp@CWT0JB0h&oSb1I7`a zqa!3F8FV<;ooC1{PQ*J0;RDH6c$?CXYrWioC%ijp(HZ7}eJUP z40%Ob^q|6{K5s`W+=nitQeWlmd&^$J-d2H)TnL%kaLg@oYo+Gqmh~16dIC0j3%5_+ zF8*uPGIYonQLi!V?d?Wt4W@lk?Q?1LquF}(omt2E#!L*j-#?a=91%)C)W)lQVOo5) zN@DV=dhC+8(WNB11ySeFrAxLSOQFutXR8L4&tNGEnIdm3^7qoR7w#nbCmE`h+XdKL zI$zk`EZ`R8aV65lK>e}k1tEz1@G0^`p$8(UBm6_( z6>}idX-f2DwpsPUIrTzuX4GqI+ub#>UVB-K=o5mwF^g@DYi-X<*`CiDm9eQ25Nk2= z3QOs@*DW>sXML%Z)URbzfzR)|s@y6^e$O#Mp}{{?O%vIa5F*4zxSC+zc&GiT#uDC8 z-HyM=u=*HW)aY$J9JVLr@L%zD{2P3|`0L)_*n~&mHb{# zZVvFnMnW|BxsC%BzkK#1=7ry-jQ=NIKV7ScG=l^&H%&4I8q*mSPWV}_rEg?3yqwZs z1;brn_u0Qdum0`h&f*+O!{cKaUd)c(AAd?jzq?k`kp5>5(nY}p0@AC2nBOQ>?3({) z#?ND9G+sseLaABwzu6=%%_xiwM<1O4Kv_G|h{skgj&3K3#P8)gKv$QH%yCqrzpkvT zQRH@74_jcmKP?MDLlI$Nu3*{&@0u}^2t??qscvU*J+}C&3Y-&Q>wcgAIgByO-v)@U z2TVcZv|P~kfWP$7Q3>FStE&LOzcT6G-Sj8|_Qd4J0y7E}f0k_`8 zCoV+)!O75qp-hqrWo+tUg^X9BgLGbTQNZ*dlOM^j-`WZ%Vg7?LV&;qRLOuvDiW3(x zE8o0vgXIo3qVvFuLCQC1eL*iUP^&2ngqB9d^^`<}$dZrX#DxQ)2xw*qxse;NV|mrD zfVdtRt7`YrWu%64EL}`+6x(ZkEIj6?d#|c=5`$gTMoa4r@*BH;OdDq%&$zUkqJe_xQs*FXs{K4xhUU;<9A5^PGr@xFK(Sz+1JZC6d{w? zW}+GEa9gf@t&q^5lRVyqt2u!Mj-3#;^nmpOtAV%aY{e5`6B*?^w%jeFs6SlvqYBCK zrV@PIa6ljsS5T4=%#RPXLgiX_Fj16fmGdX7I-}CQ1o_ z`&d1Yad^Y@q-MiyUiiseNMp~EuAopjw;xj5Z`kh#aND);haA0seuB~E0g{rIyT?ke zBsT=KFufNr*T7z>8g#XQbqu36V;YBfui9@kM>Kv83<#@~zN<_-cA%WUZs@CPVbtz( zR4N|5uCA7{U;^s^Xy*P0kx8FAeE_iwz`3M$jY;2vD=&$y3&B}eufxiu%^cuSHS-6wddy7l zCcU4Eg$#yDVP(IR_q6r{-R|)7x&R&gJaa-CDT4FH`gd+_a0Bo`GT%P77v>p<>(}kF z_W1ss{jTd_Jw1YJ@!pG*B5xArA|JsaQU*Am)JKnKrtN^>BA;q8P~24CRMkdrfr#cM7Zkf0l@HaR6e3cs!!}mQbP26@LXHW)b;jc7awm_dOURM}bVaJcHcO`7WJ&V?(ZL(vWBzj>4fSzw^-!X7j= zLnDxbA31mKYlDe}d1%}sN|lfwm$WY;6afd}-5oBJ*|g~tN+DX5eS)4Gf=afQjnZq2 z3<=pt1rp2-;7Zf!t3y;o9sy~C*q3OVxq%;}qp5Dwz@kHyhlzHx z&-pXEa3;R5u5R)=Q)re6c^Q48_(M>&KGr2BnR+s(8HIg6@KxZ+^aJ1yC!+U6^BGLX zt37X*Q;cw@-c>y?ZWCU3$6|xQA$Z~bK#?>aUkP%zMfhoy%Mzio~;K3yYuI= zJppX9pUt+WzOu=MMj&8!xk9TbRliq5{l)=+<644P!#Af_nqEtCb))DFdWM#ns*XB_ zlrF?YeVP9L9D}O-d7nI6gp@V}`>SbcHl35`>?r@DNtf#322iaTf2?U*x-nbK?mPC;OY|gH6J zj7@vUMhy~<)@?#gtJmWF0+9NKzRa6u#;$8qPq>h%Y(Ia(XZtP3d)Z73oY2SkM`LG@4Er?;3m6ahddKf%Ybe^R<+nL1+XoMb0I7NK7ty>Wwb3=b+_C98o}k;5{aqy zf7@6lmK~+04v}2M-kkg0qTV+mii{JcAQ(n@|8kh>%Ljo~H5=h|L`6p}5u*Ywkunqshy{R7 z22kTc>L^kDOds;++dvqAj1>k86D;W#u>J1i=tvrpwrxy@zA0!M0xcy_x?!v|UeSQH zZ7P47heC@%NbyHTUi<10;Ff_x%6OP$10rE{5#@|D7=(c66HtjDH26Tqf^b7(Lq_Gq zW}P$LbyJv+yfi-0G#~_Dw|*^Ll+JfJ4^kyPVC2n+!V{74#}dis0M*OB3*{I8{ofE# zjCgNN4=8D-b__W=b*55H6^+kg)|<@asHb(Z|;MM|DW%GZu*HI zVBI`J;r6UogBui0uQV-NJeGte=qZw5gYqTo%6SmoqHe8m{O>a~h5&V_B=FL4_KA{27KVk<6VyG|W_ zu}lhF#>ajw2AMu86{$IQ9s$e+aHVl$p%E*5!MnwMqFMsfV)0rJ#Fl~Ji VGV*ydR*FJ7q<&Z}Q}x8P{{f;^A^-pY literal 0 HcmV?d00001 From dcd43d240a71c2df411070f98a3bdb6810cdea4f Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 15 Feb 2025 18:21:25 -0500 Subject: [PATCH 04/46] gitignore dev/ --- test/bench.jl | 45 ++++++ test/infinite.jl | 409 +++++++++++++++++++++++++++++++++++++++++++++++ test/xy_chain.jl | 125 +++++++++++++++ 3 files changed, 579 insertions(+) create mode 100644 test/bench.jl create mode 100644 test/infinite.jl create mode 100644 test/xy_chain.jl diff --git a/test/bench.jl b/test/bench.jl new file mode 100644 index 000000000..765c940bd --- /dev/null +++ b/test/bench.jl @@ -0,0 +1,45 @@ +using TestEnv +TestEnv.activate() + +using Profile + +include("setup.jl") +using .TestSetup +using TensorKit +using BlockTensorKit +using MPSKit +using MPSKit: ∂∂AC2 +using BenchmarkTools +using KrylovKit + +L = 50 +g = 1 +D = 128 +H = heisenberg_XXX(; L) +psi = FiniteMPS(randn, ComplexF64, physicalspace(H), fill(ComplexSpace(D), L - 1)) +envs = environments(psi, H); + +eigalg = Lanczos(; tol=1e-14, krylovdim=5, maxiter=1, verbosity=0, eager=false) +@benchmark find_groundstate(psi, H, + DMRG2(; eigalg, trscheme=truncdim(D), maxiter=3, verbosity=0); + svd_alg=TensorKit.SVD()) +@benchmark find_groundstate(psi, H, + DMRG2(; eigalg, trscheme=truncdim(D), maxiter=3, verbosity=0); + svd_alg=TensorKit.SDD()) +@profview find_groundstate(psi, H, + DMRG2(; eigalg, trscheme=truncdim(D), maxiter=3, verbosity=0)); + +pos = L ÷ 2 +Heff = ∂∂AC2(pos, psi, H, envs); +@plansor x0[-1 -2; -3 -4] := psi.AC[pos][-1 -2; 1] * psi.AR[pos + 1][1 -4; -3]; + +@benchmark $Heff * $x0 + +H2 = FiniteMPO(map(SparseBlockTensorMap, parent(H))) +envs2 = environments(psi, H2); +H2eff = ∂∂AC2(pos, psi, H2, envs2); +@plansor x0[-1 -2; -3 -4] := psi.AC[pos][-1 -2; 1] * psi.AR[pos + 1][1 -4; -3]; + +@benchmark $H2eff * $x0 + +VSCodeServer.view_profile() diff --git a/test/infinite.jl b/test/infinite.jl new file mode 100644 index 000000000..adc787cf3 --- /dev/null +++ b/test/infinite.jl @@ -0,0 +1,409 @@ +using TestEnv; +TestEnv.activate() +include("setup.jl") + +using .TestSetup + +using Test, TestExtras +using MPSKit +using MPSKit: fuse_mul_mpo +using TensorKit +using TensorKit: ℙ +using BlockTensorKit + +verbosity_full = 5 +verbosity_conv = 1 +tol = 1e-8 +g = 4.0 +D = 6 + +H_ref = transverse_field_ising(; g) +H2 = InfiniteMPOHamiltonian(map(SparseBlockTensorMap, parent(H_ref))) + +ψ = InfiniteMPS(ℂ^2, ℂ^D) +v₀ = variance(ψ, H_ref) + +for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℂ^2, ℂ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) + H3 = repeat(H2, unit_cell_size) + + # test logging + ψ, envs, δ = find_groundstate(ψ, H, + VUMPS(; tol, verbosity=verbosity_full, maxiter=2)) + + ψ, envs, δ = find_groundstate(ψ, H, VUMPS(; tol, verbosity=verbosity_conv)) + v = variance(ψ, H, envs) + v2 = expectation_value(ψ, H3) + expectation_value(ψ, H, envs) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ + @test v < 1e-2 +end + +for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℂ^2, ℂ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) + + # test logging + ψ, envs, δ = find_groundstate(ψ, H, + IDMRG(; tol, verbosity=verbosity_full, maxiter=2)) + + ψ, envs, δ = find_groundstate(ψ, H, IDMRG(; tol, verbosity=verbosity_conv)) + v = variance(ψ, H, envs) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ + @test v < 1e-2 +end + +begin + ψ = repeat(InfiniteMPS(2, D), 2) + H = repeat(H_ref, 2) + + trscheme = truncbelow(1e-8) + + # test logging + ψ, envs, δ = find_groundstate(ψ, H, + IDMRG2(; tol, verbosity=verbosity_full, maxiter=2, + trscheme)) + + ψ, envs, δ = find_groundstate(ψ, H, + IDMRG2(; tol, verbosity=verbosity_conv, trscheme)) + v = variance(ψ, H, envs) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ + @test v < 1e-2 +end + +for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℂ^2, ℂ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) + + # test logging + ψ, envs, δ = find_groundstate(ψ, H, + GradientGrassmann(; tol, verbosity=verbosity_full, + maxiter=2)) + + ψ, envs, δ = find_groundstate(ψ, H, + GradientGrassmann(; tol, verbosity=verbosity_conv)) + v = variance(ψ, H, envs) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ + @test v < 1e-2 +end + +for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℂ^2, ℂ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) + + alg = VUMPS(; tol=100 * tol, verbosity=verbosity_conv, maxiter=10) & + GradientGrassmann(; tol, verbosity=verbosity_conv, maxiter=50) + ψ, envs, δ = find_groundstate(ψ, H, alg) + + v = variance(ψ, H, envs) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ + @test v < 1e-2 +end + +######################## + +tol = 1e-8 +g = 4.0 +D = 6 +L = 10 + +H = transverse_field_ising(; g, L) + +H + H + +begin + ψ₀ = FiniteMPS(randn, ComplexF64, L, ℂ^2, ℂ^D) + v₀ = variance(ψ₀, H) + + # test logging + ψ, envs, δ = find_groundstate(ψ₀, H, + DMRG(; verbosity=verbosity_full, maxiter=2)) + + ψ, envs, δ = find_groundstate(ψ, H, + DMRG(; verbosity=verbosity_conv, maxiter=10), + envs) + v = variance(ψ, H) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ && v < 1e-2 +end + +begin + ψ₀ = FiniteMPS(randn, ComplexF64, 10, ℂ^2, ℂ^D) + v₀ = variance(ψ₀, H) + trscheme = truncdim(floor(Int, D * 1.5)) + # test logging + ψ, envs, δ = find_groundstate(ψ₀, H, + DMRG2(; verbosity=verbosity_full, maxiter=2, + trscheme)) + + ψ, envs, δ = find_groundstate(ψ, H, + DMRG2(; verbosity=verbosity_conv, maxiter=10, + trscheme), envs) + v = variance(ψ, H) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + + @test v < v₀ && v < 1e-2 +end + +begin + ψ₀ = FiniteMPS(randn, ComplexF64, 10, ℂ^2, ℂ^D) + v₀ = variance(ψ₀, H) + + # test logging + ψ, envs, δ = find_groundstate(ψ₀, H, + GradientGrassmann(; verbosity=verbosity_full, + maxiter=2)) + + ψ, envs, δ = find_groundstate(ψ, H, + GradientGrassmann(; verbosity=verbosity_conv, + maxiter=50), + envs) + v = variance(ψ, H) + + # test using low variance + @test sum(δ) ≈ 0 atol = 1e-3 + @test v < v₀ && v < 1e-2 +end + +L = 3 +T = ComplexF64 +V = ℂ^2 +lattice = fill(V, L) +O₁ = rand(T, V, V) +E = id(storagetype(O₁), domain(O₁)) +O₂ = rand(T, V^2 ← V^2) + +H1 = FiniteMPOHamiltonian(lattice, i => O₁ for i in 1:L) +H2 = FiniteMPOHamiltonian(lattice, (i, i + 1) => O₂ for i in 1:(L - 1)) +H3 = FiniteMPOHamiltonian(lattice, 1 => O₁, (2, 3) => O₂, (1, 3) => O₂) + +# check if constructor works by converting back to tensormap +H1_tm = convert(TensorMap, H1) +operators = vcat(fill(E, L - 1), O₁) +@test H1_tm ≈ mapreduce(+, 1:L) do i + return reduce(⊗, circshift(operators, i)) +end +operators = vcat(fill(E, L - 2), O₂) +@test convert(TensorMap, H2) ≈ mapreduce(+, 1:(L - 1)) do i + return reduce(⊗, circshift(operators, i)) +end +@test convert(TensorMap, H3) ≈ + O₁ ⊗ E ⊗ E + E ⊗ O₂ + permute(O₂ ⊗ E, ((1, 3, 2), (4, 6, 5))) + +# check if adding terms on the same site works +single_terms = Iterators.flatten(Iterators.repeated((i => O₁ / 2 for i in 1:L), 2)) +H4 = FiniteMPOHamiltonian(lattice, single_terms) +@test H4 ≈ H1 atol = 1e-6 +double_terms = Iterators.flatten(Iterators.repeated(((i, i + 1) => O₂ / 2 + for i in 1:(L - 1)), 2)) +H5 = FiniteMPOHamiltonian(lattice, double_terms) +@test H5 ≈ H2 atol = 1e-6 + +# test linear algebra +@test H1 ≈ + FiniteMPOHamiltonian(lattice, 1 => O₁) + + FiniteMPOHamiltonian(lattice, 2 => O₁) + + FiniteMPOHamiltonian(lattice, 3 => O₁) +@test 0.8 * H1 + 0.2 * H1 ≈ H1 atol = 1e-6 +@test convert(TensorMap, H1 + H2) ≈ convert(TensorMap, H1) + convert(TensorMap, H2) atol = 1e-6 + +# test dot and application +state = rand(T, prod(lattice)) +mps = FiniteMPS(state) + +@test convert(TensorMap, H1 * mps) ≈ H1_tm * state +@test H1 * state ≈ H1_tm * state +@test dot(mps, H2, mps) ≈ dot(mps, H2 * mps) + +# test constructor from dictionary with mixed linear and Cartesian lattice indices as keys +grid = square = fill(V, 3, 3) + +local_operators = Dict((I,) => O₁ for I in eachindex(grid)) +I_vertical = CartesianIndex(1, 0) +vertical_operators = Dict((I, I + I_vertical) => O₂ + for I in eachindex(IndexCartesian(), square) + if I[1] < size(square, 1)) +operators = merge(local_operators, vertical_operators) +H4 = FiniteMPOHamiltonian(grid, operators) + +@test H4 ≈ + FiniteMPOHamiltonian(grid, local_operators) + + FiniteMPOHamiltonian(grid, vertical_operators) + +pspace = ℂ^2 +Dspace = ℂ^D +Os = map(1:3) do i + O = rand(ComplexF64, pspace^i, pspace^i) + return O += O' +end +fs = [t -> 1t, 1, 1] + +L = 5 +ψ = FiniteMPS(rand, ComplexF64, L, pspace, Dspace) +lattice = fill(pspace, L) +Hs = map(enumerate(Os)) do (i, O) + return FiniteMPOHamiltonian(lattice, + ntuple(x -> x + j, i) => O for j in 0:(L - i)) +end +summedH = LazySum(Hs) + +envs = map(H -> environments(ψ, H), Hs) +summed_envs = environments(ψ, summedH) + +expval = sum(zip(Hs, envs)) do (H, env) + return expectation_value(ψ, H, env) +end +expval1 = expectation_value(ψ, sum(summedH)) +expval2 = expectation_value(ψ, summedH, summed_envs) +expval3 = expectation_value(ψ, summedH) +@test expval ≈ expval1 +@test expval ≈ expval2 +@test expval ≈ expval3 + +# test derivatives +summedhct = MPSKit.∂∂C(1, ψ, summedH, summed_envs) +sum1 = sum(zip(Hs, envs)) do (H, env) + return MPSKit.∂∂C(1, ψ, H, env)(ψ.C[1]) +end +@test summedhct(ψ.C[1], 0.0) ≈ sum1 + +summedhct = MPSKit.∂∂AC(1, ψ, summedH, summed_envs) +sum2 = sum(zip(Hs, envs)) do (H, env) + return MPSKit.∂∂AC(1, ψ, H, env)(ψ.AC[1]) +end +@test summedhct(ψ.AC[1], 0.0) ≈ sum2 + +v = _transpose_front(ψ.AC[1]) * _transpose_tail(ψ.AR[2]) +summedhct = MPSKit.∂∂AC2(1, ψ, summedH, summed_envs) +sum3 = sum(zip(Hs, envs)) do (H, env) + return MPSKit.∂∂AC2(1, ψ, H, env)(v) +end +@test summedhct(v, 0.0) ≈ sum3 + +Hts = [MultipliedOperator(Hs[1], fs[1]), MultipliedOperator(Hs[2], fs[2]), Hs[3]] +summedH = LazySum(Hts) +t = 1.1 +summedH_at = summedH(t) +@which summedH(t) + +envs = map(H -> environments(ψ, H), Hs) +summed_envs = environments(ψ, summedH) + +expval = sum(zip(fs, Hs, envs)) do (f, H, env) + return (f isa Function ? f(t) : f) * expectation_value(ψ, H, env) +end +expval1 = expectation_value(ψ, sum(summedH_at)) +expval2 = expectation_value(ψ, summedH_at, summed_envs) +expval3 = expectation_value(ψ, summedH_at) +@test expval ≈ expval1 +@test expval ≈ expval2 +@test expval ≈ expval3 + +# test derivatives +summedhct = MPSKit.∂∂C(1, ψ, summedH, summed_envs) +sum1 = sum(zip(fs, Hs, envs)) do (f, H, env) + if f isa Function + f = f(t) + end + return f * MPSKit.∂∂C(1, ψ, H, env)(ψ.C[1]) +end +@test summedhct(ψ.C[1], t) ≈ sum1 + +summedhct = MPSKit.∂∂AC(1, ψ, summedH, summed_envs) +sum2 = sum(zip(fs, Hs, envs)) do (f, H, env) + if f isa Function + f = f(t) + end + return f * MPSKit.∂∂AC(1, ψ, H, env)(ψ.AC[1]) +end +@test summedhct(ψ.AC[1], t) ≈ sum2 + +v = _transpose_front(ψ.AC[1]) * _transpose_tail(ψ.AR[2]) +summedhct = MPSKit.∂∂AC2(1, ψ, summedH, summed_envs) +sum3 = sum(zip(fs, Hs, envs)) do (f, H, env) + return (f isa Function ? f(t) : f) * MPSKit.∂∂AC2(1, ψ, H, env)(v) +end +@test summedhct(v, t) ≈ sum3 +# ------------------------------------------------------ +dt = 0.1 +algs = [TDVP(), TDVP2()] +L = 10 + +H = (TestSetup.heisenberg_XXX(; spin=1 // 2, L)) +ψ₀ = FiniteMPS(L, ℂ^2, ℂ^1) +E₀ = expectation_value(ψ₀, H) + +@testset "Finite $(alg isa TDVP ? "TDVP" : "TDVP2")" for alg in algs + ψ, envs = timestep(ψ₀, H, 0.0, dt, alg) + E = expectation_value(ψ, H, envs) + @test E₀ ≈ E atol = 1e-2 +end + +Hlazy = LazySum([3 * H, 1.55 * H, -0.1 * H]) + +@testset "Finite LazySum $(alg isa TDVP ? "TDVP" : "TDVP2")" for alg in algs + ψ, envs = timestep(ψ₀, Hlazy, 0.0, dt, alg) + E = expectation_value(ψ, Hlazy, envs) + @test (3 + 1.55 - 0.1) * E₀ ≈ E atol = 1e-2 +end + +Ht = MultipliedOperator(H, t -> 4) + MultipliedOperator(H, 1.45); + +@testset "Finite TimeDependent LazySum $(alg isa TDVP ? "TDVP" : "TDVP2")" for alg in + algs + ψ, envs = timestep(ψ₀, Ht(1.0), 0.0, dt, alg) + E = expectation_value(ψ, Ht(1.0), envs) + + ψt, envst = timestep(ψ₀, Ht, 1.0, dt, alg) + Et = expectation_value(ψt, Ht(1.0), envst) + @test E ≈ Et atol = 1e-8 +end + +H = repeat(TestSetup.heisenberg_XXX(; spin=1), 2) +ψ₀ = InfiniteMPS([ℂ^3, ℂ^3], [ℂ^50, ℂ^50]) +E₀ = expectation_value(ψ₀, H) + +@testset "Infinite TDVP" begin + ψ, envs = timestep(ψ₀, H, 0.0, dt, TDVP()) + E = expectation_value(ψ, H, envs) + @test E₀ ≈ E atol = 1e-2 +end + +Hlazy = LazySum([3 * deepcopy(H), 1.55 * deepcopy(H), -0.1 * deepcopy(H)]) + +@testset "Infinite LazySum TDVP" begin + ψ, envs = timestep(ψ₀, Hlazy, 0.0, dt, TDVP()) + E = expectation_value(ψ, Hlazy, envs) + @test (3 + 1.55 - 0.1) * E₀ ≈ E atol = 1e-2 +end + +Ht = MultipliedOperator(H, t -> 4) + MultipliedOperator(H, 1.45) + +@testset "Infinite TimeDependent LazySum" begin + ψ, envs = timestep(ψ₀, Ht(1.0), 0.0, dt, TDVP()) + E = expectation_value(ψ, Ht(1.0), envs) + + ψt, envst = timestep(ψ₀, Ht, 1.0, dt, TDVP()) + Et = expectation_value(ψt, Ht(1.0), envst) + @test E ≈ Et atol = 1e-8 +end diff --git a/test/xy_chain.jl b/test/xy_chain.jl new file mode 100644 index 000000000..8072ede05 --- /dev/null +++ b/test/xy_chain.jl @@ -0,0 +1,125 @@ +using FiniteMPS +using CairoMakie +using BenchmarkFreeFermions +using LinearAlgebra + +""" + This script provides a benchmark between linearly increasing beta list and exponentially increasing beta list (in the initial stage), which is proposed in our tanTRG paper (https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.130.226502). + +""" + +function XYChain(L::Int64; J::Real=1.0) + Root = InteractionTreeNode(IdentityOperator(0), nothing) + + # J(SxSx + SySy) = J/2 (S+S- + S-S+) + for i in 1:(L - 1) + addIntr!(Root, U₁Spin.S₊₋, (i, i + 1), (false, false), J / 2; name=(:S₊, :S₋)) + addIntr!(Root, U₁Spin.S₋₊, (i, i + 1), (false, false), J / 2; name=(:S₋, :S₊)) + end + + return InteractionTree(Root) +end + +function ExactSolution(L::Int64, lsβ::AbstractVector{<:Real}; J::Real=1.0) + # JW transformation to spinless fermions + T = diagm(1 => J / 2 * ones(L - 1), -1 => J / 2 * ones(L - 1)) + + @show ϵ = SingleParticleSpectrum(T) + + return map(β -> FreeEnergy(ϵ, β, 0.0), lsβ) +end + +# XY chain +# convention: J(SxSx + SySy) +L = 30 +J = 1.0 +D = 64 + +lsβ_lin = 0.2:0.2:8.0 +lsβ_exp2lin = vcat(2.0 .^ (-10:1:0), 2.0:1.0:8.0) +lsF_lin = ExactSolution(L, lsβ_lin; J=J) +lsF_exp2lin = ExactSolution(L, lsβ_exp2lin; J=J) + +H = AutomataMPO(XYChain(L; J=J)) + +# 1. linearly increasing β from Id +lsF_1 = let + ρ = identityMPO(L, U1Spin.pspace) + lnZ = 2 * log(norm(ρ)) + normalize!(ρ) + Env = Environment(ρ', H, ρ) + canonicalize!(Env, 1) + map(1:length(lsβ_lin)) do i + dβ = i == 1 ? lsβ_lin[1] : lsβ_lin[i] - lsβ_lin[i - 1] + + TDVPSweep2!(Env, -dβ / 2; + trunc=truncdim(D)) + lnZ += 2 * log(norm(ρ)) + normalize!(ρ) + + F = -lnZ / lsβ_lin[i] + println("β = $(lsβ_lin[i]), F = $(F), δF = $(abs(F - lsF_lin[i]))") + return F + end +end + +# 2. exponentially increasing β in initial stage +lsF_2 = let + ρ = identityMPO(L, U1Spin.pspace) + lnZ = 2 * log(norm(ρ)) + normalize!(ρ) + Env = Environment(ρ', H, ρ) + canonicalize!(Env, 1) + map(1:length(lsβ_exp2lin)) do i + dβ = i == 1 ? lsβ_exp2lin[1] : lsβ_exp2lin[i] - lsβ_exp2lin[i - 1] + + TDVPSweep2!(Env, -dβ / 2; + trunc=truncdim(D)) + lnZ += 2 * log(norm(ρ)) + normalize!(ρ) + + F = -lnZ / lsβ_exp2lin[i] + println("β = $(lsβ_exp2lin[i]), F = $(F), δF = $(abs(F - lsF_exp2lin[i]))") + return F + end +end + +# 3. initialize high-T state via SETTN +lsF_3 = let + ρ, _ = SETTN(H, lsβ_exp2lin[1]; + maxorder=4, tol=1e-16, + compress=0.0, + trunc=truncdim(D),) + lnZ = 2 * log(norm(ρ)) + normalize!(ρ) + Env = Environment(ρ', H, ρ) + canonicalize!(Env, 1) + map(1:length(lsβ_exp2lin)) do i + i == 1 && return -lnZ / lsβ_exp2lin[1] + dβ = lsβ_exp2lin[i] - lsβ_exp2lin[i - 1] + + TDVPSweep2!(Env, -dβ / 2; + trunc=truncdim(D)) + lnZ += 2 * log(norm(ρ)) + normalize!(ρ) + + F = -lnZ / lsβ_exp2lin[i] + println("β = $(lsβ_exp2lin[i]), F = $(F), δF = $(abs(F - lsF_exp2lin[i]))") + return F + end +end + +# plot +fig = Figure(; size=(400, 300)) +ax = Axis(fig[1, 1]; + xlabel=L"\beta", + ylabel=L"\delta F", + yscale=log10,) + +lines!(ax, lsβ_lin, abs.(lsF_1 - lsF_lin); color=:blue, label="linear") +lines!(ax, lsβ_exp2lin, abs.(lsF_2 - lsF_exp2lin); color=:red, label="exp2lin") +lines!(ax, lsβ_exp2lin, abs.(lsF_3 - lsF_exp2lin); color=:green, label="exp2lin + SETTN") + +axislegend(ax; position=(1.0, 0.0)) + +display(fig) From 914c183d7224a7af3a5239cda65b1f2c53d2e16d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 15 Feb 2025 18:21:40 -0500 Subject: [PATCH 05/46] Start twosite derivative --- .../derivatives/hamiltonian_derivatives.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index d2abcc40d..727fec0dc 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -138,3 +138,16 @@ function (H::JordanMPO_∂∂AC)(x::MPSTensor) return y end + +struct JordanMPO_∂∂AC2{O1,O2,O3,O4} + onsite_left::Union{O1,Missing} + onsite_right::Union{O1,Missing} + not_started::Union{O1,Missing} + finished::Union{O1,Missing} + start_end::Union{O2,Missing} + starting_left::Union{O3,Missing} + starting_right::Union{O2,Missing} + ending_left::Union{O2,Missing} + ending_right::Union{O3,Missing} + continuing::O4 +end From e3332d7c057c7dc80efd50f65e703627a0917b16 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Mar 2025 15:58:44 -0400 Subject: [PATCH 06/46] start playing with JordanMPOTensor --- src/MPSKit.jl | 4 +- src/operators/abstractmpo.jl | 8 +- src/operators/jordanmpotensor.jl | 310 +++++++++++++++++++++++++++++++ src/operators/mpohamiltonian.jl | 13 +- test/setup.jl | 4 + 5 files changed, 328 insertions(+), 11 deletions(-) create mode 100644 src/operators/jordanmpotensor.jl diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 8effb23aa..147b7b8ea 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -60,6 +60,7 @@ using Compat: @compat using TensorKit using TensorKit: BraidingTensor using BlockTensorKit +using BlockTensorKit: TensorMapSumSpace using TensorOperations using KrylovKit using KrylovKit: KrylovAlgorithm @@ -75,7 +76,7 @@ using DocStringExtensions using LinearAlgebra: diag, Diagonal using LinearAlgebra: LinearAlgebra using Random -using Base: @kwdef +using Base: @kwdef, @propagate_inbounds using LoggingExtras using OhMyThreads @@ -112,6 +113,7 @@ include("states/ortho.jl") include("operators/abstractmpo.jl") include("operators/mpo.jl") +include("operators/jordanmpotensor.jl") include("operators/mpohamiltonian.jl") # the mpohamiltonian objects include("operators/multilinempo.jl") include("operators/projection.jl") diff --git a/src/operators/abstractmpo.jl b/src/operators/abstractmpo.jl index 21adff0be..266836422 100644 --- a/src/operators/abstractmpo.jl +++ b/src/operators/abstractmpo.jl @@ -37,10 +37,10 @@ end # Utility functions # ----------------- -function jordanmpotensortype(::Type{S}, ::Type{T}) where {S<:VectorSpace,T<:Number} - TT = Base.promote_typejoin(tensormaptype(S, 2, 2, T), BraidingTensor{T,S}) - return SparseBlockTensorMap{TT} -end +# function jordanmpotensortype(::Type{S}, ::Type{T}) where {S<:VectorSpace,T<:Number} +# TT = Base.promote_typejoin(tensormaptype(S, 2, 2, T), BraidingTensor{T,S}) +# return SparseBlockTensorMap{TT} +# end remove_orphans!(mpo::AbstractMPO; tol=eps(real(scalartype(mpo)))^(3 / 4)) = mpo function remove_orphans!(mpo::SparseMPO; tol=eps(real(scalartype(mpo)))^(3 / 4)) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl new file mode 100644 index 000000000..4aae1b079 --- /dev/null +++ b/src/operators/jordanmpotensor.jl @@ -0,0 +1,310 @@ +""" + JordanMPOTensor{E,S,TA,TB,TC,TD} <: AbstractBlockTensorMap{E,S,2,2} + +A tensor map that represents the upper triangular block form of a matrix product operator (MPO). + +```math +\\begin{pmatrix} +1 & C & D \\\\ +0 & A & B \\\\ +0 & 0 & 1 +\\end{pmatrix} +``` +""" +struct JordanMPOTensor{E,S, + TA<:AbstractTensorMap{E,S,2,2}, + TB<:AbstractTensorMap{E,S,2,1}, + TC<:AbstractTensorMap{E,S,1,2}, + TD<:AbstractTensorMap{E,S,1,1}} <: AbstractBlockTensorMap{E,S,2,2} + A::SparseBlockTensorMap{TA,E,S,2,2,4} + B::SparseBlockTensorMap{TB,E,S,2,1,3} + C::SparseBlockTensorMap{TC,E,S,1,2,3} + D::SparseBlockTensorMap{TD,E,S,1,1,2} + + # uninitialized constructor + function JordanMPOTensor{E,S,TA,TB,TC,TD}(::UndefInitializer, + V::TensorMapSumSpace{S,2,2}) where {E,S,TA,TB, + TC,TD} + allVs = eachspace(V) + + VA = space(allVs[2:(end - 1), 1, 1, 2:(end - 1)]) + A = SparseBlockTensorMap{TA}(undef, VA) + + VB = removeunit(space(allVs[2:(end - 1), 1, 1, end]), 4) + B = SparseBlockTensorMap{TB}(undef, VB) + + VC = removeunit(space(allVs[1, 1, 1, 2:(end - 1)]), 1) + C = SparseBlockTensorMap{TC}(undef, VC) + + VD = removeunit(removeunit(space(allVs[1, 1, 1, end:end]), 4), 1) + D = SparseBlockTensorMap{TD}(undef, VD) + + return new{E,S,TA,TB,TC,TD}(A, B, C, D) + end + + # constructor from data + function JordanMPOTensor{E,S,TA,TB,TC,TD}(A::SparseBlockTensorMap{TA,E,S,2,2}, + B::SparseBlockTensorMap{TB,E,S,2,1}, + C::SparseBlockTensorMap{TC,E,S,1,2}, + D::SparseBlockTensorMap{TD,E,S,1,1}) where {E, + S, + TA, + TB, + TC, + TD} + # TODO: add space and size checks + return new{E,S,TA,TB,TC,TD}(A, B, C, D) + end +end + +function JordanMPOTensor{E,S}(::UndefInitializer, + V::TensorMapSumSpace{S}) where {E,S} + TA = tensormaptype(S, 2, 2, E) + TB = tensormaptype(S, 2, 1, E) + TC = tensormaptype(S, 1, 2, E) + TD = tensormaptype(S, 1, 1, E) + return JordanMPOTensor{E,S,TA,TB,TC,TD}(undef, V) +end +function JordanMPOTensor{E}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E,S} + return JordanMPOTensor{E,S}(undef, V) +end + +function JordanMPOTensor(A::SparseBlockTensorMap{TA,E,S,2,2}, + B::SparseBlockTensorMap{TB,E,S,2,1}, + C::SparseBlockTensorMap{TC,E,S,1,2}, + D::SparseBlockTensorMap{TD,E,S,1,1}) where {E,S,TA,TB,TC,TD} + return JordanMPOTensor{E,S,TA,TB,TC,TD}(A, B, C, D) +end + +function JordanMPOTensor(W::SparseBlockTensorMap{TT,E,S,2,2}) where {TT,E,S} + @assert W[1, 1, 1, 1] isa BraidingTensor && W[end, 1, 1, end] isa BraidingTensor + # @assert all(I -> I[1] ≤ I[4], nonzero_keys(W)) + + A = W[2:(end - 1), 1, 1, 2:(end - 1)] + B = W[2:(end - 1), 1, 1, end] + C = W[1, 1, 1, 2:(end - 1)] + D = W[1, 1, 1, end:end] # ensure still blocktensor to allow for sparse + + return JordanMPOTensor(A, + removeunit(B, 4), + removeunit(C, 1), + removeunit(removeunit(D, 4), 1)) +end + +function jordanmpotensortype(::Type{S}, ::Type{E}) where {S<:VectorSpace,E<:Number} + TA = Union{tensormaptype(S, 2, 2, E),BraidingTensor{E,S}} + TB = tensormaptype(S, 2, 1, E) + TC = tensormaptype(S, 1, 2, E) + TD = tensormaptype(S, 1, 1, E) + return JordanMPOTensor{E,S,TA,TB,TC,TD} +end + +# Properties +# ---------- +function TensorKit.space(W::JordanMPOTensor) + V_triv = oneunit(spacetype(W.A)) + V_left = BlockTensorKit.oplus(V_triv, left_virtualspace(W.A), V_triv) + V_right = BlockTensorKit.oplus(V_triv, right_virtualspace(W.A), V_triv) + P = physicalspace(W.A) # == physicalspace(W.B) == physicalspace(W.C) == physicalspace(W.D) + return V_left ⊗ P ← P ⊗ V_right +end + +Base.size(W::JordanMPOTensor) = size(W.A) .+ (2, 0, 0, 2) +Base.size(W::JordanMPOTensor, i::Int) = i ≤ 4 ? size(W)[i] : 1 +Base.length(W::JordanMPOTensor) = prod(size(W)) +Base.axes(W::JordanMPOTensor) = map(Base.OneTo, size(W)) + +Base.firstindex(W::JordanMPOTensor) = 1 +Base.firstindex(::JordanMPOTensor, i::Int) = i ≤ 4 ? 1 : 1 +Base.lastindex(W::JordanMPOTensor) = prod(size(W)) +Base.lastindex(W::JordanMPOTensor, i::Int) = i ≤ 4 ? size(W, i) : 1 + +Base.CartesianIndices(W::JordanMPOTensor) = CartesianIndices(size(W)) +Base.eachindex(W::JordanMPOTensor) = eachindex(size(W)) + +Base.eltype(W::JordanMPOTensor) = eltype(typeof(W)) +Base.eltype(::Type{JordanMPOTensor{E,S,TA,TB,TC,TD}}) where {E,S,TA,TB,TC,TD} = TA + +function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) + Base.checkbounds(W, I.I...) + I == CartesianIndex(1, 1, 1, 1) || + I == CartesianIndex(size(W, 1), 1, 1, size(W, 4)) && return true + + row, col = I.I[1], I.I[4] + + if row == 1 && col == size(W, 4) + return haskey(W.D, CartesianIndex(1, 1)) + elseif row == 1 + return haskey(W.C, CartesianIndex(1, 1, col - 1)) + elseif col == size(W, 4) + return haskey(W.B, CartesianIndex(row - 1, 1, 1)) + elseif 1 < row < size(W, 1) && 1 < col < size(W, 4) + return haskey(W.A, CartesianIndex(row - 1, 1, 1, col - 1)) + else + return false + end +end + +# TODO: avoid this slow fallback wherever possible: +Base.parent(W::JordanMPOTensor) = (error(); parent(SparseBlockTensorMap(W))) + +BlockTensorKit.issparse(W::JordanMPOTensor) = true + +# Converters +# ---------- +function SparseBlockTensorMap(W::JordanMPOTensor) + τ = BraidingTensor{scalartype(W)}(eachspace(W)[1]) + W′ = SparseBlockTensorMap{Union{eltype(W.A),typeof(τ)}}(undef_blocks, space(W)) + W′[1, 1, 1, 1] = τ + W′[end, 1, 1, end] = τ + + Ia = CartesianIndex(1, 0, 0, 1) + for (I, v) in nonzero_pairs(W.A) + W′[I + Ia] = v + end + Ib = CartesianIndex(1, 0, 0) + for (I, v) in nonzero_pairs(W.B) + W′[I + Ib, size(W′, 4)] = insertrightunit(v, 3) + end + Ic = CartesianIndex(0, 0, 1) + for (I, v) in nonzero_pairs(W.C) + W′[1, I + Ic] = insertleftunit(v, 1) + end + W′[1, 1, 1, end] = insertrightunit(insertleftunit(only(W.D), 1), 3) + + return W′ +end + +# Indexing +# -------- +@inline function Base.checkbounds(W::JordanMPOTensor, I...) + checkbounds(Bool, W, I...) || Base.throw_boundserror(W, I) + return nothing +end +@inline function Base.checkbounds(::Type{Bool}, W::JordanMPOTensor, I...) + return Base.checkbounds_indices(Bool, axes(W), I) +end + +@inline function Base.getindex(W::JordanMPOTensor, I::Vararg{Int,4}) + @assert I[2] == I[3] == 1 + return W[I[1], I[4]] +end +@inline Base.getindex(W::JordanMPOTensor, I::CartesianIndex{4}) = W[I.I...] +@propagate_inbounds function Base.getindex(W::JordanMPOTensor, i::Int, j::Int) + if (i == 1 && j == 1) || (i == size(W, 1) && j == size(W, 4)) + return BraidingTensor{scalartype(W)}(eachspace(W)[1]) + elseif i == 1 && j == size(W, 4) + return insertrightunit(insertleftunit(only(W.D), 1), 3) + elseif i == 1 + return insertleftunit(W.C[1, 1, j - 1], 1) + elseif j == size(W, 4) + return insertrightunit(W.B[i - 1, 1, 1], 3) + elseif 1 < i < size(W, 1) && 1 < j < size(W, 4) + return W.A[i - 1, 1, 1, j - 1] + else + return zeros(scalartype(W), eachspace(W)[i, 1, 1, j]) + end +end + +# TODO: this is definitely suboptimal, but might not matter? +@propagate_inbounds function Base.getindex(W::JordanMPOTensor, + inds::Vararg{BlockTensorKit.SliceIndex,4}) + V = space(eachspace(W)[inds...]) + dst = similar(W, V) + + Rsrc = CartesianIndices(W)[inds...] + Rdst = CartesianIndices(dst) + + for I in nonzero_keys(W) + j = @something findfirst(==(I), Rsrc) continue + dst[Rdst[j]] = W[I] + end + + return dst +end +@propagate_inbounds function Base.getindex(W::JordanMPOTensor, + inds::Vararg{BlockTensorKit.Strided.SliceIndex, + 4}) + V = space(eachspace(W)[inds...]) + dst = similar(W, V) + + Rsrc = CartesianIndices(W)[inds...] + Rdst = CartesianIndices(dst) + + for I in nonzero_keys(W) + j = @something findfirst(==(I), Rsrc) continue + dst[Rdst[j]] = W[I] + end + + return dst +end + +@inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::Vararg{Int,4}) + @assert I[2] == I[3] == 1 + W[I[1], I[4]] = v + return W +end +@inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::CartesianIndex{4}) + return setindex!(W, v, I.I...) +end +@propagate_inbounds function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, i::Int, + j::Int) + if (i == 1 && j == 1) || (i == size(W, 1) && j == size(W, 4)) + throw(ArgumentError("Cannot set BraidingTensor")) + elseif i == 1 && j == size(W, 4) + W.D = removeunit(removeunit(v, 1), 4) + elseif i == 1 + W.C[1, 1, j - 1] = removeunit(v, 1) + elseif j == size(W, 4) + W.B[i - 1, 1, 1] = removeunit(v, 4) + elseif 1 < i < size(W, 1) && 1 < j < size(W, 4) + W.A[i - 1, 1, 1, j - 1] = v + else + throw(ArgumentError("Cannot set index ($i, 1, 1, $j)")) + end + return W +end + +# Sparse functionality +# -------------------- +function BlockTensorKit.nonzero_keys(W::JordanMPOTensor) + Ia = CartesianIndex(1, 0, 0, 1) + pA = [I + Ia for I in nonzero_keys(W.A)] + + Ib = CartesianIndex(1, 0, 0) + ncols = size(W, 4) + pB = [CartesianIndex((I + Ib).I..., ncols) for I in nonzero_keys(W.B)] + + Ic = CartesianIndex(0, 0, 1) + pC = [CartesianIndex(1, (I + Ic).I...) for I in nonzero_keys(W.C)] + + pD = [CartesianIndex(1, 1, 1, ncols) for I in nonzero_keys(W.D)] + + pτ = (CartesianIndex(1, 1, 1, 1), CartesianIndex(1, 1, 1, ncols)) + return Iterators.flatten((pτ, pA, pB, pC, pD)) +end +function BlockTensorKit.nonzero_values(W::JordanMPOTensor) + return Iterators.map(I -> W[I], nonzero_keys(W)) +end +function BlockTensorKit.nonzero_pairs(W::JordanMPOTensor) + return Iterators.map(I -> I => W[I], nonzero_keys(W)) +end +function BlockTensorKit.nonzero_length(W::JordanMPOTensor) + return nonzero_length(W.A) + nonzero_length(W.B) + nonzero_length(W.C) + + nonzero_length(W.D) + 2 +end + +# Utility +# ------- +function Base.summary(io::IO, W::JordanMPOTensor) + szstring = Base.dims2string(size(W)) + TT = eltype(W) + typeinfo = get(io, :typeinfo, Any) + if typeinfo <: typeof(W) || typeinfo <: TT + typestring = "" + else + typestring = "{$TT}" + end + V = space(W) + return print(io, "$szstring JordanMPOTensor$typestring($V)") +end diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index aef1c8d98..61820857c 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -522,13 +522,14 @@ function InfiniteMPOHamiltonian(lattice′::AbstractArray{<:VectorSpace}, return SumSpace(collect(S, V)) end - # construct the tensors - Otype = jordanmpotensortype(S, E) + # construct the tensor + TW = jordanmpotensortype(S, E) Os = map(1:length(lattice)) do site - O = Otype(undef, virtualsumspaces[site - 1] * lattice[site], - lattice[site] * virtualsumspaces[site]) - O[1, 1, 1, 1] = BraidingTensor{E}(eachspace(O)[1, 1, 1, 1]) - O[end, end, end, end] = BraidingTensor{E}(eachspace(O)[end, end, end, end]) + V = virtualsumspaces[site - 1] * lattice[site] ← + lattice[site] * virtualsumspaces[site] + O = TW(undef, V) + # O[1, 1, 1, 1] = BraidingTensor{E}(eachspace(O)[1, 1, 1, 1]) + # O[end, end, end, end] = BraidingTensor{E}(eachspace(O)[end, end, end, end]) # Fill it for ((key_L, key_R′), o) in zip(nonzero_keys[site], nonzero_opps[site]) diff --git a/test/setup.jl b/test/setup.jl index 804ca6e3a..264df3119 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -4,6 +4,7 @@ module TestSetup # imports using MPSKit +using MPSKit: JordanMPOTensor using TensorKit using TensorKit: PlanarTrivial, ℙ, BraidingTensor using BlockTensorKit @@ -57,6 +58,9 @@ function force_planar(x::SparseBlockTensorMap) data = Dict(I => force_planar(v) for (I, v) in pairs(x.data)) return SparseBlockTensorMap{valtype(data)}(data, force_planar(space(x))) end +function force_planar(W::JordanMPOTensor) + return JordanMPOTensor(force_planar(W.A), force_planar(W.B), force_planar(W.C), force_planar(W.D)) +end force_planar(mpo::MPOHamiltonian) = MPOHamiltonian(map(force_planar, parent(mpo))) force_planar(mpo::MPO) = MPO(map(force_planar, parent(mpo))) From e88e61128b7c8964ce585a209a7b772d8df633db Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Mar 2025 20:16:26 -0400 Subject: [PATCH 07/46] Contraction fixes --- .../derivatives/hamiltonian_derivatives.jl | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index 727fec0dc..c511047ea 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -32,10 +32,9 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) C = W[1, 1, 1, 2:(end - 1)] GR_2 = GR[2:(end - 1)] if nonzero_length(C) > 0 && nonzero_length(GR_2) > 0 - @plansor starting_[-1 -2; -3 -4] ≔ removeunit(C, 1)[-4; -2 1] * - GR_2[-1 1; -3] + @plansor starting_[-1 -2; -3 -4] ≔ removeunit(C, 1)[-1; -3 1] * + GR_2[-4 1; -2] starting = only(starting_) - norm(starting) else starting = missing end @@ -48,8 +47,7 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) B = W[2:(end - 1), 1, 1, end] GL_2 = GL[2:(end - 1)] if nonzero_length(B) > 0 && nonzero_length(GL_2) > 0 - @plansor ending_[-1 -2; -3 -4] ≔ removeunit(B, 4)[1 -2; -4] * - GL_2[-1 1; -3] + @plansor ending_[-1 -2; -3 -4] ≔ GL_2[-1 1; -3] * removeunit(B, 4)[1 -2; -4] ending = nonzero_length(ending_) > 0 ? only(ending_) : missing else ending = missing @@ -61,12 +59,13 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) # onsite if haskey(W, CartesianIndex(1, 1, 1, lastindex(W, 4))) if !ismissing(starting) - D = removeunit(W[1, 1, 1, end], 4) - @plansor starting[-1 -2; -3 -4] += GL[1][-1 1; -3] * D[1 -2; -4] + D = removeunit(W[1, 1, 1, end], 1) + @plansor starting[-1 -2; -3 -4] += D[-1; -3 1] * GR[end][-4 1; -2] onsite = missing elseif !ismissing(ending) - D = removeunit(W[1, 1, 1, end], 1) - @plansor ending[-1 -2; -3 -4] += D[-4; -2 1] * GR[end][-1 1; -3] + error() + D = removeunit(W[1, 1, 1, end], 4) + @plansor ending[-1 -2; -3 -4] += GL[1][-1 1; -3] * D[1 -2; -4] onsite = missing else onsite = removeunit(removeunit(W[1, 1, 1, end], 4), 1) @@ -78,7 +77,7 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) # not_started if (!isfinite(operator) || pos > 1) && !ismissing(starting) I = id(storagetype(GR[1]), physicalspace(W)) - @plansor starting[-1 -2; -3 -4] += removeunit(GR[1], 2)[-1; -3] * I[-4; -2] + @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) @@ -124,7 +123,7 @@ function (H::JordanMPO_∂∂AC)(x::MPSTensor) end if !ismissing(H.starting) - @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[1 2; -3 -2] + @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[-2 -3; 2 1] end if !ismissing(H.ending) From 7c683d951e51b4fd26ec117e66e58a765bd8958b Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Mar 2025 20:16:48 -0400 Subject: [PATCH 08/46] JordanMPO fixes --- src/operators/jordanmpotensor.jl | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 4aae1b079..5214f6ed1 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -59,11 +59,7 @@ end function JordanMPOTensor{E,S}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E,S} - TA = tensormaptype(S, 2, 2, E) - TB = tensormaptype(S, 2, 1, E) - TC = tensormaptype(S, 1, 2, E) - TD = tensormaptype(S, 1, 1, E) - return JordanMPOTensor{E,S,TA,TB,TC,TD}(undef, V) + return jordanmpotensortype(S, E)(undef, V) end function JordanMPOTensor{E}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E,S} return JordanMPOTensor{E,S}(undef, V) @@ -99,6 +95,10 @@ function jordanmpotensortype(::Type{S}, ::Type{E}) where {S<:VectorSpace,E<:Numb return JordanMPOTensor{E,S,TA,TB,TC,TD} end +function Base.similar(W::JordanMPOTensor, ::Type{T}) where {T<:Number} + return JordanMPOTensor{T}(undef, space(W)) +end + # Properties # ---------- function TensorKit.space(W::JordanMPOTensor) @@ -146,7 +146,7 @@ function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) end # TODO: avoid this slow fallback wherever possible: -Base.parent(W::JordanMPOTensor) = (error(); parent(SparseBlockTensorMap(W))) +Base.parent(W::JordanMPOTensor) = (parent(SparseBlockTensorMap(W))) BlockTensorKit.issparse(W::JordanMPOTensor) = true @@ -154,7 +154,8 @@ BlockTensorKit.issparse(W::JordanMPOTensor) = true # ---------- function SparseBlockTensorMap(W::JordanMPOTensor) τ = BraidingTensor{scalartype(W)}(eachspace(W)[1]) - W′ = SparseBlockTensorMap{Union{eltype(W.A),typeof(τ)}}(undef_blocks, space(W)) + W′ = SparseBlockTensorMap{AbstractTensorMap{scalartype(W),spacetype(W),2,2}}(undef_blocks, + space(W)) W′[1, 1, 1, 1] = τ W′[end, 1, 1, end] = τ @@ -252,7 +253,7 @@ end if (i == 1 && j == 1) || (i == size(W, 1) && j == size(W, 4)) throw(ArgumentError("Cannot set BraidingTensor")) elseif i == 1 && j == size(W, 4) - W.D = removeunit(removeunit(v, 1), 4) + W.D[1] = removeunit(removeunit(v, 4), 1) elseif i == 1 W.C[1, 1, j - 1] = removeunit(v, 1) elseif j == size(W, 4) @@ -268,11 +269,15 @@ end # Sparse functionality # -------------------- function BlockTensorKit.nonzero_keys(W::JordanMPOTensor) + nrows = size(W, 1) + ncols = size(W, 4) + + pτ = (CartesianIndex(1, 1, 1, 1), CartesianIndex(nrows, 1, 1, ncols)) + Ia = CartesianIndex(1, 0, 0, 1) pA = [I + Ia for I in nonzero_keys(W.A)] Ib = CartesianIndex(1, 0, 0) - ncols = size(W, 4) pB = [CartesianIndex((I + Ib).I..., ncols) for I in nonzero_keys(W.B)] Ic = CartesianIndex(0, 0, 1) @@ -280,7 +285,6 @@ function BlockTensorKit.nonzero_keys(W::JordanMPOTensor) pD = [CartesianIndex(1, 1, 1, ncols) for I in nonzero_keys(W.D)] - pτ = (CartesianIndex(1, 1, 1, 1), CartesianIndex(1, 1, 1, ncols)) return Iterators.flatten((pτ, pA, pB, pC, pD)) end function BlockTensorKit.nonzero_values(W::JordanMPOTensor) From 86ac51bf93ec08a9f8da61d345ca8a322fab5a54 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Mar 2025 20:17:22 -0400 Subject: [PATCH 09/46] Start simplified implementations --- src/operators/mpohamiltonian.jl | 57 +++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index 61820857c..869cf4a39 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -528,8 +528,6 @@ function InfiniteMPOHamiltonian(lattice′::AbstractArray{<:VectorSpace}, V = virtualsumspaces[site - 1] * lattice[site] ← lattice[site] * virtualsumspaces[site] O = TW(undef, V) - # O[1, 1, 1, 1] = BraidingTensor{E}(eachspace(O)[1, 1, 1, 1]) - # O[end, end, end, end] = BraidingTensor{E}(eachspace(O)[end, end, end, end]) # Fill it for ((key_L, key_R′), o) in zip(nonzero_keys[site], nonzero_opps[site]) @@ -591,9 +589,19 @@ function isidentitylevel(H::InfiniteMPOHamiltonian, i::Int) return (h[i, 1, 1, i] isa BraidingTensor) end end +function isidentitylevel(H::InfiniteMPOHamiltonian{<:JordanMPOTensor}, i::Int) + if i == 1 || i == size(H[1], 1) + return true + else + return all(H.A) do A + return haskey(A, CartesianIndex(i - 1, 1, 1, i - 1)) && + A[i - 1, 1, 1, i - 1] isa BraidingTensor + end + end +end function isemptylevel(H::InfiniteMPOHamiltonian, i::Int) return any(parent(H)) do h - return !(CartesianIndex(i, 1, 1, i) in nonzero_keys(h)) + return !haskey(h, CartesianIndex(i, 1, 1, i)) end end @@ -604,6 +612,17 @@ function Base.convert(::Type{TensorMap}, H::FiniteMPOHamiltonian) return convert(TensorMap, _instantiate_finitempo(L, M, R)) end +function Base.convert(::Type{FiniteMPOHamiltonian{O1}}, + H::FiniteMPOHamiltonian{O2}) where {O1,O2} + O1 === O2 && return H + return FiniteMPOHamiltonian(convert.(O1, parent(H))) +end +function Base.convert(::Type{InfiniteMPOHamiltonian{O1}}, + H::InfiniteMPOHamiltonian{O2}) where {O1,O2} + O1 === O2 && return H + return InfiniteMPOHamiltonian(convert.(O1, parent(H))) +end + function add_physical_charge(H::MPOHamiltonian, charges::AbstractVector{<:Sector}) W = map(add_physical_charge, parent(H), charges) if isfinite(H) @@ -716,6 +735,20 @@ function Base.:+(H₁::MPOH, H₂::MPOH) where {MPOH<:MPOHamiltonian} return H₁ isa FiniteMPOHamiltonian ? FiniteMPOHamiltonian(H) : InfiniteMPOHamiltonian(H) end +function Base.:+(H₁::InfiniteMPOHamiltonian{O}, + H₂::InfiniteMPOHamiltonian{O}) where {O<:JordanMPOTensor} + N = check_length(H₁, H₂) + H = similar(parent(H₁)) + for i in 1:N + A = cat(H₁[i].A, H₂[i].A; dims=(1, 4)) + B = cat(H₁[i].B, H₂[i].B; dims=1) + C = cat(H₁[i].C, H₂[i].C; dims=3) + D = H₁[i].D + H₂[i].D + H[i] = eltype(H)(A, B, C, D) + end + return InfiniteMPOHamiltonian(H) +end + function Base.:+(H::FiniteMPOHamiltonian, λs::AbstractVector{<:Number}) check_length(H, λs) lattice = [physicalspace(H, i) for i in 1:length(H)] @@ -749,6 +782,14 @@ function VectorInterface.scale!(H::InfiniteMPOHamiltonian, λ::Number) end return H end +function VectorInterface.scale!(H::InfiniteMPOHamiltonian{O}, + λ::Number) where {O<:JordanMPOTensor} + for i in 1:length(H) + scale!(H[i].C, λ) + scale!(H[i].D, λ) + end + return H +end function VectorInterface.scale!(H::FiniteMPOHamiltonian, λ::Number) foreach(enumerate(parent(H))) do (i, h) @@ -782,6 +823,16 @@ function VectorInterface.scale!(dst::MPOHamiltonian, src::MPOHamiltonian, return dst end +function VectorInterface.scale!(dst::MPOHamiltonian{<:JordanMPOTensor}, + src::MPOHamiltonian{<:JordanMPOTensor}, λ::Number) + N = check_length(dst, src) + for i in 1:N + scale!(dst[i].C, src[i].C, λ) + scale!(dst[i].D, src[i].D, λ) + end + return dst +end + function Base.:*(H1::MPOHamiltonian, H2::MPOHamiltonian) check_length(H1, H2) Ws = fuse_mul_mpo.(parent(H1), parent(H2)) From 22494b7ddc4e85c746c4ba0f06b7c3bf0c56070b Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 14 Mar 2025 20:17:35 -0400 Subject: [PATCH 10/46] Add support to `force_planar` for testing --- test/setup.jl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/setup.jl b/test/setup.jl index 264df3119..9e0a570c1 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -59,7 +59,16 @@ function force_planar(x::SparseBlockTensorMap) return SparseBlockTensorMap{valtype(data)}(data, force_planar(space(x))) end function force_planar(W::JordanMPOTensor) - return JordanMPOTensor(force_planar(W.A), force_planar(W.B), force_planar(W.C), force_planar(W.D)) + V = force_planar(space(W)) + TW = MPSKit.jordanmpotensortype(eltype(V[1]), scalartype(W)) + dst = TW(undef, V) + + for t in (:A, :B, :C, :D) + for (I, v) in nonzero_pairs(getproperty(W, t)) + getproperty(dst, t)[I] = force_planar(v) + end + end + return dst end force_planar(mpo::MPOHamiltonian) = MPOHamiltonian(map(force_planar, parent(mpo))) force_planar(mpo::MPO) = MPO(map(force_planar, parent(mpo))) From e426c638c6d3edb28afa9e1a5e04653a0a2e8e99 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 22 Mar 2025 16:22:49 -0400 Subject: [PATCH 11/46] Fix derivative --- src/algorithms/derivatives/hamiltonian_derivatives.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index c511047ea..db3dbb914 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -63,7 +63,6 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) @plansor starting[-1 -2; -3 -4] += D[-1; -3 1] * GR[end][-4 1; -2] onsite = missing elseif !ismissing(ending) - error() D = removeunit(W[1, 1, 1, end], 4) @plansor ending[-1 -2; -3 -4] += GL[1][-1 1; -3] * D[1 -2; -4] onsite = missing From 3a05d3accee4a3aad9dcf5f22e141198253835cb Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 22 Mar 2025 16:22:59 -0400 Subject: [PATCH 12/46] remove stray contractcheck --- src/algorithms/derivatives/mpo_derivatives.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index b216445c4..d193fb280 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -82,10 +82,9 @@ function (H::MPO_∂∂AC2{<:MPSBondTensor,Nothing,Nothing,<:MPSBondTensor})(x:: @plansor y[-1 -2; -3 -4] ≔ H.leftenv[-1; 1] * x[1 -2; 2 -4] * H.rightenv[2 -3] end function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::MPOTensor) - @plansor contractcheck = true y[-1 -2; -3 -4] ≔ H.leftenv[-1 7; 6] * x[6 5; 1 3] * - H.operators[1][7 -2; 5 4] * - H.operators[2][4 -4; 3 2] * - H.rightenv[1 2; -3] + @plansor y[-1 -2; -3 -4] ≔ H.leftenv[-1 7; 6] * x[6 5; 1 3] * + H.operators[1][7 -2; 5 4] * H.operators[2][4 -4; 3 2] * + H.rightenv[1 2; -3] end function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::AbstractTensorMap{<:Any,<:Any,3,3}) @plansor y[-1 -2 -3; -4 -5 -6] ≔ H.leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * From 83541253301124da4f3169b0573c858c150464e6 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 22 Mar 2025 16:23:22 -0400 Subject: [PATCH 13/46] Start supporting finite systems --- src/operators/jordanmpotensor.jl | 87 +++++++++++++++++++++----------- src/operators/mpohamiltonian.jl | 66 ++++++++++++++++-------- 2 files changed, 101 insertions(+), 52 deletions(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 5214f6ed1..bfecbbbf1 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -16,17 +16,19 @@ struct JordanMPOTensor{E,S, TB<:AbstractTensorMap{E,S,2,1}, TC<:AbstractTensorMap{E,S,1,2}, TD<:AbstractTensorMap{E,S,1,1}} <: AbstractBlockTensorMap{E,S,2,2} + V::TensorMapSumSpace{S,2,2} A::SparseBlockTensorMap{TA,E,S,2,2,4} B::SparseBlockTensorMap{TB,E,S,2,1,3} C::SparseBlockTensorMap{TC,E,S,1,2,3} D::SparseBlockTensorMap{TD,E,S,1,1,2} - # uninitialized constructor function JordanMPOTensor{E,S,TA,TB,TC,TD}(::UndefInitializer, V::TensorMapSumSpace{S,2,2}) where {E,S,TA,TB, TC,TD} allVs = eachspace(V) + # Note that this is a bit of a hack using end to get the last index: + # it should be 1 or end depending on this being an "edge" tensor or a "bulk" tensor VA = space(allVs[2:(end - 1), 1, 1, 2:(end - 1)]) A = SparseBlockTensorMap{TA}(undef, VA) @@ -39,11 +41,12 @@ struct JordanMPOTensor{E,S, VD = removeunit(removeunit(space(allVs[1, 1, 1, end:end]), 4), 1) D = SparseBlockTensorMap{TD}(undef, VD) - return new{E,S,TA,TB,TC,TD}(A, B, C, D) + return new{E,S,TA,TB,TC,TD}(V, A, B, C, D) end # constructor from data - function JordanMPOTensor{E,S,TA,TB,TC,TD}(A::SparseBlockTensorMap{TA,E,S,2,2}, + function JordanMPOTensor{E,S,TA,TB,TC,TD}(V::TensorMapSumSpace, + A::SparseBlockTensorMap{TA,E,S,2,2}, B::SparseBlockTensorMap{TB,E,S,2,1}, C::SparseBlockTensorMap{TC,E,S,1,2}, D::SparseBlockTensorMap{TD,E,S,1,1}) where {E, @@ -53,23 +56,23 @@ struct JordanMPOTensor{E,S, TC, TD} # TODO: add space and size checks - return new{E,S,TA,TB,TC,TD}(A, B, C, D) + return new{E,S,TA,TB,TC,TD}(V, A, B, C, D) end end -function JordanMPOTensor{E,S}(::UndefInitializer, - V::TensorMapSumSpace{S}) where {E,S} +function JordanMPOTensor{E,S}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E,S} return jordanmpotensortype(S, E)(undef, V) end function JordanMPOTensor{E}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E,S} return JordanMPOTensor{E,S}(undef, V) end -function JordanMPOTensor(A::SparseBlockTensorMap{TA,E,S,2,2}, +function JordanMPOTensor(V::TensorMapSumSpace{S,2,2}, + A::SparseBlockTensorMap{TA,E,S,2,2}, B::SparseBlockTensorMap{TB,E,S,2,1}, C::SparseBlockTensorMap{TC,E,S,1,2}, D::SparseBlockTensorMap{TD,E,S,1,1}) where {E,S,TA,TB,TC,TD} - return JordanMPOTensor{E,S,TA,TB,TC,TD}(A, B, C, D) + return JordanMPOTensor{E,S,TA,TB,TC,TD}(V, A, B, C, D) end function JordanMPOTensor(W::SparseBlockTensorMap{TT,E,S,2,2}) where {TT,E,S} @@ -81,7 +84,8 @@ function JordanMPOTensor(W::SparseBlockTensorMap{TT,E,S,2,2}) where {TT,E,S} C = W[1, 1, 1, 2:(end - 1)] D = W[1, 1, 1, end:end] # ensure still blocktensor to allow for sparse - return JordanMPOTensor(A, + return JordanMPOTensor(space(W), + A, removeunit(B, 4), removeunit(C, 1), removeunit(removeunit(D, 4), 1)) @@ -101,15 +105,9 @@ end # Properties # ---------- -function TensorKit.space(W::JordanMPOTensor) - V_triv = oneunit(spacetype(W.A)) - V_left = BlockTensorKit.oplus(V_triv, left_virtualspace(W.A), V_triv) - V_right = BlockTensorKit.oplus(V_triv, right_virtualspace(W.A), V_triv) - P = physicalspace(W.A) # == physicalspace(W.B) == physicalspace(W.C) == physicalspace(W.D) - return V_left ⊗ P ← P ⊗ V_right -end +TensorKit.space(W::JordanMPOTensor) = W.V -Base.size(W::JordanMPOTensor) = size(W.A) .+ (2, 0, 0, 2) +Base.size(W::JordanMPOTensor) = size(eachspace(W)) Base.size(W::JordanMPOTensor, i::Int) = i ≤ 4 ? size(W)[i] : 1 Base.length(W::JordanMPOTensor) = prod(size(W)) Base.axes(W::JordanMPOTensor) = map(Base.OneTo, size(W)) @@ -127,18 +125,20 @@ Base.eltype(::Type{JordanMPOTensor{E,S,TA,TB,TC,TD}}) where {E,S,TA,TB,TC,TD} = function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) Base.checkbounds(W, I.I...) - I == CartesianIndex(1, 1, 1, 1) || - I == CartesianIndex(size(W, 1), 1, 1, size(W, 4)) && return true + # only has braiding tensors if sizes are large enough + sz = size(W) + (sz[1] > 1 && I == CartesianIndex(1, 1, 1, 1) || + sz[4] > 1 && I == CartesianIndex(sz[1], 1, 1, sz[4])) && return true row, col = I.I[1], I.I[4] - if row == 1 && col == size(W, 4) + if row == 1 && col == sz[4] return haskey(W.D, CartesianIndex(1, 1)) elseif row == 1 return haskey(W.C, CartesianIndex(1, 1, col - 1)) - elseif col == size(W, 4) + elseif col == sz[4] return haskey(W.B, CartesianIndex(row - 1, 1, 1)) - elseif 1 < row < size(W, 1) && 1 < col < size(W, 4) + elseif 1 < row < sz[1] && 1 < col < sz[4] return haskey(W.A, CartesianIndex(row - 1, 1, 1, col - 1)) else return false @@ -156,8 +156,12 @@ function SparseBlockTensorMap(W::JordanMPOTensor) τ = BraidingTensor{scalartype(W)}(eachspace(W)[1]) W′ = SparseBlockTensorMap{AbstractTensorMap{scalartype(W),spacetype(W),2,2}}(undef_blocks, space(W)) - W′[1, 1, 1, 1] = τ - W′[end, 1, 1, end] = τ + if size(W, 1) > 1 + W′[1, 1, 1, 1] = τ + end + if size(W, 4) > 1 + W′[end, 1, 1, end] = τ + end Ia = CartesianIndex(1, 0, 0, 1) for (I, v) in nonzero_pairs(W.A) @@ -192,7 +196,8 @@ end end @inline Base.getindex(W::JordanMPOTensor, I::CartesianIndex{4}) = W[I.I...] @propagate_inbounds function Base.getindex(W::JordanMPOTensor, i::Int, j::Int) - if (i == 1 && j == 1) || (i == size(W, 1) && j == size(W, 4)) + if (size(W, 4) > 1 && i == 1 && j == 1) || + (size(W, 1) > 1 && i == size(W, 1) && j == size(W, 4)) return BraidingTensor{scalartype(W)}(eachspace(W)[1]) elseif i == 1 && j == size(W, 4) return insertrightunit(insertleftunit(only(W.D), 1), 3) @@ -250,21 +255,25 @@ end end @propagate_inbounds function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, i::Int, j::Int) - if (i == 1 && j == 1) || (i == size(W, 1) && j == size(W, 4)) - throw(ArgumentError("Cannot set BraidingTensor")) - elseif i == 1 && j == size(W, 4) + if i == 1 && j == size(W, 4) W.D[1] = removeunit(removeunit(v, 4), 1) - elseif i == 1 + elseif i == 1 && 1 < j < size(W, 4) W.C[1, 1, j - 1] = removeunit(v, 1) - elseif j == size(W, 4) + elseif j == size(W, 4) && 1 < i < size(W, 1) W.B[i - 1, 1, 1] = removeunit(v, 4) elseif 1 < i < size(W, 1) && 1 < j < size(W, 4) W.A[i - 1, 1, 1, j - 1] = v + elseif (size(W, 4) > 1 && i == 1 && j == 1) || + (size(W, 1) > 1 && i == size(W, 1) && j == size(W, 4)) + v isa BraidingTensor || throw(ArgumentError("Cannot set BraidingTensor")) else throw(ArgumentError("Cannot set index ($i, 1, 1, $j)")) end return W end +@inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::Int) + return setindex!(W, v, CartesianIndices(W)[I]) +end # Sparse functionality # -------------------- @@ -298,8 +307,26 @@ function BlockTensorKit.nonzero_length(W::JordanMPOTensor) nonzero_length(W.D) + 2 end +# linalg +# ------ +# do we want this? +function Base.:+(W1::JordanMPOTensor, W2::JordanMPOTensor) + return SparseBlockTensorMap(W1) + SparseBlockTensorMap(W2) +end +function Base.:-(W1::JordanMPOTensor, W2::JordanMPOTensor) + return SparseBlockTensorMap(W1) - SparseBlockTensorMap(W2) +end + # Utility # ------- +# Avoid falling back to `norm(W1 - W2)` which has to convert to SparseBlockTensorMap +function Base.isapprox(W1::JordanMPOTensor, W2::JordanMPOTensor; kwargs...) + return isapprox(W1.A, W2.A; kwargs...) && + isapprox(W1.B, W2.B; kwargs...) && + isapprox(W1.C, W2.C; kwargs...) && + isapprox(W1.D, W2.D; kwargs...) +end + function Base.summary(io::IO, W::JordanMPOTensor) szstring = Base.dims2string(size(W)) TT = eltype(W) diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index 869cf4a39..80a5c699e 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -58,7 +58,7 @@ end FiniteMPOHamiltonian(Ws::Vector{<:Matrix}) Create a `FiniteMPOHamiltonian` from a vector of matrices, such that `Ws[i][j, k]` represents -the the operator at site `i`, left level `j` and right level `k`. Here, the entries can be +the operator at site `i`, left level `j` and right level `k`. Here, the entries can be either `MPOTensor`, `Missing` or `Number`. """ function FiniteMPOHamiltonian(Ws::Vector{<:Matrix}) @@ -380,9 +380,9 @@ function FiniteMPOHamiltonian(lattice::AbstractArray{<:VectorSpace}, E = scalartype(T) S = spacetype(T) - virtualspaces = Vector{SumSpace{S}}(undef, length(lattice) + 1) - virtualspaces[1] = SumSpace(oneunit(S)) - virtualspaces[end] = SumSpace(oneunit(S)) + virtualsumspaces = Vector{SumSpace{S}}(undef, length(lattice) + 1) + virtualsumspaces[1] = SumSpace(fill(oneunit(S), 1)) + virtualsumspaces[end] = SumSpace(fill(oneunit(S), 1)) for i in 1:(length(lattice) - 1) n_channels = maximum(last, nonzero_keys[i]; init=1) + 1 @@ -390,34 +390,28 @@ function FiniteMPOHamiltonian(lattice::AbstractArray{<:VectorSpace}, if n_channels > 2 for ((key_L, key_R), O) in zip(nonzero_keys[i], nonzero_opps[i]) V[key_R == 0 ? end : key_R] = if O isa Number - virtualspaces[i][key_L] + virtualsumspaces[i][key_L] else right_virtualspace(O) end end end - virtualspaces[i + 1] = V + virtualsumspaces[i + 1] = V end - Otype = jordanmpotensortype(S, E) + # construct the tensor + TW = jordanmpotensortype(S, E) Os = map(1:length(lattice)) do site - # Initialize blocktensor - O = Otype(undef, virtualspaces[site] * lattice[site], - lattice[site] * virtualspaces[site + 1]) - fill!(O, zero(E)) - if site != length(lattice) - O[1, 1, 1, 1] = BraidingTensor{E}(eachspace(O)[1, 1, 1, 1]) - end - if site != 1 - O[end, end, end, end] = BraidingTensor{E}(eachspace(O)[end, end, end, end]) - end + V = virtualsumspaces[site] * lattice[site] ← + lattice[site] * virtualsumspaces[site + 1] + O = TW(undef, V) # Fill it - for ((key_L, key_R), o) in zip(nonzero_keys[site], nonzero_opps[site]) - key_R′ = key_R == 0 ? length(virtualspaces[site + 1]) : key_R - O[key_L, 1, 1, key_R′] += if o isa Number + for ((key_L, key_R′), o) in zip(nonzero_keys[site], nonzero_opps[site]) + key_R = key_R′ == 0 ? length(virtualsumspaces[site + 1]) : key_R′ + O[key_L, 1, 1, key_R] += if o isa Number iszero(o) && continue - τ = BraidingTensor{E}(eachspace(O)[key_L, 1, 1, key_R′]) + τ = BraidingTensor{E}(eachspace(O)[key_L, 1, 1, key_R]) isone(o) ? τ : τ * o else o @@ -735,16 +729,44 @@ function Base.:+(H₁::MPOH, H₂::MPOH) where {MPOH<:MPOHamiltonian} return H₁ isa FiniteMPOHamiltonian ? FiniteMPOHamiltonian(H) : InfiniteMPOHamiltonian(H) end +function Base.:+(H₁::FiniteMPOHamiltonian{O}, + H₂::FiniteMPOHamiltonian{O}) where {O<:JordanMPOTensor} + N = check_length(H₁, H₂) + H = similar(parent(H₁)) + Vtriv = oneunit(spacetype(H₁)) + + for i in 1:N + A = cat(H₁[i].A, H₂[i].A; dims=(1, 4)) + B = cat(H₁[i].B, H₂[i].B; dims=1) + C = cat(H₁[i].C, H₂[i].C; dims=3) + D = H₁[i].D + H₂[i].D + + Vleft = i == 1 ? left_virtualspace(H₁, 1) : + BlockTensorKit.oplus(Vtriv, left_virtualspace(A), Vtriv) + Vright = i == N ? right_virtualspace(H₁, N) : + BlockTensorKit.oplus(Vtriv, right_virtualspace(A), Vtriv) + V = Vleft ⊗ physicalspace(A) ← physicalspace(A) ⊗ Vright + + H[i] = eltype(H)(V, A, B, C, D) + end + return FiniteMPOHamiltonian(H) +end function Base.:+(H₁::InfiniteMPOHamiltonian{O}, H₂::InfiniteMPOHamiltonian{O}) where {O<:JordanMPOTensor} N = check_length(H₁, H₂) H = similar(parent(H₁)) + Vtriv = oneunit(spacetype(H₁)) for i in 1:N A = cat(H₁[i].A, H₂[i].A; dims=(1, 4)) B = cat(H₁[i].B, H₂[i].B; dims=1) C = cat(H₁[i].C, H₂[i].C; dims=3) D = H₁[i].D + H₂[i].D - H[i] = eltype(H)(A, B, C, D) + + Vleft = BlockTensorKit.oplus(Vtriv, left_virtualspace(A), Vtriv) + Vright = BlockTensorKit.oplus(Vtriv, right_virtualspace(A), Vtriv) + V = Vleft ⊗ physicalspace(A) ← physicalspace(A) ⊗ Vright + + H[i] = eltype(H)(V, A, B, C, D) end return InfiniteMPOHamiltonian(H) end From cc4f2de2c4e1327e02f84338fa57194f239b8b41 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sat, 22 Mar 2025 18:19:51 -0400 Subject: [PATCH 14/46] First attempt at twosite version --- .../derivatives/hamiltonian_derivatives.jl | 294 +++++++++++++++++- 1 file changed, 283 insertions(+), 11 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index db3dbb914..4feecf529 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -1,5 +1,8 @@ """ - struct JordanMPO_ + JordanMPO_∂∂AC{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{O1,O2,O3} onsite::Union{O1,Missing} @@ -95,6 +98,69 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) A = W[2:(end - 1), 1, 1, 2:(end - 1)] continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) + return JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) +end + +function ∂∂AC(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) + GL = leftenv(envs, site, mps) + GR = rightenv(envs, site, mps) + W = operator[site] + + # 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 (!isfinite(operator) || site < length(operator)) && !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 (!isfinite(operator) || site > 1) && !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)]) + tensor = coalesce(onsite, not_started, finished, starting, ending) ismissing(tensor) && throw(ArgumentError("unable to determine type")) S = spacetype(tensor) @@ -137,15 +203,221 @@ function (H::JordanMPO_∂∂AC)(x::MPSTensor) return y end +""" + JordanMPO_∂∂AC2{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{O1,O2,O3,O4} - onsite_left::Union{O1,Missing} - onsite_right::Union{O1,Missing} - not_started::Union{O1,Missing} - finished::Union{O1,Missing} - start_end::Union{O2,Missing} - starting_left::Union{O3,Missing} - starting_right::Union{O2,Missing} - ending_left::Union{O2,Missing} - ending_right::Union{O3,Missing} - continuing::O4 + 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 +end +function JordanMPO_∂∂AC2(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + tensor = coalesce(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + O1 = tensormaptype(S, 1, 1, M) + O2 = tensormaptype(S, 2, 2, M) + O3 = tensormaptype(S, 3, 3, M) + return JordanMPO_∂∂AC2{O1,O2,O3,typeof(AA)}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) +end + +Base.:*(H::JordanMPO_∂∂AC2, x) = H(x) + +function ∂∂AC2(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) + GL = leftenv(envs, site, mps) + GR = rightenv(envs, site + 1, mps) + W1 = operator[site] + W2 = operator[site + 1] + + # 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 !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 !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: MPO_∂∂AC2 code reuse + optimization + AA = (GL[2:(end - 1)], W1.A, W2.A, GR[2:(end - 1)]) + + return JordanMPO_∂∂AC2(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) +end + +function (H::JordanMPO_∂∂AC2)(x::MPOTensor) + y = zerovector!(similar(x)) + + if !ismissing(H.II) + @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 -4] * H.II[-3; 1] + end + + if !ismissing(H.IC) + @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 2] * H.IC[-4 -3; 2 1] + end + + if !ismissing(H.ID) + @plansor y[-1 -2; -3 -4] += x[-1 -2; -3 1] * H.ID[-4; 1] + end + + if !ismissing(H.CB) + @plansor y[-1 -2; -3 -4] += x[-1 1; -3 2] * H.CB[-2 -4; 1 2] + end + + if !ismissing(H.CA) + @plansor y[-1 -2; -3 -4] += x[-1 1; 3 2] * H.CA[-2 -4 -3; 1 2 3] + end + + if !ismissing(H.AB) + @plansor y[-1 -2; -3 -4] += x[1 2; -3 3] * H.AB[-1 -2 -4; 1 2 3] + end + + if !ismissing(H.BE) + @plansor y[-1 -2; -3 -4] += x[1 2; -3 -4] * H.BE[-1 -2; 1 2] + end + + if !ismissing(H.DE) + @plansor y[-1 -2; -3 -4] += x[-1 1; -3 -4] * H.DE[-2; 1] + end + + if !ismissing(H.EE) + @plansor y[-1 -2; -3 -4] += x[1 -2; -3 -4] * H.EE[-1; 1] + end + + GL, A1, A2, GR = H.AA + if nonzero_length(A1) > 0 && nonzero_length(A2) > 0 + # TODO: there are too many entries here! + @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 From 57cd920d9be79f857fc63ce35bab0258f3ee549c Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 14:59:17 -0400 Subject: [PATCH 15/46] Reorganize derivatives --- src/MPSKit.jl | 2 +- src/algorithms/derivatives/derivatives.jl | 24 +++++++--------- .../derivatives/hamiltonian_derivatives.jl | 28 +++++++++++-------- src/algorithms/derivatives/mpo_derivatives.jl | 23 +++++++++------ 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/MPSKit.jl b/src/MPSKit.jl index 147b7b8ea..b0abeb8e7 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -133,9 +133,9 @@ include("environments/multiple_envs.jl") 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/derivatives.jl") include("algorithms/expval.jl") include("algorithms/toolbox.jl") include("algorithms/grassmann.jl") diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 4bac98c2e..5c5bdc950 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -1,11 +1,8 @@ # Given a state and it's environments, we can act on it -const DerivativeOperator = Union{MPO_∂∂C,MPO_∂∂AC,MPO_∂∂AC2,JordanMPO_∂∂AC} +abstract type DerivativeOperator end # TODO: do we still need this? -(h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv); -(h::MPO_∂∂AC)(x) = ∂AC(x, h.o, h.leftenv, h.rightenv); -(h::MPO_∂∂AC2)(x) = ∂AC2(x, h.o1, h.o2, h.leftenv, h.rightenv); (h::DerivativeOperator)(v, ::Number) = h(v) # draft operator constructors @@ -120,12 +117,9 @@ function c_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) return c_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) end -function ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) - return ∂AC(ϕ.AC[pos], O[pos], leftenv(envs, pos, ψ), rightenv(envs, pos, ψ)) -end -function ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) - return ∂AC(ϕ.AC[pos], nothing, leftenv(envs, pos, ψ), rightenv(envs, pos, ψ)) -end +ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) = ∂∂AC(pos, ψ, O, envs) * ϕ.AC[pos] +ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂AC(pos, ψ, nothing, envs) * ϕ.AC[pos] + function ac_proj(pos::Int, ψ, Oϕs::LazySum, envs) return sum(zip(Oϕs.ops, envs.envs)) do x return ac_proj(pos, ψ, x...) @@ -137,11 +131,11 @@ end function ac2_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂AC2(AC2, O[pos], O[pos + 1], leftenv(envs, pos, ψ), rightenv(envs, pos + 1, ψ)) + return ∂∂AC2(pos, ψ, O, envs) * AC2 end function ac2_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂AC2(AC2, nothing, nothing, leftenv(envs, pos, ψ), rightenv(envs, pos + 1, ψ)) + return ∂∂AC2(pos, ψ, nothing, envs) * AC2 end function ac2_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) return ac2_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) @@ -233,10 +227,12 @@ end function ∂∂AC(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) suboperators = map((op, openv) -> ∂∂AC(pos, mps, op, openv), operator.ops, cache.envs) - return LazySum{Union{MPO_∂∂AC,MultipliedOperator{<:MPO_∂∂AC}}}(suboperators) + elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC,JordanMPO_∂∂AC}} + return LazySum{elT}(suboperators) end function ∂∂AC2(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) suboperators = map((op, openv) -> ∂∂AC2(pos, mps, op, openv), operator.ops, cache.envs) - return LazySum{Union{MPO_∂∂AC2,MultipliedOperator{<:MPO_∂∂AC2}}}(suboperators) + elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC2,JordanMPO_∂∂AC2}} + return LazySum{elT}(suboperators) end diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index 4feecf529..f6d44543c 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -4,7 +4,7 @@ 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{O1,O2,O3} +struct JordanMPO_∂∂AC{O1,O2,O3} <: DerivativeOperator onsite::Union{O1,Missing} not_started::Union{O1,Missing} finished::Union{O1,Missing} @@ -209,7 +209,7 @@ end 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{O1,O2,O3,O4} +struct JordanMPO_∂∂AC2{O1,O2,O3,O4} <: DerivativeOperator II::Union{O1,Missing} # not_started IC::Union{O2,Missing} # starting right ID::Union{O1,Missing} # onsite right @@ -220,16 +220,20 @@ struct JordanMPO_∂∂AC2{O1,O2,O3,O4} BE::Union{O2,Missing} # ending left DE::Union{O1,Missing} # onsite left EE::Union{O1,Missing} # finished -end -function JordanMPO_∂∂AC2(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - tensor = coalesce(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - ismissing(tensor) && throw(ArgumentError("unable to determine type")) - S = spacetype(tensor) - M = storagetype(tensor) - O1 = tensormaptype(S, 1, 1, M) - O2 = tensormaptype(S, 2, 2, M) - O3 = tensormaptype(S, 3, 3, M) - return JordanMPO_∂∂AC2{O1,O2,O3,typeof(AA)}(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + function JordanMPO_∂∂AC2(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + tensor = coalesce(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + 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{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 Base.:*(H::JordanMPO_∂∂AC2, x) = H(x) diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index d193fb280..17c11914b 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -3,11 +3,12 @@ Effective local operator obtained from taking the partial derivative of an MPS-MPO-MPS sandwich. """ -struct MPO_∂∂ACN{L,O<:Tuple,R} +struct MPO_∂∂ACN{L,O<:Tuple,R} <: DerivativeOperator leftenv::L operators::O rightenv::R end +Base.length(H::MPO_∂∂ACN) = length(H.operators) const MPO_∂∂C{L,R} = MPO_∂∂ACN{L,Tuple{},R} MPO_∂∂C(GL, GR) = MPO_∂∂ACN(GL, (), GR) @@ -22,17 +23,18 @@ function ∂∂C(pos::Int, mps, operator, envs) return MPO_∂∂C(leftenv(envs, pos + 1, mps), rightenv(envs, pos, mps)) end function ∂∂AC(pos::Int, mps, operator, envs) - return MPO_∂∂AC(leftenv(envs, pos, mps), operator[pos], rightenv(envs, pos, mps)) + O = isnothing(operator) ? nothing : operator[pos] + return MPO_∂∂AC(leftenv(envs, pos, mps), O, rightenv(envs, pos, mps)) end function ∂∂AC2(pos::Int, mps, operator, envs) - return MPO_∂∂AC2(leftenv(envs, pos, mps), operator[pos], operator[pos + 1], - rightenv(envs, pos + 1, mps)) + O1, O2 = isnothing(operator) ? (nothing, nothing) : (operator[pos], operator[pos + 1]) + return MPO_∂∂AC2(leftenv(envs, pos, mps), O1, O2, rightenv(envs, pos + 1, mps)) end # Multiline for ∂∂_ in (:∂∂C, :∂∂AC, :∂∂AC2) - @eval function $∂∂_(pos::Int, mps, operator::MultilineMPO, envs) - Hs = map(Base.Fix1($∂∂_, pos), mps, operator, envs) + @eval function $∂∂_(site::Int, mps, operator::MultilineMPO, envs) + Hs = [$∂∂_(site, mps[row], operator[row], envs[row]) for row in 1:size(operator, 1)] return Multiline(Hs) end end @@ -54,6 +56,10 @@ end # Actions # ------- +# (h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv); +# (h::MPO_∂∂AC)(x) = ∂AC(x, h.o, h.leftenv, h.rightenv); +# (h::MPO_∂∂AC2)(x) = ∂AC2(x, h.o1, h.o2, h.leftenv, h.rightenv); + Base.:*(H::MPO_∂∂ACN, x) = H(x) # ∂C @@ -94,6 +100,7 @@ function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x:: end # Multiline -function (H::Multiline{<:MPO_∂∂ACN})(x::Vector) - return circshift!(broadcast(parent(H), x), 1) +function (H::Multiline{<:DerivativeOperator})(x::AbstractVector) + return [H[row - 1] * x[mod1(row - 1, end)] for row in 1:size(H, 1)] end +Base.:*(H::Multiline{<:DerivativeOperator}, x::AbstractVector) = H(x) From b0b4e3c3e033f5a3607bb9ac653cf2949b712b9a Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 14:59:30 -0400 Subject: [PATCH 16/46] Improve jordanmpotensor --- src/operators/jordanmpotensor.jl | 50 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index bfecbbbf1..ef269aa8e 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -190,12 +190,11 @@ end return Base.checkbounds_indices(Bool, axes(W), I) end -@inline function Base.getindex(W::JordanMPOTensor, I::Vararg{Int,4}) - @assert I[2] == I[3] == 1 - return W[I[1], I[4]] -end @inline Base.getindex(W::JordanMPOTensor, I::CartesianIndex{4}) = W[I.I...] -@propagate_inbounds function Base.getindex(W::JordanMPOTensor, i::Int, j::Int) +@propagate_inbounds function Base.getindex(W::JordanMPOTensor, I::Vararg{Int,4}) + @assert I[2] == I[3] == 1 + i = I[1] + j = I[4] if (size(W, 4) > 1 && i == 1 && j == 1) || (size(W, 1) > 1 && i == size(W, 1) && j == size(W, 4)) return BraidingTensor{scalartype(W)}(eachspace(W)[1]) @@ -234,7 +233,11 @@ end V = space(eachspace(W)[inds...]) dst = similar(W, V) - Rsrc = CartesianIndices(W)[inds...] + # prevent discarding of singleton dimensions + inds2 = map(inds) do ind + return ind isa Int ? (ind:ind) : ind + end + Rsrc = CartesianIndices(W)[inds2...] Rdst = CartesianIndices(dst) for I in nonzero_keys(W) @@ -245,16 +248,14 @@ end return dst end -@inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::Vararg{Int,4}) - @assert I[2] == I[3] == 1 - W[I[1], I[4]] = v - return W -end @inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::CartesianIndex{4}) return setindex!(W, v, I.I...) end -@propagate_inbounds function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, i::Int, - j::Int) +@propagate_inbounds function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, + I::Vararg{Int,4}) + @assert I[2] == I[3] == 1 + i = I[1] + j = I[4] if i == 1 && j == size(W, 4) W.D[1] = removeunit(removeunit(v, 4), 1) elseif i == 1 && 1 < j < size(W, 4) @@ -280,21 +281,30 @@ end function BlockTensorKit.nonzero_keys(W::JordanMPOTensor) nrows = size(W, 1) ncols = size(W, 4) - - pτ = (CartesianIndex(1, 1, 1, 1), CartesianIndex(nrows, 1, 1, ncols)) + p = CartesianIndex{4}[] + ncols > 1 && push!(p, CartesianIndex(1, 1, 1, 1)) + nrows > 1 && push!(p, CartesianIndex(nrows, 1, 1, ncols)) Ia = CartesianIndex(1, 0, 0, 1) - pA = [I + Ia for I in nonzero_keys(W.A)] + for I in nonzero_keys(W.A) + push!(p, I + Ia) + end Ib = CartesianIndex(1, 0, 0) - pB = [CartesianIndex((I + Ib).I..., ncols) for I in nonzero_keys(W.B)] + for I in nonzero_keys(W.B) + push!(p, CartesianIndex((I + Ib).I..., ncols)) + end Ic = CartesianIndex(0, 0, 1) - pC = [CartesianIndex(1, (I + Ic).I...) for I in nonzero_keys(W.C)] + for I in nonzero_keys(W.C) + push!(p, CartesianIndex(1, (I + Ic).I...)) + end - pD = [CartesianIndex(1, 1, 1, ncols) for I in nonzero_keys(W.D)] + for I in nonzero_keys(W.D) + push!(p, CartesianIndex(1, 1, 1, ncols)) + end - return Iterators.flatten((pτ, pA, pB, pC, pD)) + return p end function BlockTensorKit.nonzero_values(W::JordanMPOTensor) return Iterators.map(I -> W[I], nonzero_keys(W)) From 960ef702f9cc280f31467adf42d7a0e4ea40f0b8 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 14:59:45 -0400 Subject: [PATCH 17/46] various fixes --- src/operators/mpohamiltonian.jl | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index 80a5c699e..0b88aa3a2 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -577,6 +577,14 @@ function Base.getproperty(H::MPOHamiltonian, sym::Symbol) end end +# function Base.getproperty(H::MPOHamiltonian{<:JordanMPOTensor}, sym::Symbol) +# if sym in (:A, :B, :C, :D) +# return map(Base.Fix2(Base.getproperty, sym), parent(H)) +# else +# return getfield(H, sym) +# end +# end + function isidentitylevel(H::InfiniteMPOHamiltonian, i::Int) isemptylevel(H, i) && return false return all(parent(H)) do h @@ -804,7 +812,7 @@ function VectorInterface.scale!(H::InfiniteMPOHamiltonian, λ::Number) end return H end -function VectorInterface.scale!(H::InfiniteMPOHamiltonian{O}, +function VectorInterface.scale!(H::MPOHamiltonian{O}, λ::Number) where {O<:JordanMPOTensor} for i in 1:length(H) scale!(H[i].C, λ) @@ -812,6 +820,17 @@ function VectorInterface.scale!(H::InfiniteMPOHamiltonian{O}, end return H end +function VectorInterface.scale!(Hdst::MPOHamiltonian{<:JordanMPOTensor}, + Hsrc::MPOHamiltonian{<:JordanMPOTensor}, λ::Number) + N = check_length(Hdst, Hsrc) + for i in 1:N + scale!(Hdst[i].C, Hsrc[i].C, λ) + scale!(Hdst[i].D, Hsrc[i].D, λ) + copy!(Hdst[i].A, Hsrc[i].A) + copy!(Hdst[i].B, Hsrc[i].B) + end + return Hdst +end function VectorInterface.scale!(H::FiniteMPOHamiltonian, λ::Number) foreach(enumerate(parent(H))) do (i, h) @@ -845,16 +864,6 @@ function VectorInterface.scale!(dst::MPOHamiltonian, src::MPOHamiltonian, return dst end -function VectorInterface.scale!(dst::MPOHamiltonian{<:JordanMPOTensor}, - src::MPOHamiltonian{<:JordanMPOTensor}, λ::Number) - N = check_length(dst, src) - for i in 1:N - scale!(dst[i].C, src[i].C, λ) - scale!(dst[i].D, src[i].D, λ) - end - return dst -end - function Base.:*(H1::MPOHamiltonian, H2::MPOHamiltonian) check_length(H1, H2) Ws = fuse_mul_mpo.(parent(H1), parent(H2)) From a3f38e449d0e29cd05f561ad31503f7adc8098f0 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 15:05:45 -0400 Subject: [PATCH 18/46] make warnings toggleable --- src/algorithms/fixedpoint.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/algorithms/fixedpoint.jl b/src/algorithms/fixedpoint.jl index 37023256f..81e7c69d9 100644 --- a/src/algorithms/fixedpoint.jl +++ b/src/algorithms/fixedpoint.jl @@ -11,7 +11,7 @@ function fixedpoint(A, x₀, which::Symbol, alg::Lanczos) vals, vecs, info = eigsolve(A, x₀, 1, which, alg) if info.converged == 0 - @warn "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" + @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" end return vals[1], vecs[1] @@ -21,10 +21,10 @@ function fixedpoint(A, x₀, which::Symbol, alg::Arnoldi) TT, vecs, vals, info = schursolve(A, x₀, 1, which, alg) if info.converged == 0 - @warn "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" + @warnv 1 "fixedpoint not converged after $(info.numiter) iterations: normres = $(info.normres[1])" end if size(TT, 2) > 1 && TT[2, 1] != 0 - @warn "non-unique fixedpoint detected" + @warnv 1 "non-unique fixedpoint detected" end return vals[1], vecs[1] From 4e8031ff90bf7d3d46ecb94e79153245f0116187 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 15:06:05 -0400 Subject: [PATCH 19/46] signature fixes --- .../derivatives/hamiltonian_derivatives.jl | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index f6d44543c..a231e954e 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -11,16 +11,20 @@ struct JordanMPO_∂∂AC{O1,O2,O3} <: DerivativeOperator starting::Union{O2,Missing} ending::Union{O2,Missing} continuing::O3 -end -function JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) - tensor = coalesce(onsite, not_started, finished, starting, ending) - ismissing(tensor) && throw(ArgumentError("unable to determine type")) - S = spacetype(tensor) - M = storagetype(tensor) - O1 = tensormaptype(S, 1, 1, M) - O2 = tensormaptype(S, 2, 2, M) - return JordanMPO_∂∂AC{O1,O2,typeof(continuing)}(onsite, not_started, finished, starting, - ending, continuing) + function JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) + tensor = coalesce(onsite, not_started, finished, starting, ending) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + 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{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 Base.:*(H::JordanMPO_∂∂AC, x) = H(x) From d8e1fbdf52b1abbad2b0711cbeb4533cfa1fe7ea Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 15:48:54 -0400 Subject: [PATCH 20/46] small fixes --- src/algorithms/approximate/idmrg.jl | 4 +--- src/algorithms/derivatives/derivatives.jl | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/algorithms/approximate/idmrg.jl b/src/algorithms/approximate/idmrg.jl index 472215629..91f71d456 100644 --- a/src/algorithms/approximate/idmrg.jl +++ b/src/algorithms/approximate/idmrg.jl @@ -90,9 +90,7 @@ function approximate!(ψ::MultilineMPS, toapprox::Tuple{<:MultilineMPO,<:Multili for row in 1:size(ψ, 1) # TODO: also write this as ac2_proj? AC2 = ϕ.AL[row, col] * _transpose_tail(ϕ.AC[row, col + 1]) - AC2′ = ∂AC2(AC2, O[row, col], O[row, col + 1], - leftenv(envs[row], col, ψ[row]), - rightenv(envs[row], col, ψ[row])) + AC2′ = ∂∂AC2(row, col, ψ, O, envs) * AC2 al, c, ar, = tsvd!(AC2′; trunc=alg.trscheme, alg=TensorKit.SVD()) normalize!(c) diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 5c5bdc950..62366edf8 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -102,12 +102,8 @@ end # end # downproject for approximate -function c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) - return ∂C(ϕ.C[pos], leftenv(envs, pos + 1, ψ), rightenv(envs, pos, ψ)) -end -function c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) - return ∂C(ϕ.C[pos], leftenv(envs, pos + 1, ψ), rightenv(envs, pos, ψ)) -end +c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) = ∂∂C(pos, ψ, operator, envs) * ϕ.C[pos] +c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂C(pos, ψ, nothing, envs) * ϕ.C[pos] function c_proj(pos::Int, ψ, Oϕs::LazySum, envs) return sum(zip(Oϕs.ops, envs.envs)) do x return c_proj(pos, ψ, x...) From df56a1d5e3ae50fc4868df5f233f1d16a4660b5d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Sun, 23 Mar 2025 16:21:54 -0400 Subject: [PATCH 21/46] Fix periodic boundary --- src/algorithms/toolbox.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/algorithms/toolbox.jl b/src/algorithms/toolbox.jl index 95582b66f..be174d48e 100644 --- a/src/algorithms/toolbox.jl +++ b/src/algorithms/toolbox.jl @@ -363,6 +363,8 @@ function periodic_boundary_conditions(H::InfiniteMPOHamiltonian, L=length(H)) F_right = fusers[site + 1][k, i, l] j′ = indmap[j, i, l] k′ = indmap[k, i, l] + ((j′ == 1 && k′ == 1) || + (j′ == size(output[site], 1) && k′ == size(output[site], 4))) && continue @plansor o[-1 -2; -3 -4] := h[1 2; -3 6] * F_left[-1; 1 3 5] * conj(F_right[-4; 6 7 8]) * @@ -377,6 +379,8 @@ function periodic_boundary_conditions(H::InfiniteMPOHamiltonian, L=length(H)) F_right = fusers[site + 1][i, l, k] j′ = indmap[i, l, j] k′ = indmap[i, l, k] + ((j′ == 1 && k′ == 1) || + (j′ == size(output[site], 1) && k′ == size(output[site], 4))) && continue @plansor o[-1 -2; -3 -4] := h[1 -2; 3 6] * F_left[-1; 4 2 1] * conj(F_right[-4; 8 7 6]) * @@ -393,6 +397,7 @@ function periodic_boundary_conditions(H::InfiniteMPOHamiltonian, L=length(H)) if j == 1 F_right = fusers[2][k, end, end] j′ = indmap[k, chi, chi] + j′ == 1 && continue @plansor o[-1 -2; -3 -4] := h[-1 -2; -3 2] * conj(F_right[-4; 2 3 3]) output[1][1, 1, 1, j′] = o end @@ -401,13 +406,13 @@ function periodic_boundary_conditions(H::InfiniteMPOHamiltonian, L=length(H)) if 1 < j < chi F_right = fusers[2][1, j, k] j′ = indmap[1, j, k] + j′ == 1 && continue @plansor o[-1 -2; -3 -4] := h[4 -2; 3 1] * conj(F_right[-4; 6 2 1]) * τ[5 4; 2 3] * τ[-3 -1; 6 5] output[1][1, 1, 1, j′] = o end end - output[1][1, 1, 1, 1] = BraidingTensor{scalartype(H)}(eachspace(output[1])[1]) # ender for (I, h) in nonzero_pairs(H[end]) @@ -415,6 +420,7 @@ function periodic_boundary_conditions(H::InfiniteMPOHamiltonian, L=length(H)) if k > 1 F_left = fusers[end][j, k, chi] k′ = indmap[j, k, chi] + k′ == size(output[end], 1) && continue @plansor o[-1 -2; -3 -4] := F_left[-1; 1 2 6] * h[1 3; -3 4] * τ[3 2; 4 5] * τ[5 6; -4 -2] output[end][k′, 1, 1, 1] = o From 96f88e11cd5107737adddb1df1ca45feb2f3ff10 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 24 Mar 2025 10:26:02 -0400 Subject: [PATCH 22/46] Make SVD algorithm accessible and trscheme mandatory --- src/algorithms/approximate/idmrg.jl | 4 +- src/algorithms/changebonds/optimalexpand.jl | 13 ++++-- src/algorithms/changebonds/randexpand.jl | 9 ++-- src/algorithms/changebonds/svdcut.jl | 13 ++++-- src/algorithms/changebonds/vumpssvd.jl | 41 ++++++++--------- src/algorithms/groundstate/dmrg.jl | 51 +++++++++++++-------- src/algorithms/groundstate/idmrg.jl | 11 +++-- src/algorithms/timestep/tdvp.jl | 11 +++-- src/utility/defaults.jl | 4 ++ 9 files changed, 93 insertions(+), 64 deletions(-) diff --git a/src/algorithms/approximate/idmrg.jl b/src/algorithms/approximate/idmrg.jl index 91f71d456..3d9ad6fb2 100644 --- a/src/algorithms/approximate/idmrg.jl +++ b/src/algorithms/approximate/idmrg.jl @@ -72,7 +72,7 @@ function approximate!(ψ::MultilineMPS, toapprox::Tuple{<:MultilineMPO,<:Multili for col in 1:size(ψ, 2) for row in 1:size(ψ, 1) AC2′ = ac2_proj(row, col, ψ, toapprox, envs) - al, c, ar, = tsvd!(AC2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(AC2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AL[row + 1, col] = al @@ -91,7 +91,7 @@ function approximate!(ψ::MultilineMPS, toapprox::Tuple{<:MultilineMPO,<:Multili # TODO: also write this as ac2_proj? AC2 = ϕ.AL[row, col] * _transpose_tail(ϕ.AC[row, col + 1]) AC2′ = ∂∂AC2(row, col, ψ, O, envs) * AC2 - al, c, ar, = tsvd!(AC2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(AC2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AL[row + 1, col] = al diff --git a/src/algorithms/changebonds/optimalexpand.jl b/src/algorithms/changebonds/optimalexpand.jl index 4a917afa8..1c273472c 100644 --- a/src/algorithms/changebonds/optimalexpand.jl +++ b/src/algorithms/changebonds/optimalexpand.jl @@ -9,9 +9,12 @@ dominant contributions of a two-site updated MPS tensor, orthogonal to the origi $(TYPEDFIELDS) """ -@kwdef struct OptimalExpand <: Algorithm +@kwdef struct OptimalExpand{S} <: Algorithm + "algorithm used for the singular value decomposition" + alg_svd::S = Defaults.alg_svd() + "algorithm used for truncating the expanded space" - trscheme::TruncationScheme = truncdim(1) + trscheme::TruncationScheme end function changebonds(ψ::InfiniteMPS, H::InfiniteMPOHamiltonian, alg::OptimalExpand, @@ -28,7 +31,7 @@ function changebonds(ψ::InfiniteMPS, H::InfiniteMPOHamiltonian, alg::OptimalExp VL = leftnull(ψ.AL[i]) VR = rightnull!(_transpose_tail(ψ.AR[i + 1])) intermediate = adjoint(VL) * AC2 * adjoint(VR) - U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=SVD()) + U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=alg.alg_svd) AL′[i] = VL * U AR′[i + 1] = V * VR @@ -54,7 +57,7 @@ function changebonds(ψ::MultilineMPS, H, alg::OptimalExpand, envs=environments( VL = leftnull(ψ.AL[i, j]) VR = rightnull!(_transpose_tail(ψ.AR[i, j + 1])) intermediate = adjoint(VL) * AC2 * adjoint(VR) - U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=SVD()) + U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=alg.alg_svd) AL′[i, j] = VL * U AR′[i, j + 1] = V * VR @@ -85,7 +88,7 @@ function changebonds!(ψ::AbstractFiniteMPS, H, alg::OptimalExpand, envs=environ #Use this nullspaces and SVD decomposition to determine the optimal expansion space intermediate = adjoint(NL) * AC2 * adjoint(NR) - _, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=SVD()) + _, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=alg.alg_svd) ar_re = V * NR ar_le = zerovector!(similar(ar_re, codomain(ψ.AC[i]) ← space(V, 1))) diff --git a/src/algorithms/changebonds/randexpand.jl b/src/algorithms/changebonds/randexpand.jl index c2c5f7cd9..3883334af 100644 --- a/src/algorithms/changebonds/randexpand.jl +++ b/src/algorithms/changebonds/randexpand.jl @@ -9,7 +9,10 @@ two-site MPS tensor, which is made orthogonal to the existing state. $(TYPEDFIELDS) """ -@kwdef struct RandExpand <: Algorithm +@kwdef struct RandExpand{S} <: Algorithm + "algorithm used for the singular value decomposition" + alg_svd::S = Defaults.alg_svd() + "algorithm used for [truncation](@extref TensorKit.tsvd] the expanded space" trscheme::TruncationScheme = truncdim(1) end @@ -26,7 +29,7 @@ function changebonds(ψ::InfiniteMPS, alg::RandExpand) VL = leftnull(ψ.AL[i]) VR = rightnull!(_transpose_tail(ψ.AR[i + 1])) intermediate = adjoint(VL) * AC2 * adjoint(VR) - U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=SVD()) + U, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=alg.alg_svd) AL′[i] = VL * U AR′[i + 1] = V * VR @@ -50,7 +53,7 @@ function changebonds!(ψ::AbstractFiniteMPS, alg::RandExpand) #Use this nullspaces and SVD decomposition to determine the optimal expansion space intermediate = adjoint(NL) * AC2 * adjoint(NR) - _, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=SVD()) + _, _, V, = tsvd!(intermediate; trunc=alg.trscheme, alg=alg.alg_svd) ar_re = V * NR ar_le = zerovector!(similar(ar_re, codomain(ψ.AC[i]) ← space(V, 1))) diff --git a/src/algorithms/changebonds/svdcut.jl b/src/algorithms/changebonds/svdcut.jl index 330b7ef06..3d7c7ab79 100644 --- a/src/algorithms/changebonds/svdcut.jl +++ b/src/algorithms/changebonds/svdcut.jl @@ -7,7 +7,10 @@ An algorithm that uses truncated SVD to change the bond dimension of a ψ. $(TYPEDFIELDS) """ -@kwdef struct SvdCut <: Algorithm +@kwdef struct SvdCut{S} <: Algorithm + "algorithm used for the singular value decomposition" + alg_svd::S = Defaults.alg_svd() + "algorithm used for [truncation][@extref TensorKit.tsvd] of the gauge tensors" trscheme::TruncationScheme = notrunc() end @@ -17,7 +20,7 @@ function changebonds(ψ::AbstractFiniteMPS, alg::SvdCut; kwargs...) end function changebonds!(ψ::AbstractFiniteMPS, alg::SvdCut; normalize::Bool=true) for i in (length(ψ) - 1):-1:1 - U, S, V, = tsvd(ψ.C[i]; trunc=alg.trscheme, alg=TensorKit.SVD()) + U, S, V, = tsvd(ψ.C[i]; trunc=alg.trscheme, alg=alg.alg_svd) AL′ = ψ.AL[i] * U ψ.AC[i] = (AL′, complex(S)) AR′ = _transpose_front(V * _transpose_tail(ψ.AR[i + 1])) @@ -41,7 +44,7 @@ function changebonds!(mpo::FiniteMPO, alg::SvdCut) O_left = transpose(mpo[1], ((3, 1, 2), (4,))) local O_right for i in 2:length(mpo) - U, S, V, = tsvd!(O_left; trunc=alg.trscheme, alg=TensorKit.SVD()) + U, S, V, = tsvd!(O_left; trunc=alg.trscheme, alg=alg.alg_svd) @inbounds mpo[i - 1] = transpose(U, ((2, 3), (1, 4))) if i < length(mpo) @plansor O_left[-3 -1 -2; -4] := S[-1; 1] * V[1; 2] * mpo[i][2 -2; -3 -4] @@ -52,7 +55,7 @@ function changebonds!(mpo::FiniteMPO, alg::SvdCut) # right to left for i in (length(mpo) - 1):-1:1 - U, S, V, = tsvd!(O_right; trunc=alg.trscheme, alg=TensorKit.SVD()) + U, S, V, = tsvd!(O_right; trunc=alg.trscheme, alg=alg.alg_svd) @inbounds mpo[i + 1] = transpose(V, ((1, 4), (2, 3))) if i > 1 @plansor O_right[-1; -3 -4 -2] := mpo[i][-1 -2; -3 2] * U[2; 1] * S[1; -4] @@ -81,7 +84,7 @@ function changebonds(ψ::InfiniteMPS, alg::SvdCut) ncr = ψ.C[1] for i in 1:length(ψ) - U, ncr, = tsvd(ψ.C[i]; trunc=alg.trscheme, alg=TensorKit.SVD()) + U, ncr, = tsvd(ψ.C[i]; trunc=alg.trscheme, alg=alg.alg_svd) copied[i] = copied[i] * U copied[i + 1] = _transpose_front(U' * _transpose_tail(copied[i + 1])) end diff --git a/src/algorithms/changebonds/vumpssvd.jl b/src/algorithms/changebonds/vumpssvd.jl index 83f45837d..d9e2e4da7 100644 --- a/src/algorithms/changebonds/vumpssvd.jl +++ b/src/algorithms/changebonds/vumpssvd.jl @@ -8,12 +8,17 @@ An algorithm that uses a two-site update step to change the bond dimension of a $(TYPEDFIELDS) """ @kwdef struct VUMPSSvdCut <: Algorithm - "tolerance for gauging algorithm" - tol_gauge = Defaults.tolgauge - "tolerance for the eigenvalue solver" - tol_eigenval = Defaults.tol + "algorithm used for gauging the `InfiniteMPS`" + alg_gauge = Defaults.alg_gauge(; dynamic_tols=false) + + "algorithm used for the eigenvalue solvers" + alg_eigsolve = Defaults.alg_eigsolve(; dynamic_tols=false) + + "algorithm used for the singular value decomposition" + alg_svd = Defaults.alg_svd() + "algorithm used for [truncation][@extref TensorKit.tsvd] of the two-site update" - trscheme::TruncationScheme = notrunc() + trscheme::TruncationScheme end function changebonds_1(state::InfiniteMPS, H, alg::VUMPSSvdCut, @@ -31,11 +36,12 @@ function changebonds_1(state::InfiniteMPS, H, alg::VUMPSSvdCut, # collapse back to 1 site if D2 != D1 - (nstate, nenvs) = changebonds(nstate, nH, - SvdCut(; trscheme=truncspace(infimum(D1, D2))), nenvs) + cut_alg = SvdCut(; alg.alg_svd, trscheme=truncspace(infimum(D1, D2))) + nstate, nenvs = changebonds(nstate, nH, cut_alg, nenvs) end - collapsed = InfiniteMPS([nstate.AL[1]], nstate.C[1]; tol=alg.tol_gauge) + collapsed = InfiniteMPS([nstate.AL[1]], nstate.C[1]; alg.alg_gauge.tol, + alg.alg_gauge.maxiter) recalculate!(envs, collapsed, H, collapsed) return collapsed, envs @@ -47,17 +53,13 @@ function changebonds_n(state::InfiniteMPS, H, alg::VUMPSSvdCut, envs=environment @plansor AC2[-1 -2; -3 -4] := state.AC[loc][-1 -2; 1] * state.AR[loc + 1][1 -4; -3] h_ac2 = ∂∂AC2(loc, state, H, envs) - (vals, vecs, _) = eigsolve(h_ac2, AC2, 1, :SR; tol=alg.tol_eigenval, - ishermitian=false) - nAC2 = vecs[1] + _, nAC2 = fixedpoint(h_ac2, AC2, :SR, alg.alg_eigsolve) h_c = ∂∂C(loc + 1, state, H, envs) - (vals, vecs, _) = eigsolve(h_c, state.C[loc + 1], 1, :SR; tol=alg.tol_eigenval, - ishermitian=false) - nC2 = vecs[1] + _, nC2 = fixedpoint(h_c, state.C[loc + 1], :SR, alg.alg_eigsolve) #svd ac2, get new AL1 and S,V ---> AC - (AL1, S, V, eps) = tsvd(nAC2; trunc=alg.trscheme, alg=TensorKit.SVD()) + AL1, S, V, eps = tsvd!(nAC2; trunc=alg.trscheme, alg=alg.alg_svd) @plansor AC[-1 -2; -3] := S[-1; 1] * V[1; -3 -2] meps = max(eps, meps) @@ -72,16 +74,13 @@ function changebonds_n(state::InfiniteMPS, H, alg::VUMPSSvdCut, envs=environment copied = copy(state.AL) copied[loc] = AL1 copied[loc + 1] = AL2 - state = InfiniteMPS(copied; tol=alg.tol_gauge) + state = InfiniteMPS(copied; alg.alg_gauge.tol, alg.alg_gauge.maxiter) recalculate!(envs, state, H, state) end return state, envs end function changebonds(state::InfiniteMPS, H, alg::VUMPSSvdCut, envs=environments(state, H)) - if (length(state) == 1) - return changebonds_1(state, H, alg, envs) - else - return changebonds_n(state, H, alg, envs) - end + return length(state) == 1 ? changebonds_1(state, H, alg, envs) : + changebonds_n(state, H, alg, envs) end diff --git a/src/algorithms/groundstate/dmrg.jl b/src/algorithms/groundstate/dmrg.jl index 0ea686faa..30c4278e7 100644 --- a/src/algorithms/groundstate/dmrg.jl +++ b/src/algorithms/groundstate/dmrg.jl @@ -10,20 +10,24 @@ $(TYPEDFIELDS) struct DMRG{A,F} <: Algorithm "tolerance for convergence criterium" tol::Float64 + "maximal amount of iterations" maxiter::Int - "callback function applied after each iteration, of signature `finalize(iter, ψ, H, envs) -> ψ, envs`" - finalize::F + "setting for how much information is displayed" verbosity::Int + "algorithm used for the eigenvalue solvers" - eigalg::A + alg_eigsolve::A + + "callback function applied after each iteration, of signature `finalize(iter, ψ, H, envs) -> ψ, envs`" + finalize::F end -function DMRG(; tol=Defaults.tol, maxiter=Defaults.maxiter, eigalg=(;), +function DMRG(; tol=Defaults.tol, maxiter=Defaults.maxiter, alg_eigsolve=(;), verbosity=Defaults.verbosity, finalize=Defaults._finalize) - eigalg′ = eigalg isa NamedTuple ? Defaults.alg_eigsolve(; eigalg...) : eigalg - return DMRG{typeof(eigalg′),typeof(finalize)}(tol, maxiter, finalize, verbosity, - eigalg′) + alg_eigsolve′ = alg_eigsolve isa NamedTuple ? Defaults.alg_eigsolve(; alg_eigsolve...) : + alg_eigsolve + return DMRG(tol, maxiter, verbosity, alg_eigsolve′, finalize) end function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG, envs=environments(ψ, H)) @@ -70,28 +74,35 @@ Two-site DMRG algorithm for finding the dominant eigenvector. $(TYPEDFIELDS) """ -struct DMRG2{A,F} <: Algorithm +struct DMRG2{A,S,F} <: Algorithm "tolerance for convergence criterium" tol::Float64 + "maximal amount of iterations" maxiter::Int - "callback function applied after each iteration, of signature `finalize(iter, ψ, H, envs) -> ψ, envs`" - finalize::F + "setting for how much information is displayed" verbosity::Int "algorithm used for the eigenvalue solvers" - eigalg::A + alg_eigsolve::A + + "algorithm used for the singular value decomposition" + alg_svd::S + "algorithm used for [truncation](@extref TensorKit.tsvd) of the two-site update" trscheme::TruncationScheme + + "callback function applied after each iteration, of signature `finalize(iter, ψ, H, envs) -> ψ, envs`" + finalize::F end # TODO: find better default truncation -function DMRG2(; tol=Defaults.tol, maxiter=Defaults.maxiter, eigalg=(;), - trscheme=truncerr(1e-6), verbosity=Defaults.verbosity, +function DMRG2(; tol=Defaults.tol, maxiter=Defaults.maxiter, verbosity=Defaults.verbosity, + alg_eigsolve=(;), alg_svd=Defaults.alg_svd(), trscheme, finalize=Defaults._finalize) - eigalg′ = eigalg isa NamedTuple ? Defaults.alg_eigsolve(; eigalg...) : eigalg - return DMRG2{typeof(eigalg′),typeof(finalize)}(tol, maxiter, finalize, verbosity, - eigalg′, trscheme) + alg_eigsolve′ = alg_eigsolve isa NamedTuple ? Defaults.alg_eigsolve(; alg_eigsolve...) : + alg_eigsolve + return DMRG2(tol, maxiter, verbosity, alg_eigsolve′, alg_svd, trscheme, finalize) end function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs=environments(ψ, H)) @@ -110,7 +121,7 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs=environmen _, newA2center = fixedpoint(∂∂AC2(pos, ψ, H, envs), ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(newA2center; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(newA2center; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) v = @plansor ac2[1 2; 3 4] * conj(al[1 2; 5]) * conj(c[5; 6]) * conj(ar[6; 3 4]) @@ -126,7 +137,7 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs=environmen _, newA2center = fixedpoint(∂∂AC2(pos, ψ, H, envs), ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(newA2center; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(newA2center; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) v = @plansor ac2[1 2; 3 4] * conj(al[1 2; 5]) * conj(c[5; 6]) * conj(ar[6; 3 4]) @@ -153,6 +164,6 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs=environmen return ψ, envs, ϵ end -function find_groundstate(ψ, H, alg::Union{DMRG,DMRG2}, envs...) - return find_groundstate!(copy(ψ), H, alg, envs...) +function find_groundstate(ψ, H, alg::Union{DMRG,DMRG2}, envs...; kwargs...) + return find_groundstate!(copy(ψ), H, alg, envs...; kwargs...) end diff --git a/src/algorithms/groundstate/idmrg.jl b/src/algorithms/groundstate/idmrg.jl index ca8b0ea9b..55abc0656 100644 --- a/src/algorithms/groundstate/idmrg.jl +++ b/src/algorithms/groundstate/idmrg.jl @@ -101,6 +101,9 @@ $(TYPEDFIELDS) "algorithm used for the eigenvalue solvers" alg_eigsolve::A = Defaults.alg_eigsolve() + "algorithm used for the singular value decomposition" + alg_svd::S = Defaults.alg_svd() + "algorithm used for [truncation](@extref TensorKit.tsvd) of the two-site update" trscheme::TruncationScheme = truncerr(1e-6) end @@ -125,7 +128,7 @@ function find_groundstate(ost::InfiniteMPS, H, alg::IDMRG2, envs=environments(os h_ac2 = ∂∂AC2(pos, ψ, H, envs) _, ac2′ = fixedpoint(h_ac2, ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AL[pos] = al @@ -143,7 +146,7 @@ function find_groundstate(ost::InfiniteMPS, H, alg::IDMRG2, envs=environments(os h_ac2 = ∂∂AC2(0, ψ, H, envs) _, ac2′ = fixedpoint(h_ac2, ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AC[end] = al * c @@ -165,7 +168,7 @@ function find_groundstate(ost::InfiniteMPS, H, alg::IDMRG2, envs=environments(os h_ac2 = ∂∂AC2(pos, ψ, H, envs) _, ac2′ = fixedpoint(h_ac2, ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AL[pos] = al @@ -183,7 +186,7 @@ function find_groundstate(ost::InfiniteMPS, H, alg::IDMRG2, envs=environments(os inv(ψ.C[end])[2; 3] * ψ.AC[1][3 -4; -3] h_ac2 = ∂∂AC2(0, ψ, H, envs) _, ac2′ = fixedpoint(h_ac2, ac2, :SR, alg_eigsolve) - al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=TensorKit.SVD()) + al, c, ar, = tsvd!(ac2′; trunc=alg.trscheme, alg=alg.alg_svd) normalize!(c) ψ.AR[end] = _transpose_front(inv(ψ.C[end - 1]) * _transpose_tail(al * c)) diff --git a/src/algorithms/timestep/tdvp.jl b/src/algorithms/timestep/tdvp.jl index 88fee9298..12c81e9fa 100644 --- a/src/algorithms/timestep/tdvp.jl +++ b/src/algorithms/timestep/tdvp.jl @@ -114,7 +114,7 @@ $(TYPEDFIELDS) * [Haegeman et al. Phys. Rev. Lett. 107 (2011)](@cite haegeman2011) """ -@kwdef struct TDVP2{A,F} <: Algorithm +@kwdef struct TDVP2{A,S,F} <: Algorithm "algorithm used in the exponential solvers" integrator::A = Defaults.alg_expsolve() @@ -124,8 +124,11 @@ $(TYPEDFIELDS) "maximal amount of iterations for gauging algorithm" gaugemaxiter::Int = Defaults.maxiter + "algorithm used for the singular value decomposition" + alg_svd::S = Defaults.alg_svd() + "algorithm used for truncation of the two-site update" - trscheme::TruncationScheme = truncerr(1e-3) + trscheme::TruncationScheme "callback function applied after each iteration, of signature `finalize(iter, ψ, H, envs) -> ψ, envs`" finalize::F = Defaults._finalize @@ -140,7 +143,7 @@ function timestep!(ψ::AbstractFiniteMPS, H, t::Number, dt::Number, alg::TDVP2, h_ac2 = ∂∂AC2(i, ψ, H, envs) nac2 = integrate(h_ac2, ac2, t, dt / 2, alg.integrator) - nal, nc, nar = tsvd!(nac2; trunc=alg.trscheme, alg=TensorKit.SVD()) + nal, nc, nar = tsvd!(nac2; trunc=alg.trscheme, alg=alg.alg_svd) ψ.AC[i] = (nal, complex(nc)) ψ.AC[i + 1] = (complex(nc), _transpose_front(nar)) @@ -156,7 +159,7 @@ function timestep!(ψ::AbstractFiniteMPS, H, t::Number, dt::Number, alg::TDVP2, h_ac2 = ∂∂AC2(i - 1, ψ, H, envs) nac2 = integrate(h_ac2, ac2, t + dt / 2, dt / 2, alg.integrator) - nal, nc, nar = tsvd!(nac2; trunc=alg.trscheme, alg=TensorKit.SVD()) + nal, nc, nar = tsvd!(nac2; trunc=alg.trscheme, alg=alg.alg_svd) ψ.AC[i - 1] = (nal, complex(nc)) ψ.AC[i] = (complex(nc), _transpose_front(nar)) diff --git a/src/utility/defaults.jl b/src/utility/defaults.jl index ecd74e0fb..71b97a97d 100644 --- a/src/utility/defaults.jl +++ b/src/utility/defaults.jl @@ -8,6 +8,7 @@ module Defaults import KrylovKit: GMRES, Arnoldi, Lanczos using OhMyThreads using ..MPSKit: DynamicTol +using TensorKit: TensorKit const VERBOSE_NONE = 0 const VERBOSE_WARN = 1 @@ -53,6 +54,8 @@ function alg_eigsolve(; ishermitian=true, tol=tol, maxiter=maxiter, verbosity=0, return dynamic_tols ? DynamicTol(alg, tol_min, tol_max, tol_factor) : alg end +alg_svd() = TensorKit.SDD() + # TODO: make verbosity and maxiter actually do something function alg_environments(; tol=tol, maxiter=maxiter, verbosity=0, dynamic_tols=dynamic_tols, tol_min=tol_min, tol_max=tol_max, @@ -60,6 +63,7 @@ function alg_environments(; tol=tol, maxiter=maxiter, verbosity=0, alg = (; tol, maxiter, verbosity) return dynamic_tols ? DynamicTol(alg, tol_min, tol_max, tol_factor) : alg end + function alg_expsolve(; tol=tol, maxiter=maxiter, verbosity=0, ishermitian=true, krylovdim=krylovdim) return ishermitian ? Lanczos(; tol, maxiter, krylovdim, verbosity) : From 1b2e6297885e488c3057ed7bb0f12b3763735893 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 24 Mar 2025 10:26:13 -0400 Subject: [PATCH 23/46] small improvement hamiltonian derivative --- .../derivatives/hamiltonian_derivatives.jl | 2 +- src/algorithms/groundstate/dmrg.jl | 4 +- src/algorithms/groundstate/idmrg.jl | 4 +- src/algorithms/groundstate/vumps.jl | 70 ++++--------------- 4 files changed, 18 insertions(+), 62 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index a231e954e..e6dc3f07e 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -382,7 +382,7 @@ function ∂∂AC2(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, end function (H::JordanMPO_∂∂AC2)(x::MPOTensor) - y = zerovector!(similar(x)) + y = zerovector(x) if !ismissing(H.II) @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 -4] * H.II[-3; 1] diff --git a/src/algorithms/groundstate/dmrg.jl b/src/algorithms/groundstate/dmrg.jl index 30c4278e7..9ab21e079 100644 --- a/src/algorithms/groundstate/dmrg.jl +++ b/src/algorithms/groundstate/dmrg.jl @@ -38,7 +38,7 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG, envs=environment LoggingExtras.withlevel(; alg.verbosity) do @infov 2 loginit!(log, ϵ, expectation_value(ψ, H, envs)) for iter in 1:(alg.maxiter) - alg_eigsolve = updatetol(alg.eigalg, iter, ϵ) + alg_eigsolve = updatetol(alg.alg_eigsolve, iter, ϵ) zerovector!(ϵs) for pos in [1:(length(ψ) - 1); length(ψ):-1:2] @@ -112,7 +112,7 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs=environmen LoggingExtras.withlevel(; alg.verbosity) do for iter in 1:(alg.maxiter) - alg_eigsolve = updatetol(alg.eigalg, iter, ϵ) + alg_eigsolve = updatetol(alg.alg_eigsolve, iter, ϵ) zerovector!(ϵs) # left to right sweep diff --git a/src/algorithms/groundstate/idmrg.jl b/src/algorithms/groundstate/idmrg.jl index 55abc0656..551632720 100644 --- a/src/algorithms/groundstate/idmrg.jl +++ b/src/algorithms/groundstate/idmrg.jl @@ -85,7 +85,7 @@ Two-site infinite DMRG algorithm for finding the dominant eigenvector. $(TYPEDFIELDS) """ -@kwdef struct IDMRG2{A} <: Algorithm +@kwdef struct IDMRG2{A,S} <: Algorithm "tolerance for convergence criterium" tol::Float64 = Defaults.tol @@ -105,7 +105,7 @@ $(TYPEDFIELDS) alg_svd::S = Defaults.alg_svd() "algorithm used for [truncation](@extref TensorKit.tsvd) of the two-site update" - trscheme::TruncationScheme = truncerr(1e-6) + trscheme::TruncationScheme end function find_groundstate(ost::InfiniteMPS, H, alg::IDMRG2, envs=environments(ost, H)) diff --git a/src/algorithms/groundstate/vumps.jl b/src/algorithms/groundstate/vumps.jl index 31a9a7352..7903951cf 100644 --- a/src/algorithms/groundstate/vumps.jl +++ b/src/algorithms/groundstate/vumps.jl @@ -81,63 +81,19 @@ function dominant_eigsolve(operator, mps, alg::VUMPS, envs=environments(mps, ope end end -function Base.iterate(it::IterativeSolver{<:VUMPS}, state=it.state) - ACs = localupdate_step!(it, state) - mps = gauge_step!(it, state, ACs) - envs = envs_step!(it, state, mps) - - # finalizer step - mps, envs = it.finalize(state.iter, mps, state.operator, envs)::typeof((mps, envs)) - - # error criterion - ϵ = calc_galerkin(mps, state.operator, mps, envs) - - # update state - it.state = VUMPSState(mps, state.operator, envs, state.iter + 1, ϵ, state.which) - - return (mps, envs, ϵ), it.state -end - -function localupdate_step!(it::IterativeSolver{<:VUMPS}, state, - scheduler=Defaults.scheduler[]) - alg_eigsolve = updatetol(it.alg_eigsolve, state.iter, state.ϵ) - alg_orth = QRpos() - - mps = state.mps - eachsite = 1:length(mps) - src_Cs = mps isa Multiline ? eachcol(mps.C) : mps.C - src_ACs = mps isa Multiline ? eachcol(mps.AC) : mps.AC - ACs = similar(mps.AC) - dst_ACs = mps isa Multiline ? eachcol(ACs) : ACs - - tforeach(eachsite, src_ACs, src_Cs; scheduler) do site, AC₀, C₀ - dst_ACs[site] = _localupdate_vumps_step!(site, mps, state.operator, state.envs, - AC₀, C₀; parallel=false, alg_orth, - state.which, alg_eigsolve) - return nothing - end - - return ACs -end - -function _localupdate_vumps_step!(site, mps, operator, envs, AC₀, C₀; - parallel::Bool=false, alg_orth=QRpos(), - alg_eigsolve=Defaults.eigsolver, which) - if !parallel - _, AC = fixedpoint(∂∂AC(site, mps, operator, envs), AC₀, which, alg_eigsolve) - _, C = fixedpoint(∂∂C(site, mps, operator, envs), C₀, which, alg_eigsolve) - return regauge!(AC, C; alg=alg_orth) - end - - local AC, C - @sync begin - @spawn begin - _, AC = fixedpoint(∂∂AC(site, mps, operator, envs), - AC₀, which, alg_eigsolve) - end - @spawn begin - _, C = fixedpoint(∂∂C(site, mps, operator, envs), - C₀, which, alg_eigsolve) +function _vumps_localupdate(loc, ψ, H, envs, alg_eigsolve, factalg=QRpos()) + local AC′, C′ + if Defaults.scheduler[] isa SerialScheduler + _, AC′ = fixedpoint(∂∂AC(loc, ψ, H, envs), ψ.AC[loc], :SR, alg_eigsolve) + _, C′ = fixedpoint(∂∂C(loc, ψ, H, envs), ψ.C[loc], :SR, alg_eigsolve) + else + @sync begin + Threads.@spawn begin + _, AC′ = fixedpoint(∂∂AC(loc, ψ, H, envs), ψ.AC[loc], :SR, alg_eigsolve) + end + Threads.@spawn begin + _, C′ = fixedpoint(∂∂C(loc, ψ, H, envs), ψ.C[loc], :SR, alg_eigsolve) + end end end return regauge!(AC, C; alg=alg_orth) From b1c5742e26828fc7e783f4249a6c5b887b245b48 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 24 Mar 2025 10:52:50 -0400 Subject: [PATCH 24/46] Fix bad merge --- src/algorithms/groundstate/vumps.jl | 70 +++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/algorithms/groundstate/vumps.jl b/src/algorithms/groundstate/vumps.jl index 7903951cf..31a9a7352 100644 --- a/src/algorithms/groundstate/vumps.jl +++ b/src/algorithms/groundstate/vumps.jl @@ -81,19 +81,63 @@ function dominant_eigsolve(operator, mps, alg::VUMPS, envs=environments(mps, ope end end -function _vumps_localupdate(loc, ψ, H, envs, alg_eigsolve, factalg=QRpos()) - local AC′, C′ - if Defaults.scheduler[] isa SerialScheduler - _, AC′ = fixedpoint(∂∂AC(loc, ψ, H, envs), ψ.AC[loc], :SR, alg_eigsolve) - _, C′ = fixedpoint(∂∂C(loc, ψ, H, envs), ψ.C[loc], :SR, alg_eigsolve) - else - @sync begin - Threads.@spawn begin - _, AC′ = fixedpoint(∂∂AC(loc, ψ, H, envs), ψ.AC[loc], :SR, alg_eigsolve) - end - Threads.@spawn begin - _, C′ = fixedpoint(∂∂C(loc, ψ, H, envs), ψ.C[loc], :SR, alg_eigsolve) - end +function Base.iterate(it::IterativeSolver{<:VUMPS}, state=it.state) + ACs = localupdate_step!(it, state) + mps = gauge_step!(it, state, ACs) + envs = envs_step!(it, state, mps) + + # finalizer step + mps, envs = it.finalize(state.iter, mps, state.operator, envs)::typeof((mps, envs)) + + # error criterion + ϵ = calc_galerkin(mps, state.operator, mps, envs) + + # update state + it.state = VUMPSState(mps, state.operator, envs, state.iter + 1, ϵ, state.which) + + return (mps, envs, ϵ), it.state +end + +function localupdate_step!(it::IterativeSolver{<:VUMPS}, state, + scheduler=Defaults.scheduler[]) + alg_eigsolve = updatetol(it.alg_eigsolve, state.iter, state.ϵ) + alg_orth = QRpos() + + mps = state.mps + eachsite = 1:length(mps) + src_Cs = mps isa Multiline ? eachcol(mps.C) : mps.C + src_ACs = mps isa Multiline ? eachcol(mps.AC) : mps.AC + ACs = similar(mps.AC) + dst_ACs = mps isa Multiline ? eachcol(ACs) : ACs + + tforeach(eachsite, src_ACs, src_Cs; scheduler) do site, AC₀, C₀ + dst_ACs[site] = _localupdate_vumps_step!(site, mps, state.operator, state.envs, + AC₀, C₀; parallel=false, alg_orth, + state.which, alg_eigsolve) + return nothing + end + + return ACs +end + +function _localupdate_vumps_step!(site, mps, operator, envs, AC₀, C₀; + parallel::Bool=false, alg_orth=QRpos(), + alg_eigsolve=Defaults.eigsolver, which) + if !parallel + _, AC = fixedpoint(∂∂AC(site, mps, operator, envs), AC₀, which, alg_eigsolve) + _, C = fixedpoint(∂∂C(site, mps, operator, envs), C₀, which, alg_eigsolve) + return regauge!(AC, C; alg=alg_orth) + end + + local AC, C + @sync begin + @spawn begin + _, AC = fixedpoint(∂∂AC(site, mps, operator, envs), + AC₀, which, alg_eigsolve) + end + @spawn begin + _, C = fixedpoint(∂∂C(site, mps, operator, envs), + C₀, which, alg_eigsolve) end end return regauge!(AC, C; alg=alg_orth) From c5a47d712b364e35f615d3d99cbf0469457a325d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 24 Mar 2025 10:58:25 -0400 Subject: [PATCH 25/46] Add required kwarg in test --- test/algorithms.jl | 4 ++-- test/states.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/algorithms.jl b/test/algorithms.jl index dcf05e883..4c01a572c 100644 --- a/test/algorithms.jl +++ b/test/algorithms.jl @@ -322,7 +322,7 @@ end @testset "timestep" verbose = true begin dt = 0.1 - algs = [TDVP(), TDVP2()] + algs = [TDVP(), TDVP2(; trscheme=truncdim(10))] L = 10 H = force_planar(heisenberg_XXX(; spin=1 // 2, L)) @@ -387,7 +387,7 @@ end @testset "time_evolve" verbose = true begin t_span = 0:0.1:0.1 - algs = [TDVP(), TDVP2()] + algs = [TDVP(), TDVP2(; trscheme=truncdim(10))] L = 10 H = force_planar(heisenberg_XXX(; spin=1 // 2, L)) diff --git a/test/states.jl b/test/states.jl index 4a7f1fee3..5c694da01 100644 --- a/test/states.jl +++ b/test/states.jl @@ -176,7 +176,7 @@ end @test real(e2) ≤ real(e1) - window, envs = timestep(window, ham, 0.1, 0.0, TDVP2(), envs) + window, envs = timestep(window, ham, 0.1, 0.0, TDVP2(; trscheme=truncdim(20)), envs) window, envs = timestep(window, ham, 0.1, 0.0, TDVP(), envs) e3 = expectation_value(window, (1, 2) => O) From 5a51625a41dcd73dc24907a60dd9415f172e1be5 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 26 Mar 2025 18:11:00 -0400 Subject: [PATCH 26/46] Fix `nonzero_length` --- src/operators/jordanmpotensor.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index ef269aa8e..79aff661a 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -314,7 +314,7 @@ function BlockTensorKit.nonzero_pairs(W::JordanMPOTensor) end function BlockTensorKit.nonzero_length(W::JordanMPOTensor) return nonzero_length(W.A) + nonzero_length(W.B) + nonzero_length(W.C) + - nonzero_length(W.D) + 2 + nonzero_length(W.D) + Int(size(W, 1) > 1) + Int(size(W, 4) > 1) end # linalg From 92b56d33da0926c043e79c5b2692bc8d51395c23 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 27 Mar 2025 16:06:16 -0400 Subject: [PATCH 27/46] restrict `ham_derivatives` types --- .../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 e6dc3f07e..b79833a26 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -28,8 +28,10 @@ struct JordanMPO_∂∂AC{O1,O2,O3} <: DerivativeOperator end Base.:*(H::JordanMPO_∂∂AC, x) = H(x) +const _HAM_MPS_TYPES = Union{FiniteMPS{<:MPSTensor},WindowMPS{<:MPSTensor}, + InfiniteMPS{<:MPSTensor}} -function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) +function ∂∂AC(pos::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian, envs) GL = leftenv(envs, pos, mps) GR = rightenv(envs, pos, mps) W = operator[pos] @@ -105,7 +107,8 @@ function ∂∂AC(pos::Int, mps, operator::MPOHamiltonian, envs) return JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) end -function ∂∂AC(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) +function ∂∂AC(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, + envs) GL = leftenv(envs, site, mps) GR = rightenv(envs, site, mps) W = operator[site] @@ -177,7 +180,7 @@ function ∂∂AC(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, e end function (H::JordanMPO_∂∂AC)(x::MPSTensor) - y = zerovector!(similar(x)) + y = zerovector(x) if !ismissing(H.onsite) @plansor y[-1 -2; -3] += x[-1 1; -3] * H.onsite[-2; 1] @@ -242,7 +245,8 @@ end Base.:*(H::JordanMPO_∂∂AC2, x) = H(x) -function ∂∂AC2(site::Int, mps, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) +function ∂∂AC2(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, + envs) GL = leftenv(envs, site, mps) GR = rightenv(envs, site + 1, mps) W1 = operator[site] From f6696b8e454b24155562618e6a4bf5fb40886759 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 28 Mar 2025 08:48:14 -0400 Subject: [PATCH 28/46] Reorganize derivatives --- src/MPSKit.jl | 1 + src/algorithms/derivatives/derivatives.jl | 405 ++++++++++-------- .../derivatives/hamiltonian_derivatives.jl | 232 +++------- src/algorithms/derivatives/mpo_derivatives.jl | 62 +-- .../derivatives/projection_derivatives.jl | 73 ++++ 5 files changed, 353 insertions(+), 420 deletions(-) create mode 100644 src/algorithms/derivatives/projection_derivatives.jl diff --git a/src/MPSKit.jl b/src/MPSKit.jl index b0abeb8e7..83647881f 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -136,6 +136,7 @@ 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") include("algorithms/grassmann.jl") diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 62366edf8..a1bca8b34 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -1,195 +1,249 @@ # Given a state and it's environments, we can act on it +""" + DerivativeOperator +Abstract supertype for derivative operators acting on MPS. These operators are used to represent +the effective local operators obtained from taking the partial derivative of an MPS-MPO-MPS sandwich. +""" abstract type DerivativeOperator end -# TODO: do we still need this? +Base.:*(h::DerivativeOperator, v) = h(v) (h::DerivativeOperator)(v, ::Number) = h(v) -# draft operator constructors -# function ∂∂C(pos::Int, mps, operator, envs) -# return MPO_∂∂C(leftenv(envs, pos + 1, mps), rightenv(envs, pos, mps)) -# end -# function ∂∂C(row::Int, col::Int, mps, operator::MultilineMPO, envs) -# return ∂∂C(col, mps[row], operator[row], envs[row]) -# end - -# function ∂∂AC(pos::Int, mps, operator, envs) -# return MPO_∂∂AC(operator[pos], leftenv(envs, pos, mps), rightenv(envs, pos, mps)) -# end -function ∂∂AC(row::Int, col::Int, mps, operator::MultilineMPO, envs) - return ∂∂AC(col, mps[row], operator[row], envs[row]) -end -# function ∂∂AC(col::Int, mps, operator::MultilineMPO, envs) -# return MPO_∂∂AC(operator[:, col], leftenv(envs, col, mps), rightenv(envs, col, mps)) -# end - -# function ∂∂AC2(pos::Int, mps, operator, envs) -# return MPO_∂∂AC2(operator[pos], operator[pos + 1], leftenv(envs, pos, mps), -# rightenv(envs, pos + 1, mps)) -# end -# function ∂∂AC2(col::Int, mps, operator::MultilineMPO, envs) -# return MPO_∂∂AC2(operator[:, col], operator[:, col + 1], leftenv(envs, col, mps), -# rightenv(envs, col + 1, mps)) -# end -function ∂∂AC2(row::Int, col::Int, mps, operator::MultilineMPO, envs::MultilineEnvironments) - return ∂∂AC2(col, mps[row], operator[row], envs[row]) -end +@doc """ + ∂∂C(site::Int, mps, operator, envs) + ∂∂C(row::Int, col::Int, mps, operator, envs) -# allow calling them with CartesianIndices -∂∂C(pos::CartesianIndex, mps, operator, envs) = ∂∂C(Tuple(pos)..., mps, operator, envs) -∂∂AC(pos::CartesianIndex, mps, operator, envs) = ∂∂AC(Tuple(pos)..., mps, operator, envs) -∂∂AC2(pos::CartesianIndex, mps, operator, envs) = ∂∂AC2(Tuple(pos)..., mps, operator, envs) +Effective zero-site local operator acting at `site`. -# function ∂AC(x::MPSTensor{S}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, -# rightenv::MPSTensor{S})::typeof(x) where {S} -# @plansor y[-1 -2; -3] := leftenv[-1 5; 4] * x[4 2; 1] * operator[5 -2; 2 3] * -# rightenv[1 3; -3] -# return y isa BlockTensorMap ? only(y) : y -# end -# function ∂AC(x::MPSTensor{S}, operator::Number, leftenv::MPSTensor{S}, -# rightenv::MPSTensor{S})::typeof(x) where {S} -# @plansor y[-1 -2; -3] := operator * (leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * -# rightenv[1 7; -3]) -# end -# function ∂AC(x::GenericMPSTensor{S,3}, operator::MPOTensor{S}, leftenv::MPSTensor{S}, -# rightenv::MPSTensor{S})::typeof(x) where {S} -# @plansor y[-1 -2 -3; -4] ≔ leftenv[-1 7; 6] * x[6 4 2; 1] * operator[7 -2; 4 5] * -# τ[5 -3; 2 3] * rightenv[1 3; -4] -# end - -# mpo multiline -# function ∂AC(x::Vector, opp, leftenv, rightenv) -# return circshift(map(∂AC, x, opp, leftenv, rightenv), 1) -# end - -# function ∂AC(x::MPSTensor, ::Nothing, leftenv, rightenv) -# return _transpose_front(leftenv * _transpose_tail(x * rightenv)) -# end - -# function ∂AC2(x::MPOTensor, operator1::MPOTensor, operator2::MPOTensor, leftenv, rightenv) -# @plansor toret[-1 -2; -3 -4] := leftenv[-1 7; 6] * x[6 5; 1 3] * -# operator1[7 -2; 5 4] * -# operator2[4 -4; 3 2] * -# rightenv[1 2; -3] -# return toret isa BlockTensorMap ? only(toret) : toret -# end -# function ∂AC2(x::MPOTensor, ::Nothing, ::Nothing, leftenv, rightenv) -# @plansor y[-1 -2; -3 -4] := x[1 -2; 2 -4] * leftenv[-1; 1] * rightenv[2; -3] -# end -# function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, -# operator2::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor)::typeof(x) -# @plansor y[-1 -2 -3; -4 -5 -6] ≔ leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * -# rightenv[1 3; -4] * -# operator1[11 -2; 8 9] * τ[9 -3; 6 7] * -# operator2[7 -6; 4 5] * τ[5 -5; 2 3] -# end - -# function ∂AC2(x::Vector, opp1, opp2, leftenv, rightenv) -# return circshift(map(∂AC2, x, opp1, opp2, leftenv, rightenv), 1) -# end - -# function ∂C(x::MPSBondTensor, leftenv::MPSTensor, rightenv::MPSTensor) -# @plansor y[-1; -2] := leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] -# return y isa BlockTensorMap ? only(y) : y -# end - -# function ∂C(x::MPSBondTensor, leftenv::MPSBondTensor, rightenv::MPSBondTensor) -# @plansor toret[-1; -2] := leftenv[-1; 1] * x[1; 2] * rightenv[2; -2] -# end - -# function ∂C(x::Vector, leftenv, rightenv) -# return circshift(map(t -> ∂C(t...), zip(x, leftenv, rightenv)), 1) -# end - -# downproject for approximate -c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) = ∂∂C(pos, ψ, operator, envs) * ϕ.C[pos] -c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂C(pos, ψ, nothing, envs) * ϕ.C[pos] -function c_proj(pos::Int, ψ, Oϕs::LazySum, envs) - return sum(zip(Oϕs.ops, envs.envs)) do x - return c_proj(pos, ψ, x...) - end -end -function c_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return c_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) -end - -ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) = ∂∂AC(pos, ψ, O, envs) * ϕ.AC[pos] -ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂AC(pos, ψ, nothing, envs) * ϕ.AC[pos] - -function ac_proj(pos::Int, ψ, Oϕs::LazySum, envs) - return sum(zip(Oϕs.ops, envs.envs)) do x - return ac_proj(pos, ψ, x...) - end -end -function ac_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return ac_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) -end - -function ac2_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) - AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂∂AC2(pos, ψ, O, envs) * AC2 -end -function ac2_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) - AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂∂AC2(pos, ψ, nothing, envs) * AC2 -end -function ac2_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return ac2_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) -end +``` + ┌─ ─┐ + │ │ +┌┴┐ ┌┴┐ +│ ├───┤ │ +└┬┘ └┬┘ + │ │ + └─ ─┘ +``` + +See also [`∂C`](@ref). +""" ∂∂C +∂∂C(pos::CartesianIndex, mps, operator, envs) = ∂∂C(Tuple(pos)..., mps, operator, envs) +function ∂∂C(row::Int, col::Int, mps::MultilineMPS, operator::MultilineMPO, envs) + return ∂∂C(col, mps[row], operator[row], envs[row]) +end +function ∂∂C(site::Int, mps, operator::MultilineMPO, envs) + return Multiline([∂∂C(row, site, mps, operator, envs) for row in 1:size(operator, 1)]) +end +function ∂∂C(pos::Int, mps, operator::MultipliedOperator, cache) + return MultipliedOperator(∂∂C(pos, mps, operator.op, cache), operator.f) +end function ∂∂C(pos::Int, mps, operator::LinearCombination, cache) return LinearCombination(broadcast((h, e) -> ∂∂C(pos, mps, h, e), operator.opps, cache.envs), operator.coeffs) end +function ∂∂C(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) + suboperators = map((op, openv) -> ∂∂C(pos, mps, op, openv), operator.ops, cache.envs) + return LazySum{Union{MPO_∂∂C,MultipliedOperator{<:MPO_∂∂C}}}(suboperators) +end + +@doc """ + ∂C(x, leftenv, rightenv) + +Application of the effective zero-site local operator on a local tensor `x`. + +``` + ┌─┐ + ┌─┤ ├─┐ + │ └─┘ │ +┌┴┐ ┌┴┐ +│ ├───┤ │ +└┬┘ └┬┘ + │ │ + └─ ─┘ +``` + +See also [`∂∂C`](@ref). +""" ∂C + +function ∂C(x::MPSBondTensor, leftenv::MPSBondTensor, rightenv::MPSBondTensor) + @plansor y[-1; -2] ≔ leftenv[-1; 1] * x[1; 2] * rightenv[2; -2] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function ∂C(x::MPSBondTensor, leftenv::MPSTensor, rightenv::MPSTensor) + @plansor y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] + return y isa AbstractBlockTensorMap ? only(y) : y +end +@doc """ + ∂∂AC(site::Int, mps, operator, envs) + ∂∂AC(row::Int, col::Int, mps, operator, envs) + +Effective one-site local operator acting at `site`. + +``` + ┌─── ───┐ + │ │ │ +┌┴┐ ┌─┴─┐ ┌┴┐ +│ ├─┤ ├─┤ │ +└┬┘ └─┬─┘ └┬┘ + │ │ │ + └─── ───┘ +``` + +See also [`∂AC`](@ref). +""" ∂∂AC +∂∂AC(pos::CartesianIndex, mps, operator, envs) = ∂∂AC(Tuple(pos)..., mps, operator, envs) +function ∂∂AC(row::Int, col::Int, mps::MultilineMPS, operator::MultilineMPO, envs) + return ∂∂AC(col, mps[row], operator[row], envs[row]) +end +function ∂∂AC(site::Int, mps, operator::MultilineMPO, envs) + return Multiline([∂∂AC(row, site, mps, operator, envs) for row in 1:size(operator, 1)]) +end +function ∂∂AC(pos::Int, mps, operator::MultipliedOperator, cache) + return MultipliedOperator(∂∂AC(pos, mps, operator.op, cache), operator.f) +end function ∂∂AC(pos::Int, mps, operator::LinearCombination, cache) return LinearCombination(broadcast((h, e) -> ∂∂AC(pos, mps, h, e), operator.opps, cache.envs), operator.coeffs) end +function ∂∂AC(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) + suboperators = map((op, openv) -> ∂∂AC(pos, mps, op, openv), operator.ops, cache.envs) + elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC,JordanMPO_∂∂AC}} + return LazySum{elT}(suboperators) +end + +@doc """ + ∂AC(x, operator, leftenv, rightenv) + +Application of the effective one-site local operator on a local tensor `x`. + +``` + ┌───┐ + ┌──┤ ├──┐ + │ └─┬─┘ │ +┌┴┐ ┌─┴─┐ ┌┴┐ +│ ├─┤ ├─┤ │ +└┬┘ └─┬─┘ └┬┘ + │ │ │ + └── ──┘ +``` + +See also [`∂∂AC`](@ref). +""" ∂AC + +function ∂AC(x::MPSTensor, operator::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor) + @plansor y[-1 -2; -3] := leftenv[-1 5; 4] * x[4 2; 1] * operator[5 -2; 2 3] * + rightenv[1 3; -3] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function ∂AC(x::MPSTensor, operator::Number, leftenv::MPSTensor, rightenv::MPSTensor) + @plansor y[-1 -2; -3] := operator * (leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * + rightenv[1 7; -3]) + return y isa AbstractBlockTensorMap ? only(y) : y +end +function ∂AC(x::MPSTensor, ::Nothing, leftenv::MPSBondTensor, rightenv::MPSBondTensor) + @plansor y[-1 -2; -3] := leftenv[-1; 2] * x[2 -2; 1] * rightenv[1; -3] +end +function ∂AC(x::GenericMPSTensor{<:Any,3}, operator::MPOTensor, + leftenv::MPSTensor, rightenv::MPSTensor) + @plansor y[-1 -2 -3; -4] ≔ leftenv[-1 7; 6] * x[6 4 2; 1] * operator[7 -2; 4 5] * + τ[5 -3; 2 3] * rightenv[1 3; -4] + return y isa AbstractBlockTensorMap ? only(y) : y +end + +@doc """ + ∂∂AC2(site::Int, mps, operator, envs) + ∂∂AC2(row::Int, col::Int, mps, operator, envs) +Effective two-site local operator acting at `site`. + +``` + ┌── ──┐ + │ │ │ │ +┌┴┐┌─┴─┐┌─┴─┐┌┴┐ +│ ├┤ ├┤ ├┤ │ +└┬┘└─┬─┘└─┬─┘└┬┘ + │ │ │ │ + └── ──┘ +``` + +See also [`∂AC2`](@ref). +""" ∂∂AC2 + +∂∂AC2(pos::CartesianIndex, mps, operator, envs) = ∂∂AC2(Tuple(pos)..., mps, operator, envs) +function ∂∂AC2(row::Int, col::Int, mps::MultilineMPS, operator::MultilineMPO, envs) + return ∂∂AC2(col, mps[row], operator[row], envs[row]) +end +function ∂∂AC2(site::Int, mps, operator::MultilineMPO, envs) + return Multiline([∂∂AC2(row, site, mps, operator, envs) for row in 1:size(operator, 1)]) +end +function ∂∂AC2(pos::Int, mps, operator::MultipliedOperator, cache) + return MultipliedOperator(∂∂AC2(pos, mps, operator.op, cache), operator.f) +end function ∂∂AC2(pos::Int, mps, operator::LinearCombination, cache) return LinearCombination(broadcast((h, e) -> ∂∂AC2(pos, mps, h, e), operator.opps, cache.envs), operator.coeffs) end - -struct AC_EffProj{A,L} - a1::A - le::L - re::L -end -struct AC2_EffProj{A,L} - a1::A - a2::A - le::L - re::L +function ∂∂AC2(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) + suboperators = map((op, openv) -> ∂∂AC2(pos, mps, op, openv), operator.ops, cache.envs) + elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC2,JordanMPO_∂∂AC2}} + return LazySum{elT}(suboperators) end -Base.:*(h::Union{AC_EffProj,AC2_EffProj}, v) = h(v); -function (h::AC_EffProj)(x::MPSTensor) - @plansor v[-1; -2 -3 -4] := h.le[4; -1 -2 5] * h.a1[5 2; 1] * h.re[1; -3 -4 3] * - conj(x[4 2; 3]) - @plansor y[-1 -2; -3] := conj(v[1; 2 5 6]) * h.le[-1; 1 2 4] * h.a1[4 -2; 3] * - h.re[3; 5 6 -3] +@doc """ + ∂AC2(x, operator1, operator2, leftenv, rightenv) + +Application of the effective two-site local operator on a local tensor `x`. + +``` + ┌──────┐ + ┌──┤ ├──┐ + │ └┬────┬┘ │ +┌┴┐┌─┴─┐┌─┴─┐┌┴┐ +│ ├┤ ├┤ ├┤ │ +└┬┘└─┬─┘└─┬─┘└┬┘ + │ │ │ │ + └── ──┘ +``` + +See also [`∂∂AC2`](@ref). +""" ∂AC2 + +function ∂AC2(x::MPOTensor, ::Nothing, ::Nothing, leftenv::MPSBondTensor, + rightenv::MPSBondTensor) + @plansor y[-1 -2; -3 -4] ≔ leftenv[-1; 1] * x[1 -2; 2 -4] * rightenv[2 -3] + return y isa AbstractBlockTensorMap ? only(y) : y end -function (h::AC2_EffProj)(x::MPOTensor) - @plansor v[-1; -2 -3 -4] := h.le[6; -1 -2 7] * h.a1[7 4; 5] * h.a2[5 2; 1] * - h.re[1; -3 -4 3] * conj(x[6 4; 3 2]) - @plansor y[-1 -2; -3 -4] := conj(v[2; 3 5 6]) * h.le[-1; 2 3 4] * h.a1[4 -2; 7] * - h.a2[7 -4; 1] * h.re[1; 5 6 -3] +function ∂AC2(x::MPOTensor, operator1::MPOTensor, operator2::MPOTensor, leftenv::MPSTensor, + rightenv::MPSTensor) + @plansor y[-1 -2; -3 -4] ≔ leftenv[-1 7; 6] * x[6 5; 1 3] * + operator1[7 -2; 5 4] * operator2[4 -4; 3 2] * + rightenv[1 2; -3] + return y isa AbstractBlockTensorMap ? only(y) : y end - -function ∂∂AC(pos::Int, state, operator::ProjectionOperator, env) - return AC_EffProj(operator.ket.AC[pos], leftenv(env, pos, state), - rightenv(env, pos, state)) +function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, + operator2::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor) + @plansor y[-1 -2 -3; -4 -5 -6] ≔ leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * + rightenv[1 3; -4] * + operator1[11 -2; 8 9] * τ[9 -3; 6 7] * + operator2[7 -6; 4 5] * τ[5 -5; 2 3] + return y isa AbstractBlockTensorMap ? only(y) : y end -function ∂∂AC2(pos::Int, state, operator::ProjectionOperator, env) - return AC2_EffProj(operator.ket.AC[pos], operator.ket.AR[pos + 1], - leftenv(env, pos, state), - rightenv(env, pos + 1, state)) + +# Varia +# ----- + +# Multiline +function (H::Multiline{<:DerivativeOperator})(x::AbstractVector) + return [H[row - 1] * x[mod1(row - 1, end)] for row in 1:size(H, 1)] end +Base.:*(H::Multiline{<:DerivativeOperator}, x::AbstractVector) = H(x) -# time dependent derivate operators + +# time dependent derivative operators (h::UntimedOperator{<:DerivativeOperator})(y, args...) = h.f * h.op(y) (h::TimedOperator{<:DerivativeOperator})(y, t::Number) = h.f(t) * h.op(y) function (x::LazySum{<:Union{MultipliedOperator{D},D} where {D<:DerivativeOperator}})(y, @@ -203,32 +257,3 @@ function Base.:*(h::LazySum{<:Union{D,MultipliedOperator{D}} where {D<:Derivativ v) return h(v) end - -function ∂∂C(pos::Int, mps, operator::MultipliedOperator, cache) - return MultipliedOperator(∂∂C(pos::Int, mps, operator.op, cache), operator.f) -end - -function ∂∂AC(pos::Int, mps, operator::MultipliedOperator, cache) - return MultipliedOperator(∂∂AC(pos::Int, mps, operator.op, cache), operator.f) -end - -function ∂∂AC2(pos::Int, mps, operator::MultipliedOperator, cache) - return MultipliedOperator(∂∂AC2(pos::Int, mps, operator.op, cache), operator.f) -end - -function ∂∂C(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) - suboperators = map((op, openv) -> ∂∂C(pos, mps, op, openv), operator.ops, cache.envs) - return LazySum{Union{MPO_∂∂C,MultipliedOperator{<:MPO_∂∂C}}}(suboperators) -end - -function ∂∂AC(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) - suboperators = map((op, openv) -> ∂∂AC(pos, mps, op, openv), operator.ops, cache.envs) - elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC,JordanMPO_∂∂AC}} - return LazySum{elT}(suboperators) -end - -function ∂∂AC2(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) - suboperators = map((op, openv) -> ∂∂AC2(pos, mps, op, openv), operator.ops, cache.envs) - elT = Union{D,MultipliedOperator{D}} where {D<:Union{MPO_∂∂AC2,JordanMPO_∂∂AC2}} - return LazySum{elT}(suboperators) -end diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index b79833a26..f80f18b41 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -27,86 +27,44 @@ struct JordanMPO_∂∂AC{O1,O2,O3} <: DerivativeOperator end end -Base.:*(H::JordanMPO_∂∂AC, x) = H(x) -const _HAM_MPS_TYPES = Union{FiniteMPS{<:MPSTensor},WindowMPS{<:MPSTensor}, - InfiniteMPS{<:MPSTensor}} - -function ∂∂AC(pos::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian, envs) - GL = leftenv(envs, pos, mps) - GR = rightenv(envs, pos, mps) - W = operator[pos] - - # starting - if !isfinite(operator) || pos < length(operator) - C = W[1, 1, 1, 2:(end - 1)] - GR_2 = GR[2:(end - 1)] - if nonzero_length(C) > 0 && nonzero_length(GR_2) > 0 - @plansor starting_[-1 -2; -3 -4] ≔ removeunit(C, 1)[-1; -3 1] * - GR_2[-4 1; -2] - starting = only(starting_) - else - starting = missing - end - else - starting = missing - end - - # ending - if !isfinite(operator) || pos > 1 - B = W[2:(end - 1), 1, 1, end] - GL_2 = GL[2:(end - 1)] - if nonzero_length(B) > 0 && nonzero_length(GL_2) > 0 - @plansor ending_[-1 -2; -3 -4] ≔ GL_2[-1 1; -3] * removeunit(B, 4)[1 -2; -4] - ending = nonzero_length(ending_) > 0 ? only(ending_) : missing - else - ending = missing - end - else - ending = missing - end - - # onsite - if haskey(W, CartesianIndex(1, 1, 1, lastindex(W, 4))) - if !ismissing(starting) - D = removeunit(W[1, 1, 1, end], 1) - @plansor starting[-1 -2; -3 -4] += D[-1; -3 1] * GR[end][-4 1; -2] - onsite = missing - elseif !ismissing(ending) - D = removeunit(W[1, 1, 1, end], 4) - @plansor ending[-1 -2; -3 -4] += GL[1][-1 1; -3] * D[1 -2; -4] - onsite = missing - else - onsite = removeunit(removeunit(W[1, 1, 1, end], 4), 1) - end - else - onsite = missing - end +""" + JordanMPO_∂∂AC2{O1,O2,O3,O4} - # not_started - if (!isfinite(operator) || pos > 1) && !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) +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{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(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + tensor = coalesce(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) + ismissing(tensor) && throw(ArgumentError("unable to determine type")) + S = spacetype(tensor) + M = storagetype(tensor) + 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 - - # finished - if (!isfinite(operator) || pos < length(operator)) && !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) + function JordanMPO_∂∂AC2{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 - - # continuing - A = W[2:(end - 1), 1, 1, 2:(end - 1)] - continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) - - return JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) end +# Constructors +# ------------ +const _HAM_MPS_TYPES = Union{FiniteMPS{<:MPSTensor},WindowMPS{<:MPSTensor}, + InfiniteMPS{<:MPSTensor}} + function ∂∂AC(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) GL = leftenv(envs, site, mps) @@ -179,72 +137,6 @@ function ∂∂AC(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:Jor ending, continuing) end -function (H::JordanMPO_∂∂AC)(x::MPSTensor) - y = zerovector(x) - - if !ismissing(H.onsite) - @plansor y[-1 -2; -3] += x[-1 1; -3] * H.onsite[-2; 1] - end - - if !ismissing(H.finished) - @plansor y[-1 -2; -3] += H.finished[-1; 1] * x[1 -2; -3] - end - - if !ismissing(H.not_started) - @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.not_started[1; -3] - end - - if !ismissing(H.starting) - @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[-2 -3; 2 1] - end - - if !ismissing(H.ending) - @plansor y[-1 -2; -3] += H.ending[-1 -2; 1 2] * x[1 2; -3] - end - - GL, A, GR = H.continuing - 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 - -""" - JordanMPO_∂∂AC2{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{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(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - tensor = coalesce(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) - ismissing(tensor) && throw(ArgumentError("unable to determine type")) - S = spacetype(tensor) - M = storagetype(tensor) - 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{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 - -Base.:*(H::JordanMPO_∂∂AC2, x) = H(x) - function ∂∂AC2(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, envs) GL = leftenv(envs, site, mps) @@ -385,48 +277,40 @@ function ∂∂AC2(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:Jo return JordanMPO_∂∂AC2(II, IC, ID, CB, CA, AB, AA, BE, DE, EE) end -function (H::JordanMPO_∂∂AC2)(x::MPOTensor) +# Actions +# ------- +function (H::JordanMPO_∂∂AC)(x::MPSTensor) y = zerovector(x) - if !ismissing(H.II) - @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 -4] * H.II[-3; 1] - end - - if !ismissing(H.IC) - @plansor y[-1 -2; -3 -4] += x[-1 -2; 1 2] * H.IC[-4 -3; 2 1] - end - - if !ismissing(H.ID) - @plansor y[-1 -2; -3 -4] += x[-1 -2; -3 1] * H.ID[-4; 1] - end - - if !ismissing(H.CB) - @plansor y[-1 -2; -3 -4] += x[-1 1; -3 2] * H.CB[-2 -4; 1 2] - end - - if !ismissing(H.CA) - @plansor y[-1 -2; -3 -4] += x[-1 1; 3 2] * H.CA[-2 -4 -3; 1 2 3] - end - - if !ismissing(H.AB) - @plansor y[-1 -2; -3 -4] += x[1 2; -3 3] * H.AB[-1 -2 -4; 1 2 3] - end + ismissing(H.onsite) || @plansor y[-1 -2; -3] += x[-1 1; -3] * H.onsite[-2; 1] + ismissing(H.finished) || @plansor y[-1 -2; -3] += H.finished[-1; 1] * x[1 -2; -3] + ismissing(H.not_started) || @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.not_started[1; -3] + ismissing(H.starting) || @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[-2 -3; 2 1] + ismissing(H.ending) || @plansor y[-1 -2; -3] += H.ending[-1 -2; 1 2] * x[1 2; -3] - if !ismissing(H.BE) - @plansor y[-1 -2; -3 -4] += x[1 2; -3 -4] * H.BE[-1 -2; 1 2] + GL, A, GR = H.continuing + 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 - if !ismissing(H.DE) - @plansor y[-1 -2; -3 -4] += x[-1 1; -3 -4] * H.DE[-2; 1] - end + return y +end - if !ismissing(H.EE) - @plansor y[-1 -2; -3 -4] += x[1 -2; -3 -4] * H.EE[-1; 1] - end +function (H::JordanMPO_∂∂AC2)(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! + # 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 diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 17c11914b..7e6408c45 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -8,12 +8,15 @@ struct MPO_∂∂ACN{L,O<:Tuple,R} <: DerivativeOperator operators::O rightenv::R end + Base.length(H::MPO_∂∂ACN) = length(H.operators) const MPO_∂∂C{L,R} = MPO_∂∂ACN{L,Tuple{},R} MPO_∂∂C(GL, GR) = MPO_∂∂ACN(GL, (), GR) + const MPO_∂∂AC{L,O,R} = MPO_∂∂ACN{L,Tuple{O},R} MPO_∂∂AC(GL, O, GR) = MPO_∂∂ACN(GL, (O,), GR) + const MPO_∂∂AC2{L,O₁,O₂,R} = MPO_∂∂ACN{L,Tuple{O₁,O₂},R} MPO_∂∂AC2(GL, O1, O2, GR) = MPO_∂∂ACN(GL, (O1, O2), GR) @@ -31,14 +34,6 @@ function ∂∂AC2(pos::Int, mps, operator, envs) return MPO_∂∂AC2(leftenv(envs, pos, mps), O1, O2, rightenv(envs, pos + 1, mps)) end -# Multiline -for ∂∂_ in (:∂∂C, :∂∂AC, :∂∂AC2) - @eval function $∂∂_(site::Int, mps, operator::MultilineMPO, envs) - Hs = [$∂∂_(site, mps[row], operator[row], envs[row]) for row in 1:size(operator, 1)] - return Multiline(Hs) - end -end - # Properties # ---------- function TensorKit.domain(H::MPO_∂∂ACN) @@ -56,51 +51,6 @@ end # Actions # ------- -# (h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv); -# (h::MPO_∂∂AC)(x) = ∂AC(x, h.o, h.leftenv, h.rightenv); -# (h::MPO_∂∂AC2)(x) = ∂AC2(x, h.o1, h.o2, h.leftenv, h.rightenv); - -Base.:*(H::MPO_∂∂ACN, x) = H(x) - -# ∂C -function (H::MPO_∂∂C{<:MPSBondTensor,<:MPSBondTensor})(x::MPSBondTensor) - @plansor y[-1; -2] ≔ H.leftenv[-1; 1] * x[1; 2] * H.rightenv[2; -2] -end -function (H::MPO_∂∂C{<:MPSTensor,<:MPSTensor})(x::MPSBondTensor) - @plansor y[-1; -2] ≔ H.leftenv[-1 3; 1] * x[1; 2] * H.rightenv[2 3; -2] -end - -# ∂AC -function (H::MPO_∂∂AC{<:MPSBondTensor,Nothing,<:MPSBondTensor})(x::MPSTensor) - @plansor y[-1 -2; -3] ≔ H.leftenv[-1; 1] * x[1 -2; 2] * H.rightenv[2; -3] -end -function (H::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::MPSTensor) - @plansor y[-1 -2; -3] ≔ H.leftenv[-1 5; 4] * x[4 2; 1] * H.operators[1][5 -2; 2 3] * - H.rightenv[1 3; -3] -end -function (H::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::GenericMPSTensor{S,3}) where {S} - @plansor y[-1 -2 -3; -4] ≔ H.leftenv[-1 7; 6] * x[6 4 2; 1] * H.operators[1][7 -2; 4 5] * - τ[5 -3; 2 3] * H.rightenv[1 3; -4] -end - -# ∂AC2 -function (H::MPO_∂∂AC2{<:MPSBondTensor,Nothing,Nothing,<:MPSBondTensor})(x::MPOTensor) - @plansor y[-1 -2; -3 -4] ≔ H.leftenv[-1; 1] * x[1 -2; 2 -4] * H.rightenv[2 -3] -end -function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::MPOTensor) - @plansor y[-1 -2; -3 -4] ≔ H.leftenv[-1 7; 6] * x[6 5; 1 3] * - H.operators[1][7 -2; 5 4] * H.operators[2][4 -4; 3 2] * - H.rightenv[1 2; -3] -end -function (H::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::AbstractTensorMap{<:Any,<:Any,3,3}) - @plansor y[-1 -2 -3; -4 -5 -6] ≔ H.leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * - H.rightenv[1 3; -4] * - H.operators[1][11 -2; 8 9] * τ[9 -3; 6 7] * - H.operators[2][7 -6; 4 5] * τ[5 -5; 2 3] -end - -# Multiline -function (H::Multiline{<:DerivativeOperator})(x::AbstractVector) - return [H[row - 1] * x[mod1(row - 1, end)] for row in 1:size(H, 1)] -end -Base.:*(H::Multiline{<:DerivativeOperator}, x::AbstractVector) = H(x) +(h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv) +(h::MPO_∂∂AC)(x) = ∂AC(x, h.operators[1], h.leftenv, h.rightenv) +(h::MPO_∂∂AC2)(x) = ∂AC2(x, h.operators[1], h.operators[2], h.leftenv, h.rightenv) diff --git a/src/algorithms/derivatives/projection_derivatives.jl b/src/algorithms/derivatives/projection_derivatives.jl new file mode 100644 index 000000000..adad28520 --- /dev/null +++ b/src/algorithms/derivatives/projection_derivatives.jl @@ -0,0 +1,73 @@ +struct AC_EffProj{A,L} <: DerivativeOperator + a1::A + le::L + re::L +end +struct AC2_EffProj{A,L} <: DerivativeOperator + a1::A + a2::A + le::L + re::L +end + +# Constructors +# ------------ +function ∂∂AC(pos::Int, state, operator::ProjectionOperator, env) + return AC_EffProj(operator.ket.AC[pos], leftenv(env, pos, state), + rightenv(env, pos, state)) +end +function ∂∂AC2(pos::Int, state, operator::ProjectionOperator, env) + return AC2_EffProj(operator.ket.AC[pos], operator.ket.AR[pos + 1], + leftenv(env, pos, state), + rightenv(env, pos + 1, state)) +end + +# Actions +# ------- +function (h::AC_EffProj)(x::MPSTensor) + @plansor v[-1; -2 -3 -4] := h.le[4; -1 -2 5] * h.a1[5 2; 1] * h.re[1; -3 -4 3] * + conj(x[4 2; 3]) + @plansor y[-1 -2; -3] := conj(v[1; 2 5 6]) * h.le[-1; 1 2 4] * h.a1[4 -2; 3] * + h.re[3; 5 6 -3] +end +function (h::AC2_EffProj)(x::MPOTensor) + @plansor v[-1; -2 -3 -4] := h.le[6; -1 -2 7] * h.a1[7 4; 5] * h.a2[5 2; 1] * + h.re[1; -3 -4 3] * conj(x[6 4; 3 2]) + @plansor y[-1 -2; -3 -4] := conj(v[2; 3 5 6]) * h.le[-1; 2 3 4] * h.a1[4 -2; 7] * + h.a2[7 -4; 1] * h.re[1; 5 6 -3] +end + +c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) = ∂∂C(pos, ψ, operator, envs) * ϕ.C[pos] +c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂C(pos, ψ, nothing, envs) * ϕ.C[pos] +function c_proj(pos::Int, ψ, Oϕs::LazySum, envs) + return sum(zip(Oϕs.ops, envs.envs)) do x + return c_proj(pos, ψ, x...) + end +end +function c_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return c_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end + +ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) = ∂∂AC(pos, ψ, O, envs) * ϕ.AC[pos] +ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂AC(pos, ψ, nothing, envs) * ϕ.AC[pos] + +function ac_proj(pos::Int, ψ, Oϕs::LazySum, envs) + return sum(zip(Oϕs.ops, envs.envs)) do x + return ac_proj(pos, ψ, x...) + end +end +function ac_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return ac_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end + +function ac2_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) + AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) + return ∂∂AC2(pos, ψ, O, envs) * AC2 +end +function ac2_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) + AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) + return ∂∂AC2(pos, ψ, nothing, envs) * AC2 +end +function ac2_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return ac2_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end From a240620bd454407f2953babbd7dfacc391b30614 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Fri, 28 Mar 2025 09:03:26 -0400 Subject: [PATCH 29/46] remove BlockTensorKit code duplication --- Project.toml | 2 +- src/operators/jordanmpotensor.jl | 61 +------------------------------- 2 files changed, 2 insertions(+), 61 deletions(-) diff --git a/Project.toml b/Project.toml index 1b4246ddb..acf27c723 100644 --- a/Project.toml +++ b/Project.toml @@ -25,7 +25,7 @@ VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8" [compat] Accessors = "0.1" Aqua = "0.8.9" -BlockTensorKit = "0.1.4" +BlockTensorKit = "0.1.6" Combinatorics = "1" Compat = "3.47, 4.10" DocStringExtensions = "0.9.3" diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 79aff661a..4c3b6de0d 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -106,21 +106,6 @@ end # Properties # ---------- TensorKit.space(W::JordanMPOTensor) = W.V - -Base.size(W::JordanMPOTensor) = size(eachspace(W)) -Base.size(W::JordanMPOTensor, i::Int) = i ≤ 4 ? size(W)[i] : 1 -Base.length(W::JordanMPOTensor) = prod(size(W)) -Base.axes(W::JordanMPOTensor) = map(Base.OneTo, size(W)) - -Base.firstindex(W::JordanMPOTensor) = 1 -Base.firstindex(::JordanMPOTensor, i::Int) = i ≤ 4 ? 1 : 1 -Base.lastindex(W::JordanMPOTensor) = prod(size(W)) -Base.lastindex(W::JordanMPOTensor, i::Int) = i ≤ 4 ? size(W, i) : 1 - -Base.CartesianIndices(W::JordanMPOTensor) = CartesianIndices(size(W)) -Base.eachindex(W::JordanMPOTensor) = eachindex(size(W)) - -Base.eltype(W::JordanMPOTensor) = eltype(typeof(W)) Base.eltype(::Type{JordanMPOTensor{E,S,TA,TB,TC,TD}}) where {E,S,TA,TB,TC,TD} = TA function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) @@ -146,7 +131,7 @@ function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) end # TODO: avoid this slow fallback wherever possible: -Base.parent(W::JordanMPOTensor) = (parent(SparseBlockTensorMap(W))) +Base.parent(W::JordanMPOTensor) = parent(SparseBlockTensorMap(W)) BlockTensorKit.issparse(W::JordanMPOTensor) = true @@ -182,13 +167,6 @@ end # Indexing # -------- -@inline function Base.checkbounds(W::JordanMPOTensor, I...) - checkbounds(Bool, W, I...) || Base.throw_boundserror(W, I) - return nothing -end -@inline function Base.checkbounds(::Type{Bool}, W::JordanMPOTensor, I...) - return Base.checkbounds_indices(Bool, axes(W), I) -end @inline Base.getindex(W::JordanMPOTensor, I::CartesianIndex{4}) = W[I.I...] @propagate_inbounds function Base.getindex(W::JordanMPOTensor, I::Vararg{Int,4}) @@ -211,43 +189,6 @@ end end end -# TODO: this is definitely suboptimal, but might not matter? -@propagate_inbounds function Base.getindex(W::JordanMPOTensor, - inds::Vararg{BlockTensorKit.SliceIndex,4}) - V = space(eachspace(W)[inds...]) - dst = similar(W, V) - - Rsrc = CartesianIndices(W)[inds...] - Rdst = CartesianIndices(dst) - - for I in nonzero_keys(W) - j = @something findfirst(==(I), Rsrc) continue - dst[Rdst[j]] = W[I] - end - - return dst -end -@propagate_inbounds function Base.getindex(W::JordanMPOTensor, - inds::Vararg{BlockTensorKit.Strided.SliceIndex, - 4}) - V = space(eachspace(W)[inds...]) - dst = similar(W, V) - - # prevent discarding of singleton dimensions - inds2 = map(inds) do ind - return ind isa Int ? (ind:ind) : ind - end - Rsrc = CartesianIndices(W)[inds2...] - Rdst = CartesianIndices(dst) - - for I in nonzero_keys(W) - j = @something findfirst(==(I), Rsrc) continue - dst[Rdst[j]] = W[I] - end - - return dst -end - @inline function Base.setindex!(W::JordanMPOTensor, v::MPOTensor, I::CartesianIndex{4}) return setindex!(W, v, I.I...) end From 11aa1f461a7723c9a15efec0b7f928050c1be73d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 13:03:37 -0400 Subject: [PATCH 30/46] implement fallback case that should never happen --- src/operators/abstractmpo.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/operators/abstractmpo.jl b/src/operators/abstractmpo.jl index 266836422..36dc498b6 100644 --- a/src/operators/abstractmpo.jl +++ b/src/operators/abstractmpo.jl @@ -203,6 +203,11 @@ end function _fuse_mpo_mpo(O1::MPOTensor, O2::MPOTensor, Fₗ, Fᵣ) return if O1 isa BraidingTensor && O2 isa BraidingTensor + # shouldn't happen + T = promote_type(scalartype(O1), scalartype(O2)) + V = fuse(left_virtualspace(O2) ⊗ left_virtualspace(O1)) ⊗ physicalspace(O1) ← + physicalspace(O2) ⊗ fuse(right_virtualspace(O2) ⊗ right_virtualspace(O1)) + return BraidingTensor{T}(V) elseif O1 isa BraidingTensor @plansor O′[-1 -2; -3 -4] := Fₗ[-1; 1 2] * O2[1 3; -3 5] * From 5d797fc359fca1b56375cf20a11a64826805ad07 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 13:03:53 -0400 Subject: [PATCH 31/46] Add space assertions in constructor --- src/operators/jordanmpotensor.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 4c3b6de0d..895eef8e3 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -72,6 +72,19 @@ function JordanMPOTensor(V::TensorMapSumSpace{S,2,2}, B::SparseBlockTensorMap{TB,E,S,2,1}, C::SparseBlockTensorMap{TC,E,S,1,2}, D::SparseBlockTensorMap{TD,E,S,1,1}) where {E,S,TA,TB,TC,TD} + allVs = eachspace(V) + VA = space(allVs[2:(end - 1), 1, 1, 2:(end - 1)]) + VA == space(A) || throw(SpaceMismatch()) + + VB = removeunit(space(allVs[2:(end - 1), 1, 1, end]), 4) + VB == space(B) || throw(SpaceMismatch()) + + VC = removeunit(space(allVs[1, 1, 1, 2:(end - 1)]), 1) + VC == space(C) || throw(SpaceMismatch()) + + VD = removeunit(removeunit(space(allVs[1, 1, 1, end:end]), 4), 1) + VD == space(D) || throw(SpaceMismatch()) + return JordanMPOTensor{E,S,TA,TB,TC,TD}(V, A, B, C, D) end From d0bc673b8de3ce6708fcaa06f8e0bc0d403b6a57 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 13:04:12 -0400 Subject: [PATCH 32/46] implement some mpotensor kernels --- src/operators/jordanmpotensor.jl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 895eef8e3..a3de3d378 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -281,6 +281,31 @@ function Base.:-(W1::JordanMPOTensor, W2::JordanMPOTensor) return SparseBlockTensorMap(W1) - SparseBlockTensorMap(W2) end +function fuse_mul_mpo(O1::JordanMPOTensor, O2::JordanMPOTensor) + TT = promote_type((eltype(O1)), eltype((O2))) + V = fuse(left_virtualspace(O2) ⊗ left_virtualspace(O1)) ⊗ physicalspace(O1) ← + physicalspace(O2) ⊗ fuse(right_virtualspace(O2) ⊗ right_virtualspace(O1)) + O = jordanmpotensortype(TT)(undef, V) + cartesian_inds = reshape(CartesianIndices(O), + size(O2, 1), size(O1, 1), + size(O, 2), size(O, 3), + size(O2, 4), size(O1, 4)) + for (I, o2) in nonzero_pairs(O2), (J, o1) in nonzero_pairs(O1) + K = cartesian_inds[I[1], J[1], I[2], I[3], I[4], J[4]] + O[K] = fuse_mul_mpo(o1, o2) + end + return O +end + +function _conj_mpo(W::JordanMPOTensor) + V = left_virtualspace(W)' ⊗ physicalspace(W) ← physicalspace(W) ⊗ right_virtualspace(W)' + A = _conj_mpo(W.A) + @plansor B[-1 -2; -3] ≔ conj(W.B[-1 -3; -2]) + @plansor C[-1; -2 -3] ≔ conj(W.C[-2; -1 -3]) + D = copy(adjoint(W.D)) + return JordanMPOTensor(V, A, B, C, D) +end + # Utility # ------- # Avoid falling back to `norm(W1 - W2)` which has to convert to SparseBlockTensorMap From d8e6c7ee51eea45e25adf73646c130d04ea8b785 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 13:04:33 -0400 Subject: [PATCH 33/46] `copy(::JordanMPOTensor)` --- src/operators/jordanmpotensor.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index a3de3d378..197649601 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -308,6 +308,18 @@ end # Utility # ------- +function Base.copy(W::JordanMPOTensor) + return JordanMPOTensor(W.V, copy(W.A), copy(W.B), copy(W.C), copy(W.D)) +end +function Base.copy!(Wdst::JordanMPOTensor, Wsrc::JordanMPOTensor) + space(Wdst) == space(Wsrc) || throw(SpaceMismatch()) + copy!(Wdst.A, Wsrc.A) + copy!(Wdst.B, Wsrc.B) + copy!(Wdst.C, Wsrc.C) + copy!(Wdst.D, Wsrc.D) + return Wdst +end + # Avoid falling back to `norm(W1 - W2)` which has to convert to SparseBlockTensorMap function Base.isapprox(W1::JordanMPOTensor, W2::JordanMPOTensor; kwargs...) return isapprox(W1.A, W2.A; kwargs...) && From 42a777205e9585db5b0b9683356340cd3def08b6 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 14:47:08 -0400 Subject: [PATCH 34/46] Go all in and replace all MPOHamiltonian objects --- src/algorithms/timestep/taylorcluster.jl | 2 +- src/operators/jordanmpotensor.jl | 3 + src/operators/mpohamiltonian.jl | 144 ++--------------------- 3 files changed, 12 insertions(+), 137 deletions(-) diff --git a/src/algorithms/timestep/taylorcluster.jl b/src/algorithms/timestep/taylorcluster.jl index 9e3b62034..029eada83 100644 --- a/src/algorithms/timestep/taylorcluster.jl +++ b/src/algorithms/timestep/taylorcluster.jl @@ -78,7 +78,7 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster; # loopback step: Algorithm 1 # constructing the Nth order time evolution MPO - mpo = MPO(parent(H_n)) + mpo = MPO(map(SparseBlockTensorMap, parent(H_n))) for (i, slice) in enumerate(parent(mpo)) V_right = virtual_sz[i + 1] linds_right = linds[i + 1] diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 197649601..61eae8f50 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -111,6 +111,9 @@ function jordanmpotensortype(::Type{S}, ::Type{E}) where {S<:VectorSpace,E<:Numb TD = tensormaptype(S, 1, 1, E) return JordanMPOTensor{E,S,TA,TB,TC,TD} end +function jordanmpotensortype(::Type{O}) where {O<:MPOTensor} + return jordanmpotensortype(spacetype(O), scalartype(O)) +end function Base.similar(W::JordanMPOTensor, ::Type{T}) where {T<:Number} return JordanMPOTensor{T}(undef, space(W)) diff --git a/src/operators/mpohamiltonian.jl b/src/operators/mpohamiltonian.jl index 0b88aa3a2..347b3bd48 100644 --- a/src/operators/mpohamiltonian.jl +++ b/src/operators/mpohamiltonian.jl @@ -28,7 +28,7 @@ H = MPOHamiltonian(lattice, (i, i+1) => O for i in 1:length(lattice)-1) See also [`instantiate_operator`](@ref), which is responsable for instantiating the local operators in a form that is compatible with this constructor. """ -struct MPOHamiltonian{TO,V<:AbstractVector{TO}} <: AbstractMPO{TO} +struct MPOHamiltonian{TO<:JordanMPOTensor,V<:AbstractVector{TO}} <: AbstractMPO{TO} W::V end @@ -63,9 +63,10 @@ either `MPOTensor`, `Missing` or `Number`. """ function FiniteMPOHamiltonian(Ws::Vector{<:Matrix}) T = promote_type(_split_mpoham_types.(Ws)...) - return FiniteMPOHamiltonian{T}(Ws) + W = jordanmpotensortype(T) + return FiniteMPOHamiltonian{W}(Ws) end -function FiniteMPOHamiltonian{O}(W_mats::Vector{<:Matrix}) where {O<:MPOTensor} +function FiniteMPOHamiltonian{O}(W_mats::Vector{<:Matrix}) where {O<:JordanMPOTensor} T = scalartype(O) L = length(W_mats) # initialize sumspaces @@ -87,7 +88,7 @@ function FiniteMPOHamiltonian{O}(W_mats::Vector{<:Matrix}) where {O<:MPOTensor} # ability to deduce spaces for (site, W_mat) in enumerate(W_mats) # physical space - operator_id = findfirst(x -> x isa O, W_mat) + operator_id = findfirst(x -> x isa MPOTensor, W_mat) @assert !isnothing(operator_id) "could not determine physical space at site $site" Pspaces[site] = physicalspace(W_mat[operator_id]) @@ -148,7 +149,8 @@ either `MPOTensor`, `Missing` or `Number`. """ function InfiniteMPOHamiltonian(Ws::Vector{<:Matrix}) T = promote_type(_split_mpoham_types.(Ws)...) - return InfiniteMPOHamiltonian{T}(Ws) + TW = jordanmpotensortype(T) + return InfiniteMPOHamiltonian{TW}(Ws) end function InfiniteMPOHamiltonian{O}(W_mats::Vector{<:Matrix}) where {O<:MPOTensor} # InfiniteMPOHamiltonian only works for square matrices: @@ -167,7 +169,7 @@ function InfiniteMPOHamiltonian{O}(W_mats::Vector{<:Matrix}) where {O<:MPOTensor # physical spaces Pspaces = map(W_mats) do W_mat - operator_id = findfirst(x -> x isa O, W_mat) + operator_id = findfirst(x -> x isa MPOTensor, W_mat) @assert !isnothing(operator_id) "could not determine physical space" return physicalspace(W_mat[operator_id]) end @@ -577,20 +579,6 @@ function Base.getproperty(H::MPOHamiltonian, sym::Symbol) end end -# function Base.getproperty(H::MPOHamiltonian{<:JordanMPOTensor}, sym::Symbol) -# if sym in (:A, :B, :C, :D) -# return map(Base.Fix2(Base.getproperty, sym), parent(H)) -# else -# return getfield(H, sym) -# end -# end - -function isidentitylevel(H::InfiniteMPOHamiltonian, i::Int) - isemptylevel(H, i) && return false - return all(parent(H)) do h - return (h[i, 1, 1, i] isa BraidingTensor) - end -end function isidentitylevel(H::InfiniteMPOHamiltonian{<:JordanMPOTensor}, i::Int) if i == 1 || i == size(H[1], 1) return true @@ -662,81 +650,6 @@ end # Linear Algebra # -------------- - -function Base.:+(H₁::MPOH, H₂::MPOH) where {MPOH<:MPOHamiltonian} - check_length(H₁, H₂) - @assert all(physicalspace.(parent(H₁)) .== physicalspace.(parent(H₂))) "physical spaces should match" - isinf = MPOH <: InfiniteMPOHamiltonian - - H = similar(parent(H₁)) - for i in 1:length(H) - # instantiate new blocktensor - Vₗ₁ = left_virtualspace(H₁, i) - Vₗ₂ = left_virtualspace(H₂, i) - @assert Vₗ₁[1] == Vₗ₂[1] && Vₗ₁[end] == Vₗ₂[end] "trivial spaces should match" - Vₗ = (!isinf && i == 1) ? Vₗ₁ : BlockTensorKit.oplus(Vₗ₁[1:(end - 1)], Vₗ₂[2:end]) - - Vᵣ₁ = right_virtualspace(H₁, i) - Vᵣ₂ = right_virtualspace(H₂, i) - @assert Vᵣ₁[1] == Vᵣ₂[1] && Vᵣ₁[end] == Vᵣ₂[end] "trivial spaces should match" - Vᵣ = (!isinf && i == length(H)) ? Vᵣ₁ : - BlockTensorKit.oplus(Vᵣ₁[1:(end - 1)], Vᵣ₂[2:end]) - - W = similar(eltype(H), Vₗ ⊗ physicalspace(H₁, i) ← physicalspace(H₁, i) ⊗ Vᵣ) - #= - (Direct) sum of two hamiltonians in Jordan form: - (1 C₁ D₁) (1 C₂ D₂) (1 C₁ C₂ D₁+D₂) - (0 A₁ B₁) + (0 A₂ B₂) = (0 A₁ 0 B₁ ) - (0 0 1 ) (0 0 1 ) (0 0 A₂ B₂ ) - (0 0 0 1 ) - =# - fill!(W, zero(scalartype(W))) - W[1, 1, 1, 1] = BraidingTensor{scalartype(W)}(eachspace(W)[1, 1, 1, 1]) - W[end, 1, 1, end] = BraidingTensor{scalartype(W)}(eachspace(W)[end, 1, 1, end]) - - if H₁ isa InfiniteMPOHamiltonian || i != length(H) - C₁ = H₁.C[i] - C₁_inds = CartesianIndices((1:1, 1:1, 1:1, 2:(size(H₁[i], 4) - 1))) - copyto!(W, C₁_inds, C₁, CartesianIndices(C₁)) - - C₂ = H₂.C[i] - C₂_inds = CartesianIndices((1:1, 1:1, 1:1, size(H₁[i], 4):(size(W, 4) - 1))) - copyto!(W, C₂_inds, C₂, CartesianIndices(C₂)) - end - - D₁ = H₁.D[i] - D₂ = H₂.D[i] - W[1, 1, 1, end] = D₁ + D₂ - - if H₁ isa InfiniteMPOHamiltonian || i != 1 && i != length(H) - A₁ = H₁.A[i] - A₁_inds = CartesianIndices((2:(size(H₁[i], 1) - 1), 1:1, 1:1, - 2:(size(H₁[i], 4) - 1))) - copyto!(W, A₁_inds, A₁, CartesianIndices(A₁)) - - A₂ = H₂.A[i] - A₂_inds = CartesianIndices((size(H₁[i], 1):(size(W, 1) - 1), 1:1, 1:1, - size(H₁[i], 4):(size(W, 4) - 1))) - copyto!(W, A₂_inds, A₂, CartesianIndices(A₂)) - end - - if H₁ isa InfiniteMPOHamiltonian || i != 1 - B₁ = H₁.B[i] - B₁_inds = CartesianIndices((2:(size(H₁[i], 1) - 1), 1:1, 1:1, - size(W, 4):size(W, 4))) - copyto!(W, B₁_inds, B₁, CartesianIndices(B₁)) - - B₂ = H₂.B[i] - B₂_inds = CartesianIndices((size(H₁[i], 1):(size(W, 1) - 1), 1:1, 1:1, - size(W, 4):size(W, 4))) - copyto!(W, B₂_inds, B₂, CartesianIndices(B₂)) - end - - H[i] = W - end - - return H₁ isa FiniteMPOHamiltonian ? FiniteMPOHamiltonian(H) : InfiniteMPOHamiltonian(H) -end function Base.:+(H₁::FiniteMPOHamiltonian{O}, H₂::FiniteMPOHamiltonian{O}) where {O<:JordanMPOTensor} N = check_length(H₁, H₂) @@ -803,15 +716,6 @@ Base.:-(H::MPOHamiltonian, λs::AbstractVector{<:Number}) = H + (-λs) Base.:-(λs::AbstractVector{<:Number}, H::MPOHamiltonian) = λs + (-H) Base.:-(H1::MPOHamiltonian, H2::MPOHamiltonian) = H1 + (-H2) -function VectorInterface.scale!(H::InfiniteMPOHamiltonian, λ::Number) - foreach(parent(H)) do h - # multiply scalar with start of every interaction - # this avoids double counting - # 2:end to avoid multiplying the top left and bottom right corners - return scale!(h[1, 1, 1, 2:end], λ) - end - return H -end function VectorInterface.scale!(H::MPOHamiltonian{O}, λ::Number) where {O<:JordanMPOTensor} for i in 1:length(H) @@ -832,38 +736,6 @@ function VectorInterface.scale!(Hdst::MPOHamiltonian{<:JordanMPOTensor}, return Hdst end -function VectorInterface.scale!(H::FiniteMPOHamiltonian, λ::Number) - foreach(enumerate(parent(H))) do (i, h) - if i != length(H) - scale!(h[1, 1, 1, 2:end], λ) # multiply top row (except BraidingTensor) - else - scale!(h[1, 1, 1, end], λ) # multiply right column (except BraidingTensor) - end - end - return H -end - -function VectorInterface.scale!(dst::MPOHamiltonian, src::MPOHamiltonian, - λ::Number) - N = check_length(dst, src) - for i in 1:N - space(dst[i]) == space(src[i]) || throw(SpaceMismatch()) - zerovector!(dst[i]) - for (I, v) in nonzero_pairs(src[i]) - # only scale "starting" terms - isstarting = I[1] == 1 && - ((isfinite(dst) && i == N && I[4] == size(src[i], 4)) || - ((!isfinite(dst) || i != N) && I[4] > 1)) - if v isa BraidingTensor && !isstarting - dst[i][I] = v - else - dst[i][I] = scale!(dst[i][I], v, isstarting ? λ : One()) - end - end - end - return dst -end - function Base.:*(H1::MPOHamiltonian, H2::MPOHamiltonian) check_length(H1, H2) Ws = fuse_mul_mpo.(parent(H1), parent(H2)) From ebfc2d55edcaaae4d633890af53777f28fe69f6f Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 14:47:44 -0400 Subject: [PATCH 35/46] Bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index acf27c723..25f73cd16 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MPSKit" uuid = "bb1c41ca-d63c-52ed-829e-0820dda26502" authors = "Lukas Devos, Maarten Van Damme and contributors" -version = "0.12.6" +version = "0.13.0-DEV" [deps] Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" From 78a3c0817e7ccd5d60c761ea00092b6323e5685f Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 14:50:02 -0400 Subject: [PATCH 36/46] Remove unused files --- benchmarks/Project.toml | 7 -- benchmarks/heisenberg_benchmarks.jl | 84 ------------------- results.png | Bin 63903 -> 0 bytes results_SU2Irrep.png | Bin 48061 -> 0 bytes results_Trivial.png | Bin 54617 -> 0 bytes results_U1Irrep.png | Bin 51901 -> 0 bytes test/xy_chain.jl | 125 ---------------------------- 7 files changed, 216 deletions(-) delete mode 100644 benchmarks/Project.toml delete mode 100644 benchmarks/heisenberg_benchmarks.jl delete mode 100644 results.png delete mode 100644 results_SU2Irrep.png delete mode 100644 results_Trivial.png delete mode 100644 results_U1Irrep.png delete mode 100644 test/xy_chain.jl diff --git a/benchmarks/Project.toml b/benchmarks/Project.toml deleted file mode 100644 index 5f5e53b78..000000000 --- a/benchmarks/Project.toml +++ /dev/null @@ -1,7 +0,0 @@ -[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" -TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" diff --git a/benchmarks/heisenberg_benchmarks.jl b/benchmarks/heisenberg_benchmarks.jl deleted file mode 100644 index 21d3f1f4b..000000000 --- a/benchmarks/heisenberg_benchmarks.jl +++ /dev/null @@ -1,84 +0,0 @@ -using LinearAlgebra: BLAS -using BenchmarkTools -using TensorKit, MPSKit, MPSKitModels -using CairoMakie - -BLAS.set_num_threads(1) - -# Parameters -L = 60 -T = ComplexF64 -sval = 1e-10 -symmetry = SU2Irrep -bench_iter = 5 - -# derived -@assert iseven(L) -lattice = FiniteChain(L) -alg = DMRG2(; trscheme=truncdim(2048), tol=1e-8, verbosity=MPSKit.VERBOSE_ITER) - -# Initialize MPS -H = heisenberg_XXX(T, symmetry, lattice; spin=1 // 2) - -function init_mps(H) - T = scalartype(H) - P = physicalspace.(Ref(H), 1:length(H)) - V = repeat([P[1], fuse(P[1]^2)], (length(H) ÷ 2)) - return FiniteMPS(rand, T, P, V[1:(end - 1)]) -end - -psi = init_mps(H); -psi, = find_groundstate(psi, H, alg); - -# Benchmark -site = L ÷ 2 -Ds = reverse([2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]) -times_sparsempo = let ψ = copy(psi), H = FiniteMPO(parent(H)) - times = map(Ds) do D - ψ = changebonds(ψ, SvdCut(; trscheme=truncdim(D))) - envs = environments(ψ, H) - h_ac = MPSKit.∂∂AC(site, ψ, H, envs) - ac = ψ.AC[site] - if bench_iter <= 0 - t = @belapsed $h_ac($ac) - else - ts = map(1:bench_iter) do i - return @elapsed h_ac(ac) - end - t = minimum(ts) - end - @info "Benchmark MPO:" D t - return t - end -end - -times_jordanmpo = let ψ = copy(psi) - times = map(Ds) do D - ψ = changebonds(ψ, SvdCut(; trscheme=truncdim(D))) - envs = environments(ψ, H) - h_ac = MPSKit.∂∂AC(site, ψ, H, envs) - ac = ψ.AC[site] - if bench_iter <= 0 - t = @belapsed $h_ac($ac) - else - ts = map(1:bench_iter) do i - return @elapsed h_ac(ac) - end - t = minimum(ts) - end - @info "Benchmark Jordan MPO:" D t - return t - end -end - -# Plot results -# ------------ -f = let f = Figure(; title="Absolute time of local application") - ax = f[1, 1] = Axis(f; xlabel="D", ylabel="time (s)", xscale=log10, yscale=log10) - positions = Ds - lines!(positions, times_sparsempo; label="Sparse MPO") - lines!(positions, times_jordanmpo; label="Jordan MPO") - f[1, 2] = Legend(f, ax, "Operators"; framevisible=false) - f -end -save("results_$symmetry.png", f) diff --git a/results.png b/results.png deleted file mode 100644 index 5c7b217c50ee98213decf4387ce6df1b99e85e4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63903 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

DkiK!hZJ2ty}U5yhQ~CiM#rx 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

@jXYgKPY{c3xcrdb^2n~< zN=MfBCWCf?Q#83KirS2QR|h+G2PUmNLJmWtK%}uCr--MRVF?Eg!j=?x6gap?nAJ zh@;HYpPbn63-CRZdgLwD7IR;P3BGMq7#!4)U%1%QH4PI5?uS1Plnxc&c%GE{<(Mv6h*lt)t>?XN$aHY0lEQ$D z_Arrl%LC*m(hSRsA`g$D))`@-HgCQ(+o?(W5{X5tywAD!l|c8lg2(ZM1_8AX0#9ul)*bxVimZknigsM%5?&(Kef-Xqiv+`--X1H^Vuq)} zZL_+SWucqQI?HKH99Y)QJGTtp4!?AOLmF16y%{Sn$wARcR+aO8ctvt{F7dLMw)j>x z%7w4(SCkr=dAksad52`xG?p^LLxnBe@cgpBq)pG=2pC&}9xR?3rv1_XW@ z*d7eolU~v~U+*+lt+in_`MR^oby0o(M*m-D9?#iVS6VBiNROeMj37jjpYwWk#Da1_~#Q}VtxJCZKr4SkAiLbxemTe zRb&$2z*KlE9_cEhN_UWyI~W8&zr;-jY2}XAjQ0 zxS|omSaY6SSjT~amEXf2ce1fd`p{{7HSYRrodOwTi^&Ve*x3TxM1Hf4d*Bwo%_sD&+yW!kIFOohR^E!nOk!J>nf!C{b=%THRr_!hB_BHy$3?((A&J|i@z z1KZwQYZxMnZB(CS+V@vhmV+0_U03$~My;DbT4_Js&9?{cVmKT4Q73a*Nl z@IHi;PNf8J`(6$|NZ=(7{s<*0P~QQ$O{nB0vUxuQ`wg6IO&bhv2{}|>b9k44DF{Ci z+uwCJXL9#U+S)mAndJIX7^|$?F$y&c^wXacE!xG};aNCciF(N-vi_;m2CsRtmpqEc za;5&qfhc?ci@VM8y3U!s%?vL(0`{wI!yTS6;vdaX-*{Vp+cJJch65Z-)BG!4u_i9H zDY7wQe=MD6+B&*La~|;<)m_jpW`lsy`{l*KXfoMN)n(VmTjGaq7%abjPrL7hA(9!1 zp#3sM)3Ydc5-37B+vI9G(BSTnn-D+`2Ng`Um@Dl)TcpktIcf_h(0pV@Mu)o34Y&sU z&K2wnR_{LS-IdVccq4eQysb-usyhyLag|g1aP^jz^=T2>yo7>>?)tmQut(fcf~3nS zlvHPrV%zJ<&wBwwcGR+;+r7t9_9Z=j8)M}E1bJgART4ZLYgGySJuD*7sa9zV!mcYx z?w8IO2nt%&FY@eWh}p7Pqh%fmR+9*JJRTDT$wAWKPrM#6Teb_(z4izN?CNSAa@_NI= z13TeS9xVT$b7_a6^%q(uxLK;Gz^k6lZRx!qEHsFSsC}oHk&Z+R;;1Tz`9Xt4K?=l#1qSzZ8e{>SL_v^-M9bN@Yit_!Awoxet~r^Jh$KcEkTUGCDaJ6pD)^)*g)P7#SL>@ zpI`5%3EXo!dcV5hJ9Xa{0gJTFmwuh9XIM;mW1Ws}6XZ)2fXxa@Yzj}5d&wf4-ypa5 zv4Yc8e_S{PFqNoCWC9?s) z0+BA!&IrwGK?SR%nkKUqhIqkatkKFjS^K)Q-^MTdIf!L)MF+LRx5ezlQ#2Tt$PO^; z0;_fA+KZpJIZ-Yw$1z>GITVG3zvx!tf~RNdT5CU>iDZQf-3t@A7xs{Jzqm2Z_vgY1 zl&><__s-2v!1IS0uCP8OyU0 zcyV%Q;m0;#LC8;~sJ@Rgy|e-2s?&ArffB=*RhN+Su#!1{Ylaf4i{p_r^-OSvVaETM}+v5N!V5JQ{zQ#eSW0>K{$jxv6H z%$30SFz*b?Df^GpZ}L9v!-a{OZ#5f*(JlD^W94cLTscKvZ|m}FgwS-7)>CRx@`Tb^ z7{~)1F|_3G3J5lVO=l6AxTp3gynYA{Ax!bTOQ?0W7>;&pWI#I<>(i2fo3>7x<;J7nKVq zR0L#j-#FnYaR)+0Tjvgw<1Gd*0(VE?(6u?ifw@F=y7Va>MpWv@u!1MxHCMMxFpXA@ zR{ohc+abZfAJrKyJLt%CTrQbuFCwpRy3L=$p?qu|^2k5rZ@z>G_hItAfD%9M1KjP4 z>N#@ufxOP7dvty`PWcl+=oO-yNPsga{2-|lTwk3hu17tI98~9m_#8{f57O?=!Ip7z zm6sYthCv^f(m{gQd(~b?_XlnKpOcw2o*z?DXm}Iv^rqU55T7C($ifbMWOUI&`%!4!D$_ zo|11?4;g@&rCxnUNPQ>^8rYwlC_U$+xw-r&UUGJ%T;5?kH;H7xXSraZ*;FW4Ap}gCKeSzE!EY0E(Tn&1_zxy~o|)OSAV0@XI#qsBwR_ zbY+K?hiW=2|5#6SWPyp0KVi4%?+HO_4pjpm)l*TV&=p%m1HRK^y92kqzo_1i_wAYn zm#Wm}5=!Q75d@NXoWk@|6?__>lS4F@bjg(2*iP+C)xNh01YMz%@-McRlh;4F&Vlke zD{boE5$fRu~$fSM3{TND-BZ0BvMg3igc?s(;VA;0@ z>^l-{UXD-PdSIn1MmxBtVz$B!9k3V0A{Jz1t;QMV*oblgET0RO60!zNFkf}b#dYd3 zH+Y}GUV7)x{j1L%iZ&W#l!C760O0THsTUlMK@fjg$RSsx7dg4vzzj*G_sh2UcS~af zwUb-z37`MUa<06JehhCChoSZaLP&YS}KT+7wrH1t%Ax|z7SmZI~XFw zgT^F~@XibqD1h%`@J~c`RFc8f%qFk_>~}V-aM_nE%C?22G(Mfz*11$WzF!?6k)eUK zD{8X3@F}IBmFBh8%DBWWk9woCm%KN!tY6ZQ-q6eBdp=D=$5k^m>9Xst#i z^@9Bu?aju+73`Sa8BtNk>VcYRJ{)6+l!F>)8Di=r-ET{i9uRXP=F|KVxH zF&eG|mBVEkpPJ-QA%{K>j{w9x> zNz_jt16YqNJF0Ez%c}#&fx(e-Vs8pf*)M!}dCljs+_z>z)YS_!XtwK0 zK`kCEb_(0sPU`OL%Zh9t+Z8fiGh z>2h8$3s#?UT|5oRSw)B+y-TV3F19<9S?Ea4>|qF}7iOiR6*2%<#CH<}6%qwoUSC0e zzUq0dk7kg8EIT_T#BgB)XSm(*qK**DZ^iD~Em%kDKg!w~g$P(7wuneZq+r!4;y^Kn8z<&Y!usK#$s_jV-7Ycj`!uX3ZQABcu@$lYGyW;% za}S7W*OU`vOKE*<$J_Orb*hW)xJQ^v<99gJpyY-V+=Y_+g=EYgxt_hglf#8NLx=gj zD(pYUnIAfmFZoV)Q3SUAqPJ9oFb@*rxqtMFjZ1Q~3o$FizoR`!H%Gtyxm_*2R|T04 zP=ng-U5MYSJe-da`xGnw{gq%d{EQWEekJ}5elh#Hobw2PI>mYWv-*3T6gWm}u5ckc zQc=6-LUs{Cc40y8&?Q6Jfpfq@(KqbbqEK}3F z}&Egq- zi7$&Ar;Z0OBel28Bu^!oH6{3vGMQAzHcBE>&*_&?j|o`vurSiZb~nIeAR@s(!^3j2;zUBZc{@fe2&-`824j10Z0ZH~#D5Mn{Tt z1Mq#0tsqrlDBqi|m(fJ)P(V#2U^iH_ySqEL3N@cVGf0HFp!TXO*^Sxn??XJ^pw{Ez z(kcLB?nof~OBxe!7bxa_u}SkDa3S2!DWwit7#wLyPhpzFMaKt|-BZsn?M4E&LhJVJ z8Mm4m4{d_LMz}4&w>@ay5&{hmFeRK0{lA= zxL%&30SGUB?uOVhuvkE$l%ESTQTgf%pqmH2C_C2$iHRMJC1LyQf&vpD7e`wF?`FOR zU3d!=*qRa*TYP%1#NP7^flYL`&c1Qh@bcQdSqM7p#+44nBP+-iQO3K6_%UyzSlxpU zt9<;VG}m=LoGzeYZ$JI?$paI?F$3jqJ-4|3^ehYyyBhkwytiADk1uzKZx{J0beh}u zWjy64^>886A+G@R&2QZ7Tx?HA`2+_hSY`)m@0;HzpirFIsXct+Tn~I_t72v{YJU{-*chwag)a|pYYVg79jIw(=!9|i&gLwUgB17*AOImh9= z@PYn*U@&ZQo$B$YKwADI8ZM^};PG zqr!ndK8F`zQB-{F8S}MXg*S#N+;w#o4!%bv(0EL9y3I-&02^aovnwkr{4)8GuoYA} zD4qmeud9-GbixOl==U-Q(pH07C9Zg`St2da(Q$zmaDqx(UY<~5JCv87c@}&H7#TpT zVPIeYDAkY~0T%&?g@d>lu{o74C|&62yi&Um*!W|)zRd2zi=21w8`D#qVB$$wMQH!3gEk4PJrKK93ZUM?7UI2Mwh)KWk1`k;1lwd1?rk8r8-$F#Jx zbJY}|9tgcw%LGA_Q!O9q;L*pF>n)r+`+f|e}IIE=~VU&9587hy#P%v9WwG0ZmHkzmfk%ZEX)W^rTpRD`6FRv;ZU zwSw%RybZ+#cI2xWdS)n0A-(&-`o_k+C!$I8--?R(DVzRj$VV2g^i6}JF%`Yw>Mz9y zk4ecG9`;AzZz&t^)mHWz}9I}%#T#A0GiK!`hMvS$eIAX-5~%v@KaE8&&viBKN2o;QNBA+ zlMkDwyd|7odi%%>MHGLGs(P-~r>2?#?;#uTUYuPnMT$LzzAVgx=rr!yJir$~O~$s| z0Hg>-KrBo5)tfhVEPodZ8*po|gAdi$!Zm@{h^+@GZ-LyX#f)F)_H7_G5da-(d5gPu zp^dr?)}&SyHsbKRA5p9>{c_PG+sOvncE}qo8McF12^w&hg#AqV}y@^rEjLqR`bRi6@2SWj*qv z&?emM*a0;0WVx&?kp~xfgQboN%?p)xxRQK$iai|6MDQG8j_L(zh zp!XnIAfCi4Ah3!6IY*r}BbOaIH)h5UOpcAf-N?rF z_TcuKx=-(Y`%#Nx08jOQ{|xr{!m5W&JQFWg`ICSzmaOklEvdEA9CuSx?U$P|-O}LgG+8 zp9!>03od%w6Dz>!2^2KIHV;JZ3*G6h8}pW-TH4yqpil=>8mI(K>by=864pcj1Wy`7 zlK@5ywAXhnEa0yNn$m`G!^6X1?*WZ2NLq-8nm;j>Q*)vLNGWU|fIsd7aOCIDN{)_t zp@eEqAE@*LX7qG*HvoM!m{JdiffuNGBJ0-J_86~eJtHM$4^EexMj)){G$=+*fgTF} zaH4l{1At1qV1_cafa+c;fQvR)flm*p)ZTZD)gOcE*)afRx@v3#;WW@BGPQuhTqkgH zZmt4%8GPeim)$~t$2a`FArCWyv0tz;$rCVOa!Cwgk1Y4&`5TQtx3wv&sg-r2;LX+6 zy%&NTp|N+P&~Jx~>wSg}T!0jEbn_4JLw&nnS|j0+4#+Y}3L0X}`K2bDZm!)$QJ@riqsvdyh6J!ue9K&Uw#c8EknKo2lAl~tG?c1EyUNJ&X` z8g{q0m&WUAH2wmI90-f*`fFs_0_G530BqqkZ9s|R&@IVRZ!)8Gz<96-_aI*qC zlh#uJh(*AI$c@zd*6g0fvtcZ;NmU-J79a^0;xgaEAuQZyQLLZe4^(o17|f<>1jT^9 z@81W1g3PII2NfVNfg~=lQOnpE2(uN+1*s?~%vtg{sY9oM4o>^dI$-{EDd7qL`aLb& z1RfMr`4;)Lfkv);^T@~^@bO;a=Dw2H4r1SPpvcVyvSlv4idBFZsAaly%RNc>!OH`pck)2$3&8iKufSP90h65q z(e=!aA|~^og?+6Mxbt(R8NhRK#a-K5x}pnWlf0Gdc!mBnIl>*&4oX>t!KYxjP*g1z z)G+o}*bZpOGkY%y7%Br5`3+0pdhU2l4-ir3jg6MgLce|0d`d8N#dU#qdPDOJ!254f zSOc7N-w45dvi)3HF*P4JP66zyPFMz#$~qb$WYZ^H+`_N;K1pBrgz>G5UT($O}n$_GbI7kVnE6G z3s}fu6#~_{M40)L8Yd9j-S`NqN25_@7v5h17Qe&kcvE>x(45?`MTA0u&mS=9gDS6n z_y=PkuM6nb6nXhEtd=5d2j4k6z`!bWuXOML-IpKf4f8+@jXX;N?0i*lHiK>w2r-eJ z0IP|ctzmC$<$IwG`=>Uu2%w&pSG({6�pfrj^01TQSMWCJkJmWoai8s^sEQ#sv)V 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 diff --git a/results_SU2Irrep.png b/results_SU2Irrep.png deleted file mode 100644 index 8b168328cd99381c3f48c121f7a24ca425b99d29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48061 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≺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

k7 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 VGV*ydR*FJ7q<&Z}Q}x8P{{f;^A^-pY diff --git a/test/xy_chain.jl b/test/xy_chain.jl deleted file mode 100644 index 8072ede05..000000000 --- a/test/xy_chain.jl +++ /dev/null @@ -1,125 +0,0 @@ -using FiniteMPS -using CairoMakie -using BenchmarkFreeFermions -using LinearAlgebra - -""" - This script provides a benchmark between linearly increasing beta list and exponentially increasing beta list (in the initial stage), which is proposed in our tanTRG paper (https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.130.226502). - -""" - -function XYChain(L::Int64; J::Real=1.0) - Root = InteractionTreeNode(IdentityOperator(0), nothing) - - # J(SxSx + SySy) = J/2 (S+S- + S-S+) - for i in 1:(L - 1) - addIntr!(Root, U₁Spin.S₊₋, (i, i + 1), (false, false), J / 2; name=(:S₊, :S₋)) - addIntr!(Root, U₁Spin.S₋₊, (i, i + 1), (false, false), J / 2; name=(:S₋, :S₊)) - end - - return InteractionTree(Root) -end - -function ExactSolution(L::Int64, lsβ::AbstractVector{<:Real}; J::Real=1.0) - # JW transformation to spinless fermions - T = diagm(1 => J / 2 * ones(L - 1), -1 => J / 2 * ones(L - 1)) - - @show ϵ = SingleParticleSpectrum(T) - - return map(β -> FreeEnergy(ϵ, β, 0.0), lsβ) -end - -# XY chain -# convention: J(SxSx + SySy) -L = 30 -J = 1.0 -D = 64 - -lsβ_lin = 0.2:0.2:8.0 -lsβ_exp2lin = vcat(2.0 .^ (-10:1:0), 2.0:1.0:8.0) -lsF_lin = ExactSolution(L, lsβ_lin; J=J) -lsF_exp2lin = ExactSolution(L, lsβ_exp2lin; J=J) - -H = AutomataMPO(XYChain(L; J=J)) - -# 1. linearly increasing β from Id -lsF_1 = let - ρ = identityMPO(L, U1Spin.pspace) - lnZ = 2 * log(norm(ρ)) - normalize!(ρ) - Env = Environment(ρ', H, ρ) - canonicalize!(Env, 1) - map(1:length(lsβ_lin)) do i - dβ = i == 1 ? lsβ_lin[1] : lsβ_lin[i] - lsβ_lin[i - 1] - - TDVPSweep2!(Env, -dβ / 2; - trunc=truncdim(D)) - lnZ += 2 * log(norm(ρ)) - normalize!(ρ) - - F = -lnZ / lsβ_lin[i] - println("β = $(lsβ_lin[i]), F = $(F), δF = $(abs(F - lsF_lin[i]))") - return F - end -end - -# 2. exponentially increasing β in initial stage -lsF_2 = let - ρ = identityMPO(L, U1Spin.pspace) - lnZ = 2 * log(norm(ρ)) - normalize!(ρ) - Env = Environment(ρ', H, ρ) - canonicalize!(Env, 1) - map(1:length(lsβ_exp2lin)) do i - dβ = i == 1 ? lsβ_exp2lin[1] : lsβ_exp2lin[i] - lsβ_exp2lin[i - 1] - - TDVPSweep2!(Env, -dβ / 2; - trunc=truncdim(D)) - lnZ += 2 * log(norm(ρ)) - normalize!(ρ) - - F = -lnZ / lsβ_exp2lin[i] - println("β = $(lsβ_exp2lin[i]), F = $(F), δF = $(abs(F - lsF_exp2lin[i]))") - return F - end -end - -# 3. initialize high-T state via SETTN -lsF_3 = let - ρ, _ = SETTN(H, lsβ_exp2lin[1]; - maxorder=4, tol=1e-16, - compress=0.0, - trunc=truncdim(D),) - lnZ = 2 * log(norm(ρ)) - normalize!(ρ) - Env = Environment(ρ', H, ρ) - canonicalize!(Env, 1) - map(1:length(lsβ_exp2lin)) do i - i == 1 && return -lnZ / lsβ_exp2lin[1] - dβ = lsβ_exp2lin[i] - lsβ_exp2lin[i - 1] - - TDVPSweep2!(Env, -dβ / 2; - trunc=truncdim(D)) - lnZ += 2 * log(norm(ρ)) - normalize!(ρ) - - F = -lnZ / lsβ_exp2lin[i] - println("β = $(lsβ_exp2lin[i]), F = $(F), δF = $(abs(F - lsF_exp2lin[i]))") - return F - end -end - -# plot -fig = Figure(; size=(400, 300)) -ax = Axis(fig[1, 1]; - xlabel=L"\beta", - ylabel=L"\delta F", - yscale=log10,) - -lines!(ax, lsβ_lin, abs.(lsF_1 - lsF_lin); color=:blue, label="linear") -lines!(ax, lsβ_exp2lin, abs.(lsF_2 - lsF_exp2lin); color=:red, label="exp2lin") -lines!(ax, lsβ_exp2lin, abs.(lsF_3 - lsF_exp2lin); color=:green, label="exp2lin + SETTN") - -axislegend(ax; position=(1.0, 0.0)) - -display(fig) From 03d2a208a3c51fb1a371ea7caec9ca0fbba00043 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 31 Mar 2025 15:18:01 -0400 Subject: [PATCH 37/46] Formatter --- src/algorithms/derivatives/derivatives.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index a1bca8b34..d04e18fb3 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -242,7 +242,6 @@ function (H::Multiline{<:DerivativeOperator})(x::AbstractVector) end Base.:*(H::Multiline{<:DerivativeOperator}, x::AbstractVector) = H(x) - # time dependent derivative operators (h::UntimedOperator{<:DerivativeOperator})(y, args...) = h.f * h.op(y) (h::TimedOperator{<:DerivativeOperator})(y, t::Number) = h.f(t) * h.op(y) From 6dbb1109ffd3e7fb66455ca656cc2e92cdfe4127 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 11:17:44 -0400 Subject: [PATCH 38/46] move `ac_proj` and friends --- src/algorithms/derivatives/derivatives.jl | 37 +++++++++++++++++++ .../derivatives/projection_derivatives.jl | 34 ----------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index d04e18fb3..219f1a7ab 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -233,6 +233,43 @@ function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, return y isa AbstractBlockTensorMap ? only(y) : y end +# Projection operators +# -------------------- +c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) = ∂∂C(pos, ψ, operator, envs) * ϕ.C[pos] +c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂C(pos, ψ, nothing, envs) * ϕ.C[pos] +function c_proj(pos::Int, ψ, Oϕs::LazySum, envs) + return sum(zip(Oϕs.ops, envs.envs)) do x + return c_proj(pos, ψ, x...) + end +end +function c_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return c_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end + +ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) = ∂∂AC(pos, ψ, O, envs) * ϕ.AC[pos] +ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂AC(pos, ψ, nothing, envs) * ϕ.AC[pos] + +function ac_proj(pos::Int, ψ, Oϕs::LazySum, envs) + return sum(zip(Oϕs.ops, envs.envs)) do x + return ac_proj(pos, ψ, x...) + end +end +function ac_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return ac_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end + +function ac2_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) + AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) + return ∂∂AC2(pos, ψ, O, envs) * AC2 +end +function ac2_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) + AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) + return ∂∂AC2(pos, ψ, nothing, envs) * AC2 +end +function ac2_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) + return ac2_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) +end + # Varia # ----- diff --git a/src/algorithms/derivatives/projection_derivatives.jl b/src/algorithms/derivatives/projection_derivatives.jl index adad28520..83cd53112 100644 --- a/src/algorithms/derivatives/projection_derivatives.jl +++ b/src/algorithms/derivatives/projection_derivatives.jl @@ -36,38 +36,4 @@ function (h::AC2_EffProj)(x::MPOTensor) @plansor y[-1 -2; -3 -4] := conj(v[2; 3 5 6]) * h.le[-1; 2 3 4] * h.a1[4 -2; 7] * h.a2[7 -4; 1] * h.re[1; 5 6 -3] end - -c_proj(pos::Int, ψ, (operator, ϕ)::Tuple, envs) = ∂∂C(pos, ψ, operator, envs) * ϕ.C[pos] -c_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂C(pos, ψ, nothing, envs) * ϕ.C[pos] -function c_proj(pos::Int, ψ, Oϕs::LazySum, envs) - return sum(zip(Oϕs.ops, envs.envs)) do x - return c_proj(pos, ψ, x...) - end -end -function c_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return c_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) -end - -ac_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) = ∂∂AC(pos, ψ, O, envs) * ϕ.AC[pos] -ac_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) = ∂∂AC(pos, ψ, nothing, envs) * ϕ.AC[pos] - -function ac_proj(pos::Int, ψ, Oϕs::LazySum, envs) - return sum(zip(Oϕs.ops, envs.envs)) do x - return ac_proj(pos, ψ, x...) - end -end -function ac_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return ac_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) -end - -function ac2_proj(pos::Int, ψ, (O, ϕ)::Tuple, envs) - AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂∂AC2(pos, ψ, O, envs) * AC2 -end -function ac2_proj(pos::Int, ψ, ϕ::AbstractMPS, envs) - AC2 = ϕ.AC[pos] * _transpose_tail(ϕ.AR[pos + 1]) - return ∂∂AC2(pos, ψ, nothing, envs) * AC2 -end -function ac2_proj(row::Int, col::Int, ψ::MultilineMPS, (O, ϕ)::Tuple, envs) - return ac2_proj(col, ψ[row], (O[row], ϕ[row]), envs[row]) end From 1408d859dbf496e4cbbd7dbaf963a9006ff9e9b9 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 11:18:01 -0400 Subject: [PATCH 39/46] consistent naming for Projection_derivatives --- .../derivatives/projection_derivatives.jl | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/algorithms/derivatives/projection_derivatives.jl b/src/algorithms/derivatives/projection_derivatives.jl index 83cd53112..48607460e 100644 --- a/src/algorithms/derivatives/projection_derivatives.jl +++ b/src/algorithms/derivatives/projection_derivatives.jl @@ -1,3 +1,15 @@ +struct Projection_∂∂ACN{L,O<:Tuple,R} <: DerivativeOperator + leftenv::L + As::O + rightenv::R +end + +const Projection_∂∂AC{L,O,R} = Projection_∂∂ACN{L,Tuple{O},R} +Projection_∂∂AC(GL, A, GR) = Projection_∂∂ACN(GL, (A,), GR) + +const Projection_∂∂AC2{L,O₁,O₂,R} = Projection_∂∂ACN{L,Tuple{O₁,O₂},R} +Projection_∂∂AC2(GL, A1, A2, GR) = Projection_∂∂ACN(GL, (A1, A2), GR) + struct AC_EffProj{A,L} <: DerivativeOperator a1::A le::L @@ -13,10 +25,13 @@ end # Constructors # ------------ function ∂∂AC(pos::Int, state, operator::ProjectionOperator, env) - return AC_EffProj(operator.ket.AC[pos], leftenv(env, pos, state), - rightenv(env, pos, state)) + return Projection_∂∂AC(leftenv(env, pos, state), operator.ket.AC[pos], + rightenv(env, pos, state)) end function ∂∂AC2(pos::Int, state, operator::ProjectionOperator, env) + return Projection_∂∂AC2(leftenv(env, pos, state), operator.ket.AC[pos], + operator.ket.AR[pos + 1], + rightenv(env, pos + 1, state)) return AC2_EffProj(operator.ket.AC[pos], operator.ket.AR[pos + 1], leftenv(env, pos, state), rightenv(env, pos + 1, state)) @@ -24,16 +39,15 @@ end # Actions # ------- -function (h::AC_EffProj)(x::MPSTensor) - @plansor v[-1; -2 -3 -4] := h.le[4; -1 -2 5] * h.a1[5 2; 1] * h.re[1; -3 -4 3] * - conj(x[4 2; 3]) - @plansor y[-1 -2; -3] := conj(v[1; 2 5 6]) * h.le[-1; 1 2 4] * h.a1[4 -2; 3] * - h.re[3; 5 6 -3] -end -function (h::AC2_EffProj)(x::MPOTensor) - @plansor v[-1; -2 -3 -4] := h.le[6; -1 -2 7] * h.a1[7 4; 5] * h.a2[5 2; 1] * - h.re[1; -3 -4 3] * conj(x[6 4; 3 2]) - @plansor y[-1 -2; -3 -4] := conj(v[2; 3 5 6]) * h.le[-1; 2 3 4] * h.a1[4 -2; 7] * - h.a2[7 -4; 1] * h.re[1; 5 6 -3] +function (h::Projection_∂∂AC)(x::MPSTensor) + @plansor v[-1; -2 -3 -4] := h.leftenv[4; -1 -2 5] * h.As[1][5 2; 1] * + h.rightenv[1; -3 -4 3] * conj(x[4 2; 3]) + @plansor y[-1 -2; -3] := conj(v[1; 2 5 6]) * h.leftenv[-1; 1 2 4] * h.As[1][4 -2; 3] * + h.rightenv[3; 5 6 -3] end +function (h::Projection_∂∂AC2)(x::MPOTensor) + @plansor v[-1; -2 -3 -4] := h.leftenv[6; -1 -2 7] * h.As[1][7 4; 5] * h.As[2][5 2; 1] * + h.rightenv[1; -3 -4 3] * conj(x[6 4; 3 2]) + @plansor y[-1 -2; -3 -4] := conj(v[2; 3 5 6]) * h.leftenv[-1; 2 3 4] * + h.As[1][4 -2; 7] * h.As[2][7 -4; 1] * h.rightenv[1; 5 6 -3] end From 6cffb55a8836adaf9c054cb55859428d63bcc24a Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 11:19:49 -0400 Subject: [PATCH 40/46] Apply suggestions from code review Co-authored-by: Lander Burgelman <39218680+leburgel@users.noreply.github.com> --- src/algorithms/changebonds/randexpand.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/changebonds/randexpand.jl b/src/algorithms/changebonds/randexpand.jl index 3883334af..d63a9f5bc 100644 --- a/src/algorithms/changebonds/randexpand.jl +++ b/src/algorithms/changebonds/randexpand.jl @@ -14,7 +14,7 @@ $(TYPEDFIELDS) alg_svd::S = Defaults.alg_svd() "algorithm used for [truncation](@extref TensorKit.tsvd] the expanded space" - trscheme::TruncationScheme = truncdim(1) + trscheme::TruncationScheme end function changebonds(ψ::InfiniteMPS, alg::RandExpand) From 43a34dc403812cb59bf1f47a5e2f9bee58ce2b57 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 12:10:58 -0400 Subject: [PATCH 41/46] move some definitons around --- src/algorithms/derivatives/derivatives.jl | 65 +++---------------- src/algorithms/derivatives/mpo_derivatives.jl | 52 ++++++++++++++- 2 files changed, 58 insertions(+), 59 deletions(-) diff --git a/src/algorithms/derivatives/derivatives.jl b/src/algorithms/derivatives/derivatives.jl index 219f1a7ab..9dc7dfe9a 100644 --- a/src/algorithms/derivatives/derivatives.jl +++ b/src/algorithms/derivatives/derivatives.jl @@ -49,7 +49,7 @@ function ∂∂C(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) return LazySum{Union{MPO_∂∂C,MultipliedOperator{<:MPO_∂∂C}}}(suboperators) end -@doc """ +""" ∂C(x, leftenv, rightenv) Application of the effective zero-site local operator on a local tensor `x`. @@ -66,16 +66,8 @@ Application of the effective zero-site local operator on a local tensor `x`. ``` See also [`∂∂C`](@ref). -""" ∂C - -function ∂C(x::MPSBondTensor, leftenv::MPSBondTensor, rightenv::MPSBondTensor) - @plansor y[-1; -2] ≔ leftenv[-1; 1] * x[1; 2] * rightenv[2; -2] - return y isa AbstractBlockTensorMap ? only(y) : y -end -function ∂C(x::MPSBondTensor, leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1; -2] ≔ leftenv[-1 3; 1] * x[1; 2] * rightenv[2 3; -2] - return y isa AbstractBlockTensorMap ? only(y) : y -end +""" +∂C(x, leftenv, rightenv) = MPO_∂∂C(leftenv, rightenv)(x) @doc """ ∂∂AC(site::Int, mps, operator, envs) @@ -115,7 +107,7 @@ function ∂∂AC(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments) return LazySum{elT}(suboperators) end -@doc """ +""" ∂AC(x, operator, leftenv, rightenv) Application of the effective one-site local operator on a local tensor `x`. @@ -132,27 +124,8 @@ Application of the effective one-site local operator on a local tensor `x`. ``` See also [`∂∂AC`](@ref). -""" ∂AC - -function ∂AC(x::MPSTensor, operator::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1 -2; -3] := leftenv[-1 5; 4] * x[4 2; 1] * operator[5 -2; 2 3] * - rightenv[1 3; -3] - return y isa AbstractBlockTensorMap ? only(y) : y -end -function ∂AC(x::MPSTensor, operator::Number, leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1 -2; -3] := operator * (leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * - rightenv[1 7; -3]) - return y isa AbstractBlockTensorMap ? only(y) : y -end -function ∂AC(x::MPSTensor, ::Nothing, leftenv::MPSBondTensor, rightenv::MPSBondTensor) - @plansor y[-1 -2; -3] := leftenv[-1; 2] * x[2 -2; 1] * rightenv[1; -3] -end -function ∂AC(x::GenericMPSTensor{<:Any,3}, operator::MPOTensor, - leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1 -2 -3; -4] ≔ leftenv[-1 7; 6] * x[6 4 2; 1] * operator[7 -2; 4 5] * - τ[5 -3; 2 3] * rightenv[1 3; -4] - return y isa AbstractBlockTensorMap ? only(y) : y -end +""" +∂AC(x, operator, leftenv, rightenv) = MPO_∂∂AC(leftenv, operator, rightenv)(x) @doc """ ∂∂AC2(site::Int, mps, operator, envs) @@ -193,7 +166,7 @@ function ∂∂AC2(pos::Int, mps, operator::LazySum, cache::MultipleEnvironments return LazySum{elT}(suboperators) end -@doc """ +""" ∂AC2(x, operator1, operator2, leftenv, rightenv) Application of the effective two-site local operator on a local tensor `x`. @@ -210,28 +183,8 @@ Application of the effective two-site local operator on a local tensor `x`. ``` See also [`∂∂AC2`](@ref). -""" ∂AC2 - -function ∂AC2(x::MPOTensor, ::Nothing, ::Nothing, leftenv::MPSBondTensor, - rightenv::MPSBondTensor) - @plansor y[-1 -2; -3 -4] ≔ leftenv[-1; 1] * x[1 -2; 2 -4] * rightenv[2 -3] - return y isa AbstractBlockTensorMap ? only(y) : y -end -function ∂AC2(x::MPOTensor, operator1::MPOTensor, operator2::MPOTensor, leftenv::MPSTensor, - rightenv::MPSTensor) - @plansor y[-1 -2; -3 -4] ≔ leftenv[-1 7; 6] * x[6 5; 1 3] * - operator1[7 -2; 5 4] * operator2[4 -4; 3 2] * - rightenv[1 2; -3] - return y isa AbstractBlockTensorMap ? only(y) : y -end -function ∂AC2(x::AbstractTensorMap{<:Any,<:Any,3,3}, operator1::MPOTensor, - operator2::MPOTensor, leftenv::MPSTensor, rightenv::MPSTensor) - @plansor y[-1 -2 -3; -4 -5 -6] ≔ leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * - rightenv[1 3; -4] * - operator1[11 -2; 8 9] * τ[9 -3; 6 7] * - operator2[7 -6; 4 5] * τ[5 -5; 2 3] - return y isa AbstractBlockTensorMap ? only(y) : y -end +""" +∂AC2(x, O₁, O₂, leftenv, rightenv) = MPO_∂∂AC2(leftenv, O₁, O₂, rightenv)(x) # Projection operators # -------------------- diff --git a/src/algorithms/derivatives/mpo_derivatives.jl b/src/algorithms/derivatives/mpo_derivatives.jl index 7e6408c45..0f93b1d4c 100644 --- a/src/algorithms/derivatives/mpo_derivatives.jl +++ b/src/algorithms/derivatives/mpo_derivatives.jl @@ -51,6 +51,52 @@ end # Actions # ------- -(h::MPO_∂∂C)(x) = ∂C(x, h.leftenv, h.rightenv) -(h::MPO_∂∂AC)(x) = ∂AC(x, h.operators[1], h.leftenv, h.rightenv) -(h::MPO_∂∂AC2)(x) = ∂AC2(x, h.operators[1], h.operators[2], h.leftenv, h.rightenv) +function (h::MPO_∂∂C{<:MPSBondTensor,<:MPSBondTensor})(x::MPSBondTensor) + @plansor y[-1; -2] ≔ h.leftenv[-1; 1] * x[1; 2] * h.rightenv[2; -2] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function (h::MPO_∂∂C{<:MPSTensor,<:MPSTensor})(x::MPSBondTensor) + @plansor y[-1; -2] ≔ h.leftenv[-1 3; 1] * x[1; 2] * h.rightenv[2 3; -2] + return y isa AbstractBlockTensorMap ? only(y) : y +end + +function (h::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::MPSTensor) + @plansor y[-1 -2; -3] ≔ h.leftenv[-1 5; 4] * x[4 2; 1] * + h.operators[1][5 -2; 2 3] * h.rightenv[1 3; -3] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function (h::MPO_∂∂AC{<:MPSTensor,<:Number,<:MPSTensor})(x::MPSTensor) + @plansor y[-1 -2; -3] ≔ (h.leftenv[-1 5; 4] * x[4 6; 1] * τ[6 5; 7 -2] * + h.rightenv[1 7; -3]) * only(h.operators) + return y isa AbstractBlockTensorMap ? only(y) : y +end +function (h::MPO_∂∂AC{<:MPSBondTensor,Nothing,<:MPSBondTensor})(x::MPSTensor) + @plansor y[-1 -2; -3] ≔ h.leftenv[-1; 2] * x[2 -2; 1] * h.rightenv[1; -3] +end +function (h::MPO_∂∂AC{<:MPSTensor,<:MPOTensor,<:MPSTensor})(x::GenericMPSTensor{<:Any,3}) + @plansor y[-1 -2 -3; -4] ≔ h.leftenv[-1 7; 6] * x[6 4 2; 1] * + h.operators[1][7 -2; 4 5] * τ[5 -3; 2 3] * + h.rightenv[1 3; -4] + return y isa AbstractBlockTensorMap ? only(y) : y +end + +function (h::MPO_∂∂AC2{<:MPSBondTensor,Nothing,Nothing,<:MPSBondTensor})(x::MPOTensor) + @plansor y[-1 -2; -3 -4] ≔ h.leftenv[-1; 1] * x[1 -2; 2 -4] * h.rightenv[2 -3] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function (h::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::MPOTensor) + @plansor y[-1 -2; -3 -4] ≔ h.leftenv[-1 7; 6] * x[6 5; 1 3] * + h.operators[1][7 -2; 5 4] * h.operators[2][4 -4; 3 2] * + h.rightenv[1 2; -3] + return y isa AbstractBlockTensorMap ? only(y) : y +end +function (h::MPO_∂∂AC2{<:MPSTensor,<:MPOTensor,<:MPOTensor,<:MPSTensor})(x::AbstractTensorMap{<:Any, + <:Any, + 3, + 3}) + @plansor y[-1 -2 -3; -4 -5 -6] ≔ h.leftenv[-1 11; 10] * x[10 8 6; 1 2 4] * + h.rightenv[1 3; -4] * + h.operators[1][11 -2; 8 9] * τ[9 -3; 6 7] * + h.operators[2][7 -6; 4 5] * τ[5 -5; 2 3] + return y isa AbstractBlockTensorMap ? only(y) : y +end From 9b322fda46b6db58d5fbb2a09cc9dbc0b86f5537 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 12:55:23 -0400 Subject: [PATCH 42/46] standardize ham derivative property names --- .../derivatives/hamiltonian_derivatives.jl | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/algorithms/derivatives/hamiltonian_derivatives.jl b/src/algorithms/derivatives/hamiltonian_derivatives.jl index f80f18b41..c7dbea837 100644 --- a/src/algorithms/derivatives/hamiltonian_derivatives.jl +++ b/src/algorithms/derivatives/hamiltonian_derivatives.jl @@ -5,12 +5,12 @@ Efficient operator for representing the single-site derivative of a `MPOHamilton 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{O1,O2,O3} <: DerivativeOperator - onsite::Union{O1,Missing} - not_started::Union{O1,Missing} - finished::Union{O1,Missing} - starting::Union{O2,Missing} - ending::Union{O2,Missing} - continuing::O3 + 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(onsite, not_started, finished, starting, ending, continuing) tensor = coalesce(onsite, not_started, finished, starting, ending) ismissing(tensor) && throw(ArgumentError("unable to determine type")) @@ -40,7 +40,7 @@ struct JordanMPO_∂∂AC2{O1,O2,O3,O4} <: DerivativeOperator 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 + AA::O4 # continuing left - continuing right BE::Union{O2,Missing} # ending left DE::Union{O1,Missing} # onsite left EE::Union{O1,Missing} # finished @@ -126,15 +126,7 @@ function ∂∂AC(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:Jor A = W.A continuing = (GL[2:(end - 1)], A, GR[2:(end - 1)]) - tensor = coalesce(onsite, not_started, finished, starting, ending) - ismissing(tensor) && throw(ArgumentError("unable to determine type")) - S = spacetype(tensor) - M = storagetype(tensor) - O1 = tensormaptype(S, 1, 1, M) - O2 = tensormaptype(S, 2, 2, M) - - return JordanMPO_∂∂AC{O1,O2,typeof(continuing)}(onsite, not_started, finished, starting, - ending, continuing) + return JordanMPO_∂∂AC(onsite, not_started, finished, starting, ending, continuing) end function ∂∂AC2(site::Int, mps::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor}, @@ -282,13 +274,13 @@ end function (H::JordanMPO_∂∂AC)(x::MPSTensor) y = zerovector(x) - ismissing(H.onsite) || @plansor y[-1 -2; -3] += x[-1 1; -3] * H.onsite[-2; 1] - ismissing(H.finished) || @plansor y[-1 -2; -3] += H.finished[-1; 1] * x[1 -2; -3] - ismissing(H.not_started) || @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.not_started[1; -3] - ismissing(H.starting) || @plansor y[-1 -2; -3] += x[-1 2; 1] * H.starting[-2 -3; 2 1] - ismissing(H.ending) || @plansor y[-1 -2; -3] += H.ending[-1 -2; 1 2] * x[1 2; -3] + 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.continuing + 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 From 6920494bc465af90b95916f1428984b974769fdf Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 12:57:48 -0400 Subject: [PATCH 43/46] Add `JordanMPOTensor` space checks --- src/operators/jordanmpotensor.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 61eae8f50..0d222ca7b 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -55,7 +55,6 @@ struct JordanMPOTensor{E,S, TB, TC, TD} - # TODO: add space and size checks return new{E,S,TA,TB,TC,TD}(V, A, B, C, D) end end @@ -74,16 +73,16 @@ function JordanMPOTensor(V::TensorMapSumSpace{S,2,2}, D::SparseBlockTensorMap{TD,E,S,1,1}) where {E,S,TA,TB,TC,TD} allVs = eachspace(V) VA = space(allVs[2:(end - 1), 1, 1, 2:(end - 1)]) - VA == space(A) || throw(SpaceMismatch()) + VA == space(A) || throw(SpaceMismatch("A-block has incompatible spaces")) VB = removeunit(space(allVs[2:(end - 1), 1, 1, end]), 4) - VB == space(B) || throw(SpaceMismatch()) + VB == space(B) || throw(SpaceMismatch("B-block has incompatible spaces")) VC = removeunit(space(allVs[1, 1, 1, 2:(end - 1)]), 1) - VC == space(C) || throw(SpaceMismatch()) + VC == space(C) || throw(SpaceMismatch("C-block has incompatible spaces")) VD = removeunit(removeunit(space(allVs[1, 1, 1, end:end]), 4), 1) - VD == space(D) || throw(SpaceMismatch()) + VD == space(D) || throw(SpaceMismatch("D-block has incompatible spaces")) return JordanMPOTensor{E,S,TA,TB,TC,TD}(V, A, B, C, D) end From 2d5bdd962f960cf573353a822ab0b7f7652318e4 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 13:00:02 -0400 Subject: [PATCH 44/46] No default `trscheme` --- src/algorithms/changebonds/svdcut.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/changebonds/svdcut.jl b/src/algorithms/changebonds/svdcut.jl index 3d7c7ab79..85497a2ea 100644 --- a/src/algorithms/changebonds/svdcut.jl +++ b/src/algorithms/changebonds/svdcut.jl @@ -12,7 +12,7 @@ $(TYPEDFIELDS) alg_svd::S = Defaults.alg_svd() "algorithm used for [truncation][@extref TensorKit.tsvd] of the gauge tensors" - trscheme::TruncationScheme = notrunc() + trscheme::TruncationScheme end function changebonds(ψ::AbstractFiniteMPS, alg::SvdCut; kwargs...) From a791799d6cf3003b5e42b4281e4c59197aa7a273 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 13:00:49 -0400 Subject: [PATCH 45/46] Remove obsolete code --- src/operators/abstractmpo.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/operators/abstractmpo.jl b/src/operators/abstractmpo.jl index 36dc498b6..753b691c9 100644 --- a/src/operators/abstractmpo.jl +++ b/src/operators/abstractmpo.jl @@ -37,11 +37,6 @@ end # Utility functions # ----------------- -# function jordanmpotensortype(::Type{S}, ::Type{T}) where {S<:VectorSpace,T<:Number} -# TT = Base.promote_typejoin(tensormaptype(S, 2, 2, T), BraidingTensor{T,S}) -# return SparseBlockTensorMap{TT} -# end - remove_orphans!(mpo::AbstractMPO; tol=eps(real(scalartype(mpo)))^(3 / 4)) = mpo function remove_orphans!(mpo::SparseMPO; tol=eps(real(scalartype(mpo)))^(3 / 4)) droptol!.(mpo, tol) From 8eaa06a40c8d64c5d437d2ca4f7709c1d12eb6c2 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 7 Apr 2025 13:01:31 -0400 Subject: [PATCH 46/46] Remove obsolete to do --- src/operators/jordanmpotensor.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/operators/jordanmpotensor.jl b/src/operators/jordanmpotensor.jl index 0d222ca7b..862cfc3a1 100644 --- a/src/operators/jordanmpotensor.jl +++ b/src/operators/jordanmpotensor.jl @@ -145,7 +145,6 @@ function Base.haskey(W::JordanMPOTensor, I::CartesianIndex{4}) end end -# TODO: avoid this slow fallback wherever possible: Base.parent(W::JordanMPOTensor) = parent(SparseBlockTensorMap(W)) BlockTensorKit.issparse(W::JordanMPOTensor) = true