Skip to content

Commit

Permalink
fix incorrect scaling of Operator(::CliffordOperator) conversion and …
Browse files Browse the repository at this point in the history
…some plotting improvements (#156)

* fix incorrect scaling of Operator(::CliffordOperator) conversion

* plotting improvements
  • Loading branch information
Krastanov authored Jul 18, 2023
1 parent 0ee56f3 commit 8621163
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 36 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

# News

## v0.8.13 - dev
## v0.8.13

- **(fix)** There was a bug with incorrect scaling for `Operator(::CliffordOperator)` conversions.
- A few more features to the `ECC` module's circuit generation routines.
- Quantikz circuit plotting improvements to `CliffordOperator` and `s*CY` and `sYC*`.

## v0.8.12 - 2023-07-12

Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumClifford"
uuid = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
authors = ["Stefan Krastanov <stefan@krastanov.org>"]
version = "0.8.12"
version = "0.8.13"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand Down Expand Up @@ -44,7 +44,7 @@ Makie = "0.19"
Nemo = "0.34, 0.35"
Plots = "1.38.0"
PrecompileTools = "1"
Quantikz = "1.2"
Quantikz = "1.3"
QuantumInterface = "0.3.0"
QuantumOpticsBase = "0.4"
SIMD = "3.4.0"
Expand Down
50 changes: 25 additions & 25 deletions ext/QuantumCliffordQOpticsExt/QuantumCliffordQOpticsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ function cliff_to_unitary(cliff)
b = bell(n, localorder=true)
apply!(b, cliff, 1:n)
ψ = Ket(b)
Operator(SpinBasis(1//2)^n,reshape.data, (2^n,2^n)))
Operator(SpinBasis(1//2)^n,reshape.data * sqrt(2)^n, (2^n,2^n)))
end

"""
Expand All @@ -163,24 +163,24 @@ Convert a `QuantumClifford.CliffordOperator` to `QuantumOptics.Operator`.
julia> Operator(tHadamard)
Operator(dim=2x2)
basis: Spin(1/2)
0.5+0.0im 0.5+0.0im
0.5+0.0im -0.5+0.0im
0.707107+0.0im 0.707107+0.0im
0.707107+0.0im -0.707107+0.0im
julia> Operator(tId1⊗tHadamard)
Operator(dim=4x4)
basis: [Spin(1/2) ⊗ Spin(1/2)]
0.353553+0.0im 0.0+0.0im 0.353553+0.0im 0.0+0.0im
0.0+0.0im 0.353553+0.0im 0.0+0.0im 0.353553+0.0im
0.353553+0.0im 0.0+0.0im -0.353553+0.0im 0.0+0.0im
0.0+0.0im 0.353553+0.0im 0.0+0.0im -0.353553+0.0im
0.707107+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.707107+0.0im
0.707107+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im -0.707107+0.0im
julia> Operator(tCNOT)
Operator(dim=4x4)
basis: [Spin(1/2) ⊗ Spin(1/2)]
0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im
0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im
0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im
1.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im
0.0+0.0im 0.0+0.0im 1.0+0.0im 0.0+0.0im
0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im
```
This conversion expects a dense tableau of type [`CliffordOperator`](@ref) as input.
Expand All @@ -191,36 +191,36 @@ If you are working with some of the implicit (a.k.a. small/sparse/symbolic) type
julia> Operator(CliffordOperator(sHadamard))
Operator(dim=2x2)
basis: Spin(1/2)
0.5+0.0im 0.5+0.0im
0.5+0.0im -0.5+0.0im
0.707107+0.0im 0.707107+0.0im
0.707107+0.0im -0.707107+0.0im
julia> Operator(CliffordOperator(sHadamard(1), 1))
Operator(dim=2x2)
basis: Spin(1/2)
0.5+0.0im 0.5+0.0im
0.5+0.0im -0.5+0.0im
0.707107+0.0im 0.707107+0.0im
0.707107+0.0im -0.707107+0.0im
julia> Operator(CliffordOperator(sHadamard(1), 2))
Operator(dim=4x4)
basis: [Spin(1/2) ⊗ Spin(1/2)]
0.353553+0.0im 0.353553+0.0im 0.0+0.0im 0.0+0.0im
0.353553+0.0im -0.353553+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.353553+0.0im 0.353553+0.0im
0.0+0.0im 0.0+0.0im 0.353553+0.0im -0.353553+0.0im
0.707107+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im
0.707107+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.707107+0.0im
0.0+0.0im 0.0+0.0im 0.707107+0.0im -0.707107+0.0im
julia> Operator(CliffordOperator(sHadamard(2), 2))
Operator(dim=4x4)
basis: [Spin(1/2) ⊗ Spin(1/2)]
0.353553+0.0im 0.0+0.0im 0.353553+0.0im 0.0+0.0im
0.0+0.0im 0.353553+0.0im 0.0+0.0im 0.353553+0.0im
0.353553+0.0im 0.0+0.0im -0.353553+0.0im 0.0+0.0im
0.0+0.0im 0.353553+0.0im 0.0+0.0im -0.353553+0.0im
0.707107+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.707107+0.0im
0.707107+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im -0.707107+0.0im
julia> Operator(CliffordOperator(sHadamard(2), 1, compact=true))
Operator(dim=2x2)
basis: Spin(1/2)
0.5+0.0im 0.5+0.0im
0.5+0.0im -0.5+0.0im
0.707107+0.0im 0.707107+0.0im
0.707107+0.0im -0.707107+0.0im
```
"""
function Operator(c::CliffordOperator)
Expand Down
11 changes: 4 additions & 7 deletions ext/QuantumCliffordQuantikzExt/QuantumCliffordQuantikzExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,12 @@ Quantikz.QuantikzOp(op::sCPHASE) = Quantikz.CPHASE(affectedqubits(op)...)
Quantikz.QuantikzOp(op::sSWAP) = Quantikz.SWAP(affectedqubits(op)...)
Quantikz.QuantikzOp(op::sZCZ) = Quantikz.CPHASE(affectedqubits(op)...)
Quantikz.QuantikzOp(op::sXCX) = Quantikz.MultiControl([],[],collect(affectedqubits(op)),[]) # TODO make Quantikz work with tuples and remove the collect
Quantikz.QuantikzOp(op::sZCY) = Quantikz.MultiControlU("Y",affectedqubits(op)...)
Quantikz.QuantikzOp(op::sZCY) = Quantikz.MultiControlU("-iY",affectedqubits(op)...)
Quantikz.QuantikzOp(op::sYCZ) = Quantikz.MultiControlU("Y",reverse(affectedqubits(op))...)
Quantikz.QuantikzOp(op::sXCY) = Quantikz.MultiControlU("-iY",[],[],[affectedqubits(op)[2]],[affectedqubits(op)[1]])
Quantikz.QuantikzOp(op::sYCX) = Quantikz.MultiControlU("Y",[],[],[affectedqubits(op)[1]],[affectedqubits(op)[2]])
function Quantikz.QuantikzOp(op::AbstractTwoQubitOperator)
T = typeof(op)
if T in (sXCY,sYCX,sYCY,sYCZ,sZCY)
return Quantikz.U(string(T),collect(affectedqubits(op))) # TODO make Quantikz work with tuples and remove the collect
else
return Quantikz.U("{U}",collect(affectedqubits(op))) # TODO make Quantikz work with tuples and remove the collect
end
return Quantikz.U("{U}",collect(affectedqubits(op))) # TODO make Quantikz work with tuples and remove the collect
end
Quantikz.QuantikzOp(op::BellMeasurement) = Quantikz.ParityMeasurement(["\\mathtt{$(string(typeof(o))[3])}" for o in op.measurements], collect(affectedqubits(op))) # TODO make Quantikz work with tuples and remove the collect
Quantikz.QuantikzOp(op::NoisyBellMeasurement) = Quantikz.QuantikzOp(op.meas)
Expand Down
1 change: 1 addition & 0 deletions src/affectedqubits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ affectedqubits(g::PauliMeasurement) = 1:length(g.pauli)
affectedqubits(p::PauliOperator) = 1:length(p)
affectedqubits(m::Union{AbstractMeasurement,sMRX,sMRY,sMRZ}) = (m.qubit,)
affectedqubits(v::VerifyOp) = v.indices
affectedqubits(c::CliffordOperator) = 1:nqubits(c)

affectedbits(o) = ()
affectedbits(m::sMRZ) = (m.bit,)
Expand Down
3 changes: 2 additions & 1 deletion test/test_quantumoptics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ end
ψ₁ = Ket(stab)
ψ₂ = Ket(apply!(stab,cliff))
# test they are equal up to a phase
@test all(x->isnan(x)||abs(x)1/sqrt(2^n) , (U*ψ₁).data ./ ψ₂.data)
@test all(x->isnan(x)||abs(x)1 , (U*ψ₁).data ./ ψ₂.data)
@test abs(det(U.data))1
end
end
end
Expand Down
30 changes: 30 additions & 0 deletions test/test_symcontrolled.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Test
using QuantumClifford
using QuantumOpticsBase

function transform_Zbasis(qubit)
transformations = Dict(:X => [sHadamard(qubit),], :Y => [sInvPhase(qubit),sHadamard(qubit)], :Z => [sHadamard(qubit), sHadamard(qubit)])
Expand Down Expand Up @@ -96,3 +97,32 @@ end
@test gate1dense == gate2dense
end
end

@testset "Ket-based definition" begin
for control in (:X, :Y, :Z)
for target in (:X, :Y, :Z)
s = Stabilizer(QuantumClifford._T_str(string(control)))
k1 = Ket(s)
s.tab.phases[1] = 0x2
k2 = Ket(s)
i = Operator(tId1)
o = Operator(CliffordOperator(eval(Symbol(:s,target,))(1),1))
gate = projector(k1)i + (target==:Y ? -im : 1) * projector(k2)o
implemented_gate = Operator(CliffordOperator(eval(Symbol(:s,control,:C,target))(1,2),2))
@test gateimplemented_gate

target, control = control, target
s = Stabilizer(QuantumClifford._T_str(string(control)))
k1 = Ket(s)
s.tab.phases[1] = 0x2
k2 = Ket(s)
i = Operator(tId1)
o = Operator(CliffordOperator(eval(Symbol(:s,target,))(1),1))
gate_perm = projector(k1)i + (target==:Y ? -im : 1) * projector(k2)o
implemented_gate_perm = Operator(CliffordOperator(eval(Symbol(:s,control,:C,target))(1,2),2))
@test gate_permimplemented_gate_perm

@test permutesystems(gate_perm,[2,1])gate
end
end
end

2 comments on commit 8621163

@Krastanov
Copy link
Member Author

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/87760

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.8.13 -m "<description of version>" 8621163f536090544d505b051f316169660bf984
git push origin v0.8.13

Please sign in to comment.