Skip to content

Commit 2d90e04

Browse files
committed
Do not move phys leg to bond tensor for middle cluster sites
1 parent de5a5d5 commit 2d90e04

8 files changed

Lines changed: 194 additions & 49 deletions

File tree

src/algorithms/contractions/bondenv/benv_ctm.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Axis order: `[DX1 DY1; DX0 DY0]`, as in
2424
```
2525
"""
2626
function bondenv_ctm(
27-
row::Int, col::Int, X::T, Y::T, env::CTMRGEnv
28-
) where {T}
27+
row::Int, col::Int, X::TX, Y::TY, env::CTMRGEnv
28+
) where {TX, TY}
2929
Nr, Nc = size(env.corners)[[2, 3]]
3030
cm1 = _prev(col, Nc)
3131
cp1 = _next(col, Nc)

src/algorithms/contractions/bondenv/benv_ntu.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ Calculate the bond environment within "NTU-NN" approximation.
3434
```
3535
"""
3636
function bondenv_ntu(
37-
row::Int, col::Int, X::T, Y::T, state::S, alg::NNEnv
38-
) where {T, S <: InfiniteState}
37+
row::Int, col::Int, X::TX, Y::TY, state::S, alg::NNEnv
38+
) where {TX, TY, S <: InfiniteState}
3939
neighbors = [(-1, 0), (0, -1), (1, 0), (1, 1), (0, 2), (-1, 1)]
4040
m = collect_neighbors(state, row, col, neighbors)
4141
X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y)
@@ -78,8 +78,8 @@ Calculate the bond environment within "NTU-NN+" approximation.
7878
Dotted lines and ○ are splitted using SVD with `truncrank(1)`.
7979
"""
8080
function bondenv_ntu(
81-
row::Int, col::Int, X::T, Y::T, state::S, alg::NNpEnv
82-
) where {T, S <: InfiniteState}
81+
row::Int, col::Int, X::TX, Y::TY, state::S, alg::NNpEnv
82+
) where {TX, TY, S <: InfiniteState}
8383
neighbors = [
8484
(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (1, 2), (0, 2), (-1, 2),
8585
(-1, 1), (-1, 0), (0, -2), (2, 0), (2, 1), (0, 3), (-2, 1), (-2, 0),
@@ -191,8 +191,8 @@ Calculates the bond environment within "NTU-NNN" approximation.
191191
```
192192
"""
193193
function bondenv_ntu(
194-
row::Int, col::Int, X::T, Y::T, state::S, alg::NNNEnv
195-
) where {T, S <: InfiniteState}
194+
row::Int, col::Int, X::TX, Y::TY, state::S, alg::NNNEnv
195+
) where {TX, TY, S <: InfiniteState}
196196
neighbors = [
197197
(-1, -1), (0, -1), (1, -1),
198198
(1, 0), (1, 1), (1, 2), (0, 2),

src/algorithms/contractions/bondenv/gaugefix.jl

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,40 +90,59 @@ function fixgauge_benv(
9090
end
9191

9292
"""
93-
When the (half) bond environment `Z` consists of
94-
two `PEPSOrth` or `PEPOOrth` tensors `X`, `Y` as
93+
Apply the gauge transformation `Rinv` for `Z`
9594
```
9695
┌-----------------------┐
97-
| |
98-
└---Z---(X)-- --(Y)---┘
96+
└---Z--(X)--Rinv-- ---┘
9997
10098
```
101-
apply the gauge transformation `Linv`, `Rinv` for `Z` to `X`, `Y`:
99+
to `X`. For example, when `X` is a `PEPSTensor`,
102100
```
103-
-1 -1
104-
| |
105-
-4 - X - 1 - Rinv - -2 -4 - Linv - 1 - Y - -2
106-
| |
107-
-3 -3
108-
109-
-2 -2
110-
| |
111-
-5 - X - 1 - Rinv - -3 -5 - Linv - 1 - Y - -3
112-
| ╲ | ╲
113-
-4 -1 -4 -1
101+
-2
102+
|
103+
-5 - X - 1 - Rinv - -3
104+
| ╲
105+
-4 -1
114106
```
115107
"""
116-
function _fixgauge_benvXY(
117-
X::PEPSOrth, Y::PEPSOrth, Linv::MPSBondTensor, Rinv::MPSBondTensor,
118-
)
119-
@plansor X[-1 -2 -3 -4] := X[-1 1 -3 -4] * Rinv[1; -2]
120-
@plansor Y[-1 -2 -3 -4] := Y[-1 -2 -3 1] * Linv[1; -4]
121-
return X, Y
108+
function _fixgauge_benvX(X::PEPSOrth, Rinv::MPSBondTensor)
109+
return @plansor X[-1 -2 -3 -4] := X[-1 1 -3 -4] * Rinv[1; -2]
122110
end
123-
function _fixgauge_benvXY(
124-
X::PEPOOrth, Y::PEPOOrth, Linv::MPSBondTensor, Rinv::MPSBondTensor,
125-
)
126-
@plansor X[-1 -2 -3 -4 -5] := X[-1 -2 1 -4 -5] * Rinv[1; -3]
127-
@plansor Y[-1 -2 -3 -4 -5] := Y[-1 -2 -3 -4 1] * Linv[1; -5]
128-
return X, Y
111+
function _fixgauge_benvX(X::PEPSTensor, Rinv::MPSBondTensor)
112+
return @plansor X[-1; -2 -3 -4 -5] := X[-1; -2 1 -4 -5] * Rinv[1; -3]
113+
end
114+
function _fixgauge_benvX(X::PEPOOrth, Rinv::MPSBondTensor)
115+
return @plansor X[-1 -2 -3 -4 -5] := X[-1 -2 1 -4 -5] * Rinv[1; -3]
116+
end
117+
function _fixgauge_benvX(X::PEPOTensor, Rinv::MPSBondTensor)
118+
return @plansor X[-1 -2; -3 -4 -5 -6] := X[-1 -2; -3 1 -5 -6] * Rinv[1; -4]
119+
end
120+
121+
"""
122+
Apply the gauge transformation `Linv` for `Z`
123+
```
124+
┌-----------------------┐
125+
└---Z--- ---Linv--(Y)--┘
126+
127+
```
128+
to `Y`. For example, when `Y` is a `PEPSTensor`,
129+
```
130+
-2
131+
|
132+
-5 - Linv - 1 - Y - -3
133+
| ╲
134+
-4 -1
135+
```
136+
"""
137+
function _fixgauge_benvY(Y::PEPSOrth, Linv::MPSBondTensor)
138+
return @plansor Y[-1 -2 -3 -4] := Y[-1 -2 -3 1] * Linv[1; -4]
139+
end
140+
function _fixgauge_benvY(Y::PEPSTensor, Linv::MPSBondTensor)
141+
return @plansor Y[-1; -2 -3 -4 -5] := Y[-1; -2 -3 -4 1] * Linv[1; -5]
142+
end
143+
function _fixgauge_benvY(Y::PEPOOrth, Linv::MPSBondTensor)
144+
return @plansor Y[-1 -2 -3 -4 -5] := Y[-1 -2 -3 -4 1] * Linv[1; -5]
145+
end
146+
function _fixgauge_benvY(Y::PEPOTensor, Linv::MPSBondTensor)
147+
return @plansor Y[-1 -2; -3 -4 -5 -6] := Y[-1 -2; -3 -4 -5 1] * Linv[1; -6]
129148
end

src/algorithms/time_evolution/ntupdate.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ function _ntu_iter(
7979
Nr, Nc = size(state)
8080
trunc = only(_get_cluster_trunc(alg.opt_alg.trunc, sites, (Nr, Nc)))
8181
alg′ = (@set alg.opt_alg.trunc = trunc)
82-
return _bond_truncate(state, wts, Tuple(sites), alg′; gate)
82+
return _bond_truncate(state, wts, Tuple(sites), (:first, :last), alg′; gate)
8383
end
8484

8585
"""

src/algorithms/time_evolution/ntupdate3site.jl

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ function _ntu_iter(
2323

2424
# truncate each bond sequentially along the path
2525
info = (; fid = 1.0)
26-
for (bondsites, trunc) in zip(zip(sites, Iterators.drop(sites, 1)), truncs)
26+
nbond = length(sites) - 1
27+
for (i, bondsites) in enumerate(zip(sites, Iterators.drop(sites, 1)))
28+
trunc = truncs[i]
2729
alg′ = (@set alg.opt_alg.trunc = trunc)
28-
state, wts, info′ = _bond_truncate(state, wts, bondsites, alg′)
30+
stype1 = (i == 1) ? :first : :middle
31+
stype2 = (i == nbond) ? :last : :middle
32+
state, wts, info′ = _bond_truncate(state, wts, bondsites, (stype1, stype2), alg′)
2933
# record the worst fidelity
3034
(info′.fid < info.fid) && (info = info′)
3135
end
@@ -35,10 +39,14 @@ end
3539
"""
3640
Truncate a nearest neighbor bond between `site1` and `site2`
3741
after rotating the bond to standard x direction `A ← B`.
42+
43+
`bondtype` takes values in (1, 2, 3), meaning that the current bond is
44+
(the first, a middle, the last) bond in the updated cluster.
3845
"""
3946
function _bond_truncate(
4047
state::InfiniteState, wts::SUWeight,
4148
(site1, site2)::NTuple{2, CartesianIndex{2}},
49+
(stype1, stype2)::NTuple{2, Symbol},
4250
alg::NeighbourUpdate; gate::Union{NNGate, Nothing} = nothing
4351
)
4452
# rotate bond to standard x direction `A ← B`
@@ -54,14 +62,26 @@ function _bond_truncate(
5462
A, B = state2[row, col], state2[row, cp1]
5563

5664
# create bond environment
57-
a, X = bond_tensor_first(A; trunc = trunctol(; rtol = 1.0e-12))
58-
b, Y = bond_tensor_last(B; trunc = trunctol(; rtol = 1.0e-12))
65+
qrtrunc = trunctol(; rtol = 1.0e-12)
66+
a, X = if stype1 == :first
67+
bond_tensor_first(A; trunc = qrtrunc)
68+
else
69+
@assert stype1 == :middle
70+
bond_tensor_midnext(A; trunc = qrtrunc)
71+
end
72+
b, Y = if stype2 == :last
73+
bond_tensor_last(B; trunc = qrtrunc)
74+
else
75+
@assert stype2 == :middle
76+
bond_tensor_midprev(B; trunc = qrtrunc)
77+
end
5978
benv = bondenv_ntu(row, col, X, Y, state2, alg.bondenv_alg)
6079
@debug "cond(benv) before gauge fix: $(LinearAlgebra.cond(benv))"
6180
if alg.fixgauge
6281
Z = positive_approx(benv)
6382
Z, a, b, (Linv, Rinv) = fixgauge_benv(Z, a, b)
64-
X, Y = _fixgauge_benvXY(X, Y, Linv, Rinv)
83+
X = _fixgauge_benvX(X, Rinv)
84+
Y = _fixgauge_benvY(Y, Linv)
6585
benv = Z' * Z
6686
@debug "cond(L) = $(LinearAlgebra.cond(Linv)); cond(R): $(LinearAlgebra.cond(Rinv))"
6787
@debug "cond(benv) after gauge fix: $(LinearAlgebra.cond(benv))"
@@ -70,14 +90,20 @@ function _bond_truncate(
7090
# (optional) apply the NN gate without truncation
7191
if !(gate === nothing)
7292
a, s, b, = _apply_gate(a, b, gate, truncerror(; atol = 1.0e-15))
93+
end
94+
a, s, b, info = bond_truncate(a, b, benv, alg.opt_alg)
95+
96+
A = if stype1 == :first
97+
undo_bond_tensor_first(a, X)
7398
else
74-
a = permute(a, ((1, 2), (3,)))
75-
b = permute(b, ((1,), (2, 3)))
99+
undo_bond_tensor_midnext(a, X)
100+
end
101+
B = if stype2 == :last
102+
undo_bond_tensor_last(b, Y)
103+
else
104+
undo_bond_tensor_midprev(b, Y)
76105
end
77106

78-
a, s, b, info = bond_truncate(a, b, benv, alg.opt_alg)
79-
A = undo_bond_tensor_first(a, X)
80-
B = undo_bond_tensor_last(b, Y)
81107
normalize!(A, Inf)
82108
normalize!(B, Inf)
83109
normalize!(s, Inf)

src/algorithms/truncation/bond_tensor.jl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,101 @@ function undo_bond_tensor_last(b::MPSTensor, Y::PEPOOrth; gate_ax::Integer = 1)
113113
return @tensor A[-1 -2; -3 -4 -5 -6] := b[-6 -2 1] * Y[-1 -3 -4 -5 1]
114114
end
115115
end
116+
117+
"""
118+
Given a middle tensor `A` in the cluster acted on by a gate,
119+
obtain reduced tensor on its next bond.
120+
121+
For PEPSTensor,
122+
```
123+
2
124+
|
125+
5 - X ← 3 1 ← a - 3
126+
| ↘ ↘
127+
4 1 (2)
128+
```
129+
For PEPOTensor,
130+
```
131+
2 3
132+
↘ |
133+
6 - X ← 4 1 ← a - 3
134+
| ↘ ↘
135+
5 1 (2)
136+
```
137+
138+
Here the physical leg on `a` is an auxiliary trivial leg.
139+
"""
140+
function bond_tensor_midnext(A::PEPSTensor; kwargs...)
141+
X, a = left_orth!(permute(A, ((1, 2, 4, 5), (3,)); copy = true); kwargs...)
142+
X = permute(X, ((1,), (2, 5, 3, 4)))
143+
a = insertrightunit(a, 1)
144+
return a, X
145+
end
146+
function bond_tensor_midnext(A::PEPOTensor; kwargs...)
147+
X, a = left_orth!(permute(A, ((1, 2, 3, 5, 6), (4,)); copy = true); kwargs...)
148+
X = permute(X, ((1, 2), (3, 6, 4, 5)))
149+
a = insertrightunit(a, 1)
150+
return a, X
151+
end
152+
153+
"""
154+
Undo the decomposition in `bond_tensor_midprev`.
155+
"""
156+
function undo_bond_tensor_midnext(a::MPSTensor, X::PEPSTensor)
157+
a = removeunit(a, 2)
158+
return @tensor A[-1; -2 -3 -4 -5] := X[-1; -2 1 -4 -5] * a[1; -3]
159+
end
160+
function undo_bond_tensor_midnext(a::MPSTensor, X::PEPOTensor)
161+
a = removeunit(a, 2)
162+
return @tensor A[-1 -2; -3 -4 -5 -6] := X[-1 -2; -3 1 -5 -6] * a[1; -4]
163+
end
164+
165+
"""
166+
Given a middle tensor `A` in the cluster acted on by a gate,
167+
obtain reduced tensor on its previous bond.
168+
169+
For PEPSTensor,
170+
```
171+
2
172+
|
173+
1 - b → 3 5 → Y - 3
174+
↘ | ↘
175+
(2) 4 1
176+
```
177+
For PEPOTensor,
178+
```
179+
2 3
180+
↘ |
181+
1 - b → 3 6 → Y - 4
182+
↘ | ↘
183+
(2) 5 1
184+
```
185+
186+
Here the physical leg on `a` is an auxiliary trivial leg.
187+
"""
188+
function bond_tensor_midprev(A::PEPSTensor; kwargs...)
189+
Y, b = left_orth!(permute(A, ((1, 2, 3, 4), (5,)); copy = true); kwargs...)
190+
Y = permute(Y, ((1,), (2, 3, 4, 5)))
191+
b = permute(b, ((2,), (1,)))
192+
b = insertrightunit(b, 1)
193+
return b, Y
194+
end
195+
function bond_tensor_midprev(A::PEPOTensor; kwargs...)
196+
Y, b = left_orth!(permute(A, ((1, 2, 3, 4, 5), (6,)); copy = true); kwargs...)
197+
Y = permute(Y, ((1, 2), (3, 4, 5, 6)))
198+
b = permute(b, ((2,), (1,)))
199+
b = insertrightunit(b, 1)
200+
return b, Y
201+
end
202+
203+
"""
204+
Undo the decomposition in `bond_tensor_midprev`.
205+
"""
206+
function undo_bond_tensor_midprev(b::MPSTensor, Y::PEPSTensor)
207+
b = removeunit(b, 2)
208+
return @tensor A[-1; -2 -3 -4 -5] := b[-5; 1] * Y[-1; -2 -3 -4 1]
209+
end
210+
function undo_bond_tensor_midprev(b::MPSTensor, Y::PEPOTensor)
211+
b = removeunit(b, 2)
212+
return @tensor A[-1 -2; -3 -4 -5 -6] := b[-6; 1] * Y[-1 -2; -3 -4 -5 1]
213+
end

test/bondenv/benv_gaugefix.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ for V1 in Vs, V2 in Vs, V3 in Vs
3737
@tensor half2[:] := Z2[-1; 1 3] * a2[1; -2 2] * b2[2 -3; 3]
3838
@test half half2
3939
# test gauge transformation of X, Y
40-
X2, Y2 = PEPSKit._fixgauge_benvXY(X, Y, Linv, Rinv)
40+
X2 = _fixgauge_benvX(X, Rinv)
41+
Y2 = _fixgauge_benvY(Y, Linv)
4142
@tensor Z2_[p; Xe Yw] := Z0[p; Xn Xs Xw Yn Ye Ys] * X2[Xn Xe Xs Xw] * Y2[Yn Ye Ys Yw]
4243
@test Z2 Z2_
4344
end

test/bondenv/benv_ntu.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ function test_ntu_env(
4141
# verify gauge transformation of X, Y
4242
@tensor a2b2[DX DY; da db] := a2[DX da D] * b2[D db DY]
4343
nrm2 = PEPSKit.inner_prod(benv2, a2b2, a2b2)
44-
X2, Y2 = PEPSKit._fixgauge_benvXY(X, Y, Linv, Rinv)
44+
X2 = _fixgauge_benvX(X, Rinv)
45+
Y2 = _fixgauge_benvY(Y, Linv)
4546
benv3 = PEPSKit.bondenv_ntu(row, col, X2, Y2, state, env_alg)
4647
benv3 *= norm(benv2, Inf)
4748
nrm3 = PEPSKit.inner_prod(benv3, a2b2, a2b2)

0 commit comments

Comments
 (0)