Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v0.4.12 - dev

- Add Gabs extension for numerical translations of symbolic Gaussian states and operators.
- Add rotation gates `Rot[X,Y,Z]Gate`.

## v0.4.11 - 2025-06-22

Expand Down
8 changes: 7 additions & 1 deletion ext/QuantumOpticsExt/QuantumOpticsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using QuantumInterface, QuantumOpticsBase
using QuantumInterface: samebases
using QuantumSymbolics
using QuantumSymbolics:
HGate, XGate, YGate, ZGate, CPHASEGate, CNOTGate, PauliP, PauliM,
HGate, XGate, YGate, ZGate, RotXGate, RotYGate, RotZGate, CPHASEGate, CNOTGate, PauliP, PauliM,
XCXGate, XCYGate, XCZGate, YCXGate, YCYGate, YCZGate, ZCXGate, ZCYGate, ZCZGate,
XBasisState, YBasisState, ZBasisState,
NumberOp, CreateOp, DestroyOp,
Expand All @@ -31,6 +31,9 @@ const _z = sigmaz(_b2)
const _x = sigmax(_b2)
const _y = sigmay(_b2)
const _hadamard = (sigmaz(_b2)+sigmax(_b2))/√2
_rotx(θ) = cos(θ/2)*_id - im*sin(θ/2)*_x
_roty(θ) = cos(θ/2)*_id - im*sin(θ/2)*_y
_rotz(θ) = cos(θ/2)*_id - im*sin(θ/2)*_z
const _cnot = _l00⊗_id + _l11⊗_x
const _cphase = _l00⊗_id + _l11⊗_z
const _phase = _l00 + im*_l11
Expand All @@ -47,6 +50,9 @@ express_nolookup(::HGate, ::QuantumOpticsRepr) = _hadamard
express_nolookup(::XGate, ::QuantumOpticsRepr) = _x
express_nolookup(::YGate, ::QuantumOpticsRepr) = _y
express_nolookup(::ZGate, ::QuantumOpticsRepr) = _z
express_nolookup(g::RotXGate, ::QuantumOpticsRepr) = _rotx(g.θ)
express_nolookup(g::RotYGate, ::QuantumOpticsRepr) = _roty(g.θ)
express_nolookup(g::RotZGate, ::QuantumOpticsRepr) = _rotz(g.θ)
express_nolookup(::CPHASEGate, ::QuantumOpticsRepr) = _cphase
express_nolookup(::CNOTGate, ::QuantumOpticsRepr) = _cnot

Expand Down
4 changes: 2 additions & 2 deletions src/QSymbolicsBase/QSymbolicsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export SymQObj,QObj,
SConjugate,STranspose,SProjector,SDagger,SInvOperator,SExpOperator,SVec,STrace,SPartialTrace,
MixedState,IdentityOp,
SApplyKet,SApplyBra,SMulOperator,SSuperOpApply,SCommutator,SAnticommutator,SBraKet,SOuterKetBra,
HGate,XGate,YGate,ZGate,CPHASEGate,CNOTGate,
HGate,XGate,YGate,ZGate,RotXGate,RotYGate,RotZGate,CPHASEGate,CNOTGate,
XBasisState,YBasisState,ZBasisState,FockState,CoherentState,SqueezedState,TwoSqueezedState,BosonicThermalState,
NumberOp,CreateOp,DestroyOp,PhaseShiftOp,DisplaceOp,SqueezeOp,
TwoSqueezeOp,BeamSplitterOp,
XCXGate,XCYGate,XCZGate,YCXGate,YCYGate,YCZGate,ZCXGate,ZCYGate,ZCZGate,
qsimplify,qsimplify_pauli,qsimplify_commutator,qsimplify_anticommutator,qsimplify_fock,
qsimplify,qsimplify_pauli,qsimplify_commutator,qsimplify_anticommutator,qsimplify_fock,qsimplify_rot,
qexpand,
isunitary,
KrausRepr,kraus
Expand Down
34 changes: 34 additions & 0 deletions src/QSymbolicsBase/predefined.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,40 @@ symbollabel(::HGate) = "H"
ishermitian(::HGate) = true
isunitary(::HGate) = true

abstract type AbstractRotGate <: AbstractSingleQubitGate end
ishermitian(::AbstractRotGate) = false
isunitary(::AbstractRotGate) = true
isexpr(::AbstractRotGate) = true
iscall(::AbstractRotGate) = true
arguments(x::AbstractRotGate) = [x.θ]

"""Rotation around the X axis"""
@withmetadata struct RotXGate <: AbstractRotGate
θ
end
operation(::RotXGate) = RotXGate
head(::RotXGate) = :RotXGate
children(x::RotXGate) = [:RotXGate, x.θ]
symbollabel(x::RotXGate) = "Rx($(x.θ))"

