Skip to content

Commit e42e898

Browse files
Revert TaylorCluster Optimizations of #199 (#220)
* revert broken TaylorCluster optimizations * make mpo using `MPO(parent(H))` instead of checking for finite or infinite case * remove commented-out code, copy master branch changes * remove TupleTools * add scaling tests for finite time evolution with TaylorClusters
1 parent 925edc4 commit e42e898

File tree

4 files changed

+87
-123
lines changed

4 files changed

+87
-123
lines changed

Project.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
2222
TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec"
2323
TensorKitManifolds = "11fa318c-39cb-4a83-b1ed-cdc7ba1e3684"
2424
Transducers = "28d57a85-8fef-5791-bfe6-a80928e7c999"
25-
TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
2625
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"
2726

2827
[compat]
@@ -50,7 +49,6 @@ TensorOperations = "5"
5049
Test = "1"
5150
TestExtras = "0.3"
5251
Transducers = "0.4"
53-
TupleTools = "1.6.0"
5452
VectorInterface = "0.2, 0.3, 0.4, 0.5"
5553
julia = "1.10"
5654

src/MPSKit.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ using RecipesBase
1212
using VectorInterface
1313
using Accessors
1414
using HalfIntegers
15-
import TupleTools as TT
1615
using DocStringExtensions
1716

1817
using LinearAlgebra: diag, Diagonal

src/algorithms/timestep/timeevmpo.jl

Lines changed: 50 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ $(TYPEDFIELDS)
3838
"include higher-order corrections"
3939
extension::Bool = true
4040
"approximate compression of corrections, accurate up to order `N`"
41-
compression::Bool = true
41+
compression::Bool = false
4242
end
4343

4444
const WI = TaylorCluster(; N=1, extension=false, compression=false)
4545

46-
function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster)
46+
function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster;
47+
tol=eps(real(scalartype(H)))^(3 / 4))
4748
N = alg.N
4849
τ = -1im * dt
4950

@@ -80,73 +81,65 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster)
8081
if alg.extension
8182
H_next = H_n * H′
8283
linds_next = LinearIndices(ntuple(i -> V, N + 1))
83-
cinds_next = CartesianIndices(linds_next)
8484
for (i, slice) in enumerate(parent(H_n))
85-
for Inext in nonzero_keys(H_next[i])
86-
aₑ = cinds_next[Inext[1]]
87-
bₑ = cinds_next[Inext[4]]
88-
for c in findall(==(1), aₑ.I), d in findall(==(V), bₑ.I)
89-
a = TT.deleteat(Tuple(aₑ), c)
90-
b = TT.deleteat(Tuple(bₑ), d)
91-
if all(>(1), b) && !(all(in((1, V), a)) && any(==(V), a))
92-
n1 = count(==(1), a) + 1
93-
n3 = count(==(V), b) + 1
94-
factor = τ * factorial(N) / (factorial(N + 1) * n1 * n3)
95-
slice[linds[a...], 1, 1, linds[b...]] += factor * H_next[i][Inext]
96-
end
85+
for a in cinds, b in cinds
86+
all(>(1), b.I) || continue
87+
all(in((1, V)), a.I) && any(==(V), a.I) && continue
88+
89+
n1 = count(==(1), a.I) + 1
90+
n3 = count(==(V), b.I) + 1
91+
factor = τ * factorial(N) / (factorial(N + 1) * n1 * n3)
92+
93+
for c in 1:(N + 1), d in 1:(N + 1)
94+
aₑ = insert!([a.I...], c, 1)
95+
bₑ = insert!([b.I...], d, V)
96+
97+
# TODO: use VectorInterface for memory efficiency
98+
slice[linds[a], 1, 1, linds[b]] += factor *
99+
H_next[i][linds_next[aₑ...], 1, 1,
100+
linds_next[bₑ...]]
97101
end
98102
end
99103
end
100104
end
101105

102106
# loopback step: Algorithm 1
103107
# constructing the Nth order time evolution MPO
104-
if H isa FiniteMPOHamiltonian
105-
mpo = FiniteMPO(parent(H_n))
106-
else
107-
mpo = InfiniteMPO(parent(H_n))
108-
end
108+
mpo = MPO(parent(H_n))
109109
for slice in parent(mpo)
110-
for (I, v) in nonzero_pairs(slice)
111-
a = cinds[I[1]]
112-
b = cinds[I[4]]
113-
if all(in((1, V)), a.I) && any(!=(1), a.I)
114-
delete!(slice, I)
115-
elseif any(!=(1), b.I) && all(in((1, V)), b.I)
116-
exponent = count(==(V), b.I)
117-
factor = τ^exponent * factorial(N - exponent) / factorial(N)
118-
Idst = CartesianIndex(Base.setindex(I.I, 1, 4))
119-
slice[Idst] += factor * v
120-
delete!(slice, I)
110+
for b in cinds[2:end]
111+
all(in((1, V)), b.I) || continue
112+
113+
b_lin = linds[b]
114+
a = count(==(V), b.I)
115+
factor = τ^a * factorial(N - a) / factorial(N)
116+
slice[:, 1, 1, 1] = slice[:, 1, 1, 1] + factor * slice[:, 1, 1, b_lin]
117+
for I in nonzero_keys(slice)
118+
(I[1] == b_lin || I[4] == b_lin) && delete!(slice, I)
121119
end
122120
end
123121
end
124122

