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

Separate normalized and unnormalized objects #50

Merged
merged 9 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/StatesZoo/StatesZoo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ using QuantumSymbolics, QuantumOpticsBase
using QuantumSymbolics: withmetadata, @withmetadata, Metadata
import QuantumSymbolics: express_nolookup

export SingleRailMidSwapBell, DualRailMidSwapBell, ZALMSpinPair
using LinearAlgebra
import LinearAlgebra: tr

export SingleRailMidSwapBellW, SingleRailMidSwapBell, DualRailMidSwapBellW, DualRailMidSwapBell, ZALMSpinPairW, ZALMSpinPair, tr

abstract type AbstractTwoQubitState <: QuantumSymbolics.AbstractTwoQubitOp end #For representing density matrices
Base.show(io::IO, x::AbstractTwoQubitState) = print(io, "$(symbollabel(x))")
Expand Down
97 changes: 93 additions & 4 deletions src/StatesZoo/single_dual_rail_midswap/single_dual_rail_midswap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,44 @@

$FIELDS

Generates the spin-spin density matrix for linear photonic entanglement swap
Generates the unnormalized spin-spin density matrix for linear photonic entanglement swap
with emissive memories emitting single rail photonic qubits from the paper [prajit2023entangling](@cite).
Since the matrix is 'weighted' by the probability for success, it is suffixed with a W to distinguish it
from the normalized object `SingleRailMidSwapBell`.
It takes the following parameters:
- eA, eB: Link efficiencies for memories A and B upto the swap (include link loss, detector efficiency, etc.)
- gA, gB: Memory initialization parameter for memories A and B
- Pd: Detector dark count probability per photonic mode (assumed to be the same for both detectors)
- Vis: Interferometer visibility for the midpoint swap' can be complex to account for phase instability

```jldoctest
julia> r = Register(2)

julia> initialize!(r[1:2], SingleRailMidSwapBellW(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99))

julia> observable(r[1:2], Z⊗Z)
```
"""
@withmetadata struct SingleRailMidSwapBellW <: AbstractTwoQubitState
eA::Float64
eB::Float64
gA::Float64
gB::Float64
Pd::Float64
Vis::Float64
end

symbollabel(x::SingleRailMidSwapBellW) = "ρˢʳᵐˢᵂ"

Check warning on line 64 in src/StatesZoo/single_dual_rail_midswap/single_dual_rail_midswap.jl

View check run for this annotation

Codecov / codecov/patch

src/StatesZoo/single_dual_rail_midswap/single_dual_rail_midswap.jl#L64

Added line #L64 was not covered by tests


"""
$TYPEDEF

Fields:

$FIELDS

Generates the normalized spin-spin density matrix for linear photonic entanglement swap
with emissive memories emitting single rail photonic qubits from the paper [prajit2023entangling](@cite)
It takes the following parameters:
- eA, eB: Link efficiencies for memories A and B upto the swap (include link loss, detector efficiency, etc.)
Expand Down Expand Up @@ -69,7 +106,44 @@

$FIELDS

Generates the spin-spin density matrix for linear photonic entanglement swap with emissive
Generates the unnormalized spin-spin density matrix for linear photonic entanglement swap with emissive
memories emitting dual rail photonic qubits from the paper [prajit2023entangling](@cite).
Since the matrix is 'weighted' by the probability for success, it is suffixed with a W to distinguish it
from the normalized object `DualRailMidSwapBell`.
It takes the following parameters:
- eA, eB: Link efficiencies for memories A and B upto the swap (include link loss, detector efficiency, etc.)
- gA, gB: Memory initialization parameter for memories A and B
- Pd: Detector dark count probability per photonic mode (assumed to be the same for both detectors)
- Vis: Interferometer visibility for the midpoint swap

```jldoctest
julia> r = Register(2)

julia> initialize!(r[1:2], DualRailMidSwapBellW(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99))

julia> observable(r[1:2], Z⊗Z)
```
"""
@withmetadata struct DualRailMidSwapBellW <: AbstractTwoQubitState
eA::Float64
eB::Float64
gA::Float64
gB::Float64
Pd::Float64
Vis::Float64
end

symbollabel(x::DualRailMidSwapBellW) = "ρᵈʳᵐˢᵂ"

Check warning on line 136 in src/StatesZoo/single_dual_rail_midswap/single_dual_rail_midswap.jl

View check run for this annotation

Codecov / codecov/patch

src/StatesZoo/single_dual_rail_midswap/single_dual_rail_midswap.jl#L136

Added line #L136 was not covered by tests


"""
$TYPEDEF

