From 6cad3d43a5f8e278d37c0d2fe0493e33de7e6fb4 Mon Sep 17 00:00:00 2001 From: AFeuerpfeil Date: Wed, 1 Apr 2026 16:22:58 -0400 Subject: [PATCH 1/4] implement in-place find_groundstate! variants and dispatch find_groundstate! on `GeometryStyle` instead of MPS type. --- src/algorithms/groundstate/dmrg.jl | 8 ++--- .../groundstate/find_groundstate.jl | 32 ++++++++++++++++--- .../groundstate/gradient_grassmann.jl | 7 ++-- src/algorithms/groundstate/idmrg.jl | 6 ++-- src/algorithms/groundstate/vumps.jl | 6 ++-- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/algorithms/groundstate/dmrg.jl b/src/algorithms/groundstate/dmrg.jl index bbca5157d..49ca93047 100644 --- a/src/algorithms/groundstate/dmrg.jl +++ b/src/algorithms/groundstate/dmrg.jl @@ -32,7 +32,7 @@ function DMRG(; return DMRG(tol, maxiter, verbosity, alg_eigsolve′, finalize) end -function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG, envs = environments(ψ, H)) +function find_groundstate!(::FiniteChainStyle, ψ, H, alg::DMRG, envs = environments(ψ, H)) ϵs = map(pos -> calc_galerkin(pos, ψ, H, ψ, envs), 1:length(ψ)) ϵ = maximum(ϵs) log = IterLog("DMRG") @@ -109,7 +109,7 @@ function DMRG2(; return DMRG2(tol, maxiter, verbosity, alg_eigsolve′, alg_svd, trscheme, finalize) end -function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs = environments(ψ, H)) +function find_groundstate!(::FiniteChainStyle, ψ, H, alg::DMRG2, envs = environments(ψ, H)) ϵs = map(pos -> calc_galerkin(pos, ψ, H, ψ, envs), 1:length(ψ)) ϵ = maximum(ϵs) log = IterLog("DMRG2") @@ -165,7 +165,3 @@ function find_groundstate!(ψ::AbstractFiniteMPS, H, alg::DMRG2, envs = environm end return ψ, envs, ϵ end - -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/find_groundstate.jl b/src/algorithms/groundstate/find_groundstate.jl index 375d25f39..28e4a874e 100644 --- a/src/algorithms/groundstate/find_groundstate.jl +++ b/src/algorithms/groundstate/find_groundstate.jl @@ -1,9 +1,13 @@ """ find_groundstate(ψ₀, H, [environments]; kwargs...) -> (ψ, environments, ϵ) - find_groundstate(ψ₀, H, algorithm, environments) -> (ψ, environments, ϵ) + find_groundstate(ψ₀, H, algorithm, [environments]) -> (ψ, environments, ϵ) + find_groundstate!(ψ₀, H, [environments]; kwargs...) -> (ψ, environments, ϵ) + find_groundstate!(ψ₀, H, algorithm, [environments]) -> (ψ, environments, ϵ) Compute the ground state for Hamiltonian `H` with initial guess `ψ`. If not specified, an optimization algorithm will be attempted based on the supplied keywords. +The `!` variant updates `ψ` in-place, reusing its storage; the non-mutating variant +operates on a copy. ## Arguments - `ψ₀::AbstractMPS`: initial guess @@ -23,10 +27,22 @@ optimization algorithm will be attempted based on the supplied keywords. """ function find_groundstate( ψ::AbstractMPS, H, envs::AbstractMPSEnvironments = environments(ψ, H); - tol = Defaults.tol, maxiter = Defaults.maxiter, + kwargs... + ) + return find_groundstate!(copy(ψ), H, envs; kwargs...) +end +function find_groundstate( + ψ::AbstractMPS, H, alg, + envs::AbstractMPSEnvironments = environments(ψ, H) + ) + return find_groundstate!(copy(ψ), H, alg, envs; tol, maxiter, verbosity, trscheme) +end +function find_groundstate!( + ψ::AbstractMPS, H, envs::AbstractMPSEnvironments = environments(ψ, H); + tol = Defaults.tol, maxiter = Defaults.maxiter, verbosity = Defaults.verbosity, trscheme = nothing ) - if isa(ψ, InfiniteMPS) + if GeometryStyle(ψ, H) isa InfiniteChainStyle alg = VUMPS(; tol = max(1.0e-4, tol), verbosity, maxiter) if tol < 1.0e-4 alg = alg & GradientGrassmann(; tol = tol, maxiter, verbosity) @@ -34,7 +50,7 @@ function find_groundstate( if !isnothing(trscheme) alg = IDMRG2(; tol = min(1.0e-2, 100tol), verbosity, trscheme) & alg end - elseif isa(ψ, AbstractFiniteMPS) + elseif GeometryStyle(ψ, H) isa FiniteChainStyle alg = DMRG(; tol, maxiter, verbosity) if !isnothing(trscheme) alg = DMRG2(; tol = min(1.0e-2, 100tol), verbosity, trscheme) & alg @@ -42,5 +58,11 @@ function find_groundstate( else throw(ArgumentError("Unknown input state type")) end - return find_groundstate(ψ, H, alg, envs) + return find_groundstate!(ψ, H, alg, envs) +end +function find_groundstate!( + ψ::AbstractMPS, H, alg::Algorithm, + envs::AbstractMPSEnvironments = environments(ψ, H) + ) + return find_groundstate!(GeometryStyle(ψ, H), ψ, H, alg, envs) end diff --git a/src/algorithms/groundstate/gradient_grassmann.jl b/src/algorithms/groundstate/gradient_grassmann.jl index 2088a6763..d8148f5d3 100644 --- a/src/algorithms/groundstate/gradient_grassmann.jl +++ b/src/algorithms/groundstate/gradient_grassmann.jl @@ -55,10 +55,11 @@ struct GradientGrassmann{O <: OptimKit.OptimizationAlgorithm, F} <: Algorithm end end -function find_groundstate( - ψ::S, H, alg::GradientGrassmann, envs::P = environments(ψ, H) +function find_groundstate!( + style::GeometryStyle, ψ::S, H, alg::GradientGrassmann, + envs::P = environments(ψ, H) )::Tuple{S, P, Float64} where {S, P} - !isa(ψ, FiniteMPS) || dim(ψ.C[end]) == 1 || + !(style isa FiniteChainStyle) || dim(ψ.C[end]) == 1 || @warn "This is not fully supported - split the mps up in a sum of mps's and optimize separately" normalize!(ψ) diff --git a/src/algorithms/groundstate/idmrg.jl b/src/algorithms/groundstate/idmrg.jl index 4b95de042..987e27b33 100644 --- a/src/algorithms/groundstate/idmrg.jl +++ b/src/algorithms/groundstate/idmrg.jl @@ -70,10 +70,12 @@ function IDMRGState{T}(mps::S, operator::O, envs::E, iter::Int, ϵ::Float64, ene return IDMRGState{S, O, E, T}(mps, operator, envs, iter, ϵ, T(energy)) end -function find_groundstate(mps, operator, alg::alg_type, envs = environments(mps, operator)) where {alg_type <: Union{<:IDMRG, <:IDMRG2}} +function find_groundstate!( + ::InfiniteChainStyle, mps, operator, alg::alg_type, + envs = environments(mps, operator) + ) where {alg_type <: Union{<:IDMRG, <:IDMRG2}} (length(mps) ≤ 1 && alg isa IDMRG2) && throw(ArgumentError("unit cell should be >= 2")) log = alg isa IDMRG ? IterLog("IDMRG") : IterLog("IDMRG2") - mps = copy(mps) iter = 0 ϵ = calc_galerkin(mps, operator, mps, envs) E = zero(TensorOperations.promote_contract(scalartype(mps), scalartype(operator))) diff --git a/src/algorithms/groundstate/vumps.jl b/src/algorithms/groundstate/vumps.jl index 47c638db9..d9a36cc23 100644 --- a/src/algorithms/groundstate/vumps.jl +++ b/src/algorithms/groundstate/vumps.jl @@ -45,8 +45,9 @@ struct VUMPSState{S, O, E} which::Symbol end -function find_groundstate( - mps::InfiniteMPS, operator, alg::VUMPS, envs = environments(mps, operator) +function find_groundstate!( + ::InfiniteChainStyle, mps, operator, alg::VUMPS, + envs = environments(mps, operator) ) return dominant_eigsolve(operator, mps, alg, envs; which = :SR) end @@ -57,7 +58,6 @@ function dominant_eigsolve( ) log = IterLog("VUMPS") iter = 0 - mps = copy(mps) ϵ = calc_galerkin(mps, operator, mps, envs) alg_environments = updatetol(alg.alg_environments, iter, ϵ) recalculate!(envs, mps, operator, mps; alg_environments.tol) From d2950e6370029e170398d4467087895890be46a5 Mon Sep 17 00:00:00 2001 From: AFeuerpfeil Date: Wed, 1 Apr 2026 16:28:42 -0400 Subject: [PATCH 2/4] format --- src/algorithms/groundstate/find_groundstate.jl | 6 +++--- src/algorithms/groundstate/gradient_grassmann.jl | 2 +- src/algorithms/groundstate/idmrg.jl | 2 +- src/algorithms/groundstate/vumps.jl | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/algorithms/groundstate/find_groundstate.jl b/src/algorithms/groundstate/find_groundstate.jl index 28e4a874e..d26bd3eea 100644 --- a/src/algorithms/groundstate/find_groundstate.jl +++ b/src/algorithms/groundstate/find_groundstate.jl @@ -32,14 +32,14 @@ function find_groundstate( return find_groundstate!(copy(ψ), H, envs; kwargs...) end function find_groundstate( - ψ::AbstractMPS, H, alg, + ψ::AbstractMPS, H, alg, envs::AbstractMPSEnvironments = environments(ψ, H) ) return find_groundstate!(copy(ψ), H, alg, envs; tol, maxiter, verbosity, trscheme) end function find_groundstate!( ψ::AbstractMPS, H, envs::AbstractMPSEnvironments = environments(ψ, H); - tol = Defaults.tol, maxiter = Defaults.maxiter, + tol = Defaults.tol, maxiter = Defaults.maxiter, verbosity = Defaults.verbosity, trscheme = nothing ) if GeometryStyle(ψ, H) isa InfiniteChainStyle @@ -61,7 +61,7 @@ function find_groundstate!( return find_groundstate!(ψ, H, alg, envs) end function find_groundstate!( - ψ::AbstractMPS, H, alg::Algorithm, + ψ::AbstractMPS, H, alg::Algorithm, envs::AbstractMPSEnvironments = environments(ψ, H) ) return find_groundstate!(GeometryStyle(ψ, H), ψ, H, alg, envs) diff --git a/src/algorithms/groundstate/gradient_grassmann.jl b/src/algorithms/groundstate/gradient_grassmann.jl index d8148f5d3..7f084660c 100644 --- a/src/algorithms/groundstate/gradient_grassmann.jl +++ b/src/algorithms/groundstate/gradient_grassmann.jl @@ -56,7 +56,7 @@ struct GradientGrassmann{O <: OptimKit.OptimizationAlgorithm, F} <: Algorithm end function find_groundstate!( - style::GeometryStyle, ψ::S, H, alg::GradientGrassmann, + style::GeometryStyle, ψ::S, H, alg::GradientGrassmann, envs::P = environments(ψ, H) )::Tuple{S, P, Float64} where {S, P} !(style isa FiniteChainStyle) || dim(ψ.C[end]) == 1 || diff --git a/src/algorithms/groundstate/idmrg.jl b/src/algorithms/groundstate/idmrg.jl index 987e27b33..7168aa202 100644 --- a/src/algorithms/groundstate/idmrg.jl +++ b/src/algorithms/groundstate/idmrg.jl @@ -71,7 +71,7 @@ function IDMRGState{T}(mps::S, operator::O, envs::E, iter::Int, ϵ::Float64, ene end function find_groundstate!( - ::InfiniteChainStyle, mps, operator, alg::alg_type, + ::InfiniteChainStyle, mps, operator, alg::alg_type, envs = environments(mps, operator) ) where {alg_type <: Union{<:IDMRG, <:IDMRG2}} (length(mps) ≤ 1 && alg isa IDMRG2) && throw(ArgumentError("unit cell should be >= 2")) diff --git a/src/algorithms/groundstate/vumps.jl b/src/algorithms/groundstate/vumps.jl index d9a36cc23..30220cf75 100644 --- a/src/algorithms/groundstate/vumps.jl +++ b/src/algorithms/groundstate/vumps.jl @@ -46,7 +46,7 @@ struct VUMPSState{S, O, E} end function find_groundstate!( - ::InfiniteChainStyle, mps, operator, alg::VUMPS, + ::InfiniteChainStyle, mps, operator, alg::VUMPS, envs = environments(mps, operator) ) return dominant_eigsolve(operator, mps, alg, envs; which = :SR) From d3d5a319fee3dd1bcfad5927ec454e8d9259547c Mon Sep 17 00:00:00 2001 From: Andreas Feuerpfeil Date: Wed, 1 Apr 2026 20:35:20 -0400 Subject: [PATCH 3/4] Remove wrong parameters from find_groundstate --- src/algorithms/groundstate/find_groundstate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/groundstate/find_groundstate.jl b/src/algorithms/groundstate/find_groundstate.jl index d26bd3eea..9e757e27c 100644 --- a/src/algorithms/groundstate/find_groundstate.jl +++ b/src/algorithms/groundstate/find_groundstate.jl @@ -35,7 +35,7 @@ function find_groundstate( ψ::AbstractMPS, H, alg, envs::AbstractMPSEnvironments = environments(ψ, H) ) - return find_groundstate!(copy(ψ), H, alg, envs; tol, maxiter, verbosity, trscheme) + return find_groundstate!(copy(ψ), H, alg, envs) end function find_groundstate!( ψ::AbstractMPS, H, envs::AbstractMPSEnvironments = environments(ψ, H); From 2c2b5f3e3fd403aff8162bc79c05bf4216ac115b Mon Sep 17 00:00:00 2001 From: Andreas Feuerpfeil Date: Thu, 2 Apr 2026 17:16:33 -0400 Subject: [PATCH 4/4] Add mutating version of find_groundstate function to unionalg --- src/algorithms/unionalg.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/algorithms/unionalg.jl b/src/algorithms/unionalg.jl index 201f24d91..d423a60e0 100644 --- a/src/algorithms/unionalg.jl +++ b/src/algorithms/unionalg.jl @@ -32,3 +32,8 @@ function find_groundstate(state, H, alg::UnionAlg, envs = environments(state, H) state, envs = find_groundstate(state, H, alg.alg1, envs) return find_groundstate(state, H, alg.alg2, envs) end + +function find_groundstate!(state, H, alg::UnionAlg, envs = environments(state, H)) + state, envs = find_groundstate!(state, H, alg.alg1, envs) + return find_groundstate!(state, H, alg.alg2, envs) +end