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 Superdense endcoding and decoding circuits to CircuitZoo #34

Merged
merged 13 commits into from
Sep 18, 2023

Conversation

ba2tro
Copy link
Member

@ba2tro ba2tro commented Aug 26, 2023

No description provided.

@codecov
Copy link

codecov bot commented Aug 26, 2023

Codecov Report

Merging #34 (de16311) into master (29d87e4) will decrease coverage by 1.04%.
Report is 4 commits behind head on master.
The diff coverage is 56.08%.

❗ Current head de16311 differs from pull request most recent head 5e514cd. Consider uploading reports for the commit 5e514cd to get more accurate results

@@            Coverage Diff             @@
##           master      #34      +/-   ##
==========================================
- Coverage   65.15%   64.11%   -1.04%     
==========================================
  Files          23       23              
  Lines         927      981      +54     
==========================================
+ Hits          604      629      +25     
- Misses        323      352      +29     
Files Changed Coverage Δ
src/QuantumSavory.jl 59.68% <ø> (+0.77%) ⬆️
src/CircuitZoo/CircuitZoo.jl 65.94% <53.62%> (-5.68%) ⬇️
src/baseops/traceout.jl 89.13% <83.33%> (ø)
src/backends/quantumoptics/express.jl 50.00% <100.00%> (ø)
src/backends/quantumoptics/quantumoptics.jl 88.37% <100.00%> (+0.27%) ⬆️

... and 2 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@ba2tro
Copy link
Member Author

ba2tro commented Aug 26, 2023

Running the circuits from this PR is somehow returning inconsistent results with multiple runs:

using QuantumSavory
using QuantumSavory.CircuitZoo: SDEncode, SDDecode

##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)

message = [1, 1]

SDEncode()(ra, message)

rec = SDDecode()(ra, rb)

versus when simply running a program without using any registers:

using QuantumSavory
using QuantumClifford, QuantumOpticsBase

function alice_node1()
    message = rand(0:1, 2)
    println("Sending message: $message")
    state = S"XX
              ZZ"
    if message[1] == 1
        state = P"ZI"*state
    end
    if message[2] == 1
        state = P"XI"*state
    end
    return state
end

function bob_node2()
    state = alice_node1()
    apply!(state, tCNOT, [2,1])
    apply!(state, tHadamard,[2])
    msg = Ket(state)
    println("Message Received by Bob: $msg")
end

bob_node2()

Does there seem to be any mistake with the encoding or decoding circuit or could there be a bug somewhere?

@Krastanov
Copy link
Member

could you try to investigate what is happening step by step

the register has a staterefs property which you can use to see what state is being stored in it

julia> r = Register(3); initialize!(r[1], X1);

julia> r.staterefs[1].state[]
Ket(dim=2)
  basis: Spin(1/2)
 0.7071067811865475 + 0.0im
 0.7071067811865475 + 0.0im

You can also try the clifford representation given that you already have a related test

julia> r = Register(3, CliffordRepr()); initialize!(r[1], X1);

julia> r.staterefs[1].state[]
𝒟ℯ𝓈𝓉𝒶𝒷
+ Z
𝒮𝓉𝒶𝒷
+ X

I will not always be able to review quickly after you submit a pull request. Please proceed with trying to investigate and fix even if I have not reviewed.


function (circuit::SDDecode)(regA, regB)
apply!((regB[1], regA[1]), CNOT)
apply!(regB[1], H)
Copy link
Member Author

Choose a reason for hiding this comment

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

Everything works fine upto this line, but when we apply H to Bob's qubit, the result is the same as what we would get if we applied H to Alice's qubit on paper, i.e., something like

Ket(dim=4)
  basis: [Spin(1/2)  Spin(1/2)]
  0.49999999999999994 + 0.0im
 -0.49999999999999994 + 0.0im
 -0.49999999999999994 + 0.0im
  0.49999999999999994 + 0.0im

which gives us the random results.
But if we apply H to regA[1] , which is Alice's qubit here, it returns the correct results. I am not sure why it behaves this way, opposite to what we get when we solve it on paper, but it resolves the issue here

Copy link
Member

Choose a reason for hiding this comment

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

Could you elaborate a bit? What is the state before the wrong step, what is the step that seems to break things, and what is the state after that step (and what should it be)?

Copy link
Member Author

@ba2tro ba2tro Aug 31, 2023

Choose a reason for hiding this comment

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

For the final part of the decoder circuit, we want to apply H to the second qubit (Bob's qubit), and H is a 1 qubit operator. But under the hood our register stores a 4 element ket vector which (if the classical message is 1 1) would be:

Ket(dim=4)
  basis: [Spin(1/2)  Spin(1/2)]
                 0.0 + 0.0im
                 0.0 + 0.0im
  0.7071067811865475 + 0.0im
 -0.7071067811865475 + 0.0im

To apply the symbolic H to the second qubit, we call the apply! method at

function apply!(regs::Vector{Register}, indices::Vector{Int}, operation; time=nothing)

Here(
state_indices = [r.stateindices[i] for (r,i) in zip(regs, indices)]
) the state_indices parameter of our ket determines whether the final operator would be I⊗H(correct) or H⊗I(wrong) given state_indices is 1 or 2 respectively. Since, Bob's qubit is the 2nd qubit of the subsystem state_indices is set to 2 and it finally hits the apply! methods in QuantumOpticsBase.jl. So, because of state_indices being 2, the final operator here (in QuantumOpticsBase.jl) becomes H⊗I which gives us the wrong answer in my previous comment.

So, [sorry for the huge description : ) ] to be short, the embed method here expects to be provided with the index where we want to put the identity operator(index 1) instead of the index of the qubit on which we're performing the single qubit operation(index 2), as described by its docstring here
Hence, I think we have a bug in this line

state_indices = [r.stateindices[i] for (r,i) in zip(regs, indices)]

and state_indices should be a vector of all the indices of the state excluding the index of our qubit, so that embed could put identity for all those indices

@ba2tro
Copy link
Member Author

ba2tro commented Sep 14, 2023

Needs the next QOBase release

@Krastanov Krastanov merged commit fd2f471 into QuantumSavory:master Sep 18, 2023
0 of 7 checks passed
@ba2tro ba2tro deleted the sdcircuit branch September 18, 2023 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants