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

Update Noisy Circuits Documentation and Simulation #456

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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
47 changes: 46 additions & 1 deletion docs/src/noisycircuits_perturb.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,52 @@ circuit = [n,g1,g2,m,v]

petrajectories(initial_state, circuit)
```

```@raw html
<div class="mermaid">

flowchart TD
state[XX ZZ] -->|Simulation 2|gate1a([CNOT 1,3])
state[XX ZZ] -->|Simulation 3|gate1b([CNOT 1,3])
state[XX ZZ] -->|Simulation 1|gate1c([CNOT 1,3])
gate1a -->|Success| gate2a([CNOT 2,4])
gate1b -->|Success| gate2b([CNOT 2,4])
gate1c -.->|Error| gate2c([CNOT 2,4])
gate2a -->|Success|result2[Result]
gate2b -.->|Error|result3[Result]
gate2c -->|Success|result1[Result]
result1-->sum([Sum results and symbolic probabilities])
result2-->sum
result3-->sum
sum-->values[Probabilities
True Success = 0.903546
Failure = 0.0365069
False Success = 0.0547604]
style state fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate1a fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate1b fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate1c fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate2a fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate2b fill:#ffffff, font-family: 'Serif',stroke:#000000
style gate2c fill:#ffffff, font-family: 'Serif',stroke:#000000
style result1 fill:#ffffff, font-family: 'Serif',stroke:#000000
style result2 fill:#ffffff, font-family: 'Serif',stroke:#000000
style result3 fill:#ffffff, font-family: 'Serif',stroke:#000000
style sum fill:#ffffff, font-family: 'Serif',stroke:#000000
style values fill:#ffffff, font-family: 'Serif',stroke:#000000
linkStyle 0 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 1 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 2 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 3 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 4 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 5 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 6 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 7 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 8 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 9 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 10 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 11 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
linkStyle 12 stroke:#000000,stroke-width:1px,color:black,font-family: 'Serif'
</div>```
For more examples, see the [notebook comparing the Monte Carlo and Perturbative method](https://nbviewer.jupyter.org/github/QuantumSavory/QuantumClifford.jl/blob/master/docs/src/notebooks/Perturbative_Expansions_vs_Monte_Carlo_Simulations.ipynb) or this tutorial on [entanglement purification](https://github.com/QuantumSavory/QuantumClifford.jl/blob/master/docs/src/notebooks/Noisy_Circuits_Tutorial_with_Purification_Circuits.ipynb).

## Symbolic expansions
Expand Down
31 changes: 29 additions & 2 deletions src/petrajectory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@
[(applywstatus!(copy(state),op)...,1,0)]
end

function applybranches(::NondeterministicOperatorTrait, state, op::T; max_order=1) where {T<:Union{sMZ,sMX,sMY}}
s = copy(state)

if T===sMZ
d, anticom, res = projectZ!(s, op.qubit)
elseif T===sMX
d, anticom, res = projectX!(s, op.qubit)
elseif T===sMY
d, anticom, res = projectY!(s, op.qubit)
else
error("not reachable")

Check warning on line 25 in src/petrajectory.jl

View check run for this annotation

Codecov / codecov/patch

src/petrajectory.jl#L25

Added line #L25 was not covered by tests
end

if isnothing(res)
tab(stabilizerview(s)).phases[anticom] = 0x0
s1 = copy(s)
tab(stabilizerview(s)).phases[anticom] = 0x2
s2 = s
return [(s1, continue_stat, .5, 0), (s2, continue_stat, .5, 0)]
else
return [(s, continue_stat, 1, 0)] end
end
Copy link
Member

Choose a reason for hiding this comment

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

there is a lot of code repetition in applybranches for sMY and sMX and sMZ. There is a private function called project_cond! (you can see it being used in projectX! projectY! projectZ!) that should let you remove a ton of the code repetition.

Or even more simply, you can do something like op::T, ...) where {T<:Union{sMZ,sMX,sMY}} in the type signature and then do

if T===sMZ
    ...
elseif T===sMX
   ...
elseif T===sMY
   ...
else
    error("not reachable")
end


function applybranches(::NondeterministicOperatorTrait, state, op; max_order=1)
throw(ArgumentError(lazy"""
You are trying to apply a non-deterministic operator $(typeof(op)) in a perturbative expansion, but this particular operator does not have a `applybranches` method defined for it.
Expand Down Expand Up @@ -45,9 +68,12 @@

function petrajectory_keep(state, circuit; branch_weight=1.0, current_order=0, max_order=1) # TODO a lot of repetition with petrajectory - dry out
A = Accumulator{Tuple{typeof(state),CircuitStatus},typeof(branch_weight)}
dict = A()
if size(circuit)[1] == 0
return A()
DataStructures.inc!(dict, (state,continue_stat), branch_weight)
return dict
Copy link
Member

Choose a reason for hiding this comment

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

this new behavior also need a test (potentially the same test as the one for the new functionality above)

end

next_op = circuit[1]
rest_of_circuit = circuit[2:end]

Expand All @@ -67,7 +93,8 @@
end

"""Run a perturbative expansion to a given order. This is the main public function for the perturbative expansion approach.

Currently only has defined behavior for Clifford operators(AbstractCliffordOperator) and single-qubit X, Y and Z measurements(sMX, sMY, sMZ)
If using the measurements, set keepstates to true. When keepstates is false, will return 0 for true success probability.
See also: [`pftrajectories`](@ref), [`mctrajectories`](@ref)"""
function petrajectories(initialstate, circuit; branch_weight=1.0, max_order=1, keepstates::Bool=false)
if keepstates
Expand Down
28 changes: 28 additions & 0 deletions test/test_noisycircuits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,34 @@
@test stabilizerview(state.stab) == S"ZZ
ZI"
end

@testset "Symbolic Measurements" begin
state = MixedDestabilizer(S"Z")
had = sHadamard(1)
Zmeas = sMZ(1)
Xmeas = sMX(1)
Ymeas = sMY(1)
circuit = [Zmeas]
pe = petrajectories(state, circuit, keepstates=true)
for i in pe
@test i[2] == 1.0
end
circuit = [had, Zmeas]
pe = petrajectories(state, circuit, keepstates=true)
for i in pe
@test i[2] == 0.5
end
circuit = [had, Xmeas]
pe = petrajectories(state, circuit, keepstates=true)
for i in pe
@test i[2] == 1.0
end
circuit = [had, Ymeas]
pe = petrajectories(state, circuit, keepstates=true)
for i in pe
@test i[2] == 0.5
end
end
end

@testset "Classical Bits" begin
Expand Down
Loading