-
Notifications
You must be signed in to change notification settings - Fork 31
Add Neighborhood Tensor Update (NTU) #144
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
Draft
Yue-Zhengyuan
wants to merge
64
commits into
QuantumKitHub:main
Choose a base branch
from
Yue-Zhengyuan:bondenv-ntu
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
c101c79
Change ALS tensor axis order
Yue-Zhengyuan 2fdd026
bondenv_ctm for PEPO
Yue-Zhengyuan 1a13c39
Rotation of LocalCircuit
Yue-Zhengyuan bfb826a
Use vector of sites in `nearest_neighbours` etc
Yue-Zhengyuan 0c74c01
Merge branch 'rotate-circuit' into bondenv-ntu
Yue-Zhengyuan f6554f3
Neighbourhood tensor update
Yue-Zhengyuan 2540e48
Fix benv_tensor for dual physical space
Yue-Zhengyuan 24145b1
Add NTU tests
Yue-Zhengyuan f9d029a
Remove unneeded bipartite restrictions
Yue-Zhengyuan 71e6e31
Merge remote-tracking branch 'upstream/master' into bondenv-ntu
Yue-Zhengyuan c51b54b
Test `timestep` for NTU
Yue-Zhengyuan e8f07eb
Convergence check for NTU
Yue-Zhengyuan a4de5ff
Streamline convergence checks
Yue-Zhengyuan c14fa16
Merge #360
Yue-Zhengyuan 3a915c4
FixedSpaceTruncation for NTU
Yue-Zhengyuan 6bfb34f
Fix time_evolve interface in tests
Yue-Zhengyuan 26344d2
Fix realtime Ising test
Yue-Zhengyuan 8ed7d13
Fix FixedSpaceTruncation for simple update
Yue-Zhengyuan 3498fea
Improve efficiency of bond truncation
Yue-Zhengyuan ea0a968
Make j1j2 finiteT test work for all allowed symmetries
Yue-Zhengyuan 3cc7769
Reorganize code to get bond tensors
Yue-Zhengyuan 5a90194
Improve NTU struct type stability
Yue-Zhengyuan 3d1c3f9
Fix FixedSpaceTruncation again
Yue-Zhengyuan 99e3e48
Require bond tensor to be an MPSTensor
Yue-Zhengyuan b6aeff3
Replace `_qr_bond` with `bond_tensor` functions
Yue-Zhengyuan bbc3bc4
Fix `undo_bond_tensor_last`
Yue-Zhengyuan de5a5d5
Change bond_tensor return order
Yue-Zhengyuan 2d90e04
Do not move phys leg to bond tensor for middle cluster sites
Yue-Zhengyuan 931a575
Fix bondenv tests
Yue-Zhengyuan 14c2fde
Get rid of ncon in benv_tensor
Yue-Zhengyuan f8aaff0
More optimizations for benv_tensor
Yue-Zhengyuan 9079316
Improve simple update performance
Yue-Zhengyuan 511a654
Fix formatting
Yue-Zhengyuan eb06fc0
Merge remote-tracking branch 'upstream/master' into bondenv-ntu
Yue-Zhengyuan c60ab31
Add Printf to test environment
Yue-Zhengyuan dbb4a6b
Remove unnecessary type specification
Yue-Zhengyuan d0bcf0e
Merge remote-tracking branch 'upstream/master' into bondenv-ntu
Yue-Zhengyuan 5234126
Revert a comment
Yue-Zhengyuan 6034a67
Change default opt_alg for NTU
Yue-Zhengyuan 8e4d44a
Add verbosity setting for NTU
Yue-Zhengyuan fa109bc
Test coverage on NTU for ground state
Yue-Zhengyuan e16c935
Unexport infinite_temperature_density_matrix
Yue-Zhengyuan fba41a2
Merge remote-tracking branch 'upstream/main' into bondenv-ntu
Yue-Zhengyuan 1fdc81c
Use periodic indexing
Yue-Zhengyuan 1655e48
Slightly reduce output
Yue-Zhengyuan 03d2c8f
Update tests
Yue-Zhengyuan e1e0a0a
Merge remote-tracking branch 'upstream/main' into bondenv-ntu
Yue-Zhengyuan 676f8d7
Refactor _cluster_truncate!
Yue-Zhengyuan e89a35b
Reverse cluster truncation order at even NTU iterations
Yue-Zhengyuan 6b54e1c
Merge remote-tracking branch 'upstream/main' into bondenv-ntu
Yue-Zhengyuan a0f819a
Fix condition when reconverging env
Yue-Zhengyuan 9976630
Comment to reverse_trunc
Yue-Zhengyuan 03a160f
Refactor bond direction helpers to use lattice direction constants
Yue-Zhengyuan 897ed8d
Merge branch 'main' into bondenv-ntu
Yue-Zhengyuan 8d21293
Allow complex time in `timestep`
Yue-Zhengyuan 01ae874
Simplify type annotation for bondenv_ntu
Yue-Zhengyuan 18d2041
Remove unnecessary const Dict
Yue-Zhengyuan 81f5f18
Type stability fix for hair_axs
Yue-Zhengyuan 44ac6d8
Explicitly keep trivially charged leading singular value in _svd_cut!
Yue-Zhengyuan e80948b
Test NNpEnv with Heisenberg ground state
Yue-Zhengyuan b3db831
Merge remote-tracking branch 'upstream/main' into bondenv-ntu
Yue-Zhengyuan 06b8c02
One-pass `@tensoropt` contraction for NTU envs
Yue-Zhengyuan 6dadf4f
Add some BP related TODOs
Yue-Zhengyuan e3f92d1
More detailed docstring for `_svd_cut!`
Yue-Zhengyuan 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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| #= | ||
| The construction of bond environment for Neighborhood Tensor Update (NTU) | ||
| is adapted from YASTN (https://github.com/yastn/yastn). | ||
| Copyright 2024 The YASTN Authors. All Rights Reserved. | ||
| Licensed under the Apache License, Version 2.0 | ||
| =# | ||
|
|
||
| """ | ||
| Algorithms to construct bond environment for Neighborhood Tensor Update (NTU). | ||
| """ | ||
| abstract type NeighbourEnv end | ||
|
|
||
| """ | ||
| For a rank-(2,2) tensor `T_{ik;jl}`, approximately decompose it to the | ||
| product of two rank-2 tensors `A_{ik;} * B_{;jl}` using truncated SVD | ||
| that keeps only the largest singular value in the charge-neutral sector. | ||
|
|
||
| The kept singular value is the largest in the entire SVD spectrum if: | ||
| - `permute(T, ((1, 3), (2, 4)))` is positive semi-definite, and | ||
| - `space(T, 1) == space(T, 2)'` and `space(T, 3) == space(T, 4)`, | ||
| """ | ||
| function _svd_cut!(t::AbstractTensorMap{<:Any, <:Any, 2, 2}) | ||
| A, B = left_orth!(t; trunc = truncspace(oneunit(spacetype(t)))) | ||
| return removeunit(A, numind(A)), removeunit(B, 1) | ||
| end | ||
|
|
||
| """ | ||
| Algorithm struct for "NTU-NN" bond environment. | ||
| """ | ||
| struct NNEnv <: NeighbourEnv end | ||
| """ | ||
| Calculate the bond environment within "NTU-NN" approximation. | ||
| ``` | ||
| -1 ●=======● | ||
| ║ ║ | ||
| 0 ●===X== ==Y===● | ||
| ║ ║ | ||
| 1 ●=======● | ||
| -1 0 1 2 | ||
| ``` | ||
| """ | ||
| function bondenv_ntu( | ||
| row::Int, col::Int, X, Y, state::InfiniteState, alg::NNEnv | ||
| ) | ||
| neighbors = [(-1, 0), (0, -1), (1, 0), (1, 1), (0, 2), (-1, 1)] | ||
| m = collect_neighbors(state, row, col, neighbors) | ||
| X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) | ||
| @tensoropt benv[Dw1 De1; Dw0 De0] := | ||
| ( # southwest half | ||
| cor_se(m[1, 1])[Dse1 Dse0 Ds1 Ds0] * | ||
| cor_sw(m[1, 0])[Dsw1 Dsw0 Ds1 Ds0] * | ||
| edge_w(X, hair_w(m[0, -1]))[Dnw1 Dnw0 Dw1 Dw0 Dsw1 Dsw0] | ||
| ) * ( # northeast half | ||
| cor_nw(m[-1, 0])[Dn1 Dn0 Dnw1 Dnw0] * | ||
| cor_ne(m[-1, 1])[Dne1 Dne0 Dn1 Dn0] * | ||
| edge_e(Y, hair_e(m[0, 2]))[Dne1 Dne0 Dse1 Dse0 De1 De0] | ||
| ) | ||
| normalize!(benv, Inf) | ||
| return benv | ||
| end | ||
|
|
||
| """ | ||
| Algorithm struct for "NTU-NN+" bond environment. | ||
| """ | ||
| struct NNpEnv <: NeighbourEnv end | ||
| """ | ||
| Calculate the bond environment within "NTU-NN+" approximation. | ||
| ``` | ||
| -2 ●.......● | ||
| ║ ║ | ||
| -1 ○===●=======●===○ | ||
| ║ ║ ║ ║ | ||
| 0 ●===●===X== ==Y===●===● | ||
| ║ ║ ║ ║ | ||
| 1 ○===●=======●===○ | ||
| ║ ║ | ||
| 2 ●.......● | ||
| -2 -1 0 1 2 3 | ||
| ``` | ||
| Dotted lines and ○ are splitted using SVD with `truncrank(1)`. | ||
| """ | ||
| function bondenv_ntu( | ||
| row::Int, col::Int, X, Y, state::InfiniteState, alg::NNpEnv | ||
| ) | ||
| neighbors = [ | ||
| (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (1, 2), (0, 2), (-1, 2), | ||
| (-1, 1), (-1, 0), (0, -2), (2, 0), (2, 1), (0, 3), (-2, 1), (-2, 0), | ||
| ] | ||
| ms = collect_neighbors(state, row, col, neighbors) | ||
| X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) | ||
|
|
||
| # ---- hairs (size D^2) with a 1D auxiliary leg ---- | ||
|
|
||
| @tensor top[-1 -2; -3 -4] := cor_nw(ms[-2, 0])[1 2 -1 -2] * cor_ne(ms[-2, 1])[-3 -4 1 2] | ||
| tl, tr = _svd_cut!(top) | ||
|
|
||
| @tensor bot[-1 -2; -3 -4] := cor_sw(ms[2, 0])[-1 -2 1 2] * cor_se(ms[2, 1])[-3 -4 1 2] | ||
| bl, br = _svd_cut!(bot) | ||
|
|
||
| nw = permute(cor_nw(ms[-1, -1]), ((3, 4), (1, 2))) | ||
| nw1, nw2 = _svd_cut!(nw) | ||
|
|
||
| ne = permute(cor_ne(ms[-1, 2]), ((3, 4), (1, 2))) | ||
| ne1, ne2 = _svd_cut!(ne) | ||
|
|
||
| sw = permute(cor_sw(ms[1, -1]), ((1, 2), (3, 4))) | ||
| sw1, sw2 = _svd_cut!(sw) | ||
|
|
||
| se = permute(cor_se(ms[1, 2]), ((3, 4), (1, 2))) | ||
| se1, se2 = _svd_cut!(se) | ||
|
|
||
| @tensoropt benv[Dw1, De1; Dw0, De0] := | ||
| ( # hW | ||
| hair_w(ms[0, -2])[Dw21 Dw20] * | ||
| nw1[Dnw11 Dnw10] * sw1[Dsw11 Dsw10] * | ||
| twistdual(ms[0, -1], 1)[phW Dnw10 DXw0 Dsw10 Dw20] * | ||
| conj(ms[0, -1][phW Dnw11 DXw1 Dsw11 Dw21]) | ||
| ) * ( # hE | ||
| hair_e(ms[0, 3])[De21 De20] * | ||
| ne2[Dne21 Dne20] * se2[Dse21 Dse20] * | ||
| twistdual(ms[0, 2], 1)[phE Dne20 De20 Dse20 DYe0] * | ||
| conj(ms[0, 2][phE Dne21 De21 Dse21 DYe1]) | ||
| ) * ( # NW | ||
| tl[Dtl1 Dtl0] * nw2[Dnw21 Dnw20] * | ||
| twistdual(ms[-1, 0], 1)[pNW Dtl0 Dn0 DXn0 Dnw20] * | ||
| conj(ms[-1, 0][pNW Dtl1 Dn1 DXn1 Dnw21]) | ||
| ) * ( # NE | ||
| tr[Dtr1 Dtr0] * ne1[Dne11 Dne10] * | ||
| twistdual(ms[-1, 1], 1)[pNE Dtr0 Dne10 DYn0 Dn0] * | ||
| conj(ms[-1, 1][pNE Dtr1 Dne11 DYn1 Dn1]) | ||
| ) * ( # SW | ||
| bl[Dbl1 Dbl0] * sw2[Dsw21 Dsw20] * | ||
| twistdual(ms[1, 0], 1)[pSW DXs0 Ds0 Dbl0 Dsw20] * | ||
| conj(ms[1, 0][pSW DXs1 Ds1 Dbl1 Dsw21]) | ||
| ) * ( # SE | ||
| br[Dbr1 Dbr0] * se1[Dse11 Dse10] * | ||
| twistdual(ms[1, 1], 1)[pSE DYs0 Dse10 Dbr0 Ds0] * | ||
| conj(ms[1, 1][pSE DYs1 Dse11 Dbr1 Ds1]) | ||
| ) * conj(X[pX DXn1 Dw1 DXs1 DXw1]) * | ||
| twistdual(X, 1)[pX DXn0 Dw0 DXs0 DXw0] * | ||
| conj(Y[pY DYn1 DYe1 DYs1 De1]) * | ||
| twistdual(Y, 1)[pY DYn0 DYe0 DYs0 De0] | ||
| normalize!(benv, Inf) | ||
| return benv | ||
| end | ||
|
|
||
| """ | ||
| Algorithm struct for "NTU-NNN" bond environment. | ||
| """ | ||
| struct NNNEnv <: NeighbourEnv end | ||
| """ | ||
| Calculates the bond environment within "NTU-NNN" approximation. | ||
| ``` | ||
| -1 ●===●=======●===● | ||
| ║ ║ ║ ║ | ||
| 0 ●===X== ==Y===● | ||
| ║ ║ ║ ║ | ||
| 1 ●===●=======●===● | ||
| -1 0 1 2 | ||
| ``` | ||
| """ | ||
| function bondenv_ntu( | ||
| row::Int, col::Int, X, Y, state::InfiniteState, alg::NNNEnv | ||
| ) | ||
| neighbors = [ | ||
| (-1, -1), (0, -1), (1, -1), | ||
| (1, 0), (1, 1), (1, 2), (0, 2), | ||
| (-1, 2), (-1, 1), (-1, 0), | ||
| ] | ||
| m = collect_neighbors(state, row, col, neighbors) | ||
| X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) | ||
| @tensoropt benv[Dw1 De1; Dw0 De0] := | ||
| ( # NW corner | ||
| cor_nw(m[-1, -1])[χnw1 χnw0 χwn1 χwn0] * | ||
| edge_n(m[-1, 0])[χn1 χn0 Dnw1 Dnw0 χnw1 χnw0] * | ||
| edge_w(m[0, -1])[χwn1 χwn0 Dww1 Dww0 χws1 χws0] * | ||
| conj(X[dX Dnw1 Dw1 Dsw1 Dww1]) * | ||
| twistdual(X, 1)[dX Dnw0 Dw0 Dsw0 Dww0] | ||
| ) * ( # SE corner | ||
| cor_se(m[1, 2])[χes1 χes0 χse1 χse0] * | ||
| edge_s(m[1, 1])[Dse1 Dse0 χse1 χse0 χs1 χs0] * | ||
| edge_e(m[0, 2])[χen1 χen0 χes1 χes0 Dee1 Dee0] * | ||
| conj(Y[dY Dne1 Dee1 Dse1 De1]) * | ||
| twistdual(Y, 1)[dY Dne0 Dee0 Dse0 De0] | ||
| ) * # NE edge | ||
| edge_n(m[-1, 1])[χne1 χne0 Dne1 Dne0 χn1 χn0] * | ||
| cor_ne(m[-1, 2])[χen1 χen0 χne1 χne0] * | ||
| # SW edge | ||
| cor_sw(m[1, -1])[χws1 χws0 χsw1 χsw0] * | ||
| edge_s(m[1, 0])[Dsw1 Dsw0 χs1 χs0 χsw1 χsw0] | ||
| normalize!(benv, Inf) | ||
| return benv | ||
| end | ||
Oops, something went wrong.
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.
Out of curiosity: do you need the weight to be distributed equally? Otherwise this might be replaced with
left_orth!(t; trunc = truncrank(1))orright_orth!(t; trunc = truncrank(1)), which I think removes some intermediate allocations.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.
On a separate note, do we need this to be trivially charged for everything to work? It might reduce quite a bit of the number of legs if we can do something like:
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.
Nice observation! Actually no, since this D = 1 leg is in the end contracted, so how we distribute
sis irrelevant.It seems that
_svd_cutis always applied to a positive map, which then (if my feeling is right) ensures that the leading singular value has trivial charge. I'll double-check this.In YASTN they don't need to worry about it, since they only support Abelian symmetries and allow a tensor to have nonzero total charge.
Uh oh!
There was an error while loading. Please reload this page.
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.
For
_svd_cut!I have updated its docstring, describing a sufficient condition under which the largest singular value in the charge-neutral sector is also the largest in the entire SVD spectrum. The condition is satisfied by tensors constructed from contracting a bra-ket pair of tensors in a twist-free way, so indeed keeping the largest charge-neutral singular value works just as fine astruncrank(1).