Skip to content

Commit 01d7ace

Browse files
committed
Get all pauli tests passing!
1 parent a699c89 commit 01d7ace

File tree

4 files changed

+115
-113
lines changed

4 files changed

+115
-113
lines changed

src/pauli.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ function _pauli_comp_1()
1111
Operator(KetBraBasis(b, b), PauliBasis(1), V)
1212
end
1313

14+
tensor(A::Operator{BL,BR}, B::Operator{BL,BR}) where {BL<:KetBraBasis, BR<:PauliBasis} = super_tensor(A,B)
15+
1416
_pauli_comp_1_cached = _pauli_comp_1()
1517

1618
# TODO: should this be further cached?
@@ -47,19 +49,24 @@ end
4749
function _choi_chi_convert(op, rev)
4850
Nl, Nr = length(basis_l(basis_l(op))), length(basis_r(basis_l(op)))
4951
V = choi_chi(Nl,Nr)
50-
rev ? V * op * dagger(V) : dagger(V) * op * V
52+
norm = 2^((Nl+Nr)÷2)
53+
out = rev ? norm * V * op * dagger(V) : (1/norm) * dagger(V) * op * V
5154
end
5255

5356
pauli(op::SuperOperatorType) = _pauli_comp_convert(op, false)
5457
super(op::PauliTransferType) = _pauli_comp_convert(op, true)
5558
chi(op::ChoiStateType) = _choi_chi_convert(op, false)
5659
choi(op::ChiType) = _choi_chi_convert(op, true)
57-
pauli(op::ChiType) = _super_choi(PauliBasis, op)
58-
chi(op::PauliTransferType) = _super_choi(ChiBasis, op)
59-
pauli(op::ChoiStateType) = pauli(chi(op))
60-
chi(op::SuperOperatorType) = chi(pauli(op))
60+
6161
super(op::ChiType) = super(choi(op))
6262
choi(op::PauliTransferType) = choi(super(op))
63+
pauli(op::ChoiStateType) = pauli(super(op))
64+
chi(op::SuperOperatorType) = chi(choi(op))
65+
pauli(op::ChiType) = pauli(super(choi(op)))
66+
chi(op::PauliTransferType) = chi(choi(super(op)))
67+
68+
#pauli(op::ChiType) = _super_choi(PauliBasis, op)
69+
#chi(op::PauliTransferType) = _super_choi(ChiBasis, op)
6370

6471
pauli(op::PauliTransferType) = op
6572
chi(op::ChiType) = op
@@ -68,6 +75,8 @@ pauli(op::Operator) = pauli(vec(op))
6875
pauli(k::Ket{<:KetBraBasis}) = dagger(pauli_comp(length(basis_l(basis(k))))) * k
6976
unvec(k::Ket{<:PauliBasis}) = unvec(pauli_comp(length(basis_l(basis(k)))) * k)
7077

78+
dagger(a::ChiType) = chi(dagger(choi(a)))
79+
7180
# TODO: document return types of mixed superoperator multiplication...
7281
# This method is necessary so we don't fall back to the method below it
7382
*(a::PauliTransferType, b::PauliTransferType) = (check_multiplicable(a,b); Operator(a.basis_l, b.basis_r, a.data*b.data))

src/superoperators.jl

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import QuantumInterface: KetBraBasis, ChoiBasis
44
const SuperOperatorType{BL,BR,T} = Operator{BL,BR,T} where {BL<:KetBraBasis,BR<:KetBraBasis}
55
const ChoiStateType{BL,BR,T} = Operator{BL,BR,T} where {BR<:ChoiBasis,BL<:ChoiBasis}
66

