Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
apply code review suggestion
Browse files Browse the repository at this point in the history
Fe-r-oz committed Nov 16, 2024
1 parent 875f0b6 commit 854e5c5
Showing 2 changed files with 31 additions and 25 deletions.
22 changes: 6 additions & 16 deletions src/nonclifford.jl
Original file line number Diff line number Diff line change
@@ -233,22 +233,12 @@ function projectrand!(sm::GeneralizedStabilizer, p::PauliOperator)
end

function _proj(sm::GeneralizedStabilizer, p::PauliOperator)
# As detailed in https://www.scottaaronson.com/showcase2/report/ted-yoder.pdf, "A generalized
# stabilizer (χ, B(S, D)) separates the “classical” part of the quantum state from the quantum
# state." In this framework, the quasi-classical tableau T = (S, D) is updated through Clifford
# gates and measurements, while the χ-matrix is updated solely by non-Clifford operations.

# In this divided simulation approach:
# 1) When encountering a Clifford gate or measurement, we update the tableau as per usual.
# 2) For a non-Clifford gate or channel, the Kraus operator decompositions and operator-sum
# coefficients are stored for use with apply!(::GeneralizedStabilizer, ::AbstractPauliChannel).

# This function returns an updated `GeneralizedStabilizer` state sm' = (χ', B(S', D')), where
# (S', D') is derived from (S, D) through traditional stabilizer update. The χ' matrix is
# updated whenever a non-Clifford gate is applied via apply!(sm, appropriately_padded_pcT).
updated_state, res = projectrand!(sm.stab, p)
# sm'.stab' is derived from sm.stab through the traditional stabilizer update.
sm.stab = updated_state # in-place
# Returns the updated `GeneralizedStabilizer` state sm′ = (χ′, B(S′, D′)),
# where (S′, D′) is derived from (S, D) through the traditional stabilizer update,
# and χ′ is the updated density matrix after measurement. Note: Λ(χ′) ≤ Λ(χ).
n = nqubits(sm)
state, res = projectrand!(sm.stab, p)
sm = GeneralizedStabilizer(state, DefaultDict(0.0im, (falses(n),falses(n))=>expect(p, sm)))
return sm, res
end

34 changes: 25 additions & 9 deletions test/test_nonclifford_quantumoptics.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using QuantumClifford
using QuantumClifford: GeneralizedStabilizer, rowdecompose, PauliChannel, mul_left!, mul_right!
using QuantumClifford: GeneralizedStabilizer, rowdecompose, PauliChannel, mul_left!, mul_right!, invsparsity
using QuantumClifford: @S_str, random_stabilizer
using QuantumOpticsBase
using LinearAlgebra
@@ -90,8 +90,7 @@ end

function multiqubit_projrand(τ,p)
qo_state = Operator(τ)
projectrand!(τ, p)[1]
qo_state_after_proj = Operator(τ)
qo_state_after_proj = Operator(projectrand!(τ, p)[1])
qo_pauli = Operator(p)
qo_proj1 = (identityoperator(qo_pauli) - qo_pauli)/2
qo_proj2 = (identityoperator(qo_pauli) + qo_pauli)/2
@@ -100,6 +99,23 @@ function multiqubit_projrand(τ,p)
return qo_state_after_proj, result1, result2
end

@testset "Single-qubit projections using for stabilizer states wrt to evolution of χ by unitary channel" begin
n = 1
for s in [S"X", S"Y", S"Z", S"-X", S"-Y", S"-Z"]
for p in [P"X", P"Y", P"Z", P"-X", P"-Y", P"-Z"]
gs = GeneralizedStabilizer(s)
apply!(gs, pcT)
qo_state_after_proj, result1, result2 = multiqubit_projrand(gs,p)
# Normalize to ensure consistent comparison of the projected state, independent of scaling factors
norm_qo_state_after_proj = qo_state_after_proj/tr(qo_state_after_proj)
norm_result1 = result1/tr(result1)
norm_result2 = result2/tr(result2)
@test projectrand!(gs, p)[1] |> invsparsity <= gs |> invsparsity # Note: Λ(χ′) ≤ Λ(χ).
@test norm_qo_state_after_proj norm_result2 || norm_qo_state_after_proj norm_result1
end
end
end

@testset "Multi-qubit projections using GeneralizedStabilizer for stabilizer states" begin
for n in 1:10
for repetition in 1:5
@@ -119,15 +135,16 @@ end
end
end

# exclusively multi-qubit
function non_stabilizer_simulator(num_trials,n)
count = 0
for n in 1:n # exponential cost in this term
for n in 2:n # exponential cost in this term
for _ in 1:num_trials
s = random_stabilizer(n)
p = random_pauli(n)
gs = GeneralizedStabilizer(s)
i = rand(1:n)
nc = embed(n, i, pcT) # multi-qubit random non-Clifford gate
nc = embed(n, i, pcT)
apply!(gs, nc)
qo_state_after_proj, result1, result2 = multiqubit_projrand(gs,p)
# Normalize to ensure consistent comparison of the projected state, independent of scaling factors
@@ -139,7 +156,7 @@ function non_stabilizer_simulator(num_trials,n)
end
end
end
prob = count/(num_trials*n)
prob = count/(num_trials*(n-1))
return prob
end

@@ -156,8 +173,7 @@ end
# Therefore, non-Clifford simulators generally require probabilistic sampling
# techniques.

num_qubits = 10
num_trials = 10
num_qubits = 5
num_trials = 5
prob = non_stabilizer_simulator(num_trials, num_qubits)
@test prob > 0.5
end

0 comments on commit 854e5c5

Please sign in to comment.