diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9af19..462f775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # News +## v0.4.3 - 2026-06-14 + +- Add a `lazy::Bool=false` option to `QuantumOpticsRepr`. When set, downstream `express` conversions (in `QuantumSymbolics.jl`) translate symbolic operator sums, products, and tensor products into `QuantumOpticsBase` lazy operators. The existing `QuantumOpticsRepr()` and `QuantumOpticsRepr(cutoff)` constructors are preserved. + ## v0.4.2 - 2025-11-29 - Define `commutator` and `anticommutator`. diff --git a/Project.toml b/Project.toml index 2029043..4b0e668 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumInterface" uuid = "5717a53b-5d69-4fa3-b976-0bf2f97ca1e5" authors = ["QuantumInterface.jl contributors"] -version = "0.4.2" +version = "0.4.3" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/express.jl b/src/express.jl index c088c27..fb8670a 100644 --- a/src/express.jl +++ b/src/express.jl @@ -22,10 +22,16 @@ express(s, repr::AbstractRepresentation) = express(s, repr, UseAsState()) # Commonly used representations -- interfaces for each one defined in separate packages ## -"""Representation using kets, bras, density matrices, and superoperators governed by `QuantumOptics.jl`.""" -Base.@kwdef struct QuantumOpticsRepr <: AbstractRepresentation +"""Representation using kets, bras, density matrices, and superoperators governed by `QuantumOptics.jl`. + +With `lazy=true`, downstream `express` conversions build the lazy operator types of +`QuantumOpticsBase` (`LazySum`, `LazyProduct`, `LazyTensor`) for symbolic sums, products, +and tensor products instead of materializing dense matrices.""" +Base.@kwdef struct QuantumOpticsRepr <: AbstractRepresentation cutoff::Int = 2 + lazy::Bool = false end +QuantumOpticsRepr(cutoff::Int) = QuantumOpticsRepr(; cutoff) """Similar to `QuantumOpticsRepr`, but using trajectories instead of superoperators.""" struct QuantumMCRepr <: AbstractRepresentation end """Representation using tableaux governed by `QuantumClifford.jl`""" diff --git a/test/runtests.jl b/test/runtests.jl index 826fe33..3c2359d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -27,6 +27,7 @@ println("Starting tests with $(Threads.nthreads()) threads out of `Sys.CPU_THREA @doset "sortedindices" @doset "bases" +@doset "express" #VERSION >= v"1.9" && @doset "doctests" get(ENV,"JET_TEST","")=="true" && @doset "jet" VERSION >= v"1.9" && @doset "aqua" diff --git a/test/test_express.jl b/test/test_express.jl new file mode 100644 index 0000000..45aefbe --- /dev/null +++ b/test/test_express.jl @@ -0,0 +1,28 @@ +using Test +using QuantumInterface: QuantumOpticsRepr + +@testset "QuantumOpticsRepr constructors" begin + # the default stays eager + @test QuantumOpticsRepr() == QuantumOpticsRepr(2, false) + @test QuantumOpticsRepr().cutoff == 2 + @test QuantumOpticsRepr().lazy == false + + # the positional `cutoff` constructor is preserved + @test QuantumOpticsRepr(4) == QuantumOpticsRepr(cutoff=4) + @test QuantumOpticsRepr(4).cutoff == 4 + @test QuantumOpticsRepr(4).lazy == false + + # the new `lazy` option is opt-in via keyword + @test QuantumOpticsRepr(lazy=true).lazy == true + @test QuantumOpticsRepr(cutoff=4, lazy=true) == QuantumOpticsRepr(4, true) +end + +@testset "QuantumOpticsRepr cache-key equality" begin + # `express` caches conversions in a `Dict` keyed on the representation value, so an + # eager and a lazy representation of the same object must compare unequal (and hash + # differently) or the cache would hand back the wrong type. + @test QuantumOpticsRepr(4) == QuantumOpticsRepr(cutoff=4, lazy=false) + @test QuantumOpticsRepr(4) != QuantumOpticsRepr(4, true) + @test hash(QuantumOpticsRepr(4)) == hash(QuantumOpticsRepr(cutoff=4, lazy=false)) + @test hash(QuantumOpticsRepr(2)) != hash(QuantumOpticsRepr(2, true)) +end