-
Notifications
You must be signed in to change notification settings - Fork 31
Compress 2-layer InfinitePEPO with local truncation #311
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
Yue-Zhengyuan
merged 41 commits into
QuantumKitHub:main
from
Yue-Zhengyuan:local-compress
Jul 14, 2026
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
5204349
Add local approximation of the product of two iPEPO
Yue-Zhengyuan dc81186
Test LocalApprox projectors
Yue-Zhengyuan 77e4e50
Test `approximate` with time evolution
Yue-Zhengyuan a740dbf
Implement `standardize_virtual_spaces`
Yue-Zhengyuan 04a0320
Some renaming
Yue-Zhengyuan 5acf0f9
Add `approx` to test groups
Yue-Zhengyuan 4d6cee7
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 90b9286
Use svd_trunc! to directly get truncation error
Yue-Zhengyuan 0ea72e8
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 42c1247
Use eigh instead of svd
Yue-Zhengyuan 9845707
Use eigh_trunc! to avoid small negative eigenvalues
Yue-Zhengyuan 4e16e25
Fix twists for fermions
Yue-Zhengyuan 1860b2e
Return truncation error
Yue-Zhengyuan f18a590
Fix tests
Yue-Zhengyuan 7437803
Return projectors in info
Yue-Zhengyuan d4dcdf4
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 93d31f1
Increase test coverage
Yue-Zhengyuan 557eae0
Update src/algorithms/approximate/approx_tools.jl
Yue-Zhengyuan 75ed94d
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 39028fa
Apply suggestions from @leburgel
Yue-Zhengyuan 6b53718
Add hermitian projection in qr/lq_twolayer; test twists
Yue-Zhengyuan ba55a23
Add project_psd! to remove small negative eigenvalues
Yue-Zhengyuan dccc2a8
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 3b7f05f
Overload MPSKit.changebonds instead
Yue-Zhengyuan 8995761
Merge remote-tracking branch 'upstream/master' into local-compress
Yue-Zhengyuan 831a50c
Fix merge hiccups
Yue-Zhengyuan 10efb0c
Merge remote-tracking branch 'upstream/main' into local-compress
Yue-Zhengyuan 2ef5720
Rename to `compress`
Yue-Zhengyuan fae8611
Improve PSD projection + square root
Yue-Zhengyuan 38a8b04
Reorder tests
Yue-Zhengyuan 44aba11
Rename qr/lq_twolayer
Yue-Zhengyuan 4d80213
Remove CompressAlgorithm abstract type
Yue-Zhengyuan da824f4
Use autoopt for MdagM and MMdag
Yue-Zhengyuan 55d64cd
Merge remote-tracking branch 'upstream/main' into local-compress
Yue-Zhengyuan 5ea481f
Cartesian `eachindex` for InfinitePEPS / PEPO / PartitionFunction
Yue-Zhengyuan 95cd0df
Reduce repeated rotations
Yue-Zhengyuan 0505fdd
Lazy multiplication of iPEPOs
Yue-Zhengyuan 4aa2833
Use iPEPO tuple for `compress`
Yue-Zhengyuan 947e00f
Merge remote-tracking branch 'upstream/main' into local-compress
Yue-Zhengyuan 4598411
Fix type annotation
Yue-Zhengyuan 3fd8da3
Reorder functions
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,158 @@ | ||
| """ | ||
| $(TYPEDEF) | ||
|
|
||
| Algorithm to truncate virtual bonds of a two-layer network | ||
| with projectors that minimizes the local cost function, | ||
| which is the 2-norm of (e.g. for two layers of iPEPO) | ||
| ``` | ||
| ↓ ╱ ↓ ╱ ↓ ╱ ↓ ╱ | ||
| ----A2---←---B2--- ----A2-←-|╲ ╱|--←-B2--- | ||
| ╱ | ╱ | ╱ | | ╲ ╱ | ╱ | | ||
| ↓ ↓ - ↓ |P1├-←-┤P2| ↓ | ||
| | ╱ | ╱ | ╱ | ╱ ╲ | | ╱ | ||
| ----A1---←---B1--- ----A1-←-|╱ ╲|--←-B1--- | ||
| ╱ ↓ ╱ ↓ ╱ ↓ ╱ ↓ | ||
| ``` | ||
| on each bond of the network. | ||
| """ | ||
| struct LocalTruncation | ||
| trunc::TruncationStrategy | ||
| end | ||
|
|
||
| """ | ||
| Calculate the `left_orth` of 2-layer PEPO tensor | ||
| with the east virtual legs transferred to the R tensor | ||
| ``` | ||
| ↓ ╱ | ||
| ----A2-←- ┌-←- | ||
| ╱ | | | ||
| ↓ = (Q)-←--R | ||
| | ╱ | | ||
| ----A1-←- └-←- | ||
| ╱ ↓ | ||
| ``` | ||
| Only `R` is calculated and returned. | ||
| """ | ||
| function left_orth_twolayer(A1::PEPOTensor, A2::PEPOTensor) | ||
| MdagM = _get_MdagM(A1, A2) | ||
| D, R = eigh_full!(MdagM) | ||
| # remove small negative eigenvalues due to numerical noises | ||
| T = eltype(D.data) | ||
| D.data .= sqrt.(max.(zero(T), D.data)) | ||
| return lmul!(D, R') | ||
| end | ||
| function _get_MdagM(A1::PEPOTensor, A2::PEPOTensor) | ||
| @assert isdual(virtualspace(A1, EAST)) && isdual(virtualspace(A2, EAST)) | ||
| A2′ = twistdual(A2, [2, 3, 5, 6]) | ||
| A1′ = twistdual(A1, [1, 3, 5, 6]) | ||
| @autoopt @tensor MdagM[Dx1 Dx2; Dx1′ Dx2′] := | ||
| conj(A2[dz dz2; DY2 Dx2 Dy2 DX2]) * A2′[dz′ dz2; DY2 Dx2′ Dy2 DX2] * | ||
| conj(A1[dz1 dz; DY1 Dx1 Dy1 DX1]) * A1′[dz1 dz′; DY1 Dx1′ Dy1 DX1] | ||
| project_hermitian!(MdagM) | ||
| return MdagM | ||
| end | ||
|
|
||
| """ | ||
| Calculate the `right_orth` of 2-layer PEPO tensor | ||
| with the west virtual legs transferred to the L tensor | ||
| ``` | ||
| ↓ ╱ | ||
| --←-A2--- -←-┐ | ||
| ╱ | | | ||
| ↓ = L--←-(Q) | ||
| | ╱ | | ||
| --←-A1--- -←-┘ | ||
| ╱ ↓ | ||
| ``` | ||
| Only `L` is calculated and returned. | ||
| """ | ||
| function right_orth_twolayer(A1::PEPOTensor, A2::PEPOTensor) | ||
| MMdag = _get_MMdag(A1, A2) | ||
| D, L = eigh_full!(MMdag) | ||
| # remove small negative eigenvalues due to numerical noises | ||
| T = eltype(D.data) | ||
| D.data .= sqrt.(max.(zero(T), D.data)) | ||
| return rmul!(L, D) | ||
| end | ||
| function _get_MMdag(A1::PEPOTensor, A2::PEPOTensor) | ||
| @assert !isdual(virtualspace(A1, WEST)) && !isdual(virtualspace(A2, WEST)) | ||
| A2′ = twistnondual(A2, [2, 3, 4, 5]) | ||
| A1′ = twistnondual(A1, [1, 3, 4, 5]) | ||
| @autoopt @tensor MMdag[Dx1 Dx2; Dx1′ Dx2′] := | ||
| A2′[dz dz2; DY2 DX2 Dy2 Dx2] * conj(A2[dz′ dz2; DY2 DX2 Dy2 Dx2′]) * | ||
| A1′[dz1 dz; DY1 DX1 Dy1 Dx1] * conj(A1[dz1 dz′; DY1 DX1 Dy1 Dx1′]) | ||
| project_hermitian!(MMdag) | ||
| return MMdag | ||
| end | ||
|
|
||
| """ | ||
| Find the local projector `P1`, `P2` for the | ||
| following truncation of two layers of InfinitePEPO | ||
| ``` | ||
| ↓ ╱ ↓ ╱ | ||
| ----A2-←-|╲ ╱|--←-B2--- | ||
| ╱ | | ╲ ╱ | ╱ | | ||
| ↓ |P1├-←-┤P2| ↓ | ||
| | ╱ | ╱ ╲ | | ╱ | ||
| ----A1-←-|╱ ╲|--←-B1--- | ||
| ╱ ↓ ╱ ↓ | ||
| ``` | ||
| Reference: Physical Review B 100, 035449 (2019) | ||
| """ | ||
| function virtual_projector( | ||
| A1::PEPOTensor, A2::PEPOTensor, B1::PEPOTensor, B2::PEPOTensor; | ||
| trunc::TruncationStrategy | ||
| ) | ||
| R1 = left_orth_twolayer(A1, A2) | ||
| R2 = right_orth_twolayer(B1, B2) | ||
| u, s, vh, ϵ = svd_trunc!(R1 * R2; trunc) | ||
| sinv_sqrt = sdiag_pow(s, -0.5) | ||
| P1 = R2 * vh' * sinv_sqrt | ||
| P2 = sinv_sqrt * u' * R1 | ||
| return P1, P2, (; s, ϵ) | ||
| end | ||
|
|
||
| """ | ||
| compress((ρ1, ρ2), alg::LocalTruncation) | ||
|
|
||
| Compress two 1-layer iPEPOs into a 1-layer iPEPO by truncating the virtual bonds | ||
| with `LocalTruncation`. In the tuple `(ρ1, ρ2)`, `ρ1` is the lower layer and | ||
| `ρ2` is the upper layer. | ||
| """ | ||
| function compress(ρs::Tuple{<:InfinitePEPO, <:InfinitePEPO}, alg::LocalTruncation) | ||
| ρ1, ρ2 = ρs | ||
| # sanity checks | ||
| size(ρ1) == size(ρ2) || error("Input PEPOs have different unit cell sizes.") | ||
| size(ρ1, 3) == 1 || error("ρ1 should have only one layer.") | ||
| size(ρ2, 3) == 1 || error("ρ2 should have only one layer.") | ||
| all(all.(_check_virtual_dualness(ρ1))) || error("East and north virtual spaces in ρ1 should be dual spaces.") | ||
| all(all.(_check_virtual_dualness(ρ2))) || error("East and north virtual spaces in ρ2 should be dual spaces.") | ||
| # x-bond projectors: [r, c] on bond [r, c]--[r, c+1] | ||
| Nr, Nc, = size(ρ1) | ||
| Pxs_info = map(Iterators.product(1:Nr, 1:Nc)) do (r, c) | ||
| # TODO: support SiteDependentTruncation | ||
| return virtual_projector( | ||
| ρ1[r, c], ρ2[r, c], ρ1[r, _next(c, Nc)], ρ2[r, _next(c, Nc)]; | ||
| trunc = alg.trunc | ||
| ) | ||
| end | ||
| # y-bond projectors: [r, c] on bond [r, c]--[r-1, c] | ||
| ρ1′, ρ2′ = rotr90.(unitcell(ρ1)), rotr90.(unitcell(ρ2)) | ||
| Pys_info = map(Iterators.product(1:Nr, 1:Nc)) do (r, c) | ||
| return virtual_projector( | ||
| ρ1′[r, c], ρ2′[r, c], ρ1′[_prev(r, Nr), c], ρ2′[_prev(r, Nr), c]; | ||
| trunc = alg.trunc | ||
| ) | ||
| end | ||
| # apply projectors | ||
| As = map(Iterators.product(1:Nr, 1:Nc)) do (r, c) | ||
| Pw, Pe = Pxs_info[r, _prev(c, Nc)][2], Pxs_info[r, c][1] | ||
| Pn, Ps = Pys_info[r, c][1], Pys_info[_next(r, Nr), c][2] | ||
| @tensoropt A[p1 p2; n e s w] := | ||
| (ρ1[r, c])[p1 p; n1 e1 s1 w1] * (ρ2[r, c])[p p2; n2 e2 s2 w2] * | ||
| Pn[n1 n2; n] * Pe[e1 e2; e] * Ps[s; s1 s2] * Pw[w; w1 w2] | ||
| return A | ||
| end | ||
| info = (; Pxs_info, Pys_info) | ||
| return InfinitePEPO(cat(As; dims = 3)), info | ||
| 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
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
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,61 @@ | ||
| using Test | ||
| using Random | ||
| using LinearAlgebra | ||
| using TensorKit | ||
| using PEPSKit | ||
| using PEPSKit: virtual_projector | ||
|
|
||
| """ | ||
| Cost function of LocalTruncation. | ||
| For test convenience, open virtual indices are made trivial and removed. | ||
| """ | ||
| function localcompress_cost(A1, A2, B1, B2, P1, P2) | ||
| @tensor net1[pa1 pb1; pa2′ pb2′] := | ||
| A1[pa1 pa; D1] * A2[pa pa2′; D2] * B1[pb1 pb; D1] * B2[pb pb2′; D2] | ||
| @tensor net2[pa1 pb1; pa2′ pb2′] := P1[Da1 Da2; D] * P2[D; Db1 Db2] * | ||
| A1[pa1 pa; Da1] * A2[pa pa2′; Da2] * B1[pb1 pb; Db1] * B2[pb pb2′; Db2] | ||
| return norm(net1 - net2) | ||
| end | ||
|
|
||
| @testset "Fermionic twists" begin | ||
| Vphy = Vect[FermionParity](0 => 2, 1 => 2) | ||
| Vvir = Vect[FermionParity](0 => 2, 1 => 2) | ||
| for _ in 1:4 # multiple trials without setting seed | ||
| Aspace = (Vphy ⊗ Vphy' ← Vvir ⊗ Vvir ⊗ Vvir' ⊗ Vvir') | ||
| A1 = randn(ComplexF64, Aspace) | ||
| A2 = randn(ComplexF64, Aspace) | ||
| for MM in [PEPSKit._get_MMdag(A1, A2), PEPSKit._get_MdagM(A1, A2)] | ||
| @test isposdef(MM) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| @testset "Cost function of LocalTruncation" begin | ||
| Random.seed!(0) | ||
| Vaux, Vphy, V = ℂ^1, ℂ^10, ℂ^4 | ||
| A1 = normalize(randn(Vphy ⊗ Vphy' ← Vaux ⊗ V ⊗ Vaux' ⊗ Vaux'), Inf) | ||
| A2 = normalize(randn(Vphy ⊗ Vphy' ← Vaux ⊗ V ⊗ Vaux' ⊗ Vaux'), Inf) | ||
| B1 = normalize(randn(Vphy ⊗ Vphy' ← Vaux ⊗ Vaux ⊗ Vaux' ⊗ V'), Inf) | ||
| B2 = normalize(randn(Vphy ⊗ Vphy' ← Vaux ⊗ Vaux ⊗ Vaux' ⊗ V'), Inf) | ||
|
|
||
| P1, P2, info = virtual_projector(A1, A2, B1, B2; trunc = notrunc()) | ||
| @test P1 * P2 ≈ TensorKit.id(domain(P2)) | ||
|
|
||
| P1, P2, info = virtual_projector(A1, A2, B1, B2; trunc = truncrank(8)) | ||
| A1 = removeunit(removeunit(removeunit(A1, 6), 5), 3) | ||
| A2 = removeunit(removeunit(removeunit(A2, 6), 5), 3) | ||
| B1 = removeunit(removeunit(removeunit(B1, 5), 4), 3) | ||
| B2 = removeunit(removeunit(removeunit(B2, 5), 4), 3) | ||
| @info "Truncation error = $(info.ϵ)." | ||
| @test info.ϵ ≈ localcompress_cost(A1, A2, B1, B2, P1, P2) | ||
| end | ||
|
|
||
| @testset "Virtual space matching" begin | ||
| Vps = ComplexSpace.([2 2; 2 2]) | ||
| Vns = ComplexSpace.([2 4; 5 3]) | ||
| Ves = ComplexSpace.([3 5; 4 2]) | ||
| ρ = InfinitePEPO(randn, ComplexF64, Vps, Vns, Ves) | ||
| alg = LocalTruncation(truncrank(2)) | ||
| ρ2, = compress((ρ, ρ), alg) | ||
| @test ρ2 isa InfinitePEPO | ||
| 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
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
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.
Uh oh!
There was an error while loading. Please reload this page.