Skip to content

Commit 24d1fbc

Browse files
authored
Add generalized pauli operators (aka clock and shift matrices) (#193)
1 parent 01fb520 commit 24d1fbc

File tree

4 files changed

+134
-4
lines changed

4 files changed

+134
-4
lines changed

src/QuantumOpticsBase.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export Basis, GenericBasis, CompositeBasis, basis,
5858
PositionBasis, MomentumBasis, samplepoints, spacing, gaussianstate,
5959
position, momentum, potentialoperator, transform,
6060
#nlevel
61-
NLevelBasis, transition, nlevelstate,
61+
NLevelBasis, transition, nlevelstate, paulix, pauliz, pauliy,
6262
#manybody
6363
ManyBodyBasis, FermionBitstring, fermionstates, bosonstates,
6464
manybodyoperator, onebodyexpect,

src/nlevel.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,65 @@ function nlevelstate(::Type{T}, b::NLevelBasis, n::Integer) where T
3131
basisstate(T, b, n)
3232
end
3333
nlevelstate(b::NLevelBasis, n::Integer) = nlevelstate(ComplexF64, b, n)
34+
35+
"""
36+
paulix([T=ComplexF64,] b::NLevelBasis, pow=1)
37+
38+
Generalized Pauli ``X`` operator for the given `N` level system. This is also
39+
called the shift matrix, and generalizes the qubit pauli matrices to qudits,
40+
while preserving the operators being unitary. A different generalization is
41+
given by the angular momentum operators which preserves the operators being
42+
Hermitian and is implemented for the `SpinBasis` (see [`sigmax`](@ref)).
43+
44+
Powers of `paulix` together with [`pauliz`](@ref) form a complete, orthornormal
45+
(under Hilbert–Schmidt norm) operator basis.
46+
47+
Returns `X^pow`.
48+
"""
49+
function paulix(::Type{T}, b::NLevelBasis, pow=1) where T
50+
N = length(b)
51+
SparseOperator(b, spdiagm(pow => fill(one(T), N-pow),
52+
pow-N => fill(one(T), pow)))
53+
end
54+
paulix(b::NLevelBasis, pow=1) = paulix(ComplexF64, b, pow)
55+
56+
"""
57+
pauliz([T=ComplexF64,] b::NLevelBasis, pow=1)
58+
59+
Generalized Pauli ``Z`` operator for the given `N` level system. This is also
60+
called the clock matrix, and generalizes the qubit pauli matrices to qudits,
61+
while preserving the operators being unitary. A different generalization is
62+
given by the angular momentum operators which preserves the operators being
63+
Hermitian and is implemented for the `SpinBasis` (see [`sigmaz`](@ref)).
64+
65+
Powers of `pauliz` together with [`paulix`](@ref) form a complete, orthornormal
66+
(under Hilbert–Schmidt norm) operator basis.
67+
68+
Returns `Z^pow`.
69+
"""
70+
function pauliz(::Type{T}, b::NLevelBasis, pow=1) where T
71+
N = length(b)
72+
ω = exp(2π*1im*pow/N)
73+
SparseOperator(b, spdiagm(0 => T[ω^n for n=1:N]))
74+
end
75+
pauliz(b::NLevelBasis, pow=1) = pauliz(ComplexF64, b, pow)
76+
77+
"""
78+
pauliy([T=ComplexF64,] b::NLevelBasis)
79+
80+
Generalized Pauli ``Y`` operator for the given `N` level system.
81+
82+
Returns `Y^pow = ω^pow X^pow Z^pow` where `ω = ω = exp(2π*1im*pow/N)` and
83+
`N = length(b)` when odd or `N = 2*length(b)` when even. This is due to the
84+
order of the generalized Pauli group in even versus odd dimensions.
85+
86+
See [`paulix`](@ref) and [`pauliz`](@ref) for more details.
87+
"""
88+
function pauliy(::Type{T}, b::NLevelBasis, pow=1) where T
89+
N = length(b)
90+
N = N%2 == 0 ? 2N : N
91+
ω = exp(2π*1im*pow/N)
92+
exp(2π*1im*pow/N)*paulix(T,b,pow)*pauliz(T,b,pow)
93+
end
94+
95+
pauliy(b::NLevelBasis, pow=1) = pauliy(ComplexF64,b)

src/spin.jl

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import QuantumInterface: SpinBasis
33
"""
44
sigmax([T=ComplexF64,] b::SpinBasis)
55
6-
Pauli ``σ_x`` operator for the given Spin basis.
6+
Angular momentum ``σ_x`` operator for the given `SpinBasis`. For
7+
`SpinBasis(1//2)` this is the Pauli ``X`` operator while for higher spins this
8+
is the Hermitian operator that gives the quantized angular momentum observable
9+
along the ``x`` direction.
10+
11+
See [`paulix`](@ref) for the generalization of the qubit pauli operators to
12+
qudits while preserving them being unitary instead of Hermitian.
713
"""
814
function sigmax(::Type{T}, b::SpinBasis) where T
915
N = length(b)
@@ -16,7 +22,13 @@ sigmax(b::SpinBasis) = sigmax(ComplexF64,b)
1622
"""
1723
sigmay([T=ComplexF64,] b::SpinBasis)
1824
19-
Pauli ``σ_y`` operator for the given Spin basis.
25+
Angular momentum ``σ_y`` operator for the given `SpinBasis`. For
26+
`SpinBasis(1//2)` this is the Pauli ``Y`` operator while for higher spins this
27+
is the Hermitian operator that gives the quantized angular momentum observable
28+
along the ``y`` direction.
29+
30+
See [`pauliy`](@ref) for the generalization of the qubit pauli operators to
31+
qudits while preserving them being unitary instead of Hermitian.
2032
"""
2133
function sigmay(::Type{T}, b::SpinBasis) where T
2234
N = length(b)
@@ -29,7 +41,13 @@ sigmay(b::SpinBasis) = sigmay(ComplexF64,b)
2941
"""
3042
sigmaz([T=ComplexF64,] b::SpinBasis)
3143
32-
Pauli ``σ_z`` operator for the given Spin basis.
44+
Angular momentum ``σ_z`` operator for the given `SpinBasis`. For
45+
`SpinBasis(1//2)` this is the Pauli ``Z`` operator while for higher spins this
46+
is the Hermitian operator that gives the quantized angular momentum observable
47+
along the ``z`` direction.
48+
49+
See [`pauliz`](@ref) for the generalization of the qubit pauli operators to
50+
qudits while preserving them being unitary instead of Hermitian.
3351
"""
3452
function sigmaz(::Type{T}, b::SpinBasis) where T
3553
N = length(b)

test/test_nlevel.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ using LinearAlgebra
44

55
@testset "nlevel" begin
66

7+
D(op1::AbstractOperator, op2::AbstractOperator) = abs(tracedistance_nh(dense(op1), dense(op2)))
8+
79
N = 3
810
b = NLevelBasis(N)
911

@@ -26,4 +28,52 @@ b = NLevelBasis(N)
2628
@test norm(dagger(nlevelstate(b, 1))*nlevelstate(b, 2)) == 0.
2729
@test norm(dagger(nlevelstate(b, 1))*transition(b, 1, 2)*nlevelstate(b, 2)) == 1.
2830

31+
for N=[2, 3, 4, 5]
32+
b = NLevelBasis(N)
33+
I = identityoperator(b)
34+
Zero = SparseOperator(b)
35+
px = paulix(b)
36+
pz = pauliz(b)
37+
38+
@test 1e-14 > abs(tr(px))
39+
@test 1e-14 > abs(tr(pz))
40+
@test 1e-14 > D(px^N, I)
41+
@test 1e-14 > D(pz^N, I)
42+
for m=2:N
43+
@test 1e-14 > D(px^m, paulix(b,m))
44+
@test 1e-14 > D(pz^m, pauliz(b,m))
45+
end
46+
47+
for m=1:N,n=1:N
48+
@test 1e-14 > D(px^m * pz^n, exp(2π*1im*m*n/N) * pz^n * px^m)
49+
end
50+
end
51+
52+
53+
# Test special relations for qubit pauli
54+
b = NLevelBasis(2)
55+
I = identityoperator(b)
56+
Zero = SparseOperator(b)
57+
px = paulix(b)
58+
py = pauliy(b)
59+
pz = pauliz(b)
60+
61+
antikommutator(x, y) = x*y + y*x
62+
63+
@test 1e-14 > D(antikommutator(px, px), 2*I)
64+
@test 1e-14 > D(antikommutator(px, py), Zero)
65+
@test 1e-14 > D(antikommutator(px, pz), Zero)
66+
@test 1e-14 > D(antikommutator(py, px), Zero)
67+
@test 1e-14 > D(antikommutator(py, py), 2*I)
68+
@test 1e-14 > D(antikommutator(py, pz), Zero)
69+
@test 1e-14 > D(antikommutator(pz, px), Zero)
70+
@test 1e-14 > D(antikommutator(pz, py), Zero)
71+
@test 1e-14 > D(antikommutator(pz, pz), 2*I)
72+
73+
# Test if involutory for spin 1/2
74+
@test 1e-14 > D(px*px, I)
75+
@test 1e-14 > D(py*py, I)
76+
@test 1e-14 > D(pz*pz, I)
77+
@test 1e-14 > D(-1im*px*py*pz, I)
78+
2979
end # testset

0 commit comments

Comments
 (0)