From a332ac986d8a666a0ded1e2c34c1ae11f9e344dd Mon Sep 17 00:00:00 2001 From: Ben Corbett Date: Tue, 15 Oct 2024 15:15:16 -0600 Subject: [PATCH] Updated docs and added tests. --- src/lib/ITensorMPS/src/mpo.jl | 27 +++++++++++++++++------- src/lib/ITensorMPS/test/base/test_mpo.jl | 22 +++++++++---------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/lib/ITensorMPS/src/mpo.jl b/src/lib/ITensorMPS/src/mpo.jl index 362b1364eb..e3e1cf88db 100644 --- a/src/lib/ITensorMPS/src/mpo.jl +++ b/src/lib/ITensorMPS/src/mpo.jl @@ -662,11 +662,16 @@ Choose the method with the `method` keyword, for example - `mindim::Int=1`: the minimal bond dimension of the resulting MPS. - `normalize::Bool=false`: whether or not to normalize the resulting MPS. - `method::String="densitymatrix"`: the algorithm to use for the contraction. - Currently the options are "densitymatrix", where the network formed by the - MPO and MPS is squared and contracted down to a density matrix which is - diagonalized iteratively at each site, and "naive", where the MPO and MPS - tensor are contracted exactly at each site and then a truncation of the - resulting MPS is performed. + - "densitymatrix": The network formed by the MPO and MPS is squared and contracted down to + a density matrix which is diagonalized iteratively at each site. + - "naive": The MPO and MPS tensor are contracted exactly at each site and then a truncation + of the resulting MPS is performed. + - "zipup": The MPO and MPS tensors are contracted then truncated at each site without enforcing + the appropriate orthogonal gauge. Once this sweep is complete a call to `truncate!` occurs. + Because the initial truncation is not locally optimal it is recommended to use a loose + `cutoff` and `maxdim` and then pass the desired truncation parameters to the locally optimal + `truncate!` sweep via the additional keyword argument `truncate_kwargs`. + Suggested use is `contract(A, ψ; method="zipup", cutoff=cutoff / 10, maxdim=2 * maxdim, truncate_kwargs=(; cutoff, maxdim))`. See also [`apply`](@ref). """ @@ -946,14 +951,20 @@ C = apply(A, B; alg="naive", truncate=false) in general you should set a `cutoff` value. - `maxdim::Int=maxlinkdim(A) * maxlinkdim(B))`: the maximal bond dimension of the results MPS. - `mindim::Int=1`: the minimal bond dimension of the resulting MPS. -- `alg="zipup"`: Either `"zipup"` or `"naive"`. `"zipup"` contracts pairs of - site tensors and truncates with SVDs in a sweep across the sites, while `"naive"` - first contracts pairs of tensor exactly and then truncates at the end if `truncate=true`. - `truncate=true`: Enable or disable truncation. If `truncate=false`, ignore other truncation parameters like `cutoff` and `maxdim`. This is most relevant for the `"naive"` version, if you just want to contract the tensors pairwise exactly. This can be useful if you are contracting MPOs that have diverging norms, such as MPOs originating from sums of local operators. +- `alg="zipup"`: the algorithm to use for the contraction. Supported algorithms are + - "naive": The MPO tensors are contracted exactly at each site and then a truncation + of the resulting MPO is performed. + - "zipup": The MPO and MPS tensors are contracted then truncated at each site without enforcing + the appropriate orthogonal gauge. Once this sweep is complete a call to `truncate!` occurs. + Because the initial truncation is not locally optimal it is recommended to use a loose + `cutoff` and `maxdim` and then pass the desired truncation parameters to the locally optimal + `truncate!` sweep via the additional keyword argument `truncate_kwargs`. + Suggested use is `contract(A, ψ; method="zipup", cutoff=cutoff / 10, maxdim=2 * maxdim, truncate_kwargs=(; cutoff, maxdim))`. See also [`apply`](@ref) for details about the arguments available. """ diff --git a/src/lib/ITensorMPS/test/base/test_mpo.jl b/src/lib/ITensorMPS/test/base/test_mpo.jl index 32746a752b..005b95a205 100644 --- a/src/lib/ITensorMPS/test/base/test_mpo.jl +++ b/src/lib/ITensorMPS/test/base/test_mpo.jl @@ -240,14 +240,14 @@ end @test_throws DimensionMismatch error_contract(phi, K, badpsi) end - @testset "contract" begin + @testset "contract(::MPO, ::MPS)" for method in ["densitymatrix", "naive", "zipup"] phi = random_mps(sites) K = random_mpo(sites) @test maxlinkdim(K) == 1 psi = random_mps(sites) - psi_out = contract(K, psi; maxdim=1) + psi_out = contract(K, psi; method, maxdim=1) @test inner(phi', psi_out) ≈ inner(phi', K, psi) - psi_out = contract(psi, K; maxdim=1) + psi_out = contract(psi, K; method, maxdim=1) @test inner(phi', psi_out) ≈ inner(phi', K, psi) psi_out = psi * K @test inner(phi', psi_out) ≈ inner(phi', K, psi) @@ -255,7 +255,7 @@ end badsites = [Index(2, "Site") for n in 1:(N + 1)] badpsi = random_mps(badsites) - @test_throws DimensionMismatch contract(K, badpsi) + @test_throws DimensionMismatch contract(K, badpsi; method) # make bigger random MPO... for link_dim in 2:5 @@ -287,7 +287,7 @@ end orthogonalize!(psi, 1; maxdim=link_dim) orthogonalize!(K, 1; maxdim=link_dim) orthogonalize!(phi, 1; normalize=true, maxdim=link_dim) - psi_out = contract(deepcopy(K), deepcopy(psi); maxdim=10 * link_dim, cutoff=0.0) + psi_out = contract(deepcopy(K), deepcopy(psi); method, maxdim=10 * link_dim, cutoff=0.0) @test inner(phi', psi_out) ≈ inner(phi', K, psi) end end @@ -354,14 +354,14 @@ end @test maxlinkdim(H) ≤ maxlinkdim(H₁) + maxlinkdim(H₂) end - @testset "contract(::MPO, ::MPO)" begin + @testset "contract(::MPO, ::MPO)" for alg in ["naive", "zipup"] psi = random_mps(sites) K = random_mpo(sites) L = random_mpo(sites) @test maxlinkdim(K) == 1 @test maxlinkdim(L) == 1 - KL = contract(prime(K), L; maxdim=1) - psi_kl_out = contract(prime(K), contract(L, psi; maxdim=1); maxdim=1) + KL = contract(prime(K), L; alg, maxdim=1) + psi_kl_out = contract(prime(K), contract(L, psi; alg, maxdim=1); alg, maxdim=1) @test inner(psi'', KL, psi) ≈ inner(psi'', psi_kl_out) atol = 5e-3 # where both K and L have differently labelled sites @@ -373,15 +373,15 @@ end replaceind!(K[ii], sites[ii]', othersitesk[ii]) replaceind!(L[ii], sites[ii]', othersitesl[ii]) end - KL = contract(K, L; maxdim=1) + KL = contract(K, L; alg, maxdim=1) psik = random_mps(othersitesk) psil = random_mps(othersitesl) - psi_kl_out = contract(K, contract(L, psil; maxdim=1); maxdim=1) + psi_kl_out = contract(K, contract(L, psil; alg, maxdim=1); alg, maxdim=1) @test inner(psik, KL, psil) ≈ inner(psik, psi_kl_out) atol = 5e-3 badsites = [Index(2, "Site") for n in 1:(N + 1)] badL = random_mpo(badsites) - @test_throws DimensionMismatch contract(K, badL) + @test_throws DimensionMismatch contract(K, badL; alg) end @testset "*(::MPO, ::MPO)" begin