From fd2f47190dbe57721583e68d973144af5de773de Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Mon, 18 Sep 2023 00:26:55 -0400 Subject: [PATCH 1/3] Added Superdense endcoding and decoding circuits to CircuitZoo (#34) --------- Co-authored-by: Stefan Krastanov --- Project.toml | 2 +- src/CircuitZoo/CircuitZoo.jl | 71 +++++++++++++++++++++ src/backends/quantumoptics/quantumoptics.jl | 1 + test/runtests.jl | 1 + test/test_circuitzoo_superdense.jl | 22 +++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 test/test_circuitzoo_superdense.jl diff --git a/Project.toml b/Project.toml index b505d9d4..61ec073c 100644 --- a/Project.toml +++ b/Project.toml @@ -39,7 +39,7 @@ PrecompileTools = "1" QuantumClifford = "0.8" QuantumInterface = "0.3.0" QuantumOptics = "1.0.5" -QuantumOpticsBase = "0.4" +QuantumOpticsBase = "0.4.14" QuantumSymbolics = "0.2.4" Reexport = "1.2.2" ResumableFunctions = "0.6.1" diff --git a/src/CircuitZoo/CircuitZoo.jl b/src/CircuitZoo/CircuitZoo.jl index 0e0b91a7..1e6133a3 100644 --- a/src/CircuitZoo/CircuitZoo.jl +++ b/src/CircuitZoo/CircuitZoo.jl @@ -851,4 +851,75 @@ function (circuit::PurifyExpedientNode)(purified,sacrificed...) [a..., b..., c..., d...] end +""" +$TYPEDEF + +Fields: + +$FIELDS + +The circuit for Superdense Coding to encode the 2 (classical) bit message +to its corresponding bell pair representation. `reg` is a single qubit register containing +Alice's half of the entangled bell pair and message is the 2 bit message Alice intends to send to Bob. +Based on the 2 bit message the state of the qubit in the register is mutated in place with `apply!` + +```jldoctest +julia> reg = Register(1) + +julia> initialize!(reg[1], Z1) + +julia> message = [1, 1] + +julia> SDEncode()(reg, message) +``` +""" + +struct SDEncode <: AbstractCircuit +end + +function (circuit::SDEncode)(reg, message) + if message[1] == 1 + apply!(reg[1], Z) + end + if message[2] == 1 + apply!(reg[1], X) + end +end + + +""" +$TYPEDEF + +Fields: + +$FIELDS + +The circuit for Superdense Coding to decode the 2 (classical) bit message +using the entangled bell pair stored in the registers regA and regB after Alice's encoding of the first qubit. +Returns a Tuple of the decoded message. + +```jldoctest +julia> regA = Register(1) + +julia> regB = Register(1) + +julia> initalize!(regA[1], Z1) + +julia> initalize!(regB[1], Z1) + +julia> SDDecode()(regA, regB) +``` +""" + +struct SDDecode <: AbstractCircuit +end + +function (circuit::SDDecode)(regA, regB) + apply!((regB[1], regA[1]), CNOT) + apply!(regB[1], H) + b1 = project_traceout!(regA, 1, Z) + b2 = project_traceout!(regB, 1, Z) + return b1-1, b2-1 +end + end # module diff --git a/src/backends/quantumoptics/quantumoptics.jl b/src/backends/quantumoptics/quantumoptics.jl index 6ec699f6..d2b081b6 100644 --- a/src/backends/quantumoptics/quantumoptics.jl +++ b/src/backends/quantumoptics/quantumoptics.jl @@ -37,6 +37,7 @@ function observable(state::Union{<:Ket,<:Operator}, indices, operation) expect(op, state) end + function project_traceout!(state::Union{Ket,Operator},stateindex,psis::Base.AbstractVecOrTuple{<:Ket}) if nsubsystems(state) == 1 # TODO is there a way to do this in a single function, instead of _overlap vs _project_and_drop _overlaps = [_overlap(psi,state) for psi in psis] diff --git a/test/runtests.jl b/test/runtests.jl index 1b1e3c0a..9bc2c8f0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,6 +28,7 @@ println("Starting tests with $(Threads.nthreads()) threads out of `Sys.CPU_THREA @doset "observable" @doset "noninstant_and_backgrounds_qubit" @doset "noninstant_and_backgrounds_qumode" +@doset "circuitzoo_superdense" @doset "circuitzoo_purification" @doset "examples" get(ENV,"QUANTUMSAVORY_PLOT_TEST","")=="true" && @doset "plotting_cairo" diff --git a/test/test_circuitzoo_superdense.jl b/test/test_circuitzoo_superdense.jl new file mode 100644 index 00000000..c1ac0e77 --- /dev/null +++ b/test/test_circuitzoo_superdense.jl @@ -0,0 +1,22 @@ +using QuantumSavory +using QuantumSavory.CircuitZoo: SDEncode, SDDecode +using Test + +## Set up an entangled bell pair +ra = Register(1) +rb = Register(1) + +initialize!(ra[1], Z1) +initialize!(rb[1], Z1) + +apply!(ra[1], H) +apply!((ra[1], rb[1]), CNOT) + +# Random 2 bit classical message +message = Tuple(rand(0:1, 2)) + +# Use the circuits to encode and decode the message +SDEncode()(ra, message) +rec = SDDecode()(ra, rb) + +@test message == rec From 7c4b68e27f69b1df088f0e2ade1b60a18f3f08dc Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Mon, 18 Sep 2023 03:06:02 -0400 Subject: [PATCH 2/3] test cleanup and compat for dependency bugs --- Project.toml | 2 +- test/test_circuitzoo_purification.jl | 10 +++------- test/test_circuitzoo_superdense.jl | 29 +++++++++++++++------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Project.toml b/Project.toml index 61ec073c..9e2539d3 100644 --- a/Project.toml +++ b/Project.toml @@ -39,7 +39,7 @@ PrecompileTools = "1" QuantumClifford = "0.8" QuantumInterface = "0.3.0" QuantumOptics = "1.0.5" -QuantumOpticsBase = "0.4.14" +QuantumOpticsBase = "0.4.16" QuantumSymbolics = "0.2.4" Reexport = "1.2.2" ResumableFunctions = "0.6.1" diff --git a/test/test_circuitzoo_purification.jl b/test/test_circuitzoo_purification.jl index 2005cbde..0977ffa4 100644 --- a/test/test_circuitzoo_purification.jl +++ b/test/test_circuitzoo_purification.jl @@ -104,19 +104,15 @@ end r = Register(6, rep()) initialize!(r[1:6], bell⊗bell⊗bell) - @testset "$leaveout1, $leaveout2" begin - @test Purify3to1(leaveout1, leaveout2)(r[1], r[2], r[3], r[5], r[4], r[6])==true - @test observable(r[1:2], projector(bell))≈1.0 - end + @test Purify3to1(leaveout1, leaveout2)(r[1], r[2], r[3], r[5], r[4], r[6])==true + @test observable(r[1:2], projector(bell))≈1.0 for error in [:X, :Y, :Z], target in 3:6 r = Register(6, rep()) for i in 1:3 initialize!(r[(2*i-1):(2*i)], bell) end apply!(r[target], Dict(:X=>X, :Y=>Y, :Z=>Z)[error]) - @testset "error: $leaveout1, $leaveout2" begin - @test Purify3to1(leaveout1, leaveout2)(r[1], r[2], r[3], r[5], r[4], r[6])==false - end + @test Purify3to1(leaveout1, leaveout2)(r[1], r[2], r[3], r[5], r[4], r[6])==false end for error in [:X, :Y, :Z], target in 1:2 r = Register(6, rep()) diff --git a/test/test_circuitzoo_superdense.jl b/test/test_circuitzoo_superdense.jl index c1ac0e77..ebdf9ece 100644 --- a/test/test_circuitzoo_superdense.jl +++ b/test/test_circuitzoo_superdense.jl @@ -2,21 +2,24 @@ using QuantumSavory using QuantumSavory.CircuitZoo: SDEncode, SDDecode using Test -## Set up an entangled bell pair -ra = Register(1) -rb = Register(1) +for i in 1:8 + ## Set up an entangled bell pair + ra = Register(1) + rb = Register(1) -initialize!(ra[1], Z1) -initialize!(rb[1], Z1) + initialize!(ra[1], Z1) + initialize!(rb[1], Z1) -apply!(ra[1], H) -apply!((ra[1], rb[1]), CNOT) + apply!(ra[1], H) + apply!((ra[1], rb[1]), CNOT) -# Random 2 bit classical message -message = Tuple(rand(0:1, 2)) + # Random 2 bit classical message + message = Tuple(rand(0:1, 2)) -# Use the circuits to encode and decode the message -SDEncode()(ra, message) -rec = SDDecode()(ra, rb) + # Use the circuits to encode and decode the message + SDEncode()(ra, message) + rec = SDDecode()(ra, rb) -@test message == rec + @test message == rec + +end From 763be70aa6691421d29b6b4caa73cb1ea8ef4408 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Mon, 18 Sep 2023 03:21:49 -0400 Subject: [PATCH 3/3] fixes and test for superdense coding --- src/CircuitZoo/CircuitZoo.jl | 43 ++++++++++++++++-------------- test/test_circuitzoo_superdense.jl | 1 - 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/CircuitZoo/CircuitZoo.jl b/src/CircuitZoo/CircuitZoo.jl index 1e6133a3..114fb96f 100644 --- a/src/CircuitZoo/CircuitZoo.jl +++ b/src/CircuitZoo/CircuitZoo.jl @@ -4,7 +4,8 @@ using QuantumSavory using DocStringExtensions export EntanglementSwap, Purify2to1, Purify2to1Node, Purify3to1, Purify3to1Node, - PurifyStringent, PurifyStringentNode, PurifyExpedient, PurifyExpedientNode + PurifyStringent, PurifyStringentNode, PurifyExpedient, PurifyExpedientNode, + SDDecode, SDEncode abstract type AbstractCircuit end @@ -858,32 +859,32 @@ Fields: $FIELDS -The circuit for Superdense Coding to encode the 2 (classical) bit message -to its corresponding bell pair representation. `reg` is a single qubit register containing -Alice's half of the entangled bell pair and message is the 2 bit message Alice intends to send to Bob. -Based on the 2 bit message the state of the qubit in the register is mutated in place with `apply!` +The circuit for [Superdense Coding](https://en.wikipedia.org/wiki/Superdense_coding) to encode the 2 (classical) bit message +to its corresponding Bell pair representation. It takes as argumes a single qubit register containing +Alice's half of the entangled Bell pair and the 2 bit message Alice intends to send to Bob. ```jldoctest -julia> reg = Register(1) +julia> regA = Register(1); regB = Register(2); -julia> initialize!(reg[1], Z1) +julia> initialize!((regA[1], regB[1]), (L0⊗L0+L1⊗L1)/√2); -julia> message = [1, 1] +julia> message = [1, 1]; -julia> SDEncode()(reg, message) +julia> SDEncode()(regA, message); ``` -""" +See also [`SDDecode`](@ref) +""" struct SDEncode <: AbstractCircuit end function (circuit::SDEncode)(reg, message) - if message[1] == 1 - apply!(reg[1], Z) - end if message[2] == 1 apply!(reg[1], X) end + if message[1] == 1 + apply!(reg[1], Z) + end end @@ -899,24 +900,26 @@ using the entangled bell pair stored in the registers regA and regB after Alice' Returns a Tuple of the decoded message. ```jldoctest -julia> regA = Register(1) +julia> regA = Register(1); regB = Register(2); -julia> regB = Register(1) +julia> initialize!((regA[1], regB[1]), (L0⊗L0+L1⊗L1)/√2); -julia> initalize!(regA[1], Z1) +julia> message = [1, 1]; -julia> initalize!(regB[1], Z1) +julia> SDEncode()(regA, message); julia> SDDecode()(regA, regB) +(1, 1) ``` -""" +See also [`SDEncode`](@ref) +""" struct SDDecode <: AbstractCircuit end function (circuit::SDDecode)(regA, regB) - apply!((regB[1], regA[1]), CNOT) - apply!(regB[1], H) + apply!((regA[1], regB[1]), CNOT) + apply!(regA[1], H) b1 = project_traceout!(regA, 1, Z) b2 = project_traceout!(regB, 1, Z) return b1-1, b2-1 diff --git a/test/test_circuitzoo_superdense.jl b/test/test_circuitzoo_superdense.jl index ebdf9ece..db3bb35a 100644 --- a/test/test_circuitzoo_superdense.jl +++ b/test/test_circuitzoo_superdense.jl @@ -21,5 +21,4 @@ for i in 1:8 rec = SDDecode()(ra, rb) @test message == rec - end