125123
# Remove equivalent rows and columns: Algorithm 2
126124
for slice in parent(mpo)
127-
for I in nonzero_keys(slice)
128-
a = cinds[I[1]]
129-
a_sort = CartesianIndex(sort(collect(a.I); by=(!=(1)))...)
130-
n1_a = count(==(1), a.I)
131-
n3_a = count(==(V), a.I)
132-
if n3_a <= n1_a && a_sort != a
133-
Idst = CartesianIndex(Base.setindex(I.I, linds[a_sort], 1))
134-
slice[Idst] += slice[I]
135-
delete!(slice, I)
136-
elseif a != a_sort
137-
delete!(slice, I)
138-
end
125+
for c in cinds
126+
c_lin = linds[c]
127+
s_c = CartesianIndex(sort(collect(c.I); by=(!=(1)))...)
128+
s_r = CartesianIndex(sort(collect(c.I); by=(!=(V)))...)
129+
130+
n1 = count(==(1), c.I)
131+
n3 = count(==(V), c.I)
139132

140-
b = cinds[I[4]]
141-
b_sort = CartesianIndex(sort(collect(b.I); by=(!=(V)))...)
142-
n1_b = count(==(1), b.I)
143-
n3_b = count(==(V), b.I)
144-
if n3_b > n1_b && b_sort != b
145-
Idst = CartesianIndex(Base.setindex(I.I, linds[b_sort], 4))
146-
slice[Idst] += slice[I]
147-
delete!(slice, I)
148-
elseif b != b_sort
149-
delete!(slice, I)
133+
if n3 <= n1 && s_c != c
134+
slice[linds[s_c], 1, 1, :] += slice[c_lin, 1, 1, :]
135+
for I in nonzero_keys(slice)
136+
(I[1] == c_lin || I[4] == c_lin) && delete!(slice, I)
137+
end
138+
elseif n3 > n1 && s_r != c
139+
slice[:, 1, 1, linds[s_r]] += slice[:, 1, 1, c_lin]
140+
for I in nonzero_keys(slice)
141+
(I[1] == c_lin || I[4] == c_lin) && delete!(slice, I)
142+
end
150143
end
151144
end
152145
end
@@ -161,14 +154,10 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster)
161154
b = CartesianIndex(replace(a.I, V => 1))
162155
b_lin = linds[b]
163156
factor = τ^n1 * factorial(N - n1) / factorial(N)
157+
slice[:, 1, 1, b_lin] += factor * slice[:, 1, 1, a_lin]
158+
164159
for I in nonzero_keys(slice)
165-
if I[4] == a_lin
166-
Idst = CartesianIndex(Base.setindex(I.I, b_lin, 4))
167-
slice[Idst] += factor * slice[I]
168-
delete!(slice, I)
169-
elseif I[1] == a_lin
170-
delete!(slice, I)
171-
end
160+
(I[1] == a_lin || I[4] == a_lin) && delete!(slice, I)
172161
end
173162
end
174163
end
@@ -180,7 +169,7 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster)
180169
mpo[end] = mpo[end][:, :, :, 1]
181170
end
182171

183-
return remove_orphans!(mpo)
172+
return remove_orphans!(mpo; tol=tol)
184173
end
185174

186175
has_prod_elem(slice, t1, t2) = all(map(x -> contains(slice, x...), zip(t1, t2)))
@@ -223,65 +212,6 @@ function interweave(a, b)
223212
end
224213
end
225214

