-
Notifications
You must be signed in to change notification settings - Fork 27
Add C4v CTMRG #321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Add C4v CTMRG #321
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
61a88c1
Generalize environment gauge fixing
pbrehmer 0ec910b
Add C4v CTMRG algorithm
pbrehmer 7256f3f
Add C4v CTMRG rrules and defaults
pbrehmer 1a326b9
Fix tensor decompositions
pbrehmer 23c1610
Fix parameter selection
pbrehmer 0a475fe
Make some tests runnable
pbrehmer 094af8c
Fix some more stuff and add fixed_iterscheme C4v test
pbrehmer a6ce108
Comment out QR things for now
pbrehmer 97760e8
Add gauge fixing and partition function C4v tests
pbrehmer 6effabe
Fix differentiability and add C4v Heisenberg test
pbrehmer 089a005
Automatically symmetrize optimization when alg=:c4v
pbrehmer f3d89e1
Fix unitcell test imports
pbrehmer fcdea38
Add eigh_wrapper test and fix IterEigh
pbrehmer 7905570
Fix eigh_wrapper test imports
Yue-Zhengyuan 30f484f
Update src/algorithms/ctmrg/gaugefix.jl
pbrehmer ee0b5e2
Rename to decomposition algorithm to `decomp_alg`
pbrehmer f4df969
Fix partition function test import
pbrehmer 0968a4c
Update docstrings to `decomp_alg`
pbrehmer 7651853
Fix flavors test import
pbrehmer 461402e
Add docstrings
pbrehmer 9a7f460
Fix `c4v_projector`
pbrehmer e2ea8dd
Update docstrings
pbrehmer 3b9d769
Fix `:full` eigh pullback
pbrehmer 2f109f0
Rename `decomp_alg` back to `decomposition_alg`
pbrehmer e8ea503
Update `initialize_random_c4v_env` and export
pbrehmer 9fb5000
Add singlet corner C4v initialization function
pbrehmer 43679c5
Merge remote-tracking branch 'upstream/master' into c4v-ctmrg
Yue-Zhengyuan 4a39c6e
Rename `project_hermitian` to `hermitian_project`
pbrehmer e603c04
Improve `isfulleig`
pbrehmer 08a1204
Remove QR file
pbrehmer abab399
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer 0f6b5c0
Rename `U` to `V` in eigendecomposition (consistent with MAK)
pbrehmer b182d90
Omit docstring type annotation
pbrehmer 09b98c4
Move all imports to `src/PEPSKit.jl`
pbrehmer f07d268
Fix U->V relabeling
pbrehmer 71371e5
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer c094446
Fix SVD test
pbrehmer f7d1111
Move KrylovKitCRCExt to SVD file
pbrehmer f262a48
Fix `IterEigh` fixed_iterscheme test
pbrehmer fbbdaa0
Fix fixed_iterscheme test imports
Yue-Zhengyuan 3f22fc4
Update fixed_iterscheme test
pbrehmer ea6e601
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer fd46a73
Remove redundant import
pbrehmer defc782
Update fixed_iterscheme test for the 10000th time
pbrehmer 483742b
Add Hermitian projection to `c4v_renormalize`
pbrehmer e580451
Rename `hermitian_project` to `_project_hermitian`
pbrehmer cef1161
Use `north_virtualspace` instead of `domain`
pbrehmer cdd8aa2
Add TODO
pbrehmer 6960981
Adjust signature of `fix_global_phases`
pbrehmer c00129f
Fix `north_virtualspace` adjointness
pbrehmer 76954b8
Change function argument order of `gauge_fix(env, ...)`
pbrehmer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,238 @@ | ||
| """ | ||
| $(TYPEDEF) | ||
|
|
||
| CTMRG algorithm assuming a C₄ᵥ-symmetric PEPS, i.e. invariance under 90° spatial rotation and | ||
| Hermitian reflection. This requires a single-site unit cell. The projector is obtained from | ||
| `eigh` decomposing the Hermitian enlarged corner. | ||
|
|
||
| ## Fields | ||
|
|
||
| $(TYPEDFIELDS) | ||
|
|
||
| ## Constructors | ||
|
|
||
| C4vCTMRG(; kwargs...) | ||
|
|
||
| Construct a C₄ᵥ CTMRG algorithm struct based on keyword arguments. | ||
| For a full description, see [`leading_boundary`](@ref). The supported keywords are: | ||
|
|
||
| * `tol::Real=$(Defaults.ctmrg_tol)` | ||
| * `maxiter::Int=$(Defaults.ctmrg_maxiter)` | ||
| * `miniter::Int=$(Defaults.ctmrg_miniter)` | ||
| * `verbosity::Int=$(Defaults.ctmrg_verbosity)` | ||
| * `trunc::Union{TruncationStrategy,NamedTuple}=(; alg::Symbol=:$(Defaults.trunc))` | ||
| * `decomposition_alg::Union{<:EighAdjoint,NamedTuple}` | ||
| * `projector_alg::Symbol=:$(Defaults.projector_alg_c4v)` | ||
| """ | ||
| struct C4vCTMRG{P <: ProjectorAlgorithm} <: CTMRGAlgorithm | ||
| tol::Float64 | ||
| maxiter::Int | ||
| miniter::Int | ||
| verbosity::Int | ||
| projector_alg::P | ||
| end | ||
| function C4vCTMRG(; kwargs...) | ||
| return CTMRGAlgorithm(; alg = :c4v, kwargs...) | ||
| end | ||
| CTMRG_SYMBOLS[:c4v] = C4vCTMRG | ||
|
|
||
| """ | ||
| $(TYPEDEF) | ||
|
|
||
| Projector algorithm implementing the `eigh` decomposition of a Hermitian enlarged corner. | ||
|
|
||
| ## Fields | ||
|
|
||
| $(TYPEDFIELDS) | ||
|
|
||
| ## Constructors | ||
|
|
||
| C4vEighProjector(; kwargs...) | ||
|
|
||
| Construct the C₄ᵥ `eigh`-based projector algorithm based on the following keyword arguments: | ||
|
|
||
| * `decomposition_alg::Union{<:EighAdjoint,NamedTuple}=EighAdjoint()` : `eigh` algorithm including the reverse rule. See [`EighAdjoint`](@ref). | ||
| * `trunc::Union{TruncationStrategy,NamedTuple}=(; alg::Symbol=:$(Defaults.trunc))` : Truncation strategy for the projector computation, which controls the resulting virtual spaces. Here, `alg` can be one of the following: | ||
| - `:fixedspace` : Keep virtual spaces fixed during projection | ||
| - `:notrunc` : No singular values are truncated and the performed SVDs are exact | ||
| - `:truncerror` : Additionally supply error threshold `η`; truncate to the maximal virtual dimension of `η` | ||
| - `:truncrank` : Additionally supply truncation dimension `η`; truncate such that the 2-norm of the truncated values is smaller than `η` | ||
| - `:truncspace` : Additionally supply truncation space `η`; truncate according to the supplied vector space | ||
| - `:trunctol` : Additionally supply singular value cutoff `η`; truncate such that every retained singular value is larger than `η` | ||
| * `verbosity::Int=$(Defaults.projector_verbosity)` : Projector output verbosity which can be: | ||
| 0. Suppress output information | ||
| 1. Print singular value degeneracy warnings | ||
| """ | ||
| struct C4vEighProjector{S <: EighAdjoint, T} <: ProjectorAlgorithm | ||
| decomposition_alg::S | ||
| trunc::T | ||
| verbosity::Int | ||
| end | ||
| function C4vEighProjector(; kwargs...) | ||
| return ProjectorAlgorithm(; alg = :c4v_eigh, kwargs...) | ||
| end | ||
| PROJECTOR_SYMBOLS[:c4v_eigh] = C4vEighProjector | ||
|
|
||
| # struct C4vQRProjector{S, T} <: ProjectorAlgorithm | ||
| # decomposition_alg::S | ||
| # verbosity::Int | ||
| # end | ||
| # function C4vQRProjector(; kwargs...) | ||
| # return ProjectorAlgorithm(; alg = :c4v_qr, kwargs...) | ||
| # end | ||
| # PROJECTOR_SYMBOLS[:c4v_qr] = C4vQRProjector | ||
|
|
||
| # | ||
| ## C4v-symmetric CTMRG iteration (called through `leading_boundary`) | ||
| # | ||
|
|
||
| function ctmrg_iteration( | ||
| network, | ||
| env::CTMRGEnv, | ||
| alg::C4vCTMRG, | ||
| ) | ||
| enlarged_corner = c4v_enlarge(network, env, alg.projector_alg) | ||
| corner′, projector, info = c4v_projector(enlarged_corner, alg.projector_alg) | ||
| edge′ = c4v_renormalize(network, env, projector) | ||
| return CTMRGEnv(corner′, edge′), info | ||
| end | ||
|
|
||
| """ | ||
| c4v_enlarge(network, env, ::C4vEighProjector) | ||
|
|
||
| Compute the normalized and Hermitian-symmetrized C₄ᵥ enlarged corner. | ||
| """ | ||
| function c4v_enlarge(network, env, ::C4vEighProjector) | ||
| enlarged_corner = TensorMap(EnlargedCorner(network, env, (NORTHWEST, 1, 1))) | ||
| return 0.5 * (enlarged_corner + enlarged_corner') / norm(enlarged_corner) | ||
| end | ||
| # function c4v_enlarge(enlarged_corner, alg::C4vQRProjector) | ||
| # # TODO | ||
| # end | ||
|
|
||
| """ | ||
| c4v_projector(enlarged_corner, alg::C4vEighProjector) | ||
|
|
||
| Compute the C₄ᵥ projector from `eigh` decomposing the Hermitian `enlarged_corner`. | ||
| Also return the normalized eigenvalues as the new corner tensor. | ||
| """ | ||
| function c4v_projector(enlarged_corner, alg::C4vEighProjector) | ||
| trunc = truncation_strategy(alg, enlarged_corner) | ||
| D, V, info = eigh_trunc!(enlarged_corner, decomposition_algorithm(alg); trunc) | ||
|
|
||
| # Check for degenerate eigenvalues | ||
| Zygote.isderiving() && ignore_derivatives() do | ||
| if alg.verbosity > 0 && is_degenerate_spectrum(D) | ||
| vals = TensorKit.SectorDict(c => diag(b) for (c, b) in blocks(D)) | ||
| @warn("degenerate eigenvalues detected: ", vals) | ||
| end | ||
| end | ||
|
|
||
| return D / norm(D), V, (; D, V, info...) | ||
| end | ||
| # function c4v_projector(enlarged_corner, alg::C4vQRProjector) | ||
| # # TODO | ||
| # end | ||
|
|
||
| """ | ||
| c4v_renormalize(network, env, projector) | ||
|
|
||
| Renormalize the single edge tensor. | ||
| """ | ||
| function c4v_renormalize(network, env, projector) | ||
| new_edge = renormalize_north_edge(env.edges[1], projector, projector', network[1, 1]) | ||
| new_edge = _project_hermitian(new_edge) # additional Hermitian projection step for numerical stability | ||
| return new_edge / norm(new_edge) | ||
| end | ||
|
|
||
| # TODO: this should eventually be the constructor for a new C4vCTMRGEnv type | ||
| function CTMRGEnv( | ||
| corner::AbstractTensorMap{T, S, 1, 1}, edge::AbstractTensorMap{T′, S, N, 1} | ||
| ) where {T, T′, S, N} | ||
| corners = fill(corner, 4, 1, 1) | ||
| edge_SW = physical_flip(edge) | ||
| edges = reshape([edge, edge, edge_SW, edge_SW], (4, 1, 1)) | ||
| return CTMRGEnv(corners, edges) | ||
| end | ||
|
|
||
| # | ||
| ## utility | ||
| # | ||
|
|
||
| # Adjoint of an edge tensor, but permutes the physical spaces back into the codomain. | ||
| # Intuitively, this conjugates a tensor and then reinterprets its 'direction' as an edge tensor. | ||
| function _dag(A::AbstractTensorMap{T, S, N, 1}) where {T, S, N} | ||
| return permute(A', ((1, (3:(N + 1))...), (2,))) | ||
| end | ||
|
|
||
| function physical_flip(A::AbstractTensorMap{T, S, N, 1}) where {T, S, N} | ||
| return flip(A, 2:N) | ||
| end | ||
|
|
||
| # call it `_project_hermitian` to avoid type piracy with MAK's exported project_hermitian | ||
| function _project_hermitian(E::AbstractTensorMap{T, S, N, 1}) where {T, S, N} | ||
| E´ = (E + physical_flip(_dag(E))) / 2 | ||
| return E´ | ||
| end | ||
| function _project_hermitian(C::AbstractTensorMap{T, S, 1, 1}) where {T, S} | ||
| C´ = (C + C') / 2 | ||
| return C´ | ||
| end | ||
|
|
||
| # should perform this check at the beginning of `leading_boundary` really... | ||
| function check_symmetry(state, ::RotateReflect; atol = 1.0e-10) | ||
| @assert length(state) == 1 "check_symmetry only works for single site unit cells" | ||
| @assert norm(state[1] - _fit_spaces(rotl90(state[1]), state[1])) / | ||
| norm(state[1]) < atol "not rotation invariant" | ||
| @assert norm(state[1] - _fit_spaces(herm_depth(state[1]), state[1])) / | ||
| norm(state[1]) < atol "not hermitian-reflection invariant" | ||
| return nothing | ||
| end | ||
|
|
||
| # | ||
| ## environment initialization | ||
| # | ||
|
|
||
| """ | ||
| initialize_random_c4v_env([f=randn, T=scalartype(state)], state, Venv::ElementarySpace) | ||
|
|
||
| Initialize a C₄ᵥ-symmetric `CTMRGEnv` on virtual spaces `Venv` with random entries created | ||
| by `f` and scalartype `T`. | ||
| """ | ||
| function initialize_random_c4v_env(state, Venv::ElementarySpace) | ||
| return initialize_random_c4v_env(randn, scalartype(state), state, Venv) | ||
| end | ||
| function initialize_random_c4v_env(f, T, state::InfinitePEPS, Venv::ElementarySpace) | ||
| Vpeps = north_virtualspace(state, 1, 1)' | ||
| return initialize_random_c4v_env(f, T, Vpeps ⊗ Vpeps', Venv) | ||
| end | ||
| function initialize_random_c4v_env(f, T, state::InfinitePartitionFunction, Venv::ElementarySpace) | ||
| Vpf = north_virtualspace(state, 1, 1)' | ||
| return initialize_random_c4v_env(f, T, Vpf, Venv) | ||
| end | ||
| function initialize_random_c4v_env(f, T, Vstate::VectorSpace, Venv::ElementarySpace) | ||
| corner₀ = DiagonalTensorMap(randn(real(T), Venv ← Venv)) | ||
| edge₀ = f(T, Venv ⊗ Vstate ← Venv) | ||
| edge₀ = _project_hermitian(edge₀) | ||
| return CTMRGEnv(corner₀, edge₀) | ||
| end | ||
|
|
||
| """ | ||
| initialize_singlet_c4v_env([T=scalartype(state)], state::InfinitePEPS, Venv::ElementarySpace) | ||
|
|
||
| Initialize a C₄ᵥ-symmetric `CTMRGEnv` with a singlet corner of dimension `dim(Venv)` and an | ||
| identity edge from `id(T, Venv ⊗ Vpeps)`. | ||
| """ | ||
| function initialize_singlet_c4v_env(state::InfinitePEPS, Venv::ElementarySpace) | ||
| return initialize_singlet_c4v_env(scalartype(state), state, Venv) | ||
| end | ||
| function initialize_singlet_c4v_env(T, state::InfinitePEPS, Venv::ElementarySpace) | ||
| Vpeps = north_virtualspace(state, 1, 1)' | ||
| return initialize_singlet_c4v_env(T, Vpeps, Venv) | ||
| end | ||
| function initialize_singlet_c4v_env(T, Vpeps::ElementarySpace, Venv::ElementarySpace) | ||
| corner₀ = DiagonalTensorMap(zeros(real(T), Venv ← Venv)) | ||
| corner₀.data[1] = one(real(T)) | ||
| edge₀ = permute(id(T, Venv ⊗ Vpeps), ((1, 2, 4), (3,))) | ||
| return CTMRGEnv(corner₀, edge₀) | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to further
project_hermitianthe updated edge with respect to the two environment indices to eliminate numerical errors?See also the QR-CTM code which does this step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I would add a leading underscore (
_project_hermitian) to avoid conflict with MAK. But it's just my opinion...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition, do we have tests with fermions to see if
project_hermitianfor edges is correctly defined? I'm not quite confident on the usage offlipthere unless it's proven correct.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, thanks! Probably doesn't make too much of a difference but it should stabilize the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'm also not sure if
flipand_dagwork for fermions right away. Would you have an idea for a quick test? (I wouldn't want to add too much more to this PR.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave the fermions for a follow up, it will be easier to review what is going on that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test idea is simple: create a random fermionic state with C4v, converge the environment with both C4v and asymmetric CTMRG, and evaluate the expectation value of a random operator, which should be the same for both cases. But frankly, I'm not even sure if the current
symmetrize!plays nicely with permutation signs fromFermionParity.