Skip to content

Commit

Permalink
Simplify synonyms (qutip#355)
Browse files Browse the repository at this point in the history
  • Loading branch information
ytdHuang authored Dec 20, 2024
1 parent f5392ee commit 270d3f6
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 277 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Code-Quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1'
- 'lts'
os:
- 'ubuntu-latest'
arch:
Expand Down
6 changes: 3 additions & 3 deletions docs/src/resources/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ trans
dag
matrix_element
unit
tensor
qeye
sqrtm
logm
expm
sinm
cosm
tensor
qeye
```

## [Time evolution](@id doc-API:Time-evolution)
Expand Down
19 changes: 16 additions & 3 deletions src/qobj/arithmetic_and_attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,15 @@ LinearAlgebra.:(/)(A::AbstractQuantumObject{DT}, n::T) where {DT,T<:Number} =
get_typename_wrapper(A)(A.data / n, A.type, A.dims)

@doc raw"""
A ⋅ B
dot(A::QuantumObject, B::QuantumObject)
Compute the dot product between two [`QuantumObject`](@ref): ``\langle A | B \rangle``
Note that `A` and `B` should be [`Ket`](@ref) or [`OperatorKet`](@ref)
`A ⋅ B` (where `⋅` can be typed by tab-completing `\cdot` in the REPL) is a synonym for `dot(A, B)`
!!! note
`A ⋅ B` (where `⋅` can be typed by tab-completing `\cdot` in the REPL) is a synonym of `dot(A, B)`.
"""
function LinearAlgebra.dot(
A::QuantumObject{DT1,OpType},
Expand All @@ -130,12 +132,16 @@ end

@doc raw"""
dot(i::QuantumObject, A::AbstractQuantumObject j::QuantumObject)
matrix_element(i::QuantumObject, A::AbstractQuantumObject j::QuantumObject)
Compute the generalized dot product `dot(i, A*j)` between a [`AbstractQuantumObject`](@ref) and two [`QuantumObject`](@ref) (`i` and `j`), namely ``\langle i | \hat{A} | j \rangle``.
Supports the following inputs:
- `A` is in the type of [`Operator`](@ref), with `i` and `j` are both [`Ket`](@ref).
- `A` is in the type of [`SuperOperator`](@ref), with `i` and `j` are both [`OperatorKet`](@ref)
!!! note
`matrix_element(i, A, j)` is a synonym of `dot(i, A, j)`.
"""
function LinearAlgebra.dot(
i::QuantumObject{DT1,KetQuantumObject},
Expand Down Expand Up @@ -195,10 +201,12 @@ LinearAlgebra.transpose(
@doc raw"""
A'
adjoint(A::AbstractQuantumObject)
dag(A::AbstractQuantumObject)
Lazy adjoint (conjugate transposition) of the [`AbstractQuantumObject`](@ref)
Note that `A'` is a synonym for `adjoint(A)`
!!! note
`A'` and `dag(A)` are synonyms of `adjoint(A)`.
"""
LinearAlgebra.adjoint(
A::AbstractQuantumObject{DT,OpType},
Expand Down Expand Up @@ -310,13 +318,17 @@ end

@doc raw"""
normalize(A::QuantumObject, p::Real)
unit(A::QuantumObject, p::Real)
Return normalized [`QuantumObject`](@ref) so that its `p`-norm equals to unity, i.e. `norm(A, p) == 1`.
Support for the following types of [`QuantumObject`](@ref):
- If `A` is [`Ket`](@ref) or [`Bra`](@ref), default `p = 2`
- If `A` is [`Operator`](@ref), default `p = 1`
!!! note
`unit` is a synonym of `normalize`.
Also, see [`norm`](@ref) about its definition for different types of [`QuantumObject`](@ref).
"""
LinearAlgebra.normalize(
Expand Down Expand Up @@ -375,7 +387,8 @@ LinearAlgebra.rmul!(B::QuantumObject{<:AbstractArray}, a::Number) = (rmul!(B.dat
Matrix square root of [`QuantumObject`](@ref)
Note that `√(A)` is a synonym for `sqrt(A)`
!!! note
`√(A)` (where `√` can be typed by tab-completing `\sqrt` in the REPL) is a synonym of `sqrt(A)`.
"""
LinearAlgebra.sqrt(A::QuantumObject{<:AbstractArray{T}}) where {T} =
QuantumObject(sqrt(sparse_to_dense(A.data)), A.type, A.dims)
Expand Down
4 changes: 4 additions & 0 deletions src/qobj/boolean_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ issuper(A) = false # default case

@doc raw"""
ishermitian(A::AbstractQuantumObject)
isherm(A::AbstractQuantumObject)
Test whether the [`AbstractQuantumObject`](@ref) is Hermitian.
!!! note
`isherm` is a synonym of `ishermitian`.
"""
LinearAlgebra.ishermitian(A::AbstractQuantumObject) = ishermitian(A.data)

Expand Down
6 changes: 6 additions & 0 deletions src/qobj/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,15 @@ end

@doc raw"""
kron(A::AbstractQuantumObject, B::AbstractQuantumObject, ...)
tensor(A::AbstractQuantumObject, B::AbstractQuantumObject, ...)
⊗(A::AbstractQuantumObject, B::AbstractQuantumObject, ...)
A ⊗ B
Returns the [Kronecker product](https://en.wikipedia.org/wiki/Kronecker_product) ``\hat{A} \otimes \hat{B} \otimes \cdots``.
!!! note
`tensor` and `⊗` (where `⊗` can be typed by tab-completing `\otimes` in the REPL) are synonyms of `kron`.
# Examples
```jldoctest
Expand Down
4 changes: 4 additions & 0 deletions src/qobj/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,16 @@ sigmaz() = rmul!(jmat(0.5, Val(:z)), 2)

@doc raw"""
eye(N::Int; type=Operator, dims=nothing)
qeye(N::Int; type=Operator, dims=nothing)
Identity operator ``\hat{\mathbb{1}}`` with size `N`.
It is also possible to specify the list of Hilbert dimensions `dims` if different subsystems are present.
Note that `type` can only be either [`Operator`](@ref) or [`SuperOperator`](@ref)
!!! note
`qeye` is a synonym of `eye`.
"""
eye(
N::Int;
Expand Down
14 changes: 11 additions & 3 deletions src/qobj/quantum_object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,18 @@ struct QuantumObject{MT<:AbstractArray,ObjType<:QuantumObjectType,N} <: Abstract
end
end

function QuantumObject(A::AbstractArray, type::ObjType, dims::Integer) where {ObjType<:QuantumObjectType}
return QuantumObject(A, type, SVector{1,Int}(dims))
end
QuantumObject(A::AbstractArray, type::ObjType, dims::Integer) where {ObjType<:QuantumObjectType} =
QuantumObject(A, type, SVector{1,Int}(dims))

@doc raw"""
Qobj(A::AbstractArray; type = nothing, dims = nothing)
QuantumObject(A::AbstractArray; type = nothing, dims = nothing)
Generate [`QuantumObject`](@ref) with a given `A::AbstractArray` and specified `type::QuantumObjectType` and `dims`.
!!! note
`Qobj` is a synonym of `QuantumObject`.
"""
function QuantumObject(
A::AbstractMatrix{T};
type::ObjType = nothing,
Expand Down
5 changes: 5 additions & 0 deletions src/qobj/quantum_object_base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,15 @@ const OperatorKet = OperatorKetQuantumObject()
@doc raw"""
size(A::AbstractQuantumObject)
size(A::AbstractQuantumObject, idx::Int)
shape(A::AbstractQuantumObject)
shape(A::AbstractQuantumObject, idx::Int)
Returns a tuple containing each dimensions of the array in the [`AbstractQuantumObject`](@ref).
Optionally, you can specify an index (`idx`) to just get the corresponding dimension of the array.
!!! note
`shape` is a synonym of `size`.
"""
Base.size(A::AbstractQuantumObject) = size(A.data)
Base.size(A::AbstractQuantumObject, idx::Int) = size(A.data, idx)
Expand Down
130 changes: 126 additions & 4 deletions src/qobj/quantum_object_evo.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#=
This file defines the QuantumObjectEvolution (QobjEvo) structure.
=#

export QuantumObjectEvolution

@doc raw"""
Expand Down Expand Up @@ -30,7 +34,7 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal
julia> coef1(p, t) = exp(-1im * t)
coef1 (generic function with 1 method)
julia> op = QuantumObjectEvolution(a, coef1)
julia> op = QobjEvo(a, coef1)
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)
```
Expand All @@ -50,7 +54,7 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal
julia> coef2(p, t) = sin(t)
coef2 (generic function with 1 method)
julia> op1 = QuantumObjectEvolution(((a, coef1), (σm, coef2)))
julia> op1 = QobjEvo(((a, coef1), (σm, coef2)))
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
(ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20))
```
Expand All @@ -75,7 +79,7 @@ coef1 (generic function with 1 method)
julia> coef2(p, t) = sin(p.ω2 * t)
coef2 (generic function with 1 method)
julia> op1 = QuantumObjectEvolution(((a, coef1), (σm, coef2)))
julia> op1 = QobjEvo(((a, coef1), (σm, coef2)))
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
(ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20))
Expand Down Expand Up @@ -143,9 +147,12 @@ function QuantumObjectEvolution(data::AbstractSciMLOperator, type::QuantumObject
end

@doc raw"""
QobjEvo(data::AbstractSciMLOperator; type::QuantumObjectType = Operator, dims = nothing)
QuantumObjectEvolution(data::AbstractSciMLOperator; type::QuantumObjectType = Operator, dims = nothing)
Generate a [`QuantumObjectEvolution`](@ref) object from a [`SciMLOperator`](https://github.com/SciML/SciMLOperators.jl), in the same way as [`QuantumObject`](@ref) for `AbstractArray` inputs.
Note that `QobjEvo` is a synonym of `QuantumObjectEvolution`
"""
function QuantumObjectEvolution(data::AbstractSciMLOperator; type::QuantumObjectType = Operator, dims = nothing)
_size = _get_size(data)
Expand All @@ -161,7 +168,93 @@ function QuantumObjectEvolution(data::AbstractSciMLOperator; type::QuantumObject
return QuantumObjectEvolution(data, type, dims)
end

# Make the QuantumObjectEvolution, with the option to pre-multiply by a scalar
@doc raw"""
QobjEvo(op_func_list::Union{Tuple,AbstractQuantumObject}, α::Union{Nothing,Number}=nothing; type::Union{Nothing, QuantumObjectType}=nothing)
QuantumObjectEvolution(op_func_list::Union{Tuple,AbstractQuantumObject}, α::Union{Nothing,Number}=nothing; type::Union{Nothing, QuantumObjectType}=nothing)
Generate [`QuantumObjectEvolution`](@ref).
# Arguments
- `op_func_list::Union{Tuple,AbstractQuantumObject}`: A tuple of tuples or operators.
- `α::Union{Nothing,Number}=nothing`: A scalar to pre-multiply the operators.
!!! warning "Beware of type-stability!"
Please note that, unlike QuTiP, this function doesn't support `op_func_list` as `Vector` type. This is related to the type-stability issue. See the Section [The Importance of Type-Stability](@ref doc:Type-Stability) for more details.
Note that if `α` is provided, all the operators in `op_func_list` will be pre-multiplied by `α`. The `type` parameter is used to specify the type of the [`QuantumObject`](@ref), either `Operator` or `SuperOperator`. The `f` parameter is used to pre-apply a function to the operators before converting them to SciML operators.
!!! note
`QobjEvo` is a synonym of `QuantumObjectEvolution`.
# Examples
This operator can be initialized in the same way as the QuTiP `QobjEvo` object. For example
```jldoctest qobjevo
julia> a = tensor(destroy(10), qeye(2))
Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false
20×20 SparseMatrixCSC{ComplexF64, Int64} with 18 stored entries:
⎡⠀⠑⢄⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠀⠑⢄⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⎦
julia> σm = tensor(qeye(10), sigmam())
Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false
20×20 SparseMatrixCSC{ComplexF64, Int64} with 10 stored entries:
⎡⠂⡀⠀⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠂⡀⠀⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠂⡀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠂⡀⠀⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠂⡀⎦
julia> coef1(p, t) = exp(-1im * t)
coef1 (generic function with 1 method)
julia> coef2(p, t) = sin(t)
coef2 (generic function with 1 method)
julia> op1 = QobjEvo(((a, coef1), (σm, coef2)))
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
(ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20))
```
We can also concretize the operator at a specific time `t`
```jldoctest qobjevo
julia> op1(0.1)
Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false
20×20 SparseMatrixCSC{ComplexF64, Int64} with 28 stored entries:
⎡⠂⡑⢄⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠂⡑⢄⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠂⡑⢄⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠂⡑⢄⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠂⡑⎦
```
It also supports parameter-dependent time evolution
```jldoctest qobjevo
julia> coef1(p, t) = exp(-1im * p.ω1 * t)
coef1 (generic function with 1 method)
julia> coef2(p, t) = sin(p.ω2 * t)
coef2 (generic function with 1 method)
julia> op1 = QobjEvo(((a, coef1), (σm, coef2)))
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
(ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20))
julia> p = (ω1 = 1.0, ω2 = 0.5)
(ω1 = 1.0, ω2 = 0.5)
julia> op1(p, 0.1)
Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false
20×20 SparseMatrixCSC{ComplexF64, Int64} with 28 stored entries:
⎡⠂⡑⢄⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠂⡑⢄⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠂⡑⢄⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠂⡑⢄⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠂⡑⎦
```
"""
function QuantumObjectEvolution(
op_func_list::Tuple,
α::Union{Nothing,Number} = nothing;
Expand All @@ -187,6 +280,35 @@ QuantumObjectEvolution(
type::Union{Nothing,QuantumObjectType} = nothing,
) = QuantumObjectEvolution((op_func,), α; type = type)

@doc raw"""
QuantumObjectEvolution(op::QuantumObject, f::Function, α::Union{Nothing,Number}=nothing; type::Union{Nothing,QuantumObjectType} = nothing)
QobjEvo(op::QuantumObject, f::Function, α::Union{Nothing,Number}=nothing; type::Union{Nothing,QuantumObjectType} = nothing)
Generate [`QuantumObjectEvolution`](@ref).
# Notes
- The `f` parameter is used to pre-apply a function to the operators before converting them to SciML operators. The `type` parameter is used to specify the type of the [`QuantumObject`](@ref), either `Operator` or `SuperOperator`.
- `QobjEvo` is a synonym of `QuantumObjectEvolution`.
# Examples
```jldoctest
julia> a = tensor(destroy(10), qeye(2))
Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false
20×20 SparseMatrixCSC{ComplexF64, Int64} with 18 stored entries:
⎡⠀⠑⢄⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠀⠑⢄⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⎦
julia> coef(p, t) = exp(-1im * t)
coef (generic function with 1 method)
julia> op = QobjEvo(a, coef)
Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false
ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)
```
"""
QuantumObjectEvolution(
op::QuantumObject,
f::Function,
Expand Down
Loading

0 comments on commit 270d3f6

Please sign in to comment.