Skip to content

Commit 8a097b1

Browse files
Periodic indexing (#377)
* Add periodic getindex/setindex! utility * add periodic getters and setters to object types * simplify codebase to avoid modular indexing * bypass non-scalar indexing calls * Move indexing utils to a separate file * Improve SUWeight to CTMRGEnv conversion * Periodic indexing for SiteDependentTruncation * Improve _is_bipartite * Improve BPEnv indexing * Drop unitcell argument in _nn_bondenv, _get_cluster_trunc * Periodic `physicalspace` for LocalOperator, LocalCircuit * Loose ends --------- Co-authored-by: Yue Zhengyuan <yuezy1997@icloud.com>
1 parent c5b94ba commit 8a097b1

41 files changed

Lines changed: 455 additions & 401 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/src/examples/heisenberg_su/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ else
6767
end
6868

6969
peps = InfinitePEPS(rand, Float64, physical_space, bond_space; unitcell = (Nr, Nc));
70-
peps.A[2, 2] = copy(peps.A[1, 1]) ## make initial random state bipartite
71-
peps.A[2, 1] = copy(peps.A[1, 2])
70+
peps[2, 2] = copy(peps[1, 1]) ## make initial random state bipartite
71+
peps[2, 1] = copy(peps[1, 2])
7272
wts = SUWeight(peps);
7373
````
7474

docs/src/examples/heisenberg_su/main.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@
9797
"end\n",
9898
"\n",
9999
"peps = InfinitePEPS(rand, Float64, physical_space, bond_space; unitcell = (Nr, Nc));\n",
100-
"peps.A[2, 2] = copy(peps.A[1, 1]) ## make initial random state bipartite\n",
101-
"peps.A[2, 1] = copy(peps.A[1, 2])\n",
100+
"peps[2, 2] = copy(peps[1, 1]) ## make initial random state bipartite\n",
101+
"peps[2, 1] = copy(peps[1, 2])\n",
102102
"wts = SUWeight(peps);"
103103
],
104104
"metadata": {},

examples/heisenberg_su/main.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ else
6060
end
6161

6262
peps = InfinitePEPS(rand, Float64, physical_space, bond_space; unitcell = (Nr, Nc));
63-
peps.A[2, 2] = copy(peps.A[1, 1]) ## make initial random state bipartite
64-
peps.A[2, 1] = copy(peps.A[1, 2])
63+
peps[2, 2] = copy(peps[1, 1]) ## make initial random state bipartite
64+
peps[2, 1] = copy(peps[1, 2])
6565
wts = SUWeight(peps);
6666

