Skip to content

Commit 191455b

Browse files
LEXUGEKrastanov
andauthored
fix: single qubit projection now takes Stabilizer (#527)
* fix: single qubit projection now accepts `AbstractStabilizer` - implemented through generic pauli string measurement - added test cases to ensure consistency of measurement restuls --------- Co-authored-by: Stefan Krastanov <[email protected]> Co-authored-by: Stefan Krastanov <[email protected]>
1 parent 2694d44 commit 191455b

File tree

3 files changed

+62
-14
lines changed

3 files changed

+62
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
# News
77

8-
## v0.10.0 - 2025-06-25
8+
## v0.10.0 - 2025-07-02
9+
910

1011
- **(fix)** The gates `SQRTY`, `CXYZ`, `CZYX` were computing phases incorrectly when acting on `I` stabilizers.
1112
- **(fix)** Paulis with imaginary phases had their phases incorrectly tracked.
1213
- **(fix)** `rowdecompose` was not accounting for the phase of the input Pauli string, leading to potential errors in non-Clifford functionality.
1314
- Various stabilizer data structures can now be constructed out of sequences of Paulis.
1415
- Most canonicalization routines can now act on sequences of Paulis.
16+
- `project*!` family of functions now work on more tableau types.
1517
- `QuantumCliffordJuMPExt` is a new extension depending on the JuMP solver suite. It enables computing minimum distance for quantum LDPC codes via Mixed Integer Programming (MIP) using `JuMP`.
1618
- `QuantumCliffordOscarExt` is a new extension depending on the Oscar CAS. It provides more convenient ways to construct two-block-group-algebra codes and more.
1719
- Improvements to `GeneralizedStabilizer` API including support for products and tensor product for many Clifford and non-Clifford operators and states.

src/project_trace_reset.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ function projectX!(d::MixedDestabilizer,qubit::Int;keep_result::Bool=true,phases
448448
@valbooldispatch project_cond!(d,qubit,Val(isZ),Val((true,false));keep_result,phases=Val(phases)) phases
449449
end
450450

451+
function projectX!(s::AbstractStabilizer,qubit::Int;keep_result::Bool=true,phases::Bool=true)
452+
project!(s, single_x(nqubits(s), qubit) ; keep_result, phases)
453+
end
454+
451455
"""
452456
Measure a given qubit in the Z basis.
453457
A faster special-case version of [`project!`](@ref).
@@ -458,6 +462,10 @@ function projectZ!(d::MixedDestabilizer,qubit::Int;keep_result::Bool=true,phases
458462
@valbooldispatch project_cond!(d,qubit,Val(isX),Val((false,true));keep_result,phases=Val(phases))
459463
end
460464

465+
function projectZ!(s::AbstractStabilizer,qubit::Int;keep_result::Bool=true,phases::Bool=true)
466+
project!(s, single_z(nqubits(s), qubit) ; keep_result, phases)
467+
end
468+
461469
"""
462470
Measure a given qubit in the Y basis.
463471
A faster special-case version of [`project!`](@ref).
@@ -468,6 +476,10 @@ function projectY!(d::MixedDestabilizer,qubit::Int;keep_result::Bool=true,phases
468476
@valbooldispatch project_cond!(d,qubit,Val(isXorZ),Val((true,true));keep_result,phases=Val(phases))
469477
end
470478

479+
function projectY!(s::AbstractStabilizer,qubit::Int;keep_result::Bool=true,phases::Bool=true)
480+
project!(s, single_y(nqubits(s), qubit) ; keep_result, phases)
481+
end
482+
471483
@inline isX(tab,row,col) = tab[row,col][1]
472484
@inline isZ(tab,row,col) = tab[row,col][2]
473485
@inline isY(tab,row,col) = (&)(tab[row,col]...)

test/test_projections.jl

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -315,26 +315,60 @@
315315
@test tab(apply!(copy(s),sMZ(r))).xzs == tab(sz).xzs == tab(ssz).xzs == tab(rssz).xzs
316316
end
317317
end
318-
@testset "project! projectrand! apply!(...,sM*) consistency" begin
318+
319+
# projext*! should accept AbstractStabilizer, or Stabilizer in particular
320+
# This testset is not merged with the previous one as "measuring commutating operator out of the stabilizer"
321+
# is not well supported for pure stabilizer state datastructure. See also "Datastructure Choice"
322+
@testset "Single Qubit Pure State Projections" begin
323+
for n in test_sizes
324+
s = random_stabilizer(n);
325+
r = rand(1:n)
326+
px = single_x(n,r);
327+
py = single_y(n,r);
328+
pz = single_z(n,r);
329+
@test project!(copy(s),px) == projectX!(copy(s),r)
330+
@test project!(copy(s),py) == projectY!(copy(s),r)
331+
@test project!(copy(s),pz) == projectZ!(copy(s),r)
332+
sx = project!(copy(s),px)[1]
333+
sy = project!(copy(s),py)[1]
334+
sz = project!(copy(s),pz)[1]
335+
ssx = project!(copy(s),sMX(r))[1]
336+
ssy = project!(copy(s),sMY(r))[1]
337+
ssz = project!(copy(s),sMZ(r))[1]
338+
rssx = projectrand!(copy(s),sMX(r))[1]
339+
rssy = projectrand!(copy(s),sMY(r))[1]
340+
rssz = projectrand!(copy(s),sMZ(r))[1]
341+
@test project!(copy(sx),px) == projectX!(copy(sx),r)
342+
@test project!(copy(sy),py) == projectY!(copy(sy),r)
343+
@test project!(copy(sz),pz) == projectZ!(copy(sz),r)
344+
@test tab(apply!(copy(s),sMX(r))).xzs == tab(sx).xzs == tab(ssx).xzs == tab(rssx).xzs
345+
@test tab(apply!(copy(s),sMY(r))).xzs == tab(sy).xzs == tab(ssy).xzs == tab(rssy).xzs
346+
@test tab(apply!(copy(s),sMZ(r))).xzs == tab(sz).xzs == tab(ssz).xzs == tab(rssz).xzs
347+
end
348+
end
349+
@testset "project! projectrand! project*! project*rand! apply!(...,sM*) consistency" begin
319350
s = S"XII -IZI IIY"
320351
_,_, r1 = project!(MixedDestabilizer(copy(s)), sMX(1))
321352
_,_, r2 = project!(copy(s), P"XII")
322-
_,_, r3 = project!(MixedDestabilizer(copy(s)), sMX(1))
323-
_, r4 = projectrand!(copy(s), P"XII")
324-
r5 = bitview(apply!(Register(copy(s), [0]),sMX(1)))[1]
325-
@test r1 == r2 == r3 == r4 == r5
353+
_, r3 = projectrand!(copy(s), P"XII")
354+
r4 = bitview(apply!(Register(copy(s), [0]),sMX(1)))[1]
355+
_, _, r5 = projectX!(copy(s), 1)
356+
_, r6 = projectXrand!(copy(s), 1)
357+
@test r1 == r2 == r3 == r4 == r5 == r6
326358
_,_, r1 = project!(MixedDestabilizer(copy(s)), sMZ(2))
327359
_,_, r2 = project!(copy(s), P"IZI")
328-
_,_, r3 = project!(MixedDestabilizer(copy(s)), sMZ(2))
329-
_, r4 = projectrand!(copy(s), P"IZI")
330-
r5 = bitview(apply!(Register(copy(s), [0]),sMZ(2)))[1]
331-
@test r1%2 == r2%2 == r3%2 == r4%2 == r5
360+
_, r3 = projectrand!(copy(s), P"IZI")
361+
r4 = bitview(apply!(Register(copy(s), [0]),sMZ(2)))[1]
362+
_, _, r5 = projectZ!(copy(s), 2)
363+
_, r6 = projectZrand!(copy(s), 2)
364+
@test r1%2 == r2%2 == r3%2 == r4 == r5%2 == r6%2
332365
_,_, r1 = project!(MixedDestabilizer(copy(s)), sMY(3))
333366
_,_, r2 = project!(copy(s), P"IIY")
334-
_,_, r3 = project!(MixedDestabilizer(copy(s)), sMY(3))
335-
_, r4 = projectrand!(copy(s), P"IIY")
336-
r5 = bitview(apply!(Register(copy(s), [0]),sMY(3)))[1]
337-
@test r1 == r2 == r3 == r4 == r5
367+
_, r3 = projectrand!(copy(s), P"IIY")
368+
r4 = bitview(apply!(Register(copy(s), [0]),sMY(3)))[1]
369+
_, _, r5 = projectY!(copy(s), 3)
370+
_, r6 = projectYrand!(copy(s), 3)
371+
@test r1 == r2 == r3 == r4 == r5 == r6
338372
end
339373
@testset "projectremoverand!" begin
340374
for n in test_sizes

0 commit comments

Comments
 (0)