7+
#const ChannelType = Union{SuperOperatorType, ChoiStateType, PauliTransferType, ChiType}
8+
79
#const SOpBasis = Union{KetBraBasis, PauliBasis}
810
#const SuperOperatorType{BL,BR,T} = Operator{BL,BR,T} where {BL<:SOpBasis,BR<:SOpBasis}
911
#const SOpKetBraType{BL,BR,T} = Operator{BL,BR,T} where {BL<:KetBraBasis,BR<:KetBraBasis}
@@ -45,21 +47,33 @@ sprepost(A::Operator, B::Operator) = Operator(KetBraBasis(basis_l(A), basis_r(B)
4547
# Operator(KetBraBasis(basis_l(A), basis_r(B)), KetBraBasis(basis_r(A), basis_l(B)), C)
4648
#end
4749

48-
function tensor(A::T, B::T) where T<:Union{SuperOperatorType, ChoiStateType}
49-
a1, a2 = basis_l(A), basis_r(A)
50-
b1, b2 = basis_l(B), basis_r(B)
51-
#da1, da2, db1, db2 = map(dimension, (a1, a2, b1, b2))
52-
#@cast C[(ν,μ), (n,m)] |= A.data[m,μ] * B.data[n,ν] (m ∈ 1:da1, μ ∈ 1:da2, n ∈ 1:db1, ν ∈ 1:db2)
53-
#data = kron(B.data, A.data)
54-
#data = reshape(data, map(dimension, (a1, a2, b1, b2)))
55-
#data = PermutedDimsArray(data, (4, 2, 3, 1))
56-
#data = reshape(data, map(dimension, (a2⊗b2, a1⊗b1)))
57-
#return Operator(a1⊗b1, a2⊗b2, data)
50+
#function super_tensor(A, B)
51+
# a1, a2 = basis_l(A), basis_r(A)
52+
# b1, b2 = basis_l(B), basis_r(B)
53+
# #da1, da2, db1, db2 = map(dimension, (a1, a2, b1, b2))
54+
# #@cast C[(ν,μ), (n,m)] |= A.data[m,μ] * B.data[n,ν] (m ∈ 1:da1, μ ∈ 1:da2, n ∈ 1:db1, ν ∈ 1:db2)
55+
# #data = kron(B.data, A.data)
56+
# #data = reshape(data, map(dimension, (a1, a2, b1, b2)))
57+
# #data = PermutedDimsArray(data, (4, 2, 3, 1))
58+
# #data = reshape(data, map(dimension, (a2⊗b2, a1⊗b1)))
59+
# #return Operator(a1⊗b1, a2⊗b2, data)
60+
# data = kron(B.data, A.data)
61+
# data = reshape(data, map(dimension, (a1, a2, b1, b2)))
62+
# data = PermutedDimsArray(data, (1, 3, 2, 4))
63+
# data = reshape(data, map(dimension, (a1⊗b1, a2⊗b2)))
64+
# return Operator(a1⊗b1, a2⊗b2, data)
65+
#end
66+
67+
function super_tensor(A, B)
68+
all, alr = basis_l(basis_l(A)), basis_r(basis_l(A))
69+
arl, arr = basis_l(basis_r(A)), basis_r(basis_r(A))
70+
bll, blr = basis_l(basis_l(A)), basis_r(basis_l(A))
71+
brl, brr = basis_l(basis_r(A)), basis_r(basis_r(A))
5872
data = kron(B.data, A.data)
59-
data = reshape(data, map(dimension, (a1, a2, b1, b2)))
60-
data = PermutedDimsArray(data, (1, 3, 2, 4))
61-
data = reshape(data, map(dimension, (a1b1, a2b2)))
62-
return Operator(a1b1, a2b2, data)
73+
data = reshape(data, map(dimension, (all, bll, alr, blr, arl, brl, arr, brr)))
74+
data = PermutedDimsArray(data, (1, 3, 2, 4, 5, 6, 7, 8))
75+
data = reshape(data, map(dimension, (basis_l(A)basis_l(B), basis_r(A)basis_r(B))))
76+
return Operator(basis_l(A)basis_l(B), basis_r(A)basis_r(B), data)
6377
end
6478

6579
#function _sch(data, l1, l2, r1, r2)

test/test_pauli.jl

Lines changed: 57 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Zsop = sprepost(Z, dagger(Z))
2929
@test pauli(Y/sqrt(2)).data [0, 0, 1., 0]
3030
@test pauli(Z/sqrt(2)).data [0, 0, 0, 1.]
3131

32-
# Test that single qubit unitary Pauli channels are diagonal
32+
# Test that single qubit unitary channels are diagonal in Pauli transfer and chi
3333
@test pauli(Isop).data diagm([1, 1, 1, 1])
3434
@test pauli(Xsop).data diagm([1, 1, -1, -1])
3535
@test pauli(Ysop).data diagm([1, -1, 1, -1])
@@ -42,23 +42,29 @@ Zsop = sprepost(Z, dagger(Z))
4242
# Test Haddamard Clifford rules
4343
H = ( (spinup(bs)+spindown(bs))dagger(spinup(bs)) +
4444
(spinup(bs)-spindown(bs))dagger(spindown(bs)) )/sqrt(2)
45-
Hsop = sprepost(H, dagger(H))
46-
@test Hsop*I I
47-
@test Hsop*X Z
48-
@test Hsop*Y -Y
49-
@test Hsop*Z X
50-
@test pauli(Hsop)*I I
51-
@test pauli(Hsop)*X Z
52-
@test pauli(Hsop)*Y -Y
53-
@test pauli(Hsop)*Z X
54-
@test chi(Hsop)*I I
55-
@test chi(Hsop)*X Z
56-
@test chi(Hsop)*Y -Y
57-
@test chi(Hsop)*Z X
58-
@test pauli(Hsop).data diagm(0=>[1,0,-1,0], 2=>[0,1], -2=>[0,1])
59-
@test chi(Hsop).data diagm(0=>[0,1,0,1], 2=>[0,1], -2=>[0,1])
60-
61-
"""
45+
H_sop = sprepost(H, dagger(H))
46+
@test pauli(H_sop).data diagm(0=>[1,0,-1,0], 2=>[0,1], -2=>[0,1])
47+
@test chi(H_sop).data diagm(0=>[0,1,0,1], 2=>[0,1], -2=>[0,1])/2
48+
49+
for op in (H_sop, choi(H_sop), pauli(H_sop), chi(H_sop))
50+
@test op*I I
51+
@test op*X Z
52+
@test op*Y -Y
53+
@test op*Z X
54+
end
55+
56+
# Test equality and conversion of identity among all three bases.
57+
IDENT_sop = identitysuperoperator(bs^2)
58+
IDENT_chi = chi(IDENT_sop)
59+
IDENT_ptm = pauli(IDENT_sop)
60+
61+
@test IDENT_sop.data IDENT_ptm.data
62+
@test chi(IDENT_ptm) IDENT_chi
63+
@test super(IDENT_chi) IDENT_sop
64+
@test super(IDENT_ptm) IDENT_sop
65+
@test pauli(IDENT_sop) IDENT_ptm
66+
@test pauli(IDENT_chi) IDENT_ptm
67+
6268
# Test bit flip encoder isometry
6369
encoder_kraus = (tensor_pow(spinup(bs), 3) dagger(spinup(bs)) +
6470
tensor_pow(spindown(bs), 3) dagger(spindown(bs)))
@@ -69,73 +75,45 @@ for f1 in [super, choi, pauli, chi]
6975
@test f1(decoder_sup) dagger(f1(encoder_sup))
7076
for f2 in [super, choi, pauli, chi]
7177
@test super(f2(f1(encoder_sup))).data encoder_sup.data
72-
@test f2(decoder_sup)*f1(encoder_sup) ≈ dense(identitysuperoperator(bs))
78+
@test super(f2(decoder_sup)*f1(encoder_sup)) dense(identitysuperoperator(bs))
7379
end
7480
end
7581

76-
# Test conversion of unitary matrices to superoperators.
82+
# Test CZ and CNOT
7783
CZ = dm(spinup(bs))identityoperator(bs) + dm(spindown(bs))sigmaz(bs)
78-
CZ_sop = sprepost(CZ,dagger(CZ))
79-
80-
@test basis_l(CZ_sop) == basis_r(CZ_sop) == KetBraBasis(bs^2, bs^2)
81-
@test CZ_sop*(I⊗I) ≈ I⊗I
82-
@test CZ_sop*(Z⊗I) ≈ X⊗I
83-
@test CZ_sop*(I⊗Z) ≈ I⊗Z
84-
@test CZ_sop*(I⊗X) ≈ X⊗X
85-
86-
# Test conversion of superoperator to Pauli transfer matrix.
87-
CZ_ptm = pauli(CZ_sop)
88-
89-
# Test construction of dense Pauli transfer matrix
90-
@test_throws DimensionMismatch Operator(PauliBasis(2), PauliBasis(3), CZ_ptm.data)
91-
@test Operator(PauliBasis(2), PauliBasis(2), CZ_ptm.data) == CZ_ptm
92-
@test CZ_ptm*pauli(I⊗I) ≈ pauli(I⊗I)
93-
@test CZ_ptm*pauli(Z⊗I) ≈ pauli(X⊗I)
94-
@test CZ_ptm*pauli(I⊗Z) ≈ pauli(I⊗Z)
95-
@test CZ_ptm*pauli(I⊗X) ≈ pauli(X⊗X)
96-
97-
@test CZ_ptm ≈ pauli(chi(CZ_sop))
98-
"""
99-
10084
CNOT = dm(spinup(bs))identityoperator(bs) + dm(spindown(bs))sigmax(bs)
101-
CNOT_sop = sprepost(CNOT,dagger(CNOT))
102-
CNOT_choi = choi(CNOT_sop)
103-
CNOT_chi = chi(CNOT_sop)
104-
CNOT_ptm = pauli(CNOT_sop)
105-
106-
@test basis_l(CNOT_sop) == basis_r(CNOT_sop) == KetBraBasis(bs^2, bs^2)
107-
@test basis_l(CNOT_chi) == basis_r(CNOT_chi) == ChiBasis(2)
108-
@test basis_l(CNOT_ptm) == basis_r(CNOT_ptm) == PauliBasis(2)
109-
110-
@test all(isapprox.(imag.(CNOT_sop.data), 0))
111-
@test all(isapprox.(imag.(CNOT_chi.data), 0))
112-
@test all(isapprox.(imag.(CNOT_ptm.data), 0))
113-
114-
for op in (CNOT_sop, CNOT_choi, CNOT_chi, CNOT_ptm)
115-
@test op*(II) II
116-
@test op*(XI) XX
117-
@test op*(ZI) ZI
118-
@test op*(IX) IX
119-
@test op*(IZ) ZZ
85+
CZ_rules = [(II, II), (XI, XZ), (ZI, ZI), (IX, IZ), (IZ, XZ)]
86+
CNOT_rules = [(II, II), (XI, XX), (ZI, ZI), (IX, IX), (IZ, ZZ)]
87+
88+
#for (gate, rules) in [(CZ, CZ_rules), (CNOT, CNOT_rules)]
89+
for (gate, rules) in [(CNOT, CNOT_rules)]
90+
op_sop = sprepost(gate,dagger(gate))
91+
op_choi = choi(op_sop)
92+
op_ptm = pauli(op_sop)
93+
op_chi = chi(op_sop)
94+
95+
@test_throws DimensionMismatch Operator(PauliBasis(2), PauliBasis(3), op_ptm.data)
96+
@test_throws DimensionMismatch Operator(ChiBasis(bs^2, bs^2), ChiBasis(bs^3, bs^3), op_chi.data)
97+
@test Operator(PauliBasis(2), PauliBasis(2), op_ptm.data) == op_ptm
98+
@test Operator(ChiBasis(bs^2, bs^2), op_chi.data) == op_chi
99+
@test basis_l(op_sop) == basis_r(op_sop) == KetBraBasis(bs^2, bs^2)
100+
@test basis_l(op_choi) == basis_r(op_choi) == ChoiBasis(bs^2, bs^2)
101+
@test basis_l(op_chi) == basis_r(op_chi) == ChiBasis(2)
102+
@test basis_l(op_ptm) == basis_r(op_ptm) == PauliBasis(2)
103+
104+
@test all(isapprox.(imag.(op_sop.data), 0))
105+
@test all(isapprox.(imag.(op_choi.data), 0))
106+
@test all(isapprox.(imag.(op_ptm.data), 0; atol=1e-26))
107+
@test dagger(op_chi) op_chi
108+
109+
for (lhs, rhs) in rules
110+
@test op_ptm*pauli(lhs) pauli(rhs)
111+
for op in (op_sop, op_choi, op_chi, op_ptm)
112+
@test op*lhs rhs
113+
end
114+
end
120115
end
121116

122-
# Test construction of chi matrix
123-
@test_throws DimensionMismatch Operator(ChiBasis(bs^2, bs^2), ChiBasis(bs^3, bs^3), CNOT_chi.data)
124-
@test Operator(ChiBasis(bs^2, bs^2), CNOT_chi.data) == CNOT_chi
125-
126-
# Test equality and conversion of identity among all three bases.
127-
IDENT_sop = identitysuperoperator(bs^2)
128-
IDENT_chi = chi(IDENT_sop)
129-
IDENT_ptm = pauli(IDENT_sop)
130-
131-
@test IDENT_sop.data IDENT_ptm.data
132-
@test chi(IDENT_ptm).data choi(IDENT_sop).data
133-
@test chi(IDENT_ptm) IDENT_chi
134-
@test super(IDENT_chi) IDENT_sop
135-
@test super(IDENT_ptm) IDENT_sop
136-
@test pauli(IDENT_sop) IDENT_ptm
137-
@test pauli(IDENT_chi) IDENT_ptm
138-
139117
# Test approximate equality and conversion among all three bases.
140118
cphase(θ) = dm(spinup(bs))identityoperator(bs) +
141119
dm(spindown(bs))(spindown(bs)spindown(bs)' + exp(1im*θ)spindown(bs)spindown(bs)')
@@ -152,6 +130,7 @@ CPHASE_ptm = pauli(CPHASE_sop)
152130
@test isapprox(pauli(CPHASE_chi), CPHASE_ptm)
153131

154132
# Test composition.
133+
CNOT_sop = sprepost(CNOT,dagger(CNOT))
155134
@test isapprox(chi(CPHASE_sop) * chi(CNOT_sop), chi(CPHASE_sop * CNOT_sop))
156135
@test isapprox(pauli(CPHASE_sop) * pauli(CNOT_sop), pauli(CPHASE_sop * CNOT_sop))
157136

test/test_superoperators.jl

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,68 +28,68 @@ s1 = SparseOperator(KetBraBasis(b1, b2), KetBraBasis(b3, b4))
2828
s2 = SparseOperator(KetBraBasis(b3, b4), KetBraBasis(b1, b2))
2929

3030
x = d1*d2
31-
@test isa(x, DenseSuperOpType)
31+
@test isa(x, DenseOpType)
3232
@test x.basis_l == x.basis_r == KetBraBasis(b1, b2)
3333

3434
x = s1*s2
35-
@test isa(x, SparseSuperOpType)
35+
@test isa(x, SparseOpType)
3636
@test x.basis_l == x.basis_r == KetBraBasis(b1, b2)
3737

3838
x = d1*s2
39-
@test isa(x, DenseSuperOpType)
39+
@test isa(x, DenseOpType)
4040
@test x.basis_l == x.basis_r == KetBraBasis(b1, b2)
4141

4242
x = s1*d2
43-
@test isa(x, DenseSuperOpType)
43+
@test isa(x, DenseOpType)
4444
@test x.basis_l == x.basis_r == KetBraBasis(b1, b2)
4545

4646
x = d1*3
47-
@test isa(x, DenseSuperOpType)
47+
@test isa(x, DenseOpType)
4848
@test x.basis_l == KetBraBasis(b1, b2)
4949
@test x.basis_r == KetBraBasis(b3, b4)
5050

5151
x = 2.5*s1
52-
@test isa(x, SparseSuperOpType)
52+
@test isa(x, SparseOpType)
5353
@test x.basis_l == KetBraBasis(b1, b2)
5454
@test x.basis_r == KetBraBasis(b3, b4)
5555

5656
x = d1 + d1
57-
@test isa(x, DenseSuperOpType)
57+
@test isa(x, DenseOpType)
5858
@test x.basis_l == KetBraBasis(b1, b2)
5959
@test x.basis_r == KetBraBasis(b3, b4)
6060

6161
x = s1 + s1
62-
@test isa(x, SparseSuperOpType)
62+
@test isa(x, SparseOpType)
6363
@test x.basis_l == KetBraBasis(b1, b2)
6464
@test x.basis_r == KetBraBasis(b3, b4)
6565

6666
x = d1 + s1
67-
@test isa(x, DenseSuperOpType)
67+
@test isa(x, DenseOpType)
6868
@test x.basis_l == KetBraBasis(b1, b2)
6969
@test x.basis_r == KetBraBasis(b3, b4)
7070

7171
x = d1 - d1
72-
@test isa(x, DenseSuperOpType)
72+
@test isa(x, DenseOpType)
7373
@test x.basis_l == KetBraBasis(b1, b2)
7474
@test x.basis_r == KetBraBasis(b3, b4)
7575

7676
x = s1 - s1
77-
@test isa(x, SparseSuperOpType)
77+
@test isa(x, SparseOpType)
7878
@test x.basis_l == KetBraBasis(b1, b2)
7979
@test x.basis_r == KetBraBasis(b3, b4)
8080

8181
x = d1 - s1
82-
@test isa(x, DenseSuperOpType)
82+
@test isa(x, DenseOpType)
8383
@test x.basis_l == KetBraBasis(b1, b2)
8484
@test x.basis_r == KetBraBasis(b3, b4)
8585

8686
x = -d1
87-
@test isa(x, DenseSuperOpType)
87+
@test isa(x, DenseOpType)
8888
@test x.basis_l == KetBraBasis(b1, b2)
8989
@test x.basis_r == KetBraBasis(b3, b4)
9090

9191
x = -s1
92-
@test isa(x, SparseSuperOpType)
92+
@test isa(x, SparseOpType)
9393
@test x.basis_l == KetBraBasis(b1, b2)
9494
@test x.basis_r == KetBraBasis(b3, b4)
9595

@@ -203,7 +203,7 @@ Ldense_ = dense(L_)
203203
Ldense .+= Ldense
204204
@test Ldense == 2*Ldense_
205205
Ldense .+= L
206-
@test isa(Ldense, DenseSuperOpType)
206+
@test isa(Ldense, DenseOpType)
207207
@test isapprox(Ldense.data, 5*Ldense_.data)
208208

209209
b = FockBasis(20)
@@ -221,7 +221,7 @@ N = exp(log(2) * sparse(L)) # 50% loss channel
221221
# Testing 0-2-4 binomial code encoder
222222
b_logical = SpinBasis(1//2)
223223
b_fock = FockBasis(5)
224-
z_l = normalize(fockstate(b_fock, 0) + fockstate(b_fock, 4))
224+
z_l = normalize(fockstate(b_fock, 0) + 1im*fockstate(b_fock, 4))
225225
o_l = fockstate(b_fock, 2)
226226
encoder_kraus = z_l dagger(spinup(b_logical)) + o_l dagger(spindown(b_logical))
227227
encoder_sup = sprepost(encoder_kraus, dagger(encoder_kraus))

0 commit comments

Comments
 (0)