6767
md"""

src/PEPSKit.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ using DocStringExtensions
4141
include("Defaults.jl") # Include first to allow for docstring interpolation with Defaults values
4242

4343
include("utility/util.jl")
44+
include("utility/indexing.jl")
4445
include("utility/diffable_threads.jl")
4546
include("utility/eigh.jl")
4647
include("utility/svd.jl")
@@ -133,6 +134,7 @@ using .Defaults: set_scheduler!
133134
export set_scheduler!
134135
export EighAdjoint, IterEigh, SVDAdjoint, IterSVD, QRAdjoint
135136
export CTMRGEnv, SequentialCTMRG, SimultaneousCTMRG
137+
export corner, edge, setcorner!, setedge!
136138
export FixedSpaceTruncation, SiteDependentTruncation
137139
export HalfInfiniteProjector, FullInfiniteProjector
138140
export C4vCTMRG, C4vEighProjector, C4vQRProjector

src/algorithms/bp/beliefpropagation.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ function update_message(I::CartesianIndex{3}, network::InfiniteSquareNetwork, en
104104
(1 <= dir <= 4) || throw(ArgumentError("Invalid direction $dir"))
105105

106106
A = network[row, col]
107-
dir == SOUTH || (M_north = env[NORTH, _prev(row, end), col])
108-
dir == WEST || (M_east = env[EAST, row, _next(col, end)])
109-
dir == NORTH || (M_south = env[SOUTH, _next(row, end), col])
110-
dir == EAST || (M_west = env[WEST, row, _prev(col, end)])
107+
dir == SOUTH || (M_north = env[NORTH, row - 1, col])
108+
dir == WEST || (M_east = env[EAST, row, col + 1])
109+
dir == NORTH || (M_south = env[SOUTH, row + 1, col])
110+
dir == EAST || (M_west = env[WEST, row, col - 1])
111111

112112
return if dir == NORTH
113113
contract_north_message(A, M_west, M_north, M_east)

src/algorithms/bp/gaugefix.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function gauge_fix(psi::InfinitePEPS, alg::BPGauge, env::BPEnv)
2525
# copy 1st column to 2nd column to eliminate differences
2626
# caused by order of applying gauge transformations
2727
for r in 1:2
28-
psi′[_next(r, 2), 2] = copy(psi′[r, 1])
28+
psi′[r + 1, 2] = copy(psi′[r, 1])
2929
end
3030
end
3131
return psi′, XXinv
@@ -52,7 +52,7 @@ end
5252
function _sqrt_bp_messages(I::CartesianIndex{3}, env::BPEnv)
5353
dir, row, col = Tuple(I)
5454
@assert dir == NORTH || dir == EAST
55-
M12 = env[dir, dir == NORTH ? _prev(row, end) : row, dir == EAST ? _next(col, end) : col]
55+
M12 = env[dir, dir == NORTH ? row - 1 : row, dir == EAST ? col + 1 : col]
5656
sqrtM12, isqrtM12 = sqrt_invsqrt(twist(M12, 1))
5757
M21 = env[dir + 2, row, col]
5858
sqrtM21, isqrtM21 = sqrt_invsqrt(M21)
@@ -90,10 +90,10 @@ function _bp_gauge_fix!(I::CartesianIndex{3}, psi::InfinitePEPS, env::BPEnv)
9090
end
9191
if dir == NORTH
9292
psi[row, col] = absorb_north_message(psi[row, col], X)
93-
psi[_prev(row, end), col] = absorb_south_message(psi[_prev(row, end), col], invX)
93+
psi[row - 1, col] = absorb_south_message(psi[row - 1, col], invX)
9494
elseif dir == EAST
9595
psi[row, col] = absorb_east_message(psi[row, col], X)
96-
psi[row, _next(col, end)] = absorb_west_message(psi[row, _next(col, end)], invX)
96+
psi[row, col + 1] = absorb_west_message(psi[row, col + 1], invX)
9797
end
9898
return psi, X, invX
9999
end
@@ -122,9 +122,9 @@ to a belief propagation environment.
122122
function BPEnv(wts::SUWeight)
123123
messages = map(Iterators.product(1:4, axes(wts, 2), axes(wts, 3))) do (d, r, c)
124124
wt = if d == NORTH
125-
twist(wts[2, _next(r, end), c], 1)
125+
twist(wts[2, r + 1, c], 1)
126126
elseif d == EAST
127-
twist(wts[1, r, _prev(c, end)], 1)
127+
twist(wts[1, r, c - 1], 1)
128128
elseif d == SOUTH
129129
copy(wts[2, r, c])
130130
else # WEST

src/algorithms/contractions/absorb_weight.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,16 @@ square root (or inverse square root if `inv = true`).
7070
function weight_to_absorb(
7171
weights::SUWeight, row::Int, col::Int, ax::Int; inv::Bool = false
7272
)
73-
_, Nr, Nc = size(weights)
74-
r, c = mod1(row, Nr), mod1(col, Nc)
7573
pow = inv ? -1 / 2 : 1 / 2
7674
wt = sdiag_pow(
7775
if ax == NORTH
78-
weights[2, r, c]
76+
weights[2, row, col]
7977
elseif ax == EAST
80-
weights[1, r, c]
78+
weights[1, row, col]
8179
elseif ax == SOUTH
82-
weights[2, _next(r, Nr), c]
80+
weights[2, row + 1, col]
8381
else # WEST
84-
weights[1, r, _prev(c, Nc)]
82+
weights[1, row, col - 1]
8583
end,
8684
pow,
8785
)

src/algorithms/contractions/bondenv/benv_ctm.jl

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,14 @@ Axis order: `[DX1 DY1; DX0 DY0]`, as in
2424
```
2525
"""
2626
function bondenv_ctm(row::Int, col::Int, X, Y, env::CTMRGEnv)
27-
Nr, Nc = size(env.corners)[[2, 3]]
28-
cm1 = _prev(col, Nc)
29-
cp1 = _next(col, Nc)
30-
cp2 = _next(cp1, Nc)
31-
rm1 = _prev(row, Nr)
32-
rp1 = _next(row, Nr)
33-
c1 = env.corners[1, rm1, cm1]
34-
c2 = env.corners[2, rm1, cp2]
35-
c3 = env.corners[3, rp1, cp2]
36-
c4 = env.corners[4, rp1, cm1]
37-
e1X, e1Y = env.edges[1, rm1, col], env.edges[1, rm1, cp1]
38-
e2 = env.edges[2, row, cp2]
39-
e3X, e3Y = env.edges[3, rp1, col], env.edges[3, rp1, cp1]
40-
e4 = env.edges[4, row, cm1]
27+
c1 = corner(env, 1, row - 1, col - 1)
28+
c2 = corner(env, 2, row - 1, col + 2)
29+
c3 = corner(env, 3, row + 1, col + 2)
30+
c4 = corner(env, 4, row + 1, col - 1)
31+
e1X, e1Y = edge(env, 1, row - 1, col), edge(env, 1, row - 1, col + 1)
32+
e2 = edge(env, 2, row, col + 2)
33+
e3X, e3Y = edge(env, 3, row + 1, col), edge(env, 3, row + 1, col + 1)
34+
e4 = edge(env, 4, row, col - 1)
4135
#= index labels
4236
4337
C1--χ4--E1X---------χ6---------E1Y--χ8---C2 r-1