226-
# function make_time_mpo(H::MPOHamiltonian{S,T}, dt, alg::WII) where {S,T}
227-
# WA = PeriodicArray{T,3}(undef, H.period, H.odim - 2, H.odim - 2)
228-
# WB = PeriodicArray{T,2}(undef, H.period, H.odim - 2)
229-
# WC = PeriodicArray{T,2}(undef, H.period, H.odim - 2)
230-
# WD = PeriodicArray{T,1}(undef, H.period)
231-
#
232-
# δ = dt * (-1im)
233-
#
234-
# for i in 1:(H.period), j in 2:(H.odim - 1), k in 2:(H.odim - 1)
235-
# init_1 = isometry(storagetype(H[i][1, H.odim]), codomain(H[i][1, H.odim]),
236-
# domain(H[i][1, H.odim]))
237-
# init = [init_1, zero(H[i][1, k]), zero(H[i][j, H.odim]), zero(H[i][j, k])]
238-
#
239-
# (y, convhist) = exponentiate(1.0, RecursiveVec(init),
240-
# Arnoldi(; tol=alg.tol, maxiter=alg.maxiter)) do x
241-
# out = similar(x.vecs)
242-
#
243-
# @plansor out[1][-1 -2; -3 -4] := δ * x[1][-1 1; -3 -4] *
244-
# H[i][1, H.odim][2 3; 1 4] * τ[-2 4; 2 3]
245-
#
246-
# @plansor out[2][-1 -2; -3 -4] := δ * x[2][-1 1; -3 -4] *
247-
# H[i][1, H.odim][2 3; 1 4] * τ[-2 4; 2 3]
248-
# @plansor out[2][-1 -2; -3 -4] += sqrt(δ) * x[1][1 2; -3 4] *
249-
# H[i][1, k][-1 -2; 3 -4] * τ[3 4; 1 2]
250-
#
251-
# @plansor out[3][-1 -2; -3 -4] := δ * x[3][-1 1; -3 -4] *
252-
# H[i][1, H.odim][2 3; 1 4] * τ[-2 4; 2 3]
253-
# @plansor out[3][-1 -2; -3 -4] += sqrt(δ) * x[1][1 2; -3 4] *
254-
# H[i][j, H.odim][-1 -2; 3 -4] * τ[3 4; 1 2]
255-
#
256-
# @plansor out[4][-1 -2; -3 -4] := δ * x[4][-1 1; -3 -4] *
257-
# H[i][1, H.odim][2 3; 1 4] * τ[-2 4; 2 3]
258-
# @plansor out[4][-1 -2; -3 -4] += x[1][1 2; -3 4] * H[i][j, k][-1 -2; 3 -4] *
259-
# τ[3 4; 1 2]
260-
# @plansor out[4][-1 -2; -3 -4] += sqrt(δ) * x[2][1 2; -3 -4] *
261-
# H[i][j, H.odim][-1 -2; 3 4] * τ[3 4; 1 2]
262-
# @plansor out[4][-1 -2; -3 -4] += sqrt(δ) * x[3][-1 4; -3 3] *
263-
# H[i][1, k][2 -2; 1 -4] * τ[3 4; 1 2]
264-
#
265-
# return RecursiveVec(out)
266-
# end
267-
# convhist.converged == 0 &&
268-
# @warn "exponentiate failed to converge: normres = $(convhist.normres)"
269-
#
270-
# WA[i, j - 1, k - 1] = y[4]
271-
# WB[i, j - 1] = y[3]
272-
# WC[i, k - 1] = y[2]
273-
# WD[i] = y[1]
274-
# end
275-
#
276-
# W2 = PeriodicArray{Union{T,Missing},3}(missing, H.period, H.odim - 1, H.odim - 1)
277-
# W2[:, 2:end, 2:end] = WA
278-
# W2[:, 2:end, 1] = WB
279-
# W2[:, 1, 2:end] = WC
280-
# W2[:, 1, 1] = WD
281-
#
282-
# return SparseMPO(W2)
283-
# end
284-
285215
function make_time_mpo(H::InfiniteMPOHamiltonian{T}, dt, alg::WII) where {T}
286216
WA = H.A
287217
WB = H.B

test/algorithms.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,4 +769,41 @@ end
769769
end
770770
end
771771

772+
@testset "TaylorCluster time evolution" begin
773+
L = 4
774+
Hs = [transverse_field_ising(; L=L), heisenberg_XXX(; L=L)]
775+
776+
Ns = [1, 2, 3]
777+
dts = [1e-2, 1e-3]
778+
for H in Hs
779+
ψ = FiniteMPS(L, physicalspace(H, 1), ℂ^16)
780+
for N in Ns
781+
εs = zeros(ComplexF64, 2)
782+
for (i, dt) in enumerate(dts)
783+
ψ₀, _ = find_groundstate(ψ, H, DMRG(; verbosity=0))
784+
E₀ = expectation_value(ψ₀, H)
785+
786+
O = make_time_mpo(H, dt, TaylorCluster(; N=N))
787+
788+
ψ₁, _ = approximate(ψ₀, (O, ψ₀), DMRG(; verbosity=0))
789+
εs[i] = norm(dot(ψ₀, ψ₁) - exp(-im * E₀ * dt))
790+
end
791+
@test (log(εs[2]) - log(εs[1])) / (log(dts[2]) - log(dts[1])) N + 1 atol = 0.1
792+
end
793+
794+
for N in Ns
795+
εs = zeros(ComplexF64, 2)
796+
for (i, dt) in enumerate(dts)
797+
ψ₀, _ = find_groundstate(ψ, H, DMRG(; verbosity=0))
798+
E₀ = expectation_value(ψ₀, H)
799+
800+
O = make_time_mpo(H, dt, TaylorCluster(; N=N, compression=true))
801+
802+
ψ₁, _ = approximate(ψ₀, (O, ψ₀), DMRG(; verbosity=0))
803+
εs[i] = norm(dot(ψ₀, ψ₁) - exp(-im * E₀ * dt))
804+
end
805+
@test (log(εs[2]) - log(εs[1])) / (log(dts[2]) - log(dts[1])) N atol = 0.1
806+
end
807+
end
808+
end
772809
end

0 commit comments

Comments
 (0)