From 50232ec424417cedd3bded605d931893678c88a4 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Tue, 24 Feb 2026 13:44:10 +0100 Subject: [PATCH 01/11] Add `check_input` method for `fixedpoint` --- .../optimization/peps_optimization.jl | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index 73dd5672b..87a4a86a4 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -14,25 +14,25 @@ $(TYPEDFIELDS) Construct a PEPS optimization algorithm struct based on keyword arguments. For a full description, see [`fixedpoint`](@ref). The supported keywords are: -* `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm}` +* `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm,...}` * `gradient_alg::Union{NamedTuple,Nothing,<:GradMode}` * `optimizer_alg::Union{NamedTuple,<:OptimKit.OptimizationAlgorithm}` * `reuse_env::Bool=$(Defaults.reuse_env)` * `symmetrization::Union{Nothing,SymmetrizationStyle}=nothing` """ -struct PEPSOptimize{G} - boundary_alg::CTMRGAlgorithm +struct PEPSOptimize{B, G} + boundary_alg::B gradient_alg::G optimizer_alg::OptimKit.OptimizationAlgorithm reuse_env::Bool symmetrization::Union{Nothing, SymmetrizationStyle} function PEPSOptimize( # Inner constructor to prohibit illegal setting combinations - boundary_alg::CTMRGAlgorithm, gradient_alg::G, optimizer_alg, + boundary_alg::B, gradient_alg::G, optimizer_alg, reuse_env, symmetrization, - ) where {G} + ) where {B, G} _check_algorithm_combination(boundary_alg, gradient_alg) - return new{G}(boundary_alg, gradient_alg, optimizer_alg, reuse_env, symmetrization) + return new{B, G}(boundary_alg, gradient_alg, optimizer_alg, reuse_env, symmetrization) end end @@ -85,13 +85,13 @@ function _OptimizationAlgorithm(; end """ - fixedpoint(operator, peps₀::InfinitePEPS, env₀::CTMRGEnv; kwargs...) -> peps_final, env_final, cost_final, info + fixedpoint(operator, peps₀::InfinitePEPS, env₀; kwargs...) -> peps_final, env_final, cost_final, info # expert version: - fixedpoint(operator, peps₀::InfinitePEPS, env₀::CTMRGEnv, alg::PEPSOptimize; finalize!=OptimKit._finalize!) + fixedpoint(operator, peps₀::InfinitePEPS, env₀, alg::PEPSOptimize; finalize!=OptimKit._finalize!) Find the fixed point of `operator` (i.e. the ground state) starting from `peps₀` according to the supplied optimization parameters. The initial environment `env₀` serves as an -initial guess for the first CTMRG run. By default, a random initial environment is used. +initial guess for the first boundary contraction run. By default, a random initial environment is used. The optimization parameters can be supplied via the keyword arguments or directly as a `PEPSOptimize` struct. The following keyword arguments are supported: @@ -113,8 +113,8 @@ The optimization parameters can be supplied via the keyword arguments or directl ### Boundary algorithm -Supply boundary algorithm parameters via `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm}` -using either a `NamedTuple` of keyword arguments or a `CTMRGAlgorithm` directly. +Supply boundary algorithm parameters via `boundary_alg` +using either a `NamedTuple` of keyword arguments or a boundary algorithm instance directly. See [`leading_boundary`](@ref) for a description of all possible keyword arguments. By default, a CTMRG tolerance of `tol=1e-4tol` and is used. @@ -165,22 +165,22 @@ information `NamedTuple` which contains the following entries: * `fg_evaluations` : Number of evaluations of the cost and gradient function. * `costs` : History of cost values. * `gradnorms` : History of gradient norms. -* `truncation_errors` : History of maximal truncation errors of the boundary algorithm. -* `condition_numbers` : History of maximal condition numbers of the CTMRG environments. +* `contraction_metrics` : History of boundary-algorithm-specific contraction information, e.g. truncation errors and condition numbers. * `gradnorms_unitcell` : History of gradient norms for each respective unit cell entry. * `times` : History of optimization step execution times. """ function fixedpoint( - operator, peps₀::InfinitePEPS, env₀::CTMRGEnv; - (finalize!) = OptimKit._finalize!, kwargs..., + operator, peps₀::InfinitePEPS, env₀; (finalize!) = OptimKit._finalize!, kwargs..., ) alg = select_algorithm(fixedpoint, env₀; kwargs...) return fixedpoint(operator, peps₀, env₀, alg; finalize!) end function fixedpoint( - operator, peps₀::InfinitePEPS, env₀::CTMRGEnv, alg::PEPSOptimize; - (finalize!) = OptimKit._finalize!, + operator, peps₀::InfinitePEPS, env₀, alg::PEPSOptimize; (finalize!) = OptimKit._finalize!, ) + # validate inputs + check_input(fixedpoint, peps₀, env₀, alg) + # setup retract and finalize! for symmetrization if isnothing(alg.symmetrization) retract = peps_retract @@ -190,21 +190,9 @@ function fixedpoint( ) end - # :fixed mode compatibility - if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed - if scalartype(env₀) <: Real # incompatible with real environments - env₀ = complex(env₀) - @warn "the provided real environment was converted to a complex environment \ - since :fixed mode generally produces complex gauges; use :diffgauge mode \ - instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ - keyword arguments to work with purely real environments" - end - end - # initialize info collection vectors T = promote_type(real(scalartype(peps₀)), real(scalartype(env₀))) - truncation_errors = Vector{T}() - condition_numbers = Vector{T}() + contraction_metrics = Vector{NamedTuple}() gradnorms_unitcell = Vector{Matrix{T}}() times = Vector{Float64}() @@ -224,8 +212,7 @@ function fixedpoint( ) ignore_derivatives() do alg.reuse_env && update!(env, env′) - push!(truncation_errors, info.truncation_error) - push!(condition_numbers, info.condition_number) + push!(contraction_metrics, info.contraction_metrics) end return cost_function(ψ, env′, operator) end @@ -240,14 +227,32 @@ function fixedpoint( fg_evaluations = numfg, costs = convergence_history[:, 1], gradnorms = convergence_history[:, 2], - truncation_errors, - condition_numbers, + contraction_metrics, gradnorms_unitcell, times, ) return peps_final, env_final, cost_final, info end +""" + check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG}) + +Check compatibility of an initial PEPS and environment with a specified PEPS optimization algorithm. +""" +function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize) end +function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG}) + # :fixed mode compatibility + if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed + if scalartype(env₀) <: Real # incompatible with real environments + msg = "the provided real environment is in compatible with :fixed mode \ + since :fixed mode generally produces complex gauges; use :diffgauge mode \ + instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ + keyword arguments to work with purely real environments and asymmetric CTMRG" + throw(ArgumentError(msg)) + end + end +end + """ peps_normalize(A::InfinitePEPS) From 53fd5aae87263fc59b8a5315b0fdf467f62e3e0b Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Tue, 24 Feb 2026 13:44:43 +0100 Subject: [PATCH 02/11] Add `contraction_metrics` tuple to returned `info` --- src/algorithms/ctmrg/c4v.jl | 7 ++++++- src/algorithms/ctmrg/ctmrg.jl | 18 +++++++++--------- src/algorithms/ctmrg/sequential.jl | 2 +- src/algorithms/ctmrg/simultaneous.jl | 5 ++++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/algorithms/ctmrg/c4v.jl b/src/algorithms/ctmrg/c4v.jl index 9aaec610f..182c77856 100644 --- a/src/algorithms/ctmrg/c4v.jl +++ b/src/algorithms/ctmrg/c4v.jl @@ -104,7 +104,7 @@ PROJECTOR_SYMBOLS[:c4v_qr] = C4vQRProjector _set_truncation(alg::C4vQRProjector, ::TruncationStrategy) = alg function check_input( - network::InfiniteSquareNetwork, env::CTMRGEnv, alg::C4vCTMRG; atol = 1.0e-10 + ::typeof(leading_boundary), network::InfiniteSquareNetwork, env::CTMRGEnv, alg::C4vCTMRG; atol = 1.0e-10 ) # check unit cell size length(network) == 1 || throw(ArgumentError("C4v CTMRG is only compatible with single-site unit cells.")) @@ -144,6 +144,10 @@ function ctmrg_iteration( enlarged_corner = c4v_enlarge(network, env, alg.projector_alg) corner′, projector, info = c4v_projector!(enlarged_corner, alg.projector_alg) edge′ = c4v_renormalize_edge(network, env, projector) + info = (; + contraction_metrics = (; info.truncation_error, info.condition_number), + info.D, info.V, info.D_full, info.V_full, info.truncation_indices, + ) return CTMRGEnv(corner′, edge′), info end function ctmrg_iteration( @@ -155,6 +159,7 @@ function ctmrg_iteration( projector, info = c4v_projector!(enlarged_corner, alg.projector_alg) edge′ = c4v_renormalize_edge(network, env, projector) corner′ = c4v_qr_renormalize_corner(edge′, projector, info.R) + info = (; contraction_metrics = (;), info.Q, info.R) return CTMRGEnv(corner′, edge′), info end diff --git a/src/algorithms/ctmrg/ctmrg.jl b/src/algorithms/ctmrg/ctmrg.jl index 7d30f5cd7..3d0189a5d 100644 --- a/src/algorithms/ctmrg/ctmrg.jl +++ b/src/algorithms/ctmrg/ctmrg.jl @@ -44,14 +44,6 @@ Perform a single CTMRG iteration in which all directions are being grown and ren """ function ctmrg_iteration(network, env, alg::CTMRGAlgorithm) end -""" - check_input(network, env, alg::CTMRGAlgorithm) - -Check compatibility of a given network and environment with a specified CTMRG algorithm. -""" -function check_input(network, env, alg::CTMRGAlgorithm) end -@non_differentiable check_input(args...) - """ leading_boundary(env₀, network; kwargs...) -> env, info # expert version: @@ -123,7 +115,7 @@ end function leading_boundary( env₀::CTMRGEnv, network::InfiniteSquareNetwork, alg::CTMRGAlgorithm ) - check_input(network, env₀, alg) + check_input(leading_boundary, network, env₀, alg) log = ignore_derivatives(() -> MPSKit.IterLog("CTMRG")) return LoggingExtras.withlevel(; alg.verbosity) do env = deepcopy(env₀) @@ -154,6 +146,14 @@ function leading_boundary(env₀::CTMRGEnv, state, args...; kwargs...) return leading_boundary(env₀, InfiniteSquareNetwork(state), args...; kwargs...) end +""" + check_input(::typeof(leading_boundary), network, env, alg::CTMRGAlgorithm) + +Check compatibility of a given network and environment with a specified CTMRG algorithm. +""" +function check_input(::typeof(leading_boundary), network, env, alg::CTMRGAlgorithm) end +@non_differentiable check_input(args...) + # custom CTMRG logging function ctmrg_loginit!(log, η, network, env) return @infov 2 loginit!(log, η, network_value(network, env)) diff --git a/src/algorithms/ctmrg/sequential.jl b/src/algorithms/ctmrg/sequential.jl index 1c9631675..9c858d36d 100644 --- a/src/algorithms/ctmrg/sequential.jl +++ b/src/algorithms/ctmrg/sequential.jl @@ -69,7 +69,7 @@ function ctmrg_iteration(network, env::CTMRGEnv, alg::SequentialCTMRG) network = rotate_north(network, EAST) env = rotate_north(env, EAST) end - return env, (; truncation_error, condition_number) + return env, (; contraction_metrics = (; truncation_error, condition_number)) end """ diff --git a/src/algorithms/ctmrg/simultaneous.jl b/src/algorithms/ctmrg/simultaneous.jl index 928246738..bf982a220 100644 --- a/src/algorithms/ctmrg/simultaneous.jl +++ b/src/algorithms/ctmrg/simultaneous.jl @@ -65,7 +65,10 @@ function _split_proj_and_info(proj_and_info) S_full = map(x -> x[2].S_full, proj_and_info) V_full = map(x -> x[2].V_full, proj_and_info) truncation_indices = map(x -> x[2].truncation_indices, proj_and_info) - info = (; truncation_error, condition_number, U, S, V, U_full, S_full, V_full, truncation_indices) + info = (; + contraction_metrics = (; truncation_error, condition_number), + U, S, V, U_full, S_full, V_full, truncation_indices, + ) return (P_left, P_right), info end From d429d4a7be284e8ef632645b97fa2277ce51279c Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Tue, 24 Feb 2026 13:45:08 +0100 Subject: [PATCH 03/11] Add tests for real C4v optimization and QR-CTMRG optimizations --- test/examples/heisenberg.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index dc5836537..ed86fab1a 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -50,21 +50,23 @@ end @test all(@. ξ_h > 0 && ξ_v > 0) end -@testset "C4v AD optimization" begin +@testset "C4v AD optimization with scalartype T=$T and projector_alg=$projector_alg" for (T, projector_alg) in + Iterators.product([Float64, ComplexF64], [:c4v_eigh, :c4v_qr]) # initialize symmetric states - Random.seed!(123) + Random.seed!(23023952) symm = RotateReflect() - H = heisenberg_XYZ_c4v(InfiniteSquare()) - peps₀ = InfinitePEPS(ComplexSpace(2), ComplexSpace(Dbond)) + H′ = heisenberg_XYZ_c4v(InfiniteSquare()) + H = T <: Real ? real(H′) : H′ + peps₀ = InfinitePEPS(randn, T, ComplexSpace(2), ComplexSpace(Dbond)) peps₀ = peps_normalize(symmetrize!(peps₀, symm)) e₀ = initialize_random_c4v_env(peps₀, ComplexSpace(χenv)) - env₀, = leading_boundary(e₀, peps₀; alg = :c4v) + env₀, = leading_boundary(e₀, peps₀; alg = :c4v, projector_alg) # optimize energy and compute correlation lengths peps, env, E, = fixedpoint( H, peps₀, env₀; optimizer_alg = (; tol = gradtol, maxiter = 25), - boundary_alg = (; alg = :c4v), + boundary_alg = (; alg = :c4v, projector_alg, maxiter = 500), ) ξ_h, ξ_v, = correlation_length(peps, env) From f57e8cddf04a5a768a8e81ddaa1540305e7d7710 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Tue, 24 Feb 2026 18:11:04 +0100 Subject: [PATCH 04/11] Fix `truncation_error` in sequential mode and catch `:fixed` mode error for real tensors in tests --- examples/heisenberg/main.jl | 10 ++++--- src/algorithms/ctmrg/c4v.jl | 3 +-- src/algorithms/ctmrg/ctmrg.jl | 27 +++++-------------- src/algorithms/ctmrg/simultaneous.jl | 9 ++++--- .../optimization/peps_optimization.jl | 4 +-- test/examples/heisenberg.jl | 7 ++--- 6 files changed, 24 insertions(+), 36 deletions(-) diff --git a/examples/heisenberg/main.jl b/examples/heisenberg/main.jl index d2dfbecfb..fa77c4369 100644 --- a/examples/heisenberg/main.jl +++ b/examples/heisenberg/main.jl @@ -102,12 +102,14 @@ env₀, info_ctmrg = leading_boundary(env_random, peps₀; boundary_alg...); md""" Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of -informational quantities such as the last maximal truncation error - that is, the SVD -approximation error incurred in the last CTMRG iteration, maximized over all spatial -directions and unit cell entries: +informational quantities which contains, among other things, a `convergence_metric` tuple. +This may contain different quantities depending on the method of contraction, and for this +CTMRG variant we return the last maximal truncation error (the SVD approximation +error maximized over all spatial directions and unit cell entries) as well as the condition +number of the decomposition (the ratio of largest to smallest singular value): """ -@show info_ctmrg.truncation_error; +@show info_ctmrg.convergence_metrics; md""" ## Ground state search diff --git a/src/algorithms/ctmrg/c4v.jl b/src/algorithms/ctmrg/c4v.jl index 182c77856..82a30dbbf 100644 --- a/src/algorithms/ctmrg/c4v.jl +++ b/src/algorithms/ctmrg/c4v.jl @@ -86,8 +86,7 @@ $(TYPEDFIELDS) C4vQRProjector(; kwargs...) -Construct the C₄ᵥ `qr`-based projector algorithm -based on the following keyword arguments: +Construct the C₄ᵥ `qr`-based projector algorithm based on the following keyword arguments: * `decomposition_alg=QRAdjoint()` : `left_orth` algorithm including the reverse rule. See [`QRAdjoint`](@ref). """ diff --git a/src/algorithms/ctmrg/ctmrg.jl b/src/algorithms/ctmrg/ctmrg.jl index 3d0189a5d..7e60be309 100644 --- a/src/algorithms/ctmrg/ctmrg.jl +++ b/src/algorithms/ctmrg/ctmrg.jl @@ -83,30 +83,15 @@ supplied via the keyword arguments or directly as an [`CTMRGAlgorithm`](@ref) st * `projector_alg::Symbol=:$(Defaults.projector_alg)` : Variant of the projector algorithm. See also [`ProjectorAlgorithm`](@ref). - `:halfinfinite` : Projection via SVDs of half-infinite (two enlarged corners) CTMRG environments. - `:fullinfinite` : Projection via SVDs of full-infinite (all four enlarged corners) CTMRG environments. - - `:c4v_eigh` : Projection via `eigh` of the Hermitian enlarged corner. + - `:c4v_eigh` : Projection via `eigh` of the Hermitian enlarged corner, works only for [`C4vCTMRG`](@ref). + - `:c4v_qr` : Projection via QR decomposition of the lower-rank column-enlarged corner, works only for [`C4vCTMRG`](@ref). ## Return values -The CTMRG routine returns the final CTMRG environment as well as an information `NamedTuple` -containing the following fields: - -* `truncation_error` : Last (maximal) SVD truncation error of the CTMRG projectors. -* `condition_number` : Last (maximal) condition number of the enlarged CTMRG environment. - -In case the `alg` is a `SimultaneousCTMRG`, the last SVD will also be returned: - -* `U` : Last unit cell of left singular vectors. -* `S` : Last unit cell of singular values. -* `V` : Last unit cell of right singular vectors. - -If, in addition, the specified SVD algorithm computes the full, untruncated SVD, the full -set of vectors and values will be returned as well: - -* `U_full` : Last unit cell of all left singular vectors. -* `S_full` : Last unit cell of all singular values. -* `V_full` : Last unit cell of all right singular vectors. - -For `C4vCTMRG` instead the last eigendecomposition `V` and `D` (and `V_full`, `D_full`) will be returned. +The `leading_boundary` routine returns the final environment as well as an information `NamedTuple` +that generally contains a `convergence_metrics` `NamedTuple` storing different contents depending +on the chosen `alg`. Depending on the contraction method, the information tuple may also contain +the final tensor decomposition (used in the projectors) including its truncation indices. """ function leading_boundary(env₀::CTMRGEnv, network::InfiniteSquareNetwork; kwargs...) alg = select_algorithm(leading_boundary, env₀; kwargs...) diff --git a/src/algorithms/ctmrg/simultaneous.jl b/src/algorithms/ctmrg/simultaneous.jl index bf982a220..7e1fafb00 100644 --- a/src/algorithms/ctmrg/simultaneous.jl +++ b/src/algorithms/ctmrg/simultaneous.jl @@ -48,6 +48,10 @@ function ctmrg_iteration(network, env::CTMRGEnv, alg::SimultaneousCTMRG) end # expand environment projectors, info = simultaneous_projectors(enlarged_corners, env, alg.projector_alg) # compute projectors on all coordinates env′ = renormalize_simultaneously(enlarged_corners, projectors, network, env) # renormalize enlarged corners + info = (; + contraction_metrics = (; info.truncation_error, info.condition_number), + info.U, info.S, info.V, info.U_full, info.S_full, info.V_full, info.truncation_indices, + ) return env′, info end @@ -65,10 +69,7 @@ function _split_proj_and_info(proj_and_info) S_full = map(x -> x[2].S_full, proj_and_info) V_full = map(x -> x[2].V_full, proj_and_info) truncation_indices = map(x -> x[2].truncation_indices, proj_and_info) - info = (; - contraction_metrics = (; truncation_error, condition_number), - U, S, V, U_full, S_full, V_full, truncation_indices, - ) + info = (; truncation_error, condition_number, U, S, V, U_full, S_full, V_full, truncation_indices) return (P_left, P_right), info end diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index 87a4a86a4..a5b5ed62b 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -180,7 +180,7 @@ function fixedpoint( ) # validate inputs check_input(fixedpoint, peps₀, env₀, alg) - + # setup retract and finalize! for symmetrization if isnothing(alg.symmetrization) retract = peps_retract @@ -242,7 +242,7 @@ Check compatibility of an initial PEPS and environment with a specified PEPS opt function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize) end function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG}) # :fixed mode compatibility - if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed + return if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed if scalartype(env₀) <: Real # incompatible with real environments msg = "the provided real environment is in compatible with :fixed mode \ since :fixed mode generally produces complex gauges; use :diffgauge mode \ diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index ed86fab1a..6873d1a7a 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -128,11 +128,12 @@ end # benchmark data from Phys. Rev. B 94, 035133 (2016) @test isapprox(e_site, -0.6594; atol = 1.0e-3) + # test if :fixed mode on real tensors errors + @test_throws ArgumentError fixedpoint(ham, peps, env) + # continue with auto differentiation peps_final, env_final, E_final, = fixedpoint( - ham, - peps, - env; + ham, peps, complex(env); # make environment complex explicitly optimizer_alg = (; tol = gradtol, maxiter = 25), boundary_alg = (; maxiter = ctmrg_maxiter), gradient_alg = (; alg = :linsolver, solver_alg = (; alg = :gmres)), From 03879506d876e463f02a3661589a660fe8a9f1b7 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Wed, 25 Feb 2026 12:11:47 +0100 Subject: [PATCH 05/11] Use type parameters in `check_input` and use old seed again --- .../optimization/peps_optimization.jl | 18 ++++++++---------- test/examples/heisenberg.jl | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index a5b5ed62b..5bec2c228 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -240,17 +240,15 @@ end Check compatibility of an initial PEPS and environment with a specified PEPS optimization algorithm. """ function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize) end -function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG}) - # :fixed mode compatibility - return if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed - if scalartype(env₀) <: Real # incompatible with real environments - msg = "the provided real environment is in compatible with :fixed mode \ - since :fixed mode generally produces complex gauges; use :diffgauge mode \ - instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ - keyword arguments to work with purely real environments and asymmetric CTMRG" - throw(ArgumentError(msg)) - end +function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG, <:GradMode{:fixed}}) + if scalartype(env₀) <: Real # :fixed mode gauge fixing is incompatible with real environments + msg = "the provided real environment is in compatible with :fixed mode \ + since :fixed mode generally produces complex gauges; use :diffgauge mode \ + instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ + keyword arguments to work with purely real environments and asymmetric CTMRG" + throw(ArgumentError(msg)) end + return nothing end """ diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index 6873d1a7a..228a60a63 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -53,7 +53,7 @@ end @testset "C4v AD optimization with scalartype T=$T and projector_alg=$projector_alg" for (T, projector_alg) in Iterators.product([Float64, ComplexF64], [:c4v_eigh, :c4v_qr]) # initialize symmetric states - Random.seed!(23023952) + Random.seed!(123) symm = RotateReflect() H′ = heisenberg_XYZ_c4v(InfiniteSquare()) H = T <: Real ? real(H′) : H′ From 2ea4108f7290c5c9e4d859a4c763df2c3ef6d728 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Wed, 25 Feb 2026 12:12:00 +0100 Subject: [PATCH 06/11] Use `:linsolver` by default for C4v CTMRG --- src/algorithms/select_algorithm.jl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/algorithms/select_algorithm.jl b/src/algorithms/select_algorithm.jl index 8ba6beda1..84dca5b24 100644 --- a/src/algorithms/select_algorithm.jl +++ b/src/algorithms/select_algorithm.jl @@ -32,6 +32,18 @@ function select_algorithm( boundary_alg = select_algorithm(leading_boundary, env₀; boundary_kwargs...) end + # C4vCTMRG-specific defaults + if boundary_alg isa C4vCTMRG + # use :linsolver GradMode since :eigsolver tends to have hiccups + if gradient_alg isa NamedTuple + haskey(gradient_alg, :alg) || (gradient_alg = merge((; alg = :linsolver), gradient_alg)) + end + # symmetrize state and gradient + if isnothing(symmetrization) + symmetrization = RotateReflect() + end + end + # adjust gradient verbosity if gradient_alg isa NamedTuple # TODO: check this: @@ -45,10 +57,6 @@ function select_algorithm( optimizer_alg = merge(defaults, optimizer_alg) end - # symmetrize state and gradient when doing C4v optimization - if boundary_alg isa C4vCTMRG && isnothing(symmetrization) - symmetrization = RotateReflect() - end return PEPSOptimize(; boundary_alg, gradient_alg, optimizer_alg, symmetrization, kwargs...) end From 8e3576b12f0bb89d0a60afce234af6240e2cb563 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Wed, 25 Feb 2026 12:54:03 +0100 Subject: [PATCH 07/11] Update changelog --- docs/src/changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/changelog.md b/docs/src/changelog.md index c177aa005..041d13df0 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -25,6 +25,7 @@ When releasing a new version, move the "Unreleased" changes to a new version sec ### Changed - Bump OptimKit.jl compatibility to v0.4 +- Move `info.truncation_error` and `info.condition_number` into the `info.convergence_metrics` named tuple for `leading_boundary` and `fixedpoint` ### Deprecated From b4ad8ef1f98d1cb3bb7abd27ecac01160410ca87 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Wed, 25 Feb 2026 13:16:59 +0100 Subject: [PATCH 08/11] Rerender Heisenberg example --- docs/src/changelog.md | 2 +- docs/src/examples/heisenberg/index.md | 195 ++++++++++++------------ docs/src/examples/heisenberg/main.ipynb | 16 +- examples/Cache.toml | 2 +- examples/heisenberg/main.jl | 4 +- src/algorithms/ctmrg/ctmrg.jl | 2 +- 6 files changed, 114 insertions(+), 107 deletions(-) diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 041d13df0..f66e30fc8 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -25,7 +25,7 @@ When releasing a new version, move the "Unreleased" changes to a new version sec ### Changed - Bump OptimKit.jl compatibility to v0.4 -- Move `info.truncation_error` and `info.condition_number` into the `info.convergence_metrics` named tuple for `leading_boundary` and `fixedpoint` +- Move `info.truncation_error` and `info.condition_number` into the `info.contraction_metrics` named tuple for `leading_boundary` and `fixedpoint` ### Deprecated diff --git a/docs/src/examples/heisenberg/index.md b/docs/src/examples/heisenberg/index.md index 298b2ffb9..f38960214 100644 --- a/docs/src/examples/heisenberg/index.md +++ b/docs/src/examples/heisenberg/index.md @@ -118,21 +118,23 @@ env₀, info_ctmrg = leading_boundary(env_random, peps₀; boundary_alg...); ```` [ Info: CTMRG init: obj = -2.749614463601e+00 +3.639628057806e+00im err = 1.0000e+00 -[ Info: CTMRG conv 27: obj = +9.727103564786e+00 err = 2.6201795901e-11 time = 7.98 sec +[ Info: CTMRG conv 27: obj = +9.727103564786e+00 err = 2.6201048445e-11 time = 0.34 sec ```` Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of -informational quantities such as the last maximal truncation error - that is, the SVD -approximation error incurred in the last CTMRG iteration, maximized over all spatial -directions and unit cell entries: +informational quantities which contains, among other things, a `contraction_metric` tuple. +This may contain different quantities depending on the method of contraction, and for this +CTMRG variant we return the last maximal truncation error (the SVD approximation +error maximized over all spatial directions and unit cell entries) as well as the condition +number of the decomposition (the ratio of largest to smallest singular value): ````julia -@show info_ctmrg.truncation_error; +@show info_ctmrg.contraction_metrics; ```` ```` -info_ctmrg.truncation_error = 0.0008076332823860801 +info_ctmrg.contraction_metrics = (truncation_error = 0.00080763328242187, condition_number = 1.0752351780901926e10) ```` @@ -149,88 +151,88 @@ peps, env, E, info_opt = fixedpoint( ```` ```` -[ Info: LBFGS: initializing with f = 6.016453104343e-04, ‖∇f‖ = 9.3548e-01 -[ Info: LBFGS: iter 1, Δt 4.52 s: f = -4.897965192207e-01, ‖∇f‖ = 6.0022e-01, α = 5.94e+01, m = 0, nfg = 5 -[ Info: LBFGS: iter 2, Δt 1.55 s: f = -5.019846341173e-01, ‖∇f‖ = 5.3738e-01, α = 2.80e-01, m = 1, nfg = 2 -[ Info: LBFGS: iter 3, Δt 328.4 ms: f = -5.231639258984e-01, ‖∇f‖ = 3.9927e-01, α = 1.00e+00, m = 2, nfg = 1 -[ Info: LBFGS: iter 4, Δt 842.4 ms: f = -5.386543628560e-01, ‖∇f‖ = 4.1552e-01, α = 2.29e-01, m = 3, nfg = 2 -[ Info: LBFGS: iter 5, Δt 2.49 s: f = -5.498211821771e-01, ‖∇f‖ = 4.4002e-01, α = 6.90e-02, m = 4, nfg = 4 -[ Info: LBFGS: iter 6, Δt 850.0 ms: f = -5.690169518488e-01, ‖∇f‖ = 4.8450e-01, α = 2.26e-01, m = 5, nfg = 2 -[ Info: LBFGS: iter 7, Δt 325.7 ms: f = -5.871277303926e-01, ‖∇f‖ = 4.1970e-01, α = 1.00e+00, m = 6, nfg = 1 -[ Info: LBFGS: iter 8, Δt 319.8 ms: f = -6.001554483426e-01, ‖∇f‖ = 2.1792e-01, α = 1.00e+00, m = 7, nfg = 1 -[ Info: LBFGS: iter 9, Δt 305.8 ms: f = -6.068835686463e-01, ‖∇f‖ = 1.9566e-01, α = 1.00e+00, m = 8, nfg = 1 -[ Info: LBFGS: iter 10, Δt 276.9 ms: f = -6.250397748968e-01, ‖∇f‖ = 3.0330e-01, α = 1.00e+00, m = 9, nfg = 1 -[ Info: LBFGS: iter 11, Δt 282.8 ms: f = -6.391659645908e-01, ‖∇f‖ = 2.3075e-01, α = 1.00e+00, m = 10, nfg = 1 -[ Info: LBFGS: iter 12, Δt 392.4 ms: f = -6.471793388973e-01, ‖∇f‖ = 2.6051e-01, α = 1.00e+00, m = 11, nfg = 1 -[ Info: LBFGS: iter 13, Δt 724.4 ms: f = -6.503370671505e-01, ‖∇f‖ = 1.6112e-01, α = 1.00e+00, m = 12, nfg = 1 -[ Info: LBFGS: iter 14, Δt 322.8 ms: f = -6.546061020085e-01, ‖∇f‖ = 7.7751e-02, α = 1.00e+00, m = 13, nfg = 1 -[ Info: LBFGS: iter 15, Δt 237.3 ms: f = -6.559626422861e-01, ‖∇f‖ = 5.1323e-02, α = 1.00e+00, m = 14, nfg = 1 -[ Info: LBFGS: iter 16, Δt 261.0 ms: f = -6.570346071528e-01, ‖∇f‖ = 5.6661e-02, α = 1.00e+00, m = 15, nfg = 1 -[ Info: LBFGS: iter 17, Δt 263.3 ms: f = -6.586101879490e-01, ‖∇f‖ = 4.5250e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 18, Δt 248.0 ms: f = -6.594209589994e-01, ‖∇f‖ = 4.8923e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 19, Δt 263.4 ms: f = -6.595831316360e-01, ‖∇f‖ = 5.7833e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 20, Δt 268.8 ms: f = -6.598106808006e-01, ‖∇f‖ = 1.7741e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 21, Δt 256.8 ms: f = -6.598737940556e-01, ‖∇f‖ = 1.4673e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 22, Δt 264.8 ms: f = -6.600721854328e-01, ‖∇f‖ = 1.9298e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 23, Δt 254.1 ms: f = -6.602319074023e-01, ‖∇f‖ = 1.7538e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 24, Δt 273.3 ms: f = -6.603792430521e-01, ‖∇f‖ = 2.3872e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 25, Δt 263.2 ms: f = -6.604617775509e-01, ‖∇f‖ = 2.3385e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 26, Δt 258.8 ms: f = -6.605536696759e-01, ‖∇f‖ = 1.2672e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 27, Δt 257.1 ms: f = -6.606169735172e-01, ‖∇f‖ = 1.0506e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 28, Δt 285.6 ms: f = -6.608141517158e-01, ‖∇f‖ = 1.8075e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 29, Δt 305.3 ms: f = -6.609609491552e-01, ‖∇f‖ = 1.7508e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 30, Δt 796.4 ms: f = -6.610389180525e-01, ‖∇f‖ = 1.1325e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 31, Δt 328.4 ms: f = -6.610873060103e-01, ‖∇f‖ = 1.0269e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 32, Δt 254.5 ms: f = -6.611212029182e-01, ‖∇f‖ = 8.8756e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 33, Δt 281.7 ms: f = -6.611799456772e-01, ‖∇f‖ = 1.1435e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 34, Δt 553.2 ms: f = -6.612071690766e-01, ‖∇f‖ = 8.8858e-03, α = 5.30e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 35, Δt 285.6 ms: f = -6.612262681103e-01, ‖∇f‖ = 6.4795e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 36, Δt 295.0 ms: f = -6.612605080039e-01, ‖∇f‖ = 5.8879e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 37, Δt 285.7 ms: f = -6.612675983705e-01, ‖∇f‖ = 1.2007e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 38, Δt 278.1 ms: f = -6.612837466720e-01, ‖∇f‖ = 4.9256e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 39, Δt 275.6 ms: f = -6.612924155095e-01, ‖∇f‖ = 4.6090e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 40, Δt 273.9 ms: f = -6.613078556647e-01, ‖∇f‖ = 6.2724e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 41, Δt 282.3 ms: f = -6.613407946569e-01, ‖∇f‖ = 8.9187e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 42, Δt 293.4 ms: f = -6.614147324894e-01, ‖∇f‖ = 1.6921e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 43, Δt 310.8 ms: f = -6.614896605795e-01, ‖∇f‖ = 2.7701e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 44, Δt 289.7 ms: f = -6.616600115097e-01, ‖∇f‖ = 2.0288e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 45, Δt 377.8 ms: f = -6.618744649549e-01, ‖∇f‖ = 2.2589e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 46, Δt 739.3 ms: f = -6.619293873126e-01, ‖∇f‖ = 2.6087e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 47, Δt 320.0 ms: f = -6.620580680546e-01, ‖∇f‖ = 1.8561e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 48, Δt 607.9 ms: f = -6.621418094892e-01, ‖∇f‖ = 2.1694e-02, α = 5.08e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 49, Δt 299.7 ms: f = -6.622424140119e-01, ‖∇f‖ = 1.4693e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 50, Δt 317.6 ms: f = -6.623561643274e-01, ‖∇f‖ = 1.5643e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 51, Δt 325.3 ms: f = -6.624189189954e-01, ‖∇f‖ = 1.2526e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 52, Δt 322.8 ms: f = -6.624484647013e-01, ‖∇f‖ = 7.7875e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 53, Δt 302.8 ms: f = -6.624620825387e-01, ‖∇f‖ = 7.2801e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 54, Δt 297.0 ms: f = -6.624761506291e-01, ‖∇f‖ = 5.6893e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 55, Δt 302.8 ms: f = -6.624920797996e-01, ‖∇f‖ = 7.4763e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 56, Δt 618.9 ms: f = -6.624974230146e-01, ‖∇f‖ = 3.9289e-03, α = 5.46e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 57, Δt 288.3 ms: f = -6.624993982624e-01, ‖∇f‖ = 3.0506e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 58, Δt 284.2 ms: f = -6.625033254432e-01, ‖∇f‖ = 2.2061e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 59, Δt 300.0 ms: f = -6.625068780651e-01, ‖∇f‖ = 2.0862e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 60, Δt 812.0 ms: f = -6.625094238841e-01, ‖∇f‖ = 3.0782e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 61, Δt 314.7 ms: f = -6.625108313560e-01, ‖∇f‖ = 1.9160e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 62, Δt 248.5 ms: f = -6.625115537204e-01, ‖∇f‖ = 8.6226e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 63, Δt 261.4 ms: f = -6.625118952372e-01, ‖∇f‖ = 7.1198e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 64, Δt 273.4 ms: f = -6.625122637335e-01, ‖∇f‖ = 6.9776e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 65, Δt 263.1 ms: f = -6.625125878909e-01, ‖∇f‖ = 1.1757e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 66, Δt 278.5 ms: f = -6.625129012017e-01, ‖∇f‖ = 6.1076e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 67, Δt 275.1 ms: f = -6.625131620795e-01, ‖∇f‖ = 6.7509e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 68, Δt 287.4 ms: f = -6.625134659017e-01, ‖∇f‖ = 7.4076e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 69, Δt 585.2 ms: f = -6.625136173027e-01, ‖∇f‖ = 1.0650e-03, α = 4.63e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 70, Δt 297.3 ms: f = -6.625138093900e-01, ‖∇f‖ = 5.3214e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 71, Δt 267.8 ms: f = -6.625138941594e-01, ‖∇f‖ = 4.9455e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 72, Δt 275.5 ms: f = -6.625139584721e-01, ‖∇f‖ = 4.6079e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 73, Δt 270.4 ms: f = -6.625140156102e-01, ‖∇f‖ = 3.5058e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 74, Δt 280.5 ms: f = -6.625140884579e-01, ‖∇f‖ = 7.7069e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 75, Δt 282.6 ms: f = -6.625141400523e-01, ‖∇f‖ = 6.5839e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 76, Δt 267.8 ms: f = -6.625141806040e-01, ‖∇f‖ = 3.1793e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 77, Δt 822.8 ms: f = -6.625142155106e-01, ‖∇f‖ = 2.0830e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 78, Δt 263.1 ms: f = -6.625142398464e-01, ‖∇f‖ = 1.8962e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 79, Δt 253.8 ms: f = -6.625142606414e-01, ‖∇f‖ = 2.6019e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 80, Δt 262.8 ms: f = -6.625142658376e-01, ‖∇f‖ = 2.4559e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: converged after 81 iterations and time 5.83 m: f = -6.625142736963e-01, ‖∇f‖ = 9.4632e-05 +[ Info: LBFGS: initializing with f = 6.016453104372e-04, ‖∇f‖ = 9.3548e-01 +[ Info: LBFGS: iter 1, Δt 5.62 s: f = -4.897965201565e-01, ‖∇f‖ = 6.0022e-01, α = 5.94e+01, m = 0, nfg = 5 +[ Info: LBFGS: iter 2, Δt 1.04 s: f = -5.019846351509e-01, ‖∇f‖ = 5.3738e-01, α = 2.80e-01, m = 1, nfg = 2 +[ Info: LBFGS: iter 3, Δt 342.4 ms: f = -5.231639268904e-01, ‖∇f‖ = 3.9927e-01, α = 1.00e+00, m = 2, nfg = 1 +[ Info: LBFGS: iter 4, Δt 747.3 ms: f = -5.386543630134e-01, ‖∇f‖ = 4.1552e-01, α = 2.29e-01, m = 3, nfg = 2 +[ Info: LBFGS: iter 5, Δt 2.15 s: f = -5.498211740486e-01, ‖∇f‖ = 4.4002e-01, α = 6.90e-02, m = 4, nfg = 4 +[ Info: LBFGS: iter 6, Δt 922.3 ms: f = -5.690169637654e-01, ‖∇f‖ = 4.8450e-01, α = 2.26e-01, m = 5, nfg = 2 +[ Info: LBFGS: iter 7, Δt 342.6 ms: f = -5.871277574299e-01, ‖∇f‖ = 4.1970e-01, α = 1.00e+00, m = 6, nfg = 1 +[ Info: LBFGS: iter 8, Δt 1.27 s: f = -6.001554858779e-01, ‖∇f‖ = 2.1792e-01, α = 1.00e+00, m = 7, nfg = 1 +[ Info: LBFGS: iter 9, Δt 334.8 ms: f = -6.068836018580e-01, ‖∇f‖ = 1.9566e-01, α = 1.00e+00, m = 8, nfg = 1 +[ Info: LBFGS: iter 10, Δt 330.7 ms: f = -6.250397688400e-01, ‖∇f‖ = 3.0330e-01, α = 1.00e+00, m = 9, nfg = 1 +[ Info: LBFGS: iter 11, Δt 251.4 ms: f = -6.391660376636e-01, ‖∇f‖ = 2.3075e-01, α = 1.00e+00, m = 10, nfg = 1 +[ Info: LBFGS: iter 12, Δt 267.4 ms: f = -6.471796195686e-01, ‖∇f‖ = 2.6051e-01, α = 1.00e+00, m = 11, nfg = 1 +[ Info: LBFGS: iter 13, Δt 226.5 ms: f = -6.503370025252e-01, ‖∇f‖ = 1.6112e-01, α = 1.00e+00, m = 12, nfg = 1 +[ Info: LBFGS: iter 14, Δt 254.5 ms: f = -6.546061095107e-01, ‖∇f‖ = 7.7752e-02, α = 1.00e+00, m = 13, nfg = 1 +[ Info: LBFGS: iter 15, Δt 266.9 ms: f = -6.559626479096e-01, ‖∇f‖ = 5.1323e-02, α = 1.00e+00, m = 14, nfg = 1 +[ Info: LBFGS: iter 16, Δt 267.1 ms: f = -6.570345925072e-01, ‖∇f‖ = 5.6663e-02, α = 1.00e+00, m = 15, nfg = 1 +[ Info: LBFGS: iter 17, Δt 260.7 ms: f = -6.586101542992e-01, ‖∇f‖ = 4.5249e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 18, Δt 273.4 ms: f = -6.594210783037e-01, ‖∇f‖ = 4.8908e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 19, Δt 270.6 ms: f = -6.595829407862e-01, ‖∇f‖ = 5.7868e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 20, Δt 261.5 ms: f = -6.598106978631e-01, ‖∇f‖ = 1.7743e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 21, Δt 267.3 ms: f = -6.598737919822e-01, ‖∇f‖ = 1.4674e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 22, Δt 256.5 ms: f = -6.600722399901e-01, ‖∇f‖ = 1.9297e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 23, Δt 264.3 ms: f = -6.602319320307e-01, ‖∇f‖ = 1.7537e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 24, Δt 264.5 ms: f = -6.603792234693e-01, ‖∇f‖ = 2.3875e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 25, Δt 276.0 ms: f = -6.604618342679e-01, ‖∇f‖ = 2.3372e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 26, Δt 1.23 s: f = -6.605536670251e-01, ‖∇f‖ = 1.2672e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 27, Δt 267.2 ms: f = -6.606170020178e-01, ‖∇f‖ = 1.0507e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 28, Δt 298.9 ms: f = -6.608142109072e-01, ‖∇f‖ = 1.8082e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 29, Δt 328.6 ms: f = -6.609609278098e-01, ‖∇f‖ = 1.7516e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 30, Δt 249.0 ms: f = -6.610389074905e-01, ‖∇f‖ = 1.1313e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 31, Δt 266.7 ms: f = -6.610872582358e-01, ‖∇f‖ = 1.0263e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 32, Δt 243.8 ms: f = -6.611211815134e-01, ‖∇f‖ = 8.8770e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 33, Δt 273.6 ms: f = -6.611798467656e-01, ‖∇f‖ = 1.1488e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 34, Δt 589.4 ms: f = -6.612071948177e-01, ‖∇f‖ = 8.8666e-03, α = 5.31e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 35, Δt 312.8 ms: f = -6.612262742065e-01, ‖∇f‖ = 6.4670e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 36, Δt 309.1 ms: f = -6.612605505781e-01, ‖∇f‖ = 5.8761e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 37, Δt 296.5 ms: f = -6.612675206044e-01, ‖∇f‖ = 1.2105e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 38, Δt 311.6 ms: f = -6.612838274236e-01, ‖∇f‖ = 4.9173e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 39, Δt 297.0 ms: f = -6.612924065028e-01, ‖∇f‖ = 4.5918e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 40, Δt 302.3 ms: f = -6.613079391530e-01, ‖∇f‖ = 6.2780e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 41, Δt 309.7 ms: f = -6.613408205522e-01, ‖∇f‖ = 8.9067e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 42, Δt 310.3 ms: f = -6.614138147418e-01, ‖∇f‖ = 1.7166e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 43, Δt 340.2 ms: f = -6.614875520889e-01, ‖∇f‖ = 2.7427e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 44, Δt 373.1 ms: f = -6.616598996952e-01, ‖∇f‖ = 1.9056e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 45, Δt 399.3 ms: f = -6.618786556444e-01, ‖∇f‖ = 2.2180e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 46, Δt 1.39 s: f = -6.619400903666e-01, ‖∇f‖ = 2.5707e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 47, Δt 319.4 ms: f = -6.620475837462e-01, ‖∇f‖ = 1.8971e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 48, Δt 415.2 ms: f = -6.621064283010e-01, ‖∇f‖ = 3.7601e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 49, Δt 402.7 ms: f = -6.622530651429e-01, ‖∇f‖ = 1.3384e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 50, Δt 335.8 ms: f = -6.623266509915e-01, ‖∇f‖ = 1.1681e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 51, Δt 368.6 ms: f = -6.623900625629e-01, ‖∇f‖ = 1.0879e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 52, Δt 400.5 ms: f = -6.624417840065e-01, ‖∇f‖ = 1.3536e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 53, Δt 843.4 ms: f = -6.624657232439e-01, ‖∇f‖ = 8.4312e-03, α = 4.80e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 54, Δt 417.5 ms: f = -6.624781165452e-01, ‖∇f‖ = 5.0930e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 55, Δt 420.6 ms: f = -6.624880687095e-01, ‖∇f‖ = 5.2557e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 56, Δt 407.4 ms: f = -6.624977042182e-01, ‖∇f‖ = 3.7286e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 57, Δt 452.2 ms: f = -6.625008746110e-01, ‖∇f‖ = 3.0276e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 58, Δt 407.0 ms: f = -6.625030255855e-01, ‖∇f‖ = 2.4305e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 59, Δt 404.5 ms: f = -6.625070516495e-01, ‖∇f‖ = 2.1048e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 60, Δt 416.0 ms: f = -6.625095242229e-01, ‖∇f‖ = 2.1471e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 61, Δt 815.1 ms: f = -6.625106856424e-01, ‖∇f‖ = 1.7835e-03, α = 5.47e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 62, Δt 375.8 ms: f = -6.625114666348e-01, ‖∇f‖ = 9.0132e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 63, Δt 367.3 ms: f = -6.625118764288e-01, ‖∇f‖ = 8.0255e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 64, Δt 1.29 s: f = -6.625122687065e-01, ‖∇f‖ = 9.0615e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 65, Δt 274.7 ms: f = -6.625126290506e-01, ‖∇f‖ = 8.0460e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 66, Δt 337.3 ms: f = -6.625129211222e-01, ‖∇f‖ = 6.8501e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 67, Δt 360.9 ms: f = -6.625132419353e-01, ‖∇f‖ = 9.0265e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 68, Δt 310.6 ms: f = -6.625134633026e-01, ‖∇f‖ = 7.9160e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 69, Δt 311.3 ms: f = -6.625136591289e-01, ‖∇f‖ = 5.0828e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 70, Δt 324.8 ms: f = -6.625138308035e-01, ‖∇f‖ = 7.9904e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 71, Δt 658.4 ms: f = -6.625138950807e-01, ‖∇f‖ = 4.3784e-04, α = 5.13e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 72, Δt 330.0 ms: f = -6.625139324941e-01, ‖∇f‖ = 3.5191e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 73, Δt 377.8 ms: f = -6.625140365412e-01, ‖∇f‖ = 2.7327e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 74, Δt 674.0 ms: f = -6.625140701012e-01, ‖∇f‖ = 7.1588e-04, α = 4.32e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 75, Δt 346.5 ms: f = -6.625141329298e-01, ‖∇f‖ = 4.5959e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 76, Δt 343.8 ms: f = -6.625141933640e-01, ‖∇f‖ = 2.3876e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 77, Δt 343.9 ms: f = -6.625142295649e-01, ‖∇f‖ = 1.7163e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 78, Δt 342.5 ms: f = -6.625142520304e-01, ‖∇f‖ = 1.3279e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 79, Δt 349.1 ms: f = -6.625142665992e-01, ‖∇f‖ = 2.8569e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 80, Δt 329.9 ms: f = -6.625142803082e-01, ‖∇f‖ = 1.2759e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: converged after 81 iterations and time 6.94 m: f = -6.625142855970e-01, ‖∇f‖ = 7.7033e-05 ```` @@ -244,8 +246,8 @@ the convergence rate: ```` ```` -info_opt.fg_evaluations = 96 -info_opt.gradnorms[1:10:end] = [0.9354752030131099, 0.3033019277899899, 0.017741463681835545, 0.01132472701425422, 0.006272379430806119, 0.015643014849711687, 0.003078240790192421, 0.000532137892512568, 0.0002455878974975024] +info_opt.fg_evaluations = 97 +info_opt.gradnorms[1:10:end] = [0.9354752017271177, 0.3033034076782405, 0.017742662111911257, 0.011312825498690943, 0.0062779819357426676, 0.011680613608174078, 0.0021471423320920044, 0.0007990427093226254, 0.0001275947945785803] ```` @@ -258,7 +260,7 @@ $E_{\text{ref}}=−0.6694421$. From our simple optimization we find: ```` ```` -E = -0.6625142736962993 +E = -0.6625142855969753 ```` @@ -285,8 +287,8 @@ correlation lengths and transfer matrix spectra for all unit cell coordinates: ```` ```` -ξ_h = [1.0345801030391306] -ξ_v = [1.0245361358882241] +ξ_h = [1.0343404931444404] +ξ_v = [1.0242351103541054] ```` @@ -304,7 +306,10 @@ need to define the observable as a `TensorMap`: 2←2 TensorMap{Float64, TensorKit.ComplexSpace, 1, 1, Vector{Float64}}: codomain: ⊗(ℂ^2) domain: ⊗(ℂ^2) - + blocks: + * Trivial() => 2×2 reshape(view(::Vector{Float64}, 1:4), 2, 2) with eltype Float64: + 1.0 0.0 + 0.0 -1.0 ```` In order to be able to contract it with the PEPS and environment, we define need to define a @@ -328,7 +333,7 @@ Finally, to evaluate the expecation value on the `LocalOperator`, we call: ```` ```` -expectation_value(peps, M, env) = -0.7533445046064892 - 1.5265566588595902e-16im +expectation_value(peps, M, env) = -0.7532893440072446 - 4.85722573273506e-17im ```` diff --git a/docs/src/examples/heisenberg/main.ipynb b/docs/src/examples/heisenberg/main.ipynb index a1731e7f4..54fb6f083 100644 --- a/docs/src/examples/heisenberg/main.ipynb +++ b/docs/src/examples/heisenberg/main.ipynb @@ -204,9 +204,11 @@ "cell_type": "markdown", "source": [ "Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of\n", - "informational quantities such as the last maximal truncation error - that is, the SVD\n", - "approximation error incurred in the last CTMRG iteration, maximized over all spatial\n", - "directions and unit cell entries:" + "informational quantities which contains, among other things, a `contraction_metric` tuple.\n", + "This may contain different quantities depending on the method of contraction, and for this\n", + "CTMRG variant we return the last maximal truncation error (the SVD approximation\n", + "error maximized over all spatial directions and unit cell entries) as well as the condition\n", + "number of the decomposition (the ratio of largest to smallest singular value):" ], "metadata": {} }, @@ -214,7 +216,7 @@ "outputs": [], "cell_type": "code", "source": [ - "@show info_ctmrg.truncation_error;" + "@show info_ctmrg.contraction_metrics;" ], "metadata": {}, "execution_count": null @@ -382,11 +384,11 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.11.7" + "version": "1.12.5" }, "kernelspec": { - "name": "julia-1.11", - "display_name": "Julia 1.11.7", + "name": "julia-1.12", + "display_name": "Julia 1.12.5", "language": "julia" } }, diff --git a/examples/Cache.toml b/examples/Cache.toml index 195db707d..f0e59d007 100644 --- a/examples/Cache.toml +++ b/examples/Cache.toml @@ -7,4 +7,4 @@ heisenberg_su = "3eb8556d949c0e47e39c679e9e438bc04d3e2a3ffe73e0a682963b37b05f9e9 xxz = "0231f0c1af2013e8edd9e5c192b108e1ab19a7dca22251c3bde525e3eee2a6aa" fermi_hubbard = "4997680c826e555557c661e605e1d7d363e0cee15522d0895fa0cfd53b1de001" j1j2_su = "c00fd13c0be323ab5825af59f3e7b31c3e51d3f65211d3836657b64274504c1c" -heisenberg = "d610c92223d41e296348f9858fab52eacbfe2a578f64f4f8ac4c70d486fb4da2" +heisenberg = "80bb9cc57ed85297b1b789a6c5f09494dac81b23631f48c6600ede9424c5d248" diff --git a/examples/heisenberg/main.jl b/examples/heisenberg/main.jl index fa77c4369..3f0139126 100644 --- a/examples/heisenberg/main.jl +++ b/examples/heisenberg/main.jl @@ -102,14 +102,14 @@ env₀, info_ctmrg = leading_boundary(env_random, peps₀; boundary_alg...); md""" Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of -informational quantities which contains, among other things, a `convergence_metric` tuple. +informational quantities which contains, among other things, a `contraction_metric` tuple. This may contain different quantities depending on the method of contraction, and for this CTMRG variant we return the last maximal truncation error (the SVD approximation error maximized over all spatial directions and unit cell entries) as well as the condition number of the decomposition (the ratio of largest to smallest singular value): """ -@show info_ctmrg.convergence_metrics; +@show info_ctmrg.contraction_metrics; md""" ## Ground state search diff --git a/src/algorithms/ctmrg/ctmrg.jl b/src/algorithms/ctmrg/ctmrg.jl index 7e60be309..839e32a43 100644 --- a/src/algorithms/ctmrg/ctmrg.jl +++ b/src/algorithms/ctmrg/ctmrg.jl @@ -89,7 +89,7 @@ supplied via the keyword arguments or directly as an [`CTMRGAlgorithm`](@ref) st ## Return values The `leading_boundary` routine returns the final environment as well as an information `NamedTuple` -that generally contains a `convergence_metrics` `NamedTuple` storing different contents depending +that generally contains a `contraction_metrics` `NamedTuple` storing different contents depending on the chosen `alg`. Depending on the contraction method, the information tuple may also contain the final tensor decomposition (used in the projectors) including its truncation indices. """ From f7b2445eee6c2bcf57042d2f3b1f188d838c9da1 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Wed, 25 Feb 2026 13:18:49 +0100 Subject: [PATCH 09/11] Alter seed to make QR-CTMRG not hickup --- test/examples/heisenberg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index 228a60a63..6abb4146b 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -53,7 +53,7 @@ end @testset "C4v AD optimization with scalartype T=$T and projector_alg=$projector_alg" for (T, projector_alg) in Iterators.product([Float64, ComplexF64], [:c4v_eigh, :c4v_qr]) # initialize symmetric states - Random.seed!(123) + Random.seed!(12345) symm = RotateReflect() H′ = heisenberg_XYZ_c4v(InfiniteSquare()) H = T <: Real ? real(H′) : H′ From 9a83bc75bf5437f68dafe51ea5309d317562ab92 Mon Sep 17 00:00:00 2001 From: Lander Burgelman <39218680+leburgel@users.noreply.github.com> Date: Tue, 3 Mar 2026 07:38:38 +0100 Subject: [PATCH 10/11] Update src/algorithms/optimization/peps_optimization.jl Co-authored-by: Lukas Devos --- src/algorithms/optimization/peps_optimization.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index 5bec2c228..3b9bed143 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -242,7 +242,7 @@ Check compatibility of an initial PEPS and environment with a specified PEPS opt function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize) end function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG, <:GradMode{:fixed}}) if scalartype(env₀) <: Real # :fixed mode gauge fixing is incompatible with real environments - msg = "the provided real environment is in compatible with :fixed mode \ + msg = "the provided real environment is incompatible with :fixed mode \ since :fixed mode generally produces complex gauges; use :diffgauge mode \ instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ keyword arguments to work with purely real environments and asymmetric CTMRG" From aeeed9d8a6d9a7cd4b8b44902fd525847b898c09 Mon Sep 17 00:00:00 2001 From: Paul Brehmer Date: Tue, 3 Mar 2026 14:12:59 +0100 Subject: [PATCH 11/11] Add symmetrization to `_check_algorithm_combination` --- .../fixed_point_differentiation.jl | 22 +++++++++++++++---- .../optimization/peps_optimization.jl | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/algorithms/optimization/fixed_point_differentiation.jl b/src/algorithms/optimization/fixed_point_differentiation.jl index faf25c04d..b5c47f979 100644 --- a/src/algorithms/optimization/fixed_point_differentiation.jl +++ b/src/algorithms/optimization/fixed_point_differentiation.jl @@ -201,13 +201,19 @@ EigSolver(; kwargs...) = GradMode(; alg = :eigsolver, kwargs...) GRADIENT_MODE_SYMBOLS[:eigsolver] = EigSolver """ - _check_algorithm_combination(boundary_alg, gradient_alg) + _check_algorithm_combination(boundary_alg, gradient_alg_or_symmetrization) + _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) Check for allowed combinations of gradient algorithm and boundary algorithm to be used for computing the gradient of a `leading_boundary` call. Throws an error containing a recommended fix if the combination is not allowed or broken. """ -function _check_algorithm_combination(boundary_alg, gradient_alg) end +function _check_algorithm_combination(boundary_alg, gradient_alg_or_symmetrization) end +function _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) + _check_algorithm_combination(boundary_alg, gradient_alg) + _check_algorithm_combination(boundary_alg, symmetrization) + return nothing +end function _check_algorithm_combination(::SequentialCTMRG, ::GradMode{:fixed}) msg = "`:fixed` mode is not compatible with `SequentialCTMRG` since the sequential \ application of SVDs does not allow to differentiate through a fixed set of \ @@ -216,10 +222,18 @@ function _check_algorithm_combination(::SequentialCTMRG, ::GradMode{:fixed}) end function _check_algorithm_combination(::C4vCTMRG{<:C4vEighProjector}, ::GradMode{:diffgauge}) msg = "`:diffgauge` mode is currently not compatible with eigh-based C4v CTMRG; \ - either switch to a different projector algorithm (e.g. `c4v_qr`), or use :fixed \ - mode for differentiation instead." + either switch to a different projector algorithm (e.g. `c4v_qr`), or use :fixed \ + mode for differentiation instead." throw(ArgumentError(msg)) end +function _check_algorithm_combination(::C4vCTMRG, symm::Union{Nothing, <:SymmetrizationStyle}) + if !(symm isa RotateReflect) + msg = "C4vCTMRG optimization is compatible only with RotateReflect symmetrization. \ + Make sure to set `symmetrization = RotateReflect()`." + throw(ArgumentError(msg)) + end + return nothing +end #= Evaluating the gradient of the cost function for CTMRG: diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index 3b9bed143..db9acb72a 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -31,7 +31,7 @@ struct PEPSOptimize{B, G} boundary_alg::B, gradient_alg::G, optimizer_alg, reuse_env, symmetrization, ) where {B, G} - _check_algorithm_combination(boundary_alg, gradient_alg) + _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) return new{B, G}(boundary_alg, gradient_alg, optimizer_alg, reuse_env, symmetrization) end end