src/algorithms/contractions/bp_contractions.jl

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,14 @@ function contract_local_operator1x1(
105105
env::BPEnv,
106106
)
107107
row, col = Tuple(ind)
108-
M_north = env.messages[NORTH, _prev(row, end), mod1(col, end)]
109-
M_east = env.messages[EAST, mod1(row, end), _next(col, end)]
110-
M_south = env.messages[SOUTH, _next(row, end), mod1(col, end)]
111-
M_west = env.messages[WEST, mod1(row, end), _prev(col, end)]
108+
M_north = env[NORTH, row - 1, col]
109+
M_east = env[EAST, row, col + 1]
110+
M_south = env[SOUTH, row + 1, col]
111+
M_west = env[WEST, row, col - 1]
112112

113113
return @autoopt @tensor begin
114-
ket[mod1(row, end), mod1(col, end)][dt; DNt DEt DSt DWt] *
115-
conj(bra[mod1(row, end), mod1(col, end)][db; DNb DEb DSb DWb]) *
114+
ket[row, col][dt; DNt DEt DSt DWt] *
115+
conj(bra[row, col][db; DNb DEb DSb DWb]) *
116116
O[db; dt] *
117117
M_north[DNt; DNb] *
118118
M_east[DEt; DEb] *
@@ -125,14 +125,14 @@ function contract_local_norm1x1(
125125
ind::CartesianIndex{2}, ket::InfinitePEPS, bra::InfinitePEPS, env::BPEnv
126126
)
127127
row, col = Tuple(ind)
128-
M_north = env.messages[NORTH, _prev(row, end), mod1(col, end)]
129-
M_east = env.messages[EAST, mod1(row, end), _next(col, end)]
130-
M_south = env.messages[SOUTH, _next(row, end), mod1(col, end)]
131-
M_west = env.messages[WEST, mod1(row, end), _prev(col, end)]
128+
M_north = env[NORTH, row - 1, col]
129+
M_east = env[EAST, row, col + 1]
130+
M_south = env[SOUTH, row + 1, col]
131+
M_west = env[WEST, row, col - 1]
132132

133133
return @autoopt @tensor begin
134-
ket[mod1(row, end), mod1(col, end)][d; DNt DEt DSt DWt] *
135-
conj(bra[mod1(row, end), mod1(col, end)][d; DNb DEb DSb DWb]) *
134+
ket[row, col][d; DNt DEt DSt DWt] *
135+
conj(bra[row, col][d; DNb DEb DSb DWb]) *
136136
M_north[DNt; DNb] *
137137
M_east[DEt; DEb] *
138138
M_south[DSb; DSt] *
@@ -148,17 +148,17 @@ function contract_local_operator2x1(
148148
env::BPEnv,
149149
)
150150
row, col = Tuple(coord)
151-
M_north = env.messages[NORTH, _prev(row, end), mod1(col, end)]
152-
M_northeast = env.messages[EAST, mod1(row, end), _next(col, end)]
153-
M_southeast = env.messages[EAST, _next(row, end), _next(col, end)]
154-
M_south = env.messages[SOUTH, mod1(row + 2, end), mod1(col, end)]
155-
M_southwest = env.messages[WEST, _next(row, end), _prev(col, end)]
156-
M_northwest = env.messages[WEST, mod1(row, end), _prev(col, end)]
151+
M_north = env[NORTH, row - 1, col]
152+
M_northeast = env[EAST, row, col + 1]
153+
M_southeast = env[EAST, row + 1, col + 1]
154+
M_south = env[SOUTH, row + 2, col]
155+
M_southwest = env[WEST, row + 1, col - 1]
156+
M_northwest = env[WEST, row, col - 1]
157157

