From f3da194a0d98b1550456d054dff9f3414ae56780 Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 17 Mar 2022 13:34:56 +0100 Subject: [PATCH 1/6] Include the product of local dimensions beginning from the start of the chain when determining the maximal reasonable bond dimensions in randomCircuitMPS. --- src/mps/mps.jl | 95 ++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/src/mps/mps.jl b/src/mps/mps.jl index f33dafb91f..345219b75d 100644 --- a/src/mps/mps.jl +++ b/src/mps/mps.jl @@ -127,48 +127,61 @@ function randomizeMPS!(M::MPS, sites::Vector{<:Index}, linkdim=1) end end -function randomCircuitMPS( - ::Type{ElT}, sites::Vector{<:Index}, linkdim::Int; kwargs... -) where {ElT<:Number} - _rmatrix(::Type{Float64}, n, m) = NDTensors.random_orthog(n, m) - _rmatrix(::Type{ComplexF64}, n, m) = NDTensors.random_unitary(n, m) - - N = length(sites) - M = MPS(N) - - if N == 1 - M[1] = ITensor(randn(dim(sites[1])), sites[1]) - M[1] /= norm(M[1]) +function myRandomCircuitMPS( + ::Type{ElT}, sites::Vector{<:Index}, linkdim::Int; kwargs... + ) where {ElT<:Number} + _rmatrix(::Type{Float64}, n, m) = NDTensors.random_orthog(n, m) + _rmatrix(::Type{ComplexF64}, n, m) = NDTensors.random_unitary(n, m) + + N = length(sites) + M = MPS(N) + + if N == 1 + M[1] = ITensor(randn(dim(sites[1])), sites[1]) + M[1] /= norm(M[1]) + return M + end + + l = Vector{Index}(undef, N) + + # Compute the bond dimension for each link. + # It should be the the minimum of the product of local + # Hilbert space dimensions taken from either end of the chain + # or the `linkdim`. + maxdims = Vector{Int}(undef, N-1) + maxdims[1] = min(dim(sites[1]), linkdim) + for i in 2:N-1 + maxdims[i] = min(maxdims[i-1]*dim(sites[i]), linkdim) + end + maxdims[N-1] = min(dim(sites[N]), maxdims[N-1]) + for i in N-2:-1:1 + maxdims[i] = min(dim(sites[i+1])*maxdims[i+1], maxdims[i]) + end + + d = dim(sites[N]) + chi = maxdims[N-1] + l[N - 1] = Index(chi, "Link,l=$(N-1)") + O = _rmatrix(ElT, chi, d) + M[N] = itensor(O, l[N - 1], sites[N]) + + for j in (N - 1):-1:2 + chi = maxdims[j-1] + l[j - 1] = Index(chi, "Link,l=$(j-1)") + O = _rmatrix(ElT, chi, dim(sites[j]) * dim(l[j])) + T = reshape(O, (chi, dim(sites[j]), dim(l[j]))) + M[j] = itensor(T, l[j - 1], sites[j], l[j]) + end + + O = _rmatrix(ElT, 1, dim(sites[1]) * dim(l[1])) + l0 = Index(1, "Link,l=0") + T = reshape(O, (1, dim(sites[1]), dim(l[1]))) + M[1] = itensor(T, l0, sites[1], l[1]) + M[1] *= onehot(l0 => 1) + + M.llim = 0 + M.rlim = 2 + return M - end - - l = Vector{Index}(undef, N) - - d = dim(sites[N]) - chi = min(linkdim, d) - l[N - 1] = Index(chi, "Link,l=$(N-1)") - O = _rmatrix(ElT, chi, d) - M[N] = itensor(O, l[N - 1], sites[N]) - - for j in (N - 1):-1:2 - chi *= dim(sites[j]) - chi = min(linkdim, chi) - l[j - 1] = Index(chi, "Link,l=$(j-1)") - O = _rmatrix(ElT, chi, dim(sites[j]) * dim(l[j])) - T = reshape(O, (chi, dim(sites[j]), dim(l[j]))) - M[j] = itensor(T, l[j - 1], sites[j], l[j]) - end - - O = _rmatrix(ElT, 1, dim(sites[1]) * dim(l[1])) - l0 = Index(1, "Link,l=0") - T = reshape(O, (1, dim(sites[1]), dim(l[1]))) - M[1] = itensor(T, l0, sites[1], l[1]) - M[1] *= onehot(l0 => 1) - - M.llim = 0 - M.rlim = 2 - - return M end function randomCircuitMPS(sites::Vector{<:Index}, linkdim::Integer; kwargs...) From 4e436ea59b2b2e46345c95499938a55cdb073a0f Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 17 Mar 2022 14:00:54 +0100 Subject: [PATCH 2/6] Added test for randomCircuitMPS bond dimensions. --- test/mps.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/mps.jl b/test/mps.jl index 0a7e1ed291..d1412e67d2 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -196,6 +196,16 @@ include("util.jl") @test norm(phi[4]) ≈ 1.0 @test norm(phic[4]) ≈ 1.0 end + + @testset "randomCircuitMPS bond dimensions" begin + phi = randomCircuitMPS(ComplexF64,sites,32) + expected_dims = [2, 4, 8, 16, 32, 16, 8, 4, 2] + + for i in 1:9 + l = getfirst(x->hastags(x,"Link,l=$(i)"),inds(mps[i])) + @test dim(l) == expected_dims[i] + end + end @testset "inner different MPS" begin phi = randomMPS(sites) From 82a4ea4a79eec6b936a843b28407468821c79cf7 Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 17 Mar 2022 14:05:35 +0100 Subject: [PATCH 3/6] Formating. --- src/mps/mps.jl | 106 ++++++++++++++++++++++++------------------------- test/mps.jl | 6 +-- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/mps/mps.jl b/src/mps/mps.jl index 345219b75d..6478cb71e6 100644 --- a/src/mps/mps.jl +++ b/src/mps/mps.jl @@ -128,60 +128,60 @@ function randomizeMPS!(M::MPS, sites::Vector{<:Index}, linkdim=1) end function myRandomCircuitMPS( - ::Type{ElT}, sites::Vector{<:Index}, linkdim::Int; kwargs... - ) where {ElT<:Number} - _rmatrix(::Type{Float64}, n, m) = NDTensors.random_orthog(n, m) - _rmatrix(::Type{ComplexF64}, n, m) = NDTensors.random_unitary(n, m) - - N = length(sites) - M = MPS(N) - - if N == 1 - M[1] = ITensor(randn(dim(sites[1])), sites[1]) - M[1] /= norm(M[1]) - return M - end - - l = Vector{Index}(undef, N) - - # Compute the bond dimension for each link. - # It should be the the minimum of the product of local - # Hilbert space dimensions taken from either end of the chain - # or the `linkdim`. - maxdims = Vector{Int}(undef, N-1) - maxdims[1] = min(dim(sites[1]), linkdim) - for i in 2:N-1 - maxdims[i] = min(maxdims[i-1]*dim(sites[i]), linkdim) - end - maxdims[N-1] = min(dim(sites[N]), maxdims[N-1]) - for i in N-2:-1:1 - maxdims[i] = min(dim(sites[i+1])*maxdims[i+1], maxdims[i]) - end - - d = dim(sites[N]) - chi = maxdims[N-1] - l[N - 1] = Index(chi, "Link,l=$(N-1)") - O = _rmatrix(ElT, chi, d) - M[N] = itensor(O, l[N - 1], sites[N]) - - for j in (N - 1):-1:2 - chi = maxdims[j-1] - l[j - 1] = Index(chi, "Link,l=$(j-1)") - O = _rmatrix(ElT, chi, dim(sites[j]) * dim(l[j])) - T = reshape(O, (chi, dim(sites[j]), dim(l[j]))) - M[j] = itensor(T, l[j - 1], sites[j], l[j]) - end - - O = _rmatrix(ElT, 1, dim(sites[1]) * dim(l[1])) - l0 = Index(1, "Link,l=0") - T = reshape(O, (1, dim(sites[1]), dim(l[1]))) - M[1] = itensor(T, l0, sites[1], l[1]) - M[1] *= onehot(l0 => 1) - - M.llim = 0 - M.rlim = 2 - + ::Type{ElT}, sites::Vector{<:Index}, linkdim::Int; kwargs... +) where {ElT<:Number} + _rmatrix(::Type{Float64}, n, m) = NDTensors.random_orthog(n, m) + _rmatrix(::Type{ComplexF64}, n, m) = NDTensors.random_unitary(n, m) + + N = length(sites) + M = MPS(N) + + if N == 1 + M[1] = ITensor(randn(dim(sites[1])), sites[1]) + M[1] /= norm(M[1]) return M + end + + l = Vector{Index}(undef, N) + + # Compute the bond dimension for each link. + # It should be the the minimum of the product of local + # Hilbert space dimensions taken from either end of the chain + # or the `linkdim`. + maxdims = Vector{Int}(undef, N - 1) + maxdims[1] = min(dim(sites[1]), linkdim) + for i in 2:(N - 1) + maxdims[i] = min(maxdims[i - 1] * dim(sites[i]), linkdim) + end + maxdims[N - 1] = min(dim(sites[N]), maxdims[N - 1]) + for i in (N - 2):-1:1 + maxdims[i] = min(dim(sites[i + 1]) * maxdims[i + 1], maxdims[i]) + end + + d = dim(sites[N]) + chi = maxdims[N - 1] + l[N - 1] = Index(chi, "Link,l=$(N-1)") + O = _rmatrix(ElT, chi, d) + M[N] = itensor(O, l[N - 1], sites[N]) + + for j in (N - 1):-1:2 + chi = maxdims[j - 1] + l[j - 1] = Index(chi, "Link,l=$(j-1)") + O = _rmatrix(ElT, chi, dim(sites[j]) * dim(l[j])) + T = reshape(O, (chi, dim(sites[j]), dim(l[j]))) + M[j] = itensor(T, l[j - 1], sites[j], l[j]) + end + + O = _rmatrix(ElT, 1, dim(sites[1]) * dim(l[1])) + l0 = Index(1, "Link,l=0") + T = reshape(O, (1, dim(sites[1]), dim(l[1]))) + M[1] = itensor(T, l0, sites[1], l[1]) + M[1] *= onehot(l0 => 1) + + M.llim = 0 + M.rlim = 2 + + return M end function randomCircuitMPS(sites::Vector{<:Index}, linkdim::Integer; kwargs...) diff --git a/test/mps.jl b/test/mps.jl index d1412e67d2..75c5ecfd83 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -196,13 +196,13 @@ include("util.jl") @test norm(phi[4]) ≈ 1.0 @test norm(phic[4]) ≈ 1.0 end - + @testset "randomCircuitMPS bond dimensions" begin - phi = randomCircuitMPS(ComplexF64,sites,32) + phi = randomCircuitMPS(ComplexF64, sites, 32) expected_dims = [2, 4, 8, 16, 32, 16, 8, 4, 2] for i in 1:9 - l = getfirst(x->hastags(x,"Link,l=$(i)"),inds(mps[i])) + l = getfirst(x -> hastags(x, "Link,l=$(i)"), inds(mps[i])) @test dim(l) == expected_dims[i] end end From d3d81b57ad78b1297108f5e05a9eabcfe561a8cd Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 5 Apr 2022 09:08:30 +0200 Subject: [PATCH 4/6] Fixed randomCircuitMPS function name. Use in test for bond dimension. --- src/mps/mps.jl | 2 +- test/mps.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mps/mps.jl b/src/mps/mps.jl index 6478cb71e6..a5fc808509 100644 --- a/src/mps/mps.jl +++ b/src/mps/mps.jl @@ -127,7 +127,7 @@ function randomizeMPS!(M::MPS, sites::Vector{<:Index}, linkdim=1) end end -function myRandomCircuitMPS( +function randomCircuitMPS( ::Type{ElT}, sites::Vector{<:Index}, linkdim::Int; kwargs... ) where {ElT<:Number} _rmatrix(::Type{Float64}, n, m) = NDTensors.random_orthog(n, m) diff --git a/test/mps.jl b/test/mps.jl index 75c5ecfd83..c8c2595bec 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -197,8 +197,8 @@ include("util.jl") @test norm(phic[4]) ≈ 1.0 end - @testset "randomCircuitMPS bond dimensions" begin - phi = randomCircuitMPS(ComplexF64, sites, 32) + @testset "randomMPS bond dimensions" begin + phi = randomMPS(ComplexF64, sites) expected_dims = [2, 4, 8, 16, 32, 16, 8, 4, 2] for i in 1:9 From c2a131aa1d939fcf87fa3329a02cbed247b2f6b9 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 13 Jul 2022 12:13:25 +0200 Subject: [PATCH 5/6] Fixed test for randomCircuitMPS --- test/mps.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mps.jl b/test/mps.jl index c8c2595bec..294cd8f826 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -202,7 +202,7 @@ include("util.jl") expected_dims = [2, 4, 8, 16, 32, 16, 8, 4, 2] for i in 1:9 - l = getfirst(x -> hastags(x, "Link,l=$(i)"), inds(mps[i])) + l = linkind(phi, i) @test dim(l) == expected_dims[i] end end From 238e4dcb183ed9171027370db11c32eb40af4d53 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 13 Jul 2022 12:59:27 +0200 Subject: [PATCH 6/6] Tests passing. --- Project.toml | 1 + test/mps.jl | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index edb849908c..b15ffe42ee 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.3.18" [deps] BitIntegers = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1" ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" diff --git a/test/mps.jl b/test/mps.jl index 832d40e3ac..e88751db10 100644 --- a/test/mps.jl +++ b/test/mps.jl @@ -198,7 +198,7 @@ include("util.jl") end @testset "randomMPS bond dimensions" begin - phi = randomMPS(ComplexF64, sites) + phi = randomMPS(ComplexF64, sites, 50) expected_dims = [2, 4, 8, 16, 32, 16, 8, 4, 2] for i in 1:9 @@ -492,7 +492,8 @@ include("util.jl") ϕ2 = +(ψ1, ψ2; alg="directsum") for j in 1:8 - @test linkdim(ϕ2, j) == χ1 + χ2 + #@test linkdim(ϕ2, j) == χ1 + χ2 + @test linkdim(ϕ2, j) == linkdim(ψ1, j) + linkdim(ψ2, j) end @test inner(ϕ2, ψ1) + inner(ϕ2, ψ2) ≈ inner(ϕ2, ϕ2) end