Skip to content

Commit 66c9788

Browse files
authored
Potts edits (#29)
* use new MPSKit function add_util_mpoleg for mpoham * generalise Potts operators to general Q * add Potts tests for Q=4 and Q=5 * Revert "use new MPSKit function add_util_mpoleg for mpoham" This reverts commit ba4a409. * generalise Potts operators to general Q * add Potts tests for Q=4 and Q=5 * remove U_matrix, V_matrix, add weyl_heisenberg_matrices, potts_Z, potts_X * fix typo in weyl_heisenberg_matrices * fix kwargs for potts_Z, potts_X * fix typo in weyl_heisenberg_matrices: the sequel * update potts_exchange, potts_field for Trivial symmetry * update potts_exchange, potts_field for Z_Q symmetry * clean up theoretical energy function * redefine potts_exchange to be the ZZ' term of the hamiltonian, i.e., remove sum * redefine potts_field to be fully dependent on potts_X, added potts_X with Z_Q symmetry * add TODO for potts_Z with Z_Q symmetry (currently uses potts_X) * update Potts hamiltonian to perform extra sum * construct potts_X with Z_Q symmetry via blocks instead of array data input * add potts_Z with Z_Q symmetry, update potts_Z to use this symmetric potts_Z * export weyl_heisenberg_matrices, potts_X, potts_Z, potts_exchange, potts_field * fix definition of W matrix in weyl_heisenberg_matrices * rename potts_exchange to potts_ZZ, construct potts_ZZ with Z_Q symmetry via block structure * remove old potts_ZZ with Z_Q symmetry, remove potts_Z with Z_Q symmetry since ill-defined * update quantum_potts to use potts_ZZ * add potts_ZZ to export, remove potts_exchange * add tests for non-symmetric and Z3 symmetric 3-state Potts * update tests for Z_Q symmetric potts operators * edit description for potts_field * add documentation for potts operators * julia formatter * use add_util_mpoleg in LocalOperator * Revert "use add_util_mpoleg in LocalOperator" This reverts commit 3a9adf2.
1 parent ba95b08 commit 66c9788

File tree

6 files changed

+196
-50
lines changed

6 files changed

+196
-50
lines changed

docs/src/man/operators.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ For convenience, the Pauli matrices can also be recovered as ``σⁱ = 2 Sⁱ``.
5252
σσ
5353
```
5454

55+
## Q-state Potts operators
56+
57+
The Q-state Potts operators `potts_X` and `potts_Z` are defined to fulfill the braiding relation ``ZX = \omega XZ`` with ``\omega = e^{2\pi i/Q}``.
58+
59+
Supported values of `symmetry` for the `X` operator are `Trivial` and `ZNIrrep{Q}`, while for the `Z` operator only `Trivial` is supported.
60+
61+
```@docs
62+
potts_X
63+
potts_Z
64+
potts_ZZ
65+
```
66+
5567
## Bosonic operators
5668

5769
The bosonic creation and annihilation operators `a_plus` ($$a^+$$) and `a_min` ($$a^-$$) are defined such that the following holds:

src/MPSKitModels.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ export SnakePattern, frontandback_pattern, backandforth_pattern
1919
export LocalOperator, SumOfLocalOperators
2020
export @mpoham
2121

22-
export spinmatrices, nonsym_spintensors, nonsym_bosonictensors
22+
export spinmatrices, nonsym_spintensors, nonsym_bosonictensors, weyl_heisenberg_matrices
2323

2424
export S_x, S_y, S_z, S_plus, S_min
2525
export S_xx, S_yy, S_zz, S_plusmin, S_minplus, S_exchange
2626
export Sˣ, Sʸ, Sᶻ, S⁺, S⁻, Sˣˣ, Sʸʸ, Sᶻᶻ, S⁺⁻, S⁻⁺, SS
2727
export σˣ, σʸ, σᶻ, σ⁺, σ⁻, σˣˣ, σʸʸ, σᶻᶻ, σ⁺⁻, σ⁻⁺, σσ
28+
export potts_X, potts_Z, potts_field, potts_ZZ
2829

2930
export a_plus, a_min, a_plusmin, a_minplus, a_number
3031
export a⁺, a⁻

src/models/hamiltonians.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,11 @@ function quantum_potts(elt::Type{<:Number}=ComplexF64,
264264
symmetry::Type{<:Sector}=Trivial,
265265
lattice::AbstractLattice=InfiniteChain(1);
266266
q=3, J=1.0, g=1.0)
267-
return @mpoham sum(nearest_neighbours(lattice)) do (i, j)
268-
return -J * potts_exchange(elt, symmetry; q){i,j}
269-
end - sum(vertices(lattice)) do i
270-
return g * potts_field(elt, symmetry; q){i}
271-
end
267+
return @mpoham sum(sum(nearest_neighbours(lattice)) do (i, j)
268+
return -J * (potts_ZZ(elt, symmetry; q)^k){i,j}
269+
end - sum(vertices(lattice)) do i
270+
return g * (potts_field(elt, symmetry; q)^k){i}
271+
end for k in 1:(q - 1))
272272
end
273273

274274
#===========================================================================================

src/operators/spinoperators.jl

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -446,62 +446,106 @@ const SS = S_exchange
446446
σσ(args...; kwargs...) = 4 * S_exchange(args...; kwargs...)
447447

448448
"""
449-
potts_exchange([eltype::Type{<:Number}], [symmetry::Type{<:Sector}]; q=3)
449+
potts_ZZ([eltype::Type{<:Number}], [symmetry::Type{<:Sector}]; q=3)
450450
451-
The Potts exchange operator ``Z ⊗ Z' + Z' ⊗ Z``, where ``Z^q = 1``.
451+
The Potts operator ``Z ⊗ Z'``, where ``Z^q = 1``.
452452
"""
453-
function potts_exchange end
454-
potts_exchange(; kwargs...) = potts_exchange(ComplexF64, Trivial; kwargs...)
455-
potts_exchange(elt::Type{<:Number}; kwargs...) = potts_exchange(elt, Trivial; kwargs...)
456-
function potts_exchange(symmetry::Type{<:Sector}; kwargs...)
457-
return potts_exchange(ComplexF64, symmetry; kwargs...)
453+
function potts_ZZ end
454+
potts_ZZ(; kwargs...) = potts_ZZ(ComplexF64, Trivial; kwargs...)
455+
potts_ZZ(elt::Type{<:Number}; kwargs...) = potts_ZZ(elt, Trivial; kwargs...)
456+
function potts_ZZ(symmetry::Type{<:Sector}; kwargs...)
457+
return potts_ZZ(ComplexF64, symmetry; kwargs...)
458458
end
459459

460-
function potts_exchange(elt::Type{<:Number}, ::Type{Trivial}; q=3)
461-
pspace = ComplexSpace(q)
462-
Z = TensorMap(zeros, elt, pspace pspace)
463-
for i in 1:q
464-
Z[i, i] = cis(2π * (i - 1) / q)
465-
end
466-
return Z Z' + Z' Z
460+
function potts_ZZ(elt::Type{<:Number}, ::Type{Trivial}; q=3)
461+
Z = potts_Z(elt, Trivial; q=q)
462+
return Z Z'
467463
end
468-
function potts_exchange(elt::Type{<:Number}, ::Type{ZNIrrep{Q}}; q=Q) where {Q}
464+
465+
function potts_ZZ(elt::Type{<:Number}, ::Type{ZNIrrep{Q}}; q=Q) where {Q}
469466
@assert q == Q "q must match the irrep charge"
470-
pspace = Vect[ZNIrrep{q}](i => 1 for i in 0:(q - 1))
471-
aspace = Vect[ZNIrrep{q}](1 => 1, -1 => 1)
472-
Z_left = TensorMap(ones, elt, pspace pspace aspace)
473-
Z_right = TensorMap(ones, elt, aspace pspace pspace)
474-
return contract_twosite(Z_left, Z_right)
467+
pspace = Vect[ZNIrrep{Q}](i => 1 for i in 0:(Q - 1))
468+
ZZ = TensorMap(zeros, elt, pspace pspace pspace pspace)
469+
for charge in 0:(Q - 1)
470+
for i in 1:Q
471+
blocks(ZZ)[ZNIrrep{Q}(charge)][i, mod1(i + 1, Q)] = one(elt)
472+
end
473+
end
474+
return ZZ
475475
end
476476

477477
"""
478478
potts_field([eltype::Type{<:Number}], [symmetry::Type{<:Sector}]; q=3)
479479
480-
The Potts field operator ``X + X'``, where ``X^q = 1``.
480+
The Potts field operator ``X``, an alias for ``potts_X``.
481481
"""
482-
function potts_field end
483-
potts_field(; kwargs...) = potts_field(ComplexF64, Trivial; kwargs...)
484-
potts_field(elt::Type{<:Number}; kwargs...) = potts_field(elt, Trivial; kwargs...)
485-
function potts_field(symmetry::Type{<:Sector}; kwargs...)
486-
return potts_field(ComplexF64, symmetry; kwargs...)
487-
end
482+
potts_field(args...; kwargs...) = potts_X(args...; kwargs...)
488483

489-
function potts_field(elt::Type{<:Number}, ::Type{Trivial}; q=3)
490-
pspace = ComplexSpace(q)
491-
X = TensorMap(zeros, elt, pspace pspace)
492-
for i in 1:q
493-
X[mod1(i - 1, q), i] = one(elt)
484+
# Generalisations of Pauli matrices
485+
486+
"""
487+
weyl_heisenberg_matrices(dimension [, eltype])
488+
489+
the Weyl-Heisenberg matrices according to [Wikipedia](https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices#Sylvester's_generalized_Pauli_matrices_(non-Hermitian)).
490+
"""
491+
492+
function weyl_heisenberg_matrices(Q::Int, elt=ComplexF64)
493+
U = zeros(elt, Q, Q) # clock matrix
494+
V = zeros(elt, Q, Q) # shift matrix
495+
W = zeros(elt, Q, Q) # DFT
496+
ω = cis(2 * pi / Q)
497+
498+
for row in 1:Q
499+
U[row, row] = ω^(row - 1)
500+
V[row, mod1(row - 1, Q)] = one(elt)
501+
for col in 1:Q
502+
W[row, col] = ω^((row - 1) * (col - 1))
503+
end
494504
end
495-
return X + X'
505+
return U, V, W / sqrt(Q)
506+
end
507+
508+
"""
509+
potts_Z([eltype::Type{<:Number}], [symmetry::Type{<:Sector}]; Q=3)
510+
511+
The Potts Z operator, also known as the clock operator, where Z^q=1.
512+
"""
513+
514+
function potts_Z end
515+
potts_Z(; kwargs...) = potts_Z(ComplexF64, Trivial; kwargs...)
516+
potts_Z(elt::Type{<:Complex}; kwargs...) = potts_Z(elt, Trivial; kwargs...)
517+
potts_Z(symm::Type{<:Sector}; kwargs...) = potts_Z(ComplexF64, symm; kwargs...)
518+
519+
function potts_Z(elt::Type{<:Number}, ::Type{Trivial}; q=3)
520+
U, _, _ = weyl_heisenberg_matrices(q, elt)
521+
Z = TensorMap(U, ComplexSpace(q) ComplexSpace(q))
522+
return Z
496523
end
497-
# TODO: generalize to arbitrary q
498-
function potts_field(elt::Type{<:Number}, ::Type{ZNIrrep{Q}}; q=Q) where {Q}
524+
525+
"""
526+
potts_X([eltype::Type{<:Number}], [symmetry::Type{<:Sector}]; Q=3)
527+
528+
The Potts X operator, also known as the shift operator, where X^q=1.
529+
"""
530+
531+
function potts_X end
532+
potts_X(; kwargs...) = potts_X(ComplexF64, Trivial; kwargs...)
533+
potts_X(elt::Type{<:Complex}; kwargs...) = potts_X(elt, Trivial; kwargs...)
534+
potts_X(symm::Type{<:Sector}; kwargs...) = potts_X(ComplexF64, symm; kwargs...)
535+
536+
function potts_X(elt::Type{<:Number}, ::Type{Trivial}; q=3)
537+
_, V, _ = weyl_heisenberg_matrices(q, elt)
538+
X = TensorMap(V, ComplexSpace(q) ComplexSpace(q))
539+
return X
540+
end
541+
542+
function potts_X(elt::Type{<:Number}, ::Type{ZNIrrep{Q}}; q=Q) where {Q}
499543
@assert q == Q "q must match the irrep charge"
500-
@assert q == 3 "only q = 3 is implemented"
501-
pspace = Vect[ZNIrrep{q}](i => 1 for i in 0:(q - 1))
544+
pspace = Vect[ZNIrrep{Q}](i => 1 for i in 0:(Q - 1))
502545
X = TensorMap(zeros, elt, pspace pspace)
503-
for (c, b) in blocks(X)
504-
b .= isone(c) ? 2 : -1
546+
ω = cis(2 * pi / Q)
547+
for i in 1:Q
548+
blocks(X)[ZNIrrep{Q}(i)] .= ω^i
505549
end
506550
return X
507551
end

test/potts.jl

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,65 @@ using MPSKit
22
using TensorKit
33

44
alg = VUMPS(; maxiter=25, verbosity=0)
5-
E₀ = -(4 / 3 + 2sqrt(3) / π)
65

7-
@testset "Trivial" begin
6+
# https://iopscience.iop.org/article/10.1088/0305-4470/14/11/020/meta
7+
function E₀(Q::Int, maxiter::Int=1000)
8+
Q == 3 && return -(4 / 3 + 2sqrt(3) / π)
9+
Q == 4 && return 2 - 8 * log(2)
10+
summation = sum((-1)^n / (sqrt(Q) / 2 - cosh((2 * n + 1) * acosh(sqrt(Q) / 2)))
11+
for n in 1:maxiter)
12+
limit = 2 - Q - sqrt(Q) * (Q - 4) * summation
13+
return limit
14+
end
15+
16+
# Q = 3
17+
@testset "Q=3 Trivial" begin
818
H = quantum_potts(; q=3)
919
ψ = InfiniteMPS(3, 32)
1020
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
1121
ψ, envs, δ = find_groundstate(ψ, H, alg)
12-
@test E₀ expectation_value(ψ, H, envs) atol = 1e-2
22+
@test E₀(3) expectation_value(ψ, H, envs) atol = 1e-2
1323
end
1424

1525
@testset "Z3Irrep" begin
1626
H = quantum_potts(Z3Irrep; q=3)
1727
ψ = InfiniteMPS(Rep[ℤ₃](i => 1 for i in 0:2), Rep[ℤ₃](i => 12 for i in 0:2))
1828
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
1929
ψ, envs, δ = find_groundstate(ψ, H, alg)
20-
@test E₀ expectation_value(ψ, H, envs) atol = 1e-2
30+
@test E₀(3) expectation_value(ψ, H, envs) atol = 1e-2
31+
end
32+
33+
# Q = 4
34+
@testset "Q=4 Trivial" begin
35+
H = quantum_potts(; q=4)
36+
ψ = InfiniteMPS(4, 45)
37+
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
38+
ψ, envs, δ = find_groundstate(ψ, H, alg)
39+
@test E₀(4) expectation_value(ψ, H, envs) atol = 1e-2
40+
end
41+
42+
@testset "Z4Irrep" begin
43+
H = quantum_potts(Z4Irrep; q=4)
44+
ψ = InfiniteMPS(Vect[Z4Irrep](i => 1 for i in 0:3), Vect[Z4Irrep](i => 12 for i in 0:3))
45+
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
46+
ψ, envs, δ = find_groundstate(ψ, H, alg)
47+
@test E₀(4) expectation_value(ψ, H, envs) atol = 1e-2
48+
end
49+
50+
# Q = 5
51+
@testset "Q=5 Trivial" begin
52+
H = quantum_potts(; q=5)
53+
ψ = InfiniteMPS(5, 60)
54+
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
55+
ψ, envs, δ = find_groundstate(ψ, H, alg)
56+
@test E₀(5) expectation_value(ψ, H, envs) atol = 1e-2
57+
end
58+
59+
@testset "ZNIrrep{5}" begin
60+
H = quantum_potts(ZNIrrep{5}; q=5)
61+
ψ = InfiniteMPS(Vect[ZNIrrep{5}](i => 1 for i in 0:4),
62+
Vect[ZNIrrep{5}](i => 12 for i in 0:4))
63+
@test imag(expectation_value(ψ, H)) 0 atol = 1e-10
64+
ψ, envs, δ = find_groundstate(ψ, H, alg)
65+
@test E₀(5) expectation_value(ψ, H, envs) atol = 1e-2
2166
end

test/spinoperators.jl

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using TensorKit
22
using TensorOperations
3-
using LinearAlgebra: tr
3+
using LinearAlgebra: tr, I
44
using TestExtras
55

66
## No symmetry ##
@@ -132,3 +132,47 @@ end
132132
@test S_exchange(U1Irrep; spin=spin)
133133
S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) + S_zz(U1Irrep; spin=spin) rtol = 1e-3
134134
end
135+
136+
# potts_ZZ test?
137+
@testset "non-symmetric Q-state potts operators" for Q in 3:5
138+
# inferrability
139+
X = @inferred potts_X(; q=Q)
140+
Z = @inferred potts_Z(; q=Q)
141+
ZZ = @inferred potts_ZZ(; q=Q)
142+
143+
# clock properties
144+
@test convert(Array, X^Q) I
145+
@test convert(Array, Z^Q) I
146+
147+
# dagger should be reversing the clock direction
148+
for s in [X Z]
149+
for i in 1:Q
150+
@test (s')^i s^(Q - i)
151+
end
152+
end
153+
154+
# commutation relations
155+
ω = cis(2π / Q)
156+
@test Z * X ω * X * Z
157+
end
158+
159+
# potts_ZZ test?
160+
@testset "Z_Q-symmetric Q-state Potts operators" for Q in 3:5
161+
# array conversion
162+
_, _, W = weyl_heisenberg_matrices(Q, ComplexF64)
163+
@test W * convert(Array, potts_X(; q=Q)) * W' convert(Array, potts_X(ZNIrrep{Q}; q=Q))
164+
165+
# inferrability
166+
X = @inferred potts_X(ZNIrrep{Q}; q=Q)
167+
ZZ = @inferred potts_ZZ(ZNIrrep{Q}; q=Q)
168+
169+
# unitarity
170+
@test X * X' X' * X
171+
@test convert(Array, X * X') I
172+
@test convert(Array, X^Q) I
173+
174+
# dagger should be reversing the clock direction
175+
for i in 1:Q
176+
@test (X')^i X^(Q - i)
177+
end
178+
end

0 commit comments

Comments
 (0)