Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial implementation of naive_encoding_circuit #184

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions src/ecc/ECC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module ECC

using QuantumClifford
using QuantumClifford: AbstractOperation
using LinearAlgebra
using Nemo
import QuantumClifford: Stabilizer, MixedDestabilizer

abstract type AbstractECC end
Expand Down Expand Up @@ -397,5 +399,200 @@ end
include("./bitflipcode.jl")
include("./shorcode.jl")
include("./steanecode.jl")
include("./cleavecode.jl")
include("./fiveonethreecode.jl")
include("./fivetwotwocode.jl")

function canonicalize_cleve97(checks::Stabilizer)
d, n = size(checks)
X0 = (checks |> stab_to_gf2)[:,1:n]'
Z0 = (checks |> stab_to_gf2)[:,n+1:2n]'

# Now let's work on getting X1 and Z1
Z2field = Nemo.ResidueRing(ZZ, 2)
b = rank(Nemo.matrix(Z2field, X0))

r = d-b
k = n-d

# First let's move the 0 columns to the left:
nullColumns = []
notNullColumns = []
for j in 1:d
if count(X0[:,j])==0 # TODO make sure this is condition -> null generator
push!(nullColumns, j)
else
push!(notNullColumns, j)
end
end

# Reorder the generators/columns so 0 vectors are in front of X0:
column_order = vcat(nullColumns, notNullColumns)
X0_5 = X0[:, column_order]
Z0_5 = Z0[:, column_order]

# Second let's perform Gaussian elimination to arrive at X1 and Z1
bank = []
for j in (r+1):(r+b)
i = 1
STOP = false
while !STOP
if X0_5[i, j] != 1
i+=1
if i > n
print("ERROR")
STOP = true
end
else
STOP = true
end
end
push!(bank, i)
for a in (r+1):(r+b)
if a == j
continue
end
if X0_5[i,a] == 1
X0_5[:,a] = (X0_5[:,j]+X0_5[:,a]).%2
Z0_5[:,a] = (Z0_5[:,j]+Z0_5[:,a]).%2
end
end
end

qubit_order = []
for i in 1:n
if i ∉ bank
push!(qubit_order, i)
end
end
append!(qubit_order, bank)
X1 = X0_5[qubit_order, :]
Z1 = Z0_5[qubit_order, :]
println("Qubit order 1", qubit_order)
checks = checks[:, qubit_order]

# Now begins the march towards X2 and Z2, starting with B'
r1 = rank(Nemo.matrix(Z2field, Z1[1:r+k,1:r]))
r2 = r - r1

# First let's move the 0 columns of B to the left:
nullColumns = []
notNullColumns = []
for j in 1:r
if count(Z1[:,j])==0 # TODO make sure this is condition <-> null generator
push!(nullColumns, j)
else
push!(notNullColumns, j)
end
end
for j in r+1:d
push!(notNullColumns, j)
end

# Reorder the generators/columns so 0 vectors are in front of B:
column_order = vcat(nullColumns, notNullColumns)
Z1_5 = Z1[:, column_order]

# Now Gaussian elimination again, this time over B'
bank = []
for j in (r2+1):(r2+r1)
i = 1
STOP = false
while !STOP
if Z1_5[i, j] != 1
i+=1
if i > n
print("ERROR")
STOP = true
end
else
STOP = true
end
end
push!(bank, i)
for a in (r2+1):(r2+r1)
if a == j
continue
end
if Z1_5[i,a] == 1
Z1_5[:,a] = (Z1_5[:,j]+Z1_5[:,a]).%2
end
end
end

qubit_order = []
for i in 1:n
if i ∉ bank && i<= k+r
push!(qubit_order, i)
end
end
for i in k+r+1:n # rows not in B
push!(bank, i)
end
append!(qubit_order, bank)
Z2 = Z1_5[qubit_order, :]
X2 = X1[qubit_order, :] # X is unchanged by operations on b, except for reindexing of qubits
println("Qubit order 2", qubit_order)
checks = checks[:, qubit_order]

# Now time for the final steps before arriving at Xstar Zstar
B1 = Z2[1:k,1+r2:r2+r1]

