Skip to content

Commit a431bec

Browse files
github-actions[bot]CompatHelper Julialkdvosleburgel
authored
Compatibility for MPSKit 0.13 (#183)
* CompatHelper: bump compat for MPSKit to 0.13, (keep existing compat) * Actually import `MPSKit.physicalspace` * Refactor derivative contractions * Add twosite derivative contraction * Include PEPO contractions * Formatter * Drop compat for older MPSKit versions * Fix typo * Update VUMPS environments calling syntax (#167) * `bose_hubbard_model` charge convention * Update `add_physical_charge` implementation for `LocalOperator` * Remove TODO * Move Bose-Hubbard example * And actually point to moved example * Add test for twosite derivative operator --------- Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org> Co-authored-by: Lukas Devos <ldevos98@gmail.com> Co-authored-by: Lander Burgelman <39218680+leburgel@users.noreply.github.com> Co-authored-by: leburgel <lander.burgelman@ugent.be>
1 parent 894e9ab commit a431bec

9 files changed

Lines changed: 104 additions & 54 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ FiniteDifferences = "0.12"
3131
KrylovKit = "0.9.5"
3232
LinearAlgebra = "1"
3333
LoggingExtras = "1"
34-
MPSKit = "0.12.4"
34+
MPSKit = "0.13"
3535
MPSKitModels = "0.4"
3636
OhMyThreads = "0.7"
3737
OptimKit = "0.3, 0.4"

src/PEPSKit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ using VectorInterface
77
using TensorKit, KrylovKit, MPSKit, OptimKit, TensorOperations
88
using ChainRulesCore, Zygote
99
using LoggingExtras
10-
import MPSKit: leading_boundary, loginit!, logiter!, logfinish!, logcancel!
10+
import MPSKit: leading_boundary, loginit!, logiter!, logfinish!, logcancel!, physicalspace
1111
using MPSKitModels
1212
using FiniteDifferences
1313
using OhMyThreads: tmap

src/algorithms/contractions/vumps_contractions.jl

Lines changed: 86 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -134,52 +134,84 @@ function MPSKit.contract_mpo_expval(
134134
return environment_overlap(GL´, GR)
135135
end
136136

137+
# PEPS Derivative contractions
138+
# ----------------------------
139+
# This is appropriating the MPSKit MPO derivative structures, which might not be the best
140+
# idea in the long run.
141+
142+
const PEPS_C_Hamiltonian{S,N} = MPSKit.MPO_C_Hamiltonian{
143+
<:GenericMPSTensor{S,N},<:GenericMPSTensor{S,N}
144+
} # this one is technically type-piracy
145+
PEPS_C_Hamiltonian(GL, GR) = MPSKit.MPODerivativeOperator(GL, (), GR)
146+
147+
const PEPS_AC_Hamiltonian{S,N} = MPSKit.MPO_AC_Hamiltonian{
148+
<:GenericMPSTensor{S,N},<:PEPSSandwich,<:GenericMPSTensor{S,N}
149+
}
150+
PEPS_AC_Hamiltonian(GL, O, GR) = MPSKit.MPODerivativeOperator(GL, (O,), GR)
151+
152+
const PEPS_AC2_Hamiltonian{S,N} = MPSKit.MPO_AC2_Hamiltonian{
153+
<:GenericMPSTensor{S,N},<:PEPSSandwich,<:PEPSSandwich,<:GenericMPSTensor{S,N}
154+
}
155+
PEPS_AC2_Hamiltonian(GL, O1, O2, GR) = MPSKit.MPODerivativeOperator(GL, (O1, O2), GR)
156+
157+
# Constructors
137158
#
138-
# Derivative contractions
139-
#
140-
141-
function MPSKit.∂C(
142-
C::MPSBondTensor{S}, GL::GenericMPSTensor{S,N}, GR::GenericMPSTensor{S,N}
143-
) where {S,N}
159+
function MPSKit.C_hamiltonian(site::Int, below, ::InfiniteTransferMatrix, above, envs)
160+
GL = leftenv(envs, site + 1, below)
144161
GL = twistdual(GL, 1)
162+
GR = rightenv(envs, site, below)
145163
GR = twistdual(GR, numind(GR))
146-
return _∂C(C, GL, GR)
164+
return PEPS_C_Hamiltonian(GL, GR)
147165
end
148-
@generated function _∂C(
149-
C::MPSBondTensor{S}, GL::GenericMPSTensor{S,N}, GR::GenericMPSTensor{S,N}
150-
) where {S,N}
151-
C´_e = tensorexpr(:C´, -1, -2)
152-
C_e = tensorexpr(:C, 1, 2)
153-
GL_e = tensorexpr(:GL, (-1, (3:(N + 1))...), 1)
154-
GR_e = tensorexpr(:GR, 2:(N + 1), -2)
155-
return macroexpand(@__MODULE__, :(return @tensor $C´_e := $GL_e * $C_e * $GR_e))
166+
167+
function MPSKit.AC_hamiltonian(
168+
site::Int, below, operator::InfiniteTransferPEPS, above, envs
169+
)
170+
GL = leftenv(envs, site, below)
171+
GL = twistdual(GL, 1)
172+
GR = rightenv(envs, site, below)
173+
GR = twistdual(GR, numind(GR))
174+
return PEPS_AC_Hamiltonian(GL, operator[site], GR)
156175
end
157176

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}
177+
function MPSKit.AC2_hamiltonian(
178+
site::Int, below, operator::InfiniteTransferPEPS, above, envs
179+
)
180+
GL = leftenv(envs, site, below)
164181
GL = twistdual(GL, 1)
182+
GR = rightenv(envs, site + 1, below)
165183
GR = twistdual(GR, numind(GR))
166-
return _∂AC(AC, O, GL, GR)
184+
return PEPS_AC2_Hamiltonian(GL, operator[site], operator[site + 1], GR)
167185
end
168186

169-
## PEPS
187+
# Actions
188+
#
189+
@generated function (h::PEPS_C_Hamiltonian{S,N})(C::MPSBondTensor{S}) where {S,N}
190+
C´_e = tensorexpr(:C´, -1, -2)
191+
C_e = tensorexpr(:C, 1, 2)
192+
GL_e = tensorexpr(:(h.leftenv), (-1, (3:(N + 1))...), 1)
193+
GR_e = tensorexpr(:(h.rightenv), (2:(N + 1)...,), -2)
194+
return macroexpand(@__MODULE__, :(return @tensor $C´_e := $GL_e * $C_e * $GR_e))
195+
end
170196

171-
function _∂AC(
172-
AC::GenericMPSTensor{S,3},
173-
O::PEPSSandwich,
174-
GL::GenericMPSTensor{S,3},
175-
GR::GenericMPSTensor{S,3},
176-
) where {S}
197+
function (h::PEPS_AC_Hamiltonian{S,N})(AC::GenericMPSTensor{S,N}) where {S,N}
177198
return @autoopt @tensor AC′[χ_SW D_S_above D_S_below; χ_SE] :=
178-
GL[χ_SW D_W_above D_W_below; χ_NW] *
199+
h.leftenv[χ_SW D_W_above D_W_below; χ_NW] *
179200
AC[χ_NW D_N_above D_N_below; χ_NE] *
180-
GR[χ_NE D_E_above D_E_below; χ_SE] *
181-
ket(O)[d; D_N_above D_E_above D_S_above D_W_above] *
182-
conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below])
201+
h.rightenv[χ_NE D_E_above D_E_below; χ_SE] *
202+
ket(h.operators[1])[d; D_N_above D_E_above D_S_above D_W_above] *
203+
conj(bra(h.operators[1])[d; D_N_below D_E_below D_S_below D_W_below])
204+
end
205+
206+
function (h::PEPS_AC2_Hamiltonian{S,3})(AC2::AbstractTensorMap{<:Any,S,3,3}) where {S}
207+
return @autoopt @tensor AC2′[χ_SW D_S_above1 D_S_below1; χ_SE D_S_below2 D_S_above2] :=
208+
h.leftenv[χ_SW D_W_above1 D_W_below1; χ_NW] *
209+
AC2[χ_NW D_N_above1 D_N_below1; χ_NE D_N_below2 D_N_above2] *
210+
h.rightenv[χ_NE D_E_above2 D_E_below2; χ_SE] *
211+
ket(h.operators[1])[d1; D_N_above1 D_E_above1 D_S_above1 D_W_above1] *
212+
conj(bra(h.operators[1])[d1; D_N_below1 D_E_below1 D_S_below1 D_W_below1]) *
213+
ket(h.operators[2])[d2; D_N_above2 D_E_above2 D_S_above2 D_E_above1] *
214+
conj(bra(h.operators[2])[d2; D_N_below2 D_E_below2 D_S_below2 D_E_below1])
183215
end
184216

