QuantumSavory / QuantumClifford.jl

Clifford circuits, graph states, and other quantum Stabilizer formalism tools.
MIT License
103 stars 42 forks source link

Type conversion error in TableDecoder #291

Closed royess closed 2 weeks ago

royess commented 2 weeks ago

I want to report a type conversion bug in TableDecoder.

It should be reproduced by:

using QuantumClifford
using QuantumClifford.ECC
import QuantumClifford.ECC: parity_checks, code_k, code_n

struct TestCode end

parity_checks(c::TestCode) = S"""
+ XY__Z_ZZXY_XXYXYX_ZZ
- ZXYZY_X____YZZ_YXZZY
- Y_X__X_Y_Y_ZYYX__Z_Z
+ YZ__XY_X_____Y_XYZ__
+ XZYYYY_ZX_XYZ___YYZX
+ XXXXY__ZZZY_YYYZXZXZ
- X_ZXYXXZ_ZZXZYXZYYYX
+ XXYYYZZYZY_ZY__XZZYY
+ Y_YYXYZZ____XYZ__YY_
- X_ZYZXXY_XZ_XY__XXZX
+ XYY_YYZZ_Z__XZ___XY_
- X_ZXZ_YZZ_ZZZYY_Z_XX
- YYZ__X_Z_Z_YX_XY__ZY
- _YXZXZYZYYZ_ZYX__XZ_
+ _XXX_YYXXZZ_YY_ZZXYZ
- YXXZXZ_X_Z_XZZ_ZZXZX
- XZXXZ___XYXXYXXZZXY_
- Z_XYYYZY_XYZZXXXZYXZ
- XZX_X_Y_Z_ZXYX_Y_X_Z
"""

code_n(c::TestCode) = 20
code_k(c::TestCode) = 1

c = TestCode()

# check it is a valid code
for ps1 in parity_checks(c)
    for ps2 in parity_checks(c)
        @assert comm(ps1, ps2) == 0x0
    end
end

noise = 0.001

d = TableDecoder
s = ShorSyndromeECCSetup(noise, 0)

e = evaluate_decoder(d(c), s, 100000)

The error reads:

