Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Release date: 2025-11-19

- Add `spre` and `spost` methods for `ComposedOperator` and cache propagator in every time evolution solver. ([#596])
- Add error message for bad input in state/operator generating functions ([#603])

## [v0.39.0]
Release date: 2025-11-17
Expand Down Expand Up @@ -381,3 +382,4 @@ Release date: 2024-11-13
[#589]: https://github.com/qutip/QuantumToolbox.jl/issues/589
[#591]: https://github.com/qutip/QuantumToolbox.jl/issues/591
[#596]: https://github.com/qutip/QuantumToolbox.jl/issues/596
[#603]: https://github.com/qutip/QuantumToolbox.jl/issues/603
10 changes: 7 additions & 3 deletions src/qobj/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ _Jordan_Wigner(N::Int, j::Int, op::QuantumObject{Operator}) = _Jordan_Wigner(Val

function _Jordan_Wigner(::Val{N}, j::Int, op::QuantumObject{Operator}) where {N}
(N < 1) && throw(ArgumentError("The total number of sites (N) cannot be less than 1"))
((j > N) || (j < 1)) && throw(ArgumentError("The site index (j) should satisfy: 1 ≤ j ≤ N"))
(1 <= j <= N) || throw(ArgumentError("The site index (j) should satisfy: 1 ≤ j ≤ N"))

σz = sigmaz().data
Z_tensor = kron(1, 1, fill(σz, j - 1)...)
Expand All @@ -493,8 +493,12 @@ end

Generates the projection operator ``\hat{O} = |i \rangle\langle j|`` with Hilbert space dimension `N`.
"""
projection(N::Int, i::Int, j::Int) =
QuantumObject(sparse([i + 1], [j + 1], [1.0 + 0.0im], N, N), type = Operator(), dims = N)
function projection(N::Int, i::Int, j::Int)
(0 <= i < N) || throw(ArgumentError("Invalid argument i, must satisfy: 0 ≤ i ≤ N-1"))
(0 <= j < N) || throw(ArgumentError("Invalid argument j, must satisfy: 0 ≤ j ≤ N-1"))

return QuantumObject(sparse([i + 1], [j + 1], [1.0 + 0.0im], N, N), type = Operator(), dims = N)
end

@doc raw"""
tunneling(N::Int, m::Int=1; sparse::Union{Bool,Val{<:Bool}}=Val(false))
Expand Down
26 changes: 12 additions & 14 deletions src/qobj/states.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Functions for generating (common) quantum states.
=#

export zero_ket, fock, basis, coherent, rand_ket
export zero_ket, fock, coherent, rand_ket
export fock_dm, coherent_dm, thermal_dm, maximally_mixed_dm, rand_dm
export spin_state, spin_coherent
export bell_state, singlet_state, triplet_states, w_state, ghz_state
Expand All @@ -25,15 +25,20 @@ zero_ket(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}) =

@doc raw"""
fock(N::Int, j::Int=0; dims::Union{Int,AbstractVector{Int},Tuple}=N, sparse::Union{Bool,Val}=Val(false))
basis(N::Int, j::Int=0; dims::Union{Int,AbstractVector{Int},Tuple}=N, sparse::Union{Bool,Val}=Val(false))

Generates a fock state ``\ket{\psi}`` of dimension `N`.

It is also possible to specify the list of dimensions `dims` if different subsystems are present.

!!! warning "Beware of type-stability!"
If you want to keep type stability, it is recommended to use `fock(N, j, dims=dims, sparse=Val(sparse))` instead of `fock(N, j, dims=dims, sparse=sparse)`. Consider also to use `dims` as a `Tuple` or `SVector` from [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) instead of `Vector`. See [this link](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-value-type) and the [related Section](@ref doc:Type-Stability) about type stability for more details.

!!! note
`basis(N, j; dims = dims, sparse = sparse)` is a synonym of `fock(N, j; dims = dims, sparse = sparse)`.
"""
function fock(N::Int, j::Int = 0; dims::Union{Int,AbstractVector{Int},Tuple} = N, sparse::Union{Bool,Val} = Val(false))
(0 <= j < N) || throw(ArgumentError("Invalid argument j, must satisfy: 0 ≤ j ≤ N-1"))
if getVal(sparse)
array = sparsevec([j + 1], [1.0 + 0im], N)
else
Expand All @@ -42,18 +47,6 @@ function fock(N::Int, j::Int = 0; dims::Union{Int,AbstractVector{Int},Tuple} = N
return QuantumObject(array; type = Ket(), dims = dims)
end

@doc raw"""
basis(N::Int, j::Int = 0; dims::Union{Int,AbstractVector{Int},Tuple}=N)

Generates a fock state like [`fock`](@ref).

It is also possible to specify the list of dimensions `dims` if different subsystems are present.

!!! warning "Beware of type-stability!"
If you want to keep type stability, it is recommended to use `basis(N, j, dims=dims)` with `dims` as a `Tuple` or `SVector` from [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) instead of `Vector`. See [this link](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-value-type) and the [related Section](@ref doc:Type-Stability) about type stability for more details.
"""
basis(N::Int, j::Int = 0; dims::Union{Int,AbstractVector{Int},Tuple} = N) = fock(N, j, dims = dims)

@doc raw"""
coherent(N::Int, α::Number)

Expand Down Expand Up @@ -203,7 +196,7 @@ function spin_state(j::Real, m::Real)
throw(ArgumentError("Invalid eigenvalue m: (j - m) must be a non-negative integer."))
(m < (-j)) && throw(ArgumentError("Invalid eigenvalue m, must satisfy: -j ≤ m ≤ j"))

return basis(Int(J), Int(Δ))
return fock(Int(J), Int(Δ))
end

@doc raw"""
Expand Down Expand Up @@ -318,6 +311,8 @@ Returns the `n`-qubit [W-state](https://en.wikipedia.org/wiki/W_state):
If you want to keep type stability, it is recommended to use `w_state(Val(n))` instead of `w_state(n)`. See [this link](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-value-type) and the [related Section](@ref doc:Type-Stability) for more details.
"""
function w_state(::Val{n}) where {n}
(n >= 2) || throw(ArgumentError("Invalid argument n, must satisfy: n ≥ 2"))

nzind = 2 .^ (0:(n-1)) .+ 1
nzval = fill(ComplexF64(1 / sqrt(n)), n)
data = zeros(ComplexF64, 2^n)
Expand All @@ -341,6 +336,9 @@ Here, `d` specifies the dimension of each qudit. Default to `d=2` (qubit).
If you want to keep type stability, it is recommended to use `ghz_state(Val(n))` instead of `ghz_state(n)`. See [this link](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-value-type) and the [related Section](@ref doc:Type-Stability) for more details.
"""
function ghz_state(::Val{n}; d::Int = 2) where {n}
(n >= 2) || throw(ArgumentError("Invalid argument n, must satisfy: n ≥ 2"))
(d >= 2) || throw(ArgumentError("Invalid argument d, must satisfy: d ≥ 2"))

nzind = collect((0:(d-1)) .* Int((d^n - 1) / (d - 1)) .+ 1)
nzval = fill(ComplexF64(1 / sqrt(d)), d)
data = zeros(ComplexF64, d^n)
Expand Down
3 changes: 3 additions & 0 deletions src/qobj/synonyms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Synonyms of the functions for QuantumObject

export Qobj, QobjEvo, shape, isherm
export trans, dag, matrix_element, unit
export basis
export tensor, ⊗
export qeye, qeye_like, qzero_like
export vector_to_operator, operator_to_vector
Expand Down Expand Up @@ -33,6 +34,8 @@ const trans = transpose

const dag = adjoint

const basis = fock

@doc raw"""
matrix_element(i::QuantumObject, A::QuantumObject, j::QuantumObject)

Expand Down
9 changes: 9 additions & 0 deletions test/core-test/states_and_operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# fock, basis, and fock_dm
@test fock_dm(4; dims = (2, 2), sparse = true) ≈ ket2dm(basis(4; dims = (2, 2)))
@test_throws DimensionMismatch fock(4; dims = 2)
@test_throws ArgumentError fock(4, 4)
end

@testset "coherent state" begin
Expand Down Expand Up @@ -121,23 +122,31 @@
@test_throws ArgumentError bell_state(0, 2)
@test_throws ArgumentError bell_state(3, 1)
@test_throws ArgumentError bell_state(2, 3)
@test_throws ArgumentError w_state(1)
@test_throws ArgumentError ghz_state(1)
@test_throws ArgumentError ghz_state(2; d = 1)
end

@testset "bosonic operators" begin
# destroy, create, num, position, momentum
n = 10
i, j = rand(0:(n-1), 2)
a = destroy(n)
ad = create(n)
N = num(n)
x = position(n)
p = momentum(n)
Pij = projection(n, i, j)
@test isoper(x)
@test isoper(p)
@test a.dims == ad.dims == N.dims == x.dims == p.dims == [n]
@test eigenenergies(ad * a) ≈ 0:(n-1)
@test commutator(N, a) ≈ -a
@test commutator(N, ad) ≈ ad
@test all(diag(commutator(x, p))[1:(n-1)] .≈ 1.0im)
@test fock(n, i) == Pij * fock(n, j)
@test_throws ArgumentError projection(n, n, 0)
@test_throws ArgumentError projection(n, 0, n)
end

@testset "displacement and squeezing operators" begin
Expand Down
Loading