158-
return @autoopt @tensor ket[mod1(row, end), mod1(col, end)][dNt; DNt DNEt DMt DNWt] *
159-
ket[_next(row, end), mod1(col, end)][dSt; DMt DSEt DSt DSWt] *
160-
conj(bra[mod1(row, end), mod1(col, end)][dNb; DNb DNEb DMb DNWb]) *
161-
conj(bra[_next(row, end), mod1(col, end)][dSb; DMb DSEb DSb DSWb]) *
158+
return @autoopt @tensor ket[row, col][dNt; DNt DNEt DMt DNWt] *
159+
ket[row + 1, col][dSt; DMt DSEt DSt DSWt] *
160+
conj(bra[row, col][dNb; DNb DNEb DMb DNWb]) *
161+
conj(bra[row + 1, col][dSb; DMb DSEb DSb DSWb]) *
162162
M_north[DNt; DNb] *
163163
M_northeast[DNEt; DNEb] *
164164
M_southeast[DSEt; DSEb] *
@@ -176,16 +176,16 @@ function contract_local_operator1x2(
176176
env::BPEnv,
177177
)
178178
row, col = Tuple(coord)
179-
M_west = env.messages[WEST, mod1(row, end), _prev(col, end)]
180-
M_northwest = env.messages[NORTH, _prev(row, end), mod1(col, end)]
181-
M_northeast = env.messages[NORTH, _prev(row, end), _next(col, end)]
182-
M_east = env.messages[EAST, mod1(row, end), mod1(col + 2, end)]
183-
M_southeast = env.messages[SOUTH, _next(row, end), _next(col, end)]
184-
M_southwest = env.messages[SOUTH, _next(row, end), mod1(col, end)]
185-
A_west = ket[mod1(row, end), mod1(col, end)]
186-
Ā_west = bra[mod1(row, end), mod1(col, end)]
187-
A_east = ket[mod1(row, end), _next(col, end)]
188-
Ā_east = bra[mod1(row, end), _next(col, end)]
179+
M_west = env[WEST, row, col - 1]
180+
M_northwest = env[NORTH, row - 1, col]
181+
M_northeast = env[NORTH, row - 1, col + 1]
182+
M_east = env[EAST, row, col + 2]
183+
M_southeast = env[SOUTH, row + 1, col + 1]
184+
M_southwest = env[SOUTH, row + 1, col]
185+
A_west = ket[row, col]
186+
Ā_west = bra[row, col]
187+
A_east = ket[row, col + 1]
188+
Ā_east = bra[row, col + 1]
189189

190190
return @autoopt @tensor begin
191191
A_west[dWt; DNWt DMt DSWt DWt] *
@@ -206,17 +206,17 @@ function contract_local_norm2x1(
206206
coord::CartesianIndex{2}, ket::InfinitePEPS, bra::InfinitePEPS, env::BPEnv
207207
)
208208
row, col = Tuple(coord)
209-
M_north = env.messages[NORTH, _prev(row, end), mod1(col, end)]
210-
M_northeast = env.messages[EAST, mod1(row, end), _next(col, end)]
211-
M_southeast = env.messages[EAST, _next(row, end), _next(col, end)]
212-
M_south = env.messages[SOUTH, mod1(row + 2, end), mod1(col, end)]
213-
M_southwest = env.messages[WEST, _next(row, end), _prev(col, end)]
214-
M_northwest = env.messages[WEST, mod1(row, end), _prev(col, end)]
209+
M_north = env[NORTH, row - 1, col]
210+
M_northeast = env[EAST, row, col + 1]
211+
M_southeast = env[EAST, row + 1, col + 1]
212+
M_south = env[SOUTH, row + 2, col]
213+
M_southwest = env[WEST, row + 1, col - 1]
214+
M_northwest = env[WEST, row, col - 1]
215215