Fields:

$FIELDS

Generates the normalized spin-spin density matrix for linear photonic entanglement swap with emissive
memories emitting dual rail photonic qubits from the paper [prajit2023entangling](@cite).
It takes the following parameters:
- eA, eB: Link efficiencies for memories A and B upto the swap (include link loss, detector efficiency, etc.)
Expand Down Expand Up @@ -99,12 +173,27 @@

## express

function express_nolookup(x::SingleRailMidSwapBellW, ::QuantumOpticsRepr)
data = midswap_single_rail(x.eA, x.eB, x.gA, x.gB, x.Pd, x.Vis)
return SparseOperator(_bspin⊗_bspin, Complex.(data))
end

function express_nolookup(x::SingleRailMidSwapBell, ::QuantumOpticsRepr)
data = midswap_single_rail(x.eA, x.eB, x.gA, x.gB, x.Pd, x.Vis)
return SparseOperator(_bspin⊗_bspin, Complex.(data/tr(data)))
end

function express_nolookup(x::DualRailMidSwapBellW, ::QuantumOpticsRepr)
data = midswap_dual_rail(x.eA, x.eB, x.gA, x.gB, x.Pd, x.Vis)
return SparseOperator(_bspin⊗_bspin, Complex.(data))
end

function express_nolookup(x::DualRailMidSwapBell, ::QuantumOpticsRepr)
data = midswap_dual_rail(x.eA, x.eB, x.gA, x.gB, x.Pd, x.Vis)
return SparseOperator(_bspin⊗_bspin, Complex.(data))
end
return SparseOperator(_bspin⊗_bspin, Complex.(data/tr(data)))
end

# Symbolic trace

tr(::SingleRailMidSwapBell) = 1
tr(::DualRailMidSwapBell) = 1
68 changes: 65 additions & 3 deletions src/StatesZoo/zalm_pair/zalm_pair.jl
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,59 @@

$FIELDS

Generate symbolic object for the spin-spin density matrix for a
Generate symbolic object for the unnormalized spin-spin density matrix for a
cascaded source swapped with emissive spin memories. Since the matrix is 'weighted' by the probability for
success, it is suffixed with a W to distinguish it from the normalized object `ZALMSpinPair`. The cascaded
source from papers [prajit2022heralded](@cite) and [kevin2023zero](@cite)
is stored in spin memories as discussed in [prajit2023entangling](@cite).
It takes the following parameters:
- Ns: mean photon number per mode of the cascaded source model
- gA: qubit initialization parameter on Alice's side
- gB: qubit initialization parameter on Bob's side
- eAm: memory out-coupling efficiency for Alice's side (Allowed range: [0,1])
- eBm: memory out-coupling efficiency for Bob's side (Allowed range: [0,1])
- eAs: source out-coupling efficiency for Alice's side (Allowed range: [0,1])
- eBs: source out-coupling efficiency for Bob's side (Allowed range: [0,1])
- eD: detector efficiency (Allowed range: [0,1])
- Pd: dark click probability per photonic mode on source's swap
- Pdo1: dark click probability per photonic mode on Alice side swap
- Pdo2: dark click probability per photonic mode on Bob side swap
- VisF: product of visibilities of all three interferometers (Allowed range: [0,1])

```jldoctest
julia> r = Register(2)

julia> initialize!(r[1:2], ZALMSpinPairW(1e-3, 0.5, 0.5, 1, 1, 1, 1, 0.9, 1e-8, 1e-8, 1e-8, 0.99))

juilia> observable(r[1:2], Z⊗Z)
```
"""
@withmetadata struct ZALMSpinPairW <: AbstractTwoQubitState
Ns::Float64
gA::Float64
gB::Float64
eAm::Float64
eBm::Float64
eAs::Float64
eBs::Float64
eD::Float64
Pd::Float64
Pdo1::Float64
Pdo2::Float64
VisF::Float64
end

symbollabel(x::ZALMSpinPairW) = "ρᶻᵃˡᵐᵂ"

Check warning on line 613 in src/StatesZoo/zalm_pair/zalm_pair.jl

View check run for this annotation

Codecov / codecov/patch

src/StatesZoo/zalm_pair/zalm_pair.jl#L613

Added line #L613 was not covered by tests


"""
$TYPEDEF

