Skip to content

Commit fa943d8

Browse files
Add correlator for InfinitePEPO (mixed state) (#274)
* Refactor iPEPS correlator * Add mixed state (iPEPO) correlator * Fix fermionic twists * Separate correlator contractions and logic * [WIP] Use `V * T` syntax [skip ci] * Move `correlator_horizontal/vertical` [skip ci] * Reorganize `transfer_left`s used by correlators * Attempt at edge transfer matrices * Test correlators with dual physical space * Remove dual physical space test for now * Don't unnecessarily depend on MPSKit.jl internals * Remove unneeded TODO * Add note --------- Co-authored-by: leburgel <lander.burgelman@gmail.com>
1 parent 6c4e3f0 commit fa943d8

11 files changed

Lines changed: 578 additions & 161 deletions

File tree

src/PEPSKit.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ using ChainRulesCore, Zygote
1515
using LoggingExtras
1616

1717
using MPSKit
18-
using MPSKit: MPOTensor, GenericMPSTensor, MPSBondTensor, TransferMatrix
18+
using MPSKit: MPSTensor, MPOTensor, GenericMPSTensor, MPSBondTensor, ProductTransferMatrix
1919
import MPSKit: tensorexpr, leading_boundary, loginit!, logiter!, logfinish!, logcancel!, physicalspace
2020
import MPSKit: infinite_temperature_density_matrix
2121

@@ -52,12 +52,15 @@ include("environments/vumps_environments.jl")
5252
include("environments/suweight.jl")
5353

5454
include("algorithms/contractions/ctmrg_contractions.jl")
55+
include("algorithms/contractions/transfer.jl")
5556
include("algorithms/contractions/localoperator.jl")
5657
include("algorithms/contractions/vumps_contractions.jl")
5758
include("algorithms/contractions/bondenv/benv_tools.jl")
5859
include("algorithms/contractions/bondenv/gaugefix.jl")
5960
include("algorithms/contractions/bondenv/als_solve.jl")
6061
include("algorithms/contractions/bondenv/benv_ctm.jl")
62+
include("algorithms/contractions/correlator/peps.jl")
63+
include("algorithms/contractions/correlator/pepo_1layer.jl")
6164

6265
include("algorithms/ctmrg/sparse_environments.jl")
6366
include("algorithms/ctmrg/ctmrg.jl")
@@ -74,6 +77,7 @@ include("algorithms/time_evolution/evoltools.jl")
7477
include("algorithms/time_evolution/simpleupdate.jl")
7578
include("algorithms/time_evolution/simpleupdate3site.jl")
7679

80+
include("algorithms/transfermatrix.jl")
7781
include("algorithms/toolbox.jl")
7882
include("algorithms/correlators.jl")
7983

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
function start_correlator(
2+
i::CartesianIndex{2}, ρ::InfinitePEPO,
3+
O::PFTensor, env::CTMRGEnv
4+
)
5+
(size(ρ, 3) == 1) ||
6+
throw(ArgumentError("The input PEPO ρ must have only one layer."))
7+
r, c = Tuple(i)
8+
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
9+
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
10+
E_west = env.edges[WEST, mod1(r, end), _prev(c, end)]
11+
C_northwest = env.corners[NORTHWEST, _prev(r, end), _prev(c, end)]
12+
C_southwest = env.corners[SOUTHWEST, _next(r, end), _prev(c, end)]
13+
t = twistdual(ρ[mod1(r, end), mod1(c, end)], 1:2)
14+
# TODO: part of these contractions is duplicated between the two output tensors,
15+
# so could be optimized further
16+
@autoopt @tensor Vn[χSE De; χNE] :=
17+
E_south[χSE Ds; χSW2] * C_southwest[χSW2; χSW] *
18+
E_west[χSW Dw; χNW] * C_northwest[χNW; χN] *
19+
t[d d; Dn De Ds Dw] * E_north[χN Dn; χNE]
20+
@autoopt @tensor Vo[χSE De dstring; χNE] :=
21+
E_south[χSE Ds; χSW2] * C_southwest[χSW2; χSW] *
22+
E_west[χSW Dw; χNW] * C_northwest[χNW; χN] *
23+
removeunit(O, 1)[d2; d1 dstring] *
24+
t[d1 d2; Dn De Ds Dw] * E_north[χN Dn; χNE]
25+
return Vn, Vo
26+
end
27+
28+
function end_correlator_numerator(
29+
j::CartesianIndex{2}, V::CTMRGEdgeTensor{T, S, 3},
30+
ρ::InfinitePEPO, O::PFTensor, env::CTMRGEnv
31+
) where {T, S}
32+
(size(ρ, 3) == 1) ||
33+
throw(ArgumentError("The input PEPO ρ must have only one layer."))
34+
r, c = Tuple(j)
35+
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
36+
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
37+
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
38+
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
39+
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]
40+
t = twistdual(ρ[mod1(r, end), mod1(c, end)], 1:2)
41+
return @autoopt @tensor V[χSW DW dstring; χNW] *
42+
E_south[χSSE DS; χSW] * E_east[χNEE DE; χSEE] * E_north[χNW DN; χNNE] *
43+
C_northeast[χNNE; χNEE] * C_southeast[χSEE; χSSE] *
44+
t[d1 d2; DN DE DS DW] * removeunit(O, 4)[dstring d2; d1]
45+
end
46+
47+
function end_correlator_denominator(
48+
j::CartesianIndex{2}, V::CTMRGEdgeTensor{T, S, 2}, env::CTMRGEnv
49+
) where {T, S}
50+
r, c = Tuple(j)
51+
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
52+
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
53+
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]
54+
return @autoopt @tensor V[χS DE; χN] * C_northeast[χN; χNE] *
55+
E_east[χNE DE; χSE] * C_southeast[χSE; χS]
56+
end
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
function start_correlator(
2+
i::CartesianIndex{2},
3+
below::InfinitePEPS,
4+
O::MPOTensor,
5+
above::InfinitePEPS,
6+
env::CTMRGEnv,
7+
)
8+
r, c = Tuple(i)
9+
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
10+
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
11+
E_west = env.edges[WEST, mod1(r, end), _prev(c, end)]
12+
C_northwest = env.corners[NORTHWEST, _prev(r, end), _prev(c, end)]
13+
C_southwest = env.corners[SOUTHWEST, _next(r, end), _prev(c, end)]
14+
sandwich = (below[mod1(r, end), mod1(c, end)], above[mod1(r, end), mod1(c, end)])
15+
16+
# TODO: part of these contractions is duplicated between the two output tensors,
17+
# so could be optimized further
18+
@autoopt @tensor Vn[χSE Detop Debot; χNE] :=
19+
E_south[χSE Dstop Dsbot; χSW2] *
20+
C_southwest[χSW2; χSW] *
21+
E_west[χSW Dwtop Dwbot; χNW] *
22+
C_northwest[χNW; χN] *
23+
conj(bra(sandwich)[d; Dnbot Debot Dsbot Dwbot]) *
24+
ket(sandwich)[d; Dntop Detop Dstop Dwtop] *
25+
E_north[χN Dntop Dnbot; χNE]
26+
27+
@autoopt @tensor Vo[χSE Detop dstring Debot; χNE] :=
28+
E_south[χSE Dstop Dsbot; χSW2] *
29+
C_southwest[χSW2; χSW] *
30+
E_west[χSW Dwtop Dwbot; χNW] *
31+
C_northwest[χNW; χN] *
32+
conj(bra(sandwich)[d1; Dnbot Debot Dsbot Dwbot]) *
33+
removeunit(O, 1)[d1; d2 dstring] *
34+
ket(sandwich)[d2; Dntop Detop Dstop Dwtop] *
35+
E_north[χN Dntop Dnbot; χNE]
36+
37+
return Vn, Vo
38+
end
39+
40+
function end_correlator_numerator(
41+
j::CartesianIndex{2},
42+
V::AbstractTensorMap{T, S, 4, 1},
43+
above::InfinitePEPS,
44+
O::MPOTensor,
45+
below::InfinitePEPS,
46+
env::CTMRGEnv,
47+
) where {T, S}
48+
r, c = Tuple(j)
49+
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
50+
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
51+
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
52+
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
53+
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]
54+
sandwich = (above[mod1(r, end), mod1(c, end)], below[mod1(r, end), mod1(c, end)])
55+
56+
return @autoopt @tensor V[χSW DWt dstring DWb; χNW] *
57+
E_south[χSSE DSt DSb; χSW] *
58+
E_east[χNEE DEt DEb; χSEE] *
59+
E_north[χNW DNt DNb; χNNE] *
60+
C_northeast[χNNE; χNEE] *
61+
C_southeast[χSEE; χSSE] *
62+
conj(bra(sandwich)[db; DNb DEb DSb DWb]) *
63+
ket(sandwich)[dt; DNt DEt DSt DWt] *
64+
removeunit(O, 4)[dstring db; dt]
65+
end
66+
67+
function end_correlator_denominator(
68+
j::CartesianIndex{2}, V::AbstractTensorMap{T, S, 3, 1},
69+
env::CTMRGEnv
70+
) where {T, S}
71+
r, c = Tuple(j)
72+
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
73+
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
74+
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]
75+
76+
return @autoopt @tensor V[χS DEt DEb; χN] *
77+
C_northeast[χN; χNE] *
78+
E_east[χNE DEt DEb; χSE] *
79+
C_southeast[χSE; χS]
80+
end
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#
2+
# Transfer function for (CTMRG) edges
3+
#
4+
5+
edge_transfer_left(v, ::Nothing, A, B) = edge_transfer_left(v, A, B)
6+
edge_transfer_right(v, ::Nothing, A, B) = edge_transfer_right(v, A, B)
7+
8+
"""
9+
edge_transfer_left(v, Et, Eb)
10+
11+
Apply an edge transfer matrix to the left.
12+
13+
```
14+
┌─Et─
15+
-v │
16+
└─qƎ─
17+
```
18+
"""
19+
@generated function edge_transfer_left(
20+
v::AbstractTensorMap{<:Any, S, 1, N₁},
21+
Etop::CTMRGEdgeTensor{<:Any, S, N₂},
22+
Ebot::CTMRGEdgeTensor{<:Any, S, N₂}
23+
) where {S, N₁, N₂}
24+
t_out = tensorexpr(:v, -1, -(2:(N₁ + 1)))
25+
t_top = tensorexpr(:Etop, 2:(N₂ + 1), -(N₁ + 1))
26+
t_bot = tensorexpr(:Ebot, (-1, (3:(N₂ + 1))...), 1)
27+
t_in = tensorexpr(:v, 1, (-(2:N₁)..., 2))
28+
return macroexpand(
29+
@__MODULE__, :(return @tensor $t_out := $t_in * $t_top * $t_bot)
30+
)
31+
end
32+
33+
34+
"""
35+
edge_transfer_right(v, Et, Eb)
36+
37+
Apply an edge transfer matrix to the right.
38+
39+
```
40+
─Et─┐
41+
│ v-
42+
─qƎ─┘
43+
```
44+
"""
45+
@generated function edge_transfer_right(
46+
v::AbstractTensorMap{<:Any, S, 1, N₁},
47+
Etop::CTMRGEdgeTensor{<:Any, S, N₂},
48+
Ebot::CTMRGEdgeTensor{<:Any, S, N₂}
49+
) where {S, N₁, N₂}
50+
t_out = tensorexpr(:v, -1, -(2:(N₁ + 1)))
51+
t_top = tensorexpr(:Etop, (-1, (3:(N₂ + 1))...), 1)
52+
t_bot = tensorexpr(:Ebot, (2, (3:(N₂ + 1))...), -(N₁ + 1))
53+
t_in = tensorexpr(:v, 1, (-(2:N₁)..., 2))
54+
return macroexpand(
55+
@__MODULE__, :(return @tensor $t_out := $t_top * $t_bot * $t_in)
56+
)
57+
end
58+
59+
"""
60+
edge_transfer_left(v, O, Et, Eb)
61+
62+
Apply an edge transfer matrix to the left.
63+
64+
```
65+
┌──Et─
66+
│ │
67+
v──O──
68+
│ │
69+
└──qƎ─
70+
```
71+
"""
72+
function edge_transfer_left(
73+
v::CTMRGEdgeTensor{<:Any, S, 3},
74+
O::PEPSSandwich,
75+
Etop::CTMRGEdgeTensor{<:Any, S, 3},
76+
Ebot::CTMRGEdgeTensor{<:Any, S, 3},
77+
) where {S}
78+
@autoopt @tensor v´[χ_SE D_E_above D_E_below; χ_NE] :=
79+
v[χ_SW D_W_above D_W_below; χ_NW] *
80+
Etop[χ_NW D_N_above D_N_below; χ_NE] *
81+
Ebot[χ_SE D_S_above D_S_below; χ_SW] *
82+
ket(O)[d; D_N_above D_E_above D_S_above D_W_above] *
83+
conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below])
84+
85+
return
86+
end
87+
function edge_transfer_left(
88+
v::CTMRGEdgeTensor{<:Any, S, 2},
89+
O::PFTensor,
90+
Etop::CTMRGEdgeTensor{<:Any, S, 2},
91+
Ebot::CTMRGEdgeTensor{<:Any, S, 2},
92+
) where {S}
93+
@autoopt @tensor v´[χ_SE D_E; χ_NE] :=
94+
v[χ_SW D_W; χ_NW] *
95+
Etop[χ_NW D_N; χ_NE] *
96+
Ebot[χ_SE D_S; χ_SW] *
97+
O[D_W D_S; D_N D_E]
98+
99+
return
100+
end
101+
102+
"""
103+
transfer_right(v, Et, Eb)
104+
105+
Apply an edge transfer matrix to the right.
106+
107+
```
108+
──Et─┐
109+
│ │
110+
──O──v
111+
│ │
112+
──qƎ─┘
113+
```
114+
"""
115+
function edge_transfer_right(
116+
v::CTMRGEdgeTensor{<:Any, S, 3},
117+
O::PEPSSandwich,
118+
Etop::CTMRGEdgeTensor{<:Any, S, 3},
119+
Ebot::CTMRGEdgeTensor{<:Any, S, 3},
120+
) where {S}
121+
@autoopt @tensor v′[χ_NW D_W_above D_W_below; χ_SW] :=
122+
v[χ_NE D_E_above D_E_below; χ_SE] *
123+
Etop[χ_NW D_N_above D_N_below; χ_NE] *
124+
Ebot[χ_SE D_S_below D_S_above; χ_SW] *
125+
ket(O)[d; D_N_above D_E_above D_S_above D_W_above] *
126+
conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below])
127+
128+
return v′
129+
end
130+
function edge_transfer_right(
131+
v::CTMRGEdgeTensor{<:Any, S, 2},
132+
O::PFTensor,
133+
Etop::CTMRGEdgeTensor{<:Any, S, 2},
134+
Ebot::CTMRGEdgeTensor{<:Any, S, 2},
135+
) where {S}
136+
return @autoopt @tensor v′[χ_NW D_W; χ_SW] :=
137+
v[χ_NE D_E; χ_SE] *
138+
Etop[χ_NW D_N; χ_NE] *
139+
Ebot[χ_SE D_S; χ_SW] *
140+
O[D_W D_S; D_N D_E]
141+
142+
return v′
143+
end
144+
145+
"""
146+
edge_transfer_left(v, O, Et, Eb)
147+
148+
Apply an edge transfer matrix to the left on an excited vector.
149+
150+
```
151+
┌──Et─
152+
│ │
153+
-v──O──
154+
│ │
155+
└──qƎ─
156+
```
157+
"""
158+
function edge_transfer_left(
159+
v::CTMRGEdgeTensor{<:Any, S, 4}, O::PEPSSandwich,
160+
Etop::CTMRGEdgeTensor{<:Any, S, 3}, Ebot::CTMRGEdgeTensor{<:Any, S, 3},
161+
) where {S}
162+
return @autoopt @tensor v′[χ_SE D_E_above d_string D_E_below; χ_NE] :=
163+
v[χ_SW D_W_above d_string D_W_below; χ_NW] *
164+
Etop[χ_NW D_N_above D_N_below; χ_NE] *
165+
Ebot[χ_SE D_S_above D_S_below; χ_SW] *
166+
ket(O)[d; D_N_above D_E_above D_S_above D_W_above] *
167+
conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below])
168+
end
169+
function edge_transfer_left(
170+
v::CTMRGEdgeTensor{<:Any, S, 3}, O::PFTensor,
171+
Etop::CTMRGEdgeTensor{<:Any, S, 2}, Ebot::CTMRGEdgeTensor{<:Any, S, 2},
172+
) where {S}
173+
return @autoopt @tensor v′[χ_SE D_E d_string; χ_NE] :=
174+
v[χ_SW D_W d_string; χ_NW] *
175+
Etop[χ_NW D_N; χ_NE] *
176+
Ebot[χ_SE D_S; χ_SW] *
177+
O[D_W D_S; D_N D_E]
178+
end

0 commit comments

Comments
 (0)