Skip to content
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

Simplify synonyms #355

Merged
merged 6 commits into from
Dec 20, 2024
Merged
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
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
Loading