Skip to content

Commit f3290c3

Browse files
committed
Port changes from hamiltonian_derivatives to mpo_derivatives and reuse code from mpo_derivatives
1 parent 5ea9055 commit f3290c3

File tree

2 files changed

+93
-27
lines changed

2 files changed

+93
-27
lines changed

src/algorithms/derivatives/hamiltonian_derivatives.jl

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,6 @@ end
6969

7070
# Constructors
7171
# ------------
72-
const _HAM_MPS_TYPES = Union{
73-
FiniteMPS{<:MPSTensor},
74-
WindowMPS{<:MPSTensor},
75-
InfiniteMPS{<:MPSTensor},
76-
}
77-
7872
function AC_hamiltonian(
7973
site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:JordanMPOTensor},
8074
above::_HAM_MPS_TYPES, envs
@@ -83,9 +77,11 @@ function AC_hamiltonian(
8377
GR = rightenv(envs, site, below)
8478
W = operator[site]
8579

80+
GR_2 = GR[2:(end - 1)]
81+
GL_2 = GL[2:(end - 1)]
82+
8683
# starting
8784
if nonzero_length(W.C) > 0
88-
GR_2 = GR[2:(end - 1)]
8985
@plansor starting_[-1 -2; -3 -4] ≔ W.C[-1; -3 1] * GR_2[-4 1; -2]
9086
starting = only(starting_)
9187
else
@@ -94,7 +90,6 @@ function AC_hamiltonian(
9490

9591
# ending
9692
if nonzero_length(W.B) > 0
97-
GL_2 = GL[2:(end - 1)]
9893
@plansor ending_[-1 -2; -3 -4] ≔ GL_2[-1 1; -3] * W.B[1 -2; -4]
9994
ending = only(ending_)
10095
else
@@ -139,8 +134,7 @@ function AC_hamiltonian(
139134
end
140135

141136
if nonzero_length(W.A) > 0
142-
@plansor GLW[-1 -2 -3; -4 -5] ≔ GL[2:(end - 1)][-1 1; -4] * W.A[1 -2; -5 -3]
143-
continuing = (GLW, GR[2:(end - 1)])
137+
continuing = AC_hamiltonian(GL_2, W.A, GR_2)
144138
else
145139
continuing = missing
146140
end
@@ -159,18 +153,21 @@ function AC2_hamiltonian(
159153
W1 = operator[site]
160154
W2 = operator[site + 1]
161155

156+
GR_2 = GR[2:(end - 1)]
157+
GL_2 = GL[2:(end - 1)]
158+
162159
# starting left - continuing right
163160
if nonzero_length(W1.C) > 0 && nonzero_length(W2.A) > 0
164161
@plansor CA_[-1 -2 -3; -4 -5 -6] ≔ W1.C[-1; -4 2] * W2.A[2 -2; -5 1] *
165-
GR[2:(end - 1)][-6 1; -3]
162+
GR_2[-6 1; -3]
166163
CA = only(CA_)
167164
else
168165
CA = missing
169166
end
170167

171168
# continuing left - ending right
172169
if nonzero_length(W1.A) > 0 && nonzero_length(W2.B) > 0
173-
@plansor AB_[-1 -2 -3; -4 -5 -6] ≔ GL[2:(end - 1)][-1 2; -4] * W1.A[2 -2; -5 1] *
170+
@plansor AB_[-1 -2 -3; -4 -5 -6] ≔ GL_2[-1 2; -4] * W1.A[2 -2; -5 1] *
174171
W2.B[1 -3; -6]
175172
AB = only(AB_)
176173
else
@@ -200,10 +197,10 @@ function AC2_hamiltonian(
200197
if !ismissing(CA)
201198
I = id(storagetype(GR[1]), physicalspace(W1))
202199
@plansor CA[-1 -2 -3; -4 -5 -6] += (I[-1; -4] * W2.C[-2; -5 1]) *
203-
GR[2:(end - 1)][-6 1; -3]
200+
GR_2[-6 1; -3]
204201
IC = missing
205202
else
206-
@plansor IC[-1 -2; -3 -4] ≔ W2.C[-1; -3 1] * GR[2:(end - 1)][-4 1; -2]
203+
@plansor IC[-1 -2; -3 -4] ≔ W2.C[-1; -3 1] * GR_2[-4 1; -2]
207204
end
208205
else
209206
IC = missing
@@ -213,11 +210,11 @@ function AC2_hamiltonian(
213210
if nonzero_length(W1.B) > 0
214211
if !ismissing(AB)
215212
I = id(storagetype(GL[end]), physicalspace(W2))
216-
@plansor AB[-1 -2 -3; -4 -5 -6] += GL[2:(end - 1)][-1 1; -4] *
213+
@plansor AB[-1 -2 -3; -4 -5 -6] += GL_2[-1 1; -4] *
217214
(W1.B[1 -2; -5] * I[-3; -6])
218215
BE = missing
219216
else
220-
@plansor BE[-1 -2; -3 -4] ≔ GL[2:(end - 1)][-1 2; -3] * W1.B[2 -2; -4]
217+
@plansor BE[-1 -2; -3 -4] ≔ GL_2[-1 2; -3] * W1.B[2 -2; -4]
221218
end
222219
else
223220
BE = missing
@@ -290,12 +287,9 @@ function AC2_hamiltonian(
290287

291288
# continuing - continuing
292289
# TODO: MPODerivativeOperator code reuse + optimization
293-
# TODO: One should only calculate these operators if necessary. One can do this by checking nonzero_length(A1) > 0 && nonzero_length(A2) > 0 and then setting AA=missing or as we discussed via bit matrix multiplication.
294290
## TODO: Think about how one could and whether one should store these objects and use them for (a) advancing environments in iDMRG, (b) reuse ind backwards-sweep in IDMRG, (c) subspace expansion
295291
if nonzero_length(W1.A) > 0 && nonzero_length(W2.A) > 0
296-
@plansor GLW[-1 -2 -3; -4 -5] ≔ GL[2:(end - 1)][-1 1; -4] * W1.A[1 -2; -5 -3]
297-
@plansor GWR[-1 -2 -3; -4 -5] ≔ W2.A[-3 -5; -2 1] * GR[2:(end - 1)][-1 1; -4]
298-
AA = (GLW, GWR)
292+
AA = AC2_hamiltonian(GL_2, W1.A, W2.A, GR_2)
299293
else
300294
AA = missing
301295
end
@@ -313,10 +307,8 @@ function (H::JordanMPO_AC_Hamiltonian)(x::MPSTensor)
313307
ismissing(H.I) || @plansor y[-1 -2; -3] += x[-1 -2; 1] * H.I[1; -3]
314308
ismissing(H.C) || @plansor y[-1 -2; -3] += x[-1 2; 1] * H.C[-2 -3; 2 1]
315309
ismissing(H.B) || @plansor y[-1 -2; -3] += H.B[-1 -2; 1 2] * x[1 2; -3]
316-
317310
if !ismissing(H.A)
318-
GLW, GR = H.A
319-
@plansor y[-1 -2; -3] += GLW[-1 -2 3; 1 2] * x[1 2; 4] * GR[4 3; -3]
311+
y += H.A(x)
320312
end
321313

322314
return y
@@ -333,10 +325,8 @@ function (H::JordanMPO_AC2_Hamiltonian)(x::MPOTensor)
333325
ismissing(H.BE) || @plansor y[-1 -2; -3 -4] += x[1 2; -3 -4] * H.BE[-1 -2; 1 2]
334326
ismissing(H.DE) || @plansor y[-1 -2; -3 -4] += x[-1 1; -3 -4] * H.DE[-2; 1]
335327
ismissing(H.EE) || @plansor y[-1 -2; -3 -4] += x[1 -2; -3 -4] * H.EE[-1; 1]
336-
337328
if !ismissing(H.AA)
338-
GLW, GWR = H.AA
339-
@plansor y[-1 -2; -3 -4] += GLW[-1 -2 5; 1 2] * x[1 2; 3 4] * GWR[3 4 5; -3 -4]
329+
y += H.AA(x)
340330
end
341331

342332
return y

src/algorithms/derivatives/mpo_derivatives.jl

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ struct MPODerivativeOperator{L, O <: Tuple, R} <: DerivativeOperator
99
rightenv::R
1010
end
1111

12+
struct MPOContractedDerivativeOperator{L, R, N} <: DerivativeOperator
13+
leftenv::L
14+
rightenv::R
15+
end
16+
1217
Base.length(H::MPODerivativeOperator) = length(H.operators)
18+
Base.length(::MPOContractedDerivativeOperator{L, R, N}) where {L, R, N} = N
1319

14-
const MPO_C_Hamiltonian{L, R} = MPODerivativeOperator{L, Tuple{}, R}
20+
const MPO_C_Hamiltonian{L, R} = MPOContractedDerivativeOperator{L, Tuple{}, R}
1521
MPO_C_Hamiltonian(GL, GR) = MPODerivativeOperator(GL, (), GR)
1622

1723
const MPO_AC_Hamiltonian{L, O, R} = MPODerivativeOperator{L, Tuple{O}, R}
@@ -20,8 +26,23 @@ MPO_AC_Hamiltonian(GL, O, GR) = MPODerivativeOperator(GL, (O,), GR)
2026
const MPO_AC2_Hamiltonian{L, O₁, O₂, R} = MPODerivativeOperator{L, Tuple{O₁, O₂}, R}
2127
MPO_AC2_Hamiltonian(GL, O1, O2, GR) = MPODerivativeOperator(GL, (O1, O2), GR)
2228

29+
const MPO_Contracted_C_Hamiltonian{L, R} = MPOContractedDerivativeOperator{L, R, 0}
30+
MPO_Contracted_C_Hamiltonian(GL::L, GR::R) where {L, R} = MPOContractedDerivativeOperator{L,R,0}(GL, GR)
31+
32+
const MPO_Contracted_AC_Hamiltonian{L, R} = MPOContractedDerivativeOperator{L, R, 1}
33+
MPO_Contracted_AC_Hamiltonian(GL::L, GR::R) where {L, R} = MPOContractedDerivativeOperator{L,R,1}(GL, GR)
34+
35+
const MPO_Contracted_AC2_Hamiltonian{L, R} = MPOContractedDerivativeOperator{L, R, 2}
36+
MPO_Contracted_AC2_Hamiltonian(GL::L, GR::R) where {L, R} = MPOContractedDerivativeOperator{L,R,2}(GL, GR)
37+
2338
# Constructors
2439
# ------------
40+
const _HAM_MPS_TYPES = Union{
41+
FiniteMPS{<:MPSTensor},
42+
WindowMPS{<:MPSTensor},
43+
InfiniteMPS{<:MPSTensor},
44+
}
45+
2546
function C_hamiltonian(site::Int, below, operator, above, envs)
2647
return MPO_C_Hamiltonian(leftenv(envs, site + 1, below), rightenv(envs, site, below))
2748
end
@@ -35,6 +56,30 @@ function AC2_hamiltonian(site::Int, below, operator, above, envs)
3556
leftenv(envs, site, below), O1, O2, rightenv(envs, site + 1, below)
3657
)
3758
end
59+
function C_hamiltonian(site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:MPOTensor}, above::_HAM_MPS_TYPES, envs)
60+
return MPO_Contracted_C_Hamiltonian(leftenv(envs, site + 1, below), rightenv(envs, site, below))
61+
end
62+
function AC_hamiltonian(site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:MPOTensor}, above::_HAM_MPS_TYPES, envs)
63+
O = operator[site]
64+
GL = leftenv(envs, site, below)
65+
return AC_hamiltonian(GL, O, rightenv(envs, site, below))
66+
end
67+
function AC_hamiltonian(GL::MPSTensor, O::MPOTensor, GR::MPSTensor)
68+
@plansor GLW[-1 -2 -3; -4 -5] ≔ GL[-1 1; -4] * O[1 -2; -5 -3]
69+
return MPO_Contracted_AC_Hamiltonian(GLW, O, GR)
70+
end
71+
function AC2_hamiltonian(site::Int, below::_HAM_MPS_TYPES, operator::MPOHamiltonian{<:MPOTensor}, above::_HAM_MPS_TYPES, envs)
72+
O1 = operator[site]
73+
O2 = operator[site + 1]
74+
GL = leftenv(envs, site, below)
75+
GR = rightenv(envs, site + 1, below)
76+
return AC2_hamiltonian(GL, O1, O2, GR)
77+
end
78+
function AC2_hamiltonian(GL::MPSTensor, O1::MPOTensor, O2::MPOTensor, GR::MPSTensor)
79+
@plansor GLW[-1 -2 -3; -4 -5] ≔ GL[-1 1; -4] * O1[1 -2; -5 -3]
80+
@plansor GWR[-1 -2 -3; -4 -5] ≔ O2[-3 -5; -2 1] * GR[-1 1; -4]
81+
return MPO_Contracted_AC2_Hamiltonian(GLW, GWR)
82+
end
3883

3984
# Properties
4085
# ----------
@@ -50,6 +95,20 @@ function TensorKit.codomain(H::MPODerivativeOperator)
5095
V_o = prod(physicalspace, H.O; init = one(V_l))
5196
return V_l V_o V_r
5297
end
98+
function TensorKit.domain(H::MPOContractedDerivativeOperator)
99+
V_l = right_virtualspace(H.leftenv)
100+
V_r = left_virtualspace(H.rightenv)
101+
## TODO: How to deal with the H.O here?
102+
V_o = prod(physicalspace, H.O; init = one(V_l))
103+
return V_l V_o V_r
104+
end
105+
function TensorKit.codomain(H::MPOContractedDerivativeOperator)
106+
V_l = left_virtualspace(H.leftenv)
107+
V_r = right_virtualspace(H.rightenv)
108+
## TODO: How to deal with the H.O here?
109+
V_o = prod(physicalspace, H.O; init = one(V_l))
110+
return V_l V_o V_r
111+
end
53112

54113
# Actions
55114
# -------
@@ -105,3 +164,20 @@ function (h::MPO_AC2_Hamiltonian{<:MPSTensor, <:MPOTensor, <:MPOTensor, <:MPSTen
105164
h.operators[2][7 -6; 4 5] * τ[5 -5; 2 3]
106165
return y isa AbstractBlockTensorMap ? only(y) : y
107166
end
167+
function (h::MPO_Contracted_C_Hamiltonian)(x::MPSBondTensor)
168+
@plansor y[-1; -2] ≔ h.leftenv[-1 3; 1] * x[1; 2] * h.rightenv[2 3; -2]
169+
return y isa AbstractBlockTensorMap ? only(y) : y
170+
end
171+
function (h::MPO_Contracted_AC_Hamiltonian)(
172+
x::GenericMPSTensor{<:Any, 3}
173+
)
174+
@plansor y[-1 -2; -3] ≔ h.leftenv[-1 -2 3; 1 2] * x[1 2; 4] * h.rightenv[4 3; -3]
175+
return y isa AbstractBlockTensorMap ? only(y) : y
176+
end
177+
function (h::MPO_Contracted_AC2_Hamiltonian)(
178+
x::MPOTensor
179+
)
180+
@plansor y[-1 -2; -3 -4] ≔ h.leftenv[-1 -2 5; 1 2] * x[1 2; 3 4] * h.rightenv[3 4 5; -3 -4]
181+
return y isa AbstractBlockTensorMap ? only(y) : y
182+
end
183+
## TODO: Which interface should we use for an inplace += version to be used in hamiltonian_derivatives.jl?

0 commit comments

Comments
 (0)