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

Added Testing for 3to1 purification #29

Merged
merged 15 commits into from
Aug 25, 2023
250 changes: 250 additions & 0 deletions src/CircuitZoo/CircuitZoo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,254 @@ function (circuit::Purify2to1)(purifiedL,purifiedR,sacrificedL,sacrificedR)
success
end

"""
$TYPEDEF

Fields:

$FIELDS

A purification circuit sacrificing 2 Bell pairs to produce another.
The circuit is parameterized by a `fixtwice` symbol argument
which specifies which of the three possible Pauli errors is fixed twice.
This purificaiton circuit is capable of detecting all errors.

If an error was detected, the circuit returns `false` and the state is reset.
If no error was detected, the circuit returns `true`.

The sacrificial qubits are removed from the register.

```jldoctest
julia> a = Register(2)
b = Register(2)
c = Register(2)
initalize!(a[1:2], bell)
initalize!(b[1:2], bell)
initalize!(c[1:2], bell)


julia> Purify3to1(:X)(a[1], a[2], [b[1], c[1]], [b[2], c[2]])
false
```

"""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty lines between docstrings and types

struct Purify3to1 <: AbstractCircuit
"""The error to be fixed twice"""
fixtwice::Symbol
function Purify3to1(fixtwice)
if fixtwice ∉ (:X, :Y, :Z)
throw(ArgumentError(lazy"""
`Purify3to1` can represent one of three purification circuits (see its docstring),
parameterized by the argument `fixtwice` which has to be one of `:X`, `:Y`, or `:Z`.
You have instead chosen `$(repr(fixtwice))` which is not a valid option.
Investigate where you are creating a purification circuit of type `Purify3to1`
and ensure you are passing a valid argument.

The `fixtwice` parameter represents the error that the putifying circuit will
'fix twice', meaning for example, for a fixtwice Y circuit (original double selection),
Purify3to1 will represent the succesive applying of a leaveout Z and then a leaveout X
Purify2to1 circuit, with coincidence measurments pushed to the end.
"""))
else
new(fixtwice)
end
end
end

function (circuit::Purify3to1)(purifiedL,purifiedR,sacrificedL::Array,sacrificedR::Array)
gate1, gate2, basis1, basis2 = if circuit.fixtwice==:X
ZCY, XCZ, σʸ, σᶻ
elseif circuit.fixtwice==:Y
XCZ, CNOT, σᶻ, σˣ
elseif circuit.fixtwice==:Z
CNOT, ZCY, σˣ, σʸ
end

apply!((sacrificedL[1], purifiedL),gate1)
apply!((sacrificedR[1], purifiedR),gate1)

apply!((sacrificedR[2],sacrificedR[1]),gate2)
apply!((sacrificedL[2],sacrificedL[1]),gate2)

measa1 = project_traceout!(sacrificedL[1], basis1)
measb1 = project_traceout!(sacrificedR[1], basis1)
measa2 = project_traceout!(sacrificedL[2], basis2)
measb2 = project_traceout!(sacrificedR[2], basis2)

success1 = measa1 == measb1
success2 = measa2 == measb2

if !(success1 && success2)
traceout!(purifiedL)
traceout!(purifiedR)
end
(success1 && success2)
end

function coin(basis, pair::Array, parity=0)
measa = project_traceout!(pair[1], basis)
measb = project_traceout!(pair[2], basis)
success = (measa ⊻ measb == parity)
success
end

struct StringentHead <: AbstractCircuit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring

type::Symbol
function StringentHead(type)
if type ∉ (:X, :Z)
throw(ArgumentError(lazy"""
`type` has to be one of `:X`, or `:Z`.
You have instead chosen `$(repr(fixtwice))` which is not a valid option.
Investigate where you are creating a purification circuit of type `StringentHead`
and ensure you are passing a valid argument.
"""))
else
new(type)
end
end
end

function (circuit::StringentHead)(purifiedL, purifiedR, sacrificedL, sacrificedR)
gate, success = if circuit.type == :Z
ZCZ, true
else
XCZ, true
end
apply!((purifiedL, sacrificedL[1]), gate)
apply!((purifiedR, sacrificedR[1]), gate)
apply!((sacrificedR[1], sacrificedR[2]), ZCZ)
apply!((sacrificedL[1], sacrificedL[2]), ZCZ)

success = success & coin(σˣ, [sacrificedL[1], sacrificedR[1]])
success = success & coin(σˣ, [sacrificedL[2], sacrificedR[2]])

success
end

struct StringentBody <: AbstractCircuit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring

type::Symbol
expedient::Bool
function StringentBody(type, expedient=false)
if type ∉ (:X, :Z)
throw(ArgumentError(lazy"""
`type` has to be one of `:X`, or `:Z`.
You have instead chosen `$(repr(fixtwice))` which is not a valid option.
Investigate where you are creating a purification circuit of type `StringentBody`
and ensure you are passing a valid argument.
"""))
else
new(type, expedient)
end
end
end