XI = zeros(Bool, k , k)
for i in 1:k
XI[i,i] = 1
end
Xs = (vcat(XI, zeros(Bool,r2, k), B1', zeros(Bool, b, k)))
Zs = zeros(Bool, n, k)

println("k, r2, r1, b: ", k, " ", r2, " ", r1, " ", b)
Xstar = hcat(Xs,X2)
Zstar = hcat(Zs,Z2)

#return X0, X0_5, X1, X2, Xstar, Z0, Z0_5, Z1, Z1_5, Z2, Zstar
return Xstar, Zstar, Stabilizer(X2', Z2')# TODO Return reordered checks or Stab(X2', Z2')?
end

""" The naive implementation of the encoding circuit by arXiv:quant-ph/9607030 """
function naive_encoding_circuit(checks::Stabilizer)
d, n = size(checks)
X0 = (checks |> stab_to_gf2)[:,1:n]'

Z2field = Nemo.ResidueRing(ZZ, 2)
b = rank(Nemo.matrix(Z2field, X0))

r = d-b
k = n-d

Xstar, Zstar, standard_tab = canonicalize_cleve97(checks)

naive_ec = AbstractOperation[]
for i in (r+k+1):(r+k+b)
push!(naive_ec, sHadamard(i))
end

for j in 1:n
if count(Xstar[:,j]) == 0 # Secondary generators are ignored
continue
end
if Zstar[j,j]==1
push!(naive_ec, sZ(j))
end
for i in 1:n
if i == j
continue
end
if Xstar[i,j] == 1 && Zstar[i,j] == 0
push!(naive_ec, sZCX(j,i))
elseif Xstar[i,j] == 0 && Zstar[i,j] == 1
push!(naive_ec, sZCZ(j,i))
elseif Xstar[i,j] == 1 && Zstar[i,j] == 1
push!(naive_ec, sZCY(j,i))
end
end
end

return naive_ec, standard_tab
end

end #module
55 changes: 55 additions & 0 deletions src/ecc/cleavecode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""A pedagogical example of a quantum error correcting [8,3] code used in [cleve1997efficient](@cite)."""
struct Cleve8 <: AbstractECC end

code_n(c::Cleve8) = 8
code_k(c::Cleve8) = 3

parity_checks(c::Cleve8) = S"XXXXXXXX
ZZZZZZZZ
XIXIZYZY
XIYZXIYZ
XZIYIYXZ"

function encoding_circuit(c::Cleve8)
c1 = sCNOT(1,4)
c2 = sCNOT(2,4)
c3 = sCNOT(3,4)
h1 = sHadamard(5)
z1 = sZ(5)
h2 = sHadamard(6)
h3 = sHadamard(7)
z3 = sZ(7)
h4 = sHadamard(8)
z4 = sZ(8)
first_part = [c1,c2,c3,h1,z1,h2,h3,z3,h4,z4]

c1 = sZCX(5, 1)
c2 = sZCX(5, 2)
c3 = sZCY(5, 3)
c4 = sZCZ(5, 4)
c5 = sZCZ(5, 6)
column1 = [c1,c2,c3,c4,c5] # 1st non null column of Zstar

c1 = sZCX(6, 1)
c2 = sZCY(6, 2)
c3 = sZCY(6, 4)
c4 = sZCZ(6, 5)
c5 = sZCZ(6, 7)
column2 = [c1,c2,c3,c4,c5]

c1 = sZCX(7, 1)
c2 = sZCY(7, 3)
c3 = sZCX(7, 4)
c4 = sZCZ(7, 5)
c5 = sZCZ(7, 8)
column3 = [c1,c2,c3,c4,c5]

c1 = sZCY(8, 2)
c2 = sZCX(8, 3)
c3 = sZCX(8, 4)
c4 = sZCZ(8, 5)
c5 = sZCZ(8, 6)
column4 = [c1,c2,c3,c4,c5]

return vcat(first_part, column1, column2, column3, column4)
end
9 changes: 9 additions & 0 deletions src/ecc/fiveonethreecode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""http://www.codetables.de/QECC.php?q=4&n=5&k=1"""
struct FiveOneThree <: AbstractECC end

code_n(c::FiveOneThree) = 8

parity_checks(c::FiveOneThree) = S"YIZXY
ZXIZY
ZIXYZ
IZZZZ"
8 changes: 8 additions & 0 deletions src/ecc/fivetwotwocode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""http://www.codetables.de/QECC.php?q=4&n=5&k=2"""
struct FiveTwoTwo <: AbstractECC end

code_n(c::FiveTwoTwo) = 8

parity_checks(c::FiveTwoTwo) = S"XXXXI
IIIIX
ZZZZI"