"""Rotation around the Y axis"""
@withmetadata struct RotYGate <: AbstractRotGate
θ
end
operation(::RotYGate) = RotYGate
head(::RotYGate) = :RotYGate
children(x::RotYGate) = [:RotYGate, x.θ]
symbollabel(x::RotYGate) = "Ry($(x.θ))"

"""Rotation around the Z axis"""
@withmetadata struct RotZGate <: AbstractRotGate
θ
end
operation(::RotZGate) = RotZGate
head(::RotZGate) = :RotZGate
children(x::RotZGate) = [:RotZGate, x.θ]
symbollabel(x::RotZGate) = "Rz($(x.θ))"

@withmetadata struct CNOTGate <: AbstractTwoQubitGate end
symbollabel(::CNOTGate) = "CNOT"
ishermitian(::CNOTGate) = true
Expand Down
24 changes: 23 additions & 1 deletion src/QSymbolicsBase/rules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,28 @@ RULES_FOCK = [
@rule(~o::_isa(TwoSqueezeOp) * ~k::isequal(vac ⊗ vac) => TwoSqueezedState((~o).z))
]

RULES_SIMPLIFY = [RULES_PAULI; RULES_COMMUTATOR; RULES_ANTICOMMUTATOR; RULES_FOCK]
RULES_ROT = [
@rule(~r::_isa(RotXGate) => I where iszero((~r).θ)),
@rule(~r::_isa(RotYGate) => I where iszero((~r).θ)),
@rule(~r::_isa(RotZGate) => I where iszero((~r).θ)),
@rule(~r::_isa(RotXGate) => (-im*X) where (~r).θ in [π, 1π]),
@rule(~r::_isa(RotYGate) => (-im*Y) where (~r).θ in [π, 1π]),
@rule(~r::_isa(RotZGate) => (-im*Z) where (~r).θ in [π, 1π]),
@rule(~r::_isa(RotXGate) => try RotXGate(mod((~r).θ, 4π)) catch end),
@rule(~r::_isa(RotYGate) => try RotYGate(mod((~r).θ, 4π)) catch end),
@rule(~r::_isa(RotZGate) => try RotZGate(mod((~r).θ, 4π)) catch end),
@rule(~r::_isa(RotXGate) => try (~r).θ ≥ 2π ? -RotXGate((~r).θ - 2π) : nothing catch end),
@rule(~r::_isa(RotYGate) => try (~r).θ ≥ 2π ? -RotYGate((~r).θ - 2π) : nothing catch end),
@rule(~r::_isa(RotZGate) => try (~r).θ ≥ 2π ? -RotZGate((~r).θ - 2π) : nothing catch end),
@rule(~r1::_isa(RotXGate) * ~r2::_isa(RotXGate) => try RotXGate((~r1).θ + (~r2).θ) catch end),
@rule(~r1::_isa(RotYGate) * ~r2::_isa(RotYGate) => try RotYGate((~r1).θ + (~r2).θ) catch end),
@rule(~r1::_isa(RotZGate) * ~r2::_isa(RotZGate) => try RotZGate((~r1).θ + (~r2).θ) catch end),
@rule(exp(~α * ~x::_isa(XGate)) => try if real(~α) == 0 RotXGate(-2imag(~α)) end catch end),
@rule(exp(~α * ~x::_isa(YGate)) => try if real(~α) == 0 RotYGate(-2imag(~α)) end catch end),
@rule(exp(~α * ~x::_isa(ZGate)) => try if real(~α) == 0 RotZGate(-2imag(~α)) end catch end)
]

RULES_SIMPLIFY = [RULES_PAULI; RULES_COMMUTATOR; RULES_ANTICOMMUTATOR; RULES_FOCK; RULES_ROT]

##
# Simplification rewriters
Expand All @@ -119,6 +140,7 @@ qsimplify_pauli = Chain(RULES_PAULI)
qsimplify_commutator = Chain(RULES_COMMUTATOR)
qsimplify_anticommutator = Chain(RULES_ANTICOMMUTATOR)
qsimplify_fock = Chain(RULES_FOCK)
qsimplify_rot = Chain(RULES_ROT)