Fields:

$FIELDS

Generate symbolic object for the normalized spin-spin density matrix for a
cascaded source swapped with emissive spin memories. The cascaded
source from papers [prajit2022heralded](@cite) and [kevin2023zero](@cite)
is stored in spin memories as discussed in [prajit2023entangling](@cite).
Expand Down Expand Up @@ -611,7 +663,17 @@

symbollabel(x::ZALMSpinPair) = "ρᶻᵃˡᵐ"

function express_nolookup(x::ZALMSpinPair, ::QuantumOpticsRepr)
## express

function express_nolookup(x::ZALMSpinPairW, ::QuantumOpticsRepr)
data = cascaded_source_spin(x.Ns, x.gA, x.gB, x.eAm, x.eBm, x.eAs, x.eBs, x.eD, x.Pd, x.Pdo1, x.Pdo2, x.VisF)
return SparseOperator(_bspin⊗_bspin, Complex.(data))
end
end

function express_nolookup(x::ZALMSpinPair, ::QuantumOpticsRepr)
data = cascaded_source_spin(x.Ns, x.gA, x.gB, x.eAm, x.eBm, x.eAs, x.eBs, x.eD, x.Pd, x.Pdo1, x.Pdo2, x.VisF)
return SparseOperator(_bspin⊗_bspin, Complex.(data/tr(data)))
end

## Symbolic trace
tr(::ZALMSpinPair) = 1
36 changes: 31 additions & 5 deletions test/test_stateszoo_api.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
using QuantumSavory
using QuantumSavory.StatesZoo: ZALMSpinPair, SingleRailMidSwapBell, DualRailMidSwapBell
using QuantumSavory.StatesZoo: ZALMSpinPairW, ZALMSpinPair, SingleRailMidSwapBellW, SingleRailMidSwapBell, DualRailMidSwapBellW, DualRailMidSwapBell
using QuantumOpticsBase
using Test

zalmW = ZALMSpinPairW(1e-3, 0.5, 0.5, 1, 1, 1, 1, 0.9, 1e-8, 1e-8, 1e-8, 0.99)
zalm = ZALMSpinPair(1e-3, 0.5, 0.5, 1, 1, 1, 1, 0.9, 1e-8, 1e-8, 1e-8, 0.99)
srmsW = SingleRailMidSwapBellW(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99)
srms = SingleRailMidSwapBell(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99)
drmsW = DualRailMidSwapBellW(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99)
drms = DualRailMidSwapBell(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99)

r_zalmW = Register(2)
initialize!(r_zalmW[1:2], zalmW)
@test ! iszero(observable(r_zalmW[1:2], Z⊗Z))

r_zalm = Register(2)
initialize!(r_zalm[1:2], ZALMSpinPair(1e-3, 0.5, 0.5, 1, 1, 1, 1, 0.9, 1e-8, 1e-8, 1e-8, 0.99))
initialize!(r_zalm[1:2], zalm)
@test ! iszero(observable(r_zalm[1:2], Z⊗Z))

r_srmsW = Register(2)
initialize!(r_srmsW[1:2], srmsW)
@test ! iszero(observable(r_srmsW[1:2], Z⊗Z))

r_srms = Register(2)
initialize!(r_srms[1:2], SingleRailMidSwapBell(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99))
initialize!(r_srms[1:2], srms)
@test ! iszero(observable(r_srms[1:2], Z⊗Z))

r_drmsW = Register(2)
initialize!(r_drmsW[1:2], drmsW)
@test ! iszero(observable(r_drmsW[1:2], Z⊗Z))

r_drms = Register(2)
initialize!(r_drms[1:2], DualRailMidSwapBell(0.9, 0.9, 0.5, 0.5, 1e-8, 0.99))
@test ! iszero(observable(r_drms[1:2], Z⊗Z))
initialize!(r_drms[1:2], drms)
@test ! iszero(observable(r_drms[1:2], Z⊗Z))

@test tr(zalm) == tr(express(zalm))

@test tr(srms) == tr(express(srms))

@test tr(drms) == tr(express(drms))
Loading