Skip to content

Commit 0eecc31

Browse files
committed
Merge branch 'pb-lorentzian-broadening' of github.com:quantumghent/PEPSKit.jl into pb-lorentzian-broadening
2 parents f1800f1 + 9bafc7b commit 0eecc31

8 files changed

Lines changed: 170 additions & 41 deletions

File tree

examples/boundary_mps.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ T = InfiniteTransferPEPS(peps, 1, 1)
2323
# encodes the norm of the state
2424

2525
# Fist we build an initial guess for the boundary MPS, choosing a bond dimension of 20
26-
mps = PEPSKit.initializeMPS(T, [ComplexSpace(20)])
26+
mps = initialize_mps(T, [ComplexSpace(20)])
2727

2828
# We then find the leading boundary MPS fixed point using the VUMPS algorithm
2929
mps, env, ϵ = leading_boundary(mps, T, VUMPS())
@@ -51,7 +51,7 @@ N´ = abs(norm(peps, ctm))
5151
peps2 = InfinitePEPS(ComplexSpace(2), ComplexSpace(2); unitcell=(2, 2))
5252
T2 = PEPSKit.MultilineTransferPEPS(peps2, 1)
5353

54-
mps2 = PEPSKit.initializeMPS(T2, fill(ComplexSpace(20), 2, 2))
54+
mps2 = initialize_mps(T2, fill(ComplexSpace(20), 2, 2))
5555
mps2, env2, ϵ = leading_boundary(mps2, T2, VUMPS())
5656
N2 = abs(prod(expectation_value(mps2, T2)))
5757

@@ -76,7 +76,7 @@ N2´ = abs(norm(peps2, ctm2))
7676
pepo = ising_pepo(1)
7777
T3 = InfiniteTransferPEPO(peps, pepo, 1, 1)
7878

79-
mps3 = PEPSKit.initializeMPS(T3, [ComplexSpace(20)])
79+
mps3 = initialize_mps(T3, [ComplexSpace(20)])
8080
mps3, env3, ϵ = leading_boundary(mps3, T3, VUMPS())
8181
@show N3 = abs(prod(expectation_value(mps3, T3)))
8282

src/PEPSKit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export InfinitePartitionFunction
8989
export InfinitePEPS, InfiniteTransferPEPS
9090
export SUWeight, InfiniteWeightPEPS
9191
export InfinitePEPO, InfiniteTransferPEPO
92-
export initializeMPS, initializePEPS
92+
export initialize_mps, initializePEPS
9393
export ReflectDepth, ReflectWidth, Rotate, RotateReflect
9494
export symmetrize!, symmetrize_retract_and_finalize!
9595
export showtypeofgrad

src/algorithms/contractions/vumps_contractions.jl

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,29 @@ using MPSKit: GenericMPSTensor, MPSBondTensor
44
# Environment transfer functions
55
#
66

7+
function MPSKit.transfer_left(
8+
GL::GenericMPSTensor{S,N},
9+
O::Union{PEPSSandwich,PEPOSandwich},
10+
A::GenericMPSTensor{S,N},
11+
::GenericMPSTensor{S,N},
12+
) where {S,N}
13+
= twistdual(Ā, 2:N)
14+
return _transfer_left(GL, O, A, Ā)
15+
end
16+
17+
function MPSKit.transfer_right(
18+
GR::GenericMPSTensor{S,N},
19+
O::Union{PEPSSandwich,PEPOSandwich},
20+
A::GenericMPSTensor{S,N},
21+
::GenericMPSTensor{S,N},
22+
) where {S,N}
23+
= twistdual(Ā, 2:N)
24+
return _transfer_right(GR, O, A, Ā)
25+
end
26+
727
## PEPS
828

