Skip to content

Add StateVectorRepr backend with tests and documentation #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ff40438
Update QuantumOpticsExt.jl
phantmgx May 29, 2025
4fa4eba
Add test_statevectorrepr.jl for StateVectorRepr tests
phantmgx May 30, 2025
3cb77e2
Update test_statevectorrepr.jl to use @testitem
phantmgx May 30, 2025
72622a9
Update index.md
phantmgx May 30, 2025
e9ec426
Add QuantumOptics as a weak dependency for QuantumOpticsExt
phantmgx May 30, 2025
1188360
Update CHANGELOG.md
phantmgx May 30, 2025
fac7b79
Fix UndefVarError by replacing AbstractSymbolic with AbstractQuantumO…
phantmgx May 30, 2025
119d511
Fix UndefVarError by replacing AbstractQuantumObject with SymbolicUti…
phantmgx May 30, 2025
952b77e
using SymbolicUtils
phantmgx May 30, 2025
77f30db
Update Project.toml
phantmgx May 30, 2025
125b52e
Update Project.toml
phantmgx May 30, 2025
ff4475b
Update Project.toml
phantmgx May 30, 2025
c0e0cb9
Update Project.toml
phantmgx May 30, 2025
e1d79c8
Update Project.toml
phantmgx May 30, 2025
eed6db7
Update Project.toml
phantmgx May 31, 2025
594d0bc
Update QuantumOpticsExt.jl
phantmgx May 31, 2025
e60a229
Update Project.toml
phantmgx May 31, 2025
372a768
Update Project.toml
phantmgx May 31, 2025
d21161f
Update Project.toml
phantmgx May 31, 2025
a388036
Update Project.toml
phantmgx May 31, 2025
e5263b7
Update ci.yml
phantmgx May 31, 2025
9b9f248
Update Project.toml
phantmgx May 31, 2025
e7365f3
Update ci.yml
phantmgx May 31, 2025
d63df5c
Update Project.toml
phantmgx May 31, 2025
175d5c3
Update Project.toml
phantmgx May 31, 2025
c524dde
Update Project.toml
phantmgx May 31, 2025
cc78eb5
Update ci-julia-nightly.yml
phantmgx May 31, 2025
808a8eb
Update downgrade.yml
phantmgx May 31, 2025
3d2d507
Update ci-julia-nightly.yml
phantmgx May 31, 2025
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# News