function (circuit::StringentBody)(purifiedL, purifiedR, sacrificedL, sacrificedR)
gate, success = if circuit.type == :Z
ZCZ, true
else
XCZ, true
end
## Indices for emulating pair creation
i1 = 1
i2 = 1
sacrificedL1 = sacrificedL[1:1]
sacrificedR1 = sacrificedR[1:1]

sacrificedL2 = circuit.expedient ? sacrificedL[2:3] : sacrificedL[2:4]
sacrificedR2 = circuit.expedient ? sacrificedR[2:3] : sacrificedR[2:4]

apply!((sacrificedL1[i1], sacrificedL2[i2]), XCZ)
apply!((sacrificedR1[i1], sacrificedR2[i2]), XCZ)
success = success & coin(σˣ, [sacrificedL2[i2], sacrificedR2[i2]])
i2 = i2 + 1

apply!((sacrificedL1[i1], sacrificedL2[i2]), ZCZ)
apply!((sacrificedR1[i1], sacrificedR2[i2]), ZCZ)
success = success & coin(σˣ, [sacrificedL2[i2], sacrificedR2[i2]])

apply!((purifiedL, sacrificedL1[i1]), gate)
apply!((purifiedR, sacrificedR1[i1]), gate)

if !circuit.expedient
i2 = i2 + 1
apply!((sacrificedL1[i1], sacrificedL2[i2]), ZCZ)
apply!((sacrificedR1[i1], sacrificedR2[i2]), ZCZ)

success = success & coin(σˣ, [sacrificedL2[i2], sacrificedR2[i2]])
end

success = success & coin(σˣ, [sacrificedL1[i1], sacrificedR1[i1]])

success

end


"""
$TYPEDEF

Fields:

$FIELDS

The STRINGENT purification circuit

If an error was detected, the circuit returns `false` and the state is reset.
If no error was detected, the circuit returns `true`.

The sacrificial qubits are removed from the register.

```jldoctest
julia> r = Register(26, rep())
for i in 1:13
initialize!(r[(2*i-1):(2*i)], bell)
end

julia> PurifyStringent()(r[1], r[2],
[r[3], r[5], r[7], r[9], r[11], r[13], r[15], r[17], r[19], r[21], r[23], r[25]],
[r[4], r[6], r[8], r[10], r[12], r[14], r[16], r[18], r[20], r[22], r[24], r[26]])
true

```

"""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line between docstring and type definition

struct PurifyStringent <: AbstractCircuit
end



function (circuit::PurifyStringent)(purifiedL,purifiedR,sacrificedL,sacrificedR)
success = true
stringentHead_Z = StringentHead(:Z)
stringentHead_X = StringentHead(:X)
stringentBody_Z = StringentBody(:Z)
stringentBody_X = StringentBody(:X)

success = success & stringentHead_Z(purifiedL, purifiedR, sacrificedL[1:2], sacrificedR[1:2])
success = success & stringentHead_X(purifiedL, purifiedR, sacrificedL[3:4], sacrificedR[3:4])
success = success & stringentBody_Z(purifiedL, purifiedR, sacrificedL[5:8], sacrificedR[5:8])
success = success & stringentBody_X(purifiedL, purifiedR, sacrificedL[9:12], sacrificedR[9:12])

success
end

struct PurifyExpedient <: AbstractCircuit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring

end

function (circuit::PurifyExpedient)(purifiedL,purifiedR,sacrificedL,sacrificedR)
success = true
stringentHead_Z = StringentHead(:Z)
stringentHead_X = StringentHead(:X)
stringentBody_Z = StringentBody(:Z, true)

success = success & stringentHead_Z(purifiedL, purifiedR, sacrificedL[1:2], sacrificedR[1:2])
success = success & stringentHead_X(purifiedL, purifiedR, sacrificedL[3:4], sacrificedR[3:4])
success = success & stringentBody_Z(purifiedL, purifiedR, sacrificedL[5:7], sacrificedR[5:7])
success = success & stringentBody_Z(purifiedL, purifiedR, sacrificedL[8:10], sacrificedR[8:10])

success
end

end # module
20 changes: 10 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ end

println("Starting tests with $(Threads.nthreads()) threads out of `Sys.CPU_THREADS = $(Sys.CPU_THREADS)`...")

@doset "register_interface"
@doset "project_traceout"
@doset "observable"
@doset "noninstant_and_backgrounds_qubit"
@doset "noninstant_and_backgrounds_qumode"
# @doset "register_interface"
# @doset "project_traceout"
# @doset "observable"
# @doset "noninstant_and_backgrounds_qubit"
# @doset "noninstant_and_backgrounds_qumode"
@doset "circuitzoo_purification"
@doset "examples"
get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && @doset "plotting_cairo"
get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && @doset "plotting_gl"
get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && VERSION >= v"1.9" && @doset "doctests"
get(ENV,"JET_TEST","")=="true" && @doset "jet"
# @doset "examples"
# get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && @doset "plotting_cairo"
# get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && @doset "plotting_gl"
# get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && VERSION >= v"1.9" && @doset "doctests"
# get(ENV,"JET_TEST","")=="true" && @doset "jet"

using Aqua
using QuantumClifford, QuantumOptics, Graphs
Expand Down
Loading