216-
return @autoopt @tensor ket[mod1(row, end), mod1(col, end)][dN; DNt DNEt DMt DNWt] *
217-
ket[_next(row, end), mod1(col, end)][dS; DMt DSEt DSt DSWt] *
218-
conj(bra[mod1(row, end), mod1(col, end)][dN; DNb DNEb DMb DNWb]) *
219-
conj(bra[_next(row, end), mod1(col, end)][dS; DMb DSEb DSb DSWb]) *
216+
return @autoopt @tensor ket[row, col][dN; DNt DNEt DMt DNWt] *
217+
ket[row + 1, col][dS; DMt DSEt DSt DSWt] *
218+
conj(bra[row, col][dN; DNb DNEb DMb DNWb]) *
219+
conj(bra[row + 1, col][dS; DMb DSEb DSb DSWb]) *
220220
M_north[DNt; DNb] *
221221
M_northeast[DNEt; DNEb] *
222222
M_southeast[DSEt; DSEb] *
@@ -230,17 +230,17 @@ function contract_local_norm1x2(
230230
)
231231
row, col = Tuple(coord)
232232

233-
M_west = env.messages[WEST, mod1(row, end), _prev(col, end)]
234-
M_northwest = env.messages[NORTH, _prev(row, end), mod1(col, end)]
235-
M_northeast = env.messages[NORTH, _prev(row, end), _next(col, end)]
236-
M_east = env.messages[EAST, mod1(row, end), mod1(col + 2, end)]
237-
M_southeast = env.messages[SOUTH, _next(row, end), _next(col, end)]
238-
M_southwest = env.messages[SOUTH, _next(row, end), mod1(col, end)]
233+
M_west = env[WEST, row, col - 1]
234+
M_northwest = env[NORTH, row - 1, col]
235+
M_northeast = env[NORTH, row - 1, col + 1]
236+
M_east = env[EAST, row, col + 2]
237+
M_southeast = env[SOUTH, row + 1, col + 1]
238+
M_southwest = env[SOUTH, row + 1, col]
239239

240-
A_west = ket[mod1(row, end), mod1(col, end)]
241-
Ā_west = bra[mod1(row, end), mod1(col, end)]
242-
A_east = ket[mod1(row, end), _next(col, end)]
243-
Ā_east = bra[mod1(row, end), _next(col, end)]
240+
A_west = ket[row, col]
241+
Ā_west = bra[row, col]
242+
A_east = ket[row, col + 1]
243+
Ā_east = bra[row, col + 1]
244244

245245
return @autoopt @tensor begin
246246
A_west[dW; DNWt DMt DSWt DWt] *

src/algorithms/contractions/correlator/pepo_1layer.jl

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ function start_correlator(
55
(size(ρ, 3) == 1) ||
66
throw(ArgumentError("The input PEPO ρ must have only one layer."))
77
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)
8+
E_north = edge(env, NORTH, r - 1, c)
9+
E_south = edge(env, SOUTH, r + 1, c)
10+
E_west = edge(env, WEST, r, c - 1)
11+
C_northwest = corner(env, NORTHWEST, r - 1, c - 1)
12+
C_southwest = corner(env, SOUTHWEST, r + 1, c - 1)
13+
t = twistdual(ρ[r, c], 1:2)
1414
# TODO: part of these contractions is duplicated between the two output tensors,
1515
# so could be optimized further
1616
@autoopt @tensor Vn[χSE De; χNE] :=
@@ -32,12 +32,12 @@ function end_correlator_numerator(
3232
(size(ρ, 3) == 1) ||
3333
throw(ArgumentError("The input PEPO ρ must have only one layer."))
3434
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)
35+
E_north = edge(env, NORTH, r - 1, c)
36+
E_east = edge(env, EAST, r, c + 1)
37+
E_south = edge(env, SOUTH, r + 1, c)
38+
C_northeast = corner(env, NORTHEAST, r - 1, c + 1)
39+
C_southeast = corner(env, SOUTHEAST, r + 1, c + 1)
40+
t = twistdual(ρ[r, c], 1:2)
4141
return @autoopt @tensor V[χSW DW dstring; χNW] *
4242
E_south[χSSE DS; χSW] * E_east[χNEE DE; χSEE] * E_north[χNW DN; χNNE] *
4343
C_northeast[χNNE; χNEE] * C_southeast[χSEE; χSSE] *
@@ -48,9 +48,9 @@ function end_correlator_denominator(
4848
j::CartesianIndex{2}, V::CTMRGEdgeTensor{T, S, 2}, env::CTMRGEnv
4949
) where {T, S}
5050
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)]
51+
C_northeast = corner(env, NORTHEAST, r - 1, c + 1)
52+
E_east = edge(env, EAST, r, c + 1)
53+
C_southeast = corner(env, SOUTHEAST, r + 1, c + 1)
5454
return @autoopt @tensor V[χS DE; χN] * C_northeast[χN; χNE] *
5555
E_east[χNE DE; χSE] * C_southeast[χSE; χS]
5656
end

0 commit comments

Comments
 (0)