From 5fac4556f90e001687abf6c12bbfa41ae893d084 Mon Sep 17 00:00:00 2001 From: Todorbsc Date: Thu, 23 Jan 2025 14:50:33 +0100 Subject: [PATCH 1/7] Iterate over output sites in canonize function --- src/MPS.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MPS.jl b/src/MPS.jl index ff853fce8..6d71b835b 100644 --- a/src/MPS.jl +++ b/src/MPS.jl @@ -511,12 +511,12 @@ function canonize!(ψ::AbstractMPO; normalize=false) Λ = Tensor[] # right-to-left QR sweep, get right-canonical tensors - for i in nsites(ψ):-1:2 + for i in nsites(ψ; set=:outputs):-1:2 canonize_site!(ψ, Lane(i); direction=:left, method=:qr) end # left-to-right SVD sweep, get left-canonical tensors and singular values without reversing - for i in 1:(nsites(ψ) - 1) + for i in 1:(nsites(ψ; set=:outputs) - 1) canonize_site!(ψ, Lane(i); direction=:right, method=:svd) # extract the singular values and contract them with the next tensor @@ -527,7 +527,7 @@ function canonize!(ψ::AbstractMPO; normalize=false) push!(Λ, Λᵢ) end - for i in 2:nsites(ψ) # tensors at i in "A" form, need to contract (Λᵢ)⁻¹ with A to get Γᵢ + for i in 2:nsites(ψ; set=:outputs) # tensors at i in "A" form, need to contract (Λᵢ)⁻¹ with A to get Γᵢ Λᵢ = Λ[i - 1] # singular values start between site 1 and 2 A = tensors(ψ; at=Lane(i)) Γᵢ = contract(A, Tensor(diag(pinv(Diagonal(parent(Λᵢ)); atol=1e-64)), inds(Λᵢ)); dims=()) From bb0b33fb39d3de34588f18a3c16c5707414d84c0 Mon Sep 17 00:00:00 2001 From: Todorbsc Date: Thu, 23 Jan 2025 14:50:54 +0100 Subject: [PATCH 2/7] Add MPO canonize test --- test/MPO_test.jl | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/MPO_test.jl b/test/MPO_test.jl index 612aa4915..a24177b0b 100644 --- a/test/MPO_test.jl +++ b/test/MPO_test.jl @@ -74,4 +74,51 @@ @test isapprox(norm(H), 1.0) @test maximum(last, size(H)) <= χ end + + @testset "canonize!" begin + using Tenet: isleftcanonical, isrightcanonical + + ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) + canonized = canonize(ψ) + + @test form(canonized) isa Canonical + + @test length(tensors(canonized)) == 9 # 5 tensors + 4 singular values vectors + @test isapprox(contract(transform(TensorNetwork(canonized), Tenet.HyperFlatten())), contract(ψ)) + @test isapprox(norm(ψ), norm(canonized)) + + # Extract the singular values between each adjacent pair of sites in the canonized chain + Λ = [tensors(canonized; between=(Lane(i), Lane(i + 1))) for i in 1:4] + @test map(λ -> sum(abs2, λ), Λ) ≈ ones(length(Λ)) * norm(canonized)^2 + + for i in 1:5 + canonized = canonize(ψ) + + if i == 1 + @test isleftcanonical(canonized, Lane(i)) + elseif i == 5 # in the limits of the chain, we get the norm of the state + normalize!(tensors(canonized; bond=(Lane(i - 1), Lane(i)))) + contract!(canonized; between=(Lane(i - 1), Lane(i)), direction=:right) + @test isleftcanonical(canonized, Lane(i)) + else + contract!(canonized; between=(Lane(i - 1), Lane(i)), direction=:right) + @test isleftcanonical(canonized, Lane(i)) + end + end + + for i in 1:5 + canonized = canonize(ψ) + + if i == 1 # in the limits of the chain, we get the norm of the state + normalize!(tensors(canonized; bond=(Lane(i), Lane(i + 1)))) + contract!(canonized; between=(Lane(i), Lane(i + 1)), direction=:left) + @test isrightcanonical(canonized, Lane(i)) + elseif i == 5 + @test isrightcanonical(canonized, Lane(i)) + else + contract!(canonized; between=(Lane(i), Lane(i + 1)), direction=:left) + @test isrightcanonical(canonized, Lane(i)) + end + end + end end From e1433a1fb57cc4ad60a1fd6fbbfd2dfcdbee78dc Mon Sep 17 00:00:00 2001 From: Todorbsc Date: Thu, 23 Jan 2025 14:56:20 +0100 Subject: [PATCH 3/7] Add MPO mixed_canonized test --- test/MPO_test.jl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/MPO_test.jl b/test/MPO_test.jl index a24177b0b..1584b2552 100644 --- a/test/MPO_test.jl +++ b/test/MPO_test.jl @@ -121,4 +121,37 @@ end end end + + @testset "mixed_canonize!" begin + @testset "single Site" begin + ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) + canonized = mixed_canonize(ψ, lane"3") + @test Tenet.check_form(canonized) + + @test form(canonized) isa MixedCanonical + @test form(canonized).orthog_center == lane"3" + + @test isisometry(canonized, lane"1"; dir=:right) + @test isisometry(canonized, lane"2"; dir=:right) + @test isisometry(canonized, lane"4"; dir=:left) + @test isisometry(canonized, lane"5"; dir=:left) + + @test contract(canonized) ≈ contract(ψ) + end + + @testset "multiple Sites" begin + ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) + canonized = mixed_canonize(ψ, [lane"2", lane"3"]) + + @test Tenet.check_form(canonized) + @test form(canonized) isa MixedCanonical + @test form(canonized).orthog_center == [lane"2", lane"3"] + + @test isisometry(canonized, lane"1"; dir=:right) + @test isisometry(canonized, lane"4"; dir=:left) + @test isisometry(canonized, lane"5"; dir=:left) + + @test contract(canonized) ≈ contract(ψ) + end + end end From 60854540f0765753eb387f4db4fec6af3fe197c1 Mon Sep 17 00:00:00 2001 From: Todorbsc <145352308+Todorbsc@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:37:27 +0100 Subject: [PATCH 4/7] Move general MPO definition outside of specific tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jofre Vallès Muns <61060572+jofrevalles@users.noreply.github.com> --- test/MPO_test.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/MPO_test.jl b/test/MPO_test.jl index 1584b2552..b6b1a12ed 100644 --- a/test/MPO_test.jl +++ b/test/MPO_test.jl @@ -123,8 +123,9 @@ end @testset "mixed_canonize!" begin + ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) + @testset "single Site" begin - ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) canonized = mixed_canonize(ψ, lane"3") @test Tenet.check_form(canonized) @@ -140,7 +141,6 @@ end @testset "multiple Sites" begin - ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) canonized = mixed_canonize(ψ, [lane"2", lane"3"]) @test Tenet.check_form(canonized) From a901371aede9c32e1302203688a961fa404925b5 Mon Sep 17 00:00:00 2001 From: Todorbsc Date: Thu, 23 Jan 2025 15:40:30 +0100 Subject: [PATCH 5/7] Format code --- test/MPO_test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/MPO_test.jl b/test/MPO_test.jl index b6b1a12ed..1425aeeee 100644 --- a/test/MPO_test.jl +++ b/test/MPO_test.jl @@ -124,7 +124,7 @@ @testset "mixed_canonize!" begin ψ = MPO([rand(4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4, 4), rand(4, 4, 4)]) - + @testset "single Site" begin canonized = mixed_canonize(ψ, lane"3") @test Tenet.check_form(canonized) From acb375b4e13a49d2728ba8de37f5fbf95ff0c463 Mon Sep 17 00:00:00 2001 From: Todorbsc <145352308+Todorbsc@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:13:00 +0100 Subject: [PATCH 6/7] Replace `nsites` calls that retrieve outputs by `nlanes` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sergio Sánchez Ramírez <15837247+mofeing@users.noreply.github.com> --- src/MPS.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MPS.jl b/src/MPS.jl index 6d71b835b..45a6c1329 100644 --- a/src/MPS.jl +++ b/src/MPS.jl @@ -511,12 +511,12 @@ function canonize!(ψ::AbstractMPO; normalize=false) Λ = Tensor[] # right-to-left QR sweep, get right-canonical tensors - for i in nsites(ψ; set=:outputs):-1:2 + for i in nlanes(ψ):-1:2 canonize_site!(ψ, Lane(i); direction=:left, method=:qr) end # left-to-right SVD sweep, get left-canonical tensors and singular values without reversing - for i in 1:(nsites(ψ; set=:outputs) - 1) + for i in 1:(nlanes(ψ) - 1) canonize_site!(ψ, Lane(i); direction=:right, method=:svd) # extract the singular values and contract them with the next tensor @@ -527,7 +527,7 @@ function canonize!(ψ::AbstractMPO; normalize=false) push!(Λ, Λᵢ) end - for i in 2:nsites(ψ; set=:outputs) # tensors at i in "A" form, need to contract (Λᵢ)⁻¹ with A to get Γᵢ + for i in 2:nlanes(ψ) # tensors at i in "A" form, need to contract (Λᵢ)⁻¹ with A to get Γᵢ Λᵢ = Λ[i - 1] # singular values start between site 1 and 2 A = tensors(ψ; at=Lane(i)) Γᵢ = contract(A, Tensor(diag(pinv(Diagonal(parent(Λᵢ)); atol=1e-64)), inds(Λᵢ)); dims=()) From 80a59eb51931eb870545e78ace648e0141170899 Mon Sep 17 00:00:00 2001 From: Todorbsc Date: Thu, 23 Jan 2025 18:37:42 +0100 Subject: [PATCH 7/7] Correct test check --- test/MPO_test.jl | 4 +++- test/MPS_test.jl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/MPO_test.jl b/test/MPO_test.jl index 1425aeeee..a4284294d 100644 --- a/test/MPO_test.jl +++ b/test/MPO_test.jl @@ -89,7 +89,9 @@ # Extract the singular values between each adjacent pair of sites in the canonized chain Λ = [tensors(canonized; between=(Lane(i), Lane(i + 1))) for i in 1:4] - @test map(λ -> sum(abs2, λ), Λ) ≈ ones(length(Λ)) * norm(canonized)^2 + + norm_psi = norm(ψ) + @test all(λ -> sqrt(sum(abs2, λ)) ≈ norm_psi, Λ) for i in 1:5 canonized = canonize(ψ) diff --git a/test/MPS_test.jl b/test/MPS_test.jl index 43a5ef9ed..16e58fd3b 100644 --- a/test/MPS_test.jl +++ b/test/MPS_test.jl @@ -249,7 +249,9 @@ using LinearAlgebra # Extract the singular values between each adjacent pair of sites in the canonized chain Λ = [tensors(canonized; between=(Lane(i), Lane(i + 1))) for i in 1:4] - @test map(λ -> sum(abs2, λ), Λ) ≈ ones(length(Λ)) * norm(canonized)^2 + + norm_psi = norm(ψ) + @test all(λ -> sqrt(sum(abs2, λ)) ≈ norm_psi, Λ) for i in 1:5 canonized = canonize(ψ)