Skip to content

Commit

Permalink
Merge pull request #40 from nzy1997/clifford_tab
Browse files Browse the repository at this point in the history
Clifford tableaux method
  • Loading branch information
nzy1997 authored Dec 9, 2024
2 parents d083f62 + 52e0b4e commit cd45d66
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 4 deletions.
9 changes: 7 additions & 2 deletions src/TensorQEC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ using LuxorGraphPlot
export pauli_basis, pauli_decomposition, pauli_mapping
import Yao.YaoArrayRegister.StaticArrays: SizedVector
import Yao.YaoArrayRegister.LuxurySparse
export arrayreg2sumofpaulis

# Mod
export Mod2
Expand All @@ -46,7 +47,7 @@ export measure_circuit_fault_tol, measure_circuit_steane,measure_circuit, measu
export make_table, save_table, load_table,correct_circuit,show_table,TruthTable,table_inference

# clifford group
export pauli_group, clifford_group, clifford_simulate,to_perm_matrix,perm_of_paulistring,paulistring_annotate,annotate_history,annotate_circuit_pics
export pauli_group, clifford_group, clifford_simulate,to_perm_matrix,perm_of_paulistring,paulistring_annotate,annotate_history,annotate_circuit_pics,perm_of_pauligroup

# simulation
export ComplexConj, SymbolRecorder,IdentityRecorder, ein_circ, QCInfo, qc2enisum
Expand All @@ -56,6 +57,9 @@ export coherent_error_unitary, error_quantum_circuit,toput, error_pairs,fidelity
export SimpleTannerGraph,sydrome_extraction,product_graph,CSSTannerGraph,plot_graph,dual_graph,get_graph,belief_propagation,random_ldpc,random_error_qubits,check_decode, check_linear_indepent,ldpc2tensor
export tensor_infer,osd,mod2matrix_inverse,bp_osd,tensor_osd

# tableaux
export Tableau, new_tableau,tableau_simulate

@const_gate CCZ::ComplexF64 = diagm([1, 1,1,1,1,1,1,-1])

include("mod2.jl")
Expand All @@ -67,7 +71,8 @@ include("codes.jl")
include("encoder.jl")
include("inferences.jl")
include("measurement.jl")
include("tablemake.jl")
include("tablemake.jl")
include("simulation.jl")
include("ldpc.jl")
include("tableaux.jl")
end
8 changes: 7 additions & 1 deletion src/cliffordgroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ struct CliffordTable{N, Ti}
end

"""
perm_of_paulistring(pm::PermMatrix, ps::PauliString, pos::Vector{Int})
perm_of_paulistring(ps::PauliString, operation::Pair{Vector{Int}, <:PermMatrix})
Map the Pauli string `ps` by a permutation matrix `pm`. Return the mapped Pauli string and the phase factor.
Expand All @@ -99,6 +99,12 @@ function perm_of_paulistring(ps::PauliString, operation::Pair{Vector{Int}, <:Per
v[pos]=[mod(div(pm.perm[ps_perm_num]-1, 4^(j-1)), 4)+1 for j in 1:length(pos)]
return PauliString(v...), pm.vals[ps_perm_num]
end
_complex2int(x) = x==1+0im ? 0 : x==0+1im ? 1 : x==-1+0im ? 2 : 3
function perm_of_pauligroup(pg::PauliGroup, operation::Pair{Vector{Int}, <:PermMatrix})
ps, val = perm_of_paulistring(pg.ps, operation)

return PauliGroup(_mul_coeff(pg.coeff,_complex2int(val)), ps)
end

"""
CliffordSimulateResult{N}
Expand Down
5 changes: 5 additions & 0 deletions src/codes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ function stabilizers(::Code832)
return pauli_string
end

"""
Code422
Construct a [[4,2,2]] CSS code instance.
"""
struct Code422 end

function stabilizers(::Code422)
Expand Down
2 changes: 1 addition & 1 deletion src/paulistring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function tensor2sumofpaulis(t::AbstractArray)
return SumOfPaulis([t[ci]=>PauliString(ci.I) for ci in CartesianIndices(t)] |> vec)
end
densitymatrix2sumofpaulis(dm::DensityMatrix) = tensor2sumofpaulis(real.(pauli_decomposition(dm.state)))

arrayreg2sumofpaulis(reg::ArrayReg) = densitymatrix2sumofpaulis(density_matrix(reg))
# inputs:
# - n is the size of the toric code
# - k is the Pauli operator, 1 for I, 2 for X, 3 for Y, 4 for Z
Expand Down
60 changes: 60 additions & 0 deletions src/tableaux.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
struct Tableau{N}
tabx::Vector{PauliGroup{N}}
tabz::Vector{PauliGroup{N}}
end

function new_tableau(n::Int)
return Tableau([PauliGroup(0,paulistring(n,2,i)) for i in 1:n], [PauliGroup(0,paulistring(n,4,i)) for i in 1:n])
end

Base.show(io::IO, ::MIME"text/plain", tab::Tableau) = show(io, tab)
function Base.show(io::IO, tab::Tableau{N}) where {N}
for i in 1:N
print(io, "X$(i): ", tab.tabx[i], "\n")
end
for i in 1:N
print(io, "Z$(i): ", tab.tabz[i], "\n")
end
end


function tableau_simulate(tab::Tableau{N}, operation::Pair{Vector{Int}, <:PermMatrix}) where N
return Tableau([perm_of_pauligroup(tab.tabx[i], operation) for i in 1:N], [perm_of_pauligroup(tab.tabz[i], operation) for i in 1:N])
end

