Skip to content

Commit 95c0819

Browse files
authored
bug in observable when nsubsystems(state)==nsubsystems(op) but the indices are disordered (#212)
1 parent 06df037 commit 95c0819

File tree

7 files changed

+68
-32
lines changed

7 files changed

+68
-32
lines changed

.typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[default.extend-words]
22
ket = "ket"
3+
BA = "BA"
34

45
[files]
56
extend-exclude = ["src/StatesZoo/zalm/*.nb"]

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Makie = "0.21, 0.22"
4646
NetworkLayout = "0.4.4"
4747
PrecompileTools = "1"
4848
Printf = "1"
49-
QuantumClifford = "0.9.9"
49+
QuantumClifford = "0.9.19"
5050
QuantumInterface = "0.3.5"
5151
QuantumOptics = "1.1.0"
5252
QuantumOpticsBase = "0.5.3"

src/QuantumSavory.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,20 @@ using SumTypes: @sum_type, isvariant, @cases
2626
import Combinatorics
2727
using Combinatorics: powerset
2828

29-
import QuantumInterface: basis, tensor, , apply!, traceout!, nsubsystems,
30-
AbstractOperator, AbstractKet, AbstractSuperOperator, Basis, SpinBasis
29+
import QuantumClifford
30+
import QuantumClifford: MixedDestabilizer
31+
32+
import QuantumOpticsBase
33+
import QuantumOpticsBase: StateVector, Ket, Operator,
34+
basisstate, spinup, spindown, sigmap, sigmax, sigmay, sigmaz, destroy, spre, spost
35+
36+
import QuantumOptics
37+
import QuantumOptics: timeevolution
38+
39+
import QuantumInterface: basis, tensor, , apply!, traceout!, nsubsystems, permutesystems,
40+
projector, identityoperator, embed, dm, expect, ptrace,
41+
AbstractOperator, AbstractKet, AbstractSuperOperator,
42+
Basis, GenericBasis, CompositeBasis, SpinBasis
3143

3244
export apply!, traceout!, removebackref!, nsubsystems
3345
export project_traceout! #TODO should move to QuantumInterface

src/backends/clifford/clifford.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import QuantumClifford
2-
import QuantumClifford: MixedDestabilizer
3-
41
subsystemcompose(states::QuantumClifford.MixedDestabilizer...) = QuantumClifford.tensor(states...)
52

63
default_repr(::QuantumClifford.MixedDestabilizer) = CliffordRepr()

src/backends/clifford/express.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ end
2222
# This is a bit of a hack to work specifically with SProjector. If you start needing more of these for other types, consider doing a bit of a redesign. This all should pass through `express(...,::UseAsObservable)`.
2323
function observable(state::QuantumClifford.MixedDestabilizer, indices::Base.AbstractVecOrTuple{Int}, operation::SProjector)
2424
pstate = express(operation.ket, CliffordRepr())
25-
QuantumClifford.nqubits(state)==length(indices)==QuantumClifford.nqubits(pstate) || error("An attempt was made to measure a projection observable while using Clifford representation for the qubits. However, the qubits that are being observed are entangled with other qubits. Currently this is not supported. Consider tracing out the extra qubits or using Pauli observables that do not suffer from this embedding limitation.")
26-
dot(pstate, state)
25+
QuantumClifford.nqubits(state)==length(indices)==QuantumClifford.nqubits(pstate) || error("An attempt was made to measure a projection observable while using Clifford representation for the qubits. However, the qubits that are being observed are entangled with other qubits. Currently this is not supported. Consider tracing out the extra qubits or using Pauli observables that do not suffer from this embedding limitation. Message us on the issue tracker if you want this functionality implemented.")
26+
cstate = permutesystems(state, indices)
27+
dot(pstate, cstate)
2728
end

src/backends/quantumoptics/quantumoptics.jl

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
import QuantumOpticsBase
2-
import QuantumOpticsBase: GenericBasis, CompositeBasis,
3-
StateVector, AbstractSuperOperator, Ket, Operator,
4-
basisstate, spinup, spindown, sigmap, sigmax, sigmay, sigmaz, destroy,
5-
projector, identityoperator, embed, dm, expect, ptrace, spre, spost
6-
import QuantumOptics
7-
import QuantumOptics: timeevolution
8-
import QuantumInterface: nsubsystems
9-
101
const QOR = QuantumOpticsRepr()
112

123
subsystemcompose(states::Ket...) = tensor(states...)
@@ -22,8 +13,9 @@ ispadded(::Operator) = false
2213

2314
function observable(state::Union{<:Ket,<:Operator}, indices::Base.AbstractVecOrTuple{Int}, operation)
2415
operation = express(operation, QOR)
25-
e = basis(state)==basis(operation)
26-
op = e ? operation : embed(basis(state), indices, operation)
16+
# TODO if indices is ascending 1:n we can skip this embed -- such an improvement should be upstreamed to QuantumOpticsBase, so that embed is faster
17+
# TODO if nsubsystems(state) == 1 the embed should still work and be a no-op -- this should be upstreamed to QuantumInterface
18+
op = nsubsystems(state) == 1 ? operation : embed(basis(state), indices, operation)
2719
expect(op, state)
2820
end
2921

test/test_observable.jl

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
1-
@testitem "Observable" tags=[:observable] begin
1+
@testitem "Observable" begin
22

3-
const bell = StabilizerState("XX ZZ")
4-
# or equivalently `const bell = (Z₁⊗Z₁+Z₂⊗Z₂)/√2`,
5-
# however converting to stabilizer state for Clifford simulations
6-
# is not implemented (and can not be done efficiently).
3+
@testset "entangled observable" begin
4+
bell = StabilizerState("XX ZZ")
5+
# or equivalently `const bell = (Z₁⊗Z₁+Z₂⊗Z₂)/√2`,
6+
# however converting to stabilizer state for Clifford simulations
7+
# is not implemented (and can not be done efficiently).
78

8-
for rep in [QuantumOpticsRepr(), CliffordRepr()]
9-
a = Register(2,rep)
10-
initialize!(a[1:2], bell)
11-
@test observable(a[1:2], SProjector(bell)) 1.0
12-
@test observable(a[1:2], σˣσˣ) 1.0
13-
apply!(a[1], σʸ)
14-
@test observable(a[1:2], SProjector(bell)) 0.0
15-
@test observable(a[1:2], σˣσˣ) -1.0
9+
for rep in [QuantumOpticsRepr(), CliffordRepr()]
10+
a = Register(2,rep)
11+
initialize!(a[1:2], bell)
12+
@test observable(a[1:2], SProjector(bell)) 1.0
13+
@test observable(a[1:2], σˣσˣ) 1.0
14+
apply!(a[1], σʸ)
15+
@test observable(a[1:2], SProjector(bell)) 0.0
16+
@test observable(a[1:2], σˣσˣ) -1.0
17+
end
1618
end
19+
20+
@testset "separable observable with order flipping" begin
21+
A = StabilizerState("X")
22+
B = StabilizerState("Z")
23+
AB = StabilizerState("XI IZ")
24+
BA = StabilizerState("ZI IX")
25+
26+
for rep in [QuantumOpticsRepr(), CliffordRepr()]
27+
r1 = Register(2,rep)
28+
r2 = Register(2,rep)
29+
r12 = Register(2,rep)
30+
r21 = Register(2,rep)
31+
32+
initialize!(r1[1], A)
33+
initialize!(r2[2], B)
34+
initialize!(r12[1:2], AB)
35+
initialize!((r21[2], r21[1]), BA)
36+
37+
@test observable(r12[1:2], SProjector(AB)) 1.0
38+
if rep == CliffordRepr()
39+
@test_throws "entangled with other qubits" observable(r12[1], SProjector(A)) 1.0
40+
else
41+
@test observable(r12[1], SProjector(A)) 1.0
42+
end
43+
@test observable(r21[1:2], SProjector(AB)) 1.0
44+
@test_broken observable((r1[1], r2[2]), SProjector(AB)) 1.0
45+
@test observable(r1[1], SProjector(A)) 1.0
46+
@test observable(r2[2], SProjector(B)) 1.0
47+
end
48+
end
49+
1750
end

0 commit comments

Comments
 (0)