"""
qsimplify(s; rewriter=nothing)
Expand Down
76 changes: 76 additions & 0 deletions test/test_rotation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@testitem "Test Rotation" begin
@testset "express tests" begin
using QuantumOptics
b = SpinBasis(1//2)

@test isapprox(express(RotXGate(π/2)), Operator(b, [1 -im; -im 1]/√2))
@test isapprox(express(RotYGate(π/2)), Operator(b, [1 -1; 1 1]/√2))
@test isapprox(express(RotZGate(π/2)), Operator(b, [1-im 0; 0 1+im]/√2))
end

@testset "Identity tests" begin
@test isequal(qsimplify(RotXGate(0), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotYGate(0), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotZGate(0), rewriter=qsimplify_rot), I)
end

@testset "Pauli tests" begin
@test isequal(qsimplify(RotXGate(π), rewriter=qsimplify_rot), -im*X)
@test isequal(qsimplify(RotYGate(π), rewriter=qsimplify_rot), -im*Y)
@test isequal(qsimplify(RotZGate(π), rewriter=qsimplify_rot), -im*Z)

@test isequal(qsimplify(RotXGate(1π), rewriter=qsimplify_rot), -im*X)
@test isequal(qsimplify(RotYGate(1π), rewriter=qsimplify_rot), -im*Y)
@test isequal(qsimplify(RotZGate(1π), rewriter=qsimplify_rot), -im*Z)
end

@testset "Fusion tests" begin
@test isequal(qsimplify(RotXGate(π/3) * RotXGate(π/3), rewriter=qsimplify_rot), RotXGate(2π/3))
@test isequal(qsimplify(RotYGate(π/3) * RotYGate(π/3), rewriter=qsimplify_rot), RotYGate(2π/3))
@test isequal(qsimplify(RotZGate(π/3) * RotZGate(π/3), rewriter=qsimplify_rot), RotZGate(2π/3))

@test isequal(qsimplify(RotXGate(π/2) * RotXGate(-π/2), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotYGate(π/2) * RotYGate(-π/2), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotZGate(π/2) * RotZGate(-π/2), rewriter=qsimplify_rot), I)

@test isequal(qsimplify(2 * RotXGate(π/2) * RotXGate(π/2), rewriter=qsimplify_rot), -2im*X)
@test isequal(qsimplify(2 * RotYGate(π/2) * RotYGate(π/2), rewriter=qsimplify_rot), -2im*Y)
@test isequal(qsimplify(2 * RotZGate(π/2) * RotZGate(π/2), rewriter=qsimplify_rot), -2im*Z)
end

@testset "Modulo tests" begin
@test isequal(qsimplify(RotXGate(2π), rewriter=qsimplify_rot), -I)
@test isequal(qsimplify(RotYGate(2π), rewriter=qsimplify_rot), -I)
@test isequal(qsimplify(RotZGate(2π), rewriter=qsimplify_rot), -I)

@test isequal(qsimplify(RotXGate(3π), rewriter=qsimplify_rot), im*X)
@test isequal(qsimplify(RotYGate(3π), rewriter=qsimplify_rot), im*Y)
@test isequal(qsimplify(RotZGate(3π), rewriter=qsimplify_rot), im*Z)

@test isequal(qsimplify(RotXGate(4π), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotYGate(4π), rewriter=qsimplify_rot), I)
@test isequal(qsimplify(RotZGate(4π), rewriter=qsimplify_rot), I)

@test isequal(qsimplify(RotXGate(5π), rewriter=qsimplify_rot), -im*X)
@test isequal(qsimplify(RotYGate(5π), rewriter=qsimplify_rot), -im*Y)
@test isequal(qsimplify(RotZGate(5π), rewriter=qsimplify_rot), -im*Z)

@test isequal(qsimplify(RotXGate(π) * RotXGate(π), rewriter=qsimplify_rot), -I)
@test isequal(qsimplify(RotYGate(π) * RotYGate(π), rewriter=qsimplify_rot), -I)
@test isequal(qsimplify(RotZGate(π) * RotZGate(π), rewriter=qsimplify_rot), -I)

@test isequal(qsimplify(2 * RotXGate(3π/2) * RotXGate(2π/2), rewriter=qsimplify_rot), -2RotXGate(π/2))
@test isequal(qsimplify(2 * RotYGate(3π/2) * RotYGate(2π/2), rewriter=qsimplify_rot), -2RotYGate(π/2))
@test isequal(qsimplify(2 * RotZGate(3π/2) * RotZGate(2π/2), rewriter=qsimplify_rot), -2RotZGate(π/2))
end

@testset "Exponential tests" begin
@test isequal(qsimplify(exp(-im * π/2 * X), rewriter=qsimplify_rot), -im*X)
@test isequal(qsimplify(exp(-im * π/2 * Y), rewriter=qsimplify_rot), -im*Y)
@test isequal(qsimplify(exp(-im * π/2 * Z), rewriter=qsimplify_rot), -im*Z)

@test isequal(qsimplify(2 * exp(-im * 2π/2 * X) * exp(-im * 5π/2 * X), rewriter=qsimplify_rot), 2im*X)
@test isequal(qsimplify(2 * exp(-im * 2π/2 * Y) * exp(-im * 5π/2 * Y), rewriter=qsimplify_rot), 2im*Y)
@test isequal(qsimplify(2 * exp(-im * 2π/2 * Z) * exp(-im * 5π/2 * Z), rewriter=qsimplify_rot), 2im*Z)
end
end
Loading