Skip to content

Commit 94ddf62

Browse files
jeffwackapkilleKrastanov
authored
start of QuantumToolboxExt (#121)
Co-authored-by: apkille <[email protected]> Co-authored-by: Stefan Krastanov <[email protected]>
1 parent 09d3659 commit 94ddf62

File tree

8 files changed

+163
-8
lines changed

8 files changed

+163
-8
lines changed

.github/workflows/downgrade.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- uses: julia-actions/setup-julia@v1
2222
with:
2323
version: ${{ matrix.version }}
24-
- uses: cjdoris/julia-downgrade-compat-action@v1
24+
- uses: julia-actions/julia-downgrade-compat@v2
2525
with:
2626
skip: Pkg,TOML,InteractiveUtils,Random,LinearAlgebra
2727
- uses: julia-actions/cache@v2

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## v0.4.12 - dev
44

55
- Add Gabs extension for numerical translations of symbolic Gaussian states and operators.
6+
- Add QuantumToolbox extension for state vector translations.
67

78
## v0.4.11 - 2025-06-22
89

Project.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,26 @@ TermInterface = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
1717
Gabs = "0eb812ee-a11f-4f5e-b8d4-bb8a44f06f50"
1818
QuantumClifford = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
1919
QuantumOpticsBase = "4f57444f-1401-5e15-980d-4471b28d5678"
20+
QuantumToolbox = "6c2fb7c5-b903-41d2-bc5e-5a7c320b9fab"
2021

2122
[extensions]
2223
GabsExt = "Gabs"
2324
MixedCliffordOpticsExt = ["QuantumClifford", "QuantumOpticsBase"]
2425
QuantumCliffordExt = "QuantumClifford"
2526
QuantumOpticsExt = "QuantumOpticsBase"
27+
QuantumToolboxExt = "QuantumToolbox"
2628

2729
[compat]
28-
Gabs = "1.3.1"
30+
Gabs = "1.3.2"
2931
Latexify = "0.16"
3032
LinearAlgebra = "1.9"
3133
MacroTools = "0.5.13"
3234
PrecompileTools = "1.2"
33-
QuantumClifford = "0.8.19, 0.9, 0.10"
34-
QuantumInterface = "0.3.7, 0.4.1"
35-
QuantumOpticsBase = "0.4.22, 0.5"
36-
SymbolicUtils = "3.7"
35+
QuantumClifford = "0.9.4, 0.10"
36+
QuantumInterface = "0.4.1"
37+
QuantumOpticsBase = "0.5.6"
38+
QuantumToolbox = "0.34.0"
39+
SymbolicUtils = "3.13"
3740
Symbolics = "6"
3841
TermInterface = "2"
3942
julia = "1.10"
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
module QuantumToolboxExt
2+
3+
using QuantumToolbox
4+
using QuantumSymbolics
5+
using QuantumSymbolics:
6+
HGate, XGate, YGate, ZGate, CPHASEGate, CNOTGate, PauliP, PauliM,
7+
XCXGate, XCYGate, XCZGate, YCXGate, YCYGate, YCZGate, ZCXGate, ZCYGate, ZCZGate,
8+
XBasisState, YBasisState, ZBasisState,
9+
NumberOp, CreateOp, DestroyOp,
10+
FockState,
11+
MixedState, IdentityOp, STensor,
12+
qubit_basis
13+
import QuantumSymbolics: express, express_nolookup
14+
using TermInterface
15+
using TermInterface: isexpr, head, operation, arguments, metadata
16+
17+
const _l0 = QuantumToolbox.basis(2,0)
18+
const _l1 = QuantumToolbox.basis(2,1)
19+
const _s₊ = (_l0+_l1)/√2
20+
const _s₋ = (_l0-_l1)/√2
21+
const _i₊ = (_l0+im*_l1)/√2
22+
const _i₋ = (_l0-im*_l1)/√2
23+
const _σ₊ = QuantumToolbox.sigmap()
24+
const _σ₋ = QuantumToolbox.sigmam()
25+
const _l00 = QuantumToolbox.proj(_l0)
26+
const _l11 = QuantumToolbox.proj(_l1)
27+
const _id = QuantumToolbox.qeye(2)
28+
const _z = QuantumToolbox.sigmaz()
29+
const _x = QuantumToolbox.sigmax()
30+
const _y = QuantumToolbox.sigmay()
31+
const _hadamard = (_z+_x)/√2
32+
const _cnot = QuantumToolbox.tensor(_l00,_id) + QuantumToolbox.tensor(_l11,_x)
33+
const _cphase = QuantumToolbox.tensor(_l00,_id) + QuantumToolbox.tensor(_l11,_z)
34+
const _phase = _l00 + im*_l11
35+
const _iphase = _l00 - im*_l11
36+
37+
const _f0₂ = QuantumToolbox.basis(2, 0)
38+
const _f1₂ = QuantumToolbox.basis(2, 1)
39+
const _ad₂ = QuantumToolbox.create(2)
40+
const _a₂ = QuantumToolbox.destroy(2)
41+
const _n₂ = QuantumToolbox.num(2)
42+
43+
express_nolookup(::HGate, ::QuantumToolboxRepr) = _hadamard
44+
express_nolookup(::XGate, ::QuantumToolboxRepr) = _x
45+
express_nolookup(::YGate, ::QuantumToolboxRepr) = _y
46+
express_nolookup(::ZGate, ::QuantumToolboxRepr) = _z
47+
express_nolookup(::CPHASEGate, ::QuantumToolboxRepr) = _cphase
48+
express_nolookup(::CNOTGate, ::QuantumToolboxRepr) = _cnot
49+
50+
const xyzopdict = Dict(:X=>_x, :Y=>_y, :Z=>_z)
51+
const xyzstatedict = Dict(:X=>(_s₊,_s₋),:Y=>(_i₊,_i₋),:Z=>(_l0,_l1))
52+
for control in (:X, :Y, :Z)
53+
for target in (:X, :Y, :Z)
54+
k1, k2 = xyzstatedict[control]
55+
o = xyzopdict[target]
56+
gate = QuantumToolbox.tensor(proj(k1),_id) + QuantumToolbox.tensor(proj(k2),o)
57+
structname = Symbol(control,"C",target,"Gate")
58+
let gate=copy(gate)
59+
@eval express_nolookup(::$(structname), ::QuantumToolboxRepr) = $gate
60+
end
61+
end
62+
end
63+
64+
express_nolookup(::PauliM, ::QuantumToolboxRepr) = _σ₋
65+
express_nolookup(::PauliP, ::QuantumToolboxRepr) = _σ₊
66+
67+
express_nolookup(s::XBasisState, ::QuantumToolboxRepr) = (_s₊,_s₋)[s.idx]
68+
express_nolookup(s::YBasisState, ::QuantumToolboxRepr) = (_i₊,_i₋)[s.idx]
69+
express_nolookup(s::ZBasisState, ::QuantumToolboxRepr) = (_l0,_l1)[s.idx]
70+
71+
express_nolookup(s::FockState, r::QuantumToolboxRepr) = fock(r.cutoff, s.idx)
72+
express_nolookup(s::CoherentState, r::QuantumToolboxRepr) = coherent(r.cutoff,s.alpha)
73+
express_nolookup(s::SqueezedState, r::QuantumToolboxRepr) = (c = r.cutoff; squeeze(c, s.z)*fock(c, 0))
74+
express_nolookup(o::NumberOp, r::QuantumToolboxRepr) = num(r.cutoff)
75+
express_nolookup(o::CreateOp, r::QuantumToolboxRepr) = create(r.cutoff)
76+
express_nolookup(o::DestroyOp, r::QuantumToolboxRepr) = destroy(r.cutoff)
77+
express_nolookup(o::DisplaceOp, r::QuantumToolboxRepr) = displace(r.cutoff, o.alpha)
78+
express_nolookup(o::SqueezeOp, r::QuantumToolboxRepr) = squeeze(r.cutoff, o.z)
79+
express_nolookup(x::MixedState, r::QuantumToolboxRepr) = (l = length(x.basis); return qeye(l)/l)
80+
express_nolookup(x::IdentityOp, r::QuantumToolboxRepr) = qeye(length(x.basis))
81+
82+
express_nolookup(s::SOuterKetBra, r::QuantumToolboxRepr) = proj(express(s.ket, r), express(s.bra, r))
83+
express_nolookup(s::STensor, r::QuantumToolboxRepr) = QuantumToolbox.tensor((express(i, r) for i in s.terms)...)
84+
85+
end

src/QSymbolicsBase/QSymbolicsBase.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import QuantumInterface:
2222

2323
export SymQObj,QObj,
2424
AbstractRepresentation,AbstractUse,
25-
QuantumOpticsRepr,QuantumMCRepr,CliffordRepr,GabsRepr,
25+
QuantumOpticsRepr,QuantumMCRepr,CliffordRepr,GabsRepr,QuantumToolboxRepr,
2626
UseAsState,UseAsObservable,UseAsOperation,
2727
apply!,
2828
express,
@@ -52,6 +52,15 @@ export SymQObj,QObj,
5252
isunitary,
5353
KrausRepr,kraus
5454

55+
56+
57+
58+
# TODO: move this to QuantumInterface
59+
"""Representation using kets, bras, density matrices, and superoperators governed by `QuantumToolbox.jl`."""
60+
Base.@kwdef struct QuantumToolboxRepr <: AbstractRepresentation
61+
cutoff::Int = 2
62+
end
63+
5564
##
5665
# Metadata cache helpers
5766
##

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ QuantumClifford = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
1212
QuantumInterface = "5717a53b-5d69-4fa3-b976-0bf2f97ca1e5"
1313
QuantumOptics = "6e0679c1-51ea-5a7c-ac74-d61b76210b0c"
1414
QuantumOpticsBase = "4f57444f-1401-5e15-980d-4471b28d5678"
15+
QuantumToolbox = "6c2fb7c5-b903-41d2-bc5e-5a7c320b9fab"
1516
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1617
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1718
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"

test/test_conditional_cliffords.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
@testitem "Conditional Cliffords" begin
22
using QuantumClifford
33
using QuantumOpticsBase
4+
using QuantumToolbox
45
using LinearAlgebra
56

7+
P = [1. 0. 0. 0.; # Maps QuantumOptics to QuantumToolbox basis
8+
0. 0. 1. 0.;
9+
0. 1. 0. 0.;
10+
0. 0. 0. 1.]
611
for control in (:X, :Y, :Z)
712
for target in (:X, :Y, :Z)
813
structname = Symbol(control,"C",target,"Gate")
914
gate = eval(structname)()
1015
gate_qo = express(gate, QuantumOpticsRepr())
11-
gate_qc = Operator(CliffordOperator(express(gate, CliffordRepr(), UseAsOperation())(1,2),2))
16+
gate_qc = QuantumOpticsBase.Operator(CliffordOperator(express(gate, CliffordRepr(), UseAsOperation())(1,2),2))
17+
gate_qt = express(gate, QuantumToolboxRepr())
1218
@test gate_qo gate_qc
19+
@test P * gate_qo.data * P' gate_qt.data atol = 1e-10
1320
end
1421
end
1522
end

test/test_quantumtoolbox.jl

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
@testitem "QuantumToolbox objects" begin
2+
using QuantumSymbolics
3+
using QuantumToolbox
4+
5+
α = rand(ComplexF64)
6+
n = rand(1:9)
7+
8+
@testset "Fock states and operators" begin
9+
repr = QuantumToolboxRepr(cutoff = 10)
10+
@test express(vac, repr) fock(10, 0)
11+
@test express(FockState(n), repr) fock(10, n)
12+
@test express(CoherentState(α), repr) coherent(10, α)
13+
@test express(SqueezedState(α), repr) squeeze(10, α) * fock(10, 0)
14+
@test express(NumberOp(), repr) num(10)
15+
@test express(CreateOp(), repr) create(10)
16+
@test express(DestroyOp(), repr) destroy(10)
17+
@test express(DisplaceOp(α), repr) displace(10, α)
18+
end
19+
20+
@testset "Quantum gates" begin
21+
repr = QuantumToolboxRepr()
22+
@test express(H, repr) to_sparse(Qobj([1.0+0.0im 1.; 1. -1.]/√2))
23+
@test express(X, repr) sigmax()
24+
@test express(Y, repr) sigmay()
25+
@test express(Z, repr) sigmaz()
26+
@test express(CPHASE, repr) Qobj([1.0+0.0im 0. 0. 0.; 0. 1. 0. 0.; 0. 0. 1. 0.; 0. 0. 0. -1.], dims = (2,2))
27+
@test express(CNOT, repr) Qobj([1.0+0.0im 0. 0. 0.; 0. 1. 0. 0.; 0. 0. 0. 1.; 0. 0. 1. 0.], dims = (2,2))
28+
@test express(QuantumSymbolics.PauliM(), repr) sigmam()
29+
@test express(QuantumSymbolics.PauliP(), repr) sigmap()
30+
end
31+
32+
@testset "Pure states" begin
33+
repr = QuantumToolboxRepr()
34+
@test express(XBasisState(1, SpinBasis(1//2)), repr) Qobj([1.0+0.0im, 1.0]/√2)
35+
@test express(XBasisState(2, SpinBasis(1//2)), repr) Qobj([1.0+0.0im, -1.0]/√2)
36+
@test express(YBasisState(1, SpinBasis(1//2)), repr) Qobj([1.0+0.0im, 1.0im]/√2)
37+
@test express(YBasisState(2, SpinBasis(1//2)), repr) Qobj([1.0+0.0im, -1.0im]/√2)
38+
@test express(ZBasisState(1, SpinBasis(1//2)), repr) Qobj([1.0+0.0im, 0.0])
39+
@test express(ZBasisState(2, SpinBasis(1//2)), repr) Qobj([0.0+0.0im, 1.0])
40+
end
41+
42+
@testset "Linear algebra" begin
43+
repr = QuantumToolboxRepr()
44+
@test express(QuantumSymbolics.tensor(X, Y) + QuantumSymbolics.tensor(Z, X), repr) QuantumToolbox.tensor(express(X, repr), express(Y, repr)) + QuantumToolbox.tensor(express(Z, repr), express(X, repr))
45+
@test express(CreateOp() * (FockState(1) + CoherentState(α)), repr) express(CreateOp(), repr) * (express(FockState(1), repr) + express(CoherentState(α), repr))
46+
@test express(IdentityOp(QuantumSymbolics.tensor(X, Y)), repr) qeye(4)
47+
@test express(MixedState(QuantumSymbolics.tensor(X, Y)), repr) qeye(4) / 4
48+
end
49+
end

0 commit comments

Comments
 (0)