185217
# PEPS derivative
@@ -198,22 +230,32 @@ function ∂peps(
198230
conj(ĀC[χ_SW D_S_above D_S_below; χ_SE])
199231
end
200232

201-
## PEPO
233+
# PEPO Derivative contractions
234+
# ----------------------------
235+
const PEPO_AC_Hamiltonian{S,N,H} = MPSKit.MPO_AC_Hamiltonian{
236+
<:GenericMPSTensor{S,N},<:PEPOSandwich{H},<:GenericMPSTensor{S,N}
237+
}
238+
PEPO_AC_Hamiltonian(GL, O, GR) = MPSKit.MPODerivativeOperator(GL, (O,), GR)
239+
240+
function MPSKit.AC_hamiltonian(
241+
site::Int, below, operator::InfiniteTransferPEPO, above, envs
242+
)
243+
GL = leftenv(envs, site, below)
244+
GL = twistdual(GL, 1)
245+
GR = rightenv(envs, site, below)
246+
GR = twistdual(GR, numind(GR))
247+
return PEPO_AC_Hamiltonian(GL, operator[site], GR)
248+
end
202249

203-
@generated function _∂AC(
204-
AC::GenericMPSTensor{S,N},
205-
O::PEPOSandwich{H},
206-
GL::GenericMPSTensor{S,N},
207-
GR::GenericMPSTensor{S,N},
208-
) where {S,N,H}
250+
@generated function (h::PEPO_AC_Hamiltonian{S,N,H})(AC::GenericMPSTensor{S,N}) where {S,N,H}
209251
# sanity check
210-
@assert H == N - 3
252+
@assert H == N - 3 "Incompatible number of legs and layers"
211253

212254
AC´_e = _pepo_edge_expr(:AC´, :SW, :SE, :S, H)
213255
AC_e = _pepo_edge_expr(:AC, :NW, :NE, :N, H)
214-
GL_e = _pepo_edge_expr(:GL, :SW, :NW, :W, H)
215-
GR_e = _pepo_edge_expr(:GR, :NE, :SE, :E, H)
216-
ket_e, bra_e, pepo_es = _pepo_sandwich_expr(:O, H)
256+
GL_e = _pepo_edge_expr(:(h.leftenv), :SW, :NW, :W, H)
257+
GR_e = _pepo_edge_expr(:(h.rightenv), :NE, :SE, :E, H)
258+
ket_e, bra_e, pepo_es = _pepo_sandwich_expr(:(h.operators[1]), H)
217259

218260
rhs = Expr(:call, :*, AC_e, GL_e, GR_e, ket_e, Expr(:call, :conj, bra_e), pepo_es...)
219261

src/environments/vumps_environments.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ using MPSKit: InfiniteEnvironments
55

66
function MPSKit.issamespace(
77
env::InfiniteEnvironments,
8-
above::InfiniteMPS,
9-
operator::InfiniteTransferMatrix,
108
below::InfiniteMPS,
9+
operator::InfiniteTransferMatrix,
10+
above::InfiniteMPS,
1111
)
1212
L = MPSKit.check_length(above, operator, below)
1313
for i in 1:L

src/operators/localoperator.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,17 +264,19 @@ end
264264
"""
265265
MPSKit.add_physical_charge(H::LocalOperator, charges::AbstractMatrix{<:Sector}) where {S}
266266
267-
Change the spaces of a `LocalOperator` by fusing in an auxiliary charge on every site,
268-
according to a given matrix of 'auxiliary' physical charges.
267+
Change the spaces of a `LocalOperator` by fusing in an auxiliary charge into the domain of
268+
the operator on every site, according to a given matrix of 'auxiliary' physical charges.
269269
"""
270270
function MPSKit.add_physical_charge(H::LocalOperator, charges::AbstractMatrix{<:Sector})
271271
size(H.lattice) == size(charges) ||
272272
throw(ArgumentError("Incompatible lattice and auxiliary charge sizes"))
273273
sectortype(H) === eltype(charges) ||
274274
throw(SectorMismatch("Incompatible lattice and auxiliary charge sizes"))
275275

276-
# make indexing periodic, for convenience
277-
Paux = PeriodicArray(map(c -> Vect[typeof(c)](c => 1), charges))
276+
# auxiliary spaces will be fused into codomain, so need to dualize the space to fuse
277+
# the charge into the domain as desired
278+
# also, make indexing periodic for convenience
279+
Paux = PeriodicArray(map(c -> Vect[typeof(c)](c => 1)', charges))
278280

279281
# new physical spaces
280282
Pspaces = map(fuse, H.lattice, Paux)

src/operators/models.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ function MPSKitModels.bose_hubbard_model(
198198
elseif symmetry === U1Irrep
199199
isinteger(2n) ||
200200
throw(ArgumentError("`U₁` symmetry requires halfinteger particle number"))
201-
H = MPSKit.add_physical_charge(H, fill(U1Irrep(-n), size(spaces)...)) # TODO: settle on convention here?
201+
H = MPSKit.add_physical_charge(H, fill(U1Irrep(n), size(spaces)...))
202202
else
203203
throw(ArgumentError("symmetry not implemented"))
204204
end

test/boundarymps/vumps.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Random.seed!(29384293742893)
1010
const vumps_alg = VUMPS(;
1111
tol=1e-6, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), verbosity=2
1212
)
13+
1314
@testset "(1, 1) PEPS" begin
1415
psi = InfinitePEPS(ComplexSpace(2), ComplexSpace(2))
1516

@@ -19,6 +20,11 @@ const vumps_alg = VUMPS(;
1920
mps, env, ϵ = leading_boundary(mps, T, vumps_alg)
2021
N = abs(sum(expectation_value(mps, T)))
2122

23+
mps2, = changebonds(mps, T, OptimalExpand(; trscheme=truncdim(30)))
24+
mps2, env2, ϵ = leading_boundary(mps2, T, vumps_alg)
25+
N2 = abs(sum(expectation_value(mps2, T)))
26+
@test N N2 rtol = 1e-2
27+
2228
ctm, = leading_boundary(CTMRGEnv(psi, ComplexSpace(20)), psi)
2329
= abs(norm(psi, ctm))
2430

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ end
7676
include("examples/pwave.jl")
7777
end
7878
@time @safetestset "U1-symmetric Bose-Hubbard model" begin
79-
include("bose_hubbard.jl")
79+
include("examples/bose_hubbard.jl")
8080
end
8181
end
8282
end

0 commit comments

Comments
 (0)