diff --git a/src/operators/densempo.jl b/src/operators/densempo.jl index daf9f9f6..ca4c1584 100644 --- a/src/operators/densempo.jl +++ b/src/operators/densempo.jl @@ -83,12 +83,12 @@ function Base.convert(::Type{<:AbstractTensorMap}, mpo::FiniteMPO) U_right = Tensor(ones, scalartype(mpo), V_right') tensors = vcat(U_left, mpo.opp, U_right) - indices = [[i, -i, -(i + N), i + 1] for i in 1:length(mpo)] + indices = [[i, -i, -(2N - i + 1), i + 1] for i in 1:length(mpo)] pushfirst!(indices, [1]) push!(indices, [N + 1]) O = ncon(tensors, indices) - return transpose(O, (ntuple(identity, N), ntuple(i -> i + N, N))) + return transpose(O, (ntuple(identity, N), ntuple(i -> 2N - i + 1, N))) end # Linear Algebra @@ -210,7 +210,8 @@ function Base.:*(mpo1::FiniteMPO{TO}, mpo2::FiniteMPO{TO}) where {TO} Fₗ = i != 1 ? Fᵣ : isomorphism(A, fuse(left_virtualspace(mpo2, i), left_virtualspace(mpo1, i)), left_virtualspace(mpo2, i) * left_virtualspace(mpo1, i)) - Fᵣ = isomorphism(A, fuse(right_virtualspace(mpo2, i), right_virtualspace(mpo1, i)), + Fᵣ = isomorphism(A, + fuse(right_virtualspace(mpo2, i)', right_virtualspace(mpo1, i)'), right_virtualspace(mpo2, i)' * right_virtualspace(mpo1, i)') @plansor O[i][-1 -2; -3 -4] := Fₗ[-1; 1 4] * mpo2[i][1 2; -3 3] * @@ -232,7 +233,7 @@ function Base.:*(mpo::FiniteMPO, mps::FiniteMPS) Fₗ = i != 1 ? Fᵣ : isomorphism(TT, fuse(left_virtualspace(A[i]), left_virtualspace(mpo, i)), left_virtualspace(A[i]) * left_virtualspace(mpo, i)) - Fᵣ = isomorphism(TT, fuse(right_virtualspace(A[i]), right_virtualspace(mpo, i)), + Fᵣ = isomorphism(TT, fuse(right_virtualspace(A[i])', right_virtualspace(mpo, i)'), right_virtualspace(A[i])' * right_virtualspace(mpo, i)') @plansor A[i][-1 -2; -3] := Fₗ[-1; 1 3] * A[i][1 2; 4] * mpo[i][3 -2; 2 5] * diff --git a/test/algorithms.jl b/test/algorithms.jl index 24305d87..4d0ca284 100644 --- a/test/algorithms.jl +++ b/test/algorithms.jl @@ -72,14 +72,17 @@ end tol = 1e-8 g = 4.0 D = 6 - H = force_planar(transverse_field_ising(; g)) - @testset "VUMPS" begin - ψ₀ = InfiniteMPS(ℙ^2, ℙ^D) - v₀ = variance(ψ₀, H) + H_ref = force_planar(transverse_field_ising(; g)) + ψ = InfiniteMPS(ℙ^2, ℙ^D) + v₀ = variance(ψ, H_ref) + + @testset "VUMPS" for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℙ^2, ℙ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) # test logging - ψ, envs, δ = find_groundstate(ψ₀, H, VUMPS(; tol, verbosity=5, maxiter=2)) + ψ, envs, δ = find_groundstate(ψ, H, VUMPS(; tol, verbosity=5, maxiter=2)) ψ, envs, δ = find_groundstate(ψ, H, VUMPS(; tol, verbosity=1)) v = variance(ψ, H, envs) @@ -90,12 +93,12 @@ end @test v < 1e-2 end - @testset "IDMRG1" begin - ψ₀ = InfiniteMPS(ℙ^2, ℙ^D) - v₀ = variance(ψ₀, H) + @testset "IDMRG1" for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℙ^2, ℙ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) # test logging - ψ, envs, δ = find_groundstate(ψ₀, H, IDMRG1(; tol, verbosity=5, maxiter=2)) + ψ, envs, δ = find_groundstate(ψ, H, IDMRG1(; tol, verbosity=5, maxiter=2)) ψ, envs, δ = find_groundstate(ψ, H, IDMRG1(; tol, verbosity=1)) v = variance(ψ, H, envs) @@ -107,19 +110,19 @@ end end @testset "IDMRG2" begin - ψ₀ = repeat(InfiniteMPS(ℙ^2, ℙ^D), 2) - H2 = repeat(H, 2) - v₀ = variance(ψ₀, H2) + ψ = repeat(InfiniteMPS(ℙ^2, ℙ^D), 2) + H = repeat(H_ref, 2) + trscheme = truncbelow(1e-8) # test logging - ψ, envs, δ = find_groundstate(ψ₀, H2, + ψ, envs, δ = find_groundstate(ψ, H, IDMRG2(; tol, verbosity=5, maxiter=2, trscheme)) - ψ, envs, δ = find_groundstate(ψ, H2, + ψ, envs, δ = find_groundstate(ψ, H, IDMRG2(; tol, verbosity=1, trscheme)) - v = variance(ψ, H2, envs) + v = variance(ψ, H, envs) # test using low variance @test sum(δ) ≈ 0 atol = 1e-3 @@ -127,12 +130,12 @@ end @test v < 1e-2 end - @testset "GradientGrassmann" begin - ψ₀ = InfiniteMPS(ℙ^2, ℙ^D) - v₀ = variance(ψ₀, H) + @testset "GradientGrassmann" for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℙ^2, ℙ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) # test logging - ψ, envs, δ = find_groundstate(ψ₀, H, + ψ, envs, δ = find_groundstate(ψ, H, GradientGrassmann(; tol, verbosity=5, maxiter=2)) ψ, envs, δ = find_groundstate(ψ, H, GradientGrassmann(; tol, verbosity=1)) @@ -144,13 +147,13 @@ end @test v < 1e-2 end - @testset "Combination" begin - ψ₀ = InfiniteMPS(ℙ^2, ℙ^D) - v₀ = variance(ψ₀, H) + @testset "Combination" for unit_cell_size in [1, 3] + ψ = unit_cell_size == 1 ? InfiniteMPS(ℙ^2, ℙ^D) : repeat(ψ, unit_cell_size) + H = repeat(H_ref, unit_cell_size) alg = VUMPS(; tol=100 * tol, verbosity=1, maxiter=10) & GradientGrassmann(; tol, verbosity=1, maxiter=50) - ψ, envs, δ = find_groundstate(ψ₀, H, alg) + ψ, envs, δ = find_groundstate(ψ, H, alg) v = variance(ψ, H, envs) @@ -452,7 +455,7 @@ end Rep[SU₂](0 => 2, 1 => 2, 2 => 1))] @testset "mpo" begin - #random nn interaction + # random nn interaction nn = TensorMap(rand, ComplexF64, pspace * pspace, pspace * pspace) nn += nn' H = MPOHamiltonian(nn) @@ -467,33 +470,49 @@ end end @testset "infinite mps" begin - #random nn interaction + # random nn interaction nn = TensorMap(rand, ComplexF64, pspace * pspace, pspace * pspace) nn += nn' - state = InfiniteMPS([pspace, pspace], [Dspace, Dspace]) - - state_re = changebonds(state, - RandExpand(; trscheme=truncdim(dim(Dspace) * dim(Dspace)))) - @test dot(state, state_re) ≈ 1 atol = 1e-8 - - state_oe, _ = changebonds(state, - repeat(MPOHamiltonian(nn), 2), - OptimalExpand(; - trscheme=truncdim(dim(Dspace) * - dim(Dspace)))) - @test dot(state, state_oe) ≈ 1 atol = 1e-8 - - state_vs, _ = changebonds(state, repeat(MPOHamiltonian(nn), 2), - VUMPSSvdCut(; trscheme=notrunc())) - @test dim(left_virtualspace(state, 1)) < dim(left_virtualspace(state_vs, 1)) + # test rand_expand + for unit_cell_size in 2:3 + H = repeat(MPOHamiltonian(nn), unit_cell_size) + state = InfiniteMPS(fill(pspace, unit_cell_size), fill(Dspace, unit_cell_size)) - state_vs_tr = changebonds(state_vs, SvdCut(; trscheme=truncdim(dim(Dspace)))) - @test dim(right_virtualspace(state_vs_tr, 1)) < dim(right_virtualspace(state_vs, 1)) + state_re = changebonds(state, + RandExpand(; + trscheme=truncdim(dim(Dspace) * dim(Dspace)))) + @test dot(state, state_re) ≈ 1 atol = 1e-8 + end + # test optimal_expand + for unit_cell_size in 2:3 + H = repeat(MPOHamiltonian(nn), unit_cell_size) + state = InfiniteMPS(fill(pspace, unit_cell_size), fill(Dspace, unit_cell_size)) + + state_oe, _ = changebonds(state, + H, + OptimalExpand(; + trscheme=truncdim(dim(Dspace) * + dim(Dspace)))) + @test dot(state, state_oe) ≈ 1 atol = 1e-8 + end + # test VUMPSSvdCut + for unit_cell_size in [1, 2, 3, 4] + H = repeat(MPOHamiltonian(nn), unit_cell_size) + state = InfiniteMPS(fill(pspace, unit_cell_size), fill(Dspace, unit_cell_size)) + + state_vs, _ = changebonds(state, H, + VUMPSSvdCut(; trscheme=notrunc())) + @test dim(left_virtualspace(state, 1)) < dim(left_virtualspace(state_vs, 1)) + + state_vs_tr = changebonds(state_vs, SvdCut(; trscheme=truncdim(dim(Dspace)))) + @test dim(right_virtualspace(state_vs_tr, 1)) < + dim(right_virtualspace(state_vs, 1)) + end end @testset "finite mps" begin - #random nn interaction + # random nn interaction nn = TensorMap(rand, ComplexF64, pspace * pspace, pspace * pspace) nn += nn' @@ -576,7 +595,7 @@ end for λ in [1.05, 2.0, 4.0] H = hamiltonian(λ) ψ = InfiniteMPS([ℂ^2], [ℂ^16]) - ψ, envs, = find_groundstate(ψ, H, VUMPS(; maxiter=100, verbosity=0)) + ψ, envs = find_groundstate(ψ, H, VUMPS(; maxiter=100, verbosity=0)) numerical_scusceptibility = fidelity_susceptibility(ψ, H, [H_X], envs; maxiter=10) @test numerical_scusceptibility[1, 1] ≈ analytical_susceptibility(λ) atol = 1e-2 @@ -584,7 +603,7 @@ end # test if the finite fid sus approximates the analytical one with increasing system size fin_en = map([20, 15, 10]) do L ψ = FiniteMPS(rand, ComplexF64, L, ℂ^2, ℂ^16) - ψ, envs, = find_groundstate(ψ, H, DMRG(; verbosity=0)) + ψ, envs = find_groundstate(ψ, H, DMRG(; verbosity=0)) numerical_scusceptibility = fidelity_susceptibility(ψ, H, [H_X], envs; maxiter=10) return numerical_scusceptibility[1, 1] / L @@ -593,7 +612,7 @@ end end end -#stub tests +# stub tests @testset "correlation length / entropy" begin ψ = InfiniteMPS([ℙ^2], [ℙ^10]) H = force_planar(transverse_field_ising()) @@ -697,7 +716,7 @@ end @testset "periodic boundary conditions" begin len = 10 - #impose periodic boundary conditions on the hamiltonian (circle size 10) + # impose periodic boundary conditions on the hamiltonian (circle size 10) H = transverse_field_ising() H = periodic_boundary_conditions(H, len) @@ -705,12 +724,12 @@ end gs, envs = find_groundstate(ψ, H, DMRG(; verbosity=0)) - #translation mpo: + # translation mpo: @tensor bulk[-1 -2; -3 -4] := isomorphism(ℂ^2, ℂ^2)[-2, -4] * isomorphism(ℂ^2, ℂ^2)[-1, -3] translation = periodic_boundary_conditions(DenseMPO(bulk), len) - #the groundstate should be translation invariant: + # the groundstate should be translation invariant: ut = Tensor(ones, ℂ^1) @tensor leftstart[-1 -2; -3] := l_LL(gs)[-1, -3] * conj(ut[-2]) T = TransferMatrix([gs.AC[1]; gs.AR[2:end]], translation[:], [gs.AC[1]; gs.AR[2:end]]) diff --git a/test/operators.jl b/test/operators.jl index 7c105fce..a0dac1d4 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -19,39 +19,43 @@ vspaces = (ℙ^10, Rep[U₁]((0 => 20)), Rep[SU₂](1 // 2 => 10, 3 // 2 => 5, 5 @testset "FiniteMPO" begin # start from random operators L = 4 - O₁ = TensorMap(rand, ComplexF64, (ℂ^2)^L, (ℂ^2)^L) - O₂ = TensorMap(rand, ComplexF64, space(O₁)) + T = ComplexF64 - # create MPO and convert it back to see if it is the same - mpo₁ = FiniteMPO(O₁) # type-unstable for now! - mpo₂ = FiniteMPO(O₂) - @test convert(TensorMap, mpo₁) ≈ O₁ - @test convert(TensorMap, -mpo₂) ≈ -O₂ + for V in (ℂ^2, U1Space(0 => 1, 1 => 1)) + O₁ = TensorMap(rand, T, V^L, V^L) + O₂ = TensorMap(rand, T, space(O₁)) - # test scalar multiplication - α = rand(ComplexF64) - @test convert(TensorMap, α * mpo₁) ≈ α * O₁ - @test convert(TensorMap, mpo₁ * α) ≈ O₁ * α + # create MPO and convert it back to see if it is the same + mpo₁ = FiniteMPO(O₁) # type-unstable for now! + mpo₂ = FiniteMPO(O₂) + @test convert(TensorMap, mpo₁) ≈ O₁ + @test convert(TensorMap, -mpo₂) ≈ -O₂ - # test addition and multiplication - @test convert(TensorMap, mpo₁ + mpo₂) ≈ O₁ + O₂ - @test convert(TensorMap, mpo₁ * mpo₂) ≈ O₁ * O₂ + # test scalar multiplication + α = rand(T) + @test convert(TensorMap, α * mpo₁) ≈ α * O₁ + @test convert(TensorMap, mpo₁ * α) ≈ O₁ * α - # test application to a state - ψ₁ = Tensor(rand, ComplexF64, domain(O₁)) - mps₁ = FiniteMPS(ψ₁) + # test addition and multiplication + @test convert(TensorMap, mpo₁ + mpo₂) ≈ O₁ + O₂ + @test convert(TensorMap, mpo₁ * mpo₂) ≈ O₁ * O₂ - @test convert(TensorMap, mpo₁ * mps₁) ≈ O₁ * ψ₁ + # test application to a state + ψ₁ = Tensor(rand, T, domain(O₁)) + mps₁ = FiniteMPS(ψ₁) - @test dot(mps₁, mpo₁, mps₁) ≈ dot(ψ₁, O₁, ψ₁) - @test dot(mps₁, mpo₁, mps₁) ≈ dot(mps₁, mpo₁ * mps₁) - # test conversion to and from mps - mpomps₁ = convert(FiniteMPS, mpo₁) - mpompsmpo₁ = convert(FiniteMPO, mpomps₁) + @test convert(TensorMap, mpo₁ * mps₁) ≈ O₁ * ψ₁ - @test convert(FiniteMPO, mpomps₁) ≈ mpo₁ rtol = 1e-6 + @test dot(mps₁, mpo₁, mps₁) ≈ dot(ψ₁, O₁, ψ₁) + @test dot(mps₁, mpo₁, mps₁) ≈ dot(mps₁, mpo₁ * mps₁) + # test conversion to and from mps + mpomps₁ = convert(FiniteMPS, mpo₁) + mpompsmpo₁ = convert(FiniteMPO, mpomps₁) - @test dot(mpomps₁, mpomps₁) ≈ dot(mpo₁, mpo₁) + @test convert(FiniteMPO, mpomps₁) ≈ mpo₁ rtol = 1e-6 + + @test dot(mpomps₁, mpomps₁) ≈ dot(mpo₁, mpo₁) + end end @testset "Finite MPOHamiltonian" begin