9-
function MPSKit.transfer_left(
29+
function _transfer_left(
1030
GL::GenericMPSTensor{S,3},
1131
O::PEPSSandwich,
1232
A::GenericMPSTensor{S,3},
@@ -20,7 +40,7 @@ function MPSKit.transfer_left(
2040
A[χ_NW D_N_above D_N_below; χ_NE]
2141
end
2242

23-
function MPSKit.transfer_right(
43+
function _transfer_right(
2444
GR::GenericMPSTensor{S,3},
2545
O::PEPSSandwich,
2646
A::GenericMPSTensor{S,3},
@@ -36,7 +56,7 @@ end
3656

3757
## PEPO
3858

39-
@generated function MPSKit.transfer_left(
59+
@generated function _transfer_left(
4060
GL::GenericMPSTensor{S,N},
4161
O::PEPOSandwich{H},
4262
A::GenericMPSTensor{S,N},
@@ -65,7 +85,7 @@ end
6585
return macroexpand(@__MODULE__, :(return @autoopt @tensor $GL´_e := $rhs))
6686
end
6787

68-
@generated function MPSKit.transfer_right(
88+
@generated function _transfer_right(
6989
GR::GenericMPSTensor{S,N},
7090
O::PEPOSandwich{H},
7191
A::GenericMPSTensor{S,N},
@@ -118,7 +138,14 @@ end
118138
# Derivative contractions
119139
#
120140

121-
@generated function MPSKit.∂C(
141+
function MPSKit.∂C(
142+
C::MPSBondTensor{S}, GL::GenericMPSTensor{S,N}, GR::GenericMPSTensor{S,N}
143+
) where {S,N}
144+
GL = twistdual(GL, 1)
145+
GR = twistdual(GR, numind(GR))
146+
return _∂C(C, GL, GR)
147+
end
148+
@generated function _∂C(
122149
C::MPSBondTensor{S}, GL::GenericMPSTensor{S,N}, GR::GenericMPSTensor{S,N}
123150
) where {S,N}
124151
C´_e = tensorexpr(:C´, -1, -2)
@@ -128,9 +155,20 @@ end
128155
return macroexpand(@__MODULE__, :(return @tensor $C´_e := $GL_e * $C_e * $GR_e))
129156
end
130157

158+
function MPSKit.∂AC(
159+
AC::GenericMPSTensor{S,N},
160+
O::Union{PEPSSandwich,PEPOSandwich},
161+
GL::GenericMPSTensor{S,N},
162+
GR::GenericMPSTensor{S,N},
163+
) where {S,N}
164+
GL = twistdual(GL, 1)
165+
GR = twistdual(GR, numind(GR))
166+
return _∂AC(AC, O, GL, GR)
167+
end
168+
131169
## PEPS
132170

133-
function MPSKit.∂AC(
171+
function _∂AC(
134172
AC::GenericMPSTensor{S,3},
135173
O::PEPSSandwich,
136174
GL::GenericMPSTensor{S,3},
@@ -162,7 +200,7 @@ end
162200

163201
## PEPO
164202

165-
@generated function MPSKit.∂AC(
203+
@generated function _∂AC(
166204
AC::GenericMPSTensor{S,N},
167205
O::PEPOSandwich{H},
168206
GL::GenericMPSTensor{S,N},

src/algorithms/toolbox.jl

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,11 @@ environment `env`.
142142
"""
143143
function _contract_corners(ind::Tuple{Int,Int}, env::CTMRGEnv)
144144
r, c = ind
145-
return tr(
146-
env.corners[NORTHWEST, _prev(r, end), _prev(c, end)] *
147-
env.corners[NORTHEAST, _prev(r, end), c] *
148-
env.corners[SOUTHEAST, r, c] *
149-
env.corners[SOUTHWEST, r, _prev(c, end)],
150-
)
145+
C_NW = env.corners[NORTHWEST, _prev(r, end), _prev(c, end)]
146+
C_NE = env.corners[NORTHEAST, _prev(r, end), c]
147+
C_SE = env.corners[SOUTHEAST, r, c]
148+
C_SW = env.corners[SOUTHWEST, r, _prev(c, end)]
149+
return @tensor C_NW[1; 2] * C_NE[2; 3] * C_SE[3; 4] * C_SW[4; 1]
151150
end
152151

153152
"""

src/networks/local_sandwich.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,39 @@ function virtualspace(O::PEPSSandwich, dir)
5555
return virtualspace(ket(O), dir) virtualspace(bra(O), dir)'
5656
end
5757

58+
# not overloading MPOTensor because that defines AbstractTensorMap{<:Any,S,2,2}(::PEPSTensor, ::PEPSTensor)
59+
# ie type piracy
60+
mpotensor(top::PEPSTensor) = mpotensor((top, top))
61+
function mpotensor((top, bot)::PEPSSandwich)
62+
@assert virtualspace(top, NORTH) == dual(virtualspace(top, SOUTH)) &&
63+
virtualspace(bot, NORTH) == dual(virtualspace(bot, SOUTH)) &&
64+
virtualspace(top, EAST) == dual(virtualspace(top, WEST)) &&
65+
virtualspace(bot, EAST) == dual(virtualspace(bot, WEST)) &&
66+
isdual(virtualspace(top, NORTH)) &&
67+
isdual(virtualspace(bot, NORTH)) &&
68+
isdual(virtualspace(top, EAST)) &&
69+
isdual(virtualspace(bot, EAST)) "Method not yet implemented for given virtual spaces"
70+
71+
F_west = isomorphism(
72+
storagetype(top),
73+
fuse(virtualspace(top, WEST), virtualspace(bot, WEST)'),
74+
virtualspace(top, WEST) virtualspace(bot, WEST)',
75+
)
76+
F_south = isomorphism(
77+
storagetype(top),
78+
fuse(virtualspace(top, SOUTH), virtualspace(bot, SOUTH)'),
79+
virtualspace(top, SOUTH) virtualspace(bot, SOUTH)',
80+
)
81+
@tensor O[west south; north east] :=
82+
top[phys; top_north top_east top_south top_west] *
83+
conj(bot[phys; bot_north bot_east bot_south bot_west]) *
84+
twist(F_west, 3)[west; top_west bot_west] *
85+
twist(F_south, 3)[south; top_south bot_south] *
86+
conj(F_west[east; top_east bot_east]) *
87+
conj(F_south[north; top_north bot_north])
88+
return O
89+
end
90+
5891
## PEPO
5992

6093
const PEPOSandwich{N,T<:PEPSTensor,P<:PEPOTensor} = Tuple{T,T,Vararg{P,N}}

src/operators/transfermatrix.jl

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,53 +125,59 @@ const MultilineTransferMatrix = Union{MultilineTransferPEPS,MultilineTransferPEP
125125
virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir)
126126

127127
"""
128-
initializeMPS(
128+
initialize_mps(
129+
f=randn,
130+
T=scalartype(O),
129131
O::Union{InfiniteTransferPEPS,InfiniteTransferPEPO},
130132
virtualspaces::AbstractArray{<:ElementarySpace,1}
131133
)
132-
initializeMPS(
134+
initialize_mps(
135+
f=randn,
136+
T=scalartype(O),
133137
O::Union{MultilineTransferPEPS,MultilineTransferPEPO},
134138
virtualspaces::AbstractArray{<:ElementarySpace,2}
135139
)
136140
137141
Inialize a boundary MPS for the transfer operator `O` by specifying an array of virtual
138142
spaces consistent with the unit cell.
139143
"""
140-
function initializeMPS(
141-
O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S,1}
144+
function initialize_mps(O::Union{InfiniteTransferMatrix,MultilineTransferMatrix}, arg) # initialize(f=randn, T=scalartype(O), O, ...)
145+
return initialize_mps(randn, scalartype(O), O, arg)
146+
end
147+
function initialize_mps(
148+
f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S,1}
142149
) where {S}
143150
return InfiniteMPS([
144-
randn(
145-
scalartype(O),
151+
f(
152+
T,
146153
virtualspaces[_prev(i, end)] * _elementwise_dual(north_virtualspace(O, i)),
147154
virtualspaces[mod1(i, end)],
148155
) for i in 1:length(O)
149156
])
150157
end
151-
function initializeMPS(O::InfiniteTransferMatrix, χ::Int)
158+
function initialize_mps(f, T, O::InfiniteTransferMatrix, χ::Int)
152159
return InfiniteMPS([
153-
randn(calartype(O), ℂ^χ * _elementwise_dual(north_virtualspace(O, i)), ℂ^χ) for
154-
i in 1:length(O)
160+
f(T, ℂ^χ * _elementwise_dual(north_virtualspace(O, i)), ℂ^χ) for i in 1:length(O)
155161
])
156162
end
157-
function initializeMPS(
158-
O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,2}
163+
function initialize_mps(
164+
f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,2}
159165
) where {S}
160166
mpss = map(1:size(O, 1)) do r
161-
return initializeMPS(O[r], virtualspaces[r, :])
167+
return initialize_mps(f, T, O[r], virtualspaces[r, :])
162168
end
163169
return MPSKit.Multiline(mpss)
164170
end
165-
function initializeMPS(
166-
O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,1}
171+
function initialize_mps(
172+
f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,1}
167173
) where {S}
168-
return initializeMPS(O, repeat(virtualspaces, length(O), 1))
174+
return initialize_mps(f, T, O, repeat(virtualspaces, length(O), 1))
169175
end
170-
function initializeMPS(O::MultilineTransferMatrix, V::ElementarySpace)
171-
return initializeMPS(O, repeat([V], length(O), length(O[1])))
176+
function initialize_mps(f, T, O::MultilineTransferMatrix, V::ElementarySpace)
177+
return initialize_mps(f, T, O, repeat([V], length(O), length(O[1])))
172178
end
173-
function initializeMPS(O::MultilineTransferMatrix, χ::Int)
174-
return initializeMPS(O, repeat([ℂ^χ], length(O), length(O[1])))
179+
function initialize_mps(f, T, O::MultilineTransferMatrix, χ::Int)
180+
return initialize_mps(f, T, O, repeat([ℂ^χ], length(O), length(O[1])))
175181
end
176182

177183
@doc """

src/utility/util.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,22 @@ function absorb_s(u::AbstractTensorMap, s::DiagonalTensorMap, vh::AbstractTensor
102102
return u * sqrt_s, sqrt_s * vh
103103
end
104104

105+
"""
106+
twistdual(t::AbstractTensorMap, i)
107+
twistdual!(t::AbstractTensorMap, i)
108+
109+
Twist the i-th leg of a tensor `t` if it represents a dual space.
110+
"""
111+
function twistdual!(t::AbstractTensorMap, i::Int)
112+
isdual(space(t, i)) || return t
113+
return twist!(t, i)
114+
end
115+
function twistdual!(t::AbstractTensorMap, is)
116+
is′ = filter(i -> isdual(space(t, i)), is)
117+
return twist!(t, is′)
118+
end
119+
twistdual(t::AbstractTensorMap, is) = twistdual!(copy(t), is)
120+
105121
# Check whether diagonals contain degenerate values up to absolute or relative tolerance
106122
function is_degenerate_spectrum(
107123
S; atol::Real=0, rtol::Real=atol > 0 ? 0 : sqrt(eps(scalartype(S)))

test/boundarymps/vumps.jl

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ using LinearAlgebra
77

88
Random.seed!(29384293742893)
99

10-
const vumps_alg = VUMPS(; alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))
10+
const vumps_alg = VUMPS(;
11+
tol=1e-6, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), verbosity=2
12+
)
1113
@testset "(1, 1) PEPS" begin
1214
psi = InfinitePEPS(ComplexSpace(2), ComplexSpace(2))
1315

1416
T = PEPSKit.InfiniteTransferPEPS(psi, 1, 1)
15-
mps = PEPSKit.initializeMPS(T, [ComplexSpace(20)])
17+
mps = initialize_mps(T, [ComplexSpace(20)])
1618

1719
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
1820
N = abs(sum(expectation_value(mps, T)))
@@ -27,7 +29,7 @@ end
2729
psi = InfinitePEPS(ComplexSpace(2), ComplexSpace(2); unitcell=(2, 2))
2830
T = PEPSKit.MultilineTransferPEPS(psi, 1)
2931

30-
mps = PEPSKit.initializeMPS(T, fill(ComplexSpace(20), 2, 2))
32+
mps = initialize_mps(rand, scalartype(T), T, fill(ComplexSpace(20), 2, 2))
3133
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
3234
N = abs(prod(expectation_value(mps, T)))
3335

@@ -37,6 +39,41 @@ end
3739
@test N N´ rtol = 1e-2
3840
end
3941

42+
@testset "Fermionic PEPS" begin
43+
D = Vect[fℤ₂](0 => 1, 1 => 1)
44+
d = Vect[fℤ₂](0 => 1, 1 => 1)
45+
χ = Vect[fℤ₂](0 => 10, 1 => 10)
46+
47+
psi = InfinitePEPS(D, d; unitcell=(1, 1))
48+
n = InfiniteSquareNetwork(psi)
49+
T = InfiniteTransferPEPS(psi, 1, 1)
50+
51+
# compare boundary MPS contraction to CTMRG contraction
52+
mps = initialize_mps(T, [χ])
53+
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
54+
N_vumps = abs(prod(expectation_value(mps, T)))
55+
56+
ctm, = leading_boundary(CTMRGEnv(psi, χ), psi)
57+
N_ctm = abs(norm(psi, ctm))
58+
59+
@test N_vumps N_ctm rtol = 1e-2
60+
61+
# and again after blocking the local sandwiches
62+
= InfiniteSquareNetwork(map(PEPSKit.mpotensor, PEPSKit.unitcell(n)))
63+
= InfiniteMPO(map(PEPSKit.mpotensor, T.O))
64+
65+
mps´ = InfiniteMPS(randn, ComplexF64, [physicalspace(T´, 1)], [χ])
66+
mps´, env´, ϵ = leading_boundary(mps´, T´, vumps_alg)
67+
N_vumps´ = abs(prod(expectation_value(mps´, T´)))
68+
69+
ctm´, = leading_boundary(CTMRGEnv(n´, χ), n´)
70+
N_ctm´ = abs(network_value(n´, ctm´))
71+
72+
@show N_vumps´
73+
@test N_vumps´ N_vumps rtol = 1e-2
74+
@test N_vumps´ N_ctm´ rtol = 1e-2
75+
end
76+
4077
@testset "PEPO runthrough" begin
4178
function ising_pepo(beta; unitcell=(1, 1, 1))
4279
t = ComplexF64[exp(beta) exp(-beta); exp(-beta) exp(beta)]
@@ -64,7 +101,7 @@ end
64101
psi = PEPSKit.initializePEPS(O, ComplexSpace(2))
65102
T = InfiniteTransferPEPO(psi, O, 1, 1)
66103

67-
mps = PEPSKit.initializeMPS(T, [ComplexSpace(10)])
104+
mps = initialize_mps(rand, scalartype(T), T, [ComplexSpace(10)])
68105
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
69106
f = abs(prod(expectation_value(mps, T)))
70107

@@ -73,7 +110,7 @@ end
73110
psi2 = initializePEPS(O, ComplexSpace(2))
74111
T = InfiniteTransferPEPO(psi, O, 1, 1)
75112

76-
mps = PEPSKit.initializeMPS(T, [ComplexSpace(8)])
113+
mps = initialize_mps(rand, scalartype(T), T, [ComplexSpace(8)])
77114
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
78115
f = abs(prod(expectation_value(mps, T)))
79116
end

0 commit comments

Comments
 (0)