diff --git a/.github/workflows/Code-Quality.yml b/.github/workflows/Code-Quality.yml index 29d56c44..b231d2b2 100644 --- a/.github/workflows/Code-Quality.yml +++ b/.github/workflows/Code-Quality.yml @@ -39,7 +39,7 @@ jobs: fail-fast: false matrix: version: - - '1' + - 'lts' os: - 'ubuntu-latest' arch: diff --git a/docs/src/resources/api.md b/docs/src/resources/api.md index b701d8e7..ff890fea 100644 --- a/docs/src/resources/api.md +++ b/docs/src/resources/api.md @@ -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) diff --git a/src/qobj/arithmetic_and_attributes.jl b/src/qobj/arithmetic_and_attributes.jl index a3baf214..52e6859e 100644 --- a/src/qobj/arithmetic_and_attributes.jl +++ b/src/qobj/arithmetic_and_attributes.jl @@ -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}, @@ -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}, @@ -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}, @@ -310,6 +318,7 @@ 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`. @@ -317,6 +326,9 @@ 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( @@ -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) diff --git a/src/qobj/boolean_functions.jl b/src/qobj/boolean_functions.jl index 869d1464..c67f8fe4 100644 --- a/src/qobj/boolean_functions.jl +++ b/src/qobj/boolean_functions.jl @@ -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) diff --git a/src/qobj/functions.jl b/src/qobj/functions.jl index 84631688..2731de8a 100644 --- a/src/qobj/functions.jl +++ b/src/qobj/functions.jl @@ -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 diff --git a/src/qobj/operators.jl b/src/qobj/operators.jl index ccb989de..b65865d4 100644 --- a/src/qobj/operators.jl +++ b/src/qobj/operators.jl @@ -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; diff --git a/src/qobj/quantum_object.jl b/src/qobj/quantum_object.jl index 46a38d7d..c89826e7 100644 --- a/src/qobj/quantum_object.jl +++ b/src/qobj/quantum_object.jl @@ -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, diff --git a/src/qobj/quantum_object_base.jl b/src/qobj/quantum_object_base.jl index e4cb9644..df259307 100644 --- a/src/qobj/quantum_object_base.jl +++ b/src/qobj/quantum_object_base.jl @@ -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) diff --git a/src/qobj/quantum_object_evo.jl b/src/qobj/quantum_object_evo.jl index ddef7764..e9417b8f 100644 --- a/src/qobj/quantum_object_evo.jl +++ b/src/qobj/quantum_object_evo.jl @@ -1,3 +1,7 @@ +#= +This file defines the QuantumObjectEvolution (QobjEvo) structure. +=# + export QuantumObjectEvolution @doc raw""" @@ -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) ``` @@ -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)) ``` @@ -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)) @@ -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) @@ -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; @@ -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, diff --git a/src/qobj/synonyms.jl b/src/qobj/synonyms.jl index 6518d00a..7f00dbc1 100644 --- a/src/qobj/synonyms.jl +++ b/src/qobj/synonyms.jl @@ -4,184 +4,33 @@ Synonyms of the functions for QuantumObject export Qobj, QobjEvo, shape, isherm export trans, dag, matrix_element, unit -export sqrtm, logm, expm, sinm, cosm export tensor, ⊗ export qeye +export sqrtm, logm, expm, sinm, cosm @doc raw""" - Qobj(A::AbstractArray; type::QuantumObjectType, dims::Vector{Int}) - -Generate [`QuantumObject`](@ref) - -Note that this functions is same as `QuantumObject(A; type=type, dims=dims)`. -""" -Qobj(A; kwargs...) = QuantumObject(A; kwargs...) - -@doc raw""" - QobjEvo(op::QuantumObject, f::Function; type::Union{Nothing,QuantumObjectType} = nothing) - -Generate [`QuantumObjectEvolution`](@ref). - -Note that this functions is same as `QuantumObjectEvolution(op, f; type = type)`. 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`. - -# 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) -``` -""" -QobjEvo(op::QuantumObject, f::Function; type::Union{Nothing,QuantumObjectType} = nothing) = - QuantumObjectEvolution(op, f; type = type) - -@doc raw""" - QobjEvo(op_func_list::Union{Tuple,AbstractQuantumObject}, α::Union{Nothing,Number}=nothing; type::Union{Nothing, QuantumObjectType}=nothing) - -Generate [`QuantumObjectEvolution`](@ref). - -Note that this functions is same as `QuantumObjectEvolution(op_func_list)`. 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. - -# 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. - -# 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: -⎡⠂⡑⢄⠀⠀⠀⠀⠀⠀⠀⎤ -⎢⠀⠀⠂⡑⢄⠀⠀⠀⠀⠀⎥ -⎢⠀⠀⠀⠀⠂⡑⢄⠀⠀⠀⎥ -⎢⠀⠀⠀⠀⠀⠀⠂⡑⢄⠀⎥ -⎣⠀⠀⠀⠀⠀⠀⠀⠀⠂⡑⎦ -``` -""" -QobjEvo( - op_func_list::Union{Tuple,AbstractQuantumObject}, - α::Union{Nothing,Number} = nothing; - type::Union{Nothing,QuantumObjectType} = nothing, -) = QuantumObjectEvolution(op_func_list, α; type = type) - -QobjEvo(data::AbstractSciMLOperator, type::QuantumObjectType, dims::Integer) = - QuantumObjectEvolution(data, type, SVector{1,Int}(dims)) - -""" - QobjEvo(data::AbstractSciMLOperator; type::QuantumObjectType = Operator, dims = nothing) - -Synonym of [`QuantumObjectEvolution`](@ref) object from a [`SciMLOperator`](https://github.com/SciML/SciMLOperators.jl). See the documentation for [`QuantumObjectEvolution`](@ref) for more information. -""" -QobjEvo(data::AbstractSciMLOperator; type::QuantumObjectType = Operator, dims = nothing) = - QuantumObjectEvolution(data; type = type, dims = dims) - -@doc raw""" - shape(A::AbstractQuantumObject) + Qobj(A; kwargs...) -Returns a tuple containing each dimensions of the array in the [`AbstractQuantumObject`](@ref). - -Note that this function is same as `size(A)`. +!!! note + `Qobj` is a synonym for generating [`QuantumObject`](@ref). See the docstring of [`QuantumObject`](@ref) for more details. """ -shape(A::AbstractQuantumObject) = size(A.data) +const Qobj = QuantumObject # we need the docstring here, otherwise the docstring won't be found because QuantumObject is not a public symbol @doc raw""" - isherm(A::AbstractQuantumObject) - -Test whether the [`AbstractQuantumObject`](@ref) is Hermitian. + QobjEvo(args...; kwargs...) -Note that this functions is same as `ishermitian(A)`. +!!! note + `QobjEvo` is a synonym for generating [`QuantumObjectEvolution`](@ref). See the docstrings of [`QuantumObjectEvolution`](@ref) for more details. """ -isherm(A::AbstractQuantumObject) = ishermitian(A) - -@doc raw""" - trans(A::AbstractQuantumObject) +const QobjEvo = QuantumObjectEvolution # we need the docstring here, otherwise the docstring won't be found because QuantumObjectEvolution is not a public symbol -Lazy matrix transpose of the [`AbstractQuantumObject`](@ref). +const shape = size -Note that this function is same as `transpose(A)`. -""" -trans(A::AbstractQuantumObject{DT,OpType}) where {DT,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} = - transpose(A) +const isherm = ishermitian -@doc raw""" - dag(A::AbstractQuantumObject) +const trans = transpose -Lazy adjoint (conjugate transposition) of the [`AbstractQuantumObject`](@ref) - -Note that this function is same as `adjoint(A)`. -""" -dag(A::AbstractQuantumObject) = adjoint(A) +const dag = adjoint @doc raw""" matrix_element(i::QuantumObject, A::QuantumObject j::QuantumObject) @@ -194,35 +43,14 @@ 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) """ -matrix_element( - i::QuantumObject{<:AbstractArray{T1},KetQuantumObject}, - A::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject}, - j::QuantumObject{<:AbstractArray{T3},KetQuantumObject}, -) where {T1<:Number,T2<:Number,T3<:Number} = dot(i, A, j) -matrix_element( - i::QuantumObject{<:AbstractArray{T1},OperatorKetQuantumObject}, - A::QuantumObject{<:AbstractArray{T2},SuperOperatorQuantumObject}, - j::QuantumObject{<:AbstractArray{T3},OperatorKetQuantumObject}, -) where {T1<:Number,T2<:Number,T3<:Number} = dot(i, A, j) - -@doc raw""" - unit(A::QuantumObject, p::Real) +matrix_element(i, A, j) = dot(i, A, j) -Return normalized [`QuantumObject`](@ref) so that its `p`-norm equals to unity, i.e. `norm(A, p) == 1`. +const unit = normalize -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` +const tensor = kron +const ⊗ = kron -Note that this function is same as `normalize(A, p)` - -Also, see [`norm`](@ref) about its definition for different types of [`QuantumObject`](@ref). -""" -unit( - A::QuantumObject{<:AbstractArray{T},ObjType}, - p::Real = 2, -) where {T,ObjType<:Union{KetQuantumObject,BraQuantumObject}} = normalize(A, p) -unit(A::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}, p::Real = 1) where {T} = normalize(A, p) +const qeye = eye @doc raw""" sqrtm(A::QuantumObject) @@ -280,76 +108,3 @@ Note that this function is same as `cos(A)` and only supports for [`Operator`](@ cosm( A::QuantumObject{<:AbstractMatrix{T},ObjType}, ) where {T,ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} = cos(A) - -@doc raw""" - tensor(A::QuantumObject, B::QuantumObject, ...) - -Returns the [Kronecker product](https://en.wikipedia.org/wiki/Kronecker_product) ``\hat{A} \otimes \hat{B} \otimes \cdots``. - -Note that this function is same as `kron(A, B, ...)`. - -# Examples - -```jldoctest -julia> x = sigmax() -Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true -2×2 SparseMatrixCSC{ComplexF64, Int64} with 2 stored entries: - ⋅ 1.0+0.0im - 1.0+0.0im ⋅ - -julia> x_list = fill(x, 3); - -julia> tensor(x_list...).dims -3-element SVector{3, Int64} with indices SOneTo(3): - 2 - 2 - 2 -``` -""" -tensor(A...) = kron(A...) - -@doc raw""" - ⊗(A::QuantumObject, B::QuantumObject) - -Returns the [Kronecker product](https://en.wikipedia.org/wiki/Kronecker_product) ``\hat{A} \otimes \hat{B}``. - -Note that this function is same as `kron(A, B)`. - -# Examples - -```jldoctest -julia> a = destroy(20) -Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false -20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: -⎡⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⎤ -⎢⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⎥ -⎢⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⎥ -⎢⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⎥ -⎣⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⎦ - -julia> O = a ⊗ a; - -julia> size(a), size(O) -((20, 20), (400, 400)) - -julia> a.dims, O.dims -([20], [20, 20]) -``` -""" -⊗(A::QuantumObject, B::QuantumObject) = kron(A, B) - -@doc raw""" - 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 this function is same as `eye(N, type=type, dims=dims)`, and `type` can only be either [`Operator`](@ref) or [`SuperOperator`](@ref). -""" -qeye( - N::Int; - type::ObjType = Operator, - dims = nothing, -) where {ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} = - QuantumObject(Diagonal(ones(ComplexF64, N)); type = type, dims = dims)