## [Unreleased]
### Added
- New `StateVectorRepr` backend for converting symbolic quantum objects to numerical vectors/matrices using `QuantumOpticsRepr` (Conversion of symbolic objects to base linear algebra objects (vectors, matrices, sparse matrices, etc)) (#118).

## v0.4.10 - 2025-05-11

- Polish `Base.show` methods for application products and scaled quantum objects.
Expand Down
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ TermInterface = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
[weakdeps]
QuantumClifford = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
QuantumOpticsBase = "4f57444f-1401-5e15-980d-4471b28d5678"
QuantumOptics = "6e4d0e0e-3d2e-5f0e-8f3f-2b5b8e8d2f1e"
Copy link
Member

Choose a reason for hiding this comment

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

QuantumOpticsBase should be sufficient. I do not think you need QuantumOptics.

Copy link
Author

Choose a reason for hiding this comment

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

thanks i have removed that line now


[extensions]
MixedCliffordOpticsExt = ["QuantumClifford", "QuantumOpticsBase"]
QuantumCliffordExt = "QuantumClifford"
QuantumOpticsExt = "QuantumOpticsBase"
QuantumOpticsExt = ["QuantumOpticsBase", "QuantumOptics"]

[compat]
Latexify = "0.16"
Expand All @@ -29,6 +30,7 @@ MacroTools = "0.5.13"
PrecompileTools = "1.2"
QuantumClifford = "0.8.19, 0.9"
QuantumInterface = "0.3.7"
QuantumOptics = "0.9"
QuantumOpticsBase = "0.4.22, 0.5"
SymbolicUtils = "3.7"
Symbolics = "6"
Expand Down
15 changes: 15 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,18 @@ express(MixedState(X1)/2+SProjector(Z1)/2, CliffordRepr())
!!! warning "Stabilizer state expressions"

The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`projector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices.

## Backends

`QuantumSymbolics.jl` supports multiple numerical backends via the `express` API. In addition to structured representations like `QuantumOpticsRepr` and `CliffordRepr`, the new `StateVectorRepr` backend converts symbolic objects to basic linear algebra objects:

```julia
julia> express(X1, StateVectorRepr())
2-element Vector{ComplexF64}:
0.7071067811865475 + 0.0im
0.7071067811865475 + 0.0im

julia> express(Z1, StateVectorRepr())
2×2 Matrix{ComplexF64}:
1.0+0.0im 0.0+0.0im
0.0+0.0im -1.0+0.0im
26 changes: 26 additions & 0 deletions ext/QuantumOpticsExt/QuantumOpticsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import QuantumSymbolics: express, express_nolookup
using TermInterface
using TermInterface: isexpr, head, operation, arguments, metadata

using SymbolicUtils

const _b2 = SpinBasis(1//2)
const _l0 = spinup(_b2)
const _l1 = spindown(_b2)
Expand Down Expand Up @@ -100,4 +102,28 @@ express_nolookup(s::SOuterKetBra, r::QuantumOpticsRepr) = projector(express(s.ke

include("should_upstream.jl")

"""
StateVectorRepr(config=nothing)

A custom backend for `QuantumSymbolics.express`. Converts symbolic quantum
objects into Julia's `Vector{ComplexF64}` (kets) or `Matrix{ComplexF64}` (operators).

Internally uses `QuantumOptics.QuantumOpticsRepr` and extracts `.data`.
An optional `config` (e.g., `(cutoff=4,)`) is forwarded to `QuantumOptics.QuantumOpticsRepr`.
"""
struct StateVectorRepr{C}
config::C
StateVectorRepr(config=nothing) = new{typeof(config)}(config)
end
Copy link
Member

Choose a reason for hiding this comment

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

The type parameterization here is a bit overly complicated. Any reason to set it up like this? Check out the QuantumOpticsRepr -- it can be a good reference for how to do it in a simpler way.


function QuantumSymbolics.express(sym_obj::SymbolicUtils.Symbolic, backend::StateVectorRepr)
qo_repr = if backend.config isa Nothing
QuantumOptics.QuantumOpticsRepr()
else
QuantumOptics.QuantumOpticsRepr(backend.config...)
end
qo_obj = QuantumSymbolics.express(sym_obj, qo_repr)
return qo_obj.data
end

end
12 changes: 11 additions & 1 deletion test/Project.toml
Copy link
Member

Choose a reason for hiding this comment

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

The changes to this file seem a bit weird. Was this done by an LLM?

Copy link
Author

Choose a reason for hiding this comment

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

Indeed, an LLM provided some initial support on these changes, especially with deciphering a few errors and code patterns

Copy link
Member

Choose a reason for hiding this comment

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

check the Pkg.jl documentation and look at how QuantumSymbolics.jl and QuantumClifford.jl have things done as a reference, so that you can detect whether the LLM is suggesting silly things

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27 wrapping-240"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand All @@ -20,3 +20,13 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
TermInterface = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"

[deps.QuantumSavory]
git = "https://github.com/QuantumSavory/QuantumSavory.jl"

[compat]
julia = "1"
QuantumSavory = "0.1"

[targets]
test = ["Test", "TestItemRunner", "QuantumSavory", "QuantumOptics", "QuantumClifford", "QuantumInterface", "QuantumOpticsBase", "SymbolicUtils", "TermInterface"]
37 changes: 37 additions & 0 deletions test/test_statevectorrepr.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using QuantumSymbolics
using QuantumOptics
using QuantumSavory

@testitem "StateVectorRepr Conversion Tests" begin
# Test: Symbolic Ket (X1) conversion
sym_X1_test = QuantumSavory.X1
qo_X1_data = QuantumOptics.express(sym_X1_test, QuantumOptics.QuantumOpticsRepr()).data
sv_X1_data = express(sym_X1_test, StateVectorRepr())
@test sv_X1_data isa Vector{ComplexF64}
@test isapprox(sv_X1_data, qo_X1_data)
@test length(sv_X1_data) == 2

# Test: Symbolic Operator (Z1) conversion
sym_Z1_test = QuantumSavory.Z1
qo_Z1_data = QuantumOptics.express(sym_Z1_test, QuantumOptics.QuantumOpticsRepr()).data
sv_Z1_data = express(sym_Z1_test, StateVectorRepr())
@test sv_Z1_data isa Matrix{ComplexF64}
@test isapprox(sv_Z1_data, qo_Z1_data)
@test size(sv_Z1_data) == (2, 2)

# Test: Product operator (X1 * Y2) conversion
sym_XY_test = QuantumSavory.X1 * QuantumSavory.Y2
qo_XY_data = QuantumOptics.express(sym_XY_test, QuantumOptics.QuantumOpticsRepr()).data
sv_XY_data = express(sym_XY_test, StateVectorRepr())
@test sv_XY_data isa Matrix{ComplexF64}
@test isapprox(sv_XY_data, qo_XY_data)
@test size(sv_XY_data) == (4, 4)

# Test: Bosonic operator (N) with custom cutoff
sym_N_test = QuantumSavory.N
qo_N_cutoff4_data = QuantumOptics.express(sym_N_test, QuantumOptics.QuantumOpticsRepr(cutoff=4)).data
sv_N_cutoff4_data = express(sym_N_test, StateVectorRepr(cutoff=4))
@test sv_N_cutoff4_data isa Matrix{ComplexF64}
@test isapprox(sv_N_cutoff4_data, qo_N_cutoff4_data)
@test size(sv_N_cutoff4_data) == (5, 5)
end
Loading