ERROR: LoadError: MethodError: Cannot `convert` an object of type 
  ClassicalXOR{17} to an object of type 
  Union{SumTypes.Variant{Symbol("QuantumClifford.sHadamard"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sId1"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sInvPhase"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sPhase"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sX"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sY"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sZ"), (:_1,), Tuple{Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sCNOT"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sCPHASE"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sSWAP"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sXCX"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sXCY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sXCZ"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sYCX"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sYCY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sYCZ"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sZCX"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sZCY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sZCZ"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sZCrY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMX"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMZ"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMRX"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMRY"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.sMRZ"), (:_1, :_2), Tuple{Int64, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{2}"), (:_1, :_2), Tuple{Tuple{Int64, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{3}"), (:_1, :_2), Tuple{Tuple{Int64, Int64, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{4}"), (:_1, :_2), Tuple{NTuple{4, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{5}"), (:_1, :_2), Tuple{NTuple{5, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{6}"), (:_1, :_2), Tuple{NTuple{6, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{7}"), (:_1, :_2), Tuple{NTuple{7, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{8}"), (:_1, :_2), Tuple{NTuple{8, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{9}"), (:_1, :_2), Tuple{NTuple{9, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{10}"), (:_1, :_2), Tuple{NTuple{10, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{11}"), (:_1, :_2), Tuple{NTuple{11, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{12}"), (:_1, :_2), Tuple{NTuple{12, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{13}"), (:_1, :_2), Tuple{NTuple{13, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{14}"), (:_1, :_2), Tuple{NTuple{14, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{15}"), (:_1, :_2), Tuple{NTuple{15, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.ClassicalXOR{16}"), (:_1, :_2), Tuple{NTuple{16, Int64}, Int64}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 1)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, Tuple{Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 2)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, Tuple{Int64, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 3)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, Tuple{Int64, Int64, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 4)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, NTuple{4, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 5)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, NTuple{5, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 6)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, NTuple{6, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 7)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, NTuple{7, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOp{(QuantumClifford.UnbiasedUncorrelatedNoise{Float64}, 8)}"), (:_1, :_2), Tuple{UnbiasedUncorrelatedNoise{Float64}, NTuple{8, Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.SingleQubitOperator"), (:_1, :_2, :_3, :_4, :_5, :_6, :_7), Tuple{Int64, Vararg{Bool, 6}}}, SumTypes.Variant{Symbol("QuantumClifford.NoiseOpAll"), (:_1,), Tuple{QuantumClifford.AbstractNoise}}, SumTypes.Variant{Symbol("QuantumClifford.VerifyOp"), (:_1, :_2), Tuple{Stabilizer, AbstractVector{Int64}}}, SumTypes.Variant{Symbol("QuantumClifford.BellMeasurement"), (:_1, :_2), Tuple{Vector{Union{sMX, sMY, sMZ}}, Bool}}, SumTypes.Variant{Symbol("QuantumClifford.NoisyGate"), (:_1, :_2), Tuple{QuantumClifford.AbstractOperation, QuantumClifford.AbstractNoise}}}

Closest candidates are:
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:84

Stacktrace:
  [1] QuantumClifford.CompactifiedGate(data::ClassicalXOR{17})
    @ QuantumClifford ./none:0
  [2] _broadcast_getindex_evalf
    @ ./broadcast.jl:709 [inlined]
  [3] _broadcast_getindex
    @ ./broadcast.jl:682 [inlined]
  [4] getindex
    @ ./broadcast.jl:636 [inlined]
  [5] macro expansion
    @ ./broadcast.jl:1004 [inlined]
  [6] macro expansion
    @ ./simdloop.jl:77 [inlined]
  [7] copyto!
    @ ./broadcast.jl:1003 [inlined]
  [8] copyto!
    @ ./broadcast.jl:956 [inlined]
  [9] copy
    @ ./broadcast.jl:928 [inlined]
 [10] materialize
    @ ./broadcast.jl:903 [inlined]
 [11] compactify_circuit(circuit::Vector{QuantumClifford.AbstractOperation})
    @ QuantumClifford ~/Documents/Repos/QuantumClifford.jl/src/sumtypes.jl:207
 [12] _pftrajectories(circuit::Vector{QuantumClifford.AbstractOperation}; trajectories::Int64, threads::Bool)
    @ QuantumClifford ~/Documents/Repos/QuantumClifford.jl/src/pauli_frames.jl:178
 [13] _pftrajectories
    @ ~/Documents/Repos/QuantumClifford.jl/src/pauli_frames.jl:174 [inlined]
 [14] #pftrajectories#192
    @ ~/Documents/Repos/QuantumClifford.jl/src/pauli_frames.jl:165 [inlined]
 [15] pftrajectories
    @ ~/Documents/Repos/QuantumClifford.jl/src/pauli_frames.jl:164 [inlined]
 [16] evaluate_decoder(d::TableDecoder, nsamples::Int64, circuit::Vector{QuantumClifford.AbstractOperation}, syndrome_bits::UnitRange{Int64}, logical_bits::UnitRange{Int64}, faults_submatrix::BitMatrix)
    @ QuantumClifford.ECC ~/Documents/Repos/QuantumClifford.jl/src/ecc/decoder_pipeline.jl:164
 [17] evaluate_decoder(d::TableDecoder, setup::ShorSyndromeECCSetup, nsamples::Int64)
    @ QuantumClifford.ECC ~/Documents/Repos/QuantumClifford.jl/src/ecc/decoder_pipeline.jl:142
 [18] top-level scope
    @ ~/Documents/Repos/qecc-devlog/reproduce_decoding_bug.jl:46
in expression starting at /home/yuxuan/Documents/Repos/qecc-devlog/reproduce_decoding_bug.jl:46

It seems that a classical XOR operation is compactified when doing Pauli frame simulation, which is not properly handled.

The code I use is a random Clifford circuit code, which triggers this error randomly but with a high probability.

The error seems related to the number of qubits. During my tests, smaller codes of 10 qubits, constructed similarly, have not triggered the error.

royess commented 2 weeks ago

@Benzillaist @Krastanov, I would appreciate your help with this.