Skip to content

Commit

Permalink
breaking changes to the probability conventions in UnbiasedUncorrelat…
Browse files Browse the repository at this point in the history
…edNoise
  • Loading branch information
Krastanov committed Mar 19, 2024
1 parent 0f9c370 commit 5c73f40
Show file tree
Hide file tree
Showing 11 changed files with 5,403 additions and 4,286 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@

- `permute` will be a wrapper around to `QuantumInterface.permutesubsystems`. Documentation for `permute!` would be similarly updated
- reworking the rest of `NoisyCircuits` and moving it out of `Experimental`
- `random_pauli(...; realphase=true)` should be the default

# News

## v0.9.0 - 2024-03-19

- **(breaking)** The defaults in `random_pauli` are now `realphase=true` and `nophase=true`.
- **(breaking)** The convention for for flip probability in `random_pauli`.
- **(breaking)** The convention for noise probability in `UnbiasedUncorrelatedNoise` changed. The input number is the total probability for an error to occur.
- Implement an inplace `random_pauli!`, a non-allocating alternative to `random_pauli`.
- Significant improvement in the performance of the ECC decoder pipeline (but many low-hanging fruits still remain).


## v0.8.21 - 2024-03-17

- Implemented the Gottesman code family, also known as [[2^j, 2^j - j - 2, 3]] quantum Hamming codes.
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumClifford"
uuid = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
authors = ["Stefan Krastanov <stefan@krastanov.org>"]
version = "0.8.21"
version = "0.9.0"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand Down
1,010 changes: 413 additions & 597 deletions docs/src/notebooks/Noisy_Circuits_Tutorial_with_Purification_Circuits.ipynb

Large diffs are not rendered by default.

2,487 changes: 1,291 additions & 1,196 deletions docs/src/notebooks/Perturbative_Expansions_vs_Monte_Carlo_Simulations.ipynb

Large diffs are not rendered by default.

5,784 changes: 3,489 additions & 2,295 deletions docs/src/notebooks/Stabilizer_Codes_Based_on_Random_Circuits.ipynb

Large diffs are not rendered by default.

362 changes: 181 additions & 181 deletions docs/src/notebooks/Symbolic_Perturbative_Expansions.ipynb

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions ext/QuantumCliffordGPUExt/apply_noise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using QuantumClifford: _div, _mod
#according to https://github.com/JuliaGPU/CUDA.jl/blob/ac1bc29a118e7be56d9edb084a4dea4224c1d707/test/core/device/random.jl#L33
#CUDA.jl supports calling rand() inside kernel
function applynoise!(frame::PauliFrameGPU{T},noise::UnbiasedUncorrelatedNoise,i::Int) where {T <: Unsigned}
p = noise.errprobthird
p = noise.p
lowbit = T(1)
ibig = _div(T,i-1)+1
ismall = _mod(T,i-1)
Expand All @@ -22,14 +22,15 @@ function applynoise_kernel(xzs::DeviceMatrix{Tme},
p::Real,
ibig::Int,
ismallm::Tme,
rows::Int) where {Tme <: Unsigned}
rows::Int) where {Tme <: Unsigned}

f = (blockIdx().x - 1) * blockDim().x + threadIdx().x;
if f > rows
return nothing
end

r = rand()
p = p/3
if r < p # X error
xzs[ibig,f] ⊻= ismallm
elseif r < 2p # Z error
Expand Down
13 changes: 7 additions & 6 deletions src/noise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,24 @@ function applynoise!(r::Register, n, indices::Base.AbstractVecOrTuple)
return r
end

"""Depolarization noise model with total probability of error `3*errprobthird`."""
"""Depolarization noise model with total probability of error `p`."""
struct UnbiasedUncorrelatedNoise{T} <: AbstractNoise
errprobthird::T
p::T
end
UnbiasedUncorrelatedNoise(p::Integer) = UnbiasedUncorrelatedNoise(float(p))

"""A convenient constructor for various types of Pauli noise models.
Returns more specific types when necessary."""
function PauliNoise end

"""Constructs an unbiased Pauli noise model with total probability of error `p`."""
function PauliNoise(p)
UnbiasedUncorrelatedNoise(p/3)
UnbiasedUncorrelatedNoise(p)
end