function tableau_simulate(tab::Tableau{N}, qc::ChainBlock) where N
qc = simplify(qc; rules=[to_basictypes, Optimise.eliminate_nested])
gatedict=Dict{UInt64, PermMatrix}()
for _gate in qc
gate = toput(_gate)
key = hash(gate.content)
if haskey(gatedict, key)
tab = tableau_simulate(tab, collect(gate.locs)=>gatedict[key])
else
pm = to_perm_matrix(Int8, UInt8, pauli_repr(mat(gate.content)))
push!(gatedict, key => pm)
tab = tableau_simulate(tab, collect(gate.locs)=>pm)
end
end
return tab
end
function tableau_simulate(qc::ChainBlock)
tab = new_tableau(nqubits(qc))
return tableau_simulate(tab, qc)
end
function tableau_simulate(ps::PauliString{N}, qc::ChainBlock) where N
tab = tableau_simulate(qc)
res = PauliGroup{N}(0, paulistring(N, 1,1))
count = 0
for i in 1:N
if ps.ids[i] == 2
res *= tab.tabx[i]
elseif ps.ids[i] == 4
res *= tab.tabz[i]
elseif ps.ids[i] == 3
res *= tab.tabx[i] * tab.tabz[i]
count += 1
end
end
return PauliGroup{N}(_mul_coeff(res.coeff,count), res.ps)
end
11 changes: 11 additions & 0 deletions test/cliffordgroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ end
@test ps2.ids == (2, 3, 2, 2)
end

@testset "perm_of_pauligroup" begin
ps = PauliString(2,3,4,3,2,1)
pg = PauliGroup(1, ps)
pm = TensorQEC.to_perm_matrix(Int8, Int, pauli_repr(ConstGate.CNOT))

pg2 = perm_of_pauligroup(pg, [2, 3]=>pm)
ps2, val = perm_of_paulistring(ps, [2, 3]=>pm)
@test pg2 == PauliGroup(1, ps2)
end

@testset "clifford_simulate" begin
qc = chain(put(5, 1 => H), control(5, 1, 2 => Z), control(5, 3, 4 => X), control(5, 5, 3 => X), put(5, 1 => X))
ps = PauliString((4, 3, 1, 3, 2))
Expand All @@ -68,3 +78,4 @@ end

annotate_circuit_pics(res)
end

12 changes: 12 additions & 0 deletions test/paulibasis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ end
@test mat(sp) dm.state
end

@testset "arrayreg2sumofpaulis" begin
reg = rand_state(3)
dm = density_matrix(reg)
sp1 = arrayreg2sumofpaulis(reg)
@test mat(sp1) dm.state

reg = ghz_state(3)
dm = density_matrix(reg)
sp2 = arrayreg2sumofpaulis(reg)
@test mat(sp2) dm.state
end

@testset "pauli_string_map" begin
ps = PauliString(2,3,4,3,2,1)
@test TensorQEC.pauli_string_map(ps, pauli_mapping(mat(ComplexF64,cnot(2,1,2))), [5,6]).ids ==(2,3,4,3,2,2)
Expand Down
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ end

@testset "ldpc" begin
include("ldpc.jl")
end

@testset "tableau" begin
include("tableaux.jl")
end
31 changes: 31 additions & 0 deletions test/tableaux.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Test, TensorQEC, TensorQEC.Yao, TensorQEC.LinearAlgebra

@testset "new_tableau" begin
tab2 = new_tableau(2)
@test getfield.(tab2.tabx,:ps) == [paulistring(2,2,1), paulistring(2,2,2)]
@test getfield.(tab2.tabz,:ps) == [paulistring(2,4,1), paulistring(2,4,2)]

tab3 = new_tableau(3)
@test getfield.(tab3.tabx,:ps) == [paulistring(3,2,1), paulistring(3,2,2), paulistring(3,2,3)]
@test getfield.(tab3.tabz,:ps) == [paulistring(3,4,1), paulistring(3,4,2), paulistring(3,4,3)]
@show tab3
end

@testset "tableau_simulate" begin
tab = new_tableau(2)
tab2 = tableau_simulate(tab, [1]=>to_perm_matrix(Int8, Int, TensorQEC.pauli_repr(H)))
@test getfield.(tab2.tabx,:ps) == [paulistring(2,4,1), paulistring(2,2,2)]
@test getfield.(tab2.tabz,:ps) == [paulistring(2,2,1), paulistring(2,4,2)]

tab = new_tableau(3)
tab2 = tableau_simulate(tab, [1,3]=>to_perm_matrix(Int8, Int, TensorQEC.pauli_repr(ConstGate.CNOT)))
@test getfield.(tab2.tabx,:ps) == [paulistring(3,2,(1,3)), paulistring(3,2,2), paulistring(3,2,3)]
@test getfield.(tab2.tabz,:ps) == [paulistring(3,4,(1)), paulistring(3,4,2), paulistring(3,4,(1,3))]

qc = chain(put(5, 1 => H), control(5, 1, 2 => Z), control(5, 3, 4 => X), control(5, 5, 3 => X), put(5, 1 => X))
ps = PauliString((4, 3, 1, 3, 2))
res = clifford_simulate(ps, qc)
res2 = tableau_simulate(ps, qc)
@test res.output == res2.ps
@test res.phase == im^res2.coeff
end

0 comments on commit cd45d66

Please sign in to comment.