function applynoise!(s::AbstractStabilizer,noise::UnbiasedUncorrelatedNoise,i::Int)
n = nqubits(s)
infid = noise.errprobthird
infid = noise.p/3
r = rand()
if r<infid
apply_single_x!(s,i)
Expand Down Expand Up @@ -121,11 +122,11 @@ end
function applynoise_branches(s::AbstractStabilizer,noise::UnbiasedUncorrelatedNoise,indices; max_order=1)
n = nqubits(s)
l = length(indices)
infid = noise.errprobthird
infid = noise.p/3
if l==0
return [s,one(infid)]
end
error1 = 3*infid
error1 = noise.p
no_error1 = 1-error1
no_error = no_error1^l
results = [(copy(s),no_error,0)] # state, prob, order
Expand Down
3 changes: 2 additions & 1 deletion src/pauli_frames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ function apply!(frame::PauliFrame, op::sMRZ) # TODO sMRY, and faster sMRX
end

function applynoise!(frame::PauliFrame,noise::UnbiasedUncorrelatedNoise,i::Int)
p = noise.errprobthird
p = noise.p
T = eltype(frame.frame.tab.xzs)

lowbit = T(1)
ibig = _div(T,i-1)+1
ismall = _mod(T,i-1)
ismallm = lowbit<<(ismall)
p = p/3

@inbounds @simd for f in eachindex(frame)
r = rand()
Expand Down
2 changes: 1 addition & 1 deletion test/test_gpu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,6 @@ end
]).measurements
avg_result = to_cpu(sum(measurements, dims=1) / trajectories)
error_threshold = 0.02
approx(vec(avg_result), [0, .5, 2p, .5], error_threshold)
approx(vec(avg_result), [0, .5, 2p/3, .5], error_threshold)
end
end
11 changes: 6 additions & 5 deletions test/test_noisycircuits.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# TODO split in separate files
using Test
using Random
using QuantumClifford

Expand All @@ -12,7 +13,7 @@ import AbstractAlgebra
g2 = SparseGate(tCNOT, [2,3])
g3 = sCNOT(4,5)
g4 = sHadamard(6)
n = UnbiasedUncorrelatedNoise(1/3)
n = UnbiasedUncorrelatedNoise(1)
ng1 = NoisyGate(g1, n)
ng2 = NoisyGate(g2, n)
ng3 = NoisyGate(g3, n)
Expand All @@ -33,7 +34,7 @@ end
ZZ"
canonicalize_rref!(good_bell_state)
v = VerifyOp(good_bell_state,[1,2])
n = NoiseOpAll(UnbiasedUncorrelatedNoise(0.01))
n = NoiseOpAll(UnbiasedUncorrelatedNoise(0.03))
init = Register(MixedDestabilizer(good_bell_stategood_bell_state))
with_purification = mctrajectories(init, [n,g1,g2,m,v], trajectories=500)
@test with_purification[failure_stat] > 5
Expand Down Expand Up @@ -61,7 +62,7 @@ end
ZZ"
canonicalize_rref!(good_bell_state)
v = VerifyOp(good_bell_state,[1,2])
n = NoiseOpAll(UnbiasedUncorrelatedNoise(0.01))
n = NoiseOpAll(UnbiasedUncorrelatedNoise(0.03))
init = Register(MixedDestabilizer(good_bell_stategood_bell_state))
mc = mctrajectories(init, [n,g1,g2,m,v], trajectories=500)
pe = petrajectories(init, [n,g1,g2,m,v])
Expand All @@ -88,8 +89,8 @@ end
g2 = SparseGate(tCNOT, [2,4]) # CNOT between qubit 2 and qubit 4 (both with Bob)
m = BellMeasurement([sMX(3),sMX(4)]) # Bell measurement on qubit 3 and 4
v = VerifyOp(good_bell_state,[1,2]) # Verify that qubit 1 and 2 indeed form a good Bell pair
epsilon = e # The error rate
n = NoiseOpAll(UnbiasedUncorrelatedNoise(epsilon))
epsilon = e # The X or Y or Z error rate
n = NoiseOpAll(UnbiasedUncorrelatedNoise(3epsilon))
circuit = [n,g1,g2,m,v]
pe_symbolic = petrajectories(initial_state, circuit, branch_weight=unity) # perturbative expansion
@test pe_symbolic[false_success_stat] == -162.0*e^4 + 162.0*e^3 + -54.0*e^2 + 6.0*e
Expand Down

0 comments on commit 5c73f40

Please sign in to comment.